Merge remote-tracking branch 'origin/master' into 553-delete-comment

This commit is contained in:
Wolfgang Huß 2019-05-29 12:17:24 +02:00
commit 7807831e0e
54 changed files with 865 additions and 207 deletions

View File

@ -22,7 +22,7 @@ install:
script: script:
# Backend # Backend
- docker-compose exec backend yarn run lint - docker-compose exec backend yarn run lint
- docker-compose exec backend yarn run test:jest --ci --verbose=false - docker-compose exec backend yarn run test:jest --ci --verbose=false --coverage
- docker-compose exec backend yarn run db:reset - docker-compose exec backend yarn run db:reset
- docker-compose exec backend yarn run db:seed - docker-compose exec backend yarn run db:seed
- docker-compose exec backend yarn run test:cucumber - docker-compose exec backend yarn run test:cucumber
@ -30,7 +30,7 @@ script:
- docker-compose exec backend yarn run db:seed - docker-compose exec backend yarn run db:seed
# Frontend # Frontend
- docker-compose exec webapp yarn run lint - docker-compose exec webapp yarn run lint
- docker-compose exec webapp yarn run test --ci --verbose=false - docker-compose exec webapp yarn run test --ci --verbose=false --coverage
- docker-compose exec -d backend yarn run test:before:seeder - docker-compose exec -d backend yarn run test:before:seeder
# Fullstack # Fullstack
- CYPRESS_RETRIES=1 yarn run cypress:run - CYPRESS_RETRIES=1 yarn run cypress:run

View File

@ -7,6 +7,9 @@ ENV BUILD_COMMIT=$BUILD_COMMIT
ARG WORKDIR=/nitro-backend ARG WORKDIR=/nitro-backend
RUN mkdir -p $WORKDIR RUN mkdir -p $WORKDIR
WORKDIR $WORKDIR WORKDIR $WORKDIR
RUN apk --no-cache add git
COPY package.json yarn.lock ./ COPY package.json yarn.lock ./
COPY .env.template .env COPY .env.template .env
CMD ["yarn", "run", "start"] CMD ["yarn", "run", "start"]

View File

@ -26,7 +26,6 @@
"license": "MIT", "license": "MIT",
"jest": { "jest": {
"verbose": true, "verbose": true,
"collectCoverage": true,
"collectCoverageFrom": [ "collectCoverageFrom": [
"**/*.js", "**/*.js",
"!**/node_modules/**", "!**/node_modules/**",
@ -56,7 +55,7 @@
"date-fns": "2.0.0-alpha.27", "date-fns": "2.0.0-alpha.27",
"debug": "~4.1.1", "debug": "~4.1.1",
"dotenv": "~8.0.0", "dotenv": "~8.0.0",
"express": "~4.17.0", "express": "~4.17.1",
"faker": "~4.1.0", "faker": "~4.1.0",
"graphql": "~14.3.1", "graphql": "~14.3.1",
"graphql-custom-directives": "~0.2.14", "graphql-custom-directives": "~0.2.14",
@ -71,7 +70,7 @@
"lodash": "~4.17.11", "lodash": "~4.17.11",
"ms": "~2.1.1", "ms": "~2.1.1",
"neo4j-driver": "~1.7.4", "neo4j-driver": "~1.7.4",
"neo4j-graphql-js": "~2.6.1", "neo4j-graphql-js": "git+https://github.com/Human-Connection/neo4j-graphql-js.git#temporary_fixes",
"node-fetch": "~2.6.0", "node-fetch": "~2.6.0",
"npm-run-all": "~4.1.5", "npm-run-all": "~4.1.5",
"request": "~2.88.0", "request": "~2.88.0",
@ -97,7 +96,7 @@
"eslint": "~5.16.0", "eslint": "~5.16.0",
"eslint-config-standard": "~12.0.0", "eslint-config-standard": "~12.0.0",
"eslint-config-prettier": "~4.3.0", "eslint-config-prettier": "~4.3.0",
"eslint-plugin-import": "~2.17.2", "eslint-plugin-import": "~2.17.3",
"eslint-plugin-jest": "~22.6.4", "eslint-plugin-jest": "~22.6.4",
"eslint-plugin-node": "~9.1.0", "eslint-plugin-node": "~9.1.0",
"eslint-plugin-prettier": "~3.1.0", "eslint-plugin-prettier": "~3.1.0",
@ -105,8 +104,8 @@
"eslint-plugin-standard": "~4.0.0", "eslint-plugin-standard": "~4.0.0",
"graphql-request": "~1.8.2", "graphql-request": "~1.8.2",
"jest": "~24.8.0", "jest": "~24.8.0",
"nodemon": "~1.19.0", "nodemon": "~1.19.1",
"prettier": "~1.14.3", "prettier": "~1.14.3",
"supertest": "~4.0.2" "supertest": "~4.0.2"
} }
} }

View File

View File

@ -12,6 +12,7 @@ import rewards from './resolvers/rewards.js'
import socialMedia from './resolvers/socialMedia.js' import socialMedia from './resolvers/socialMedia.js'
import notifications from './resolvers/notifications' import notifications from './resolvers/notifications'
import comments from './resolvers/comments' import comments from './resolvers/comments'
import users from './resolvers/users'
export const typeDefs = fs export const typeDefs = fs
.readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql')) .readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql'))
@ -35,5 +36,6 @@ export const resolvers = {
...socialMedia.Mutation, ...socialMedia.Mutation,
...notifications.Mutation, ...notifications.Mutation,
...comments.Mutation, ...comments.Mutation,
...users.Mutation,
}, },
} }

View File

