From eb7f8290aff7f7b43c9ee380765e185e03e90936 Mon Sep 17 00:00:00 2001 From: ogerly Date: Wed, 8 Jun 2022 22:15:59 +0200 Subject: [PATCH 001/528] add Page Community, add query listContributionLinks --- frontend/src/components/Menu/Sidebar.vue | 4 ++ frontend/src/graphql/queries.js | 15 +++++++ frontend/src/pages/Community.vue | 50 ++++++++++++++++++++++++ frontend/src/routes/routes.js | 7 ++++ 4 files changed, 76 insertions(+) create mode 100644 frontend/src/pages/Community.vue diff --git a/frontend/src/components/Menu/Sidebar.vue b/frontend/src/components/Menu/Sidebar.vue index 028b7aca6..8062e5ef5 100644 --- a/frontend/src/components/Menu/Sidebar.vue +++ b/frontend/src/components/Menu/Sidebar.vue @@ -34,6 +34,10 @@ {{ $t('navigation.admin_area') }} + + + {{ $t('community.community') }} + {{ $t('navigation.logout') }} diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index 601880a51..c6c847868 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -144,3 +144,18 @@ export const listTransactionLinks = gql` } } ` + +export const listContributionLinks = gql` + query { + listContributionLinks { + startDate + endDate + name + memo + amount + cycle + repetition + maxAmount + } + } +` diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue new file mode 100644 index 000000000..1786f30a0 --- /dev/null +++ b/frontend/src/pages/Community.vue @@ -0,0 +1,50 @@ + + diff --git a/frontend/src/routes/routes.js b/frontend/src/routes/routes.js index e68f97502..540ef9d69 100755 --- a/frontend/src/routes/routes.js +++ b/frontend/src/routes/routes.js @@ -38,6 +38,13 @@ const routes = [ requiresAuth: true, }, }, + { + path: '/community', + component: () => import('@/pages/Community.vue'), + meta: { + requiresAuth: true, + }, + }, { path: '/login/:code?', component: () => import('@/pages/Login.vue'), From 83ebf4aa2efb8396dc6ee42c8b7d3454567ee340 Mon Sep 17 00:00:00 2001 From: ogerly Date: Wed, 8 Jun 2022 22:25:14 +0200 Subject: [PATCH 002/528] add Statistik Container --- frontend/src/pages/Community.vue | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 1786f30a0..a59d708d8 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -34,6 +34,20 @@ suport@gradido.net +
+ +
Statistik
+
+
+ Mitglieder + 1203 +
+
+ Mitglieder + 1203 +
+
+
diff --git a/frontend/src/routes/routes.js b/frontend/src/routes/routes.js index e68f97502..540ef9d69 100755 --- a/frontend/src/routes/routes.js +++ b/frontend/src/routes/routes.js @@ -38,6 +38,13 @@ const routes = [ requiresAuth: true, }, }, + { + path: '/community', + component: () => import('@/pages/Community.vue'), + meta: { + requiresAuth: true, + }, + }, { path: '/login/:code?', component: () => import('@/pages/Login.vue'), From 1664a2070fdb96bcbbfe83d42ef9895d3c16dae9 Mon Sep 17 00:00:00 2001 From: ogerly Date: Thu, 7 Jul 2022 08:16:00 +0200 Subject: [PATCH 042/528] locales for Community.vue Page --- frontend/src/locales/de.json | 7 +++++-- frontend/src/locales/en.json | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index fec24b1dc..74850d556 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -28,7 +28,9 @@ "continue-to-registration": "Weiter zur Registrierung", "current-community": "Aktuelle Gemeinschaft", "other-communities": "Weitere Gemeinschaften", - "switch-to-this-community": "zu dieser Gemeinschaft wechseln" + "switch-to-this-community": "zu dieser Gemeinschaft wechseln", + "writing":"Schreiben", + "myContributions":"Meine Beiträge" }, "contribution-link": { "thanksYouWith": "dankt dir mit" @@ -200,7 +202,8 @@ "profile": "Mein Profil", "send": "Senden", "support": "Support", - "transactions": "Transaktionen" + "transactions": "Transaktionen", + "community":"Gemeinschaft" }, "qrCode": "QR Code", "send_gdd": "GDD versenden", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index a0ef6723d..1312b60b4 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -28,7 +28,9 @@ "continue-to-registration": "Continue to registration", "current-community": "Current community", "other-communities": "Other communities", - "switch-to-this-community": "Switch to this community" + "switch-to-this-community": "Switch to this community", + "writing":"Writing", + "myContributions":"My contributions" }, "contribution-link": { "thanksYouWith": "thanks you with" @@ -200,7 +202,8 @@ "profile": "My profile", "send": "Send", "support": "Support", - "transactions": "Transactions" + "transactions": "Transactions", + "community":"Community" }, "qrCode": "QR Code", "send_gdd": "GDD send", From d8fb3608a2931d380f1902244b9169e70ef1476d Mon Sep 17 00:00:00 2001 From: ogerly Date: Thu, 7 Jul 2022 12:01:27 +0200 Subject: [PATCH 043/528] add new component ContributionForm.vue --- .../Contributions/ContributionForm.vue | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 frontend/src/components/Contributions/ContributionForm.vue diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue new file mode 100644 index 000000000..a67b4642f --- /dev/null +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -0,0 +1,79 @@ + + From fa0598c75262da33fedd4056ec9defba4f969551 Mon Sep 17 00:00:00 2001 From: ogerly Date: Thu, 7 Jul 2022 12:02:31 +0200 Subject: [PATCH 044/528] add form in ContributionForm.vue --- frontend/src/i18n.js | 18 ++++++++++++++++++ frontend/src/locales/de.json | 10 +++++++++- frontend/src/locales/en.json | 9 ++++++++- frontend/src/pages/Community.vue | 6 +++++- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/frontend/src/i18n.js b/frontend/src/i18n.js index f4f969008..74de46c29 100644 --- a/frontend/src/i18n.js +++ b/frontend/src/i18n.js @@ -75,6 +75,15 @@ const dateTimeFormats = { hour: 'numeric', minute: 'numeric', }, + monthShort: { + month: 'short', + }, + month: { + month: 'long', + }, + year: { + year: 'numeric', + }, }, de: { short: { @@ -90,6 +99,15 @@ const dateTimeFormats = { hour: 'numeric', minute: 'numeric', }, + monthShort: { + month: 'short', + }, + month: { + month: 'long', + }, + year: { + year: 'numeric', + }, }, } diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 74850d556..3af893009 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -32,6 +32,10 @@ "writing":"Schreiben", "myContributions":"Meine Beiträge" }, + "contribution": { + "activity":"Tätigkeit", + "submit":"Einreichen" + }, "contribution-link": { "thanksYouWith": "dankt dir mit" }, @@ -182,7 +186,10 @@ "equal": "=", "exclaim": "!", "minus": "−", - "pipe": "|" + "pipe": "|", + "divide": "/", + "equalTo":"<" + }, "message": { "activateEmail": "Dein Konto wurde noch nicht aktiviert. Bitte überprüfe deine E-Mail und klicke den Aktivierungslink oder fordere einen neuen Aktivierungslink über die Password Reset Seite an.", @@ -275,6 +282,7 @@ "days": "Tage", "hours": "Stunden", "minutes": "Minuten", + "month": "Monat", "months": "Monate", "seconds": "Sekunden", "years": "Jahr" diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 1312b60b4..8244eb1fb 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -32,6 +32,10 @@ "writing":"Writing", "myContributions":"My contributions" }, + "contribution": { + "activity":"Activity", + "submit":"Submit" + }, "contribution-link": { "thanksYouWith": "thanks you with" }, @@ -182,7 +186,9 @@ "equal": "=", "exclaim": "!", "minus": "−", - "pipe": "|" + "pipe": "|", + "divide": "/", + "equalTo":"<" }, "message": { "activateEmail": "Your account has not been activated yet. Please check your emails and click the activation link or order a new activation link over the password reset page.", @@ -275,6 +281,7 @@ "days": "Days", "hours": "Hours", "minutes": "Minutes", + "month": "Month", "months": "Months", "seconds": "Seconds", "years": "Year" diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 9264df623..66fdfcae6 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -3,7 +3,7 @@
-

{{ $t('community.writing') }}

+

{{ $t('community.myContributions') }}

@@ -16,7 +16,11 @@
From 50050e138f96bcd7b75890b001737ce419643840 Mon Sep 17 00:00:00 2001 From: ogerly Date: Thu, 7 Jul 2022 12:05:06 +0200 Subject: [PATCH 045/528] change form.text to form.memo --- .../components/Contributions/ContributionForm.vue | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index a67b4642f..9b4f9de1b 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -13,7 +13,7 @@
- {{ form.text.length }} - {{ $t('math.equalTo') }} {{ minlength }} + {{ form.memo.length }} + {{ $t('math.equalTo') }} {{ minlength }} {{ $t('math.divide') }} {{ maxlength }}
@@ -49,8 +49,9 @@ export default { minlength: 50, maxlength: 500, form: { - text: '', selected: this.$moment().format('MMMM'), + memo: '', + amount: 0, }, options: [ @@ -70,7 +71,7 @@ export default { }, computed: { disable() { - if (this.form.text.length < this.minlength) return true + if (this.form.memo.length < this.minlength) return true if (this.form.amount < 1 && this.form.amount < 1000) return true return false }, From 1543c568aecce88311f3066a9d4f025d3b5f3e04 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 7 Jul 2022 13:47:14 +0200 Subject: [PATCH 046/528] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Wolfgang Huß --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a707639ac..d12edfb89 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ Each component has a `.env.dist` file. This file contains all environment variab Each component has a `.env.template` file. These files are very important on deploy. -There is one `.env.dist` in the `deployment/bare_metal/` folder. This `.env.dist` contains all variables used by the components, e.g. unites all `.env.dist` from the components. On deploy, we copy this `.env.dist` to `.env` and set all variables in this new file. The deploy script loads this variables and provides them by the `.env.templates` of each component, creating a `.env` for each component (see in `deployment/bare_metal/start.sh` the `envsubst`). +There is one `.env.dist` in the `deployment/bare_metal/` folder. This `.env.dist` contains all variables used by the components, e.g. unites all `.env.dist` from the components. On deploy, we copy this `.env.dist` to `.env` and set all variables in this new file. The deploy script loads this variables and provides them by the `.env.templates` of each component, creating an `.env` for each component (see in `deployment/bare_metal/start.sh` the `envsubst`). To avoid forgetting to update an existing `.env` in the `deployment/bare_metal/` folder when deploying, we have a environment version variable inside the codebase of each component. You should update this version, when environment variables must be changed or added on deploy. The code checks, that the environement version provided by the `.env` is the one expected by the codebase. From 9840017f0cd0048ad0bd561ecbb6cc56876632cc Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 7 Jul 2022 13:47:24 +0200 Subject: [PATCH 047/528] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Wolfgang Huß --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d12edfb89..145ce4141 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ Each component has a `.env.template` file. These files are very important on dep There is one `.env.dist` in the `deployment/bare_metal/` folder. This `.env.dist` contains all variables used by the components, e.g. unites all `.env.dist` from the components. On deploy, we copy this `.env.dist` to `.env` and set all variables in this new file. The deploy script loads this variables and provides them by the `.env.templates` of each component, creating an `.env` for each component (see in `deployment/bare_metal/start.sh` the `envsubst`). -To avoid forgetting to update an existing `.env` in the `deployment/bare_metal/` folder when deploying, we have a environment version variable inside the codebase of each component. You should update this version, when environment variables must be changed or added on deploy. The code checks, that the environement version provided by the `.env` is the one expected by the codebase. +To avoid forgetting to update an existing `.env` in the `deployment/bare_metal/` folder when deploying, we have an environment version variable inside the codebase of each component. You should update this version, when environment variables must be changed or added on deploy. The code checks, that the environement version provided by the `.env` is the one expected by the codebase. ## Troubleshooting From 924db68d0638172d3dbc280e1ca7dd321d9abed6 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 7 Jul 2022 15:52:55 +0200 Subject: [PATCH 048/528] setup community statistics --- backend/src/auth/RIGHTS.ts | 1 + .../src/graphql/model/CommunityStatistics.ts | 26 +++++++++++++++++++ .../graphql/resolver/StatisticsResolver.ts | 26 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 backend/src/graphql/model/CommunityStatistics.ts create mode 100644 backend/src/graphql/resolver/StatisticsResolver.ts diff --git a/backend/src/auth/RIGHTS.ts b/backend/src/auth/RIGHTS.ts index c10fc96de..cbf650ec1 100644 --- a/backend/src/auth/RIGHTS.ts +++ b/backend/src/auth/RIGHTS.ts @@ -44,4 +44,5 @@ export enum RIGHTS { LIST_CONTRIBUTION_LINKS = 'LIST_CONTRIBUTION_LINKS', DELETE_CONTRIBUTION_LINK = 'DELETE_CONTRIBUTION_LINK', UPDATE_CONTRIBUTION_LINK = 'UPDATE_CONTRIBUTION_LINK', + COMMUNITY_STATISTICS = 'COMMUNITY_STATISTICS', } diff --git a/backend/src/graphql/model/CommunityStatistics.ts b/backend/src/graphql/model/CommunityStatistics.ts new file mode 100644 index 000000000..61354115c --- /dev/null +++ b/backend/src/graphql/model/CommunityStatistics.ts @@ -0,0 +1,26 @@ +import { ObjectType, Field } from 'type-graphql' +import Decimal from 'decimal.js-light' + +@ObjectType() +export class CommunityStatistics { + @Field(() => Number) + totalUsers: number + + @Field(() => Number) + activeUsers: number + + @Field(() => Number) + deletedUsers: number + + @Field(() => Decimal) + totalGradidoCreated: Decimal + + @Field(() => Decimal) + totalGradidoDecayed: Decimal + + @Field(() => Decimal) + totalGradidoAvailable: Decimal + + @Field(() => Decimal) + totalGradidoUnbookedDecayed: Decimal +} diff --git a/backend/src/graphql/resolver/StatisticsResolver.ts b/backend/src/graphql/resolver/StatisticsResolver.ts new file mode 100644 index 000000000..a90d42f75 --- /dev/null +++ b/backend/src/graphql/resolver/StatisticsResolver.ts @@ -0,0 +1,26 @@ +import { Resolver, Query, Arg, Args, Authorized, Ctx, Int } from 'type-graphql' +import { RIGHTS } from '@/auth/RIGHTS' +import { CommunityStatistics } from '@model/CommunityStatistics' +import { User as DbUser } from '@entity/User' +import { getConnection } from '@dbTools/typeorm' +import Decimal from 'decimal.js-light' + +@Resolver() +export class StatisticsResolver { + @Authorized([RIGHTS.COMMUNITY_STATISTICS]) + @Query(() => CommunityStatistics) + async communityStatistics(): Promise { + const totalUsers = await DbUser.find({ withDeleted: true }) + console.log(totalUsers.length) + + return { + totalUsers: 12, + activeUsers: 6, + deletedUsers: 1, + totalGradidoCreated: new Decimal(3000), + totalGradidoDecayed: new Decimal(200), + totalGradidoAvailable: new Decimal(2800), + totalGradidoUnbookedDecayed: new Decimal(200), + } + } +} From df227607ad539ad0bc209eebed917d0a7b356bed Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 7 Jul 2022 17:27:50 +0200 Subject: [PATCH 049/528] get basic statistics from database --- .../graphql/resolver/StatisticsResolver.ts | 71 ++++++++++++++++--- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/backend/src/graphql/resolver/StatisticsResolver.ts b/backend/src/graphql/resolver/StatisticsResolver.ts index a90d42f75..4c1500839 100644 --- a/backend/src/graphql/resolver/StatisticsResolver.ts +++ b/backend/src/graphql/resolver/StatisticsResolver.ts @@ -1,26 +1,77 @@ -import { Resolver, Query, Arg, Args, Authorized, Ctx, Int } from 'type-graphql' +import { Resolver, Query, Authorized } from 'type-graphql' import { RIGHTS } from '@/auth/RIGHTS' import { CommunityStatistics } from '@model/CommunityStatistics' import { User as DbUser } from '@entity/User' +import { Transaction as DbTransaction } from '@entity/Transaction' import { getConnection } from '@dbTools/typeorm' import Decimal from 'decimal.js-light' +import { calculateDecay } from '@/util/decay' @Resolver() export class StatisticsResolver { @Authorized([RIGHTS.COMMUNITY_STATISTICS]) @Query(() => CommunityStatistics) async communityStatistics(): Promise { - const totalUsers = await DbUser.find({ withDeleted: true }) - console.log(totalUsers.length) + const allUsers = await DbUser.find({ withDeleted: true }) + + let totalUsers = 0 + let activeUsers = 0 + let deletedUsers = 0 + + let totalGradidoAvailable: Decimal = new Decimal(0) + let totalGradidoUnbookedDecayed: Decimal = new Decimal(0) + + const receivedCallDate = new Date() + + for (let i = 0; i < allUsers.length; i++) { + if (allUsers[i].deletedAt) { + deletedUsers++ + } else { + totalUsers++ + const lastTransaction = await DbTransaction.findOne({ + where: { userId: allUsers[i].id }, + order: { balanceDate: 'DESC' }, + }) + if (lastTransaction) { + activeUsers++ + const decay = calculateDecay( + lastTransaction.balance, + lastTransaction.balanceDate, + receivedCallDate, + ) + if (decay) { + totalGradidoAvailable = totalGradidoAvailable.plus(decay.balance.toString()) + totalGradidoUnbookedDecayed = totalGradidoUnbookedDecayed.plus(decay.decay.toString()) + } + } + } + } + + const queryRunner = getConnection().createQueryRunner() + await queryRunner.connect() + + const { totalGradidoCreated } = await queryRunner.manager + .createQueryBuilder() + .select('SUM(transaction.amount) AS totalGradidoCreated') + .from(DbTransaction, 'transaction') + .where('transaction.typeId = 1') + .getRawOne() + + const { totalGradidoDecayed } = await queryRunner.manager + .createQueryBuilder() + .select('SUM(transaction.decay) AS totalGradidoDecayed') + .from(DbTransaction, 'transaction') + .where('transaction.decay IS NOT NULL') + .getRawOne() return { - totalUsers: 12, - activeUsers: 6, - deletedUsers: 1, - totalGradidoCreated: new Decimal(3000), - totalGradidoDecayed: new Decimal(200), - totalGradidoAvailable: new Decimal(2800), - totalGradidoUnbookedDecayed: new Decimal(200), + totalUsers, + activeUsers, + deletedUsers, + totalGradidoCreated, + totalGradidoDecayed, + totalGradidoAvailable, + totalGradidoUnbookedDecayed, } } } From baa5084f5d6365485f1af3a109e5dcd771155eed Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 7 Jul 2022 17:29:09 +0200 Subject: [PATCH 050/528] add query for communty statistics --- admin/src/graphql/communityStatistics.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 admin/src/graphql/communityStatistics.js diff --git a/admin/src/graphql/communityStatistics.js b/admin/src/graphql/communityStatistics.js new file mode 100644 index 000000000..868bfd02a --- /dev/null +++ b/admin/src/graphql/communityStatistics.js @@ -0,0 +1,15 @@ +import gql from 'graphql-tag' + +export const communityStatistics = gql` + query { + communityStatistics { + totalUsers + activeUsers + deletedUsers + totalGradidoCreated + totalGradidoDecayed + totalGradidoAvailable + totalGradidoUnbookedDecayed + } + } +` From c3d62db1e5bdb8d2eeaf7b4eefaca40313d3fded Mon Sep 17 00:00:00 2001 From: ogerly Date: Fri, 8 Jul 2022 11:34:55 +0200 Subject: [PATCH 051/528] add componente ContributionList.vue --- .../Contributions/ContributionList.vue | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 frontend/src/components/Contributions/ContributionList.vue diff --git a/frontend/src/components/Contributions/ContributionList.vue b/frontend/src/components/Contributions/ContributionList.vue new file mode 100644 index 000000000..e3dc41b5f --- /dev/null +++ b/frontend/src/components/Contributions/ContributionList.vue @@ -0,0 +1,17 @@ + + From 4cc1642988fb65a0d4f50440f8346bced7f8bff3 Mon Sep 17 00:00:00 2001 From: ogerly Date: Fri, 8 Jul 2022 21:26:18 +0200 Subject: [PATCH 052/528] add mutations createContribution --- frontend/src/graphql/mutations.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/src/graphql/mutations.js b/frontend/src/graphql/mutations.js index 9b035cba6..d70eb8c99 100644 --- a/frontend/src/graphql/mutations.js +++ b/frontend/src/graphql/mutations.js @@ -89,3 +89,12 @@ export const redeemTransactionLink = gql` redeemTransactionLink(code: $code) } ` + +export const createContribution = gql` + mutation($creationDate: String!, $memo: String!, $amount: Decimal!) { + createContribution(creationDate: $creationDate, memo: $memo, amount: $amount) { + amount + memo + } + } +` From a65d680bdaf125f539982d203df2ac033b2eb5cf Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 11 Jul 2022 08:19:29 +0200 Subject: [PATCH 053/528] change form, ,maxlenght 255, add items for list --- .../Contributions/ContributionForm.vue | 40 ++++++------- frontend/src/locales/de.json | 3 +- frontend/src/locales/en.json | 3 +- frontend/src/pages/Community.vue | 60 ++++++++++++++++++- 4 files changed, 79 insertions(+), 27 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index 9b4f9de1b..ac59959a1 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -1,15 +1,17 @@ From f79ff13183c946ff1f403749bb5a00d2bb1883f4 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 11 Jul 2022 08:20:23 +0200 Subject: [PATCH 054/528] fix locales --- frontend/src/locales/de.json | 21 ++++++++++----------- frontend/src/locales/en.json | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index d8374a541..14e0d2300 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -27,15 +27,15 @@ "community": "Gemeinschaft", "continue-to-registration": "Weiter zur Registrierung", "current-community": "Aktuelle Gemeinschaft", + "myContributions": "Meine Beiträge", "other-communities": "Weitere Gemeinschaften", "switch-to-this-community": "zu dieser Gemeinschaft wechseln", - "writing":"Schreiben", - "myContributions":"Meine Beiträge" + "writing": "Schreiben" }, "contribution": { - "activity":"Tätigkeit", - "submit":"Einreichen", - "noDateSelected": "Kein Datum ausgewählt" + "activity": "Tätigkeit", + "noDateSelected": "Kein Datum ausgewählt", + "submit": "Einreichen" }, "contribution-link": { "thanksYouWith": "dankt dir mit" @@ -184,13 +184,12 @@ "login": "Anmeldung", "math": { "aprox": "~", + "divide": "/", "equal": "=", + "equalTo": "<", "exclaim": "!", "minus": "−", - "pipe": "|", - "divide": "/", - "equalTo":"<" - + "pipe": "|" }, "message": { "activateEmail": "Dein Konto wurde noch nicht aktiviert. Bitte überprüfe deine E-Mail und klicke den Aktivierungslink oder fordere einen neuen Aktivierungslink über die Password Reset Seite an.", @@ -204,14 +203,14 @@ }, "navigation": { "admin_area": "Adminbereich", + "community": "Gemeinschaft", "logout": "Abmelden", "members_area": "Mitgliederbereich", "overview": "Übersicht", "profile": "Mein Profil", "send": "Senden", "support": "Support", - "transactions": "Transaktionen", - "community":"Gemeinschaft" + "transactions": "Transaktionen" }, "qrCode": "QR Code", "send_gdd": "GDD versenden", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index c10b62508..b06d141d3 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -27,15 +27,15 @@ "community": "Community", "continue-to-registration": "Continue to registration", "current-community": "Current community", + "myContributions": "My contributions", "other-communities": "Other communities", "switch-to-this-community": "Switch to this community", - "writing":"Writing", - "myContributions":"My contributions" + "writing": "Writing" }, "contribution": { - "activity":"Activity", - "submit":"Submit", - "noDateSelected": "No date selected" + "activity": "Activity", + "noDateSelected": "No date selected", + "submit": "Submit" }, "contribution-link": { "thanksYouWith": "thanks you with" @@ -184,12 +184,12 @@ "login": "Login", "math": { "aprox": "~", + "divide": "/", "equal": "=", + "equalTo": "<", "exclaim": "!", "minus": "−", - "pipe": "|", - "divide": "/", - "equalTo":"<" + "pipe": "|" }, "message": { "activateEmail": "Your account has not been activated yet. Please check your emails and click the activation link or order a new activation link over the password reset page.", @@ -203,14 +203,14 @@ }, "navigation": { "admin_area": "Admin Area", + "community": "Community", "logout": "Logout", "members_area": "Members area", "overview": "Overview", "profile": "My profile", "send": "Send", "support": "Support", - "transactions": "Transactions", - "community":"Community" + "transactions": "Transactions" }, "qrCode": "QR Code", "send_gdd": "GDD send", From 0c857417e5bda4581589bd11ce067c3dd9e06f92 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 11 Jul 2022 08:27:45 +0200 Subject: [PATCH 055/528] fix test --- frontend/src/components/Menu/Sidebar.spec.js | 13 ++++++++----- frontend/src/routes/router.test.js | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Menu/Sidebar.spec.js b/frontend/src/components/Menu/Sidebar.spec.js index fec7945c8..982192a8f 100644 --- a/frontend/src/components/Menu/Sidebar.spec.js +++ b/frontend/src/components/Menu/Sidebar.spec.js @@ -33,7 +33,7 @@ describe('Sidebar', () => { describe('navigation Navbar', () => { it('has seven b-nav-item in the navbar', () => { - expect(wrapper.findAll('.nav-item')).toHaveLength(7) + expect(wrapper.findAll('.nav-item')).toHaveLength(8) }) it('has first nav-item "navigation.overview" in navbar', () => { @@ -50,15 +50,18 @@ describe('Sidebar', () => { it('has first nav-item "navigation.profile" in navbar', () => { expect(wrapper.findAll('.nav-item').at(3).text()).toEqual('navigation.profile') }) + it('has a link to the community area', () => { + expect(wrapper.findAll('.nav-item').at(4).text()).toContain('navigation.community') + }) it('has a link to the members area', () => { - expect(wrapper.findAll('.nav-item').at(4).text()).toContain('navigation.members_area') - expect(wrapper.findAll('.nav-item').at(4).find('a').attributes('href')).toBe('#') + expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.members_area') + expect(wrapper.findAll('.nav-item').at(5).find('a').attributes('href')).toBe('#') }) it('has first nav-item "navigation.admin_area" in navbar', () => { - expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.admin_area') + expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('navigation.admin_area') }) it('has first nav-item "navigation.logout" in navbar', () => { - expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('navigation.logout') + expect(wrapper.findAll('.nav-item').at(7).text()).toEqual('navigation.logout') }) }) }) diff --git a/frontend/src/routes/router.test.js b/frontend/src/routes/router.test.js index 32ab90d4e..1edc6568b 100644 --- a/frontend/src/routes/router.test.js +++ b/frontend/src/routes/router.test.js @@ -50,7 +50,7 @@ describe('router', () => { }) it('has sixteen routes defined', () => { - expect(routes).toHaveLength(16) + expect(routes).toHaveLength(17) }) describe('overview', () => { From 4d622ee52cbaf065f6882359d5ceced1d32c0988 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 11 Jul 2022 14:53:57 +0200 Subject: [PATCH 056/528] add test for Community.vue --- frontend/src/pages/Community.spec.js | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 frontend/src/pages/Community.spec.js diff --git a/frontend/src/pages/Community.spec.js b/frontend/src/pages/Community.spec.js new file mode 100644 index 000000000..30bb2acda --- /dev/null +++ b/frontend/src/pages/Community.spec.js @@ -0,0 +1,41 @@ +import { mount } from '@vue/test-utils' +import Community from './Community' +// import { createContribution } from '@/graphql/mutations' + +// import { toastErrorSpy } from '@test/testSetup' + +const localVue = global.localVue + +const apolloMutationMock = jest.fn() +apolloMutationMock.mockResolvedValue('success') + +describe('Community', () => { + let wrapper + + const mocks = { + $t: jest.fn((t) => t), + $apollo: { + mutate: apolloMutationMock, + }, + $route: { + query: {}, + }, + } + + const Wrapper = () => { + return mount(Community, { + localVue, + mocks, + }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('has a components community-page', () => { + expect(wrapper.find('div.community-page').exists()).toBe(true) + }) + }) +}) From 280f386a35be55150d17e262cfeeb92fbb454052 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 11 Jul 2022 14:54:35 +0200 Subject: [PATCH 057/528] change text for fromular, change disable submit --- .../Contributions/ContributionForm.vue | 25 ++++++++++++++++--- frontend/src/locales/de.json | 9 ++++++- frontend/src/locales/en.json | 9 ++++++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index ac59959a1..67db69f5b 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -1,6 +1,18 @@ diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 552b7f0a7..12ebc86b3 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -35,10 +35,10 @@ "activity": "Tätigkeit", "formText": { "h3": "Dein Beitrag zum Gemeinwohl", - "lastMonth": "Für Juni 2022 kannst du noch 200 GDD einreichen .", + "lastMonth": "Für {month} {year} kannst du noch {creation} GDD einreichen.", "text1": "Bring dich mit deinen Talenten in die Gemeinschaft ein! Dein freiwilliges Engagement honorieren wir mit 20 GDD pro Stunde bis maximal 1.000 GDD im Monat.", "text2": "Beschreibe deine Gemeinwohl-Tätigkeit mit Angabe der Stunden und trage einen Betrag von 20 GDD pro Stunde ein! Nach Bestätigung durch einen Moderator wird der Betrag deinem Konto gutgeschrieben.", - "thisMonth": "Für Juli 2022 kannst du noch 500 GDD einreichen. " + "thisMonth": "Für {month} {year} kannst du noch {creation} GDD einreichen. " }, "noDateSelected": "Kein Datum ausgewählt", "submit": "Einreichen" diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index a25d2da56..1ef7052d5 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -35,10 +35,10 @@ "activity": "Activity", "formText": { "h3": "Your contribution to the common good", - "lastMonth": "For June 2022, you can still submit 200 GDD.", + "lastMonth": "For {month} {year}, you can still submit {creation} GDD.", "text1": "Bring your talents to the community! Your voluntary commitment will be rewarded with 20 GDD per hour up to a maximum of 1,000 GDD per month.", "text2": "Describe your community service activity with hours and enter an amount of 20 GDD per hour! After confirmation by a moderator, the amount will be credited to your account.", - "thisMonth": "For July 2022, you can still submit 500 GDD." + "thisMonth": "For {month} {year}, you can still submit {creation} GDD." }, "noDateSelected": "No date selected", "submit": "Submit" From 910ba6bbdf7630c85db5c1d919ff89d92dc8d722 Mon Sep 17 00:00:00 2001 From: ogerly Date: Wed, 13 Jul 2022 08:54:28 +0200 Subject: [PATCH 075/528] moved from v-html to computed --- .../Contributions/ContributionForm.vue | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index edbaca6de..072f6c04d 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -4,8 +4,8 @@

{{ $t('contribution.formText.h3') }}

{{ $t('contribution.formText.text1') }}
    -
  • -
  • +
  • +
@@ -39,7 +39,6 @@ class="text-right" :class="form.memo.length < minlength ? 'text-danger' : 'text-success'" > - {{ form.memo.length }} {{ $t('math.equalTo') }} {{ minlength }} {{ $t('math.divide') }} {{ maxlength }}
@@ -65,10 +64,10 @@ From 6dd11a961ffbdaba903f3bb4eb6f253e5e768732 Mon Sep 17 00:00:00 2001 From: ogerly Date: Wed, 13 Jul 2022 09:04:14 +0200 Subject: [PATCH 076/528] resolve merge conflict for ContributionResolver.ts 2 --- backend/src/graphql/resolver/ContributionResolver.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index bfce1ba03..4424b40d0 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -3,7 +3,6 @@ import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { Contribution as dbContribution } from '@entity/Contribution' import { Arg, Args, Authorized, Ctx, Mutation, Query, Resolver } from 'type-graphql' -<<<<<<< HEAD import { FindOperator, IsNull } from '@dbTools/typeorm' import ContributionArgs from '@arg/ContributionArgs' import Paginated from '@arg/Paginated' @@ -11,15 +10,6 @@ import { Order } from '@enum/Order' import { Contribution } from '@model/Contribution' import { UnconfirmedContribution } from '@model/UnconfirmedContribution' import { User } from '@model/User' -======= -import { IsNull, Not } from '../../../../database/node_modules/typeorm' -import ContributionArgs from '../arg/ContributionArgs' -import Paginated from '../arg/Paginated' -import { Order } from '../enum/Order' -import { Contribution } from '../model/Contribution' -import { UnconfirmedContribution } from '../model/UnconfirmedContribution' -import { User } from '../model/User' ->>>>>>> 193c7927e (resolve conflict) import { validateContribution, getUserCreation } from './util/creations' @Resolver() From 9d9d1a78f18abda66333139ac1b4ffd66e631607 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 13 Jul 2022 11:01:44 +0200 Subject: [PATCH 077/528] Add confirmedBy and confirmedAt for the contribution query. --- backend/src/graphql/model/Contribution.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/graphql/model/Contribution.ts b/backend/src/graphql/model/Contribution.ts index dc1dd39e9..348a6eb98 100644 --- a/backend/src/graphql/model/Contribution.ts +++ b/backend/src/graphql/model/Contribution.ts @@ -12,6 +12,8 @@ export class Contribution { this.memo = contribution.memo this.createdAt = contribution.createdAt this.deletedAt = contribution.deletedAt + this.confirmedAt = contribution.confirmedAt + this.confirmedBy = contribution.confirmedBy } @Field(() => Number) @@ -31,6 +33,12 @@ export class Contribution { @Field(() => Date, { nullable: true }) deletedAt: Date | null + + @Field(() => Date, { nullable: true }) + confirmedAt: Date | null + + @Field(() => Number, { nullable: true }) + confirmedBy: number | null } @ObjectType() From b0df5996e0f8f4029a23120855bf04656d357eac Mon Sep 17 00:00:00 2001 From: ogerly Date: Wed, 13 Jul 2022 11:06:29 +0200 Subject: [PATCH 078/528] change computed lastMonthObject --- .../Contributions/ContributionForm.vue | 14 +---- frontend/src/graphql/queries.js | 22 +++++++ frontend/src/pages/Community.vue | 57 ++++++++++--------- 3 files changed, 56 insertions(+), 37 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index 072f6c04d..5eae4718f 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -57,7 +57,6 @@ {{ $t('contribution.submit') }} - {{ form }} @@ -102,19 +101,12 @@ export default { return false }, lastMonthObject() { - let obj = { - month: new Date(this.lastMonth).toLocaleString(this.$i18n.locale, { month: 'long' }), - year: new Date().getFullYear(), - creation: this.$store.state.creation[1], - } - // If the current month is January then the current year must be counted back by -1. - if (new Date().getMonth === 1) { - obj = { + // new Date().getMonth === 1 If the current month is January, then one year must be gone back in the previous month + const obj = { month: new Date(this.lastMonth).toLocaleString(this.$i18n.locale, { month: 'long' }), - year: new Date().getFullYear() - 1, + year: new Date().getMonth === 1 ? new Date().getFullYear() - 1 : new Date().getFullYear(), creation: this.$store.state.creation[1], } - } return this.$t('contribution.formText.lastMonth', obj) }, thisMonthObject() { diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index 27e63d568..a25c4b4f4 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -162,3 +162,25 @@ export const listTransactionLinks = gql` } } ` + +export const listContributions = gql` + query( + $currentPage: Int = 1 + $pageSize: Int = 25 + $order: Order = DESC + $filterConfirmed: Boolean = false + ) { + listContributions( + currentPage: $currentPage + pageSize: $pageSize + order: $order + filterConfirmed: $filterConfirmed + ) { + id + amount + memo + createdAt + deletedAt + } + } +` diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 0559ea3e8..dc7c22aa0 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -20,6 +20,7 @@ import ContributionForm from '@/components/Contributions/ContributionForm.vue' import ContributionList from '@/components/Contributions/ContributionList.vue' import { createContribution } from '@/graphql/mutations' +import { listContributions } from '@/graphql/queries' export default { name: 'Community', @@ -29,39 +30,18 @@ export default { }, data() { return { - items: [ - { - id: '0', - date: '07/06/2022', - memo: 'Ich habe 10 Stunden die Elbwiesen von Müll befreit.', - amount: 200, - status: 'pending', - }, - { - id: '1', - date: '06/22/2022', - memo: 'Ich habe 30 Stunden Frau Müller beim EInkaufen und im Haushalt geholfen.', - amount: 600, - status: 'pending', - }, - { - id: '2', - date: '05/04/2022', - memo: - 'Ich habe 50 Stunden den Nachbarkindern bei ihren Hausaufgaben geholfen und Nachhilfeunterricht gegeben.', - amount: 1000, - status: 'pending', - }, - ], + currentPage: 1, + pageSize: 25, + items: [], } }, methods: { setContribution(data) { // console.log('setContribution', data) this.$apollo - .query({ + .mutate({ fetchPolicy: 'no-cache', - query: createContribution, + mutation: createContribution, variables: { creationDate: data.date, memo: data.memo, @@ -76,6 +56,31 @@ export default { this.toastError(err.message) }) }, + getListContributions(data) { + this.$apollo + .query({ + fetchPolicy: 'no-cache', + query: listContributions, + variables: { + currentPage: this.currentPage, + pageSize: this.pageSize, + }, + }) + .then((result) => { + console.log('result', result.data) + const { + data: { listContributions }, + } = result + this.items = listContributions + // this.toastSuccess(result.data) + }) + .catch((err) => { + this.toastError(err.message) + }) + }, + }, + created() { + this.getListContributions() }, } From 802a629d2684d03647f1dd80b01cd9585a07fa2a Mon Sep 17 00:00:00 2001 From: ogerly Date: Wed, 13 Jul 2022 11:12:33 +0200 Subject: [PATCH 079/528] remove console statement --- .../src/components/Contributions/ContributionForm.vue | 10 +++++----- frontend/src/pages/Community.vue | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index 5eae4718f..a788e1563 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -101,12 +101,12 @@ export default { return false }, lastMonthObject() { - // new Date().getMonth === 1 If the current month is January, then one year must be gone back in the previous month + // new Date().getMonth === 1 If the current month is January, then one year must be gone back in the previous month const obj = { - month: new Date(this.lastMonth).toLocaleString(this.$i18n.locale, { month: 'long' }), - year: new Date().getMonth === 1 ? new Date().getFullYear() - 1 : new Date().getFullYear(), - creation: this.$store.state.creation[1], - } + month: new Date(this.lastMonth).toLocaleString(this.$i18n.locale, { month: 'long' }), + year: new Date().getMonth === 1 ? new Date().getFullYear() - 1 : new Date().getFullYear(), + creation: this.$store.state.creation[1], + } return this.$t('contribution.formText.lastMonth', obj) }, thisMonthObject() { diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index dc7c22aa0..c639ec969 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -67,7 +67,7 @@ export default { }, }) .then((result) => { - console.log('result', result.data) + // console.log('result', result.data) const { data: { listContributions }, } = result From 99c4e8367048fe1d100a307be5febd84b6036177 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 13 Jul 2022 11:26:18 +0200 Subject: [PATCH 080/528] Add deleted contribution to the list of contribution. --- backend/src/graphql/resolver/ContributionResolver.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 4424b40d0..562859116 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -58,6 +58,7 @@ export class ContributionResolver { order: { createdAt: order, }, + withDeleted: true, skip: (currentPage - 1) * pageSize, take: pageSize, }) From ffe8831d090557efd107e4499cfa29ec6b2567af Mon Sep 17 00:00:00 2001 From: ogerly Date: Wed, 13 Jul 2022 11:28:35 +0200 Subject: [PATCH 081/528] change listContributions query add confirmedBy and confirmedAt --- frontend/src/graphql/queries.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/graphql/queries.js b/frontend/src/graphql/queries.js index a25c4b4f4..a523d18a1 100644 --- a/frontend/src/graphql/queries.js +++ b/frontend/src/graphql/queries.js @@ -181,6 +181,8 @@ export const listContributions = gql` memo createdAt deletedAt + confirmedBy + confirmedAt } } ` From b7c24978392ae1f74baf3442ed32521d167c6637 Mon Sep 17 00:00:00 2001 From: elweyn Date: Wed, 13 Jul 2022 12:18:47 +0200 Subject: [PATCH 082/528] Add new right LIST_ALL_CONFIRMED_CONTRIBUTIONS. --- backend/src/auth/RIGHTS.ts | 1 + backend/src/auth/ROLES.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/backend/src/auth/RIGHTS.ts b/backend/src/auth/RIGHTS.ts index 6a6f8b7c0..975c2006a 100644 --- a/backend/src/auth/RIGHTS.ts +++ b/backend/src/auth/RIGHTS.ts @@ -27,6 +27,7 @@ export enum RIGHTS { GDT_BALANCE = 'GDT_BALANCE', CREATE_CONTRIBUTION = 'CREATE_CONTRIBUTION', LIST_CONTRIBUTIONS = 'LIST_CONTRIBUTIONS', + LIST_ALL_CONFIRMED_CONTRIBUTIONS = 'LIST_ALL_CONFIRMED_CONTRIBUTIONS', // Admin SEARCH_USERS = 'SEARCH_USERS', SET_USER_ROLE = 'SET_USER_ROLE', diff --git a/backend/src/auth/ROLES.ts b/backend/src/auth/ROLES.ts index f56106664..e5628bb62 100644 --- a/backend/src/auth/ROLES.ts +++ b/backend/src/auth/ROLES.ts @@ -25,6 +25,7 @@ export const ROLE_USER = new Role('user', [ RIGHTS.GDT_BALANCE, RIGHTS.CREATE_CONTRIBUTION, RIGHTS.LIST_CONTRIBUTIONS, + RIGHTS.LIST_ALL_CONFIRMED_CONTRIBUTIONS, ]) export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights From eb404cf8b3e0d106f18a12883a00bccb4e9dfc57 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 13 Jul 2022 14:30:46 +0200 Subject: [PATCH 083/528] add migrations to insert contributions to all transactions with type creation that do not have a contribution yet --- .../0043-insert_missing_contributions.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 database/migrations/0043-insert_missing_contributions.ts diff --git a/database/migrations/0043-insert_missing_contributions.ts b/database/migrations/0043-insert_missing_contributions.ts new file mode 100644 index 000000000..a14141498 --- /dev/null +++ b/database/migrations/0043-insert_missing_contributions.ts @@ -0,0 +1,34 @@ +/* MIGRATION TO INSERT contributions for all transactions with type creation that do not have a contribution yet */ + +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + `INSERT INTO gradido_community.contributions + (user_id, created_at, contribution_date, memo, amount, moderator_id, confirmed_by, confirmed_at, transaction_id) +SELECT + user_id, + balance_date, + creation_date AS contribution_date, + memo, + amount, + 20 AS moderator_id, + 502 AS confirmed_by, + balance_date AS confirmed_at, + id +FROM + gradido_community.transactions +WHERE + type_id = 1 + AND NOT EXISTS( + SELECT * FROM gradido_community.contributions + WHERE gradido_community.contributions.transaction_id = gradido_community.transactions.id);`, + ) +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn( + 'DELETE FROM `contributions` WHERE `contributions`.`moderator_id` = 20 AND `contributions`.`confirmed_by` = 502 AND `contributions`.`created_at` = `contributions`.`confirmed_at`;', + ) +} From bdcbb196b77fc16cd165e898c7d54bf9b5aef6f1 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 13 Jul 2022 14:31:31 +0200 Subject: [PATCH 084/528] update database version --- backend/src/config/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 8b84c059d..208425792 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -10,7 +10,7 @@ Decimal.set({ }) const constants = { - DB_VERSION: '0042-update_transactions_for_blockchain', + DB_VERSION: '0043-insert_missing_contributions', DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0 LOG4JS_CONFIG: 'log4js-config.json', // default log level on production should be info From 14619384a4f7171f8505fa9047480309814ccde5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus-Peter=20H=C3=BCbner?= Date: Wed, 13 Jul 2022 18:52:11 +0200 Subject: [PATCH 085/528] remove comments --- backend/src/event/Event.ts | 13 ------------- backend/src/event/EventProtocolEmitter.ts | 20 +------------------- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/backend/src/event/Event.ts b/backend/src/event/Event.ts index c51acf627..6f07661f1 100644 --- a/backend/src/event/Event.ts +++ b/backend/src/event/Event.ts @@ -2,19 +2,6 @@ import { EventProtocol } from '@entity/EventProtocol' import decimal from 'decimal.js-light' import { EventProtocolType } from './EventProtocolType' -/* -export interface EventInterface { - type: string - createdAt: Date - userId: number - xUserId?: number - xCommunityId?: number - transactionId?: number - contributionId?: number - amount?: Decimal -} -*/ - export class EventBasic { type: string createdAt: Date diff --git a/backend/src/event/EventProtocolEmitter.ts b/backend/src/event/EventProtocolEmitter.ts index 1040feb32..5991bbded 100644 --- a/backend/src/event/EventProtocolEmitter.ts +++ b/backend/src/event/EventProtocolEmitter.ts @@ -1,8 +1,6 @@ import { Event } from '@/event/Event' import { backendLogger as logger } from '@/server/logger' -// import { EventProtocolType } from './EventProtocolType' import { EventProtocol } from '@entity/EventProtocol' -// import { getConnection } from '@dbTools/typeorm' import CONFIG from '@/config' class EventProtocolEmitter { @@ -23,7 +21,7 @@ class EventProtocolEmitter { } public async writeEvent(event: Event): Promise { - // if (!eventProtocol.isEnabled()) return + if (!eventProtocol.isEnabled()) return logger.info(`writeEvent(${JSON.stringify(event)})`) const dbEvent = new EventProtocol() dbEvent.type = event.type @@ -38,19 +36,3 @@ class EventProtocolEmitter { } } export const eventProtocol = new EventProtocolEmitter() - -/* -eventProtocol.on('error', (err) => { - logger.error(`ERROR in EventProtocol: ${err}`) -}) - -eventProtocol.on('writeEvents', async (events: Event[]) => { - for (let i = 0; i < events.length; i++) { - await writeEvent(events[i]) - } -}) - -eventProtocol.on('writeEvent', async (event: Event) => { - await writeEvent(event) -}) -*/ From 84706e430b0d6fda8f818e18e512f5126b10ea57 Mon Sep 17 00:00:00 2001 From: ogerly Date: Thu, 14 Jul 2022 11:50:17 +0200 Subject: [PATCH 086/528] add slot ContributionListItem.vue, add verifyLogin, update store for creation --- .../Contributions/ContributionForm.vue | 1 + .../Contributions/ContributionList.vue | 52 ++++++++++++- .../Contributions/ContributionListItem.vue | 73 +++++++++++++++++++ frontend/src/pages/Community.vue | 51 ++++++++++--- 4 files changed, 164 insertions(+), 13 deletions(-) create mode 100644 frontend/src/components/Contributions/ContributionListItem.vue diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index a788e1563..20d7ff921 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -57,6 +57,7 @@ {{ $t('contribution.submit') }} + {{ $store.state }} diff --git a/frontend/src/components/Contributions/ContributionList.vue b/frontend/src/components/Contributions/ContributionList.vue index e3dc41b5f..e7fc930e6 100644 --- a/frontend/src/components/Contributions/ContributionList.vue +++ b/frontend/src/components/Contributions/ContributionList.vue @@ -1,17 +1,65 @@ diff --git a/frontend/src/components/Contributions/ContributionListItem.vue b/frontend/src/components/Contributions/ContributionListItem.vue new file mode 100644 index 000000000..11cb2266e --- /dev/null +++ b/frontend/src/components/Contributions/ContributionListItem.vue @@ -0,0 +1,73 @@ + + diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index c639ec969..6db97b5a0 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -6,12 +6,15 @@ - - - - - + + @@ -20,7 +23,7 @@ import ContributionForm from '@/components/Contributions/ContributionForm.vue' import ContributionList from '@/components/Contributions/ContributionList.vue' import { createContribution } from '@/graphql/mutations' -import { listContributions } from '@/graphql/queries' +import { listContributions, verifyLogin } from '@/graphql/queries' export default { name: 'Community', @@ -30,9 +33,10 @@ export default { }, data() { return { + items: [], currentPage: 1, pageSize: 25, - items: [], + contributionCount: 0, } }, methods: { @@ -51,19 +55,24 @@ export default { .then((result) => { // console.log('result', result.data) this.toastSuccess(result.data) + this.updateListContributions({ + currentPage: this.currentPage, + pageSize: this.pageSize, + }) + this.verifyLogin() }) .catch((err) => { this.toastError(err.message) }) }, - getListContributions(data) { + async updateListContributions(pagination) { this.$apollo .query({ fetchPolicy: 'no-cache', query: listContributions, variables: { - currentPage: this.currentPage, - pageSize: this.pageSize, + currentPage: pagination.currentPage, + pageSize: pagination.pageSize, }, }) .then((result) => { @@ -71,6 +80,7 @@ export default { const { data: { listContributions }, } = result + this.contributionCount = listContributions.length this.items = listContributions // this.toastSuccess(result.data) }) @@ -78,9 +88,28 @@ export default { this.toastError(err.message) }) }, + verifyLogin() { + this.$apollo + .query({ + query: verifyLogin, + fetchPolicy: 'network-only', + }) + .then((result) => { + const { + data: { verifyLogin }, + } = result + this.$store.dispatch('login', verifyLogin) + }) + .catch(() => { + this.$emit('logout') + }) + }, }, created() { - this.getListContributions() + this.updateListContributions({ + currentPage: this.currentPage, + pageSize: this.pageSize, + }) }, } From 7c698de325294811d144f6ac7bac058d44200735 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 14 Jul 2022 12:25:45 +0200 Subject: [PATCH 087/528] Add constructor to ContributionListResult. --- backend/src/graphql/model/Contribution.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/src/graphql/model/Contribution.ts b/backend/src/graphql/model/Contribution.ts index dc1dd39e9..989296848 100644 --- a/backend/src/graphql/model/Contribution.ts +++ b/backend/src/graphql/model/Contribution.ts @@ -35,6 +35,11 @@ export class Contribution { @ObjectType() export class ContributionListResult { + constructor(count: number, list: Contribution[]) { + this.linkCount = count + this.linkList = list + } + @Field(() => Int) linkCount: number From 2f90bd981126ef77f744beacb5fa8d27bc3cc225 Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 14 Jul 2022 12:58:01 +0200 Subject: [PATCH 088/528] Withdrew User from Contribution object and replaced it with userId, firstName and lastName. --- backend/src/graphql/model/Contribution.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/backend/src/graphql/model/Contribution.ts b/backend/src/graphql/model/Contribution.ts index 989296848..324b0ff07 100644 --- a/backend/src/graphql/model/Contribution.ts +++ b/backend/src/graphql/model/Contribution.ts @@ -7,7 +7,9 @@ import { User } from './User' export class Contribution { constructor(contribution: dbContribution, user: User) { this.id = contribution.id - this.user = user + this.userId = user ? user.id : null + this.firstName = user ? user.firstName : null + this.lastName = user ? user.lastName : null this.amount = contribution.amount this.memo = contribution.memo this.createdAt = contribution.createdAt @@ -17,8 +19,14 @@ export class Contribution { @Field(() => Number) id: number - @Field(() => User) - user: User + @Field(() => Number, { nullable: true }) + userId: number | null + + @Field(() => String, { nullable: true }) + firstName: string | null + + @Field(() => String, { nullable: true }) + lastName: string | null @Field(() => Decimal) amount: Decimal From c02f575780166a8f2e6c29df4a83ffac59fcd36d Mon Sep 17 00:00:00 2001 From: elweyn Date: Thu, 14 Jul 2022 12:59:21 +0200 Subject: [PATCH 089/528] Withdrew userid from contribution object. --- backend/src/graphql/model/Contribution.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/src/graphql/model/Contribution.ts b/backend/src/graphql/model/Contribution.ts index 324b0ff07..a1537244d 100644 --- a/backend/src/graphql/model/Contribution.ts +++ b/backend/src/graphql/model/Contribution.ts @@ -7,7 +7,6 @@ import { User } from './User' export class Contribution { constructor(contribution: dbContribution, user: User) { this.id = contribution.id - this.userId = user ? user.id : null this.firstName = user ? user.firstName : null this.lastName = user ? user.lastName : null this.amount = contribution.amount @@ -19,9 +18,6 @@ export class Contribution { @Field(() => Number) id: number - @Field(() => Number, { nullable: true }) - userId: number | null - @Field(() => String, { nullable: true }) firstName: string | null From af0f434d011171ec08c464db8c354624b0ab9d14 Mon Sep 17 00:00:00 2001 From: ogerly Date: Thu, 14 Jul 2022 15:22:38 +0200 Subject: [PATCH 090/528] add updateContribution --- .../Contributions/ContributionForm.vue | 26 ++++++++++++++----- .../Contributions/ContributionList.vue | 5 +++- .../Contributions/ContributionListItem.vue | 21 ++++++++++++--- frontend/src/pages/Community.vue | 18 +++++++++++-- 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index 20d7ff921..ff74786d6 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -16,7 +16,7 @@ {{ $t('contribution.activity') }} {{ $t('contribution.submit') }} - {{ $store.state }} + {{date}}, {{amount}}, {{ memo}} @@ -70,6 +70,12 @@ */ export default { name: 'ContributionForm', + props: { + id: { type: Number, required: false}, + date: { type: String, required: true}, + memo: { type: String, required: true}, + amount: { type: String, required: true}, + }, data() { return { minlength: 50, @@ -78,9 +84,9 @@ export default { min: new Date(new Date(new Date().setMonth(new Date().getMonth() - 1)).setDate(1)), max: new Date(), form: { - date: '', - memo: '', - amount: 0, + date: this.date, + memo: this.memo, + amount: this.amount, }, } }, @@ -119,5 +125,11 @@ export default { return this.$t('contribution.formText.thisMonth', obj) }, }, + watch: { + id(newId, oldId){ + console.log('eine id kommt mit') + } + + } } diff --git a/frontend/src/components/Contributions/ContributionList.vue b/frontend/src/components/Contributions/ContributionList.vue index e7fc930e6..c08d22c79 100644 --- a/frontend/src/components/Contributions/ContributionList.vue +++ b/frontend/src/components/Contributions/ContributionList.vue @@ -2,7 +2,7 @@
{{ items.length }}
- +
{{ $d(new Date(date), 'short') }}
{{ memo }}
-
+
-
- -
@@ -69,5 +77,10 @@ export default { return this.createdAt }, }, + methods: { + updateContribution(item) { + this.$emit('update-contribution', item) + }, + }, } diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 6db97b5a0..b5907aefa 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -1,14 +1,15 @@ From c170c48ac4bb41b4e2f8e1621fbf1f348a00547a Mon Sep 17 00:00:00 2001 From: ogerly Date: Fri, 15 Jul 2022 10:11:07 +0200 Subject: [PATCH 105/528] change for tests --- .../Contributions/ContributionForm.spec.js | 6 ++++++ .../Contributions/ContributionList.spec.js | 19 ++++++++++--------- frontend/src/components/Menu/Sidebar.spec.js | 8 ++++---- frontend/src/pages/Community.spec.js | 8 +++++--- frontend/src/pages/Community.vue | 4 ++++ 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.spec.js b/frontend/src/components/Contributions/ContributionForm.spec.js index 4d39e2942..633d0e1ae 100644 --- a/frontend/src/components/Contributions/ContributionForm.spec.js +++ b/frontend/src/components/Contributions/ContributionForm.spec.js @@ -8,6 +8,12 @@ describe('ContributionForm', () => { const mocks = { $t: jest.fn((t) => t), + $d: jest.fn((d) => d), + $store: { + state: { + creation: ["1000","1000","1000"], + }, + }, } const Wrapper = () => { diff --git a/frontend/src/components/Contributions/ContributionList.spec.js b/frontend/src/components/Contributions/ContributionList.spec.js index 7accfcad9..ba6e15786 100644 --- a/frontend/src/components/Contributions/ContributionList.spec.js +++ b/frontend/src/components/Contributions/ContributionList.spec.js @@ -8,31 +8,32 @@ describe('ContributionList', () => { const mocks = { $t: jest.fn((t) => t), + $d: jest.fn((d) => d), } const propsData = { + contributionCount: 3, + showPagination: true, + pageSize: 25, items: [ { - id: '0', + id: 0, date: '07/06/2022', memo: 'Ich habe 10 Stunden die Elbwiesen von Müll befreit.', - amount: 200, - status: 'pending', + amount: '200', }, { - id: '1', + id: 1, date: '06/22/2022', memo: 'Ich habe 30 Stunden Frau Müller beim EInkaufen und im Haushalt geholfen.', - amount: 600, - status: 'pending', + amount: '600', }, { - id: '2', + id: 2, date: '05/04/2022', memo: 'Ich habe 50 Stunden den Nachbarkindern bei ihren Hausaufgaben geholfen und Nachhilfeunterricht gegeben.', - amount: 1000, - status: 'pending', + amount: '1000', }, ], } diff --git a/frontend/src/components/Menu/Sidebar.spec.js b/frontend/src/components/Menu/Sidebar.spec.js index 982192a8f..afee93def 100644 --- a/frontend/src/components/Menu/Sidebar.spec.js +++ b/frontend/src/components/Menu/Sidebar.spec.js @@ -47,11 +47,11 @@ describe('Sidebar', () => { it('has first nav-item "navigation.transactions" in navbar', () => { expect(wrapper.findAll('.nav-item').at(2).text()).toEqual('navigation.transactions') }) - it('has first nav-item "navigation.profile" in navbar', () => { - expect(wrapper.findAll('.nav-item').at(3).text()).toEqual('navigation.profile') - }) it('has a link to the community area', () => { - expect(wrapper.findAll('.nav-item').at(4).text()).toContain('navigation.community') + expect(wrapper.findAll('.nav-item').at(3).text()).toContain('navigation.community') + }) + it('has first nav-item "navigation.profile" in navbar', () => { + expect(wrapper.findAll('.nav-item').at(4).text()).toEqual('navigation.profile') }) it('has a link to the members area', () => { expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.members_area') diff --git a/frontend/src/pages/Community.spec.js b/frontend/src/pages/Community.spec.js index 7f1540369..a90f035ee 100644 --- a/frontend/src/pages/Community.spec.js +++ b/frontend/src/pages/Community.spec.js @@ -1,11 +1,9 @@ import { mount } from '@vue/test-utils' import Community from './Community' -// import { createContribution } from '@/graphql/mutations' - -// import { toastErrorSpy } from '@test/testSetup' const localVue = global.localVue +const mockStoreDispach = jest.fn() const apolloMutationMock = jest.fn() apolloMutationMock.mockResolvedValue('success') @@ -14,9 +12,13 @@ describe('Community', () => { const mocks = { $t: jest.fn((t) => t), + $d: jest.fn((d) => d), $apollo: { mutate: apolloMutationMock, }, + $store: { + dispatch: mockStoreDispach, + }, } const Wrapper = () => { diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 4774fc3c0..ddf4333bf 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -118,12 +118,16 @@ export default { this.form.memo = item.memo this.form.amount = item.amount }, + updateTransactions(pagination) { + this.$emit('update-transactions', pagination) + }, }, created() { this.updateListContributions({ currentPage: this.currentPage, pageSize: this.pageSize, }) + this.updateTransactions(0) }, } From 9efb83b2afe953d9e3b63811a65ec500b48de991 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 15 Jul 2022 11:01:36 +0200 Subject: [PATCH 106/528] fix tests --- .../Contributions/ContributionForm.spec.js | 2 +- .../Contributions/ContributionListItem.vue | 16 +++++++------- frontend/src/pages/Community.spec.js | 21 ++++++++++++++++++- frontend/src/pages/Community.vue | 2 +- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.spec.js b/frontend/src/components/Contributions/ContributionForm.spec.js index 633d0e1ae..44fa170b1 100644 --- a/frontend/src/components/Contributions/ContributionForm.spec.js +++ b/frontend/src/components/Contributions/ContributionForm.spec.js @@ -11,7 +11,7 @@ describe('ContributionForm', () => { $d: jest.fn((d) => d), $store: { state: { - creation: ["1000","1000","1000"], + creation: ['1000', '1000', '1000'], }, }, } diff --git a/frontend/src/components/Contributions/ContributionListItem.vue b/frontend/src/components/Contributions/ContributionListItem.vue index 499c23e63..cbc986326 100644 --- a/frontend/src/components/Contributions/ContributionListItem.vue +++ b/frontend/src/components/Contributions/ContributionListItem.vue @@ -57,23 +57,23 @@ export default { }, computed: { type() { - if (this.deletedAt !== null) return 'deleted' - if (this.confirmedAt !== null) return 'confirmed' + if (this.deletedAt) return 'deleted' + if (this.confirmedAt) return 'confirmed' return 'pending' }, icon() { - if (this.deletedAt !== null) return 'x-circle' - if (this.confirmedAt !== null) return 'check' + if (this.deletedAt) return 'x-circle' + if (this.confirmedAt) return 'check' return 'bell-fill' }, variant() { - if (this.deletedAt !== null) return 'danger' - if (this.confirmedAt !== null) return 'success' + if (this.deletedAt) return 'danger' + if (this.confirmedAt) return 'success' return 'primary' }, date() { - if (this.deletedAt !== null) return this.deletedAt - if (this.confirmedAt !== null) return this.confirmedAt + if (this.deletedAt) return this.deletedAt + if (this.confirmedAt) return this.confirmedAt return this.createdAt }, }, diff --git a/frontend/src/pages/Community.spec.js b/frontend/src/pages/Community.spec.js index a90f035ee..efb96cc67 100644 --- a/frontend/src/pages/Community.spec.js +++ b/frontend/src/pages/Community.spec.js @@ -4,8 +4,23 @@ import Community from './Community' const localVue = global.localVue const mockStoreDispach = jest.fn() +const apolloQueryMock = jest.fn() const apolloMutationMock = jest.fn() -apolloMutationMock.mockResolvedValue('success') +apolloQueryMock.mockResolvedValue({ + data: { + listContributions: [ + { + id: 1555, + amount: '200', + memo: 'Fleisig, fleisig am Arbeiten mein Lieber Freund, 50 Zeichen sind viel', + createdAt: '2022-07-15T08:47:06.000Z', + deletedAt: null, + confirmedBy: null, + confirmedAt: null, + }, + ], + }, +}) describe('Community', () => { let wrapper @@ -14,10 +29,14 @@ describe('Community', () => { $t: jest.fn((t) => t), $d: jest.fn((d) => d), $apollo: { + query: apolloQueryMock, mutate: apolloMutationMock, }, $store: { dispatch: mockStoreDispach, + state: { + creation: ['1000', '1000', '1000'], + }, }, } diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index ddf4333bf..42102a005 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -73,7 +73,7 @@ export default { this.toastError(err.message) }) }, - async updateListContributions(pagination) { + updateListContributions(pagination) { this.$apollo .query({ fetchPolicy: 'no-cache', From 66f10df1d0d656758213eb83ed89b263c77e2ff7 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Fri, 15 Jul 2022 11:23:03 +0200 Subject: [PATCH 107/528] improve logic and date handling. use v-model for form --- .../Contributions/ContributionForm.vue | 21 ++++--------------- frontend/src/pages/Community.vue | 5 +++-- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index 1a43e87ef..777806c30 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -12,7 +12,6 @@ {{ $t('contribution.formText.text2') }} - {{ id }} diff --git a/frontend/src/pages/Community.vue b/frontend/src/pages/Community.vue index 42102a005..ee2cc0aff 100644 --- a/frontend/src/pages/Community.vue +++ b/frontend/src/pages/Community.vue @@ -3,7 +3,7 @@
- + Date: Fri, 15 Jul 2022 13:36:31 +0200 Subject: [PATCH 108/528] feat: Do not log IntrospectionQuery from Query Browser --- backend/src/server/plugins.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/backend/src/server/plugins.ts b/backend/src/server/plugins.ts index 1972bc1c8..24df45baa 100644 --- a/backend/src/server/plugins.ts +++ b/backend/src/server/plugins.ts @@ -31,20 +31,24 @@ const filterVariables = (variables: any) => { const logPlugin = { requestDidStart(requestContext: any) { const { logger } = requestContext - const { query, mutation, variables } = requestContext.request - logger.info(`Request: + const { query, mutation, variables, operationName } = requestContext.request + if (operationName !== 'IntrospectionQuery') { + logger.info(`Request: ${mutation || query}variables: ${JSON.stringify(filterVariables(variables), null, 2)}`) + } return { willSendResponse(requestContext: any) { - if (requestContext.context.user) logger.info(`User ID: ${requestContext.context.user.id}`) - if (requestContext.response.data) { - logger.info('Response Success!') - logger.trace(`Response-Data: + if (operationName !== 'IntrospectionQuery') { + if (requestContext.context.user) logger.info(`User ID: ${requestContext.context.user.id}`) + if (requestContext.response.data) { + logger.info('Response Success!') + logger.trace(`Response-Data: ${JSON.stringify(requestContext.response.data, null, 2)}`) - } - if (requestContext.response.errors) - logger.error(`Response-Errors: + } + if (requestContext.response.errors) + logger.error(`Response-Errors: ${JSON.stringify(requestContext.response.errors, null, 2)}`) + } return requestContext }, } From d0662270431f112710c23748c72c6577c99eef3e Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 15 Jul 2022 14:13:33 +0200 Subject: [PATCH 109/528] Change the Contribution entity to join on user. --- .../0039-contributions_table/Contribution.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/database/entity/0039-contributions_table/Contribution.ts b/database/entity/0039-contributions_table/Contribution.ts index 6c7358f90..ee6e0f73f 100644 --- a/database/entity/0039-contributions_table/Contribution.ts +++ b/database/entity/0039-contributions_table/Contribution.ts @@ -1,6 +1,15 @@ import Decimal from 'decimal.js-light' -import { BaseEntity, Column, Entity, PrimaryGeneratedColumn, DeleteDateColumn } from 'typeorm' +import { + BaseEntity, + Column, + Entity, + PrimaryGeneratedColumn, + DeleteDateColumn, + OneToOne, + JoinColumn, +} from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' +import { User } from '../User' @Entity('contributions') export class Contribution extends BaseEntity { @@ -10,6 +19,10 @@ export class Contribution extends BaseEntity { @Column({ unsigned: true, nullable: false, name: 'user_id' }) userId: number + @OneToOne(() => User) + @JoinColumn({ name: 'user_id' }) + user: User + @Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP', name: 'created_at' }) createdAt: Date From 5f5c19e6ba364ee036284fb47a197a6da3683832 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 15 Jul 2022 14:14:15 +0200 Subject: [PATCH 110/528] Change find to much more efficient code. --- .../graphql/resolver/ContributionResolver.ts | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 812e81527..d71ecac59 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -2,7 +2,6 @@ import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { Contribution as dbContribution } from '@entity/Contribution' -import { User as dbUser } from '@entity/User' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' import { FindOperator, IsNull } from '@dbTools/typeorm' import ContributionArgs from '@arg/ContributionArgs' @@ -72,31 +71,20 @@ export class ContributionResolver { @Args() { currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated, ): Promise { - const dbContributions = await dbContribution.find({ + const [dbContributions, count] = await dbContribution.findAndCount({ + relations: ['user'], order: { createdAt: order, }, skip: (currentPage - 1) * pageSize, take: pageSize, }) - const contributions: Contribution[] = [] - const userIds: number[] = [] - dbContributions.forEach(async (dbContribution) => { - userIds.push(dbContribution.userId) - }) - userIds.filter((elem, index, self) => { - return index === self.indexOf(elem) - }) - const users = new Map() - for (let i = 0; i < userIds.length; i++) { - const id = userIds[i] - const user = await dbUser.findOneOrFail({ id }) - users.set(id, user) - } - dbContributions.forEach((dbContribution) => { - contributions.push(new Contribution(dbContribution, users.get(dbContribution.userId))) - }) - return new ContributionListResult(contributions.length, contributions) + return new ContributionListResult( + count, + dbContributions.map( + (contribution) => new Contribution(contribution, new User(contribution.user)), + ), + ) } @Authorized([RIGHTS.UPDATE_CONTRIBUTION]) From 382211f3ca12fa9585ef853751d886672997876e Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 15 Jul 2022 14:14:55 +0200 Subject: [PATCH 111/528] Adapt test so that we check findAllContributions. --- .../src/graphql/resolver/ContributionResolver.test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 247d1be0e..fd5ff68a2 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -466,15 +466,14 @@ describe('ContributionResolver', () => { beforeAll(async () => { await userFactory(testEnv, bibiBloxberg) await userFactory(testEnv, peterLustig) - await userFactory(testEnv, raeuberHotzenplotz) - await userFactory(testEnv, bobBaumeister) + const bibisCreation = creations.find((creation) => creation.email === 'bibi@bloxberg.de') // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - creations.forEach(async (creation) => await creationFactory(testEnv, creation!)) + await creationFactory(testEnv, bibisCreation!) await query({ query: login, variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' }, }) - result = await mutate({ + await mutate({ mutation: createContribution, variables: { amount: 100.0, @@ -499,7 +498,7 @@ describe('ContributionResolver', () => { expect.objectContaining({ data: { listAllContributions: { - linkCount: 25, + linkCount: 2, linkList: expect.arrayContaining([ expect.objectContaining({ id: expect.any(Number), From cada4eca19cfa95b3ba7603838f2f163effb05ad Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 15 Jul 2022 14:32:20 +0200 Subject: [PATCH 112/528] Change OneToOne relation to OneToMany / ManyToOne. --- .../0039-contributions_table/Contribution.ts | 3 ++- .../0040-add_contribution_link_id_to_user/User.ts | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/database/entity/0039-contributions_table/Contribution.ts b/database/entity/0039-contributions_table/Contribution.ts index ee6e0f73f..5df527530 100644 --- a/database/entity/0039-contributions_table/Contribution.ts +++ b/database/entity/0039-contributions_table/Contribution.ts @@ -7,6 +7,7 @@ import { DeleteDateColumn, OneToOne, JoinColumn, + ManyToOne, } from 'typeorm' import { DecimalTransformer } from '../../src/typeorm/DecimalTransformer' import { User } from '../User' @@ -19,7 +20,7 @@ export class Contribution extends BaseEntity { @Column({ unsigned: true, nullable: false, name: 'user_id' }) userId: number - @OneToOne(() => User) + @ManyToOne(() => User, (user) => user.contributions) @JoinColumn({ name: 'user_id' }) user: User diff --git a/database/entity/0040-add_contribution_link_id_to_user/User.ts b/database/entity/0040-add_contribution_link_id_to_user/User.ts index 9bf76e5f5..56047345a 100644 --- a/database/entity/0040-add_contribution_link_id_to_user/User.ts +++ b/database/entity/0040-add_contribution_link_id_to_user/User.ts @@ -1,4 +1,13 @@ -import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, DeleteDateColumn } from 'typeorm' +import { + BaseEntity, + Entity, + PrimaryGeneratedColumn, + Column, + DeleteDateColumn, + OneToMany, + JoinColumn, +} from 'typeorm' +import { Contribution } from '../Contribution' @Entity('users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' }) export class User extends BaseEntity { @@ -76,4 +85,8 @@ export class User extends BaseEntity { default: null, }) passphrase: string + + @OneToMany(() => Contribution, (contribution) => contribution.user) + @JoinColumn({ name: 'user_id' }) + contributions?: Contribution[] } From 843993e34085397eb86b8e67477bf58e94debd6a Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 15 Jul 2022 14:34:47 +0200 Subject: [PATCH 113/528] Fix linting. --- backend/src/graphql/resolver/ContributionResolver.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index fd5ff68a2..e6478ffc2 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -14,8 +14,6 @@ import { userFactory } from '@/seeds/factory/user' import { creationFactory } from '@/seeds/factory/creation' import { creations } from '@/seeds/creation/index' import { peterLustig } from '@/seeds/users/peter-lustig' -import { bobBaumeister } from '@/seeds/users/bob-baumeister' -import { raeuberHotzenplotz } from '@/seeds/users/raeuber-hotzenplotz' let mutate: any, query: any, con: any let testEnv: any From 5892f7b42947db8270fe4d26a4faed587abe68c3 Mon Sep 17 00:00:00 2001 From: elweyn Date: Fri, 15 Jul 2022 14:48:51 +0200 Subject: [PATCH 114/528] Remove OneToOne import from contribution entity. --- database/entity/0039-contributions_table/Contribution.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/database/entity/0039-contributions_table/Contribution.ts b/database/entity/0039-contributions_table/Contribution.ts index 5df527530..b5e6ac0e0 100644 --- a/database/entity/0039-contributions_table/Contribution.ts +++ b/database/entity/0039-contributions_table/Contribution.ts @@ -5,7 +5,6 @@ import { Entity, PrimaryGeneratedColumn, DeleteDateColumn, - OneToOne, JoinColumn, ManyToOne, } from 'typeorm' From 5810235cec56053a6413b5601544a14b1d2b77db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus-Peter=20H=C3=BCbner?= Date: Fri, 15 Jul 2022 16:40:46 +0200 Subject: [PATCH 115/528] add EVENT_PROTOCOL_ENABLED --- deployment/bare_metal/.env.dist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 5747e40ef..a7f63fa27 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -53,6 +53,10 @@ EMAIL_CODE_REQUEST_TIME=10 WEBHOOK_ELOPAGE_SECRET=secret +# EventProtocol +EVENT_PROTOCOL_ENABLED=true + + # database DATABASE_CONFIG_VERSION=v1.2022-03-18 From 0b8e8988189f8c8a8a832e7102ae70e935e63185 Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 18 Jul 2022 11:12:21 +0200 Subject: [PATCH 116/528] refactor contribution form --- .../Contributions/ContributionForm.vue | 78 ++++++++++++++----- frontend/src/locales/de.json | 3 +- frontend/src/locales/en.json | 3 +- 3 files changed, 63 insertions(+), 21 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionForm.vue b/frontend/src/components/Contributions/ContributionForm.vue index 777806c30..08bfa635e 100644 --- a/frontend/src/components/Contributions/ContributionForm.vue +++ b/frontend/src/components/Contributions/ContributionForm.vue @@ -12,14 +12,14 @@ {{ $t('contribution.formText.text2') }}
- +
+ {{ form.memo.length }} {{ $t('math.equalTo') }} {{ minlength }} {{ $t('math.divide') }} {{ maxlength }}
@@ -49,15 +51,39 @@ v-model="form.amount" type="number" min="1" - max="1000" + :max="isThisMonth ? maxGddThisMonth : maxGddLastMonth" > - -
- - {{ $t('contribution.submit') }} - +
+ {{ + isThisMonth && form.amount > maxGddThisMonth + ? $t('contribution.formText.maxGDDforMonth', { amount: maxGddThisMonth }) + : '' + }} + {{ + !isThisMonth && form.amount > maxGddLastMonth + ? $t('contribution.formText.maxGDDforMonth', { amount: maxGddLastMonth }) + : '' + }}
+ + + + {{ $t('form.reset') }} + + + + + {{ id === null ? $t('contribution.submit') : $t('form.edit') }} + + +
@@ -69,36 +95,47 @@ export default { }, data() { return { + maxGddLastMonth: this.$store.state.creation[1], + maxGddThisMonth: this.$store.state.creation[2], minlength: 50, maxlength: 255, - max: new Date(), + maximalDate: new Date(), form: this.value, + id: this.value.id, } }, methods: { submit() { - this.$emit('set-contribution', this.form) + if (this.id === null) { + this.$emit('set-contribution', this.form) + } else { + this.$emit('edit-contribution', this.value) + } + this.reset() + }, + reset() { this.$refs.form.reset() this.form.date = '' + this.id = null + this.form.memo = '' }, }, computed: { /* * lastMonth() = The date set back by one month. - * min() = The date is reset by one month to the 1st of the previous month. + * minimalDate() = The date is reset by one month to the 1st of the previous month. * */ - lastMonth() { - return new Date(this.max.getFullYear(), this.max.getMonth() - 1, 1) - }, - min() { - return new Date(this.max.getFullYear(), this.max.getMonth() - 1, 1) + minimalDate() { + return new Date(this.maximalDate.getFullYear(), this.maximalDate.getMonth() - 1, 1) }, disabled() { if ( this.form.memo.length < this.minlength || this.form.amount <= 0 || - this.form.amount > 1000 + this.form.amount > 1000 || + (this.isThisMonth && this.form.amount > this.maxGddThisMonth) || + (!this.isThisMonth && this.form.amount > this.maxGddlastMonth) ) return true return false @@ -106,7 +143,7 @@ export default { lastMonthObject() { // new Date().getMonth === 1 If the current month is January, then one year must be gone back in the previous month const obj = { - monthAndYear: this.$d(new Date(this.lastMonth), 'monthAndYear'), + monthAndYear: this.$d(new Date(this.minimalDate), 'monthAndYear'), creation: this.$store.state.creation[1], } return this.$t('contribution.formText.lastMonth', obj) @@ -118,6 +155,9 @@ export default { } return this.$t('contribution.formText.thisMonth', obj) }, + isThisMonth() { + return new Date(this.form.date).getMonth() === new Date().getMonth() + }, }, } diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 5c8b8b366..bc27e4b3e 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -38,7 +38,8 @@ "lastMonth": "Für {monthAndYear} kannst du noch {creation} GDD einreichen.", "text1": "Bring dich mit deinen Talenten in die Gemeinschaft ein! Dein freiwilliges Engagement honorieren wir mit 20 GDD pro Stunde bis maximal 1.000 GDD im Monat.", "text2": "Beschreibe deine Gemeinwohl-Tätigkeit mit Angabe der Stunden und trage einen Betrag von 20 GDD pro Stunde ein! Nach Bestätigung durch einen Moderator wird der Betrag deinem Konto gutgeschrieben.", - "thisMonth": "Für {monthAndYear} kannst du noch {creation} GDD einreichen. " + "thisMonth": "Für {monthAndYear} kannst du noch {creation} GDD einreichen.", + "maxGDDforMonth":"Du kannst für den ausgewählten Monat nur noch maximal {amount} GDD einreichen." }, "noDateSelected": "Kein Datum ausgewählt", "submit": "Einreichen" diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 8b0df2595..304cae4c7 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -38,7 +38,8 @@ "lastMonth": "For {monthAndYear}, you can still submit {creation} GDD.", "text1": "Bring your talents to the community! Your voluntary commitment will be rewarded with 20 GDD per hour up to a maximum of 1,000 GDD per month.", "text2": "Describe your community service activity with hours and enter an amount of 20 GDD per hour! After confirmation by a moderator, the amount will be credited to your account.", - "thisMonth": "For {monthAndYear}, you can still submit {creation} GDD." + "thisMonth": "For {monthAndYear}, you can still submit {creation} GDD.", + "maxGDDforMonth":"You can only submit a maximum of {amount} GDD for the selected month." }, "noDateSelected": "No date selected", "submit": "Submit" From 1e4540ef71a23919d99eb5d9335319911f88a29d Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 18 Jul 2022 11:13:11 +0200 Subject: [PATCH 117/528] fix locales --- frontend/src/locales/de.json | 4 ++-- frontend/src/locales/en.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index bc27e4b3e..8676eba9f 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -36,10 +36,10 @@ "formText": { "h3": "Dein Beitrag zum Gemeinwohl", "lastMonth": "Für {monthAndYear} kannst du noch {creation} GDD einreichen.", + "maxGDDforMonth": "Du kannst für den ausgewählten Monat nur noch maximal {amount} GDD einreichen.", "text1": "Bring dich mit deinen Talenten in die Gemeinschaft ein! Dein freiwilliges Engagement honorieren wir mit 20 GDD pro Stunde bis maximal 1.000 GDD im Monat.", "text2": "Beschreibe deine Gemeinwohl-Tätigkeit mit Angabe der Stunden und trage einen Betrag von 20 GDD pro Stunde ein! Nach Bestätigung durch einen Moderator wird der Betrag deinem Konto gutgeschrieben.", - "thisMonth": "Für {monthAndYear} kannst du noch {creation} GDD einreichen.", - "maxGDDforMonth":"Du kannst für den ausgewählten Monat nur noch maximal {amount} GDD einreichen." + "thisMonth": "Für {monthAndYear} kannst du noch {creation} GDD einreichen." }, "noDateSelected": "Kein Datum ausgewählt", "submit": "Einreichen" diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 304cae4c7..4282c1086 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -36,10 +36,10 @@ "formText": { "h3": "Your contribution to the common good", "lastMonth": "For {monthAndYear}, you can still submit {creation} GDD.", + "maxGDDforMonth": "You can only submit a maximum of {amount} GDD for the selected month.", "text1": "Bring your talents to the community! Your voluntary commitment will be rewarded with 20 GDD per hour up to a maximum of 1,000 GDD per month.", "text2": "Describe your community service activity with hours and enter an amount of 20 GDD per hour! After confirmation by a moderator, the amount will be credited to your account.", - "thisMonth": "For {monthAndYear}, you can still submit {creation} GDD.", - "maxGDDforMonth":"You can only submit a maximum of {amount} GDD for the selected month." + "thisMonth": "For {monthAndYear}, you can still submit {creation} GDD." }, "noDateSelected": "No date selected", "submit": "Submit" From 93c2d6814ad1952105d1fbdc05f94ef174712c10 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:27:44 +0200 Subject: [PATCH 118/528] Change the listContribution query to give back ContributionListResult object with linkCount. --- backend/src/graphql/resolver/ContributionResolver.ts | 12 ++++++++---- backend/src/seeds/graphql/queries.ts | 9 ++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index d71ecac59..c834904d6 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -2,6 +2,7 @@ import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { Contribution as dbContribution } from '@entity/Contribution' +import { User as dbUser } from '@entity/User' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' import { FindOperator, IsNull } from '@dbTools/typeorm' import ContributionArgs from '@arg/ContributionArgs' @@ -39,21 +40,21 @@ export class ContributionResolver { } @Authorized([RIGHTS.LIST_CONTRIBUTIONS]) - @Query(() => [Contribution]) + @Query(() => ContributionListResult) async listContributions( @Args() { currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated, @Arg('filterConfirmed', () => Boolean) filterConfirmed: boolean | null, @Ctx() context: Context, - ): Promise { + ): Promise { const user = getUser(context) const where: { userId: number confirmedBy?: FindOperator | null } = { userId: user.id } if (filterConfirmed) where.confirmedBy = IsNull() - const contributions = await dbContribution.find({ + const [contributions, count] = await dbContribution.findAndCount({ where, order: { createdAt: order, @@ -62,7 +63,10 @@ export class ContributionResolver { skip: (currentPage - 1) * pageSize, take: pageSize, }) - return contributions.map((contribution) => new Contribution(contribution, new User(user))) + return new ContributionListResult( + count, + contributions.map((contribution) => new Contribution(contribution, new User(user))), + ) } @Authorized([RIGHTS.LIST_ALL_CONTRIBUTIONS]) diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index deae5f97b..e18d6b303 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -185,9 +185,12 @@ export const listContributions = gql` order: $order filterConfirmed: $filterConfirmed ) { - id - amount - memo + linkCount + linkList { + id + amount + memo + } } } ` From 495fbfd05ce3b16b3d081ed128854d0c32e014eb Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:31:04 +0200 Subject: [PATCH 119/528] Change linkCount to contributionCount and linkList to contributionList. --- backend/src/graphql/model/Contribution.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/graphql/model/Contribution.ts b/backend/src/graphql/model/Contribution.ts index 34bffd6d7..13c2d40d7 100644 --- a/backend/src/graphql/model/Contribution.ts +++ b/backend/src/graphql/model/Contribution.ts @@ -48,13 +48,13 @@ export class Contribution { @ObjectType() export class ContributionListResult { constructor(count: number, list: Contribution[]) { - this.linkCount = count - this.linkList = list + this.contributionCount = count + this.contributionList = list } @Field(() => Int) - linkCount: number + contributionCount: number @Field(() => [Contribution]) - linkList: Contribution[] + contributionList: Contribution[] } From 3a8fb6b353454452e344ae9eef76cfeea51ed8d4 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:31:39 +0200 Subject: [PATCH 120/528] Change query of listContribution to get contributionCount and contributionList instead of link... --- backend/src/seeds/graphql/queries.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index e18d6b303..0d72c165d 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -185,8 +185,8 @@ export const listContributions = gql` order: $order filterConfirmed: $filterConfirmed ) { - linkCount - linkList { + contributionCount + contributionList { id amount memo From 11dacd40be4c9fec9000253d1898ee536a3eb0c1 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:34:30 +0200 Subject: [PATCH 121/528] Change query listAllContributions now gets contributionCount and contributionList instead of linkCount and linkList. --- backend/src/seeds/graphql/queries.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index 0d72c165d..9f7a02e70 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -198,8 +198,8 @@ export const listContributions = gql` export const listAllContributions = ` query ($currentPage: Int = 1, $pageSize: Int = 5, $order: Order = DESC) { listAllContributions(currentPage: $currentPage, pageSize: $pageSize, order: $order) { - linkCount - linkList { + contributionCount + contributionList { id firstName lastName From 1ec317259b2e1b65eb70303355395c081d060004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 18 Jul 2022 11:35:31 +0200 Subject: [PATCH 122/528] Document the setup of the GraphQL Playground --- backend/README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/backend/README.md b/backend/README.md index e74750c46..173450fe7 100644 --- a/backend/README.md +++ b/backend/README.md @@ -1,16 +1,18 @@ # backend ## Project setup -``` + +```bash yarn install ``` ## Seed DB -``` + +```bash yarn seed ``` -Deletes all data in database. Then seeds data in database. +Deletes all data in database. Then seeds data in database. ## Seeded Users @@ -22,3 +24,47 @@ Deletes all data in database. Then seeds data in database. | bob@baumeister.de | `Aa12345_` | `false` | `true` | `false` | | garrick@ollivander.com | | `false` | `false` | `false` | | stephen@hawking.uk | `Aa12345_` | `false` | `true` | `true` | + +## Setup GraphQL Playground + +### Setup In The Code + +Setting up the GraphQL Playground in our code requires the following steps: + +- Create an empty `.env` file in the `backend` folder and set "GRAPHIQL=true" there. +- Start or restart Docker Compose. +- For verification, Docker should display `GraphQL available at http://localhost:4000` in the terminal. +- If you open "http://localhost:4000/" in your browser, you should see the GraphQL Playground. + +### Authentication + +To authenticate yourself in GraphQL Playground to be able to send queries and mutations, follow the steps below: + +- in Firefox go to "Network Analysis" and delete all entries +- enter and send the login query: + +```gql +{ + login(email: "bibi@bloxberg.de", password:"Aa12345_") { + id + publisherId + email + firstName + lastName + emailChecked + language + hasElopage + } +} +``` + +- search in Firefox under „Network Analysis" for the smallest size of a header and copy the token +- open the header section in GraphQL Playground and set your current token by filling in and replacing `XXX`: + +```qgl +{ + "Authorization": "XXX" +} +``` + +Now you can open a new tap in the Playground and enter your query or mutation there. From 42b8d625da34a908c5c3dd79254141f7bc5ee52f Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:38:58 +0200 Subject: [PATCH 123/528] Change query fields to new names. --- .../resolver/ContributionResolver.test.ts | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index e6478ffc2..37ff45f25 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -193,18 +193,21 @@ describe('ContributionResolver', () => { ).resolves.toEqual( expect.objectContaining({ data: { - listContributions: expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(Number), - memo: 'Herzlich Willkommen bei Gradido!', - amount: '1000', - }), - expect.objectContaining({ - id: expect.any(Number), - memo: 'Test env contribution', - amount: '100', - }), - ]), + listContributions: { + contributionCount: 2, + contributionList: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(Number), + memo: 'Herzlich Willkommen bei Gradido!', + amount: '1000', + }), + expect.objectContaining({ + id: expect.any(Number), + memo: 'Test env contribution', + amount: '100', + }), + ]), + }, }, }), ) @@ -226,13 +229,16 @@ describe('ContributionResolver', () => { ).resolves.toEqual( expect.objectContaining({ data: { - listContributions: expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(Number), - memo: 'Test env contribution', - amount: '100', - }), - ]), + listContributions: { + contributionCount: 1, + contributionList: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(Number), + memo: 'Test env contribution', + amount: '100', + }), + ]), + }, }, }), ) @@ -496,8 +502,8 @@ describe('ContributionResolver', () => { expect.objectContaining({ data: { listAllContributions: { - linkCount: 2, - linkList: expect.arrayContaining([ + contributionCount: 2, + contributionList: expect.arrayContaining([ expect.objectContaining({ id: expect.any(Number), memo: 'Herzlich Willkommen bei Gradido!', From ae04024dd38b56ed5e702fc7a9e37d183cf76066 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:39:17 +0200 Subject: [PATCH 124/528] Remove unused import. --- backend/src/graphql/resolver/ContributionResolver.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index c834904d6..f21c65068 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -2,7 +2,6 @@ import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { Contribution as dbContribution } from '@entity/Contribution' -import { User as dbUser } from '@entity/User' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' import { FindOperator, IsNull } from '@dbTools/typeorm' import ContributionArgs from '@arg/ContributionArgs' From 45013efd8da7fb5c366ddb1592650a3e897f624b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 18 Jul 2022 12:02:56 +0200 Subject: [PATCH 125/528] Remove forgotten to delete lines in Docker Compose Apple M1 override --- docker-compose.apple-m1.override.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docker-compose.apple-m1.override.yml b/docker-compose.apple-m1.override.yml index 7cf3efd3e..72152f9ae 100644 --- a/docker-compose.apple-m1.override.yml +++ b/docker-compose.apple-m1.override.yml @@ -41,12 +41,3 @@ services: ######################################################### nginx: platform: linux/amd64 - -networks: - external-net: - internal-net: - internal: true - -volumes: - db_vol: - From b7c49b2410ce18c7fdf6eca4ab0fd94553717445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 18 Jul 2022 12:24:29 +0200 Subject: [PATCH 126/528] Change Docker Compose image names and add comments wy --- docker-compose.override.yml | 19 ++++++++++++------- docker-compose.test.yml | 1 + docker-compose.yml | 13 +++++++++---- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 2583ea77c..9d3e0b8d4 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -1,11 +1,13 @@ version: "3.4" services: + ######################################################## # FRONTEND ############################################# ######################################################## frontend: - # image: gradido/frontend:development + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there + image: gradido/frontend:local-development build: target: development environment: @@ -22,7 +24,8 @@ services: # ADMIN INTERFACE ###################################### ######################################################## admin: - # image: gradido/admin:development + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there + image: gradido/admin:local-development build: target: development environment: @@ -39,7 +42,8 @@ services: # BACKEND ############################################## ######################################################## backend: - # image: gradido/backend:development + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there + image: gradido/backend:local-development build: target: development networks: @@ -62,10 +66,11 @@ services: ######################################################## database: # we always run on production here since else the service lingers - # feel free to change this behaviour if it seems useful - # Due to problems with the volume caching the built files - # we changed this to test build. This keeps the service running. - # image: gradido/database:test_up + # feel free to change this behaviour if it seems useful + # Due to problems with the volume caching the built files + # we changed this to test build. This keeps the service running. + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there + image: gradido/database:local-test_up build: target: test_up environment: diff --git a/docker-compose.test.yml b/docker-compose.test.yml index 221ecba20..7db318176 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -6,6 +6,7 @@ services: # BACKEND ############################################## ######################################################## backend: + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there image: gradido/backend:test build: target: test diff --git a/docker-compose.yml b/docker-compose.yml index 26a1ecbe2..6c0dffe15 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,11 +6,13 @@ version: "3.4" services: + ######################################################## # FRONTEND ############################################# ######################################################## frontend: - # image: gradido/frontend:latest + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there + image: gradido/frontend:local-production build: context: ./frontend target: production @@ -35,7 +37,8 @@ services: # ADMIN INTERFACE ###################################### ######################################################## admin: - # image: gradido/admin:latest + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there + image: gradido/admin:local-production build: context: ./admin target: production @@ -77,7 +80,8 @@ services: # BACKEND ############################################## ######################################################## backend: - # image: gradido/backend:latest + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there + image: gradido/backend:local-production build: # since we have to include the entities from ./database we cannot define the context as ./backend # this might blow build image size to the moon ?! @@ -108,7 +112,8 @@ services: # DATABASE ############################################# ######################################################## database: - #image: gradido/database:production_up + # name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there + image: gradido/database:local-production_up build: context: ./database target: production_up From c6279a3ba141f4a93dc29783ef42f718db517ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 18 Jul 2022 12:25:36 +0200 Subject: [PATCH 127/528] Update backend/README.md Co-authored-by: Hannes Heine --- backend/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/README.md b/backend/README.md index 173450fe7..c28469aa9 100644 --- a/backend/README.md +++ b/backend/README.md @@ -38,7 +38,7 @@ Setting up the GraphQL Playground in our code requires the following steps: ### Authentication -To authenticate yourself in GraphQL Playground to be able to send queries and mutations, follow the steps below: +You need to authenticate yourself in GraphQL Playground to be able to send queries and mutations, to do so follow the steps below: - in Firefox go to "Network Analysis" and delete all entries - enter and send the login query: From b7949a62201e5592a8ddc4d0c6af113a335d0903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 18 Jul 2022 12:25:58 +0200 Subject: [PATCH 128/528] Update backend/README.md Co-authored-by: Hannes Heine --- backend/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/README.md b/backend/README.md index c28469aa9..b27ab16d9 100644 --- a/backend/README.md +++ b/backend/README.md @@ -58,7 +58,7 @@ You need to authenticate yourself in GraphQL Playground to be able to send queri } ``` -- search in Firefox under „Network Analysis" for the smallest size of a header and copy the token +- search in Firefox under „Network Analysis" for the smallest size of a header and copy the value of the token - open the header section in GraphQL Playground and set your current token by filling in and replacing `XXX`: ```qgl From da3574edb81aa93a362aa61a69ff5cbd459fe5ba Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 12:35:42 +0200 Subject: [PATCH 129/528] Fix merge conflict and reviewed name changes. --- .../graphql/resolver/ContributionResolver.ts | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index 20eeaa199..90ec6b5a6 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -1,13 +1,6 @@ import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' -<<<<<<< HEAD -import { Contribution } from '@entity/Contribution' -import { Arg, Args, Authorized, Ctx, Int, Mutation, Resolver } from 'type-graphql' -import ContributionArgs from '../arg/ContributionArgs' -import { UnconfirmedContribution } from '../model/UnconfirmedContribution' -import { validateContribution, getUserCreation } from './util/creations' -======= import { Contribution as dbContribution } from '@entity/Contribution' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' import { FindOperator, IsNull } from '@dbTools/typeorm' @@ -18,7 +11,6 @@ import { Contribution, ContributionListResult } from '@model/Contribution' import { UnconfirmedContribution } from '@model/UnconfirmedContribution' import { User } from '@model/User' import { validateContribution, getUserCreation, updateCreations } from './util/creations' ->>>>>>> master @Resolver() export class ContributionResolver { @@ -46,15 +38,14 @@ export class ContributionResolver { return new UnconfirmedContribution(contribution, user, creations) } -<<<<<<< HEAD @Authorized([RIGHTS.DELETE_CONTRIBUTION]) @Mutation(() => Boolean) - async adminDeleteContribution( + async deleteContribution( @Arg('id', () => Int) id: number, @Ctx() context: Context, ): Promise { const user = getUser(context) - const contribution = await Contribution.findOne(id) + const contribution = await dbContribution.findOne(id) if (!contribution) { throw new Error('Contribution not found for given id.') } @@ -63,7 +54,8 @@ export class ContributionResolver { } const res = await contribution.softRemove() return !!res -======= + } + @Authorized([RIGHTS.LIST_CONTRIBUTIONS]) @Query(() => [Contribution]) async listContributions( @@ -147,6 +139,5 @@ export class ContributionResolver { dbContribution.save(contributionToUpdate) return new UnconfirmedContribution(contributionToUpdate, user, creations) ->>>>>>> master } } From 4338328690bedc4087f058bc953ad8fd9ee2ba54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Mon, 18 Jul 2022 12:40:13 +0200 Subject: [PATCH 130/528] Add Docker documentation in DOCKER_MORE_CLOSELY.md --- DOCKER_MORE_CLOSELY.md | 44 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 DOCKER_MORE_CLOSELY.md diff --git a/DOCKER_MORE_CLOSELY.md b/DOCKER_MORE_CLOSELY.md new file mode 100644 index 000000000..f2aae81c7 --- /dev/null +++ b/DOCKER_MORE_CLOSELY.md @@ -0,0 +1,44 @@ +# Docker More Closely + +## Apple M1 Platform + +***Attention:** For using Docker commands in Apple M1 environments!* + +### Enviroment Variable For Apple M1 Platform + +To set the Docker platform environment variable in your terminal tab, run: + +```bash +# set env variable for your shell +$ export DOCKER_DEFAULT_PLATFORM=linux/amd64 +``` + +### Docker Compose Override File For Apple M1 Platform + +For Docker compose `up` or `build` commands, you can use our Apple M1 override file that specifies the M1 platform: + +```bash +# in main folder + +# for development +$ docker compose -f docker-compose.yml -f docker-compose.override.yml -f docker-compose.apple-m1.override.yml up + +# for production +$ docker compose -f docker-compose.yml -f docker-compose.apple-m1.override.yml up +``` + +## Analysing Docker Builds + +To analyze a Docker build, there is a wonderful tool called [dive](https://github.com/wagoodman/dive). Please sponsor if you're using it! + +The `dive build` command is exactly the right one to fulfill what we are looking for. +We can use it just like the `docker build` command and get an analysis afterwards. + +So, in our main folder, we use it in the following way: + +```bash +# in main folder +$ dive build --target -t "gradido/:local-" / +``` + +For the specific applications, see our [publish.yml](.github/workflows/publish.yml). From 4c33d3784b4dfcbe13ad0d2054c0e3d3863f904d Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 13:07:44 +0200 Subject: [PATCH 131/528] Added mutation for deleteContribution --- backend/src/seeds/graphql/mutations.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/seeds/graphql/mutations.ts b/backend/src/seeds/graphql/mutations.ts index 4e7fa8a90..bf898bd7d 100644 --- a/backend/src/seeds/graphql/mutations.ts +++ b/backend/src/seeds/graphql/mutations.ts @@ -255,3 +255,9 @@ export const updateContribution = gql` } } ` + +export const deleteContribution = gql` + mutation ($id: Int!) { + deleteContribution(id: $id) + } +` From e84061c412a9ba5ecb3b7f0c35dff2ba8702c35d Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 13:08:27 +0200 Subject: [PATCH 132/528] Added tests for deleteContribution --- .../resolver/ContributionResolver.test.ts | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index e6478ffc2..37cb2c645 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -5,6 +5,7 @@ import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg' import { adminUpdateContribution, createContribution, + deleteContribution, updateContribution, } from '@/seeds/graphql/mutations' import { listAllContributions, listContributions, login } from '@/seeds/graphql/queries' @@ -481,6 +482,11 @@ describe('ContributionResolver', () => { }) }) + afterAll(async () => { + await cleanDB() + resetToken() + }) + it('returns allCreation', async () => { await expect( query({ @@ -516,4 +522,98 @@ describe('ContributionResolver', () => { }) }) }) + + describe('deleteContribution', () => { + describe('unauthenticated', () => { + it('returns an error', async () => { + await expect( + query({ + query: deleteContribution, + variables: { + id: -1, + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('401 Unauthorized')], + }), + ) + }) + }) + + describe('authenticated', () => { + beforeAll(async () => { + await userFactory(testEnv, bibiBloxberg) + await userFactory(testEnv, peterLustig) + await query({ + query: login, + variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' }, + }) + result = await mutate({ + mutation: createContribution, + variables: { + amount: 100.0, + memo: 'Test env contribution', + creationDate: new Date().toString(), + }, + }) + }) + + afterAll(async () => { + await cleanDB() + resetToken() + }) + + describe('wrong contribution id', () => { + it('returns an error', async () => { + await expect( + query({ + query: deleteContribution, + variables: { + id: -1, + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('Contribution not found for given id.')], + }), + ) + }) + }) + + describe('other user sends a deleteContribtuion', () => { + it('returns an error', async () => { + await query({ + query: login, + variables: { email: 'peter@lustig.de', password: 'Aa12345_' }, + }) + await expect( + query({ + query: deleteContribution, + variables: { + id: result.data.createContribution.id, + }, + }), + ).resolves.toEqual( + expect.objectContaining({ + errors: [new GraphQLError('Can not delete contribution of another user')], + }), + ) + }) + }) + + describe('User deletes own contribution', () => { + it('deletes successfully', async () => { + await expect( + query({ + query: deleteContribution, + variables: { + id: result.data.createContribution.id, + }, + }), + ).resolves.toBeTruthy() + }) + }) + }) + }) }) From 951d7f2f884274b5d5ebe4de8285a82a7d76e61a Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:27:44 +0200 Subject: [PATCH 133/528] Change the listContribution query to give back ContributionListResult object with linkCount. --- backend/src/graphql/resolver/ContributionResolver.ts | 12 ++++++++---- backend/src/seeds/graphql/queries.ts | 9 ++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index d71ecac59..c834904d6 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -2,6 +2,7 @@ import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { Contribution as dbContribution } from '@entity/Contribution' +import { User as dbUser } from '@entity/User' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' import { FindOperator, IsNull } from '@dbTools/typeorm' import ContributionArgs from '@arg/ContributionArgs' @@ -39,21 +40,21 @@ export class ContributionResolver { } @Authorized([RIGHTS.LIST_CONTRIBUTIONS]) - @Query(() => [Contribution]) + @Query(() => ContributionListResult) async listContributions( @Args() { currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated, @Arg('filterConfirmed', () => Boolean) filterConfirmed: boolean | null, @Ctx() context: Context, - ): Promise { + ): Promise { const user = getUser(context) const where: { userId: number confirmedBy?: FindOperator | null } = { userId: user.id } if (filterConfirmed) where.confirmedBy = IsNull() - const contributions = await dbContribution.find({ + const [contributions, count] = await dbContribution.findAndCount({ where, order: { createdAt: order, @@ -62,7 +63,10 @@ export class ContributionResolver { skip: (currentPage - 1) * pageSize, take: pageSize, }) - return contributions.map((contribution) => new Contribution(contribution, new User(user))) + return new ContributionListResult( + count, + contributions.map((contribution) => new Contribution(contribution, new User(user))), + ) } @Authorized([RIGHTS.LIST_ALL_CONTRIBUTIONS]) diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index deae5f97b..e18d6b303 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -185,9 +185,12 @@ export const listContributions = gql` order: $order filterConfirmed: $filterConfirmed ) { - id - amount - memo + linkCount + linkList { + id + amount + memo + } } } ` From f1238957f9262b62323341e631d964a302a0c651 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:31:04 +0200 Subject: [PATCH 134/528] Change linkCount to contributionCount and linkList to contributionList. --- backend/src/graphql/model/Contribution.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/graphql/model/Contribution.ts b/backend/src/graphql/model/Contribution.ts index 34bffd6d7..13c2d40d7 100644 --- a/backend/src/graphql/model/Contribution.ts +++ b/backend/src/graphql/model/Contribution.ts @@ -48,13 +48,13 @@ export class Contribution { @ObjectType() export class ContributionListResult { constructor(count: number, list: Contribution[]) { - this.linkCount = count - this.linkList = list + this.contributionCount = count + this.contributionList = list } @Field(() => Int) - linkCount: number + contributionCount: number @Field(() => [Contribution]) - linkList: Contribution[] + contributionList: Contribution[] } From b384782e63c83863dcce60540b3fe340e64384a5 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:31:39 +0200 Subject: [PATCH 135/528] Change query of listContribution to get contributionCount and contributionList instead of link... --- backend/src/seeds/graphql/queries.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index e18d6b303..0d72c165d 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -185,8 +185,8 @@ export const listContributions = gql` order: $order filterConfirmed: $filterConfirmed ) { - linkCount - linkList { + contributionCount + contributionList { id amount memo From 7d5555c7e40ec621f1f9746a7a155cdecf745de0 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:34:30 +0200 Subject: [PATCH 136/528] Change query listAllContributions now gets contributionCount and contributionList instead of linkCount and linkList. --- backend/src/seeds/graphql/queries.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index 0d72c165d..9f7a02e70 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -198,8 +198,8 @@ export const listContributions = gql` export const listAllContributions = ` query ($currentPage: Int = 1, $pageSize: Int = 5, $order: Order = DESC) { listAllContributions(currentPage: $currentPage, pageSize: $pageSize, order: $order) { - linkCount - linkList { + contributionCount + contributionList { id firstName lastName From a25d9f73991199607022911f5e450794ad79e2fe Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:38:58 +0200 Subject: [PATCH 137/528] Change query fields to new names. --- .../resolver/ContributionResolver.test.ts | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index e6478ffc2..37ff45f25 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -193,18 +193,21 @@ describe('ContributionResolver', () => { ).resolves.toEqual( expect.objectContaining({ data: { - listContributions: expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(Number), - memo: 'Herzlich Willkommen bei Gradido!', - amount: '1000', - }), - expect.objectContaining({ - id: expect.any(Number), - memo: 'Test env contribution', - amount: '100', - }), - ]), + listContributions: { + contributionCount: 2, + contributionList: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(Number), + memo: 'Herzlich Willkommen bei Gradido!', + amount: '1000', + }), + expect.objectContaining({ + id: expect.any(Number), + memo: 'Test env contribution', + amount: '100', + }), + ]), + }, }, }), ) @@ -226,13 +229,16 @@ describe('ContributionResolver', () => { ).resolves.toEqual( expect.objectContaining({ data: { - listContributions: expect.arrayContaining([ - expect.objectContaining({ - id: expect.any(Number), - memo: 'Test env contribution', - amount: '100', - }), - ]), + listContributions: { + contributionCount: 1, + contributionList: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(Number), + memo: 'Test env contribution', + amount: '100', + }), + ]), + }, }, }), ) @@ -496,8 +502,8 @@ describe('ContributionResolver', () => { expect.objectContaining({ data: { listAllContributions: { - linkCount: 2, - linkList: expect.arrayContaining([ + contributionCount: 2, + contributionList: expect.arrayContaining([ expect.objectContaining({ id: expect.any(Number), memo: 'Herzlich Willkommen bei Gradido!', From 93856482853f2f5c00c21ee0857993b7612a8875 Mon Sep 17 00:00:00 2001 From: elweyn Date: Mon, 18 Jul 2022 11:39:17 +0200 Subject: [PATCH 138/528] Remove unused import. --- backend/src/graphql/resolver/ContributionResolver.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index c834904d6..f21c65068 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -2,7 +2,6 @@ import { RIGHTS } from '@/auth/RIGHTS' import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { Contribution as dbContribution } from '@entity/Contribution' -import { User as dbUser } from '@entity/User' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' import { FindOperator, IsNull } from '@dbTools/typeorm' import ContributionArgs from '@arg/ContributionArgs' From 70a8f9b0ca06da047b9c645046bb4fff4e75132f Mon Sep 17 00:00:00 2001 From: ogerly Date: Mon, 18 Jul 2022 11:50:07 +0200 Subject: [PATCH 139/528] change query to get contributionCount and contributionList --- .../Contributions/ContributionList.vue | 2 +- frontend/src/graphql/queries.js | 18 +++++++++++------- frontend/src/pages/Community.vue | 4 ++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/Contributions/ContributionList.vue b/frontend/src/components/Contributions/ContributionList.vue index c08d22c79..f5aa536ba 100644 --- a/frontend/src/components/Contributions/ContributionList.vue +++ b/frontend/src/components/Contributions/ContributionList.vue @@ -1,6 +1,6 @@
@@ -145,6 +150,8 @@ export default { .then((result) => { this.$emit('set-tunneled-email', null) this.link = result.data.createTransactionLink.link + this.amount = this.transactionData.amount + this.memo = this.transactionData.memo this.transactionData = { ...EMPTY_TRANSACTION_DATA } this.currentTransactionStep = TRANSACTION_STEPS.transactionResultLink this.updateTransactions({}) From ae6c83becfa55fddcd8ce0e7c92c169f505a311c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Claus-Peter=20H=C3=BCbner?= Date: Wed, 27 Jul 2022 00:34:50 +0200 Subject: [PATCH 250/528] add two variants to store a deny of a contribution --- .../UC_Contribution_Messaging.md | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/docu/Concepts/BusinessRequirements/UC_Contribution_Messaging.md b/docu/Concepts/BusinessRequirements/UC_Contribution_Messaging.md index ba54e631e..98ef7bd68 100644 --- a/docu/Concepts/BusinessRequirements/UC_Contribution_Messaging.md +++ b/docu/Concepts/BusinessRequirements/UC_Contribution_Messaging.md @@ -74,6 +74,16 @@ Mit diesem Service werden alle Contributions aber keine Messages, aller User gel Mit diesem Service kann eine Contribution im Status "eingereicht" und nur vom Ersteller selbst gelöscht werden. Dabei wird nur ein SoftDelete durchgeführt, indem das deletedAt-Datum auf den aktuellen Zeitpunkt gesetzt wird. +### confirmContribution + +Über diesen Service kann der Moderator im AdminInterface eine "eingereichte" Contribution bestätigen. Dabei wird implizit das Attribut "confirmed_by" auf die UserId des Moderators gesetzt und das Attribut "confirmed_at" auf den aktuellen Zeitpunkt. Bei der Migrations-Variante-1 der Contribution-Tabelle wird implizit das Attribut "confirmed_state" auf TRUE gesetzt. + +### denyContribution + +Über diesen Service kann der Moderator im AdminInterface eine "eingereichte" Contribution ablehnen. Dabei wird bei der Migrations-Variante-1 implizit das Attribut "confirmed_by" auf die UserId des Moderators gesetzt, das Attribut "confirmed_at" auf den aktuellen Zeitpunkt und das Attribut "confirmed_state" auf FALSE gesetzt. Zusätzlich gibt der Moderator eine Begründung der Ablehnung ein, die in dem Attribut "denied_reason" gespeichert wird. + +Bei der Migrations-Variante-2 wird bei einer Ablehnung das Attribut "denied_by" auf die UserId des Moderators gesetzt, das Attribut "denied_at" auf den aktuellen Zeitpunkt und in das Attribut "denied_reason" wird die Begründung der Ablehnung gespeichert. Die Attribute "confirmed_by", "confirmed_at" bleiben leer bzw auf null, das Attribut "confirm_state" existiert nicht. + ### searchContributionMessages Dieser Service liefert zu einer bestimmten Contribution alle gespeicherten Nachrichten chronologisch nach dem CreatedAt-Datum absteigend sortiert. Neben dem Nachrichtentext und dem CreatedAt-Datum wird auch der User, der die Nachricht erstellt hat, geliefert. Als User-Daten wird entweder der Vorname und Nachname oder falls vorhanden der Alias geliefert. @@ -92,8 +102,20 @@ Das Class-Diagramm der beteiligten Tabellen gibt einen ersten Eindruck: Die Contribution-Tabelle benötigt für die Confirmation ein zusätzliches Attribut, das das Ergebnis der Confirmation - bestätigt oder abgelehnt - speichert. +#### Variante 1: + confirmed_state: speichert das Ergebnis der Confirmation, das entweder true für bestätigt oder false für abgelehnt +denied_reason: speichert die Begründung der Ablehnung, die der Moderator als Argumentation formuliert + +#### Variante 2: + +denied_at: speichert den Zeitpunkt, wann die Ablehnung erfolgte + +denied_by: speichert die UserId des Moderators, der die Ablehnung durchgeführt hat + +denied_reason: speichert die Begründung der Ablehnung, die der Moderator als Argumentation formuliert + ### ContributionMessages Tabelle -Die ContributionMessages Tabelle ist gänzlich neu. +Die ContributionMessages Tabelle ist gänzlich neu mit allen Attributen. From 21c9bc22a710febd6d5d61aa5f43a11933981da5 Mon Sep 17 00:00:00 2001 From: mahula Date: Wed, 27 Jul 2022 10:13:00 +0200 Subject: [PATCH 251/528] adapt existing unit tests for copying a created transaction link --- frontend/src/pages/Send.spec.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/frontend/src/pages/Send.spec.js b/frontend/src/pages/Send.spec.js index 47a30ff65..79ba65133 100644 --- a/frontend/src/pages/Send.spec.js +++ b/frontend/src/pages/Send.spec.js @@ -20,6 +20,9 @@ describe('Send', () => { balance: 123.45, GdtBalance: 1234.56, pending: true, + amount: '15', + link: 'http://localhost/redeem/0123456789', + memo: 'Quis auctor elit sed vulputate mi sit amet mauris commodo quis imperdiet.', } const mocks = { @@ -28,6 +31,7 @@ describe('Send', () => { $store: { state: { email: 'sender@example.org', + firstName: 'Testy', }, }, $apollo: { @@ -228,21 +232,26 @@ describe('Send', () => { navigator.clipboard = navigatorClipboard }) - describe('copy with success', () => { + describe('copy link with success', () => { beforeEach(async () => { navigatorClipboardMock.mockResolvedValue() - await wrapper.findAll('button').at(0).trigger('click') + await wrapper.findAll('button').at(1).trigger('click') }) + it('should call clipboard.writeText', () => { + expect(navigator.clipboard.writeText).toHaveBeenCalledWith( + 'http://localhost/redeem/0123456789', + ) + }) it('toasts success message', () => { expect(toastSuccessSpy).toBeCalledWith('gdd_per_link.link-copied') }) }) - describe('copy with error', () => { + describe('copy link with error', () => { beforeEach(async () => { navigatorClipboardMock.mockRejectedValue() - await wrapper.findAll('button').at(0).trigger('click') + await wrapper.findAll('button').at(1).trigger('click') }) it('toasts error message', () => { @@ -253,7 +262,7 @@ describe('Send', () => { describe('close button click', () => { beforeEach(async () => { - await wrapper.findAll('button').at(2).trigger('click') + await wrapper.findAll('button').at(3).trigger('click') }) it('Shows the TransactionForm', () => { From d1cc3115ba642ae9a20ec6c2af92995f4f050438 Mon Sep 17 00:00:00 2001 From: mahula Date: Wed, 27 Jul 2022 11:07:58 +0200 Subject: [PATCH 252/528] add unit tests for copying a created transaction link with username, amount and memo text --- frontend/src/pages/Send.spec.js | 43 ++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/frontend/src/pages/Send.spec.js b/frontend/src/pages/Send.spec.js index 79ba65133..be63027b1 100644 --- a/frontend/src/pages/Send.spec.js +++ b/frontend/src/pages/Send.spec.js @@ -20,9 +20,6 @@ describe('Send', () => { balance: 123.45, GdtBalance: 1234.56, pending: true, - amount: '15', - link: 'http://localhost/redeem/0123456789', - memo: 'Quis auctor elit sed vulputate mi sit amet mauris commodo quis imperdiet.', } const mocks = { @@ -260,6 +257,46 @@ describe('Send', () => { }) }) + describe('copy link and text with success', () => { + const navigatorClipboard = navigator.clipboard + beforeAll(() => { + delete navigator.clipboard + navigator.clipboard = { writeText: navigatorClipboardMock } + }) + afterAll(() => { + navigator.clipboard = navigatorClipboard + }) + + describe('copy link and text with success', () => { + beforeEach(async () => { + navigatorClipboardMock.mockResolvedValue() + await wrapper.findAll('button').at(0).trigger('click') + }) + + it('should call clipboard.writeText', () => { + expect(navigator.clipboard.writeText).toHaveBeenCalledWith( + 'http://localhost/redeem/0123456789\n' + + 'Testy transaction-link.send_you 56.78 Gradido.\n' + + '"Make the best of the link!"', + ) + }) + it('toasts success message', () => { + expect(toastSuccessSpy).toBeCalledWith('gdd_per_link.link-and-text-copied') + }) + }) + + describe('copy link and text with error', () => { + beforeEach(async () => { + navigatorClipboardMock.mockRejectedValue() + await wrapper.findAll('button').at(0).trigger('click') + }) + + it('toasts error message', () => { + expect(toastErrorSpy).toBeCalledWith('gdd_per_link.not-copied') + }) + }) + }) + describe('close button click', () => { beforeEach(async () => { await wrapper.findAll('button').at(3).trigger('click') From 3c539a6edf0a2136470c12c530965462aaaee339 Mon Sep 17 00:00:00 2001 From: mahula Date: Wed, 27 Jul 2022 11:21:47 +0200 Subject: [PATCH 253/528] make the wording more precise wherever a link can be copied --- frontend/src/components/ClipboardCopy.vue | 4 ++-- frontend/src/components/TransactionLinks/TransactionLink.vue | 4 ++-- frontend/src/locales/de.json | 3 ++- frontend/src/locales/en.json | 4 +++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/ClipboardCopy.vue b/frontend/src/components/ClipboardCopy.vue index 78af3c772..efddf8ab3 100644 --- a/frontend/src/components/ClipboardCopy.vue +++ b/frontend/src/components/ClipboardCopy.vue @@ -4,10 +4,10 @@ - {{ $t('gdd_per_link.copy-with-text') }} + {{ $t('gdd_per_link.copy-link-with-text') }} - {{ $t('gdd_per_link.copy') }} + {{ $t('gdd_per_link.copy-link') }} diff --git a/frontend/src/components/TransactionLinks/TransactionLink.vue b/frontend/src/components/TransactionLinks/TransactionLink.vue index 5618c8696..fe5e44658 100644 --- a/frontend/src/components/TransactionLinks/TransactionLink.vue +++ b/frontend/src/components/TransactionLinks/TransactionLink.vue @@ -20,7 +20,7 @@ - {{ $t('gdd_per_link.copy') }} + {{ $t('gdd_per_link.copy-link') }} - {{ $t('gdd_per_link.copy-with-text') }} + {{ $t('gdd_per_link.copy-link-with-text') }} Date: Wed, 27 Jul 2022 12:17:04 +0200 Subject: [PATCH 254/528] fix linting and locales --- frontend/src/locales/de.json | 1 - frontend/src/locales/en.json | 2 -- 2 files changed, 3 deletions(-) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index aebbffab2..91e602990 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -150,7 +150,6 @@ "GDD": "GDD", "gdd_per_link": { "choose-amount": "Wähle einen Betrag aus, welchen du per Link versenden möchtest. Du kannst auch noch eine Nachricht eintragen. Beim Klick „Jetzt generieren“ wird ein Link erstellt, den du versenden kannst.", - "copy": "kopieren", "copy-link": "Link kopieren", "copy-link-with-text": "Link und Text kopieren", "created": "Der Link wurde erstellt!", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 4ace4e10b..fcd604fea 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -12,7 +12,6 @@ "hasAccount": "You already have an account?", "hereLogin": "Log in here", "learnMore": "Learn more …", - "oneDignity": "We gift to each other and give thanks with Gradido.", "oneDonation": "You are a gift for the community. 1000 thanks because you are with us.", "oneGratitude": "For each other, for all people, for nature." @@ -151,7 +150,6 @@ "GDD": "GDD", "gdd_per_link": { "choose-amount": "Select an amount that you would like to send via link. You can also enter a message. Click 'Generate now' to create a link that you can share.", - "copy": "copy", "copy-link": "Copy link", "copy-link-with-text": "Copy link and text", "created": "Link was created!", From dff0853bc7c55813b769e4f63431dc5d011240aa Mon Sep 17 00:00:00 2001 From: mahula Date: Wed, 27 Jul 2022 14:38:53 +0200 Subject: [PATCH 255/528] remove member area from menu, if user has no elopage account --- frontend/src/components/Menu/Sidebar.vue | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/src/components/Menu/Sidebar.vue b/frontend/src/components/Menu/Sidebar.vue index b54eb541e..a8850ed18 100644 --- a/frontend/src/components/Menu/Sidebar.vue +++ b/frontend/src/components/Menu/Sidebar.vue @@ -27,12 +27,9 @@
- + {{ $t('navigation.members_area') }} - - {{ $t('math.exclaim') }} - From 2c07ec98ab77f3c04adcdf80e3c42d9bc132a633 Mon Sep 17 00:00:00 2001 From: mahula Date: Wed, 27 Jul 2022 21:06:49 +0200 Subject: [PATCH 256/528] remove the member area entry from the footer and adjust the unit tests accordingly --- frontend/src/components/ContentFooter.spec.js | 24 ++++--------------- frontend/src/components/ContentFooter.vue | 6 ----- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/frontend/src/components/ContentFooter.spec.js b/frontend/src/components/ContentFooter.spec.js index f67560e44..c578d3fac 100644 --- a/frontend/src/components/ContentFooter.spec.js +++ b/frontend/src/components/ContentFooter.spec.js @@ -97,24 +97,14 @@ describe('ContentFooter', () => { ) }) - it('has a link to the members area', () => { - expect(wrapper.findAll('a.nav-link').at(2).text()).toEqual('navigation.members_area') - }) - - it('links to the elopage', () => { - expect(wrapper.findAll('a.nav-link').at(2).attributes('href')).toEqual( - 'https://elopage.com/s/gradido/sign_in?locale=en', - ) - }) - it('links to the whitepaper', () => { - expect(wrapper.findAll('a.nav-link').at(3).attributes('href')).toEqual( + expect(wrapper.findAll('a.nav-link').at(2).attributes('href')).toEqual( 'https://docs.google.com/document/d/1kcX1guOi6tDgnFHD9tf7fB_MneKTx-0nHJxzdN8ygNs/edit?usp=sharing', ) }) it('links to the support', () => { - expect(wrapper.findAll('a.nav-link').at(4).attributes('href')).toEqual( + expect(wrapper.findAll('a.nav-link').at(3).attributes('href')).toEqual( 'https://gradido.net/en/contact/', ) }) @@ -142,20 +132,14 @@ describe('ContentFooter', () => { ) }) - it('links to the German elopage when locale is de', () => { - expect(wrapper.findAll('a.nav-link').at(2).attributes('href')).toEqual( - 'https://elopage.com/s/gradido/sign_in?locale=de', - ) - }) - it('links to the German whitepaper when locale is de', () => { - expect(wrapper.findAll('a.nav-link').at(3).attributes('href')).toEqual( + expect(wrapper.findAll('a.nav-link').at(2).attributes('href')).toEqual( 'https://docs.google.com/document/d/1jZp-DiiMPI9ZPNXmjsvOQ1BtnfDFfx8BX7CDmA8KKjY/edit?usp=sharing', ) }) it('links to the German support-page when locale is de', () => { - expect(wrapper.findAll('a.nav-link').at(4).attributes('href')).toEqual( + expect(wrapper.findAll('a.nav-link').at(3).attributes('href')).toEqual( 'https://gradido.net/de/contact/', ) }) diff --git a/frontend/src/components/ContentFooter.vue b/frontend/src/components/ContentFooter.vue index bdcb5b1a9..c563cc23d 100755 --- a/frontend/src/components/ContentFooter.vue +++ b/frontend/src/components/ContentFooter.vue @@ -34,12 +34,6 @@ {{ $t('footer.privacy_policy') }} - - {{ $t('navigation.members_area') }} - { expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('navigation.profile') }) - + }) + describe('navigation Navbar (user has an elopage account)', () => { it('has a link to the members area', () => { expect(wrapper.findAll('.nav-item').at(7).text()).toContain('navigation.members_area') expect(wrapper.findAll('.nav-item').at(7).find('a').attributes('href')).toBe( @@ -81,6 +82,18 @@ describe('Navbar', () => { expect(wrapper.findAll('.nav-item').at(9).text()).toEqual('navigation.logout') }) }) + describe('navigation Navbar (user has no elopage account)', () => { + beforeAll(() => { + mocks.$store.state.hasElopage = false + wrapper = Wrapper() + }) + it('has first nav-item "navigation.admin_area" in navbar', () => { + expect(wrapper.findAll('.nav-item').at(7).text()).toEqual('navigation.admin_area') + }) + it('has first nav-item "navigation.logout" in navbar', () => { + expect(wrapper.findAll('.nav-item').at(8).text()).toEqual('navigation.logout') + }) + }) }) describe('check watch visible true', () => { beforeEach(async () => { diff --git a/frontend/src/components/Menu/Navbar.vue b/frontend/src/components/Menu/Navbar.vue index 2f26f381e..d8fc942fe 100644 --- a/frontend/src/components/Menu/Navbar.vue +++ b/frontend/src/components/Menu/Navbar.vue @@ -57,12 +57,9 @@ {{ $t('navigation.profile') }}
- + {{ $t('navigation.members_area') }} - - {{ $t('math.exclaim') }} - From 7fdba919ca93655d06844c96f9578ee324c2efac Mon Sep 17 00:00:00 2001 From: mahula Date: Wed, 27 Jul 2022 22:16:17 +0200 Subject: [PATCH 258/528] fix removal of exclamation mark in navbar --- frontend/src/components/Menu/Navbar.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/components/Menu/Navbar.vue b/frontend/src/components/Menu/Navbar.vue index d8fc942fe..1c49a1aa3 100644 --- a/frontend/src/components/Menu/Navbar.vue +++ b/frontend/src/components/Menu/Navbar.vue @@ -60,6 +60,9 @@ {{ $t('navigation.members_area') }} + + {{ $t('math.exclaim') }} + From 67453c8a27ec60ee677e724c6a671aef09d76246 Mon Sep 17 00:00:00 2001 From: mahula Date: Wed, 27 Jul 2022 22:16:53 +0200 Subject: [PATCH 259/528] remove the member area entry from sidebar menu and adjust the unit tests accordingly --- frontend/src/components/Menu/Sidebar.spec.js | 28 +++++++++++++++----- frontend/src/components/Menu/Sidebar.vue | 10 ++++++- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/Menu/Sidebar.spec.js b/frontend/src/components/Menu/Sidebar.spec.js index f6051c733..dd9511562 100644 --- a/frontend/src/components/Menu/Sidebar.spec.js +++ b/frontend/src/components/Menu/Sidebar.spec.js @@ -31,11 +31,7 @@ describe('Sidebar', () => { expect(wrapper.find('div#component-sidebar').exists()).toBeTruthy() }) - describe('navigation Navbar', () => { - it('has seven b-nav-item in the navbar', () => { - expect(wrapper.findAll('.nav-item')).toHaveLength(8) - }) - + describe('navigation Navbar (general elements)', () => { it('has first nav-item "navigation.overview" in navbar', () => { expect(wrapper.findAll('.nav-item').at(0).text()).toEqual('navigation.overview') }) @@ -55,7 +51,12 @@ describe('Sidebar', () => { it('has first nav-item "navigation.profile" in navbar', () => { expect(wrapper.findAll('.nav-item').at(4).text()).toEqual('navigation.profile') }) - + }) + // ---- + describe('navigation Navbar (user has an elopage account)', () => { + it('has seven b-nav-item in the navbar', () => { + expect(wrapper.findAll('.nav-item')).toHaveLength(8) + }) it('has a link to the members area', () => { expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.members_area') expect(wrapper.findAll('.nav-item').at(5).find('a').attributes('href')).toBe('#') @@ -69,5 +70,20 @@ describe('Sidebar', () => { expect(wrapper.findAll('.nav-item').at(7).text()).toEqual('navigation.logout') }) }) + describe('navigation Navbar (user has no elopage account)', () => { + beforeAll(() => { + mocks.$store.state.hasElopage = false + wrapper = Wrapper() + }) + it('has six b-nav-item in the navbar', () => { + expect(wrapper.findAll('.nav-item')).toHaveLength(7) + }) + it('has first nav-item "navigation.admin_area" in navbar', () => { + expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.admin_area') + }) + it('has first nav-item "navigation.logout" in navbar', () => { + expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('navigation.logout') + }) + }) }) }) diff --git a/frontend/src/components/Menu/Sidebar.vue b/frontend/src/components/Menu/Sidebar.vue index a8850ed18..0cdab31c3 100644 --- a/frontend/src/components/Menu/Sidebar.vue +++ b/frontend/src/components/Menu/Sidebar.vue @@ -27,9 +27,17 @@

- + {{ $t('navigation.members_area') }} + + {{ $t('math.exclaim') }} + From bb120b8b82f9c25f5caa39cdd81064c1a36e4dc9 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 28 Jul 2022 08:39:31 +0200 Subject: [PATCH 260/528] improve unit test structure for better readability --- frontend/src/components/Menu/Navbar.spec.js | 11 +++++++++++ frontend/src/components/Menu/Sidebar.spec.js | 8 +++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Menu/Navbar.spec.js b/frontend/src/components/Menu/Navbar.spec.js index ef39fdc0e..109190e39 100644 --- a/frontend/src/components/Menu/Navbar.spec.js +++ b/frontend/src/components/Menu/Navbar.spec.js @@ -43,9 +43,11 @@ describe('Navbar', () => { it('has .navbar-brand in the navbar', () => { expect(wrapper.find('.navbar-brand').exists()).toBeTruthy() }) + it('has b-navbar-toggle in the navbar', () => { expect(wrapper.find('.navbar-toggler').exists()).toBeTruthy() }) + it('has ten b-nav-item in the navbar', () => { expect(wrapper.findAll('.nav-item')).toHaveLength(10) }) @@ -57,16 +59,20 @@ describe('Navbar', () => { it('has first nav-item "navigation.overview" in navbar', () => { expect(wrapper.findAll('.nav-item').at(3).text()).toEqual('navigation.overview') }) + it('has first nav-item "navigation.send" in navbar', () => { expect(wrapper.findAll('.nav-item').at(4).text()).toEqual('navigation.send') }) + it('has first nav-item "navigation.transactions" in navbar', () => { expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.transactions') }) + it('has first nav-item "navigation.profile" in navbar', () => { expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('navigation.profile') }) }) + describe('navigation Navbar (user has an elopage account)', () => { it('has a link to the members area', () => { expect(wrapper.findAll('.nav-item').at(7).text()).toContain('navigation.members_area') @@ -78,23 +84,28 @@ describe('Navbar', () => { it('has first nav-item "navigation.admin_area" in navbar', () => { expect(wrapper.findAll('.nav-item').at(8).text()).toEqual('navigation.admin_area') }) + it('has first nav-item "navigation.logout" in navbar', () => { expect(wrapper.findAll('.nav-item').at(9).text()).toEqual('navigation.logout') }) }) + describe('navigation Navbar (user has no elopage account)', () => { beforeAll(() => { mocks.$store.state.hasElopage = false wrapper = Wrapper() }) + it('has first nav-item "navigation.admin_area" in navbar', () => { expect(wrapper.findAll('.nav-item').at(7).text()).toEqual('navigation.admin_area') }) + it('has first nav-item "navigation.logout" in navbar', () => { expect(wrapper.findAll('.nav-item').at(8).text()).toEqual('navigation.logout') }) }) }) + describe('check watch visible true', () => { beforeEach(async () => { await wrapper.setProps({ visible: true }) diff --git a/frontend/src/components/Menu/Sidebar.spec.js b/frontend/src/components/Menu/Sidebar.spec.js index dd9511562..7be68363b 100644 --- a/frontend/src/components/Menu/Sidebar.spec.js +++ b/frontend/src/components/Menu/Sidebar.spec.js @@ -27,6 +27,7 @@ describe('Sidebar', () => { beforeEach(() => { wrapper = Wrapper() }) + it('renders the component', () => { expect(wrapper.find('div#component-sidebar').exists()).toBeTruthy() }) @@ -52,11 +53,12 @@ describe('Sidebar', () => { expect(wrapper.findAll('.nav-item').at(4).text()).toEqual('navigation.profile') }) }) - // ---- + describe('navigation Navbar (user has an elopage account)', () => { it('has seven b-nav-item in the navbar', () => { expect(wrapper.findAll('.nav-item')).toHaveLength(8) }) + it('has a link to the members area', () => { expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.members_area') expect(wrapper.findAll('.nav-item').at(5).find('a').attributes('href')).toBe('#') @@ -70,17 +72,21 @@ describe('Sidebar', () => { expect(wrapper.findAll('.nav-item').at(7).text()).toEqual('navigation.logout') }) }) + describe('navigation Navbar (user has no elopage account)', () => { beforeAll(() => { mocks.$store.state.hasElopage = false wrapper = Wrapper() }) + it('has six b-nav-item in the navbar', () => { expect(wrapper.findAll('.nav-item')).toHaveLength(7) }) + it('has first nav-item "navigation.admin_area" in navbar', () => { expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.admin_area') }) + it('has first nav-item "navigation.logout" in navbar', () => { expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('navigation.logout') }) From a41385141902b7611c7fbde289d68cc3d2fe4c6b Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 28 Jul 2022 08:50:26 +0200 Subject: [PATCH 261/528] specify the wording of the unit tests regarding the number of nav items --- frontend/src/components/Menu/Sidebar.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Menu/Sidebar.spec.js b/frontend/src/components/Menu/Sidebar.spec.js index 7be68363b..1593a79a8 100644 --- a/frontend/src/components/Menu/Sidebar.spec.js +++ b/frontend/src/components/Menu/Sidebar.spec.js @@ -55,7 +55,7 @@ describe('Sidebar', () => { }) describe('navigation Navbar (user has an elopage account)', () => { - it('has seven b-nav-item in the navbar', () => { + it('has eight b-nav-item in the navbar', () => { expect(wrapper.findAll('.nav-item')).toHaveLength(8) }) @@ -79,7 +79,7 @@ describe('Sidebar', () => { wrapper = Wrapper() }) - it('has six b-nav-item in the navbar', () => { + it('has seven b-nav-item in the navbar', () => { expect(wrapper.findAll('.nav-item')).toHaveLength(7) }) From 6f081c4cc941ea6a242d17b2986d8cd98f6513da Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 28 Jul 2022 11:12:17 +0200 Subject: [PATCH 262/528] fix: Use Inner Join for Contribution and User --- .../graphql/resolver/ContributionResolver.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/backend/src/graphql/resolver/ContributionResolver.ts b/backend/src/graphql/resolver/ContributionResolver.ts index a22715fb4..3307252e4 100644 --- a/backend/src/graphql/resolver/ContributionResolver.ts +++ b/backend/src/graphql/resolver/ContributionResolver.ts @@ -3,7 +3,7 @@ import { Context, getUser } from '@/server/context' import { backendLogger as logger } from '@/server/logger' import { Contribution as dbContribution } from '@entity/Contribution' import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type-graphql' -import { FindOperator, IsNull } from '@dbTools/typeorm' +import { FindOperator, IsNull, getConnection } from '@dbTools/typeorm' import ContributionArgs from '@arg/ContributionArgs' import Paginated from '@arg/Paginated' import { Order } from '@enum/Order' @@ -106,14 +106,15 @@ export class ContributionResolver { @Args() { currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated, ): Promise { - const [dbContributions, count] = await dbContribution.findAndCount({ - relations: ['user'], - order: { - createdAt: order, - }, - skip: (currentPage - 1) * pageSize, - take: pageSize, - }) + const [dbContributions, count] = await getConnection() + .createQueryBuilder() + .select('c') + .from(dbContribution, 'c') + .innerJoinAndSelect('c.user', 'u') + .orderBy('c.createdAt', order) + .limit(pageSize) + .offset((currentPage - 1) * pageSize) + .getManyAndCount() return new ContributionListResult( count, dbContributions.map( From 2d80c7029eae75fbda6c925cc8b0e5b54ef41e17 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 28 Jul 2022 13:06:42 +0200 Subject: [PATCH 263/528] including validation date infos to link copying after transaction link creation - adapt transaction link creation mutation to get the validation date - add validation date and text to link copy - utilize mixins to avoid code doubling --- frontend/src/components/ClipboardCopy.vue | 42 ++----------------- .../GddSend/TransactionResultLink.vue | 4 +- frontend/src/graphql/mutations.js | 3 ++ frontend/src/pages/Send.vue | 13 ++++-- 4 files changed, 19 insertions(+), 43 deletions(-) diff --git a/frontend/src/components/ClipboardCopy.vue b/frontend/src/components/ClipboardCopy.vue index efddf8ab3..66e47a264 100644 --- a/frontend/src/components/ClipboardCopy.vue +++ b/frontend/src/components/ClipboardCopy.vue @@ -6,7 +6,7 @@ {{ $t('gdd_per_link.copy-link-with-text') }} - + {{ $t('gdd_per_link.copy-link') }} @@ -21,46 +21,10 @@