Merge remote-tracking branch 'origin/master' into refactor_factories_with_rosie

There was a single step definition that created a post and a comment. I
would say let's put that in two different steps.
This commit is contained in:
roschaefer 2020-01-31 18:46:09 +01:00
commit fa0e64b7cb
80 changed files with 1323 additions and 1390 deletions

View File

@ -64,7 +64,7 @@ Regular pair programming sessions
* we team up and work on an issue together (often using Visual Studio live sharing sessions)
Open-Source Community Meeting
* every Thursday 13:00
* bi-weekly on Mondays 13:00 (when there is no sprint retrospective)
* the link will be posted in the [discord chat](https://discord.gg/6ub73U3) and on the [Agile Ventures website](https://www.agileventures.org/events?utf8=%E2%9C%93&project_id=220&commit=Filter+by+Project)
* all contributors welcome!
@ -99,3 +99,34 @@ We believe in open source contributions as a learning experience everyone is
We use pair programming sessions as a tool for knowledge sharing. We can learn a lot from each other and only by sharing what we know and overcoming challenges together can we grow as a team and truly own this project collectively.
As a volunteeer you have no commitment except your own self development and your awesomeness by contributing to this free and open-source software project. Cheers to you!
## Open-Source Bounties
There are so many good reasons to contribute to Human Connection
* You learn state-of-the-art technologies
* You build your portfolio
* You contribute to a good cause
Now there is one more good reason: You can receive a small fincancial
compensation for your contribution! :tada:
### How it works
Before you can benefit from the Open-Source bounty program you **must get one
pull request approved and merged for free**. You can choose something really
quick and easy. What's important is starting a working relationship with the
team, learning the workflow, and understanding this contribution guide. You can
filter issues by 'good first issue', to get an idea where to start. Please join
our our [community chat](https://human-connection.org/discord), too.
You can filter Github issues with label [bounty](https://github.com/Human-Connection/Human-Connection/issues?q=is%3Aopen+is%3Aissue+label%3Abounty). These issues should have a second label `€<amount>`
which indicate their respective financial compensation in Euros.
You can bill us after your pull request got approved and merged into `master`.
Payment methods are up to you: Bank transfer or PayPal is fine for us. Just send
us your invoice as .pdf file attached to an E-Mail once you are done.
Our Open-Source bounty program is a work-in-progress. Based on our future
experience we will make changes and improvements. So keep an eye on this
contribution guide.

View File

@ -52,6 +52,10 @@ Check out the [contribution guideline](./CONTRIBUTING.md), too!
[![](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/images/0)](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/0)[![](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/images/1)](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/1)[![](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/images/2)](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/2)[![](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/images/3)](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/3)[![](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/images/4)](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/4)[![](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/images/5)](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/5)[![](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/images/6)](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/6)[![](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/images/7)](https://sourcerer.io/fame/roschaefer/Human-Connection/Human-Connection/links/7)
## Open-Source Bounties
You can get a small financial compensation for your contribution :moneybag: See
details in our [Contribution Guidelines](./CONTRIBUTING.md#open-source-bounties).
## Attributions

View File

@ -38,7 +38,7 @@
},
"dependencies": {
"@hapi/joi": "^17.1.0",
"@sentry/node": "^5.11.1",
"@sentry/node": "^5.11.2",
"apollo-cache-inmemory": "~1.6.5",
"apollo-client": "~2.6.8",
"apollo-link-context": "~1.0.19",
@ -60,7 +60,7 @@
"graphql-iso-date": "~3.6.1",
"graphql-middleware": "~4.0.2",
"graphql-middleware-sentry": "^3.2.1",
"graphql-shield": "~7.0.8",
"graphql-shield": "~7.0.9",
"graphql-tag": "~2.10.1",
"helmet": "~3.21.2",
"jsonwebtoken": "~8.5.1",
@ -103,11 +103,11 @@
"xregexp": "^4.2.4"
},
"devDependencies": {
"@babel/cli": "~7.8.3",
"@babel/core": "~7.8.3",
"@babel/node": "~7.8.3",
"@babel/cli": "~7.8.4",
"@babel/core": "~7.8.4",
"@babel/node": "~7.8.4",
"@babel/plugin-proposal-throw-expressions": "^7.8.3",
"@babel/preset-env": "~7.8.3",
"@babel/preset-env": "~7.8.4",
"@babel/register": "^7.8.3",
"apollo-server-testing": "~2.9.16",
"babel-core": "~7.0.0-0",
@ -116,7 +116,7 @@
"chai": "~4.2.0",
"cucumber": "~6.0.5",
"eslint": "~6.8.0",
"eslint-config-prettier": "~6.9.0",
"eslint-config-prettier": "~6.10.0",
"eslint-config-standard": "~14.1.0",
"eslint-plugin-import": "~2.20.0",
"eslint-plugin-jest": "~23.6.0",

View File

@ -1,5 +1,5 @@
import { handler } from './webfinger'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { getDriver } from '../../db/neo4j'
let resource, res, json, status, contentType

View File

@ -1,4 +1,4 @@
import { cleanDatabase } from '../factories'
import { cleanDatabase } from '../db/factories'
if (process.env.NODE_ENV === 'production') {
throw new Error(`You cannot clean the database in production environment!`)

View File

@ -3,7 +3,7 @@ import faker from 'faker'
import slugify from 'slug'
import { hashSync } from 'bcryptjs'
import { Factory } from 'rosie'
import { getDriver, getNeode } from './db/neo4j'
import { getDriver, getNeode } from './neo4j'
const neode = getNeode()
@ -26,8 +26,8 @@ export const cleanDatabase = async (options = {}) => {
Factory.define('category')
.attr('id', uuid)
.attr('icon', 'img/badges/fundraisingbox_de_airship.svg')
.attr('name', 'Some category name')
.attr('icon', 'globe')
.attr('name', 'global-peace-nonviolence')
.after((buildObject, options) => {
return neode.create('Category', buildObject)
})

View File

@ -2,7 +2,7 @@ import faker from 'faker'
import sample from 'lodash/sample'
import { createTestClient } from 'apollo-server-testing'
import createServer from '../server'
import Factory from '../factories'
import Factory from '../db/factories'
import { getNeode, getDriver } from '../db/neo4j'
import { gql } from '../helpers/jest'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../factories'
import Factory, { cleanDatabase } from '../db/factories'
import { getDriver, getNeode } from '../db/neo4j'
import decode from './decode'

View File

@ -1,5 +1,5 @@
import { gql } from '../../helpers/jest'
import { cleanDatabase } from '../../factories'
import { cleanDatabase } from '../../db/factories'
import { createTestClient } from 'apollo-server-testing'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -50,7 +50,7 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
MATCH (post: Post { id: $id })<-[:WROTE]-(author: User)
MATCH (user: User)
WHERE user.id in $idsOfUsers
AND NOT (user)<-[:BLOCKED]-(author)
AND NOT (user)-[:BLOCKED]-(author)
MERGE (post)-[notification:NOTIFIED {reason: $reason}]->(user)
`
break
@ -60,8 +60,8 @@ const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
MATCH (postAuthor: User)-[:WROTE]->(post: Post)<-[:COMMENTS]-(comment: Comment { id: $id })<-[:WROTE]-(author: User)
MATCH (user: User)
WHERE user.id in $idsOfUsers
AND NOT (user)<-[:BLOCKED]-(author)
AND NOT (user)<-[:BLOCKED]-(postAuthor)
AND NOT (user)-[:BLOCKED]-(author)
AND NOT (user)-[:BLOCKED]-(postAuthor)
MERGE (comment)-[notification:NOTIFIED {reason: $reason}]->(user)
`
break

View File

@ -1,5 +1,5 @@
import { gql } from '../../helpers/jest'
import { cleanDatabase } from '../../factories'
import { cleanDatabase } from '../../db/factories'
import { createTestClient } from 'apollo-server-testing'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,5 +1,5 @@
import { gql } from '../helpers/jest'
import { cleanDatabase } from '../factories'
import { cleanDatabase } from '../db/factories'
import { getNeode, getDriver } from '../db/neo4j'
import { createTestClient } from 'apollo-server-testing'
import createServer from '../server'

View File

@ -102,6 +102,7 @@ export default shield(
PostsEmotionsCountByEmotion: allow,
PostsEmotionsByCurrentUser: isAuthenticated,
mutedUsers: isAuthenticated,
blockedUsers: isAuthenticated,
notifications: isAuthenticated,
Donations: isAuthenticated,
},
@ -139,6 +140,8 @@ export default shield(
RemovePostEmotions: isAuthenticated,
muteUser: isAuthenticated,
unmuteUser: isAuthenticated,
blockUser: isAuthenticated,
unblockUser: isAuthenticated,
markAsRead: isAuthenticated,
AddEmailAddress: isAuthenticated,
VerifyEmailAddress: isAuthenticated,

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing'
import createServer from '../server'
import Factory, { cleanDatabase } from '../factories'
import Factory, { cleanDatabase } from '../db/factories'
import { gql } from '../helpers/jest'
import { getDriver, getNeode } from '../db/neo4j'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../factories'
import Factory, { cleanDatabase } from '../db/factories'
import { gql } from '../helpers/jest'
import { getNeode, getDriver } from '../db/neo4j'
import createServer from '../server'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,5 +1,5 @@
import { gql } from '../../helpers/jest'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { getNeode, getDriver } from '../../db/neo4j'
import { createTestClient } from 'apollo-server-testing'
import createServer from '../../server'

View File

@ -41,5 +41,15 @@ export default {
language: { type: 'string', allow: [null] },
imageBlurred: { type: 'boolean', default: false },
imageAspectRatio: { type: 'float', default: 1.0 },
comments: {
type: 'relationship',
relationship: 'COMMENTS',
target: 'Comment',
direction: 'in',
properties: {
createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() },
updatedAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() },
},
},
pinned: { type: 'boolean', default: null, valid: [null, true] },
}

View File

@ -1,4 +1,4 @@
import { cleanDatabase } from '../factories'
import { cleanDatabase } from '../db/factories'
import { getNeode } from '../db/neo4j'
const neode = getNeode()

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { createTestClient } from 'apollo-server-testing'
import createServer from '../../server'

View File

@ -1,5 +1,5 @@
import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getDriver, getNeode } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,5 +1,5 @@
import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { getDriver, getNeode } from '../../db/neo4j'
import createServer from '../../server'
import { gql } from '../../helpers/jest'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,5 +1,5 @@
import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getDriver } from '../../db/neo4j'
import { createTestClient } from 'apollo-server-testing'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createPasswordReset from './helpers/createPasswordReset'

View File

@ -1,5 +1,5 @@
import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getDriver, getNeode } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing'
import createServer from '../.././server'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getDriver, getNeode } from '../../db/neo4j'

View File

@ -1,5 +1,5 @@
import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -20,7 +20,7 @@ export default {
AND NOT (
author.deleted = true OR author.disabled = true
OR resource.deleted = true OR resource.disabled = true
OR (:User { id: $thisUserId })-[:BLOCKED]-(author)
OR (:User {id: $thisUserId})-[:MUTED]->(author)
)
WITH resource, author,
[(resource)<-[:COMMENTS]-(comment:Comment) | comment] as comments,
@ -40,8 +40,7 @@ export default {
YIELD node as resource, score
MATCH (resource)
WHERE score >= 0.5
AND NOT (resource.deleted = true OR resource.disabled = true
OR (:User { id: $thisUserId })-[:BLOCKED]-(resource))
AND NOT (resource.deleted = true OR resource.disabled = true)
RETURN resource {.*, __typename: labels(resource)[0]}
LIMIT $limit
`

View File

@ -1,5 +1,5 @@
import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing'
import createServer from '../../server'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getDriver } from '../../db/neo4j'

View File

@ -1,5 +1,5 @@
import { createTestClient } from 'apollo-server-testing'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,6 +1,6 @@
import jwt from 'jsonwebtoken'
import CONFIG from './../../config'
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { createTestClient } from 'apollo-server-testing'
import createServer, { context } from '../../server'

View File

@ -23,6 +23,21 @@ export const getMutedUsers = async context => {
return mutedUsers
}
export const getBlockedUsers = async context => {
const { neode } = context
const userModel = neode.model('User')
let blockedUsers = neode
.query()
.match('user', userModel)
.where('user.id', context.user.id)
.relationship(userModel.relationships().get('blocked'))
.to('blocked', userModel)
.return('blocked')
blockedUsers = await blockedUsers.execute()
blockedUsers = blockedUsers.records.map(r => r.get('blocked').properties)
return blockedUsers
}
export default {
Query: {
mutedUsers: async (object, args, context, resolveInfo) => {
@ -32,6 +47,13 @@ export default {
throw new UserInputError(e.message)
}
},
blockedUsers: async (object, args, context, resolveInfo) => {
try {
return getBlockedUsers(context)
} catch (e) {
throw new UserInputError(e.message)
}
},
User: async (object, args, context, resolveInfo) => {
const { email } = args
if (email) {
@ -86,7 +108,7 @@ export default {
const unmutedUser = await neode.find('User', params.id)
return unmutedUser.toJson()
},
block: async (object, args, context, resolveInfo) => {
blockUser: async (object, args, context, resolveInfo) => {
const { user: currentUser } = context
if (currentUser.id === args.id) return null
await neode.cypher(
@ -103,7 +125,7 @@ export default {
await user.relateTo(blockedUser, 'blocked')
return blockedUser.toJson()
},
unblock: async (object, args, context, resolveInfo) => {
unblockUser: async (object, args, context, resolveInfo) => {
const { user: currentUser } = context
if (currentUser.id === args.id) return null
await neode.cypher(
@ -229,7 +251,7 @@ export default {
boolean: {
followedByCurrentUser:
'MATCH (this)<-[:FOLLOWS]-(u:User {id: $cypherParams.currentUserId}) RETURN COUNT(u) >= 1',
isBlocked:
blocked:
'MATCH (this)<-[:BLOCKED]-(u:User {id: $cypherParams.currentUserId}) RETURN COUNT(u) >= 1',
isMuted:
'MATCH (this)<-[:MUTED]-(u:User {id: $cypherParams.currentUserId}) RETURN COUNT(u) >= 1',

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../factories'
import Factory, { cleanDatabase } from '../../db/factories'
import { gql } from '../../helpers/jest'
import { getNeode, getDriver } from '../../db/neo4j'
import createServer from '../../server'

View File

@ -1,5 +1,5 @@
import { gql } from '../../../helpers/jest'
import Factory, { cleanDatabase } from '../../../factories'
import Factory, { cleanDatabase } from '../../../db/factories'
import { getNeode, getDriver } from '../../../db/neo4j'
import { createTestClient } from 'apollo-server-testing'
import createServer from '../../../server'

View File

@ -1,6 +1,6 @@
import { createTestClient } from 'apollo-server-testing'
import createServer from '../../../server'
import { cleanDatabase } from '../../../factories'
import { cleanDatabase } from '../../../db/factories'
import { gql } from '../../../helpers/jest'
import { getNeode, getDriver } from '../../../db/neo4j'

View File

@ -68,10 +68,11 @@ type User {
RETURN COUNT(u) >= 1
"""
)
isBlocked: Boolean! @cypher(
blocked: Boolean! @cypher(
statement: """
MATCH (this)<-[: BLOCKED]-(u: User { id: $cypherParams.currentUserId})
RETURN COUNT(u) >= 1
MATCH (this)-[:BLOCKED]-(user:User {id: $cypherParams.currentUserId})
RETURN COUNT(user) >= 1
"""
)
@ -207,6 +208,6 @@ type Mutation {
muteUser(id: ID!): User
unmuteUser(id: ID!): User
block(id: ID!): User
unblock(id: ID!): User
blockUser(id: ID!): User
unblockUser(id: ID!): User
}

View File

@ -3,7 +3,7 @@ import { Given, When, Then, AfterAll } from 'cucumber'
import { expect } from 'chai'
// import { client } from '../../../src/activitypub/apollo-client'
import { GraphQLClient } from 'graphql-request'
import Factory from '../../../src/factories'
import Factory from '../../../src/db/factories'
const debug = require('debug')('ea:test:steps')
const client = new GraphQLClient(host)

View File

@ -33,10 +33,10 @@
resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.24.tgz#3ce939cb127fb8aaa3ffc1e90dff9b8af9f2e3dc"
integrity sha512-8GqG48m1XqyXh4mIZrtB5xOhUwSsh1WsrrsaZQOEYYql3YN9DEu9OOSg0ILzXHZo/h2Q74777YE4YzlArQzQEQ==
"@babel/cli@~7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.8.3.tgz#121beb7c273e0521eb2feeb3883a2b7435d12328"
integrity sha512-K2UXPZCKMv7KwWy9Bl4sa6+jTNP7JyDiHKzoOiUUygaEDbC60vaargZDnO9oFMvlq8pIKOOyUUgeMYrsaN9djA==
"@babel/cli@~7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.8.4.tgz#505fb053721a98777b2b175323ea4f090b7d3c1c"
integrity sha512-XXLgAm6LBbaNxaGhMAznXXaxtCWfuv6PIDJ9Alsy9JYTOh+j2jJz+L/162kkfU1j/pTSxK1xGmlwI4pdIMkoag==
dependencies:
commander "^4.0.1"
convert-source-map "^1.1.0"
@ -56,26 +56,26 @@
dependencies:
"@babel/highlight" "^7.8.3"
"@babel/compat-data@^7.8.0", "@babel/compat-data@^7.8.1":
version "7.8.1"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.1.tgz#fc0bbbb7991e4fb2b47e168e60f2cc2c41680be9"
integrity sha512-Z+6ZOXvyOWYxJ50BwxzdhRnRsGST8Y3jaZgxYig575lTjVSs3KtJnmESwZegg6e2Dn0td1eDhoWlp1wI4BTCPw==
"@babel/compat-data@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.4.tgz#bbe65d05a291667a8394fe8a0e0e277ef22b0d2a"
integrity sha512-lHLhlsvFjJAqNU71b7k6Vv9ewjmTXKvqaMv7n0G1etdCabWLw3nEYE8mmgoVOxMIFE07xOvo7H7XBASirX6Rrg==
dependencies:
browserslist "^4.8.2"
browserslist "^4.8.5"
invariant "^2.2.4"
semver "^5.5.0"
"@babel/core@^7.1.0", "@babel/core@^7.7.5", "@babel/core@~7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941"
integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==
"@babel/core@^7.1.0", "@babel/core@^7.7.5", "@babel/core@~7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e"
integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==
dependencies:
"@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.8.3"
"@babel/helpers" "^7.8.3"
"@babel/parser" "^7.8.3"
"@babel/generator" "^7.8.4"
"@babel/helpers" "^7.8.4"
"@babel/parser" "^7.8.4"
"@babel/template" "^7.8.3"
"@babel/traverse" "^7.8.3"
"@babel/traverse" "^7.8.4"
"@babel/types" "^7.8.3"
convert-source-map "^1.7.0"
debug "^4.1.0"
@ -86,10 +86,10 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03"
integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==
"@babel/generator@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e"
integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==
dependencies:
"@babel/types" "^7.8.3"
jsesc "^2.5.1"
@ -120,15 +120,15 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
"@babel/helper-compilation-targets@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.3.tgz#2deedc816fd41dca7355ef39fd40c9ea69f0719a"
integrity sha512-JLylPCsFjhLN+6uBSSh3iYdxKdeO9MNmoY96PE/99d8kyBFaXLORtAVhqN6iHa+wtPeqxKLghDOZry0+Aiw9Tw==
"@babel/helper-compilation-targets@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz#03d7ecd454b7ebe19a254f76617e61770aed2c88"
integrity sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg==
dependencies:
"@babel/compat-data" "^7.8.1"
browserslist "^4.8.2"
"@babel/compat-data" "^7.8.4"
browserslist "^4.8.5"
invariant "^2.2.4"
levenary "^1.1.0"
levenary "^1.1.1"
semver "^5.5.0"
"@babel/helper-create-regexp-features-plugin@^7.8.3":
@ -270,13 +270,13 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
"@babel/helpers@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.3.tgz#382fbb0382ce7c4ce905945ab9641d688336ce85"
integrity sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==
"@babel/helpers@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73"
integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==
dependencies:
"@babel/template" "^7.8.3"
"@babel/traverse" "^7.8.3"
"@babel/traverse" "^7.8.4"
"@babel/types" "^7.8.3"
"@babel/highlight@^7.8.3":
@ -288,10 +288,10 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
"@babel/node@~7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.8.3.tgz#29784d445e135ca7214a9ac40535f2b8d2f980aa"
integrity sha512-GZpHg1gPnZTk1PvHRc4g/M5c50nHERkk3ojb5AuUTZFAjEKzDhBJcqvwWa7NrNT3W3Nf8t8Sj8JjA6rtXJ1z/g==
"@babel/node@~7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.8.4.tgz#59b2ed7e5a9df2224592f83292d77d616fbf1ab8"
integrity sha512-MlczXI/VYRnoaWHjicqrzq2z4DhRPaWQIC+C3ISEQs5z+mEccBsn7IAI5Q97ZDTnFYw6ts5IUTzqArilC/g7nw==
dependencies:
"@babel/register" "^7.8.3"
commander "^4.0.1"
@ -302,10 +302,10 @@
resolve "^1.13.1"
v8flags "^3.1.1"
"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.7.5", "@babel/parser@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081"
integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==
"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.7.5", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8"
integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==
"@babel/plugin-proposal-async-generator-functions@^7.8.3":
version "7.8.3"
@ -532,10 +532,10 @@
"@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-for-of@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.3.tgz#15f17bce2fc95c7d59a24b299e83e81cedc22e18"
integrity sha512-ZjXznLNTxhpf4Q5q3x1NsngzGA38t9naWH8Gt+0qYZEJAcvPI9waSStSh56u19Ofjr7QmD0wUsQ8hw8s/p1VnA==
"@babel/plugin-transform-for-of@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz#6fe8eae5d6875086ee185dd0b098a8513783b47d"
integrity sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
@ -620,10 +620,10 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-replace-supers" "^7.8.3"
"@babel/plugin-transform-parameters@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.3.tgz#7890576a13b17325d8b7d44cb37f21dc3bbdda59"
integrity sha512-/pqngtGb54JwMBZ6S/D3XYylQDFtGjWrnoCF4gXZOUpFV/ujbxnoNGNvDGu6doFWRPBveE72qTx/RRU44j5I/Q==
"@babel/plugin-transform-parameters@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz#1d5155de0b65db0ccf9971165745d3bb990d77d3"
integrity sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==
dependencies:
"@babel/helper-call-delegate" "^7.8.3"
"@babel/helper-get-function-arity" "^7.8.3"
@ -680,10 +680,10 @@
"@babel/helper-annotate-as-pure" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-typeof-symbol@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.3.tgz#5cffb216fb25c8c64ba6bf5f76ce49d3ab079f4d"
integrity sha512-3TrkKd4LPqm4jHs6nPtSDI/SV9Cm5PRJkHLUgTcqRQQTMAZ44ZaAdDZJtvWFSaRcvT0a1rTmJ5ZA5tDKjleF3g==
"@babel/plugin-transform-typeof-symbol@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412"
integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
@ -695,13 +695,13 @@
"@babel/helper-create-regexp-features-plugin" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/preset-env@~7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.3.tgz#dc0fb2938f52bbddd79b3c861a4b3427dd3a6c54"
integrity sha512-Rs4RPL2KjSLSE2mWAx5/iCH+GC1ikKdxPrhnRS6PfFVaiZeom22VFKN4X8ZthyN61kAaR05tfXTbCvatl9WIQg==
"@babel/preset-env@~7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.4.tgz#9dac6df5f423015d3d49b6e9e5fa3413e4a72c4e"
integrity sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w==
dependencies:
"@babel/compat-data" "^7.8.0"
"@babel/helper-compilation-targets" "^7.8.3"
"@babel/compat-data" "^7.8.4"
"@babel/helper-compilation-targets" "^7.8.4"
"@babel/helper-module-imports" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-proposal-async-generator-functions" "^7.8.3"
@ -730,7 +730,7 @@
"@babel/plugin-transform-dotall-regex" "^7.8.3"
"@babel/plugin-transform-duplicate-keys" "^7.8.3"
"@babel/plugin-transform-exponentiation-operator" "^7.8.3"
"@babel/plugin-transform-for-of" "^7.8.3"
"@babel/plugin-transform-for-of" "^7.8.4"
"@babel/plugin-transform-function-name" "^7.8.3"
"@babel/plugin-transform-literals" "^7.8.3"
"@babel/plugin-transform-member-expression-literals" "^7.8.3"
@ -741,7 +741,7 @@
"@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3"
"@babel/plugin-transform-new-target" "^7.8.3"
"@babel/plugin-transform-object-super" "^7.8.3"
"@babel/plugin-transform-parameters" "^7.8.3"
"@babel/plugin-transform-parameters" "^7.8.4"
"@babel/plugin-transform-property-literals" "^7.8.3"
"@babel/plugin-transform-regenerator" "^7.8.3"
"@babel/plugin-transform-reserved-words" "^7.8.3"
@ -749,13 +749,13 @@
"@babel/plugin-transform-spread" "^7.8.3"
"@babel/plugin-transform-sticky-regex" "^7.8.3"
"@babel/plugin-transform-template-literals" "^7.8.3"
"@babel/plugin-transform-typeof-symbol" "^7.8.3"
"@babel/plugin-transform-typeof-symbol" "^7.8.4"
"@babel/plugin-transform-unicode-regex" "^7.8.3"
"@babel/types" "^7.8.3"
browserslist "^4.8.2"
browserslist "^4.8.5"
core-js-compat "^3.6.2"
invariant "^2.2.2"
levenary "^1.1.0"
levenary "^1.1.1"
semver "^5.5.0"
"@babel/register@^7.8.3":
@ -793,16 +793,16 @@
"@babel/parser" "^7.8.3"
"@babel/types" "^7.8.3"
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.7.4", "@babel/traverse@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a"
integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.7.4", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c"
integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==
dependencies:
"@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.8.3"
"@babel/generator" "^7.8.4"
"@babel/helper-function-name" "^7.8.3"
"@babel/helper-split-export-declaration" "^7.8.3"
"@babel/parser" "^7.8.3"
"@babel/parser" "^7.8.4"
"@babel/types" "^7.8.3"
debug "^4.1.0"
globals "^11.1.0"
@ -1275,65 +1275,65 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
"@sentry/apm@5.11.1":
version "5.11.1"
resolved "https://registry.yarnpkg.com/@sentry/apm/-/apm-5.11.1.tgz#cc89fa4150056fbf009f92eca94fccc3980db34e"
integrity sha512-4iZH11p/7w9IMLT9hqNY1+EqLESltiIoF6/YsbpK93sXWGEs8VQ83IuvGuKWxajvHgDmj4ND0TxIliTsYqTqFw==
"@sentry/apm@5.11.2":
version "5.11.2"
resolved "https://registry.yarnpkg.com/@sentry/apm/-/apm-5.11.2.tgz#35961b9d2319ad21ae91f1b697998a8c523f1919"
integrity sha512-qn4HiSZ+6b1Gg+DlXdHVpiPPEbRu4IicGSbI8HTJLzrlsjoaBQPPkDwtuQUBVq21tU3RYXnTwrl9m45KuX6alA==
dependencies:
"@sentry/browser" "5.11.1"
"@sentry/hub" "5.11.1"
"@sentry/minimal" "5.11.1"
"@sentry/browser" "5.11.2"
"@sentry/hub" "5.11.2"
"@sentry/minimal" "5.11.2"
"@sentry/types" "5.11.0"
"@sentry/utils" "5.11.1"
tslib "^1.9.3"
"@sentry/browser@5.11.1":
version "5.11.1"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.11.1.tgz#337ffcb52711b23064c847a07629e966f54a5ebb"
integrity sha512-oqOX/otmuP92DEGRyZeBuQokXdeT9HQRxH73oqIURXXNLMP3PWJALSb4HtT4AftEt/2ROGobZLuA4TaID6My/Q==
"@sentry/browser@5.11.2":
version "5.11.2"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.11.2.tgz#f0b19bd97e9f09a20e9f93a9835339ed9ab1f5a4"
integrity sha512-ls6ARX5m+23ld8OsuoPnR+kehjR5ketYWRcDYlmJDX2VOq5K4EzprujAo8waDB0o5a92yLXQ0ZSoK/zzAV2VoA==
dependencies:
"@sentry/core" "5.11.1"
"@sentry/core" "5.11.2"
"@sentry/types" "5.11.0"
"@sentry/utils" "5.11.1"
tslib "^1.9.3"
"@sentry/core@5.11.1":
version "5.11.1"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.11.1.tgz#9e2da485e196ae32971545c1c49ee6fe719930e2"
integrity sha512-BpvPosVNT20Xso4gAV54Lu3KqDmD20vO63HYwbNdST5LUi8oYV4JhvOkoBraPEM2cbBwQvwVcFdeEYKk4tin9A==
"@sentry/core@5.11.2":
version "5.11.2"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.11.2.tgz#f2d9d37940d291dbcb9a9e4a012f76919474bdf6"
integrity sha512-IFCXGy7ebqIq/Kb8RVryCo/SjwhPcrfBmOjkicr4+DxN1UybLre2N3p9bejQMPIteOfDVHlySLYeipjTf+mxZw==
dependencies:
"@sentry/hub" "5.11.1"
"@sentry/minimal" "5.11.1"
"@sentry/hub" "5.11.2"
"@sentry/minimal" "5.11.2"
"@sentry/types" "5.11.0"
"@sentry/utils" "5.11.1"
tslib "^1.9.3"
"@sentry/hub@5.11.1":
version "5.11.1"
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.11.1.tgz#ddcb865563fae53852d405885c46b4c6de68a91b"
integrity sha512-ucKprYCbGGLLjVz4hWUqHN9KH0WKUkGf5ZYfD8LUhksuobRkYVyig0ZGbshECZxW5jcDTzip4Q9Qimq/PkkXBg==
"@sentry/hub@5.11.2":
version "5.11.2"
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.11.2.tgz#a3b7ec27cd4cea2cddd75c372fbf1b4bc04c6aae"
integrity sha512-5BiDin6ZPsaiTm29rCC41MAjP1vOaKniqfjtXHVPm7FeOBA2bpHm95ncjLkshKGJTPfPZHXTpX/1IZsHrfGVEA==
dependencies:
"@sentry/types" "5.11.0"
"@sentry/utils" "5.11.1"
tslib "^1.9.3"
"@sentry/minimal@5.11.1":
version "5.11.1"
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.11.1.tgz#0e705d01a567282d8fbbda2aed848b4974cc3cec"
integrity sha512-HK8zs7Pgdq7DsbZQTThrhQPrJsVWzz7MaluAbQA0rTIAJ3TvHKQpsVRu17xDpjZXypqWcKCRsthDrC4LxDM1Bg==
"@sentry/minimal@5.11.2":
version "5.11.2"
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.11.2.tgz#ae417699342266ecd109a97e53cd9519c0893b21"
integrity sha512-oNuJuz3EZhVtamzABmPdr6lcYo06XHLWb2LvgnoNaYcMD1ExUSvhepOSyZ2h5STCMbmVgGVfXBNPV9RUTp8GZg==
dependencies:
"@sentry/hub" "5.11.1"
"@sentry/hub" "5.11.2"
"@sentry/types" "5.11.0"
tslib "^1.9.3"
"@sentry/node@^5.11.1":
version "5.11.1"
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.11.1.tgz#2a9c18cd1209cfdf7a69b9d91303413149d2c910"
integrity sha512-FbJs0blJ36gEzE0rc2yBfA/KE+kXOLl8MUfFTcyJCBdCGF8XMETDCmgINnJ4TyBUJviwKoPw2TCk9TL2pa/A1w==
"@sentry/node@^5.11.2":
version "5.11.2"
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.11.2.tgz#575c320b624c218d2155183f6bbe82b732bfb1f2"
integrity sha512-jYq9u76BdAbOKPuYg39Xh/+797MevzjMkCIC9cw/bQxAm6nHc3FXeKqd79O33jO4Jag0JL+Bz/0JidgrKgKgXg==
dependencies:
"@sentry/apm" "5.11.1"
"@sentry/core" "5.11.1"
"@sentry/hub" "5.11.1"
"@sentry/apm" "5.11.2"
"@sentry/core" "5.11.2"
"@sentry/hub" "5.11.2"
"@sentry/types" "5.11.0"
"@sentry/utils" "5.11.1"
cookie "^0.3.1"
@ -1607,10 +1607,10 @@
dependencies:
"@types/yargs-parser" "*"
"@types/yup@0.26.28":
version "0.26.28"
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.26.28.tgz#6b8a98fb56ddb5c8a3a7f60996165221671c1ca1"
integrity sha512-DiT584YBKBENDzgk50LwiJLLOh+XgHpiy9p8PwSoOY696LpfrJRIeJ2AoBCG9KyjE8gWL4J64xDZgw15itecag==
"@types/yup@0.26.29":
version "0.26.29"
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.26.29.tgz#5a533ad6f74e442436698e20b1441c68a7a1c931"
integrity sha512-M81oZOgLap0b0I/BySnpLwHjOj1BFxUKV1ytG2Kqj3jmkh8F3H11PEnk658UniftpjTXdueloOL+KZYn+SMQ9w==
"@types/zen-observable@^0.8.0":
version "0.8.0"
@ -2461,14 +2461,14 @@ browser-resolve@^1.11.3:
dependencies:
resolve "1.1.7"
browserslist@^4.8.2, browserslist@^4.8.3:
version "4.8.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.3.tgz#65802fcd77177c878e015f0e3189f2c4f627ba44"
integrity sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg==
browserslist@^4.8.3, browserslist@^4.8.5:
version "4.8.6"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.6.tgz#96406f3f5f0755d272e27a66f4163ca821590a7e"
integrity sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg==
dependencies:
caniuse-lite "^1.0.30001017"
electron-to-chromium "^1.3.322"
node-releases "^1.1.44"
caniuse-lite "^1.0.30001023"
electron-to-chromium "^1.3.341"
node-releases "^1.1.47"
bser@^2.0.0:
version "2.1.0"
@ -2547,10 +2547,10 @@ camelize@1.0.0:
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
caniuse-lite@^1.0.30001017:
version "1.0.30001020"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001020.tgz#3f04c1737500ffda78be9beb0b5c1e2070e15926"
integrity sha512-yWIvwA68wRHKanAVS1GjN8vajAv7MBFshullKCeq/eKpK7pJBVDgFFEqvgWTkcP2+wIDeQGYFRXECjKZnLkUjA==
caniuse-lite@^1.0.30001023:
version "1.0.30001023"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001023.tgz#b82155827f3f5009077bdd2df3d8968bcbcc6fc4"
integrity sha512-C5TDMiYG11EOhVOA62W1p3UsJ2z4DsHtMBQtjzp3ZsUglcQn62WOUgW0y795c7A5uZ+GCEIvzkMatLIlAsbNTA==
capture-exit@^2.0.0:
version "2.0.0"
@ -3439,10 +3439,10 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
electron-to-chromium@^1.3.322:
version "1.3.322"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8"
integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA==
electron-to-chromium@^1.3.341:
version "1.3.344"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.344.tgz#f1397a633c35e726730c24be1084cd25c3ee8148"
integrity sha512-tvbx2Wl8WBR+ym3u492D0L6/jH+8NoQXqe46+QhbWH3voVPauGuZYeb1QAXYoOAWuiP2dbSvlBx0kQ1F3hu/Mw==
emoji-regex@^7.0.1:
version "7.0.3"
@ -3589,10 +3589,10 @@ escodegen@^1.11.1:
optionalDependencies:
source-map "~0.6.1"
eslint-config-prettier@~6.9.0:
version "6.9.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.9.0.tgz#430d24822e82f7deb1e22a435bfa3999fae4ad64"
integrity sha512-k4E14HBtcLv0uqThaI6I/n1LEqROp8XaPu6SO9Z32u5NlGRC07Enu1Bh2KEFw4FNHbekH8yzbIU9kUGxbiGmCA==
eslint-config-prettier@~6.10.0:
version "6.10.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.0.tgz#7b15e303bf9c956875c948f6b21500e48ded6a7f"
integrity sha512-AtndijGte1rPILInUdHjvKEGbIV06NuvPrqlIEaEaWtbtvJh464mDeyGMdZEQMsGvC0ZVkiex1fSNcC4HAbRGg==
dependencies:
get-stdin "^6.0.0"
@ -4476,12 +4476,12 @@ graphql-middleware@~4.0.2:
dependencies:
graphql-tools "^4.0.5"
graphql-shield@~7.0.8:
version "7.0.8"
resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.0.8.tgz#5ade058610e1b247b0762cb2424d121e9a5f5b46"
integrity sha512-KxYMhoiv5lsHcO0HZDhYjjWLbwzreDCmqmnkLRsLNY+6P0q81KSowoNVPuoAsItkjr9m5Fa6IDObOVxSTSt5Lw==
graphql-shield@~7.0.9:
version "7.0.9"
resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.0.9.tgz#8248916e9636a7e3c05719a52fd13f2d37ccaeb2"
integrity sha512-2Dfddd2hcObCSqAj64c/Aaxvs7gaoD2QU14crj7H486QjS8jIAtEPUyLVyv8SmJ1ZD7jT6wqx6wrB15Npn5Sgw==
dependencies:
"@types/yup" "0.26.28"
"@types/yup" "0.26.29"
object-hash "^2.0.0"
yup "^0.28.0"
@ -5880,10 +5880,10 @@ leven@^3.1.0:
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
levenary@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.0.tgz#fc146fe75f32dc483a0a2c64aef720f602cd6210"
integrity sha512-VHcwhO0UTpUW7rLPN2/OiWJdgA1e9BqEDALhrgCe/F+uUJnep6CoUsTzMeP8Rh0NGr9uKquXxqe7lwLZo509nQ==
levenary@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77"
integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==
dependencies:
leven "^3.1.0"
@ -6620,10 +6620,10 @@ node-pre-gyp@^0.12.0:
semver "^5.3.0"
tar "^4"
node-releases@^1.1.44:
version "1.1.45"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.45.tgz#4cf7e9175d71b1317f15ffd68ce63bce1d53e9f2"
integrity sha512-cXvGSfhITKI8qsV116u2FTzH5EWZJfgG7d4cpqwF8I8+1tWpD6AsvvGRKq2onR0DNj1jfqsjkXZsm14JMS7Cyg==
node-releases@^1.1.47:
version "1.1.47"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.47.tgz#c59ef739a1fd7ecbd9f0b7cf5b7871e8a8b591e4"
integrity sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA==
dependencies:
semver "^6.3.0"

View File

@ -17,8 +17,13 @@ Then("I click on the {string} button", text => {
.click();
});
Then("I click on the reply button", () => {
cy.get(".reply-button")
.click();
});
Then("my comment should be successfully created", () => {
cy.get(".iziToast-message").contains("Comment Submitted");
cy.get(".iziToast-message").contains("Comment submitted!");
});
Then("I should see my comment", () => {
@ -45,6 +50,12 @@ Then("the editor should be cleared", () => {
cy.get(".ProseMirror p").should("have.class", "is-empty");
});
Then("it should create a mention in the CommentForm", () => {
cy.get(".ProseMirror a")
.should('have.class', 'mention')
.should('contain', '@peter-pan')
})
When("I open the content menu of post {string}", (title)=> {
cy.contains('.post-card', title)
.find('.content-menu .base-button')

View File

@ -11,15 +11,24 @@ Then("I should have one item in the select dropdown", () => {
});
});
Then("the search has no results", () => {
Then("the search should not contain posts by the annoying user", () => {
cy.get(".searchable-input .ds-select-dropdown").should($li => {
expect($li).to.have.length(1);
});
cy.get(".ds-select-dropdown").should("contain", 'Nothing found');
})
cy.get(".ds-select-dropdown")
.should("not.have.class", '.search-post')
.should("not.contain", 'Spam')
});
Then("the search should contain the annoying user", () => {
cy.get(".searchable-input .ds-select-dropdown").should($li => {
expect($li).to.have.length(1);
})
cy.get(".ds-select-dropdown .user-teaser .slug").should("contain", '@spammy-spammer');
cy.get(".searchable-input .ds-select-search")
.focus()
.type("{esc}");
});
})
Then("I should see the following posts in the select dropdown:", table => {
table.hashes().forEach(({ title }) => {

View File

@ -30,6 +30,7 @@ const narratorParams = {
const annoyingParams = {
email: "spammy-spammer@example.org",
slug: 'spammy-spammer',
password: "1234",
};
@ -37,8 +38,12 @@ Given("I am logged in", () => {
cy.login(loginCredentials);
});
Given("I am logged in as the muted user", () => {
cy.login({ email: annoyingParams.email, password: '1234' });
Given("the {string} user searches for {string}", (_, postTitle) => {
cy.logout()
.login({ email: annoyingParams.email, password: '1234' })
.get(".searchable-input .ds-select-search")
.focus()
.type(postTitle);
});
Given("we have a selection of categories", () => {
@ -106,6 +111,12 @@ When("I visit the {string} page", page => {
cy.openPage(page);
});
When("a blocked user visits the post page of one of my authored posts", () => {
cy.logout()
.login({ email: annoyingParams.email, password: annoyingParams.password })
.openPage('/post/previously-created-post')
})
Given("I am on the {string} page", page => {
cy.openPage(page);
});
@ -175,6 +186,16 @@ When("I press {string}", label => {
cy.contains(label).click();
});
Given("we have the following comments in our database:", table => {
table.hashes().forEach((attributesOrOptions, i) => {
cy.factory().build("comment", {
...attributesOrOptions,
}, {
...attributesOrOptions,
});
})
});
Given("we have the following posts in our database:", table => {
cy.factory().build('category', {
id: `cat-456`,
@ -212,11 +233,15 @@ When(
);
Given("I previously created a post", () => {
lastPost.authorId = narratorParams.id
lastPost.title = "previously created post";
lastPost.content = "with some content";
lastPost = {
lastPost,
title: "previously created post",
content: "with some content",
};
cy.factory()
.build("post", lastPost);
.build("post", lastPost, {
authorId: narratorParams.id
});
});
When("I choose {string} as the title of the post", title => {
@ -461,7 +486,7 @@ Given("I follow the user {string}", name => {
});
});
Given('"Spammy Spammer" wrote a post {string}', title => {
Given('{string} wrote a post {string}', (_, title) => {
cy.factory()
.build("post", {
title,
@ -475,7 +500,7 @@ Then("the list of posts of this user is empty", () => {
cy.get(".main-container").find(".ds-space.hc-empty");
});
Then("nobody is following the user profile anymore", () => {
Then("I get removed from his follower collection", () => {
cy.get(".ds-card-content").not(".post-link");
cy.get(".main-container").contains(
".ds-card-content",
@ -506,6 +531,20 @@ When("I mute the user {string}", name => {
});
});
When("I block the user {string}", name => {
cy.neode()
.first("User", {
name
})
.then(blockedUser => {
cy.neode()
.first("User", {
id: narratorParams.id
})
.relateTo(blockedUser, "blocked");
});
});
When("I log in with:", table => {
const [firstRow] = table.hashes();
const {
@ -524,3 +563,11 @@ Then("I see only one post with the title {string}", title => {
.should("have.length", 1);
cy.get(".main-container").contains(".post-link", title);
});
Then("they should not see the comment form", () => {
cy.get(".ds-card-footer").children().should('not.have.class', 'comment-form')
})
Then("they should see a text explaining why commenting is not possible", () => {
cy.get('.ds-placeholder').should('contain', "Commenting is not possible at this time on this post.")
})

View File

@ -4,10 +4,13 @@ Feature: Post Comment
To be able to express my thoughts and emotions about these, discuss, and add give further information.
Background:
Given we have the following posts in our database:
| id | title | slug |
| bWBjpkTKZp | 101 Essays that will change the way you think | 101-essays |
And I have a user account
Given I have a user account
And we have the following posts in our database:
| id | title | slug | authorId |
| bWBjpkTKZp | 101 Essays that will change the way you think | 101-essays | id-of-peter-pan |
And we have the following comments in our database:
| postId | content | authorId |
| bWBjpkTKZp | @peter-pan reply to me | id-of-peter-pan |
And I am logged in
Scenario: Comment creation
@ -36,3 +39,8 @@ Feature: Post Comment
Then my comment should be successfully created
And I should see an abreviated version of my comment
And the editor should be cleared
Scenario: Direct reply to Comment
Given I visit "post/bWBjpkTKZp/101-essays"
And I click on the reply button
Then it should create a mention in the CommentForm

View File

@ -0,0 +1,46 @@
Feature: Block a User
As a user
I'd like to have a button to block another user
To prevent him from seeing and interacting with my contributions
Background:
Given I have a user account
And there is an annoying user called "Harassing User"
And I am logged in
Scenario: Block a user
Given I am on the profile page of the annoying user
When I click on "Block user" from the content menu in the user info box
And I navigate to my "Blocked users" settings page
Then I can see the following table:
| Avatar | Name |
| | Harassing User |
Scenario: Blocked user cannot interact with my contributions
Given I block the user "Harassing User"
And I previously created a post
And a blocked user visits the post page of one of my authored posts
Then they should see a text explaining why commenting is not possible
And they should not see the comment form
Scenario: Block a previously followed user
Given I follow the user "Harassing User"
When I visit the profile page of the annoying user
And I click on "Block user" from the content menu in the user info box
And I get removed from his follower collection
Scenario: Posts of blocked users are not filtered from search results
Given "Harassing User" wrote a post "You can still see my posts"
And I block the user "Harassing User"
When I search for "see"
Then I should see the following posts in the select dropdown:
| title |
| You can still see my posts |
Scenario: Blocked users can still see my posts
Given I previously created a post
And I block the user "Harassing User"
And the "blocked" user searches for "previously created"
Then I should see the following posts in the select dropdown:
| title |
| previously created post |

View File

@ -1,8 +1,7 @@
Feature: Mute a User
As a user
I'd like to have a button to mute another user
To prevent him from seeing and interacting with my contributions and also to avoid seeing his/her posts
To prevent him from seeing and interacting with my contributions
Background:
Given I have a user account
And there is an annoying user called "Spammy Spammer"
@ -22,9 +21,9 @@ Feature: Mute a User
When I visit the profile page of the annoying user
And I click on "Mute user" from the content menu in the user info box
Then the list of posts of this user is empty
And nobody is following the user profile anymore
And I get removed from his follower collection
Scenario: Posts of muted users are filtered from search results
Scenario: Posts of muted users are filtered from search results, users are not
Given we have the following posts in our database:
| id | title | content |
| im-not-muted | Post that should be seen | cause I'm not muted |
@ -36,18 +35,17 @@ Feature: Mute a User
When I mute the user "Spammy Spammer"
And I refresh the page
And I search for "Spam"
Then the search has no results
Then the search should not contain posts by the annoying user
But the search should contain the annoying user
But I search for "not muted"
Then I should see the following posts in the select dropdown:
| title |
| Post that should be seen |
Scenario: Muted users can still see my posts
Given I previously created a post
And I mute the user "Spammy Spammer"
Given I log out
And I am logged in as the muted user
When I search for "previously created"
And the "muted" user searches for "previously created"
Then I should see the following posts in the select dropdown:
| title |
| previously created post |

View File

@ -15,7 +15,6 @@
/* globals Cypress cy */
import "cypress-file-upload";
import helpers from "./helpers";
import users from "../fixtures/users.json";
import { GraphQLClient, request } from 'graphql-request'
import { gql } from '../../backend/src/helpers/jest'
import config from '../../backend/src/config'

View File

@ -1,4 +1,4 @@
import Factory, { cleanDatabase } from '../../backend/src/factories'
import Factory, { cleanDatabase } from '../../backend/src/db/factories'
import { getDriver, getNeode } from '../../backend/src/db/neo4j'
const neo4jConfigs = {
@ -6,10 +6,7 @@ const neo4jConfigs = {
username: Cypress.env('NEO4J_USERNAME'),
password: Cypress.env('NEO4J_PASSWORD')
}
const neo4jDriver = getDriver(neo4jConfigs)
const neodeInstance = getNeode(neo4jConfigs)
const factoryOptions = { neo4jDriver, neodeInstance }
const factory = Factory(factoryOptions)
beforeEach(async () => {
await cleanDatabase()
@ -18,6 +15,7 @@ beforeEach(async () => {
Cypress.Commands.add('neode', () => {
return neodeInstance
})
Cypress.Commands.add(
'first',
{ prevSubject: true },
@ -33,15 +31,13 @@ Cypress.Commands.add(
}
)
Cypress.Commands.add('factory', () => {
return Factory(factoryOptions)
})
Cypress.Commands.add('factory', () => Factory)
Cypress.Commands.add(
'build',
{ prevSubject: true },
async (factory, name, atrributes, options) => {
await Factory.build(name, atrributes, options)
await factory.build(name, atrributes, options)
return factory
}
)

View File

@ -1,6 +1,6 @@
// features/support/steps.js
import { Given, When, Then, After, AfterAll } from 'cucumber'
import Factory, { cleanDatabase } from '../../backend/src/factories'
import Factory, { cleanDatabase } from '../../backend/src/db/factories'
import dotenv from 'dotenv'
import expect from 'expect'

View File

@ -25,8 +25,8 @@
"release": "standard-version"
},
"devDependencies": {
"@babel/core": "^7.8.3",
"@babel/preset-env": "^7.8.3",
"@babel/core": "^7.8.4",
"@babel/preset-env": "^7.8.4",
"@babel/register": "^7.8.3",
"auto-changelog": "^1.16.2",
"bcryptjs": "^2.4.3",

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
sed -i "s/<COMMIT>/${TRAVIS_COMMIT}/g" $TRAVIS_BUILD_DIR/scripts/patches/patch-deployment.yaml
sed -i "s/<COMMIT>/${TRAVIS_COMMIT}/g" $TRAVIS_BUILD_DIR/scripts/patches/patch-configmap.yaml
kubectl --namespace=human-connection patch configmap configmap -p "$(cat $TRAVIS_BUILD_DIR/scripts/patches/patch-configmap.yaml)"
kubectl --namespace=human-connection patch deployment backend -p "$(cat $TRAVIS_BUILD_DIR/scripts/patches/patch-deployment.yaml)"
kubectl --namespace=human-connection patch deployment web -p "$(cat $TRAVIS_BUILD_DIR/scripts/patches/patch-deployment.yaml)"
kubectl --namespace=human-connection patch configmap develop-configmap -p "$(cat $TRAVIS_BUILD_DIR/scripts/patches/patch-configmap.yaml)"
kubectl --namespace=human-connection patch deployment develop-backend -p "$(cat $TRAVIS_BUILD_DIR/scripts/patches/patch-deployment.yaml)"
kubectl --namespace=human-connection patch deployment develop-webapp -p "$(cat $TRAVIS_BUILD_DIR/scripts/patches/patch-deployment.yaml)"

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>level-down</title>
<path d="M5 5h17v19.063l4.281-4.281 1.438 1.438-6 6-0.719 0.688-0.719-0.688-6-6 1.438-1.438 4.281 4.281v-17.063h-15v-2z"></path>
</svg>

After

Width:  |  Height:  |  Size: 293 B

View File

@ -1,17 +1,15 @@
import { config, shallowMount } from '@vue/test-utils'
import { config, mount } from '@vue/test-utils'
import Comment from './Comment.vue'
import Vuex from 'vuex'
const localVue = global.localVue
localVue.directive('scrollTo', jest.fn())
config.stubs['client-only'] = '<span><slot /></span>'
config.stubs['nuxt-link'] = '<span><slot /></span>'
describe('Comment.vue', () => {
let propsData
let mocks
let getters
let wrapper
let Wrapper
let propsData, mocks, stubs, getters, wrapper, Wrapper
beforeEach(() => {
propsData = {}
@ -39,6 +37,9 @@ describe('Comment.vue', () => {
}),
},
}
stubs = {
ContentViewer: true,
}
getters = {
'auth/user': () => {
return {}
@ -47,18 +48,19 @@ describe('Comment.vue', () => {
}
})
describe('shallowMount', () => {
describe('mount', () => {
beforeEach(jest.useFakeTimers)
Wrapper = () => {
const store = new Vuex.Store({
getters,
})
return shallowMount(Comment, {
return mount(Comment, {
store,
propsData,
mocks,
localVue,
stubs,
})
}
@ -68,6 +70,7 @@ describe('Comment.vue', () => {
id: '2',
contentExcerpt: 'Hello I am a comment content',
content: 'Hello I am comment content',
author: { id: 'commentAuthorId', slug: 'ogerly' },
}
})
@ -199,6 +202,24 @@ describe('Comment.vue', () => {
})
})
})
describe('click reply button', () => {
beforeEach(async () => {
wrapper = Wrapper()
await wrapper.find('.reply-button').trigger('click')
})
it('emits "reply"', () => {
expect(wrapper.emitted('reply')).toEqual([
[
{
id: 'commentAuthorId',
slug: 'ogerly',
},
],
])
})
})
})
})
})

View File

@ -33,7 +33,7 @@
</client-only>
</ds-space>
<div v-if="openEditCommentMenu">
<hc-comment-form
<comment-form
:update="true"
:post="post"
:comment="comment"
@ -54,6 +54,15 @@
</button>
</div>
<ds-space margin-bottom="small" />
<base-button
:title="this.$t('post.comment.reply')"
icon="level-down"
class="reply-button"
circle
size="small"
v-scroll-to="'.editor'"
@click.prevent="reply"
></base-button>
</ds-card>
</div>
</template>
@ -64,9 +73,10 @@ import { COMMENT_MAX_UNTRUNCATED_LENGTH, COMMENT_TRUNCATE_TO_LENGTH } from '~/co
import UserTeaser from '~/components/UserTeaser/UserTeaser'
import ContentMenu from '~/components/ContentMenu/ContentMenu'
import ContentViewer from '~/components/Editor/ContentViewer'
import HcCommentForm from '~/components/CommentForm/CommentForm'
import CommentForm from '~/components/CommentForm/CommentForm'
import CommentMutations from '~/graphql/CommentMutations'
import scrollToAnchor from '~/mixins/scrollToAnchor.js'
import BaseButton from '~/components/_new/generic/BaseButton/BaseButton'
export default {
mixins: [scrollToAnchor],
@ -85,7 +95,8 @@ export default {
UserTeaser,
ContentMenu,
ContentViewer,
HcCommentForm,
CommentForm,
BaseButton,
},
props: {
routeHash: { type: String, default: () => '' },
@ -105,7 +116,6 @@ export default {
if (this.isLongComment && this.isCollapsed) {
return this.$filters.truncate(this.comment.content, COMMENT_TRUNCATE_TO_LENGTH)
}
return this.comment.content
},
displaysComment() {
@ -141,6 +151,10 @@ export default {
},
},
methods: {
reply() {
const message = { slug: this.comment.author.slug, id: this.comment.author.id }
this.$emit('reply', message)
},
checkAnchor(anchor) {
return `#${this.anchor}` === anchor
},
@ -193,6 +207,14 @@ export default {
float: right;
}
.reply-button {
float: right;
top: 0px;
}
.reply-button:after {
clear: both;
}
@keyframes highlight {
0% {
border: 1px solid $color-primary;

View File

@ -51,6 +51,9 @@ export default {
}
},
methods: {
reply(message) {
this.$refs.editor.insertReply(message)
},
updateEditorContent(value) {
const sanitizedContent = this.$filters.removeHtml(value, false)
if (!this.update) {
@ -133,8 +136,8 @@ export default {
query() {
return minimisedUserQuery()
},
result(result) {
this.users = result.data.User
update({ User }) {
this.users = User
},
},
},

View File

@ -1,10 +1,13 @@
import { config, mount } from '@vue/test-utils'
import CommentList from './CommentList'
import Comment from '~/components/Comment/Comment'
import Vuex from 'vuex'
import Vue from 'vue'
const localVue = global.localVue
localVue.filter('truncate', string => string)
localVue.directive('scrollTo', jest.fn())
config.stubs['v-popover'] = '<span><slot /></span>'
config.stubs['nuxt-link'] = '<span><slot /></span>'
@ -97,5 +100,27 @@ describe('CommentList.vue', () => {
})
})
})
describe('Comment', () => {
beforeEach(() => {
wrapper = Wrapper()
})
it('Comment emitted reply()', () => {
wrapper.find(Comment).vm.$emit('reply', {
id: 'commentAuthorId',
slug: 'ogerly',
})
Vue.nextTick()
expect(wrapper.emitted('reply')).toEqual([
[
{
id: 'commentAuthorId',
slug: 'ogerly',
},
],
])
})
})
})
})

