Merge branch 'master' of https://github.com/Human-Connection/Human-Connection into 1017-send-out-notifications-on-create-omment

This commit is contained in:
Wolfgang Huß 2019-07-16 16:10:36 +02:00
commit cd0c509c81
47 changed files with 1080 additions and 550 deletions

View File

@ -95,7 +95,7 @@ coverage:
# - master
#flags:
# - integration
paths:
paths:
- backend/ # only include coverage in "backend/" folder
webapp: # declare a new status context "frontend"
against: parent
@ -127,7 +127,7 @@ coverage:
# - integration
# paths:
# - folder
#changes:
# default:
# against: parent
@ -150,20 +150,8 @@ coverage:
#ignore: # files and folders for processing
# - tests/*
#fixes:
# - "old_path::new_path"
comment:
# layout options are quite limited in v4.x - there have been way more options in v1.0
layout: reach, diff, flags, files # mostly old options: header, diff, uncovered, reach, files, tree, changes, sunburst, flags
behavior: new # default = posts once then update, posts new if delete
# once = post once then updates
# new = delete old, post new
# spammy = post new
require_changes: false # if true: only post the comment if coverage changes
require_base: no # [yes :: must have a base report to post]
require_head: no # [yes :: must have a head report to post]
branches: null # branch names that can post comment
flags: null
paths: null
comment: off

View File

@ -11,7 +11,6 @@ addons:
before_install:
- yarn global add wait-on
# Install Codecov
- yarn global add codecov
- yarn install
- cp cypress.env.template.json cypress.env.json
@ -40,7 +39,7 @@ script:
# Fullstack
- yarn run cypress:run
# Coverage
- codecov
- yarn run codecov
after_success:
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh

View File

