mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
Merge branch 'master' into cypress-migrate-to-v10
This commit is contained in:
commit
287827b3db
157
.codecov.yml
157
.codecov.yml
@ -1,157 +0,0 @@
|
||||
codecov:
|
||||
#token: uuid # Your private repository token
|
||||
#url: "http" # for Codecov Enterprise customers
|
||||
#slug: "owner/repo" # for Codecov Enterprise customers
|
||||
#branch: master # override the default branch
|
||||
#bot: username # set user whom will be the consumer of oauth requests
|
||||
#ci: # Custom CI domains if Codecov does not identify them automatically
|
||||
# - ci.domain.com
|
||||
# - !provider # ignore these providers when checking if CI passed
|
||||
# # ex. You may test on Travis, Circle, and AppVeyor, but only need
|
||||
# # to check if Travis passes. Therefore add: !circle and !appveyor
|
||||
notify:
|
||||
#after_n_builds: null # number of expected builds to recieve before sending notifications
|
||||
# # after: check ci status unless disabled via require_ci_to_pass
|
||||
require_ci_to_pass: yes # yes: will delay sending notifications until all ci is finished
|
||||
# no: will send notifications without checking ci status and wait till "after_n_builds" are uploaded
|
||||
#countdown: null # number of seconds to wait before first ci build check
|
||||
#delay: null # number of seconds to wait between ci build checks
|
||||
|
||||
coverage:
|
||||
precision: 2 # 2 = xx.xx%, 0 = xx%
|
||||
round: nearest # down|up|nearest - default down
|
||||
# range: 50...60 # default 70...90. red...green
|
||||
|
||||
#notify:
|
||||
# irc:
|
||||
# default:
|
||||
# server: "chat.freenode.net"|encrypted
|
||||
# branches: null # all branches by default
|
||||
# threshold: 1%
|
||||
# message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message
|
||||
# flags: null
|
||||
# paths: null
|
||||
#
|
||||
# slack:
|
||||
# default:
|
||||
# url: "http"|encrypted
|
||||
# threshold: 1%
|
||||
# branches: null # all branches by default
|
||||
# message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message
|
||||
# attachments: "sunburst, diff"
|
||||
# only_pulls: false
|
||||
# flags: null
|
||||
# paths: null
|
||||
#
|
||||
# email:
|
||||
# default:
|
||||
# to:
|
||||
# - example@domain.com
|
||||
# - &author
|
||||
# threshold: 1%
|
||||
# only_pulls: false
|
||||
# layout: header, diff, trends
|
||||
# flags: null
|
||||
# paths: null
|
||||
#
|
||||
# hipchat:
|
||||
# default:
|
||||
# url: "http"|encrypted
|
||||
# room: name|id
|
||||
# threshold: 1%
|
||||
# token: encrypted
|
||||
# branches: null # all branches by default
|
||||
# notify: false # if the hipchat message is silent or loud (default false)
|
||||
# message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message
|
||||
# flags: null
|
||||
# paths: null
|
||||
#
|
||||
# gitter:
|
||||
# url: "http"|encrypted
|
||||
# threshold: 1%
|
||||
# branches: null # all branches by default
|
||||
# message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message
|
||||
#
|
||||
# webhooks:
|
||||
# _name_:
|
||||
# url: "http"|encrypted
|
||||
# threshold: 1%
|
||||
# branches: null # all branches by default
|
||||
|
||||
status:
|
||||
project:
|
||||
default: false # disable the default status that measures entire project
|
||||
backend: # declare a new status context "backend"
|
||||
against: parent
|
||||
target: auto
|
||||
threshold: null
|
||||
#threshold: 1%
|
||||
base: auto
|
||||
if_no_uploads: error
|
||||
if_not_found: success
|
||||
if_ci_failed: error
|
||||
only_pulls: false
|
||||
#branches:
|
||||
# - master
|
||||
#flags:
|
||||
# - integration
|
||||
paths:
|
||||
- backend/ # only include coverage in "backend/" folder
|
||||
webapp: # declare a new status context "frontend"
|
||||
against: parent
|
||||
target: auto
|
||||
threshold: null
|
||||
#threshold: 1%
|
||||
base: auto
|
||||
if_no_uploads: error
|
||||
if_not_found: success
|
||||
if_ci_failed: error
|
||||
only_pulls: false
|
||||
#branches:
|
||||
# - master
|
||||
#flags:
|
||||
# - integration
|
||||
paths:
|
||||
- webapp/ # only include coverage in "webapp/" folder
|
||||
|
||||
patch:
|
||||
default: false
|
||||
# against: parent
|
||||
# target: 80%
|
||||
# branches: null
|
||||
# if_no_uploads: success
|
||||
# if_not_found: success
|
||||
# if_ci_failed: error
|
||||
# only_pulls: false
|
||||
# flags:
|
||||
# - integration
|
||||
# paths:
|
||||
# - folder
|
||||
|
||||
#changes:
|
||||
# default:
|
||||
# against: parent
|
||||
# branches: null
|
||||
# if_no_uploads: error
|
||||
# if_not_found: success
|
||||
# if_ci_failed: error
|
||||
# only_pulls: false
|
||||
# flags:
|
||||
# - integration
|
||||
# paths:
|
||||
# - folder
|
||||
|
||||
#flags:
|
||||
# integration:
|
||||
# branches:
|
||||
# - master
|
||||
# ignore:
|
||||
# - app/ui
|
||||
|
||||
#ignore: # files and folders for processing
|
||||
# - tests/*
|
||||
|
||||
#fixes:
|
||||
# - "old_path::new_path"
|
||||
|
||||
comment: off
|
||||
9
.github/file-filters.yml
vendored
Normal file
9
.github/file-filters.yml
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
backend: &backend
|
||||
- 'backend/**/*'
|
||||
- 'neo4j/**/*'
|
||||
|
||||
docker: &docker
|
||||
- 'docker-compose.*'
|
||||
|
||||
webapp: &webapp
|
||||
- 'webapp/**/*'
|
||||
79
.github/workflows/publish-branded.yml
vendored
79
.github/workflows/publish-branded.yml
vendored
@ -1,79 +0,0 @@
|
||||
name: publish-branded
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [trigger-build-success]
|
||||
jobs:
|
||||
build_branded:
|
||||
name: Docker Build Branded
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.ref }}
|
||||
- name: Setup env
|
||||
run: echo "OCELOT_VERSION=${{ github.event.client_payload.BUILD_VERSION }}" >> $GITHUB_ENV
|
||||
- name: Build branded images
|
||||
run: |
|
||||
deployment/scripts/branded-images.build.sh
|
||||
docker save "ocelotsocialnetwork/backend-branded" > /tmp/backend-branded.tar
|
||||
docker save "ocelotsocialnetwork/webapp-branded" > /tmp/webapp-branded.tar
|
||||
docker save "ocelotsocialnetwork/maintenance-branded" > /tmp/maintenance-branded.tar
|
||||
|
||||
- name: Upload Artifact (Backend)
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: docker-backend-branded
|
||||
path: /tmp/backend-branded.tar
|
||||
|
||||
- name: Upload Artifact (Webapp)
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: docker-webapp-branded
|
||||
path: /tmp/webapp-branded.tar
|
||||
|
||||
- name: Upload Artifact (Maintenance)
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: docker-maintenance-branded
|
||||
path: /tmp/maintenance-branded.tar
|
||||
|
||||
upload_to_dockerhub:
|
||||
name: Upload to Dockerhub
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_branded]
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.ref }}
|
||||
|
||||
- name: Download Docker Image (Backend)
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: docker-backend-branded
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/backend-branded.tar
|
||||
|
||||
- name: Download Docker Image (Webapp)
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: docker-webapp-branded
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/webapp-branded.tar
|
||||
|
||||
- name: Download Docker Image (Maintenance)
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: docker-maintenance-branded
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/maintenance-branded.tar
|
||||
|
||||
- name: Upload to dockerhub
|
||||
run: deployment/scripts/branded-images.upload.sh
|
||||
26
.github/workflows/publish.yml
vendored
26
.github/workflows/publish.yml
vendored
@ -292,18 +292,26 @@ jobs:
|
||||
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_ENV
|
||||
echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
|
||||
- run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
|
||||
- name: Repository Dispatch
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
event-type: trigger-build-success
|
||||
repository: ${{ github.repository }}
|
||||
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}'
|
||||
#- name: Repository Dispatch
|
||||
# uses: peter-evans/repository-dispatch@v2
|
||||
# with:
|
||||
# token: ${{ github.token }}
|
||||
# event-type: trigger-ocelot-build-success
|
||||
# repository: ${{ github.repository }}
|
||||
# client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}'
|
||||
|
||||
- name: Repository Dispatch stage.ocelot.social
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
with:
|
||||
token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository
|
||||
event-type: trigger-build-success
|
||||
event-type: trigger-ocelot-build-success
|
||||
repository: 'Ocelot-Social-Community/stage.ocelot.social'
|
||||
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}'
|
||||
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "GITHUB_RUN_NUMBER": "${{ env.GITHUB_RUN_NUMBER }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}'
|
||||
|
||||
- name: Repository Dispatch stage.yunite.me
|
||||
uses: peter-evans/repository-dispatch@v2
|
||||
with:
|
||||
token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository
|
||||
event-type: trigger-ocelot-build-success
|
||||
repository: 'Yunite-Net/stage.yunite.me'
|
||||
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "GITHUB_RUN_NUMBER": "${{ env.GITHUB_RUN_NUMBER }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}'
|
||||
120
.github/workflows/test-backend.yml
vendored
Normal file
120
.github/workflows/test-backend.yml
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
name: ocelot.social backend test CI
|
||||
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes - Backend
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
backend: ${{ steps.changes.outputs.backend }}
|
||||
docker: ${{ steps.changes.outputs.docker }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
- name: Check for frontend file changes
|
||||
uses: dorny/paths-filter@v2.11.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
list-files: shell
|
||||
|
||||
build_test_neo4j:
|
||||
name: Docker Build Test - Neo4J
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Neo4J | Build 'community' image
|
||||
run: |
|
||||
docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/
|
||||
docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-neo4j-image
|
||||
path: /tmp/neo4j.tar
|
||||
|
||||
build_test_backend:
|
||||
name: Docker Build Test - Backend
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: backend | Build 'test' image
|
||||
run: |
|
||||
docker build --target test -t "ocelotsocialnetwork/backend:test" backend/
|
||||
docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-backend-test
|
||||
path: /tmp/backend.tar
|
||||
|
||||
lint_backend:
|
||||
name: Lint Backend
|
||||
if: needs.files-changed.outputs.backend == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: backend | Lint
|
||||
run: cd backend && yarn && yarn run lint
|
||||
|
||||
unit_test_backend:
|
||||
name: Unit tests - Backend
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true'
|
||||
needs: [files-changed, build_test_neo4j, build_test_backend]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Download Docker Image (Neo4J)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-neo4j-image
|
||||
path: /tmp
|
||||
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/neo4j.tar
|
||||
|
||||
- name: Download Docker Image (Backend)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-backend-test
|
||||
path: /tmp
|
||||
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/backend.tar
|
||||
|
||||
- name: backend | copy env files webapp
|
||||
run: cp webapp/.env.template webapp/.env
|
||||
- name: backend | copy env files backend
|
||||
run: cp backend/.env.template backend/.env
|
||||
|
||||
- name: backend | docker-compose
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps neo4j backend
|
||||
|
||||
- name: backend | Initialize Database
|
||||
run: docker-compose exec -T backend yarn db:migrate init
|
||||
|
||||
- name: backend | Migrate Database Up
|
||||
run: docker-compose exec -T backend yarn db:migrate up
|
||||
|
||||
- name: backend | Unit test incl. coverage check
|
||||
run: docker-compose exec -T backend yarn test
|
||||
41
.github/workflows/test-e2e.yml
vendored
Normal file
41
.github/workflows/test-e2e.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
name: ocelot.social end-to-end test CI
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
fullstack_tests:
|
||||
name: Fullstack tests
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
jobs: 8
|
||||
strategy:
|
||||
matrix:
|
||||
# run copies of the current job in parallel
|
||||
job: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: webapp | copy env file
|
||||
run: cp webapp/.env.template webapp/.env
|
||||
|
||||
- name: backend | copy env file
|
||||
run: cp backend/.env.template backend/.env
|
||||
|
||||
- name: boot up test system | docker-compose
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend
|
||||
|
||||
- name: cypress | Fullstack tests
|
||||
id: e2e-tests
|
||||
run: |
|
||||
yarn install
|
||||
yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} )
|
||||
|
||||
##########################################################################
|
||||
# UPLOAD SCREENSHOTS - IF TESTS FAIL #####################################
|
||||
##########################################################################
|
||||
- name: Full stack tests | if any test failed, upload screenshots
|
||||
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cypress-screenshots
|
||||
path: cypress/screenshots/
|
||||
101
.github/workflows/test-webapp.yml
vendored
Normal file
101
.github/workflows/test-webapp.yml
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
name: ocelot.social webapp test CI
|
||||
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
name: Detect File Changes - Webapp
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
docker: ${{ steps.changes.outputs.docker }}
|
||||
webapp: ${{ steps.changes.outputs.webapp }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3.3.0
|
||||
|
||||
- name: Check for frontend file changes
|
||||
uses: dorny/paths-filter@v2.11.1
|
||||
id: changes
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
filters: .github/file-filters.yml
|
||||
list-files: shell
|
||||
|
||||
prepare:
|
||||
name: Prepare
|
||||
if: needs.files-changed.outputs.webapp
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Check translation files
|
||||
run: |
|
||||
scripts/translations/sort.sh
|
||||
scripts/translations/missing-keys.sh
|
||||
|
||||
build_test_webapp:
|
||||
name: Docker Build Test - Webapp
|
||||
if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp
|
||||
needs: [files-changed, prepare]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: webapp | Build 'test' image
|
||||
run: |
|
||||
docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/
|
||||
docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-webapp-test
|
||||
path: /tmp/webapp.tar
|
||||
|
||||
lint_webapp:
|
||||
name: Lint Webapp
|
||||
if: needs.files-changed.outputs.webapp
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: webapp | Lint
|
||||
run: cd webapp && yarn && yarn run lint
|
||||
|
||||
unit_test_webapp:
|
||||
name: Unit Tests - Webapp
|
||||
if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp
|
||||
needs: [files-changed, build_test_webapp]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Download Docker Image (Webapp)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-webapp-test
|
||||
path: /tmp
|
||||
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/webapp.tar
|
||||
|
||||
- name: backend | copy env files webapp
|
||||
run: cp webapp/.env.template webapp/.env
|
||||
|
||||
- name: backend | copy env files backend
|
||||
run: cp backend/.env.template backend/.env
|
||||
|
||||
- name: backend | docker-compose
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp
|
||||
|
||||
- name: webapp | Unit tests incl. coverage check
|
||||
run: docker-compose exec -T webapp yarn test
|
||||
|
||||
344
.github/workflows/test.yml
vendored
344
.github/workflows/test.yml
vendored
@ -1,344 +0,0 @@
|
||||
name: ocelot.social test CI
|
||||
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
##############################################################################
|
||||
# JOB: PREPARE #####################################################
|
||||
##############################################################################
|
||||
prepare:
|
||||
name: Prepare
|
||||
runs-on: ubuntu-latest
|
||||
# needs: [nothing]
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# TODO: DO STUFF ??? #####################################################
|
||||
##########################################################################
|
||||
- name: Check translation files
|
||||
run: |
|
||||
scripts/translations/sort.sh
|
||||
scripts/translations/missing-keys.sh
|
||||
|
||||
##############################################################################
|
||||
# JOB: DOCKER BUILD TEST NEO4J ###############################################
|
||||
##############################################################################
|
||||
build_test_neo4j:
|
||||
name: Docker Build Test - Neo4J
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# NEO4J ##################################################################
|
||||
##########################################################################
|
||||
- name: Neo4J | Build `community` image
|
||||
run: |
|
||||
docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/
|
||||
docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-neo4j-image
|
||||
path: /tmp/neo4j.tar
|
||||
|
||||
##############################################################################
|
||||
# JOB: DOCKER BUILD TEST BACKEND #############################################
|
||||
##############################################################################
|
||||
build_test_backend:
|
||||
name: Docker Build Test - Backend
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# BUILD BACKEND DOCKER IMAGE (build) #####################################
|
||||
##########################################################################
|
||||
- name: backend | Build `test` image
|
||||
run: |
|
||||
docker build --target test -t "ocelotsocialnetwork/backend:test" backend/
|
||||
docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-backend-test
|
||||
path: /tmp/backend.tar
|
||||
|
||||
##############################################################################
|
||||
# JOB: DOCKER BUILD TEST WEBAPP ##############################################
|
||||
##############################################################################
|
||||
build_test_webapp:
|
||||
name: Docker Build Test - WebApp
|
||||
runs-on: ubuntu-latest
|
||||
needs: [prepare]
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# BUILD WEBAPP DOCKER IMAGE (build) ######################################
|
||||
##########################################################################
|
||||
- name: webapp | Build `test` image
|
||||
run: |
|
||||
docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/
|
||||
docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: docker-webapp-test
|
||||
path: /tmp/webapp.tar
|
||||
|
||||
##############################################################################
|
||||
# JOB: LINT BACKEND ##########################################################
|
||||
##############################################################################
|
||||
lint_backend:
|
||||
name: Lint backend
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_test_backend]
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# DOWNLOAD DOCKER IMAGE ##################################################
|
||||
##########################################################################
|
||||
- name: Download Docker Image (Backend)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-backend-test
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/backend.tar
|
||||
##########################################################################
|
||||
# LINT BACKEND ###########################################################
|
||||
##########################################################################
|
||||
- name: backend | Lint
|
||||
run: docker run --rm ocelotsocialnetwork/backend:test yarn run lint
|
||||
|
||||
##############################################################################
|
||||
# JOB: LINT WEBAPP ###########################################################
|
||||
##############################################################################
|
||||
lint_webapp:
|
||||
name: Lint webapp
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_test_webapp]
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# DOWNLOAD DOCKER IMAGE ##################################################
|
||||
##########################################################################
|
||||
- name: Download Docker Image (Webapp)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-webapp-test
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/webapp.tar
|
||||
##########################################################################
|
||||
# LINT WEBAPP ############################################################
|
||||
##########################################################################
|
||||
- name: webapp | Lint
|
||||
run: docker run --rm ocelotsocialnetwork/webapp:test yarn run lint
|
||||
|
||||
##############################################################################
|
||||
# JOB: UNIT TEST BACKEND #####################################################
|
||||
##############################################################################
|
||||
unit_test_backend:
|
||||
name: Unit tests - backend
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_test_neo4j,build_test_backend]
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# DOWNLOAD DOCKER IMAGES #################################################
|
||||
##########################################################################
|
||||
- name: Download Docker Image (Neo4J)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-neo4j-image
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/neo4j.tar
|
||||
- name: Download Docker Image (Backend)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-backend-test
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/backend.tar
|
||||
##########################################################################
|
||||
# UNIT TESTS BACKEND #####################################################
|
||||
##########################################################################
|
||||
- name: backend | copy env files webapp
|
||||
run: cp webapp/.env.template webapp/.env
|
||||
- name: backend | copy env files backend
|
||||
run: cp backend/.env.template backend/.env
|
||||
- name: backend | docker-compose
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps neo4j backend
|
||||
- name: backend | Initialize Database
|
||||
run: docker-compose exec -T backend yarn db:migrate init
|
||||
- name: backend | Migrate Database Up
|
||||
run: docker-compose exec -T backend yarn db:migrate up
|
||||
- name: backend | Unit test
|
||||
run: docker-compose exec -T backend yarn test
|
||||
##########################################################################
|
||||
# COVERAGE CHECK BACKEND #################################################
|
||||
##########################################################################
|
||||
- name: backend | Coverage check
|
||||
uses: webcraftmedia/coverage-check-action@master
|
||||
with:
|
||||
report_name: Coverage Backend
|
||||
type: lcov
|
||||
result_path: ./coverage/lcov.info
|
||||
min_coverage: 57
|
||||
token: ${{ github.token }}
|
||||
|
||||
##############################################################################
|
||||
# JOB: UNIT TEST WEBAPP ######################################################
|
||||
##############################################################################
|
||||
unit_test_webapp:
|
||||
name: Unit tests - webapp
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_test_webapp]
|
||||
permissions:
|
||||
checks: write
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# DOWNLOAD DOCKER IMAGES #################################################
|
||||
##########################################################################
|
||||
- name: Download Docker Image (Webapp)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-webapp-test
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/webapp.tar
|
||||
##########################################################################
|
||||
# UNIT TESTS WEBAPP ######################################################
|
||||
##########################################################################
|
||||
- name: backend | copy env files webapp
|
||||
run: cp webapp/.env.template webapp/.env
|
||||
- name: backend | copy env files backend
|
||||
run: cp backend/.env.template backend/.env
|
||||
- name: backend | docker-compose
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp
|
||||
- name: webapp | Unit tests
|
||||
run: docker-compose exec -T webapp yarn test
|
||||
##########################################################################
|
||||
# COVERAGE REPORT FRONTEND ################################################
|
||||
##########################################################################
|
||||
#- name: frontend | Coverage report
|
||||
# uses: romeovs/lcov-reporter-action@v0.2.21
|
||||
# with:
|
||||
# github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# lcov-file: ./coverage/lcov.info
|
||||
##########################################################################
|
||||
# COVERAGE CHECK WEBAPP ##################################################
|
||||
##########################################################################
|
||||
- name: webapp | Coverage check
|
||||
uses: webcraftmedia/coverage-check-action@master
|
||||
with:
|
||||
report_name: Coverage Webapp
|
||||
type: lcov
|
||||
result_path: ./coverage/lcov.info
|
||||
min_coverage: 83
|
||||
token: ${{ github.token }}
|
||||
|
||||
##############################################################################
|
||||
# JOB: FULLSTACK TESTS #######################################################
|
||||
##############################################################################
|
||||
fullstack_tests:
|
||||
name: Fullstack tests
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build_test_webapp, build_test_backend, build_test_neo4j]
|
||||
env:
|
||||
jobs: 8
|
||||
strategy:
|
||||
matrix:
|
||||
# run copies of the current job in parallel
|
||||
job: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
steps:
|
||||
##########################################################################
|
||||
# CHECKOUT CODE ##########################################################
|
||||
##########################################################################
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
##########################################################################
|
||||
# DOWNLOAD DOCKER IMAGES #################################################
|
||||
##########################################################################
|
||||
- name: Download Docker Image (Neo4J)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-neo4j-image
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/neo4j.tar
|
||||
- name: Download Docker Image (Backend)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-backend-test
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/backend.tar
|
||||
- name: Download Docker Image (Webapp)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: docker-webapp-test
|
||||
path: /tmp
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/webapp.tar
|
||||
##########################################################################
|
||||
# FULLSTACK TESTS CYPRESS ################################################
|
||||
##########################################################################
|
||||
- name: webapp | copy env files webapp
|
||||
run: cp webapp/.env.template webapp/.env
|
||||
- name: backend | copy env files backend
|
||||
run: cp backend/.env.template backend/.env
|
||||
- name: backend | docker-compose
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend
|
||||
- name: cypress | Fullstack tests
|
||||
id: e2e-tests
|
||||
run: |
|
||||
yarn install
|
||||
yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} )
|
||||
##########################################################################
|
||||
# UPLOAD SCREENSHOTS - IF TESTS FAIL #####################################
|
||||
##########################################################################
|
||||
- name: Full stack tests | if any test failed, upload screenshots
|
||||
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: cypress-screenshots
|
||||
path: cypress/screenshots/
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "styleguide"]
|
||||
path = styleguide
|
||||
url = https://github.com/Human-Connection/Nitro-Styleguide.git
|
||||
[submodule "deployment/configurations/stage.ocelot.social"]
|
||||
path = deployment/configurations/stage.ocelot.social
|
||||
url = git@github.com:Ocelot-Social-Community/stage.ocelot.social.git
|
||||
|
||||
84
.travis.yml
84
.travis.yml
@ -1,84 +0,0 @@
|
||||
dist: xenial
|
||||
language: node_js
|
||||
node_js: lts/*
|
||||
cache:
|
||||
yarn: false
|
||||
npm: false
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libgconf-2-4
|
||||
snaps:
|
||||
- docker
|
||||
firefox: "latest-esr"
|
||||
|
||||
install:
|
||||
- yarn global add wait-on
|
||||
# Install Codecov
|
||||
- yarn install --frozen-lockfile
|
||||
- cp backend/.env.template backend/.env
|
||||
|
||||
before_script:
|
||||
- docker-compose -f docker-compose.yml build --parallel
|
||||
- docker-compose -f docker-compose.yml -f docker-compose.build-and-test.yml build # just tagging, just be quite fast
|
||||
- docker-compose -f docker-compose.yml -f docker-compose.build-and-test.yml up -d
|
||||
- wait-on http://localhost:7474
|
||||
- docker-compose -f docker-compose.yml -f docker-compose.build-and-test.yml exec backend yarn run db:migrate init
|
||||
|
||||
script:
|
||||
- export CYPRESS_RETRIES=1
|
||||
- export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
|
||||
- echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH"
|
||||
# Miscellaneous
|
||||
- ./scripts/translations/sort.sh
|
||||
- ./scripts/translations/missing-keys.sh
|
||||
# Backend
|
||||
- docker-compose exec backend yarn run lint
|
||||
- docker-compose exec backend yarn run test --ci --verbose=false --coverage
|
||||
- docker-compose exec backend yarn run db:seed
|
||||
- docker-compose exec backend yarn run db:reset
|
||||
# Frontend
|
||||
- docker-compose exec webapp yarn run lint
|
||||
- docker-compose exec webapp yarn run test --ci --verbose=false --coverage
|
||||
# Fullstack
|
||||
- docker-compose down
|
||||
- docker-compose -f docker-compose.yml up -d
|
||||
- wait-on http://localhost:7474
|
||||
# disable for last deploy, because of flakiness!
|
||||
# - yarn run cypress:run --record
|
||||
# - yarn run cucumber
|
||||
# Coverage
|
||||
# disable this uneffective thing for last deploy, because of easyness!
|
||||
# - yarn run codecov
|
||||
|
||||
after_success:
|
||||
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
|
||||
- chmod +x send.sh
|
||||
- ./send.sh success $WEBHOOK_URL
|
||||
- if [ $TRAVIS_BRANCH == "master" ] && [ $TRAVIS_EVENT_TYPE == "push" ]; then
|
||||
wget https://raw.githubusercontent.com/Human-Connection/Discord-Bot/develop/tester.sh &&
|
||||
chmod +x tester.sh &&
|
||||
./tester.sh staging $WEBHOOK_URL;
|
||||
fi
|
||||
|
||||
after_failure:
|
||||
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh
|
||||
- chmod +x send.sh
|
||||
- ./send.sh failure $WEBHOOK_URL
|
||||
|
||||
before_deploy:
|
||||
- go get -u github.com/tcnksm/ghr
|
||||
# stop deployment to kubernetes until we have set it up
|
||||
# - ./scripts/setup_kubernetes.sh
|
||||
|
||||
deploy:
|
||||
- provider: script
|
||||
script: bash scripts/docker_push.sh
|
||||
on:
|
||||
branch: master
|
||||
# stop deployment to kubernetes until we have set it up
|
||||
# - provider: script
|
||||
# script: bash scripts/deploy.sh
|
||||
# on:
|
||||
# branch: master
|
||||
169
CHANGELOG.md
169
CHANGELOG.md
@ -4,8 +4,177 @@ All notable changes to this project will be documented in this file. Dates are d
|
||||
|
||||
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
|
||||
#### [2.6.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.1...2.6.0)
|
||||
|
||||
- fix(other): docker-compose for rebranding deployment [`#6265`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6265)
|
||||
- feat(webapp): default categories of group for posts in group [`#6259`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6259)
|
||||
- refactor(webapp): make action radius select in group form a reusable component [`#6244`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6244)
|
||||
- fix(webapp): show avatar for group members [`#6258`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6258)
|
||||
- fix(webapp): fix search for 3 chars [`#6256`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6256)
|
||||
- fix(backend): group posts cannot be pinned [`#6242`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6242)
|
||||
- Bump metascraper-soundcloud from 5.33.5 to 5.34.2 in /backend [`#6213`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6213)
|
||||
- refactor(other): refactor test workflows [`#6151`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6151)
|
||||
- fix(other): deployment fix typo, update stage.ocelot.social reference [`#6230`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6230)
|
||||
- fix(other): bump metascraper-url from 5.33.5 to 5.34.2 in /backend [`#6217`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6217)
|
||||
- fix(other): workflow typo [`#6235`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6235)
|
||||
- feat(other): publish stage.yunite.me hook [`#6234`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6234)
|
||||
- fix(other): reduce kubernetes memory limits [`#6229`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6229)
|
||||
- fix(other): deployment for branded image with custom names [`#6228`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6228)
|
||||
- Bump node from 19.8.1-alpine3.17 to 19.9.0-alpine3.17 in /backend [`#6219`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6219)
|
||||
- Bump node from 19.8.1-alpine3.17 to 19.9.0-alpine3.17 in /webapp [`#6220`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6220)
|
||||
- feat(other): deployment pod resources [`#6132`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6132)
|
||||
- Bump @babel/core from 7.12.17 to 7.21.4 in /webapp [`#6215`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6215)
|
||||
- Bump jsonwebtoken from 8.5.1 to 9.0.0 in /webapp [`#6079`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6079)
|
||||
- Bump jest from 29.4.2 to 29.5.0 in /webapp [`#6094`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6094)
|
||||
- Bump babel-jest from 29.4.2 to 29.5.0 in /webapp [`#6095`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6095)
|
||||
- Bump neode from 0.4.8 to 0.4.9 in /backend [`#6075`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6075)
|
||||
- Bump node from 19.4.0-alpine3.17 to 19.8.1-alpine3.17 in /webapp [`#6155`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6155)
|
||||
- Bump node from 19.4.0-alpine3.17 to 19.8.1-alpine3.17 in /backend [`#6156`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6156)
|
||||
- Bump @babel/core from 7.9.0 to 7.21.4 [`#6200`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6200)
|
||||
- Bump @babel/preset-env from 7.12.7 to 7.21.4 [`#6204`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6204)
|
||||
- Bump expect from 25.3.0 to 29.5.0 [`#6098`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6098)
|
||||
- separate test workflows [`3533a36`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3533a36cdc811c0e1dae218fbc2184f7c4bc3951)
|
||||
- get it working [`8df7d5d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/8df7d5d265b0c5ba16f167a213631d765d2f985e)
|
||||
- feat(webapp): group categories on posts [`3244f3f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3244f3f86d1e8c09e0fd49f43c49f0a3aa8b85ab)
|
||||
|
||||
#### [2.5.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.0...2.5.1)
|
||||
|
||||
> 23 March 2023
|
||||
|
||||
- chore(other): release v2.5.1 – fix filter menu width [`#6180`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6180)
|
||||
- feat(webapp): add tooltips to all menu icons [`#6185`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6185)
|
||||
- fix(webapp): popup filter max-width [`#6177`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6177)
|
||||
- Add tooltip to header notifications menu [`28505a5`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/28505a5b181008ebcde6fa58b7a4a8459a492018)
|
||||
- Add tooltip to header avatar menu [`4c0469f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4c0469f61a3c2fae23e50c6a5a2a91b63fac149a)
|
||||
- Release v2.5.1 - fix filter menu width [`08def14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/08def14cafef7816d8e43f1896430400bda9635d)
|
||||
|
||||
#### [2.5.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.4.0...2.5.0)
|
||||
|
||||
> 21 March 2023
|
||||
|
||||
- chore(other): release v2.5.0 [`#6172`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6172)
|
||||
- fix(other): publish transmit github run number properly [`#6171`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6171)
|
||||
- feat(other): deployment include GitHub run number on branded images [`#6170`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6170)
|
||||
- fix(backend): new migration to create search indexes [`#6167`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6167)
|
||||
- fix(other): prevent exposing secrets in the github actions by not setting debug mode on cluster deploy [`#6168`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6168)
|
||||
- feat(other): echo current configuration when running scripts [`#6169`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6169)
|
||||
- refactor(other): build & deployment of branded images on stage.ocelot.social [`#6163`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6163)
|
||||
- fix(webapp): close popover notification menu [`#6166`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6166)
|
||||
- fix(webapp): small buttons in notifications menu [`#6162`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6162)
|
||||
- fix(webapp): revert pr `on newsfeed add bigger y-gap between posts #6121` [`#6164`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6164)
|
||||
- fix(webapp): join leave button for pending members [`#6152`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6152)
|
||||
- feat(backend): notifications for groups [`#6150`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6150)
|
||||
- feat(webapp): add hint text to create and edit a post of a group aside of the save and abort buttons [`#6114`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6114)
|
||||
- fix(other): use access token to trigger build on external repo [`#6145`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6145)
|
||||
- feat(webapp): set different icon and text on join leave button, when member is pending [`#6124`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6124)
|
||||
- refactor(other): deployment upgrade to specific version, trigger build on stage [`#6143`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6143)
|
||||
- feat(webapp): show 2 GroupItem per row in GroupList [`#6135`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6135)
|
||||
- fix(backend): do not delete migrations on db reset [`#6136`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6136)
|
||||
- feat(other): deployment reseed [`#6129`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6129)
|
||||
- feat(other): deployment secrets [`#6120`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6120)
|
||||
- feat(webapp): refactor notification page [`#6116`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6116)
|
||||
- fix(webapp): fix ribbons position [`#6130`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6130)
|
||||
- fix(webapp): fix donation bar blink [`#6107`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6107)
|
||||
- feat(webapp): change order of groups to new first [`#6122`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6122)
|
||||
- fix(webapp): error in user profil on the 'show x more' button [`#6093`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6093)
|
||||
- feat(webapp): filter button style change [`#6109`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6109)
|
||||
- refactor(other): deactivate video recording & only upload screenshots, if tests fail for e2e tests [`#6125`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6125)
|
||||
- fix(webapp): change icon color of active topics (categories) of post teaser [`#6112`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6112)
|
||||
- docs(other): correct **/README.md [`#6059`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6059)
|
||||
- fix(webapp): fix `viewport``width=device-width` by removing it [`#6110`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6110)
|
||||
- feat(webapp): on newsfeed add bigger y-gap between posts [`#6121`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6121)
|
||||
- Bump peter-evans/repository-dispatch from 1 to 2 [`#6117`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6117)
|
||||
- fix(webapp): fix gap news feed [`#6065`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6065)
|
||||
- feat(webapp): change shout icon `bullhorn` to `heart-o` [`#6115`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6115)
|
||||
- refactor(webapp): change invite code button and menu to copy invite link [`#6108`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6108)
|
||||
- feat(webapp): change group filter button text [`#6105`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6105)
|
||||
- feat(webapp): 🍰 allows mark all notifications as read [`#3922`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3922)
|
||||
- fix(other): deploy branded - upload to dockerhub [`#6099`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6099)
|
||||
- feat(webapp): remove user from group [`#6072`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6072)
|
||||
- chore(other): remove apple m1 docker overrides [`#6056`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6056)
|
||||
- refactor(other): ocelot publish workflows [`#6083`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6083)
|
||||
- fix(other): lint pr only on pullrequest [`#6088`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6088)
|
||||
- fix(other): dependabot do not rebase [`#6096`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6096)
|
||||
- feat(backend): filter posts in my groups [`#6091`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6091)
|
||||
- refactor(backend): withdraw mock of gql and replace with graphql-tag function [`#6022`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6022)
|
||||
- docs(other): update readme.md [`#6090`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6090)
|
||||
- feat(webapp): adjust and create branding possibilities [`#6063`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6063)
|
||||
- fix(other): exclude dependabot from pr title linting [`#6085`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6085)
|
||||
- feat(webapp): change ``Benutzer`` to ``Nutzer`` [`#6027`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6027)
|
||||
- docs(webapp): change the used nvm version [`#6023`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6023)
|
||||
- feat(other): backup script [`#6051`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6051)
|
||||
- fix(backend): user or group has null as description [`#5996`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5996)
|
||||
- feat(other): script to set a cluster in maintenance mode [`#6042`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6042)
|
||||
- feat(other): fix dependabot [`#6035`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6035)
|
||||
- fix(other): fix maintenance page & maintenance build [`#6032`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6032)
|
||||
- refactor(webapp): upgrade jest and vue test util [`#5968`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5968)
|
||||
- refactor(other): deployment [`#5975`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5975)
|
||||
- fix(webapp): remove additional markers from map [`#6021`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6021)
|
||||
- feat(webapp): add align center to the user profile slug [`#6012`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6012)
|
||||
- chore(other): update github actions for node 16 [`#5971`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5971)
|
||||
- refactor(backend): update jest [`#5964`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5964)
|
||||
- Revert "V2.3.0" [`#95`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/95)
|
||||
- V2.3.0 [`#94`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/94)
|
||||
- v2.3.0-281 [`#93`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/93)
|
||||
- rebranding for yunite [`#26`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/26)
|
||||
- feat(webapp): copy fonts from assets [`#25`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/25)
|
||||
- feat(webapp): copy fonts from assets [`#92`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/92)
|
||||
- chore: 🍰 Release v2.2.0-267 – Fixes And Groups Page Etc. [`#19`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/19)
|
||||
- fix: 🍰 Change Hasttag Menu Search Color To `#17b53f` [`#21`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/21)
|
||||
- chore: 🍰 Release v2.2.0-267 [`#90`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/90)
|
||||
- Docu Updates [`#86`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/86)
|
||||
- chore: 🍰 Release v2.1.0-253 – Merge Groups Into master – Epic Groups [`#12`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/12)
|
||||
- chore: 🍰 Release v2.1.0-253 [`#87`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/87)
|
||||
- chore: [WIP] 🍰 Release v2.0.0-250 – Groups – Configurable Header Menu Is Translatable Etc. [`#16`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/16)
|
||||
- chore: 🍰 Release v2.0.0 – Groups Etc. – Extend Rebranding And Deployment [`#83`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/83)
|
||||
- fix: 🍰 Fix Implementation Of Overwriting Locales [`#80`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/80)
|
||||
- feat: 🍰 Merge Locales [`#77`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/77)
|
||||
- chore: 🍰 Groups Release v1.1.1-231 - Show New Features [`#14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/14)
|
||||
- chore: 🍰 Release v1.1.1 – First Design Rebranding [`#10`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/10)
|
||||
- chore: [WIP] 🍰 Refine Rebanding And Deployment [`#8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8)
|
||||
- chore: 🍰 Fix Folder Name From `branding/assets/styles/import` To `branding/assets/styles/imports` [`#71`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/71)
|
||||
- chore: 🍰 Release v1.1.1-228 – Refactor Rebranding [`#68`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/68)
|
||||
- chore: 🍰 Release v1.1.0-205 [`#6`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6)
|
||||
- chore: 🍰 Release v1.1.0-225 [`#66`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/66)
|
||||
- chore: [WIP] 🍰 Refine Deployment Setup And Documentation [`#46`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/46)
|
||||
- chore: [WIP] 🍰 Release v1.1.0 - Implement Categories Again [`#63`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/63)
|
||||
- Update issue templates [`#3`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3)
|
||||
- chore: 🍰 Release v1.0.9-199 [`#59`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/59)
|
||||
- chore: 🍰 Implement `PRODUCTION_DB_CLEAN_ALLOW` for Staging Production Environments [`#56`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/56)
|
||||
- chore: 🍰 Add Docker Compose Override For Apple M1 And Docu [`#57`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/57)
|
||||
- Chore: 🍰 Fix `apiVersion: cert-manager.io/v1alpha2` To `*/v1` [`#53`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/53)
|
||||
- chore: 🍰 Adjust `maintenance` Container Name In Deployment With Helm [`#50`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/50)
|
||||
- chore: 🍰 Release New Build Version `v1.0.8-184` [`#51`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/51)
|
||||
- chore: 🍰 Rename Neo4j Docker Image In General To `neo4j-community:*` [`#49`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/49)
|
||||
- feat: 🍰 Release v1.0.8 – Configure Cookie Expire Time – second run [`#44`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/44)
|
||||
- feat: 🍰 Configure Cookie Expire Time [`#43`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/43)
|
||||
- docs: 🍰 Add Docs For Backups, Rollbacks, And Release v1.0.7-171 [`#40`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/40)
|
||||
- chore: 🍰 Realease v1.0.6-170 [`#37`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/37)
|
||||
- chore: 🍰 Refactor FAQ Link To Use Internal Page Which Was Implemented Before [`#36`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/36)
|
||||
- chore: 🍰 Add Branding Templates For Terms And Conditions Etc. [`#32`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/32)
|
||||
- feat: 🍰 Add Rebranded E-Mails For Sending Notifications [`#29`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/29)
|
||||
- bug: 🍰 Fix Minor Errors And Clarify Docs [`#28`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/28)
|
||||
- chore: 🍰 Implement New Internal Pages – Main Release v1.0.5 [`#25`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/25)
|
||||
- feat: [WIP] 🍰 Add Landing Page Etc. [`#22`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/22)
|
||||
- docs: 🍰 [WIP] Add Configure And Rebranding Readme.md [`#20`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/20)
|
||||
- chore: [WIP] 🍰 New Deployment With 'base' And 'code' Docker Images [`#15`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/15)
|
||||
- feat: [WIP] 🍰 Flexible Footer Links [`#17`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/17)
|
||||
- 💥 Release v1.0.3 [`#12`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/12)
|
||||
- 🛠 [Refactor] Add README And LICENSE [`#11`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/11)
|
||||
- chore: 🍰 Implement Use Of package.json 'Version' Etc. For Build And Refine Helm Chart [`#8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8)
|
||||
- chore: 🍰 Replace Ocelot Logos 619x593 With 600x570 [`#6`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6)
|
||||
- brand_as_default [`#4`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4)
|
||||
- limit_replicasets [`#3`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3)
|
||||
- Deployment [`#2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2)
|
||||
- moved example into stage.ocelot.social [`61b5112`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/61b5112b8b547a7491d644c7c4dbfead39b61d79)
|
||||
- feat(backand): upgrade jest to 29.4 [`4390d72`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4390d72477fb941f69bc9bdc24ac7713ef06e827)
|
||||
- pages tests nearly working [`4850e45`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4850e456fe5b7c158f23acc7f153576472604300)
|
||||
|
||||
#### [2.4.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.3.0...2.4.0)
|
||||
|
||||
> 10 February 2023
|
||||
|
||||
- chore(release): v2.4.0 [`#5961`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5961)
|
||||
- fix(webapp): post teaser width in mobile view [`#5958`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5958)
|
||||
- fix(webapp): navbar disappears when scrolling to top [`#5957`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5957)
|
||||
- fix(webapp): close mobile menu on all links [`#5956`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5956)
|
||||
|
||||
@ -13,7 +13,7 @@ docker-compose*.yml
|
||||
|
||||
node_modules/
|
||||
scripts/
|
||||
dist/
|
||||
build/
|
||||
|
||||
maintenance-worker/
|
||||
neo4j/
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
DEBUG=true
|
||||
|
||||
NEO4J_URI=bolt://localhost:7687
|
||||
NEO4J_USERNAME=neo4j
|
||||
NEO4J_PASSWORD=letmein
|
||||
|
||||
2
backend/.gitignore
vendored
2
backend/.gitignore
vendored
@ -3,7 +3,7 @@ node_modules/
|
||||
.vscode
|
||||
.idea
|
||||
yarn-error.log
|
||||
dist/*
|
||||
build/*
|
||||
coverage.lcov
|
||||
.nyc_output/
|
||||
public/uploads/*
|
||||
|
||||
@ -1 +1 @@
|
||||
v19.4.0
|
||||
v20.2.0
|
||||
@ -1,7 +1,7 @@
|
||||
##################################################################################
|
||||
# BASE (Is pushed to DockerHub for rebranding) ###################################
|
||||
##################################################################################
|
||||
FROM node:19.4.0-alpine3.17 as base
|
||||
FROM node:20.2.0-alpine3.17 as base
|
||||
|
||||
# ENVs
|
||||
## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame
|
||||
@ -90,7 +90,7 @@ CMD /bin/sh -c "yarn run dev"
|
||||
FROM base as production
|
||||
|
||||
# Copy "binary"-files from build image
|
||||
COPY --from=build ${DOCKER_WORKDIR}/dist ./dist
|
||||
COPY --from=build ${DOCKER_WORKDIR}/build ./build
|
||||
COPY --from=build ${DOCKER_WORKDIR}/node_modules ./node_modules
|
||||
# Copy static files
|
||||
# TODO - externalize the uploads so we can copy the whole folder
|
||||
|
||||
@ -5,10 +5,14 @@ module.exports = {
|
||||
'**/*.js',
|
||||
'!**/node_modules/**',
|
||||
'!**/test/**',
|
||||
'!**/dist/**',
|
||||
'!**/build/**',
|
||||
'!**/src/**/?(*.)+(spec|test).js?(x)'
|
||||
],
|
||||
coverageReporters: ['lcov', 'text'],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 57,
|
||||
},
|
||||
},
|
||||
testMatch: ['**/src/**/?(*.)+(spec|test).js?(x)'],
|
||||
setupFilesAfterEnv: ['<rootDir>/test/setup.js']
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ocelot-social-backend",
|
||||
"version": "2.4.0",
|
||||
"version": "2.6.0",
|
||||
"description": "GraphQL Backend for ocelot.social",
|
||||
"repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social",
|
||||
"author": "ocelot.social Community",
|
||||
@ -9,10 +9,10 @@
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"__migrate": "migrate --compiler 'js:@babel/register' --migrations-dir ./src/db/migrations",
|
||||
"prod:migrate": "migrate --migrations-dir ./dist/db/migrations --store ./dist/db/migrate/store.js",
|
||||
"start": "node dist/",
|
||||
"build": "babel src/ -d dist/ --copy-files",
|
||||
"dev": "nodemon --exec babel-node src/ -e js,gql",
|
||||
"prod:migrate": "migrate --migrations-dir ./build/db/migrations --store ./build/db/migrate/store.js",
|
||||
"start": "node build/",
|
||||
"build": "tsc && mkdir -p build/middleware/helpers/email/templates/ && cp -r src/middleware/helpers/email/templates/*.html build/middleware/helpers/email/templates/ && mkdir -p build/middleware/helpers/email/templates/en/ && cp -r src/middleware/helpers/email/templates/en/*.html build/middleware/helpers/email/templates/en/ && mkdir -p build/middleware/helpers/email/templates/de/ && cp -r src/middleware/helpers/email/templates/de/*.html build/middleware/helpers/email/templates/de/ && mkdir -p build/schema/types/ && cp -r src/schema/types/*.gql build/schema/types/ && mkdir -p build/schema/types/enum/ && cp -r src/schema/types/enum/*.gql build/schema/types/enum/ && mkdir -p build/schema/types/scalar/ && cp -r src/schema/types/scalar/*.gql build/schema/types/scalar/ && mkdir -p build/schema/types/type/ && cp -r src/schema/types/type/*.gql build/schema/types/type/",
|
||||
"dev": "nodemon --exec ts-node src/ -e js,ts,gql",
|
||||
"dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql",
|
||||
"lint": "eslint src --config .eslintrc.js",
|
||||
"test": "cross-env NODE_ENV=test NODE_OPTIONS=--max-old-space-size=8192 jest --runInBand --coverage --forceExit --detectOpenHandles",
|
||||
@ -29,7 +29,6 @@
|
||||
"@babel/plugin-proposal-throw-expressions": "^7.8.3",
|
||||
"@babel/preset-env": "~7.9.5",
|
||||
"@babel/register": "^7.9.0",
|
||||
"@hapi/joi": "^17.1.1",
|
||||
"@sentry/node": "^5.15.4",
|
||||
"apollo-cache-inmemory": "~1.6.5",
|
||||
"apollo-client": "~2.6.8",
|
||||
@ -46,19 +45,16 @@
|
||||
"cheerio": "~1.0.0-rc.3",
|
||||
"cors": "~2.8.5",
|
||||
"cross-env": "~7.0.3",
|
||||
"date-fns": "2.22.1",
|
||||
"debug": "~4.1.1",
|
||||
"dotenv": "~8.2.0",
|
||||
"express": "^4.17.1",
|
||||
"graphql": "^14.6.0",
|
||||
"graphql-custom-directives": "~0.2.14",
|
||||
"graphql-iso-date": "~3.6.1",
|
||||
"graphql-middleware": "~4.0.2",
|
||||
"graphql-middleware-sentry": "^3.2.1",
|
||||
"graphql-redis-subscriptions": "^2.2.1",
|
||||
"graphql-shield": "~7.2.2",
|
||||
"graphql-tag": "~2.10.3",
|
||||
"helmet": "~3.22.0",
|
||||
"helmet": "~7.0.0",
|
||||
"ioredis": "^4.16.1",
|
||||
"jsonwebtoken": "~8.5.1",
|
||||
"languagedetect": "^2.0.0",
|
||||
@ -66,9 +62,8 @@
|
||||
"lodash": "~4.17.14",
|
||||
"merge-graphql-schemas": "^1.7.8",
|
||||
"metascraper": "^5.33.5",
|
||||
"metascraper-audio": "^5.33.5",
|
||||
"metascraper-audio": "^5.34.4",
|
||||
"metascraper-author": "^5.33.5",
|
||||
"metascraper-clearbit-logo": "^5.3.0",
|
||||
"metascraper-date": "^5.33.5",
|
||||
"metascraper-description": "^5.33.5",
|
||||
"metascraper-image": "^5.33.5",
|
||||
@ -76,9 +71,9 @@
|
||||
"metascraper-lang-detector": "^4.10.2",
|
||||
"metascraper-logo": "^5.33.5",
|
||||
"metascraper-publisher": "^5.33.5",
|
||||
"metascraper-soundcloud": "^5.33.5",
|
||||
"metascraper-soundcloud": "^5.34.4",
|
||||
"metascraper-title": "^5.33.5",
|
||||
"metascraper-url": "^5.33.5",
|
||||
"metascraper-url": "^5.34.2",
|
||||
"metascraper-video": "^5.33.5",
|
||||
"metascraper-youtube": "^5.33.5",
|
||||
"migrate": "^1.7.0",
|
||||
@ -87,23 +82,21 @@
|
||||
"mustache": "^4.2.0",
|
||||
"neo4j-driver": "^4.0.2",
|
||||
"neo4j-graphql-js": "^2.11.5",
|
||||
"neode": "^0.4.8",
|
||||
"neode": "^0.4.9",
|
||||
"node-fetch": "~2.6.1",
|
||||
"nodemailer": "^6.4.4",
|
||||
"nodemailer-html-to-text": "^3.2.0",
|
||||
"npm-run-all": "~4.1.5",
|
||||
"request": "~2.88.2",
|
||||
"sanitize-html": "~1.22.0",
|
||||
"slug": "~6.0.0",
|
||||
"subscriptions-transport-ws": "^0.9.19",
|
||||
"trunc-html": "~1.1.2",
|
||||
"uuid": "~8.3.2",
|
||||
"validator": "^13.0.0",
|
||||
"wait-on": "~4.0.1",
|
||||
"validator": "^13.9.0",
|
||||
"xregexp": "^4.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "5.1.0",
|
||||
"@faker-js/faker": "7.6.0",
|
||||
"apollo-server-testing": "~2.11.0",
|
||||
"chai": "~4.2.0",
|
||||
"cucumber": "~6.0.5",
|
||||
@ -120,7 +113,8 @@
|
||||
"nodemon": "~2.0.2",
|
||||
"prettier": "~2.3.2",
|
||||
"rosie": "^2.0.1",
|
||||
"supertest": "~4.0.2"
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.0.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"**/**/fs-capacitor": "^6.2.0",
|
||||
|
||||
@ -2,7 +2,7 @@ import { v4 as uuid } from 'uuid'
|
||||
import slugify from 'slug'
|
||||
import { hashSync } from 'bcryptjs'
|
||||
import { Factory } from 'rosie'
|
||||
import faker from '@faker-js/faker'
|
||||
import { faker } from '@faker-js/faker'
|
||||
import { getDriver, getNeode } from './neo4j'
|
||||
import CONFIG from '../config/index.js'
|
||||
import generateInviteCode from '../schema/resolvers/helpers/generateInviteCode.js'
|
||||
@ -63,7 +63,7 @@ Factory.define('basicUser')
|
||||
.option('password', '1234')
|
||||
.attrs({
|
||||
id: uuid,
|
||||
name: faker.name.findName,
|
||||
name: faker.name.fullName,
|
||||
password: '1234',
|
||||
role: 'user',
|
||||
termsAndConditionsAgreedVersion: '0.0.1',
|
||||
|
||||
@ -86,13 +86,6 @@ class Store {
|
||||
if (CONFIG.CATEGORIES_ACTIVE) await createCategories(session)
|
||||
const writeTxResultPromise = session.writeTransaction(async (txc) => {
|
||||
await txc.run('CALL apoc.schema.assert({},{},true)') // drop all indices and constraints
|
||||
return Promise.all(
|
||||
[
|
||||
'CALL db.index.fulltext.createNodeIndex("user_fulltext_search",["User"],["name", "slug"])',
|
||||
'CALL db.index.fulltext.createNodeIndex("post_fulltext_search",["Post"],["title", "content"])',
|
||||
'CALL db.index.fulltext.createNodeIndex("tag_fulltext_search",["Tag"],["id"])',
|
||||
].map((statement) => txc.run(statement)),
|
||||
)
|
||||
})
|
||||
try {
|
||||
await writeTxResultPromise
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
import { getDriver } from '../../db/neo4j'
|
||||
|
||||
export const description = ''
|
||||
|
||||
export async function up(next) {
|
||||
const driver = getDriver()
|
||||
const session = driver.session()
|
||||
const transaction = session.beginTransaction()
|
||||
|
||||
try {
|
||||
// Drop indexes if they exist because due to legacy code they might be set already
|
||||
const indexesResponse = await transaction.run(`CALL db.indexes()`)
|
||||
const indexes = indexesResponse.records.map((record) => record.get('indexName'))
|
||||
if (indexes.indexOf('user_fulltext_search') > -1) {
|
||||
await transaction.run(`CALL db.index.fulltext.drop("user_fulltext_search")`)
|
||||
}
|
||||
if (indexes.indexOf('post_fulltext_search') > -1) {
|
||||
await transaction.run(`CALL db.index.fulltext.drop("post_fulltext_search")`)
|
||||
}
|
||||
if (indexes.indexOf('tag_fulltext_search') > -1) {
|
||||
await transaction.run(`CALL db.index.fulltext.drop("tag_fulltext_search")`)
|
||||
}
|
||||
// Create indexes
|
||||
await transaction.run(
|
||||
`CALL db.index.fulltext.createNodeIndex("user_fulltext_search",["User"],["name", "slug"])`,
|
||||
)
|
||||
await transaction.run(
|
||||
`CALL db.index.fulltext.createNodeIndex("post_fulltext_search",["Post"],["title", "content"])`,
|
||||
)
|
||||
await transaction.run(
|
||||
`CALL db.index.fulltext.createNodeIndex("tag_fulltext_search",["Tag"],["id"])`,
|
||||
)
|
||||
await transaction.commit()
|
||||
next()
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error)
|
||||
await transaction.rollback()
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('rolled back')
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(next) {
|
||||
const driver = getDriver()
|
||||
const session = driver.session()
|
||||
const transaction = session.beginTransaction()
|
||||
|
||||
try {
|
||||
await transaction.run(`CALL db.index.fulltext.drop("user_fulltext_search")`)
|
||||
await transaction.run(`CALL db.index.fulltext.drop("post_fulltext_search")`)
|
||||
await transaction.run(`CALL db.index.fulltext.drop("tag_fulltext_search")`)
|
||||
await transaction.commit()
|
||||
next()
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error)
|
||||
await transaction.rollback()
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('rolled back')
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
import { getDriver } from '../../db/neo4j'
|
||||
|
||||
export const description = 'Add to all existing posts the Article label'
|
||||
|
||||
export async function up(next) {
|
||||
const driver = getDriver()
|
||||
const session = driver.session()
|
||||
const transaction = session.beginTransaction()
|
||||
|
||||
try {
|
||||
await transaction.run(`
|
||||
MATCH (post:Post)
|
||||
SET post:Article
|
||||
RETURN post
|
||||
`)
|
||||
await transaction.commit()
|
||||
next()
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error)
|
||||
await transaction.rollback()
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('rolled back')
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(next) {
|
||||
const driver = getDriver()
|
||||
const session = driver.session()
|
||||
const transaction = session.beginTransaction()
|
||||
|
||||
try {
|
||||
await transaction.run(`
|
||||
MATCH (post:Post)
|
||||
REMOVE post:Article
|
||||
RETURN post
|
||||
`)
|
||||
await transaction.commit()
|
||||
next()
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error)
|
||||
await transaction.rollback()
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('rolled back')
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@ import sample from 'lodash/sample'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import CONFIG from '../config'
|
||||
import createServer from '../server'
|
||||
import faker from '@faker-js/faker'
|
||||
import { faker } from '@faker-js/faker'
|
||||
import Factory from '../db/factories'
|
||||
import { getNeode, getDriver } from '../db/neo4j'
|
||||
import {
|
||||
@ -173,6 +173,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
||||
},
|
||||
{
|
||||
email: 'moderator@example.org',
|
||||
avatar: null,
|
||||
},
|
||||
),
|
||||
Factory.build(
|
||||
@ -209,6 +210,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
||||
},
|
||||
{
|
||||
email: 'dewey@example.org',
|
||||
avatar: null,
|
||||
},
|
||||
),
|
||||
Factory.build(
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
# GraphQL Playground
|
||||
|
||||
***Attention:** For using the GraphQL Playground set `DEBUG=true` in your backend `.env`, see `.env.template`!*
|
||||
|
||||
To use GraphQL Playground, we need to know some basics:
|
||||
|
||||
## How To Login?
|
||||
|
||||
@ -11,6 +11,8 @@ export const createPostMutation = () => {
|
||||
$content: String!
|
||||
$categoryIds: [ID]
|
||||
$groupId: ID
|
||||
$postType: PostType
|
||||
$eventInput: _EventInput
|
||||
) {
|
||||
CreatePost(
|
||||
id: $id
|
||||
@ -19,11 +21,31 @@ export const createPostMutation = () => {
|
||||
content: $content
|
||||
categoryIds: $categoryIds
|
||||
groupId: $groupId
|
||||
postType: $postType
|
||||
eventInput: $eventInput
|
||||
) {
|
||||
id
|
||||
slug
|
||||
title
|
||||
content
|
||||
disabled
|
||||
deleted
|
||||
postType
|
||||
author {
|
||||
name
|
||||
}
|
||||
categories {
|
||||
id
|
||||
}
|
||||
eventStart
|
||||
eventEnd
|
||||
eventLocationName
|
||||
eventVenue
|
||||
eventIsOnline
|
||||
eventLocation {
|
||||
lng
|
||||
lat
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -50,6 +72,7 @@ export const filterPosts = () => {
|
||||
id
|
||||
title
|
||||
content
|
||||
eventStart
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@ -51,6 +51,50 @@ const publishNotifications = async (context, promises) => {
|
||||
})
|
||||
}
|
||||
|
||||
const handleJoinGroup = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(context, [
|
||||
notifyOwnersOfGroup(groupId, userId, 'user_joined_group', context),
|
||||
])
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleLeaveGroup = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(context, [
|
||||
notifyOwnersOfGroup(groupId, userId, 'user_left_group', context),
|
||||
])
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleChangeGroupMemberRole = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(context, [
|
||||
notifyMemberOfGroup(groupId, userId, 'changed_group_member_role', context),
|
||||
])
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleRemoveUserFromGroup = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { groupId, userId } = args
|
||||
const user = await resolve(root, args, context, resolveInfo)
|
||||
if (user) {
|
||||
await publishNotifications(context, [
|
||||
notifyMemberOfGroup(groupId, userId, 'removed_user_from_group', context),
|
||||
])
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => {
|
||||
const idsOfUsers = extractMentionedUsers(args.content)
|
||||
const post = await resolve(root, args, context, resolveInfo)
|
||||
@ -94,6 +138,72 @@ const postAuthorOfComment = async (commentId, { context }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const notifyOwnersOfGroup = async (groupId, userId, reason, context) => {
|
||||
const cypher = `
|
||||
MATCH (group:Group { id: $groupId })<-[membership:MEMBER_OF]-(owner:User)
|
||||
WHERE membership.role = 'owner'
|
||||
WITH owner, group
|
||||
MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(owner)
|
||||
WITH group, owner, notification
|
||||
SET notification.read = FALSE
|
||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||
SET notification.updatedAt = toString(datetime())
|
||||
SET notification.relatedUserId = $userId
|
||||
RETURN notification {.*, from: group, to: properties(owner)}
|
||||
`
|
||||
const session = context.driver.session()
|
||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||
const notificationTransactionResponse = await transaction.run(cypher, {
|
||||
groupId,
|
||||
reason,
|
||||
userId,
|
||||
})
|
||||
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
||||
})
|
||||
try {
|
||||
const notifications = await writeTxResultPromise
|
||||
return notifications
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
|
||||
const notifyMemberOfGroup = async (groupId, userId, reason, context) => {
|
||||
const { user: owner } = context
|
||||
const cypher = `
|
||||
MATCH (user:User { id: $userId })
|
||||
MATCH (group:Group { id: $groupId })
|
||||
WITH user, group
|
||||
MERGE (group)-[notification:NOTIFIED {reason: $reason}]->(user)
|
||||
WITH group, user, notification
|
||||
SET notification.read = FALSE
|
||||
SET notification.createdAt = COALESCE(notification.createdAt, toString(datetime()))
|
||||
SET notification.updatedAt = toString(datetime())
|
||||
SET notification.relatedUserId = $ownerId
|
||||
RETURN notification {.*, from: group, to: properties(user)}
|
||||
`
|
||||
const session = context.driver.session()
|
||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||
const notificationTransactionResponse = await transaction.run(cypher, {
|
||||
groupId,
|
||||
reason,
|
||||
userId,
|
||||
ownerId: owner.id,
|
||||
})
|
||||
return notificationTransactionResponse.records.map((record) => record.get('notification'))
|
||||
})
|
||||
try {
|
||||
const notifications = await writeTxResultPromise
|
||||
return notifications
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
|
||||
const notifyUsersOfMention = async (label, id, idsOfUsers, reason, context) => {
|
||||
if (!(idsOfUsers && idsOfUsers.length)) return []
|
||||
await validateNotifyUsers(label, reason)
|
||||
@ -188,5 +298,9 @@ export default {
|
||||
UpdatePost: handleContentDataOfPost,
|
||||
CreateComment: handleContentDataOfComment,
|
||||
UpdateComment: handleContentDataOfComment,
|
||||
JoinGroup: handleJoinGroup,
|
||||
LeaveGroup: handleLeaveGroup,
|
||||
ChangeGroupMemberRole: handleChangeGroupMemberRole,
|
||||
RemoveUserFromGroup: handleRemoveUserFromGroup,
|
||||
},
|
||||
}
|
||||
|
||||
@ -3,6 +3,13 @@ import { cleanDatabase } from '../../db/factories'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import { getNeode, getDriver } from '../../db/neo4j'
|
||||
import createServer, { pubsub } from '../../server'
|
||||
import {
|
||||
createGroupMutation,
|
||||
joinGroupMutation,
|
||||
leaveGroupMutation,
|
||||
changeGroupMemberRoleMutation,
|
||||
removeUserFromGroupMutation,
|
||||
} from '../../graphql/groups'
|
||||
|
||||
let server, query, mutate, notifiedUser, authenticatedUser
|
||||
let publishSpy
|
||||
@ -92,6 +99,9 @@ describe('notifications', () => {
|
||||
read
|
||||
reason
|
||||
createdAt
|
||||
relatedUser {
|
||||
id
|
||||
}
|
||||
from {
|
||||
__typename
|
||||
... on Post {
|
||||
@ -102,6 +112,9 @@ describe('notifications', () => {
|
||||
id
|
||||
content
|
||||
}
|
||||
... on Group {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,6 +198,7 @@ describe('notifications', () => {
|
||||
id: 'c47',
|
||||
content: commentContent,
|
||||
},
|
||||
relatedUser: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -357,6 +371,7 @@ describe('notifications', () => {
|
||||
id: 'p47',
|
||||
content: expectedUpdatedContent,
|
||||
},
|
||||
relatedUser: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -513,6 +528,7 @@ describe('notifications', () => {
|
||||
id: 'c47',
|
||||
content: commentContent,
|
||||
},
|
||||
relatedUser: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -547,6 +563,7 @@ describe('notifications', () => {
|
||||
id: 'c47',
|
||||
content: commentContent,
|
||||
},
|
||||
relatedUser: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -616,4 +633,232 @@ describe('notifications', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('group notifications', () => {
|
||||
let groupOwner
|
||||
|
||||
beforeEach(async () => {
|
||||
groupOwner = await neode.create(
|
||||
'User',
|
||||
{
|
||||
id: 'group-owner',
|
||||
name: 'Group Owner',
|
||||
slug: 'group-owner',
|
||||
},
|
||||
{
|
||||
email: 'owner@example.org',
|
||||
password: '1234',
|
||||
},
|
||||
)
|
||||
authenticatedUser = await groupOwner.toJson()
|
||||
await mutate({
|
||||
mutation: createGroupMutation(),
|
||||
variables: {
|
||||
id: 'closed-group',
|
||||
name: 'The Closed Group',
|
||||
about: 'Will test the closed group!',
|
||||
description: 'Some description' + Array(50).join('_'),
|
||||
groupType: 'public',
|
||||
actionRadius: 'regional',
|
||||
categoryIds,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('user joins group', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await notifiedUser.toJson()
|
||||
await mutate({
|
||||
mutation: joinGroupMutation(),
|
||||
variables: {
|
||||
groupId: 'closed-group',
|
||||
userId: authenticatedUser.id,
|
||||
},
|
||||
})
|
||||
authenticatedUser = await groupOwner.toJson()
|
||||
})
|
||||
|
||||
it('has the notification in database', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
notifications: [
|
||||
{
|
||||
read: false,
|
||||
reason: 'user_joined_group',
|
||||
createdAt: expect.any(String),
|
||||
from: {
|
||||
__typename: 'Group',
|
||||
id: 'closed-group',
|
||||
},
|
||||
relatedUser: {
|
||||
id: 'you',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('user leaves group', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await notifiedUser.toJson()
|
||||
await mutate({
|
||||
mutation: joinGroupMutation(),
|
||||
variables: {
|
||||
groupId: 'closed-group',
|
||||
userId: authenticatedUser.id,
|
||||
},
|
||||
})
|
||||
await mutate({
|
||||
mutation: leaveGroupMutation(),
|
||||
variables: {
|
||||
groupId: 'closed-group',
|
||||
userId: authenticatedUser.id,
|
||||
},
|
||||
})
|
||||
authenticatedUser = await groupOwner.toJson()
|
||||
})
|
||||
|
||||
it('has two the notification in database', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
notifications: [
|
||||
{
|
||||
read: false,
|
||||
reason: 'user_left_group',
|
||||
createdAt: expect.any(String),
|
||||
from: {
|
||||
__typename: 'Group',
|
||||
id: 'closed-group',
|
||||
},
|
||||
relatedUser: {
|
||||
id: 'you',
|
||||
},
|
||||
},
|
||||
{
|
||||
read: false,
|
||||
reason: 'user_joined_group',
|
||||
createdAt: expect.any(String),
|
||||
from: {
|
||||
__typename: 'Group',
|
||||
id: 'closed-group',
|
||||
},
|
||||
relatedUser: {
|
||||
id: 'you',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('user role in group changes', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await notifiedUser.toJson()
|
||||
await mutate({
|
||||
mutation: joinGroupMutation(),
|
||||
variables: {
|
||||
groupId: 'closed-group',
|
||||
userId: authenticatedUser.id,
|
||||
},
|
||||
})
|
||||
authenticatedUser = await groupOwner.toJson()
|
||||
await mutate({
|
||||
mutation: changeGroupMemberRoleMutation(),
|
||||
variables: {
|
||||
groupId: 'closed-group',
|
||||
userId: 'you',
|
||||
roleInGroup: 'admin',
|
||||
},
|
||||
})
|
||||
authenticatedUser = await notifiedUser.toJson()
|
||||
})
|
||||
|
||||
it('has notification in database', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
notifications: [
|
||||
{
|
||||
read: false,
|
||||
reason: 'changed_group_member_role',
|
||||
createdAt: expect.any(String),
|
||||
from: {
|
||||
__typename: 'Group',
|
||||
id: 'closed-group',
|
||||
},
|
||||
relatedUser: {
|
||||
id: 'group-owner',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('user is removed from group', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await notifiedUser.toJson()
|
||||
await mutate({
|
||||
mutation: joinGroupMutation(),
|
||||
variables: {
|
||||
groupId: 'closed-group',
|
||||
userId: authenticatedUser.id,
|
||||
},
|
||||
})
|
||||
authenticatedUser = await groupOwner.toJson()
|
||||
await mutate({
|
||||
mutation: removeUserFromGroupMutation(),
|
||||
variables: {
|
||||
groupId: 'closed-group',
|
||||
userId: 'you',
|
||||
},
|
||||
})
|
||||
authenticatedUser = await notifiedUser.toJson()
|
||||
})
|
||||
|
||||
it('has notification in database', async () => {
|
||||
await expect(
|
||||
query({
|
||||
query: notificationQuery,
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
notifications: [
|
||||
{
|
||||
read: false,
|
||||
reason: 'removed_user_from_group',
|
||||
createdAt: expect.any(String),
|
||||
from: {
|
||||
__typename: 'Group',
|
||||
id: 'closed-group',
|
||||
},
|
||||
relatedUser: {
|
||||
id: 'group-owner',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -126,7 +126,7 @@ describe('Query', () => {
|
||||
author: null,
|
||||
date: expect.any(String),
|
||||
description:
|
||||
'Human Connection, Weilheim an der Teck. Gefällt 24.407 Mal. An upcoming non-profit social network focused on local and global positive change. Twitter accounts : @hc_world (EN), @hc_deutschland (GE),...',
|
||||
'Human Connection, Weilheim an der Teck. Gefällt 24.407 Mal. An upcoming non-profit social network focused on local and global positive change. Twitter accounts : @hc_world (EN), @hc_deutschland (GE),…',
|
||||
html: null,
|
||||
image:
|
||||
'https://scontent.ftxl3-1.fna.fbcdn.net/v/t1.0-1/c5.0.200.200a/p200x200/12108307_997373093648222_70057205881020137_n.jpg?_nc_cat=110&_nc_oc=AQnPPYQlR0dU556gOfl4xkXr7IPZdRIAUfQeXl3fpUv4DAsFN8T4PfgOjPwuq85GPKGZ5S5E5mWQ8IVV1UiRBAIZ&_nc_ht=scontent.ftxl3-1.fna&oh=90309adddaab38839782f16e7d4b7bcf&oe=5DEEDFE5',
|
||||
@ -196,7 +196,7 @@ Have all the information for the brand in separate config files. Set these defau
|
||||
publisher: 'YouTube',
|
||||
date: expect.any(String),
|
||||
description:
|
||||
'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...',
|
||||
'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al…',
|
||||
url: 'https://www.youtube.com/watch?v=qkdXAtO40Fo',
|
||||
image: 'https://i.ytimg.com/vi/qkdXAtO40Fo/maxresdefault.jpg',
|
||||
audio: null,
|
||||
|
||||
@ -17,7 +17,6 @@ const metascraper = Metascraper([
|
||||
require('metascraper-lang')(),
|
||||
require('metascraper-lang-detector')(),
|
||||
require('metascraper-logo')(),
|
||||
// require('metascraper-clearbit-logo')(),
|
||||
require('metascraper-publisher')(),
|
||||
require('metascraper-title')(),
|
||||
require('metascraper-url')(),
|
||||
|
||||
230
backend/src/schema/resolvers/filter-posts.spec.js
Normal file
230
backend/src/schema/resolvers/filter-posts.spec.js
Normal file
@ -0,0 +1,230 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import Factory, { cleanDatabase } from '../../db/factories'
|
||||
import { getNeode, getDriver } from '../../db/neo4j'
|
||||
import createServer from '../../server'
|
||||
import CONFIG from '../../config'
|
||||
import { filterPosts, createPostMutation } from '../../graphql/posts'
|
||||
|
||||
CONFIG.CATEGORIES_ACTIVE = false
|
||||
|
||||
const driver = getDriver()
|
||||
const neode = getNeode()
|
||||
|
||||
let query
|
||||
let mutate
|
||||
let authenticatedUser
|
||||
let user
|
||||
|
||||
beforeAll(async () => {
|
||||
await cleanDatabase()
|
||||
|
||||
const { server } = createServer({
|
||||
context: () => {
|
||||
return {
|
||||
driver,
|
||||
neode,
|
||||
user: authenticatedUser,
|
||||
}
|
||||
},
|
||||
})
|
||||
query = createTestClient(server).query
|
||||
mutate = createTestClient(server).mutate
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await cleanDatabase()
|
||||
driver.close()
|
||||
})
|
||||
|
||||
describe('Filter Posts', () => {
|
||||
const now = new Date()
|
||||
|
||||
beforeAll(async () => {
|
||||
user = await Factory.build('user', {
|
||||
id: 'user',
|
||||
name: 'User',
|
||||
about: 'I am a user.',
|
||||
})
|
||||
authenticatedUser = await user.toJson()
|
||||
await mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
id: 'a1',
|
||||
title: 'I am an article',
|
||||
content: 'I am an article written by user.',
|
||||
},
|
||||
})
|
||||
await mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
id: 'a2',
|
||||
title: 'I am anonther article',
|
||||
content: 'I am another article written by user.',
|
||||
},
|
||||
})
|
||||
await mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
id: 'e1',
|
||||
title: 'Illegaler Kindergeburtstag',
|
||||
content: 'Elli wird fünf. Wir feiern ihren Geburtstag.',
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventVenue: 'Garten der Familie Maier',
|
||||
},
|
||||
},
|
||||
})
|
||||
await mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
id: 'e2',
|
||||
title: 'Räuber-Treffen',
|
||||
content: 'Planung der nächsten Räuberereien',
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(),
|
||||
eventVenue: 'Wirtshaus im Spessart',
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('no filters set', () => {
|
||||
it('finds all posts', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({ query: filterPosts() })
|
||||
expect(result).toHaveLength(4)
|
||||
expect(result).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: 'a1' }),
|
||||
expect.objectContaining({ id: 'a2' }),
|
||||
expect.objectContaining({ id: 'e1' }),
|
||||
expect.objectContaining({ id: 'e2' }),
|
||||
]),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('post type filter set to ["Article"]', () => {
|
||||
it('finds the articles', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({ query: filterPosts(), variables: { filter: { postType_in: ['Article'] } } })
|
||||
expect(result).toHaveLength(2)
|
||||
expect(result).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: 'a1' }),
|
||||
expect.objectContaining({ id: 'a2' }),
|
||||
]),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('post type filter set to ["Event"]', () => {
|
||||
it('finds the articles', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({ query: filterPosts(), variables: { filter: { postType_in: ['Event'] } } })
|
||||
expect(result).toHaveLength(2)
|
||||
expect(result).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: 'e1' }),
|
||||
expect.objectContaining({ id: 'e2' }),
|
||||
]),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('post type filter set to ["Article", "Event"]', () => {
|
||||
it('finds all posts', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({
|
||||
query: filterPosts(),
|
||||
variables: { filter: { postType_in: ['Article', 'Event'] } },
|
||||
})
|
||||
expect(result).toHaveLength(4)
|
||||
expect(result).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ id: 'a1' }),
|
||||
expect.objectContaining({ id: 'a2' }),
|
||||
expect.objectContaining({ id: 'e1' }),
|
||||
expect.objectContaining({ id: 'e2' }),
|
||||
]),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('order events by event start descending', () => {
|
||||
it('finds the events orderd accordingly', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({
|
||||
query: filterPosts(),
|
||||
variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_desc'] },
|
||||
})
|
||||
expect(result).toHaveLength(2)
|
||||
expect(result).toEqual([
|
||||
expect.objectContaining({
|
||||
id: 'e1',
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: 'e2',
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(),
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('order events by event start ascending', () => {
|
||||
it('finds the events orderd accordingly', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({
|
||||
query: filterPosts(),
|
||||
variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_asc'] },
|
||||
})
|
||||
expect(result).toHaveLength(2)
|
||||
expect(result).toEqual([
|
||||
expect.objectContaining({
|
||||
id: 'e2',
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: 'e1',
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe('filter events by event start date', () => {
|
||||
it('finds only events after given date', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({
|
||||
query: filterPosts(),
|
||||
variables: {
|
||||
filter: {
|
||||
postType_in: ['Event'],
|
||||
eventStart_gte: new Date(
|
||||
now.getFullYear(),
|
||||
now.getMonth(),
|
||||
now.getDate() + 2,
|
||||
).toISOString(),
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(result).toHaveLength(1)
|
||||
expect(result).toEqual([
|
||||
expect.objectContaining({
|
||||
id: 'e1',
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
47
backend/src/schema/resolvers/helpers/events.js
Normal file
47
backend/src/schema/resolvers/helpers/events.js
Normal file
@ -0,0 +1,47 @@
|
||||
import { UserInputError } from 'apollo-server'
|
||||
|
||||
export const validateEventParams = (params) => {
|
||||
if (params.postType && params.postType === 'Event') {
|
||||
const { eventInput } = params
|
||||
validateEventDate(eventInput.eventStart)
|
||||
params.eventStart = eventInput.eventStart
|
||||
if (eventInput.eventEnd) {
|
||||
validateEventEnd(eventInput.eventStart, eventInput.eventEnd)
|
||||
params.eventEnd = eventInput.eventEnd
|
||||
}
|
||||
if (eventInput.eventLocationName && !eventInput.eventVenue) {
|
||||
throw new UserInputError('Event venue must be present if event location is given!')
|
||||
}
|
||||
params.eventVenue = eventInput.eventVenue
|
||||
params.eventLocationName = eventInput.eventLocationName
|
||||
params.eventIsOnline = !!eventInput.eventIsOnline
|
||||
}
|
||||
delete params.eventInput
|
||||
let locationName
|
||||
if (params.eventLocationName) {
|
||||
locationName = params.eventLocationName
|
||||
} else {
|
||||
params.eventLocationName = null
|
||||
locationName = null
|
||||
}
|
||||
return locationName
|
||||
}
|
||||
|
||||
const validateEventDate = (dateString) => {
|
||||
const date = new Date(dateString)
|
||||
if (date.toString() === 'Invalid Date')
|
||||
throw new UserInputError('Event start date must be a valid date!')
|
||||
const now = new Date()
|
||||
if (date.getTime() < now.getTime()) {
|
||||
throw new UserInputError('Event start date must be in the future!')
|
||||
}
|
||||
}
|
||||
|
||||
const validateEventEnd = (start, end) => {
|
||||
const endDate = new Date(end)
|
||||
if (endDate.toString() === 'Invalid Date')
|
||||
throw new UserInputError('Event end date must be a valid date!')
|
||||
const startDate = new Date(start)
|
||||
if (endDate < startDate)
|
||||
throw new UserInputError('Event end date must be a after event start date!')
|
||||
}
|
||||
@ -47,12 +47,22 @@ export default {
|
||||
`
|
||||
MATCH (resource {deleted: false, disabled: false})-[notification:NOTIFIED]->(user:User {id:$id})
|
||||
${whereClause}
|
||||
WITH user, notification, resource,
|
||||
OPTIONAL MATCH (relatedUser:User { id: notification.relatedUserId })
|
||||
OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(relatedUser)
|
||||
WITH user, notification, resource, membership, relatedUser,
|
||||
[(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors,
|
||||
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts
|
||||
WITH resource, user, notification, authors, posts,
|
||||
resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource
|
||||
RETURN notification {.*, from: finalResource, to: properties(user)}
|
||||
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts
|
||||
WITH resource, user, notification, authors, posts, relatedUser, membership,
|
||||
resource {.*,
|
||||
__typename: labels(resource)[0],
|
||||
author: authors[0],
|
||||
post: posts[0],
|
||||
myRole: membership.role } AS finalResource
|
||||
RETURN notification {.*,
|
||||
from: finalResource,
|
||||
to: properties(user),
|
||||
relatedUser: properties(relatedUser)
|
||||
}
|
||||
${orderByClause}
|
||||
${offset} ${limit}
|
||||
`,
|
||||
@ -80,9 +90,10 @@ export default {
|
||||
SET notification.read = TRUE
|
||||
WITH user, notification, resource,
|
||||
[(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors,
|
||||
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts
|
||||
WITH resource, user, notification, authors, posts,
|
||||
resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource
|
||||
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts
|
||||
OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(user)
|
||||
WITH resource, user, notification, authors, posts, membership,
|
||||
resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], myRole: membership.role } AS finalResource
|
||||
RETURN notification {.*, from: finalResource, to: properties(user)}
|
||||
`,
|
||||
{ resourceId: args.id, id: currentUser.id },
|
||||
@ -109,9 +120,10 @@ export default {
|
||||
SET notification.read = TRUE
|
||||
WITH user, notification, resource,
|
||||
[(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors,
|
||||
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts
|
||||
WITH resource, user, notification, authors, posts,
|
||||
resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0]} AS finalResource
|
||||
[(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts
|
||||
OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(user)
|
||||
WITH resource, user, notification, authors, posts, membership,
|
||||
resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], myRole: membership.role} AS finalResource
|
||||
RETURN notification {.*, from: finalResource, to: properties(user)}
|
||||
`,
|
||||
{ id: currentUser.id },
|
||||
|
||||
@ -397,18 +397,20 @@ describe('given some notifications', () => {
|
||||
|
||||
it('returns all as read', async () => {
|
||||
const response = await mutate({ mutation: markAllAsReadMutation(), variables })
|
||||
expect(response.data.markAllAsRead).toEqual([
|
||||
{
|
||||
createdAt: '2019-08-30T19:33:48.651Z',
|
||||
from: { __typename: 'Comment', content: 'You have been mentioned in a comment' },
|
||||
read: true,
|
||||
},
|
||||
{
|
||||
createdAt: '2019-08-31T17:33:48.651Z',
|
||||
from: { __typename: 'Post', content: 'You have been mentioned in a post' },
|
||||
read: true,
|
||||
},
|
||||
])
|
||||
expect(response.data.markAllAsRead).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
createdAt: '2019-08-30T19:33:48.651Z',
|
||||
from: { __typename: 'Comment', content: 'You have been mentioned in a comment' },
|
||||
read: true,
|
||||
},
|
||||
{
|
||||
createdAt: '2019-08-31T17:33:48.651Z',
|
||||
from: { __typename: 'Post', content: 'You have been mentioned in a post' },
|
||||
read: true,
|
||||
},
|
||||
]),
|
||||
)
|
||||
expect(response.errors).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
@ -7,6 +7,8 @@ import Resolver from './helpers/Resolver'
|
||||
import { filterForMutedUsers } from './helpers/filterForMutedUsers'
|
||||
import { filterInvisiblePosts } from './helpers/filterInvisiblePosts'
|
||||
import { filterPostsOfMyGroups } from './helpers/filterPostsOfMyGroups'
|
||||
import { validateEventParams } from './helpers/events'
|
||||
import { createOrUpdateLocations } from './users/location'
|
||||
import CONFIG from '../../config'
|
||||
|
||||
const maintainPinnedPosts = (params) => {
|
||||
@ -81,6 +83,9 @@ export default {
|
||||
CreatePost: async (_parent, params, context, _resolveInfo) => {
|
||||
const { categoryIds, groupId } = params
|
||||
const { image: imageInput } = params
|
||||
|
||||
const locationName = validateEventParams(params)
|
||||
|
||||
delete params.categoryIds
|
||||
delete params.image
|
||||
delete params.groupId
|
||||
@ -125,12 +130,13 @@ export default {
|
||||
SET post.updatedAt = toString(datetime())
|
||||
SET post.clickedCount = 0
|
||||
SET post.viewedTeaserCount = 0
|
||||
SET post:${params.postType}
|
||||
WITH post
|
||||
MATCH (author:User {id: $userId})
|
||||
MERGE (post)<-[:WROTE]-(author)
|
||||
${categoriesCypher}
|
||||
${groupCypher}
|
||||
RETURN post {.*}
|
||||
RETURN post {.*, postType: filter(l IN labels(post) WHERE NOT l = "Post") }
|
||||
`,
|
||||
{ userId: context.user.id, categoryIds, groupId, params },
|
||||
)
|
||||
@ -142,6 +148,9 @@ export default {
|
||||
})
|
||||
try {
|
||||
const post = await writeTxResultPromise
|
||||
if (locationName) {
|
||||
await createOrUpdateLocations('Post', post.id, locationName, session)
|
||||
}
|
||||
return post
|
||||
} catch (e) {
|
||||
if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||
@ -154,6 +163,9 @@ export default {
|
||||
UpdatePost: async (_parent, params, context, _resolveInfo) => {
|
||||
const { categoryIds } = params
|
||||
const { image: imageInput } = params
|
||||
|
||||
const locationName = validateEventParams(params)
|
||||
|
||||
delete params.categoryIds
|
||||
delete params.image
|
||||
const session = context.driver.session()
|
||||
@ -183,7 +195,16 @@ export default {
|
||||
`
|
||||
}
|
||||
|
||||
updatePostCypher += `RETURN post {.*}`
|
||||
if (params.postType) {
|
||||
updatePostCypher += `
|
||||
REMOVE post:Article
|
||||
REMOVE post:Event
|
||||
SET post:${params.postType}
|
||||
WITH post
|
||||
`
|
||||
}
|
||||
|
||||
updatePostCypher += `RETURN post {.*, postType: filter(l IN labels(post) WHERE NOT l = "Post")}`
|
||||
const updatePostVariables = { categoryIds, params }
|
||||
try {
|
||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||
@ -196,6 +217,9 @@ export default {
|
||||
return post
|
||||
})
|
||||
const post = await writeTxResultPromise
|
||||
if (locationName) {
|
||||
await createOrUpdateLocations('Post', post.id, locationName, session)
|
||||
}
|
||||
return post
|
||||
} finally {
|
||||
session.close()
|
||||
@ -310,6 +334,7 @@ export default {
|
||||
`
|
||||
MATCH (user:User {id: $userId}) WHERE user.role = 'admin'
|
||||
MATCH (post:Post {id: $params.id})
|
||||
WHERE NOT((post)-[:IN]->(:Group))
|
||||
MERGE (user)-[pinned:PINNED {createdAt: toString(datetime())}]->(post)
|
||||
SET post.pinned = true
|
||||
RETURN post, pinned.createdAt as pinnedAt
|
||||
@ -322,10 +347,12 @@ export default {
|
||||
}))
|
||||
})
|
||||
const [transactionResult] = await writeTxResultPromise
|
||||
const { pinnedPost, pinnedAt } = transactionResult
|
||||
pinnedPostWithNestedAttributes = {
|
||||
...pinnedPost,
|
||||
pinnedAt,
|
||||
if (transactionResult) {
|
||||
const { pinnedPost, pinnedAt } = transactionResult
|
||||
pinnedPostWithNestedAttributes = {
|
||||
...pinnedPost,
|
||||
pinnedAt,
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
session.close()
|
||||
@ -382,7 +409,19 @@ export default {
|
||||
},
|
||||
Post: {
|
||||
...Resolver('Post', {
|
||||
undefinedToNull: ['activityId', 'objectId', 'language', 'pinnedAt', 'pinned'],
|
||||
undefinedToNull: [
|
||||
'activityId',
|
||||
'objectId',
|
||||
'language',
|
||||
'pinnedAt',
|
||||
'pinned',
|
||||
'eventVenue',
|
||||
'eventLocation',
|
||||
'eventLocationName',
|
||||
'eventStart',
|
||||
'eventEnd',
|
||||
'eventIsOnline',
|
||||
],
|
||||
hasMany: {
|
||||
tags: '-[:TAGGED]->(related:Tag)',
|
||||
categories: '-[:CATEGORIZED]->(related:Category)',
|
||||
@ -395,6 +434,7 @@ export default {
|
||||
pinnedBy: '<-[:PINNED]-(related:User)',
|
||||
image: '-[:HERO_IMAGE]->(related:Image)',
|
||||
group: '-[:IN]->(related:Group)',
|
||||
eventLocation: '-[:IS_IN]->(related:Location)',
|
||||
},
|
||||
count: {
|
||||
commentsCount:
|
||||
|
||||
@ -3,6 +3,10 @@ import Factory, { cleanDatabase } from '../../db/factories'
|
||||
import gql from 'graphql-tag'
|
||||
import { getNeode, getDriver } from '../../db/neo4j'
|
||||
import createServer from '../../server'
|
||||
import { createPostMutation } from '../../graphql/posts'
|
||||
import CONFIG from '../../config'
|
||||
|
||||
CONFIG.CATEGORIES_ACTIVE = true
|
||||
|
||||
const driver = getDriver()
|
||||
const neode = getNeode()
|
||||
@ -15,29 +19,6 @@ let user
|
||||
const categoryIds = ['cat9', 'cat4', 'cat15']
|
||||
let variables
|
||||
|
||||
const createPostMutation = gql`
|
||||
mutation ($id: ID, $title: String!, $content: String!, $language: String, $categoryIds: [ID]) {
|
||||
CreatePost(
|
||||
id: $id
|
||||
title: $title
|
||||
content: $content
|
||||
language: $language
|
||||
categoryIds: $categoryIds
|
||||
) {
|
||||
id
|
||||
title
|
||||
content
|
||||
slug
|
||||
disabled
|
||||
deleted
|
||||
language
|
||||
author {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
beforeAll(async () => {
|
||||
await cleanDatabase()
|
||||
|
||||
@ -281,7 +262,7 @@ describe('CreatePost', () => {
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
it('throws authorization error', async () => {
|
||||
const { errors } = await mutate({ mutation: createPostMutation, variables })
|
||||
const { errors } = await mutate({ mutation: createPostMutation(), variables })
|
||||
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
|
||||
})
|
||||
})
|
||||
@ -296,7 +277,7 @@ describe('CreatePost', () => {
|
||||
data: { CreatePost: { title: 'I am a title', content: 'Some content' } },
|
||||
errors: undefined,
|
||||
}
|
||||
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject(
|
||||
await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject(
|
||||
expected,
|
||||
)
|
||||
})
|
||||
@ -313,25 +294,327 @@ describe('CreatePost', () => {
|
||||
},
|
||||
errors: undefined,
|
||||
}
|
||||
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject(
|
||||
await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject(
|
||||
expected,
|
||||
)
|
||||
})
|
||||
|
||||
it('`disabled` and `deleted` default to `false`', async () => {
|
||||
const expected = { data: { CreatePost: { disabled: false, deleted: false } } }
|
||||
await expect(mutate({ mutation: createPostMutation, variables })).resolves.toMatchObject(
|
||||
await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject(
|
||||
expected,
|
||||
)
|
||||
})
|
||||
|
||||
it('has label "Article" as default', async () => {
|
||||
await expect(mutate({ mutation: createPostMutation(), variables })).resolves.toMatchObject({
|
||||
data: { CreatePost: { postType: ['Article'] } },
|
||||
})
|
||||
})
|
||||
|
||||
describe('with invalid post type', () => {
|
||||
it('throws an error', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: { ...variables, postType: 'not-valid' },
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message:
|
||||
'Variable "$postType" got invalid value "not-valid"; Expected type PostType.',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with post type "Event"', () => {
|
||||
describe('without event start date', () => {
|
||||
it('throws an error', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: "Cannot read properties of undefined (reading 'eventStart')",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with invalid event start date', () => {
|
||||
it('throws an error', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: 'no date',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Event start date must be a valid date!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with event start date in the past', () => {
|
||||
it('throws an error', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() - 1).toISOString(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Event start date must be in the future!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with valid start date and invalid end date', () => {
|
||||
it('throws an error', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventEnd: 'not-valid',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Event end date must be a valid date!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with valid start date and end date before start date', () => {
|
||||
it('throws an error', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(),
|
||||
eventEnd: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Event end date must be a after event start date!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with valid start date and valid end date', () => {
|
||||
it('creates the event', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventEnd: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
CreatePost: {
|
||||
postType: ['Event'],
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventEnd: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(),
|
||||
eventIsOnline: false,
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with valid start date and event is online', () => {
|
||||
it('creates the event', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventIsOnline: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
CreatePost: {
|
||||
postType: ['Event'],
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventIsOnline: true,
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('event location name is given but event venue is missing', () => {
|
||||
it('throws an error', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventLocationName: 'Berlin',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Event venue must be present if event location is given!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('valid event input without location', () => {
|
||||
it('has label "Event" set', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
CreatePost: {
|
||||
postType: ['Event'],
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventIsOnline: false,
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('valid event input with location name', () => {
|
||||
it('has label "Event" set', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventLocationName: 'Leipzig',
|
||||
eventVenue: 'Connewitzer Kreuz',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
CreatePost: {
|
||||
postType: ['Event'],
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventLocationName: 'Leipzig',
|
||||
eventVenue: 'Connewitzer Kreuz',
|
||||
eventLocation: {
|
||||
lng: 12.374733,
|
||||
lat: 51.340632,
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('UpdatePost', () => {
|
||||
let author, newlyCreatedPost
|
||||
const updatePostMutation = gql`
|
||||
mutation ($id: ID!, $title: String!, $content: String!, $image: ImageInput) {
|
||||
UpdatePost(id: $id, title: $title, content: $content, image: $image) {
|
||||
mutation (
|
||||
$id: ID!
|
||||
$title: String!
|
||||
$content: String!
|
||||
$image: ImageInput
|
||||
$categoryIds: [ID]
|
||||
$postType: PostType
|
||||
$eventInput: _EventInput
|
||||
) {
|
||||
UpdatePost(
|
||||
id: $id
|
||||
title: $title
|
||||
content: $content
|
||||
image: $image
|
||||
categoryIds: $categoryIds
|
||||
postType: $postType
|
||||
eventInput: $eventInput
|
||||
) {
|
||||
id
|
||||
title
|
||||
content
|
||||
@ -341,26 +624,34 @@ describe('UpdatePost', () => {
|
||||
}
|
||||
createdAt
|
||||
updatedAt
|
||||
categories {
|
||||
id
|
||||
}
|
||||
postType
|
||||
eventStart
|
||||
eventLocationName
|
||||
eventVenue
|
||||
eventLocation {
|
||||
lng
|
||||
lat
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
beforeEach(async () => {
|
||||
author = await Factory.build('user', { slug: 'the-author' })
|
||||
newlyCreatedPost = await Factory.build(
|
||||
'post',
|
||||
{
|
||||
id: 'p9876',
|
||||
authenticatedUser = await author.toJson()
|
||||
const { data } = await mutate({
|
||||
mutation: createPostMutation(),
|
||||
variables: {
|
||||
title: 'Old title',
|
||||
content: 'Old content',
|
||||
},
|
||||
{
|
||||
author,
|
||||
categoryIds,
|
||||
},
|
||||
)
|
||||
|
||||
})
|
||||
newlyCreatedPost = data.CreatePost
|
||||
variables = {
|
||||
id: 'p9876',
|
||||
id: newlyCreatedPost.id,
|
||||
title: 'New title',
|
||||
content: 'New content',
|
||||
}
|
||||
@ -394,7 +685,7 @@ describe('UpdatePost', () => {
|
||||
|
||||
it('updates a post', async () => {
|
||||
const expected = {
|
||||
data: { UpdatePost: { id: 'p9876', content: 'New content' } },
|
||||
data: { UpdatePost: { id: newlyCreatedPost.id, content: 'New content' } },
|
||||
errors: undefined,
|
||||
}
|
||||
await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
|
||||
@ -405,7 +696,11 @@ describe('UpdatePost', () => {
|
||||
it('updates a post, but maintains non-updated attributes', async () => {
|
||||
const expected = {
|
||||
data: {
|
||||
UpdatePost: { id: 'p9876', content: 'New content', createdAt: expect.any(String) },
|
||||
UpdatePost: {
|
||||
id: newlyCreatedPost.id,
|
||||
content: 'New content',
|
||||
createdAt: expect.any(String),
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
}
|
||||
@ -415,23 +710,20 @@ describe('UpdatePost', () => {
|
||||
})
|
||||
|
||||
it('updates the updatedAt attribute', async () => {
|
||||
newlyCreatedPost = await newlyCreatedPost.toJson()
|
||||
const {
|
||||
data: { UpdatePost },
|
||||
} = await mutate({ mutation: updatePostMutation, variables })
|
||||
expect(newlyCreatedPost.updatedAt).toBeTruthy()
|
||||
expect(Date.parse(newlyCreatedPost.updatedAt)).toEqual(expect.any(Number))
|
||||
expect(UpdatePost.updatedAt).toBeTruthy()
|
||||
expect(Date.parse(UpdatePost.updatedAt)).toEqual(expect.any(Number))
|
||||
expect(newlyCreatedPost.updatedAt).not.toEqual(UpdatePost.updatedAt)
|
||||
})
|
||||
|
||||
/* describe('no new category ids provided for update', () => {
|
||||
describe('no new category ids provided for update', () => {
|
||||
it('resolves and keeps current categories', async () => {
|
||||
const expected = {
|
||||
data: {
|
||||
UpdatePost: {
|
||||
id: 'p9876',
|
||||
id: newlyCreatedPost.id,
|
||||
categories: expect.arrayContaining([{ id: 'cat9' }, { id: 'cat4' }, { id: 'cat15' }]),
|
||||
},
|
||||
},
|
||||
@ -441,9 +733,9 @@ describe('UpdatePost', () => {
|
||||
expected,
|
||||
)
|
||||
})
|
||||
}) */
|
||||
})
|
||||
|
||||
/* describe('given category ids', () => {
|
||||
describe('given category ids', () => {
|
||||
beforeEach(() => {
|
||||
variables = { ...variables, categoryIds: ['cat27'] }
|
||||
})
|
||||
@ -452,7 +744,7 @@ describe('UpdatePost', () => {
|
||||
const expected = {
|
||||
data: {
|
||||
UpdatePost: {
|
||||
id: 'p9876',
|
||||
id: newlyCreatedPost.id,
|
||||
categories: expect.arrayContaining([{ id: 'cat27' }]),
|
||||
},
|
||||
},
|
||||
@ -462,9 +754,160 @@ describe('UpdatePost', () => {
|
||||
expected,
|
||||
)
|
||||
})
|
||||
}) */
|
||||
})
|
||||
|
||||
describe('params.image', () => {
|
||||
describe('change post type to event', () => {
|
||||
describe('with missing event start date', () => {
|
||||
it('throws an error', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: updatePostMutation,
|
||||
variables: { ...variables, postType: 'Event' },
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: "Cannot read properties of undefined (reading 'eventStart')",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with invalid event start date', () => {
|
||||
it('throws an error', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: updatePostMutation,
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: 'no-date',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Event start date must be a valid date!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('with event start date in the past', () => {
|
||||
it('throws an error', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: updatePostMutation,
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() - 1).toISOString(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Event start date must be in the future!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('event location name is given but event venue is missing', () => {
|
||||
it('throws an error', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: updatePostMutation,
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventLocationName: 'Berlin',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Event venue must be present if event location is given!',
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('valid event input without location name', () => {
|
||||
it('has label "Event" set', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: updatePostMutation,
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
UpdatePost: {
|
||||
postType: ['Event'],
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('valid event input with location name', () => {
|
||||
it('has label "Event" set', async () => {
|
||||
const now = new Date()
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: updatePostMutation,
|
||||
variables: {
|
||||
...variables,
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventLocationName: 'Leipzig',
|
||||
eventVenue: 'Connewitzer Kreuz',
|
||||
},
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
UpdatePost: {
|
||||
postType: ['Event'],
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventLocationName: 'Leipzig',
|
||||
eventVenue: 'Connewitzer Kreuz',
|
||||
eventLocation: {
|
||||
lng: 12.374733,
|
||||
lat: 51.340632,
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe.skip('params.image', () => {
|
||||
describe('is object', () => {
|
||||
beforeEach(() => {
|
||||
variables = { ...variables, image: { sensitive: true } }
|
||||
|
||||
@ -818,11 +818,13 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -846,11 +848,13 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -874,11 +878,13 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -902,11 +908,13 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -930,21 +938,25 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1319,16 +1331,19 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1361,21 +1376,25 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1410,16 +1429,19 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1452,11 +1474,13 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1489,21 +1513,25 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1534,21 +1562,25 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1579,21 +1611,25 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1628,21 +1664,25 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1675,21 +1715,25 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-public-group',
|
||||
title: 'A post to a public group',
|
||||
content: 'I am posting into a public group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-without-group',
|
||||
title: 'A post without a group',
|
||||
content: 'I am a user who does not belong to a group yet.',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
@ -1739,11 +1783,13 @@ describe('Posts in Groups', () => {
|
||||
id: 'post-to-closed-group',
|
||||
title: 'A post to a closed group',
|
||||
content: 'I am posting into a closed group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
{
|
||||
id: 'post-to-hidden-group',
|
||||
title: 'A post to a hidden group',
|
||||
content: 'I am posting into a hidden group as a member of the group',
|
||||
eventStart: null,
|
||||
},
|
||||
]),
|
||||
},
|
||||
|
||||
@ -223,8 +223,7 @@ export default {
|
||||
},
|
||||
searchResults: async (_parent, args, context, _resolveInfo) => {
|
||||
const { query, limit } = args
|
||||
let userId = null
|
||||
if (context.user) userId = context.user.id
|
||||
const userId = context.user?.id || null
|
||||
|
||||
const searchType = query.replace(/^([!@#&]?).*$/, '$1')
|
||||
const searchString = query.replace(/^([!@#&])/, '')
|
||||
|
||||
@ -33,7 +33,7 @@ const matchSomeWordsExactly = (str, boost = 2) => {
|
||||
const matchBeginningOfWords = (str) => {
|
||||
return str
|
||||
.split(' ')
|
||||
.filter((s) => s.length > 3)
|
||||
.filter((s) => s.length >= 2)
|
||||
.map((s) => s + '*')
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ describe('queryString', () => {
|
||||
|
||||
describe('globbing for longer words', () => {
|
||||
it('globs words with more than three characters', () => {
|
||||
expect(queryString('a couple of words')).toContain('couple* words*')
|
||||
expect(queryString('a couple of words')).toContain('couple* of* words*')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -22,7 +22,7 @@ const locales = ['en', 'de', 'fr', 'nl', 'it', 'es', 'pt', 'pl', 'ru']
|
||||
|
||||
const createLocation = async (session, mapboxData) => {
|
||||
const data = {
|
||||
id: mapboxData.id,
|
||||
id: mapboxData.id + (mapboxData.address ? `-${mapboxData.address}` : ''),
|
||||
nameEN: mapboxData.text_en,
|
||||
nameDE: mapboxData.text_de,
|
||||
nameFR: mapboxData.text_fr,
|
||||
@ -33,6 +33,7 @@ const createLocation = async (session, mapboxData) => {
|
||||
namePL: mapboxData.text_pl,
|
||||
nameRU: mapboxData.text_ru,
|
||||
type: mapboxData.id.split('.')[0].toLowerCase(),
|
||||
address: mapboxData.address,
|
||||
lng: mapboxData.center && mapboxData.center.length ? mapboxData.center[0] : null,
|
||||
lat: mapboxData.center && mapboxData.center.length ? mapboxData.center[1] : null,
|
||||
}
|
||||
@ -54,6 +55,10 @@ const createLocation = async (session, mapboxData) => {
|
||||
if (data.lat && data.lng) {
|
||||
mutation += ', l.lat = $lat, l.lng = $lng'
|
||||
}
|
||||
if (data.address) {
|
||||
mutation += ', l.address = $address'
|
||||
}
|
||||
|
||||
mutation += ' RETURN l.id'
|
||||
|
||||
await session.writeTransaction((transaction) => {
|
||||
@ -72,7 +77,7 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s
|
||||
locationName,
|
||||
)}.json?access_token=${
|
||||
CONFIG.MAPBOX_TOKEN
|
||||
}&types=region,place,country&language=${locales.join(',')}`,
|
||||
}&types=region,place,country,address&language=${locales.join(',')}`,
|
||||
)
|
||||
|
||||
debug(res)
|
||||
@ -103,6 +108,10 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s
|
||||
|
||||
let parent = data
|
||||
|
||||
if (parent.address) {
|
||||
parent.id += `-${parent.address}`
|
||||
}
|
||||
|
||||
if (data.context) {
|
||||
await asyncForEach(data.context, async (ctx) => {
|
||||
await createLocation(session, ctx)
|
||||
|
||||
4
backend/src/schema/types/enum/PostType.gql
Normal file
4
backend/src/schema/types/enum/PostType.gql
Normal file
@ -0,0 +1,4 @@
|
||||
enum PostType {
|
||||
Article
|
||||
Event
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
enum ReasonNotification {
|
||||
mentioned_in_post
|
||||
mentioned_in_comment
|
||||
commented_on_post
|
||||
}
|
||||
@ -1,17 +1,3 @@
|
||||
type Mutation {
|
||||
# Get a JWT Token for the given Email and password
|
||||
login(email: String!, password: String!): String!
|
||||
changePassword(oldPassword: String!, newPassword: String!): String!
|
||||
requestPasswordReset(email: String!): Boolean!
|
||||
resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean!
|
||||
# Shout the given Type and ID
|
||||
shout(id: ID!, type: ShoutTypeEnum): Boolean!
|
||||
# Unshout the given Type and ID
|
||||
unshout(id: ID!, type: ShoutTypeEnum): Boolean!
|
||||
followUser(id: ID!): User
|
||||
unfollowUser(id: ID!): User
|
||||
}
|
||||
|
||||
enum ShoutTypeEnum {
|
||||
Post
|
||||
}
|
||||
@ -27,4 +13,4 @@ type Reward {
|
||||
type SharedInboxEndpoint {
|
||||
id: ID!
|
||||
uri: String
|
||||
}
|
||||
}
|
||||
@ -6,9 +6,10 @@ type NOTIFIED {
|
||||
updatedAt: String!
|
||||
read: Boolean
|
||||
reason: NotificationReason
|
||||
relatedUser: User
|
||||
}
|
||||
|
||||
union NotificationSource = Post | Comment
|
||||
union NotificationSource = Post | Comment | Group
|
||||
|
||||
enum NotificationOrdering {
|
||||
createdAt_asc
|
||||
@ -21,6 +22,10 @@ enum NotificationReason {
|
||||
mentioned_in_post
|
||||
mentioned_in_comment
|
||||
commented_on_post
|
||||
user_joined_group
|
||||
user_left_group
|
||||
changed_group_member_role
|
||||
removed_user_from_group
|
||||
}
|
||||
|
||||
type Query {
|
||||
|
||||
@ -83,6 +83,8 @@ input _PostFilter {
|
||||
emotions_every: _PostEMOTEDFilter
|
||||
group: _GroupFilter
|
||||
postsInMyGroups: Boolean
|
||||
postType_in: [PostType]
|
||||
eventStart_gte: String
|
||||
}
|
||||
|
||||
enum _PostOrdering {
|
||||
@ -104,6 +106,8 @@ enum _PostOrdering {
|
||||
language_desc
|
||||
pinned_asc
|
||||
pinned_desc
|
||||
eventStart_asc
|
||||
eventStart_desc
|
||||
}
|
||||
|
||||
|
||||
@ -171,12 +175,30 @@ type Post {
|
||||
@cypher(statement: "MATCH (this)<-[emoted:EMOTED]-(:User) RETURN COUNT(DISTINCT emoted)")
|
||||
|
||||
group: Group @relation(name: "IN", direction: "OUT")
|
||||
|
||||
postType: [PostType]
|
||||
@cypher(statement: "RETURN filter(l IN labels(this) WHERE NOT l = 'Post')")
|
||||
|
||||
eventLocationName: String
|
||||
eventLocation: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
||||
eventVenue: String
|
||||
eventStart: String
|
||||
eventEnd: String
|
||||
eventIsOnline: Boolean
|
||||
}
|
||||
|
||||
input _PostInput {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
input _EventInput {
|
||||
eventStart: String!
|
||||
eventEnd: String
|
||||
eventVenue: String
|
||||
eventLocationName: String
|
||||
eventIsOnline: Boolean
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
CreatePost(
|
||||
id: ID
|
||||
@ -189,6 +211,8 @@ type Mutation {
|
||||
categoryIds: [ID]
|
||||
contentExcerpt: String
|
||||
groupId: ID
|
||||
postType: PostType = Article
|
||||
eventInput: _EventInput
|
||||
): Post
|
||||
UpdatePost(
|
||||
id: ID!
|
||||
@ -200,6 +224,8 @@ type Mutation {
|
||||
visibility: Visibility
|
||||
language: String
|
||||
categoryIds: [ID]
|
||||
postType: PostType
|
||||
eventInput: _EventInput
|
||||
): Post
|
||||
DeletePost(id: ID!): Post
|
||||
AddPostEmotions(to: _PostInput!, data: _EMOTEDInput!): EMOTED
|
||||
@ -207,6 +233,11 @@ type Mutation {
|
||||
pinPost(id: ID!): Post
|
||||
unpinPost(id: ID!): Post
|
||||
markTeaserAsViewed(id: ID!): Post
|
||||
|
||||
# Shout the given Type and ID
|
||||
shout(id: ID!, type: ShoutTypeEnum): Boolean!
|
||||
# Unshout the given Type and ID
|
||||
unshout(id: ID!, type: ShoutTypeEnum): Boolean!
|
||||
}
|
||||
|
||||
type Query {
|
||||
|
||||
@ -214,10 +214,21 @@ type Mutation {
|
||||
|
||||
muteUser(id: ID!): User
|
||||
unmuteUser(id: ID!): User
|
||||
|
||||
blockUser(id: ID!): User
|
||||
unblockUser(id: ID!): User
|
||||
|
||||
followUser(id: ID!): User
|
||||
unfollowUser(id: ID!): User
|
||||
|
||||
switchUserRole(role: UserRole!, id: ID!): User
|
||||
|
||||
saveCategorySettings(activeCategories: [String]): Boolean
|
||||
|
||||
requestPasswordReset(email: String!): Boolean!
|
||||
resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean!
|
||||
changePassword(oldPassword: String!, newPassword: String!): String!
|
||||
|
||||
# Get a JWT Token for the given Email and password
|
||||
login(email: String!, password: String!): String!
|
||||
}
|
||||
|
||||
@ -82,7 +82,13 @@ const createServer = (options) => {
|
||||
const app = express()
|
||||
|
||||
app.set('driver', driver)
|
||||
app.use(helmet())
|
||||
// TODO: this exception is required for the graphql playground, since the playground loads external resources
|
||||
// See: https://github.com/graphql/graphql-playground/issues/1283
|
||||
app.use(
|
||||
helmet(
|
||||
(CONFIG.DEBUG && { contentSecurityPolicy: false, crossOriginEmbedderPolicy: false }) || {},
|
||||
),
|
||||
)
|
||||
app.use('/.well-known/', webfinger())
|
||||
app.use(express.static('public'))
|
||||
app.use(bodyParser.json({ limit: '10mb' }))
|
||||
|
||||
111
backend/tsconfig.json
Normal file
111
backend/tsconfig.json
Normal file
@ -0,0 +1,111 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
||||
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
||||
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
||||
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
"outDir": "./build", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
},
|
||||
"include": ["./src/**/*"],
|
||||
"exclude": ["./src/**/*.spec.ts", "./src/**/*.spec.js"]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,62 @@ You have the following options for a deployment:
|
||||
|
||||
After the first deployment of the new network on your server, the database is initialized with the default administrator:
|
||||
|
||||
- E-mail: admin@example.org
|
||||
- Password: 1234
|
||||
- E-mail: `admin@example.org`
|
||||
- Password: `1234`
|
||||
|
||||
***ATTENTION:*** When you are logged in for the first time, please change your (the admin's) e-mail to an existing one and change your password to a secure one !!!
|
||||
|
||||
## Use the Scripts
|
||||
|
||||
To use all the scripts you have to set the variable `CONFIGURATION` in your terminal by entering:
|
||||
|
||||
```bash
|
||||
# in deployment folder
|
||||
|
||||
# set configuration name to folder name in 'configurations' folder (network name)
|
||||
$ export CONFIGURATION=`<your-configuration-name>`
|
||||
# to check this
|
||||
$ echo $CONFIGURATION
|
||||
```
|
||||
|
||||
### Secrets Encrypt/Decrypt
|
||||
|
||||
To encrypt and decrypt the secrets of your network in your terminal set a correct password in a (new) file `configurations/<your-configuration-name>/SECRET`.
|
||||
If done please enter:
|
||||
|
||||
```bash
|
||||
# in deployment folder
|
||||
|
||||
# encrypt secrets
|
||||
$ scripts/secrets.encrypt.sh
|
||||
|
||||
# decrypt secrets
|
||||
$ scripts/secrets.decrypt.sh
|
||||
```
|
||||
|
||||
### Maintenance Mode On/Off
|
||||
|
||||
Activate or deactivate maintenance mode in your terminal:
|
||||
|
||||
```bash
|
||||
# in deployment folder
|
||||
|
||||
# activate maintenance mode
|
||||
$ scripts/cluster.maintenance.sh on
|
||||
|
||||
# deactivate maintenance mode
|
||||
$ scripts/cluster.maintenance.sh off
|
||||
```
|
||||
|
||||
### Backup Script
|
||||
|
||||
To save a locale backup of the database and uploaded images:
|
||||
|
||||
```bash
|
||||
# in deployment folder
|
||||
|
||||
# save backup
|
||||
$ scripts/cluster.backup.sh
|
||||
```
|
||||
|
||||
The backup will be saved into your network folders `backup` folder in a new folder with the date and time.
|
||||
|
||||
@ -2,7 +2,9 @@
|
||||
|
||||
When you overtake this deploy and rebrand repo to your network you have to recognize the following changes and doings:
|
||||
|
||||
## Version >= 2.4.0 with 'ocelotDockerVersionTag' 2.4.0-XXX
|
||||
## Version >= 2.4.0 with 'ocelotDockerVersionTag' 2.4.0-298
|
||||
|
||||
- You have to set `SHOW_CONTENT_FILTER_HEADER_MENU` and `SHOW_CONTENT_FILTER_MASONRY_GRID` in `branding/constants/filter.js` originally in main code file `webapp/constants/filter.js` to your preferred value.
|
||||
|
||||
### Main Code PR – feat(webapp): map #5843
|
||||
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
# Configure And Branding
|
||||
|
||||
In this folder you will find all configuration files and logo images to customise the configuration and branding of the [ocelot.social](https://github.com/Ocelot-Social-Community/Ocelot-Social) network code to your own needs.
|
||||
|
||||
Please change these and they will be used automatically as part of the [deployment](/deployment/README.md) process.
|
||||
@ -1,5 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Here, all SCSS variables and classes can be adapted to your custom design.
|
||||
*
|
||||
*/
|
||||
@ -1 +0,0 @@
|
||||
export const PROGRESS_BAR_COLOR_TYPE = 'gradient' // 'uni' is the other option
|
||||
@ -1,8 +0,0 @@
|
||||
// this file is duplicated in `backend/src/config/` and `webapp/constants/` and replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/constants/
|
||||
export default {
|
||||
SUPPORT_EMAIL: 'hello@ocelot.social',
|
||||
MODERATION_EMAIL: 'hello@ocelot.social',
|
||||
// ATTENTION: the following links have to be defined even for internal pages with full URLs as example like 'https://staging.ocelot.social/support', because they are used in e-mails!
|
||||
ORGANIZATION_LINK: 'https://ocelot.social',
|
||||
SUPPORT_LINK: 'https://ocelot.social',
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
// this file is duplicated in `backend/src/constants/group.js` and `webapp/constants/group.js`
|
||||
export const NAME_LENGTH_MIN = 3
|
||||
export const NAME_LENGTH_MAX = 50
|
||||
export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 100 // with removed HTML tags
|
||||
export const SHOW_GROUP_BUTTON_IN_HEADER = true
|
||||
@ -1,13 +0,0 @@
|
||||
export default {
|
||||
MENU: [
|
||||
// {
|
||||
// nameIdent: 'nameIdent',
|
||||
// path: '/',
|
||||
// },
|
||||
// {
|
||||
// nameIdent: 'nameIdent',
|
||||
// url: 'https://ocelot.social',
|
||||
// target: '_blank',
|
||||
// },
|
||||
],
|
||||
}
|
||||
@ -1,152 +0,0 @@
|
||||
// this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/constants/
|
||||
|
||||
import { defaultPageParamsPages } from '~/components/utils/InternalPages.js'
|
||||
|
||||
const ORGANIZATION = defaultPageParamsPages.ORGANIZATION.overwrite({
|
||||
// if defined it's dominating
|
||||
externalLink: {
|
||||
url: 'https://ocelot.social',
|
||||
target: '_blank',
|
||||
},
|
||||
|
||||
internalPage: {
|
||||
// footerIdent: 'site.made', // localized string identifier, if undefined default is used
|
||||
// headTitleIdent: 'site.made', // localized string identifier, if undefined default is used
|
||||
// headlineIdent: 'site.made', // localized string identifier, on null it's hidden, if undefined default is used
|
||||
hasContainer: true,
|
||||
hasBaseCard: true,
|
||||
hasLoginInHeader: true,
|
||||
// in case internal page content is here 'branding/locales/html/'
|
||||
},
|
||||
})
|
||||
const DONATE = defaultPageParamsPages.DONATE.overwrite({
|
||||
// if defined it's dominating
|
||||
externalLink: {
|
||||
// we use 'ocelot-social.herokuapp.com' at the moment, because redirections of 'ocelot.social' subpages are not working correctly
|
||||
url: 'https://ocelot-social.herokuapp.com/donations',
|
||||
target: '_blank',
|
||||
},
|
||||
|
||||
internalPage: {
|
||||
// footerIdent: 'site.donate', // localized string identifier, if undefined default is used
|
||||
// headTitleIdent: 'site.donate', // localized string identifier, if undefined default is used
|
||||
// headlineIdent: 'site.donate', // localized string identifier, on null it's hidden, if undefined default is used
|
||||
hasContainer: true,
|
||||
hasBaseCard: true,
|
||||
hasLoginInHeader: true,
|
||||
// in case internal page content is here 'branding/locales/html/'
|
||||
},
|
||||
})
|
||||
const IMPRINT = defaultPageParamsPages.IMPRINT.overwrite({
|
||||
// if defined it's dominating
|
||||
externalLink: {
|
||||
// we use 'ocelot-social.herokuapp.com' at the moment, because redirections of 'ocelot.social' subpages are not working correctly
|
||||
url: 'https://ocelot-social.herokuapp.com/imprint',
|
||||
target: '_blank',
|
||||
},
|
||||
|
||||
internalPage: {
|
||||
// footerIdent: 'site.imprint', // localized string identifier, if undefined default is used
|
||||
// headTitleIdent: 'site.imprint', // localized string identifier, if undefined default is used
|
||||
// headlineIdent: 'site.imprint', // localized string identifier, on null it's hidden, if undefined default is used
|
||||
hasContainer: true,
|
||||
hasBaseCard: true,
|
||||
hasLoginInHeader: true,
|
||||
// in case internal page content is here 'branding/locales/html/'
|
||||
},
|
||||
})
|
||||
const TERMS_AND_CONDITIONS = defaultPageParamsPages.TERMS_AND_CONDITIONS.overwrite({
|
||||
// externalLink: null, // if defined it's dominating
|
||||
|
||||
internalPage: {
|
||||
// footerIdent: 'site.termsAndConditions', // localized string identifier, if undefined default is used
|
||||
// headTitleIdent: 'site.termsAndConditions', // localized string identifier, if undefined default is used
|
||||
// headlineIdent: 'site.termsAndConditions', // localized string identifier, on null it's hidden, if undefined default is used
|
||||
hasContainer: true,
|
||||
hasBaseCard: true,
|
||||
hasLoginInHeader: true,
|
||||
// in case internal page content is here 'branding/locales/html/'
|
||||
},
|
||||
})
|
||||
const CODE_OF_CONDUCT = defaultPageParamsPages.CODE_OF_CONDUCT.overwrite({
|
||||
// externalLink: null, // if defined it's dominating
|
||||
|
||||
internalPage: {
|
||||
// footerIdent: 'site.code-of-conduct', // localized string identifier, if undefined default is used
|
||||
// headTitleIdent: 'site.code-of-conduct', // localized string identifier, if undefined default is used
|
||||
// headlineIdent: 'site.code-of-conduct', // localized string identifier, on null it's hidden, if undefined default is used
|
||||
hasContainer: true,
|
||||
hasBaseCard: true,
|
||||
hasLoginInHeader: true,
|
||||
// in case internal page content is here 'branding/locales/html/'
|
||||
},
|
||||
})
|
||||
const DATA_PRIVACY = defaultPageParamsPages.DATA_PRIVACY.overwrite({
|
||||
// externalLink: null, // if defined it's dominating
|
||||
|
||||
internalPage: {
|
||||
// footerIdent: 'site.data-privacy', // localized string identifier, if undefined default is used
|
||||
// headTitleIdent: 'site.data-privacy', // localized string identifier, if undefined default is used
|
||||
// headlineIdent: 'site.data-privacy', // localized string identifier, on null it's hidden, if undefined default is used
|
||||
hasContainer: true,
|
||||
hasBaseCard: true,
|
||||
hasLoginInHeader: true,
|
||||
// in case internal page content is here 'branding/locales/html/'
|
||||
},
|
||||
})
|
||||
const FAQ = defaultPageParamsPages.FAQ.overwrite({
|
||||
// externalLink: null, // if defined it's dominating
|
||||
|
||||
internalPage: {
|
||||
// footerIdent: 'site.faq', // localized string identifier, if undefined default is used
|
||||
// headTitleIdent: 'site.faq', // localized string identifier, if undefined default is used
|
||||
// headlineIdent: 'site.faq', // on null default is used, on empty string it's hidden
|
||||
hasContainer: true,
|
||||
hasBaseCard: true,
|
||||
hasLoginInHeader: true,
|
||||
// in case internal page content is here 'branding/locales/html/'
|
||||
},
|
||||
})
|
||||
const SUPPORT = defaultPageParamsPages.SUPPORT.overwrite({
|
||||
// if defined it's dominating
|
||||
externalLink: {
|
||||
url: 'https://ocelot.social',
|
||||
target: '_blank',
|
||||
},
|
||||
|
||||
internalPage: {
|
||||
// footerIdent: 'site.support', // localized string identifier, if undefined default is used
|
||||
// headTitleIdent: 'site.support', // localized string identifier, if undefined default is used
|
||||
// headlineIdent: 'site.support', // on null default is used, on empty string it's hidden
|
||||
hasContainer: true,
|
||||
hasBaseCard: true,
|
||||
hasLoginInHeader: true,
|
||||
// in case internal page content is here 'branding/locales/html/'
|
||||
},
|
||||
})
|
||||
|
||||
export default {
|
||||
LANDING_PAGE: '/login', // examples: '/login', '/registration', '/organization', or external 'https://ocelot.social'
|
||||
|
||||
// you can find and store templates for 👇🏼 at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/
|
||||
|
||||
ORGANIZATION,
|
||||
DONATE,
|
||||
IMPRINT,
|
||||
TERMS_AND_CONDITIONS,
|
||||
CODE_OF_CONDUCT,
|
||||
DATA_PRIVACY,
|
||||
FAQ,
|
||||
SUPPORT,
|
||||
|
||||
FOOTER_LINK_LIST: [
|
||||
ORGANIZATION,
|
||||
TERMS_AND_CONDITIONS,
|
||||
CODE_OF_CONDUCT,
|
||||
DATA_PRIVACY,
|
||||
FAQ,
|
||||
DONATE,
|
||||
IMPRINT,
|
||||
SUPPORT,
|
||||
],
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
// this file is duplicated in `backend/src/config/logos.js` and `webapp/constants/logos.js` and replaced on rebranding
|
||||
// this are the paths in the webapp
|
||||
export default {
|
||||
LOGO_HEADER_PATH: '/img/custom/logo-horizontal.svg',
|
||||
LOGO_HEADER_WIDTH: '130px',
|
||||
LOGO_HEADER_CLICK: {
|
||||
// externalLink: {
|
||||
// url: 'https://ocelot.social',
|
||||
// target: '_blank',
|
||||
// },
|
||||
externalLink: null,
|
||||
internalPath: {
|
||||
to: {
|
||||
name: 'index',
|
||||
},
|
||||
scrollTo: '.main-navigation',
|
||||
},
|
||||
},
|
||||
LOGO_SIGNUP_PATH: '/img/custom/logo-squared.svg',
|
||||
LOGO_WELCOME_PATH: '/img/custom/logo-squared.svg',
|
||||
LOGO_LOGOUT_PATH: '/img/custom/logo-squared.svg',
|
||||
LOGO_PASSWORD_RESET_PATH: '/img/custom/logo-squared.svg',
|
||||
LOGO_MAINTENACE_RESET_PATH: '/img/custom/logo-squared.svg',
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
// this file is duplicated in `backend/src/config/metadata.js` and `webapp/constants/metadata.js` and replaced on rebranding
|
||||
export default {
|
||||
APPLICATION_NAME: 'ocelot.social',
|
||||
APPLICATION_SHORT_NAME: 'ocelot.social',
|
||||
APPLICATION_DESCRIPTION: 'Ocelot Social Community',
|
||||
COOKIE_NAME: 'ocelot-social-token',
|
||||
ORGANIZATION_NAME: 'busFaktor e.V.',
|
||||
ORGANIZATION_JURISDICTION: 'Deutschland',
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
we can put multilanguage e-mails and a layout.html in here
|
||||
@ -1 +0,0 @@
|
||||
we can put translated e-mails in here
|
||||
@ -1 +0,0 @@
|
||||
we can put translated e-mails in here
|
||||
@ -1,2 +0,0 @@
|
||||
{
|
||||
}
|
||||
@ -1,2 +0,0 @@
|
||||
{
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Präambel
|
||||
</h3>
|
||||
<p>
|
||||
Ich bin der Inhalt vom Verhaltenskodex.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Information über die Erhebung personenbezogener Daten
|
||||
</h3>
|
||||
<p>
|
||||
Das hier wäre der Inhalt der Datenschutzbestimmungen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Wohin kann ich spenden?
|
||||
</h3>
|
||||
<p>
|
||||
Hier steht was zu den Spenden.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,67 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Wie bediene ich dieses Netzwerk?
|
||||
</h3>
|
||||
<p>
|
||||
Hier findest Du die
|
||||
<a href="https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki" target="_blank" >Bedienungsanleitung</a>.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Betreiberspezifische FAQs
|
||||
</h3>
|
||||
<p>
|
||||
Hier steht was zu den betreiberspezifischen FAQs.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Betreiber
|
||||
</h3>
|
||||
<p>
|
||||
Ich bin das Impressum.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Das Entwicklernetzwerk
|
||||
</h3>
|
||||
<p>
|
||||
Hier wird das Netzwerk beschrieben.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Ansprechpartner
|
||||
</h3>
|
||||
<p>
|
||||
Ich bin der Inhalt vom Support.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,61 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Nutzung und Lizenz
|
||||
</h3>
|
||||
<p>
|
||||
Ich bin der Inhalt der Seite "Nutzungsbedingungen".
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Präambel
|
||||
</h3>
|
||||
<p>
|
||||
I am the content of the code of conduct.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Information about the collection of personal data
|
||||
</h3>
|
||||
<p>
|
||||
This would be our data privacy section.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Where can I donate?
|
||||
</h3>
|
||||
<p>
|
||||
Here's what it says about donations.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,67 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
How do I operate this network?
|
||||
</h3>
|
||||
<p>
|
||||
Here you can find the
|
||||
<a href="https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki" target="_blank" >user manual</a>.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Operator-Specific FAQs
|
||||
</h3>
|
||||
<p>
|
||||
Here are the operator-specific FAQs.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Operator
|
||||
</h3>
|
||||
<p>
|
||||
I am the imprint.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
The Developers Network
|
||||
</h3>
|
||||
<p>
|
||||
Here the network is described.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Contact
|
||||
</h3>
|
||||
<p>
|
||||
I am the content of the support.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,60 +0,0 @@
|
||||
<!-- this file is replaced on rebranding by https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/locales/html/ -->
|
||||
<!-- you can find and store templates at https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/tree/master/branding/templates/ -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network Ocelot.Social Staging
|
||||
</h2>
|
||||
<h3>
|
||||
Use and License
|
||||
</h3>
|
||||
<p>
|
||||
I am the content of the page "Terms And Conditions".
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 34 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 34 KiB |
@ -1,62 +0,0 @@
|
||||
<!-- this file is a template for rebranding of 'branding/locales/html/de/faq.html' -->
|
||||
|
||||
<!-- template for the 'FAQ' in general -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk {{ organization }}
|
||||
</h2>
|
||||
<h3>
|
||||
Wie bediene ich dieses Netzwerk?
|
||||
</h3>
|
||||
<p>
|
||||
Hier findest Du die
|
||||
<a href="https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki" target="_blank" >Bedienungsanleitung</a>.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,62 +0,0 @@
|
||||
<!-- this file is a template for rebranding of 'branding/locales/html/de/faq.html' -->
|
||||
|
||||
<!-- template for the 'FAQ' in general -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network of {{ organization }}
|
||||
</h2>
|
||||
<h3>
|
||||
How do I operate this network?
|
||||
</h3>
|
||||
<p>
|
||||
Here you can find the
|
||||
<a href="https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki" target="_blank" >user manual</a>.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,163 +0,0 @@
|
||||
<!-- this file is a template for rebranding of 'branding/locales/html/en/code-of-conduct.html' -->
|
||||
|
||||
<!-- template for the 'Code Of Conduct' from the old HC network. in the old repo you will find other languages as well -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk {{ organization }}
|
||||
</h2>
|
||||
<h3>
|
||||
Präambel
|
||||
</h3>
|
||||
<p>
|
||||
{{ networkName}} ist ein gemeinnütziges soziales Wissens- und Aktionsnetzwerk der nächsten Generation.
|
||||
Von Menschen – für Menschen.
|
||||
Free-Software, Open-Source, fair und transparent.
|
||||
Für positiven lokalen und globalen Wandel in allen Lebensbereichen.
|
||||
Wir gestalten den öffentlichen Austausch von Wissen, Ideen und Projekten völlig neu.
|
||||
Die Funktionen von {{ networkName }} bringen die Menschen zusammen – offline und online – so dass wir die Welt zu einem besseren Ort machen können.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Zweck
|
||||
</h3>
|
||||
<p>
|
||||
Mit diesen Verhaltensregeln regeln wir die wesentlichen Grundsätze für das Verhalten in unserem Sozialen Netzwerk.
|
||||
Dabei ist die Menschenrechtscharta der Vereinten Nationen unsere Orientierung und bildet das Herz unseres Werteverständnisses.
|
||||
Die Verhaltensregeln dienen als Leitsätze für den persönlichen Auftritt und den Umgang untereinander.
|
||||
Wer als Nutzer im {{ networkName }} Netzwerk aktiv ist, Beiträge verfasst, kommentiert oder mit anderen Nutzern, auch außerhalb des Netzwerkes, Kontakt aufnimmt, erkennt diese Verhaltensregeln als verbindlich an.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Erwartetes Verhalten
|
||||
</h3>
|
||||
<p>
|
||||
Die folgenden Verhaltensweisen werden von allen Community-Mitgliedern erwartet und gefordert:<br>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Sei rücksichtsvoll und respektvoll, bei dem, was Du schreibst und tust.
|
||||
</li>
|
||||
<li>
|
||||
Versuche auf andere zuzugehen, bevor ein Konflikt entsteht.
|
||||
</li>
|
||||
<li>
|
||||
Vermeide erniedrigende, diskriminierende oder belästigende Verhaltensweisen und Ausdrücke.
|
||||
</li>
|
||||
<li>
|
||||
Achte Dein Umfeld und Deine Mitmenschen. Warne die Verantwortlichen der Community, falls Du eine gefährliche Situation, jemanden in Not oder Verstöße gegen diesen Verhaltenskodex bemerkst, auch wenn diese unbedeutend erscheinen.
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
Nichtakzeptables Verhalten
|
||||
</h3>
|
||||
<p>
|
||||
Die folgenden Verhaltensweisen sind in unserer Community inakzeptabel:<br>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Diskriminierende Beiträge, Kommentare, Äußerungen oder Beleidigungen, insbesondere solche, die sich auf Geschlecht, sexuelle Orientierung, Rasse, Religion, politische oder weltanschauliche Ausrichtung oder Behinderung beziehen
|
||||
</li>
|
||||
<li>
|
||||
Das Senden oder Verlinken eindeutig pornografischen Materials
|
||||
</li>
|
||||
<li>
|
||||
Verherrlichung oder Verharmlosung grausamer oder unmenschlicher Gewalttätigkeiten
|
||||
</li>
|
||||
<li>
|
||||
Das Veröffentlichen von personenbezogenen Daten anderer ohne deren Einverständnis oder das Androhen dessen („Doxing“)
|
||||
</li>
|
||||
<li>
|
||||
Absichtliche Einschüchterung, Stalking oder Verfolgung
|
||||
</li>
|
||||
<li>
|
||||
Bewerben von Produkten und Dienstleistungen mit kommerzieller Absicht
|
||||
</li>
|
||||
<li>
|
||||
Strafbares Verhalten bzw. Verstoß gegen deutsches Recht
|
||||
</li>
|
||||
<li>
|
||||
Befürworten oder Ermutigen zu diesen Verhaltensweisen
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
Konsequenzen inakzeptablen Verhaltens
|
||||
</h3>
|
||||
<p>
|
||||
Wenn ein Gemeinschaftsmitglied inakzeptables Verhalten an den Tag legt, können die verantwortlichen Betreiber, Moderatoren und Administratoren des Netzwerks angemessene Maßnahmen ergreifen, u.a.:<br>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Auffordern zum sofortigen Abstellen des inakzeptablen Verhaltens
|
||||
</li>
|
||||
<li>
|
||||
Sperren oder Löschen von Kommentaren
|
||||
</li>
|
||||
<li>
|
||||
Vorübergehender Ausschluss aus dem jeweiligen Beitrag
|
||||
</li>
|
||||
<li>
|
||||
Sperren bzw. Löschen von Inhalten
|
||||
</li>
|
||||
<li>
|
||||
Vorübergehender Entzug von Schreibrechten
|
||||
</li>
|
||||
<li>
|
||||
Vorübergehender Ausschluss aus dem Netzwerk
|
||||
</li>
|
||||
<li>
|
||||
Endgültiger Ausschluss aus dem Netzwerk
|
||||
</li>
|
||||
<li>
|
||||
Verstöße gegen deutsches Recht können zur Anzeige gebracht werden.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Wenn Du einem inakzeptablen Verhalten ausgesetzt bist, es miterlebst oder andere Bedenken hast, melde bitte so schnell wie möglich den oder die entsprechenden Inhalte an die Moderatoren.
|
||||
Bitte klicke beim Beitrag, Kommentar oder Benutzer auf die drei Punkte und melde ihn über das aufgeklappte Menü.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,136 +0,0 @@
|
||||
<!-- this file is a template for rebranding of 'branding/locales/html/de/terms-and-conditions.html' -->
|
||||
|
||||
<!-- template for the 'Terms And Conditions' from the old HC network. in the old repo you will find other languages as well -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
Für das soziale Netzwerk {{ organization }}
|
||||
</h2>
|
||||
<h3>
|
||||
Nutzungsbedingungen
|
||||
</h3>
|
||||
<p>
|
||||
Die folgenden Nutzungsbedingungen sind Basis für die Nutzung unseres {{ networkName }} Netzwerkes.
|
||||
Beim Registrieren musst Du diese anerkennen und wir werden Dich auch später über ggf. stattfindende Änderungen informieren.
|
||||
Unser Netzwerk wird in der {{ organizationLocation }} betrieben und unterliegt daher {{ organizationLocation2 }} Recht.
|
||||
Gerichtsstand ist {{ legacyLocation }}.
|
||||
Zu Details schau in unser Impressum: <a href="https://{{ networkURL }}/imprint/" target="_blank" >https://{{ networkURL }}/imprint/</a>.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Nutzung und Lizenz
|
||||
</h3>
|
||||
<p>
|
||||
Sind Inhalte, die Du bei uns einstellst, durch Rechte am geistigen Eigentum geschützt, erteilst Du uns eine nicht-exklusive, übertragbare, unterlizenzierbare und weltweite Lizenz für die Nutzung dieser Inhalte für die Bereitstellung in unserem Netzwerk.
|
||||
Diese Lizenz endet, sobald Du Deine Inhalte oder Deinen ganzen Account löscht.
|
||||
Bedenke, dass andere Deine Inhalte weiter teilen können und wir diese nicht löschen können.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Datenschutz
|
||||
</h3>
|
||||
<p>
|
||||
Unser Netzwerk ist ein soziales Wissens- und Aktionsnetzwerk.
|
||||
Daher ist es uns besonders wichtig, dass möglichst viele Inhalte öffentlich zugänglich sind.
|
||||
Im Laufe der Entwicklung unseres Netzwerkes wird es mehr und mehr die Möglichkeit geben, über die Sichtbarkeit der selbst angegebenen bzw. persönlichen Daten zu entscheiden.
|
||||
Über diese neuen Funktionen werden wir Euch informieren.
|
||||
Ansonsten gilt, dass Du immer darüber nachdenken solltest, welche persönlichen Daten Du über Dich (oder andere) preisgibst.
|
||||
Dies gilt insbesondere für Inhalte von Beiträgen und Kommentaren, da diese einen weitgehend öffentlichen Charakter haben.
|
||||
Später wird es Möglichkeiten geben, die Sichtbarkeit Deines Profils einzuschränken.
|
||||
Teil der Nutzungsbedingungen ist unsere Datenschutzerklärung, die Dich über die einzelnen Datenverarbeitungen in unserem Netzwerk informiert: <a href="https://{{ networkURL }}/data-privacy" target="_blank">https://{{ networkURL }}/data-privacy</a>.
|
||||
Unsere Datenschutzerklärung ist an die Gesetzeslage und die Charakteristika unseres Netzwerks angepasst und gilt immer in der aktuellsten Version.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Verhaltenscodex
|
||||
</h3>
|
||||
<p>
|
||||
Unser Verhaltenskodex dient als Leitfaden für das persönliche Auftreten und den Umgang miteinander.
|
||||
Wer als Nutzer im {{ networkName }} 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://{{ networkURL }}/code-of-conduct" target="_blank">https://{{ networkURL }}/code-of-conduct</a><br>
|
||||
</p>
|
||||
<h3>
|
||||
Moderation
|
||||
</h3>
|
||||
<p>
|
||||
Bis unsere finanziellen Möglichkeiten uns erlauben, das Community-Moderationssystem zu implementieren, moderieren wir mit einem vereinfachten System und eigenen bzw. ggf. ehrenamtlichen Mitarbeitern.
|
||||
Wir schulen diese Moderatoren und aus diesem Grund treffen auch nur diese entsprechende Entscheidungen.
|
||||
Diese Moderatoren führen Ihre Tätigkeit anonym aus.
|
||||
Du kannst uns Beiträge, Kommentare und auch Nutzer melden (wenn diese zum Beispiel in ihrem Profil Angaben machen oder Bilder haben, die diese Nutzungsbedingungen verletzen).
|
||||
Wenn Du uns etwas meldest, kannst Du einen Meldegrund angeben und noch eine kurze Erläuterung mitgeben.
|
||||
Wir schauen uns dann das Gemeldete an und sanktionieren ggf., z.B. indem wir Beiträge, Kommentare oder Nutzer sperren.
|
||||
Du und auch der Betroffene erhalten derzeitig von uns leider noch keine Rückmeldung, das ist aber in Planung.
|
||||
Unabhängig davon behalten wir uns prinzipiell Sanktionen vor aus Gründen, die unter Umständen nicht oder noch nicht in unserem Verhaltenscodex oder diesen Nutzungsbedingungen aufgeführt sind.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Fehler und Rückmeldungen
|
||||
</h3>
|
||||
<p>
|
||||
Wir sind sehr bemüht, unser Netzwerk und unsere Daten sicher und abrufbar zu erhalten.
|
||||
Jede neue Version der Software durchläuft sowohl automatisierte als auch manuelle Tests.
|
||||
Es können jedoch unvorhergesehene Fehler auftreten.
|
||||
Deshalb sind wir dankbar für jeden gemeldeten Fehler.
|
||||
Du kannst gerne jeden von Dir entdeckten Fehler dem Support/der Hilfe-Assistenz mitteilen: <a href="https://{{ networkURL }}/support" target="_blank">https://{{ networkURL }}/support</a>.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Keine kommerzielle Nutzung
|
||||
</h3>
|
||||
<p>
|
||||
Die Nutzung des {{ networkName }} Netzwerkes ist nicht für kommerzielle Zwecke gestattet.
|
||||
Darunter fällt unter anderem das Bewerben von Produkten mit kommerzieller Absicht, das Einstellen von Affiliate-Links (Geschäftspartner-Links), direkter Aufruf zu Spenden oder finanzieller Unterstützung für Zwecke, die steuerlich nicht als gemeinnützig anerkannt sind.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Keine politische Nutzung
|
||||
</h3>
|
||||
<p>
|
||||
Nutzerkonten von politischen Parteien oder offizielle Nutzerkonten eines politischen Vertreters sind unzulässig.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Hilfe und Fragen
|
||||
</h3>
|
||||
<p>
|
||||
Für Hilfe und Fragen haben wir Dir eine umfassende Sammlung an häufig gestellten Fragen und Antworten (FAQ) zusammengestellt; Du findest diese auf <a href="https://{{ networkURL }}/faq" target="_blank">https://{{ networkURL }}/faq</a>.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,163 +0,0 @@
|
||||
<!-- this file is a template for rebranding of 'branding/locales/html/en/code-of-conduct.html' -->
|
||||
|
||||
<!-- template for the 'Code Of Conduct' from the old HC network. in the old repo you will find other languages as well -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network of {{ organization }}
|
||||
</h2>
|
||||
<h3>
|
||||
Präambel
|
||||
</h3>
|
||||
<p>
|
||||
{{ networkName }} is a non-profit social knowledge and action network of the next generation.
|
||||
By people - for people. Free software, open source, fair and transparent.
|
||||
For positive local and global change in all areas of life.
|
||||
We completely redesign the public exchange of knowledge, ideas and projects.
|
||||
The functions of {{ networkName }} bring people together - offline and online - so that we can make the world a better place.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Purpose
|
||||
</h3>
|
||||
<p>
|
||||
With these code of conduct we regulate the essential principles for behavior in our social network.
|
||||
The United Nations Charter of Human Rights is our orientation and forms the heart of our understanding of values.
|
||||
The code of conduct serves as guiding principles for our personal appearance and interaction with one another.
|
||||
Anyone who is active as a user in the {{ networkName }} Network, writes articles, comments or contacts other users, including those outside the network,acknowledges these rules of conduct as binding.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Expected Behaviour
|
||||
</h3>
|
||||
<p>
|
||||
The following behaviors are expected and requested of all community members:<br>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Exercise consideration and respect in your speech and actions.
|
||||
</li>
|
||||
<li>
|
||||
Attempt collaboration before conflict.
|
||||
</li>
|
||||
<li>
|
||||
Refrain from demeaning, discriminatory, or harassing behavior and speech.
|
||||
</li>
|
||||
<li>
|
||||
Be mindful of your surroundings and of your fellow participants.
|
||||
Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
Unacceptable Behavior
|
||||
</h3>
|
||||
<p>
|
||||
The following behaviors are unacceptable within our community:<br>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Discriminatory posts, comments, utterances or insults, particularly those relating to gender, sexual orientation, race, religion, political or philosophical orientation or disability.
|
||||
</li>
|
||||
<li>
|
||||
Posting or linking of clearly pornographic material.
|
||||
</li>
|
||||
<li>
|
||||
Glorification or trivialization of cruel or inhuman acts of violence.
|
||||
</li>
|
||||
<li>
|
||||
The disclosure of others' personal information without their consent or threat there of ("doxing").
|
||||
</li>
|
||||
<li>
|
||||
Intentional intimidation, stalking or persecution.
|
||||
</li>
|
||||
<li>
|
||||
Advertising products and services with commercial intent.
|
||||
</li>
|
||||
<li>
|
||||
Criminal behavior or violation of German law.
|
||||
</li>
|
||||
<li>
|
||||
Endorse or encourage such conduct.
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
Consequences of Unacceptable Behavior
|
||||
</h3>
|
||||
<p>
|
||||
If a community member exhibits unacceptable behaviour, the responsible operators, moderators and administrators of the network may take appropriate measures, including but not limited to:<br>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Request for immediate cessation of unacceptable conduct
|
||||
</li>
|
||||
<li>
|
||||
Locking or deleting comments
|
||||
</li>
|
||||
<li>
|
||||
Temporary exclusion from the respective post or contribution
|
||||
</li>
|
||||
<li>
|
||||
Blocking or deleting of content
|
||||
</li>
|
||||
<li>
|
||||
Temporary withdrawal of write permissions
|
||||
</li>
|
||||
<li>
|
||||
Temporary exclusion from the network
|
||||
</li>
|
||||
<li>
|
||||
Final exclusion from the network
|
||||
</li>
|
||||
<li>
|
||||
Violations of German law can be reported.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible and link or refer to the corresponding content.
|
||||
Please click on the three dots on the post, comment or user and report it using the drop-down menu.<br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,135 +0,0 @@
|
||||
<!-- this file is a template for rebranding of 'branding/locales/html/en/terms-and-conditions.html' -->
|
||||
|
||||
<!-- template for the 'Terms And Conditions' from the old HC network. in the old repo you will find other languages as well -->
|
||||
|
||||
<div class="info-page">
|
||||
<h2>
|
||||
For the social network of {{ organization }}
|
||||
</h2>
|
||||
<h3>
|
||||
Terms of Service
|
||||
</h3>
|
||||
<p>
|
||||
The following terms of use form the basis for the use of our network.
|
||||
When you register, you must accept them and we will inform you later about any changes that may take place.
|
||||
The {{ networkName }} Network is operated in Germany and is therefore subject to German law.
|
||||
Place of jurisdiction is {{ organizationLocation }}.
|
||||
For details see our imprint: <a href="https://{{ networkURL }}/imprint/" target="_blank" >https://{{ networkURL }}/imprint/</a><br>
|
||||
</p>
|
||||
<h3>
|
||||
Use and License
|
||||
</h3>
|
||||
<p>
|
||||
If any content you post to us is protected by intellectual property rights, you grant us a non-exclusive, transferable, sublicensable, worldwide license to use such content for posting to our network.
|
||||
This license expires when you delete your content or your entire account.
|
||||
Remember that others may share your content and we cannot delete it.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Privacy Statement
|
||||
</h3>
|
||||
<p>
|
||||
Our network is a social knowledge and action network.
|
||||
It is therefore particularly important to us that as much content as possible is publicly accessible.
|
||||
In the course of the development of our network there will be more and more the possibility to decide about the visibility of the personal data.
|
||||
We will inform you about these new features.
|
||||
Otherwise, you should always think about which personal data you disclose about yourself (or others).
|
||||
This applies in particular to the content of posts and comments, as these have a largely public character.
|
||||
Later there will be possibilities to limit the visibility of your profile.
|
||||
Part of the terms of service is our privacy statement, which informs you about the individual data processing operations in our network: <a href="https://{{ networkURL }}/data-privacy" target="_blank">https://{{ networkURL }}/data-privacy</a>.
|
||||
Our privacy statement is adapted to the legal situation and characteristics of our network and is always valid in the most current version.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Code of Conduct
|
||||
</h3>
|
||||
<p>
|
||||
Our code of conduct serves as a handbook for personal appearance and interaction with each other.
|
||||
Whoever is active as a user in the {{ networkName }} network, writes articles, comments or makes contact with other users, even outside the network, acknowledges these rules of conduct as binding. <a href="https://{{ networkURL }}/code-of-conduct" target="_blank">https://{{ networkURL }}/code-of-conduct</a><br>
|
||||
</p>
|
||||
<h3>
|
||||
Moderation
|
||||
</h3>
|
||||
<p>
|
||||
Until our financial possibilities allow us to implement the community moderation system, we moderate with a simplified system and with our own or possibly volunteer staff.
|
||||
We train these moderators and for this reason only they make the appropriate decisions.
|
||||
These moderators carry out their work anonymously.
|
||||
You can report posts, comments and users to us (for example, if they provide information in their profile or have images that violate these Terms of Use).
|
||||
If you report something to us, you can give us a reason and a short explanation.
|
||||
We will then take a look at what you have reported and sanction you if necessary, e.g. by blocking contributions, comments or users.
|
||||
Unfortunately, you and the person concerned will not receive any feedback from us at this time, but this is in the planning stage.
|
||||
Irrespective of this, we reserve the right to impose sanctions in principle for reasons that may not or not yet be listed in our Code of Conduct or these terms of service.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Errors and Feedback
|
||||
</h3>
|
||||
<p>
|
||||
We make every effort to keep our network and data secure and available.
|
||||
Each new release of the software goes through both automated and manual testing.
|
||||
However, unforeseen errors may occur. Therefore, we are grateful for any reported bugs.
|
||||
You are welcome to report any bugs you discover by emailing Support at <a href="https://{{ networkURL }}/support" target="_blank">https://{{ networkURL }}/support</a><br>
|
||||
</p>
|
||||
<h3>
|
||||
No Commercial Use
|
||||
</h3>
|
||||
<p>
|
||||
The use of the {{ networkName }} Network is not permitted for commercial purposes.
|
||||
This includes, but is not limited to, advertising products with commercial intent, posting affiliate links, directly soliciting donations, or providing financial support for purposes that are not recognized as charitable for tax purposes.<br>
|
||||
</p>
|
||||
<h3>
|
||||
No Political Use
|
||||
</h3>
|
||||
<p>
|
||||
User accounts of political parties or official user accounts of a political representative are not permitted.<br>
|
||||
</p>
|
||||
<h3>
|
||||
Help and Questions
|
||||
</h3>
|
||||
<p>
|
||||
For help and questions we have compiled a comprehensive collection of frequently asked questions and answers (FAQ) for you. You can find them here: <a href="https://{{ networkURL }}/faq" target="_blank">https://{{ networkURL }}/faq</a><br>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style type="text/css">
|
||||
.info-page {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
.info-page h2 {
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.info-page h3 {
|
||||
margin: 24px 0 16px 0;
|
||||
}
|
||||
|
||||
.info-page h4 {
|
||||
margin: 16px 0 8px 0;
|
||||
}
|
||||
|
||||
.info-page p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.info-page ul {
|
||||
list-style-type: disc;
|
||||
margin: 16px 0 16px 14px;
|
||||
}
|
||||
|
||||
.info-page table {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e0dede;
|
||||
border-collapse: collapse;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,.08),inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
margin: 16px 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.info-page table thead {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.info-page table td,
|
||||
.info-page table th {
|
||||
border: 1px solid #e0dede;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,12 +0,0 @@
|
||||
# please duplicate template file and rename to "dns.values.yaml" and fill in your value
|
||||
|
||||
provider: digitalocean
|
||||
digitalocean:
|
||||
# create the API token at https://cloud.digitalocean.com/account/api/tokens
|
||||
# needs read + write
|
||||
apiToken: "TODO"
|
||||
domainFilters:
|
||||
# domains you want external-dns to be able to edit
|
||||
- TODO.TODO
|
||||
rbac:
|
||||
create: true
|
||||
@ -1,120 +0,0 @@
|
||||
# please duplicate template file and rename to "values.yaml" and fill in your value
|
||||
|
||||
# change all the below if needed
|
||||
MAPBOX_TOKEN: "pk.eyJ1IjoiYnVzZmFrdG9yIiwiYSI6ImNraDNiM3JxcDBhaWQydG1uczhpZWtpOW4ifQ.7TNRTO-o9aK1Y6MyW_Nd4g"
|
||||
PRODUCTION_DB_CLEAN_ALLOW: false # only true for production environments on staging servers
|
||||
PUBLIC_REGISTRATION: false
|
||||
INVITE_REGISTRATION: false
|
||||
COOKIE_EXPIRE_TIME: 730 # days (730 days, two years is the default in main code)
|
||||
CATEGORIES_ACTIVE: false
|
||||
|
||||
BACKEND:
|
||||
# change all the below if needed
|
||||
# DOCKER_IMAGE_REPO - change that to your branded docker image
|
||||
# label is appended based on .Chart.appVersion
|
||||
DOCKER_IMAGE_REPO: "ocelotsocialnetwork/backend-branded"
|
||||
CLIENT_URI: "https://staging.ocelot.social"
|
||||
# create a new one for your network
|
||||
JWT_SECRET: "b/&&7b78BF&fv/Vd"
|
||||
PRIVATE_KEY_PASSPHRASE: "a7dsf78sadg87ad87sfagsadg78"
|
||||
# ocelot.social mail dummy
|
||||
EMAIL_DEFAULT_SENDER: "devops@ocelot.social"
|
||||
SMTP_HOST: "mail.ocelot.social"
|
||||
SMTP_USERNAME: "devops@ocelot.social"
|
||||
SMTP_PASSWORD: "devops@ocelot.social"
|
||||
SMTP_PORT: "587"
|
||||
SMTP_IGNORE_TLS: 'false'
|
||||
SMTP_SECURE: 'false' # true for 465, false for other ports
|
||||
# or
|
||||
# SMTP_PORT: "465"
|
||||
# SMTP_IGNORE_TLS: 'true'
|
||||
# SMTP_SECURE: 'true' # true for 465, false for other ports
|
||||
|
||||
# most likely you don't need to change this
|
||||
MIN_READY_SECONDS: "15"
|
||||
PROGRESS_DEADLINE_SECONDS: "60"
|
||||
REVISIONS_HISTORY_LIMIT: "25"
|
||||
CONTAINER_RESTART_POLICY: "Always"
|
||||
CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS: "30"
|
||||
DOCKER_IMAGE_PULL_POLICY: "Always"
|
||||
STORAGE_UPLOADS: "25Gi"
|
||||
|
||||
WEBAPP:
|
||||
# change all the below if needed
|
||||
# DOCKER_IMAGE_REPO - change that to your branded docker image
|
||||
# label is appended based on .Chart.appVersion
|
||||
DOCKER_IMAGE_REPO: "ocelotsocialnetwork/webapp-branded"
|
||||
WEBSOCKETS_URI: "wss://staging.ocelot.social/api/graphql"
|
||||
|
||||
# Most likely you don't need to change this
|
||||
REPLICAS: "2"
|
||||
MIN_READY_SECONDS: "15"
|
||||
PROGRESS_DEADLINE_SECONDS: "60"
|
||||
REVISIONS_HISTORY_LIMIT: "25"
|
||||
CONTAINER_RESTART_POLICY: "Always"
|
||||
CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS: "30"
|
||||
DOCKER_IMAGE_PULL_POLICY: "Always"
|
||||
|
||||
NEO4J:
|
||||
# most likely you don't need to change this
|
||||
REVISIONS_HISTORY_LIMIT: "25"
|
||||
DOCKER_IMAGE_REPO: "ocelotsocialnetwork/neo4j-community-branded"
|
||||
DOCKER_IMAGE_PULL_POLICY: "Always"
|
||||
CONTAINER_RESTART_POLICY: "Always"
|
||||
CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS: "30"
|
||||
STORAGE: "5Gi"
|
||||
# RESOURCE_REQUESTS_MEMORY configures the memory available for requests.
|
||||
RESOURCE_REQUESTS_MEMORY: "2G"
|
||||
# RESOURCE_LIMITS_MEMORY configures the memory limits available.
|
||||
RESOURCE_LIMITS_MEMORY: "4G"
|
||||
# required for Neo4j Enterprice version
|
||||
#ACCEPT_LICENSE_AGREEMENT: "yes"
|
||||
ACCEPT_LICENSE_AGREEMENT: "no"
|
||||
AUTH: "none"
|
||||
#DBMS_CONNECTOR_BOLT_THREAD_POOL_MAX_SIZE: "10000" # hc value
|
||||
DBMS_CONNECTOR_BOLT_THREAD_POOL_MAX_SIZE: "400" # default value
|
||||
#DBMS_MEMORY_HEAP_INITIAL_SIZE: "500MB" # HC value
|
||||
DBMS_MEMORY_HEAP_INITIAL_SIZE: "" # default
|
||||
#DBMS_MEMORY_HEAP_MAX_SIZE: "500MB" # HC value
|
||||
DBMS_MEMORY_HEAP_MAX_SIZE: "" # default
|
||||
#DBMS_MEMORY_PAGECACHE_SIZE: "490M" # HC value
|
||||
DBMS_MEMORY_PAGECACHE_SIZE: "" # default
|
||||
#APOC_IMPORT_FILE_ENABLED: "true" # HC value
|
||||
APOC_IMPORT_FILE_ENABLED: "false" # default
|
||||
DBMS_SECURITY_PROCEDURES_UNRESTRICTED: "algo.*,apoc.*"
|
||||
|
||||
MAINTENANCE:
|
||||
# change all the below if needed
|
||||
# DOCKER_IMAGE_REPO - change that to your branded docker image
|
||||
# label is appended based on .Chart.appVersion
|
||||
DOCKER_IMAGE_REPO: "ocelotsocialnetwork/maintenance-branded"
|
||||
|
||||
# Most likely you don't need to change this
|
||||
REVISIONS_HISTORY_LIMIT: "25"
|
||||
CONTAINER_RESTART_POLICY: "Always"
|
||||
CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS: "30"
|
||||
DOCKER_IMAGE_PULL_POLICY: "Always"
|
||||
|
||||
LETSENCRYPT:
|
||||
# change all the below if needed
|
||||
# ISSUER is used by cert-manager to set up certificates with the given provider.
|
||||
# change it to "letsencrypt-production" once you are ready to have valid cetrificates.
|
||||
# Be aware that the is an issuing limit with letsencrypt, so a dry run with staging might be wise
|
||||
ISSUER: "letsencrypt-staging"
|
||||
EMAIL: "devops@ocelot.social"
|
||||
DOMAINS:
|
||||
- "staging.ocelot.social"
|
||||
- "www.staging.ocelot.social"
|
||||
|
||||
NGINX:
|
||||
# most likely you don't need to change this
|
||||
PROXY_BODY_SIZE: "10m"
|
||||
|
||||
STORAGE:
|
||||
# change all the below if needed
|
||||
PROVISIONER: "dobs.csi.digitalocean.com"
|
||||
|
||||
# most likely you don't need to change this
|
||||
RECLAIM_POLICY: "Retain"
|
||||
VOLUME_BINDING_MODE: "Immediate"
|
||||
ALLOW_VOLUME_EXPANSION: true
|
||||
1
deployment/configurations/stage.ocelot.social
Submodule
1
deployment/configurations/stage.ocelot.social
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit be3ac7ad29f37d6a00fb3203db302cd91cebb9fa
|
||||
@ -65,10 +65,10 @@ services:
|
||||
|
||||
backend:
|
||||
image: ocelotsocialnetwork/backend-branded:local-${CONFIGURATION}
|
||||
container_name: backend
|
||||
container_name: backend-branded
|
||||
build:
|
||||
dockerfile: src/docker/backend.Dockerfile
|
||||
target: branded-branded
|
||||
target: branded
|
||||
context: .
|
||||
args:
|
||||
- CONFIGURATION=$CONFIGURATION
|
||||
@ -143,7 +143,7 @@ services:
|
||||
|
||||
neo4j:
|
||||
image: ocelotsocialnetwork/neo4j-community:latest
|
||||
container_name: neo4j
|
||||
container_name: neo4j-branded
|
||||
networks:
|
||||
- test-network
|
||||
volumes:
|
||||
|
||||
@ -9,20 +9,38 @@
|
||||
SCRIPT_PATH=$(realpath $0)
|
||||
SCRIPT_DIR=$(dirname $SCRIPT_PATH)
|
||||
|
||||
# check CONFIGURATION
|
||||
if [ -z ${CONFIGURATION} ]; then
|
||||
echo "You must provide a `CONFIGURATION` via environment variable"
|
||||
exit 1
|
||||
fi
|
||||
echo "Using CONFIGURATION=${CONFIGURATION}"
|
||||
|
||||
# check DOCKERHUB_BRAND_VARRIANT
|
||||
if [ -z ${DOCKERHUB_BRAND_VARRIANT} ]; then
|
||||
echo "You must provide a `DOCKERHUB_BRAND_VARRIANT` via environment variable"
|
||||
exit 1
|
||||
fi
|
||||
echo "Using DOCKERHUB_BRAND_VARRIANT=${DOCKERHUB_BRAND_VARRIANT}"
|
||||
|
||||
# configuration
|
||||
CONFIGURATION=${CONFIGURATION:-"example"}
|
||||
DOCKERHUB_ORGANISATION=${DOCKERHUB_ORGANISATION:-"ocelotsocialnetwork"}
|
||||
OCELOT_VERSION=${OCELOT_VERSION:-$(node -p -e "require('${SCRIPT_DIR}/../../package.json').version")}
|
||||
OCELOT_GITHUB_RUN_NUMBER=${OCELOT_GITHUB_RUN_NUMBER:-master}
|
||||
OCELOT_VERSION_BUILD=${OCELOT_VERSION_BUILD:-${OCELOT_VERSION}-${OCELOT_GITHUB_RUN_NUMBER}}
|
||||
BRANDED_VERSION=${BRANDED_VERSION:-${GITHUB_RUN_NUMBER:-"local"}}
|
||||
BUILD_DATE=${BUILD_DATE:-$(date -u +'%Y-%m-%dT%H:%M:%SZ')}
|
||||
BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION}
|
||||
BUILD_VERSION_BASE=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION}
|
||||
BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION_BUILD}
|
||||
BUILD_COMMIT=${GITHUB_SHA:-"0000000"}
|
||||
|
||||
# backend
|
||||
docker build --target branded \
|
||||
-t "${DOCKERHUB_ORGANISATION}/backend-branded:latest" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/backend-branded:${OCELOT_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/backend-branded:${BUILD_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:latest" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \
|
||||
-f "${SCRIPT_DIR}/../src/docker/backend.Dockerfile" \
|
||||
--build-arg "CONFIGURATION=${CONFIGURATION}" \
|
||||
--build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \
|
||||
@ -31,9 +49,11 @@ docker build --target branded \
|
||||
|
||||
# webapp
|
||||
docker build --target branded \
|
||||
-t "${DOCKERHUB_ORGANISATION}/webapp-branded:latest" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/webapp-branded:${OCELOT_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/webapp-branded:${BUILD_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:latest" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \
|
||||
-f "${SCRIPT_DIR}/../src/docker/webapp.Dockerfile" \
|
||||
--build-arg "CONFIGURATION=${CONFIGURATION}" \
|
||||
--build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \
|
||||
@ -42,9 +62,11 @@ docker build --target branded \
|
||||
|
||||
# mainteance
|
||||
docker build --target branded \
|
||||
-t "${DOCKERHUB_ORGANISATION}/maintenance-branded:latest" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/maintenance-branded:${OCELOT_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/maintenance-branded:${BUILD_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:latest" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \
|
||||
-t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \
|
||||
-f "${SCRIPT_DIR}/../src/docker/maintenance.Dockerfile" \
|
||||
--build-arg "CONFIGURATION=${CONFIGURATION}" \
|
||||
--build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \
|
||||
|
||||
@ -10,26 +10,42 @@
|
||||
SCRIPT_PATH=$(realpath $0)
|
||||
SCRIPT_DIR=$(dirname $SCRIPT_PATH)
|
||||
|
||||
# check DOCKERHUB_BRAND_VARRIANT
|
||||
if [ -z ${DOCKERHUB_BRAND_VARRIANT} ]; then
|
||||
echo "You must provide a `DOCKERHUB_BRAND_VARRIANT` via environment variable"
|
||||
exit 1
|
||||
fi
|
||||
echo "Using DOCKERHUB_BRAND_VARRIANT=${DOCKERHUB_BRAND_VARRIANT}"
|
||||
|
||||
# configuration
|
||||
DOCKERHUB_ORGANISATION=${DOCKERHUB_ORGANISATION:-"ocelotsocialnetwork"}
|
||||
OCELOT_VERSION=${OCELOT_VERSION:-$(node -p -e "require('${SCRIPT_DIR}/../../package.json').version")}
|
||||
OCELOT_GITHUB_RUN_NUMBER=${OCELOT_GITHUB_RUN_NUMBER:-master}
|
||||
OCELOT_VERSION_BUILD=${OCELOT_VERSION_BUILD:-${OCELOT_VERSION}-${OCELOT_GITHUB_RUN_NUMBER}}
|
||||
BRANDED_VERSION=${BRANDED_VERSION:-${GITHUB_RUN_NUMBER:-"local"}}
|
||||
BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION}
|
||||
BUILD_VERSION_BASE=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION}
|
||||
BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION_BUILD}
|
||||
|
||||
# login to dockerhub
|
||||
echo "${DOCKERHUB_TOKEN}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin
|
||||
|
||||
# push backend images
|
||||
docker push ${DOCKERHUB_ORGANISATION}/backend-branded:latest
|
||||
docker push ${DOCKERHUB_ORGANISATION}/backend-branded:${OCELOT_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/backend-branded:${BUILD_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:latest
|
||||
docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}
|
||||
|
||||
# push webapp images
|
||||
docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:latest
|
||||
docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:${OCELOT_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:${BUILD_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:latest
|
||||
docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}
|
||||
|
||||
# push maintenance images
|
||||
docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:latest
|
||||
docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:${OCELOT_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:${BUILD_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:latest
|
||||
docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}
|
||||
docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user