mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into refactor-balance-resolver
This commit is contained in:
commit
43242c98b4
@ -1,5 +1,5 @@
|
|||||||
import { mount } from '@vue/test-utils'
|
import { mount } from '@vue/test-utils'
|
||||||
import CreationTransactionListFormular from './CreationTransactionListFormular.vue'
|
import CreationTransactionList from './CreationTransactionList.vue'
|
||||||
import { toastErrorSpy } from '../../test/testSetup'
|
import { toastErrorSpy } from '../../test/testSetup'
|
||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
@ -46,11 +46,11 @@ const propsData = {
|
|||||||
fields: ['date', 'balance', 'name', 'memo', 'decay'],
|
fields: ['date', 'balance', 'name', 'memo', 'decay'],
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('CreationTransactionListFormular', () => {
|
describe('CreationTransactionList', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
|
|
||||||
const Wrapper = () => {
|
const Wrapper = () => {
|
||||||
return mount(CreationTransactionListFormular, { localVue, mocks, propsData })
|
return mount(CreationTransactionList, { localVue, mocks, propsData })
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('mount', () => {
|
describe('mount', () => {
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="component-creation-transaction-list">
|
<div class="component-creation-transaction-list">
|
||||||
{{ $t('transactionlist.title') }}
|
<div class="h3">{{ $t('transactionlist.title') }}</div>
|
||||||
<b-table striped hover :fields="fields" :items="items"></b-table>
|
<b-table striped hover :fields="fields" :items="items"></b-table>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
129
admin/src/components/Tables/OpenCreationsTable.spec.js
Normal file
129
admin/src/components/Tables/OpenCreationsTable.spec.js
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import OpenCreationsTable from './OpenCreationsTable.vue'
|
||||||
|
|
||||||
|
const localVue = global.localVue
|
||||||
|
|
||||||
|
const apolloMutateMock = jest.fn().mockResolvedValue({})
|
||||||
|
const apolloQueryMock = jest.fn().mockResolvedValue({})
|
||||||
|
|
||||||
|
const propsData = {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
firstName: 'Bob',
|
||||||
|
lastName: 'der Baumeister',
|
||||||
|
email: 'bob@baumeister.de',
|
||||||
|
amount: 300,
|
||||||
|
memo: 'Aktives Grundeinkommen für Januar 2022',
|
||||||
|
date: '2022-01-01T00:00:00.000Z',
|
||||||
|
moderator: 1,
|
||||||
|
creation: [700, 1000, 1000],
|
||||||
|
__typename: 'PendingCreation',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
firstName: 'Räuber',
|
||||||
|
lastName: 'Hotzenplotz',
|
||||||
|
email: 'raeuber@hotzenplotz.de',
|
||||||
|
amount: 210,
|
||||||
|
memo: 'Aktives Grundeinkommen für Januar 2022',
|
||||||
|
date: '2022-01-01T00:00:00.000Z',
|
||||||
|
moderator: 1,
|
||||||
|
creation: [790, 1000, 1000],
|
||||||
|
__typename: 'PendingCreation',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
firstName: 'Stephen',
|
||||||
|
lastName: 'Hawking',
|
||||||
|
email: 'stephen@hawking.uk',
|
||||||
|
amount: 330,
|
||||||
|
memo: 'Aktives Grundeinkommen für Januar 2022',
|
||||||
|
date: '2022-01-01T00:00:00.000Z',
|
||||||
|
moderator: 1,
|
||||||
|
creation: [670, 1000, 1000],
|
||||||
|
__typename: 'PendingCreation',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
fields: [
|
||||||
|
{ key: 'bookmark', label: 'delete' },
|
||||||
|
{ key: 'email', label: 'e_mail' },
|
||||||
|
{ key: 'firstName', label: 'firstname' },
|
||||||
|
{ key: 'lastName', label: 'lastname' },
|
||||||
|
{
|
||||||
|
key: 'amount',
|
||||||
|
label: 'creation',
|
||||||
|
formatter: (value) => {
|
||||||
|
return value + ' GDD'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ key: 'memo', label: 'text' },
|
||||||
|
{
|
||||||
|
key: 'date',
|
||||||
|
label: 'date',
|
||||||
|
formatter: (value) => {
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ key: 'moderator', label: 'moderator' },
|
||||||
|
{ key: 'edit_creation', label: 'edit' },
|
||||||
|
{ key: 'confirm', label: 'save' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const mocks = {
|
||||||
|
$t: jest.fn((t) => t),
|
||||||
|
$d: jest.fn((d) => d),
|
||||||
|
$apollo: {
|
||||||
|
mutate: apolloMutateMock,
|
||||||
|
query: apolloQueryMock,
|
||||||
|
},
|
||||||
|
$store: {
|
||||||
|
state: {
|
||||||
|
moderator: {
|
||||||
|
id: 0,
|
||||||
|
name: 'test moderator',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('OpenCreationsTable', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const Wrapper = () => {
|
||||||
|
return mount(OpenCreationsTable, { localVue, mocks, propsData })
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('mount', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has a DIV element with the class .open-creations-table', () => {
|
||||||
|
expect(wrapper.find('div.open-creations-table').exists()).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has a table with three rows', () => {
|
||||||
|
expect(wrapper.findAll('tbody > tr')).toHaveLength(3)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('find first button.bi-pencil-square for open EditCreationFormular ', () => {
|
||||||
|
expect(wrapper.findAll('tr').at(1).find('.bi-pencil-square').exists()).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('show edit details', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await wrapper.findAll('tr').at(1).find('.bi-pencil-square').trigger('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
it.skip('has a component element with name EditCreationFormular', () => {
|
||||||
|
expect(wrapper.findComponent({ name: 'EditCreationFormular' }).exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it.skip('renders the component component-edit-creation-formular', () => {
|
||||||
|
expect(wrapper.find('div.component-edit-creation-formular').exists()).toBeTruthy()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="component-open-creations-table">
|
<div class="open-creations-table">
|
||||||
<b-table-lite :items="items" :fields="fields" caption-top striped hover stacked="md">
|
<b-table-lite :items="items" :fields="fields" caption-top striped hover stacked="md">
|
||||||
<template #cell(bookmark)="row">
|
<template #cell(bookmark)="row">
|
||||||
<b-button
|
<b-button
|
||||||
|
|||||||
@ -69,10 +69,9 @@
|
|||||||
: ''
|
: ''
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<creation-transaction-list-formular
|
<creation-transaction-list v-if="!row.item.deletedAt" :userId="row.item.userId" />
|
||||||
v-if="!row.item.deletedAt"
|
<transaction-link-list :userId="row.item.userId" />
|
||||||
:userId="row.item.userId"
|
|
||||||
/>
|
|
||||||
<deleted-user-formular :item="row.item" @updateDeletedAt="updateDeletedAt" />
|
<deleted-user-formular :item="row.item" @updateDeletedAt="updateDeletedAt" />
|
||||||
</b-card>
|
</b-card>
|
||||||
</template>
|
</template>
|
||||||
@ -82,7 +81,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import CreationFormular from '../CreationFormular.vue'
|
import CreationFormular from '../CreationFormular.vue'
|
||||||
import ConfirmRegisterMailFormular from '../ConfirmRegisterMailFormular.vue'
|
import ConfirmRegisterMailFormular from '../ConfirmRegisterMailFormular.vue'
|
||||||
import CreationTransactionListFormular from '../CreationTransactionListFormular.vue'
|
import CreationTransactionList from '../CreationTransactionList.vue'
|
||||||
|
import TransactionLinkList from '../TransactionLinkList.vue'
|
||||||
import DeletedUserFormular from '../DeletedUserFormular.vue'
|
import DeletedUserFormular from '../DeletedUserFormular.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -90,7 +90,8 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
CreationFormular,
|
CreationFormular,
|
||||||
ConfirmRegisterMailFormular,
|
ConfirmRegisterMailFormular,
|
||||||
CreationTransactionListFormular,
|
CreationTransactionList,
|
||||||
|
TransactionLinkList,
|
||||||
DeletedUserFormular,
|
DeletedUserFormular,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|||||||
140
admin/src/components/TransactionLinkList.spec.js
Normal file
140
admin/src/components/TransactionLinkList.spec.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import TransactionLinkList from './TransactionLinkList.vue'
|
||||||
|
import { listTransactionLinksAdmin } from '../graphql/listTransactionLinksAdmin.js'
|
||||||
|
import { toastErrorSpy } from '../../test/testSetup'
|
||||||
|
|
||||||
|
const localVue = global.localVue
|
||||||
|
|
||||||
|
const apolloQueryMock = jest.fn()
|
||||||
|
apolloQueryMock.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
listTransactionLinksAdmin: {
|
||||||
|
linkCount: 8,
|
||||||
|
linkList: [
|
||||||
|
{
|
||||||
|
amount: '19.99',
|
||||||
|
code: '62ef8236ace7217fbd066c5a',
|
||||||
|
createdAt: '2022-03-24T17:43:09.000Z',
|
||||||
|
deletedAt: null,
|
||||||
|
holdAvailableAmount: '20.51411720068412022949',
|
||||||
|
id: 36,
|
||||||
|
memo: 'Kein Trick, keine Zauberrei,\nbei Gradidio sei dabei!',
|
||||||
|
redeemedAt: null,
|
||||||
|
validUntil: '2022-04-07T17:43:09.000Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
amount: '19.99',
|
||||||
|
code: '2b603f36521c617fbd066cef',
|
||||||
|
createdAt: '2022-03-24T17:43:09.000Z',
|
||||||
|
deletedAt: null,
|
||||||
|
holdAvailableAmount: '20.51411720068412022949',
|
||||||
|
id: 37,
|
||||||
|
memo: 'Kein Trick, keine Zauberrei,\nbei Gradidio sei dabei!',
|
||||||
|
redeemedAt: null,
|
||||||
|
validUntil: '2022-04-07T17:43:09.000Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
amount: '19.99',
|
||||||
|
code: '0bb789b5bd5b717fbd066eb5',
|
||||||
|
createdAt: '2022-03-24T17:43:09.000Z',
|
||||||
|
deletedAt: '2022-03-24T17:43:09.000Z',
|
||||||
|
holdAvailableAmount: '20.51411720068412022949',
|
||||||
|
id: 40,
|
||||||
|
memo: 'Da habe ich mich wohl etwas übernommen.',
|
||||||
|
redeemedAt: '2022-04-07T14:43:09.000Z',
|
||||||
|
validUntil: '2022-04-07T17:43:09.000Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
amount: '19.99',
|
||||||
|
code: '2d4a763e516b317fbd066a85',
|
||||||
|
createdAt: '2022-01-01T00:00:00.000Z',
|
||||||
|
deletedAt: null,
|
||||||
|
holdAvailableAmount: '20.51411720068412022949',
|
||||||
|
id: 33,
|
||||||
|
memo: 'Leider wollte niemand meine Gradidos zum Neujahr haben :(',
|
||||||
|
redeemedAt: null,
|
||||||
|
validUntil: '2022-01-15T00:00:00.000Z',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const propsData = {
|
||||||
|
userId: 42,
|
||||||
|
}
|
||||||
|
|
||||||
|
const mocks = {
|
||||||
|
$apollo: {
|
||||||
|
query: apolloQueryMock,
|
||||||
|
},
|
||||||
|
$t: jest.fn((t) => t),
|
||||||
|
$d: jest.fn((d) => d),
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('TransactionLinkList', () => {
|
||||||
|
let wrapper
|
||||||
|
|
||||||
|
const Wrapper = () => {
|
||||||
|
return mount(TransactionLinkList, { localVue, mocks, propsData })
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('mount', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls the API', () => {
|
||||||
|
expect(apolloQueryMock).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
query: listTransactionLinksAdmin,
|
||||||
|
variables: {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
userId: 42,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has 4 items in the table', () => {
|
||||||
|
expect(wrapper.findAll('tbody > tr')).toHaveLength(4)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has pagination buttons', () => {
|
||||||
|
expect(wrapper.findComponent({ name: 'BPagination' }).exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('next page', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
await wrapper.findComponent({ name: 'BPagination' }).vm.$emit('input', 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls the API again', () => {
|
||||||
|
expect(apolloQueryMock).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
query: listTransactionLinksAdmin,
|
||||||
|
variables: {
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
userId: 42,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('server response with error', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
apolloQueryMock.mockRejectedValue({ message: 'Oh no!' })
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toasts an error message', () => {
|
||||||
|
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
105
admin/src/components/TransactionLinkList.vue
Normal file
105
admin/src/components/TransactionLinkList.vue
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<div class="transaction-link-list">
|
||||||
|
<div v-if="items.length > 0">
|
||||||
|
<div class="h3">{{ $t('transactionlink.form_header') }}</div>
|
||||||
|
<b-table striped hover :fields="fields" :items="items"></b-table>
|
||||||
|
</div>
|
||||||
|
<b-pagination
|
||||||
|
pills
|
||||||
|
size="lg"
|
||||||
|
v-model="currentPage"
|
||||||
|
:per-page="perPage"
|
||||||
|
:total-rows="rows"
|
||||||
|
align="center"
|
||||||
|
></b-pagination>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { listTransactionLinksAdmin } from '../graphql/listTransactionLinksAdmin.js'
|
||||||
|
export default {
|
||||||
|
name: 'TransactionLinkList',
|
||||||
|
props: {
|
||||||
|
userId: { type: Number, required: true },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
items: [],
|
||||||
|
rows: 0,
|
||||||
|
currentPage: 1,
|
||||||
|
perPage: 5,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getListTransactionLinks() {
|
||||||
|
this.$apollo
|
||||||
|
.query({
|
||||||
|
query: listTransactionLinksAdmin,
|
||||||
|
variables: {
|
||||||
|
currentPage: this.currentPage,
|
||||||
|
pageSize: this.perPage,
|
||||||
|
userId: this.userId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
this.rows = result.data.listTransactionLinksAdmin.linkCount
|
||||||
|
this.items = result.data.listTransactionLinksAdmin.linkList
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.toastError(error.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
fields() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'createdAt',
|
||||||
|
label: this.$t('transactionlink.created'),
|
||||||
|
formatter: (value, key, item) => {
|
||||||
|
return this.$d(new Date(value))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'amount',
|
||||||
|
label: this.$t('transactionlist.amount'),
|
||||||
|
formatter: (value, key, item) => {
|
||||||
|
return `${value} GDD`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ key: 'memo', label: this.$t('transactionlist.memo') },
|
||||||
|
{
|
||||||
|
key: 'validUntil',
|
||||||
|
label: this.$t('transactionlink.valid_until'),
|
||||||
|
formatter: (value, key, item) => {
|
||||||
|
return this.$d(new Date(value))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'status',
|
||||||
|
label: 'status',
|
||||||
|
formatter: (value, key, item) => {
|
||||||
|
// deleted
|
||||||
|
if (item.deletedAt) return this.$t('deleted') + ': ' + this.$d(new Date(item.deletedAt))
|
||||||
|
// redeemed
|
||||||
|
if (item.redeemedAt)
|
||||||
|
return this.$t('redeemed') + ': ' + this.$d(new Date(item.redeemedAt))
|
||||||
|
// expired
|
||||||
|
if (new Date() > new Date(item.validUntil))
|
||||||
|
return this.$t('expired') + ': ' + this.$d(new Date(item.validUntil))
|
||||||
|
// open
|
||||||
|
return this.$t('open')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getListTransactionLinks()
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
currentPage() {
|
||||||
|
this.getListTransactionLinks()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
20
admin/src/graphql/listTransactionLinksAdmin.js
Normal file
20
admin/src/graphql/listTransactionLinksAdmin.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
|
export const listTransactionLinksAdmin = gql`
|
||||||
|
query ($currentPage: Int = 1, $pageSize: Int = 5, $userId: Int!) {
|
||||||
|
listTransactionLinksAdmin(currentPage: $currentPage, pageSize: $pageSize, userId: $userId) {
|
||||||
|
linkCount
|
||||||
|
linkList {
|
||||||
|
id
|
||||||
|
amount
|
||||||
|
holdAvailableAmount
|
||||||
|
memo
|
||||||
|
code
|
||||||
|
createdAt
|
||||||
|
validUntil
|
||||||
|
redeemedAt
|
||||||
|
deletedAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
@ -27,6 +27,7 @@
|
|||||||
"edit": "Bearbeiten",
|
"edit": "Bearbeiten",
|
||||||
"enabled": "aktiviert",
|
"enabled": "aktiviert",
|
||||||
"error": "Fehler",
|
"error": "Fehler",
|
||||||
|
"expired": "abgelaufen",
|
||||||
"e_mail": "E-Mail",
|
"e_mail": "E-Mail",
|
||||||
"firstname": "Vorname",
|
"firstname": "Vorname",
|
||||||
"footer": {
|
"footer": {
|
||||||
@ -56,6 +57,7 @@
|
|||||||
"user_search": "Nutzersuche"
|
"user_search": "Nutzersuche"
|
||||||
},
|
},
|
||||||
"not_open_creations": "Keine offenen Schöpfungen",
|
"not_open_creations": "Keine offenen Schöpfungen",
|
||||||
|
"open": "offen",
|
||||||
"open_creations": "Offene Schöpfungen",
|
"open_creations": "Offene Schöpfungen",
|
||||||
"overlay": {
|
"overlay": {
|
||||||
"confirm": {
|
"confirm": {
|
||||||
@ -66,6 +68,7 @@
|
|||||||
"yes": "Ja, Schöpfung bestätigen und speichern!"
|
"yes": "Ja, Schöpfung bestätigen und speichern!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redeemed": "eingelöst",
|
||||||
"remove": "Entfernen",
|
"remove": "Entfernen",
|
||||||
"removeNotSelf": "Als Admin / Moderator kannst du dich nicht selber löschen.",
|
"removeNotSelf": "Als Admin / Moderator kannst du dich nicht selber löschen.",
|
||||||
"remove_all": "alle Nutzer entfernen",
|
"remove_all": "alle Nutzer entfernen",
|
||||||
@ -73,6 +76,11 @@
|
|||||||
"status": "Status",
|
"status": "Status",
|
||||||
"success": "Erfolg",
|
"success": "Erfolg",
|
||||||
"text": "Text",
|
"text": "Text",
|
||||||
|
"transactionlink": {
|
||||||
|
"created": "Erstellt",
|
||||||
|
"form_header": "Transaktion-Links",
|
||||||
|
"valid_until": "Gültig bis"
|
||||||
|
},
|
||||||
"transactionlist": {
|
"transactionlist": {
|
||||||
"amount": "Betrag",
|
"amount": "Betrag",
|
||||||
"balanceDate": "Schöpfungsdatum",
|
"balanceDate": "Schöpfungsdatum",
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"enabled": "enabled",
|
"enabled": "enabled",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
|
"expired": "expired",
|
||||||
"e_mail": "E-mail",
|
"e_mail": "E-mail",
|
||||||
"firstname": "Firstname",
|
"firstname": "Firstname",
|
||||||
"footer": {
|
"footer": {
|
||||||
@ -56,6 +57,7 @@
|
|||||||
"user_search": "User search"
|
"user_search": "User search"
|
||||||
},
|
},
|
||||||
"not_open_creations": "No open creations",
|
"not_open_creations": "No open creations",
|
||||||
|
"open": "open",
|
||||||
"open_creations": "Open creations",
|
"open_creations": "Open creations",
|
||||||
"overlay": {
|
"overlay": {
|
||||||
"confirm": {
|
"confirm": {
|
||||||
@ -66,6 +68,7 @@
|
|||||||
"yes": "Yes, confirm and save creation!"
|
"yes": "Yes, confirm and save creation!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"redeemed": "redeemed",
|
||||||
"remove": "Remove",
|
"remove": "Remove",
|
||||||
"removeNotSelf": "As admin / moderator you cannot delete yourself.",
|
"removeNotSelf": "As admin / moderator you cannot delete yourself.",
|
||||||
"remove_all": "Remove all users",
|
"remove_all": "Remove all users",
|
||||||
@ -73,6 +76,11 @@
|
|||||||
"status": "Status",
|
"status": "Status",
|
||||||
"success": "Success",
|
"success": "Success",
|
||||||
"text": "Text",
|
"text": "Text",
|
||||||
|
"transactionlink": {
|
||||||
|
"created": "Created",
|
||||||
|
"form_header": "Transaction links",
|
||||||
|
"valid_until": "Valid until"
|
||||||
|
},
|
||||||
"transactionlist": {
|
"transactionlist": {
|
||||||
"amount": "Amount",
|
"amount": "Amount",
|
||||||
"balanceDate": "Creation date",
|
"balanceDate": "Creation date",
|
||||||
|
|||||||
@ -36,4 +36,5 @@ export enum RIGHTS {
|
|||||||
DELETE_USER = 'DELETE_USER',
|
DELETE_USER = 'DELETE_USER',
|
||||||
UNDELETE_USER = 'UNDELETE_USER',
|
UNDELETE_USER = 'UNDELETE_USER',
|
||||||
CREATION_TRANSACTION_LIST = 'CREATION_TRANSACTION_LIST',
|
CREATION_TRANSACTION_LIST = 'CREATION_TRANSACTION_LIST',
|
||||||
|
LIST_TRANSACTION_LINKS_ADMIN = 'LIST_TRANSACTION_LINKS_ADMIN',
|
||||||
}
|
}
|
||||||
|
|||||||
13
backend/src/graphql/arg/TransactionLinkFilters.ts
Normal file
13
backend/src/graphql/arg/TransactionLinkFilters.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { ArgsType, Field } from 'type-graphql'
|
||||||
|
|
||||||
|
@ArgsType()
|
||||||
|
export default class TransactionLinkFilters {
|
||||||
|
@Field(() => Boolean, { nullable: true, defaultValue: true })
|
||||||
|
withDeleted?: boolean
|
||||||
|
|
||||||
|
@Field(() => Boolean, { nullable: true, defaultValue: true })
|
||||||
|
withExpired?: boolean
|
||||||
|
|
||||||
|
@Field(() => Boolean, { nullable: true, defaultValue: true })
|
||||||
|
withRedeemed?: boolean
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { ObjectType, Field } from 'type-graphql'
|
import { ObjectType, Field, Int } from 'type-graphql'
|
||||||
import Decimal from 'decimal.js-light'
|
import Decimal from 'decimal.js-light'
|
||||||
import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
|
import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
|
||||||
import { User } from './User'
|
import { User } from './User'
|
||||||
@ -52,3 +52,12 @@ export class TransactionLink {
|
|||||||
@Field(() => User, { nullable: true })
|
@Field(() => User, { nullable: true })
|
||||||
redeemedBy: User | null
|
redeemedBy: User | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class TransactionLinkResult {
|
||||||
|
@Field(() => Int)
|
||||||
|
linkCount: number
|
||||||
|
|
||||||
|
@Field(() => [TransactionLink])
|
||||||
|
linkList: TransactionLink[]
|
||||||
|
}
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import {
|
|||||||
ObjectLiteral,
|
ObjectLiteral,
|
||||||
getConnection,
|
getConnection,
|
||||||
In,
|
In,
|
||||||
|
MoreThan,
|
||||||
|
FindOperator,
|
||||||
} from '@dbTools/typeorm'
|
} from '@dbTools/typeorm'
|
||||||
import { UserAdmin, SearchUsersResult } from '@model/UserAdmin'
|
import { UserAdmin, SearchUsersResult } from '@model/UserAdmin'
|
||||||
import { PendingCreation } from '@model/PendingCreation'
|
import { PendingCreation } from '@model/PendingCreation'
|
||||||
@ -21,6 +23,8 @@ import UpdatePendingCreationArgs from '@arg/UpdatePendingCreationArgs'
|
|||||||
import SearchUsersArgs from '@arg/SearchUsersArgs'
|
import SearchUsersArgs from '@arg/SearchUsersArgs'
|
||||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||||
import { Transaction } from '@model/Transaction'
|
import { Transaction } from '@model/Transaction'
|
||||||
|
import { TransactionLink, TransactionLinkResult } from '@model/TransactionLink'
|
||||||
|
import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
|
||||||
import { TransactionRepository } from '@repository/Transaction'
|
import { TransactionRepository } from '@repository/Transaction'
|
||||||
import { calculateDecay } from '@/util/decay'
|
import { calculateDecay } from '@/util/decay'
|
||||||
import { AdminPendingCreation } from '@entity/AdminPendingCreation'
|
import { AdminPendingCreation } from '@entity/AdminPendingCreation'
|
||||||
@ -32,6 +36,7 @@ import { TransactionTypeId } from '@enum/TransactionTypeId'
|
|||||||
import Decimal from 'decimal.js-light'
|
import Decimal from 'decimal.js-light'
|
||||||
import { Decay } from '@model/Decay'
|
import { Decay } from '@model/Decay'
|
||||||
import Paginated from '@arg/Paginated'
|
import Paginated from '@arg/Paginated'
|
||||||
|
import TransactionLinkFilters from '@arg/TransactionLinkFilters'
|
||||||
import { Order } from '@enum/Order'
|
import { Order } from '@enum/Order'
|
||||||
import { communityUser } from '@/util/communityUser'
|
import { communityUser } from '@/util/communityUser'
|
||||||
|
|
||||||
@ -369,6 +374,41 @@ export class AdminResolver {
|
|||||||
const user = await dbUser.findOneOrFail({ id: userId })
|
const user = await dbUser.findOneOrFail({ id: userId })
|
||||||
return userTransactions.map((t) => new Transaction(t, new User(user), communityUser))
|
return userTransactions.map((t) => new Transaction(t, new User(user), communityUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Authorized([RIGHTS.LIST_TRANSACTION_LINKS_ADMIN])
|
||||||
|
@Query(() => TransactionLinkResult)
|
||||||
|
async listTransactionLinksAdmin(
|
||||||
|
@Args()
|
||||||
|
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
|
||||||
|
@Args()
|
||||||
|
filters: TransactionLinkFilters,
|
||||||
|
@Arg('userId', () => Int) userId: number,
|
||||||
|
): Promise<TransactionLinkResult> {
|
||||||
|
const user = await dbUser.findOneOrFail({ id: userId })
|
||||||
|
const where: {
|
||||||
|
userId: number
|
||||||
|
redeemedBy?: number | null
|
||||||
|
validUntil?: FindOperator<Date> | null
|
||||||
|
} = {
|
||||||
|
userId,
|
||||||
|
}
|
||||||
|
if (!filters.withRedeemed) where.redeemedBy = null
|
||||||
|
if (!filters.withExpired) where.validUntil = MoreThan(new Date())
|
||||||
|
const [transactionLinks, count] = await dbTransactionLink.findAndCount({
|
||||||
|
where,
|
||||||
|
withDeleted: filters.withDeleted,
|
||||||
|
order: {
|
||||||
|
createdAt: order,
|
||||||
|
},
|
||||||
|
skip: (currentPage - 1) * pageSize,
|
||||||
|
take: pageSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
linkCount: count,
|
||||||
|
linkList: transactionLinks.map((tl) => new TransactionLink(tl, new User(user))),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CreationMap {
|
interface CreationMap {
|
||||||
|
|||||||
@ -49,6 +49,8 @@ KLICKTIPP_APIKEY_EN=
|
|||||||
DATABASE_CONFIG_VERSION=v1.2022-03-18
|
DATABASE_CONFIG_VERSION=v1.2022-03-18
|
||||||
|
|
||||||
# frontend
|
# frontend
|
||||||
|
FRONTEND_CONFIG_VERSION=v1.2022-03-18
|
||||||
|
|
||||||
GRAPHQL_URI=https://stage1.gradido.net/graphql
|
GRAPHQL_URI=https://stage1.gradido.net/graphql
|
||||||
ADMIN_AUTH_URL=https://stage1.gradido.net/admin/authenticate?token={token}
|
ADMIN_AUTH_URL=https://stage1.gradido.net/admin/authenticate?token={token}
|
||||||
|
|
||||||
@ -62,5 +64,7 @@ META_KEYWORDS_EN="Basic Income, Currency, Gratitude, Gift Economy, Natural Econo
|
|||||||
META_AUTHOR="Bernd Hückstädt - Gradido-Akademie"
|
META_AUTHOR="Bernd Hückstädt - Gradido-Akademie"
|
||||||
|
|
||||||
# admin
|
# admin
|
||||||
|
ADMIN_CONFIG_VERSION=v1.2022-03-18
|
||||||
|
|
||||||
WALLET_AUTH_URL=https://stage1.gradido.net/authenticate?token={token}
|
WALLET_AUTH_URL=https://stage1.gradido.net/authenticate?token={token}
|
||||||
WALLET_URL=https://stage1.gradido.net/login
|
WALLET_URL=https://stage1.gradido.net/login
|
||||||
@ -78,8 +78,8 @@
|
|||||||
> git clone https://github.com/gradido/gradido.git
|
> git clone https://github.com/gradido/gradido.git
|
||||||
|
|
||||||
# Timezone
|
# Timezone
|
||||||
# Note: This is not needed - UTC(default) is REQUIRED for production data
|
# Note: This is needed - since there is Summer-Time included in the default server Setup - UTC is REQUIRED for production data
|
||||||
# > sudo timedatectl set-timezone UTC
|
> sudo timedatectl set-timezone UTC
|
||||||
# > sudo timedatectl set-ntp on
|
# > sudo timedatectl set-ntp on
|
||||||
# > sudo apt purge ntp
|
# > sudo apt purge ntp
|
||||||
# > sudo systemctl start systemd-timesyncd
|
# > sudo systemctl start systemd-timesyncd
|
||||||
|
|||||||
@ -67,7 +67,7 @@ BRANCH=${1:-master}
|
|||||||
echo "Starting with git pull - branch:$BRANCH" >> $UPDATE_HTML
|
echo "Starting with git pull - branch:$BRANCH" >> $UPDATE_HTML
|
||||||
cd $PROJECT_ROOT
|
cd $PROJECT_ROOT
|
||||||
# TODO: this overfetches alot, but ensures we can use start.sh with tags
|
# TODO: this overfetches alot, but ensures we can use start.sh with tags
|
||||||
git fetch origin --all
|
git fetch --all
|
||||||
git checkout $BRANCH
|
git checkout $BRANCH
|
||||||
git pull
|
git pull
|
||||||
export BUILD_COMMIT="$(git rev-parse HEAD)"
|
export BUILD_COMMIT="$(git rev-parse HEAD)"
|
||||||
|
|||||||
@ -2,7 +2,9 @@
|
|||||||
<div class="date-row">
|
<div class="date-row">
|
||||||
<b-row>
|
<b-row>
|
||||||
<b-col cols="5">
|
<b-col cols="5">
|
||||||
<div class="text-right">{{ diffNow ? $t('gdd_per_link.expired') : $t('form.date') }}</div>
|
<div class="text-right">
|
||||||
|
{{ diffNow ? $t('gdd_per_link.valid_until') : $t('form.date') }}
|
||||||
|
</div>
|
||||||
</b-col>
|
</b-col>
|
||||||
<b-col cols="7">
|
<b-col cols="7">
|
||||||
<div class="gdd-transaction-list-item-date">
|
<div class="gdd-transaction-list-item-date">
|
||||||
|
|||||||
@ -100,7 +100,6 @@
|
|||||||
"decay-14-day": "Vergänglichkeit für 14 Tage",
|
"decay-14-day": "Vergänglichkeit für 14 Tage",
|
||||||
"delete-the-link": "Den Link löschen?",
|
"delete-the-link": "Den Link löschen?",
|
||||||
"deleted": "Der Link wurde gelöscht!",
|
"deleted": "Der Link wurde gelöscht!",
|
||||||
"expired": "Abgelaufen",
|
|
||||||
"has-account": "Du besitzt bereits ein Gradido Konto",
|
"has-account": "Du besitzt bereits ein Gradido Konto",
|
||||||
"header": "Gradidos versenden per Link",
|
"header": "Gradidos versenden per Link",
|
||||||
"link-copied": "Link wurde in die Zwischenablage kopiert",
|
"link-copied": "Link wurde in die Zwischenablage kopiert",
|
||||||
@ -118,7 +117,8 @@
|
|||||||
"redeemed-at": "Der Link wurde bereits am {date} eingelöst.",
|
"redeemed-at": "Der Link wurde bereits am {date} eingelöst.",
|
||||||
"redeemed-title": "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"
|
||||||
},
|
},
|
||||||
"gdt": {
|
"gdt": {
|
||||||
"calculation": "Berechnung der GradidoTransform",
|
"calculation": "Berechnung der GradidoTransform",
|
||||||
|
|||||||
@ -100,7 +100,6 @@
|
|||||||
"decay-14-day": "Decay for 14 days",
|
"decay-14-day": "Decay for 14 days",
|
||||||
"delete-the-link": "Delete the link?",
|
"delete-the-link": "Delete the link?",
|
||||||
"deleted": "The link was deleted!",
|
"deleted": "The link was deleted!",
|
||||||
"expired": "Expired",
|
|
||||||
"has-account": "You already have a Gradido account",
|
"has-account": "You already have a Gradido account",
|
||||||
"header": "Send Gradidos via link",
|
"header": "Send Gradidos via link",
|
||||||
"link-copied": "Link copied to clipboard",
|
"link-copied": "Link copied to clipboard",
|
||||||
@ -118,7 +117,8 @@
|
|||||||
"redeemed-at": "The link was already redeemed on {date}.",
|
"redeemed-at": "The link was already redeemed on {date}.",
|
||||||
"redeemed-title": "redeemed",
|
"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"
|
||||||
},
|
},
|
||||||
"gdt": {
|
"gdt": {
|
||||||
"calculation": "Calculation of GradidoTransform",
|
"calculation": "Calculation of GradidoTransform",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user