View File

@ -12,9 +12,11 @@
:comment="comment"
:post="post"
:routeHash="routeHash"
class="comment-tag"
@deleteComment="updateCommentList"
@updateComment="updateCommentList"
@toggleNewCommentForm="toggleNewCommentForm"
@reply="reply"
/>
</div>
</div>
@ -35,6 +37,9 @@ export default {
post: { type: Object, default: () => {} },
},
methods: {
reply(message) {
this.$emit('reply', message)
},
checkAnchor(anchor) {
return anchor === '#comments'
},

View File

@ -161,7 +161,7 @@ export default {
callback: () => {
this.$emit('unmute', this.resource)
},
icon: 'user-plus',
icon: 'eye',
})
} else {
routes.push({
@ -169,6 +169,23 @@ export default {
callback: () => {
this.$emit('mute', this.resource)
},
icon: 'eye-slash',
})
}
if (this.resource.blocked) {
routes.push({
label: this.$t(`settings.blocked-users.unblock`),
callback: () => {
this.$emit('unblock', this.resource)
},
icon: 'user-plus',
})
} else {
routes.push({
label: this.$t(`settings.blocked-users.block`),
callback: () => {
this.$emit('block', this.resource)
},
icon: 'user-times',
})
}

View File

@ -141,7 +141,6 @@ export default {
methods: {
openSuggestionList({ items, query, range, command, virtualNode }, suggestionType) {
this.suggestionType = suggestionType
this.query = this.sanitizeQuery(query)
this.filteredItems = items
this.suggestionRange = range
@ -237,6 +236,9 @@ export default {
const content = e.getHTML()
this.$emit('input', content)
},
insertReply(message) {
this.editor.commands.mention({ id: message.id, label: message.slug })
},
toggleLinkInput(attrs, element) {
if (!this.isLinkInputActive && attrs && element) {
this.$refs.linkInput.linkUrl = attrs.href

View File

@ -105,7 +105,7 @@ export default {
postId: this.post.id,
}
},
result({ data: { PostsEmotionsByCurrentUser } }) {
update({ PostsEmotionsByCurrentUser }) {
this.selectedEmotions = PostsEmotionsByCurrentUser
},
},

View File

@ -71,7 +71,7 @@ export default {
},
computed: {
emptyText() {
return this.isActive && !this.pending ? this.$t('search.failed') : this.$t('search.hint')
return this.isActive && !this.loading ? this.$t('search.failed') : this.$t('search.hint')
},
isActive() {
return !isEmpty(this.previousSearchTerm)
@ -104,7 +104,7 @@ export default {
*/
onEnter(event) {
clearTimeout(this.searchProcess)
if (!this.pending) {
if (!this.loading) {
this.previousSearchTerm = this.unprocessedSearchInput
this.$emit('query', this.unprocessedSearchInput)
}

View File

@ -29,6 +29,7 @@ export default i18n => {
...user
...userCounts
...locationAndBadges
blocked
}
comments(orderBy: createdAt_asc) {
...comment

View File

@ -24,6 +24,7 @@ export default i18n => {
createdAt
followedByCurrentUser
isMuted
blocked
following(first: 7) {
...user
...userCounts

View File

@ -0,0 +1,43 @@
import gql from 'graphql-tag'
export const blockedUsers = () => {
return gql`
{
blockedUsers {
id
name
slug
avatar
about
disabled
deleted
}
}
`
}
export const blockUser = () => {
return gql`
mutation($id: ID!) {
blockUser(id: $id) {
id
name
blocked
followedByCurrentUser
}
}
`
}
export const unblockUser = () => {
return gql`
mutation($id: ID!) {
unblockUser(id: $id) {
id
name
blocked
followedByCurrentUser
}
}
`
}

View File

@ -70,6 +70,11 @@
"passwordStrength4": "Sehr sicheres Passwort"
}
},
"privacy": {
"name": "Privatsphäre",
"make-shouts-public": "Teile von mir empfohlene Artikel öffentlich auf meinem Profil",
"success-update": "Privatsphäre-Einstellungen gespeichert"
},
"invites": {
"name": "Einladungen"
},
@ -143,27 +148,44 @@
"successDelete": "Social-Media gelöscht. Profil aktualisiert!"
},
"muted-users": {
"name": "Stummgeschaltete Benutzer",
"explanation": {
"intro": "Wenn ein anderer Benutzer von dir stummgeschaltet wurde, dann passiert folgendes:",
"your-perspective": "In deiner Beitragsübersicht tauchen keine Beiträge der stummgeschalteten Person mehr auf.",
"search": "Die Beiträge von stummgeschalteten Personen verschwinden aus deinen Suchergebnissen."
},
"columns": {
"name": "Name",
"slug": "Alias",
"unmute": "Entsperren"
},
"empty": "Bislang hast du niemanden stummgeschaltet.",
"how-to": "Du kannst andere Benutzer auf deren Profilseite über das Inhaltsmenü stummschalten.",
"mute": "Stumm schalten",
"unmute": "Stummschaltung aufheben",
"unmuted": "{name} ist nicht mehr stummgeschaltet"
"name": "Stummgeschaltete Benutzer",
"explanation": {
"intro": "Wenn ein anderer Benutzer von dir stummgeschaltet wurde, dann passiert folgendes:",
"your-perspective": "In deiner Beitragsübersicht tauchen keine Beiträge der stummgeschalteten Person mehr auf.",
"search": "Die Beiträge von stummgeschalteten Personen verschwinden aus deinen Suchergebnissen."
},
"columns": {
"name": "Name",
"slug": "Alias",
"unmute": "Entsperren"
},
"empty": "Bislang hast du niemanden stummgeschaltet.",
"how-to": "Du kannst andere Benutzer auf deren Profilseite über das Inhaltsmenü stummschalten.",
"mute": "Stumm schalten",
"unmute": "Stummschaltung aufheben",
"unmuted": "{name} ist nicht mehr stummgeschaltet"
},
"privacy": {
"name": "Privatsphäre",
"make-shouts-public": "Teile von mir empfohlene Artikel öffentlich auf meinem Profil",
"success-update": "Privatsphäre-Einstellungen gespeichert"
"blocked-users": {
"name": "Blocked users",
"explanation": {
"intro": "Wenn ein anderer Benutzer von dir blockiert wurde, dann passiert folgendes:",
"your-perspective": "Du kannst keine Beiträge der blockierten Person mehr kommentieren.",
"their-perspective": "Die blockierte Person kann deine Beiträge nicht mehr kommentieren",
"notifications": "Von dir blockierte Personen erhalten keine Benachrichtigungen mehr, wenn sie in deinen Beiträgen erwähnt werden.",
"closing": "Das sollte fürs Erste genügen, damit blockierte Benutzer dich nicht mehr länger belästigen können.",
"commenting-disabled": "Du kannst den Beitrag derzeit nicht kommentieren.",
"commenting-explanation": "Dafür kann es mehrere Gründe geben, bitte schau in unsere "
},
"columns": {
"name": "Name",
"slug": "Alias",
"unblock": "Entsperren"
},
"empty": "Bislang hast du niemanden blockiert.",
"how-to": "Du kannst andere Benutzer auf deren Profilseite über das Inhaltsmenü blockieren.",
"block": "Nutzer blockieren",
"unblock": "Nutzer entsperren",
"unblocked": "{name} ist wieder entsperrt"
}
},
"admin": {
@ -257,8 +279,9 @@
},
"comment": {
"submit": "Kommentiere",
"submitted": "Kommentar gesendet",
"updated": "Änderungen gespeichert"
"submitted": "Kommentar gesendet!",
"updated": "Änderungen gespeichert",
"reply": "Antworten"
},
"edited": "bearbeitet"
},

View File

@ -329,6 +329,28 @@
"mute": "Mute user",
"unmute": "Unmute user",
"unmuted": "{name} is unmuted again"
},
"blocked-users": {
"name": "Blocked users",
"explanation": {
"intro": "If another user has been blocked by you, this is what happens:",
"your-perspective": "You will no longer be able to interact with their contributions.",
"their-perspective": "Vice versa: The blocked person will also no longer be able to interact with your contributions.",
"notifications": "Blocked users will no longer receive notifications if they mention each other.",
"closing": "This should be sufficient for now so that blocked users can no longer bother you.",
"commenting-disabled": "Commenting is not possible at this time on this post.",
"commenting-explanation": "This can happen for several reasons, please see our "
},
"columns": {
"name": "Name",
"slug": "Slug",
"unblock": "Unblock"
},
"empty": "So far, you have not blocked anybody.",
"how-to": "You can block other users on their profile page via the content menu.",
"block": "Block user",
"unblock": "Unblock user",
"unblocked": "{name} is unblocked again"
}
},
"admin": {
@ -422,8 +444,9 @@
},
"comment": {
"submit": "Comment",
"submitted": "Comment Submitted",
"updated": "Changes Saved"
"submitted": "Comment submitted!",
"updated": "Changes saved!",
"reply": "Reply"
},
"edited": "edited"
},

View File

@ -59,15 +59,15 @@
"dependencies": {
"@human-connection/styleguide": "0.5.22",
"@nuxtjs/apollo": "^4.0.0-rc19",
"@nuxtjs/axios": "~5.9.3",
"@nuxtjs/axios": "~5.9.4",
"@nuxtjs/dotenv": "~1.4.1",
"@nuxtjs/pwa": "^3.0.0-beta.19",
"@nuxtjs/sentry": "^3.0.1",
"@nuxtjs/sentry": "^3.1.0",
"@nuxtjs/style-resources": "~1.0.0",
"accounting": "~0.4.1",
"apollo-cache-inmemory": "~1.6.5",
"apollo-client": "~2.6.8",
"cookie-universal-nuxt": "~2.1.0",
"cookie-universal-nuxt": "~2.1.1",
"cropperjs": "^1.5.5",
"cross-env": "~7.0.0",
"date-fns": "2.9.0",
@ -96,9 +96,9 @@
"zxcvbn": "^4.4.2"
},
"devDependencies": {
"@babel/core": "~7.8.3",
"@babel/core": "~7.8.4",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "~7.8.3",
"@babel/preset-env": "~7.8.4",
"@storybook/addon-a11y": "^5.3.9",
"@storybook/addon-actions": "^5.3.9",
"@storybook/addon-notes": "^5.3.9",
@ -117,7 +117,7 @@
"core-js": "~2.6.10",
"css-loader": "~3.4.2",
"eslint": "~6.8.0",
"eslint-config-prettier": "~6.9.0",
"eslint-config-prettier": "~6.10.0",
"eslint-config-standard": "~14.1.0",
"eslint-loader": "~3.0.3",
"eslint-plugin-import": "~2.20.0",

View File

@ -1,29 +1,33 @@
import { config, shallowMount } from '@vue/test-utils'
import PostSlug from './index.vue'
import { config, mount } from '@vue/test-utils'
import Vuex from 'vuex'
const localVue = global.localVue
import PostSlug from './index.vue'
import CommentList from '~/components/CommentList/CommentList'
config.stubs['client-only'] = '<span><slot /></span>'
config.stubs['nuxt-link'] = '<span><slot /></span>'
config.stubs['router-link'] = '<span><slot /></span>'
const localVue = global.localVue
localVue.directive('scrollTo', jest.fn())
describe('PostSlug', () => {
let wrapper
let Wrapper
let store
let mocks
let store, propsData, mocks, stubs, wrapper, Wrapper
beforeEach(() => {
store = new Vuex.Store({
getters: {
'auth/user': () => {
return {}
return { id: '1stUser' }
},
'auth/isModerator': () => false,
},
})
propsData = {}
mocks = {
$t: jest.fn(),
$filters: {
truncate: a => a,
removeHtml: a => a,
},
$route: {
hash: '',
@ -40,38 +44,53 @@ describe('PostSlug', () => {
},
$apollo: {
mutate: jest.fn().mockResolvedValue(),
query: jest.fn().mockResolvedValue({ data: { PostEmotionsCountByEmotion: {} } }),
},
$scrollTo: jest.fn(),
}
stubs = {
HcEditor: { render: () => {}, methods: { insertReply: jest.fn(() => null) } },
ContentViewer: true,
}
jest.useFakeTimers()
wrapper = Wrapper()
wrapper.setData({
post: {
id: '1',
author: {
id: '1stUser',
},
comments: [
{
id: 'comment134',
contentExcerpt: 'this is a comment',
content: 'this is a comment',
author: {
id: '1stUser',
slug: '1st-user',
},
},
],
},
ready: true,
})
})
describe('shallowMount', () => {
describe('mount', () => {
Wrapper = () => {
return shallowMount(PostSlug, {
return mount(PostSlug, {
store,
mocks,
localVue,
propsData,
stubs,
})
}
beforeEach(jest.useFakeTimers)
describe('test Post callbacks', () => {
beforeEach(() => {
wrapper = Wrapper()
wrapper.setData({
post: {
id: 'p23',
name: 'It is a post',
author: {
id: 'u1',
},
},
})
})
describe('deletion of Post from Page by invoking "deletePostCallback()"', () => {
beforeEach(() => {
wrapper.vm.deletePostCallback()
beforeEach(async () => {
await wrapper.vm.deletePostCallback()
})
describe('after timeout', () => {
@ -91,5 +110,18 @@ describe('PostSlug', () => {
})
})
})
describe('reply method called when emitted reply received', () => {
it('CommentList', async () => {
wrapper.find(CommentList).vm.$emit('reply', {
id: 'commentAuthorId',
slug: 'ogerly',
})
expect(stubs.HcEditor.methods.insertReply).toHaveBeenCalledWith({
id: 'commentAuthorId',
slug: 'ogerly',
})
})
})
})
})

View File

@ -84,13 +84,25 @@
</ds-space>
<!-- Comments -->
<ds-section slot="footer">
<hc-comment-list
<comment-list
:post="post"
:routeHash="$route.hash"
@toggleNewCommentForm="toggleNewCommentForm"
@reply="reply"
/>
<ds-space margin-bottom="large" />
<hc-comment-form v-if="showNewCommentForm" :post="post" @createComment="createComment" />
<comment-form
v-if="showNewCommentForm && !post.author.blocked"
ref="commentForm"
:post="post"
@createComment="createComment"
/>
<ds-placeholder v-else>
{{ $t('settings.blocked-users.explanation.commenting-disabled') }}
<br />
{{ $t('settings.blocked-users.explanation.commenting-explanation') }}
<a href="https://support.human-connection.org/kb/" target="_blank">FAQ</a>
</ds-placeholder>
</ds-section>
</ds-card>
</transition>
@ -103,8 +115,8 @@ import HcHashtag from '~/components/Hashtag/Hashtag'
import ContentMenu from '~/components/ContentMenu/ContentMenu'
import UserTeaser from '~/components/UserTeaser/UserTeaser'
import HcShoutButton from '~/components/ShoutButton.vue'
import HcCommentForm from '~/components/CommentForm/CommentForm'
import HcCommentList from '~/components/CommentList/CommentList'
import CommentForm from '~/components/CommentForm/CommentForm'
import CommentList from '~/components/CommentList/CommentList'
import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers'
import PostQuery from '~/graphql/PostQuery'
import HcEmotions from '~/components/Emotions/Emotions'
@ -122,8 +134,8 @@ export default {
UserTeaser,
HcShoutButton,
ContentMenu,
HcCommentForm,
HcCommentList,
CommentForm,
CommentList,
HcEmotions,
ContentViewer,
},
@ -139,15 +151,10 @@ export default {
title: 'loading',
showNewCommentForm: true,
blurred: false,
blocked: null,
postAuthor: null,
}
},
watch: {
Post(post) {
this.post = post[0] || {}
this.title = this.post.title
this.blurred = this.post.imageBlurred
},
},
mounted() {
setTimeout(() => {
// NOTE: quick fix for jumping flexbox implementation
@ -165,6 +172,9 @@ export default {
},
},
methods: {
reply(message) {
this.$refs.commentForm && this.$refs.commentForm.reply(message)
},
isAuthor(id) {
return this.$store.getters['auth/user'].id === id
},
@ -216,6 +226,12 @@ export default {
id: this.$route.params.id,
}
},
update({ Post }) {
this.post = Post[0] || {}
this.title = this.post.title
this.blurred = this.post.imageBlurred
this.postAuthor = this.post.author
},
fetchPolicy: 'cache-and-network',
},
},

View File

@ -24,6 +24,8 @@
class="user-content-menu"
@mute="muteUser"
@unmute="unmuteUser"
@block="blockUser"
@unblock="unblockUser"
/>
</client-only>
<ds-space margin="small">
@ -64,20 +66,21 @@
</client-only>
</ds-flex-item>
</ds-flex>
<ds-space margin="small">
<template v-if="!myProfile">
<hc-follow-button
v-if="!user.isMuted"
:follow-id="user.id"
:is-followed="user.followedByCurrentUser"
@optimistic="optimisticFollow"
@update="updateFollow"
/>
<base-button v-else @click="unmuteUser(user)" class="unblock-user-button">
{{ $t('settings.muted-users.unmute') }}
</base-button>
</template>
</ds-space>
<div v-if="!myProfile" class="action-buttons">
<base-button v-if="user.blocked" @click="unblockUser(user)">
{{ $t('settings.blocked-users.unblock') }}
</base-button>
<base-button v-if="user.isMuted" @click="unmuteUser(user)">
{{ $t('settings.muted-users.unmute') }}
</base-button>
<hc-follow-button
v-if="!(user.blocked || user.isMuted)"
:follow-id="user.id"
:is-followed="user.followedByCurrentUser"
@optimistic="optimisticFollow"
@update="updateFollow"
/>
</div>
<template v-if="user.about">
<hr />
<ds-space margin-top="small" margin-bottom="small">
@ -285,6 +288,7 @@ import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
import { profilePagePosts } from '~/graphql/PostQuery'
import UserQuery from '~/graphql/User'
import { muteUser, unmuteUser } from '~/graphql/settings/MutedUsers'
import { blockUser, unblockUser } from '~/graphql/settings/BlockedUsers'
import PostMutations from '~/graphql/PostMutations'
import UpdateQuery from '~/components/utils/UpdateQuery'
@ -417,6 +421,24 @@ export default {
this.$apollo.queries.profilePagePosts.refetch()
}
},
async blockUser(user) {
try {
await this.$apollo.mutate({ mutation: blockUser(), variables: { id: user.id } })
} catch (error) {
this.$toast.error(error.message)
} finally {
this.$apollo.queries.User.refetch()
}
},
async unblockUser(user) {
try {
this.$apollo.mutate({ mutation: unblockUser(), variables: { id: user.id } })
} catch (error) {
this.$toast.error(error.message)
} finally {
this.$apollo.queries.User.refetch()
}
},
pinPost(post) {
this.$apollo
.mutate({
@ -559,8 +581,13 @@ export default {
.profile-post-add-button {
box-shadow: $box-shadow-x-large;
}
.unblock-user-button {
display: block;
width: 100%;
.action-buttons {
margin: $space-small 0;
> .base-button {
display: block;
width: 100%;
margin-bottom: $space-x-small;
}
}
</style>

View File

@ -43,6 +43,10 @@ export default {
name: this.$t('settings.muted-users.name'),
path: `/settings/muted-users`,
},
{
name: this.$t('settings.blocked-users.name'),
path: `/settings/blocked-users`,
},
{
name: this.$t('settings.embeds.name'),
path: `/settings/embeds`,

View File

@ -0,0 +1,69 @@
import { config, mount, createLocalVue } from '@vue/test-utils'
import BlockedUsers from './blocked-users.vue'
import Styleguide from '@human-connection/styleguide'
import Filters from '~/plugins/vue-filters'
import { unblockUser } from '~/graphql/settings/BlockedUsers'
const localVue = createLocalVue()
localVue.use(Styleguide)
localVue.use(Filters)
config.stubs['nuxt-link'] = '<span><slot /></span>'
describe('blocked-users.vue', () => {
let wrapper
let mocks
beforeEach(() => {
mocks = {
$t: jest.fn(),
$apollo: {
mutate: jest.fn(),
queries: {
blockedUsers: {
refetch: jest.fn(),
},
},
},
$toast: {
error: jest.fn(),
success: jest.fn(),
},
}
})
describe('mount', () => {
const Wrapper = () => {
return mount(BlockedUsers, { mocks, localVue })
}
beforeEach(() => {
wrapper = Wrapper()
})
it('renders', () => {
expect(wrapper.is('div')).toBe(true)
})
describe('given a list of blocked users', () => {
beforeEach(() => {
const blockedUsers = [{ id: 'u1', name: 'John Doe', slug: 'john-doe', avatar: '' }]
wrapper.setData({ blockedUsers })
})
describe('click unblock', () => {
beforeEach(() => {
wrapper.find('.base-button').trigger('click')
})
it('calls unblock mutation with given user', () => {
expect(mocks.$apollo.mutate).toHaveBeenCalledWith({
mutation: unblockUser(),
variables: { id: 'u1' },
})
})
})
})
})
})

View File

@ -0,0 +1,118 @@
<template>
<div>
<ds-space>
<ds-card :header="$t('settings.blocked-users.name')">
<ds-text>
{{ $t('settings.blocked-users.explanation.intro') }}
</ds-text>
<ds-list>
<ds-list-item>
{{ $t('settings.blocked-users.explanation.your-perspective') }}
</ds-list-item>
<ds-list-item>
{{ $t('settings.blocked-users.explanation.their-perspective') }}
</ds-list-item>
<ds-list-item>
{{ $t('settings.blocked-users.explanation.notifications') }}
</ds-list-item>
</ds-list>
</ds-card>
</ds-space>
<ds-card v-if="blockedUsers && blockedUsers.length">
<ds-table :data="blockedUsers" :fields="fields" condensed>
<template #avatar="scope">
<nuxt-link
:to="{
name: 'profile-id-slug',
params: { id: scope.row.id, slug: scope.row.slug },
}"
>
<user-avatar :user="scope.row" size="small" />
</nuxt-link>
</template>
<template #name="scope">
<nuxt-link
:to="{
name: 'profile-id-slug',
params: { id: scope.row.id, slug: scope.row.slug },
}"
>
<b>{{ scope.row.name | truncate(20) }}</b>
</nuxt-link>
</template>
<template #slug="scope">
<nuxt-link
:to="{
name: 'profile-id-slug',
params: { id: scope.row.id, slug: scope.row.slug },
}"
>
<b>{{ scope.row.slug | truncate(20) }}</b>
</nuxt-link>
</template>
<template #unblockUser="scope">
<base-button circle size="small" @click="unblockUser(scope)" icon="user-plus" />
</template>
</ds-table>
</ds-card>
<ds-card v-else>
<ds-space>
<ds-placeholder>
{{ $t('settings.blocked-users.empty') }}
</ds-placeholder>
</ds-space>
<ds-space>
<ds-text align="center">
{{ $t('settings.blocked-users.how-to') }}
</ds-text>
</ds-space>
</ds-card>
</div>
</template>
<script>
import { blockedUsers, unblockUser } from '~/graphql/settings/BlockedUsers'
import UserAvatar from '~/components/_new/generic/UserAvatar/UserAvatar'
export default {
components: {
UserAvatar,
},
data() {
return {
blockedUsers: [],
}
},
computed: {
fields() {
return {
avatar: '',
name: this.$t('settings.blocked-users.columns.name'),
slug: this.$t('settings.blocked-users.columns.slug'),
unblockUser: this.$t('settings.blocked-users.columns.unblock'),
}
},
},
apollo: {
blockedUsers: { query: blockedUsers, fetchPolicy: 'cache-and-network' },
},
methods: {
async unblockUser(user) {
await this.$apollo.mutate({
mutation: unblockUser(),
variables: { id: user.row.id },
})
this.$apollo.queries.blockedUsers.refetch()
const { name } = user.row
this.$toast.success(this.$t('settings.blocked-user.unblocked', { name }))
},
},
}
</script>
<style lang="scss">
.ds-table-col {
vertical-align: middle;
}
</style>

View File

@ -46,7 +46,7 @@ describe('muted-users.vue', () => {
expect(wrapper.is('div')).toBe(true)
})
describe('given a list of blocked users', () => {
describe('given a list of muted users', () => {
beforeEach(() => {
const mutedUsers = [{ id: 'u1', name: 'John Doe', slug: 'john-doe', avatar: '' }]
wrapper.setData({ mutedUsers })
@ -54,7 +54,7 @@ describe('muted-users.vue', () => {
describe('click unmute', () => {
beforeEach(() => {
wrapper.find('button').trigger('click')
wrapper.find('.base-button').trigger('click')
})
it('calls unmute mutation with given user', () => {

View File

@ -17,7 +17,7 @@
</ds-space>
<ds-card v-if="mutedUsers && mutedUsers.length">
<ds-table :data="mutedUsers" :fields="fields" condensed>
<template slot="avatar" slot-scope="scope">
<template #avatar="scope">
<nuxt-link
:to="{
name: 'profile-id-slug',
@ -27,7 +27,7 @@
<user-avatar :user="scope.row" size="small" />
</nuxt-link>
</template>
<template slot="name" slot-scope="scope">
<template #name="scope">
<nuxt-link
:to="{
name: 'profile-id-slug',
@ -37,7 +37,7 @@
<b>{{ scope.row.name | truncate(20) }}</b>
</nuxt-link>
</template>
<template slot="slug" slot-scope="scope">
<template #slug="scope">
<nuxt-link
:to="{
name: 'profile-id-slug',
@ -48,7 +48,7 @@
</nuxt-link>
</template>
<template slot="unmuteUser" slot-scope="scope">
<template #unmuteUser="scope">
<base-button circle size="small" @click="unmuteUser(scope)" icon="user-plus" />
</template>
</ds-table>

File diff suppressed because it is too large Load Diff

170
yarn.lock
View File

@ -9,12 +9,12 @@
dependencies:
"@babel/highlight" "^7.8.3"
"@babel/compat-data@^7.8.0", "@babel/compat-data@^7.8.1":
version "7.8.1"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.1.tgz#fc0bbbb7991e4fb2b47e168e60f2cc2c41680be9"
integrity sha512-Z+6ZOXvyOWYxJ50BwxzdhRnRsGST8Y3jaZgxYig575lTjVSs3KtJnmESwZegg6e2Dn0td1eDhoWlp1wI4BTCPw==
"@babel/compat-data@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.4.tgz#bbe65d05a291667a8394fe8a0e0e277ef22b0d2a"
integrity sha512-lHLhlsvFjJAqNU71b7k6Vv9ewjmTXKvqaMv7n0G1etdCabWLw3nEYE8mmgoVOxMIFE07xOvo7H7XBASirX6Rrg==
dependencies:
browserslist "^4.8.2"
browserslist "^4.8.5"
invariant "^2.2.4"
semver "^5.5.0"
@ -38,17 +38,17 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/core@^7.1.0", "@babel/core@^7.7.5", "@babel/core@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941"
integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==
"@babel/core@^7.1.0", "@babel/core@^7.7.5", "@babel/core@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e"
integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==
dependencies:
"@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.8.3"
"@babel/helpers" "^7.8.3"
"@babel/parser" "^7.8.3"
"@babel/generator" "^7.8.4"
"@babel/helpers" "^7.8.4"
"@babel/parser" "^7.8.4"
"@babel/template" "^7.8.3"
"@babel/traverse" "^7.8.3"
"@babel/traverse" "^7.8.4"
"@babel/types" "^7.8.3"
convert-source-map "^1.7.0"
debug "^4.1.0"
@ -59,10 +59,10 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.4.4", "@babel/generator@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03"
integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==
"@babel/generator@^7.4.4", "@babel/generator@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e"
integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==
dependencies:
"@babel/types" "^7.8.3"
jsesc "^2.5.1"
@ -101,15 +101,15 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
"@babel/helper-compilation-targets@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.3.tgz#2deedc816fd41dca7355ef39fd40c9ea69f0719a"
integrity sha512-JLylPCsFjhLN+6uBSSh3iYdxKdeO9MNmoY96PE/99d8kyBFaXLORtAVhqN6iHa+wtPeqxKLghDOZry0+Aiw9Tw==
"@babel/helper-compilation-targets@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz#03d7ecd454b7ebe19a254f76617e61770aed2c88"
integrity sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg==
dependencies:
"@babel/compat-data" "^7.8.1"
browserslist "^4.8.2"
"@babel/compat-data" "^7.8.4"
browserslist "^4.8.5"
invariant "^2.2.4"
levenary "^1.1.0"
levenary "^1.1.1"
semver "^5.5.0"
"@babel/helper-create-class-features-plugin@^7.3.0":
@ -310,13 +310,13 @@
"@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3"
"@babel/helpers@^7.4.4", "@babel/helpers@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.3.tgz#382fbb0382ce7c4ce905945ab9641d688336ce85"
integrity sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==
"@babel/helpers@^7.4.4", "@babel/helpers@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73"
integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==
dependencies:
"@babel/template" "^7.8.3"
"@babel/traverse" "^7.8.3"
"@babel/traverse" "^7.8.4"
"@babel/types" "^7.8.3"
"@babel/highlight@^7.8.3":
@ -328,10 +328,10 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
"@babel/parser@^7.4.5", "@babel/parser@^7.7.5", "@babel/parser@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081"
integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==
"@babel/parser@^7.4.5", "@babel/parser@^7.7.5", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8"
integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==
"@babel/plugin-proposal-async-generator-functions@^7.2.0", "@babel/plugin-proposal-async-generator-functions@^7.8.3":
version "7.8.3"
@ -559,10 +559,10 @@
"@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-for-of@^7.4.4", "@babel/plugin-transform-for-of@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.3.tgz#15f17bce2fc95c7d59a24b299e83e81cedc22e18"
integrity sha512-ZjXznLNTxhpf4Q5q3x1NsngzGA38t9naWH8Gt+0qYZEJAcvPI9waSStSh56u19Ofjr7QmD0wUsQ8hw8s/p1VnA==
"@babel/plugin-transform-for-of@^7.4.4", "@babel/plugin-transform-for-of@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz#6fe8eae5d6875086ee185dd0b098a8513783b47d"
integrity sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
@ -647,10 +647,10 @@
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/helper-replace-supers" "^7.8.3"
"@babel/plugin-transform-parameters@^7.4.4", "@babel/plugin-transform-parameters@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.3.tgz#7890576a13b17325d8b7d44cb37f21dc3bbdda59"
integrity sha512-/pqngtGb54JwMBZ6S/D3XYylQDFtGjWrnoCF4gXZOUpFV/ujbxnoNGNvDGu6doFWRPBveE72qTx/RRU44j5I/Q==
"@babel/plugin-transform-parameters@^7.4.4", "@babel/plugin-transform-parameters@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz#1d5155de0b65db0ccf9971165745d3bb990d77d3"
integrity sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==
dependencies:
"@babel/helper-call-delegate" "^7.8.3"
"@babel/helper-get-function-arity" "^7.8.3"
@ -749,10 +749,10 @@
"@babel/helper-annotate-as-pure" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-transform-typeof-symbol@^7.2.0", "@babel/plugin-transform-typeof-symbol@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.3.tgz#5cffb216fb25c8c64ba6bf5f76ce49d3ab079f4d"
integrity sha512-3TrkKd4LPqm4jHs6nPtSDI/SV9Cm5PRJkHLUgTcqRQQTMAZ44ZaAdDZJtvWFSaRcvT0a1rTmJ5ZA5tDKjleF3g==
"@babel/plugin-transform-typeof-symbol@^7.2.0", "@babel/plugin-transform-typeof-symbol@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412"
integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
@ -818,13 +818,13 @@
js-levenshtein "^1.1.3"
semver "^5.5.0"
"@babel/preset-env@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.3.tgz#dc0fb2938f52bbddd79b3c861a4b3427dd3a6c54"
integrity sha512-Rs4RPL2KjSLSE2mWAx5/iCH+GC1ikKdxPrhnRS6PfFVaiZeom22VFKN4X8ZthyN61kAaR05tfXTbCvatl9WIQg==
"@babel/preset-env@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.4.tgz#9dac6df5f423015d3d49b6e9e5fa3413e4a72c4e"
integrity sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w==
dependencies:
"@babel/compat-data" "^7.8.0"
"@babel/helper-compilation-targets" "^7.8.3"
"@babel/compat-data" "^7.8.4"
"@babel/helper-compilation-targets" "^7.8.4"
"@babel/helper-module-imports" "^7.8.3"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/plugin-proposal-async-generator-functions" "^7.8.3"
@ -853,7 +853,7 @@
"@babel/plugin-transform-dotall-regex" "^7.8.3"
"@babel/plugin-transform-duplicate-keys" "^7.8.3"
"@babel/plugin-transform-exponentiation-operator" "^7.8.3"
"@babel/plugin-transform-for-of" "^7.8.3"
"@babel/plugin-transform-for-of" "^7.8.4"
"@babel/plugin-transform-function-name" "^7.8.3"
"@babel/plugin-transform-literals" "^7.8.3"
"@babel/plugin-transform-member-expression-literals" "^7.8.3"
@ -864,7 +864,7 @@
"@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3"
"@babel/plugin-transform-new-target" "^7.8.3"
"@babel/plugin-transform-object-super" "^7.8.3"
"@babel/plugin-transform-parameters" "^7.8.3"
"@babel/plugin-transform-parameters" "^7.8.4"
"@babel/plugin-transform-property-literals" "^7.8.3"
"@babel/plugin-transform-regenerator" "^7.8.3"
"@babel/plugin-transform-reserved-words" "^7.8.3"
@ -872,13 +872,13 @@
"@babel/plugin-transform-spread" "^7.8.3"
"@babel/plugin-transform-sticky-regex" "^7.8.3"
"@babel/plugin-transform-template-literals" "^7.8.3"
"@babel/plugin-transform-typeof-symbol" "^7.8.3"
"@babel/plugin-transform-typeof-symbol" "^7.8.4"
"@babel/plugin-transform-unicode-regex" "^7.8.3"
"@babel/types" "^7.8.3"
browserslist "^4.8.2"
browserslist "^4.8.5"
core-js-compat "^3.6.2"
invariant "^2.2.2"
levenary "^1.1.0"
levenary "^1.1.1"
semver "^5.5.0"
"@babel/preset-react@7.0.0":
@ -934,16 +934,16 @@
"@babel/parser" "^7.8.3"
"@babel/types" "^7.8.3"
"@babel/traverse@^7.4.5", "@babel/traverse@^7.5.5", "@babel/traverse@^7.7.4", "@babel/traverse@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a"
integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==
"@babel/traverse@^7.4.5", "@babel/traverse@^7.5.5", "@babel/traverse@^7.7.4", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c"
integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==
dependencies:
"@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.8.3"
"@babel/generator" "^7.8.4"
"@babel/helper-function-name" "^7.8.3"
"@babel/helper-split-export-declaration" "^7.8.3"
"@babel/parser" "^7.8.3"
"@babel/parser" "^7.8.4"
"@babel/types" "^7.8.3"
debug "^4.1.0"
globals "^11.1.0"
@ -1737,14 +1737,14 @@ browserify@16.2.3, browserify@^16.1.0:
vm-browserify "^1.0.0"
xtend "^4.0.0"
browserslist@^4.6.0, browserslist@^4.8.2, browserslist@^4.8.3:
version "4.8.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.3.tgz#65802fcd77177c878e015f0e3189f2c4f627ba44"
integrity sha512-iU43cMMknxG1ClEZ2MDKeonKE1CCrFVkQK2AqO2YWFmvIrx4JWrvQ4w4hQez6EpVI8rHTtqh/ruHHDHSOKxvUg==
browserslist@^4.6.0, browserslist@^4.8.3, browserslist@^4.8.5:
version "4.8.6"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.6.tgz#96406f3f5f0755d272e27a66f4163ca821590a7e"
integrity sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg==
dependencies:
caniuse-lite "^1.0.30001017"
electron-to-chromium "^1.3.322"
node-releases "^1.1.44"
caniuse-lite "^1.0.30001023"
electron-to-chromium "^1.3.341"
node-releases "^1.1.47"
bser@2.1.1:
version "2.1.1"
@ -1845,10 +1845,10 @@ camelcase@^5.0.0, camelcase@^5.3.1:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
caniuse-lite@^1.0.30001017:
version "1.0.30001020"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001020.tgz#3f04c1737500ffda78be9beb0b5c1e2070e15926"
integrity sha512-yWIvwA68wRHKanAVS1GjN8vajAv7MBFshullKCeq/eKpK7pJBVDgFFEqvgWTkcP2+wIDeQGYFRXECjKZnLkUjA==
caniuse-lite@^1.0.30001023:
version "1.0.30001023"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001023.tgz#b82155827f3f5009077bdd2df3d8968bcbcc6fc4"
integrity sha512-C5TDMiYG11EOhVOA62W1p3UsJ2z4DsHtMBQtjzp3ZsUglcQn62WOUgW0y795c7A5uZ+GCEIvzkMatLIlAsbNTA==
capture-exit@^2.0.0:
version "2.0.0"
@ -2923,10 +2923,10 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
electron-to-chromium@^1.3.322:
version "1.3.322"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8"
integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA==
electron-to-chromium@^1.3.341:
version "1.3.344"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.344.tgz#f1397a633c35e726730c24be1084cd25c3ee8148"
integrity sha512-tvbx2Wl8WBR+ym3u492D0L6/jH+8NoQXqe46+QhbWH3voVPauGuZYeb1QAXYoOAWuiP2dbSvlBx0kQ1F3hu/Mw==
elegant-spinner@^1.0.1:
version "1.0.1"
@ -4396,10 +4396,10 @@ leven@^3.1.0:
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
levenary@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.0.tgz#fc146fe75f32dc483a0a2c64aef720f602cd6210"
integrity sha512-VHcwhO0UTpUW7rLPN2/OiWJdgA1e9BqEDALhrgCe/F+uUJnep6CoUsTzMeP8Rh0NGr9uKquXxqe7lwLZo509nQ==
levenary@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77"
integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==
dependencies:
leven "^3.1.0"
@ -4977,10 +4977,10 @@ node-pre-gyp@^0.10.0:
semver "^5.3.0"
tar "^4"
node-releases@^1.1.44:
version "1.1.45"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.45.tgz#4cf7e9175d71b1317f15ffd68ce63bce1d53e9f2"
integrity sha512-cXvGSfhITKI8qsV116u2FTzH5EWZJfgG7d4cpqwF8I8+1tWpD6AsvvGRKq2onR0DNj1jfqsjkXZsm14JMS7Cyg==
node-releases@^1.1.47:
version "1.1.47"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.47.tgz#c59ef739a1fd7ecbd9f0b7cf5b7871e8a8b591e4"
integrity sha512-k4xjVPx5FpwBUj0Gw7uvFOTF4Ep8Hok1I6qjwL3pLfwe7Y0REQSAqOwwv9TWBCUtMHxcXfY4PgRLRozcChvTcA==
dependencies:
semver "^6.3.0"