@ -34,7 +34,6 @@
"!**/src/**/?(*.)+(spec|test).js?(x)"
],
"coverageReporters": [
"text",
"lcov"
],
"testMatch": [
@ -49,6 +48,7 @@
"apollo-link-context": "~1.0.18",
"apollo-link-http": "~1.5.15",
"apollo-server": "~2.6.9",
"apollo-server-express": "^2.6.9",
"bcryptjs": "~2.4.3",
"cheerio": "~1.0.0-rc.3",
"cors": "~2.8.5",
@ -56,7 +56,7 @@
"date-fns": "2.0.0-beta.1",
"debug": "~4.1.1",
"dotenv": "~8.0.0",
"express": "~4.17.1",
"express": "^4.17.1",
"faker": "Marak/faker.js#master",
"graphql": "~14.4.2",
"graphql-custom-directives": "~0.2.14",
@ -64,7 +64,6 @@
"graphql-middleware": "~3.0.2",
"graphql-shield": "~6.0.3",
"graphql-tag": "~2.10.1",
"graphql-yoga": "~1.18.0",
"helmet": "~3.18.0",
"jsonwebtoken": "~8.5.1",
"linkifyjs": "~2.1.8",
@ -74,7 +73,7 @@
"neo4j-graphql-js": "^2.6.3",
"neode": "^0.2.16",
"node-fetch": "~2.6.0",
"nodemailer": "^6.2.1",
"nodemailer": "^6.3.0",
"npm-run-all": "~4.1.5",
"request": "~2.88.0",
"sanitize-html": "~1.20.1",
@ -100,7 +99,7 @@
"eslint-config-prettier": "~6.0.0",
"eslint-config-standard": "~12.0.0",
"eslint-plugin-import": "~2.18.0",
"eslint-plugin-jest": "~22.7.2",
"eslint-plugin-jest": "~22.8.0",
"eslint-plugin-node": "~9.1.0",
"eslint-plugin-prettier": "~3.1.0",
"eslint-plugin-promise": "~4.2.1",

View File

@ -1,18 +1,8 @@
import createServer from './server'
import ActivityPub from './activitypub/ActivityPub'
import CONFIG from './config'
const serverConfig = {
port: CONFIG.GRAPHQL_PORT,
// cors: {
// credentials: true,
// origin: [CONFIG.CLIENT_URI] // your frontend url.
// }
}
const server = createServer()
server.start(serverConfig, options => {
const { app } = createServer()
app.listen({ port: CONFIG.GRAPHQL_PORT }, () => {
/* eslint-disable-next-line no-console */
console.log(`GraphQLServer ready at ${CONFIG.GRAPHQL_URI} 🚀`)
ActivityPub.init(server)
})

View File

@ -15,3 +15,9 @@ export async function login(variables) {
authorization: `Bearer ${response.login}`,
}
}
//* This is a fake ES2015 template string, just to benefit of syntax
// highlighting of `gql` template strings in certain editors.
export function gql(strings) {
return strings.join('')
}

View File

@ -11,6 +11,7 @@ export const signupTemplate = options => {
} = options
const actionUrl = new URL('/registration/create-user-account', CONFIG.CLIENT_URI)
actionUrl.searchParams.set('nonce', nonce)
actionUrl.searchParams.set('email', email)
return {
to: email,

View File

@ -1,6 +1,5 @@
import { GraphQLClient } from 'graphql-request'
import gql from 'graphql-tag'
import { host, login } from '../../jest/helpers'
import { host, login, gql } from '../../jest/helpers'
import Factory from '../../seed/factories'
const factory = Factory()

View File

@ -1,4 +1,6 @@
import { applyMiddleware } from 'graphql-middleware'
import CONFIG from './../config'
import activityPub from './activityPubMiddleware'
import softDelete from './softDeleteMiddleware'
import sluggify from './sluggifyMiddleware'
@ -56,5 +58,6 @@ export default schema => {
console.log(`Warning: "${disabledMiddlewares}" middlewares have been disabled.`)
}
return order.map(key => middlewares[key])
const appliedMiddlewares = order.map(key => middlewares[key])
return applyMiddleware(schema, ...appliedMiddlewares)
}

View File

@ -1,7 +1,6 @@
import gql from 'graphql-tag'
import { GraphQLClient } from 'graphql-request'
import Factory from '../../seed/factories'
import { host, login } from '../../jest/helpers'
import { host, login, gql } from '../../jest/helpers'
const factory = Factory()
let client

View File

@ -18,10 +18,11 @@ const createPostWithCategoriesMutation = `
mutation($title: String!, $content: String!, $categoryIds: [ID]) {
CreatePost(title: $title, content: $content, categoryIds: $categoryIds) {
id
title
}
}
`
const creatPostWithCategoriesVariables = {
const createPostWithCategoriesVariables = {
title: postTitle,
content: postContent,
categoryIds: ['cat9', 'cat4', 'cat15'],
@ -35,6 +36,26 @@ const postQueryWithCategories = `
}
}
`
const createPostWithoutCategoriesVariables = {
title: 'This is a post without categories',
content: 'I should be able to filter it out',
categoryIds: null,
}
const postQueryFilteredByCategory = `
query Post($filter: _PostFilter) {
Post(filter: $filter) {
title
id
categories {
id
}
}
}
`
const postCategoriesFilterParam = { categories_some: { id_in: ['cat4'] } }
const postQueryFilteredByCategoryVariables = {
filter: postCategoriesFilterParam,
}
beforeEach(async () => {
userParams = {
name: 'TestUser',
@ -133,7 +154,8 @@ describe('CreatePost', () => {
})
describe('categories', () => {
it('allows a user to set the categories of the post', async () => {
let postWithCategories
beforeEach(async () => {
await Promise.all([
factory.create('Category', {
id: 'cat9',
@ -151,18 +173,39 @@ describe('CreatePost', () => {
icon: 'shopping-cart',
}),
])
const expected = [{ id: 'cat9' }, { id: 'cat4' }, { id: 'cat15' }]
const postWithCategories = await client.request(
postWithCategories = await client.request(
createPostWithCategoriesMutation,
creatPostWithCategoriesVariables,
createPostWithCategoriesVariables,
)
})
it('allows a user to set the categories of the post', async () => {
const expected = [{ id: 'cat9' }, { id: 'cat4' }, { id: 'cat15' }]
const postQueryWithCategoriesVariables = {
id: postWithCategories.CreatePost.id,
}
await expect(
client.request(postQueryWithCategories, postQueryWithCategoriesVariables),
).resolves.toEqual({ Post: [{ categories: expect.arrayContaining(expected) }] })
})
it('allows a user to filter for posts by category', async () => {
await client.request(createPostWithCategoriesMutation, createPostWithoutCategoriesVariables)
const categoryIds = [{ id: 'cat4' }, { id: 'cat15' }, { id: 'cat9' }]
const expected = {
Post: [
{
title: postTitle,
id: postWithCategories.CreatePost.id,
categories: expect.arrayContaining(categoryIds),
},
],
}
await expect(
client.request(postQueryFilteredByCategory, postQueryFilteredByCategoryVariables),
).resolves.toEqual(expected)
})
})
})
})
@ -260,7 +303,7 @@ describe('UpdatePost', () => {
])
postWithCategories = await client.request(
createPostWithCategoriesMutation,
creatPostWithCategoriesVariables,
createPostWithCategoriesVariables,
)
updatePostVariables = {
id: postWithCategories.CreatePost.id,

View File

@ -1,7 +1,6 @@
import { GraphQLClient } from 'graphql-request'
import Factory from '../../seed/factories'
import { host, login } from '../../jest/helpers'
import gql from 'graphql-tag'
import { host, login, gql } from '../../jest/helpers'
const factory = Factory()
let user
@ -107,10 +106,11 @@ describe('rewards', () => {
id: 'indiegogo_en_racoon',
icon: '/img/badges/indiegogo_en_racoon.svg',
})
const badges = [{ id: 'indiegogo_en_racoon' }, { id: 'indiegogo_en_rhino' }]
const expected = {
reward: {
id: 'u1',
badges: [{ id: 'indiegogo_en_racoon' }, { id: 'indiegogo_en_rhino' }],
badges: expect.arrayContaining(badges),
},
}
await client.request(mutation, variables)

View File

@ -1,7 +1,6 @@
import gql from 'graphql-tag'
import { GraphQLClient } from 'graphql-request'
import Factory from '../../seed/factories'
import { host, login } from '../../jest/helpers'
import { host, login, gql } from '../../jest/helpers'
const factory = Factory()

View File

@ -1,7 +1,6 @@
import { GraphQLClient } from 'graphql-request'
import { login, host } from '../../jest/helpers'
import Factory from '../../seed/factories'
import gql from 'graphql-tag'
import { host, login, gql } from '../../jest/helpers'
const factory = Factory()
let client

View File

@ -81,6 +81,9 @@ type User {
input _UserFilter {
AND: [_UserFilter!]
OR: [_UserFilter!]
name_contains: String
about_contains: String
slug_contains: String
id: ID
id_not: ID
id_in: [ID!]

View File

@ -706,6 +706,13 @@ import Factory from './factories'
to: 'o3',
}),
])
await Promise.all(
[...Array(30).keys()].map(i => {
return f.create('User')
}),
)
/* eslint-disable-next-line no-console */
console.log('Seeded Data...')
process.exit(0)

View File

@ -1,6 +1,6 @@
import express from 'express'
import helmet from 'helmet'
import { GraphQLServer } from 'graphql-yoga'
import { ApolloServer } from 'apollo-server-express'
import CONFIG, { requiredConfigs } from './config'
import mocks from './mocks'
import middleware from './middleware'
@ -20,28 +20,30 @@ const driver = getDriver()
const createServer = options => {
const defaults = {
context: async ({ request }) => {
const user = await decode(driver, request.headers.authorization)
context: async ({ req }) => {
const user = await decode(driver, req.headers.authorization)
return {
driver,
user,
req: request,
req,
cypherParams: {
currentUserId: user ? user.id : null,
},
}
},
schema,
schema: middleware(schema),
debug: CONFIG.DEBUG,
tracing: CONFIG.DEBUG,
middlewares: middleware(schema),
mocks: CONFIG.MOCKS ? mocks : false,
}
const server = new GraphQLServer(Object.assign({}, defaults, options))
const server = new ApolloServer(Object.assign({}, defaults, options))
server.express.use(helmet())
server.express.use(express.static('public'))
return server
const app = express()
app.use(helmet())
app.use(express.static('public'))
server.applyMiddleware({ app, path: '/' })
return { server, app }
}
export default createServer

View File

@ -0,0 +1,43 @@
import { createTestClient } from 'apollo-server-testing'
import createServer from './server'
/**
* This file is for demonstration purposes. It does not really test the
* `isLoggedIn` query but demonstrates how we can use `apollo-server-testing`.
* All we need to do is to get an instance of `ApolloServer` and maybe we want
* stub out `context` as shown below.
*
*/
let user
let action
describe('isLoggedIn', () => {
beforeEach(() => {
action = async () => {
const { server } = createServer({
context: () => {
return {
user,
}
},
})
const { query } = createTestClient(server)
const isLoggedIn = `{ isLoggedIn }`
return query({ query: isLoggedIn })
}
})
it('returns false', async () => {
const expected = expect.objectContaining({ data: { isLoggedIn: false } })
await expect(action()).resolves.toEqual(expected)
})
describe('when authenticated', () => {
it('returns true', async () => {
user = { id: '123' }
const expected = expect.objectContaining({ data: { isLoggedIn: true } })
await expect(action()).resolves.toEqual(expected)
})
})
})

View File

@ -1084,7 +1084,7 @@
"@types/node" "*"
"@types/range-parser" "*"
"@types/express@*", "@types/express@4.17.0", "@types/express@^4.11.1":
"@types/express@*", "@types/express@4.17.0":
version "4.17.0"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.0.tgz#49eaedb209582a86f12ed9b725160f12d04ef287"
integrity sha512-CjaMu57cjgjuZbh9DpkloeGxV45CnMGlVd+XpG7Gm9QgVrd7KFq+X4HY0vM+2v0bczS48Wg7bvnMY5TN+Xmcfw==
@ -1093,16 +1093,6 @@
"@types/express-serve-static-core" "*"
"@types/serve-static" "*"
"@types/graphql-deduplicator@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/graphql-deduplicator/-/graphql-deduplicator-2.0.0.tgz#9e577b8f3feb3d067b0ca756f4a1fb356d533922"
integrity sha512-swUwj5hWF1yFzbUXStLJrUa0ksAt11B8+SwhsAjQAX0LYJ1LLioAyuDcJ9bovWbsNzIXJYXLvljSPQw8nR728w==
"@types/graphql@^14.0.0":
version "14.0.3"
resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-14.0.3.tgz#389e2e5b83ecdb376d9f98fae2094297bc112c1c"
integrity sha512-TcFkpEjcQK7w8OcrQcd7iIBPjU0rdyi3ldj6d0iJ4PPSzbWqPBvXj9KSwO14hTOX2dm9RoiH7VuxksJLNYdXUQ==
"@types/istanbul-lib-coverage@*":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
@ -1179,11 +1169,6 @@
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.26.21.tgz#bfca27a02a0631495bfd25b6c63647a125e6944e"
integrity sha512-1C45M7hZrVsl8bXxYV01bitRp0r35djt+eX5HWFH3NdH+8ejqta3KM7rmQLRLrupkhF7jRkAtXl2EgDsriIqwA==
"@types/zen-observable@^0.5.3":
version "0.5.4"
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.4.tgz#b863a4191e525206819e008097ebf0fb2e3a1cdc"
integrity sha512-sW6xN96wUak4tgc89d0tbTg7QDGYhGv5hvQIS6h4mRCd8h2btiZ80loPU8cyLwsBbA4ZeQt0FjvUhJ4rNhdsGg==
"@types/zen-observable@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d"
@ -1351,13 +1336,6 @@ apollo-cache-control@0.7.5:
apollo-server-env "2.4.0"
graphql-extensions "0.7.7"
apollo-cache-control@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.1.1.tgz#173d14ceb3eb9e7cb53de7eb8b61bee6159d4171"
integrity sha512-XJQs167e9u+e5ybSi51nGYr70NPBbswdvTEHtbtXbwkZ+n9t0SLPvUcoqceayOSwjK1XYOdU/EKPawNdb3rLQA==
dependencies:
graphql-extensions "^0.0.x"
apollo-cache-inmemory@~1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.2.tgz#bbf2e4e1eacdf82b2d526f5c2f3b37e5acee3c5e"
@ -1512,15 +1490,6 @@ apollo-server-core@2.6.9:
subscriptions-transport-ws "^0.9.11"
ws "^6.0.0"
apollo-server-core@^1.3.6, apollo-server-core@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-1.4.0.tgz#4faff7f110bfdd6c3f47008302ae24140f94c592"
integrity sha512-BP1Vh39krgEjkQxbjTdBURUjLHbFq1zeOChDJgaRsMxGtlhzuLWwwC6lLdPatN8jEPbeHq8Tndp9QZ3iQZOKKA==
dependencies:
apollo-cache-control "^0.1.0"
apollo-tracing "^0.1.0"
graphql-extensions "^0.0.x"
apollo-server-env@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-2.4.0.tgz#6611556c6b627a1636eed31317d4f7ea30705872"
@ -1534,7 +1503,7 @@ apollo-server-errors@2.3.1:
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.1.tgz#033cf331463ebb99a563f8354180b41ac6714eb6"
integrity sha512-errZvnh0vUQChecT7M4A/h94dnBSRL213dNxpM5ueMypaLYgnp4hiCTWIEaooo9E4yMGd1qA6WaNbLDG2+bjcg==
apollo-server-express@2.6.9:
apollo-server-express@2.6.9, apollo-server-express@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.6.9.tgz#176dab7f2cd5a99655c8eb382ad9b10797422a7b"
integrity sha512-iTkdIdX7m9EAlmL/ZPkKR+x/xuFk1HYZWuJIJG57hHUhcOxj50u7F1E5+5fDwl5RFIdepQ61azF31hhNZuNi4g==
@ -1552,27 +1521,6 @@ apollo-server-express@2.6.9:
graphql-tools "^4.0.0"
type-is "^1.6.16"
apollo-server-express@^1.3.6:
version "1.4.0"
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-1.4.0.tgz#7d7c58d6d6f9892b83fe575669093bb66738b125"
integrity sha512-zkH00nxhLnJfO0HgnNPBTfZw8qI5ILaPZ5TecMCI9+Y9Ssr2b0bFr9pBRsXy9eudPhI+/O4yqegSUsnLdF/CPw==
dependencies:
apollo-server-core "^1.4.0"
apollo-server-module-graphiql "^1.4.0"
apollo-server-lambda@1.3.6:
version "1.3.6"
resolved "https://registry.yarnpkg.com/apollo-server-lambda/-/apollo-server-lambda-1.3.6.tgz#bdaac37f143c6798e40b8ae75580ba673cea260e"
integrity sha1-varDfxQ8Z5jkC4rnVYC6ZzzqJg4=
dependencies:
apollo-server-core "^1.3.6"
apollo-server-module-graphiql "^1.3.4"
apollo-server-module-graphiql@^1.3.4, apollo-server-module-graphiql@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.4.0.tgz#c559efa285578820709f1769bb85d3b3eed3d8ec"
integrity sha512-GmkOcb5he2x5gat+TuiTvabnBf1m4jzdecal3XbXBh/Jg+kx4hcvO3TTDFQ9CuTprtzdcVyA11iqG7iOMOt7vA==
apollo-server-plugin-base@0.5.8:
version "0.5.8"
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.5.8.tgz#77b4127aff4e3514a9d49e3cc61256aee4d9422e"
@ -1604,23 +1552,6 @@ apollo-tracing@0.7.4:
apollo-server-env "2.4.0"
graphql-extensions "0.7.7"
apollo-tracing@^0.1.0:
version "0.1.4"
resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.1.4.tgz#5b8ae1b01526b160ee6e552a7f131923a9aedcc7"
integrity sha512-Uv+1nh5AsNmC3m130i2u3IqbS+nrxyVV3KYimH5QKsdPjxxIQB3JAT+jJmpeDxBel8gDVstNmCh82QSLxLSIdQ==
dependencies:
graphql-extensions "~0.0.9"
apollo-upload-server@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/apollo-upload-server/-/apollo-upload-server-7.1.0.tgz#21e07b52252b3749b913468599813e13cfca805f"
integrity sha512-cD9ReCeyurYwZyEDqJYb5TOc9dt8yhPzS+MtrY3iJdqw+pqiiyPngAvVXHjN+Ca7Lajvom4/AT/PBrYVDMM3Kw==
dependencies:
busboy "^0.2.14"
fs-capacitor "^1.0.0"
http-errors "^1.7.0"
object-path "^0.11.4"
apollo-utilities@1.3.2, apollo-utilities@^1.0.1, apollo-utilities@^1.3.0, apollo-utilities@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.2.tgz#8cbdcf8b012f664cd6cb5767f6130f5aed9115c9"
@ -1806,30 +1737,6 @@ atob@^2.1.1:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
aws-lambda@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/aws-lambda/-/aws-lambda-0.1.2.tgz#19b1585075df31679597b976a5f1def61f12ccee"
integrity sha1-GbFYUHXfMWeVl7l2pfHe9h8SzO4=
dependencies:
aws-sdk "^*"
commander "^2.5.0"
dotenv "^0.4.0"
aws-sdk@^*:
version "2.373.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.373.0.tgz#fcc5606634b3b11d80810ad252d1b52b3733d780"
integrity sha512-NZYXwXGtFt9jxaKXc+PJsLPnpbD03t0MAZRxh93g36kbFMuRXtY8CDqHYNQ0ZcrgQpXbCQiz1fxT5/wu5Cu70g==
dependencies:
buffer "4.9.1"
events "1.1.1"
ieee754 "1.1.8"
jmespath "0.15.0"
querystring "0.2.0"
sax "1.2.1"
url "0.10.3"
uuid "3.1.0"
xml2js "0.4.19"
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
@ -1919,11 +1826,6 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
base64-js@^1.0.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==
base@^0.11.1:
version "0.11.2"
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
@ -1992,14 +1894,7 @@ bn.js@^2.0.0:
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625"
integrity sha1-EhYrwq5x/EClYmwzQ486h1zTdiU=
body-parser-graphql@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/body-parser-graphql/-/body-parser-graphql-1.1.0.tgz#80a80353c7cb623562fd375750dfe018d75f0f7c"
integrity sha512-bOBF4n1AnUjcY1SzLeibeIx4XOuYqEkjn/Lm4yKhnN6KedoXMv4hVqgcKHGRnxOMJP64tErqrQU+4cihhpbJXg==
dependencies:
body-parser "^1.18.2"
body-parser@1.19.0, body-parser@^1.18.2, body-parser@^1.18.3:
body-parser@1.19.0, body-parser@^1.18.3:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
@ -2110,28 +2005,11 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
buffer@4.9.1:
version "4.9.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
isarray "^1.0.0"
builtin-modules@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
busboy@^0.2.14:
version "0.2.14"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
dependencies:
dicer "0.2.5"
readable-stream "1.1.x"
busboy@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
@ -2365,7 +2243,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
commander@^2.5.0, commander@^2.8.1, commander@^2.9.0:
commander@^2.8.1, commander@^2.9.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
@ -2477,7 +2355,7 @@ core-js-pure@3.1.2:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.1.2.tgz#62fc435f35b7374b9b782013cdcb2f97e9f6dffa"
integrity sha512-5ckIdBF26B3ldK9PM177y2ZcATP2oweam9RskHSoqfZCrJ2As6wVg8zJ1zTriFsZf6clj/N1ThDFRGaomMsh9w==
core-js@^2.4.0, core-js@^2.5.3, core-js@^2.5.7, core-js@^2.6.5:
core-js@^2.4.0, core-js@^2.5.7, core-js@^2.6.5:
version "2.6.9"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
@ -2777,14 +2655,6 @@ detect-newline@^2.1.0:
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
dicer@0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
dependencies:
readable-stream "1.1.x"
streamsearch "0.1.2"
dicer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.3.0.tgz#eacd98b3bfbf92e8ab5c2fdb71aaac44bb06b872"
@ -2877,11 +2747,6 @@ dot-prop@^4.1.0:
dependencies:
is-obj "^1.0.0"
dotenv@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-0.4.0.tgz#f6fb351363c2d92207245c737802c9ab5ae1495a"
integrity sha1-9vs1E2PC2SIHJFxzeALJq1rhSVo=
dotenv@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d"
@ -3124,10 +2989,10 @@ eslint-plugin-import@~2.18.0:
read-pkg-up "^2.0.0"
resolve "^1.11.0"
eslint-plugin-jest@~22.7.2:
version "22.7.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.7.2.tgz#7ab118a66a34e46ae5e16a128b5d24fd28b43dca"
integrity sha512-Aecqe3ulBVI7amgOycVI8ZPL8o0SnGHOf3zn2/Ciu8TXyXDHcjtwD3hOs3ss/Qh/VAwlW/DMcuiXg5btgF+XMA==
eslint-plugin-jest@~22.8.0:
version "22.8.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.8.0.tgz#242ef5459e8da25d2c41438e95eb546e03d7fae1"
integrity sha512-2VftZMfILmlhL3VMq5ptHRIuyyXb3ShDEDb1J1UjvWNzm4l+UK/YmwNuTuJcM0gv8pJuOfiR/8ZptJ8Ou68pFw==
eslint-plugin-node@~9.1.0:
version "9.1.0"
@ -3279,11 +3144,6 @@ eventemitter3@^3.1.0:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
integrity sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==
events@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
exec-sh@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.2.tgz#6738de2eb7c8e671d0366aea0b0db8c6f7d7391b"
@ -3350,7 +3210,7 @@ expect@^24.8.0:
jest-message-util "^24.8.0"
jest-regex-util "^24.3.0"
express@^4.0.0, express@^4.16.3, express@~4.17.1:
express@^4.0.0, express@^4.17.1:
version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
@ -3605,11 +3465,6 @@ fresh@0.5.2:
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
fs-capacitor@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-1.0.1.tgz#ff9dbfa14dfaf4472537720f19c3088ed9278df0"
integrity sha512-XdZK0Q78WP29Vm3FGgJRhRhrBm51PagovzWtW2kJ3Q6cYJbGtZqWSGTSPwvtEkyjIirFd7b8Yes/dpOYjt4RRQ==
fs-capacitor@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-2.0.4.tgz#5a22e72d40ae5078b4fe64fe4d08c0d3fc88ad3c"
@ -3786,11 +3641,6 @@ graphql-custom-directives@~0.2.14:
moment "^2.22.2"
numeral "^2.0.6"
graphql-deduplicator@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/graphql-deduplicator/-/graphql-deduplicator-2.0.2.tgz#d8608161cf6be97725e178df0c41f6a1f9f778f3"
integrity sha512-0CGmTmQh4UvJfsaTPppJAcHwHln8Ayat7yXXxdnuWT+Mb1dBzkbErabCWzjXyKh/RefqlGTTA7EQOZHofMaKJA==
graphql-extensions@0.7.7:
version "0.7.7"
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.7.7.tgz#19f4dea35391065de72b25def98f8396887bdf43"
@ -3799,53 +3649,18 @@ graphql-extensions@0.7.7:
"@apollographql/apollo-tools" "^0.3.6"
apollo-server-env "2.4.0"
graphql-extensions@^0.0.x, graphql-extensions@~0.0.9:
version "0.0.10"
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.0.10.tgz#34bdb2546d43f6a5bc89ab23c295ec0466c6843d"
integrity sha512-TnQueqUDCYzOSrpQb3q1ngDSP2otJSF+9yNLrQGPzkMsvnQ+v6e2d5tl+B35D4y+XpmvVnAn4T3ZK28mkILveA==
dependencies:
core-js "^2.5.3"
source-map-support "^0.5.1"
graphql-import@^0.7.0:
version "0.7.1"
resolved "https://registry.yarnpkg.com/graphql-import/-/graphql-import-0.7.1.tgz#4add8d91a5f752d764b0a4a7a461fcd93136f223"
integrity sha512-YpwpaPjRUVlw2SN3OPljpWbVRWAhMAyfSba5U47qGMOSsPLi2gYeJtngGpymjm9nk57RFWEpjqwh4+dpYuFAPw==
dependencies:
lodash "^4.17.4"
resolve-from "^4.0.0"
graphql-iso-date@~3.6.1:
version "3.6.1"
resolved "https://registry.yarnpkg.com/graphql-iso-date/-/graphql-iso-date-3.6.1.tgz#bd2d0dc886e0f954cbbbc496bbf1d480b57ffa96"
integrity sha512-AwFGIuYMJQXOEAgRlJlFL4H1ncFM8n8XmoVDTNypNOZyQ8LFDG2ppMFlsS862BSTCDcSUfHp8PD3/uJhv7t59Q==
graphql-middleware@3.0.2, graphql-middleware@~3.0.2:
graphql-middleware@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/graphql-middleware/-/graphql-middleware-3.0.2.tgz#c8cdb67615eec02aec237b455e679f5fc973ddc4"
integrity sha512-sRqu1sF+77z42z1OVM1QDHKQWnWY5K3nAgqWiZwx3U4tqNZprrDuXxSChPMliV343IrVkpYdejUYq9w24Ot3FA==
dependencies:
graphql-tools "^4.0.4"
graphql-playground-html@1.6.12:
version "1.6.12"
resolved "https://registry.yarnpkg.com/graphql-playground-html/-/graphql-playground-html-1.6.12.tgz#8b3b34ab6013e2c877f0ceaae478fafc8ca91b85"
integrity sha512-yOYFwwSMBL0MwufeL8bkrNDgRE7eF/kTHiwrqn9FiR9KLcNIl1xw9l9a+6yIRZM56JReQOHpbQFXTZn1IuSKRg==
graphql-playground-middleware-express@1.7.11:
version "1.7.11"
resolved "https://registry.yarnpkg.com/graphql-playground-middleware-express/-/graphql-playground-middleware-express-1.7.11.tgz#bbffd784a37133bfa7165bdd8f429081dbf4bcf6"
integrity sha512-sKItB4s3FxqlwCgXdMfwRAfssSoo31bcFsGAAg/HzaZLicY6CDlofKXP8G5iPDerB6NaoAcAaBLutLzl9sd4fQ==
dependencies:
graphql-playground-html "1.6.12"
graphql-playground-middleware-lambda@1.7.12:
version "1.7.12"
resolved "https://registry.yarnpkg.com/graphql-playground-middleware-lambda/-/graphql-playground-middleware-lambda-1.7.12.tgz#1b06440a288dbcd53f935b43e5b9ca2738a06305"
integrity sha512-fJ1Y0Ck5ctmfaQFoWv7vNnVP7We19P3miVmOT85YPrjpzbMYv0wPfxm4Zjt8nnqXr0KU9nGW53tz3K7/Lvzxtw==
dependencies:
graphql-playground-html "1.6.12"
graphql-request@~1.8.2:
version "1.8.2"
resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-1.8.2.tgz#398d10ae15c585676741bde3fc01d5ca948f8fbe"
@ -3863,13 +3678,6 @@ graphql-shield@~6.0.3:
object-hash "^1.3.1"
yup "^0.27.0"
graphql-subscriptions@^0.5.8:
version "0.5.8"
resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-0.5.8.tgz#13a6143c546bce390404657dc73ca501def30aa7"
integrity sha512-0CaZnXKBw2pwnIbvmVckby5Ge5e2ecmjofhYCdyeACbCly2j3WXDP/pl+s+Dqd2GQFC7y99NB+53jrt55CKxYQ==
dependencies:
iterall "^1.2.1"
graphql-subscriptions@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/graphql-subscriptions/-/graphql-subscriptions-1.0.0.tgz#475267694b3bd465af6477dbab4263a3f62702b8"
@ -3893,7 +3701,7 @@ graphql-tools@^4.0.0, graphql-tools@^4.0.4:
iterall "^1.1.3"
uuid "^3.1.0"
graphql-upload@^8.0.0, graphql-upload@^8.0.2:
graphql-upload@^8.0.2:
version "8.0.7"
resolved "https://registry.yarnpkg.com/graphql-upload/-/graphql-upload-8.0.7.tgz#8644264e241529552ea4b3797e7ee15809cf01a3"
integrity sha512-gi2yygbDPXbHPC7H0PNPqP++VKSoNoJO4UrXWq4T0Bi4IhyUd3Ycop/FSxhx2svWIK3jdXR/i0vi91yR1aAF0g==
@ -3903,35 +3711,7 @@ graphql-upload@^8.0.0, graphql-upload@^8.0.2:
http-errors "^1.7.2"
object-path "^0.11.4"
graphql-yoga@~1.18.0:
version "1.18.0"
resolved "https://registry.yarnpkg.com/graphql-yoga/-/graphql-yoga-1.18.0.tgz#2668278e94a0bd1b2ff8c60f928c4e18d62e381a"
integrity sha512-WEibitQA2oFTmD7XBO8/ps8DWeVpkzOzgbB3EvtM2oIpyGhPCzRZYrC7OS9MmijvRwLRXsgHImHWUm82ZrIOWA==
dependencies:
"@types/cors" "^2.8.4"
"@types/express" "^4.11.1"
"@types/graphql" "^14.0.0"
"@types/graphql-deduplicator" "^2.0.0"
"@types/zen-observable" "^0.5.3"
apollo-server-express "^1.3.6"
apollo-server-lambda "1.3.6"
apollo-upload-server "^7.0.0"
aws-lambda "^0.1.2"
body-parser-graphql "1.1.0"
cors "^2.8.4"
express "^4.16.3"
graphql "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0"
graphql-deduplicator "^2.0.1"
graphql-import "^0.7.0"
graphql-middleware "3.0.2"
graphql-playground-middleware-express "1.7.11"
graphql-playground-middleware-lambda "1.7.12"
graphql-subscriptions "^0.5.8"
graphql-tools "^4.0.0"
graphql-upload "^8.0.0"
subscriptions-transport-ws "^0.9.8"
"graphql@^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0", graphql@^14.2.1, graphql@~14.4.2:
graphql@^14.2.1, graphql@~14.4.2:
version "14.4.2"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.4.2.tgz#553a7d546d524663eda49ed6df77577be3203ae3"
integrity sha512-6uQadiRgnpnSS56hdZUSvFrVcQ6OF9y6wkxJfKquFtHlnl7+KSuWwSJsdwiK1vybm1HgcdbpGkCpvhvsVQ0UZQ==
@ -4138,17 +3918,6 @@ http-errors@1.7.2, http-errors@^1.7.2, http-errors@~1.7.2:
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
http-errors@^1.7.0:
version "1.7.1"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.1.tgz#6a4ffe5d35188e1c39f872534690585852e1f027"
integrity sha512-jWEUgtZWGSMba9I1N3gc1HmvpBUaNC9vDdA46yScAdp+C5rdEuKWUBLWTQpW9FwSWSbYYs++b6SDCxf9UEJzfw==
dependencies:
depd "~1.1.2"
inherits "2.0.3"
setprototypeof "1.1.0"
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
@ -4165,16 +3934,6 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
dependencies:
safer-buffer ">= 2.1.2 < 3"
ieee754@1.1.8:
version "1.1.8"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
integrity sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=
ieee754@^1.1.4:
version "1.1.12"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"
integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==
ienoopen@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.1.0.tgz#411e5d530c982287dbdc3bb31e7a9c9e32630974"
@ -4241,7 +4000,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
@ -4535,11 +4294,6 @@ is-windows@^1.0.0, is-windows@^1.0.2:
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@ -4976,11 +4730,6 @@ jest@~24.8.0:
import-local "^2.0.0"
jest-cli "^24.8.0"
jmespath@0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=
joi@^13.7.0:
version "13.7.0"
resolved "https://registry.yarnpkg.com/joi/-/joi-13.7.0.tgz#cfd85ebfe67e8a1900432400b4d03bbd93fb879f"
@ -5359,7 +5108,7 @@ lodash@=3.10.1:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
integrity sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=
lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.14:
lodash@^4.13.1, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.5, lodash@~4.17.14:
version "4.17.14"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba"
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==
@ -5795,10 +5544,10 @@ node-releases@^1.1.19:
dependencies:
semver "^5.3.0"
nodemailer@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.2.1.tgz#20d773925eb8f7a06166a0b62c751dc8290429f3"
integrity sha512-TagB7iuIi9uyNgHExo8lUDq3VK5/B0BpbkcjIgNvxbtVrjNqq0DwAOTuzALPVkK76kMhTSzIgHqg8X1uklVs6g==
nodemailer@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.3.0.tgz#a89b0c62d3937bdcdeecbf55687bd7911b627e12"
integrity sha512-TEHBNBPHv7Ie/0o3HXnb7xrPSSQmH1dXwQKRaMKDBGt/ZN54lvDVujP6hKkO/vjkIYL9rK8kHSG11+G42Nhxuw==
nodemon@~1.19.1:
version "1.19.1"
@ -6458,11 +6207,6 @@ pump@^3.0.0:
end-of-stream "^1.1.0"
once "^1.3.1"
punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
@ -6483,11 +6227,6 @@ qs@~6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
querystring@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
range-parser@~1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
@ -6572,16 +6311,6 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2"
path-type "^3.0.0"
readable-stream@1.1.x:
version "1.1.14"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
isarray "0.0.1"
string_decoder "~0.10.x"
readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.3, readable-stream@^2.3.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
@ -6931,11 +6660,6 @@ sanitize-html@~1.20.1:
srcset "^1.0.0"
xtend "^4.0.1"
sax@1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a"
integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o=
sax@>=0.6.0, sax@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
@ -7035,11 +6759,6 @@ set-value@^2.0.0:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
setprototypeof@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
@ -7152,7 +6871,7 @@ source-map-resolve@^0.5.0:
source-map-url "^0.4.0"
urix "^0.1.0"
source-map-support@^0.5.1, source-map-support@^0.5.6, source-map-support@^0.5.9:
source-map-support@^0.5.6, source-map-support@^0.5.9:
version "0.5.9"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f"
integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==
@ -7358,11 +7077,6 @@ string_decoder@^1.1.1:
dependencies:
safe-buffer "~5.1.0"
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@ -7406,7 +7120,7 @@ strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
subscriptions-transport-ws@^0.9.11, subscriptions-transport-ws@^0.9.8:
subscriptions-transport-ws@^0.9.11:
version "0.9.15"
resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.15.tgz#68a8b7ba0037d8c489fb2f5a102d1494db297d0d"
integrity sha512-f9eBfWdHsePQV67QIX+VRhf++dn1adyC/PZHP6XI5AfKnZ4n0FW+v5omxwdHVpd4xq2ZijaHEcmlQrhBY79ZWQ==
@ -7837,14 +7551,6 @@ url-parse-lax@^1.0.0:
dependencies:
prepend-http "^1.0.1"
url@0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64"
integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=
dependencies:
punycode "1.3.2"
querystring "0.2.0"
use@^3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
@ -7880,11 +7586,6 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
uuid@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
integrity sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==
uuid@^3.1.0, uuid@^3.3.2, uuid@~3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
@ -8156,7 +7857,7 @@ xml-name-validator@^3.0.0:
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
xml2js@0.4.19, xml2js@^0.4.17:
xml2js@^0.4.17:
version "0.4.19"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==

View File

@ -22,16 +22,16 @@ Feature: Tags and Categories
When I navigate to the administration dashboard
And I click on the menu item "Categories"
Then I can see the following table:
| | Name | Posts |
| | Just For Fun | 2 |
| | Happyness & Values | 1 |
| | Health & Wellbeing | 0 |
| | Name | Posts |
| | Just For Fun | 2 |
| | Happyness & Values | 1 |
| | Health & Wellbeing | 0 |
Scenario: See an overview of tags
When I navigate to the administration dashboard
And I click on the menu item "Tags"
Then I can see the following table:
| | Name | Users | Posts |
| 1 | Democracy | 3 | 4 |
| 2 | Nature | 2 | 3 |
| 3 | Ecology | 1 | 1 |
| | Name | Users | Posts |
| 1 | Democracy | 3 | 4 |
| 2 | Nature | 2 | 3 |
| 3 | Ecology | 1 | 1 |

View File

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

View File

@ -4,14 +4,10 @@
data:
SMTP_HOST: "mailserver.human-connection"
SMTP_PORT: "25"
SMTP_USERNAME: ""
SMTP_PASSWORD: ""
GRAPHQL_PORT: "4000"
GRAPHQL_URI: "http://nitro-backend.human-connection:4000"
MOCKS: "false"
NEO4J_URI: "bolt://nitro-neo4j.human-connection:7687"
NEO4J_USERNAME: "neo4j"
NEO4J_PASSWORD: "neo4j"
NEO4J_AUTH: "none"
CLIENT_URI: "https://nitro-staging.human-connection.org"
metadata:

View File

@ -5,11 +5,10 @@ data:
MONGODB_PASSWORD: "TU9OR09EQl9QQVNTV09SRA=="
PRIVATE_KEY_PASSPHRASE: "YTdkc2Y3OHNhZGc4N2FkODdzZmFnc2FkZzc4"
MAPBOX_TOKEN: "cGsuZXlKMUlqb2lhSFZ0WVc0dFkyOXVibVZqZEdsdmJpSXNJbUVpT2lKamFqbDBjbkJ1Ykdvd2VUVmxNM1Z3WjJsek5UTnVkM1p0SW4wLktaOEtLOWw3MG9talhiRWtrYkhHc1EK"
SMTP_HOST:
SMTP_PORT: 587
SMTP_USERNAME:
SMTP_PASSWORD:
SMTP_IGNORE_TLS:
NEO4J_USERNAME:
NEO4J_PASSWORD:
metadata:
name: human-connection
namespace: human-connection

View File

@ -101,7 +101,7 @@ ON CREATE SET
u.name = user.name,
u.slug = user.slug,
u.email = user.email,
u.password = user.password,
u.encryptedPassword = user.password,
u.avatar = replace(user.avatar, 'https://api-alpha.human-connection.org', ''),
u.coverImg = replace(user.coverImg, 'https://api-alpha.human-connection.org', ''),
u.wasInvited = user.wasInvited,

View File

@ -26,9 +26,4 @@ services:
ports:
- 4001:4001
- 4123:4123
neo4j:
environment:
- NEO4J_AUTH=none
ports:
- 7687:7687
- 7474:7474

View File

@ -12,6 +12,7 @@ services:
networks:
- hc-network
environment:
- NUXT_BUILD=.nuxt-dist
- HOST=0.0.0.0
- GRAPHQL_URI=http://backend:4000
- MAPBOX_TOKEN="pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.bZ8KK9l70omjXbEkkbHGsQ"

View File

@ -24,7 +24,7 @@
"cross-env": "^5.2.0",
"cypress": "^3.4.0",
"cypress-cucumber-preprocessor": "^1.12.0",
"cypress-file-upload": "^3.2.1",
"cypress-file-upload": "^3.3.1",
"cypress-plugin-retries": "^1.2.2",
"dotenv": "^8.0.0",
"faker": "Marak/faker.js#master",

2
webapp/.gitignore vendored
View File

@ -61,6 +61,8 @@ typings/
# nuxt.js build output
.nuxt
# also the build output in docker container
.nuxt-dist
# Nuxt generate
dist

View File

@ -27,7 +27,7 @@
</template>
<script>
import gql from 'graphql-tag'
import CategoryQuery from '~/graphql/CategoryQuery.js'
export default {
props: {
@ -85,13 +85,7 @@ export default {
apollo: {
Category: {
query() {
return gql(`{
Category {
id
name
icon
}
}`)
return CategoryQuery()
},
result(result) {
this.categories = result.data.Category

View File

@ -0,0 +1,134 @@
import { mount, createLocalVue } from '@vue/test-utils'
import VTooltip from 'v-tooltip'
import Styleguide from '@human-connection/styleguide'
import Vuex from 'vuex'
import FilterPosts from './FilterPosts.vue'
import FilterPostsMenuItem from './FilterPostsMenuItems.vue'
import { mutations } from '~/store/posts'
const localVue = createLocalVue()
localVue.use(Styleguide)
localVue.use(VTooltip)
localVue.use(Vuex)
describe('FilterPosts.vue', () => {
let wrapper
let mocks
let propsData
let menuToggle
let allCategoriesButton
let environmentAndNatureButton
let consumptionAndSustainabiltyButton
let democracyAndPoliticsButton
beforeEach(() => {
mocks = {
$apollo: {
query: jest
.fn()
.mockResolvedValueOnce({
data: { Post: { title: 'Post with Category', category: [{ id: 'cat4' }] } },
})
.mockRejectedValue({ message: 'We were unable to filter' }),
},
$t: jest.fn(),
$i18n: {
locale: () => 'en',
},
$toast: {
error: jest.fn(),
},
}
propsData = {
categories: [
{ id: 'cat4', name: 'Environment & Nature', icon: 'tree' },
{ id: 'cat15', name: 'Consumption & Sustainability', icon: 'shopping-cart' },
{ id: 'cat9', name: 'Democracy & Politics', icon: 'university' },
],
}
})
describe('mount', () => {
const store = new Vuex.Store({
mutations: {
'posts/SET_POSTS': mutations.SET_POSTS,
},
})
const Wrapper = () => {
return mount(FilterPosts, { mocks, localVue, propsData, store })
}
beforeEach(() => {
wrapper = Wrapper()
menuToggle = wrapper.findAll('a').at(0)
menuToggle.trigger('click')
})
it('groups the categories by pair', () => {
expect(wrapper.vm.chunk).toEqual([
[
{ id: 'cat4', name: 'Environment & Nature', icon: 'tree' },
{ id: 'cat15', name: 'Consumption & Sustainability', icon: 'shopping-cart' },
],
[{ id: 'cat9', name: 'Democracy & Politics', icon: 'university' }],
])
})
it('starts with all categories button active', () => {
allCategoriesButton = wrapper.findAll('button').at(0)
expect(allCategoriesButton.attributes().class).toContain('ds-button-primary')
})
it('adds a categories id to selectedCategoryIds when clicked', () => {
environmentAndNatureButton = wrapper.findAll('button').at(1)
environmentAndNatureButton.trigger('click')
const filterPostsMenuItem = wrapper.find(FilterPostsMenuItem)
expect(filterPostsMenuItem.vm.selectedCategoryIds).toEqual(['cat4'])
})
it('sets primary to true when the button is clicked', () => {
democracyAndPoliticsButton = wrapper.findAll('button').at(3)
democracyAndPoliticsButton.trigger('click')
expect(democracyAndPoliticsButton.attributes().class).toContain('ds-button-primary')
})
it('queries a post by its categories', () => {
consumptionAndSustainabiltyButton = wrapper.findAll('button').at(2)
consumptionAndSustainabiltyButton.trigger('click')
expect(mocks.$apollo.query).toHaveBeenCalledWith(
expect.objectContaining({
variables: {
filter: { categories_some: { id_in: ['cat15'] } },
first: expect.any(Number),
offset: expect.any(Number),
},
}),
)
})
it('supports a query of multiple categories', () => {
environmentAndNatureButton = wrapper.findAll('button').at(1)
environmentAndNatureButton.trigger('click')
consumptionAndSustainabiltyButton = wrapper.findAll('button').at(2)
consumptionAndSustainabiltyButton.trigger('click')
expect(mocks.$apollo.query).toHaveBeenCalledWith(
expect.objectContaining({
variables: {
filter: { categories_some: { id_in: ['cat4', 'cat15'] } },
first: expect.any(Number),
offset: expect.any(Number),
},
}),
)
})
it('toggles the categoryIds when clicked more than once', () => {
environmentAndNatureButton = wrapper.findAll('button').at(1)
environmentAndNatureButton.trigger('click')
environmentAndNatureButton.trigger('click')
const filterPostsMenuItem = wrapper.find(FilterPostsMenuItem)
expect(filterPostsMenuItem.vm.selectedCategoryIds).toEqual([])
})
})
})

View File

@ -0,0 +1,61 @@
<template>
<dropdown ref="menu" :placement="placement" :offset="offset">
<a slot="default" slot-scope="{ toggleMenu }" href="#" @click.prevent="toggleMenu()">
<ds-icon style="margin: 12px 0px 0px 10px;" name="filter" size="large" />
<ds-icon style="margin: 7px 0px 0px 2px" size="xx-small" name="angle-down" />
</a>
<template slot="popover">
<filter-posts-menu-items :chunk="chunk" @filterPosts="filterPosts" />
</template>
</dropdown>
</template>
<script>
import _ from 'lodash'
import Dropdown from '~/components/Dropdown'
import { filterPosts } from '~/graphql/PostQuery.js'
import { mapMutations } from 'vuex'
import FilterPostsMenuItems from '~/components/FilterPosts/FilterPostsMenuItems'
export default {
components: {
Dropdown,
FilterPostsMenuItems,
},
props: {
placement: { type: String },
offset: { type: [String, Number] },
categories: { type: Array, default: () => [] },
},
data() {
return {
pageSize: 12,
}
},
computed: {
chunk() {
return _.chunk(this.categories, 2)
},
},
methods: {
...mapMutations({
setPosts: 'posts/SET_POSTS',
}),
filterPosts(categoryIds) {
const filter = categoryIds.length ? { categories_some: { id_in: categoryIds } } : {}
this.$apollo
.query({
query: filterPosts(this.$i18n),
variables: {
filter: filter,
first: this.pageSize,
offset: 0,
},
})
.then(({ data: { Post } }) => {
this.setPosts(Post)
})
.catch(error => this.$toast.error(error.message))
},
},
}
</script>

View File

@ -0,0 +1,126 @@
<template>
<ds-container>
<ds-space />
<ds-flex id="filter-posts-header">
<ds-heading tag="h4">{{ $t('filter-posts.header') }}</ds-heading>
<ds-space margin-bottom="large" />
</ds-flex>
<ds-flex>
<ds-flex-item
:width="{ base: '100%', sm: '100%', md: '100%', lg: '5%' }"
class="categories-menu-item"
>
<ds-flex>
<ds-flex-item width="10%" />
<ds-flex-item width="100%">
<ds-button
icon="check"
@click.stop.prevent="toggleCategory()"
:primary="allCategories"
/>
<ds-flex-item>
<label class="category-labels">{{ $t('filter-posts.all') }}</label>
</ds-flex-item>
<ds-space />
</ds-flex-item>
</ds-flex>
</ds-flex-item>
<ds-flex-item :width="{ base: '0%', sm: '0%', md: '0%', lg: '4%' }" />
<ds-flex-item
:width="{ base: '0%', sm: '0%', md: '0%', lg: '3%' }"
id="categories-menu-divider"
/>
<ds-flex-item
:width="{ base: '50%', sm: '50%', md: '50%', lg: '11%' }"
v-for="index in chunk.length"
:key="index"
>
<ds-flex v-for="category in chunk[index - 1]" :key="category.id" class="categories-menu">
<ds-flex class="categories-menu">
<ds-flex-item width="100%" class="categories-menu-item">
<ds-button
:icon="category.icon"
:primary="isActive(category.id)"
@click.stop.prevent="toggleCategory(category.id)"
/>
<ds-space margin-bottom="small" />
</ds-flex-item>
<ds-flex>
<ds-flex-item class="categories-menu-item">
<label class="category-labels">{{ category.name }}</label>
</ds-flex-item>
<ds-space margin-bottom="xx-large" />
</ds-flex>
</ds-flex>
</ds-flex>
</ds-flex-item>
</ds-flex>
</ds-container>
</template>
<script>
export default {
props: {
chunk: { type: Array, default: () => [] },
},
data() {
return {
selectedCategoryIds: [],
allCategories: true,
}
},
methods: {
isActive(id) {
const index = this.selectedCategoryIds.indexOf(id)
if (index > -1) {
return true
}
return false
},
toggleCategory(id) {
if (!id) {
this.selectedCategoryIds = []
this.allCategories = true
} else {
const index = this.selectedCategoryIds.indexOf(id)
if (index > -1) {
this.selectedCategoryIds.splice(index, 1)
} else {
this.selectedCategoryIds.push(id)
}
this.allCategories = false
}
this.$emit('filterPosts', this.selectedCategoryIds)
},
},
}
</script>
<style lang="scss">
#filter-posts-header {
display: block;
}
.categories-menu-item {
text-align: center;
}
.categories-menu {
justify-content: center;
}
.category-labels {
font-size: $font-size-small;
}
@media only screen and (min-width: 960px) {
#categories-menu-divider {
border-left: 1px solid $border-color-soft;
margin: 9px 0px 40px 0px;
}
}
@media only screen and (max-width: 960px) {
#filter-posts-header {
text-align: center;
}
}
</style>

View File

@ -2,7 +2,7 @@
<ds-button v-if="totalNotifications <= 0" class="notifications-menu" disabled icon="bell">
{{ totalNotifications }}
</ds-button>
<dropdown v-else class="notifications-menu">
<dropdown v-else class="notifications-menu" :placement="placement">
<template slot="default" slot-scope="{ toggleMenu }">
<ds-button primary icon="bell" @click.prevent="toggleMenu">
{{ totalNotifications }}
@ -95,6 +95,9 @@ export default {
NotificationList,
Dropdown,
},
props: {
placement: { type: String },
},
computed: {
totalNotifications() {
return (this.notifications || []).length

View File

@ -0,0 +1,11 @@
import gql from 'graphql-tag'
export default () => {
return gql(`{
Category {
id
name
icon
}
}`)
}

View File

@ -75,3 +75,48 @@ export default i18n => {
}
`)
}
export const filterPosts = i18n => {
const lang = i18n.locale().toUpperCase()
return gql(`
query Post($filter: _PostFilter, $first: Int, $offset: Int) {
Post(filter: $filter, first: $first, offset: $offset) {
id
title
contentExcerpt
createdAt
disabled
deleted
slug
image
author {
id
avatar
slug
name
disabled
deleted
contributionsCount
shoutedCount
commentsCount
followedByCount
followedByCurrentUser
location {
name: name${lang}
}
badges {
id
icon
}
}
commentsCount
categories {
id
name
icon
}
shoutedCount
}
}
`)
}

View File

@ -3,14 +3,24 @@
<div class="main-navigation">
<ds-container class="main-navigation-container" style="padding: 10px 10px;">
<div>
<ds-flex>
<ds-flex-item :width="{ base: '49px', md: '150px' }">
<nuxt-link to="/">
<ds-flex class="main-navigation-flex">
<ds-flex-item :width="{ lg: '3.5%' }" />
<ds-flex-item :width="{ base: '80%', sm: '80%', md: '80%', lg: '15%' }">
<a @click="redirectToRoot">
<ds-logo />
</nuxt-link>
</a>
</ds-flex-item>
<ds-flex-item>
<div id="nav-search-box" v-on:click="unfolded" @blur.capture="foldedup">
<ds-flex-item
:width="{ base: '20%', sm: '20%', md: '20%', lg: '0%' }"
class="mobile-hamburger-menu"
>
<ds-button icon="bars" @click="toggleMobileMenuView" right />
</ds-flex-item>
<ds-flex-item
:width="{ base: '85%', sm: '85%', md: '50%', lg: '50%' }"
:class="{ 'hide-mobile-menu': !toggleMobileMenu }"
>
<div id="nav-search-box">
<search-input
id="nav-search"
:delay="300"
@ -22,17 +32,36 @@
/>
</div>
</ds-flex-item>
<ds-flex-item width="200px" style="background-color:white">
<div class="main-navigation-right" style="float:right">
<ds-flex-item
:width="{ base: '15%', sm: '15%', md: '10%', lg: '10%' }"
:class="{ 'hide-mobile-menu': !toggleMobileMenu }"
>
<no-ssr>
<filter-posts placement="top-start" offset="8" :categories="categories" />
</no-ssr>
</ds-flex-item>
<ds-flex-item :width="{ base: '100%', sm: '100%', md: '10%', lg: '2%' }" />
<ds-flex-item
:width="{ base: '100%', sm: '100%', md: '100%', lg: '13%' }"
style="background-color:white"
:class="{ 'hide-mobile-menu': !toggleMobileMenu }"
>
<div
class="main-navigation-right"
:class="{
'desktop-view': !toggleMobileMenu,
'hide-mobile-menu': !toggleMobileMenu,
}"
>
<no-ssr>
<locale-switch class="topbar-locale-switch" placement="bottom" offset="23" />
<locale-switch class="topbar-locale-switch" placement="top" offset="8" />
</no-ssr>
<template v-if="isLoggedIn">
<no-ssr>
<notification-menu />
<notification-menu placement="top" />
</no-ssr>
<no-ssr>
<dropdown class="avatar-menu">
<dropdown class="avatar-menu" offset="8">
<template slot="default" slot-scope="{ toggleMenu }">
<a
class="avatar-menu-trigger"
@ -118,6 +147,8 @@ import NotificationMenu from '~/components/notifications/NotificationMenu'
import Dropdown from '~/components/Dropdown'
import HcAvatar from '~/components/Avatar/Avatar.vue'
import seo from '~/mixins/seo'
import FilterPosts from '~/components/FilterPosts/FilterPosts.vue'
import CategoryQuery from '~/graphql/CategoryQuery.js'
export default {
components: {
@ -127,11 +158,14 @@ export default {
Modal,
NotificationMenu,
HcAvatar,
FilterPosts,
},
mixins: [seo],
data() {
return {
mobileSearchVisible: false,
toggleMobileMenu: false,
categories: [],
}
},
computed: {
@ -180,10 +214,16 @@ export default {
return routes
},
},
watch: {
Category(category) {
this.categories = category || []
},
},
methods: {
...mapActions({
quickSearchClear: 'search/quickClear',
quickSearch: 'search/quickSearch',
fetchPosts: 'posts/fetchPosts',
}),
goToPost(item) {
this.$nextTick(() => {
@ -200,23 +240,24 @@ export default {
}
return this.$route.path.indexOf(url) === 0
},
unfolded: function() {
document.getElementById('nav-search-box').classList.add('unfolded')
toggleMobileMenuView() {
this.toggleMobileMenu = !this.toggleMobileMenu
},
foldedup: function() {
document.getElementById('nav-search-box').classList.remove('unfolded')
redirectToRoot() {
this.$router.replace('/')
this.fetchPosts({ i18n: this.$i18n, filter: {} })
},
},
apollo: {
Category: {
query() {
return CategoryQuery()
},
fetchPolicy: 'cache-and-network',
},
},
}
</script>
<style>
.unfolded {
position: absolute;
right: 0px;
left: 0px;
z-index: 1;
}
</style>
<style lang="scss">
.topbar-locale-switch {
@ -228,7 +269,7 @@ export default {
.main-container {
padding-top: 6rem;
padding-botton: 5rem;
padding-bottom: 5rem;
}
.main-navigation {
@ -242,6 +283,14 @@ export default {
flex: 1;
}
.main-navigation-right .desktop-view {
float: right;
}
.avatar-menu {
margin: 2px 0px 0px 5px;
}
.avatar-menu-trigger {
user-select: none;
display: flex;
@ -285,6 +334,24 @@ export default {
}
}
}
@media only screen and (min-width: 960px) {
.mobile-hamburger-menu {
display: none;
}
}
@media only screen and (max-width: 960px) {
#nav-search-box,
.main-navigation-right {
margin: 10px 0px;
}
.hide-mobile-menu {
display: none;
}
}
.ds-footer {
text-align: center;
position: fixed;

View File

@ -4,6 +4,10 @@
"hashtag-search": "Suche nach #{hashtag}",
"clearSearch": "Suche löschen"
},
"filter-posts": {
"header": "Themenkategorien",
"all": "Alle"
},
"site": {
"made": "Mit &#10084; gemacht",
"imprint": "Impressum",
@ -188,7 +192,19 @@
"name": "Organisationen"
},
"users": {
"name": "Benutzer"
"name": "Benutzer",
"form": {
"placeholder": "E-Mail, Name oder Beschreibung"
},
"table": {
"columns": {
"name": "Name",
"slug": "Slug",
"role": "Rolle",
"createdAt": "Erstellt am"
}
},
"empty": "Keine Benutzer gefunden"
},
"pages": {
"name": "Seiten"
@ -396,5 +412,4 @@
"terms": {
"text": "<div ><ol><li><strong>UNFALLGEFAHR: </strong>Das ist eine Testversion! Alle Daten, Dein Profil und die Server können jederzeit komplett vernichtet, verloren, verbrannt und vielleicht auch in der Nähe von Alpha Centauri synchronisiert werden. Die Benutzung läuft auf eigene Gefahr. Mit kommerziellen Nebenwirkungen ist jedoch nicht zu rechnen.</li><br><li><strong>DU UND DEINE DATEN: </strong>Bitte beachte, dass wir die Inhalte der Alphaversion zu Werbezwecken, Webpräsentationen usw. verwenden, aber wir glauben, dass das auch in Deinem Interesse ist. Am besten keinen Nachnamen eingeben und bei noch mehr Datensparsamkeit ein Profilfoto ohne Identität verwenden. Mehr in unserer <a href='/pages/privacy' target='_blank'>Datenschutzerklärung</a>.</li><br><li><strong>BAUSTELLEN: </strong>Das ist immer noch eine Testversion. Wenn etwas nicht funktioniert, blockiert, irritiert, falsch angezeigt, verbogen oder nicht anklickbar ist, bitten wir dies zu entschuldigen. Fehler, Käfer und Bugs bitte melden! <a href='http://localhost:3000/%22https://human-connection.org/alpha/#bugreport%5C%22' target='_blank'>https://human-connection.org/support</a></li><br><li><strong>VERHALTENSCODEX</strong>: Die Verhaltensregeln dienen als Leitsätze für den persönlichen Auftritt und den Umgang untereinander. Wer als Nutzer im Human Connection Netzwerk aktiv ist, Beiträge verfasst, kommentiert oder mit anderen Nutzern, auch außerhalb des Netzwerkes, Kontakt aufnimmt, erkennt diese Verhaltensregeln als verbindlich an: <a href='https://alpha.human-connection.org/pages/code-of-conduct' target='_blank'>https://alpha.human-connection.org/pages/code-of-conduct</a></li><br><li><strong>MODERATION: </strong>Solange kein Community-Moderationssystem lauffähig ist, entscheidet ein Regenbogen-Einhorn darüber, ob Du körperlich und psychisch stabil genug bist, unsere Testversion zu bedienen. Das Einhorn kann Dich jederzeit von der Alpha entfernen. Also sei nett und lass Regenbogenfutter da!</li><br><li><strong>FAIRNESS: </strong>Sollte Dir die Alphaversion unseres Netzwerks wider Erwarten, egal aus welchen Gründen, nicht gefallen, überweisen wir Dir Deine gespendeten Monatsbeiträge innerhalb der ersten 2 Monate gerne zurück. Einfach Mail an: <a href='mailto:info@human-connection.org' target='_blank'>info@human-connection.org </a><strong>Achtung: Viele Funktionen werden erst nach und nach eingebaut. </strong></li><br><li><strong>FRAGEN?</strong> Die Termine und Links zu den Zoom-Räumen findest Du hier: <a href='http://localhost:3000/%22https://human-connection.org/events-und-news//%22' target='_blank'>https://human-connection.org/veranstaltungen/</a></li><br><li><strong>VON MENSCHEN FÜR MENSCHEN: </strong>Bitte hilf uns weitere monatlichen Spender für Human Connection zu bekommen, damit das Netzwerk so schnell wie möglich offiziell an den Start gehen kann. <a href='http://localhost:3000/%22https://human-connection.org/alpha/#bugreport%5C%22' target='_blank'>https://human-connection.org</a></li></ol><p>Jetzt aber viel Spaß mit der Alpha von Human Connection! Für den ersten Weltfrieden. ♥︎</p><br><p><strong>Herzlichst,</strong></p><p><strong>Euer Human Connection Team</strong></p></div>"
}
}

View File

@ -4,6 +4,10 @@
"hashtag-search": "Searching for #{hashtag}",
"clearSearch": "Clear search"
},
"filter-posts": {
"header": "Categories of Content",
"all": "All"
},
"site": {
"made": "Made with &#10084;",
"imprint": "Imprint",
@ -50,8 +54,8 @@
"email-exists": "There is already a user account with this email address!",
"invalid-invitation-token": "It looks like as if the invitation has been used already. Invitation links can only be used once."
},
"submit": "Create an account",
"success": "A mail with a link to complete your registration has been sent to <b>{email}</b>"
"submit": "Create an account",
"success": "A mail with a link to complete your registration has been sent to <b>{email}</b>"
}
},
"create-user-account": {
@ -189,7 +193,19 @@
"name": "Organizations"
},
"users": {
"name": "Users"
"name": "Users",
"form": {
"placeholder": "E-Mail, name or description"
},
"table": {
"columns": {
"name": "Name",
"slug": "Slug",
"role": "Role",
"createdAt": "Created at"
}
},
"empty": "No users found"
},
"pages": {
"name": "Pages"
@ -245,7 +261,6 @@
"more": "show more",
"less": "show less"
}
},
"quotes": {
"african": {

View File

@ -10,7 +10,10 @@ const styleguideStyles = process.env.STYLEGUIDE_DEV
]
: '@human-connection/styleguide/dist/shared.scss'
const buildDir = process.env.NUXT_BUILD || '.nuxt'
module.exports = {
buildDir,
mode: 'universal',
dev: dev,

View File

@ -29,7 +29,6 @@
"!**/?(*.)+(spec|test).js?(x)"
],
"coverageReporters": [
"text",
"lcov"
],
"transform": {
@ -63,8 +62,9 @@
"date-fns": "2.0.0-beta.2",
"express": "~4.17.1",
"graphql": "~14.4.2",
"isemail": "^3.2.0",
"jsonwebtoken": "~8.5.1",
"linkify-it": "~2.1.0",
"linkify-it": "~2.2.0",
"nuxt": "~2.8.1",
"nuxt-dropzone": "^1.0.2",
"nuxt-env": "~0.1.0",
@ -95,7 +95,7 @@
"eslint-config-standard": "~12.0.0",
"eslint-loader": "~2.2.1",
"eslint-plugin-import": "~2.18.0",
"eslint-plugin-jest": "~22.7.2",
"eslint-plugin-jest": "~22.8.0",
"eslint-plugin-node": "~9.1.0",
"eslint-plugin-prettier": "~3.1.0",
"eslint-plugin-promise": "~4.2.1",
@ -111,4 +111,4 @@
"vue-jest": "~3.0.4",
"vue-svg-loader": "~0.12.0"
}
}
}

View File

@ -24,11 +24,10 @@ export default {
name: this.$t('admin.dashboard.name'),
path: `/admin`,
},
// TODO implement
/* {
{
name: this.$t('admin.users.name'),
path: `/admin/users`
}, */
path: `/admin/users`,
},
// TODO implement
/* {
name: this.$t('admin.organizations.name'),

View File

@ -0,0 +1,70 @@
import { mount, createLocalVue } from '@vue/test-utils'
import Users from './users.vue'
import Styleguide from '@human-connection/styleguide'
const localVue = createLocalVue()
localVue.use(Styleguide)
describe('Users', () => {
let wrapper
let Wrapper
let mocks
beforeEach(() => {
mocks = {
$t: jest.fn(),
$apollo: {
loading: false,
},
}
})
describe('mount', () => {
Wrapper = () => {
return mount(Users, {
mocks,
localVue,
})
}
it('renders', () => {
wrapper = Wrapper()
expect(wrapper.is('div')).toBe(true)
})
describe('search', () => {
let searchAction
beforeEach(() => {
searchAction = (wrapper, { query }) => {
wrapper.find('input').setValue(query)
wrapper.find('form').trigger('submit')
return wrapper
}
})
describe('query looks like an email address', () => {
it('searches users for exact email address', async () => {
const wrapper = await searchAction(Wrapper(), { query: 'email@example.org' })
expect(wrapper.vm.email).toEqual('email@example.org')
expect(wrapper.vm.filter).toBe(null)
})
})
describe('query is just text', () => {
it('tries to find matching users by `name`, `slug` or `about`', async () => {
const wrapper = await searchAction(await Wrapper(), { query: 'Find me' })
const expected = {
OR: [
{ name_contains: 'Find me' },
{ slug_contains: 'Find me' },
{ about_contains: 'Find me' },
],
}
expect(wrapper.vm.email).toBe(null)
expect(wrapper.vm.filter).toEqual(expected)
})
})
})
})
})

View File

@ -1,15 +1,173 @@
<template>
<ds-card :header="$t('admin.users.name')">
<hc-empty icon="tasks" message="Coming Soon…" />
</ds-card>
<div>
<ds-space>
<ds-card :header="$t('admin.users.name')">
<ds-form v-model="form" @submit="submit">
<ds-flex gutter="small">
<ds-flex-item width="90%">
<ds-input
model="query"
:placeholder="$t('admin.users.form.placeholder')"
icon="search"
/>
</ds-flex-item>
<ds-flex-item width="30px">
<ds-button primary type="submit" icon="search" :loading="$apollo.loading" />
</ds-flex-item>
</ds-flex>
</ds-form>
</ds-card>
</ds-space>
<ds-card v-if="User && User.length">
<ds-table :data="User" :fields="fields" condensed>
<template slot="index" slot-scope="scope">
{{ scope.row.index }}.
</template>
<template slot="name" slot-scope="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 slot="slug" slot-scope="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 slot="createdAt" slot-scope="scope">
{{ scope.row.createdAt | dateTime }}
</template>
</ds-table>
<ds-flex direction="row-reverse">
<ds-flex-item width="50px">
<ds-button @click="next" :disabled="!hasNext" icon="arrow-right" primary />
</ds-flex-item>
<ds-flex-item width="50px">
<ds-button @click="back" :disabled="!hasPrevious" icon="arrow-left" primary />
</ds-flex-item>
</ds-flex>
</ds-card>
<ds-card v-else>
<ds-placeholder>
{{ $t('admin.users.empty') }}
</ds-placeholder>
</ds-card>
</div>
</template>
<script>
import HcEmpty from '~/components/Empty.vue'
import gql from 'graphql-tag'
import isemail from 'isemail'
export default {
components: {
HcEmpty,
data() {
const pageSize = 15
return {
offset: 0,
pageSize,
first: pageSize,
User: [],
hasNext: false,
email: null,
filter: null,
form: {
formData: {
query: '',
},
},
}
},
computed: {
hasPrevious() {
return this.offset > 0
},
fields() {
return {
index: '#',
name: this.$t('admin.users.table.columns.name'),
slug: this.$t('admin.users.table.columns.slug'),
createdAt: this.$t('admin.users.table.columns.createdAt'),
contributionsCount: {
label: '🖉',
align: 'right',
},
commentedCount: {
label: '🗨',
align: 'right',
},
shoutedCount: {
label: '❤',
align: 'right',
},
role: {
label: this.$t('admin.users.table.columns.role'),
align: 'right',
},
}
},
},
apollo: {
User: {
query() {
return gql(`
query($filter: _UserFilter, $first: Int, $offset: Int, $email: String) {
User(email: $email, filter: $filter, first: $first, offset: $offset, orderBy: createdAt_desc) {
id
name
slug
role
createdAt
contributionsCount
commentedCount
shoutedCount
}
}
`)
},
variables() {
const { offset, first, email, filter } = this
const variables = { first, offset }
if (email) variables.email = email
if (filter) variables.filter = filter
return variables
},
update({ User }) {
if (!User) return []
this.hasNext = User.length >= this.pageSize
if (User.length <= 0 && this.offset > 0) return this.User // edge case, avoid a blank page
return User.map((u, i) => Object.assign({}, u, { index: this.offset + i }))
},
},
},
methods: {
back() {
this.offset = Math.max(this.offset - this.pageSize, 0)
},
next() {
this.offset += this.pageSize
},
submit(formData) {
this.offset = 0
const { query } = formData
if (isemail.validate(query)) {
this.email = query
this.filter = null
} else {
this.email = null
this.filter = {
OR: [{ name_contains: query }, { slug_contains: query }, { about_contains: query }],
}
}
},
},
}
</script>

View File

@ -10,7 +10,7 @@
/>
</ds-flex-item>
<hc-post-card
v-for="(post, index) in uniq(Post)"
v-for="(post, index) in posts"
:key="post.id"
:post="post"
:width="{ base: '100%', xs: '100%', md: '50%', xl: '33%' }"
@ -33,11 +33,11 @@
<script>
import FilterMenu from '~/components/FilterMenu/FilterMenu.vue'
import gql from 'graphql-tag'
import uniqBy from 'lodash/uniqBy'
import HcPostCard from '~/components/PostCard'
import HcLoadMore from '~/components/LoadMore.vue'
import { mapGetters } from 'vuex'
import { mapGetters, mapMutations } from 'vuex'
import { filterPosts } from '~/graphql/PostQuery.js'
export default {
components: {
@ -49,7 +49,6 @@ export default {
const { hashtag = null } = this.$route.query
return {
// Initialize your apollo data
Post: [],
page: 1,
pageSize: 12,
filter: {},
@ -61,18 +60,27 @@ export default {
this.changeFilterBubble({ tags_some: { name: this.hashtag } })
}
},
watch: {
Post(post) {
this.setPosts(this.Post)
},
},
computed: {
...mapGetters({
currentUser: 'auth/user',
posts: 'posts/posts',
}),
tags() {
return this.Post ? this.Post[0].tags.map(tag => tag.name) : '-'
return this.posts ? this.posts.tags.map(tag => tag.name) : '-'
},
offset() {
return (this.page - 1) * this.pageSize
},
},
methods: {
...mapMutations({
setPosts: 'posts/SET_POSTS',
}),
changeFilterBubble(filter) {
if (this.hashtag) {
filter = {
@ -129,47 +137,7 @@ export default {
apollo: {
Post: {
query() {
return gql(`
query Post($filter: _PostFilter, $first: Int, $offset: Int) {
Post(filter: $filter, first: $first, offset: $offset) {
id
title
contentExcerpt
createdAt
disabled
deleted
slug
image
author {
id
avatar
slug
name
disabled
deleted
contributionsCount
shoutedCount
commentsCount
followedByCount
followedByCurrentUser
location {
name: name${this.$i18n.locale().toUpperCase()}
}
badges {
id
icon
}
}
commentsCount
categories {
id
name
icon
}
shoutedCount
}
}
`)
return filterPosts(this.$i18n)
},
variables() {
return {

View File

@ -206,7 +206,7 @@
:key="post.id"
:post="post"
:width="{ base: '100%', md: '100%', xl: '50%' }"
@removePostFromList="activePosts.splice(index, 1)"
@removePostFromList="removePostFromList(index)"
/>
</template>
<template v-else-if="$apollo.loading">
@ -331,6 +331,10 @@ export default {
},
},
methods: {
removePostFromList(index) {
this.activePosts.splice(index, 1)
this.$apollo.queries.User.refetch()
},
handleTab(tab) {
this.tabActive = tab
this.Post = null

76
webapp/store/posts.js Normal file
View File

@ -0,0 +1,76 @@
import gql from 'graphql-tag'
export const state = () => {
return {
posts: [],
}
}
export const mutations = {
SET_POSTS(state, posts) {
state.posts = posts || null
},
}
export const getters = {
posts(state) {
return state.posts || []
},
}
export const actions = {
async fetchPosts({ commit, dispatch }, { i18n, filter }) {
const client = this.app.apolloProvider.defaultClient
const {
data: { Post },
} = await client.query({
query: gql(`
query Post($filter: _PostFilter, $first: Int, $offset: Int) {
Post(filter: $filter, first: $first, offset: $offset) {
id
title
contentExcerpt
createdAt
disabled
deleted
slug
image
author {
id
avatar
slug
name
disabled
deleted
contributionsCount
shoutedCount
commentsCount
followedByCount
followedByCurrentUser
location {
name: name${i18n.locale().toUpperCase()}
}
badges {
id
icon
}
}
commentsCount
categories {
id
name
icon
}
shoutedCount
}
}`),
variables: {
filter,
first: 12,
offset: 0,
},
})
commit('SET_POSTS', Post)
return Post
},
}

View File

@ -4320,10 +4320,10 @@ eslint-plugin-import@~2.18.0:
read-pkg-up "^2.0.0"
resolve "^1.11.0"
eslint-plugin-jest@~22.7.2:
version "22.7.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.7.2.tgz#7ab118a66a34e46ae5e16a128b5d24fd28b43dca"
integrity sha512-Aecqe3ulBVI7amgOycVI8ZPL8o0SnGHOf3zn2/Ciu8TXyXDHcjtwD3hOs3ss/Qh/VAwlW/DMcuiXg5btgF+XMA==
eslint-plugin-jest@~22.8.0:
version "22.8.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.8.0.tgz#242ef5459e8da25d2c41438e95eb546e03d7fae1"
integrity sha512-2VftZMfILmlhL3VMq5ptHRIuyyXb3ShDEDb1J1UjvWNzm4l+UK/YmwNuTuJcM0gv8pJuOfiR/8ZptJ8Ou68pFw==
eslint-plugin-node@~9.1.0:
version "9.1.0"
@ -6047,6 +6047,13 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isemail@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c"
integrity sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==
dependencies:
punycode "2.x.x"
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@ -6777,10 +6784,10 @@ levn@^0.3.0, levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
linkify-it@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.1.0.tgz#c4caf38a6cd7ac2212ef3c7d2bde30a91561f9db"
integrity sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg==
linkify-it@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf"
integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==
dependencies:
uc.micro "^1.0.1"
@ -9173,16 +9180,16 @@ punycode@1.3.2:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
punycode@^1.2.4, punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
q@^1.1.2:
version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"

View File

@ -1827,10 +1827,10 @@ cypress-cucumber-preprocessor@^1.12.0:
glob "^7.1.2"
through "^2.3.8"
cypress-file-upload@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-3.2.1.tgz#12befbd5f685883b2ce39133d675173f60caae5b"
integrity sha512-Wx9+DVon1Sc8HhiNpWaCYvjn5q8izYg9+Es0MhwlRj2APRToaihtM0EJgS/om9gA9HeKbU0ReTpv+xk/0VCUjw==
cypress-file-upload@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-3.3.1.tgz#19bb6c296ffc492dbfae8a7511c94d6b4d0ad4d5"
integrity sha512-iUtq/a30i73JXx9sUj5HhmuEV9pHMV2/7C06H8/zFDSgFweFSwKL0SSprQu8Ewf7cAEsExBKigwlLQYFdTW8PA==
cypress-plugin-retries@^1.2.2:
version "1.2.2"