@ -2,6 +2,7 @@ import cheerio from 'cheerio'
const ID_REGEX = /\/profile\/([\w\-.!~*'"(),]+)/g const ID_REGEX = /\/profile\/([\w\-.!~*'"(),]+)/g
export default function(content) { export default function(content) {
if (!content) return []
const $ = cheerio.load(content) const $ = cheerio.load(content)
const urls = $('.mention') const urls = $('.mention')
.map((_, el) => { .map((_, el) => {

View File

@ -1,6 +1,12 @@
import extractIds from './extractMentions' import extractIds from '.'
describe('extractIds', () => {
describe('content undefined', () => {
it('returns empty array', () => {
expect(extractIds()).toEqual([])
})
})
describe('extract', () => {
describe('searches through links', () => { describe('searches through links', () => {
it('ignores links without .mention class', () => { it('ignores links without .mention class', () => {
const content = const content =

View File

@ -1,4 +1,4 @@
import extractIds from './extractMentions' import extractIds from './extractIds'
const notify = async (resolve, root, args, context, resolveInfo) => { const notify = async (resolve, root, args, context, resolveInfo) => {
// extract user ids before xss-middleware removes link classes // extract user ids before xss-middleware removes link classes

View File

@ -3,7 +3,7 @@ import { UserInputError } from 'apollo-server'
const USERNAME_MIN_LENGTH = 3 const USERNAME_MIN_LENGTH = 3
const validateUsername = async (resolve, root, args, context, info) => { const validateUsername = async (resolve, root, args, context, info) => {
if (args.name && args.name.length >= USERNAME_MIN_LENGTH) { if (!('name' in args) || (args.name && args.name.length >= USERNAME_MIN_LENGTH)) {
/* eslint-disable-next-line no-return-await */ /* eslint-disable-next-line no-return-await */
return await resolve(root, args, context, info) return await resolve(root, args, context, info)
} else { } else {

View File

@ -0,0 +1,27 @@
import { createWriteStream } from 'fs'
import path from 'path'
import slug from 'slug'
const storeUpload = ({ createReadStream, fileLocation }) =>
new Promise((resolve, reject) =>
createReadStream()
.pipe(createWriteStream(`public${fileLocation}`))
.on('finish', resolve)
.on('error', reject),
)
export default async function fileUpload(params, { file, url }, uploadCallback = storeUpload) {
const upload = params[file]
if (upload) {
const { createReadStream, filename } = await upload
const { name } = path.parse(filename)
const fileLocation = `/uploads/${Date.now()}-${slug(name)}`
await uploadCallback({ createReadStream, fileLocation })
delete params[file]
params[url] = fileLocation
}
return params
}

View File

@ -0,0 +1,65 @@
import fileUpload from '.'
describe('fileUpload', () => {
let params
let uploadCallback
beforeEach(() => {
params = {
uploadAttribute: {
filename: 'avatar.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream: jest.fn(),
},
}
uploadCallback = jest.fn()
})
it('calls uploadCallback', async () => {
await fileUpload(params, { file: 'uploadAttribute', url: 'attribute' }, uploadCallback)
expect(uploadCallback).toHaveBeenCalled()
})
describe('file name', () => {
it('saves the upload url in params[url]', async () => {
await fileUpload(params, { file: 'uploadAttribute', url: 'attribute' }, uploadCallback)
expect(params.attribute).toMatch(/^\/uploads\/\d+-avatar$/)
})
it('uses the name without file ending', async () => {
params.uploadAttribute.filename = 'somePng.png'
await fileUpload(params, { file: 'uploadAttribute', url: 'attribute' }, uploadCallback)
expect(params.attribute).toMatch(/^\/uploads\/\d+-somePng/)
})
it('creates a url safe name', async () => {
params.uploadAttribute.filename =
'/path/to/awkward?/ file-location/?foo- bar-avatar.jpg?foo- bar'
await fileUpload(params, { file: 'uploadAttribute', url: 'attribute' }, uploadCallback)
expect(params.attribute).toMatch(/^\/uploads\/\d+-foo-bar-avatar$/)
})
describe('in case of duplicates', () => {
it('creates unique names to avoid overwriting existing files', async () => {
const { attribute: first } = await fileUpload(
{
...params,
},
{ file: 'uploadAttribute', url: 'attribute' },
uploadCallback,
)
await new Promise(resolve => setTimeout(resolve, 1000))
const { attribute: second } = await fileUpload(
{
...params,
},
{ file: 'uploadAttribute', url: 'attribute' },
uploadCallback,
)
expect(first).not.toEqual(second)
})
})
})
})

View File

@ -1,8 +1,15 @@
import { neo4jgraphql } from 'neo4j-graphql-js' import { neo4jgraphql } from 'neo4j-graphql-js'
import fileUpload from './fileUpload'
export default { export default {
Mutation: { Mutation: {
UpdatePost: async (object, params, context, resolveInfo) => {
params = await fileUpload(params, { file: 'imageUpload', url: 'image' })
return neo4jgraphql(object, params, context, resolveInfo, false)
},
CreatePost: async (object, params, context, resolveInfo) => { CreatePost: async (object, params, context, resolveInfo) => {
params = await fileUpload(params, { file: 'imageUpload', url: 'image' })
const result = await neo4jgraphql(object, params, context, resolveInfo, false) const result = await neo4jgraphql(object, params, context, resolveInfo, false)
const session = context.driver.session() const session = context.driver.session()

View File

@ -0,0 +1,15 @@
import { neo4jgraphql } from 'neo4j-graphql-js'
import fileUpload from './fileUpload'
export default {
Mutation: {
UpdateUser: async (object, params, context, resolveInfo) => {
params = await fileUpload(params, { file: 'avatarUpload', url: 'avatar' })
return neo4jgraphql(object, params, context, resolveInfo, false)
},
CreateUser: async (object, params, context, resolveInfo) => {
params = await fileUpload(params, { file: 'avatarUpload', url: 'avatar' })
return neo4jgraphql(object, params, context, resolveInfo, false)
},
},
}

View File

@ -67,6 +67,7 @@ describe('users', () => {
it('with no name', async () => { it('with no name', async () => {
const variables = { const variables = {
id: 'u47', id: 'u47',
name: null,
} }
const expected = 'Username must be at least 3 characters long!' const expected = 'Username must be at least 3 characters long!'
await expect(client.request(mutation, variables)).rejects.toThrow(expected) await expect(client.request(mutation, variables)).rejects.toThrow(expected)

View File

@ -1,3 +1,5 @@
scalar Upload
type Query { type Query {
isLoggedIn: Boolean! isLoggedIn: Boolean!
# Get the currently logged in User based on the given JWT Token # Get the currently logged in User based on the given JWT Token
@ -18,6 +20,7 @@ type Query {
) )
CommentByPost(postId: ID!): [Comment]! CommentByPost(postId: ID!): [Comment]!
} }
type Mutation { type Mutation {
# Get a JWT Token for the given Email and password # Get a JWT Token for the given Email and password
login(email: String!, password: String!): String! login(email: String!, password: String!): String!
@ -99,6 +102,7 @@ type User {
slug: String slug: String
password: String! password: String!
avatar: String avatar: String
avatarUpload: Upload
deleted: Boolean deleted: Boolean
disabled: Boolean disabled: Boolean
disabledBy: User @relation(name: "DISABLED", direction: "IN") disabledBy: User @relation(name: "DISABLED", direction: "IN")
@ -175,6 +179,7 @@ type Post {
content: String! content: String!
contentExcerpt: String contentExcerpt: String
image: String image: String
imageUpload: Upload
visibility: VisibilityEnum visibility: VisibilityEnum
deleted: Boolean deleted: Boolean
disabled: Boolean disabled: Boolean

View File

@ -3043,10 +3043,10 @@ eslint-plugin-es@^1.4.0:
eslint-utils "^1.3.0" eslint-utils "^1.3.0"
regexpp "^2.0.1" regexpp "^2.0.1"
eslint-plugin-import@~2.17.2: eslint-plugin-import@~2.17.3:
version "2.17.2" version "2.17.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.2.tgz#d227d5c6dc67eca71eb590d2bb62fb38d86e9fcb" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz#00548b4434c18faebaba04b24ae6198f280de189"
integrity sha512-m+cSVxM7oLsIpmwNn2WXTJoReOF9f/CtLMo7qOVmKd1KntBy0hEcuNZ3erTmWjx+DxRO0Zcrm5KwAvI9wHcV5g== integrity sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==
dependencies: dependencies:
array-includes "^3.0.3" array-includes "^3.0.3"
contains-path "^0.1.0" contains-path "^0.1.0"
@ -3058,7 +3058,7 @@ eslint-plugin-import@~2.17.2:
lodash "^4.17.11" lodash "^4.17.11"
minimatch "^3.0.4" minimatch "^3.0.4"
read-pkg-up "^2.0.0" read-pkg-up "^2.0.0"
resolve "^1.10.0" resolve "^1.11.0"
eslint-plugin-jest@~22.6.4: eslint-plugin-jest@~22.6.4:
version "22.6.4" version "22.6.4"
@ -3286,10 +3286,10 @@ expect@^24.8.0:
jest-message-util "^24.8.0" jest-message-util "^24.8.0"
jest-regex-util "^24.3.0" jest-regex-util "^24.3.0"
express@^4.0.0, express@^4.16.3, express@~4.17.0: express@^4.0.0, express@^4.16.3, express@~4.17.1:
version "4.17.0" version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.0.tgz#288af62228a73f4c8ea2990ba3b791bb87cd4438" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
integrity sha512-1Z7/t3Z5ZnBG252gKUPyItc4xdeaA0X934ca2ewckAsVsw9EG71i++ZHZPYnus8g/s5Bty8IMpSVEuRkmwwPRQ== integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
dependencies: dependencies:
accepts "~1.3.7" accepts "~1.3.7"
array-flatten "1.1.1" array-flatten "1.1.1"
@ -5599,10 +5599,9 @@ neo4j-driver@^1.7.3, neo4j-driver@~1.7.4:
text-encoding "^0.6.4" text-encoding "^0.6.4"
uri-js "^4.2.1" uri-js "^4.2.1"
neo4j-graphql-js@~2.6.1: "neo4j-graphql-js@git+https://github.com/Human-Connection/neo4j-graphql-js.git#temporary_fixes":
version "2.6.1" version "2.6.1"
resolved "https://registry.yarnpkg.com/neo4j-graphql-js/-/neo4j-graphql-js-2.6.1.tgz#fc25d44d875a73114b6df08259985b555704b9bb" resolved "git+https://github.com/Human-Connection/neo4j-graphql-js.git#84d529b9ecbc5c284cce4f86238c6d19b192cf0f"
integrity sha512-bPqzKumlCoHtS2qfPoTcZXrTkdXky210Kdu6Ubh5GhT+84wf+mo4Dzj4nxgDP2UgB77uA/caesIUImrSTLM8yQ==
dependencies: dependencies:
graphql "^14.2.1" graphql "^14.2.1"
graphql-auth-directives "^2.1.0" graphql-auth-directives "^2.1.0"
@ -5697,10 +5696,10 @@ node-releases@^1.1.19:
dependencies: dependencies:
semver "^5.3.0" semver "^5.3.0"
nodemon@~1.19.0: nodemon@~1.19.1:
version "1.19.0" version "1.19.1"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.0.tgz#358e005549a1e9e1148cb2b9b8b28957dc4e4527" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.1.tgz#576f0aad0f863aabf8c48517f6192ff987cd5071"
integrity sha512-NHKpb/Je0Urmwi3QPDHlYuFY9m1vaVfTsRZG5X73rY46xPj0JpNe8WhUGQdkDXQDOxrBNIU3JrcflE9Y44EcuA== integrity sha512-/DXLzd/GhiaDXXbGId5BzxP1GlsqtMGM9zTmkWrgXtSqjKmGSbLicM/oAy4FR0YWm14jCHRwnR31AHS2dYFHrg==
dependencies: dependencies:
chokidar "^2.1.5" chokidar "^2.1.5"
debug "^3.1.0" debug "^3.1.0"
@ -6704,10 +6703,10 @@ resolve@1.1.7:
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
resolve@^1.10.0, resolve@^1.10.1, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.5.0: resolve@^1.10.1, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.3.3, resolve@^1.5.0:
version "1.10.1" version "1.11.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.1.tgz#664842ac960795bbe758221cdccda61fb64b5f18" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232"
integrity sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA== integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==
dependencies: dependencies:
path-parse "^1.0.6" path-parse "^1.0.6"

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -0,0 +1,34 @@
import { When, Then } from 'cypress-cucumber-preprocessor/steps'
/* global cy */
When('I visit my profile page', () => {
cy.openPage('profile/peter-pan')
})
Then('I should be able to change my profile picture', () => {
const avatarUpload = 'onourjourney.png'
cy.fixture(avatarUpload, 'base64').then(fileContent => {
cy.get('#customdropzone').upload(
{ fileContent, fileName: avatarUpload, mimeType: 'image/png' },
{ subjectType: 'drag-n-drop' },
)
})
cy.get('#customdropzone')
.should('have.attr', 'style')
.and('contains', 'onourjourney')
cy.contains('.iziToast-message', 'Upload successful')
.should('have.length', 1)
})
When("I visit another user's profile page", () => {
cy.openPage('profile/peter-pan')
})
Then('I cannot upload a picture', () => {
cy.get('.ds-card-content')
.children()
.should('not.have.id', 'customdropzone')
.should('have.class', 'ds-avatar')
})

View File

@ -45,6 +45,7 @@ When('people visit my profile page', url => {
cy.openPage('/profile/peter-pan') cy.openPage('/profile/peter-pan')
}) })
When('they can see the text in the info box below my avatar', () => { When('they can see the text in the info box below my avatar', () => {
cy.contains(aboutMeText) cy.contains(aboutMeText)
}) })

View File

@ -0,0 +1,18 @@
Feature: Upload UserProfile Image
As a user
I would like to be able to add an avatar/profile pic to my profile
So that I can personalize my profile
Background:
Given I have a user account
Scenario: Change my UserProfile Image
Given I am logged in
And I visit my profile page
Then I should be able to change my profile picture
Scenario: Unable to change another user's avatar
Given I am logged in with a "user" role
And I visit another user's profile page
Then I cannot upload a picture

View File

@ -13,7 +13,7 @@
// Cypress.Commands.add('login', (email, password) => { ... }) // Cypress.Commands.add('login', (email, password) => { ... })
/* globals Cypress cy */ /* globals Cypress cy */
import 'cypress-file-upload'
import { getLangByName } from './helpers' import { getLangByName } from './helpers'
import users from '../fixtures/users.json' import users from '../fixtures/users.json'

View File

@ -6,7 +6,7 @@ just apply our provided configuration files to your cluster.
## Configuration ## Configuration
Copy our provided templates: Change into the `./deployment` directory and copy our provided templates:
```bash ```bash
# in folder deployment/human-connection/ # in folder deployment/human-connection/
@ -14,7 +14,7 @@ $ cp templates/secrets.template.yaml ./secrets.yaml
$ cp templates/configmap.template.yaml ./configmap.yaml $ cp templates/configmap.template.yaml ./configmap.yaml
``` ```
Change the `configmap.yaml` as needed, all variables will be available as Change the `configmap.yaml` in the `./deployment/human-connection` directory as needed, all variables will be available as
environment variables in your deployed kubernetes pods. environment variables in your deployed kubernetes pods.
Probably you want to change this environment variable to your actual domain: Probably you want to change this environment variable to your actual domain:
@ -28,7 +28,7 @@ If you want to edit secrets, you have to `base64` encode them. See [kubernetes d
```bash ```bash
# example how to base64 a string: # example how to base64 a string:
$ echo -n 'admin' | base64 --wrap 0 $ echo -n 'admin' | base64
YWRtaW4= YWRtaW4=
``` ```

View File

@ -8,5 +8,5 @@ do
fi fi
done done
/migration/mongo/import.sh /migration/mongo/export.sh
/migration/neo4j/import.sh /migration/neo4j/import.sh

View File

@ -0,0 +1,16 @@
# SSH Access
# SSH_USERNAME='username'
# SSH_HOST='example.org'
# Mongo DB on Remote Maschine
# MONGODB_USERNAME='mongouser'
# MONGODB_PASSWORD='mongopassword'
# MONGODB_DATABASE='mongodatabase'
# MONGODB_AUTH_DB='admin'
# Export Settings
# On Windows this resolves to C:\Users\dornhoeschen\AppData\Local\Temp\mongo-export (MinGW)
EXPORT_PATH='/tmp/mongo-export/'
EXPORT_MONGOEXPORT_BIN='mongoexport'
# On Windows use something like this
# EXPORT_MONGOEXPORT_BIN='C:\Program Files\MongoDB\Server\3.6\bin\mongoexport.exe'

View File

@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -e
# import .env config
set -o allexport
source $(dirname "$0")/.env
set +o allexport
# Export collection function defintion
function export_collection () {
"${EXPORT_MONGOEXPORT_BIN}" --db ${MONGODB_DATABASE} --host localhost -d ${MONGODB_DATABASE} --port 27018 --username ${MONGODB_USERNAME} --password ${MONGODB_PASSWORD} --authenticationDatabase ${MONGODB_AUTH_DB} --collection $1 --collection $1 --out "${EXPORT_PATH}$1.json"
mkdir -p ${EXPORT_PATH}splits/$1/
split -l 1000 -a 3 ${EXPORT_PATH}$1.json ${EXPORT_PATH}splits/$1/
}
# Delete old export & ensure directory
rm -rf ${EXPORT_PATH}*
mkdir -p ${EXPORT_PATH}
# Open SSH Tunnel
ssh -4 -M -S my-ctrl-socket -fnNT -L 27018:localhost:27017 -l ${SSH_USERNAME} ${SSH_HOST}
# Export all Data from the Alpha to json and split them up
export_collection "badges"
export_collection "categories"
export_collection "comments"
export_collection "contributions"
export_collection "emotions"
export_collection "follows"
export_collection "invites"
export_collection "notifications"
export_collection "organizations"
export_collection "pages"
export_collection "projects"
export_collection "settings"
export_collection "shouts"
export_collection "status"
export_collection "systemnotifications"
export_collection "users"
export_collection "userscandos"
export_collection "usersettings"
# Close SSH Tunnel
ssh -S my-ctrl-socket -O check -l ${SSH_USERNAME} ${SSH_HOST}
ssh -S my-ctrl-socket -O exit -l ${SSH_USERNAME} ${SSH_HOST}

View File

@ -1,26 +0,0 @@
#!/usr/bin/env bash
set -e
echo "SSH_USERNAME ${SSH_USERNAME}"
echo "SSH_HOST ${SSH_HOST}"
echo "MONGODB_USERNAME ${MONGODB_USERNAME}"
echo "MONGODB_PASSWORD ${MONGODB_PASSWORD}"
echo "MONGODB_DATABASE ${MONGODB_DATABASE}"
echo "MONGODB_AUTH_DB ${MONGODB_AUTH_DB}"
echo "-------------------------------------------------"
rm -rf /tmp/mongo-export/*
mkdir -p /tmp/mongo-export/
ssh -4 -M -S my-ctrl-socket -fnNT -L 27018:localhost:27017 -l ${SSH_USERNAME} ${SSH_HOST}
for collection in "categories" "badges" "users" "contributions" "comments" "follows" "shouts"
do
mongoexport --db ${MONGODB_DATABASE} --host localhost -d ${MONGODB_DATABASE} --port 27018 --username ${MONGODB_USERNAME} --password ${MONGODB_PASSWORD} --authenticationDatabase ${MONGODB_AUTH_DB} --collection $collection --collection $collection --out "/tmp/mongo-export/$collection.json"
mkdir -p /tmp/mongo-export/splits/$collection/
split -l 1000 -a 3 /tmp/mongo-export/$collection.json /tmp/mongo-export/splits/$collection/
done
ssh -S my-ctrl-socket -O check -l ${SSH_USERNAME} ${SSH_HOST}
ssh -S my-ctrl-socket -O exit -l ${SSH_USERNAME} ${SSH_HOST}

View File

@ -0,0 +1,16 @@
# Neo4J Settings
# NEO4J_USERNAME='neo4j'
# NEO4J_PASSWORD='letmein'
# Import Settings
# On Windows this resolves to C:\Users\dornhoeschen\AppData\Local\Temp\mongo-export (MinGW)
IMPORT_PATH='/tmp/mongo-export/'
IMPORT_CHUNK_PATH='/tmp/mongo-export/splits/current-chunk.json'
IMPORT_CHUNK_PATH_CQL='/tmp/mongo-export/splits/current-chunk.json'
# On Windows this path needs to be windows style since the cypher-shell runs native - note the forward slash
# IMPORT_CHUNK_PATH_CQL='C:/Users/dornhoeschen/AppData/Local/Temp/mongo-export/splits/current-chunk.json'
IMPORT_CYPHERSHELL_BIN='cypher-shell'
# On Windows use something like this
# IMPORT_CYPHERSHELL_BIN='C:\Program Files\neo4j-community\bin\cypher-shell.bat'

View File

@ -1,4 +1,4 @@
CALL apoc.load.json('file:/tmp/mongo-export/splits/current-chunk.json') YIELD value as badge CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL}") YIELD value as badge
MERGE(b:Badge {id: badge._id["$oid"]}) MERGE(b:Badge {id: badge._id["$oid"]})
ON CREATE SET ON CREATE SET
b.key = badge.key, b.key = badge.key,

View File

@ -1,4 +1,4 @@
CALL apoc.load.json('file:/tmp/mongo-export/splits/current-chunk.json') YIELD value as category CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL}") YIELD value as category
MERGE(c:Category {id: category._id["$oid"]}) MERGE(c:Category {id: category._id["$oid"]})
ON CREATE SET ON CREATE SET
c.name = category.title, c.name = category.title,

View File

@ -1,4 +1,4 @@
CALL apoc.load.json('file:/tmp/mongo-export/splits/current-chunk.json') YIELD value as json CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL}") YIELD value as json
MERGE (comment:Comment {id: json._id["$oid"]}) MERGE (comment:Comment {id: json._id["$oid"]})
ON CREATE SET ON CREATE SET

View File

@ -1,4 +1,4 @@
CALL apoc.load.json('file:/tmp/mongo-export/splits/current-chunk.json') YIELD value as post CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL}") YIELD value as post
MERGE (p:Post {id: post._id["$oid"]}) MERGE (p:Post {id: post._id["$oid"]})
ON CREATE SET ON CREATE SET
p.title = post.title, p.title = post.title,
@ -20,6 +20,6 @@ MATCH (c:Category {id: categoryId})
MERGE (p)-[:CATEGORIZED]->(c) MERGE (p)-[:CATEGORIZED]->(c)
WITH p, post.tags AS tags WITH p, post.tags AS tags
UNWIND tags AS tag UNWIND tags AS tag
MERGE (t:Tag {id: apoc.create.uuid(), name: tag}) MERGE (t:Tag {id: tag, name: tag})
MERGE (p)-[:TAGGED]->(t) MERGE (p)-[:TAGGED]->(t)
; ;

View File

@ -1,4 +1,4 @@
CALL apoc.load.json('file:/tmp/mongo-export/splits/current-chunk.json') YIELD value as follow CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL}") YIELD value as follow
MATCH (u1:User {id: follow.userId}), (u2:User {id: follow.foreignId}) MATCH (u1:User {id: follow.userId}), (u2:User {id: follow.foreignId})
MERGE (u1)-[:FOLLOWS]->(u2) MERGE (u1)-[:FOLLOWS]->(u2)
; ;

View File

@ -1,17 +1,48 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
SECONDS=0 # import .env config
SCRIPT_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" set -o allexport
source $(dirname "$0")/.env
set +o allexport
echo "MATCH (n) DETACH DELETE n;" | cypher-shell # Import collection function defintion
function import_collection () {
for collection in "badges" "categories" "users" "follows" "contributions" "shouts" "comments" for chunk in ${IMPORT_PATH}splits/$1/*
do
for chunk in /tmp/mongo-export/splits/$collection/*
do do
mv $chunk /tmp/mongo-export/splits/current-chunk.json mv $chunk ${IMPORT_CHUNK_PATH}
echo "Import ${chunk}" && cypher-shell < $SCRIPT_DIRECTORY/$collection.cql NEO4J_COMMAND="$(envsubst '${IMPORT_CHUNK_PATH_CQL}' < $(dirname "$0")/$1.cql)"
echo "Import ${chunk}"
echo "${NEO4J_COMMAND}" | "${IMPORT_CYPHERSHELL_BIN}" -u ${NEO4J_USERNAME} -p ${NEO4J_PASSWORD}
done done
done }
# Time variable
SECONDS=0
# Delete all Neo4J Database content
echo "Deleting Database Contents"
echo "MATCH (n) DETACH DELETE n;" | "${IMPORT_CYPHERSHELL_BIN}" -u ${NEO4J_USERNAME} -p ${NEO4J_PASSWORD}
# Import Data
echo "Start Importing Data"
import_collection "badges"
import_collection "categories"
import_collection "users"
import_collection "follows"
import_collection "contributions"
import_collection "shouts"
import_collection "comments"
#import_collection "emotions"
#import_collection "invites"
#import_collection "notifications"
#import_collection "organizations"
#import_collection "pages"
#import_collection "projects"
#import_collection "settings"
#import_collection "status"
#import_collection "systemnotifications"
#import_collection "userscandos"
#import_collection "usersettings"
echo "Time elapsed: $SECONDS seconds" echo "Time elapsed: $SECONDS seconds"

View File

@ -1,4 +1,4 @@
CALL apoc.load.json('file:/tmp/mongo-export/splits/current-chunk.json') YIELD value as shout CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL}") YIELD value as shout
MATCH (u:User {id: shout.userId}), (p:Post {id: shout.foreignId}) MATCH (u:User {id: shout.userId}), (p:Post {id: shout.foreignId})
MERGE (u)-[:SHOUTED]->(p) MERGE (u)-[:SHOUTED]->(p)
; ;

View File

@ -1,4 +1,4 @@
CALL apoc.load.json('file:/tmp/mongo-export/splits/current-chunk.json') YIELD value as user CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL}") YIELD value as user
MERGE(u:User {id: user._id["$oid"]}) MERGE(u:User {id: user._id["$oid"]})
ON CREATE SET ON CREATE SET
u.name = user.name, u.name = user.name,

View File

@ -23,11 +23,12 @@
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"cypress": "^3.3.1", "cypress": "^3.3.1",
"cypress-cucumber-preprocessor": "^1.11.2", "cypress-cucumber-preprocessor": "^1.11.2",
"cypress-file-upload": "^3.1.2",
"cypress-plugin-retries": "^1.2.2", "cypress-plugin-retries": "^1.2.2",
"dotenv": "^8.0.0", "dotenv": "^8.0.0",
"faker": "^4.1.0", "faker": "^4.1.0",
"graphql-request": "^1.8.2", "graphql-request": "^1.8.2",
"neo4j-driver": "^1.7.4", "neo4j-driver": "^1.7.5",
"npm-run-all": "^4.1.5" "npm-run-all": "^4.1.5"
} }
} }

View File

@ -0,0 +1,69 @@
import { mount, createLocalVue } from '@vue/test-utils'
import Styleguide from '@human-connection/styleguide'
import Avatar from './Avatar.vue'
const localVue = createLocalVue()
localVue.use(Styleguide)
describe('Avatar.vue', () => {
let propsData = {}
const Wrapper = () => {
return mount(Avatar, { propsData, localVue })
}
it('renders no image', () => {
expect(
Wrapper()
.find('img')
.exists(),
).toBe(false)
})
it('renders an icon', () => {
expect(
Wrapper()
.find('.ds-icon')
.exists(),
).toBe(true)
})
describe('given a user', () => {
describe('with a relative avatar url', () => {
beforeEach(() => {
propsData = {
user: {
avatar: '/avatar.jpg',
},
}
})
it('adds a prefix to load the image from the uploads service', () => {
expect(
Wrapper()
.find('img')
.attributes('src'),
).toBe('/api/avatar.jpg')
})
})
describe('with an absolute avatar url', () => {
beforeEach(() => {
propsData = {
user: {
avatar: 'http://lorempixel.com/640/480/animals',
},
}
})
it('keeps the avatar URL as is', () => {
// e.g. our seeds have absolute image URLs
expect(
Wrapper()
.find('img')
.attributes('src'),
).toBe('http://lorempixel.com/640/480/animals')
})
})
})
})

View File

@ -0,0 +1,33 @@
<template>
<ds-avatar
:image="avatarUrl"
:name="userName"
class="avatar"
:size="size"
/>
</template>
<script>
export default {
name: 'HcAvatar',
props: {
user: { type: Object, default: null },
size: { type: String, default: 'small' },
},
computed: {
avatarUrl() {
const { avatar: imageSrc } = this.user || {}
if (!imageSrc) return imageSrc
return imageSrc.startsWith('/') ? imageSrc.replace('/', '/api/') : imageSrc
},
userName() {
const { name } = this.user || {}
// The name is used to display the initials in case
// the image cannot be loaded.
return name
// If the name is undefined, then our styleguide will
// display an icon for the anonymous user.
},
},
}
</script>

View File

@ -327,10 +327,18 @@ export default {
}, },
}, },
}, },
mounted() {
this.$root.$on('changeLanguage', () => {
this.changePlaceHolderText()
})
},
beforeDestroy() { beforeDestroy() {
this.editor.destroy() this.editor.destroy()
}, },
methods: { methods: {
changePlaceHolderText() {
this.editor.extensions.options.placeholder.emptyNodeText = this.$t('editor.placeholder')
},
// navigate to the previous item // navigate to the previous item
// if it's the first item, navigate to the last one // if it's the first item, navigate to the last one
upHandler() { upHandler() {

View File

@ -14,7 +14,8 @@
<ds-icon <ds-icon
style="margin-right: 2px;" style="margin-right: 2px;"
name="globe" name="globe"
/> {{ current.code.toUpperCase() }} />
{{ current.code.toUpperCase() }}
<ds-icon <ds-icon
style="margin-left: 2px" style="margin-left: 2px"
size="xx-small" size="xx-small"
@ -78,6 +79,7 @@ export default {
changeLanguage(locale, toggleMenu) { changeLanguage(locale, toggleMenu) {
this.$i18n.set(locale) this.$i18n.set(locale)
toggleMenu() toggleMenu()
this.$root.$emit('changeLanguage')
}, },
matcher(locale) { matcher(locale) {
return locale === this.$i18n.locale() return locale === this.$i18n.locale()

View File

@ -0,0 +1,153 @@
<template>
<div>
<vue-dropzone
id="customdropzone"
:key="user.avatar"
ref="el"
:options="dropzoneOptions"
:include-styling="false"
:style="backgroundImage"
@vdropzone-thumbnail="thumbnail"
@vdropzone-drop="vddrop"
/>
</div>
</template>
<script>
import vueDropzone from 'nuxt-dropzone'
import gql from 'graphql-tag'
export default {
components: {
vueDropzone,
},
props: {
user: { type: Object, default: null },
},
data() {
return {
dropzoneOptions: {
url: this.vddrop,
maxFilesize: 0.5,
previewTemplate: this.template(),
dictDefaultMessage: '',
},
}
},
computed: {
backgroundImage() {
const { avatar } = this.user || {}
const userAvatar = avatar.startsWith('/') ? avatar.replace('/', '/api/') : avatar
return {
backgroundImage: `url(${userAvatar})`,
}
},
},
methods: {
template() {
return `<div class="dz-preview dz-file-preview">
<div class="dz-image">
<div data-dz-thumbnail-bg></div>
</div>
<div class="dz-details">
<div class="dz-size"><span data-dz-size></span></div>
<div class="dz-filename"><span data-dz-name></span></div>
</div>
<div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>
<div class="dz-error-message"><span data-dz-errormessage></span></div>
</div>
</div>
`
},
thumbnail(file, dataUrl) {
let j, len, ref, thumbnailElement
if (file.previewElement) {
this.$refs.el.$el.style.backgroundImage = ''
file.previewElement.classList.remove('dz-file-preview')
ref = file.previewElement.querySelectorAll('[data-dz-thumbnail-bg]')
for (j = 0, len = ref.length; j < len; j++) {
thumbnailElement = ref[j]
thumbnailElement.alt = file.name
thumbnailElement.style.backgroundImage = 'url("' + dataUrl + '")'
}
file.previewElement.classList.add('dz-image-preview')
}
},
vddrop(file) {
const avatarUpload = file[0]
this.$apollo
.mutate({
mutation: gql`
mutation($id: ID!, $avatarUpload: Upload) {
UpdateUser(id: $id, avatarUpload: $avatarUpload) {
id
avatar
}
}
`,
variables: {
avatarUpload,
id: this.user.id,
},
})
.then(() => {
this.$toast.success(this.$t('user.avatar.submitted'))
})
.catch(error => this.$toast.error(error.message))
},
},
}
</script>
<style>
#customdropzone {
margin: -60px auto auto;
width: 122px;
min-height: 122px;
background-size: cover;
background-repeat: no-repeat;
border-radius: 50%;
font-family: 'Arial', sans-serif;
letter-spacing: 0.2px;
color: #777;
transition: background-color 0.2s linear;
padding: 40px;
}
#customdropzone:hover {
cursor: pointer;
}
#customdropzone .dz-preview {
width: 160px;
display: flex;
}
#customdropzone .dz-preview .dz-image {
position: relative;
width: 122px;
height: 122px;
margin: -35px;
}
#customdropzone .dz-preview .dz-image > div {
width: inherit;
height: inherit;
border-radius: 50%;
background-size: cover;
}
#customdropzone .dz-preview .dz-image > img {
width: 100%;
}
#customdropzone .dz-preview .dz-details {
color: white;
transition: opacity 0.2s linear;
text-align: center;
}
#customdropzone .dz-success-mark,
.dz-error-mark,
.dz-remove {
display: none;
}
</style>

View File

@ -0,0 +1,71 @@
import { shallowMount, createLocalVue } from '@vue/test-utils'
import Upload from '.'
import Vuex from 'vuex'
import Styleguide from '@human-connection/styleguide'
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(Styleguide)
describe('Upload', () => {
let wrapper
const mocks = {
$apollo: {
mutate: jest
.fn()
.mockResolvedValueOnce({
data: { UpdateUser: { id: 'upload1', avatar: '/upload/avatar.jpg' } },
})
.mockRejectedValue({
message: 'File upload unsuccessful! Whatcha gonna do?',
}),
},
$toast: {
success: jest.fn(),
error: jest.fn(),
},
}
const propsData = {
user: {
avatar: '/api/generic.jpg',
},
}
const file = {
filename: 'avatar.jpg',
previewElement: {
classList: {
remove: jest.fn(),
add: jest.fn(),
},
querySelectorAll: jest.fn().mockReturnValue([
{
alt: '',
style: {
'background-image': '/api/generic.jpg',
},
},
]),
},
}
const dataUrl = 'avatar.jpg'
beforeEach(() => {
jest.useFakeTimers()
wrapper = shallowMount(Upload, { localVue, propsData, mocks })
})
it('sends a the UpdateUser mutation when vddrop is called', () => {
wrapper.vm.vddrop([{ filename: 'avatar.jpg' }])
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
})
it('thumbnail', () => {
wrapper.vm.thumbnail(file, dataUrl)
expect(file.previewElement.classList.add).toHaveBeenCalledTimes(1)
})
})

View File

@ -3,10 +3,7 @@
<div <div
style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;" style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;"
> >
<ds-avatar <hc-avatar />
style="display: inline-block; vertical-align: middle;"
size="small"
/>
</div> </div>
<div style="display: inline-block; height: 100%; vertical-align: middle;"> <div style="display: inline-block; height: 100%; vertical-align: middle;">
<b <b
@ -36,11 +33,8 @@
<div <div
style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;" style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;"
> >
<ds-avatar <hc-avatar
:image="user.avatar" :user="user"
:name="userName"
style="display: inline-block; vertical-align: middle;"
size="small"
/> />
</div> </div>
<div style="display: inline-block; height: 100%; vertical-align: middle;"> <div style="display: inline-block; height: 100%; vertical-align: middle;">
@ -143,6 +137,7 @@ import { mapGetters } from 'vuex'
import HcRelativeDateTime from '~/components/RelativeDateTime' import HcRelativeDateTime from '~/components/RelativeDateTime'
import HcFollowButton from '~/components/FollowButton' import HcFollowButton from '~/components/FollowButton'
import HcBadges from '~/components/Badges' import HcBadges from '~/components/Badges'
import HcAvatar from '~/components/Avatar/Avatar.vue'
import Dropdown from '~/components/Dropdown' import Dropdown from '~/components/Dropdown'
export default { export default {
@ -150,6 +145,7 @@ export default {
components: { components: {
HcRelativeDateTime, HcRelativeDateTime,
HcFollowButton, HcFollowButton,
HcAvatar,
HcBadges, HcBadges,
Dropdown, Dropdown,
}, },
@ -183,12 +179,6 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
.profile-avatar {
display: block;
margin: auto;
margin-top: -45px;
border: #fff 5px solid;
}
.user { .user {
white-space: nowrap; white-space: nowrap;
position: relative; position: relative;

View File

@ -5,14 +5,12 @@
> >
<template slot-scope="{ errors }"> <template slot-scope="{ errors }">
<ds-card> <ds-card>
<no-ssr> <hc-editor
<hc-editor ref="editor"
ref="editor" :users="users"
:users="users" :value="form.content"
:value="form.content" @input="updateEditorContent"
@input="updateEditorContent" />
/>
</no-ssr>
<ds-space /> <ds-space />
<ds-flex :gutter="{ base: 'small', md: 'small', sm: 'x-large', xs: 'x-large' }"> <ds-flex :gutter="{ base: 'small', md: 'small', sm: 'x-large', xs: 'x-large' }">
<ds-flex-item :width="{ base: '0%', md: '50%', sm: '0%', xs: '0%' }" /> <ds-flex-item :width="{ base: '0%', md: '50%', sm: '0%', xs: '0%' }" />

View File

@ -1,4 +1,4 @@
import { config, mount, createLocalVue, createWrapper } from '@vue/test-utils' import { mount, createLocalVue, createWrapper } from '@vue/test-utils'
import CommentForm from './index.vue' import CommentForm from './index.vue'
import Styleguide from '@human-connection/styleguide' import Styleguide from '@human-connection/styleguide'
@ -6,8 +6,6 @@ const localVue = createLocalVue()
localVue.use(Styleguide) localVue.use(Styleguide)
config.stubs['no-ssr'] = '<span><slot /></span>'
describe('CommentForm.vue', () => { describe('CommentForm.vue', () => {
let mocks let mocks
let wrapper let wrapper

View File

@ -33,6 +33,13 @@ describe('CommentList.vue', () => {
}) })
mocks = { mocks = {
$t: jest.fn(), $t: jest.fn(),
$apollo: {
queries: {
Post: {
refetch: jest.fn(),
},
},
},
} }
data = () => { data = () => {
return { return {
@ -63,5 +70,10 @@ describe('CommentList.vue', () => {
it('displays comments when there are comments to display', () => { it('displays comments when there are comments to display', () => {
expect(wrapper.find('div#comments').text()).toEqual('this is a comment') expect(wrapper.find('div#comments').text()).toEqual('this is a comment')
}) })
it("refetches a post's comments from the backend", () => {
wrapper.vm.refetchPostComments()
expect(mocks.$apollo.queries.Post.refetch).toHaveBeenCalledTimes(1)
})
}) })
}) })

View File

@ -62,13 +62,15 @@ export default {
}, },
}, },
mounted() { mounted() {
this.$root.$on('refetchPostComments', comment => { this.$root.$on('refetchPostComments', () => {
this.refetchPostComments(comment) this.refetchPostComments()
}) })
}, },
methods: { methods: {
refetchPostComments(comment) { refetchPostComments() {
this.$apollo.queries.Post.refetch() if (this.$apollo.queries.Post) {
this.$apollo.queries.Post.refetch()
}
}, },
deleteComment(index) { deleteComment(index) {
this.comments.splice(index, 1) this.comments.splice(index, 1)

View File

@ -45,10 +45,8 @@
:href="$router.resolve({name: 'profile-id-slug', params: {id: user.id, slug: user.slug}}).href" :href="$router.resolve({name: 'profile-id-slug', params: {id: user.id, slug: user.slug}}).href"
@click.prevent="toggleMenu" @click.prevent="toggleMenu"
> >
<ds-avatar <hc-avatar
:image="user.avatar" :user="user"
:name="user.name"
size="small"
/> />
<ds-icon <ds-icon
size="xx-small" size="xx-small"
@ -123,6 +121,7 @@ import SearchInput from '~/components/SearchInput.vue'
import Modal from '~/components/Modal' import Modal from '~/components/Modal'
import NotificationMenu from '~/components/notifications/NotificationMenu' import NotificationMenu from '~/components/notifications/NotificationMenu'
import Dropdown from '~/components/Dropdown' import Dropdown from '~/components/Dropdown'
import HcAvatar from '~/components/Avatar/Avatar.vue'
import seo from '~/mixins/seo' import seo from '~/mixins/seo'
export default { export default {
@ -132,6 +131,7 @@ export default {
SearchInput, SearchInput,
Modal, Modal,
NotificationMenu, NotificationMenu,
HcAvatar,
}, },
mixins: [seo], mixins: [seo],
data() { data() {

View File

@ -257,5 +257,10 @@
}, },
"shoutButton": { "shoutButton": {
"shouted": "shouted" "shouted": "shouted"
},
"user": {
"avatar": {
"submitted": "Upload successful"
}
} }
} }

View File

@ -22,7 +22,6 @@
}, },
"jest": { "jest": {
"verbose": true, "verbose": true,
"collectCoverage": true,
"collectCoverageFrom": [ "collectCoverageFrom": [
"**/*.{js,vue}", "**/*.{js,vue}",
"!**/node_modules/**", "!**/node_modules/**",
@ -52,7 +51,7 @@
"dependencies": { "dependencies": {
"@human-connection/styleguide": "0.5.17", "@human-connection/styleguide": "0.5.17",
"@nuxtjs/apollo": "4.0.0-rc4.2", "@nuxtjs/apollo": "4.0.0-rc4.2",
"@nuxtjs/axios": "~5.5.1", "@nuxtjs/axios": "~5.5.2",
"@nuxtjs/dotenv": "~1.3.0", "@nuxtjs/dotenv": "~1.3.0",
"@nuxtjs/style-resources": "~0.1.2", "@nuxtjs/style-resources": "~0.1.2",
"accounting": "~0.4.1", "accounting": "~0.4.1",
@ -61,11 +60,12 @@
"cookie-universal-nuxt": "~2.0.14", "cookie-universal-nuxt": "~2.0.14",
"cross-env": "~5.2.0", "cross-env": "~5.2.0",
"date-fns": "2.0.0-alpha.27", "date-fns": "2.0.0-alpha.27",
"express": "~4.17.0", "express": "~4.17.1",
"graphql": "~14.3.1", "graphql": "~14.3.1",
"jsonwebtoken": "~8.5.1", "jsonwebtoken": "~8.5.1",
"linkify-it": "~2.1.0", "linkify-it": "~2.1.0",
"nuxt": "~2.7.1", "nuxt": "~2.7.1",
"nuxt-dropzone": "^1.0.2",
"nuxt-env": "~0.1.0", "nuxt-env": "~0.1.0",
"stack-utils": "^1.0.2", "stack-utils": "^1.0.2",
"string-hash": "^1.1.3", "string-hash": "^1.1.3",
@ -75,6 +75,7 @@
"vue-count-to": "~1.0.13", "vue-count-to": "~1.0.13",
"vue-izitoast": "1.1.2", "vue-izitoast": "1.1.2",
"vue-sweetalert-icons": "~3.2.0", "vue-sweetalert-icons": "~3.2.0",
"vue2-dropzone": "^3.5.9",
"vuex-i18n": "~1.11.0", "vuex-i18n": "~1.11.0",
"zxcvbn": "^4.4.2" "zxcvbn": "^4.4.2"
}, },
@ -82,7 +83,7 @@
"@babel/core": "~7.4.5", "@babel/core": "~7.4.5",
"@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "~7.4.5", "@babel/preset-env": "~7.4.5",
"@vue/cli-shared-utils": "~3.7.0", "@vue/cli-shared-utils": "~3.8.0",
"@vue/eslint-config-prettier": "~4.0.1", "@vue/eslint-config-prettier": "~4.0.1",
"@vue/server-test-utils": "~1.0.0-beta.29", "@vue/server-test-utils": "~1.0.0-beta.29",
"@vue/test-utils": "~1.0.0-beta.29", "@vue/test-utils": "~1.0.0-beta.29",
@ -93,7 +94,7 @@
"eslint-config-standard": "~12.0.0", "eslint-config-standard": "~12.0.0",
"eslint-config-prettier": "~4.3.0", "eslint-config-prettier": "~4.3.0",
"eslint-loader": "~2.1.2", "eslint-loader": "~2.1.2",
"eslint-plugin-import": "~2.17.2", "eslint-plugin-import": "~2.17.3",
"eslint-plugin-jest": "~22.6.4", "eslint-plugin-jest": "~22.6.4",
"eslint-plugin-node": "~9.1.0", "eslint-plugin-node": "~9.1.0",
"eslint-plugin-prettier": "~3.1.0", "eslint-plugin-prettier": "~3.1.0",
@ -103,11 +104,11 @@
"fuse.js": "^3.4.4", "fuse.js": "^3.4.4",
"jest": "~24.8.0", "jest": "~24.8.0",
"node-sass": "~4.12.0", "node-sass": "~4.12.0",
"nodemon": "~1.19.0", "nodemon": "~1.19.1",
"prettier": "~1.14.3", "prettier": "~1.14.3",
"sass-loader": "~7.1.0", "sass-loader": "~7.1.0",
"tippy.js": "^4.3.1", "tippy.js": "^4.3.1",
"vue-jest": "~3.0.4", "vue-jest": "~3.0.4",
"vue-svg-loader": "~0.12.0" "vue-svg-loader": "~0.12.0"
} }
} }

View File

@ -14,9 +14,13 @@
:class="{'disabled-content': user.disabled}" :class="{'disabled-content': user.disabled}"
style="position: relative; height: auto;" style="position: relative; height: auto;"
> >
<ds-avatar <hc-upload
:image="user.avatar" v-if="myProfile"
:name="userName" :user="user"
/>
<hc-avatar
v-else
:user="user"
class="profile-avatar" class="profile-avatar"
size="x-large" size="x-large"
/> />
@ -224,7 +228,7 @@
> >
<a :href="link.url"> <a :href="link.url">
<ds-avatar :image="link.favicon" /> <ds-avatar :image="link.favicon" />
{{ link.username }} {{ 'link.username' }}
</a> </a>
</ds-space> </ds-space>
</template> </template>
@ -328,6 +332,8 @@ import HcBadges from '~/components/Badges.vue'
import HcLoadMore from '~/components/LoadMore.vue' import HcLoadMore from '~/components/LoadMore.vue'
import HcEmpty from '~/components/Empty.vue' import HcEmpty from '~/components/Empty.vue'
import ContentMenu from '~/components/ContentMenu' import ContentMenu from '~/components/ContentMenu'
import HcUpload from '~/components/Upload'
import HcAvatar from '~/components/Avatar/Avatar.vue'
import PostMutationHelpers from '~/mixins/PostMutationHelpers' import PostMutationHelpers from '~/mixins/PostMutationHelpers'
export default { export default {
@ -339,7 +345,9 @@ export default {
HcBadges, HcBadges,
HcLoadMore, HcLoadMore,
HcEmpty, HcEmpty,
HcAvatar,
ContentMenu, ContentMenu,
HcUpload,
}, },
mixins: [PostMutationHelpers], mixins: [PostMutationHelpers],
transition: { transition: {
@ -455,7 +463,7 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
.profile-avatar { .profile-avatar.ds-avatar {
display: block; display: block;
margin: auto; margin: auto;
margin-top: -60px; margin-top: -60px;

View File

@ -1,5 +1,6 @@
export default ({ app }) => { export default ({ app }) => {
const backendUrl = process.env.GRAPHQL_URI || 'http://localhost:4000' const backendUrl = process.env.GRAPHQL_URI || 'http://localhost:4000'
return { return {
httpEndpoint: process.server ? backendUrl : '/api', httpEndpoint: process.server ? backendUrl : '/api',
httpLinkOptions: { httpLinkOptions: {

View File

@ -710,6 +710,32 @@
resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==
"@hapi/address@2.x.x":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a"
integrity sha512-mV6T0IYqb0xL1UALPFplXYQmR0twnXG0M6jUswpquqT2sD12BOiCiLy3EvMp/Fy7s3DZElC4/aPjEjo2jeZpvw==
"@hapi/hoek@6.x.x":
version "6.2.4"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-6.2.4.tgz#4b95fbaccbfba90185690890bdf1a2fbbda10595"
integrity sha512-HOJ20Kc93DkDVvjwHyHawPwPkX44sIrbXazAUDiUXaY2R9JwQGo2PhFfnQtdrsIe4igjG2fPgMra7NYw7qhy0A==
"@hapi/joi@^15.0.1":
version "15.0.3"
resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.0.3.tgz#e94568fd859e5e945126d5675e7dd218484638a7"
integrity sha512-z6CesJ2YBwgVCi+ci8SI8zixoj8bGFn/vZb9MBPbSyoxsS2PnWYjHcyTM17VLK6tx64YVK38SDIh10hJypB+ig==
dependencies:
"@hapi/address" "2.x.x"
"@hapi/hoek" "6.x.x"
"@hapi/topo" "3.x.x"
"@hapi/topo@3.x.x":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.0.tgz#5c47cd9637c2953db185aa957a27bcb2a8b7a6f8"
integrity sha512-gZDI/eXOIk8kP2PkUKjWu9RW8GGVd2Hkgjxyr/S7Z+JF+0mr7bAlbw+DkTRxnD580o8Kqxlnba9wvqp5aOHBww==
dependencies:
"@hapi/hoek" "6.x.x"
"@human-connection/styleguide@0.5.17": "@human-connection/styleguide@0.5.17":
version "0.5.17" version "0.5.17"
resolved "https://registry.yarnpkg.com/@human-connection/styleguide/-/styleguide-0.5.17.tgz#99816579616c8d5be6c66ee86c39cb6c4e694878" resolved "https://registry.yarnpkg.com/@human-connection/styleguide/-/styleguide-0.5.17.tgz#99816579616c8d5be6c66ee86c39cb6c4e694878"
@ -1115,10 +1141,10 @@
vue-cli-plugin-apollo "^0.20.0" vue-cli-plugin-apollo "^0.20.0"
webpack-node-externals "^1.7.2" webpack-node-externals "^1.7.2"
"@nuxtjs/axios@~5.5.1": "@nuxtjs/axios@~5.5.2":
version "5.5.1" version "5.5.2"
resolved "https://registry.yarnpkg.com/@nuxtjs/axios/-/axios-5.5.1.tgz#e0eeddcbbec4f04bd705b96afd05071340169b36" resolved "https://registry.yarnpkg.com/@nuxtjs/axios/-/axios-5.5.2.tgz#b6447bb12707b56b16b942ae6c737a0b051cecba"
integrity sha512-MRZGuXM13D7tFf01D6LJZ7jYxIxD+poRfqgpVHbXIA/AN2FEWvVx9Sv3VlwniEM50+NqzcHHEGv4k2s2ZSSE6g== integrity sha512-S5+IkUjCSSFeMVZp/JAzjoit9P7Di2QM4beAlFbHXbOEG+/vSaZReW8l817u9WC6nuKa3x6HhZfWD3tJDTvljg==
dependencies: dependencies:
"@nuxtjs/proxy" "^1.3.3" "@nuxtjs/proxy" "^1.3.3"
axios "^0.18.0" axios "^0.18.0"
@ -1455,18 +1481,18 @@
"@vue/babel-plugin-transform-vue-jsx" "^1.0.0" "@vue/babel-plugin-transform-vue-jsx" "^1.0.0"
camelcase "^5.0.0" camelcase "^5.0.0"
"@vue/cli-shared-utils@~3.7.0": "@vue/cli-shared-utils@~3.8.0":
version "3.7.0" version "3.8.0"
resolved "https://registry.yarnpkg.com/@vue/cli-shared-utils/-/cli-shared-utils-3.7.0.tgz#957dd3c31a31208caf9f119cac6008fd4960d46e" resolved "https://registry.yarnpkg.com/@vue/cli-shared-utils/-/cli-shared-utils-3.8.0.tgz#e7e728164eb92bd9e205fcd08dae896ee79cba5a"
integrity sha512-+LPDAQ1CE3ci1ADOvNqJMPdqyxgJxOq5HUgGDSKCHwviXF6GtynfljZXiSzgWh5ueMFxJphCfeMsTZqFWwsHVg== integrity sha512-wn1L8pmQnotfftHOYm0VeXs2+cQTySd73uhWXwyO6pT0ehjqlY5c2RTipClmFF3Q+YCYjwlNpsV650F3l1tV8w==
dependencies: dependencies:
"@hapi/joi" "^15.0.1"
chalk "^2.4.1" chalk "^2.4.1"
execa "^1.0.0" execa "^1.0.0"
joi "^14.3.0"
launch-editor "^2.2.1" launch-editor "^2.2.1"
lru-cache "^5.1.1" lru-cache "^5.1.1"
node-ipc "^9.1.1" node-ipc "^9.1.1"
opn "^5.3.0" open "^6.3.0"
ora "^3.4.0" ora "^3.4.0"
request "^2.87.0" request "^2.87.0"
request-promise-native "^1.0.7" request-promise-native "^1.0.7"
@ -3968,6 +3994,11 @@ dotenv@^6.0.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064"
integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w== integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==
dropzone@^5.5.1:
version "5.5.1"
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-5.5.1.tgz#06e2f513e61d6aa363d4b556f18574f47cf7ba26"
integrity sha512-3VduRWLxx9hbVr42QieQN25mx/I61/mRdUSuxAmDGdDqZIN8qtP7tcKMa3KfpJjuGjOJGYYUzzeq6eGDnkzesA==
duplexer3@^0.1.4: duplexer3@^0.1.4:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
@ -4217,10 +4248,10 @@ eslint-plugin-es@^1.4.0:
eslint-utils "^1.3.0" eslint-utils "^1.3.0"
regexpp "^2.0.1" regexpp "^2.0.1"
eslint-plugin-import@~2.17.2: eslint-plugin-import@~2.17.3:
version "2.17.2" version "2.17.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.2.tgz#d227d5c6dc67eca71eb590d2bb62fb38d86e9fcb" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz#00548b4434c18faebaba04b24ae6198f280de189"
integrity sha512-m+cSVxM7oLsIpmwNn2WXTJoReOF9f/CtLMo7qOVmKd1KntBy0hEcuNZ3erTmWjx+DxRO0Zcrm5KwAvI9wHcV5g== integrity sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==
dependencies: dependencies:
array-includes "^3.0.3" array-includes "^3.0.3"
contains-path "^0.1.0" contains-path "^0.1.0"
@ -4232,7 +4263,7 @@ eslint-plugin-import@~2.17.2:
lodash "^4.17.11" lodash "^4.17.11"
minimatch "^3.0.4" minimatch "^3.0.4"
read-pkg-up "^2.0.0" read-pkg-up "^2.0.0"
resolve "^1.10.0" resolve "^1.11.0"
eslint-plugin-jest@~22.6.4: eslint-plugin-jest@~22.6.4:
version "22.6.4" version "22.6.4"
@ -4499,10 +4530,10 @@ expect@^24.8.0:
jest-message-util "^24.8.0" jest-message-util "^24.8.0"
jest-regex-util "^24.3.0" jest-regex-util "^24.3.0"
express@^4.16.3, express@^4.16.4, express@~4.17.0: express@^4.16.3, express@^4.16.4, express@~4.17.1:
version "4.17.0" version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.0.tgz#288af62228a73f4c8ea2990ba3b791bb87cd4438" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
integrity sha512-1Z7/t3Z5ZnBG252gKUPyItc4xdeaA0X934ca2ewckAsVsw9EG71i++ZHZPYnus8g/s5Bty8IMpSVEuRkmwwPRQ== integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
dependencies: dependencies:
accepts "~1.3.7" accepts "~1.3.7"
array-flatten "1.1.1" array-flatten "1.1.1"
@ -5312,11 +5343,6 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1" minimalistic-crypto-utils "^1.0.1"
hoek@6.x.x:
version "6.1.3"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
hoopy@^0.1.2: hoopy@^0.1.2:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
@ -5945,13 +5971,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isemail@3.x.x:
version "3.2.0"
resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c"
integrity sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==
dependencies:
punycode "2.x.x"
isexe@^2.0.0: isexe@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@ -6389,15 +6408,6 @@ jest@~24.8.0:
import-local "^2.0.0" import-local "^2.0.0"
jest-cli "^24.8.0" jest-cli "^24.8.0"
joi@^14.3.0:
version "14.3.1"
resolved "https://registry.yarnpkg.com/joi/-/joi-14.3.1.tgz#164a262ec0b855466e0c35eea2a885ae8b6c703c"
integrity sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==
dependencies:
hoek "6.x.x"
isemail "3.x.x"
topo "3.x.x"
js-base64@^2.1.8: js-base64@^2.1.8:
version "2.5.1" version "2.5.1"
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121"
@ -7453,10 +7463,10 @@ node-sass@~4.12.0:
stdout-stream "^1.4.0" stdout-stream "^1.4.0"
"true-case-path" "^1.0.2" "true-case-path" "^1.0.2"
nodemon@^1.18.10, nodemon@~1.19.0: nodemon@^1.18.10, nodemon@~1.19.1:
version "1.19.0" version "1.19.1"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.0.tgz#358e005549a1e9e1148cb2b9b8b28957dc4e4527" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.1.tgz#576f0aad0f863aabf8c48517f6192ff987cd5071"
integrity sha512-NHKpb/Je0Urmwi3QPDHlYuFY9m1vaVfTsRZG5X73rY46xPj0JpNe8WhUGQdkDXQDOxrBNIU3JrcflE9Y44EcuA== integrity sha512-/DXLzd/GhiaDXXbGId5BzxP1GlsqtMGM9zTmkWrgXtSqjKmGSbLicM/oAy4FR0YWm14jCHRwnR31AHS2dYFHrg==
dependencies: dependencies:
chokidar "^2.1.5" chokidar "^2.1.5"
debug "^3.1.0" debug "^3.1.0"
@ -7579,6 +7589,13 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
nuxt-dropzone@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/nuxt-dropzone/-/nuxt-dropzone-1.0.2.tgz#7b39014ebf4c2084ea5c976f8d9f7b3cead2c7af"
integrity sha512-Oj6YrQxNH5KhCyFSFz2O809u23+cFAevBTdcld88qakbR2l5stTQjrv8VJ9beaqfenT9kKEkhYQT0mXc3nUdKw==
dependencies:
vue2-dropzone "3.5.8"
nuxt-env@~0.1.0: nuxt-env@~0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/nuxt-env/-/nuxt-env-0.1.0.tgz#8ac50b9ff45391ad3044ea932cbd05f06a585f87" resolved "https://registry.yarnpkg.com/nuxt-env/-/nuxt-env-0.1.0.tgz#8ac50b9ff45391ad3044ea932cbd05f06a585f87"
@ -7694,18 +7711,18 @@ onetime@^2.0.0:
dependencies: dependencies:
mimic-fn "^1.0.0" mimic-fn "^1.0.0"
open@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/open/-/open-6.3.0.tgz#60d0b845ee38fae0631f5d739a21bd40e3d2a527"
integrity sha512-6AHdrJxPvAXIowO/aIaeHZ8CeMdDf7qCyRNq8NwJpinmCdXhz+NZR7ie1Too94lpciCDsG+qHGO9Mt0svA4OqA==
dependencies:
is-wsl "^1.1.0"
opener@1.5.1, opener@^1.5.1: opener@1.5.1, opener@^1.5.1:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
opn@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==
dependencies:
is-wsl "^1.1.0"
optimism@^0.6.9: optimism@^0.6.9:
version "0.6.9" version "0.6.9"
resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.6.9.tgz#19258ff8b3be0cea29ac35f06bff818e026e30bb" resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.6.9.tgz#19258ff8b3be0cea29ac35f06bff818e026e30bb"
@ -9069,16 +9086,16 @@ punycode@1.3.2:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
punycode@^1.2.4, punycode@^1.4.1: punycode@^1.2.4, punycode@^1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
q@^1.1.2: q@^1.1.2:
version "1.5.1" version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
@ -9487,7 +9504,7 @@ resolve@1.1.7:
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1: resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.5.0, resolve@^1.8.1:
version "1.11.0" version "1.11.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232"
integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw== integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==
@ -10557,13 +10574,6 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
topo@3.x.x:
version "3.0.3"
resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.3.tgz#d5a67fb2e69307ebeeb08402ec2a2a6f5f7ad95c"
integrity sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==
dependencies:
hoek "6.x.x"
toposort@^1.0.0: toposort@^1.0.0:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029"
@ -11155,6 +11165,20 @@ vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue2-dropzone@3.5.8:
version "3.5.8"
resolved "https://registry.yarnpkg.com/vue2-dropzone/-/vue2-dropzone-3.5.8.tgz#cbe92d5424b5cc62c4d4ad62814d0cf6f3bb6cda"
integrity sha512-32rLGSx+mLKhyzxRz4CdeNT9JmbO6NsYX8m83WYqrf2ilRbm6KSZmUqZ8EIT+2dwq8EzY9jdrWlWuZJRBFPUGw==
dependencies:
dropzone "^5.5.1"
vue2-dropzone@^3.5.9:
version "3.5.9"
resolved "https://registry.yarnpkg.com/vue2-dropzone/-/vue2-dropzone-3.5.9.tgz#a63999a45a7aad24d4c21e3d35be409b4e6bdce8"
integrity sha512-nJz6teulVKlZIAeKgvPU7wBI/gzfIgqDOrEp1okSkQIkdprDVCoM0U7XWM0NOM4AAVX+4XGRtMoocYWdTYb3bQ==
dependencies:
dropzone "^5.5.1"
vue@^2.6.10, vue@^2.6.6: vue@^2.6.10, vue@^2.6.6:
version "2.6.10" version "2.6.10"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"

View File

@ -652,6 +652,13 @@
dependencies: dependencies:
regenerator-runtime "^0.12.0" regenerator-runtime "^0.12.0"
"@babel/runtime@^7.4.4":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==
dependencies:
regenerator-runtime "^0.13.2"
"@babel/template@^7.1.0", "@babel/template@^7.2.2", "@babel/template@^7.4.0": "@babel/template@^7.1.0", "@babel/template@^7.2.2", "@babel/template@^7.4.0":
version "7.4.0" version "7.4.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.0.tgz#12474e9c077bae585c5d835a95c0b0b790c25c8b" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.0.tgz#12474e9c077bae585c5d835a95c0b0b790c25c8b"
@ -990,7 +997,7 @@ babel-plugin-add-module-exports@1.0.0:
optionalDependencies: optionalDependencies:
chokidar "^2.0.4" chokidar "^2.0.4"
babel-runtime@^6.11.6, babel-runtime@^6.26.0: babel-runtime@^6.11.6:
version "6.26.0" version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
@ -1815,6 +1822,11 @@ cypress-cucumber-preprocessor@^1.11.2:
glob "^7.1.2" glob "^7.1.2"
through "^2.3.8" through "^2.3.8"
cypress-file-upload@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-3.1.2.tgz#4a0024f99ca157565bf2b20c110e6e6874da28cb"
integrity sha512-gZE2G7ZTD2Y8APrcgs+ATRMKs/IgH2rafCmi+8o99q5sDoNRLR+XKxOcoyWLehj9raGnO98YDYO8DY7k1VMGBw==
cypress-plugin-retries@^1.2.2: cypress-plugin-retries@^1.2.2:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/cypress-plugin-retries/-/cypress-plugin-retries-1.2.2.tgz#7235371ca575ad9e16f883169e7f1588379f80f2" resolved "https://registry.yarnpkg.com/cypress-plugin-retries/-/cypress-plugin-retries-1.2.2.tgz#7235371ca575ad9e16f883169e7f1588379f80f2"
@ -3520,14 +3532,14 @@ needle@^2.2.1:
iconv-lite "^0.4.4" iconv-lite "^0.4.4"
sax "^1.2.4" sax "^1.2.4"
neo4j-driver@^1.7.4: neo4j-driver@^1.7.5:
version "1.7.4" version "1.7.5"
resolved "https://registry.yarnpkg.com/neo4j-driver/-/neo4j-driver-1.7.4.tgz#9661cf643b63818bff85e82c4691918e75098c1e" resolved "https://registry.yarnpkg.com/neo4j-driver/-/neo4j-driver-1.7.5.tgz#c3fe3677f69c12f26944563d45e7e7d818a685e4"
integrity sha512-pbK1HbXh92zNSwMlXL8aNynkHohg9Jx/Tk+EewdJawGm8n8sKIY4NpRkp0nRw6RHvVBU3u9cQXt01ftFVe7j+A== integrity sha512-xCD2F5+tp/SD9r5avX5bSoY8u8RH2o793xJ9Ikjz1s5qQy7cFxFbbj2c52uz3BVGhRAx/NmB57VjOquYmmxGtw==
dependencies: dependencies:
babel-runtime "^6.26.0" "@babel/runtime" "^7.4.4"
text-encoding "^0.6.4" text-encoding-utf-8 "^1.0.2"
uri-js "^4.2.1" uri-js "^4.2.2"
next-tick@^1.0.0: next-tick@^1.0.0:
version "1.0.0" version "1.0.0"
@ -4085,6 +4097,11 @@ regenerator-runtime@^0.12.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
regenerator-runtime@^0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==
regenerator-transform@^0.13.4: regenerator-transform@^0.13.4:
version "0.13.4" version "0.13.4"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.4.tgz#18f6763cf1382c69c36df76c6ce122cc694284fb" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.4.tgz#18f6763cf1382c69c36df76c6ce122cc694284fb"
@ -4682,10 +4699,10 @@ teeny-request@^3.11.3:
node-fetch "^2.2.0" node-fetch "^2.2.0"
uuid "^3.3.2" uuid "^3.3.2"
text-encoding@^0.6.4: text-encoding-utf-8@^1.0.2:
version "0.6.4" version "1.0.2"
resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13"
integrity sha1-45mpgiV6J22uQou5KEXLcb3CbRk= integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==
thenify-all@^1.0.0: thenify-all@^1.0.0:
version "1.6.0" version "1.6.0"
@ -4888,7 +4905,7 @@ upper-case@^1.0.3:
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
uri-js@^4.2.1, uri-js@^4.2.2: uri-js@^4.2.2:
version "4.2.2" version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==