mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into 2290-New-Design
This commit is contained in:
commit
51b770012b
@ -20,10 +20,10 @@ ENV PORT="8080"
|
||||
# Labels
|
||||
LABEL org.label-schema.build-date="${BUILD_DATE}"
|
||||
LABEL org.label-schema.name="gradido:admin"
|
||||
LABEL org.label-schema.description="Gradido Vue Admin Interface"
|
||||
LABEL org.label-schema.usage="https://github.com/gradido/gradido/admin/README.md"
|
||||
LABEL org.label-schema.description="Gradido Admin Interface"
|
||||
LABEL org.label-schema.usage="https://github.com/gradido/gradido/blob/master/README.md"
|
||||
LABEL org.label-schema.url="https://gradido.net"
|
||||
LABEL org.label-schema.vcs-url="https://github.com/gradido/gradido/backend"
|
||||
LABEL org.label-schema.vcs-url="https://github.com/gradido/gradido/tree/master/admin"
|
||||
LABEL org.label-schema.vcs-ref="${BUILD_COMMIT}"
|
||||
LABEL org.label-schema.vendor="gradido Community"
|
||||
LABEL org.label-schema.version="${BUILD_VERSION}"
|
||||
|
||||
@ -46,5 +46,10 @@ describe('ContributionLink', () => {
|
||||
wrapper.vm.editContributionLinkData()
|
||||
expect(wrapper.vm.$root.$emit('bv::toggle::collapse', 'newContribution')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('emits toggle::collapse close Contribution-Form ', async () => {
|
||||
wrapper.vm.closeContributionForm()
|
||||
expect(wrapper.vm.$root.$emit('bv::toggle::collapse', 'newContribution')).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -8,7 +8,11 @@
|
||||
header-class="text-center"
|
||||
class="mt-5"
|
||||
>
|
||||
<b-button v-b-toggle.newContribution class="my-3 d-flex justify-content-left">
|
||||
<b-button
|
||||
v-if="!editContributionLink"
|
||||
v-b-toggle.newContribution
|
||||
class="my-3 d-flex justify-content-left"
|
||||
>
|
||||
{{ $t('math.plus') }} {{ $t('contributionLink.newContributionLink') }}
|
||||
</b-button>
|
||||
|
||||
@ -17,7 +21,9 @@
|
||||
<p class="h2 ml-5">{{ $t('contributionLink.contributionLinks') }}</p>
|
||||
<contribution-link-form
|
||||
:contributionLinkData="contributionLinkData"
|
||||
:editContributionLink="editContributionLink"
|
||||
@get-contribution-links="$emit('get-contribution-links')"
|
||||
@closeContributionForm="closeContributionForm"
|
||||
/>
|
||||
</b-card>
|
||||
</b-collapse>
|
||||
@ -58,12 +64,23 @@ export default {
|
||||
return {
|
||||
visible: false,
|
||||
contributionLinkData: {},
|
||||
editContributionLink: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closeContributionForm() {
|
||||
if (this.visible) {
|
||||
this.$root.$emit('bv::toggle::collapse', 'newContribution')
|
||||
this.editContributionLink = false
|
||||
this.contributionLinkData = {}
|
||||
}
|
||||
},
|
||||
editContributionLinkData(data) {
|
||||
if (!this.visible) this.$root.$emit('bv::toggle::collapse', 'newContribution')
|
||||
if (!this.visible) {
|
||||
this.$root.$emit('bv::toggle::collapse', 'newContribution')
|
||||
}
|
||||
this.contributionLinkData = data
|
||||
this.editContributionLink = true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ global.alert = jest.fn()
|
||||
|
||||
const propsData = {
|
||||
contributionLinkData: {},
|
||||
editContributionLink: false,
|
||||
}
|
||||
const apolloMutateMock = jest.fn().mockResolvedValue()
|
||||
|
||||
@ -108,6 +109,7 @@ describe('ContributionLinkForm', () => {
|
||||
cycle: 'ONCE',
|
||||
maxPerCycle: 1,
|
||||
maxAmountPerMonth: '0',
|
||||
id: null,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
<b-col>
|
||||
<b-form-group :label="$t('contributionLink.validFrom')">
|
||||
<b-form-datepicker
|
||||
reset-button
|
||||
v-model="form.validFrom"
|
||||
size="lg"
|
||||
:min="min"
|
||||
@ -19,6 +20,7 @@
|
||||
<b-col>
|
||||
<b-form-group :label="$t('contributionLink.validTo')">
|
||||
<b-form-datepicker
|
||||
reset-button
|
||||
v-model="form.validTo"
|
||||
size="lg"
|
||||
:min="form.validFrom ? form.validFrom : min"
|
||||
@ -102,16 +104,25 @@
|
||||
</b-form-group>
|
||||
-->
|
||||
<div class="mt-6">
|
||||
<b-button type="submit" variant="primary">{{ $t('contributionLink.create') }}</b-button>
|
||||
<b-button type="submit" variant="primary">
|
||||
{{
|
||||
editContributionLink ? $t('contributionLink.saveChange') : $t('contributionLink.create')
|
||||
}}
|
||||
</b-button>
|
||||
<b-button type="reset" variant="danger" @click.prevent="onReset">
|
||||
{{ $t('contributionLink.clear') }}
|
||||
</b-button>
|
||||
<b-button @click.prevent="$emit('closeContributionForm')">
|
||||
{{ $t('contributionLink.close') }}
|
||||
</b-button>
|
||||
</div>
|
||||
</b-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { createContributionLink } from '@/graphql/createContributionLink.js'
|
||||
import { updateContributionLink } from '@/graphql/updateContributionLink.js'
|
||||
|
||||
export default {
|
||||
name: 'ContributionLinkForm',
|
||||
props: {
|
||||
@ -121,6 +132,7 @@ export default {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
editContributionLink: { type: Boolean, required: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -157,23 +169,24 @@ export default {
|
||||
if (this.form.validFrom === null)
|
||||
return this.toastError(this.$t('contributionLink.noStartDate'))
|
||||
if (this.form.validTo === null) return this.toastError(this.$t('contributionLink.noEndDate'))
|
||||
|
||||
const variables = {
|
||||
...this.form,
|
||||
id: this.contributionLinkData.id ? this.contributionLinkData.id : null,
|
||||
}
|
||||
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: createContributionLink,
|
||||
variables: {
|
||||
validFrom: this.form.validFrom,
|
||||
validTo: this.form.validTo,
|
||||
name: this.form.name,
|
||||
amount: this.form.amount,
|
||||
memo: this.form.memo,
|
||||
cycle: this.form.cycle,
|
||||
maxPerCycle: this.form.maxPerCycle,
|
||||
maxAmountPerMonth: this.form.maxAmountPerMonth,
|
||||
},
|
||||
mutation: this.editContributionLink ? updateContributionLink : createContributionLink,
|
||||
variables: variables,
|
||||
})
|
||||
.then((result) => {
|
||||
this.link = result.data.createContributionLink.link
|
||||
this.toastSuccess(this.link)
|
||||
const link = this.editContributionLink
|
||||
? result.data.updateContributionLink.link
|
||||
: result.data.createContributionLink.link
|
||||
this.toastSuccess(
|
||||
this.editContributionLink ? this.$t('contributionLink.changeSaved') : link,
|
||||
)
|
||||
this.onReset()
|
||||
this.$root.$emit('bv::toggle::collapse', 'newContribution')
|
||||
this.$emit('get-contribution-links')
|
||||
@ -195,14 +208,7 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
contributionLinkData() {
|
||||
this.form.name = this.contributionLinkData.name
|
||||
this.form.memo = this.contributionLinkData.memo
|
||||
this.form.amount = this.contributionLinkData.amount
|
||||
this.form.validFrom = this.contributionLinkData.validFrom
|
||||
this.form.validTo = this.contributionLinkData.validTo
|
||||
this.form.cycle = this.contributionLinkData.cycle
|
||||
this.form.maxPerCycle = this.contributionLinkData.maxPerCycle
|
||||
this.form.maxAmountPerMonth = this.contributionLinkData.maxAmountPerMonth
|
||||
this.form = this.contributionLinkData
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
40
admin/src/graphql/updateContributionLink.js
Normal file
40
admin/src/graphql/updateContributionLink.js
Normal file
@ -0,0 +1,40 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const updateContributionLink = gql`
|
||||
mutation (
|
||||
$amount: Decimal!
|
||||
$name: String!
|
||||
$memo: String!
|
||||
$cycle: String!
|
||||
$validFrom: String
|
||||
$validTo: String
|
||||
$maxAmountPerMonth: Decimal
|
||||
$maxPerCycle: Int! = 1
|
||||
$id: Int!
|
||||
) {
|
||||
updateContributionLink(
|
||||
amount: $amount
|
||||
name: $name
|
||||
memo: $memo
|
||||
cycle: $cycle
|
||||
validFrom: $validFrom
|
||||
validTo: $validTo
|
||||
maxAmountPerMonth: $maxAmountPerMonth
|
||||
maxPerCycle: $maxPerCycle
|
||||
id: $id
|
||||
) {
|
||||
id
|
||||
amount
|
||||
name
|
||||
memo
|
||||
code
|
||||
link
|
||||
createdAt
|
||||
validFrom
|
||||
validTo
|
||||
maxAmountPerMonth
|
||||
cycle
|
||||
maxPerCycle
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -3,7 +3,9 @@
|
||||
"back": "zurück",
|
||||
"contributionLink": {
|
||||
"amount": "Betrag",
|
||||
"changeSaved": "Änderungen gespeichert",
|
||||
"clear": "Löschen",
|
||||
"close": "Schließen",
|
||||
"contributionLinks": "Beitragslinks",
|
||||
"create": "Anlegen",
|
||||
"cycle": "Zyklus",
|
||||
@ -23,6 +25,7 @@
|
||||
"once": "einmalig"
|
||||
}
|
||||
},
|
||||
"saveChange": "Änderungen speichern",
|
||||
"validFrom": "Startdatum",
|
||||
"validTo": "Enddatum"
|
||||
},
|
||||
|
||||
@ -3,7 +3,9 @@
|
||||
"back": "back",
|
||||
"contributionLink": {
|
||||
"amount": "Amount",
|
||||
"changeSaved": "Changes saved",
|
||||
"clear": "Clear",
|
||||
"close": "Close",
|
||||
"contributionLinks": "Contribution Links",
|
||||
"create": "Create",
|
||||
"cycle": "Cycle",
|
||||
@ -23,6 +25,7 @@
|
||||
"once": "once"
|
||||
}
|
||||
},
|
||||
"saveChange": "Save Changes",
|
||||
"validFrom": "Start-date",
|
||||
"validTo": "End-Date"
|
||||
},
|
||||
|
||||
@ -63,6 +63,7 @@ import ContributionMessageArgs from '@arg/ContributionMessageArgs'
|
||||
import { ContributionMessageType } from '@enum/MessageType'
|
||||
import { ContributionMessage } from '@model/ContributionMessage'
|
||||
import { sendContributionConfirmedEmail } from '@/mailer/sendContributionConfirmedEmail'
|
||||
import { sendContributionRejectedEmail } from '@/mailer/sendContributionRejectedEmail'
|
||||
import { sendAddedContributionMessageEmail } from '@/mailer/sendAddedContributionMessageEmail'
|
||||
import { eventProtocol } from '@/event/EventProtocolEmitter'
|
||||
import {
|
||||
@ -455,6 +456,10 @@ export class AdminResolver {
|
||||
) {
|
||||
throw new Error('Own contribution can not be deleted as admin')
|
||||
}
|
||||
const user = await dbUser.findOneOrFail(
|
||||
{ id: contribution.userId },
|
||||
{ relations: ['emailContact'] },
|
||||
)
|
||||
contribution.contributionStatus = ContributionStatus.DELETED
|
||||
contribution.deletedBy = moderator.id
|
||||
await contribution.save()
|
||||
@ -468,6 +473,16 @@ export class AdminResolver {
|
||||
await eventProtocol.writeEvent(
|
||||
event.setEventAdminContributionDelete(eventAdminContributionDelete),
|
||||
)
|
||||
sendContributionRejectedEmail({
|
||||
senderFirstName: moderator.firstName,
|
||||
senderLastName: moderator.lastName,
|
||||
recipientEmail: user.emailContact.email,
|
||||
recipientFirstName: user.firstName,
|
||||
recipientLastName: user.lastName,
|
||||
contributionMemo: contribution.memo,
|
||||
contributionAmount: contribution.amount,
|
||||
overviewURL: CONFIG.EMAIL_LINK_OVERVIEW,
|
||||
})
|
||||
|
||||
return !!res
|
||||
}
|
||||
|
||||
38
backend/src/mailer/sendContributionRejectedEmail.test.ts
Normal file
38
backend/src/mailer/sendContributionRejectedEmail.test.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { sendContributionRejectedEmail } from './sendContributionRejectedEmail'
|
||||
import { sendEMail } from './sendEMail'
|
||||
|
||||
jest.mock('./sendEMail', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
sendEMail: jest.fn(),
|
||||
}
|
||||
})
|
||||
|
||||
describe('sendContributionConfirmedEmail', () => {
|
||||
beforeEach(async () => {
|
||||
await sendContributionRejectedEmail({
|
||||
senderFirstName: 'Peter',
|
||||
senderLastName: 'Lustig',
|
||||
recipientFirstName: 'Bibi',
|
||||
recipientLastName: 'Bloxberg',
|
||||
recipientEmail: 'bibi@bloxberg.de',
|
||||
contributionMemo: 'Vielen herzlichen Dank für den neuen Hexenbesen!',
|
||||
contributionAmount: new Decimal(200.0),
|
||||
overviewURL: 'http://localhost/overview',
|
||||
})
|
||||
})
|
||||
|
||||
it('calls sendEMail', () => {
|
||||
expect(sendEMail).toBeCalledWith({
|
||||
to: 'Bibi Bloxberg <bibi@bloxberg.de>',
|
||||
subject: 'Schöpfung wurde abgelehnt',
|
||||
text:
|
||||
expect.stringContaining('Hallo Bibi Bloxberg') &&
|
||||
expect.stringContaining(
|
||||
'Dein Gradido Schöpfungsantrag "Vielen herzlichen Dank für den neuen Hexenbesen!" wurde soeben von Peter Lustig abgelehnt.',
|
||||
) &&
|
||||
expect.stringContaining('Link zu deinem Konto: http://localhost/overview'),
|
||||
})
|
||||
})
|
||||
})
|
||||
26
backend/src/mailer/sendContributionRejectedEmail.ts
Normal file
26
backend/src/mailer/sendContributionRejectedEmail.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { sendEMail } from './sendEMail'
|
||||
import { contributionRejected } from './text/contributionRejected'
|
||||
|
||||
export const sendContributionRejectedEmail = (data: {
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
recipientFirstName: string
|
||||
recipientLastName: string
|
||||
recipientEmail: string
|
||||
contributionMemo: string
|
||||
contributionAmount: Decimal
|
||||
overviewURL: string
|
||||
}): Promise<boolean> => {
|
||||
logger.info(
|
||||
`sendEmail(): to=${data.recipientFirstName} ${data.recipientLastName} <${data.recipientEmail}>,
|
||||
subject=${contributionRejected.de.subject},
|
||||
text=${contributionRejected.de.text(data)}`,
|
||||
)
|
||||
return sendEMail({
|
||||
to: `${data.recipientFirstName} ${data.recipientLastName} <${data.recipientEmail}>`,
|
||||
subject: contributionRejected.de.subject,
|
||||
text: contributionRejected.de.text(data),
|
||||
})
|
||||
}
|
||||
27
backend/src/mailer/text/contributionRejected.ts
Normal file
27
backend/src/mailer/text/contributionRejected.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
|
||||
export const contributionRejected = {
|
||||
de: {
|
||||
subject: 'Schöpfung wurde abgelehnt',
|
||||
text: (data: {
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
recipientFirstName: string
|
||||
recipientLastName: string
|
||||
contributionMemo: string
|
||||
contributionAmount: Decimal
|
||||
overviewURL: string
|
||||
}): string =>
|
||||
`Hallo ${data.recipientFirstName} ${data.recipientLastName},
|
||||
|
||||
Dein eingereichter Gemeinwohl-Beitrag "${data.contributionMemo}" wurde soeben von ${data.senderFirstName} ${data.senderLastName} abgelehnt.
|
||||
|
||||
Bitte antworte nicht auf diese E-Mail!
|
||||
|
||||
Mit freundlichen Grüßen,
|
||||
dein Gradido-Team
|
||||
|
||||
|
||||
Link zu deinem Konto: ${data.overviewURL}`,
|
||||
},
|
||||
}
|
||||
@ -18,7 +18,7 @@ ENV NODE_ENV="production"
|
||||
# Labels
|
||||
LABEL org.label-schema.build-date="${BUILD_DATE}"
|
||||
LABEL org.label-schema.name="gradido:database"
|
||||
LABEL org.label-schema.description="Gradido GraphQL Backend"
|
||||
LABEL org.label-schema.description="Gradido Database Migration Service"
|
||||
LABEL org.label-schema.usage="https://github.com/gradido/gradido/blob/master/README.md"
|
||||
LABEL org.label-schema.url="https://gradido.net"
|
||||
LABEL org.label-schema.vcs-url="https://github.com/gradido/gradido/tree/master/database"
|
||||
|
||||
@ -20,10 +20,10 @@ ENV PORT="3000"
|
||||
# Labels
|
||||
LABEL org.label-schema.build-date="${BUILD_DATE}"
|
||||
LABEL org.label-schema.name="gradido:frontend"
|
||||
LABEL org.label-schema.description="Gradido Vue Webwallet"
|
||||
LABEL org.label-schema.usage="https://github.com/gradido/gradido_vue_wallet/blob/master/README.md"
|
||||
LABEL org.label-schema.description="Gradido Wallet Interface"
|
||||
LABEL org.label-schema.usage="https://github.com/gradido/gradido/blob/master/README.md"
|
||||
LABEL org.label-schema.url="https://gradido.net"
|
||||
LABEL org.label-schema.vcs-url="https://github.com/gradido/gradido_vue_wallet/tree/master/backend"
|
||||
LABEL org.label-schema.vcs-url="https://github.com/gradido/gradido/tree/master/frontend"
|
||||
LABEL org.label-schema.vcs-ref="${BUILD_COMMIT}"
|
||||
LABEL org.label-schema.vendor="gradido Community"
|
||||
LABEL org.label-schema.version="${BUILD_VERSION}"
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<div class="m-1 mt-2">{{ $t('GDD') }}</div>
|
||||
</b-input-group-prepend>
|
||||
|
||||
<div class="p-3">{{ (amount * -1) | GDD }}</div>
|
||||
<div class="p-3">{{ amount | GDD }}</div>
|
||||
</b-input-group>
|
||||
|
||||
<br />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user