diff --git a/backend/src/schema/resolvers/rewards.spec.js b/backend/src/schema/resolvers/rewards.spec.js index a20472243..eaaa852ec 100644 --- a/backend/src/schema/resolvers/rewards.spec.js +++ b/backend/src/schema/resolvers/rewards.spec.js @@ -16,6 +16,7 @@ describe('rewards', () => { } beforeAll(async () => { + await cleanDatabase() const { server } = createServer({ context: () => { return { diff --git a/webapp/components/ComponentSlider/ComponentSlider.vue b/webapp/components/ComponentSlider/ComponentSlider.vue new file mode 100644 index 000000000..9ecaa5711 --- /dev/null +++ b/webapp/components/ComponentSlider/ComponentSlider.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/webapp/components/Registration/CreateUserAccount.story.js b/webapp/components/Registration/CreateUserAccount.story.js new file mode 100644 index 000000000..054ee71b4 --- /dev/null +++ b/webapp/components/Registration/CreateUserAccount.story.js @@ -0,0 +1,84 @@ +import { storiesOf } from '@storybook/vue' +import { withA11y } from '@storybook/addon-a11y' +import { action } from '@storybook/addon-actions' +import Vuex from 'vuex' +import helpers from '~/storybook/helpers' +import links from '~/constants/links.js' +import metadata from '~/constants/metadata.js' +import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch' +import CreateUserAccount from './CreateUserAccount.vue' + +helpers.init() + +const createStore = ({ loginSuccess }) => { + return new Vuex.Store({ + modules: { + auth: { + namespaced: true, + state: () => ({ + pending: false, + }), + mutations: { + SET_PENDING(state, pending) { + state.pending = pending + }, + }, + getters: { + pending(state) { + return !!state.pending + }, + }, + actions: { + async login({ commit, dispatch }, args) { + action('Vuex action `auth/login`')(args) + return new Promise((resolve, reject) => { + commit('SET_PENDING', true) + setTimeout(() => { + commit('SET_PENDING', false) + if (loginSuccess) { + resolve(loginSuccess) + } else { + reject(new Error('Login unsuccessful')) + } + }, 1000) + }) + }, + }, + }, + }, + }) +} + +storiesOf('CreateUserAccount', module) + .addDecorator(withA11y) + .addDecorator(helpers.layout) + .add('standard', () => ({ + components: { LocaleSwitch, CreateUserAccount }, + store: createStore({ loginSuccess: true }), + data: () => ({ + links, + metadata, + nonce: 'A34RB56', + email: 'user@example.org', + }), + methods: { + handleSuccess() { + action('You are logged in!')() + }, + }, + template: ` + + + + + + + + `, + })) diff --git a/webapp/components/Registration/RegistrationItemCreateUserAccount.vue b/webapp/components/Registration/RegistrationItemCreateUserAccount.vue new file mode 100644 index 000000000..c76e6f71e --- /dev/null +++ b/webapp/components/Registration/RegistrationItemCreateUserAccount.vue @@ -0,0 +1,321 @@ + + + + + diff --git a/webapp/components/Registration/RegistrationItemEnterEmail.vue b/webapp/components/Registration/RegistrationItemEnterEmail.vue new file mode 100644 index 000000000..d2b886fc5 --- /dev/null +++ b/webapp/components/Registration/RegistrationItemEnterEmail.vue @@ -0,0 +1,262 @@ + + + + diff --git a/webapp/components/Registration/RegistrationItemEnterInvite.vue b/webapp/components/Registration/RegistrationItemEnterInvite.vue new file mode 100644 index 000000000..b52704224 --- /dev/null +++ b/webapp/components/Registration/RegistrationItemEnterInvite.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/webapp/components/Registration/RegistrationItemEnterNonce.vue b/webapp/components/Registration/RegistrationItemEnterNonce.vue new file mode 100644 index 000000000..52ec572c2 --- /dev/null +++ b/webapp/components/Registration/RegistrationItemEnterNonce.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/webapp/components/Registration/RegistrationSlider.story.js b/webapp/components/Registration/RegistrationSlider.story.js new file mode 100644 index 000000000..fc6dd3e32 --- /dev/null +++ b/webapp/components/Registration/RegistrationSlider.story.js @@ -0,0 +1,160 @@ +import { storiesOf } from '@storybook/vue' +import { withA11y } from '@storybook/addon-a11y' +import RegistrationSlider from './RegistrationSlider.vue' +import helpers from '~/storybook/helpers' +import Vue from 'vue' + +const plugins = [ + (app = {}) => { + app.$apollo = { + mutate: (data) => { + if (JSON.stringify(data).includes('UpdateUser')) { + return { data: { UpdateUser: { id: data.variables.id, locale: data.variables.locale } } } + } + if (JSON.stringify(data).includes('Signup')) { + return { data: { Signup: { email: data.variables.email } } } + } + if (JSON.stringify(data).includes('SignupByInvitation')) { + return { data: { SignupByInvitation: { email: data.variables.email } } } + } + if (JSON.stringify(data).includes('SignupVerification')) { + return { data: { SignupByInvitation: { ...data.variables } } } + } + throw new Error(`Mutation name not found!`) + }, + query: (data) => { + if (JSON.stringify(data).includes('isValidInviteCode')) { + return { data: { isValidInviteCode: true } } + } + throw new Error(`Query name not found!`) + }, + } + Vue.prototype.$apollo = app.$apollo + return app + }, +] +helpers.init({ plugins }) + +storiesOf('RegistrationSlider', module) + .addDecorator(withA11y) + .addDecorator(helpers.layout) + .add('invite-code empty', () => ({ + components: { RegistrationSlider }, + store: helpers.store, + data: () => ({}), + template: ` + + `, + })) + .add('invite-code with data', () => ({ + components: { RegistrationSlider }, + store: helpers.store, + data: () => ({ + overwriteSliderData: { + collectedInputData: { + inviteCode: 'IN1T6Y', + email: 'wolle.huss@pjannto.com', + emailSend: false, + nonce: 'NTRSCZ', + name: 'Wolle', + password: 'Hello', + passwordConfirmation: 'Hello', + about: `Hey`, + termsAndConditionsConfirmed: true, + dataPrivacy: true, + minimumAge: true, + noCommercial: true, + noPolitical: true, + }, + }, + }), + template: ` + + `, + })) + .add('public-registration empty', () => ({ + components: { RegistrationSlider }, + store: helpers.store, + data: () => ({}), + template: ` + + `, + })) + .add('public-registration with data', () => ({ + components: { RegistrationSlider }, + store: helpers.store, + data: () => ({ + overwriteSliderData: { + collectedInputData: { + inviteCode: null, + email: 'wolle.huss@pjannto.com', + emailSend: false, + nonce: 'NTRSCZ', + name: 'Wolle', + password: 'Hello', + passwordConfirmation: 'Hello', + about: `Hey`, + termsAndConditionsConfirmed: true, + dataPrivacy: true, + minimumAge: true, + noCommercial: true, + noPolitical: true, + }, + }, + }), + template: ` + + `, + })) + .add('invite-mail empty', () => ({ + components: { RegistrationSlider }, + store: helpers.store, + data: () => ({ + overwriteSliderData: { + collectedInputData: { + inviteCode: null, + email: 'wolle.huss@pjannto.com', + emailSend: true, + nonce: null, + name: null, + password: null, + passwordConfirmation: null, + about: null, + termsAndConditionsConfirmed: null, + dataPrivacy: null, + minimumAge: null, + noCommercial: null, + noPolitical: null, + }, + }, + }), + template: ` + + `, + })) + .add('invite-mail with data', () => ({ + components: { RegistrationSlider }, + store: helpers.store, + data: () => ({ + overwriteSliderData: { + collectedInputData: { + inviteCode: null, + email: 'wolle.huss@pjannto.com', + emailSend: true, + nonce: 'NTRSCZ', + name: 'Wolle', + password: 'Hello', + passwordConfirmation: 'Hello', + about: `Hey`, + termsAndConditionsConfirmed: true, + dataPrivacy: true, + minimumAge: true, + noCommercial: true, + noPolitical: true, + }, + }, + }), + template: ` + + `, + })) diff --git a/webapp/components/Registration/RegistrationSlider.vue b/webapp/components/Registration/RegistrationSlider.vue new file mode 100644 index 000000000..e69231c78 --- /dev/null +++ b/webapp/components/Registration/RegistrationSlider.vue @@ -0,0 +1,235 @@ + + + + + diff --git a/webapp/components/utils/PasswordFormHelper.js b/webapp/components/utils/PasswordFormHelper.js index 578238aca..da6cead90 100644 --- a/webapp/components/utils/PasswordFormHelper.js +++ b/webapp/components/utils/PasswordFormHelper.js @@ -15,7 +15,7 @@ export default function PasswordForm({ translate }) { }, passwordConfirmation: [ { - validator(rule, value, callback, source, options) { + validator(_rule, value, callback, source, _options) { var errors = [] if (source.password !== value) { errors.push(new Error(passwordMismatchMessage)) diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 2033a8d04..e02e4f6b0 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -120,6 +120,16 @@ "versus": "Versus" }, "components": { + "enter-invite": { + "form": { + "description": "Gib den Einladungs-Code ein, den du bekommen hast.", + "invite-code": "Einladungs-Code eingeben", + "next": "Weiter", + "validations": { + "length": "muss genau 6 Buchstaben lang sein" + } + } + }, "enter-nonce": { "form": { "description": "Öffne Dein E-Mail Postfach und gib den Code ein, den wir geschickt haben.", @@ -152,9 +162,19 @@ "success": "Dein Benutzerkonto wurde erstellt!", "title": "Benutzerkonto anlegen" }, + "email": { + "form": { + "success": "Verifikations-E-Mail gesendet an {email}!" + } + }, + "invite-code": { + "form": { + "success": "Gültiger Einladungs-Code {inviteCode}!" + } + }, "signup": { "form": { - "data-privacy": "Ich habe die Datenschutzerklärung gelesen und verstanden", + "data-privacy": "Ich habe die Datenschutzerklärung gelesen und verstanden.", "description": "Um loszulegen, kannst Du Dich hier kostenfrei registrieren:", "errors": { "email-exists": "Es gibt schon ein Benutzerkonto mit dieser E-Mail-Adresse!", @@ -733,7 +753,7 @@ "bank": "Bankverbindung", "code-of-conduct": "Verhaltenscodex", "contact": "Kontakt", - "data-privacy": "Datenschutz", + "data-privacy": "Datenschutzerklärung", "director": "Geschäftsführer", "error-occurred": "Ein Fehler ist aufgetreten.", "faq": "FAQ", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 147fb252e..e195f542e 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -120,6 +120,16 @@ "versus": "Versus" }, "components": { + "enter-invite": { + "form": { + "description": "Enter the invitation code you received.", + "invite-code": "Enter your invite code", + "next": "Continue", + "validations": { + "length": "must be 6 characters long" + } + } + }, "enter-nonce": { "form": { "description": "Open your inbox and enter the code that we've sent to you.", @@ -152,9 +162,19 @@ "success": "Your account has been created!", "title": "Create user account" }, + "email": { + "form": { + "success": "Verification e-mail send to {email}!" + } + }, + "invite-code": { + "form": { + "success": "Valid invite code {inviteCode}!" + } + }, "signup": { "form": { - "data-privacy": "I have read and understood the Privacy Statement.", + "data-privacy": "I have read and understood the privacy statement.", "description": "To get started, you can register here for free:", "errors": { "email-exists": "There is already a user account with this e-mail address!", @@ -762,7 +782,7 @@ "termsAndConditions": { "agree": "I agree!", "newTermsAndConditions": "New Terms and Conditions", - "termsAndConditionsConfirmed": "I have read and confirmed the Terms and Conditions.", + "termsAndConditionsConfirmed": "I have read and confirmed the terms and conditions.", "termsAndConditionsNewConfirm": "I have read and agree to the new terms of conditions.", "termsAndConditionsNewConfirmText": "Please read the new terms of use now!" },