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:
# Backend
- 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:seed
- docker-compose exec backend yarn run test:cucumber
@ -30,7 +30,7 @@ script:
- docker-compose exec backend yarn run db:seed
# Frontend
- 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
# Fullstack
- CYPRESS_RETRIES=1 yarn run cypress:run

View File

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

View File

@ -26,7 +26,6 @@
"license": "MIT",
"jest": {
"verbose": true,
"collectCoverage": true,
"collectCoverageFrom": [
"**/*.js",
"!**/node_modules/**",
@ -56,7 +55,7 @@
"date-fns": "2.0.0-alpha.27",
"debug": "~4.1.1",
"dotenv": "~8.0.0",
"express": "~4.17.0",
"express": "~4.17.1",
"faker": "~4.1.0",
"graphql": "~14.3.1",
"graphql-custom-directives": "~0.2.14",
@ -71,7 +70,7 @@
"lodash": "~4.17.11",
"ms": "~2.1.1",
"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",
"npm-run-all": "~4.1.5",
"request": "~2.88.0",
@ -97,7 +96,7 @@
"eslint": "~5.16.0",
"eslint-config-standard": "~12.0.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-node": "~9.1.0",
"eslint-plugin-prettier": "~3.1.0",
@ -105,8 +104,8 @@
"eslint-plugin-standard": "~4.0.0",
"graphql-request": "~1.8.2",
"jest": "~24.8.0",
"nodemon": "~1.19.0",
"nodemon": "~1.19.1",
"prettier": "~1.14.3",
"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 notifications from './resolvers/notifications'
import comments from './resolvers/comments'
import users from './resolvers/users'
export const typeDefs = fs
.readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, 'schema.graphql'))
@ -35,5 +36,6 @@ export const resolvers = {
...socialMedia.Mutation,
...notifications.Mutation,
...comments.Mutation,
...users.Mutation,
},
}

View File

