Merge branch 'master' into 1265-Mouse-Hovering-Over-Pencil-in-Settings

This commit is contained in:
elweyn 2022-01-13 09:40:00 +01:00
commit 2848504fe1
42 changed files with 258 additions and 149 deletions

View File

@ -470,7 +470,7 @@ jobs:
report_name: Coverage Admin Interface
type: lcov
result_path: ./coverage/lcov.info
min_coverage: 76
min_coverage: 77
token: ${{ github.token }}
##############################################################################

View File

@ -1,3 +1,4 @@
GRAPHQL_URI=http://localhost:4000/graphql
WALLET_AUTH_URL=http://localhost/vue/authenticate?token=$1
WALLET_URL=http://localhost/vue/login
DEBUG_DISABLE_AUTH=false

View File

@ -8,7 +8,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
transactionList: {
transactions: [
{
type: 'created',
type: 'creation',
balance: 100,
decayStart: 0,
decayEnd: 0,
@ -27,7 +27,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
},
},
{
type: 'created',
type: 'creation',
balance: 200,
decayStart: 0,
decayEnd: 0,
@ -58,9 +58,7 @@ const mocks = {
query: apolloQueryMock,
},
$toasted: {
global: {
error: toastedErrorMock,
},
error: toastedErrorMock,
},
}

View File

@ -30,10 +30,10 @@ export default {
},
})
.then((result) => {
this.items = result.data.transactionList.transactions
this.items = result.data.transactionList.transactions.filter((t) => t.type === 'creation')
})
.catch((error) => {
this.$toasted.global.error(error.message)
this.$toasted.error(error.message)
})
},
},

View File

