mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge branch 'master' of https://github.com/Human-Connection/Human-Connection into 1455-fix-update-comment-list
This commit is contained in:
commit
0e39f1de86
@ -15,10 +15,10 @@ COPY .env.template .env
|
||||
CMD ["yarn", "run", "start"]
|
||||
|
||||
FROM base as builder
|
||||
RUN yarn install --frozen-lockfile --non-interactive
|
||||
RUN yarn install --production=false --frozen-lockfile --non-interactive
|
||||
COPY . .
|
||||
RUN cp .env.template .env
|
||||
RUN yarn run build
|
||||
RUN NODE_ENV=production yarn run build
|
||||
|
||||
# reduce image size with a multistage build
|
||||
FROM base as production
|
||||
|
||||
@ -117,7 +117,7 @@
|
||||
"chai": "~4.2.0",
|
||||
"cucumber": "~5.1.0",
|
||||
"eslint": "~6.3.0",
|
||||
"eslint-config-prettier": "~6.2.0",
|
||||
"eslint-config-prettier": "~6.3.0",
|
||||
"eslint-config-standard": "~14.1.0",
|
||||
"eslint-plugin-import": "~2.18.2",
|
||||
"eslint-plugin-jest": "~22.17.0",
|
||||
|
||||
@ -1,120 +0,0 @@
|
||||
import { gql } from '../../jest/helpers'
|
||||
import Factory from '../../seed/factories'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../../server'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
|
||||
const factory = Factory()
|
||||
const neode = getNeode()
|
||||
const driver = getDriver()
|
||||
|
||||
let authenticatedUser
|
||||
let user
|
||||
let query
|
||||
|
||||
const currentUserParams = {
|
||||
id: 'u1',
|
||||
email: 'you@example.org',
|
||||
name: 'This is you',
|
||||
password: '1234',
|
||||
}
|
||||
const followedAuthorParams = {
|
||||
id: 'u2',
|
||||
email: 'followed@example.org',
|
||||
name: 'Followed User',
|
||||
password: '1234',
|
||||
}
|
||||
const randomAuthorParams = {
|
||||
email: 'someone@example.org',
|
||||
name: 'Someone else',
|
||||
password: 'else',
|
||||
}
|
||||
const categoryIds = ['cat9']
|
||||
|
||||
beforeEach(async () => {
|
||||
const [currentUser, followedAuthor, randomAuthor] = await Promise.all([
|
||||
factory.create('User', currentUserParams),
|
||||
factory.create('User', followedAuthorParams),
|
||||
factory.create('User', randomAuthorParams),
|
||||
])
|
||||
user = currentUser
|
||||
await neode.create('Category', {
|
||||
id: 'cat9',
|
||||
name: 'Democracy & Politics',
|
||||
icon: 'university',
|
||||
})
|
||||
await currentUser.relateTo(followedAuthor, 'following')
|
||||
await factory.create('Post', {
|
||||
author: followedAuthor,
|
||||
title: 'This is the post of a followed user',
|
||||
categoryIds,
|
||||
})
|
||||
await factory.create('Post', {
|
||||
author: randomAuthor,
|
||||
title: 'This is some random post',
|
||||
categoryIds,
|
||||
})
|
||||
})
|
||||
|
||||
beforeAll(() => {
|
||||
const { server } = createServer({
|
||||
context: () => {
|
||||
return {
|
||||
driver,
|
||||
neode,
|
||||
user: authenticatedUser,
|
||||
}
|
||||
},
|
||||
})
|
||||
const client = createTestClient(server)
|
||||
query = client.query
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('Filter posts by author is followed by sb.', () => {
|
||||
describe('given an authenticated user', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
})
|
||||
|
||||
describe('no filter bubble', () => {
|
||||
it('returns all posts', async () => {
|
||||
const postQuery = gql`
|
||||
{
|
||||
Post(filter: {}) {
|
||||
title
|
||||
}
|
||||
}
|
||||
`
|
||||
const expected = {
|
||||
data: {
|
||||
Post: [
|
||||
{ title: 'This is some random post' },
|
||||
{ title: 'This is the post of a followed user' },
|
||||
],
|
||||
},
|
||||
}
|
||||
await expect(query({ query: postQuery })).resolves.toMatchObject(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('filtering for posts of followed users only', () => {
|
||||
it('returns only posts authored by followed users', async () => {
|
||||
const postQuery = gql`
|
||||
{
|
||||
Post(filter: { author: { followedBy_some: { id: "u1" } } }) {
|
||||
title
|
||||
}
|
||||
}
|
||||
`
|
||||
const expected = {
|
||||
data: { Post: [{ title: 'This is the post of a followed user' }] },
|
||||
}
|
||||
await expect(query({ query: postQuery })).resolves.toMatchObject(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -56,7 +56,7 @@ beforeAll(() => {
|
||||
beforeEach(async () => {
|
||||
variables = {}
|
||||
user = await factory.create('User', {
|
||||
id: 'u198',
|
||||
id: 'current-user',
|
||||
name: 'TestUser',
|
||||
email: 'test@example.org',
|
||||
password: '1234',
|
||||
@ -91,44 +91,63 @@ afterEach(async () => {
|
||||
})
|
||||
|
||||
describe('Post', () => {
|
||||
const postQueryFilteredByCategories = gql`
|
||||
query Post($filter: _PostFilter) {
|
||||
Post(filter: $filter) {
|
||||
id
|
||||
categories {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const postQueryFilteredByEmotions = gql`
|
||||
query Post($filter: _PostFilter) {
|
||||
Post(filter: $filter) {
|
||||
id
|
||||
emotions {
|
||||
emotion
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
describe('can be filtered', () => {
|
||||
let post31, post32
|
||||
let followedUser, happyPost, cryPost
|
||||
beforeEach(async () => {
|
||||
;[post31, post32] = await Promise.all([
|
||||
factory.create('Post', { id: 'p31', categoryIds: ['cat4'] }),
|
||||
factory.create('Post', { id: 'p32', categoryIds: ['cat15'] }),
|
||||
factory.create('Post', { id: 'p33', categoryIds: ['cat9'] }),
|
||||
;[followedUser] = await Promise.all([
|
||||
factory.create('User', {
|
||||
id: 'followed-by-me',
|
||||
email: 'followed@example.org',
|
||||
name: 'Followed User',
|
||||
password: '1234',
|
||||
}),
|
||||
])
|
||||
;[happyPost, cryPost] = await Promise.all([
|
||||
factory.create('Post', { id: 'happy-post', categoryIds: ['cat4'] }),
|
||||
factory.create('Post', { id: 'cry-post', categoryIds: ['cat15'] }),
|
||||
factory.create('Post', {
|
||||
id: 'post-by-followed-user',
|
||||
categoryIds: ['cat9'],
|
||||
author: followedUser,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
describe('no filter', () => {
|
||||
it('returns all posts', async () => {
|
||||
const postQueryNoFilters = gql`
|
||||
query Post($filter: _PostFilter) {
|
||||
Post(filter: $filter) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
const expected = [{ id: 'happy-post' }, { id: 'cry-post' }, { id: 'post-by-followed-user' }]
|
||||
variables = { filter: {} }
|
||||
await expect(query({ query: postQueryNoFilters, variables })).resolves.toMatchObject({
|
||||
data: {
|
||||
Post: expect.arrayContaining(expected),
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('by categories', async () => {
|
||||
const postQueryFilteredByCategories = gql`
|
||||
query Post($filter: _PostFilter) {
|
||||
Post(filter: $filter) {
|
||||
id
|
||||
categories {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
const expected = {
|
||||
data: {
|
||||
Post: [
|
||||
{
|
||||
id: 'p33',
|
||||
id: 'post-by-followed-user',
|
||||
categories: [{ id: 'cat9' }],
|
||||
},
|
||||
],
|
||||
@ -140,45 +159,88 @@ describe('Post', () => {
|
||||
).resolves.toMatchObject(expected)
|
||||
})
|
||||
|
||||
it('by emotions', async () => {
|
||||
describe('by emotions', () => {
|
||||
const postQueryFilteredByEmotions = gql`
|
||||
query Post($filter: _PostFilter) {
|
||||
Post(filter: $filter) {
|
||||
id
|
||||
emotions {
|
||||
emotion
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
it('filters by single emotion', async () => {
|
||||
const expected = {
|
||||
data: {
|
||||
Post: [
|
||||
{
|
||||
id: 'happy-post',
|
||||
emotions: [{ emotion: 'happy' }],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
|
||||
variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy'] } } }
|
||||
await expect(
|
||||
query({ query: postQueryFilteredByEmotions, variables }),
|
||||
).resolves.toMatchObject(expected)
|
||||
})
|
||||
|
||||
it('filters by multiple emotions', async () => {
|
||||
const expected = [
|
||||
{
|
||||
id: 'happy-post',
|
||||
emotions: [{ emotion: 'happy' }],
|
||||
},
|
||||
{
|
||||
id: 'cry-post',
|
||||
emotions: [{ emotion: 'cry' }],
|
||||
},
|
||||
]
|
||||
await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
|
||||
await user.relateTo(cryPost, 'emoted', { emotion: 'cry' })
|
||||
variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy', 'cry'] } } }
|
||||
await expect(
|
||||
query({ query: postQueryFilteredByEmotions, variables }),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
Post: expect.arrayContaining(expected),
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('by followed-by', async () => {
|
||||
const postQueryFilteredByUsersFollowed = gql`
|
||||
query Post($filter: _PostFilter) {
|
||||
Post(filter: $filter) {
|
||||
id
|
||||
author {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
await user.relateTo(followedUser, 'following')
|
||||
variables = { filter: { author: { followedBy_some: { id: 'current-user' } } } }
|
||||
const expected = {
|
||||
data: {
|
||||
Post: [
|
||||
{
|
||||
id: 'p31',
|
||||
emotions: [{ emotion: 'happy' }],
|
||||
id: 'post-by-followed-user',
|
||||
author: { id: 'followed-by-me', name: 'Followed User' },
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
await user.relateTo(post31, 'emoted', { emotion: 'happy' })
|
||||
variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy'] } } }
|
||||
await expect(query({ query: postQueryFilteredByEmotions, variables })).resolves.toMatchObject(
|
||||
expected,
|
||||
)
|
||||
})
|
||||
|
||||
it('supports filtering by multiple emotions', async () => {
|
||||
const expected = [
|
||||
{
|
||||
id: 'p31',
|
||||
emotions: [{ emotion: 'happy' }],
|
||||
},
|
||||
{
|
||||
id: 'p32',
|
||||
emotions: [{ emotion: 'cry' }],
|
||||
},
|
||||
]
|
||||
await user.relateTo(post31, 'emoted', { emotion: 'happy' })
|
||||
await user.relateTo(post32, 'emoted', { emotion: 'cry' })
|
||||
variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy', 'cry'] } } }
|
||||
await expect(query({ query: postQueryFilteredByEmotions, variables })).resolves.toMatchObject(
|
||||
{
|
||||
data: {
|
||||
Post: expect.arrayContaining(expected),
|
||||
},
|
||||
},
|
||||
)
|
||||
await expect(
|
||||
query({ query: postQueryFilteredByUsersFollowed, variables }),
|
||||
).resolves.toMatchObject(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -656,7 +718,7 @@ describe('emotions', () => {
|
||||
const expected = {
|
||||
data: {
|
||||
AddPostEmotions: {
|
||||
from: { id: 'u198' },
|
||||
from: { id: 'current-user' },
|
||||
to: { id: 'p1376' },
|
||||
emotion: 'happy',
|
||||
},
|
||||
@ -690,8 +752,8 @@ describe('emotions', () => {
|
||||
Post: [
|
||||
{
|
||||
emotions: expect.arrayContaining([
|
||||
{ emotion: 'happy', User: { id: 'u198' } },
|
||||
{ emotion: 'surprised', User: { id: 'u198' } },
|
||||
{ emotion: 'happy', User: { id: 'current-user' } },
|
||||
{ emotion: 'surprised', User: { id: 'current-user' } },
|
||||
]),
|
||||
},
|
||||
],
|
||||
@ -795,7 +857,7 @@ describe('emotions', () => {
|
||||
data: {
|
||||
RemovePostEmotions: {
|
||||
to: { id: 'p1376' },
|
||||
from: { id: 'u198' },
|
||||
from: { id: 'current-user' },
|
||||
emotion: 'cry',
|
||||
},
|
||||
},
|
||||
|
||||
@ -3282,10 +3282,10 @@ escodegen@^1.9.1:
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
eslint-config-prettier@~6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.2.0.tgz#80e0b8714e3f6868c4ac2a25fbf39c02e73527a7"
|
||||
integrity sha512-VLsgK/D+S/FEsda7Um1+N8FThec6LqE3vhcMyp8mlmto97y3fGf3DX7byJexGuOb1QY0Z/zz222U5t+xSfcZDQ==
|
||||
eslint-config-prettier@~6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.3.0.tgz#e73b48e59dc49d950843f3eb96d519e2248286a3"
|
||||
integrity sha512-EWaGjlDAZRzVFveh2Jsglcere2KK5CJBhkNSa1xs3KfMUGdRiT7lG089eqPdvlzWHpAqaekubOsOMu8W8Yk71A==
|
||||
dependencies:
|
||||
get-stdin "^6.0.0"
|
||||
|
||||
|
||||
@ -15,7 +15,8 @@ services:
|
||||
- ./webapp:/nitro-web
|
||||
- webapp_node_modules:/nitro-web/node_modules
|
||||
command: yarn run dev
|
||||
user: root
|
||||
environment:
|
||||
- NUXT_BUILD=.nuxt-dist # avoid file ownership issues with shared folders
|
||||
factories:
|
||||
image: humanconnection/nitro-backend:builder
|
||||
build:
|
||||
|
||||
@ -14,8 +14,6 @@ services:
|
||||
volumes:
|
||||
#/nitro-web
|
||||
- ./webapp/coverage:/nitro-web/coverage
|
||||
environment:
|
||||
- GRAPHQL_URI=http://backend:4000
|
||||
backend:
|
||||
image: humanconnection/nitro-backend:builder
|
||||
build:
|
||||
|
||||
@ -12,7 +12,6 @@ services:
|
||||
networks:
|
||||
- hc-network
|
||||
environment:
|
||||
- NUXT_BUILD=.nuxt-dist
|
||||
- HOST=0.0.0.0
|
||||
- GRAPHQL_URI=http://backend:4000
|
||||
- MAPBOX_TOKEN="pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.bZ8KK9l70omjXbEkkbHGsQ"
|
||||
|
||||
@ -19,7 +19,7 @@ COPY . .
|
||||
FROM base as build-and-test
|
||||
RUN cp .env.template .env
|
||||
RUN yarn install --production=false --frozen-lockfile --non-interactive
|
||||
RUN yarn run build
|
||||
RUN NODE_ENV=production yarn run build
|
||||
|
||||
FROM base as production
|
||||
ENV NODE_ENV=production
|
||||
|
||||
@ -59,16 +59,15 @@ export default {
|
||||
this.hovered = true
|
||||
}
|
||||
},
|
||||
toggle() {
|
||||
async toggle() {
|
||||
const follow = !this.isFollowed
|
||||
const mutation = follow ? 'follow' : 'unfollow'
|
||||
|
||||
this.hovered = false
|
||||
|
||||
this.$emit('optimistic', follow)
|
||||
|
||||
this.$apollo
|
||||
.mutate({
|
||||
try {
|
||||
await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation($id: ID!) {
|
||||
${mutation}(id: $id, type: User)
|
||||
@ -78,13 +77,11 @@ export default {
|
||||
id: this.followId,
|
||||
},
|
||||
})
|
||||
.then(res => {
|
||||
// this.$emit('optimistic', follow ? res.data.follow : follow)
|
||||
this.$emit('update', follow)
|
||||
})
|
||||
.catch(() => {
|
||||
this.$emit('optimistic', !follow)
|
||||
})
|
||||
|
||||
this.$emit('update', follow)
|
||||
} catch {
|
||||
this.$emit('optimistic', !follow)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -71,8 +71,8 @@
|
||||
<hc-follow-button
|
||||
:follow-id="user.id"
|
||||
:is-followed="user.followedByCurrentUser"
|
||||
@optimistic="follow => (user.followedByCurrentUser = follow)"
|
||||
@update="follow => (user.followedByCurrentUser = follow)"
|
||||
@optimistic="optimisticFollow"
|
||||
@update="updateFollow"
|
||||
/>
|
||||
</ds-flex-item>
|
||||
<ds-flex-item :width="{ base: 1 }">
|
||||
@ -131,6 +131,16 @@ export default {
|
||||
return name || this.$t('profile.userAnonym')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
optimisticFollow(follow) {
|
||||
const inc = follow ? 1 : -1
|
||||
this.user.followedByCurrentUser = follow
|
||||
this.user.followedByCount += inc
|
||||
},
|
||||
updateFollow(follow) {
|
||||
this.user.followedByCurrentUser = follow
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -10,11 +10,11 @@
|
||||
"author": "Human Connection gGmbH",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
|
||||
"dev:styleguide": "cross-env STYLEGUIDE_DEV=true yarn dev",
|
||||
"dev": "nuxt",
|
||||
"dev:styleguide": "cross-env STYLEGUIDE_DEV=true yarn run dev",
|
||||
"storybook": "start-storybook -p 3002 -c storybook/",
|
||||
"build": "nuxt build",
|
||||
"start": "cross-env node server/index.js",
|
||||
"start": "nuxt start",
|
||||
"generate": "nuxt generate",
|
||||
"lint": "eslint --ext .js,.vue .",
|
||||
"precommit": "yarn lint",
|
||||
@ -103,7 +103,7 @@
|
||||
"core-js": "~2.6.9",
|
||||
"css-loader": "~3.2.0",
|
||||
"eslint": "~5.16.0",
|
||||
"eslint-config-prettier": "~6.2.0",
|
||||
"eslint-config-prettier": "~6.3.0",
|
||||
"eslint-config-standard": "~12.0.0",
|
||||
"eslint-loader": "~3.0.0",
|
||||
"eslint-plugin-import": "~2.18.2",
|
||||
@ -118,7 +118,6 @@
|
||||
"jest": "~24.9.0",
|
||||
"mutation-observer": "^1.0.3",
|
||||
"node-sass": "~4.12.0",
|
||||
"nodemon": "~1.19.2",
|
||||
"prettier": "~1.18.2",
|
||||
"sass-loader": "~8.0.0",
|
||||
"style-loader": "~0.23.1",
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
const express = require('express')
|
||||
const consola = require('consola')
|
||||
const { Nuxt, Builder } = require('nuxt')
|
||||
const app = express()
|
||||
|
||||
require('dotenv').config()
|
||||
|
||||
const host = process.env.HOST || '127.0.0.1'
|
||||
const port = process.env.PORT || 3000
|
||||
app.set('port', port)
|
||||
|
||||
// Import and Set Nuxt.js options
|
||||
let config = require('../nuxt.config.js')
|
||||
config.dev = !(process.env.NODE_ENV === 'production')
|
||||
|
||||
async function start() {
|
||||
// Init Nuxt.js
|
||||
const nuxt = new Nuxt(config)
|
||||
|
||||
// Build only in dev mode
|
||||
if (config.dev) {
|
||||
const builder = new Builder(nuxt)
|
||||
await builder.build()
|
||||
}
|
||||
|
||||
// Give nuxt middleware to express
|
||||
app.use(nuxt.render)
|
||||
|
||||
// Listen the server
|
||||
app.listen(port, host)
|
||||
consola.ready({
|
||||
message: `Server listening on http://${host}:${port}`,
|
||||
badge: true,
|
||||
})
|
||||
}
|
||||
start()
|
||||
@ -6335,10 +6335,10 @@ escodegen@^1.9.1:
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
eslint-config-prettier@^6.0.0, eslint-config-prettier@~6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.2.0.tgz#80e0b8714e3f6868c4ac2a25fbf39c02e73527a7"
|
||||
integrity sha512-VLsgK/D+S/FEsda7Um1+N8FThec6LqE3vhcMyp8mlmto97y3fGf3DX7byJexGuOb1QY0Z/zz222U5t+xSfcZDQ==
|
||||
eslint-config-prettier@^6.0.0, eslint-config-prettier@~6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.3.0.tgz#e73b48e59dc49d950843f3eb96d519e2248286a3"
|
||||
integrity sha512-EWaGjlDAZRzVFveh2Jsglcere2KK5CJBhkNSa1xs3KfMUGdRiT7lG089eqPdvlzWHpAqaekubOsOMu8W8Yk71A==
|
||||
dependencies:
|
||||
get-stdin "^6.0.0"
|
||||
|
||||
@ -10558,7 +10558,7 @@ node-sass@^4.12.0, node-sass@~4.12.0:
|
||||
stdout-stream "^1.4.0"
|
||||
"true-case-path" "^1.0.2"
|
||||
|
||||
nodemon@^1.19.1, nodemon@~1.19.2:
|
||||
nodemon@^1.19.1:
|
||||
version "1.19.2"
|
||||
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.19.2.tgz#b0975147dc99b3761ceb595b3f9277084931dcc0"
|
||||
integrity sha512-hRLYaw5Ihyw9zK7NF+9EUzVyS6Cvgc14yh8CAYr38tPxJa6UrOxwAQ351GwrgoanHCF0FalQFn6w5eoX/LGdJw==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user