mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
initial commit
This commit is contained in:
commit
5fcceda30f
6
.env
Normal file
6
.env
Normal file
@ -0,0 +1,6 @@
|
||||
NEO4J_URI=bolt://localhost:7687
|
||||
NEO4J_USER=neo4j
|
||||
NEO4J_PASSWORD=letmein
|
||||
GRAPHQL_LISTEN_PORT=4000
|
||||
GRAPHQL_URI=http://localhost:4000
|
||||
MOCK=false
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
||||
3
.graphqlconfig
Normal file
3
.graphqlconfig
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"schemaPath": "./src/schema.graphql"
|
||||
}
|
||||
93
README.md
Normal file
93
README.md
Normal file
@ -0,0 +1,93 @@
|
||||
# Human-Connection - GraphQL API - Prototype
|
||||
|
||||
> This Prototype tries to resolve the biggest hurdle of connecting
|
||||
> our services together. This is not possible in a sane way using
|
||||
> our current approach.
|
||||
>
|
||||
> With this Prototype we can explore using the combination of
|
||||
> GraphQL and the Neo4j Graph Database for achieving the connected
|
||||
> nature of a social graph with better development experience as we
|
||||
> do not need to connect data by our own any more through weird table
|
||||
> structures etc.
|
||||
|
||||
>
|
||||
> #### Advantages:
|
||||
> - easer data structure
|
||||
> - better connected data
|
||||
> - easy to achieve "recommendations" based on actions (relations)
|
||||
> - more performant and better to understand API
|
||||
> - better API client that uses caching
|
||||
>
|
||||
> We still need to evaluate the drawbacks and estimate the development
|
||||
> cost of such an approach
|
||||
|
||||
## Quick Start
|
||||
|
||||
Install dependencies:
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
# -or-
|
||||
npm install
|
||||
```
|
||||
|
||||
Start the GraphQL service:
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
# -or-
|
||||
npm start
|
||||
```
|
||||
|
||||
This will start the GraphQL service (by default on localhost:4000)
|
||||
where you can issue GraphQL requests or access GraphQL Playground in the browser:
|
||||
|
||||

