mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into optin-valid-time
This commit is contained in:
commit
0c5719140d
@ -1,5 +1,5 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import CreationTransactionListFormular from './CreationTransactionListFormular.vue'
|
||||
import CreationTransactionList from './CreationTransactionList.vue'
|
||||
import { toastErrorSpy } from '../../test/testSetup'
|
||||
|
||||
const localVue = global.localVue
|
||||
@ -46,11 +46,11 @@ const propsData = {
|
||||
fields: ['date', 'balance', 'name', 'memo', 'decay'],
|
||||
}
|
||||
|
||||
describe('CreationTransactionListFormular', () => {
|
||||
describe('CreationTransactionList', () => {
|
||||
let wrapper
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(CreationTransactionListFormular, { localVue, mocks, propsData })
|
||||
return mount(CreationTransactionList, { localVue, mocks, propsData })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<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>
|
||||
</div>
|
||||
</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>
|
||||
<div class="component-open-creations-table">
|
||||
<div class="open-creations-table">
|
||||
<b-table-lite :items="items" :fields="fields" caption-top striped hover stacked="md">
|
||||
<template #cell(bookmark)="row">
|
||||
<b-button
|
||||
|
||||
@ -69,10 +69,9 @@
|
||||
: ''
|
||||
"
|
||||
/>
|
||||
<creation-transaction-list-formular
|
||||
v-if="!row.item.deletedAt"
|
||||
:userId="row.item.userId"
|
||||
/>
|
||||
<creation-transaction-list v-if="!row.item.deletedAt" :userId="row.item.userId" />
|
||||
<transaction-link-list :userId="row.item.userId" />
|
||||
|
||||
<deleted-user-formular :item="row.item" @updateDeletedAt="updateDeletedAt" />
|
||||
</b-card>
|
||||
</template>
|
||||
@ -82,7 +81,8 @@
|
||||
<script>
|
||||
import CreationFormular from '../CreationFormular.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'
|
||||
|
||||
export default {
|
||||
@ -90,7 +90,8 @@ export default {
|
||||
components: {
|
||||
CreationFormular,
|
||||
ConfirmRegisterMailFormular,
|
||||
CreationTransactionListFormular,
|
||||
CreationTransactionList,
|
||||
TransactionLinkList,
|
||||
DeletedUserFormular,
|
||||
},
|
||||
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",
|
||||
"enabled": "aktiviert",
|
||||
"error": "Fehler",
|
||||
"expired": "abgelaufen",
|
||||
"e_mail": "E-Mail",
|
||||
"firstname": "Vorname",
|
||||
"footer": {
|
||||
@ -56,6 +57,7 @@
|
||||
"user_search": "Nutzersuche"
|
||||
},
|
||||
"not_open_creations": "Keine offenen Schöpfungen",
|
||||
"open": "offen",
|
||||
"open_creations": "Offene Schöpfungen",
|
||||
"overlay": {
|
||||
"confirm": {
|
||||
@ -66,6 +68,7 @@
|
||||
"yes": "Ja, Schöpfung bestätigen und speichern!"
|
||||
}
|
||||
},
|
||||
"redeemed": "eingelöst",
|
||||
"remove": "Entfernen",
|
||||
"removeNotSelf": "Als Admin / Moderator kannst du dich nicht selber löschen.",
|
||||
"remove_all": "alle Nutzer entfernen",
|
||||
@ -73,6 +76,11 @@
|
||||
"status": "Status",
|
||||
"success": "Erfolg",
|
||||
"text": "Text",
|
||||
"transactionlink": {
|
||||
"created": "Erstellt",
|
||||
"form_header": "Transaktion-Links",
|
||||
"valid_until": "Gültig bis"
|
||||
},
|
||||
"transactionlist": {
|
||||
"amount": "Betrag",
|
||||
"balanceDate": "Schöpfungsdatum",
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
"edit": "Edit",
|
||||
"enabled": "enabled",
|
||||
"error": "Error",
|
||||
"expired": "expired",
|
||||
"e_mail": "E-mail",
|
||||
"firstname": "Firstname",
|
||||
"footer": {
|
||||
@ -56,6 +57,7 @@
|
||||
"user_search": "User search"
|
||||
},
|
||||
"not_open_creations": "No open creations",
|
||||
"open": "open",
|
||||
"open_creations": "Open creations",
|
||||
"overlay": {
|
||||
"confirm": {
|
||||
@ -66,6 +68,7 @@
|
||||
"yes": "Yes, confirm and save creation!"
|
||||
}
|
||||
},
|
||||
"redeemed": "redeemed",
|
||||
"remove": "Remove",
|
||||
"removeNotSelf": "As admin / moderator you cannot delete yourself.",
|
||||
"remove_all": "Remove all users",
|
||||
@ -73,6 +76,11 @@
|
||||
"status": "Status",
|
||||
"success": "Success",
|
||||
"text": "Text",
|
||||
"transactionlink": {
|
||||
"created": "Created",
|
||||
"form_header": "Transaction links",
|
||||
"valid_until": "Valid until"
|
||||
},
|
||||
"transactionlist": {
|
||||
"amount": "Amount",
|
||||
"balanceDate": "Creation date",
|
||||
|
||||
@ -35,4 +35,5 @@ export enum RIGHTS {
|
||||
DELETE_USER = 'DELETE_USER',
|
||||
UNDELETE_USER = 'UNDELETE_USER',
|
||||
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 { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
|
||||
import { User } from './User'
|
||||
@ -52,3 +52,12 @@ export class TransactionLink {
|
||||
@Field(() => User, { nullable: true })
|
||||
redeemedBy: User | null
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class TransactionLinkResult {
|
||||
@Field(() => Int)
|
||||
linkCount: number
|
||||
|
||||
@Field(() => [TransactionLink])
|
||||
linkList: TransactionLink[]
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import {
|
||||
ObjectLiteral,
|
||||
getConnection,
|
||||
In,
|
||||
MoreThan,
|
||||
FindOperator,
|
||||
} from '@dbTools/typeorm'
|
||||
import { UserAdmin, SearchUsersResult } from '@model/UserAdmin'
|
||||
import { PendingCreation } from '@model/PendingCreation'
|
||||
@ -21,6 +23,8 @@ import UpdatePendingCreationArgs from '@arg/UpdatePendingCreationArgs'
|
||||
import SearchUsersArgs from '@arg/SearchUsersArgs'
|
||||
import { Transaction as DbTransaction } from '@entity/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 { calculateDecay } from '@/util/decay'
|
||||
import { AdminPendingCreation } from '@entity/AdminPendingCreation'
|
||||
@ -32,6 +36,7 @@ import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { Decay } from '@model/Decay'
|
||||
import Paginated from '@arg/Paginated'
|
||||
import TransactionLinkFilters from '@arg/TransactionLinkFilters'
|
||||
import { Order } from '@enum/Order'
|
||||
import { communityUser } from '@/util/communityUser'
|
||||
import { checkOptInCode, activationLink } from './UserResolver'
|
||||
@ -404,6 +409,41 @@ export class AdminResolver {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@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 {
|
||||
|
||||
@ -49,6 +49,8 @@ KLICKTIPP_APIKEY_EN=
|
||||
DATABASE_CONFIG_VERSION=v1.2022-03-18
|
||||
|
||||
# frontend
|
||||
FRONTEND_CONFIG_VERSION=v1.2022-03-18
|
||||
|
||||
GRAPHQL_URI=https://stage1.gradido.net/graphql
|
||||
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"
|
||||
|
||||
# admin
|
||||
ADMIN_CONFIG_VERSION=v1.2022-03-18
|
||||
|
||||
WALLET_AUTH_URL=https://stage1.gradido.net/authenticate?token={token}
|
||||
WALLET_URL=https://stage1.gradido.net/login
|
||||
@ -78,8 +78,8 @@
|
||||
> git clone https://github.com/gradido/gradido.git
|
||||
|
||||
# Timezone
|
||||
# Note: This is not needed - UTC(default) is REQUIRED for production data
|
||||
# > sudo timedatectl set-timezone UTC
|
||||
# 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-ntp on
|
||||
# > sudo apt purge ntp
|
||||
# > sudo systemctl start systemd-timesyncd
|
||||
|
||||
@ -67,7 +67,7 @@ BRANCH=${1:-master}
|
||||
echo "Starting with git pull - branch:$BRANCH" >> $UPDATE_HTML
|
||||
cd $PROJECT_ROOT
|
||||
# TODO: this overfetches alot, but ensures we can use start.sh with tags
|
||||
git fetch origin --all
|
||||
git fetch --all
|
||||
git checkout $BRANCH
|
||||
git pull
|
||||
export BUILD_COMMIT="$(git rev-parse HEAD)"
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
<div class="date-row">
|
||||
<b-row>
|
||||
<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 cols="7">
|
||||
<div class="gdd-transaction-list-item-date">
|
||||
|
||||
@ -100,7 +100,6 @@
|
||||
"decay-14-day": "Vergänglichkeit für 14 Tage",
|
||||
"delete-the-link": "Den Link löschen?",
|
||||
"deleted": "Der Link wurde gelöscht!",
|
||||
"expired": "Abgelaufen",
|
||||
"has-account": "Du besitzt bereits ein Gradido Konto",
|
||||
"header": "Gradidos versenden per Link",
|
||||
"link-copied": "Link wurde in die Zwischenablage kopiert",
|
||||
@ -118,7 +117,8 @@
|
||||
"redeemed-at": "Der Link wurde bereits am {date} eingelöst.",
|
||||
"redeemed-title": "eingelöst",
|
||||
"to-login": "Log dich ein",
|
||||
"to-register": "Registriere ein neues Konto"
|
||||
"to-register": "Registriere ein neues Konto",
|
||||
"valid_until": "Gültig bis"
|
||||
},
|
||||
"gdt": {
|
||||
"calculation": "Berechnung der GradidoTransform",
|
||||
|
||||
@ -100,7 +100,6 @@
|
||||
"decay-14-day": "Decay for 14 days",
|
||||
"delete-the-link": "Delete the link?",
|
||||
"deleted": "The link was deleted!",
|
||||
"expired": "Expired",
|
||||
"has-account": "You already have a Gradido account",
|
||||
"header": "Send Gradidos via link",
|
||||
"link-copied": "Link copied to clipboard",
|
||||
@ -118,7 +117,8 @@
|
||||
"redeemed-at": "The link was already redeemed on {date}.",
|
||||
"redeemed-title": "redeemed",
|
||||
"to-login": "Log in",
|
||||
"to-register": "Register a new account"
|
||||
"to-register": "Register a new account",
|
||||
"valid_until": "Valid until"
|
||||
},
|
||||
"gdt": {
|
||||
"calculation": "Calculation of GradidoTransform",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user