Merge branch 'master' into 1555-Admin-see-user-generated-link

This commit is contained in:
Alexander Friedland 2022-03-28 18:00:25 +02:00 committed by GitHub
commit d5b57dcf1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 103 additions and 12 deletions

View File

@ -34,6 +34,9 @@ import { virtualLinkTransaction, virtualDecayTransaction } from '@/util/virtualT
import Decimal from 'decimal.js-light' import Decimal from 'decimal.js-light'
import { calculateDecay } from '@/util/decay' import { calculateDecay } from '@/util/decay'
const MEMO_MAX_CHARS = 255
const MEMO_MIN_CHARS = 5
export const executeTransaction = async ( export const executeTransaction = async (
amount: Decimal, amount: Decimal,
memo: string, memo: string,
@ -45,6 +48,14 @@ export const executeTransaction = async (
throw new Error('Sender and Recipient are the same.') throw new Error('Sender and Recipient are the same.')
} }
if (memo.length > MEMO_MAX_CHARS) {
throw new Error(`memo text is too long (${MEMO_MAX_CHARS} characters maximum)`)
}
if (memo.length < MEMO_MIN_CHARS) {
throw new Error(`memo text is too short (${MEMO_MIN_CHARS} characters minimum)`)
}
// validate amount // validate amount
const receivedCallDate = new Date() const receivedCallDate = new Date()
const sendBalance = await calculateBalance(sender.id, amount.mul(-1), receivedCallDate) const sendBalance = await calculateBalance(sender.id, amount.mul(-1), receivedCallDate)

View File

@ -62,11 +62,8 @@ describe('TransactionForm', () => {
}) })
}) })
describe('is selected: "send"', () => { describe('send GDD', () => {
beforeEach(async () => { beforeEach(async () => {
// await wrapper.setData({
// selected: 'send',
// })
await wrapper.findAll('input[type="radio"]').at(0).setChecked() await wrapper.findAll('input[type="radio"]').at(0).setChecked()
}) })
@ -78,15 +75,18 @@ describe('TransactionForm', () => {
beforeEach(() => { beforeEach(() => {
wrapper.setProps({ balance: 100.0 }) wrapper.setProps({ balance: 100.0 })
}) })
describe('transaction form show because balance 100,0 GDD', () => { describe('transaction form show because balance 100,0 GDD', () => {
it('has no warning message ', () => { it('has no warning message ', () => {
expect(wrapper.find('.errors').exists()).toBe(false) expect(wrapper.find('.errors').exists()).toBe(false)
}) })
it('has a reset button', () => { it('has a reset button', () => {
expect(wrapper.find('.test-buttons').findAll('button').at(0).attributes('type')).toBe( expect(wrapper.find('.test-buttons').findAll('button').at(0).attributes('type')).toBe(
'reset', 'reset',
) )
}) })
it('has a submit button', () => { it('has a submit button', () => {
expect(wrapper.find('.test-buttons').findAll('button').at(1).attributes('type')).toBe( expect(wrapper.find('.test-buttons').findAll('button').at(1).attributes('type')).toBe(
'submit', 'submit',
@ -121,6 +121,12 @@ describe('TransactionForm', () => {
expect(wrapper.find('span.errors').text()).toBe('validations.messages.email') expect(wrapper.find('span.errors').text()).toBe('validations.messages.email')
}) })
it('flushes an error message when email is the email of logged in user', async () => {
await wrapper.find('#input-group-1').find('input').setValue('user@example.org')
await flushPromises()
expect(wrapper.find('span.errors').text()).toBe('form.validation.is-not')
})
it('trims the email after blur', async () => { it('trims the email after blur', async () => {
await wrapper.find('#input-group-1').find('input').setValue(' valid@email.com ') await wrapper.find('#input-group-1').find('input').setValue(' valid@email.com ')
await wrapper.find('#input-group-1').find('input').trigger('blur') await wrapper.find('#input-group-1').find('input').trigger('blur')
@ -195,6 +201,41 @@ describe('TransactionForm', () => {
expect(wrapper.find('span.errors').text()).toBe('validations.messages.min') expect(wrapper.find('span.errors').text()).toBe('validations.messages.min')
}) })
it('flushes an error message when memo is more than 255 characters', async () => {
await wrapper.find('#input-group-3').find('textarea').setValue(`
Es ist ein König in Thule, der trinkt
Champagner, es geht ihm nichts drüber;
Und wenn er seinen Champagner trinkt,
Dann gehen die Augen ihm über.
Die Ritter sitzen um ihn her,
Die ganze Historische Schule;
Ihm aber wird die Zunge schwer,
Es lallt der König von Thule:
Als Alexander, der Griechenheld,
Mit seinem kleinen Haufen
Erobert hatte die ganze Welt,
Da gab er sich ans Saufen.
Ihn hatten so durstig gemacht der Krieg
Und die Schlachten, die er geschlagen;
Er soff sich zu Tode nach dem Sieg,
Er konnte nicht viel vertragen.
Ich aber bin ein stärkerer Mann
Und habe mich klüger besonnen:
Wie jener endete, fang ich an,
Ich hab mit dem Trinken begonnen.
Im Rausche wird der Heldenzug
Mir später weit besser gelingen;
Dann werde ich, taumelnd von Krug zu Krug,
Die ganze Welt bezwingen.`)
await flushPromises()
expect(wrapper.find('span.errors').text()).toBe('validations.messages.max')
})
it('flushes no error message when memo is valid', async () => { it('flushes no error message when memo is valid', async () => {
await wrapper.find('#input-group-3').find('textarea').setValue('Long enough') await wrapper.find('#input-group-3').find('textarea').setValue('Long enough')
await flushPromises() await flushPromises()

View File

@ -99,7 +99,7 @@
:rules="{ :rules="{
required: true, required: true,
min: 5, min: 5,
max: 150, max: 255,
}" }"
:name="$t('form.message')" :name="$t('form.message')"
v-slot="{ errors }" v-slot="{ errors }"

View File

@ -10,9 +10,20 @@
</b-col> </b-col>
<b-col cols="7"> <b-col cols="7">
<div class="gdd-transaction-list-item-name"> <div class="gdd-transaction-list-item-name">
<b-link v-if="linkedUser && linkedUser.email" @click.stop="tunnelEmail"> <div v-if="linkedUser && linkedUser.email">
<b-link @click.stop="tunnelEmail">
{{ itemText }} {{ itemText }}
</b-link> </b-link>
<span v-if="transactionLinkId">
{{ $t('via_link') }}
<b-icon
icon="link45deg"
variant="muted"
class="m-mb-1"
:title="$t('gdd_per_link.redeemed-title')"
/>
</span>
</div>
<span v-else>{{ itemText }}</span> <span v-else>{{ itemText }}</span>
</div> </div>
</b-col> </b-col>
@ -35,6 +46,11 @@ export default {
type: String, type: String,
required: false, required: false,
}, },
transactionLinkId: {
type: Number,
required: false,
default: null,
},
}, },
methods: { methods: {
tunnelEmail() { tunnelEmail() {

View File

@ -13,7 +13,12 @@
<b-col cols="11"> <b-col cols="11">
<!-- Amount / Name || Text --> <!-- Amount / Name || Text -->
<amount-and-name-row :amount="amount" :linkedUser="linkedUser" v-on="$listeners" /> <amount-and-name-row
v-on="$listeners"
:amount="amount"
:linkedUser="linkedUser"
:transactionLinkId="transactionLinkId"
/>
<!-- Nachricht Memo --> <!-- Nachricht Memo -->
<memo-row :memo="memo" /> <memo-row :memo="memo" />
@ -86,6 +91,10 @@ export default {
type: Date, type: Date,
required: true, required: true,
}, },
transactionLinkId: {
type: Number,
required: false,
},
}, },
data() { data() {
return { return {

View File

@ -13,7 +13,12 @@
<b-col cols="11"> <b-col cols="11">
<!-- Amount / Name --> <!-- Amount / Name -->
<amount-and-name-row :amount="amount" :linkedUser="linkedUser" v-on="$listeners" /> <amount-and-name-row
v-on="$listeners"
:amount="amount"
:linkedUser="linkedUser"
:transactionLinkId="transactionLinkId"
/>
<!-- Memo --> <!-- Memo -->
<memo-row :memo="memo" /> <memo-row :memo="memo" />
@ -87,6 +92,10 @@ export default {
type: Date, type: Date,
required: true, required: true,
}, },
transactionLinkId: {
type: Number,
required: false,
},
}, },
data() { data() {
return { return {

View File

@ -70,6 +70,7 @@ export const transactionsQuery = gql`
linkedUser { linkedUser {
email email
} }
transactionLinkId
} }
} }
} }

View File

@ -115,6 +115,7 @@
"redeem-text": "Willst du den Betrag jetzt einlösen?", "redeem-text": "Willst du den Betrag jetzt einlösen?",
"redeemed": "Erfolgreich eingelöst! Deinem Konto wurden {n} GDD gutgeschrieben.", "redeemed": "Erfolgreich eingelöst! Deinem Konto wurden {n} GDD gutgeschrieben.",
"redeemed-at": "Der Link wurde bereits am {date} eingelöst.", "redeemed-at": "Der Link wurde bereits am {date} eingelöst.",
"redeemed-title": "eingelöst",
"to-login": "Log dich ein", "to-login": "Log dich ein",
"to-register": "Registriere ein neues Konto", "to-register": "Registriere ein neues Konto",
"valid_until": "Gültig bis" "valid_until": "Gültig bis"
@ -249,5 +250,6 @@
}, },
"transaction-link": { "transaction-link": {
"send_you": "sendet dir" "send_you": "sendet dir"
} },
"via_link": "über einen Link"
} }

View File

@ -115,6 +115,7 @@
"redeem-text": "Do you want to redeem the amount now?", "redeem-text": "Do you want to redeem the amount now?",
"redeemed": "Successfully redeemed! Your account has been credited with {n} GDD.", "redeemed": "Successfully redeemed! Your account has been credited with {n} GDD.",
"redeemed-at": "The link was already redeemed on {date}.", "redeemed-at": "The link was already redeemed on {date}.",
"redeemed-title": "redeemed",
"to-login": "Log in", "to-login": "Log in",
"to-register": "Register a new account", "to-register": "Register a new account",
"valid_until": "Valid until" "valid_until": "Valid until"
@ -249,5 +250,6 @@
}, },
"transaction-link": { "transaction-link": {
"send_you": "wants to send you" "send_you": "wants to send you"
} },
"via_link": "via Link"
} }