mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-12 15:25:49 +00:00
Merge remote-tracking branch 'origin/master' into 2882-feature-distingue-communities-and-communities_federation-in-database
This commit is contained in:
commit
5739a77348
64
CHANGELOG.md
64
CHANGELOG.md
@ -4,8 +4,72 @@ All notable changes to this project will be documented in this file. Dates are d
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
#### [1.20.0](https://github.com/gradido/gradido/compare/1.19.1...1.20.0)
|
||||
|
||||
- fix(backend): no await for emails [`#2918`](https://github.com/gradido/gradido/pull/2918)
|
||||
- fix(frontend): no receiver on send by link [`#2933`](https://github.com/gradido/gradido/pull/2933)
|
||||
- fix(admin): pagination set currentPage by switch tabs [`#2902`](https://github.com/gradido/gradido/pull/2902)
|
||||
- fix(federation): correct export of the community url [`#2931`](https://github.com/gradido/gradido/pull/2931)
|
||||
- fix(frontend): displayed decay duration [`#2927`](https://github.com/gradido/gradido/pull/2927)
|
||||
- fix(frontend): community tab navigation [`#2928`](https://github.com/gradido/gradido/pull/2928)
|
||||
- fix(frontend): moderator id missing [`#2925`](https://github.com/gradido/gradido/pull/2925)
|
||||
- fix(frontend): reset button send coins [`#2924`](https://github.com/gradido/gradido/pull/2924)
|
||||
- refactor(backend): eslint plugin import export style [`#2908`](https://github.com/gradido/gradido/pull/2908)
|
||||
- fix(backend): vscode intellisense fixes [`#2919`](https://github.com/gradido/gradido/pull/2919)
|
||||
- refactor(backend): eslint import-no-cycle enabled [`#2905`](https://github.com/gradido/gradido/pull/2905)
|
||||
- docs(backend): alias rules and conventions [`#2881`](https://github.com/gradido/gradido/pull/2881)
|
||||
- refactor(backend): get transaction list [`#2923`](https://github.com/gradido/gradido/pull/2923)
|
||||
- feat(backend): previous balance in transaction [`#2914`](https://github.com/gradido/gradido/pull/2914)
|
||||
- refactor(backend): eslint update packages [`#2829`](https://github.com/gradido/gradido/pull/2829)
|
||||
- feat(frontend): send coins via gradido ID [`#2837`](https://github.com/gradido/gradido/pull/2837)
|
||||
- refactor(database): cleanup database [`#2808`](https://github.com/gradido/gradido/pull/2808)
|
||||
- refactor(backend): eslint plugin n + fixes [`#2828`](https://github.com/gradido/gradido/pull/2828)
|
||||
- feat(frontend): add link to download QR-Code [`#2889`](https://github.com/gradido/gradido/pull/2889)
|
||||
- fix(other): delete node_modules and /tmp/yarn--* on start.sh [`#2904`](https://github.com/gradido/gradido/pull/2904)
|
||||
- fix(admin): add confirmation modal for user role change and user (un)deletion [`#2880`](https://github.com/gradido/gradido/pull/2880)
|
||||
- fix(admin): admin open contribution edit button [`#2811`](https://github.com/gradido/gradido/pull/2811)
|
||||
- fix(backend): import order [`#2911`](https://github.com/gradido/gradido/pull/2911)
|
||||
- fix(other): use default values for undefined .env database values [`#2910`](https://github.com/gradido/gradido/pull/2910)
|
||||
- refactor(backend): eslint plugin import + fixes [`#2827`](https://github.com/gradido/gradido/pull/2827)
|
||||
- refactor(backend): missing event tests [`#2900`](https://github.com/gradido/gradido/pull/2900)
|
||||
- refactor(backend): unify event names [`#2799`](https://github.com/gradido/gradido/pull/2799)
|
||||
- feat(backend): events for users [`#2797`](https://github.com/gradido/gradido/pull/2797)
|
||||
- fix(backend): subscription get's email and languages from user [`#2885`](https://github.com/gradido/gradido/pull/2885)
|
||||
- refactor(backend): eslint-plugin-jest + fixes [`#2816`](https://github.com/gradido/gradido/pull/2816)
|
||||
- fix(frontend): fr change ` and ´ to ' [`#2888`](https://github.com/gradido/gradido/pull/2888)
|
||||
- feat(backend): events for transaction links [`#2792`](https://github.com/gradido/gradido/pull/2792)
|
||||
- feat(backend): events for contributions [`#2784`](https://github.com/gradido/gradido/pull/2784)
|
||||
- feat(backend): events for contribution messages [`#2783`](https://github.com/gradido/gradido/pull/2783)
|
||||
- refactor(backend): upgrade coverage to 85% [`#2884`](https://github.com/gradido/gradido/pull/2884)
|
||||
- refactor(backend): add klicktipp-api library [`#2883`](https://github.com/gradido/gradido/pull/2883)
|
||||
- feat(backend): events for contribution links [`#2780`](https://github.com/gradido/gradido/pull/2780)
|
||||
- refactor(backend): separate events in own files [`#2777`](https://github.com/gradido/gradido/pull/2777)
|
||||
- refactor(backend): rename `evenProtocolType` to `eventType` [`#2776`](https://github.com/gradido/gradido/pull/2776)
|
||||
- refactor(other): add yarn installAll on gradido folder [`#2703`](https://github.com/gradido/gradido/pull/2703)
|
||||
- docs(federation): describe the technical federation architecture [`#2716`](https://github.com/gradido/gradido/pull/2716)
|
||||
- refactor(admin): admin list contributions for creation transaction list query [`#2791`](https://github.com/gradido/gradido/pull/2791)
|
||||
- refactor(workflow): separate workflow with file filter for nginx testing [`#2871`](https://github.com/gradido/gradido/pull/2871)
|
||||
- feat(backend): read communities data from database [`#2807`](https://github.com/gradido/gradido/pull/2807)
|
||||
- feat(federation): implement a graphql endpoint to answer getpublickey-request [`#2651`](https://github.com/gradido/gradido/pull/2651)
|
||||
- refactor(workflow): add file filters to dht node and federation workflows [`#2838`](https://github.com/gradido/gradido/pull/2838)
|
||||
- refactor(workflow): separate test workflow for end-to-end tests [`#2836`](https://github.com/gradido/gradido/pull/2836)
|
||||
- refactor(workflow): separate test workflow for frontend [`#2835`](https://github.com/gradido/gradido/pull/2835)
|
||||
- feat(federation): add federation modul to deployment scripts [`#2733`](https://github.com/gradido/gradido/pull/2733)
|
||||
- refactor(database): event table [`#2720`](https://github.com/gradido/gradido/pull/2720)
|
||||
- refactor(workflow): separate test workflow with file change filters for admin interface [`#2734`](https://github.com/gradido/gradido/pull/2734)
|
||||
- fix(admin): fix translation in menu (english) [`#2814`](https://github.com/gradido/gradido/pull/2814)
|
||||
- refactor(workflow): configure jest to directly check coverage to schlanken the test workflows [`#2790`](https://github.com/gradido/gradido/pull/2790)
|
||||
- fix(database): removed commands from package.json not working [`#2805`](https://github.com/gradido/gradido/pull/2805)
|
||||
- fix(other): repair UserProfile.ChangePassword.feature scenario [`#2782`](https://github.com/gradido/gradido/pull/2782)
|
||||
- feat(backend): test double redeem transaction links [`#2788`](https://github.com/gradido/gradido/pull/2788)
|
||||
- feat(backend): admin open creations query [`#2813`](https://github.com/gradido/gradido/pull/2813)
|
||||
- refactor(backend): eslint-plugin-type-graphql + fixes [`#2745`](https://github.com/gradido/gradido/pull/2745)
|
||||
|
||||
#### [1.19.1](https://github.com/gradido/gradido/compare/1.19.0...1.19.1)
|
||||
|
||||
> 10 March 2023
|
||||
|
||||
- chore(other): upgrade version to 1.19.1 [`#2812`](https://github.com/gradido/gradido/pull/2812)
|
||||
- fix(frontend): admin question clickable [`#2810`](https://github.com/gradido/gradido/pull/2810)
|
||||
- refactor(frontend): change b-img to b-icon send [`#2809`](https://github.com/gradido/gradido/pull/2809)
|
||||
- fix(admin): update openCreation in case of tab open. [`#2806`](https://github.com/gradido/gradido/pull/2806)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"description": "Administraion Interface for Gradido",
|
||||
"main": "index.js",
|
||||
"author": "Moriz Wahl",
|
||||
"version": "1.19.1",
|
||||
"version": "1.20.0",
|
||||
"license": "Apache-2.0",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
@ -33,6 +33,7 @@
|
||||
"bootstrap": "4.3.1",
|
||||
"bootstrap-vue": "^2.21.2",
|
||||
"core-js": "^3.6.5",
|
||||
"date-fns": "^2.29.3",
|
||||
"dotenv-webpack": "^7.0.3",
|
||||
"express": "^4.17.1",
|
||||
"graphql": "^15.6.1",
|
||||
|
||||
@ -28,6 +28,7 @@ const mocks = {
|
||||
|
||||
let propsData
|
||||
let wrapper
|
||||
let spy
|
||||
|
||||
describe('ChangeUserRoleFormular', () => {
|
||||
const Wrapper = () => {
|
||||
@ -70,12 +71,16 @@ describe('ChangeUserRoleFormular', () => {
|
||||
expect(wrapper.text()).toContain('userRole.notChangeYourSelf')
|
||||
})
|
||||
|
||||
it('has role select disabled', () => {
|
||||
expect(wrapper.find('select[disabled="disabled"]').exists()).toBe(true)
|
||||
it('has no role select', () => {
|
||||
expect(wrapper.find('select.role-select').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('has no button', () => {
|
||||
expect(wrapper.find('button.btn.btn-dange').exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('change others role', () => {
|
||||
describe("change other user's role", () => {
|
||||
let rolesToSelect
|
||||
|
||||
describe('general', () => {
|
||||
@ -106,19 +111,12 @@ describe('ChangeUserRoleFormular', () => {
|
||||
expect(wrapper.find('select.role-select[disabled="disabled"]').exists()).toBe(false)
|
||||
})
|
||||
|
||||
describe('on API error', () => {
|
||||
beforeEach(() => {
|
||||
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
||||
rolesToSelect.at(1).setSelected()
|
||||
})
|
||||
|
||||
it('toasts an error message', () => {
|
||||
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
||||
})
|
||||
it('has "change_user_role" button', () => {
|
||||
expect(wrapper.find('button.btn.btn-danger').text()).toBe('change_user_role')
|
||||
})
|
||||
})
|
||||
|
||||
describe('user is usual user', () => {
|
||||
describe('user has role "usual user"', () => {
|
||||
beforeEach(() => {
|
||||
apolloMutateMock.mockResolvedValue({
|
||||
data: {
|
||||
@ -141,6 +139,10 @@ describe('ChangeUserRoleFormular', () => {
|
||||
|
||||
describe('change select to', () => {
|
||||
describe('same role', () => {
|
||||
it('has "change_user_role" button disabled', () => {
|
||||
expect(wrapper.find('button.btn.btn-danger[disabled="disabled"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('does not call the API', () => {
|
||||
rolesToSelect.at(0).setSelected()
|
||||
expect(apolloMutateMock).not.toHaveBeenCalled()
|
||||
@ -152,39 +154,75 @@ describe('ChangeUserRoleFormular', () => {
|
||||
rolesToSelect.at(1).setSelected()
|
||||
})
|
||||
|
||||
it('calls the API', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
mutation: setUserRole,
|
||||
variables: {
|
||||
userId: 1,
|
||||
isAdmin: true,
|
||||
},
|
||||
}),
|
||||
it('has "change_user_role" button enabled', () => {
|
||||
expect(wrapper.find('button.btn.btn-danger').exists()).toBe(true)
|
||||
expect(wrapper.find('button.btn.btn-danger[disabled="disabled"]').exists()).toBe(
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
it('emits "updateIsAdmin"', () => {
|
||||
expect(wrapper.emitted('updateIsAdmin')).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.arrayContaining([
|
||||
{
|
||||
userId: 1,
|
||||
isAdmin: expect.any(Date),
|
||||
},
|
||||
]),
|
||||
]),
|
||||
)
|
||||
})
|
||||
describe('clicking the "change_user_role" button', () => {
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
spy.mockImplementation(() => Promise.resolve(true))
|
||||
await wrapper.find('button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('toasts success message', () => {
|
||||
expect(toastSuccessSpy).toBeCalledWith('userRole.successfullyChangedTo')
|
||||
it('calls the modal', () => {
|
||||
expect(wrapper.emitted('showModal'))
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
describe('confirm role change with success', () => {
|
||||
it('calls the API', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
mutation: setUserRole,
|
||||
variables: {
|
||||
userId: 1,
|
||||
isAdmin: true,
|
||||
},
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('emits "updateIsAdmin"', () => {
|
||||
expect(wrapper.emitted('updateIsAdmin')).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.arrayContaining([
|
||||
{
|
||||
userId: 1,
|
||||
isAdmin: expect.any(Date),
|
||||
},
|
||||
]),
|
||||
]),
|
||||
)
|
||||
})
|
||||
|
||||
it('toasts success message', () => {
|
||||
expect(toastSuccessSpy).toBeCalledWith('userRole.successfullyChangedTo')
|
||||
})
|
||||
})
|
||||
|
||||
describe('confirm role change with error', () => {
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
||||
await wrapper.find('button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('toasts an error message', () => {
|
||||
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('user is admin', () => {
|
||||
describe('user has role "admin"', () => {
|
||||
beforeEach(() => {
|
||||
apolloMutateMock.mockResolvedValue({
|
||||
data: {
|
||||
@ -207,6 +245,10 @@ describe('ChangeUserRoleFormular', () => {
|
||||
|
||||
describe('change select to', () => {
|
||||
describe('same role', () => {
|
||||
it('has "change_user_role" button disabled', () => {
|
||||
expect(wrapper.find('button.btn.btn-danger[disabled="disabled"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('does not call the API', () => {
|
||||
rolesToSelect.at(1).setSelected()
|
||||
expect(apolloMutateMock).not.toHaveBeenCalled()
|
||||
@ -218,33 +260,69 @@ describe('ChangeUserRoleFormular', () => {
|
||||
rolesToSelect.at(0).setSelected()
|
||||
})
|
||||
|
||||
it('calls the API', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
mutation: setUserRole,
|
||||
variables: {
|
||||
userId: 1,
|
||||
isAdmin: false,
|
||||
},
|
||||
}),
|
||||
it('has "change_user_role" button enabled', () => {
|
||||
expect(wrapper.find('button.btn.btn-danger').exists()).toBe(true)
|
||||
expect(wrapper.find('button.btn.btn-danger[disabled="disabled"]').exists()).toBe(
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
it('emits "updateIsAdmin"', () => {
|
||||
expect(wrapper.emitted('updateIsAdmin')).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.arrayContaining([
|
||||
{
|
||||
userId: 1,
|
||||
isAdmin: null,
|
||||
},
|
||||
]),
|
||||
]),
|
||||
)
|
||||
})
|
||||
describe('clicking the "change_user_role" button', () => {
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
spy.mockImplementation(() => Promise.resolve(true))
|
||||
await wrapper.find('button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('toasts success message', () => {
|
||||
expect(toastSuccessSpy).toBeCalledWith('userRole.successfullyChangedTo')
|
||||
it('calls the modal', () => {
|
||||
expect(wrapper.emitted('showModal'))
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
describe('confirm role change with success', () => {
|
||||
it('calls the API', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
mutation: setUserRole,
|
||||
variables: {
|
||||
userId: 1,
|
||||
isAdmin: false,
|
||||
},
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('emits "updateIsAdmin"', () => {
|
||||
expect(wrapper.emitted('updateIsAdmin')).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.arrayContaining([
|
||||
{
|
||||
userId: 1,
|
||||
isAdmin: null,
|
||||
},
|
||||
]),
|
||||
]),
|
||||
)
|
||||
})
|
||||
|
||||
it('toasts success message', () => {
|
||||
expect(toastSuccessSpy).toBeCalledWith('userRole.successfullyChangedTo')
|
||||
})
|
||||
})
|
||||
|
||||
describe('confirm role change with error', () => {
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
||||
await wrapper.find('button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('toasts an error message', () => {
|
||||
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -4,19 +4,23 @@
|
||||
<div v-if="item.userId === $store.state.moderator.id" class="m-3 mb-4">
|
||||
{{ $t('userRole.notChangeYourSelf') }}
|
||||
</div>
|
||||
<div class="m-3">
|
||||
<div v-else class="m-3">
|
||||
<label for="role" class="mr-3">{{ $t('userRole.selectLabel') }}</label>
|
||||
<b-form-select
|
||||
class="role-select"
|
||||
v-model="roleSelected"
|
||||
:options="roles"
|
||||
:disabled="item.userId === $store.state.moderator.id"
|
||||
/>
|
||||
<b-form-select class="role-select" v-model="roleSelected" :options="roles" />
|
||||
<div class="mt-3 mb-5">
|
||||
<b-button
|
||||
variant="danger"
|
||||
v-b-modal.user-role-modal
|
||||
:disabled="currentRole === roleSelected"
|
||||
@click="showModal()"
|
||||
>
|
||||
{{ $t('change_user_role') }}
|
||||
</b-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { setUserRole } from '../graphql/setUserRole'
|
||||
|
||||
@ -35,6 +39,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentRole: this.item.isAdmin ? rolesValues.admin : rolesValues.user,
|
||||
roleSelected: this.item.isAdmin ? rolesValues.admin : rolesValues.user,
|
||||
roles: [
|
||||
{ value: rolesValues.user, text: this.$t('userRole.selectRoles.user') },
|
||||
@ -42,14 +47,35 @@ export default {
|
||||
],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
roleSelected(newRole, oldRole) {
|
||||
if (newRole !== oldRole) {
|
||||
this.setUserRole(newRole, oldRole)
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
showModal() {
|
||||
this.$bvModal
|
||||
.msgBoxConfirm(
|
||||
this.$t('overlay.changeUserRole.question', {
|
||||
username: `${this.item.firstName} ${this.item.lastName}`,
|
||||
newRole:
|
||||
this.roleSelected === 'admin'
|
||||
? this.$t('userRole.selectRoles.admin')
|
||||
: this.$t('userRole.selectRoles.user'),
|
||||
}),
|
||||
{
|
||||
cancelTitle: this.$t('overlay.cancel'),
|
||||
centered: true,
|
||||
hideHeaderClose: true,
|
||||
title: this.$t('overlay.changeUserRole.title'),
|
||||
okTitle: this.$t('overlay.changeUserRole.yes'),
|
||||
okVariant: 'danger',
|
||||
},
|
||||
)
|
||||
.then((okClicked) => {
|
||||
if (okClicked) {
|
||||
this.setUserRole(this.roleSelected, this.currentRole)
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
setUserRole(newRole, oldRole) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
|
||||
@ -2,14 +2,18 @@ import { mount } from '@vue/test-utils'
|
||||
import CreationFormular from './CreationFormular'
|
||||
import { adminCreateContribution } from '../graphql/adminCreateContribution'
|
||||
import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup'
|
||||
import VueApollo from 'vue-apollo'
|
||||
import { createMockClient } from 'mock-apollo-client'
|
||||
import { adminOpenCreations } from '../graphql/adminOpenCreations'
|
||||
|
||||
const mockClient = createMockClient()
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: mockClient,
|
||||
})
|
||||
|
||||
const localVue = global.localVue
|
||||
localVue.use(VueApollo)
|
||||
|
||||
const apolloMutateMock = jest.fn().mockResolvedValue({
|
||||
data: {
|
||||
adminCreateContribution: [0, 0, 0],
|
||||
},
|
||||
})
|
||||
const stateCommitMock = jest.fn()
|
||||
|
||||
const mocks = {
|
||||
@ -18,9 +22,6 @@ const mocks = {
|
||||
const date = new Date(d)
|
||||
return date.toISOString().split('T')[0]
|
||||
}),
|
||||
$apollo: {
|
||||
mutate: apolloMutateMock,
|
||||
},
|
||||
$store: {
|
||||
commit: stateCommitMock,
|
||||
},
|
||||
@ -31,7 +32,8 @@ const propsData = {
|
||||
creation: [],
|
||||
}
|
||||
|
||||
const now = new Date(Date.now())
|
||||
const now = new Date()
|
||||
|
||||
const getCreationDate = (sub) => {
|
||||
const date = sub === 0 ? now : new Date(now.getFullYear(), now.getMonth() - sub, 1, 0)
|
||||
return date.toISOString().split('T')[0]
|
||||
@ -40,8 +42,43 @@ const getCreationDate = (sub) => {
|
||||
describe('CreationFormular', () => {
|
||||
let wrapper
|
||||
|
||||
const adminOpenCreationsMock = jest.fn()
|
||||
const adminCreateContributionMock = jest.fn()
|
||||
mockClient.setRequestHandler(
|
||||
adminOpenCreations,
|
||||
adminOpenCreationsMock.mockResolvedValue({
|
||||
data: {
|
||||
adminOpenCreations: [
|
||||
{
|
||||
month: new Date(now.getFullYear(), now.getMonth() - 2).getMonth(),
|
||||
year: new Date(now.getFullYear(), now.getMonth() - 2).getFullYear(),
|
||||
amount: '200',
|
||||
},
|
||||
{
|
||||
month: new Date(now.getFullYear(), now.getMonth() - 1).getMonth(),
|
||||
year: new Date(now.getFullYear(), now.getMonth() - 1).getFullYear(),
|
||||
amount: '400',
|
||||
},
|
||||
{
|
||||
month: now.getMonth(),
|
||||
year: now.getFullYear(),
|
||||
amount: '600',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
mockClient.setRequestHandler(
|
||||
adminCreateContribution,
|
||||
adminCreateContributionMock.mockResolvedValue({
|
||||
data: {
|
||||
adminCreateContribution: [0, 0, 0],
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(CreationFormular, { localVue, mocks, propsData })
|
||||
return mount(CreationFormular, { localVue, mocks, propsData, apolloProvider })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
@ -107,17 +144,12 @@ describe('CreationFormular', () => {
|
||||
})
|
||||
|
||||
it('sends ... to apollo', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
mutation: adminCreateContribution,
|
||||
variables: {
|
||||
email: 'benjamin@bluemchen.de',
|
||||
creationDate: getCreationDate(2),
|
||||
amount: 90,
|
||||
memo: 'Test create coins',
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(adminCreateContributionMock).toBeCalledWith({
|
||||
email: 'benjamin@bluemchen.de',
|
||||
creationDate: getCreationDate(2),
|
||||
amount: 90,
|
||||
memo: 'Test create coins',
|
||||
})
|
||||
})
|
||||
|
||||
it('emits update-user-data', () => {
|
||||
@ -144,7 +176,7 @@ describe('CreationFormular', () => {
|
||||
|
||||
describe('sendForm with server error', () => {
|
||||
beforeEach(async () => {
|
||||
apolloMutateMock.mockRejectedValueOnce({ message: 'Ouch!' })
|
||||
adminCreateContributionMock.mockRejectedValueOnce({ message: 'Ouch!' })
|
||||
await wrapper.find('.test-submit').trigger('click')
|
||||
})
|
||||
|
||||
@ -212,7 +244,7 @@ describe('CreationFormular', () => {
|
||||
})
|
||||
|
||||
it('sends ... to apollo', () => {
|
||||
expect(apolloMutateMock).toBeCalled()
|
||||
expect(adminCreateContributionMock).toBeCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@ -275,7 +307,7 @@ describe('CreationFormular', () => {
|
||||
})
|
||||
|
||||
it('sends mutation to apollo', () => {
|
||||
expect(apolloMutateMock).toBeCalled()
|
||||
expect(adminCreateContributionMock).toBeCalled()
|
||||
})
|
||||
|
||||
it('toast success message', () => {
|
||||
|
||||
@ -117,10 +117,6 @@ export default {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
creation: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -129,6 +125,7 @@ export default {
|
||||
rangeMin: 0,
|
||||
rangeMax: 1000,
|
||||
selected: '',
|
||||
userId: this.item.userId,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -136,7 +133,7 @@ export default {
|
||||
// do we want to reset the memo everytime the month changes?
|
||||
this.text = this.$t('creation_form.creation_for') + ' ' + name.short + ' ' + name.year
|
||||
this.rangeMin = 0
|
||||
this.rangeMax = name.creation
|
||||
this.rangeMax = Number(name.creation)
|
||||
},
|
||||
submitCreation() {
|
||||
this.$apollo
|
||||
@ -167,6 +164,10 @@ export default {
|
||||
this.$refs.creationForm.reset()
|
||||
this.value = 0
|
||||
})
|
||||
.finally(() => {
|
||||
this.$apollo.queries.OpenCreations.refetch()
|
||||
this.selected = ''
|
||||
})
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
||||
@ -35,6 +35,7 @@ const propsData = {
|
||||
|
||||
describe('DeletedUserFormular', () => {
|
||||
let wrapper
|
||||
let spy
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(DeletedUserFormular, { localVue, mocks, propsData })
|
||||
@ -62,6 +63,10 @@ describe('DeletedUserFormular', () => {
|
||||
it('shows a text that you cannot delete yourself', () => {
|
||||
expect(wrapper.text()).toBe('removeNotSelf')
|
||||
})
|
||||
|
||||
it('has no "delete_user" button', () => {
|
||||
expect(wrapper.find('button').exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('delete other user', () => {
|
||||
@ -71,35 +76,32 @@ describe('DeletedUserFormular', () => {
|
||||
userId: 1,
|
||||
deletedAt: null,
|
||||
},
|
||||
static: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('has a checkbox', () => {
|
||||
expect(wrapper.find('input[type="checkbox"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('shows the text "delete_user"', () => {
|
||||
expect(wrapper.text()).toBe('delete_user')
|
||||
})
|
||||
|
||||
describe('click on checkbox', () => {
|
||||
it('has a "delete_user" button', () => {
|
||||
expect(wrapper.find('button').text()).toBe('delete_user')
|
||||
})
|
||||
|
||||
describe('click on "delete_user" button', () => {
|
||||
beforeEach(async () => {
|
||||
await wrapper.find('input[type="checkbox"]').setChecked()
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
spy.mockImplementation(() => Promise.resolve(true))
|
||||
await wrapper.find('button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('has a confirmation button', () => {
|
||||
expect(wrapper.find('button').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has the button text "delete_user"', () => {
|
||||
expect(wrapper.find('button').text()).toBe('delete_user')
|
||||
it('calls the modal', () => {
|
||||
expect(wrapper.emitted('showDeleteModal'))
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
describe('confirm delete with success', () => {
|
||||
beforeEach(async () => {
|
||||
await wrapper.find('button').trigger('click')
|
||||
})
|
||||
|
||||
it('calls the API', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
@ -123,32 +125,20 @@ describe('DeletedUserFormular', () => {
|
||||
]),
|
||||
)
|
||||
})
|
||||
|
||||
it('unchecks the checkbox', () => {
|
||||
expect(wrapper.find('input').attributes('checked')).toBe(undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe('confirm delete with error', () => {
|
||||
beforeEach(async () => {
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
||||
await wrapper.find('button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('toasts an error message', () => {
|
||||
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('click on checkbox again', () => {
|
||||
beforeEach(async () => {
|
||||
await wrapper.find('input[type="checkbox"]').setChecked(false)
|
||||
})
|
||||
|
||||
it('has no confirmation button anymore', () => {
|
||||
expect(wrapper.find('button').exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -162,37 +152,33 @@ describe('DeletedUserFormular', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('has a checkbox', () => {
|
||||
expect(wrapper.find('input[type="checkbox"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('shows the text "undelete_user"', () => {
|
||||
expect(wrapper.text()).toBe('undelete_user')
|
||||
})
|
||||
|
||||
describe('click on checkbox', () => {
|
||||
it('has a "undelete_user" button', () => {
|
||||
expect(wrapper.find('button').text()).toBe('undelete_user')
|
||||
})
|
||||
|
||||
describe('click on "undelete_user" button', () => {
|
||||
beforeEach(async () => {
|
||||
apolloMutateMock.mockResolvedValue({
|
||||
data: {
|
||||
unDeleteUser: null,
|
||||
},
|
||||
})
|
||||
await wrapper.find('input[type="checkbox"]').setChecked()
|
||||
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||
spy.mockImplementation(() => Promise.resolve(true))
|
||||
await wrapper.find('button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('has a confirmation button', () => {
|
||||
expect(wrapper.find('button').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has the button text "undelete_user"', () => {
|
||||
expect(wrapper.find('button').text()).toBe('undelete_user')
|
||||
it('calls the modal', () => {
|
||||
expect(wrapper.emitted('showUndeleteModal'))
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
describe('confirm recover with success', () => {
|
||||
beforeEach(async () => {
|
||||
await wrapper.find('button').trigger('click')
|
||||
})
|
||||
|
||||
it('calls the API', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
@ -205,7 +191,7 @@ describe('DeletedUserFormular', () => {
|
||||
})
|
||||
|
||||
it('emits update deleted At', () => {
|
||||
expect(wrapper.emitted('updateDeletedAt')).toEqual(
|
||||
expect(wrapper.emitted('updateDeletedAt')).toMatchObject(
|
||||
expect.arrayContaining([
|
||||
expect.arrayContaining([
|
||||
{
|
||||
@ -216,10 +202,6 @@ describe('DeletedUserFormular', () => {
|
||||
]),
|
||||
)
|
||||
})
|
||||
|
||||
it('unchecks the checkbox', () => {
|
||||
expect(wrapper.find('input').attributes('checked')).toBe(undefined)
|
||||
})
|
||||
})
|
||||
|
||||
describe('confirm recover with error', () => {
|
||||
@ -232,16 +214,6 @@ describe('DeletedUserFormular', () => {
|
||||
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('click on checkbox again', () => {
|
||||
beforeEach(async () => {
|
||||
await wrapper.find('input[type="checkbox"]').setChecked(false)
|
||||
})
|
||||
|
||||
it('has no confirmation button anymore', () => {
|
||||
expect(wrapper.find('button').exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -4,15 +4,16 @@
|
||||
{{ $t('removeNotSelf') }}
|
||||
</div>
|
||||
<div v-else class="mt-5">
|
||||
<b-form-checkbox switch size="lg" v-model="checked">
|
||||
<div>{{ item.deletedAt ? $t('undelete_user') : $t('delete_user') }}</div>
|
||||
</b-form-checkbox>
|
||||
|
||||
<div class="mt-3 mb-5">
|
||||
<b-button v-if="checked && item.deletedAt === null" variant="danger" @click="deleteUser">
|
||||
<b-button
|
||||
v-if="!item.deletedAt"
|
||||
variant="danger"
|
||||
v-b-modal.delete-user-modal
|
||||
@click="showDeleteModal()"
|
||||
>
|
||||
{{ $t('delete_user') }}
|
||||
</b-button>
|
||||
<b-button v-if="checked && item.deletedAt !== null" variant="success" @click="unDeleteUser">
|
||||
<b-button v-else variant="success" v-b-modal.delete-user-modal @click="showUndeleteModal()">
|
||||
{{ $t('undelete_user') }}
|
||||
</b-button>
|
||||
</div>
|
||||
@ -31,12 +32,56 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
checked: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showDeleteModal() {
|
||||
this.$bvModal
|
||||
.msgBoxConfirm(
|
||||
this.$t('overlay.deleteUser.question', {
|
||||
username: `${this.item.firstName} ${this.item.lastName}`,
|
||||
}),
|
||||
{
|
||||
cancelTitle: this.$t('overlay.cancel'),
|
||||
centered: true,
|
||||
hideHeaderClose: true,
|
||||
title: this.$t('overlay.deleteUser.title'),
|
||||
okTitle: this.$t('overlay.deleteUser.yes'),
|
||||
okVariant: 'danger',
|
||||
static: true,
|
||||
},
|
||||
)
|
||||
.then((okClicked) => {
|
||||
if (okClicked) {
|
||||
this.deleteUser()
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
showUndeleteModal() {
|
||||
this.$bvModal
|
||||
.msgBoxConfirm(
|
||||
this.$t('overlay.undeleteUser.question', {
|
||||
username: `${this.item.firstName} ${this.item.lastName}`,
|
||||
}),
|
||||
{
|
||||
cancelTitle: this.$t('overlay.cancel'),
|
||||
centered: true,
|
||||
hideHeaderClose: true,
|
||||
title: this.$t('overlay.undeleteUser.title'),
|
||||
okTitle: this.$t('overlay.undeleteUser.yes'),
|
||||
okVariant: 'success',
|
||||
},
|
||||
)
|
||||
.then((okClicked) => {
|
||||
if (okClicked) {
|
||||
this.unDeleteUser()
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
deleteUser() {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
@ -50,7 +95,6 @@ export default {
|
||||
userId: this.item.userId,
|
||||
deletedAt: result.data.deleteUser,
|
||||
})
|
||||
this.checked = false
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
@ -69,7 +113,6 @@ export default {
|
||||
userId: this.item.userId,
|
||||
deletedAt: result.data.unDeleteUser,
|
||||
})
|
||||
this.checked = false
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import EditCreationFormular from './EditCreationFormular'
|
||||
import { toastErrorSpy, toastSuccessSpy } from '../../test/testSetup'
|
||||
import VueApollo from 'vue-apollo'
|
||||
import { createMockClient } from 'mock-apollo-client'
|
||||
import { adminOpenCreations } from '../graphql/adminOpenCreations'
|
||||
import { adminUpdateContribution } from '../graphql/adminUpdateContribution'
|
||||
|
||||
const mockClient = createMockClient()
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: mockClient,
|
||||
})
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
const apolloMutateMock = jest.fn().mockResolvedValue({
|
||||
data: {
|
||||
adminUpdateContribution: {
|
||||
creation: [0, 0, 0],
|
||||
amount: 500,
|
||||
date: new Date(),
|
||||
memo: 'Test Schöpfung 2',
|
||||
},
|
||||
},
|
||||
})
|
||||
localVue.use(VueApollo)
|
||||
|
||||
const stateCommitMock = jest.fn()
|
||||
|
||||
@ -23,22 +22,18 @@ const mocks = {
|
||||
const date = new Date(d)
|
||||
return date.toISOString().split('T')[0]
|
||||
}),
|
||||
$apollo: {
|
||||
mutate: apolloMutateMock,
|
||||
},
|
||||
$store: {
|
||||
commit: stateCommitMock,
|
||||
},
|
||||
}
|
||||
|
||||
const now = new Date(Date.now())
|
||||
const now = new Date()
|
||||
const getCreationDate = (sub) => {
|
||||
const date = sub === 0 ? now : new Date(now.getFullYear(), now.getMonth() - sub, 1, 0)
|
||||
return date.toISOString().split('T')[0]
|
||||
}
|
||||
|
||||
const propsData = {
|
||||
creation: [200, 400, 600],
|
||||
creationUserData: {
|
||||
memo: 'Test schöpfung 1',
|
||||
amount: 100,
|
||||
@ -46,20 +41,65 @@ const propsData = {
|
||||
},
|
||||
item: {
|
||||
id: 0,
|
||||
email: 'bob@baumeister.de',
|
||||
amount: '300',
|
||||
contributionDate: `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`,
|
||||
},
|
||||
}
|
||||
|
||||
const data = () => {
|
||||
return { creation: ['1000', '1000', '400'] }
|
||||
}
|
||||
|
||||
describe('EditCreationFormular', () => {
|
||||
let wrapper
|
||||
|
||||
const adminUpdateContributionMock = jest.fn()
|
||||
const adminOpenCreationsMock = jest.fn()
|
||||
mockClient.setRequestHandler(
|
||||
adminOpenCreations,
|
||||
adminOpenCreationsMock.mockResolvedValue({
|
||||
data: {
|
||||
adminOpenCreations: [
|
||||
{
|
||||
month: new Date(now.getFullYear(), now.getMonth() - 2).getMonth(),
|
||||
year: new Date(now.getFullYear(), now.getMonth() - 2).getFullYear(),
|
||||
amount: '1000',
|
||||
},
|
||||
{
|
||||
month: new Date(now.getFullYear(), now.getMonth() - 1).getMonth(),
|
||||
year: new Date(now.getFullYear(), now.getMonth() - 1).getFullYear(),
|
||||
amount: '1000',
|
||||
},
|
||||
{
|
||||
month: now.getMonth(),
|
||||
year: now.getFullYear(),
|
||||
amount: '400',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
mockClient.setRequestHandler(
|
||||
adminUpdateContribution,
|
||||
adminUpdateContributionMock.mockResolvedValue({
|
||||
data: {
|
||||
adminUpdateContribution: {
|
||||
amount: '600',
|
||||
date: new Date(),
|
||||
memo: 'This is my memo',
|
||||
},
|
||||
},
|
||||
}),
|
||||
)
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(EditCreationFormular, { localVue, mocks, propsData })
|
||||
return mount(EditCreationFormular, { localVue, mocks, propsData, data, apolloProvider })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
wrapper = Wrapper()
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('has a DIV element with the class.component-edit-creation-formular', () => {
|
||||
@ -89,42 +129,16 @@ describe('EditCreationFormular', () => {
|
||||
})
|
||||
|
||||
it('calls the API', () => {
|
||||
expect(apolloMutateMock).toBeCalledWith(
|
||||
expect.objectContaining({
|
||||
variables: {
|
||||
id: 0,
|
||||
email: 'bob@baumeister.de',
|
||||
creationDate: getCreationDate(0),
|
||||
amount: 500,
|
||||
memo: 'Test Schöpfung 2',
|
||||
},
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it('emits update-user-data', () => {
|
||||
expect(wrapper.emitted('update-user-data')).toEqual([
|
||||
[
|
||||
{
|
||||
id: 0,
|
||||
email: 'bob@baumeister.de',
|
||||
},
|
||||
[0, 0, 0],
|
||||
],
|
||||
])
|
||||
expect(adminUpdateContributionMock).toBeCalledWith({
|
||||
id: 0,
|
||||
creationDate: getCreationDate(0),
|
||||
amount: 500,
|
||||
memo: 'Test Schöpfung 2',
|
||||
})
|
||||
})
|
||||
|
||||
it('emits update-creation-data', () => {
|
||||
expect(wrapper.emitted('update-creation-data')).toEqual([
|
||||
[
|
||||
{
|
||||
amount: 500,
|
||||
date: expect.any(Date),
|
||||
memo: 'Test Schöpfung 2',
|
||||
row: expect.any(Object),
|
||||
},
|
||||
],
|
||||
])
|
||||
expect(wrapper.emitted('update-creation-data')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('toasts a success message', () => {
|
||||
@ -134,7 +148,7 @@ describe('EditCreationFormular', () => {
|
||||
|
||||
describe('change and save memo and value with error', () => {
|
||||
beforeEach(async () => {
|
||||
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
||||
adminUpdateContributionMock.mockRejectedValue({ message: 'Oh no!' })
|
||||
await wrapper.find('input[type="number"]').setValue(500)
|
||||
await wrapper.find('textarea').setValue('Test Schöpfung 2')
|
||||
await wrapper.find('.test-submit').trigger('click')
|
||||
|
||||
@ -96,18 +96,14 @@ export default {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
creation: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
text: !this.creationUserData.memo ? '' : this.creationUserData.memo,
|
||||
value: !this.creationUserData.amount ? 0 : Number(this.creationUserData.amount),
|
||||
rangeMin: 0,
|
||||
rangeMax: 1000,
|
||||
selected: '',
|
||||
selected: this.selectedComputed,
|
||||
userId: this.item.userId,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -117,20 +113,13 @@ export default {
|
||||
mutation: adminUpdateContribution,
|
||||
variables: {
|
||||
id: this.item.id,
|
||||
email: this.item.email,
|
||||
creationDate: this.selected.date,
|
||||
amount: Number(this.value),
|
||||
memo: this.text,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
this.$emit('update-user-data', this.item, result.data.adminUpdateContribution.creation)
|
||||
this.$emit('update-creation-data', {
|
||||
amount: Number(result.data.adminUpdateContribution.amount),
|
||||
date: result.data.adminUpdateContribution.date,
|
||||
memo: result.data.adminUpdateContribution.memo,
|
||||
row: this.row,
|
||||
})
|
||||
this.$emit('update-creation-data')
|
||||
this.toastSuccess(
|
||||
this.$t('creation_form.toasted_update', {
|
||||
value: this.value,
|
||||
@ -149,15 +138,29 @@ export default {
|
||||
// Den geschöpften Wert auf o setzen
|
||||
this.value = 0
|
||||
})
|
||||
.finally(() => {
|
||||
this.$apollo.queries.OpenCreations.refetch()
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (this.creationUserData.date) {
|
||||
const month = this.$d(new Date(this.creationUserData.date), 'month')
|
||||
const index = this.radioOptions.findIndex((obj) => obj.item.short === month)
|
||||
this.selected = this.radioOptions[index].item
|
||||
this.rangeMax = Number(this.creation[index]) + Number(this.creationUserData.amount)
|
||||
}
|
||||
computed: {
|
||||
creationIndex() {
|
||||
const month = this.$d(new Date(this.item.contributionDate), 'month')
|
||||
return this.radioOptions.findIndex((obj) => {
|
||||
return obj.item.short === month
|
||||
})
|
||||
},
|
||||
selectedComputed() {
|
||||
return this.radioOptions[this.creationIndex].item
|
||||
},
|
||||
rangeMax() {
|
||||
return Number(this.creation[this.creationIndex]) + Number(this.item.amount)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedComputed() {
|
||||
this.selected = this.selectedComputed
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
183
admin/src/components/Fedaration/FederationVisualizeItem.spec.js
Normal file
183
admin/src/components/Fedaration/FederationVisualizeItem.spec.js
Normal file
@ -0,0 +1,183 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import FederationVisualizeItem from './FederationVisualizeItem.vue'
|
||||
|
||||
const localVue = global.localVue
|
||||
const today = new Date()
|
||||
const createdDate = new Date()
|
||||
createdDate.setDate(createdDate.getDate() - 3)
|
||||
|
||||
let propsData = {
|
||||
item: {
|
||||
id: 7590,
|
||||
foreign: false,
|
||||
publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7',
|
||||
url: 'http://localhost/api/2_0',
|
||||
lastAnnouncedAt: createdDate,
|
||||
verifiedAt: today,
|
||||
lastErrorAt: null,
|
||||
createdAt: createdDate,
|
||||
updatedAt: null,
|
||||
},
|
||||
}
|
||||
|
||||
const mocks = {
|
||||
$i18n: {
|
||||
locale: 'en',
|
||||
},
|
||||
}
|
||||
|
||||
describe('FederationVisualizeItem', () => {
|
||||
let wrapper
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(FederationVisualizeItem, { localVue, mocks, propsData })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders the component', () => {
|
||||
expect(wrapper.find('div.federation-visualize-item').exists()).toBe(true)
|
||||
})
|
||||
|
||||
describe('rendering item properties', () => {
|
||||
it('has the url', () => {
|
||||
expect(wrapper.find('.row > div:nth-child(2) > div').text()).toBe(
|
||||
'http://localhost/api/2_0',
|
||||
)
|
||||
})
|
||||
|
||||
it('has the public key', () => {
|
||||
expect(wrapper.find('.row > div:nth-child(2) > small').text()).toContain(
|
||||
'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7'.substring(0, 26),
|
||||
)
|
||||
})
|
||||
|
||||
describe('verified item', () => {
|
||||
it('has the check icon', () => {
|
||||
expect(wrapper.find('svg.bi-check').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has the text variant "success"', () => {
|
||||
expect(wrapper.find('.text-success').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('not verified item', () => {
|
||||
beforeEach(() => {
|
||||
propsData = {
|
||||
item: {
|
||||
id: 7590,
|
||||
foreign: false,
|
||||
publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7',
|
||||
url: 'http://localhost/api/2_0',
|
||||
lastAnnouncedAt: createdDate,
|
||||
verifiedAt: null,
|
||||
lastErrorAt: null,
|
||||
createdAt: createdDate,
|
||||
updatedAt: null,
|
||||
},
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('has the x-circle icon', () => {
|
||||
expect(wrapper.find('svg.bi-x-circle').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has the text variant "danger"', () => {
|
||||
expect(wrapper.find('.text-danger').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
// describe('with different locales (de, en, fr, es, nl)', () => {
|
||||
describe('lastAnnouncedAt', () => {
|
||||
it('computes the time string for different locales (de, en, fr, es, nl)', () => {
|
||||
wrapper.vm.$i18n.locale = 'de'
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.vm.lastAnnouncedAt).toBe('vor 3 Tagen')
|
||||
|
||||
wrapper.vm.$i18n.locale = 'fr'
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.vm.lastAnnouncedAt).toBe('il y a 3 jours')
|
||||
|
||||
wrapper.vm.$i18n.locale = 'es'
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.vm.lastAnnouncedAt).toBe('hace 3 días')
|
||||
|
||||
wrapper.vm.$i18n.locale = 'nl'
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.vm.lastAnnouncedAt).toBe('3 dagen geleden')
|
||||
})
|
||||
|
||||
describe('lastAnnouncedAt == null', () => {
|
||||
beforeEach(() => {
|
||||
propsData = {
|
||||
item: {
|
||||
id: 7590,
|
||||
foreign: false,
|
||||
publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7',
|
||||
url: 'http://localhost/api/2_0',
|
||||
lastAnnouncedAt: null,
|
||||
verifiedAt: null,
|
||||
lastErrorAt: null,
|
||||
createdAt: createdDate,
|
||||
updatedAt: null,
|
||||
},
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('computes empty string', async () => {
|
||||
expect(wrapper.vm.lastAnnouncedAt).toBe('')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('createdAt', () => {
|
||||
it('computes the time string for different locales (de, en, fr, es, nl)', () => {
|
||||
wrapper.vm.$i18n.locale = 'de'
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.vm.createdAt).toBe('vor 3 Tagen')
|
||||
|
||||
wrapper.vm.$i18n.locale = 'fr'
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.vm.createdAt).toBe('il y a 3 jours')
|
||||
|
||||
wrapper.vm.$i18n.locale = 'es'
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.vm.createdAt).toBe('hace 3 días')
|
||||
|
||||
wrapper.vm.$i18n.locale = 'nl'
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.vm.createdAt).toBe('3 dagen geleden')
|
||||
})
|
||||
|
||||
describe('createdAt == null', () => {
|
||||
beforeEach(() => {
|
||||
propsData = {
|
||||
item: {
|
||||
id: 7590,
|
||||
foreign: false,
|
||||
publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7',
|
||||
url: 'http://localhost/api/2_0',
|
||||
lastAnnouncedAt: createdDate,
|
||||
verifiedAt: null,
|
||||
lastErrorAt: null,
|
||||
createdAt: null,
|
||||
updatedAt: null,
|
||||
},
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('computes empty string', async () => {
|
||||
expect(wrapper.vm.createdAt).toBe('')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
63
admin/src/components/Fedaration/FederationVisualizeItem.vue
Normal file
63
admin/src/components/Fedaration/FederationVisualizeItem.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="federation-visualize-item">
|
||||
<b-row>
|
||||
<b-col cols="1"><b-icon :icon="icon" :variant="variant" class="mr-4"></b-icon></b-col>
|
||||
<b-col>
|
||||
<div>{{ item.url }}</div>
|
||||
<small>{{ `${item.publicKey.substring(0, 26)}…` }}</small>
|
||||
</b-col>
|
||||
<b-col cols="2">{{ lastAnnouncedAt }}</b-col>
|
||||
<b-col cols="2">{{ createdAt }}</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { formatDistanceToNow } from 'date-fns'
|
||||
import { de, en, fr, es, nl } from 'date-fns/locale'
|
||||
|
||||
const locales = { en, de, es, fr, nl }
|
||||
|
||||
export default {
|
||||
name: 'FederationVisualizeItem',
|
||||
props: {
|
||||
item: { type: Object },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formatDistanceToNow,
|
||||
locale: this.$i18n.locale,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
verified() {
|
||||
return new Date(this.item.verifiedAt) >= new Date(this.item.lastAnnouncedAt)
|
||||
},
|
||||
icon() {
|
||||
return this.verified ? 'check' : 'x-circle'
|
||||
},
|
||||
variant() {
|
||||
return this.verified ? 'success' : 'danger'
|
||||
},
|
||||
lastAnnouncedAt() {
|
||||
if (this.item.lastAnnouncedAt) {
|
||||
return formatDistanceToNow(new Date(this.item.lastAnnouncedAt), {
|
||||
includeSecond: true,
|
||||
addSuffix: true,
|
||||
locale: locales[this.locale],
|
||||
})
|
||||
}
|
||||
return ''
|
||||
},
|
||||
createdAt() {
|
||||
if (this.item.createdAt) {
|
||||
return formatDistanceToNow(new Date(this.item.createdAt), {
|
||||
includeSecond: true,
|
||||
addSuffix: true,
|
||||
locale: locales[this.locale],
|
||||
})
|
||||
}
|
||||
return ''
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -62,8 +62,12 @@ describe('NavBar', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('has a link to /federation', () => {
|
||||
expect(wrapper.findAll('.nav-item').at(3).find('a').attributes('href')).toBe('/federation')
|
||||
})
|
||||
|
||||
it('has a link to /statistic', () => {
|
||||
expect(wrapper.findAll('.nav-item').at(3).find('a').attributes('href')).toBe('/statistic')
|
||||
expect(wrapper.findAll('.nav-item').at(4).find('a').attributes('href')).toBe('/statistic')
|
||||
})
|
||||
})
|
||||
|
||||
@ -72,7 +76,7 @@ describe('NavBar', () => {
|
||||
beforeEach(async () => {
|
||||
delete window.location
|
||||
window.location = ''
|
||||
await wrapper.findAll('.nav-item').at(4).find('a').trigger('click')
|
||||
await wrapper.findAll('.nav-item').at(5).find('a').trigger('click')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
@ -97,7 +101,7 @@ describe('NavBar', () => {
|
||||
window.location = {
|
||||
assign: windowLocationMock,
|
||||
}
|
||||
await wrapper.findAll('.nav-item').at(5).find('a').trigger('click')
|
||||
await wrapper.findAll('.nav-item').at(6).find('a').trigger('click')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="component-nabvar">
|
||||
<b-navbar toggleable="md" type="dark" variant="success">
|
||||
<b-navbar toggleable="lg" type="dark" class="bg-dark">
|
||||
<b-navbar-brand class="mb-2" to="/">
|
||||
<img src="img/brand/gradido_logo_w.png" class="navbar-brand-img pl-2" alt="..." />
|
||||
</b-navbar-brand>
|
||||
@ -19,6 +19,9 @@
|
||||
<b-nav-item to="/contribution-links">
|
||||
{{ $t('navbar.automaticContributions') }}
|
||||
</b-nav-item>
|
||||
<b-nav-item to="/federation">
|
||||
{{ $t('navbar.instances') }}
|
||||
</b-nav-item>
|
||||
<b-nav-item to="/statistic">{{ $t('navbar.statistic') }}</b-nav-item>
|
||||
<b-nav-item @click="wallet">{{ $t('navbar.my-account') }}</b-nav-item>
|
||||
<b-nav-item @click="logout">{{ $t('navbar.logout') }}</b-nav-item>
|
||||
|
||||
@ -5,7 +5,6 @@ const localVue = global.localVue
|
||||
|
||||
const apolloMutateMock = jest.fn().mockResolvedValue({})
|
||||
const apolloQueryMock = jest.fn().mockResolvedValue({})
|
||||
const toggleDetailsMock = jest.fn()
|
||||
|
||||
const propsData = {
|
||||
items: [
|
||||
@ -17,7 +16,7 @@ const propsData = {
|
||||
amount: 300,
|
||||
memo: 'Aktives Grundeinkommen für Januar 2022',
|
||||
date: '2022-01-01T00:00:00.000Z',
|
||||
moderator: 1,
|
||||
moderatorId: 1,
|
||||
creation: [700, 1000, 1000],
|
||||
__typename: 'PendingCreation',
|
||||
},
|
||||
@ -29,7 +28,7 @@ const propsData = {
|
||||
amount: 210,
|
||||
memo: 'Aktives Grundeinkommen für Januar 2022',
|
||||
date: '2022-01-01T00:00:00.000Z',
|
||||
moderator: null,
|
||||
moderatorId: null,
|
||||
creation: [790, 1000, 1000],
|
||||
__typename: 'PendingCreation',
|
||||
},
|
||||
@ -41,7 +40,7 @@ const propsData = {
|
||||
amount: 330,
|
||||
memo: 'Aktives Grundeinkommen für Januar 2022',
|
||||
date: '2022-01-01T00:00:00.000Z',
|
||||
moderator: 1,
|
||||
moderatorId: 1,
|
||||
creation: [670, 1000, 1000],
|
||||
__typename: 'PendingCreation',
|
||||
},
|
||||
@ -83,7 +82,7 @@ const mocks = {
|
||||
$store: {
|
||||
state: {
|
||||
moderator: {
|
||||
id: 0,
|
||||
id: 1,
|
||||
name: 'test moderator',
|
||||
},
|
||||
},
|
||||
@ -132,14 +131,6 @@ describe('OpenCreationsTable', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('call updateUserData', () => {
|
||||
it('user creations has updated data', async () => {
|
||||
wrapper.vm.updateUserData(propsData.items[0], [444, 555, 666])
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(wrapper.vm.items[0].creation).toEqual([444, 555, 666])
|
||||
})
|
||||
})
|
||||
|
||||
describe('call updateState', () => {
|
||||
beforeEach(() => {
|
||||
wrapper.vm.updateState(4)
|
||||
@ -149,40 +140,5 @@ describe('OpenCreationsTable', () => {
|
||||
expect(wrapper.vm.$root.$emit('update-state', 4)).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
describe('call updateCreationData', () => {
|
||||
const date = new Date()
|
||||
beforeEach(() => {
|
||||
wrapper.vm.updateCreationData({
|
||||
amount: Number(80.0),
|
||||
date: date,
|
||||
memo: 'Test memo',
|
||||
row: {
|
||||
item: {},
|
||||
detailsShowing: false,
|
||||
toggleDetails: toggleDetailsMock,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('emits update-state', () => {
|
||||
expect(
|
||||
wrapper.vm.$emit('update-contributions', {
|
||||
amount: Number(80.0),
|
||||
date: date,
|
||||
memo: 'Test memo',
|
||||
row: {
|
||||
item: {},
|
||||
detailsShowing: false,
|
||||
toggleDetails: toggleDetailsMock,
|
||||
},
|
||||
}),
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
it('calls toggleDetails', () => {
|
||||
expect(toggleDetailsMock).toBeCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -27,9 +27,10 @@
|
||||
<template #cell(editCreation)="row">
|
||||
<div v-if="!myself(row.item)">
|
||||
<b-button
|
||||
v-if="row.item.moderator"
|
||||
v-if="row.item.moderatorId"
|
||||
variant="info"
|
||||
size="md"
|
||||
:index="0"
|
||||
@click="rowToggleDetails(row, 0)"
|
||||
class="mr-2"
|
||||
>
|
||||
@ -89,14 +90,13 @@
|
||||
@row-toggle-details="rowToggleDetails(row, 0)"
|
||||
>
|
||||
<template #show-creation>
|
||||
<div v-if="row.item.moderator">
|
||||
<div v-if="row.item.moderatorId">
|
||||
<edit-creation-formular
|
||||
type="singleCreation"
|
||||
:creation="row.item.creation"
|
||||
:item="row.item"
|
||||
:row="row"
|
||||
:creationUserData="creationUserData"
|
||||
@update-creation-data="updateCreationData"
|
||||
@update-creation-data="$emit('update-contributions')"
|
||||
/>
|
||||
</div>
|
||||
<div v-else>
|
||||
@ -104,7 +104,6 @@
|
||||
:contributionId="row.item.id"
|
||||
:contributionState="row.item.state"
|
||||
@update-state="updateState"
|
||||
@update-user-data="updateUserData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -146,22 +145,9 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
creationUserData: {
|
||||
amount: null,
|
||||
date: null,
|
||||
memo: null,
|
||||
moderator: null,
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
myself(item) {
|
||||
return (
|
||||
`${item.firstName} ${item.lastName}` ===
|
||||
`${this.$store.state.moderator.firstName} ${this.$store.state.moderator.lastName}`
|
||||
)
|
||||
return item.userId === this.$store.state.moderator.id
|
||||
},
|
||||
getStatusIcon(status) {
|
||||
return iconMap[status] ? iconMap[status] : 'default-icon'
|
||||
@ -174,16 +160,6 @@ export default {
|
||||
if (item.state === 'IN_PROGRESS') return 'table-primary'
|
||||
if (item.state === 'PENDING') return 'table-primary'
|
||||
},
|
||||
updateCreationData(data) {
|
||||
const row = data.row
|
||||
this.$emit('update-contributions', data)
|
||||
delete data.row
|
||||
this.creationUserData = { ...this.creationUserData, ...data }
|
||||
row.toggleDetails()
|
||||
},
|
||||
updateUserData(rowItem, newCreation) {
|
||||
rowItem.creation = newCreation
|
||||
},
|
||||
updateState(id) {
|
||||
this.$emit('update-state', id)
|
||||
},
|
||||
|
||||
@ -32,6 +32,8 @@ export const adminListContributions = gql`
|
||||
deniedBy
|
||||
deletedAt
|
||||
deletedBy
|
||||
moderatorId
|
||||
userId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
admin/src/graphql/adminOpenCreations.js
Normal file
11
admin/src/graphql/adminOpenCreations.js
Normal file
@ -0,0 +1,11 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const adminOpenCreations = gql`
|
||||
query ($userId: Int!) {
|
||||
adminOpenCreations(userId: $userId) {
|
||||
year
|
||||
month
|
||||
amount
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -1,18 +1,11 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const adminUpdateContribution = gql`
|
||||
mutation ($id: Int!, $email: String!, $amount: Decimal!, $memo: String!, $creationDate: String!) {
|
||||
adminUpdateContribution(
|
||||
id: $id
|
||||
email: $email
|
||||
amount: $amount
|
||||
memo: $memo
|
||||
creationDate: $creationDate
|
||||
) {
|
||||
mutation ($id: Int!, $amount: Decimal!, $memo: String!, $creationDate: String!) {
|
||||
adminUpdateContribution(id: $id, amount: $amount, memo: $memo, creationDate: $creationDate) {
|
||||
amount
|
||||
date
|
||||
memo
|
||||
creation
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
17
admin/src/graphql/getCommunities.js
Normal file
17
admin/src/graphql/getCommunities.js
Normal file
@ -0,0 +1,17 @@
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const getCommunities = gql`
|
||||
query {
|
||||
getCommunities {
|
||||
id
|
||||
foreign
|
||||
publicKey
|
||||
url
|
||||
lastAnnouncedAt
|
||||
verifiedAt
|
||||
lastErrorAt
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -1,6 +1,7 @@
|
||||
{
|
||||
"all_emails": "Alle Nutzer",
|
||||
"back": "zurück",
|
||||
"change_user_role": "Nutzerrolle ändern",
|
||||
"chat": "Chat",
|
||||
"contributionLink": {
|
||||
"amount": "Betrag",
|
||||
@ -67,6 +68,13 @@
|
||||
"error": "Fehler",
|
||||
"expired": "abgelaufen",
|
||||
"e_mail": "E-Mail",
|
||||
"federation": {
|
||||
"createdAt": "Erstellt am",
|
||||
"gradidoInstances": "Gradido Instanzen",
|
||||
"lastAnnouncedAt": "letzte Bekanntgabe",
|
||||
"url": "Url",
|
||||
"verified": "Verifiziert"
|
||||
},
|
||||
"firstname": "Vorname",
|
||||
"footer": {
|
||||
"app_version": "App version {version}",
|
||||
@ -104,6 +112,7 @@
|
||||
"name": "Name",
|
||||
"navbar": {
|
||||
"automaticContributions": "Automatische Beiträge",
|
||||
"instances": "Instanzen",
|
||||
"logout": "Abmelden",
|
||||
"my-account": "Mein Konto",
|
||||
"statistic": "Statistik",
|
||||
@ -114,6 +123,11 @@
|
||||
"open_creations": "Offene Schöpfungen",
|
||||
"overlay": {
|
||||
"cancel": "Abbrechen",
|
||||
"changeUserRole": {
|
||||
"question": "Willst du die Rolle von {username} wirklich zu {newRole} ändern?",
|
||||
"title": "Nutzerrolle ändern",
|
||||
"yes": "Ja, Nutzerrolle ändern"
|
||||
},
|
||||
"confirm": {
|
||||
"question": "Willst du diesen Gemeinwohl-Beitrag wirklich bestätigen und gutschreiben?",
|
||||
"text": "Nach dem Speichern ist der Datensatz nicht mehr änderbar. Bitte überprüfe genau, dass alles stimmt.",
|
||||
@ -126,11 +140,21 @@
|
||||
"title": "Gemeinwohl-Beitrag löschen!",
|
||||
"yes": "Ja, Beitrag löschen!"
|
||||
},
|
||||
"deleteUser": {
|
||||
"question": "Willst du {username} wirklich löschen?",
|
||||
"title": "Nutzer löschen",
|
||||
"yes": "Ja, Nutzer löschen"
|
||||
},
|
||||
"deny": {
|
||||
"question": "Willst du diesen Gemeinwohl-Beitrag wirklich ablehnen?",
|
||||
"text": "Nach dem Speichern ist der Datensatz nicht mehr änderbar und kann auch nicht mehr gelöscht werden. Bitte überprüfe genau, dass alles stimmt.",
|
||||
"title": "Gemeinwohl-Beitrag ablehnen!",
|
||||
"yes": "Ja, Beitrag ablehnen und speichern!"
|
||||
},
|
||||
"undeleteUser": {
|
||||
"question": "Willst du wirklich {username} wiederherstellen?",
|
||||
"title": "Nutzer wiederherstellen",
|
||||
"yes": "Ja, Nutzer wiederherstellen"
|
||||
}
|
||||
},
|
||||
"redeemed": "eingelöst",
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
{
|
||||
"all_emails": "All users",
|
||||
"back": "back",
|
||||
"change_user_role": "Change user role",
|
||||
"chat": "Chat",
|
||||
"contributionLink": {
|
||||
"amount": "Amount",
|
||||
@ -67,6 +68,13 @@
|
||||
"error": "Error",
|
||||
"expired": "expired",
|
||||
"e_mail": "E-mail",
|
||||
"federation": {
|
||||
"createdAt": "Created At ",
|
||||
"gradidoInstances": "Gradido Instances",
|
||||
"lastAnnouncedAt": "Last Announced",
|
||||
"url": "Url",
|
||||
"verified": "Verified"
|
||||
},
|
||||
"firstname": "Firstname",
|
||||
"footer": {
|
||||
"app_version": "App version {version}",
|
||||
@ -104,6 +112,7 @@
|
||||
"name": "Name",
|
||||
"navbar": {
|
||||
"automaticContributions": "Automatic Contributions",
|
||||
"instances": "Instances",
|
||||
"logout": "Logout",
|
||||
"my-account": "My Account",
|
||||
"statistic": "Statistic",
|
||||
@ -114,6 +123,11 @@
|
||||
"open_creations": "Open creations",
|
||||
"overlay": {
|
||||
"cancel": "Cancel",
|
||||
"changeUserRole": {
|
||||
"question": "Do you really want to change {username}'s role to {newRole}?",
|
||||
"title": "Change user role",
|
||||
"yes": "Yes, change user role"
|
||||
},
|
||||
"confirm": {
|
||||
"question": "Do you really want to carry out and finally save this pre-stored creation?",
|
||||
"text": "After saving, the record can no longer be changed. Please check carefully that everything is correct.",
|
||||
@ -126,11 +140,21 @@
|
||||
"title": "Delete creation!",
|
||||
"yes": "Yes, delete and save creation!"
|
||||
},
|
||||
"deleteUser": {
|
||||
"question": "Do you really want to delete {username}?",
|
||||
"title": "Delete user",
|
||||
"yes": "Yes, delete user"
|
||||
},
|
||||
"deny": {
|
||||
"question": "Do you really want to carry out and finally save this pre-stored creation?",
|
||||
"text": "After saving, the record can no longer be changed or deleted. Please check carefully that everything is correct.",
|
||||
"title": "Reject creation!",
|
||||
"yes": "Yes, reject and save creation!"
|
||||
},
|
||||
"undeleteUser": {
|
||||
"question": "Do you really want to undelete {username}",
|
||||
"title": "Undelete user",
|
||||
"yes": "Yes,undelete user"
|
||||
}
|
||||
},
|
||||
"redeemed": "redeemed",
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { adminOpenCreations } from '../graphql/adminOpenCreations'
|
||||
|
||||
export const creationMonths = {
|
||||
props: {
|
||||
creation: {
|
||||
type: Array,
|
||||
default: () => [1000, 1000, 1000],
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
creation: [1000, 1000, 1000],
|
||||
userId: 0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
creationDates() {
|
||||
@ -38,4 +40,23 @@ export const creationMonths = {
|
||||
return this.creationDates.map((date) => this.$d(date, 'monthShort')).join(' | ')
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
OpenCreations: {
|
||||
query() {
|
||||
return adminOpenCreations
|
||||
},
|
||||
variables() {
|
||||
return {
|
||||
userId: this.userId,
|
||||
}
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
update({ adminOpenCreations }) {
|
||||
this.creation = adminOpenCreations.map((obj) => obj.amount)
|
||||
},
|
||||
error({ message }) {
|
||||
this.toastError(message)
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ const mocks = {
|
||||
const defaultData = () => {
|
||||
return {
|
||||
adminListContributions: {
|
||||
contributionCount: 2,
|
||||
contributionCount: 30,
|
||||
contributionList: [
|
||||
{
|
||||
id: 1,
|
||||
@ -407,6 +407,44 @@ describe('CreationConfirm', () => {
|
||||
statusFilter: ['IN_PROGRESS', 'PENDING', 'CONFIRMED', 'DENIED', 'DELETED'],
|
||||
})
|
||||
})
|
||||
|
||||
describe('change pagination', () => {
|
||||
it('has pagination buttons', () => {
|
||||
expect(wrapper.findComponent({ name: 'BPagination' }).exists()).toBe(true)
|
||||
})
|
||||
|
||||
describe('next page', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
wrapper.findComponent({ name: 'BPagination' }).vm.$emit('input', 2)
|
||||
})
|
||||
|
||||
it('calls the API again', () => {
|
||||
expect(adminListContributionsMock).toBeCalledWith({
|
||||
currentPage: 2,
|
||||
order: 'DESC',
|
||||
pageSize: 25,
|
||||
statusFilter: ['IN_PROGRESS', 'PENDING', 'CONFIRMED', 'DENIED', 'DELETED'],
|
||||
})
|
||||
})
|
||||
|
||||
describe('click tab "open" again', () => {
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks()
|
||||
await wrapper.find('a[data-test="open"]').trigger('click')
|
||||
})
|
||||
|
||||
it('refetches contributions with proper filter and current page = 1', () => {
|
||||
expect(adminListContributionsMock).toBeCalledWith({
|
||||
currentPage: 1,
|
||||
order: 'DESC',
|
||||
pageSize: 25,
|
||||
statusFilter: ['IN_PROGRESS', 'PENDING'],
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
:fields="fields"
|
||||
@show-overlay="showOverlay"
|
||||
@update-state="updateStatus"
|
||||
@update-contributions="$apollo.queries.AllContributions.refetch()"
|
||||
@update-contributions="$apollo.queries.ListAllContributions.refetch()"
|
||||
/>
|
||||
|
||||
<b-pagination
|
||||
@ -116,6 +116,11 @@ export default {
|
||||
pageSize: 25,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
tabIndex() {
|
||||
this.currentPage = 1
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
deleteCreation() {
|
||||
this.$apollo
|
||||
@ -212,7 +217,7 @@ export default {
|
||||
return this.formatDateOrDash(value)
|
||||
},
|
||||
},
|
||||
{ key: 'moderator', label: this.$t('moderator') },
|
||||
{ key: 'moderatorId', label: this.$t('moderator') },
|
||||
{ key: 'editCreation', label: this.$t('chat') },
|
||||
{ key: 'confirm', label: this.$t('save') },
|
||||
],
|
||||
|
||||
125
admin/src/pages/FederationVisualize.spec.js
Normal file
125
admin/src/pages/FederationVisualize.spec.js
Normal file
@ -0,0 +1,125 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import FederationVisualize from './FederationVisualize'
|
||||
import VueApollo from 'vue-apollo'
|
||||
import { createMockClient } from 'mock-apollo-client'
|
||||
import { getCommunities } from '@/graphql/getCommunities'
|
||||
import { toastErrorSpy } from '../../test/testSetup'
|
||||
|
||||
const mockClient = createMockClient()
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: mockClient,
|
||||
})
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
localVue.use(VueApollo)
|
||||
|
||||
const mocks = {
|
||||
$t: (key) => key,
|
||||
$d: jest.fn((d) => d),
|
||||
$i18n: {
|
||||
locale: 'en',
|
||||
t: (key) => key,
|
||||
},
|
||||
}
|
||||
|
||||
const defaultData = () => {
|
||||
return {
|
||||
getCommunities: [
|
||||
{
|
||||
id: 1776,
|
||||
foreign: true,
|
||||
publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527',
|
||||
url: 'http://localhost/api/2_0',
|
||||
lastAnnouncedAt: '2023-04-07T12:27:24.037Z',
|
||||
verifiedAt: null,
|
||||
lastErrorAt: null,
|
||||
createdAt: '2023-04-07T11:45:06.254Z',
|
||||
updatedAt: null,
|
||||
__typename: 'Community',
|
||||
},
|
||||
{
|
||||
id: 1775,
|
||||
foreign: true,
|
||||
publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527',
|
||||
url: 'http://localhost/api/1_1',
|
||||
lastAnnouncedAt: '2023-04-07T12:27:24.023Z',
|
||||
verifiedAt: null,
|
||||
lastErrorAt: null,
|
||||
createdAt: '2023-04-07T11:45:06.234Z',
|
||||
updatedAt: null,
|
||||
__typename: 'Community',
|
||||
},
|
||||
{
|
||||
id: 1774,
|
||||
foreign: true,
|
||||
publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527',
|
||||
url: 'http://localhost/api/1_0',
|
||||
lastAnnouncedAt: '2023-04-07T12:27:24.009Z',
|
||||
verifiedAt: null,
|
||||
lastErrorAt: null,
|
||||
createdAt: '2023-04-07T11:45:06.218Z',
|
||||
updatedAt: null,
|
||||
__typename: 'Community',
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
describe('FederationVisualize', () => {
|
||||
let wrapper
|
||||
const getCommunitiesMock = jest.fn()
|
||||
|
||||
mockClient.setRequestHandler(
|
||||
getCommunities,
|
||||
getCommunitiesMock
|
||||
.mockRejectedValueOnce({ message: 'Ouch!' })
|
||||
.mockResolvedValue({ data: defaultData() }),
|
||||
)
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(FederationVisualize, { localVue, mocks, apolloProvider })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
describe('server error', () => {
|
||||
it('toast error', () => {
|
||||
expect(toastErrorSpy).toBeCalledWith('Ouch!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('sever success', () => {
|
||||
it('sends query to Apollo when created', () => {
|
||||
expect(getCommunitiesMock).toBeCalled()
|
||||
})
|
||||
|
||||
it('has a DIV element with the class "federation-visualize"', () => {
|
||||
expect(wrapper.find('div.federation-visualize').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has a refresh button', () => {
|
||||
expect(wrapper.find('[data-test="federation-communities-refresh-btn"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders 3 community list items', () => {
|
||||
expect(wrapper.findAll('.list-group-item').length).toBe(3)
|
||||
})
|
||||
|
||||
describe('cklicking the refresh button', () => {
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks()
|
||||
await wrapper.find('[data-test="federation-communities-refresh-btn"]').trigger('click')
|
||||
})
|
||||
|
||||
it('calls the API', async () => {
|
||||
expect(getCommunitiesMock).toBeCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
69
admin/src/pages/FederationVisualize.vue
Normal file
69
admin/src/pages/FederationVisualize.vue
Normal file
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="federation-visualize">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<span class="h2">{{ $t('federation.gradidoInstances') }}</span>
|
||||
<b-button>
|
||||
<b-icon
|
||||
icon="arrow-clockwise"
|
||||
font-scale="2"
|
||||
:animation="animation"
|
||||
@click="$apollo.queries.GetCommunities.refresh()"
|
||||
data-test="federation-communities-refresh-btn"
|
||||
></b-icon>
|
||||
</b-button>
|
||||
</div>
|
||||
<b-list-group>
|
||||
<b-row>
|
||||
<b-col cols="1" class="ml-1">{{ $t('federation.verified') }}</b-col>
|
||||
<b-col class="ml-3">{{ $t('federation.url') }}</b-col>
|
||||
<b-col cols="2">{{ $t('federation.lastAnnouncedAt') }}</b-col>
|
||||
<b-col cols="2">{{ $t('federation.createdAt') }}</b-col>
|
||||
</b-row>
|
||||
<b-list-group-item
|
||||
v-for="item in communities"
|
||||
:key="item.id"
|
||||
:variant="!item.foreign ? 'primary' : 'warning'"
|
||||
>
|
||||
<federation-visualize-item :item="item" />
|
||||
</b-list-group-item>
|
||||
</b-list-group>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getCommunities } from '@/graphql/getCommunities'
|
||||
|
||||
import FederationVisualizeItem from '../components/Fedaration/FederationVisualizeItem.vue'
|
||||
|
||||
export default {
|
||||
name: 'FederationVisualize',
|
||||
components: {
|
||||
FederationVisualizeItem,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
oldPublicKey: '',
|
||||
communities: [],
|
||||
icon: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
animation() {
|
||||
return this.$apollo.queries.GetCommunities.loading ? 'spin' : ''
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
GetCommunities: {
|
||||
fetchPolicy: 'network-only',
|
||||
query() {
|
||||
return getCommunities
|
||||
},
|
||||
update({ getCommunities }) {
|
||||
this.communities = getCommunities
|
||||
},
|
||||
error({ message }) {
|
||||
this.toastError(message)
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -42,7 +42,7 @@ const defaultData = () => {
|
||||
amount: 500,
|
||||
memo: 'Danke für alles',
|
||||
date: new Date(),
|
||||
moderator: 1,
|
||||
moderatorId: 1,
|
||||
state: 'PENDING',
|
||||
creation: [500, 500, 500],
|
||||
messagesCount: 0,
|
||||
@ -64,7 +64,7 @@ const defaultData = () => {
|
||||
amount: 1000000,
|
||||
memo: 'Gut Ergattert',
|
||||
date: new Date(),
|
||||
moderator: 1,
|
||||
moderatorId: 1,
|
||||
state: 'PENDING',
|
||||
creation: [500, 500, 500],
|
||||
messagesCount: 0,
|
||||
|
||||
@ -25,7 +25,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
|
||||
email: 'benjamin@bluemchen.de',
|
||||
creation: [1000, 1000, 1000],
|
||||
emailChecked: true,
|
||||
deletedAt: null,
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
{
|
||||
userId: 3,
|
||||
@ -243,6 +243,17 @@ describe('UserSearch', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('recover user', () => {
|
||||
const userId = 2
|
||||
beforeEach(() => {
|
||||
wrapper.findComponent({ name: 'SearchUserTable' }).vm.$emit('updateDeletedAt', userId, null)
|
||||
})
|
||||
|
||||
it('toasts a success message', () => {
|
||||
expect(toastSuccessSpy).toBeCalledWith('user_recovered')
|
||||
})
|
||||
})
|
||||
|
||||
describe('apollo returns error', () => {
|
||||
beforeEach(() => {
|
||||
apolloQueryMock.mockRejectedValue({
|
||||
|
||||
@ -45,7 +45,7 @@ describe('router', () => {
|
||||
|
||||
describe('routes', () => {
|
||||
it('has nine routes defined', () => {
|
||||
expect(routes).toHaveLength(8)
|
||||
expect(routes).toHaveLength(9)
|
||||
})
|
||||
|
||||
it('has "/overview" as default', async () => {
|
||||
@ -88,6 +88,13 @@ describe('router', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('federation', () => {
|
||||
it('loads the "FederationVisualize" page', async () => {
|
||||
const component = await routes.find((r) => r.path === '/federation').component()
|
||||
expect(component.default.name).toBe('FederationVisualize')
|
||||
})
|
||||
})
|
||||
|
||||
describe('not found page', () => {
|
||||
it('renders the "NotFound" component', async () => {
|
||||
const component = await routes.find((r) => r.path === '*').component()
|
||||
|
||||
@ -31,6 +31,10 @@ const routes = [
|
||||
path: '*',
|
||||
component: () => import('@/components/NotFoundPage.vue'),
|
||||
},
|
||||
{
|
||||
path: '/federation',
|
||||
component: () => import('@/pages/FederationVisualize.vue'),
|
||||
},
|
||||
]
|
||||
|
||||
export default routes
|
||||
|
||||
@ -5038,6 +5038,11 @@ data-urls@^2.0.0:
|
||||
whatwg-mimetype "^2.3.0"
|
||||
whatwg-url "^8.0.0"
|
||||
|
||||
date-fns@^2.29.3:
|
||||
version "2.29.3"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
|
||||
integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
|
||||
|
||||
de-indent@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
|
||||
|
||||
@ -1,12 +1,29 @@
|
||||
// eslint-disable-next-line import/no-commonjs, import/unambiguous
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['prettier', '@typescript-eslint', 'type-graphql'],
|
||||
extends: ['standard', 'eslint:recommended', 'plugin:prettier/recommended'],
|
||||
// add your custom rules here
|
||||
plugins: ['prettier', '@typescript-eslint', 'type-graphql', 'jest', 'import', 'n'],
|
||||
extends: [
|
||||
'standard',
|
||||
'eslint:recommended',
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:import/recommended',
|
||||
'plugin:import/typescript',
|
||||
],
|
||||
settings: {
|
||||
'import/parsers': {
|
||||
'@typescript-eslint/parser': ['.ts', '.tsx'],
|
||||
},
|
||||
'import/resolver': {
|
||||
typescript: {
|
||||
project: ['./tsconfig.json', '**/tsconfig.json'],
|
||||
},
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'no-console': ['error'],
|
||||
'no-debugger': 'error',
|
||||
@ -16,11 +33,120 @@ module.exports = {
|
||||
htmlWhitespaceSensitivity: 'ignore',
|
||||
},
|
||||
],
|
||||
// jest
|
||||
'jest/no-disabled-tests': 'error',
|
||||
'jest/no-focused-tests': 'error',
|
||||
'jest/no-identical-title': 'error',
|
||||
'jest/prefer-to-have-length': 'error',
|
||||
'jest/valid-expect': 'error',
|
||||
// import
|
||||
'import/export': 'error',
|
||||
'import/no-deprecated': 'error',
|
||||
'import/no-empty-named-blocks': 'error',
|
||||
'import/no-extraneous-dependencies': 'error',
|
||||
'import/no-mutable-exports': 'error',
|
||||
'import/no-unused-modules': 'error',
|
||||
'import/no-named-as-default': 'error',
|
||||
'import/no-named-as-default-member': 'error',
|
||||
'import/no-amd': 'error',
|
||||
'import/no-commonjs': 'error',
|
||||
'import/no-import-module-exports': 'error',
|
||||
'import/no-nodejs-modules': 'off',
|
||||
'import/unambiguous': 'error',
|
||||
'import/default': 'error',
|
||||
'import/named': 'error',
|
||||
'import/namespace': 'error',
|
||||
'import/no-absolute-path': 'error',
|
||||
'import/no-cycle': 'error',
|
||||
'import/no-dynamic-require': 'error',
|
||||
'import/no-internal-modules': 'off',
|
||||
'import/no-relative-packages': 'error',
|
||||
'import/no-relative-parent-imports': ['error', { ignore: ['@/*'] }],
|
||||
'import/no-self-import': 'error',
|
||||
'import/no-unresolved': 'error',
|
||||
'import/no-useless-path-segments': 'error',
|
||||
'import/no-webpack-loader-syntax': 'error',
|
||||
'import/consistent-type-specifier-style': 'error',
|
||||
'import/exports-last': 'off',
|
||||
'import/extensions': 'error',
|
||||
'import/first': 'error',
|
||||
'import/group-exports': 'off',
|
||||
'import/newline-after-import': 'error',
|
||||
'import/no-anonymous-default-export': 'error',
|
||||
'import/no-default-export': 'error',
|
||||
'import/no-duplicates': 'error',
|
||||
'import/no-named-default': 'error',
|
||||
'import/no-namespace': 'error',
|
||||
'import/no-unassigned-import': 'error',
|
||||
'import/order': [
|
||||
'error',
|
||||
{
|
||||
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
|
||||
'newlines-between': 'always',
|
||||
pathGroups: [
|
||||
{
|
||||
pattern: '@?*/**',
|
||||
group: 'external',
|
||||
position: 'after',
|
||||
},
|
||||
{
|
||||
pattern: '@/**',
|
||||
group: 'external',
|
||||
position: 'after',
|
||||
},
|
||||
],
|
||||
alphabetize: {
|
||||
order: 'asc' /* sort in ascending order. Options: ['ignore', 'asc', 'desc'] */,
|
||||
caseInsensitive: true /* ignore case. Options: [true, false] */,
|
||||
},
|
||||
distinctGroup: true,
|
||||
},
|
||||
],
|
||||
'import/prefer-default-export': 'off',
|
||||
// n
|
||||
'n/handle-callback-err': 'error',
|
||||
'n/no-callback-literal': 'error',
|
||||
'n/no-exports-assign': 'error',
|
||||
'n/no-extraneous-import': 'error',
|
||||
'n/no-extraneous-require': 'error',
|
||||
'n/no-hide-core-modules': 'error',
|
||||
'n/no-missing-import': 'off', // not compatible with typescript
|
||||
'n/no-missing-require': 'error',
|
||||
'n/no-new-require': 'error',
|
||||
'n/no-path-concat': 'error',
|
||||
'n/no-process-exit': 'error',
|
||||
'n/no-unpublished-bin': 'error',
|
||||
'n/no-unpublished-import': 'off', // TODO need to exclude seeds
|
||||
'n/no-unpublished-require': 'error',
|
||||
'n/no-unsupported-features': ['error', { ignores: ['modules'] }],
|
||||
'n/no-unsupported-features/es-builtins': 'error',
|
||||
'n/no-unsupported-features/es-syntax': 'error',
|
||||
'n/no-unsupported-features/node-builtins': 'error',
|
||||
'n/process-exit-as-throw': 'error',
|
||||
'n/shebang': 'error',
|
||||
'n/callback-return': 'error',
|
||||
'n/exports-style': 'error',
|
||||
'n/file-extension-in-import': 'off',
|
||||
'n/global-require': 'error',
|
||||
'n/no-mixed-requires': 'error',
|
||||
'n/no-process-env': 'error',
|
||||
'n/no-restricted-import': 'error',
|
||||
'n/no-restricted-require': 'error',
|
||||
'n/no-sync': 'error',
|
||||
'n/prefer-global/buffer': 'error',
|
||||
'n/prefer-global/console': 'error',
|
||||
'n/prefer-global/process': 'error',
|
||||
'n/prefer-global/text-decoder': 'error',
|
||||
'n/prefer-global/text-encoder': 'error',
|
||||
'n/prefer-global/url': 'error',
|
||||
'n/prefer-global/url-search-params': 'error',
|
||||
'n/prefer-promises/dns': 'error',
|
||||
'n/prefer-promises/fs': 'error',
|
||||
},
|
||||
overrides: [
|
||||
// only for ts files
|
||||
{
|
||||
files: ['*.ts'],
|
||||
files: ['*.ts', '*.tsx'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
@ -32,10 +158,12 @@ module.exports = {
|
||||
'no-void': ['error', { allowAsStatement: true }],
|
||||
// ignore prefer-regexp-exec rule to allow string.match(regex)
|
||||
'@typescript-eslint/prefer-regexp-exec': 'off',
|
||||
// this should not run on ts files: https://github.com/import-js/eslint-plugin-import/issues/2215#issuecomment-911245486
|
||||
'import/unambiguous': 'off',
|
||||
},
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./tsconfig.json'],
|
||||
project: ['./tsconfig.json', '**/tsconfig.json'],
|
||||
// this is to properly reference the referenced project database without requirement of compiling it
|
||||
EXPERIMENTAL_useSourceOfProjectReferenceRedirect: true,
|
||||
},
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
|
||||
// eslint-disable-next-line import/no-commonjs, import/unambiguous
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
preset: 'ts-jest',
|
||||
@ -21,10 +22,12 @@ module.exports = {
|
||||
'@repository/(.*)': '<rootDir>/src/typeorm/repository/$1',
|
||||
'@test/(.*)': '<rootDir>/test/$1',
|
||||
'@entity/(.*)':
|
||||
// eslint-disable-next-line n/no-process-env
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/entity/$1'
|
||||
: '<rootDir>/../database/build/entity/$1',
|
||||
'@dbTools/(.*)':
|
||||
// eslint-disable-next-line n/no-process-env
|
||||
process.env.NODE_ENV === 'development'
|
||||
? '<rootDir>/../database/src/$1'
|
||||
: '<rootDir>/../database/build/src/$1',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gradido-backend",
|
||||
"version": "1.19.1",
|
||||
"version": "1.20.0",
|
||||
"description": "Gradido unified backend providing an API-Service for Gradido Transactions",
|
||||
"main": "src/index.ts",
|
||||
"repository": "https://github.com/gradido/gradido/backend",
|
||||
@ -12,7 +12,7 @@
|
||||
"clean": "tsc --build --clean",
|
||||
"start": "cross-env TZ=UTC TS_NODE_BASEURL=./build node -r tsconfig-paths/register build/src/index.js",
|
||||
"dev": "cross-env TZ=UTC nodemon -w src --ext ts --exec ts-node -r tsconfig-paths/register src/index.ts",
|
||||
"lint": "eslint --max-warnings=0 --ext .js,.ts .",
|
||||
"lint": "eslint --max-warnings=0 .",
|
||||
"test": "cross-env TZ=UTC NODE_ENV=development jest --runInBand --forceExit --detectOpenHandles",
|
||||
"seed": "cross-env TZ=UTC NODE_ENV=development ts-node -r tsconfig-paths/register src/seeds/index.ts",
|
||||
"klicktipp": "cross-env TZ=UTC NODE_ENV=development ts-node -r tsconfig-paths/register src/util/klicktipp.ts",
|
||||
@ -29,6 +29,7 @@
|
||||
"dotenv": "^10.0.0",
|
||||
"email-templates": "^10.0.1",
|
||||
"express": "^4.17.1",
|
||||
"gradido-database": "file:../database",
|
||||
"graphql": "^15.5.1",
|
||||
"graphql-request": "5.0.0",
|
||||
"i18n": "^0.15.1",
|
||||
@ -55,22 +56,25 @@
|
||||
"@types/node": "^16.10.3",
|
||||
"@types/nodemailer": "^6.4.4",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
||||
"@typescript-eslint/parser": "^4.28.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
||||
"@typescript-eslint/parser": "^5.57.1",
|
||||
"apollo-server-testing": "^2.25.2",
|
||||
"eslint": "^7.29.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint-plugin-import": "^2.23.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^3.4.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint": "^8.37.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint-config-standard": "^17.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.4",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"eslint-plugin-n": "^15.7.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-type-graphql": "^1.0.0",
|
||||
"faker": "^5.5.3",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"jest": "^27.2.4",
|
||||
"klicktipp-api": "^1.0.2",
|
||||
"nodemon": "^2.0.7",
|
||||
"prettier": "^2.3.1",
|
||||
"prettier": "^2.8.7",
|
||||
"ts-jest": "^27.0.5",
|
||||
"ts-node": "^10.0.0",
|
||||
"tsconfig-paths": "^3.14.0",
|
||||
@ -80,5 +84,8 @@
|
||||
"ignore": [
|
||||
"**/*.test.ts"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
import axios from 'axios'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import LogError from '@/server/LogError'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const apiPost = async (url: string, payload: unknown): Promise<any> => {
|
||||
|
||||
@ -4,8 +4,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
// eslint-disable-next-line import/no-relative-parent-imports
|
||||
import KlicktippConnector from 'klicktipp-api'
|
||||
import CONFIG from '@/config'
|
||||
|
||||
const klicktippConnector = new KlicktippConnector()
|
||||
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
import jwt from 'jsonwebtoken'
|
||||
import CONFIG from '@/config/'
|
||||
import { verify, sign } from 'jsonwebtoken'
|
||||
|
||||
import { CONFIG } from '@/config/'
|
||||
import { LogError } from '@/server/LogError'
|
||||
|
||||
import { CustomJwtPayload } from './CustomJwtPayload'
|
||||
import LogError from '@/server/LogError'
|
||||
|
||||
export const decode = (token: string): CustomJwtPayload | null => {
|
||||
if (!token) throw new LogError('401 Unauthorized')
|
||||
try {
|
||||
return <CustomJwtPayload>jwt.verify(token, CONFIG.JWT_SECRET)
|
||||
return <CustomJwtPayload>verify(token, CONFIG.JWT_SECRET)
|
||||
} catch (err) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export const encode = (gradidoID: string): string => {
|
||||
const token = jwt.sign({ gradidoID }, CONFIG.JWT_SECRET, {
|
||||
const token = sign({ gradidoID }, CONFIG.JWT_SECRET, {
|
||||
expiresIn: CONFIG.JWT_EXPIRES_IN,
|
||||
})
|
||||
return token
|
||||
|
||||
@ -35,6 +35,7 @@ export enum RIGHTS {
|
||||
CREATE_CONTRIBUTION_MESSAGE = 'CREATE_CONTRIBUTION_MESSAGE',
|
||||
LIST_ALL_CONTRIBUTION_MESSAGES = 'LIST_ALL_CONTRIBUTION_MESSAGES',
|
||||
OPEN_CREATIONS = 'OPEN_CREATIONS',
|
||||
USER = 'USER',
|
||||
// Admin
|
||||
SEARCH_USERS = 'SEARCH_USERS',
|
||||
SET_USER_ROLE = 'SET_USER_ROLE',
|
||||
|
||||
@ -34,6 +34,7 @@ export const ROLE_USER = new Role('user', [
|
||||
RIGHTS.CREATE_CONTRIBUTION_MESSAGE,
|
||||
RIGHTS.LIST_ALL_CONTRIBUTION_MESSAGES,
|
||||
RIGHTS.OPEN_CREATIONS,
|
||||
RIGHTS.USER,
|
||||
])
|
||||
export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import CONFIG from './index'
|
||||
import { CONFIG } from './index'
|
||||
|
||||
describe('config/index', () => {
|
||||
describe('decay start block', () => {
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env)
|
||||
/* eslint-disable n/no-process-env */
|
||||
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import dotenv from 'dotenv'
|
||||
import Decimal from 'decimal.js-light'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
Decimal.set({
|
||||
@ -10,7 +12,7 @@ Decimal.set({
|
||||
})
|
||||
|
||||
const constants = {
|
||||
DB_VERSION: '0063-event_link_fields',
|
||||
DB_VERSION: '0064-event_rename',
|
||||
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
|
||||
@ -74,7 +76,7 @@ const email = {
|
||||
EMAIL_SENDER: process.env.EMAIL_SENDER || 'info@gradido.net',
|
||||
EMAIL_PASSWORD: process.env.EMAIL_PASSWORD || '',
|
||||
EMAIL_SMTP_URL: process.env.EMAIL_SMTP_URL || 'mailserver',
|
||||
EMAIL_SMTP_PORT: process.env.EMAIL_SMTP_PORT || '1025',
|
||||
EMAIL_SMTP_PORT: Number(process.env.EMAIL_SMTP_PORT) || 1025,
|
||||
// eslint-disable-next-line no-unneeded-ternary
|
||||
EMAIL_TLS: process.env.EMAIL_TLS === 'false' ? false : true,
|
||||
EMAIL_LINK_VERIFICATION:
|
||||
@ -119,7 +121,7 @@ const federation = {
|
||||
Number(process.env.FEDERATION_VALIDATE_COMMUNITY_TIMER) || 60000,
|
||||
}
|
||||
|
||||
const CONFIG = {
|
||||
export const CONFIG = {
|
||||
...constants,
|
||||
...server,
|
||||
...database,
|
||||
@ -130,5 +132,3 @@ const CONFIG = {
|
||||
...webhook,
|
||||
...federation,
|
||||
}
|
||||
|
||||
export default CONFIG
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
import { createTransport } from 'nodemailer'
|
||||
|
||||
import { logger, i18n } from '@test/testSetup'
|
||||
import CONFIG from '@/config'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
import { sendEmailTranslated } from './sendEmailTranslated'
|
||||
|
||||
CONFIG.EMAIL = false
|
||||
CONFIG.EMAIL_SMTP_URL = 'EMAIL_SMTP_URL'
|
||||
CONFIG.EMAIL_SMTP_PORT = '1234'
|
||||
CONFIG.EMAIL_SMTP_PORT = 1234
|
||||
CONFIG.EMAIL_USERNAME = 'user'
|
||||
CONFIG.EMAIL_PASSWORD = 'pwd'
|
||||
CONFIG.EMAIL_TLS = true
|
||||
@ -28,7 +31,7 @@ jest.mock('nodemailer', () => {
|
||||
})
|
||||
|
||||
describe('sendEmailTranslated', () => {
|
||||
let result: Record<string, unknown> | null
|
||||
let result: Record<string, unknown> | boolean | null
|
||||
|
||||
describe('config email is false', () => {
|
||||
beforeEach(async () => {
|
||||
@ -102,10 +105,12 @@ describe('sendEmailTranslated', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('calls "i18n.setLocale" with "en"', () => {
|
||||
expect(i18n.setLocale).toBeCalledWith('en')
|
||||
})
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('calls "i18n.__" for translation', () => {
|
||||
expect(i18n.__).toBeCalled()
|
||||
})
|
||||
|
||||
@ -1,47 +1,52 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
import CONFIG from '@/config'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
import path from 'path'
|
||||
import { createTransport } from 'nodemailer'
|
||||
|
||||
import Email from 'email-templates'
|
||||
import i18n from 'i18n'
|
||||
import LogError from '@/server/LogError'
|
||||
import { createTransport } from 'nodemailer'
|
||||
|
||||
export const sendEmailTranslated = async (params: {
|
||||
import { CONFIG } from '@/config'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
export const sendEmailTranslated = async ({
|
||||
receiver,
|
||||
template,
|
||||
locals,
|
||||
}: {
|
||||
receiver: {
|
||||
to: string
|
||||
cc?: string
|
||||
}
|
||||
template: string
|
||||
locals: Record<string, unknown>
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
let resultSend: Record<string, unknown> | null = null
|
||||
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
// TODO: test the calling order of 'i18n.setLocale' for example: language of logging 'en', language of email receiver 'es', reset language of current user 'de'
|
||||
|
||||
// because language of receiver can differ from language of current user who triggers the sending
|
||||
const rememberLocaleToRestore = i18n.getLocale()
|
||||
|
||||
i18n.setLocale('en') // for logging
|
||||
logger.info(
|
||||
`send Email: language=${params.locals.locale} to=${params.receiver.to}` +
|
||||
(params.receiver.cc ? `, cc=${params.receiver.cc}` : '') +
|
||||
`, subject=${i18n.__('emails.' + params.template + '.subject')}`,
|
||||
)
|
||||
|
||||
if (!CONFIG.EMAIL) {
|
||||
logger.info(`Emails are disabled via config...`)
|
||||
return null
|
||||
}
|
||||
|
||||
// because language of receiver can differ from language of current user who triggers the sending
|
||||
// const rememberLocaleToRestore = i18n.getLocale()
|
||||
|
||||
i18n.setLocale('en') // for logging
|
||||
logger.info(
|
||||
`send Email: language=${locals.locale as string} to=${receiver.to}` +
|
||||
(receiver.cc ? `, cc=${receiver.cc}` : '') +
|
||||
`, subject=${i18n.__('emails.' + template + '.subject')}`,
|
||||
)
|
||||
|
||||
if (CONFIG.EMAIL_TEST_MODUS) {
|
||||
logger.info(
|
||||
`Testmodus=ON: change receiver from ${params.receiver.to} to ${CONFIG.EMAIL_TEST_RECEIVER}`,
|
||||
`Testmodus=ON: change receiver from ${receiver.to} to ${CONFIG.EMAIL_TEST_RECEIVER}`,
|
||||
)
|
||||
params.receiver.to = CONFIG.EMAIL_TEST_RECEIVER
|
||||
receiver.to = CONFIG.EMAIL_TEST_RECEIVER
|
||||
}
|
||||
const transport = createTransport({
|
||||
host: CONFIG.EMAIL_SMTP_URL,
|
||||
port: Number(CONFIG.EMAIL_SMTP_PORT),
|
||||
port: CONFIG.EMAIL_SMTP_PORT,
|
||||
secure: false, // true for 465, false for other ports
|
||||
requireTLS: CONFIG.EMAIL_TLS,
|
||||
auth: {
|
||||
@ -50,7 +55,7 @@ export const sendEmailTranslated = async (params: {
|
||||
},
|
||||
})
|
||||
|
||||
i18n.setLocale(params.locals.locale as string) // for email
|
||||
i18n.setLocale(locals.locale as string) // for email
|
||||
|
||||
// TESTING: see 'README.md'
|
||||
const email = new Email({
|
||||
@ -62,23 +67,16 @@ export const sendEmailTranslated = async (params: {
|
||||
// i18n, // is only needed if you don't install i18n
|
||||
})
|
||||
|
||||
// ATTENTION: await is needed, because otherwise on send the email gets send in the language of the current user, because below the language gets reset
|
||||
await email
|
||||
const resultSend = await email
|
||||
.send({
|
||||
template: path.join(__dirname, 'templates', params.template),
|
||||
message: params.receiver,
|
||||
locals: params.locals, // the 'locale' in here seems not to be used by 'email-template', because it doesn't work if the language isn't set before by 'i18n.setLocale'
|
||||
})
|
||||
.then((result: Record<string, unknown>) => {
|
||||
resultSend = result
|
||||
logger.info('Send email successfully !!!')
|
||||
logger.info('Result: ', result)
|
||||
template: path.join(__dirname, 'templates', template),
|
||||
message: receiver,
|
||||
locals, // the 'locale' in here seems not to be used by 'email-template', because it doesn't work if the language isn't set before by 'i18n.setLocale'
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
throw new LogError('Error sending notification email', error)
|
||||
logger.error('Error sending notification email', error)
|
||||
return false
|
||||
})
|
||||
|
||||
i18n.setLocale(rememberLocaleToRestore)
|
||||
|
||||
return resultSend
|
||||
}
|
||||
|
||||
@ -3,10 +3,14 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { testEnvironment } from '@test/helpers'
|
||||
import { logger, i18n as localization } from '@test/testSetup'
|
||||
import CONFIG from '@/config'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
|
||||
import { sendEmailTranslated } from './sendEmailTranslated'
|
||||
import {
|
||||
sendAddedContributionMessageEmail,
|
||||
sendAccountActivationEmail,
|
||||
@ -18,7 +22,6 @@ import {
|
||||
sendTransactionLinkRedeemedEmail,
|
||||
sendTransactionReceivedEmail,
|
||||
} from './sendEmailVariants'
|
||||
import { sendEmailTranslated } from './sendEmailTranslated'
|
||||
|
||||
let con: any
|
||||
let testEnv: any
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import CONFIG from '@/config'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { CONFIG } from '@/config'
|
||||
import { decimalSeparatorByLanguage } from '@/util/utilities'
|
||||
|
||||
import { sendEmailTranslated } from './sendEmailTranslated'
|
||||
|
||||
export const sendAddedContributionMessageEmail = (data: {
|
||||
@ -11,7 +13,7 @@ export const sendAddedContributionMessageEmail = (data: {
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
contributionMemo: string
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: {
|
||||
to: `${data.firstName} ${data.lastName} <${data.email}>`,
|
||||
@ -38,7 +40,7 @@ export const sendAccountActivationEmail = (data: {
|
||||
language: string
|
||||
activationLink: string
|
||||
timeDurationObject: Record<string, unknown>
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` },
|
||||
template: 'accountActivation',
|
||||
@ -60,7 +62,7 @@ export const sendAccountMultiRegistrationEmail = (data: {
|
||||
lastName: string
|
||||
email: string
|
||||
language: string
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` },
|
||||
template: 'accountMultiRegistration',
|
||||
@ -84,7 +86,7 @@ export const sendContributionConfirmedEmail = (data: {
|
||||
senderLastName: string
|
||||
contributionMemo: string
|
||||
contributionAmount: Decimal
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` },
|
||||
template: 'contributionConfirmed',
|
||||
@ -111,7 +113,7 @@ export const sendContributionDeletedEmail = (data: {
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
contributionMemo: string
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` },
|
||||
template: 'contributionDeleted',
|
||||
@ -137,7 +139,7 @@ export const sendContributionDeniedEmail = (data: {
|
||||
senderFirstName: string
|
||||
senderLastName: string
|
||||
contributionMemo: string
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` },
|
||||
template: 'contributionDenied',
|
||||
@ -162,7 +164,7 @@ export const sendResetPasswordEmail = (data: {
|
||||
language: string
|
||||
resetLink: string
|
||||
timeDurationObject: Record<string, unknown>
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` },
|
||||
template: 'resetPassword',
|
||||
@ -189,7 +191,7 @@ export const sendTransactionLinkRedeemedEmail = (data: {
|
||||
senderEmail: string
|
||||
transactionMemo: string
|
||||
transactionAmount: Decimal
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` },
|
||||
template: 'transactionLinkRedeemed',
|
||||
@ -218,7 +220,7 @@ export const sendTransactionReceivedEmail = (data: {
|
||||
senderLastName: string
|
||||
senderEmail: string
|
||||
transactionAmount: Decimal
|
||||
}): Promise<Record<string, unknown> | null> => {
|
||||
}): Promise<Record<string, unknown> | boolean | null> => {
|
||||
return sendEmailTranslated({
|
||||
receiver: { to: `${data.firstName} ${data.lastName} <${data.email}>` },
|
||||
template: 'transactionReceived',
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
|
||||
export const EVENT_ACTIVATE_ACCOUNT = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.ACTIVATE_ACCOUNT, user, user).save()
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_CONFIRM = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_CREATE = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_DELETE = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_DENY = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_LINK_CREATE = async (
|
||||
moderator: DbUser,
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_LINK_DELETE = async (
|
||||
moderator: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE = async (
|
||||
moderator: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_CONTRIBUTION_UPDATE = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
|
||||
export const EVENT_ADMIN_SEND_CONFIRMATION_EMAIL = async (
|
||||
user: DbUser,
|
||||
moderator: DbUser,
|
||||
): Promise<DbEvent> => Event(EventType.ADMIN_SEND_CONFIRMATION_EMAIL, user, moderator).save()
|
||||
8
backend/src/event/EVENT_ADMIN_USER_DELETE.ts
Normal file
8
backend/src/event/EVENT_ADMIN_USER_DELETE.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_USER_DELETE = async (user: DbUser, moderator: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.ADMIN_USER_DELETE, user, moderator).save()
|
||||
10
backend/src/event/EVENT_ADMIN_USER_ROLE_SET.ts
Normal file
10
backend/src/event/EVENT_ADMIN_USER_ROLE_SET.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_USER_ROLE_SET = async (
|
||||
user: DbUser,
|
||||
moderator: DbUser,
|
||||
): Promise<DbEvent> => Event(EventType.ADMIN_USER_ROLE_SET, user, moderator).save()
|
||||
10
backend/src/event/EVENT_ADMIN_USER_UNDELETE.ts
Normal file
10
backend/src/event/EVENT_ADMIN_USER_UNDELETE.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_ADMIN_USER_UNDELETE = async (
|
||||
user: DbUser,
|
||||
moderator: DbUser,
|
||||
): Promise<DbEvent> => Event(EventType.ADMIN_USER_UNDELETE, user, moderator).save()
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_CONTRIBUTION_CREATE = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_CONTRIBUTION_DELETE = async (
|
||||
user: DbUser,
|
||||
|
||||
29
backend/src/event/EVENT_CONTRIBUTION_LINK_REDEEM.ts
Normal file
29
backend/src/event/EVENT_CONTRIBUTION_LINK_REDEEM.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_CONTRIBUTION_LINK_REDEEM = async (
|
||||
user: DbUser,
|
||||
transaction: DbTransaction,
|
||||
contribution: DbContribution,
|
||||
contributionLink: DbContributionLink,
|
||||
amount: Decimal,
|
||||
): Promise<DbEvent> =>
|
||||
Event(
|
||||
EventType.CONTRIBUTION_LINK_REDEEM,
|
||||
user,
|
||||
user,
|
||||
null,
|
||||
transaction,
|
||||
contribution,
|
||||
null,
|
||||
null,
|
||||
contributionLink,
|
||||
amount,
|
||||
).save()
|
||||
@ -1,8 +1,10 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_CONTRIBUTION_MESSAGE_CREATE = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_CONTRIBUTION_UPDATE = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.EMAIL_ACCOUNT_MULTIREGISTRATION, user, { id: 0 } as DbUser).save()
|
||||
10
backend/src/event/EVENT_EMAIL_ADMIN_CONFIRMATION.ts
Normal file
10
backend/src/event/EVENT_EMAIL_ADMIN_CONFIRMATION.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_EMAIL_ADMIN_CONFIRMATION = async (
|
||||
user: DbUser,
|
||||
moderator: DbUser,
|
||||
): Promise<DbEvent> => Event(EventType.EMAIL_ADMIN_CONFIRMATION, user, moderator).save()
|
||||
8
backend/src/event/EVENT_EMAIL_CONFIRMATION.ts
Normal file
8
backend/src/event/EVENT_EMAIL_CONFIRMATION.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_EMAIL_CONFIRMATION = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.EMAIL_CONFIRMATION, user, user).save()
|
||||
8
backend/src/event/EVENT_EMAIL_FORGOT_PASSWORD.ts
Normal file
8
backend/src/event/EVENT_EMAIL_FORGOT_PASSWORD.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_EMAIL_FORGOT_PASSWORD = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.EMAIL_FORGOT_PASSWORD, user, { id: 0 } as DbUser).save()
|
||||
@ -1,6 +0,0 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
|
||||
export const EVENT_LOGIN = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.LOGIN, user, user).save()
|
||||
@ -1,6 +0,0 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
|
||||
export const EVENT_REGISTER = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.REGISTER, user, user).save()
|
||||
@ -1,6 +0,0 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
|
||||
export const EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.SEND_ACCOUNT_MULTIREGISTRATION_EMAIL, user, { id: 0 } as DbUser).save()
|
||||
@ -1,6 +0,0 @@
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
|
||||
export const EVENT_SEND_CONFIRMATION_EMAIL = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.SEND_CONFIRMATION_EMAIL, user, user).save()
|
||||
25
backend/src/event/EVENT_TRANSACTION_LINK_CREATE.ts
Normal file
25
backend/src/event/EVENT_TRANSACTION_LINK_CREATE.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_TRANSACTION_LINK_CREATE = async (
|
||||
user: DbUser,
|
||||
transactionLink: DbTransactionLink,
|
||||
amount: Decimal,
|
||||
): Promise<DbEvent> =>
|
||||
Event(
|
||||
EventType.TRANSACTION_LINK_CREATE,
|
||||
user,
|
||||
user,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
transactionLink,
|
||||
null,
|
||||
amount,
|
||||
).save()
|
||||
21
backend/src/event/EVENT_TRANSACTION_LINK_DELETE.ts
Normal file
21
backend/src/event/EVENT_TRANSACTION_LINK_DELETE.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_TRANSACTION_LINK_DELETE = async (
|
||||
user: DbUser,
|
||||
transactionLink: DbTransactionLink,
|
||||
): Promise<DbEvent> =>
|
||||
Event(
|
||||
EventType.TRANSACTION_LINK_DELETE,
|
||||
user,
|
||||
user,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
transactionLink,
|
||||
).save()
|
||||
26
backend/src/event/EVENT_TRANSACTION_LINK_REDEEM.ts
Normal file
26
backend/src/event/EVENT_TRANSACTION_LINK_REDEEM.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_TRANSACTION_LINK_REDEEM = async (
|
||||
user: DbUser,
|
||||
senderUser: DbUser,
|
||||
transactionLink: DbTransactionLink,
|
||||
amount: Decimal,
|
||||
): Promise<DbEvent> =>
|
||||
Event(
|
||||
EventType.TRANSACTION_LINK_REDEEM,
|
||||
user,
|
||||
user,
|
||||
senderUser,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
transactionLink,
|
||||
null,
|
||||
amount,
|
||||
).save()
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_TRANSACTION_RECEIVE = async (
|
||||
user: DbUser,
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { Event, EventType } from './Event'
|
||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_TRANSACTION_SEND = async (
|
||||
user: DbUser,
|
||||
|
||||
8
backend/src/event/EVENT_USER_ACTIVATE_ACCOUNT.ts
Normal file
8
backend/src/event/EVENT_USER_ACTIVATE_ACCOUNT.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_USER_ACTIVATE_ACCOUNT = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.USER_ACTIVATE_ACCOUNT, user, user).save()
|
||||
8
backend/src/event/EVENT_USER_INFO_UPDATE.ts
Normal file
8
backend/src/event/EVENT_USER_INFO_UPDATE.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_USER_INFO_UPDATE = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.USER_INFO_UPDATE, user, user).save()
|
||||
8
backend/src/event/EVENT_USER_LOGIN.ts
Normal file
8
backend/src/event/EVENT_USER_LOGIN.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_USER_LOGIN = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.USER_LOGIN, user, user).save()
|
||||
8
backend/src/event/EVENT_USER_LOGOUT.ts
Normal file
8
backend/src/event/EVENT_USER_LOGOUT.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_USER_LOGOUT = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.USER_LOGOUT, user, user).save()
|
||||
8
backend/src/event/EVENT_USER_REGISTER.ts
Normal file
8
backend/src/event/EVENT_USER_REGISTER.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
|
||||
import { Event } from './Event'
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const EVENT_USER_REGISTER = async (user: DbUser): Promise<DbEvent> =>
|
||||
Event(EventType.USER_REGISTER, user, user).save()
|
||||
@ -1,12 +1,13 @@
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
||||
import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage'
|
||||
import { Event as DbEvent } from '@entity/Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Transaction as DbTransaction } from '@entity/Transaction'
|
||||
import { TransactionLink as DbTransactionLink } from '@entity/TransactionLink'
|
||||
import { Contribution as DbContribution } from '@entity/Contribution'
|
||||
import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage'
|
||||
import { ContributionLink as DbContributionLink } from '@entity/ContributionLink'
|
||||
import Decimal from 'decimal.js-light'
|
||||
import { EventType } from './Event'
|
||||
import { User as DbUser } from '@entity/User'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
|
||||
import { EventType } from './EventType'
|
||||
|
||||
export const Event = (
|
||||
type: EventType,
|
||||
@ -33,27 +34,3 @@ export const Event = (
|
||||
event.amount = amount
|
||||
return event
|
||||
}
|
||||
|
||||
export { EventType } from './EventType'
|
||||
|
||||
export { EVENT_ACTIVATE_ACCOUNT } from './EVENT_ACTIVATE_ACCOUNT'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_CONFIRM } from './EVENT_ADMIN_CONTRIBUTION_CONFIRM'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_CREATE } from './EVENT_ADMIN_CONTRIBUTION_CREATE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_DELETE } from './EVENT_ADMIN_CONTRIBUTION_DELETE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_DENY } from './EVENT_ADMIN_CONTRIBUTION_DENY'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_UPDATE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_LINK_CREATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_CREATE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_LINK_DELETE } from './EVENT_ADMIN_CONTRIBUTION_LINK_DELETE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE'
|
||||
export { EVENT_ADMIN_SEND_CONFIRMATION_EMAIL } from './EVENT_ADMIN_SEND_CONFIRMATION_EMAIL'
|
||||
export { EVENT_CONTRIBUTION_CREATE } from './EVENT_CONTRIBUTION_CREATE'
|
||||
export { EVENT_CONTRIBUTION_DELETE } from './EVENT_CONTRIBUTION_DELETE'
|
||||
export { EVENT_CONTRIBUTION_UPDATE } from './EVENT_CONTRIBUTION_UPDATE'
|
||||
export { EVENT_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_CONTRIBUTION_MESSAGE_CREATE'
|
||||
export { EVENT_LOGIN } from './EVENT_LOGIN'
|
||||
export { EVENT_REGISTER } from './EVENT_REGISTER'
|
||||
export { EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL } from './EVENT_SEND_ACCOUNT_MULTIREGISTRATION_EMAIL'
|
||||
export { EVENT_SEND_CONFIRMATION_EMAIL } from './EVENT_SEND_CONFIRMATION_EMAIL'
|
||||
export { EVENT_TRANSACTION_SEND } from './EVENT_TRANSACTION_SEND'
|
||||
export { EVENT_TRANSACTION_RECEIVE } from './EVENT_TRANSACTION_RECEIVE'
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
export enum EventType {
|
||||
ACTIVATE_ACCOUNT = 'ACTIVATE_ACCOUNT',
|
||||
// TODO CONTRIBUTION_CONFIRM = 'CONTRIBUTION_CONFIRM',
|
||||
ADMIN_CONTRIBUTION_CONFIRM = 'ADMIN_CONTRIBUTION_CONFIRM',
|
||||
ADMIN_CONTRIBUTION_CREATE = 'ADMIN_CONTRIBUTION_CREATE',
|
||||
@ -10,24 +9,34 @@ export enum EventType {
|
||||
ADMIN_CONTRIBUTION_LINK_DELETE = 'ADMIN_CONTRIBUTION_LINK_DELETE',
|
||||
ADMIN_CONTRIBUTION_LINK_UPDATE = 'ADMIN_CONTRIBUTION_LINK_UPDATE',
|
||||
ADMIN_CONTRIBUTION_MESSAGE_CREATE = 'ADMIN_CONTRIBUTION_MESSAGE_CREATE',
|
||||
ADMIN_SEND_CONFIRMATION_EMAIL = 'ADMIN_SEND_CONFIRMATION_EMAIL',
|
||||
ADMIN_USER_DELETE = 'ADMIN_USER_DELETE',
|
||||
ADMIN_USER_UNDELETE = 'ADMIN_USER_UNDELETE',
|
||||
ADMIN_USER_ROLE_SET = 'ADMIN_USER_ROLE_SET',
|
||||
CONTRIBUTION_CREATE = 'CONTRIBUTION_CREATE',
|
||||
CONTRIBUTION_DELETE = 'CONTRIBUTION_DELETE',
|
||||
CONTRIBUTION_UPDATE = 'CONTRIBUTION_UPDATE',
|
||||
CONTRIBUTION_MESSAGE_CREATE = 'CONTRIBUTION_MESSAGE_CREATE',
|
||||
LOGIN = 'LOGIN',
|
||||
REGISTER = 'REGISTER',
|
||||
REDEEM_REGISTER = 'REDEEM_REGISTER',
|
||||
SEND_ACCOUNT_MULTIREGISTRATION_EMAIL = 'SEND_ACCOUNT_MULTIREGISTRATION_EMAIL',
|
||||
SEND_CONFIRMATION_EMAIL = 'SEND_CONFIRMATION_EMAIL',
|
||||
CONTRIBUTION_LINK_REDEEM = 'CONTRIBUTION_LINK_REDEEM',
|
||||
EMAIL_ACCOUNT_MULTIREGISTRATION = 'EMAIL_ACCOUNT_MULTIREGISTRATION',
|
||||
EMAIL_ADMIN_CONFIRMATION = 'EMAIL_ADMIN_CONFIRMATION',
|
||||
EMAIL_CONFIRMATION = 'EMAIL_CONFIRMATION',
|
||||
EMAIL_FORGOT_PASSWORD = 'EMAIL_FORGOT_PASSWORD',
|
||||
TRANSACTION_SEND = 'TRANSACTION_SEND',
|
||||
TRANSACTION_RECEIVE = 'TRANSACTION_RECEIVE',
|
||||
TRANSACTION_LINK_CREATE = 'TRANSACTION_LINK_CREATE',
|
||||
TRANSACTION_LINK_DELETE = 'TRANSACTION_LINK_DELETE',
|
||||
TRANSACTION_LINK_REDEEM = 'TRANSACTION_LINK_REDEEM',
|
||||
USER_ACTIVATE_ACCOUNT = 'ACTIVATE_ACCOUNT',
|
||||
USER_INFO_UPDATE = 'USER_INFO_UPDATE',
|
||||
USER_LOGIN = 'USER_LOGIN',
|
||||
USER_LOGOUT = 'USER_LOGOUT',
|
||||
USER_REGISTER = 'USER_REGISTER',
|
||||
USER_REGISTER_REDEEM = 'USER_REGISTER_REDEEM',
|
||||
// VISIT_GRADIDO = 'VISIT_GRADIDO',
|
||||
// VERIFY_REDEEM = 'VERIFY_REDEEM',
|
||||
// INACTIVE_ACCOUNT = 'INACTIVE_ACCOUNT',
|
||||
// CONFIRM_EMAIL = 'CONFIRM_EMAIL',
|
||||
// REGISTER_EMAIL_KLICKTIPP = 'REGISTER_EMAIL_KLICKTIPP',
|
||||
// LOGOUT = 'LOGOUT',
|
||||
// REDEEM_LOGIN = 'REDEEM_LOGIN',
|
||||
// SEND_FORGOT_PASSWORD_EMAIL = 'SEND_FORGOT_PASSWORD_EMAIL',
|
||||
// PASSWORD_CHANGE = 'PASSWORD_CHANGE',
|
||||
|
||||
33
backend/src/event/Events.ts
Normal file
33
backend/src/event/Events.ts
Normal file
@ -0,0 +1,33 @@
|
||||
export { EventType } from './EventType'
|
||||
export { Event } from './Event'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_CONFIRM } from './EVENT_ADMIN_CONTRIBUTION_CONFIRM'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_CREATE } from './EVENT_ADMIN_CONTRIBUTION_CREATE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_DELETE } from './EVENT_ADMIN_CONTRIBUTION_DELETE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_DENY } from './EVENT_ADMIN_CONTRIBUTION_DENY'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_UPDATE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_LINK_CREATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_CREATE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_LINK_DELETE } from './EVENT_ADMIN_CONTRIBUTION_LINK_DELETE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE } from './EVENT_ADMIN_CONTRIBUTION_LINK_UPDATE'
|
||||
export { EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_ADMIN_CONTRIBUTION_MESSAGE_CREATE'
|
||||
export { EVENT_ADMIN_USER_DELETE } from './EVENT_ADMIN_USER_DELETE'
|
||||
export { EVENT_ADMIN_USER_UNDELETE } from './EVENT_ADMIN_USER_UNDELETE'
|
||||
export { EVENT_ADMIN_USER_ROLE_SET } from './EVENT_ADMIN_USER_ROLE_SET'
|
||||
export { EVENT_CONTRIBUTION_CREATE } from './EVENT_CONTRIBUTION_CREATE'
|
||||
export { EVENT_CONTRIBUTION_DELETE } from './EVENT_CONTRIBUTION_DELETE'
|
||||
export { EVENT_CONTRIBUTION_UPDATE } from './EVENT_CONTRIBUTION_UPDATE'
|
||||
export { EVENT_CONTRIBUTION_MESSAGE_CREATE } from './EVENT_CONTRIBUTION_MESSAGE_CREATE'
|
||||
export { EVENT_CONTRIBUTION_LINK_REDEEM } from './EVENT_CONTRIBUTION_LINK_REDEEM'
|
||||
export { EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION } from './EVENT_EMAIL_ACCOUNT_MULTIREGISTRATION'
|
||||
export { EVENT_EMAIL_ADMIN_CONFIRMATION } from './EVENT_EMAIL_ADMIN_CONFIRMATION'
|
||||
export { EVENT_EMAIL_CONFIRMATION } from './EVENT_EMAIL_CONFIRMATION'
|
||||
export { EVENT_EMAIL_FORGOT_PASSWORD } from './EVENT_EMAIL_FORGOT_PASSWORD'
|
||||
export { EVENT_TRANSACTION_SEND } from './EVENT_TRANSACTION_SEND'
|
||||
export { EVENT_TRANSACTION_RECEIVE } from './EVENT_TRANSACTION_RECEIVE'
|
||||
export { EVENT_TRANSACTION_LINK_CREATE } from './EVENT_TRANSACTION_LINK_CREATE'
|
||||
export { EVENT_TRANSACTION_LINK_DELETE } from './EVENT_TRANSACTION_LINK_DELETE'
|
||||
export { EVENT_TRANSACTION_LINK_REDEEM } from './EVENT_TRANSACTION_LINK_REDEEM'
|
||||
export { EVENT_USER_ACTIVATE_ACCOUNT } from './EVENT_USER_ACTIVATE_ACCOUNT'
|
||||
export { EVENT_USER_INFO_UPDATE } from './EVENT_USER_INFO_UPDATE'
|
||||
export { EVENT_USER_LOGIN } from './EVENT_USER_LOGIN'
|
||||
export { EVENT_USER_LOGOUT } from './EVENT_USER_LOGOUT'
|
||||
export { EVENT_USER_REGISTER } from './EVENT_USER_REGISTER'
|
||||
@ -1,11 +1,12 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { gql } from 'graphql-request'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import { Community as DbCommunity } from '@entity/Community'
|
||||
import { GraphQLGetClient } from '../GraphQLGetClient'
|
||||
import LogError from '@/server/LogError'
|
||||
import { gql } from 'graphql-request'
|
||||
|
||||
import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
export async function requestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> {
|
||||
let endpoint = dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import { gql } from 'graphql-request'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import { Community as DbCommunity } from '@entity/Community'
|
||||
import { GraphQLGetClient } from '../GraphQLGetClient'
|
||||
import LogError from '@/server/LogError'
|
||||
import { gql } from 'graphql-request'
|
||||
|
||||
import { GraphQLGetClient } from '@/federation/client/GraphQLGetClient'
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
export async function requestGetPublicKey(dbCom: DbCommunity): Promise<string | undefined> {
|
||||
let endpoint = dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'
|
||||
|
||||
@ -5,9 +5,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
|
||||
import { logger } from '@test/testSetup'
|
||||
import { Community as DbCommunity } from '@entity/Community'
|
||||
|
||||
import { testEnvironment, cleanDB } from '@test/helpers'
|
||||
import { logger } from '@test/testSetup'
|
||||
|
||||
import { validateCommunities } from './validateCommunities'
|
||||
|
||||
let con: any
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { Community as DbCommunity } from '@entity/Community'
|
||||
import { IsNull } from '@dbTools/typeorm'
|
||||
import { Community as DbCommunity } from '@entity/Community'
|
||||
|
||||
import { LogError } from '@/server/LogError'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
import { requestGetPublicKey as v1_0_requestGetPublicKey } from './client/1_0/FederationClient'
|
||||
// eslint-disable-next-line camelcase
|
||||
import { requestGetPublicKey as v1_1_requestGetPublicKey } from './client/1_1/FederationClient'
|
||||
import { backendLogger as logger } from '@/server/logger'
|
||||
import { ApiVersionType } from './enum/apiVersionType'
|
||||
import LogError from '@/server/LogError'
|
||||
|
||||
export function startValidateCommunities(timerInterval: number): void {
|
||||
logger.info(
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { ArgsType, Field, InputType } from 'type-graphql'
|
||||
import Decimal from 'decimal.js-light'
|
||||
|
||||
@InputType()
|
||||
@ArgsType()
|
||||
export default class AdminCreateContributionArgs {
|
||||
export class AdminCreateContributionArgs {
|
||||
@Field(() => String)
|
||||
email: string
|
||||
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { ArgsType, Field, Int } from 'type-graphql'
|
||||
import Decimal from 'decimal.js-light'
|
||||
|
||||
@ArgsType()
|
||||
export default class AdminUpdateContributionArgs {
|
||||
export class AdminUpdateContributionArgs {
|
||||
@Field(() => Int)
|
||||
id: number
|
||||
|
||||
@Field(() => String)
|
||||
email: string
|
||||
|
||||
@Field(() => Decimal)
|
||||
amount: Decimal
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { ArgsType, Field, InputType } from 'type-graphql'
|
||||
import Decimal from 'decimal.js-light'
|
||||
|
||||
@InputType()
|
||||
@ArgsType()
|
||||
export default class ContributionArgs {
|
||||
export class ContributionArgs {
|
||||
@Field(() => Decimal)
|
||||
amount: Decimal
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { ArgsType, Field, Int } from 'type-graphql'
|
||||
import Decimal from 'decimal.js-light'
|
||||
|
||||
@ArgsType()
|
||||
export default class ContributionLinkArgs {
|
||||
export class ContributionLinkArgs {
|
||||
@Field(() => Decimal)
|
||||
amount: Decimal
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { ArgsType, Field, Int, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
@ArgsType()
|
||||
export default class ContributionMessageArgs {
|
||||
export class ContributionMessageArgs {
|
||||
@Field(() => Int)
|
||||
contributionId: number
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { ArgsType, Field, Int } from 'type-graphql'
|
||||
|
||||
@ArgsType()
|
||||
export default class CreateUserArgs {
|
||||
export class CreateUserArgs {
|
||||
@Field(() => String)
|
||||
email: string
|
||||
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
/* eslint-disable type-graphql/invalid-nullable-input-type */
|
||||
import { ArgsType, Field, Int } from 'type-graphql'
|
||||
|
||||
import { Order } from '@enum/Order'
|
||||
|
||||
@ArgsType()
|
||||
export default class Paginated {
|
||||
export class Paginated {
|
||||
@Field(() => Int, { nullable: true })
|
||||
currentPage?: number
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { ArgsType, Field, Int } from 'type-graphql'
|
||||
import SearchUsersFilters from '@arg/SearchUsersFilters'
|
||||
|
||||
import { SearchUsersFilters } from '@arg/SearchUsersFilters'
|
||||
|
||||
@ArgsType()
|
||||
export default class SearchUsersArgs {
|
||||
export class SearchUsersArgs {
|
||||
@Field(() => String)
|
||||
searchText: string
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Field, InputType } from 'type-graphql'
|
||||
|
||||
@InputType()
|
||||
export default class SearchUsersFilters {
|
||||
export class SearchUsersFilters {
|
||||
@Field(() => Boolean, { nullable: true, defaultValue: null })
|
||||
byActivated?: boolean | null
|
||||
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
import { ArgsType, Field } from 'type-graphql'
|
||||
|
||||
@ArgsType()
|
||||
export default class SubscribeNewsletterArgs {
|
||||
@Field(() => String)
|
||||
email: string
|
||||
|
||||
@Field(() => String)
|
||||
language: string
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user