|
||||
|
||||
## Configure
|
||||
|
||||
Set your Neo4j connection string and credentials in `.env`.
|
||||
For example:
|
||||
|
||||
_.env_
|
||||
|
||||
```yaml
|
||||
NEO4J_URI=bolt://localhost:7687
|
||||
NEO4J_USER=neo4j
|
||||
NEO4J_PASSWORD=letmein
|
||||
```
|
||||
|
||||
Note that grand-stack-starter does not currently bundle a distribution
|
||||
of Neo4j. You can download [Neo4j Desktop](https://neo4j.com/download/)
|
||||
and run locally for development, spin up a [hosted Neo4j Sandbox instance](https://neo4j.com/download/),
|
||||
run Neo4j in one of the [many cloud options](https://neo4j.com/developer/guide-cloud-deployment/),
|
||||
or [spin up Neo4j in a Docker container](https://neo4j.com/developer/docker/).
|
||||
Just be sure to update the Neo4j connection string and credentials accordingly in `.env`.
|
||||
|
||||
## Deployment
|
||||
|
||||
You can deploy to any service that hosts Node.js apps, but [Zeit Now](https://zeit.co/now)
|
||||
is a great easy to use service for hosting your app that has an easy to use free plan for small projects.
|
||||
|
||||
To deploy your GraphQL service on Zeit Now, first install [Now Desktop](https://zeit.co/download) -
|
||||
you'll need to provide an email address. Then run
|
||||
|
||||
```
|
||||
now
|
||||
```
|
||||
|
||||
to deploy your GraphQL service on Zeit Now. Once deployed you'll be given
|
||||
a fresh URL that represents the current state of your application where you
|
||||
can access your GraphQL endpoint and GraphQL Playgound.
|
||||
For example: https://hc-graph-api-prototype-sdga96ad7.now.sh/
|
||||
|
||||
## Seeding The Database
|
||||
|
||||
Optionally you can seed the GraphQL service by executing mutations that
|
||||
will write sample data to the database:
|
||||
|
||||
```bash
|
||||
yarn seedDb
|
||||
# -or-
|
||||
npm run seedDb
|
||||
```
|
||||
32
package.json
Normal file
32
package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "hc-graph-api-prototype",
|
||||
"version": "0.0.1",
|
||||
"description": "Graph API Protype for Human Connection",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "./node_modules/.bin/nodemon --exec babel-node src/index.js",
|
||||
"seedDb": "./node_modules/.bin/babel-node src/seed/seed-db.js"
|
||||
},
|
||||
"author": "Grzegorz Leoniec",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"apollo-boost": "^0.1.10",
|
||||
"apollo-cache-inmemory": "^1.2.5",
|
||||
"apollo-client": "^2.3.2",
|
||||
"apollo-link-http": "^1.5.4",
|
||||
"apollo-server": "^2.0.4",
|
||||
"dotenv": "^6.0.0",
|
||||
"faker": "^4.1.0",
|
||||
"graphql-custom-directives": "^0.2.13",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"neo4j-driver": "^1.6.1",
|
||||
"neo4j-graphql-js": "^1.0.2",
|
||||
"node-fetch": "^2.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"nodemon": "^1.17.5"
|
||||
}
|
||||
}
|
||||
17
src/graphql-schema.js
Normal file
17
src/graphql-schema.js
Normal file
@ -0,0 +1,17 @@
|
||||
// import { neo4jgraphql } from "neo4j-graphql-js"
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
export const typeDefs =
|
||||
fs.readFileSync(process.env.GRAPHQL_SCHEMA || path.join(__dirname, "schema.graphql"))
|
||||
.toString('utf-8')
|
||||
|
||||
export const resolvers = {
|
||||
// Query: {
|
||||
// usersBySubstring: neo4jgraphql
|
||||
// }
|
||||
}
|
||||
|
||||
export const mutations = {
|
||||
|
||||
}
|
||||
64
src/index.js
Normal file
64
src/index.js
Normal file
@ -0,0 +1,64 @@
|
||||
// import { GraphQLServer } from 'graphql-yoga'
|
||||
import { ApolloServer, makeExecutableSchema } from 'apollo-server'
|
||||
import { augmentSchema } from 'neo4j-graphql-js'
|
||||
import { typeDefs, resolvers } from './graphql-schema'
|
||||
import { v1 as neo4j } from 'neo4j-driver'
|
||||
import dotenv from 'dotenv'
|
||||
import {
|
||||
GraphQLLowerCaseDirective,
|
||||
GraphQLTrimDirective,
|
||||
GraphQLDefaultToDirective
|
||||
} from 'graphql-custom-directives';
|
||||
import faker from 'faker'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers
|
||||
})
|
||||
|
||||
// augmentSchema will add auto generated mutations based on types in schema
|
||||
const augmentedSchema = augmentSchema(schema)
|
||||
|
||||
// add custom directives
|
||||
const directives = [
|
||||
GraphQLLowerCaseDirective,
|
||||
GraphQLTrimDirective,
|
||||
GraphQLDefaultToDirective
|
||||
]
|
||||
augmentedSchema._directives.push.apply(augmentedSchema._directives, directives)
|
||||
|
||||
const driver = neo4j.driver(
|
||||
process.env.NEO4J_URI || 'bolt://localhost:7687',
|
||||
neo4j.auth.basic(
|
||||
process.env.NEO4J_USER || 'neo4j',
|
||||
process.env.NEO4J_PASSWORD || 'neo4j'
|
||||
)
|
||||
)
|
||||
|
||||
const MOCK = (process.env.MOCK === 'true')
|
||||
console.log('MOCK:', MOCK)
|
||||
|
||||
const server = new ApolloServer({
|
||||
context: {
|
||||
driver
|
||||
},
|
||||
tracing: true,
|
||||
schema: augmentedSchema,
|
||||
mocks: MOCK ? {
|
||||
User: () => ({
|
||||
name: () => `${faker.name.firstName()} ${faker.name.lastName()}`,
|
||||
email: () => `${faker.internet.email()}`
|
||||
}),
|
||||
Post: () => ({
|
||||
title: () => faker.lorem.lines(1),
|
||||
slug: () => faker.lorem.slug(3),
|
||||
content: () => faker.lorem.paragraphs(5),
|
||||
contentExcerpt: () => faker.lorem.paragraphs(1)
|
||||
})
|
||||
} : false
|
||||
})
|
||||
server.listen().then(({ url }) => {
|
||||
console.log(`Server ready at ${url} 🚀`);
|
||||
})
|
||||
107
src/schema.graphql
Normal file
107
src/schema.graphql
Normal file
@ -0,0 +1,107 @@
|
||||
enum VisibilityEnum {
|
||||
Public
|
||||
Friends
|
||||
Private
|
||||
}
|
||||
|
||||
enum UserGroupEnum {
|
||||
Admin
|
||||
Moderator
|
||||
User
|
||||
}
|
||||
|
||||
type WrittenPost @relation(name: "WROTE") {
|
||||
from: User
|
||||
to: Post
|
||||
timestamp: Int
|
||||
}
|
||||
type WrittenComment @relation(name: "WROTE") {
|
||||
from: User
|
||||
to: Comment
|
||||
timestamp: Int
|
||||
}
|
||||
|
||||
type User {
|
||||
id: ID!
|
||||
name: String!
|
||||
email: String
|
||||
disabled: Boolean @default(to: false)
|
||||
role: UserGroupEnum
|
||||
|
||||
friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
|
||||
friendsCount: Int! @cypher(statement: "MATCH (this)<-[:FRIENDS]->(r:User) RETURN COUNT(r)")
|
||||
|
||||
following: [User]! @relation(name: "FOLLOWING", direction: "OUT")
|
||||
followingCount: Int! @cypher(statement: "MATCH (this)-[:FOLLOWING]->(r:User) RETURN COUNT(r)")
|
||||
|
||||
followedBy: [User]! @relation(name: "FOLLOWING", direction: "IN")
|
||||
followedByCount: Int! @cypher(statement: "MATCH (this)<-[:FOLLOWING]-(r:User) RETURN COUNT(r)")
|
||||
|
||||
contributions: [WrittenPost]!
|
||||
contributionsCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(r:Post) RETURN COUNT(r)")
|
||||
|
||||
comments: [WrittenComment]!
|
||||
commentsCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(r:Comment) RETURN COUNT(r)")
|
||||
|
||||
shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT")
|
||||
|
||||
organizationsCreated: [Organization] @relation(name: "CREATED_ORGA", direction: "OUT")
|
||||
organizationsOwned: [Organization] @relation(name: "OWNING_ORGA", direction: "OUT")
|
||||
}
|
||||
|
||||
type Post {
|
||||
id: ID!
|
||||
author: WrittenPost
|
||||
title: String!
|
||||
slug: String!
|
||||
content: String!
|
||||
contentExcerpt: String!
|
||||
visibility: VisibilityEnum
|
||||
disabled: Boolean @default(to: false)
|
||||
|
||||
tags: [Tag]! @relation(name: "TAGGED", direction: "OUT")
|
||||
categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT")
|
||||
|
||||
comments: [Comment]! @relation(name: "COMMENT", direction: "IN")
|
||||
commentsCount: Int! @cypher(statement: "MATCH (this)<-[:COMMENT]-(r:Comment) RETURN COUNT(r)")
|
||||
|
||||
shoutedBy: [User]! @relation(name: "SHOUTED", direction: "IN")
|
||||
shoutedCount: Int! @cypher(statement: "MATCH (this)<-[:SHOUTED]-(r:User) RETURN COUNT(r)")
|
||||
}
|
||||
|
||||
type Comment {
|
||||
id: ID!
|
||||
author: WrittenComment
|
||||
content: String!
|
||||
contentExcerpt: String!
|
||||
post: Post @relation(name: "COMMENT", direction: "OUT")
|
||||
disabled: Boolean @default(to: false)
|
||||
}
|
||||
|
||||
type Category {
|
||||
id: ID!
|
||||
name: String!
|
||||
slug: String!
|
||||
icon: String!
|
||||
}
|
||||
|
||||
type Organization {
|
||||
id: ID!
|
||||
createdBy: User @relation(name: "CREATED_ORGA", direction: "IN")
|
||||
ownedBy: [User] @relation(name: "OWNING_ORGA", direction: "IN")
|
||||
name: String!
|
||||
slug: String!
|
||||
disabled: Boolean @default(to: false)
|
||||
|
||||
tags: [Tag]! @relation(name: "TAGGED", direction: "OUT")
|
||||
categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT")
|
||||
}
|
||||
|
||||
type Tag {
|
||||
id: ID!
|
||||
name: String!
|
||||
taggedPosts: [Post]! @relation(name: "TAGGED", direction: "IN")
|
||||
taggedOrganizations: [Organization]! @relation(name: "TAGGED", direction: "IN")
|
||||
taggedCount: Int! @cypher(statement: "MATCH (this)<-[:TAGGED]-(r) RETURN COUNT(r)")
|
||||
disabled: Boolean @default(to: false)
|
||||
}
|
||||
21
src/seed/seed-db.js
Normal file
21
src/seed/seed-db.js
Normal file
@ -0,0 +1,21 @@
|
||||
import ApolloClient from "apollo-client";
|
||||
import dotenv from "dotenv";
|
||||
import gql from 'graphql-tag'
|
||||
import seedMutations from "./seed-mutations";
|
||||
import fetch from "node-fetch";
|
||||
import { HttpLink } from "apollo-link-http";
|
||||
import { InMemoryCache } from "apollo-cache-inmemory";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const client = new ApolloClient({
|
||||
link: new HttpLink({ uri: process.env.GRAPHQL_URI, fetch }),
|
||||
cache: new InMemoryCache()
|
||||
});
|
||||
|
||||
client
|
||||
.mutate({
|
||||
mutation: gql(seedMutations)
|
||||
})
|
||||
.then(data => console.log(data))
|
||||
.catch(error => console.error(error));
|
||||
321
src/seed/seed-mutations.js
Normal file
321
src/seed/seed-mutations.js
Normal file
@ -0,0 +1,321 @@
|
||||
export default `
|
||||
mutation {
|
||||
u1: CreateUser(id: "u1", name: "Will Blast", email: "Will-Blast@Yahoo.com", role: Admin) {
|
||||
id
|
||||
name
|
||||
email
|
||||
role
|
||||
}
|
||||
u2: CreateUser(id: "u2", name: "Bob der Bausmeister", email: "Bob-der-Bausmeister@yahoo.com", role: Moderator) {
|
||||
id
|
||||
name
|
||||
email
|
||||
role
|
||||
}
|
||||
u3: CreateUser(id: "u3", name: "Jenny Rostock", email: "JennyRostock@yahoo.com", role: Admin) {
|
||||
id
|
||||
name
|
||||
email
|
||||
role
|
||||
}
|
||||
u4: CreateUser(id: "u4", name: "Angie Banjie", email: "Angie_Banjie@yahoo.com", role: User) {
|
||||
id
|
||||
name
|
||||
email
|
||||
role
|
||||
}
|
||||
|
||||
cat1: CreateCategory( id: "cat1", name: "Just For Fun", slug: "justforfun", icon: "categories-justforfun" ) { name }
|
||||
cat2: CreateCategory( id: "cat2", name: "Happyness & Values", slug: "happyness-values", icon: "categories-luck" ) { name }
|
||||
cat3: CreateCategory( id: "cat3", name: "Health & Wellbeing", slug: "health-wellbeing", icon: "categories-health" ) { name }
|
||||
cat4: CreateCategory( id: "cat4", name: "Environment & Nature", slug: "environment-nature", icon: "categories-environment" ) { name }
|
||||
cat5: CreateCategory( id: "cat5", name: "Animal Protection", slug: "animalprotection", icon: "categories-animal-justice" ) { name }
|
||||
cat6: CreateCategory( id: "cat6", name: "Humanrights Justice", slug: "humanrights-justice", icon: "categories-human-rights" ) { name }
|
||||
cat7: CreateCategory( id: "cat7", name: "Education & Sciences", slug: "education-sciences", icon: "categories-education" ) { name }
|
||||
cat8: CreateCategory( id: "cat8", name: "Cooperation & Development", slug: "cooperation-development", icon: "categories-cooperation" ) { name }
|
||||
cat9: CreateCategory( id: "cat9", name: "Democracy & Politics", slug: "democracy-politics", icon: "categories-politics" ) { name }
|
||||
cat10: CreateCategory( id: "cat10", name: "Economy & Finances", slug: "economy-finances", icon: "categories-economy" ) { name }
|
||||
cat11: CreateCategory( id: "cat11", name: "Energy & Technology", slug: "energy-technology", icon: "categories-technology" ) { name }
|
||||
cat12: CreateCategory( id: "cat12", name: "IT, Internet & Data Privacy", slug: "it-internet-dataprivacy", icon: "categories-internet" ) { name }
|
||||
cat13: CreateCategory( id: "cat13", name: "Art, Curlure & Sport", slug: "art-culture-sport", icon: "categories-art" ) { name }
|
||||
cat14: CreateCategory( id: "cat14", name: "Freedom of Speech", slug: "freedomofspeech", icon: "categories-freedom-of-speech" ) { name }
|
||||
cat15: CreateCategory( id: "cat15", name: "Consumption & Sustainability", slug: "consumption-sustainability", icon: "categories-sustainability" ) { name }
|
||||
cat16: CreateCategory( id: "cat16", name: "Global Peace & Nonviolence", slug: "globalpeace-nonviolence", icon: "categories-peace" ) { name }
|
||||
|
||||
p1: CreatePost(
|
||||
id: "p1",
|
||||
title: "Gedanken eines Polizisten zum Einsatz im Hambacher Forst",
|
||||
slug: "gedanken-eines-polizisten-zum-einsatz-im-hambacher-forst",
|
||||
content: "# 1 This is my content 1",
|
||||
contentExcerpt: "# 1 This is my content 1",
|
||||
visibility: Public
|
||||
) { title }
|
||||
p1_cat1: AddPostCategories(from: {id: "p1"}, to: {id: "cat1"}) { from { id } }
|
||||
p1_cat2: AddPostCategories(from: {id: "p1"}, to: {id: "cat2"}) { from { id } }
|
||||
|
||||
p2: CreatePost(
|
||||
id: "p2",
|
||||
title: "Julian Assange",
|
||||
slug: "julian-assange",
|
||||
content: "#2 This is my content 2",
|
||||
contentExcerpt: "#2 This is my content 2",
|
||||
visibility: Public
|
||||
) { title }
|
||||
p2_cat1: AddPostCategories(from: {id: "p2"}, to: {id: "cat1"}) { from { id } }
|
||||
p2_cat16: AddPostCategories(from: {id: "p2"}, to: {id: "cat16"}) { from { id } }
|
||||
|
||||
p3: CreatePost(
|
||||
id: "p3",
|
||||
title: "Hacker, Freaks und Funktionäre...Der CCC",
|
||||
slug: "hacker-freaks-und-funktionäre-der-ccc",
|
||||
content: "#3 This is my content 3",
|
||||
contentExcerpt: "#3 This is my content 3",
|
||||
visibility: Public
|
||||
) { title }
|
||||
p3_cat1: AddPostCategories(from: {id: "p3"}, to: {id: "cat1"}) { from { id } }
|
||||
p3_cat3: AddPostCategories(from: {id: "p3"}, to: {id: "cat3"}) { from { id } }
|
||||
p3_cat14: AddPostCategories(from: {id: "p3"}, to: {id: "cat14"}) { from { id } }
|
||||
|
||||
p4: CreatePost(
|
||||
id: "p4",
|
||||
title: "Lebensmittel (?)",
|
||||
slug: "lebensmittel",
|
||||
content: "#4 This is my content 4",
|
||||
contentExcerpt: "#4 This is my content 4",
|
||||
visibility: Public
|
||||
) { title }
|
||||
p4_cat1: AddPostCategories(from: {id: "p4"}, to: {id: "cat1"}) { from { id } }
|
||||
p4_cat9: AddPostCategories(from: {id: "p4"}, to: {id: "cat9"}) { from { id } }
|
||||
p4_cat4: AddPostCategories(from: {id: "p4"}, to: {id: "cat4"}) { from { id } }
|
||||
|
||||
c1: CreateComment(
|
||||
id: "c1",
|
||||
content: "# 1 This is my comment 1",
|
||||
contentExcerpt: "# 1 This is my..."
|
||||
) { id }
|
||||
c2: CreateComment(
|
||||
id: "c2",
|
||||
content: "# 2 This is my comment 2",
|
||||
contentExcerpt: "# 2 This is my..."
|
||||
) { id }
|
||||
c3: CreateComment(
|
||||
id: "c3",
|
||||
content: "# 3 This is my comment 3",
|
||||
contentExcerpt: "# 3 This is my..."
|
||||
) { id }
|
||||
c4: CreateComment(
|
||||
id: "c4",
|
||||
content: "# 4 This is my comment 4",
|
||||
contentExcerpt: "# 4 This is my..."
|
||||
) { id }
|
||||
c5: CreateComment(
|
||||
id: "c5",
|
||||
content: "# 5 This is my comment 5",
|
||||
contentExcerpt: "# 5 This is my..."
|
||||
) { id }
|
||||
|
||||
c1_u1: AddCommentAuthor(
|
||||
from: { id: "u1" },
|
||||
to: { id: "c1" },
|
||||
data: { timestamp: 1538655020 }
|
||||
) { from { id } }
|
||||
c2_u1: AddCommentAuthor(
|
||||
from: { id: "u1" },
|
||||
to: { id: "c2" },
|
||||
data: { timestamp: 1538655020 }
|
||||
) { from { id } }
|
||||
c3_u2: AddCommentAuthor(
|
||||
from: { id: "u2" },
|
||||
to: { id: "c3" },
|
||||
data: { timestamp: 1538655020 }
|
||||
) { from { id } }
|
||||
c4_u3: AddCommentAuthor(
|
||||
from: { id: "u3" },
|
||||
to: { id: "c4" },
|
||||
data: { timestamp: 1538655020 }
|
||||
) { from { id } }
|
||||
c5_u4: AddCommentAuthor(
|
||||
from: { id: "u4" },
|
||||
to: { id: "c5" },
|
||||
data: { timestamp: 1538655020 }
|
||||
) { from { id } }
|
||||
|
||||
c1_p1: AddCommentPost(
|
||||
from: { id: "c1" },
|
||||
to: { id: "p1" }
|
||||
) { from { id } }
|
||||
c2_p1: AddCommentPost(
|
||||
from: { id: "c2" },
|
||||
to: { id: "p1" }
|
||||
) { from { id } }
|
||||
c3_p2: AddCommentPost(
|
||||
from: { id: "c3" },
|
||||
to: { id: "p2" }
|
||||
) { from { id } }
|
||||
c4_p3: AddCommentPost(
|
||||
from: { id: "c4" },
|
||||
to: { id: "p3" }
|
||||
) { from { id } }
|
||||
c5_p4: AddCommentPost(
|
||||
from: { id: "c5" },
|
||||
to: { id: "p4" }
|
||||
) { from { id } }
|
||||
|
||||
t1: CreateTag(
|
||||
id: "t1",
|
||||
name: "Umwelt"
|
||||
) { name }
|
||||
t2: CreateTag(
|
||||
id: "t2",
|
||||
name: "Naturschutz"
|
||||
) { name }
|
||||
t3: CreateTag(
|
||||
id: "t3",
|
||||
name: "Demokratie"
|
||||
) { name }
|
||||
t4: CreateTag(
|
||||
id: "t4",
|
||||
name: "Freiheit"
|
||||
) { name }
|
||||
|
||||
p1_t1: AddPostTags(
|
||||
from: { id: "p1" }
|
||||
to: { id: "t1" }
|
||||
) { from { id } }
|
||||
p1_t2: AddPostTags(
|
||||
from: { id: "p1" }
|
||||
to: { id: "t2" }
|
||||
) { from { id } }
|
||||
p1_t3: AddPostTags(
|
||||
from: { id: "p1" }
|
||||
to: { id: "t3" }
|
||||
) { from { id } }
|
||||
p2_t4: AddPostTags(
|
||||
from: { id: "p2" }
|
||||
to: { id: "t4" }
|
||||
) { from { id } }
|
||||
p3_t2: AddPostTags(
|
||||
from: { id: "p3" }
|
||||
to: { id: "t2" }
|
||||
) { from { id } }
|
||||
p3_t4: AddPostTags(
|
||||
from: { id: "p3" }
|
||||
to: { id: "t4" }
|
||||
) { from { id } }
|
||||
|
||||
o1: CreateOrganization(
|
||||
id: "o1",
|
||||
name: "Democracy Deutschland",
|
||||
slug: "democracy-deutschland"
|
||||
) { name }
|
||||
o2: CreateOrganization(
|
||||
id: "o2",
|
||||
name: "Human-Connection",
|
||||
slug: "human-connection"
|
||||
) { name }
|
||||
o3: CreateOrganization(
|
||||
id: "o3",
|
||||
name: "Pro Veg",
|
||||
slug: "pro-veg"
|
||||
) { name }
|
||||
o4: CreateOrganization(
|
||||
id: "o4",
|
||||
name: "Greenpeace",
|
||||
slug: "greenpeace"
|
||||
) { name }
|
||||
|
||||
u1_c_o1: AddOrganizationCreatedBy(
|
||||
from: { id: "u1" },
|
||||
to: { id: "o1" }
|
||||
) { from { id } }
|
||||
u1_c_o2: AddOrganizationCreatedBy(
|
||||
from: { id: "u1" },
|
||||
to: { id: "o2" }
|
||||
) { from { id } }
|
||||
|
||||
u2_o_o1: AddOrganizationOwnedBy(
|
||||
from: { id: "u2" },
|
||||
to: { id: "o2" }
|
||||
) { from { id } }
|
||||
u2_c_o3: AddOrganizationOwnedBy(
|
||||
from: { id: "u2" },
|
||||
to: { id: "o3" }
|
||||
) { from { id } }
|
||||
|
||||
u1_friends_u2: AddUserFriends(
|
||||
from: { id: "u1" },
|
||||
to: { id: "u2" }
|
||||
) { from { id } }
|
||||
u1_friends_u3: AddUserFriends(
|
||||
from: { id: "u1" },
|
||||
to: { id: "u3" }
|
||||
) { from { id } }
|
||||
|
||||
u1_follow_u2: AddUserFollowing(
|
||||
from: { id: "u1" },
|
||||
to: { id: "u2" }
|
||||
) { from { id } }
|
||||
u2_follow_u1: AddUserFollowing(
|
||||
from: { id: "u2" },
|
||||
to: { id: "u1" }
|
||||
) { from { id } }
|
||||
u2_follow_u3: AddUserFollowing(
|
||||
from: { id: "u2" },
|
||||
to: { id: "u3" }
|
||||
) { from { id } }
|
||||
u2_follow_u4: AddUserFollowing(
|
||||
from: { id: "u2" },
|
||||
to: { id: "u4" }
|
||||
) { from { id } }
|
||||
u4_follow_u2: AddUserFollowing(
|
||||
from: { id: "u4" },
|
||||
to: { id: "u2" }
|
||||
) { from { id } }
|
||||
|
||||
ur1: AddUserContributions(
|
||||
from: { id: "u1" },
|
||||
to: { id: "p1" },
|
||||
data: { timestamp: 1538655020 }
|
||||
) { from { id } }
|
||||
ur2: AddUserContributions(
|
||||
from: { id: "u2" },
|
||||
to: { id: "p2" },
|
||||
data: { timestamp: 1538655120 }
|
||||
) { from { id } }
|
||||
ur3: AddUserContributions(
|
||||
from: { id: "u3" },
|
||||
to: { id: "p3" },
|
||||
data: { timestamp: 1538653120 }
|
||||
) { from { id } }
|
||||
ur4: AddUserContributions(
|
||||
from: { id: "u4" },
|
||||
to: { id: "p4" },
|
||||
data: { timestamp: 1538615120 }
|
||||
) { from { id } }
|
||||
|
||||
u1s2: AddUserShouted(
|
||||
from: { id: "u1" },
|
||||
to: { id: "p2" }
|
||||
) { from { id } }
|
||||
u1s3: AddUserShouted(
|
||||
from: { id: "u1" },
|
||||
to: { id: "p3" }
|
||||
) { from { id } }
|
||||
u2s1: AddUserShouted(
|
||||
from: { id: "u2" },
|
||||
to: { id: "p1" }
|
||||
) { from { id } }
|
||||
u3s1: AddUserShouted(
|
||||
from: { id: "u3" },
|
||||
to: { id: "p1" }
|
||||
) { from { id } }
|
||||
u3s4: AddUserShouted(
|
||||
from: { id: "u3" },
|
||||
to: { id: "p4" }
|
||||
) { from { id } }
|
||||
u4s1: AddUserShouted(
|
||||
from: { id: "u4" },
|
||||
to: { id: "p1" }
|
||||
) { from { id } }
|
||||
}
|
||||
`
|
||||
Loading…
x
Reference in New Issue
Block a user