diff --git a/backend/package.json b/backend/package.json
index 7c66ba4a2..5016d7c9f 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -34,13 +34,13 @@
]
},
"dependencies": {
- "@hapi/joi": "^16.1.7",
+ "@hapi/joi": "^16.1.8",
"@sentry/node": "^5.9.0",
"apollo-cache-inmemory": "~1.6.3",
"apollo-client": "~2.6.4",
"apollo-link-context": "~1.0.19",
"apollo-link-http": "~1.5.16",
- "apollo-server": "~2.9.11",
+ "apollo-server": "~2.9.12",
"apollo-server-express": "^2.9.7",
"babel-plugin-transform-runtime": "^6.23.0",
"bcryptjs": "~2.4.3",
@@ -57,7 +57,7 @@
"graphql-iso-date": "~3.6.1",
"graphql-middleware": "~4.0.2",
"graphql-middleware-sentry": "^3.2.1",
- "graphql-shield": "~7.0.2",
+ "graphql-shield": "~7.0.4",
"graphql-tag": "~2.10.1",
"helmet": "~3.21.2",
"jsonwebtoken": "~8.5.1",
@@ -99,10 +99,10 @@
"xregexp": "^4.2.4"
},
"devDependencies": {
- "@babel/cli": "~7.7.0",
- "@babel/core": "~7.7.2",
+ "@babel/cli": "~7.7.4",
+ "@babel/core": "~7.7.4",
"@babel/node": "~7.7.4",
- "@babel/plugin-proposal-throw-expressions": "^7.2.0",
+ "@babel/plugin-proposal-throw-expressions": "^7.7.4",
"@babel/preset-env": "~7.7.4",
"@babel/register": "~7.7.0",
"apollo-server-testing": "~2.9.12",
@@ -111,11 +111,11 @@
"babel-jest": "~24.9.0",
"chai": "~4.2.0",
"cucumber": "~6.0.5",
- "eslint": "~6.7.1",
+ "eslint": "~6.7.2",
"eslint-config-prettier": "~6.7.0",
"eslint-config-standard": "~14.1.0",
"eslint-plugin-import": "~2.18.2",
- "eslint-plugin-jest": "~23.0.4",
+ "eslint-plugin-jest": "~23.1.1",
"eslint-plugin-node": "~10.0.0",
"eslint-plugin-prettier": "~3.1.1",
"eslint-plugin-promise": "~4.2.1",
diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js
index b0d07c8ec..e729123c9 100644
--- a/backend/src/middleware/permissionsMiddleware.js
+++ b/backend/src/middleware/permissionsMiddleware.js
@@ -1,4 +1,4 @@
-import { rule, shield, deny, allow, and, or, not } from 'graphql-shield'
+import { rule, shield, deny, allow, or } from 'graphql-shield'
import { neode } from '../bootstrap/neo4j'
import CONFIG from '../config'
@@ -41,48 +41,27 @@ const isMySocialMedia = rule({
return socialMedia.ownedBy.node.id === user.id
})
-const invitationLimitReached = rule({
- cache: 'no_cache',
-})(async (parent, args, { user, driver }) => {
- const session = driver.session()
- try {
- const result = await session.run(
- `
- MATCH (user:User {id:$id})-[:GENERATED]->(i:InvitationCode)
- RETURN COUNT(i) >= 3 as limitReached
- `,
- { id: user.id },
- )
- const [limitReached] = result.records.map(record => {
- return record.get('limitReached')
- })
- return limitReached
- } finally {
- session.close()
- }
-})
-
const isAuthor = rule({
cache: 'no_cache',
})(async (_parent, args, { user, driver }) => {
if (!user) return false
const session = driver.session()
const { id: resourceId } = args
- const result = await session.run(
- `
- MATCH (resource {id: $resourceId})<-[:WROTE]-(author)
- RETURN author
- `,
- {
- resourceId,
- },
- )
- session.close()
- const [author] = result.records.map(record => {
- return record.get('author')
- })
- const authorId = author && author.properties && author.properties.id
- return authorId === user.id
+ try {
+ const result = await session.run(
+ `
+ MATCH (resource {id: $resourceId})<-[:WROTE]-(author {id: $userId})
+ RETURN author
+ `,
+ { resourceId, userId: user.id },
+ )
+ const [author] = result.records.map(record => {
+ return record.get('author')
+ })
+ return !!author
+ } finally {
+ session.close()
+ }
})
const isDeletingOwnAccount = rule({
@@ -100,7 +79,7 @@ const noEmailFilter = rule({
const publicRegistration = rule()(() => !!CONFIG.PUBLIC_REGISTRATION)
// Permissions
-const permissions = shield(
+export default shield(
{
Query: {
'*': deny,
@@ -129,7 +108,6 @@ const permissions = shield(
SignupByInvitation: allow,
Signup: or(publicRegistration, isAdmin),
SignupVerification: allow,
- CreateInvitationCode: and(isAuthenticated, or(not(invitationLimitReached), isAdmin)),
UpdateUser: onlyYourself,
CreatePost: isAuthenticated,
UpdatePost: isAuthor,
@@ -176,5 +154,3 @@ const permissions = shield(
fallbackRule: allow,
},
)
-
-export default permissions
diff --git a/backend/src/models/index.js b/backend/src/models/index.js
index bd89ddc51..239076adc 100644
--- a/backend/src/models/index.js
+++ b/backend/src/models/index.js
@@ -3,7 +3,6 @@
export default {
Badge: require('./Badge.js'),
User: require('./User.js'),
- InvitationCode: require('./InvitationCode.js'),
EmailAddress: require('./EmailAddress.js'),
UnverifiedEmailAddress: require('./UnverifiedEmailAddress.js'),
SocialMedia: require('./SocialMedia.js'),
diff --git a/backend/src/schema/index.js b/backend/src/schema/index.js
index 516f47abd..4252bd817 100644
--- a/backend/src/schema/index.js
+++ b/backend/src/schema/index.js
@@ -10,7 +10,6 @@ export default makeAugmentedSchema({
exclude: [
'Badge',
'Embed',
- 'InvitationCode',
'EmailAddress',
'Notfication',
'Statistics',
diff --git a/backend/src/schema/resolvers/emails.js b/backend/src/schema/resolvers/emails.js
index 06c0dbd1a..8711a5996 100644
--- a/backend/src/schema/resolvers/emails.js
+++ b/backend/src/schema/resolvers/emails.js
@@ -3,7 +3,7 @@ import Resolver from './helpers/Resolver'
import existingEmailAddress from './helpers/existingEmailAddress'
import { UserInputError } from 'apollo-server'
import Validator from 'neode/build/Services/Validator.js'
-import { normalizeEmail } from 'validator'
+import normalizeEmail from './helpers/normalizeEmail'
export default {
Mutation: {
diff --git a/backend/src/schema/resolvers/helpers/createPasswordReset.js b/backend/src/schema/resolvers/helpers/createPasswordReset.js
index 8d575abfc..d73cfaa81 100644
--- a/backend/src/schema/resolvers/helpers/createPasswordReset.js
+++ b/backend/src/schema/resolvers/helpers/createPasswordReset.js
@@ -1,4 +1,4 @@
-import { normalizeEmail } from 'validator'
+import normalizeEmail from './normalizeEmail'
export default async function createPasswordReset(options) {
const { driver, nonce, email, issuedAt = new Date() } = options
diff --git a/backend/src/schema/resolvers/helpers/normalizeEmail.js b/backend/src/schema/resolvers/helpers/normalizeEmail.js
new file mode 100644
index 000000000..bdd12e991
--- /dev/null
+++ b/backend/src/schema/resolvers/helpers/normalizeEmail.js
@@ -0,0 +1,11 @@
+import { normalizeEmail } from 'validator'
+
+export default email =>
+ normalizeEmail(email, {
+ // gmail_remove_dots: true, default
+ gmail_remove_subaddress: false,
+ // gmail_convert_googlemaildotcom: true, default
+ outlookdotcom_remove_subaddress: false,
+ yahoo_remove_subaddress: false,
+ icloud_remove_subaddress: false,
+ })
diff --git a/backend/src/schema/resolvers/registration.js b/backend/src/schema/resolvers/registration.js
index d425357c3..206c8db74 100644
--- a/backend/src/schema/resolvers/registration.js
+++ b/backend/src/schema/resolvers/registration.js
@@ -4,31 +4,12 @@ import fileUpload from './fileUpload'
import encryptPassword from '../../helpers/encryptPassword'
import generateNonce from './helpers/generateNonce'
import existingEmailAddress from './helpers/existingEmailAddress'
-import { normalizeEmail } from 'validator'
+import normalizeEmail from './helpers/normalizeEmail'
const instance = neode()
export default {
Mutation: {
- CreateInvitationCode: async (_parent, args, context, _resolveInfo) => {
- args.token = generateNonce()
- const {
- user: { id: userId },
- } = context
- let response
- try {
- const [user, invitationCode] = await Promise.all([
- instance.find('User', userId),
- instance.create('InvitationCode', args),
- ])
- await invitationCode.relateTo(user, 'generatedBy')
- response = invitationCode.toJson()
- response.generatedBy = user.toJson()
- } catch (e) {
- throw new UserInputError(e)
- }
- return response
- },
Signup: async (_parent, args, context) => {
args.nonce = generateNonce()
args.email = normalizeEmail(args.email)
@@ -41,35 +22,6 @@ export default {
throw new UserInputError(e.message)
}
},
- SignupByInvitation: async (_parent, args, context) => {
- const { token } = args
- args.nonce = generateNonce()
- args.email = normalizeEmail(args.email)
- let emailAddress = await existingEmailAddress({ args, context })
- if (emailAddress) return emailAddress
- try {
- const result = await instance.cypher(
- `
- MATCH (invitationCode:InvitationCode {token:{token}})
- WHERE NOT (invitationCode)-[:ACTIVATED]->()
- RETURN invitationCode
- `,
- { token },
- )
- const validInvitationCode = instance.hydrateFirst(
- result,
- 'invitationCode',
- instance.model('InvitationCode'),
- )
- if (!validInvitationCode)
- throw new UserInputError('Invitation code already used or does not exist.')
- emailAddress = await instance.create('EmailAddress', args)
- await validInvitationCode.relateTo(emailAddress, 'activated')
- return emailAddress.toJson()
- } catch (e) {
- throw new UserInputError(e)
- }
- },
SignupVerification: async (_parent, args) => {
const { termsAndConditionsAgreedVersion } = args
const regEx = new RegExp(/^[0-9]+\.[0-9]+\.[0-9]+$/g)
diff --git a/backend/src/schema/resolvers/registration.spec.js b/backend/src/schema/resolvers/registration.spec.js
index 7d53b63c9..35b16b9bb 100644
--- a/backend/src/schema/resolvers/registration.spec.js
+++ b/backend/src/schema/resolvers/registration.spec.js
@@ -9,7 +9,6 @@ const neode = getNeode()
let mutate
let authenticatedUser
-let user
let variables
const driver = getDriver()
@@ -34,243 +33,6 @@ afterEach(async () => {
await factory.cleanDatabase()
})
-describe('CreateInvitationCode', () => {
- const mutation = gql`
- mutation {
- CreateInvitationCode {
- token
- }
- }
- `
-
- describe('unauthenticated', () => {
- beforeEach(() => {
- authenticatedUser = null
- })
-
- it('throws Authorization error', async () => {
- await expect(mutate({ mutation })).resolves.toMatchObject({
- errors: [{ message: 'Not Authorised!' }],
- })
- })
- })
-
- describe('authenticated', () => {
- beforeEach(async () => {
- user = await factory.create('User', {
- id: 'i123',
- name: 'Inviter',
- email: 'inviter@example.org',
- password: '1234',
- termsAndConditionsAgreedVersion: null,
- })
- authenticatedUser = await user.toJson()
- })
-
- it('resolves', async () => {
- await expect(mutate({ mutation })).resolves.toMatchObject({
- data: { CreateInvitationCode: { token: expect.any(String) } },
- })
- })
-
- it('creates an InvitationCode with a `createdAt` attribute', async () => {
- await mutate({ mutation })
- const codes = await neode.all('InvitationCode')
- const invitation = await codes.first().toJson()
- expect(invitation.createdAt).toBeTruthy()
- expect(Date.parse(invitation.createdAt)).toEqual(expect.any(Number))
- })
-
- it('relates inviting User to InvitationCode', async () => {
- await mutate({ mutation })
- const result = await neode.cypher(
- 'MATCH(code:InvitationCode)<-[:GENERATED]-(user:User) RETURN user',
- )
- const inviter = neode.hydrateFirst(result, 'user', neode.model('User'))
- await expect(inviter.toJson()).resolves.toEqual(expect.objectContaining({ name: 'Inviter' }))
- })
-
- describe('who has invited a lot of users already', () => {
- beforeEach(async () => {
- await Promise.all([mutate({ mutation }), mutate({ mutation }), mutate({ mutation })])
- })
-
- describe('as ordinary `user`', () => {
- it('throws `Not Authorised` because of maximum number of invitations', async () => {
- await expect(mutate({ mutation })).resolves.toMatchObject({
- errors: [{ message: 'Not Authorised!' }],
- })
- })
-
- it('creates no additional invitation codes', async () => {
- await mutate({ mutation })
- const invitationCodes = await neode.all('InvitationCode')
- await expect(invitationCodes.toJson()).resolves.toHaveLength(3)
- })
- })
-
- describe('as a strong donator', () => {
- beforeEach(() => {
- // What is the setup?
- })
-
- it.todo('can invite more people')
- // it('can invite more people', async () => {
- // await action()
- // const invitationQuery = `{ User { createdAt } }`
- // const { User: users } = await client.request(invitationQuery )
- // expect(users).toHaveLength(3 + 1 + 1)
- // })
- })
- })
- })
-})
-
-describe('SignupByInvitation', () => {
- const mutation = gql`
- mutation($email: String!, $token: String!) {
- SignupByInvitation(email: $email, token: $token) {
- email
- }
- }
- `
-
- describe('with valid email but invalid InvitationCode', () => {
- beforeEach(() => {
- variables = {
- ...variables,
- email: 'any-email@example.org',
- token: 'wut?',
- }
- })
-
- it('throws UserInputError', async () => {
- await expect(mutate({ mutation, variables })).resolves.toMatchObject({
- errors: [{ message: 'UserInputError: Invitation code already used or does not exist.' }],
- })
- })
-
- describe('with valid InvitationCode', () => {
- beforeEach(async () => {
- const inviter = await factory.create('User', {
- name: 'Inviter',
- email: 'inviter@example.org',
- password: '1234',
- })
- authenticatedUser = await inviter.toJson()
- const invitationMutation = gql`
- mutation {
- CreateInvitationCode {
- token
- }
- }
- `
- const {
- data: {
- CreateInvitationCode: { token },
- },
- } = await mutate({ mutation: invitationMutation })
- authenticatedUser = null
- variables = {
- ...variables,
- token,
- }
- })
-
- describe('given an invalid email', () => {
- beforeEach(() => {
- variables = { ...variables, email: 'someuser' }
- })
-
- it('throws `email is not a valid email`', async () => {
- await expect(mutate({ mutation, variables })).resolves.toMatchObject({
- errors: [{ message: expect.stringContaining('"email" must be a valid email') }],
- })
- })
-
- it('creates no additional EmailAddress node', async () => {
- let emailAddresses = await neode.all('EmailAddress')
- emailAddresses = await emailAddresses.toJson()
- expect(emailAddresses).toHaveLength(1)
- await mutate({ mutation, variables })
- emailAddresses = await neode.all('EmailAddress')
- emailAddresses = await emailAddresses.toJson()
- expect(emailAddresses).toHaveLength(1)
- })
- })
-
- describe('given a valid email', () => {
- beforeEach(() => {
- variables = { ...variables, email: 'someUser@example.org' }
- })
-
- it('resolves', async () => {
- await expect(mutate({ mutation, variables })).resolves.toMatchObject({
- data: { SignupByInvitation: { email: 'someuser@example.org' } },
- })
- })
-
- describe('creates a EmailAddress node', () => {
- it('with a `createdAt` attribute', async () => {
- await mutate({ mutation, variables })
- let emailAddress = await neode.first('EmailAddress', { email: 'someuser@example.org' })
- emailAddress = await emailAddress.toJson()
- expect(emailAddress.createdAt).toBeTruthy()
- expect(Date.parse(emailAddress.createdAt)).toEqual(expect.any(Number))
- })
-
- it('with a cryptographic `nonce`', async () => {
- await mutate({ mutation, variables })
- let emailAddress = await neode.first('EmailAddress', { email: 'someuser@example.org' })
- emailAddress = await emailAddress.toJson()
- expect(emailAddress.nonce).toEqual(expect.any(String))
- })
-
- it('connects inviter through invitation code', async () => {
- await mutate({ mutation, variables })
- const result = await neode.cypher(
- 'MATCH(inviter:User)-[:GENERATED]->(:InvitationCode)-[:ACTIVATED]->(email:EmailAddress {email: {email}}) RETURN inviter',
- { email: 'someuser@example.org' },
- )
- const inviter = neode.hydrateFirst(result, 'inviter', neode.model('User'))
- await expect(inviter.toJson()).resolves.toEqual(
- expect.objectContaining({ name: 'Inviter' }),
- )
- })
-
- describe('using the same InvitationCode twice', () => {
- it('rejects because codes can be used only once', async () => {
- await mutate({ mutation, variables })
- variables = { ...variables, email: 'yetanotheremail@example.org' }
- await expect(mutate({ mutation, variables })).resolves.toMatchObject({
- errors: [
- { message: 'UserInputError: Invitation code already used or does not exist.' },
- ],
- })
- })
- })
-
- describe('if a user account with the given email already exists', () => {
- beforeEach(async () => {
- await factory.create('User', { email: 'someuser@example.org' })
- })
-
- it('throws unique violation error', async () => {
- await expect(mutate({ mutation, variables })).resolves.toMatchObject({
- errors: [{ message: 'A user account with this email already exists.' }],
- })
- })
- })
-
- describe('if the EmailAddress already exists but without user account', () => {
- it.todo('shall we re-send the registration email?')
- })
- })
- })
- })
- })
-})
-
describe('Signup', () => {
const mutation = gql`
mutation($email: String!) {
diff --git a/backend/src/schema/resolvers/user_management.js b/backend/src/schema/resolvers/user_management.js
index b7584dd68..81550d8cf 100644
--- a/backend/src/schema/resolvers/user_management.js
+++ b/backend/src/schema/resolvers/user_management.js
@@ -2,7 +2,7 @@ import encode from '../../jwt/encode'
import bcrypt from 'bcryptjs'
import { AuthenticationError } from 'apollo-server'
import { neode } from '../../bootstrap/neo4j'
-import { normalizeEmail } from 'validator'
+import normalizeEmail from './helpers/normalizeEmail'
const instance = neode()
diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js
index 3024bf5a5..02ed8dbac 100644
--- a/backend/src/schema/resolvers/users.js
+++ b/backend/src/schema/resolvers/users.js
@@ -49,10 +49,22 @@ export default {
User: async (object, args, context, resolveInfo) => {
const { email } = args
if (email) {
- const e = await instance.first('EmailAddress', { email })
- let user = e.get('belongsTo')
- user = await user.toJson()
- return [user.node]
+ let session
+ try {
+ session = context.driver.session()
+ const readTxResult = await session.readTransaction(txc => {
+ const result = txc.run(
+ `
+ MATCH (user:User)-[:PRIMARY_EMAIL]->(e:EmailAddress {email: $args.email})
+ RETURN user`,
+ { args },
+ )
+ return result
+ })
+ return readTxResult.records.map(r => r.get('user').properties)
+ } finally {
+ session.close()
+ }
}
return neo4jgraphql(object, args, context, resolveInfo)
},
diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js
index 36b77d611..483c70214 100644
--- a/backend/src/schema/resolvers/users.spec.js
+++ b/backend/src/schema/resolvers/users.spec.js
@@ -70,6 +70,21 @@ describe('User', () => {
data: { User: [{ name: 'Johnny' }] },
})
})
+
+ it('non-existing email address, issue #2294', async () => {
+ // see: https://github.com/Human-Connection/Human-Connection/issues/2294
+ await expect(
+ query({
+ query: userQuery,
+ variables: {
+ email: 'this-email-does-not-exist@example.org',
+ },
+ }),
+ ).resolves.toMatchObject({
+ data: { User: [] },
+ errors: undefined,
+ })
+ })
})
})
})
diff --git a/backend/src/schema/types/type/InvitationCode.gql b/backend/src/schema/types/type/InvitationCode.gql
deleted file mode 100644
index 61ce0f689..000000000
--- a/backend/src/schema/types/type/InvitationCode.gql
+++ /dev/null
@@ -1,10 +0,0 @@
-type InvitationCode {
- id: ID!
- token: String
- generatedBy: User @relation(name: "GENERATED", direction: "IN")
- createdAt: String
-}
-
-type Mutation {
- CreateInvitationCode: InvitationCode
-}
diff --git a/backend/yarn.lock b/backend/yarn.lock
index 7f0c95a43..8e2ca5446 100644
--- a/backend/yarn.lock
+++ b/backend/yarn.lock
@@ -33,12 +33,12 @@
resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.24.tgz#3ce939cb127fb8aaa3ffc1e90dff9b8af9f2e3dc"
integrity sha512-8GqG48m1XqyXh4mIZrtB5xOhUwSsh1WsrrsaZQOEYYql3YN9DEu9OOSg0ILzXHZo/h2Q74777YE4YzlArQzQEQ==
-"@babel/cli@~7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.7.0.tgz#8d10c9acb2acb362d7614a9493e1791c69100d89"
- integrity sha512-jECEqAq6Ngf3pOhLSg7od9WKyrIacyh1oNNYtRXNn+ummSHCTXBamGywOAtiae34Vk7zKuQNnLvo2BKTMCoV4A==
+"@babel/cli@~7.7.4":
+ version "7.7.4"
+ resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.7.4.tgz#38804334c8db40209f88c69a5c90998e60cca18b"
+ integrity sha512-O7mmzaWdm+VabWQmxuM8hqNrWGGihN83KfhPUzp2lAW4kzIMwBxujXkZbD4fMwKMYY9FXTbDvXsJqU+5XHXi4A==
dependencies:
- commander "^2.8.1"
+ commander "^4.0.1"
convert-source-map "^1.1.0"
fs-readdir-recursive "^1.1.0"
glob "^7.0.0"
@@ -56,18 +56,18 @@
dependencies:
"@babel/highlight" "^7.0.0"
-"@babel/core@^7.1.0", "@babel/core@~7.7.2":
- version "7.7.2"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.2.tgz#ea5b99693bcfc058116f42fa1dd54da412b29d91"
- integrity sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==
+"@babel/core@^7.1.0", "@babel/core@~7.7.4":
+ version "7.7.4"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.4.tgz#37e864532200cb6b50ee9a4045f5f817840166ab"
+ integrity sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ==
dependencies:
"@babel/code-frame" "^7.5.5"
- "@babel/generator" "^7.7.2"
- "@babel/helpers" "^7.7.0"
- "@babel/parser" "^7.7.2"
- "@babel/template" "^7.7.0"
- "@babel/traverse" "^7.7.2"
- "@babel/types" "^7.7.2"
+ "@babel/generator" "^7.7.4"
+ "@babel/helpers" "^7.7.4"
+ "@babel/parser" "^7.7.4"
+ "@babel/template" "^7.7.4"
+ "@babel/traverse" "^7.7.4"
+ "@babel/types" "^7.7.4"
convert-source-map "^1.7.0"
debug "^4.1.0"
json5 "^2.1.0"
@@ -76,17 +76,7 @@
semver "^5.4.1"
source-map "^0.5.0"
-"@babel/generator@^7.4.0", "@babel/generator@^7.7.2":
- version "7.7.2"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af"
- integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==
- dependencies:
- "@babel/types" "^7.7.2"
- jsesc "^2.5.1"
- lodash "^4.17.13"
- source-map "^0.5.0"
-
-"@babel/generator@^7.7.4":
+"@babel/generator@^7.4.0", "@babel/generator@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369"
integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==
@@ -145,15 +135,6 @@
"@babel/traverse" "^7.7.4"
"@babel/types" "^7.7.4"
-"@babel/helper-function-name@^7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3"
- integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==
- dependencies:
- "@babel/helper-get-function-arity" "^7.7.0"
- "@babel/template" "^7.7.0"
- "@babel/types" "^7.7.0"
-
"@babel/helper-function-name@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e"
@@ -163,13 +144,6 @@
"@babel/template" "^7.7.4"
"@babel/types" "^7.7.4"
-"@babel/helper-get-function-arity@^7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d"
- integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==
- dependencies:
- "@babel/types" "^7.7.0"
-
"@babel/helper-get-function-arity@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0"
@@ -258,13 +232,6 @@
"@babel/template" "^7.7.4"
"@babel/types" "^7.7.4"
-"@babel/helper-split-export-declaration@^7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300"
- integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==
- dependencies:
- "@babel/types" "^7.7.0"
-
"@babel/helper-split-export-declaration@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8"
@@ -282,14 +249,14 @@
"@babel/traverse" "^7.7.4"
"@babel/types" "^7.7.4"
-"@babel/helpers@^7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.0.tgz#359bb5ac3b4726f7c1fde0ec75f64b3f4275d60b"
- integrity sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==
+"@babel/helpers@^7.7.4":
+ version "7.7.4"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302"
+ integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg==
dependencies:
- "@babel/template" "^7.7.0"
- "@babel/traverse" "^7.7.0"
- "@babel/types" "^7.7.0"
+ "@babel/template" "^7.7.4"
+ "@babel/traverse" "^7.7.4"
+ "@babel/types" "^7.7.4"
"@babel/highlight@^7.0.0":
version "7.5.0"
@@ -313,12 +280,7 @@
regenerator-runtime "^0.13.3"
v8flags "^3.1.1"
-"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.0", "@babel/parser@^7.7.2":
- version "7.7.2"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.2.tgz#ea8334dc77416bfd9473eb470fd00d8245b3943b"
- integrity sha512-DDaR5e0g4ZTb9aP7cpSZLkACEBdoLGwJDWgHtBhrGX7Q1RjhdoMOfexICj5cqTAtpowjGQWfcvfnQG7G2kAB5w==
-
-"@babel/parser@^7.7.4":
+"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.4.tgz#75ab2d7110c2cf2fa949959afb05fa346d2231bb"
integrity sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==
@@ -364,13 +326,13 @@
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.7.4"
-"@babel/plugin-proposal-throw-expressions@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.2.0.tgz#2d9e452d370f139000e51db65d0a85dc60c64739"
- integrity sha512-adsydM8DQF4i5DLNO4ySAU5VtHTPewOtNBV3u7F4lNMPADFF9bWQ+iDtUUe8+033cYCUz+bFlQdXQJmJOwoLpw==
+"@babel/plugin-proposal-throw-expressions@^7.7.4":
+ version "7.7.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.7.4.tgz#0321bd4acb699abef3006f7cd3d1b2c00daf1b82"
+ integrity sha512-yMcK1dM9Rv+Y5n62rKaHfRoRD4eOWIqYn4uy/Xu7C47rJKaR5JpQR905Hc/OL8EEaGNcEyuvjOtYdNAVXZKDZQ==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
- "@babel/plugin-syntax-throw-expressions" "^7.2.0"
+ "@babel/plugin-syntax-throw-expressions" "^7.7.4"
"@babel/plugin-proposal-unicode-property-regex@^7.7.4":
version "7.7.4"
@@ -415,10 +377,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
-"@babel/plugin-syntax-throw-expressions@^7.2.0":
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-throw-expressions/-/plugin-syntax-throw-expressions-7.2.0.tgz#79001ee2afe1b174b1733cdc2fc69c9a46a0f1f8"
- integrity sha512-ngwynuqu1Rx0JUS9zxSDuPgW1K8TyVZCi2hHehrL4vyjqE7RGoNHWlZsS7KQT2vw9Yjk4YLa0+KldBXTRdPLRg==
+"@babel/plugin-syntax-throw-expressions@^7.7.4":
+ version "7.7.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-throw-expressions/-/plugin-syntax-throw-expressions-7.7.4.tgz#2e1e91485f9a35f1f71547717ccd8407a900092c"
+ integrity sha512-qtLTzzOJ1Co6tQ8pMqnsfRgeUfzExP90Tc6GISTC34O0lR6IDvymWLfVJFcJaQinz6reciQ4auALV3JM+b3D/Q==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
@@ -756,16 +718,7 @@
dependencies:
regenerator-runtime "^0.13.2"
-"@babel/template@^7.4.0", "@babel/template@^7.7.0":
- version "7.7.0"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0"
- integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==
- dependencies:
- "@babel/code-frame" "^7.0.0"
- "@babel/parser" "^7.7.0"
- "@babel/types" "^7.7.0"
-
-"@babel/template@^7.7.4":
+"@babel/template@^7.4.0", "@babel/template@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b"
integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==
@@ -774,22 +727,7 @@
"@babel/parser" "^7.7.4"
"@babel/types" "^7.7.4"
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2":
- version "7.7.2"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09"
- integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==
- dependencies:
- "@babel/code-frame" "^7.5.5"
- "@babel/generator" "^7.7.2"
- "@babel/helper-function-name" "^7.7.0"
- "@babel/helper-split-export-declaration" "^7.7.0"
- "@babel/parser" "^7.7.2"
- "@babel/types" "^7.7.2"
- debug "^4.1.0"
- globals "^11.1.0"
- lodash "^4.17.13"
-
-"@babel/traverse@^7.7.4":
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558"
integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==
@@ -804,7 +742,7 @@
globals "^11.1.0"
lodash "^4.17.13"
-"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.7.0", "@babel/types@^7.7.2", "@babel/types@^7.7.4":
+"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.7.4":
version "7.7.4"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193"
integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==
@@ -879,10 +817,10 @@
"@hapi/hoek" "8.x.x"
"@hapi/topo" "3.x.x"
-"@hapi/joi@^16.1.7":
- version "16.1.7"
- resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-16.1.7.tgz#360857223a87bb1f5f67691537964c1b4908ed93"
- integrity sha512-anaIgnZhNooG3LJLrTFzgGALTiO97zRA1UkvQHm9KxxoSiIzCozB3RCNCpDnfhTJD72QlrHA8nwGmNgpFFCIeg==
+"@hapi/joi@^16.1.8":
+ version "16.1.8"
+ resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-16.1.8.tgz#84c1f126269489871ad4e2decc786e0adef06839"
+ integrity sha512-wAsVvTPe+FwSrsAurNt5vkg3zo+TblvC5Bb1zMVK6SJzZqw9UrJnexxR+76cpePmtUZKHAPxcQ2Bf7oVHyahhg==
dependencies:
"@hapi/address" "^2.1.2"
"@hapi/formula" "^1.2.0"
@@ -1453,10 +1391,10 @@
dependencies:
"@types/yargs-parser" "*"
-"@types/yup@0.26.24":
- version "0.26.24"
- resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.26.24.tgz#c24170b3a5c867b4fabd49fcc42fe45f780cb153"
- integrity sha512-x0bhHnYjH5mZit4HivUYbTMO4LouOTGwp/LLxSL1mbJYVwNJtHYESH0ed2bwM1lkI2yDmsoCDYJnWEgHeJDACg==
+"@types/yup@0.26.26":
+ version "0.26.26"
+ resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.26.26.tgz#2e7065384ac2b7711271d8790f26ac7d73f6a33d"
+ integrity sha512-5cLJLd8NIT7OfJLi7ScquRn/NWfmewBqJ92nT/FYfdpgKzyUNcR4n2BKEOQ7mOG8WuJXgomIvNl5P3sn9Akd4A==
"@types/zen-observable@^0.8.0":
version "0.8.0"
@@ -1693,13 +1631,6 @@ apollo-datasource@^0.6.3:
apollo-server-caching "^0.5.0"
apollo-server-env "^2.4.3"
-apollo-engine-reporting-protobuf@^0.4.3:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.4.3.tgz#c8cf52aa799a2d8fc92bd59c5942bb2989d225aa"
- integrity sha512-ikRiu2PJOOYoTfJ1gAPB58tmVwu8IF71J9u1jWJJ7tLO+RvGOvntA4kwImiKbHrc/zsAx12lPnpjjfn7tOF1AQ==
- dependencies:
- protobufjs "^6.8.6"
-
apollo-engine-reporting-protobuf@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.4.4.tgz#73a064f8c9f2d6605192d1673729c66ec47d9cb7"
@@ -1788,7 +1719,7 @@ apollo-server-caching@^0.5.0:
dependencies:
lru-cache "^5.0.0"
-apollo-server-core@^2.9.11, apollo-server-core@^2.9.12:
+apollo-server-core@^2.9.12:
version "2.9.12"
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.12.tgz#c8ed48540762913242eef5fce0da8b59b131a1e8"
integrity sha512-jhGr2R655PSwUUBweXDl+0F3oa74Elu5xXF+88ymUUej34EwBUCqz97wPqR07BEuyxaAlRfZwPMvKaHhMUKg5g==
@@ -1828,10 +1759,10 @@ apollo-server-errors@^2.3.4:
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.4.tgz#b70ef01322f616cbcd876f3e0168a1a86b82db34"
integrity sha512-Y0PKQvkrb2Kd18d1NPlHdSqmlr8TgqJ7JQcNIfhNDgdb45CnqZlxL1abuIRhr8tiw8OhVOcFxz2KyglBi8TKdA==
-apollo-server-express@^2.9.11, apollo-server-express@^2.9.7:
- version "2.9.11"
- resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.9.11.tgz#ae1b6161a563bc6aa0dd7456deec998236a4234a"
- integrity sha512-38ZaPnahJPnibVii6i983Uu32iGR2xO5kUZvGxqH4lSPiy8V9Ph93TxeTmIlzHUqd8z4CguZsCV+ngd5KT7lFQ==
+apollo-server-express@^2.9.12, apollo-server-express@^2.9.7:
+ version "2.9.12"
+ resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.9.12.tgz#e779ea2c107fcc63b0c9b888a4cbf0f65af6d505"
+ integrity sha512-4Ev8MY7m23mSzwO/BvLTy97a/68IP/wZoCRBn2R81OoZt9/GxlvvYZGvozJCXYsQt1qAbIT4Sn05LmqawsI98w==
dependencies:
"@apollographql/graphql-playground-html" "1.6.24"
"@types/accepts" "^1.3.5"
@@ -1839,8 +1770,8 @@ apollo-server-express@^2.9.11, apollo-server-express@^2.9.7:
"@types/cors" "^2.8.4"
"@types/express" "4.17.1"
accepts "^1.3.5"
- apollo-server-core "^2.9.11"
- apollo-server-types "^0.2.7"
+ apollo-server-core "^2.9.12"
+ apollo-server-types "^0.2.8"
body-parser "^1.18.3"
cors "^2.8.4"
express "^4.17.1"
@@ -1864,15 +1795,6 @@ apollo-server-testing@~2.9.12:
dependencies:
apollo-server-core "^2.9.12"
-apollo-server-types@^0.2.7:
- version "0.2.7"
- resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.2.7.tgz#832760017a9d55beda23bc7ba8af357802ee9b49"
- integrity sha512-umbXyo7DVG6/lZIAL1D666e16+gZM/Y/kfPx2nn9KTSamIJHUDLs2p0es78RuUx2VS8XoKZDgL0BTkIi5Nt8Iw==
- dependencies:
- apollo-engine-reporting-protobuf "^0.4.3"
- apollo-server-caching "^0.5.0"
- apollo-server-env "^2.4.3"
-
apollo-server-types@^0.2.8:
version "0.2.8"
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.2.8.tgz#729208a8dd72831af3aa4f1eb584022ada146e6b"
@@ -1882,13 +1804,13 @@ apollo-server-types@^0.2.8:
apollo-server-caching "^0.5.0"
apollo-server-env "^2.4.3"
-apollo-server@~2.9.11:
- version "2.9.11"
- resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.9.11.tgz#fafa7bc8f758689b0675c3300599a9b1128c58cd"
- integrity sha512-BhMpBqgdEYN2SqjigRyEDUDKN3GwrYXzMZXUv/WD55HaKST8RAP4GiJp8lHswdeoUfr/9fsfvtVlrN++zJziuQ==
+apollo-server@~2.9.12:
+ version "2.9.12"
+ resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.9.12.tgz#3fe28c361ee373d52ae38ca190869508b0c532c0"
+ integrity sha512-Q+qaBTgTxb2vwqyh7NTHs9rOmadbuKw34SgeAOLsCnr3MLVjisa50fL3nQrGbhOGfRaroF8SSZYgya0tvnefig==
dependencies:
- apollo-server-core "^2.9.11"
- apollo-server-express "^2.9.11"
+ apollo-server-core "^2.9.12"
+ apollo-server-express "^2.9.12"
express "^4.0.0"
graphql-subscriptions "^1.0.0"
graphql-tools "^4.0.0"
@@ -2648,6 +2570,11 @@ commander@^3.0.1:
resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e"
integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==
+commander@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-4.0.1.tgz#b67622721785993182e807f4883633e6401ba53c"
+ integrity sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA==
+
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -3407,10 +3334,10 @@ eslint-plugin-import@~2.18.2:
read-pkg-up "^2.0.0"
resolve "^1.11.0"
-eslint-plugin-jest@~23.0.4:
- version "23.0.4"
- resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.0.4.tgz#1ab81ffe3b16c5168efa72cbd4db14d335092aa0"
- integrity sha512-OaP8hhT8chJNodUPvLJ6vl8gnalcsU/Ww1t9oR3HnGdEWjm/DdCCUXLOral+IPGAeWu/EwgVQCK/QtxALpH1Yw==
+eslint-plugin-jest@~23.1.1:
+ version "23.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.1.1.tgz#1220ab53d5a4bf5c3c4cd07c0dabc6199d4064dd"
+ integrity sha512-2oPxHKNh4j1zmJ6GaCBuGcb8FVZU7YjFUOJzGOPnl9ic7VA/MGAskArLJiRIlnFUmi1EUxY+UiATAy8dv8s5JA==
dependencies:
"@typescript-eslint/experimental-utils" "^2.5.0"
@@ -3463,10 +3390,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
-eslint@~6.7.1:
- version "6.7.1"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.1.tgz#269ccccec3ef60ab32358a44d147ac209154b919"
- integrity sha512-UWzBS79pNcsDSxgxbdjkmzn/B6BhsXMfUaOHnNwyE8nD+Q6pyT96ow2MccVayUTV4yMid4qLhMiQaywctRkBLA==
+eslint@~6.7.2:
+ version "6.7.2"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1"
+ integrity sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng==
dependencies:
"@babel/code-frame" "^7.0.0"
ajv "^6.10.0"
@@ -4173,12 +4100,12 @@ graphql-middleware@~4.0.2:
dependencies:
graphql-tools "^4.0.5"
-graphql-shield@~7.0.2:
- version "7.0.2"
- resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.0.2.tgz#65d51528b4e36c4a5023276267abbd1abb57ce0b"
- integrity sha512-ZgCQ9efzgehkIVMFoxaOubnvwHVqthtsIXA+xRu8B4ga2Ch/EHiswNCDKpTXTBQZmjeDCSHeAj4XDmbzR4Trxw==
+graphql-shield@~7.0.4:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.0.4.tgz#fdff8066f9fbb86b363e7dd6a9cf295dbbf8a09b"
+ integrity sha512-+SEz/tKx2uJAbMKzS7X0hCUWsZo54J8SARhXb5jNDG/RKur44mjIGfBnuBRszw73+dUdBvTlLl1j1WKwm0ZhEA==
dependencies:
- "@types/yup" "0.26.24"
+ "@types/yup" "0.26.26"
object-hash "^2.0.0"
yup "^0.27.0"
@@ -6936,25 +6863,6 @@ property-expr@^1.5.0:
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f"
integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==
-protobufjs@^6.8.6:
- version "6.8.8"
- resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.8.tgz#c8b4f1282fd7a90e6f5b109ed11c84af82908e7c"
- integrity sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==
- dependencies:
- "@protobufjs/aspromise" "^1.1.2"
- "@protobufjs/base64" "^1.1.2"
- "@protobufjs/codegen" "^2.0.4"
- "@protobufjs/eventemitter" "^1.1.0"
- "@protobufjs/fetch" "^1.1.0"
- "@protobufjs/float" "^1.0.2"
- "@protobufjs/inquire" "^1.1.0"
- "@protobufjs/path" "^1.1.2"
- "@protobufjs/pool" "^1.1.0"
- "@protobufjs/utf8" "^1.1.0"
- "@types/long" "^4.0.0"
- "@types/node" "^10.1.0"
- long "^4.0.0"
-
proxy-addr@~2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34"
diff --git a/neo4j/Dockerfile b/neo4j/Dockerfile
index 5d4827586..a180a18a2 100644
--- a/neo4j/Dockerfile
+++ b/neo4j/Dockerfile
@@ -1,4 +1,4 @@
-FROM neo4j:3.5.12-enterprise
+FROM neo4j:3.5.13-enterprise
LABEL Description="Neo4J database of the Social Network Human-Connection.org with preinstalled database constraints and indices" Vendor="Human Connection gGmbH" Version="0.0.1" Maintainer="Human Connection gGmbH (developer@human-connection.org)"
ARG BUILD_COMMIT
diff --git a/package.json b/package.json
index d403bfe5b..2c1793041 100644
--- a/package.json
+++ b/package.json
@@ -23,10 +23,10 @@
"bcryptjs": "^2.4.3",
"codecov": "^3.6.1",
"cross-env": "^6.0.3",
- "cypress": "^3.6.1",
- "cypress-cucumber-preprocessor": "^1.16.2",
+ "cypress": "^3.7.0",
+ "cypress-cucumber-preprocessor": "^1.17.0",
"cypress-file-upload": "^3.5.0",
- "cypress-plugin-retries": "^1.4.0",
+ "cypress-plugin-retries": "^1.5.0",
"date-fns": "^2.8.1",
"dotenv": "^8.2.0",
"faker": "Marak/faker.js#master",
diff --git a/webapp/.babelrc b/webapp/.babelrc
index b23873e12..4538e0ac0 100644
--- a/webapp/.babelrc
+++ b/webapp/.babelrc
@@ -12,6 +12,7 @@
],
"env": {
"test": {
+ "plugins": ["require-context-hook"],
"presets": [
[
"@babel/preset-env",
@@ -24,4 +25,4 @@
]
}
}
-}
\ No newline at end of file
+}
diff --git a/webapp/README.md b/webapp/README.md
index def0b739e..185557fc7 100644
--- a/webapp/README.md
+++ b/webapp/README.md
@@ -92,15 +92,15 @@ You can then visit the Storybook playground on `http://localhost:3002`
## Styleguide Migration
-We are currently in the process of migrating our styleguide components and design tokens from the [Nitro Styleguide](https://github.com/Human-Connection/Nitro-Styleguide) into the main [Human Connection repository](https://github.com/Human-Connection/Human-Connection) and refactoring our components in the process. During this migration, our new components will live in a `view` folder to separate them from the old, yet untouched components.
+We are currently in the process of migrating our styleguide components and design tokens from the [Nitro Styleguide](https://github.com/Human-Connection/Nitro-Styleguide) into the main [Human Connection repository](https://github.com/Human-Connection/Human-Connection) and refactoring our components in the process. During this migration, our new components will live in a `_new/` folder to separate them from the old, yet untouched components.
### Folder Structure
-The folder structure we are aiming for is based on the [directory setup proposed by Nuxt.js](https://nuxtjs.org/guide/directory-structure):
+The folder structure we are following is [prescribed by Nuxt.js](https://nuxtjs.org/guide/directory-structure):
-- **assets** contains icons, images and logos in `svg` format
-- **components** are the generic building blocks of the app – small, reusable and usually not coupled to state
-- **features** are composed of components but tied to a particular function of the app (e.g. `comment` or `post`)
+- **assets** contains icons, images and logos in `svg` format and all shared SCSS files such as `tokens`
+- **components** separated into two sub-folders:
+ - **generic** are the generic building blocks of the app – small, reusable and usually not coupled to state
+ - **features** are composed of components but tied to a particular function of the app (e.g. `comment` or `post`)
- **layouts** can use components to create layout templates for pages
- **pages** are the entry points for all `routes` in the app and are composed of layouts, features and components
-- **styles** holds all shared SCSS files such as `variables` and `mixins`
diff --git a/webapp/assets/_new/icons/index.js b/webapp/assets/_new/icons/index.js
new file mode 100644
index 000000000..daa0714f2
--- /dev/null
+++ b/webapp/assets/_new/icons/index.js
@@ -0,0 +1,13 @@
+const svgFileList = require.context('./svgs', true, /\.svg/)
+const icons = {}
+const iconNames = []
+
+svgFileList.keys().forEach(fileName => {
+ const svgCode = svgFileList(fileName)
+ const iconName = fileName.replace('./', '').replace('.svg', '')
+ icons[iconName] = svgCode
+ iconNames.push(iconName)
+})
+
+export { iconNames }
+export default icons
diff --git a/webapp/assets/_new/icons/svgs/angellist.svg b/webapp/assets/_new/icons/svgs/angellist.svg
new file mode 100755
index 000000000..34123f5f0
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/angellist.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/angle-down.svg b/webapp/assets/_new/icons/svgs/angle-down.svg
new file mode 100755
index 000000000..aa6f763c8
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/angle-down.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/arrow-down.svg b/webapp/assets/_new/icons/svgs/arrow-down.svg
new file mode 100755
index 000000000..6cee34766
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/arrow-down.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/arrow-left.svg b/webapp/assets/_new/icons/svgs/arrow-left.svg
new file mode 100755
index 000000000..f7489c43a
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/arrow-left.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/arrow-right.svg b/webapp/assets/_new/icons/svgs/arrow-right.svg
new file mode 100755
index 000000000..62d753057
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/arrow-right.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/at.svg b/webapp/assets/_new/icons/svgs/at.svg
new file mode 100755
index 000000000..e046ea75a
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/at.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/balance-scale.svg b/webapp/assets/_new/icons/svgs/balance-scale.svg
new file mode 100755
index 000000000..f5e446fd2
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/balance-scale.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/ban.svg b/webapp/assets/_new/icons/svgs/ban.svg
new file mode 100755
index 000000000..7dc338541
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/ban.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/bars.svg b/webapp/assets/_new/icons/svgs/bars.svg
new file mode 100755
index 000000000..5ea0f464d
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/bars.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/bell.svg b/webapp/assets/_new/icons/svgs/bell.svg
new file mode 100755
index 000000000..ee58c443c
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/bell.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/bold.svg b/webapp/assets/_new/icons/svgs/bold.svg
new file mode 100755
index 000000000..c3516808d
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/bold.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/bookmark.svg b/webapp/assets/_new/icons/svgs/bookmark.svg
new file mode 100755
index 000000000..bd3ff4559
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/bookmark.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/bullhorn.svg b/webapp/assets/_new/icons/svgs/bullhorn.svg
new file mode 100755
index 000000000..95e0d21d3
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/bullhorn.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/check.svg b/webapp/assets/_new/icons/svgs/check.svg
new file mode 100755
index 000000000..bf49fe01d
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/check.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/clock.svg b/webapp/assets/_new/icons/svgs/clock.svg
new file mode 100755
index 000000000..2344dd890
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/clock.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/close.svg b/webapp/assets/_new/icons/svgs/close.svg
new file mode 100755
index 000000000..48604d097
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/close.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/cogs.svg b/webapp/assets/_new/icons/svgs/cogs.svg
new file mode 100755
index 000000000..3d0104d19
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/cogs.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/comment.svg b/webapp/assets/_new/icons/svgs/comment.svg
new file mode 100755
index 000000000..fe848ec20
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/comment.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/comments.svg b/webapp/assets/_new/icons/svgs/comments.svg
new file mode 100755
index 000000000..551f10e4e
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/comments.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/edit.svg b/webapp/assets/_new/icons/svgs/edit.svg
new file mode 100755
index 000000000..a80101e6c
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/edit.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/ellipsis-v.svg b/webapp/assets/_new/icons/svgs/ellipsis-v.svg
new file mode 100755
index 000000000..89313ddfd
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/ellipsis-v.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/envelope.svg b/webapp/assets/_new/icons/svgs/envelope.svg
new file mode 100755
index 000000000..92d5320c0
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/envelope.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/exclamation-circle.svg b/webapp/assets/_new/icons/svgs/exclamation-circle.svg
new file mode 100755
index 000000000..cd658b997
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/exclamation-circle.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/eye-slash.svg b/webapp/assets/_new/icons/svgs/eye-slash.svg
new file mode 100755
index 000000000..4e434ac8d
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/eye-slash.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/eye.svg b/webapp/assets/_new/icons/svgs/eye.svg
new file mode 100755
index 000000000..1e3e8fef3
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/eye.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/file.svg b/webapp/assets/_new/icons/svgs/file.svg
new file mode 100755
index 000000000..82d36fe17
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/file.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/filter.svg b/webapp/assets/_new/icons/svgs/filter.svg
new file mode 100755
index 000000000..6e9f379b6
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/filter.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/flag.svg b/webapp/assets/_new/icons/svgs/flag.svg
new file mode 100755
index 000000000..6d2769808
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/flag.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/flash.svg b/webapp/assets/_new/icons/svgs/flash.svg
new file mode 100755
index 000000000..f3647d420
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/flash.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/globe.svg b/webapp/assets/_new/icons/svgs/globe.svg
new file mode 100755
index 000000000..91bf9bf2b
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/globe.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/graduation-cap.svg b/webapp/assets/_new/icons/svgs/graduation-cap.svg
new file mode 100755
index 000000000..5d35226d3
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/graduation-cap.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/heart-o.svg b/webapp/assets/_new/icons/svgs/heart-o.svg
new file mode 100755
index 000000000..6605b96ac
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/heart-o.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/image.svg b/webapp/assets/_new/icons/svgs/image.svg
new file mode 100755
index 000000000..efbd9131f
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/image.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/italic.svg b/webapp/assets/_new/icons/svgs/italic.svg
new file mode 100755
index 000000000..81d29483c
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/italic.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/link.svg b/webapp/assets/_new/icons/svgs/link.svg
new file mode 100755
index 000000000..624a255b1
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/link.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/list-ol.svg b/webapp/assets/_new/icons/svgs/list-ol.svg
new file mode 100755
index 000000000..f3fb101ac
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/list-ol.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/list-ul.svg b/webapp/assets/_new/icons/svgs/list-ul.svg
new file mode 100755
index 000000000..d565a8064
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/list-ul.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/lock.svg b/webapp/assets/_new/icons/svgs/lock.svg
new file mode 100755
index 000000000..31813d729
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/lock.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/map-marker.svg b/webapp/assets/_new/icons/svgs/map-marker.svg
new file mode 100755
index 000000000..af7f96727
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/map-marker.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/medkit.svg b/webapp/assets/_new/icons/svgs/medkit.svg
new file mode 100755
index 000000000..43076dc9c
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/medkit.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/minus.svg b/webapp/assets/_new/icons/svgs/minus.svg
new file mode 100755
index 000000000..b7a94beb1
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/minus.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/money.svg b/webapp/assets/_new/icons/svgs/money.svg
new file mode 100755
index 000000000..04a116d2a
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/money.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/mouse-pointer.svg b/webapp/assets/_new/icons/svgs/mouse-pointer.svg
new file mode 100755
index 000000000..2917ef518
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/mouse-pointer.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/paint-brush.svg b/webapp/assets/_new/icons/svgs/paint-brush.svg
new file mode 100755
index 000000000..03b06aac6
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/paint-brush.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/paragraph.svg b/webapp/assets/_new/icons/svgs/paragraph.svg
new file mode 100755
index 000000000..26365f984
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/paragraph.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/paw.svg b/webapp/assets/_new/icons/svgs/paw.svg
new file mode 100755
index 000000000..364ff1918
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/paw.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/plus.svg b/webapp/assets/_new/icons/svgs/plus.svg
new file mode 100755
index 000000000..66da52005
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/plus.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/question-circle.svg b/webapp/assets/_new/icons/svgs/question-circle.svg
new file mode 100755
index 000000000..1ae2bbf6b
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/question-circle.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/quote-right.svg b/webapp/assets/_new/icons/svgs/quote-right.svg
new file mode 100755
index 000000000..4e6469624
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/quote-right.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/search.svg b/webapp/assets/_new/icons/svgs/search.svg
new file mode 100755
index 000000000..ddbb4da44
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/search.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/shield.svg b/webapp/assets/_new/icons/svgs/shield.svg
new file mode 100755
index 000000000..d897203ad
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/shield.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/shopping-cart.svg b/webapp/assets/_new/icons/svgs/shopping-cart.svg
new file mode 100755
index 000000000..9ca3c5e13
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/shopping-cart.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/sign-in.svg b/webapp/assets/_new/icons/svgs/sign-in.svg
new file mode 100755
index 000000000..bb300f950
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/sign-in.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/sign-out.svg b/webapp/assets/_new/icons/svgs/sign-out.svg
new file mode 100755
index 000000000..d185fbe6f
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/sign-out.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/smile.svg b/webapp/assets/_new/icons/svgs/smile.svg
new file mode 100755
index 000000000..7de0ac746
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/smile.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/sort-amount-asc.svg b/webapp/assets/_new/icons/svgs/sort-amount-asc.svg
new file mode 100755
index 000000000..6344da1a9
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/sort-amount-asc.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/sort-amount-desc.svg b/webapp/assets/_new/icons/svgs/sort-amount-desc.svg
new file mode 100755
index 000000000..7239c1d72
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/sort-amount-desc.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/trash.svg b/webapp/assets/_new/icons/svgs/trash.svg
new file mode 100755
index 000000000..6475fd236
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/trash.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/tree.svg b/webapp/assets/_new/icons/svgs/tree.svg
new file mode 100755
index 000000000..e0534af45
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/tree.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/university.svg b/webapp/assets/_new/icons/svgs/university.svg
new file mode 100755
index 000000000..cddb5775a
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/university.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/unlink.svg b/webapp/assets/_new/icons/svgs/unlink.svg
new file mode 100755
index 000000000..f63b36e9b
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/unlink.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/user-plus.svg b/webapp/assets/_new/icons/svgs/user-plus.svg
new file mode 100755
index 000000000..dea6ab228
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/user-plus.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/user-times.svg b/webapp/assets/_new/icons/svgs/user-times.svg
new file mode 100755
index 000000000..8f4cb905a
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/user-times.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/user.svg b/webapp/assets/_new/icons/svgs/user.svg
new file mode 100755
index 000000000..04cc45b41
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/user.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/users.svg b/webapp/assets/_new/icons/svgs/users.svg
new file mode 100755
index 000000000..7572021ba
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/users.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/assets/_new/icons/svgs/warning.svg b/webapp/assets/_new/icons/svgs/warning.svg
new file mode 100755
index 000000000..cd0a7baed
--- /dev/null
+++ b/webapp/assets/_new/icons/svgs/warning.svg
@@ -0,0 +1,5 @@
+
+
diff --git a/webapp/view/styles/tokens.scss b/webapp/assets/_new/styles/tokens.scss
similarity index 100%
rename from webapp/view/styles/tokens.scss
rename to webapp/assets/_new/styles/tokens.scss
diff --git a/webapp/assets/styles/main.scss b/webapp/assets/styles/main.scss
index 5c4964688..b59399b02 100644
--- a/webapp/assets/styles/main.scss
+++ b/webapp/assets/styles/main.scss
@@ -160,7 +160,7 @@ hr {
align-content: center;
align-items: center;
- .ds-icon {
+ .base-icon {
padding-right: $space-xx-small;
}
}
diff --git a/webapp/components/Avatar/Avatar.spec.js b/webapp/components/Avatar/Avatar.spec.js
index 626e584c9..03eaee160 100644
--- a/webapp/components/Avatar/Avatar.spec.js
+++ b/webapp/components/Avatar/Avatar.spec.js
@@ -1,11 +1,7 @@
-import { mount, createLocalVue } from '@vue/test-utils'
-import Styleguide from '@human-connection/styleguide'
+import { mount } from '@vue/test-utils'
import Avatar from './Avatar.vue'
-import Filters from '~/plugins/vue-filters'
-const localVue = createLocalVue()
-localVue.use(Styleguide)
-localVue.use(Filters)
+const localVue = global.localVue
describe('Avatar.vue', () => {
let propsData = {}
@@ -22,6 +18,7 @@ describe('Avatar.vue', () => {
).toBe(false)
})
+ // this is testing the style guide
it('renders an icon', () => {
expect(
Wrapper()
diff --git a/webapp/components/AvatarMenu/AvatarMenu.spec.js b/webapp/components/AvatarMenu/AvatarMenu.spec.js
index 6327ded0a..519b61d00 100644
--- a/webapp/components/AvatarMenu/AvatarMenu.spec.js
+++ b/webapp/components/AvatarMenu/AvatarMenu.spec.js
@@ -1,15 +1,8 @@
-import { config, mount, createLocalVue } from '@vue/test-utils'
+import { config, mount } from '@vue/test-utils'
import Vuex from 'vuex'
-import VTooltip from 'v-tooltip'
-import Styleguide from '@human-connection/styleguide'
import AvatarMenu from './AvatarMenu.vue'
-import Filters from '~/plugins/vue-filters'
-const localVue = createLocalVue()
-localVue.use(Styleguide)
-localVue.use(Vuex)
-localVue.use(Filters)
-localVue.use(VTooltip)
+const localVue = global.localVue
config.stubs['nuxt-link'] = ''
config.stubs['router-link'] = ''
diff --git a/webapp/components/AvatarMenu/AvatarMenu.vue b/webapp/components/AvatarMenu/AvatarMenu.vue
index 7443c91a7..54426852e 100644
--- a/webapp/components/AvatarMenu/AvatarMenu.vue
+++ b/webapp/components/AvatarMenu/AvatarMenu.vue
@@ -12,7 +12,7 @@
@click.prevent="toggleMenu"
>
-
+
@@ -33,13 +33,13 @@
:parents="item.parents"
@click.native="closeMenu(false)"
>
-
+
{{ item.route.name }}
-
+
{{ $t('login.logout') }}
diff --git a/webapp/components/CategoriesSelect/CategoriesSelect.spec.js b/webapp/components/CategoriesSelect/CategoriesSelect.spec.js
index 56534c6ad..b633e5811 100644
--- a/webapp/components/CategoriesSelect/CategoriesSelect.spec.js
+++ b/webapp/components/CategoriesSelect/CategoriesSelect.spec.js
@@ -1,9 +1,7 @@
-import { mount, createLocalVue } from '@vue/test-utils'
+import { mount } from '@vue/test-utils'
import CategoriesSelect from './CategoriesSelect'
-import Styleguide from '@human-connection/styleguide'
-const localVue = createLocalVue()
-localVue.use(Styleguide)
+const localVue = global.localVue
describe('CategoriesSelect.vue', () => {
let wrapper
diff --git a/webapp/components/CategoriesSelect/CategoriesSelect.vue b/webapp/components/CategoriesSelect/CategoriesSelect.vue
index 1fdb3ce0a..493256546 100644
--- a/webapp/components/CategoriesSelect/CategoriesSelect.vue
+++ b/webapp/components/CategoriesSelect/CategoriesSelect.vue
@@ -10,7 +10,7 @@
:primary="isActive(category.id)"
:disabled="isDisabled(category.id)"
>
-
+
{{ $t(`contribution.category.name.${category.slug}`) }}
diff --git a/webapp/components/Category/index.spec.js b/webapp/components/Category/index.spec.js
index 13de0b690..9abb8a11d 100644
--- a/webapp/components/Category/index.spec.js
+++ b/webapp/components/Category/index.spec.js
@@ -1,9 +1,8 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils'
-import Styleguide from '@human-connection/styleguide'
+import { shallowMount } from '@vue/test-utils'
+
import Category from './index'
-const localVue = createLocalVue()
-localVue.use(Styleguide)
+const localVue = global.localVue
describe('Category', () => {
let icon
@@ -21,7 +20,7 @@ describe('Category', () => {
describe('given Strings for Icon and Name', () => {
beforeEach(() => {
- icon = 'mouse-cursor'
+ icon = 'mouse-pointer'
name = 'Peter'
})
diff --git a/webapp/components/Category/index.vue b/webapp/components/Category/index.vue
index acc35772a..a6410d750 100644
--- a/webapp/components/Category/index.vue
+++ b/webapp/components/Category/index.vue
@@ -1,6 +1,6 @@
-
-
+
+
{{ name }}
@@ -14,3 +14,15 @@ export default {
},
}
+
+
diff --git a/webapp/components/Comment/Comment.spec.js b/webapp/components/Comment/Comment.spec.js
index 59e3f6c5a..b307700d9 100644
--- a/webapp/components/Comment/Comment.spec.js
+++ b/webapp/components/Comment/Comment.spec.js
@@ -1,12 +1,8 @@
-import { config, shallowMount, createLocalVue } from '@vue/test-utils'
+import { config, shallowMount } from '@vue/test-utils'
import Comment from './Comment.vue'
import Vuex from 'vuex'
-import Styleguide from '@human-connection/styleguide'
-const localVue = createLocalVue()
-
-localVue.use(Vuex)
-localVue.use(Styleguide)
+const localVue = global.localVue
config.stubs['client-only'] = ''
diff --git a/webapp/components/Comment/Comment.vue b/webapp/components/Comment/Comment.vue
index 2da0df5fa..cc7f815b9 100644
--- a/webapp/components/Comment/Comment.vue
+++ b/webapp/components/Comment/Comment.vue
@@ -3,7 +3,7 @@
-
+
{{ this.$t('comment.content.unavailable-placeholder') }}
@@ -62,7 +62,7 @@
import { mapGetters } from 'vuex'
import { COMMENT_MAX_UNTRUNCATED_LENGTH, COMMENT_TRUNCATE_TO_LENGTH } from '~/constants/comment'
import HcUser from '~/components/User/User'
-import ContentMenu from '~/components/ContentMenu'
+import ContentMenu from '~/components/ContentMenu/ContentMenu'
import ContentViewer from '~/components/Editor/ContentViewer'
import HcCommentForm from '~/components/CommentForm/CommentForm'
import CommentMutations from '~/graphql/CommentMutations'
diff --git a/webapp/components/CommentForm/CommentForm.spec.js b/webapp/components/CommentForm/CommentForm.spec.js
index 94ce5aa66..47bc01982 100644
--- a/webapp/components/CommentForm/CommentForm.spec.js
+++ b/webapp/components/CommentForm/CommentForm.spec.js
@@ -1,12 +1,11 @@
-import { mount, createLocalVue } from '@vue/test-utils'
+import { mount } from '@vue/test-utils'
import CommentForm from './CommentForm'
-import Styleguide from '@human-connection/styleguide'
+
import MutationObserver from 'mutation-observer'
global.MutationObserver = MutationObserver
-const localVue = createLocalVue()
-localVue.use(Styleguide)
+const localVue = global.localVue
describe('CommentForm.vue', () => {
let mocks
diff --git a/webapp/components/CommentList/CommentList.spec.js b/webapp/components/CommentList/CommentList.spec.js
index 3287b7cd4..0c037d2ff 100644
--- a/webapp/components/CommentList/CommentList.spec.js
+++ b/webapp/components/CommentList/CommentList.spec.js
@@ -1,14 +1,9 @@
-import { config, mount, createLocalVue } from '@vue/test-utils'
+import { config, mount } from '@vue/test-utils'
import CommentList from './CommentList'
import Vuex from 'vuex'
-import Styleguide from '@human-connection/styleguide'
-import Filters from '~/plugins/vue-filters'
-const localVue = createLocalVue()
+const localVue = global.localVue
-localVue.use(Styleguide)
-localVue.use(Vuex)
-localVue.use(Filters)
localVue.filter('truncate', string => string)
config.stubs['v-popover'] = ''
diff --git a/webapp/components/CommentList/CommentList.vue b/webapp/components/CommentList/CommentList.vue
index df008e9ee..888c167e9 100644
--- a/webapp/components/CommentList/CommentList.vue
+++ b/webapp/components/CommentList/CommentList.vue
@@ -2,7 +2,7 @@
-
+
'
+
+let getters, mutations, mocks, menuToggle, openModalSpy
+
+describe('ContentMenu.vue', () => {
+ beforeEach(() => {
+ mocks = {
+ $t: jest.fn(str => str),
+ $i18n: {
+ locale: () => 'en',
+ },
+ $router: {
+ resolve: jest.fn(obj => {
+ obj.href = '/post/edit/d23a4265-f5f7-4e17-9f86-85f714b4b9f8'
+ return obj
+ }),
+ push: jest.fn(),
+ },
+ }
+ })
+
+ describe('mount', () => {
+ mutations = {
+ 'modal/SET_OPEN': jest.fn(),
+ }
+ getters = {
+ 'auth/isModerator': () => false,
+ 'auth/isAdmin': () => false,
+ }
+
+ const openContentMenu = (values = {}) => {
+ const store = new Vuex.Store({ mutations, getters })
+ const wrapper = mount(ContentMenu, {
+ propsData: {
+ ...values,
+ },
+ mocks,
+ store,
+ localVue,
+ })
+ menuToggle = wrapper.find('.content-menu-trigger')
+ menuToggle.trigger('click')
+ return wrapper
+ }
+
+ describe('owner of contribution', () => {
+ let wrapper
+ beforeEach(() => {
+ wrapper = openContentMenu({
+ isOwner: true,
+ resourceType: 'contribution',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ })
+
+ it('can edit the contribution', () => {
+ expect(
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'post.menu.edit')
+ .at(0)
+ .find('span.ds-menu-item-link')
+ .attributes('to'),
+ ).toBe('/post/edit/d23a4265-f5f7-4e17-9f86-85f714b4b9f8')
+ })
+
+ it('can delete the contribution', () => {
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'post.menu.delete')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('delete')
+ })
+ })
+
+ describe('admin can', () => {
+ it('pin unpinned post', () => {
+ getters['auth/isAdmin'] = () => true
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'contribution',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ pinnedBy: null,
+ },
+ })
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'post.menu.pin')
+ .at(0)
+ .trigger('click')
+ expect(wrapper.emitted('pinPost')).toEqual([
+ [
+ {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ pinnedBy: null,
+ },
+ ],
+ ])
+ })
+
+ it('unpin pinned post', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'contribution',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ pinnedBy: 'someone',
+ },
+ })
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'post.menu.unpin')
+ .at(0)
+ .trigger('click')
+ expect(wrapper.emitted('unpinPost')).toEqual([
+ [
+ {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ pinnedBy: 'someone',
+ },
+ ],
+ ])
+ })
+ })
+
+ describe('owner of comment can', () => {
+ let wrapper
+ beforeEach(() => {
+ wrapper = openContentMenu({
+ isOwner: true,
+ resourceType: 'comment',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ })
+ it('edit the comment', () => {
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'comment.menu.edit')
+ .at(0)
+ .trigger('click')
+ expect(wrapper.emitted('showEditCommentMenu')).toEqual([[true]])
+ })
+ it('delete the comment', () => {
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'comment.menu.delete')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('delete')
+ })
+ })
+
+ describe('reporting', () => {
+ it('a post of another user is possible', () => {
+ getters['auth/isAdmin'] = () => false
+ getters['auth/isModerator'] = () => false
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'contribution',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'report.contribution.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('report')
+ })
+
+ it('a comment of another user is possible', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'comment',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'report.comment.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('report')
+ })
+
+ it('another user is possible', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'user',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'report.user.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('report')
+ })
+
+ it('another organization is possible', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'organization',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'report.organization.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('report')
+ })
+ })
+
+ describe('moderator', () => {
+ it('can disable posts', () => {
+ getters['auth/isAdmin'] = () => false
+ getters['auth/isModerator'] = () => true
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'contribution',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ disabled: false,
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'disable.contribution.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('disable')
+ })
+
+ it('can disable comments', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'comment',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ disabled: false,
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'disable.comment.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('disable')
+ })
+
+ it('can disable users', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'user',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ disabled: false,
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'disable.user.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('disable')
+ })
+
+ it('can disable organizations', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'organization',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ disabled: false,
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'disable.organization.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('disable')
+ })
+
+ it('can release posts', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'contribution',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ disabled: true,
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'release.contribution.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('release', 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8')
+ })
+
+ it('can release comments', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'comment',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ disabled: true,
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'release.comment.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('release', 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8')
+ })
+
+ it('can release users', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'user',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ disabled: true,
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'release.user.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('release', 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8')
+ })
+
+ it('can release organizations', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'organization',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ disabled: true,
+ },
+ })
+ openModalSpy = jest.spyOn(wrapper.vm, 'openModal')
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'release.organization.title')
+ .at(0)
+ .trigger('click')
+ expect(openModalSpy).toHaveBeenCalledWith('release', 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8')
+ })
+ })
+
+ describe('user', () => {
+ it('can access settings', () => {
+ getters['auth/isAdmin'] = () => false
+ getters['auth/isModerator'] = () => false
+ const wrapper = openContentMenu({
+ isOwner: true,
+ resourceType: 'user',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ },
+ })
+ expect(
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'settings.name')
+ .at(0)
+ .find('span.ds-menu-item-link')
+ .attributes('to'),
+ ).toBe('/settings')
+ })
+
+ it('can block other users', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'user',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ isBlocked: false,
+ },
+ })
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'settings.blocked-users.block')
+ .at(0)
+ .trigger('click')
+ expect(wrapper.emitted('block')).toEqual([
+ [
+ {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ isBlocked: false,
+ },
+ ],
+ ])
+ })
+
+ it('can unblock blocked users', () => {
+ const wrapper = openContentMenu({
+ isOwner: false,
+ resourceType: 'user',
+ resource: {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ isBlocked: true,
+ },
+ })
+ wrapper
+ .findAll('.ds-menu-item')
+ .filter(item => item.text() === 'settings.blocked-users.unblock')
+ .at(0)
+ .trigger('click')
+ expect(wrapper.emitted('unblock')).toEqual([
+ [
+ {
+ id: 'd23a4265-f5f7-4e17-9f86-85f714b4b9f8',
+ isBlocked: true,
+ },
+ ],
+ ])
+ })
+ })
+ })
+})
diff --git a/webapp/components/ContentMenu.vue b/webapp/components/ContentMenu/ContentMenu.vue
similarity index 98%
rename from webapp/components/ContentMenu.vue
rename to webapp/components/ContentMenu/ContentMenu.vue
index 72b514ce2..f0d9dc8d3 100644
--- a/webapp/components/ContentMenu.vue
+++ b/webapp/components/ContentMenu/ContentMenu.vue
@@ -3,7 +3,7 @@
-
+
@@ -16,7 +16,7 @@
:parents="item.parents"
@click.stop.prevent="openItem(item.route, toggleMenu)"
>
-
+
{{ item.route.name }}
diff --git a/webapp/components/ContributionForm/ContributionForm.spec.js b/webapp/components/ContributionForm/ContributionForm.spec.js
index 603724eca..3815fd4e4 100644
--- a/webapp/components/ContributionForm/ContributionForm.spec.js
+++ b/webapp/components/ContributionForm/ContributionForm.spec.js
@@ -1,20 +1,16 @@
-import { config, mount, createLocalVue } from '@vue/test-utils'
+import { config, mount } from '@vue/test-utils'
import ContributionForm from './ContributionForm.vue'
-import Styleguide from '@human-connection/styleguide'
+
import Vuex from 'vuex'
import PostMutations from '~/graphql/PostMutations.js'
import CategoriesSelect from '~/components/CategoriesSelect/CategoriesSelect'
-import Filters from '~/plugins/vue-filters'
+
import TeaserImage from '~/components/TeaserImage/TeaserImage'
import MutationObserver from 'mutation-observer'
global.MutationObserver = MutationObserver
-const localVue = createLocalVue()
-
-localVue.use(Vuex)
-localVue.use(Styleguide)
-localVue.use(Filters)
+const localVue = global.localVue
config.stubs['client-only'] = ' '
config.stubs['nuxt-link'] = ' '
diff --git a/webapp/components/DeleteData/DeleteData.spec.js b/webapp/components/DeleteData/DeleteData.spec.js
index 73ca985fa..abcdf9101 100644
--- a/webapp/components/DeleteData/DeleteData.spec.js
+++ b/webapp/components/DeleteData/DeleteData.spec.js
@@ -1,12 +1,9 @@
-import { mount, createLocalVue } from '@vue/test-utils'
+import { mount } from '@vue/test-utils'
import DeleteData from './DeleteData.vue'
-import Styleguide from '@human-connection/styleguide'
+
import Vuex from 'vuex'
-const localVue = createLocalVue()
-
-localVue.use(Vuex)
-localVue.use(Styleguide)
+const localVue = global.localVue
describe('DeleteData.vue', () => {
let mocks
diff --git a/webapp/components/DeleteData/DeleteData.vue b/webapp/components/DeleteData/DeleteData.vue
index 451a44eb4..045d00f26 100644
--- a/webapp/components/DeleteData/DeleteData.vue
+++ b/webapp/components/DeleteData/DeleteData.vue
@@ -5,7 +5,7 @@
-
+
{{ $t('settings.deleteUserAccount.name') }}
@@ -134,6 +134,7 @@ export default {
diff --git a/webapp/components/utils/NormalizeEmail.js b/webapp/components/utils/NormalizeEmail.js
new file mode 100644
index 000000000..f79c5118b
--- /dev/null
+++ b/webapp/components/utils/NormalizeEmail.js
@@ -0,0 +1,11 @@
+import { normalizeEmail } from 'validator'
+
+export default email =>
+ normalizeEmail(email, {
+ // gmail_remove_dots: false, default
+ gmail_remove_subaddress: false,
+ // gmail_convert_googlemaildotcom: true, default
+ outlookdotcom_remove_subaddress: false,
+ yahoo_remove_subaddress: false,
+ icloud_remove_subaddress: false,
+ })
diff --git a/webapp/locales/de.json b/webapp/locales/de.json
index fc40276c2..33bf43ea7 100644
--- a/webapp/locales/de.json
+++ b/webapp/locales/de.json
@@ -737,6 +737,10 @@
"title": "Fehler und Rückmeldungen",
"description": "Wir sind sehr bemüht, unser Netzwerk und unsere Daten sicher und abrufbar zu erhalten. Jede neue Version der Software durchläuft sowohl automatisierte als auch manuelle Tests. Es können jedoch unvorhergesehene Fehler auftreten. Deshalb sind wir dankbar für jeden gemeldeten Fehler. Du kannst gerne jeden von Dir entdeckten Fehler dem Support\/der Hilfe-Assistenz mitteilen: support@human-connection.org"
},
+ "no-commercial-use" : {
+ "title": "Keine kommerzielle Nutzung",
+ "description": "Die Nutzung des Human Connection Netzwerkes ist nicht gestattet für kommerzielle Nutzung. Darunter fällt unter anderem das Bewerben von Produkten mit kommerzieller Absicht, das Einstellen von Affiliate-Links, direkter Aufruf zu Spenden oder finanzieller Unterstützung für Zwecke, die steuerlich nicht als gemeinnützig anerkannt sind."
+ },
"help-and-questions": {
"title": "Hilfe und Fragen",
"description": "Für Hilfe und Fragen haben wir Dir eine umfassende Sammlung an häufig gestellten Fragen und Antworten (FAQ) zusammengestellt. Du findest diese hier: https:\/\/support.human-connection.org\/kb\/ <\/a>"
diff --git a/webapp/locales/en.json b/webapp/locales/en.json
index bf2af3058..c85a0e51a 100644
--- a/webapp/locales/en.json
+++ b/webapp/locales/en.json
@@ -729,6 +729,10 @@
"title": "Errors and Feedback",
"description": "We make every effort to keep our network and data secure and available. Each new release of the software goes through both automated and manual testing. However, unforeseen errors may occur. Therefore, we are grateful for any reported bugs. You are welcome to report any bugs you discover by emailing Support at support@human-connection.org"
},
+ "no-commercial-use" : {
+ "title": "No Commercial Use",
+ "description": "The use of the Human Connection Network is not permitted for commercial purposes. This includes, but is not limited to, advertising products with commercial intent, posting affiliate links, directly soliciting donations, or providing financial support for purposes that are not recognized as charitable for tax purposes."
+ },
"help-and-questions" : {
"title": "Help and Questions",
"description": "For help and questions we have compiled a comprehensive collection of frequently asked questions and answers (FAQ) for you. You can find them here: https://support.human-connection.org/kb/ "
diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json
index ecad7851b..c8a2952b4 100644
--- a/webapp/locales/pt.json
+++ b/webapp/locales/pt.json
@@ -11,7 +11,7 @@
"no-account": "Ainda não tem uma conta?",
"register": "Cadastrar-se",
"moreInfoURL": "https:\/\/human-connection.org\/en\/",
- "moreInfoHint": "",
+ "moreInfoHint": "para a página de apresentação",
"success": "Você está conectado!",
"failure": "Endereço de e-mail ou senha incorretos."
},
@@ -125,15 +125,15 @@
"name": "Fornecedores de terceiros",
"info-description": "Se você concordar, as publicações da seguinte lista de provedores incluirão automaticamente código de terceiros de outros provedores (terceiros) na forma de vídeos, imagens ou texto incorporados.",
"status": {
- "description": "",
+ "description": "Como padrão para você, o código incorporado de provedores de terceiros é",
"disabled": {
- "off": "",
- "on": ""
+ "off": "não exibido inicialmente",
+ "on": "exibido imediatamente"
},
"change": {
- "question": "",
- "allow": "",
- "deny": ""
+ "question": "O código-fonte incorporado de terceiros deve sempre ser exibido para você?",
+ "allow": "Certeza",
+ "deny": "Não, obrigado"
}
}
},
@@ -158,13 +158,13 @@
"columns": {
"name": "Nome",
"slug": "Slug",
- "unblock": ""
+ "unblock": "Desbloquear"
},
"empty": "Até agora, você não bloqueou ninguém.",
"how-to": "Você pode bloquear outros usuários em suas páginas de perfil através do menu de conteúdo.",
"block": "Bloquear usuário",
"unblock": "Desbloquear usuário",
- "unblocked": ""
+ "unblocked": "{name} está desbloqueado novamente"
},
"privacy": {
"name": "Privacidade",
@@ -261,10 +261,10 @@
"menu": {
"edit": "Editar publicação",
"delete": "Excluir publicação",
- "pin": "",
- "pinnedSuccessfully": "",
- "unpin": "",
- "unpinnedSuccessfully": ""
+ "pin": "Fixar publicação",
+ "pinnedSuccessfully": "Publicação fixada com sucesso!",
+ "unpin": "Desafixar publicação",
+ "unpinnedSuccessfully": "Publicação desafixada com sucesso!"
},
"comment": {
"submit": "Commentar",
@@ -299,7 +299,7 @@
"validations": {
"email": "deve ser um endereço de e-mail válido",
"url": "deve ser uma URL válida",
- "categories": ""
+ "categories": "devem ser seleccionadas, no mínimo uma e, no máximo três categorias"
}
},
"actions": {
@@ -430,7 +430,7 @@
"teaserImage": {
"cropperConfirm": "Confirmar"
},
- "languageSelectText": ""
+ "languageSelectText": "Selecionar Idioma"
},
"comment": {
"edit": "Editar Comentário",
@@ -745,8 +745,8 @@
}
},
"donations": {
- "donations-for": "",
- "donate-now": "",
- "amount-of-total": ""
+ "donations-for": "Doações para",
+ "donate-now": "Doe agora",
+ "amount-of-total": "{amount} dos {total} € foram coletados"
}
}
\ No newline at end of file
diff --git a/webapp/nuxt.config.js b/webapp/nuxt.config.js
index eb628c7d6..0d61302ff 100644
--- a/webapp/nuxt.config.js
+++ b/webapp/nuxt.config.js
@@ -100,13 +100,14 @@ export default {
** Global processed styles
*/
styleResources: {
- scss: [styleguideStyles, '~view/styles/tokens.scss'],
+ scss: [styleguideStyles, '~assets/_new/styles/tokens.scss'],
},
/*
** Plugins to load before mounting the App
*/
plugins: [
+ { src: '~/plugins/base-components.js', ssr: true },
{
src: `~/plugins/styleguide${process.env.STYLEGUIDE_DEV ? '-dev' : ''}.js`,
ssr: true,
diff --git a/webapp/package.json b/webapp/package.json
index 4af522143..f999a2e14 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -45,15 +45,20 @@
"moduleNameMapper": {
"^@/(.*)$": "/src/$1",
"^~/(.*)$": "/$1",
- "\\.(css|less)$": "identity-obj-proxy"
+ "\\.(css|less)$": "identity-obj-proxy",
+ "\\.(svg)$": "/test/fileMock.js"
},
+ "setupFiles": [
+ "/test/registerContext.js",
+ "/test/testSetup.js"
+ ],
"testMatch": [
"**/?(*.)+(spec|test).js?(x)"
]
},
"dependencies": {
"@human-connection/styleguide": "0.5.21",
- "@nuxtjs/apollo": "^4.0.0-rc17",
+ "@nuxtjs/apollo": "^4.0.0-rc18",
"@nuxtjs/axios": "~5.8.0",
"@nuxtjs/dotenv": "~1.4.1",
"@nuxtjs/pwa": "^3.0.0-beta.19",
@@ -65,7 +70,7 @@
"cookie-universal-nuxt": "~2.0.19",
"cropperjs": "^1.5.5",
"cross-env": "~6.0.3",
- "date-fns": "2.7.0",
+ "date-fns": "2.8.1",
"express": "~4.17.1",
"graphql": "~14.5.8",
"jsonwebtoken": "~8.5.1",
@@ -95,19 +100,20 @@
"@babel/core": "~7.7.4",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "~7.7.4",
- "@storybook/addon-a11y": "^5.2.6",
+ "@storybook/addon-a11y": "^5.2.7",
"@storybook/addon-actions": "^5.2.6",
"@storybook/addon-notes": "^5.2.5",
"@storybook/vue": "~5.2.6",
"@vue/cli-shared-utils": "~4.0.5",
"@vue/eslint-config-prettier": "~6.0.0",
- "@vue/server-test-utils": "~1.0.0-beta.29",
+ "@vue/server-test-utils": "~1.0.0-beta.30",
"@vue/test-utils": "~1.0.0-beta.29",
"async-validator": "^3.2.2",
"babel-core": "~7.0.0-bridge.0",
"babel-eslint": "~10.0.3",
"babel-jest": "~24.9.0",
"babel-loader": "~8.0.6",
+ "babel-plugin-require-context-hook": "^1.0.0",
"babel-preset-vue": "~2.0.2",
"core-js": "~2.6.10",
"css-loader": "~3.2.0",
@@ -116,7 +122,7 @@
"eslint-config-standard": "~14.1.0",
"eslint-loader": "~3.0.2",
"eslint-plugin-import": "~2.18.2",
- "eslint-plugin-jest": "~23.0.4",
+ "eslint-plugin-jest": "~23.0.5",
"eslint-plugin-node": "~10.0.0",
"eslint-plugin-prettier": "~3.1.1",
"eslint-plugin-promise": "~4.2.1",
diff --git a/webapp/pages/admin/categories.vue b/webapp/pages/admin/categories.vue
index 23aa4d606..c72506e64 100644
--- a/webapp/pages/admin/categories.vue
+++ b/webapp/pages/admin/categories.vue
@@ -2,7 +2,7 @@
-
+
diff --git a/webapp/pages/admin/index.spec.js b/webapp/pages/admin/index.spec.js
index 68256aa9d..35e8ba212 100644
--- a/webapp/pages/admin/index.spec.js
+++ b/webapp/pages/admin/index.spec.js
@@ -1,11 +1,10 @@
-import { mount, createLocalVue } from '@vue/test-utils'
+import { mount } from '@vue/test-utils'
import AdminIndexPage from './index.vue'
-import Styleguide from '@human-connection/styleguide'
+
import VueApollo from 'vue-apollo'
-const localVue = createLocalVue()
+const localVue = global.localVue
-localVue.use(Styleguide)
localVue.use(VueApollo)
describe('admin/index.vue', () => {
diff --git a/webapp/pages/admin/users.spec.js b/webapp/pages/admin/users.spec.js
index f477aab1d..37d155b92 100644
--- a/webapp/pages/admin/users.spec.js
+++ b/webapp/pages/admin/users.spec.js
@@ -1,10 +1,7 @@
-import { mount, createLocalVue } from '@vue/test-utils'
+import { mount } from '@vue/test-utils'
import Users from './users.vue'
-import Styleguide from '@human-connection/styleguide'
-const localVue = createLocalVue()
-
-localVue.use(Styleguide)
+const localVue = global.localVue
describe('Users', () => {
let wrapper
diff --git a/webapp/pages/admin/users.vue b/webapp/pages/admin/users.vue
index 67594180d..6a7bf8adb 100644
--- a/webapp/pages/admin/users.vue
+++ b/webapp/pages/admin/users.vue
@@ -67,7 +67,8 @@