mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into feat-send-coins-via-gradido-ID
This commit is contained in:
commit
a1ed92b643
@ -28,6 +28,7 @@ const mocks = {
|
|||||||
|
|
||||||
let propsData
|
let propsData
|
||||||
let wrapper
|
let wrapper
|
||||||
|
let spy
|
||||||
|
|
||||||
describe('ChangeUserRoleFormular', () => {
|
describe('ChangeUserRoleFormular', () => {
|
||||||
const Wrapper = () => {
|
const Wrapper = () => {
|
||||||
@ -70,12 +71,16 @@ describe('ChangeUserRoleFormular', () => {
|
|||||||
expect(wrapper.text()).toContain('userRole.notChangeYourSelf')
|
expect(wrapper.text()).toContain('userRole.notChangeYourSelf')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has role select disabled', () => {
|
it('has no role select', () => {
|
||||||
expect(wrapper.find('select[disabled="disabled"]').exists()).toBe(true)
|
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
|
let rolesToSelect
|
||||||
|
|
||||||
describe('general', () => {
|
describe('general', () => {
|
||||||
@ -106,19 +111,12 @@ describe('ChangeUserRoleFormular', () => {
|
|||||||
expect(wrapper.find('select.role-select[disabled="disabled"]').exists()).toBe(false)
|
expect(wrapper.find('select.role-select[disabled="disabled"]').exists()).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('on API error', () => {
|
it('has "change_user_role" button', () => {
|
||||||
beforeEach(() => {
|
expect(wrapper.find('button.btn.btn-danger').text()).toBe('change_user_role')
|
||||||
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
|
||||||
rolesToSelect.at(1).setSelected()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('toasts an error message', () => {
|
|
||||||
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('user is usual user', () => {
|
describe('user has role "usual user"', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
apolloMutateMock.mockResolvedValue({
|
apolloMutateMock.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
@ -141,6 +139,10 @@ describe('ChangeUserRoleFormular', () => {
|
|||||||
|
|
||||||
describe('change select to', () => {
|
describe('change select to', () => {
|
||||||
describe('same role', () => {
|
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', () => {
|
it('does not call the API', () => {
|
||||||
rolesToSelect.at(0).setSelected()
|
rolesToSelect.at(0).setSelected()
|
||||||
expect(apolloMutateMock).not.toHaveBeenCalled()
|
expect(apolloMutateMock).not.toHaveBeenCalled()
|
||||||
@ -152,6 +154,27 @@ describe('ChangeUserRoleFormular', () => {
|
|||||||
rolesToSelect.at(1).setSelected()
|
rolesToSelect.at(1).setSelected()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
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('calls the modal', () => {
|
||||||
|
expect(wrapper.emitted('showModal'))
|
||||||
|
expect(spy).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('confirm role change with success', () => {
|
||||||
it('calls the API', () => {
|
it('calls the API', () => {
|
||||||
expect(apolloMutateMock).toBeCalledWith(
|
expect(apolloMutateMock).toBeCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@ -181,10 +204,25 @@ describe('ChangeUserRoleFormular', () => {
|
|||||||
expect(toastSuccessSpy).toBeCalledWith('userRole.successfullyChangedTo')
|
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(() => {
|
beforeEach(() => {
|
||||||
apolloMutateMock.mockResolvedValue({
|
apolloMutateMock.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
@ -207,6 +245,10 @@ describe('ChangeUserRoleFormular', () => {
|
|||||||
|
|
||||||
describe('change select to', () => {
|
describe('change select to', () => {
|
||||||
describe('same role', () => {
|
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', () => {
|
it('does not call the API', () => {
|
||||||
rolesToSelect.at(1).setSelected()
|
rolesToSelect.at(1).setSelected()
|
||||||
expect(apolloMutateMock).not.toHaveBeenCalled()
|
expect(apolloMutateMock).not.toHaveBeenCalled()
|
||||||
@ -218,6 +260,27 @@ describe('ChangeUserRoleFormular', () => {
|
|||||||
rolesToSelect.at(0).setSelected()
|
rolesToSelect.at(0).setSelected()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
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('calls the modal', () => {
|
||||||
|
expect(wrapper.emitted('showModal'))
|
||||||
|
expect(spy).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('confirm role change with success', () => {
|
||||||
it('calls the API', () => {
|
it('calls the API', () => {
|
||||||
expect(apolloMutateMock).toBeCalledWith(
|
expect(apolloMutateMock).toBeCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@ -247,6 +310,21 @@ describe('ChangeUserRoleFormular', () => {
|
|||||||
expect(toastSuccessSpy).toBeCalledWith('userRole.successfullyChangedTo')
|
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">
|
<div v-if="item.userId === $store.state.moderator.id" class="m-3 mb-4">
|
||||||
{{ $t('userRole.notChangeYourSelf') }}
|
{{ $t('userRole.notChangeYourSelf') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="m-3">
|
<div v-else class="m-3">
|
||||||
<label for="role" class="mr-3">{{ $t('userRole.selectLabel') }}</label>
|
<label for="role" class="mr-3">{{ $t('userRole.selectLabel') }}</label>
|
||||||
<b-form-select
|
<b-form-select class="role-select" v-model="roleSelected" :options="roles" />
|
||||||
class="role-select"
|
<div class="mt-3 mb-5">
|
||||||
v-model="roleSelected"
|
<b-button
|
||||||
:options="roles"
|
variant="danger"
|
||||||
:disabled="item.userId === $store.state.moderator.id"
|
v-b-modal.user-role-modal
|
||||||
/>
|
:disabled="currentRole === roleSelected"
|
||||||
|
@click="showModal()"
|
||||||
|
>
|
||||||
|
{{ $t('change_user_role') }}
|
||||||
|
</b-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { setUserRole } from '../graphql/setUserRole'
|
import { setUserRole } from '../graphql/setUserRole'
|
||||||
|
|
||||||
@ -35,6 +39,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
currentRole: this.item.isAdmin ? rolesValues.admin : rolesValues.user,
|
||||||
roleSelected: this.item.isAdmin ? rolesValues.admin : rolesValues.user,
|
roleSelected: this.item.isAdmin ? rolesValues.admin : rolesValues.user,
|
||||||
roles: [
|
roles: [
|
||||||
{ value: rolesValues.user, text: this.$t('userRole.selectRoles.user') },
|
{ 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: {
|
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) {
|
setUserRole(newRole, oldRole) {
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
|
|||||||
@ -35,6 +35,7 @@ const propsData = {
|
|||||||
|
|
||||||
describe('DeletedUserFormular', () => {
|
describe('DeletedUserFormular', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
|
let spy
|
||||||
|
|
||||||
const Wrapper = () => {
|
const Wrapper = () => {
|
||||||
return mount(DeletedUserFormular, { localVue, mocks, propsData })
|
return mount(DeletedUserFormular, { localVue, mocks, propsData })
|
||||||
@ -62,6 +63,10 @@ describe('DeletedUserFormular', () => {
|
|||||||
it('shows a text that you cannot delete yourself', () => {
|
it('shows a text that you cannot delete yourself', () => {
|
||||||
expect(wrapper.text()).toBe('removeNotSelf')
|
expect(wrapper.text()).toBe('removeNotSelf')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('has no "delete_user" button', () => {
|
||||||
|
expect(wrapper.find('button').exists()).toBe(false)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('delete other user', () => {
|
describe('delete other user', () => {
|
||||||
@ -71,35 +76,32 @@ describe('DeletedUserFormular', () => {
|
|||||||
userId: 1,
|
userId: 1,
|
||||||
deletedAt: null,
|
deletedAt: null,
|
||||||
},
|
},
|
||||||
|
static: true,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has a checkbox', () => {
|
|
||||||
expect(wrapper.find('input[type="checkbox"]').exists()).toBe(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('shows the text "delete_user"', () => {
|
it('shows the text "delete_user"', () => {
|
||||||
expect(wrapper.text()).toBe('delete_user')
|
expect(wrapper.text()).toBe('delete_user')
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('click on checkbox', () => {
|
it('has a "delete_user" button', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.find('input[type="checkbox"]').setChecked()
|
|
||||||
})
|
|
||||||
|
|
||||||
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')
|
expect(wrapper.find('button').text()).toBe('delete_user')
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('confirm delete with success', () => {
|
describe('click on "delete_user" button', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||||
|
spy.mockImplementation(() => Promise.resolve(true))
|
||||||
await wrapper.find('button').trigger('click')
|
await wrapper.find('button').trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('calls the modal', () => {
|
||||||
|
expect(wrapper.emitted('showDeleteModal'))
|
||||||
|
expect(spy).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('confirm delete with success', () => {
|
||||||
it('calls the API', () => {
|
it('calls the API', () => {
|
||||||
expect(apolloMutateMock).toBeCalledWith(
|
expect(apolloMutateMock).toBeCalledWith(
|
||||||
expect.objectContaining({
|
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', () => {
|
describe('confirm delete with error', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
|
||||||
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
||||||
await wrapper.find('button').trigger('click')
|
await wrapper.find('button').trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('toasts an error message', () => {
|
it('toasts an error message', () => {
|
||||||
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
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"', () => {
|
it('shows the text "undelete_user"', () => {
|
||||||
expect(wrapper.text()).toBe('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 () => {
|
beforeEach(async () => {
|
||||||
apolloMutateMock.mockResolvedValue({
|
apolloMutateMock.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
unDeleteUser: null,
|
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', () => {
|
it('calls the modal', () => {
|
||||||
expect(wrapper.find('button').exists()).toBe(true)
|
expect(wrapper.emitted('showUndeleteModal'))
|
||||||
})
|
expect(spy).toHaveBeenCalled()
|
||||||
|
|
||||||
it('has the button text "undelete_user"', () => {
|
|
||||||
expect(wrapper.find('button').text()).toBe('undelete_user')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('confirm recover with success', () => {
|
describe('confirm recover with success', () => {
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.find('button').trigger('click')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('calls the API', () => {
|
it('calls the API', () => {
|
||||||
expect(apolloMutateMock).toBeCalledWith(
|
expect(apolloMutateMock).toBeCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@ -205,7 +191,7 @@ describe('DeletedUserFormular', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('emits update deleted At', () => {
|
it('emits update deleted At', () => {
|
||||||
expect(wrapper.emitted('updateDeletedAt')).toEqual(
|
expect(wrapper.emitted('updateDeletedAt')).toMatchObject(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
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', () => {
|
describe('confirm recover with error', () => {
|
||||||
@ -232,16 +214,6 @@ describe('DeletedUserFormular', () => {
|
|||||||
expect(toastErrorSpy).toBeCalledWith('Oh no!')
|
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') }}
|
{{ $t('removeNotSelf') }}
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="mt-5">
|
<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">
|
<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') }}
|
{{ $t('delete_user') }}
|
||||||
</b-button>
|
</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') }}
|
{{ $t('undelete_user') }}
|
||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
@ -31,12 +32,56 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
checked: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
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() {
|
deleteUser() {
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
@ -50,7 +95,6 @@ export default {
|
|||||||
userId: this.item.userId,
|
userId: this.item.userId,
|
||||||
deletedAt: result.data.deleteUser,
|
deletedAt: result.data.deleteUser,
|
||||||
})
|
})
|
||||||
this.checked = false
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.toastError(error.message)
|
this.toastError(error.message)
|
||||||
@ -69,7 +113,6 @@ export default {
|
|||||||
userId: this.item.userId,
|
userId: this.item.userId,
|
||||||
deletedAt: result.data.unDeleteUser,
|
deletedAt: result.data.unDeleteUser,
|
||||||
})
|
})
|
||||||
this.checked = false
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.toastError(error.message)
|
this.toastError(error.message)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"all_emails": "Alle Nutzer",
|
"all_emails": "Alle Nutzer",
|
||||||
"back": "zurück",
|
"back": "zurück",
|
||||||
|
"change_user_role": "Nutzerrolle ändern",
|
||||||
"chat": "Chat",
|
"chat": "Chat",
|
||||||
"contributionLink": {
|
"contributionLink": {
|
||||||
"amount": "Betrag",
|
"amount": "Betrag",
|
||||||
@ -114,6 +115,11 @@
|
|||||||
"open_creations": "Offene Schöpfungen",
|
"open_creations": "Offene Schöpfungen",
|
||||||
"overlay": {
|
"overlay": {
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
|
"changeUserRole": {
|
||||||
|
"question": "Willst du die Rolle von {username} wirklich zu {newRole} ändern?",
|
||||||
|
"title": "Nutzerrolle ändern",
|
||||||
|
"yes": "Ja, Nutzerrolle ändern"
|
||||||
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"question": "Willst du diesen Gemeinwohl-Beitrag wirklich bestätigen und gutschreiben?",
|
"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.",
|
"text": "Nach dem Speichern ist der Datensatz nicht mehr änderbar. Bitte überprüfe genau, dass alles stimmt.",
|
||||||
@ -126,11 +132,21 @@
|
|||||||
"title": "Gemeinwohl-Beitrag löschen!",
|
"title": "Gemeinwohl-Beitrag löschen!",
|
||||||
"yes": "Ja, 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": {
|
"deny": {
|
||||||
"question": "Willst du diesen Gemeinwohl-Beitrag wirklich ablehnen?",
|
"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.",
|
"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!",
|
"title": "Gemeinwohl-Beitrag ablehnen!",
|
||||||
"yes": "Ja, Beitrag ablehnen und speichern!"
|
"yes": "Ja, Beitrag ablehnen und speichern!"
|
||||||
|
},
|
||||||
|
"undeleteUser": {
|
||||||
|
"question": "Willst du wirklich {username} wiederherstellen?",
|
||||||
|
"title": "Nutzer wiederherstellen",
|
||||||
|
"yes": "Ja, Nutzer wiederherstellen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"redeemed": "eingelöst",
|
"redeemed": "eingelöst",
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"all_emails": "All users",
|
"all_emails": "All users",
|
||||||
"back": "back",
|
"back": "back",
|
||||||
|
"change_user_role": "Change user role",
|
||||||
"chat": "Chat",
|
"chat": "Chat",
|
||||||
"contributionLink": {
|
"contributionLink": {
|
||||||
"amount": "Amount",
|
"amount": "Amount",
|
||||||
@ -114,6 +115,11 @@
|
|||||||
"open_creations": "Open creations",
|
"open_creations": "Open creations",
|
||||||
"overlay": {
|
"overlay": {
|
||||||
"cancel": "Cancel",
|
"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": {
|
"confirm": {
|
||||||
"question": "Do you really want to carry out and finally save this pre-stored creation?",
|
"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.",
|
"text": "After saving, the record can no longer be changed. Please check carefully that everything is correct.",
|
||||||
@ -126,11 +132,21 @@
|
|||||||
"title": "Delete creation!",
|
"title": "Delete creation!",
|
||||||
"yes": "Yes, delete and save creation!"
|
"yes": "Yes, delete and save creation!"
|
||||||
},
|
},
|
||||||
|
"deleteUser": {
|
||||||
|
"question": "Do you really want to delete {username}?",
|
||||||
|
"title": "Delete user",
|
||||||
|
"yes": "Yes, delete user"
|
||||||
|
},
|
||||||
"deny": {
|
"deny": {
|
||||||
"question": "Do you really want to carry out and finally save this pre-stored creation?",
|
"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.",
|
"text": "After saving, the record can no longer be changed or deleted. Please check carefully that everything is correct.",
|
||||||
"title": "Reject creation!",
|
"title": "Reject creation!",
|
||||||
"yes": "Yes, reject and save 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",
|
"redeemed": "redeemed",
|
||||||
|
|||||||
@ -25,7 +25,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
|
|||||||
email: 'benjamin@bluemchen.de',
|
email: 'benjamin@bluemchen.de',
|
||||||
creation: [1000, 1000, 1000],
|
creation: [1000, 1000, 1000],
|
||||||
emailChecked: true,
|
emailChecked: true,
|
||||||
deletedAt: null,
|
deletedAt: new Date(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
userId: 3,
|
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', () => {
|
describe('apollo returns error', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
apolloQueryMock.mockRejectedValue({
|
apolloQueryMock.mockRejectedValue({
|
||||||
|
|||||||
@ -5,7 +5,7 @@ module.exports = {
|
|||||||
node: true,
|
node: true,
|
||||||
},
|
},
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
plugins: ['prettier', '@typescript-eslint', 'type-graphql', 'jest', 'import'],
|
plugins: ['prettier', '@typescript-eslint', 'type-graphql', 'jest', 'import', 'n'],
|
||||||
extends: [
|
extends: [
|
||||||
'standard',
|
'standard',
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
@ -101,6 +101,45 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
'import/prefer-default-export': 'off', // TODO
|
'import/prefer-default-export': 'off', // TODO
|
||||||
|
// 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: [
|
overrides: [
|
||||||
// only for ts files
|
// only for ts files
|
||||||
|
|||||||
@ -22,10 +22,12 @@ module.exports = {
|
|||||||
'@repository/(.*)': '<rootDir>/src/typeorm/repository/$1',
|
'@repository/(.*)': '<rootDir>/src/typeorm/repository/$1',
|
||||||
'@test/(.*)': '<rootDir>/test/$1',
|
'@test/(.*)': '<rootDir>/test/$1',
|
||||||
'@entity/(.*)':
|
'@entity/(.*)':
|
||||||
|
// eslint-disable-next-line n/no-process-env
|
||||||
process.env.NODE_ENV === 'development'
|
process.env.NODE_ENV === 'development'
|
||||||
? '<rootDir>/../database/entity/$1'
|
? '<rootDir>/../database/entity/$1'
|
||||||
: '<rootDir>/../database/build/entity/$1',
|
: '<rootDir>/../database/build/entity/$1',
|
||||||
'@dbTools/(.*)':
|
'@dbTools/(.*)':
|
||||||
|
// eslint-disable-next-line n/no-process-env
|
||||||
process.env.NODE_ENV === 'development'
|
process.env.NODE_ENV === 'development'
|
||||||
? '<rootDir>/../database/src/$1'
|
? '<rootDir>/../database/src/$1'
|
||||||
: '<rootDir>/../database/build/src/$1',
|
: '<rootDir>/../database/build/src/$1',
|
||||||
|
|||||||
@ -65,6 +65,7 @@
|
|||||||
"eslint-import-resolver-typescript": "^3.5.3",
|
"eslint-import-resolver-typescript": "^3.5.3",
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-jest": "^27.2.1",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
|
"eslint-plugin-n": "^15.6.1",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-prettier": "^3.4.0",
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
"eslint-plugin-promise": "^5.1.0",
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
@ -84,5 +85,8 @@
|
|||||||
"ignore": [
|
"ignore": [
|
||||||
"**/*.test.ts"
|
"**/*.test.ts"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env)
|
// ATTENTION: DO NOT PUT ANY SECRETS IN HERE (or the .env)
|
||||||
|
/* eslint-disable n/no-process-env */
|
||||||
|
|
||||||
import { Decimal } from 'decimal.js-light'
|
import { Decimal } from 'decimal.js-light'
|
||||||
import dotenv from 'dotenv'
|
import dotenv from 'dotenv'
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
// config
|
|
||||||
import CONFIG from './config'
|
import CONFIG from './config'
|
||||||
import { startValidateCommunities } from './federation/validateCommunities'
|
import { startValidateCommunities } from './federation/validateCommunities'
|
||||||
import createServer from './server/createServer'
|
import createServer from './server/createServer'
|
||||||
@ -22,5 +20,5 @@ async function main() {
|
|||||||
main().catch((e) => {
|
main().catch((e) => {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error(e)
|
console.error(e)
|
||||||
process.exit(1)
|
throw e
|
||||||
})
|
})
|
||||||
|
|||||||
@ -28,6 +28,7 @@ export const klicktippNewsletterStateMiddleware: MiddlewareFn = async (
|
|||||||
{ root, args, context, info },
|
{ root, args, context, info },
|
||||||
next,
|
next,
|
||||||
) => {
|
) => {
|
||||||
|
// eslint-disable-next-line n/callback-return
|
||||||
const result = await next()
|
const result = await next()
|
||||||
let klickTipp = new KlickTipp({ status: 'Unsubscribed' })
|
let klickTipp = new KlickTipp({ status: 'Unsubscribed' })
|
||||||
if (CONFIG.KLICKTIPP) {
|
if (CONFIG.KLICKTIPP) {
|
||||||
|
|||||||
@ -61,6 +61,7 @@ ${JSON.stringify(requestContext.response.errors, null, 2)}`)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const plugins =
|
const plugins =
|
||||||
|
// eslint-disable-next-line n/no-process-env
|
||||||
process.env.NODE_ENV === 'development' ? [setHeadersPlugin] : [setHeadersPlugin, logPlugin]
|
process.env.NODE_ENV === 'development' ? [setHeadersPlugin] : [setHeadersPlugin, logPlugin]
|
||||||
|
|
||||||
export default plugins
|
export default plugins
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
|
||||||
import { initialize } from '@dbTools/helpers'
|
|
||||||
import { entities } from '@entity/index'
|
import { entities } from '@entity/index'
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
import { createTestClient } from 'apollo-server-testing'
|
||||||
|
|
||||||
@ -40,7 +39,6 @@ export const testEnvironment = async (testLogger: any = logger, testI18n: any =
|
|||||||
const testClient = createTestClient(server.apollo)
|
const testClient = createTestClient(server.apollo)
|
||||||
const mutate = testClient.mutate
|
const mutate = testClient.mutate
|
||||||
const query = testClient.query
|
const query = testClient.query
|
||||||
await initialize()
|
|
||||||
return { mutate, query, con }
|
return { mutate, query, con }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1998,6 +1998,13 @@ buffer@^6.0.3:
|
|||||||
base64-js "^1.3.1"
|
base64-js "^1.3.1"
|
||||||
ieee754 "^1.2.1"
|
ieee754 "^1.2.1"
|
||||||
|
|
||||||
|
builtins@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9"
|
||||||
|
integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==
|
||||||
|
dependencies:
|
||||||
|
semver "^7.0.0"
|
||||||
|
|
||||||
busboy@^0.3.1:
|
busboy@^0.3.1:
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
||||||
@ -2937,6 +2944,14 @@ eslint-plugin-es@^3.0.0:
|
|||||||
eslint-utils "^2.0.0"
|
eslint-utils "^2.0.0"
|
||||||
regexpp "^3.0.0"
|
regexpp "^3.0.0"
|
||||||
|
|
||||||
|
eslint-plugin-es@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz#f0822f0c18a535a97c3e714e89f88586a7641ec9"
|
||||||
|
integrity sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==
|
||||||
|
dependencies:
|
||||||
|
eslint-utils "^2.0.0"
|
||||||
|
regexpp "^3.0.0"
|
||||||
|
|
||||||
eslint-plugin-import@^2.27.5:
|
eslint-plugin-import@^2.27.5:
|
||||||
version "2.27.5"
|
version "2.27.5"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65"
|
||||||
@ -2965,6 +2980,20 @@ eslint-plugin-jest@^27.2.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/utils" "^5.10.0"
|
"@typescript-eslint/utils" "^5.10.0"
|
||||||
|
|
||||||
|
eslint-plugin-n@^15.6.1:
|
||||||
|
version "15.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-15.6.1.tgz#f7e77f24abb92a550115cf11e29695da122c398c"
|
||||||
|
integrity sha512-R9xw9OtCRxxaxaszTQmQAlPgM+RdGjaL1akWuY/Fv9fRAi8Wj4CUKc6iYVG8QNRjRuo8/BqVYIpfqberJUEacA==
|
||||||
|
dependencies:
|
||||||
|
builtins "^5.0.1"
|
||||||
|
eslint-plugin-es "^4.1.0"
|
||||||
|
eslint-utils "^3.0.0"
|
||||||
|
ignore "^5.1.1"
|
||||||
|
is-core-module "^2.11.0"
|
||||||
|
minimatch "^3.1.2"
|
||||||
|
resolve "^1.22.1"
|
||||||
|
semver "^7.3.8"
|
||||||
|
|
||||||
eslint-plugin-node@^11.1.0:
|
eslint-plugin-node@^11.1.0:
|
||||||
version "11.1.0"
|
version "11.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d"
|
||||||
@ -6300,7 +6329,7 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||||
|
|
||||||
semver@^7.3.7:
|
semver@^7.0.0, semver@^7.3.7, semver@^7.3.8:
|
||||||
version "7.3.8"
|
version "7.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
|
||||||
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
||||||
|
|||||||
@ -4,5 +4,3 @@ DB_USER=root
|
|||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
DB_DATABASE=gradido_community
|
DB_DATABASE=gradido_community
|
||||||
MIGRATIONS_TABLE=migrations
|
MIGRATIONS_TABLE=migrations
|
||||||
|
|
||||||
TYPEORM_SEEDING_FACTORIES=src/factories/**/*{.ts,.js}
|
|
||||||
|
|||||||
@ -6,5 +6,3 @@ DB_USER=$DB_USER
|
|||||||
DB_PASSWORD=$DB_PASSWORD
|
DB_PASSWORD=$DB_PASSWORD
|
||||||
DB_DATABASE=gradido_community
|
DB_DATABASE=gradido_community
|
||||||
MIGRATIONS_TABLE=migrations
|
MIGRATIONS_TABLE=migrations
|
||||||
|
|
||||||
TYPEORM_SEEDING_FACTORIES=src/factories/**/*{.ts,.js}
|
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
|
|
||||||
const CONFIG = require('./src/config')
|
|
||||||
|
|
||||||
module.export = {
|
|
||||||
name: 'default',
|
|
||||||
type: 'mysql',
|
|
||||||
host: CONFIG.DB_HOST,
|
|
||||||
port: CONFIG.DB_PORT,
|
|
||||||
username: CONFIG.DB_USER,
|
|
||||||
password: CONFIG.DB_PASSWORD,
|
|
||||||
database: CONFIG.DB_DATABASE,
|
|
||||||
seeds: ['src/seeds/**/*{.ts,.js}'],
|
|
||||||
factories: ['src/factories/**/*{.ts,.js}'],
|
|
||||||
}
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
import CONFIG from './config'
|
|
||||||
import { createPool, PoolConfig } from 'mysql'
|
|
||||||
import { Migration } from 'ts-mysql-migrate'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
const poolConfig: PoolConfig = {
|
|
||||||
host: CONFIG.DB_HOST,
|
|
||||||
port: CONFIG.DB_PORT,
|
|
||||||
user: CONFIG.DB_USER,
|
|
||||||
password: CONFIG.DB_PASSWORD,
|
|
||||||
database: CONFIG.DB_DATABASE,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pool?
|
|
||||||
const pool = createPool(poolConfig)
|
|
||||||
|
|
||||||
// Create & Initialize Migrations
|
|
||||||
const migration = new Migration({
|
|
||||||
conn: pool,
|
|
||||||
tableName: CONFIG.MIGRATIONS_TABLE,
|
|
||||||
silent: true,
|
|
||||||
dir: path.join(__dirname, '..', 'migrations'),
|
|
||||||
})
|
|
||||||
|
|
||||||
const initialize = async (): Promise<void> => {
|
|
||||||
await migration.initialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
const resetDB = async (closePool = false): Promise<void> => {
|
|
||||||
await migration.reset() // use for resetting database
|
|
||||||
if (closePool) pool.end()
|
|
||||||
}
|
|
||||||
|
|
||||||
export { resetDB, pool, migration, initialize }
|
|
||||||
@ -1,18 +1,29 @@
|
|||||||
import 'reflect-metadata'
|
import 'reflect-metadata'
|
||||||
import prepare from './prepare'
|
import { createDatabase } from './prepare'
|
||||||
import connection from './typeorm/connection'
|
import CONFIG from './config'
|
||||||
import { resetDB, pool, migration } from './helpers'
|
|
||||||
|
import { createPool } from 'mysql'
|
||||||
|
import { Migration } from 'ts-mysql-migrate'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
const run = async (command: string) => {
|
const run = async (command: string) => {
|
||||||
// Database actions not supported by our migration library
|
// Database actions not supported by our migration library
|
||||||
await prepare()
|
await createDatabase()
|
||||||
|
|
||||||
// Database connection for TypeORM
|
|
||||||
const con = await connection()
|
|
||||||
if (!con || !con.isConnected) {
|
|
||||||
throw new Error(`Couldn't open connection to database`)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Initialize Migrations
|
||||||
|
const pool = createPool({
|
||||||
|
host: CONFIG.DB_HOST,
|
||||||
|
port: CONFIG.DB_PORT,
|
||||||
|
user: CONFIG.DB_USER,
|
||||||
|
password: CONFIG.DB_PASSWORD,
|
||||||
|
database: CONFIG.DB_DATABASE,
|
||||||
|
})
|
||||||
|
const migration = new Migration({
|
||||||
|
conn: pool,
|
||||||
|
tableName: CONFIG.MIGRATIONS_TABLE,
|
||||||
|
silent: true,
|
||||||
|
dir: path.join(__dirname, '..', 'migrations'),
|
||||||
|
})
|
||||||
await migration.initialize()
|
await migration.initialize()
|
||||||
|
|
||||||
// Execute command
|
// Execute command
|
||||||
@ -25,14 +36,13 @@ const run = async (command: string) => {
|
|||||||
break
|
break
|
||||||
case 'reset':
|
case 'reset':
|
||||||
// TODO protect from production
|
// TODO protect from production
|
||||||
await resetDB() // use for resetting database
|
await migration.reset()
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported command ${command}`)
|
throw new Error(`Unsupported command ${command}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminate connections gracefully
|
// Terminate connections gracefully
|
||||||
await con.close()
|
|
||||||
pool.end()
|
pool.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
import Decimal from 'decimal.js-light'
|
|
||||||
|
|
||||||
export interface TransactionContext {
|
|
||||||
typeId: number
|
|
||||||
userId: number
|
|
||||||
balance: Decimal
|
|
||||||
balanceDate: Date
|
|
||||||
amount: Decimal
|
|
||||||
memo: string
|
|
||||||
creationDate?: Date
|
|
||||||
sendReceiverUserId?: number
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
export interface UserContext {
|
|
||||||
pubKey?: Buffer
|
|
||||||
email?: string
|
|
||||||
firstName?: string
|
|
||||||
lastName?: string
|
|
||||||
deletedAt?: Date
|
|
||||||
password?: BigInt
|
|
||||||
privKey?: Buffer
|
|
||||||
emailHash?: Buffer
|
|
||||||
createdAt?: Date
|
|
||||||
emailChecked?: boolean
|
|
||||||
language?: string
|
|
||||||
publisherId?: number
|
|
||||||
passphrase?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ServerUserContext {
|
|
||||||
username?: string
|
|
||||||
password?: string
|
|
||||||
email?: string
|
|
||||||
role?: string
|
|
||||||
activated?: number
|
|
||||||
lastLogin?: Date
|
|
||||||
created?: Date
|
|
||||||
modified?: Date
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
import Decimal from 'decimal.js-light'
|
|
||||||
|
|
||||||
export interface UserInterface {
|
|
||||||
// from user
|
|
||||||
email?: string
|
|
||||||
firstName?: string
|
|
||||||
lastName?: string
|
|
||||||
password?: BigInt
|
|
||||||
pubKey?: Buffer
|
|
||||||
privKey?: Buffer
|
|
||||||
emailHash?: Buffer
|
|
||||||
createdAt?: Date
|
|
||||||
emailChecked?: boolean
|
|
||||||
language?: string
|
|
||||||
deletedAt?: Date
|
|
||||||
publisherId?: number
|
|
||||||
passphrase?: string
|
|
||||||
// from server user
|
|
||||||
serverUserPassword?: string
|
|
||||||
role?: string
|
|
||||||
activated?: number
|
|
||||||
lastLogin?: Date
|
|
||||||
modified?: Date
|
|
||||||
// flag for admin
|
|
||||||
isAdmin?: boolean
|
|
||||||
// flag for balance (creation of 1000 GDD)
|
|
||||||
addBalance?: boolean
|
|
||||||
// balance
|
|
||||||
recordDate?: Date
|
|
||||||
creationDate?: Date
|
|
||||||
amount?: Decimal
|
|
||||||
}
|
|
||||||
@ -1,15 +1,8 @@
|
|||||||
/* PREPARE SCRIPT
|
import { createConnection } from 'mysql2/promise'
|
||||||
*
|
|
||||||
* This file ensures operations our migration library
|
|
||||||
* can not take care of are done.
|
|
||||||
* This applies to all Database Operations like
|
|
||||||
* creating, deleting, renaming Databases.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { createConnection, RowDataPacket } from 'mysql2/promise'
|
|
||||||
import CONFIG from './config'
|
import CONFIG from './config'
|
||||||
|
|
||||||
export default async (): Promise<void> => {
|
export const createDatabase = async (): Promise<void> => {
|
||||||
const con = await createConnection({
|
const con = await createConnection({
|
||||||
host: CONFIG.DB_HOST,
|
host: CONFIG.DB_HOST,
|
||||||
port: CONFIG.DB_PORT,
|
port: CONFIG.DB_PORT,
|
||||||
@ -25,6 +18,8 @@ export default async (): Promise<void> => {
|
|||||||
DEFAULT CHARACTER SET utf8mb4
|
DEFAULT CHARACTER SET utf8mb4
|
||||||
DEFAULT COLLATE utf8mb4_unicode_ci;`)
|
DEFAULT COLLATE utf8mb4_unicode_ci;`)
|
||||||
|
|
||||||
|
/* LEGACY CODE
|
||||||
|
import { RowDataPacket } from 'mysql2/promise'
|
||||||
// Check if old migration table is present, delete if needed
|
// Check if old migration table is present, delete if needed
|
||||||
const [rows] = await con.query(`SHOW TABLES FROM \`${CONFIG.DB_DATABASE}\` LIKE 'migrations';`)
|
const [rows] = await con.query(`SHOW TABLES FROM \`${CONFIG.DB_DATABASE}\` LIKE 'migrations';`)
|
||||||
if ((<RowDataPacket>rows).length > 0) {
|
if ((<RowDataPacket>rows).length > 0) {
|
||||||
@ -37,6 +32,7 @@ export default async (): Promise<void> => {
|
|||||||
console.log('Found and dropped old migrations table')
|
console.log('Found and dropped old migrations table')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
await con.end()
|
await con.end()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
import { createConnection, Connection } from 'typeorm'
|
|
||||||
import CONFIG from '../config'
|
|
||||||
import { entities } from '../../entity/index'
|
|
||||||
|
|
||||||
const connection = async (): Promise<Connection | null> => {
|
|
||||||
let con = null
|
|
||||||
try {
|
|
||||||
con = await createConnection({
|
|
||||||
name: 'default',
|
|
||||||
type: 'mysql',
|
|
||||||
host: CONFIG.DB_HOST,
|
|
||||||
port: CONFIG.DB_PORT,
|
|
||||||
username: CONFIG.DB_USER,
|
|
||||||
password: CONFIG.DB_PASSWORD,
|
|
||||||
database: CONFIG.DB_DATABASE,
|
|
||||||
entities,
|
|
||||||
synchronize: false,
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
return con
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connection
|
|
||||||
@ -118,6 +118,18 @@ case "$NGINX_SSL" in
|
|||||||
esac
|
esac
|
||||||
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $NGINX_CONFIG_DIR/$TEMPLATE_FILE > $NGINX_CONFIG_DIR/update-page.conf
|
envsubst "$(env | sed -e 's/=.*//' -e 's/^/\$/g')" < $NGINX_CONFIG_DIR/$TEMPLATE_FILE > $NGINX_CONFIG_DIR/update-page.conf
|
||||||
|
|
||||||
|
# Clean tmp folder - remove yarn files
|
||||||
|
find /tmp -name "yarn--*" -exec rm -r {} \;
|
||||||
|
|
||||||
|
# Remove node_modules folders
|
||||||
|
# we had problems with corrupted node_modules folder
|
||||||
|
rm -Rf $PROJECT_ROOT/database/node_modules
|
||||||
|
rm -Rf $PROJECT_ROOT/backend/node_modules
|
||||||
|
rm -Rf $PROJECT_ROOT/frontend/node_modules
|
||||||
|
rm -Rf $PROJECT_ROOT/admin/node_modules
|
||||||
|
rm -Rf $PROJECT_ROOT/dht-node/node_modules
|
||||||
|
rm -Rf $PROJECT_ROOT/federation/node_modules
|
||||||
|
|
||||||
# Regenerate .env files
|
# Regenerate .env files
|
||||||
cp -f $PROJECT_ROOT/database/.env $PROJECT_ROOT/database/.env.bak
|
cp -f $PROJECT_ROOT/database/.env $PROJECT_ROOT/database/.env.bak
|
||||||
cp -f $PROJECT_ROOT/backend/.env $PROJECT_ROOT/backend/.env.bak
|
cp -f $PROJECT_ROOT/backend/.env $PROJECT_ROOT/backend/.env.bak
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
import CONFIG from '@/config'
|
import CONFIG from '@/config'
|
||||||
import connection from '@/typeorm/connection'
|
import connection from '@/typeorm/connection'
|
||||||
import { checkDBVersion } from '@/typeorm/DBVersion'
|
import { checkDBVersion } from '@/typeorm/DBVersion'
|
||||||
import { initialize } from '@dbTools/helpers'
|
|
||||||
import { entities } from '@entity/index'
|
import { entities } from '@entity/index'
|
||||||
import { logger } from './testSetup'
|
import { logger } from './testSetup'
|
||||||
|
|
||||||
@ -42,7 +41,6 @@ export const testEnvironment = async () => {
|
|||||||
logger.fatal('Fatal: Database Version incorrect')
|
logger.fatal('Fatal: Database Version incorrect')
|
||||||
throw new Error('Fatal: Database Version incorrect')
|
throw new Error('Fatal: Database Version incorrect')
|
||||||
}
|
}
|
||||||
await initialize()
|
|
||||||
return { con }
|
return { con }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,12 +6,15 @@ const localVue = global.localVue
|
|||||||
const propsData = {
|
const propsData = {
|
||||||
link: '',
|
link: '',
|
||||||
}
|
}
|
||||||
|
const mocks = {
|
||||||
|
$t: jest.fn((t) => t),
|
||||||
|
}
|
||||||
|
|
||||||
describe('FigureQrCode', () => {
|
describe('FigureQrCode', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
|
|
||||||
const Wrapper = () => {
|
const Wrapper = () => {
|
||||||
return mount(FigureQrCode, { localVue, propsData })
|
return mount(FigureQrCode, { localVue, mocks, propsData })
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('mount', () => {
|
describe('mount', () => {
|
||||||
@ -19,12 +22,55 @@ describe('FigureQrCode', () => {
|
|||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders the Div Element ".figure-qr-code"', () => {
|
afterEach(() => {
|
||||||
expect(wrapper.find('div.figure-qr-code').exists()).toBeTruthy()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders the Div Element "q-r-canvas"', () => {
|
it('has options filled', () => {
|
||||||
expect(wrapper.find('q-r-canvas'))
|
expect(wrapper.vm.options).toEqual({
|
||||||
|
cellSize: 8,
|
||||||
|
correctLevel: 'H',
|
||||||
|
data: '',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders the Div Element ".figure-qr-code"', () => {
|
||||||
|
expect(wrapper.find('div.figure-qr-code').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders the Div Element "qrbox"', () => {
|
||||||
|
expect(wrapper.find('div.qrbox').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders the Canvas Element "#qrcanvas"', () => {
|
||||||
|
const canvas = wrapper.find('#qrcanvas')
|
||||||
|
|
||||||
|
expect(canvas.exists()).toBe(true)
|
||||||
|
const canvasEl = canvas.element
|
||||||
|
const canvasWidth = canvasEl.width
|
||||||
|
const canvasHeight = canvasEl.height
|
||||||
|
|
||||||
|
expect(canvasWidth).toBeGreaterThan(0)
|
||||||
|
expect(canvasHeight).toBeGreaterThan(0)
|
||||||
|
|
||||||
|
const canvasContext = canvasEl.toDataURL('image/png')
|
||||||
|
expect(canvasContext).not.toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders the A Element "#download"', () => {
|
||||||
|
const downloadLink = wrapper.find('#download')
|
||||||
|
expect(downloadLink.exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Download QR-Code link', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const downloadLink = wrapper.find('#download')
|
||||||
|
downloadLink.trigger('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('click the A Element "#download" set an href', () => {
|
||||||
|
expect(wrapper.find('#download').attributes('href')).toEqual('data:image/png;base64,00')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,7 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="figure-qr-code">
|
<div class="figure-qr-code">
|
||||||
<div class="qrbox">
|
<div class="qrbox">
|
||||||
<q-r-canvas :options="options" class="canvas" />
|
<div>
|
||||||
|
<q-r-canvas :options="options" class="canvas mb-3" id="qrcanvas" ref="canvas" />
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
id="download"
|
||||||
|
ref="download"
|
||||||
|
download="GradidoLinkQRCode.png"
|
||||||
|
href=""
|
||||||
|
@click="downloadImg(this)"
|
||||||
|
>
|
||||||
|
{{ $t('download') }}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -37,6 +48,13 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
downloadImg() {
|
||||||
|
const canvas = this.$refs.canvas.$el
|
||||||
|
const image = canvas.toDataURL('image/png')
|
||||||
|
this.$refs.download.href = image
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@ -100,6 +100,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"delete": "Löschen",
|
"delete": "Löschen",
|
||||||
|
"download": "Herunterladen",
|
||||||
"edit": "bearbeiten",
|
"edit": "bearbeiten",
|
||||||
"em-dash": "—",
|
"em-dash": "—",
|
||||||
"error": {
|
"error": {
|
||||||
|
|||||||
@ -100,6 +100,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
|
"download": "Download",
|
||||||
"edit": "edit",
|
"edit": "edit",
|
||||||
"em-dash": "—",
|
"em-dash": "—",
|
||||||
"error": {
|
"error": {
|
||||||
|
|||||||
@ -88,6 +88,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"delete": "Supprimer",
|
"delete": "Supprimer",
|
||||||
|
"download": "Télécharger",
|
||||||
"edit": "modifier",
|
"edit": "modifier",
|
||||||
"em-dash": "—",
|
"em-dash": "—",
|
||||||
"error": {
|
"error": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user