@ -53,13 +53,17 @@ describe('NavBar', () => {
})
describe('logout', () => {
// const assignLocationSpy = jest.fn()
const windowLocationMock = jest.fn()
beforeEach(async () => {
delete window.location
window.location = {
assign: windowLocationMock,
}
await wrapper.findAll('a').at(6).trigger('click')
})
it('redirects to /logout', () => {
expect(routerPushMock).toBeCalledWith('/logout')
expect(windowLocationMock).toBeCalledWith('http://localhost/vue/login')
})
it('dispatches logout to store', () => {

View File

@ -33,8 +33,9 @@ export default {
name: 'navbar',
methods: {
logout() {
window.location.assign(CONFIG.WALLET_URL)
// window.location = CONFIG.WALLET_URL
this.$store.dispatch('logout')
this.$router.push('/logout')
},
wallet() {
window.location = CONFIG.WALLET_AUTH_URL.replace('$1', this.$store.state.token)

View File

@ -3,6 +3,9 @@ import UserTable from './UserTable.vue'
const localVue = global.localVue
const apolloQueryMock = jest.fn()
apolloQueryMock.mockResolvedValue()
describe('UserTable', () => {
let wrapper
@ -114,6 +117,12 @@ describe('UserTable', () => {
}),
}
}),
$apollo: {
query: apolloQueryMock,
},
$store: {
commit: jest.fn(),
},
}
const Wrapper = (propsData) => {

View File

@ -20,6 +20,7 @@ const environment = {
const endpoints = {
GRAPHQL_URI: process.env.GRAPHQL_URI || 'http://localhost:4000/graphql',
WALLET_AUTH_URL: process.env.WALLET_AUTH_URL || 'http://localhost/vue/authenticate?token=$1',
WALLET_URL: process.env.WALLET_URL || 'http://localhost/vue/login',
}
const debug = {

View File

@ -7,6 +7,7 @@ export const verifyLogin = gql`
lastName
isAdmin
id
language
}
}
`

View File

@ -2,7 +2,7 @@
"bookmark": "bookmark",
"confirmed": "bestätigt",
"creation_form": {
"creation_for": "Schöpfung für ",
"creation_for": "Schöpfung für",
"enter_text": "Text eintragen",
"form": "Schöpfungsformular",
"min_characters": "Mindestens 10 Zeichen eingeben",

View File

@ -2,7 +2,7 @@
"bookmark": "Remember",
"confirmed": "confirmed",
"creation_form": {
"creation_for": "Creation for ",
"creation_for": "Creation for",
"enter_text": "Enter text",
"form": "Creation form",
"min_characters": "Enter at least 10 characters",

View File

@ -42,7 +42,7 @@ Vue.use(Toasted, {
},
})
addNavigationGuards(router, store, apolloProvider.defaultClient)
addNavigationGuards(router, store, apolloProvider.defaultClient, i18n)
new Vue({
moment,

View File

@ -8,14 +8,14 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
data: {
searchUsers: [
{
id: 1,
userId: 1,
firstName: 'Bibi',
lastName: 'Bloxberg',
email: 'bibi@bloxberg.de',
creation: [200, 400, 600],
},
{
id: 2,
userId: 2,
firstName: 'Benjamin',
lastName: 'Blümchen',
email: 'benjamin@bluemchen.de',
@ -71,7 +71,7 @@ describe('Creation', () => {
it('sets the data of itemsList', () => {
expect(wrapper.vm.itemsList).toEqual([
{
id: 1,
userId: 1,
firstName: 'Bibi',
lastName: 'Bloxberg',
email: 'bibi@bloxberg.de',
@ -79,7 +79,7 @@ describe('Creation', () => {
showDetails: false,
},
{
id: 2,
userId: 2,
firstName: 'Benjamin',
lastName: 'Blümchen',
email: 'benjamin@bluemchen.de',
@ -100,7 +100,7 @@ describe('Creation', () => {
wrapper.findComponent({ name: 'UserTable' }).vm.$emit(
'update-item',
{
id: 2,
userId: 2,
firstName: 'Benjamin',
lastName: 'Blümchen',
email: 'benjamin@bluemchen.de',
@ -114,7 +114,7 @@ describe('Creation', () => {
it('removes the pushed item from itemsList', () => {
expect(wrapper.vm.itemsList).toEqual([
{
id: 1,
userId: 1,
firstName: 'Bibi',
lastName: 'Bloxberg',
email: 'bibi@bloxberg.de',
@ -127,7 +127,7 @@ describe('Creation', () => {
it('adds the pushed item to itemsMassCreation', () => {
expect(wrapper.vm.itemsMassCreation).toEqual([
{
id: 2,
userId: 2,
firstName: 'Benjamin',
lastName: 'Blümchen',
email: 'benjamin@bluemchen.de',
@ -142,7 +142,7 @@ describe('Creation', () => {
wrapper.findComponent({ name: 'UserTable' }).vm.$emit(
'update-item',
{
id: 2,
userId: 2,
firstName: 'Benjamin',
lastName: 'Blümchen',
email: 'benjamin@bluemchen.de',
@ -160,7 +160,7 @@ describe('Creation', () => {
it('adds the item to itemsList', () => {
expect(wrapper.vm.itemsList).toEqual([
{
id: 1,
userId: 1,
firstName: 'Bibi',
lastName: 'Bloxberg',
email: 'bibi@bloxberg.de',
@ -168,7 +168,7 @@ describe('Creation', () => {
showDetails: false,
},
{
id: 2,
userId: 2,
firstName: 'Benjamin',
lastName: 'Blümchen',
email: 'benjamin@bluemchen.de',
@ -206,7 +206,7 @@ describe('Creation', () => {
await wrapper.findComponent({ name: 'UserTable' }).vm.$emit(
'update-item',
{
id: 2,
userId: 2,
firstName: 'Benjamin',
lastName: 'Blümchen',
email: 'benjamin@bluemchen.de',

View File

@ -133,16 +133,16 @@ export default {
switch (event) {
case 'push':
findArr = this.itemsList.find((arr) => arr.id === e.id)
findArr = this.itemsList.find((item) => e.userId === item.userId)
index = this.itemsList.indexOf(findArr)
this.itemsList.splice(index, 1)
this.itemsMassCreation.push(e)
this.itemsMassCreation.push(findArr)
break
case 'remove':
findArr = this.itemsMassCreation.find((arr) => arr.id === e.id)
findArr = this.itemsMassCreation.find((item) => e.userId === item.userId)
index = this.itemsMassCreation.indexOf(findArr)
this.itemsMassCreation.splice(index, 1)
this.itemsList.push(e)
this.itemsList.push(findArr)
break
default:
throw new Error(event)

View File

@ -42,15 +42,13 @@ export default {
{ key: 'lastName', label: this.$t('lastname') },
{
key: 'creation',
// label: this.$t('open_creation') + 'Jan | Feb | März',
label:
this.$moment().subtract(2, 'month').format('MMM') +
' | ' +
this.$moment().subtract(1, 'month').format('MMM') +
' | ' +
label: [
this.$moment().subtract(2, 'month').format('MMM'),
this.$moment().subtract(1, 'month').format('MMM'),
this.$moment().format('MMM'),
].join(' | '),
formatter: (value, key, item) => {
return String(value[0]) + ` | ` + String(value[1]) + ` | ` + String(value[2])
return value.join(' | ')
},
},
{ key: 'show_details', label: this.$t('details') },

View File

@ -1,7 +1,7 @@
import { verifyLogin } from '../graphql/verifyLogin'
import CONFIG from '../config'
const addNavigationGuards = (router, store, apollo) => {
const addNavigationGuards = (router, store, apollo, i18n) => {
// store token on `authenticate`
router.beforeEach(async (to, from, next) => {
if (to.path === '/authenticate' && to.query && to.query.token) {
@ -14,6 +14,7 @@ const addNavigationGuards = (router, store, apollo) => {
.then((result) => {
const moderator = result.data.verifyLogin
if (moderator.isAdmin) {
i18n.locale = moderator.language
store.commit('moderator', moderator)
next({ path: '/' })
} else {

View File

@ -6,9 +6,11 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
data: {
verifyLogin: {
isAdmin: true,
language: 'de',
},
},
})
const i18nLocaleMock = jest.fn()
const store = {
commit: storeCommitMock,
@ -21,7 +23,11 @@ const apollo = {
query: apolloQueryMock,
}
addNavigationGuards(router, store, apollo)
const i18n = {
locale: i18nLocaleMock,
}
addNavigationGuards(router, store, apollo, i18n)
describe('navigation guards', () => {
beforeEach(() => {
@ -33,19 +39,23 @@ describe('navigation guards', () => {
const next = jest.fn()
describe('with valid token and as admin', () => {
beforeEach(() => {
navGuard({ path: '/authenticate', query: { token: 'valid-token' } }, {}, next)
beforeEach(async () => {
await navGuard({ path: '/authenticate', query: { token: 'valid-token' } }, {}, next)
})
it('commits the token to the store', async () => {
it('commits the token to the store', () => {
expect(storeCommitMock).toBeCalledWith('token', 'valid-token')
})
it('commits the moderator to the store', () => {
expect(storeCommitMock).toBeCalledWith('moderator', { isAdmin: true })
it.skip('sets the locale', () => {
expect(i18nLocaleMock).toBeCalledWith('de')
})
it('redirects to /', async () => {
it('commits the moderator to the store', () => {
expect(storeCommitMock).toBeCalledWith('moderator', { isAdmin: true, language: 'de' })
})
it('redirects to /', () => {
expect(next).toBeCalledWith({ path: '/' })
})
})

View File

@ -1,3 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { Resolver, Query, Arg, Args, Authorized, Mutation, Ctx } from 'type-graphql'
import { getCustomRepository, Raw } from 'typeorm'
import { UserAdmin } from '../model/UserAdmin'
@ -62,9 +65,9 @@ export class AdminResolver {
loginPendingTaskAdmin.memo = memo
loginPendingTaskAdmin.moderator = moderator
loginPendingTasksAdminRepository.save(loginPendingTaskAdmin)
await loginPendingTasksAdminRepository.save(loginPendingTaskAdmin)
}
return await getUserCreations(user.id)
return getUserCreations(user.id)
}
@Authorized([RIGHTS.CREATE_PENDING_CREATION])

View File

@ -503,7 +503,7 @@ export class TransactionResolver {
email: userEntity.email,
})
if (!resultGDTSum.success) throw new Error(resultGDTSum.data)
transactions.gdtSum = resultGDTSum.data.sum || 0
transactions.gdtSum = Number(resultGDTSum.data.sum / 100) || 0
// get balance
const balanceRepository = getCustomRepository(BalanceRepository)

View File

@ -738,7 +738,7 @@ export class UserResolver {
if (password && passwordNew) {
// TODO: This had some error cases defined - like missing private key. This is no longer checked.
const oldPasswordHash = SecretKeyCryptographyCreateKey(loginUser.email, password)
if (loginUser.password !== oldPasswordHash[0].readBigUInt64LE()) {
if (BigInt(loginUser.password.toString()) !== oldPasswordHash[0].readBigUInt64LE()) {
throw new Error(`Old password is invalid`)
}
@ -748,7 +748,7 @@ export class UserResolver {
const encryptedPrivkey = SecretKeyCryptographyEncrypt(privKey, newPasswordHash[1])
// Save new password hash and newly encrypted private key
loginUser.password = newPasswordHash[0].readBigInt64LE()
loginUser.password = newPasswordHash[0].readBigUInt64LE()
loginUser.privKey = encryptedPrivkey
}

View File

@ -8,7 +8,11 @@ const plugins = [
willSendResponse(requestContext: any) {
const { setHeaders = [] } = requestContext.context
setHeaders.forEach(({ key, value }: { [key: string]: string }) => {
requestContext.response.http.headers.append(key, value)
if (requestContext.response.http.headers.get(key)) {
requestContext.response.http.headers.set(key, value)
} else {
requestContext.response.http.headers.append(key, value)
}
})
return requestContext
},

View File

@ -1,6 +1,7 @@
import { EntityRepository, Repository } from 'typeorm'
import { Order } from '../../graphql/enum/Order'
import { UserTransaction } from '@entity/UserTransaction'
import { TransactionTypeId } from '../../graphql/enum/TransactionTypeId'
@EntityRepository(UserTransaction)
export class UserTransactionRepository extends Repository<UserTransaction> {
@ -14,7 +15,9 @@ export class UserTransactionRepository extends Repository<UserTransaction> {
if (onlyCreation) {
return this.createQueryBuilder('userTransaction')
.where('userTransaction.userId = :userId', { userId })
.andWhere('userTransaction.type = "creation"')
.andWhere('userTransaction.transactionTypeId = :transactionTypeId', {
transactionTypeId: TransactionTypeId.CREATION,
})
.orderBy('userTransaction.balanceDate', order)
.limit(limit)
.offset(offset)

View File

@ -19,7 +19,7 @@ define(LoginUser, (faker: typeof Faker, context?: LoginUserContext) => {
user.privKey = context.privKey ? context.privKey : randomBytes(80)
user.emailHash = context.emailHash ? context.emailHash : randomBytes(32)
user.createdAt = context.createdAt ? context.createdAt : faker.date.recent()
user.emailChecked = context.emailChecked ? context.emailChecked : true
user.emailChecked = context.emailChecked === undefined ? false : context.emailChecked
user.passphraseShown = context.passphraseShown ? context.passphraseShown : false
user.language = context.language ? context.language : 'en'
user.disabled = context.disabled ? context.disabled : false

View File

@ -6,6 +6,7 @@ import { CreatePeterLustigSeed } from './seeds/users/peter-lustig.admin.seed'
import { CreateBibiBloxbergSeed } from './seeds/users/bibi-bloxberg.seed'
import { CreateRaeuberHotzenplotzSeed } from './seeds/users/raeuber-hotzenplotz.seed'
import { CreateBobBaumeisterSeed } from './seeds/users/bob-baumeister.seed'
import { CreateGarrickOllivanderSeed } from './seeds/users/garrick-ollivander.seed'
import { DecayStartBlockSeed } from './seeds/decay-start-block.seed'
import { resetDB, pool, migration } from './helpers'
@ -44,6 +45,7 @@ const run = async (command: string) => {
await runSeeder(CreateBibiBloxbergSeed)
await runSeeder(CreateRaeuberHotzenplotzSeed)
await runSeeder(CreateBobBaumeisterSeed)
await runSeeder(CreateGarrickOllivanderSeed)
break
default:
throw new Error(`Unsupported command ${command}`)

View File

@ -23,7 +23,7 @@ export interface LoginUserContext {
language?: string
disabled?: boolean
groupId?: number
publisherId?: number | null
publisherId?: number
}
export interface LoginUserBackupContext {

View File

@ -15,7 +15,7 @@ export interface UserInterface {
language?: string
disabled?: boolean
groupId?: number
publisherId?: number | null
publisherId?: number
// from login user backup
passphrase?: string
mnemonicType?: number

View File

@ -17,7 +17,6 @@ export const bibiBloxberg = {
language: 'de',
disabled: false,
groupId: 1,
publisherId: null,
passphrase:
'knife normal level all hurdle crucial color avoid warrior stadium road bachelor affair topple hawk pottery right afford immune two ceiling budget glance hour ',
mnemonicType: 2,

View File

@ -17,7 +17,6 @@ export const bobBaumeister = {
language: 'de',
disabled: false,
groupId: 1,
publisherId: null,
passphrase:
'detail master source effort unable waste tilt flush domain orchard art truck hint barrel response gate impose peanut secret merry three uncle wink resource ',
mnemonicType: 2,

View File

@ -0,0 +1,9 @@
import { Factory, Seeder } from 'typeorm-seeding'
import { garrickOllivander } from './garrick-ollivander'
import { userSeeder } from '../helpers/user-helpers'
export class CreateGarrickOllivanderSeed implements Seeder {
public async run(factory: Factory): Promise<void> {
await userSeeder(factory, garrickOllivander)
}
}

View File

@ -0,0 +1,21 @@
export const garrickOllivander = {
email: 'garrick@ollivander.com',
firstName: 'Garrick',
lastName: 'Ollivander',
username: 'garrick',
description: `Curious ... curious ...
Renowned wandmaker Mr Ollivander owns the wand shop Ollivanders: Makers of Fine Wands Since 382 BC in Diagon Alley. His shop is widely considered the best place to purchase a wand.`,
password: BigInt('0'),
emailHash: Buffer.from('91e358000e908146342789979d62a7255b2b88a71dad0c6a10e32af44be57886', 'hex'),
createdAt: new Date('2022-01-10T10:23:17'),
emailChecked: false,
passphraseShown: false,
language: 'en',
disabled: false,
groupId: 1,
passphrase:
'human glide theory clump wish history other duty door fringe neck industry ostrich equal plate diesel tornado neck people antenna door category moon hen ',
mnemonicType: 2,
isAdmin: false,
addBalance: false,
}

View File

@ -17,7 +17,6 @@ export const peterLustig = {
language: 'de',
disabled: false,
groupId: 1,
publisherId: null,
passphrase:
'okay property choice naive calm present weird increase stuff royal vibrant frame attend wood one else tribe pull hedgehog woman kitchen hawk snack smart ',
mnemonicType: 2,

View File

@ -17,7 +17,6 @@ export const raeuberHotzenplotz = {
language: 'de',
disabled: false,
groupId: 1,
publisherId: null,
passphrase:
'gospel trip tenant mouse spider skill auto curious man video chief response same little over expire drum display fancy clinic keen throw urge basket ',
mnemonicType: 2,

View File

@ -0,0 +1,25 @@
# Onboarding process
## Meeting with Bernd (zoom)
## Meeting with Claus-Peter and perhaps concerning team member (zoom)
## Presentation to all team members (discord)
## Grant access to
- Nextcloud server
- Add to github repository (create github account if not available)
## Start working
- install docker desktop
- install git: https://git-scm.com/book/de/v2/Erste-Schritte-Git-installieren
- add new ssh key: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account
- download gradido repository: git clone git@github.com:gradido/gradido.git --recursive
- install visual studio code
- docker-compose build
- docker-compose up
http://localhost/vue should be same as https://gdd1.gradido.com/vue
## git basics to update this document
- git status
- git branch onboarding_process
- git checkout onboarding_process
- git add onboarding_process.md
- git commit
- git push
- git push --set-upstream origin onboarding_process

View File

@ -26,7 +26,7 @@
"days": "Tage",
"decay": "Vergänglichkeit",
"decayStart": " - Startblock für Vergänglichkeit am: ",
"decay_introduced": "Die Vergänglichkeit wurde Eingeführt am ",
"decay_introduced": "Die Vergänglichkeit wurde eingeführt am ",
"decay_since_last_transaction": "Vergänglichkeit seit der letzten Transaktion",
"hours": "Stunden",
"last_transaction": "Letzte Transaktion",
@ -47,8 +47,8 @@
"change-password": "Fehler beim Ändern des Passworts",
"empty-transactionlist": "Es gab einen Fehler mit der Übermittlung der Anzahl deiner Transaktionen.",
"error": "Fehler",
"no-account": "Leider konnten wir keinen Account finden mit diesen Daten!",
"no-email-verify": "Die Email wurde noch nicht bestätigt, bitte überprüfe deine Emails und klicke auf den Aktivierungslink!",
"no-account": "Leider konnten wir keinen Account mit diesen Daten finden.",
"no-email-verify": "Dein Konto wurde noch nicht bestätigt. Bitte überprüfe deine E-Mails und klicke auf den Aktivierungslink!",
"no-transactionlist": "Es gab leider einen Fehler. Es wurden keine Transaktionen vom Server übermittelt",
"session-expired": "Die Sitzung wurde aus Sicherheitsgründen beendet."
},
@ -56,29 +56,29 @@
"amount": "Betrag",
"at": "am",
"cancel": "Abbrechen",
"close": "schließen",
"current_balance": "aktueller Kontostand",
"close": "Schließen",
"current_balance": "Aktueller Kontostand",
"date": "Datum",
"description": "Beschreibung",
"edit": "bearbeiten",
"edit": "Bearbeiten",
"email": "E-Mail",
"firstname": "Vorname",
"from": "von",
"from": "Von",
"lastname": "Nachname",
"memo": "Nachricht",
"message": "Nachricht",
"new_balance": "neuer Kontostand nach Bestätigung",
"new_balance": "Neuer Kontostand nach Bestätigung",
"password": "Passwort",
"passwordRepeat": "Passwort wiederholen",
"password_new": "neues Passwort",
"password_new_repeat": "neues Passwort wiederholen",
"password_old": "altes Passwort",
"password_new": "Neues Passwort",
"password_new_repeat": "Neues Passwort wiederholen",
"password_old": "Altes Passwort",
"recipient": "Empfänger",
"reset": "Zurücksetzen",
"save": "speichern",
"save": "Speichern",
"scann_code": "<strong>QR Code Scanner</strong> - Scanne den QR Code deines Partners",
"sender": "Absender",
"send_check": "Bestätige deine Zahlung. Prüfe bitte nochmal alle Daten!",
"send_check": "Bestätige deine Transaktion. Prüfe bitte nochmal alle Angaben!",
"send_now": "Jetzt senden",
"send_transaction_error": "Leider konnte die Transaktion nicht ausgeführt werden!",
"send_transaction_success": "Deine Transaktion wurde erfolgreich ausgeführt",
@ -90,39 +90,39 @@
"validation": {
"gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein",
"is-not": "Du kannst dir selbst keine Gradidos überweisen",
"usernmae-regex": "Der Username muss mit einem Buchstaben beginnen auf den mindestens zwei alfanumerische Zeichen folgen müssen.",
"usernmae-regex": "Der Username muss mit einem Buchstaben beginnen, auf den mindestens zwei alpha-numerische Zeichen folgen müssen.",
"usernmae-unique": "Der Username ist bereits vergeben."
},
"your_amount": "Dein Betrag"
},
"gdt": {
"action": "Aktion",
"calculation": "Berechnung der Gradido Transform",
"calculation": "Berechnung der GradidoTransform",
"contribution": "Beitrag",
"conversion": "Umrechnung",
"conversion-gdt-euro": "Umrechnung Euro / Gradido Transform (GDT)",
"conversion-gdt-euro": "Umrechnung Euro / GradidoTransform (GDT)",
"credit": "Gutschrift",
"factor": "Faktor",
"formula": "Berechnungsformel",
"funding": "Zu den Förderbeiträgen",
"gdt-received": "Gradido Transform (GDT) erhalten",
"no-transactions": "Du hast noch keine Gradido Transform (GDT).",
"gdt-received": "GradidoTransform (GDT) erhalten",
"no-transactions": "Du hast noch keine GradidoTransform (GDT).",
"publisher": "Dein geworbenes Mitglied hat einen Beitrag bezahlt",
"raise": "Erhöhung",
"recruited-member": "Geworbenes Mitglied"
"recruited-member": "Eingeladenes Mitglied"
},
"imprint": "Impressum",
"language": "Sprache",
"login": "Anmeldung",
"logout": "Abmelden",
"members_area": "Mitgliederbereich",
"message": "hallo gradido !!",
"message": "hallo gradido!!",
"overview": "Übersicht",
"privacy_policy": "Datenschutzerklärung",
"publisher": {
"infoNoRegister": "Dies ist für die Registrieung nicht nötig!",
"infoText": "Trage hier die ID des Herausgebers ein. Wenn du keine ID hast dann bitte leer lassen.",
"publisherId": "PublisherID"
"infoNoRegister": "Dies ist für die Registrieung nicht nötig.",
"infoText": "Wenn dir dein Empfehlungsgeber seine Publisher-Id gegeben hat, trage sie hier ein, sonst lass das Feld bitte unverändert!",
"publisherId": "Publisher-Id"
},
"send": "Senden",
"settings": {
@ -143,7 +143,7 @@
"change-success": "Dein Name wurde erfolgreich geändert."
},
"newsletter": {
"newsletter": "Newsletter",
"newsletter": "Informationen per E-Mail",
"newsletterFalse": "Du erhältst keine Informationen per E-Mail.",
"newsletterTrue": "Du erhältst Informationen per E-Mail."
},
@ -151,15 +151,15 @@
"change-password": "Passwort ändern",
"forgot_pwd": "Passwort vergessen?",
"not-authenticated": "Leider konnten wir dich nicht authentifizieren. Bitte wende dich an den Support.",
"resend_subtitle": "Dein Aktivierungslink ist abgelaufen, Du kannst hier ein neuen anfordern.",
"resend_subtitle": "Dein Aktivierungslink ist abgelaufen. Du kannst hier ein neuen anfordern.",
"reset": "Passwort zurücksetzen",
"reset-password": {
"text": "Jetzt kannst du ein neues Passwort speichern, mit dem du dich zukünftig in der Gradido-App anmelden kannst."
"text": "Gib nun ein neues Passwort ein, mit dem du dich zukünftig in deinem Gradido-Konto anmelden willst."
},
"send_now": "Jetzt senden",
"set": "Passwort festlegen",
"set-password": {
"text": "Jetzt kannst du ein neues Passwort speichern, mit dem du dich zukünftig in der Gradido-App anmelden kannst."
"text": "Speichere nun dein neues Passwort, mit dem du dich zukünftig in deinem Gradido-Konto anmelden kannst."
},
"subtitle": "Wenn du dein Passwort vergessen hast, kannst du es hier zurücksetzen."
}
@ -167,13 +167,13 @@
"signup": "Registrieren",
"site": {
"404": {
"back": "Zurück zur Übersicht!",
"back": "Zurück zur Übersicht",
"ooops": "Ooops!",
"text": "Seite nicht gefunden. Aber keine Sorge, wir haben noch viele andere Seiten zum Erkunden"
"text": "Seite nicht gefunden. Aber keine Sorge, wir haben noch viele andere Seiten zu erkunden."
},
"checkEmail": {
"errorText": "Email konnte nicht verifiziert werden.",
"title": "Email wird verifiziert"
"errorText": "E-Mail konnte nicht verifiziert werden.",
"title": "E-Mail wird verifiziert"
},
"login": {
"community": "Tausend Dank, weil du bei uns bist!",
@ -190,17 +190,17 @@
"lowercase": "Ein Kleinbuchstabe erforderlich.",
"minimum": "Mindestens 8 Zeichen.",
"no-whitespace": "Keine Leerzeichen und Tabulatoren",
"one_number": "Eine Zahl erforderlich.",
"special-char": "Ein Sonderzeichen erforderlich (z.B. _ oder ä)",
"one_number": "Zahl erforderlich.",
"special-char": "Sonderzeichen erforderlich (z.B. _ oder ä)",
"subtitle": "Werde Teil der Gemeinschaft!",
"title": "Erstelle dein Gradido-Konto",
"uppercase": "Ein Großbuchstabe erforderlich."
"uppercase": "Großbuchstabe erforderlich."
},
"thx": {
"activateEmail": "Deine Email wurde noch nicht aktiviert, bitte überprüfe deine Email und Klicke den Aktivierungslink!",
"checkEmail": "Deine Email würde erfolgreich verifiziert.",
"email": "Wir haben dir eine eMail gesendet.",
"emailActivated": "Danke dass Du deine Email bestätigt hast.",
"activateEmail": "Dein Konto wurde noch nicht aktiviert. Bitte überprüfe deine E-Mail und klicke den Aktivierungslink!",
"checkEmail": "Deine E-Mail wurde erfolgreich verifiziert.",
"email": "Wir haben dir eine E-Mail gesendet.",
"emailActivated": "Danke dass Du deine E-Mail bestätigt hast.",
"errorTitle": "Achtung!",
"register": "Du bist jetzt registriert, bitte überprüfe deine Emails und klicke auf den Aktivierungslink.",
"reset": "Dein Passwort wurde geändert.",
@ -209,7 +209,7 @@
},
"transaction": {
"gdd-text": "Gradido Transaktionen",
"gdt-text": "Gradido Transform Transaktionen",
"gdt-text": "GradidoTransform Transaktionen",
"more": "mehr",
"nullTransactions": "Du hast noch keine Transaktionen auf deinem Konto.",
"receiverNotFound": "Empfänger nicht gefunden",

View File

@ -1,5 +1,5 @@
{
"admin_area": "Admin's area",
"admin_area": "Admin Area",
"back": "Back",
"community": {
"choose-another-community": "Choose another community",
@ -9,7 +9,7 @@
"hours": "hours",
"hours_report": "Hourly report",
"more_hours": "more hours",
"submit": "submit"
"submit": "Submit"
}
},
"community": "Community",
@ -17,23 +17,23 @@
"current-community": "Current community",
"location": "Location:",
"other-communities": "Other communities",
"switch-to-this-community": "switch to this community"
"switch-to-this-community": "Switch to this community"
},
"decay": {
"calculation_decay": "Calculation of Decay",
"calculation_total": "Calculation of the grand total",
"calculation_total": "Calculation of the total Amount",
"created": "Created",
"days": "Days",
"decay": "Decay",
"decayStart": " - Starting block for decay at: ",
"decay_introduced": "Decay was Introduced on",
"decay_introduced": "Decay was introduced on",
"decay_since_last_transaction": "Decay since the last transaction",
"hours": "Hours",
"last_transaction": "Last transaction:",
"minutes": "Minutes",
"months": "Months",
"noDecay": "No Decay",
"past_time": "Past time",
"past_time": "Time passed",
"received": "Received",
"seconds": "Seconds",
"sent": "Sent",
@ -48,7 +48,7 @@
"empty-transactionlist": "There was an error with the transmission of the number of your transactions.",
"error": "Error",
"no-account": "Unfortunately we could not find an account to the given data!",
"no-email-verify": "Your email is not activated yet, please check your emails and click the activation link!",
"no-email-verify": "Your account has not been confirmed yet. Please check your emails and click on the activation link!",
"no-transactionlist": "Unfortunately, there was an error. No transactions have been sent from the server.",
"session-expired": "The session was closed for security reasons."
},
@ -57,7 +57,7 @@
"at": "at",
"cancel": "Cancel",
"close": "Close",
"current_balance": "current balance",
"current_balance": "Current Balance",
"date": "Date",
"description": "Description",
"edit": "Edit",
@ -67,7 +67,7 @@
"lastname": "Lastname",
"memo": "Message",
"message": "Message",
"new_balance": "account balance after confirmation",
"new_balance": "Account balance after confirmation",
"password": "Password",
"passwordRepeat": "Repeat password",
"password_new": "New password",
@ -75,10 +75,10 @@
"password_old": "Old password",
"recipient": "Recipient",
"reset": "Reset",
"save": "save",
"save": "Save",
"scann_code": "<strong>QR Code Scanner</strong> - Scan the QR Code of your partner",
"sender": "Sender",
"send_check": "Confirm your payment. Please check all data again!",
"send_check": "Confirm your transaction. Please check all data again!",
"send_now": "Send now",
"send_transaction_error": "Unfortunately, the transaction could not be executed!",
"send_transaction_success": "Your transaction was successfully completed",
@ -88,40 +88,40 @@
"to": "to",
"to1": "to",
"validation": {
"gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits",
"gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits after the decimal point",
"is-not": "You cannot send Gradidos to yourself",
"usernmae-regex": "The username must start with a letter, followed by at least two alphanumeric characters.",
"usernmae-unique": "The username is already taken."
"usernmae-unique": "This username is already taken."
},
"your_amount": "Your amount"
},
"gdt": {
"action": "Action",
"calculation": "Calculation of Gradido Transform",
"calculation": "Calculation of GradidoTransform",
"contribution": "Contribution",
"conversion": "Conversion",
"conversion-gdt-euro": "Conversion Euro / Gradido Transform (GDT)",
"conversion-gdt-euro": "Conversion Euro / GradidoTransform (GDT)",
"credit": "Credit",
"factor": "Factor",
"formula": "Calculation formula",
"funding": "Regarding the funding contributions",
"gdt-received": "Gradido Transform (GDT) received",
"no-transactions": "You do not have Gradido Transform (GDT) yet.",
"funding": "To the funding contributions",
"gdt-received": "GradidoTransform (GDT) received",
"no-transactions": "You do not have GradidoTransform (GDT) yet.",
"publisher": "A member you referred has paid a contribution",
"raise": "Increase",
"recruited-member": "Recruited Member"
"recruited-member": "Invited member"
},
"imprint": "Legal notice",
"language": "Language",
"login": "Login",
"logout": "Logout",
"members_area": "Member's area",
"members_area": "Members area",
"message": "hello gradido !!",
"overview": "Overview",
"privacy_policy": "Privacy policy",
"publisher": {
"infoNoRegister": "This is not necessary for registration!",
"infoText": "Enter the ID of the publisher here. If you do not have an ID, please leave it blank.",
"infoNoRegister": "This is not necessary for registration.",
"infoText": "If your referrer has given you his publisher id, enter it here, otherwise leave the field unchanged!",
"publisherId": "PublisherID"
},
"send": "Send",
@ -135,7 +135,7 @@
"changeLanguage": "Change language",
"de": "Deutsch",
"en": "English",
"select_language": "Please choose a language.",
"select_language": "Please choose your language.",
"success": "Your language has been successfully updated."
},
"name": {
@ -143,23 +143,23 @@
"change-success": "Your name has been successfully changed."
},
"newsletter": {
"newsletter": "Newsletter",
"newsletterFalse": "You will not receive any information by e-mail.",
"newsletterTrue": "You will receive information by e-mail."
"newsletter": "Information by email",
"newsletterFalse": "You will not receive any information by email.",
"newsletterTrue": "You will receive information by email."
},
"password": {
"change-password": "Change password",
"forgot_pwd": "Forgot password?",
"not-authenticated": "Unfortunately we could not authenticate you. Please contact the support.",
"resend_subtitle": "Your activation link is expired, here you can order a new one.",
"resend_subtitle": "Your activation link has expired, here you can order a new one.",
"reset": "Reset password",
"reset-password": {
"text": "Now you can save a new password to login to the Gradido-App in the future."
"text": "Enter a new password that you will use to log in to your Gradido account in the future.."
},
"send_now": "Send now",
"set": "Set password",
"set-password": {
"text": "Now you can save a new password to login to the Gradido-App in the future."
"text": "Now save your new password, which you can use to log in to your Gradido account in the future."
},
"subtitle": "If you have forgotten your password, you can reset it here."
}
@ -167,9 +167,9 @@
"signup": "Sign up",
"site": {
"404": {
"back": "Back to dashboard!",
"back": "Back to the overview",
"ooops": "Ooops!",
"text": "Page not found. Do not worry though, we have plenty of other pages to explore"
"text": "Page not found. But don't worry, we have many other sites to explore."
},
"checkEmail": {
"errorText": "Could not verify the email.",
@ -197,7 +197,7 @@
"uppercase": "One uppercase letter required."
},
"thx": {
"activateEmail": "Your email has not been activated yet, please check your emails and click the activation link!",
"activateEmail": "Your account has not been activated yet, please check your emails and click the activation link!",
"checkEmail": "Your email has been successfully verified.",
"email": "We have sent you an email.",
"emailActivated": "Thank you your email has been activated.",
@ -209,7 +209,7 @@
},
"transaction": {
"gdd-text": "Gradido Transactions",
"gdt-text": "Gradido Transform Transactions",
"gdt-text": "GradidoTransform Transactions",
"more": "more",
"nullTransactions": "You don't have any transactions on your account yet.",
"receiverNotFound": "Recipient not found",

View File

@ -28,7 +28,7 @@ Vue.toasted.register(
loadAllRules(i18n)
addNavigationGuards(router, store, apolloProvider.defaultClient)
addNavigationGuards(router, store, apolloProvider.defaultClient, i18n)
if (!store) {
setTimeout(

View File

@ -1,6 +1,6 @@
import { verifyLogin } from '../graphql/queries'
const addNavigationGuards = (router, store, apollo) => {
const addNavigationGuards = (router, store, apollo, i18n) => {
// handle publisherId
router.beforeEach((to, from, next) => {
const publisherId = to.query.pid
@ -21,6 +21,7 @@ const addNavigationGuards = (router, store, apollo) => {
fetchPolicy: 'network-only',
})
.then((result) => {
i18n.locale = result.data.verifyLogin.language
store.dispatch('login', result.data.verifyLogin)
next({ path: '/overview' })
})

View File

@ -23,7 +23,11 @@ const apollo = {
query: apolloQueryMock,
}
addNavigationGuards(router, store, apollo)
const i18n = {
locale: jest.fn(),
}
addNavigationGuards(router, store, apollo, i18n)
describe('navigation guards', () => {
beforeEach(() => {

View File

@ -15,6 +15,7 @@ describe('AuthLayoutGdd', () => {
meta: {
hideFooter: false,
},
path: '/',
},
$store: {
state: {},
@ -47,5 +48,20 @@ describe('AuthLayoutGdd', () => {
it('has a footer inside the main content', () => {
expect(wrapper.find('div.main-content').find('footer.footer').exists()).toBeTruthy()
})
it('has LanguageSwitch', () => {
expect(wrapper.findComponent({ name: 'LanguageSwitch' }).exists()).toBeTruthy()
})
describe('check LanguageSwitch on register page', () => {
beforeEach(() => {
mocks.$route.path = '/register'
wrapper = Wrapper()
})
it('has not LanguageSwitch', () => {
expect(wrapper.findComponent({ name: 'LanguageSwitch' }).exists()).toBeFalsy()
})
})
})
})

View File

@ -2,7 +2,7 @@
<div class="wrapper">
<div class="main-content mt-4">
<router-view></router-view>
<language-switch class="text-center mb-5 mt-5" />
<language-switch v-if="$route.path !== '/register'" class="text-center mb-5 mt-5" />
<content-footer v-if="!$route.meta.hideFooter"></content-footer>
</div>
</div>

View File

@ -28,6 +28,9 @@ const createMockObject = (comingFrom) => {
optin: '123',
comingFrom,
},
path: {
includes: (t) => t,
},
},
$toasted: {
global: {

View File

@ -5,10 +5,10 @@
<div class="header-body text-center mb-7">
<b-row class="justify-content-center">
<b-col xl="5" lg="6" md="8" class="px-2">
<h1>{{ $t('settings.password.reset') }}</h1>
<h1>{{ $t(displaySetup.authenticated) }}</h1>
<div class="pb-4">
<span>
{{ $t('settings.password.reset-password.text') }}
{{ $t(displaySetup.notAuthenticated) }}
</span>
</div>
</b-col>
@ -49,14 +49,14 @@ import { setPassword } from '../../graphql/mutations'
const textFields = {
reset: {
authenticated: 'settings.password.reset-password.text',
notAuthenticated: 'settings.password.not-authenticated',
button: 'settings.password.reset',
authenticated: 'settings.password.change-password',
notAuthenticated: 'settings.password.reset-password.text',
button: 'settings.password.change-password',
linkTo: '/login',
},
checkEmail: {
authenticated: 'settings.password.set-password.text',
notAuthenticated: 'settings.password.not-authenticated',
authenticated: 'settings.password.set',
notAuthenticated: 'settings.password.set-password.text',
button: 'settings.password.set',
linkTo: '/login',
},
@ -95,19 +95,17 @@ export default {
this.$router.push('/thx/reset')
})
.catch((error) => {
if (error.message.includes('Code is older than 10 minutes')) {
this.$toasted.global.error(error.message)
this.$toasted.global.error(error.message)
if (error.message.includes('Code is older than 10 minutes'))
this.$router.push('/password/reset')
} else {
this.$toasted.global.error(error.message)
}
})
},
setDisplaySetup() {
if (!this.$route.params.comingFrom) {
if (this.$route.path.includes('checkEmail')) {
this.displaySetup = textFields.checkEmail
}
if (this.$route.path.includes('reset')) {
this.displaySetup = textFields.reset
} else {
this.displaySetup = textFields[this.$route.params.comingFrom]
}
},
},