@ -2,6 +2,7 @@ import cheerio from 'cheerio'
const ID_REGEX = /\/profile\/([\w\-.!~*'"(),]+)/g
export default function(content) {
if (!content) return []
const $ = cheerio.load(content)
const urls = $('.mention')
.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', () => {
it('ignores links without .mention class', () => {
const content =

View File

@ -1,4 +1,4 @@
import extractIds from './extractMentions'
import extractIds from './extractIds'
const notify = async (resolve, root, args, context, resolveInfo) => {
// 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 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 */
return await resolve(root, args, context, info)
} 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 fileUpload from './fileUpload'
export default {
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) => {
params = await fileUpload(params, { file: 'imageUpload', url: 'image' })
const result = await neo4jgraphql(object, params, context, resolveInfo, false)
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 () => {
const variables = {
id: 'u47',
name: null,
}
const expected = 'Username must be at least 3 characters long!'
await expect(client.request(mutation, variables)).rejects.toThrow(expected)

View File

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

View File

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

View File

@ -6,7 +6,7 @@ just apply our provided configuration files to your cluster.
## Configuration
Copy our provided templates:
Change into the `./deployment` directory and copy our provided templates:
```bash
# in folder deployment/human-connection/
@ -14,7 +14,7 @@ $ cp templates/secrets.template.yaml ./secrets.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.
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
# example how to base64 a string:
$ echo -n 'admin' | base64 --wrap 0
$ echo -n 'admin' | base64
YWRtaW4=
```

View File

@ -8,5 +8,5 @@ do
fi
done
/migration/mongo/import.sh
/migration/mongo/export.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"]})
ON CREATE SET
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"]})
ON CREATE SET
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"]})
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"]})
ON CREATE SET
p.title = post.title,
@ -20,6 +20,6 @@ MATCH (c:Category {id: categoryId})
MERGE (p)-[:CATEGORIZED]->(c)
WITH p, post.tags AS tags
UNWIND tags AS tag
MERGE (t:Tag {id: apoc.create.uuid(), name: tag})
MERGE (t:Tag {id: tag, name: tag})
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})
MERGE (u1)-[:FOLLOWS]->(u2)
;

View File

@ -1,17 +1,48 @@
#!/usr/bin/env bash
set -e
SECONDS=0
SCRIPT_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
# import .env config
set -o allexport
source $(dirname "$0")/.env
set +o allexport
echo "MATCH (n) DETACH DELETE n;" | cypher-shell
for collection in "badges" "categories" "users" "follows" "contributions" "shouts" "comments"
do
for chunk in /tmp/mongo-export/splits/$collection/*
# Import collection function defintion
function import_collection () {
for chunk in ${IMPORT_PATH}splits/$1/*
do
mv $chunk /tmp/mongo-export/splits/current-chunk.json
echo "Import ${chunk}" && cypher-shell < $SCRIPT_DIRECTORY/$collection.cql
mv $chunk ${IMPORT_CHUNK_PATH}
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
}
# 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"

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})
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"]})
ON CREATE SET
u.name = user.name,

View File

@ -23,11 +23,12 @@
"cross-env": "^5.2.0",
"cypress": "^3.3.1",
"cypress-cucumber-preprocessor": "^1.11.2",
"cypress-file-upload": "^3.1.2",
"cypress-plugin-retries": "^1.2.2",
"dotenv": "^8.0.0",
"faker": "^4.1.0",
"graphql-request": "^1.8.2",
"neo4j-driver": "^1.7.4",
"neo4j-driver": "^1.7.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() {
this.editor.destroy()
},
methods: {
changePlaceHolderText() {
this.editor.extensions.options.placeholder.emptyNodeText = this.$t('editor.placeholder')
},
// navigate to the previous item
// if it's the first item, navigate to the last one
upHandler() {

View File

@ -14,7 +14,8 @@
<ds-icon
style="margin-right: 2px;"
name="globe"
/> {{ current.code.toUpperCase() }}
/>
{{ current.code.toUpperCase() }}
<ds-icon
style="margin-left: 2px"
size="xx-small"
@ -78,6 +79,7 @@ export default {
changeLanguage(locale, toggleMenu) {
this.$i18n.set(locale)
toggleMenu()
this.$root.$emit('changeLanguage')
},
matcher(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
style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;"
>
<ds-avatar
style="display: inline-block; vertical-align: middle;"
size="small"
/>
<hc-avatar />
</div>
<div style="display: inline-block; height: 100%; vertical-align: middle;">
<b
@ -36,11 +33,8 @@
<div
style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;"
>
<ds-avatar
:image="user.avatar"
:name="userName"
style="display: inline-block; vertical-align: middle;"
size="small"
<hc-avatar
:user="user"
/>
</div>
<div style="display: inline-block; height: 100%; vertical-align: middle;">
@ -143,6 +137,7 @@ import { mapGetters } from 'vuex'
import HcRelativeDateTime from '~/components/RelativeDateTime'
import HcFollowButton from '~/components/FollowButton'
import HcBadges from '~/components/Badges'
import HcAvatar from '~/components/Avatar/Avatar.vue'
import Dropdown from '~/components/Dropdown'
export default {
@ -150,6 +145,7 @@ export default {
components: {
HcRelativeDateTime,
HcFollowButton,
HcAvatar,
HcBadges,
Dropdown,
},
@ -183,12 +179,6 @@ export default {
</script>
<style lang="scss">
.profile-avatar {
display: block;
margin: auto;
margin-top: -45px;
border: #fff 5px solid;
}
.user {
white-space: nowrap;
position: relative;

View File

@ -5,14 +5,12 @@
>
<template slot-scope="{ errors }">
<ds-card>
<no-ssr>
<hc-editor
ref="editor"
:users="users"
:value="form.content"
@input="updateEditorContent"
/>
</no-ssr>
<hc-editor
ref="editor"
:users="users"
:value="form.content"
@input="updateEditorContent"
/>
<ds-space />
<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%' }" />

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 Styleguide from '@human-connection/styleguide'
@ -6,8 +6,6 @@ const localVue = createLocalVue()
localVue.use(Styleguide)
config.stubs['no-ssr'] = '<span><slot /></span>'
describe('CommentForm.vue', () => {
let mocks
let wrapper

View File

@ -33,6 +33,13 @@ describe('CommentList.vue', () => {
})
mocks = {
$t: jest.fn(),
$apollo: {
queries: {
Post: {
refetch: jest.fn(),
},
},
},
}
data = () => {
return {
@ -63,5 +70,10 @@ describe('CommentList.vue', () => {
it('displays comments when there are comments to display', () => {
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() {
this.$root.$on('refetchPostComments', comment => {
this.refetchPostComments(comment)
this.$root.$on('refetchPostComments', () => {
this.refetchPostComments()
})
},
methods: {
refetchPostComments(comment) {
this.$apollo.queries.Post.refetch()
refetchPostComments() {
if (this.$apollo.queries.Post) {
this.$apollo.queries.Post.refetch()
}
},
deleteComment(index) {
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"
@click.prevent="toggleMenu"
>
<ds-avatar
:image="user.avatar"
:name="user.name"
size="small"
<hc-avatar
:user="user"
/>
<ds-icon
size="xx-small"
@ -123,6 +121,7 @@ import SearchInput from '~/components/SearchInput.vue'
import Modal from '~/components/Modal'
import NotificationMenu from '~/components/notifications/NotificationMenu'
import Dropdown from '~/components/Dropdown'
import HcAvatar from '~/components/Avatar/Avatar.vue'
import seo from '~/mixins/seo'
export default {
@ -132,6 +131,7 @@ export default {
SearchInput,
Modal,
NotificationMenu,
HcAvatar,
},
mixins: [seo],
data() {

View File

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

View File

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

View File

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

View File

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

View File

@ -710,6 +710,32 @@
resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
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":
version "0.5.17"
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"
webpack-node-externals "^1.7.2"
"@nuxtjs/axios@~5.5.1":
version "5.5.1"
resolved "https://registry.yarnpkg.com/@nuxtjs/axios/-/axios-5.5.1.tgz#e0eeddcbbec4f04bd705b96afd05071340169b36"
integrity sha512-MRZGuXM13D7tFf01D6LJZ7jYxIxD+poRfqgpVHbXIA/AN2FEWvVx9Sv3VlwniEM50+NqzcHHEGv4k2s2ZSSE6g==
"@nuxtjs/axios@~5.5.2":
version "5.5.2"
resolved "https://registry.yarnpkg.com/@nuxtjs/axios/-/axios-5.5.2.tgz#b6447bb12707b56b16b942ae6c737a0b051cecba"
integrity sha512-S5+IkUjCSSFeMVZp/JAzjoit9P7Di2QM4beAlFbHXbOEG+/vSaZReW8l817u9WC6nuKa3x6HhZfWD3tJDTvljg==
dependencies:
"@nuxtjs/proxy" "^1.3.3"
axios "^0.18.0"
@ -1455,18 +1481,18 @@
"@vue/babel-plugin-transform-vue-jsx" "^1.0.0"
camelcase "^5.0.0"
"@vue/cli-shared-utils@~3.7.0":
version "3.7.0"
resolved "https://registry.yarnpkg.com/@vue/cli-shared-utils/-/cli-shared-utils-3.7.0.tgz#957dd3c31a31208caf9f119cac6008fd4960d46e"
integrity sha512-+LPDAQ1CE3ci1ADOvNqJMPdqyxgJxOq5HUgGDSKCHwviXF6GtynfljZXiSzgWh5ueMFxJphCfeMsTZqFWwsHVg==
"@vue/cli-shared-utils@~3.8.0":
version "3.8.0"
resolved "https://registry.yarnpkg.com/@vue/cli-shared-utils/-/cli-shared-utils-3.8.0.tgz#e7e728164eb92bd9e205fcd08dae896ee79cba5a"
integrity sha512-wn1L8pmQnotfftHOYm0VeXs2+cQTySd73uhWXwyO6pT0ehjqlY5c2RTipClmFF3Q+YCYjwlNpsV650F3l1tV8w==
dependencies:
"@hapi/joi" "^15.0.1"
chalk "^2.4.1"
execa "^1.0.0"
joi "^14.3.0"
launch-editor "^2.2.1"
lru-cache "^5.1.1"
node-ipc "^9.1.1"
opn "^5.3.0"
open "^6.3.0"
ora "^3.4.0"
request "^2.87.0"
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"
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:
version "0.1.4"
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"
regexpp "^2.0.1"
eslint-plugin-import@~2.17.2:
version "2.17.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.2.tgz#d227d5c6dc67eca71eb590d2bb62fb38d86e9fcb"
integrity sha512-m+cSVxM7oLsIpmwNn2WXTJoReOF9f/CtLMo7qOVmKd1KntBy0hEcuNZ3erTmWjx+DxRO0Zcrm5KwAvI9wHcV5g==
eslint-plugin-import@~2.17.3:
version "2.17.3"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz#00548b4434c18faebaba04b24ae6198f280de189"
integrity sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==
dependencies:
array-includes "^3.0.3"
contains-path "^0.1.0"
@ -4232,7 +4263,7 @@ eslint-plugin-import@~2.17.2:
lodash "^4.17.11"
minimatch "^3.0.4"
read-pkg-up "^2.0.0"
resolve "^1.10.0"
resolve "^1.11.0"
eslint-plugin-jest@~22.6.4:
version "22.6.4"
@ -4499,10 +4530,10 @@ expect@^24.8.0:
jest-message-util "^24.8.0"
jest-regex-util "^24.3.0"
express@^4.16.3, express@^4.16.4, express@~4.17.0:
version "4.17.0"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.0.tgz#288af62228a73f4c8ea2990ba3b791bb87cd4438"
integrity sha512-1Z7/t3Z5ZnBG252gKUPyItc4xdeaA0X934ca2ewckAsVsw9EG71i++ZHZPYnus8g/s5Bty8IMpSVEuRkmwwPRQ==
express@^4.16.3, express@^4.16.4, express@~4.17.1:
version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
dependencies:
accepts "~1.3.7"
array-flatten "1.1.1"
@ -5312,11 +5343,6 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
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:
version "0.1.4"
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"
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:
version "2.0.0"
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"
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:
version "2.5.1"
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"
"true-case-path" "^1.0.2"
nodemon@^1.18.10, nodemon@~1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.0.tgz#358e005549a1e9e1148cb2b9b8b28957dc4e4527"
integrity sha512-NHKpb/Je0Urmwi3QPDHlYuFY9m1vaVfTsRZG5X73rY46xPj0JpNe8WhUGQdkDXQDOxrBNIU3JrcflE9Y44EcuA==
nodemon@^1.18.10, nodemon@~1.19.1:
version "1.19.1"
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.1.tgz#576f0aad0f863aabf8c48517f6192ff987cd5071"
integrity sha512-/DXLzd/GhiaDXXbGId5BzxP1GlsqtMGM9zTmkWrgXtSqjKmGSbLicM/oAy4FR0YWm14jCHRwnR31AHS2dYFHrg==
dependencies:
chokidar "^2.1.5"
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"
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:
version "0.1.0"
resolved "https://registry.yarnpkg.com/nuxt-env/-/nuxt-env-0.1.0.tgz#8ac50b9ff45391ad3044ea932cbd05f06a585f87"
@ -7694,18 +7711,18 @@ onetime@^2.0.0:
dependencies:
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:
version "1.5.1"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
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:
version "0.6.9"
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"
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:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
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:
version "1.5.1"
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"
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"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232"
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"
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:
version "1.0.7"
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"
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:
version "2.6.10"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"

View File

@ -652,6 +652,13 @@
dependencies:
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":
version "7.4.0"
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:
chokidar "^2.0.4"
babel-runtime@^6.11.6, babel-runtime@^6.26.0:
babel-runtime@^6.11.6:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
@ -1815,6 +1822,11 @@ cypress-cucumber-preprocessor@^1.11.2:
glob "^7.1.2"
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:
version "1.2.2"
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"
sax "^1.2.4"
neo4j-driver@^1.7.4:
version "1.7.4"
resolved "https://registry.yarnpkg.com/neo4j-driver/-/neo4j-driver-1.7.4.tgz#9661cf643b63818bff85e82c4691918e75098c1e"
integrity sha512-pbK1HbXh92zNSwMlXL8aNynkHohg9Jx/Tk+EewdJawGm8n8sKIY4NpRkp0nRw6RHvVBU3u9cQXt01ftFVe7j+A==
neo4j-driver@^1.7.5:
version "1.7.5"
resolved "https://registry.yarnpkg.com/neo4j-driver/-/neo4j-driver-1.7.5.tgz#c3fe3677f69c12f26944563d45e7e7d818a685e4"
integrity sha512-xCD2F5+tp/SD9r5avX5bSoY8u8RH2o793xJ9Ikjz1s5qQy7cFxFbbj2c52uz3BVGhRAx/NmB57VjOquYmmxGtw==
dependencies:
babel-runtime "^6.26.0"
text-encoding "^0.6.4"
uri-js "^4.2.1"
"@babel/runtime" "^7.4.4"
text-encoding-utf-8 "^1.0.2"
uri-js "^4.2.2"
next-tick@^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"
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:
version "0.13.4"
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"
uuid "^3.3.2"
text-encoding@^0.6.4:
version "0.6.4"
resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19"
integrity sha1-45mpgiV6J22uQou5KEXLcb3CbRk=
text-encoding-utf-8@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13"
integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg==
thenify-all@^1.0.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"
integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
uri-js@^4.2.1, uri-js@^4.2.2:
uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==