Merge branch 'master' into LarsE11-changed-placeholder-field-for-event-location

This commit is contained in:
Hannes Heine 2024-03-04 09:48:07 +01:00 committed by GitHub
commit 563bdeb9be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
237 changed files with 57411 additions and 3768 deletions

View File

@ -66,3 +66,29 @@ updates:
day: "saturday"
timezone: "Europe/Berlin"
time: "03:00"
# frontend
- package-ecosystem: "github-actions"
directory: "/frontend"
rebase-strategy: "disabled"
schedule:
interval: weekly
day: "saturday"
timezone: "Europe/Berlin"
time: "03:00"
- package-ecosystem: npm
directory: "/frontend"
rebase-strategy: "disabled"
schedule:
interval: weekly
day: "saturday"
timezone: "Europe/Berlin"
time: "03:00"
- package-ecosystem: docker
directory: "/frontend"
rebase-strategy: "disabled"
schedule:
interval: weekly
day: "saturday"
timezone: "Europe/Berlin"
time: "03:00"

View File

@ -1,3 +1,5 @@
# These file filter patterns are used by the action https://github.com/dorny/paths-filter
backend: &backend
- '.github/workflows/test-backend.yml'
- 'backend/**/*'
@ -11,3 +13,41 @@ webapp: &webapp
- '.github/workflows/test-webapp.yml'
- 'webapp/**/*'
- 'package.json'
docs-check: &docs-check
- '.github/workflows/check-documentation.yml'
markdown: &markdown
- *docs-check
- '**/*.md'
- '.github/workflows/mlc_config.json'
vuepress: &vuepress
- *docs-check
- '.github/workflows/deploy-documentation.yml'
- '.vuepress/**/*'
- 'package.json'
documentation: &documentation
- *vuepress
- *markdown
# frontend
frontend-test-lint-code: &frontend-test-lint-code
- 'frontend/**/*'
frontend-test-unit-code: &frontend-test-unit-code
- 'frontend/**/*'
frontend-test-build-code: &frontend-test-build-code
- 'frontend/**/*'
frontend-test-build-docker: &frontend-test-build-docker
- 'frontend/**/*'
frontend-test-build-docs: &frontend-test-build-docs
- 'frontend/**/*.md'
- 'frontend/.vuepress/*'
frontend-test-build-storybook: &frontend-test-build-storybook
- 'frontend/**/*'

View File

@ -0,0 +1,65 @@
name: ocelot.social check documentation
on: push
jobs:
files-changed:
name: Detect File Changes - Markdown files
runs-on: ubuntu-latest
outputs:
markdown: ${{ steps.changes.outputs.markdown }}
documentation: ${{ steps.changes.outputs.documentation }}
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Check for markdown file changes
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
check-markdown-links:
name: Check Markdown links
needs: files-changed
runs-on: ubuntu-latest
if: needs.files-changed.outputs.markdown == 'true'
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Remove old documentation files
run: rm -rf ./deployment/src/old/ ./CHANGELOG.md # workaround until https://github.com/gaurav-nelson/github-action-markdown-link-check/pull/183 has been done
- name: Check Markdown Links
uses: gaurav-nelson/github-action-markdown-link-check@master
with:
use-quiet-mode: 'yes'
use-verbose-mode: 'no'
# at any .md file change take the chance to check the links in all .md files
check-modified-files-only: 'no'
config-file: '.github/workflows/mlc_config.json'
base-branch: 'master'
folder-path: '.'
test-vuepress-build:
name: Test Vuepress build
needs: files-changed
runs-on: ubuntu-latest
if: needs.files-changed.outputs.documentation == 'true'
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Setup Node 20
uses: actions/setup-node@v4
with:
node-version: '20'
- name: npm-install
run: npm install
- name: npm-docs:build
run: npm run docs:build

View File

@ -0,0 +1,48 @@
name: ocelot.social deploy documentation
on:
push:
branches:
- master
jobs:
files-changed:
name: Detect File Changes - Markdown and Vuepress files
runs-on: ubuntu-latest
outputs:
documentation: ${{ steps.changes.outputs.documentation }}
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Check for file changes
uses: dorny/paths-filter@master
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: Setup Node 20
uses: actions/setup-node@v4
with:
node-version: 20
- name: Build Vuepress Pages
run: npm install && npm run docs:build
- name: Deploy Vuepress to Github Pages
uses: crazy-max/ghaction-github-pages@v4
with:
target_branch: gh-pages
build_dir: .vuepress/dist
author: Wolfgang Huß <vorstand@busfaktor.org>
fqdn: docs.ocelot.social
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -0,0 +1,21 @@
name: "frontend:deploy:chromatic"
on:
push:
branches:
- master
jobs:
build-and-deploy:
name: Chromatic - Frontend
runs-on: ubuntu-latest
env:
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
WORKING_DIRECTORY: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Frontend | Build
run: npm install && npm run chromatic -- --exit-zero-on-changes
working-directory: ${{env.WORKING_DIRECTORY}}

View File

@ -0,0 +1,37 @@
name: "frontend:test:build test code"
on: push
jobs:
# only (but most important) job from this workflow required for pull requests
# check results serve as run conditions for all other jobs here
files-changed:
name: Detect File Changes - frontend-test-build-code
runs-on: ubuntu-latest
outputs:
changes: ${{ steps.changes.outputs.frontend-test-build-code }}
steps:
- uses: actions/checkout@v4
- name: Check for frontend file changes
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
build:
if: needs.files-changed.outputs.changes == 'true'
name: Build - Frontend
needs: files-changed
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Frontend | Build
run: npm install && npm run build
working-directory: ${{env.WORKING_DIRECTORY}}

View File

@ -0,0 +1,52 @@
name: "frontend:test:build test docker"
on: push
jobs:
# only (but most important) job from this workflow required for pull requests
# check results serve as run conditions for all other jobs here
files-changed:
name: Detect File Changes - frontend-test-build-docker
runs-on: ubuntu-latest
outputs:
changes: ${{ steps.changes.outputs.frontend-test-build-docker }}
steps:
- uses: actions/checkout@v4
- name: Check for frontend file changes
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
build-production:
if: needs.files-changed.outputs.changes == 'true'
name: Build Docker Production - Frontend
needs: files-changed
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Frontend | Build Docker Production
run: docker compose -f docker-compose.yml build
working-directory: ${{env.WORKING_DIRECTORY}}
build-development:
if: needs.files-changed.outputs.changes == 'true'
name: Build Docker Development - Frontend
needs: files-changed
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Frontend | Build Docker Development
run: docker compose build
working-directory: ${{env.WORKING_DIRECTORY}}

View File

@ -0,0 +1,37 @@
name: "frontend:test:build test docs"
on: push
jobs:
# only (but most important) job from this workflow required for pull requests
# check results serve as run conditions for all other jobs here
files-changed:
name: Detect File Changes - frontend-test-build-docs
runs-on: ubuntu-latest
outputs:
changes: ${{ steps.changes.outputs.frontend-test-build-docs }}
steps:
- uses: actions/checkout@v4
- name: Check for frontend file changes
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
build:
if: needs.files-changed.outputs.changes == 'true'
name: Build Docs - Frontend
needs: files-changed
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Frontend | Build Docs
run: npm install && npm run docs:build
working-directory: ${{env.WORKING_DIRECTORY}}

View File

@ -0,0 +1,37 @@
name: "frontend:test:build test storybook"
on: push
jobs:
# only (but most important) job from this workflow required for pull requests
# check results serve as run conditions for all other jobs here
files-changed:
name: Detect File Changes - frontend-test-build-storybook
runs-on: ubuntu-latest
outputs:
changes: ${{ steps.changes.outputs.frontend-test-build-storybook }}
steps:
- uses: actions/checkout@v4
- name: Check for frontend file changes
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
storybook:
if: needs.files-changed.outputs.changes == 'true'
name: Build Storybook - Frontend
needs: files-changed
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Frontend | Build Storybook
run: npm install && npm run storybook:build
working-directory: ${{env.WORKING_DIRECTORY}}

View File

@ -0,0 +1,37 @@
name: "frontend:test:lint code with defined linters"
on: push
jobs:
# only (but most important) job from this workflow required for pull requests
# check results serve as run conditions for all other jobs here
files-changed:
name: Detect File Changes - frontend-test-lint-code
runs-on: ubuntu-latest
outputs:
changes: ${{ steps.changes.outputs.frontend-test-lint-code }}
steps:
- uses: actions/checkout@v4
- name: Check for frontend file changes
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
lint:
if: needs.files-changed.outputs.changes == 'true'
name: Lint - Frontend
needs: files-changed
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Frontend | Lint
run: npm install && npm run test:lint
working-directory: ${{env.WORKING_DIRECTORY}}

View File

@ -0,0 +1,37 @@
name: "frontend:test:unit test code with defined suites"
on: push
jobs:
# only (but most important) job from this workflow required for pull requests
# check results serve as run conditions for all other jobs here
files-changed:
name: Detect File Changes - frontend-test-unit-code
runs-on: ubuntu-latest
outputs:
changes: ${{ steps.changes.outputs.frontend-test-unit-code }}
steps:
- uses: actions/checkout@v4
- name: Check for frontend file changes
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
filters: .github/file-filters.yml
list-files: shell
unit:
if: needs.files-changed.outputs.changes == 'true'
name: Unit - Frontend
needs: files-changed
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Frontend | Unit
run: npm install && npm run test:unit
working-directory: ${{env.WORKING_DIRECTORY}}

12
.github/workflows/mlc_config.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"timeout": "20s",
"retryOn429": true,
"retryCount": 2,
"fallbackRetryDelay": "30s",
"aliveStatusCodes": [200, 206, 303, 403],
"ignorePatterns": [
{
"pattern": "^(https:\/\/github.com\/Ocelot-Social-Community\/Ocelot-Social\/(pull|deployment\/src\/old)\/|http:\/\/localhost)"
}
]
}

View File

@ -34,7 +34,7 @@ jobs:
- name: Neo4J | Save docker image
run: docker save "ocelotsocialnetwork/neo4j-community" > /tmp/neo4j.tar
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docker-neo4j-community
path: /tmp/neo4j.tar
@ -83,7 +83,7 @@ jobs:
- name: Backend | Save docker image
run: docker save "ocelotsocialnetwork/backend" > /tmp/backend.tar
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docker-backend-production
path: /tmp/backend.tar
@ -132,7 +132,7 @@ jobs:
- name: Webapp | Save docker image
run: docker save "ocelotsocialnetwork/webapp" > /tmp/webapp.tar
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docker-webapp-production
path: /tmp/webapp.tar
@ -184,7 +184,7 @@ jobs:
- name: Maintenance | Save docker image
run: docker save "ocelotsocialnetwork/maintenance" > /tmp/maintenance.tar
- name: Upload Artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docker-maintenance-production
path: /tmp/maintenance.tar
@ -201,25 +201,25 @@ jobs:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
steps:
- name: Download Docker Image (Neo4J)
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: docker-neo4j-community
path: /tmp
- run: docker load < /tmp/neo4j.tar
- name: Download Docker Image (Backend)
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: docker-backend-production
path: /tmp
- run: docker load < /tmp/backend.tar
- name: Download Docker Image (WebApp)
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: docker-webapp-production
path: /tmp
- run: docker load < /tmp/webapp.tar
- name: Download Docker Image (Maintenance)
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: docker-maintenance-production
path: /tmp
@ -253,7 +253,7 @@ jobs:
echo "BUILD_COMMIT=${GITHUB_SHA}" >> $GITHUB_ENV
- run: echo "BUILD_VERSION=${VERSION}-${GITHUB_RUN_NUMBER}" >> $GITHUB_ENV
- name: package-version-to-git-tag + build number
uses: pkgdeps/git-tag-action@v2
uses: pkgdeps/git-tag-action@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
github_repo: ${{ github.repository }}
@ -293,7 +293,7 @@ jobs:
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
# uses: peter-evans/repository-dispatch@v3
# with:
# token: ${{ github.token }}
# event-type: trigger-ocelot-build-success
@ -301,7 +301,7 @@ jobs:
# 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
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository
event-type: trigger-ocelot-build-success
@ -309,7 +309,7 @@ jobs:
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
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository
event-type: trigger-ocelot-build-success

View File

@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v4
- name: Check for backend file changes
uses: dorny/paths-filter@v2.11.1
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
@ -37,7 +37,7 @@ jobs:
- name: Cache docker images
id: cache-neo4j
uses: actions/cache/save@v3.3.2
uses: actions/cache/save@v4.0.1
with:
path: /tmp/neo4j.tar
key: ${{ github.run_id }}-backend-neo4j-cache
@ -58,7 +58,7 @@ jobs:
- name: Cache docker images
id: cache-backend
uses: actions/cache/save@v3.3.2
uses: actions/cache/save@v4.0.1
with:
path: /tmp/backend.tar
key: ${{ github.run_id }}-backend-cache
@ -87,14 +87,14 @@ jobs:
uses: actions/checkout@v4
- name: Restore Neo4J cache
uses: actions/cache/restore@v3.3.2
uses: actions/cache/restore@v4.0.1
with:
path: /tmp/neo4j.tar
key: ${{ github.run_id }}-backend-neo4j-cache
fail-on-cache-miss: true
- name: Restore Backend cache
uses: actions/cache/restore@v3.3.2
uses: actions/cache/restore@v4.0.1
with:
path: /tmp/backend.tar
key: ${{ github.run_id }}-backend-cache
@ -108,6 +108,7 @@ jobs:
- name: backend | copy env files
run: |
cp webapp/.env.template webapp/.env
cp frontend/.env.dist frontend/.env
cp backend/.env.template backend/.env
- name: backend | docker-compose

View File

@ -13,6 +13,7 @@ jobs:
- name: Copy env files
run: |
cp webapp/.env.template webapp/.env
cp frontend/.env.dist frontend/.env
cp backend/.env.template backend/.env
- name: Build docker images
@ -36,7 +37,7 @@ jobs:
- name: Cache docker images
id: cache
uses: actions/cache/save@v3.3.2
uses: actions/cache/save@v4.0.1
with:
path: |
/opt/cucumber-json-formatter
@ -58,7 +59,7 @@ jobs:
job: [1, 2, 3, 4, 5, 6, 7, 8]
steps:
- name: Restore cache
uses: actions/cache/restore@v3.3.2
uses: actions/cache/restore@v4.0.1
id: cache
with:
path: |
@ -92,7 +93,7 @@ jobs:
- name: Full stack tests | if tests failed, upload report
id: e2e-report
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ocelot-e2e-test-report-pr${{ needs.docker_preparation.outputs.pr-number }}
path: /home/runner/work/Ocelot-Social/Ocelot-Social/cypress/reports/cucumber_html_report

View File

@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v4
- name: Check for frontend file changes
uses: dorny/paths-filter@v2.11.1
uses: dorny/paths-filter@v3.0.1
id: changes
with:
token: ${{ github.token }}
@ -50,7 +50,7 @@ jobs:
docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar
- name: Cache docker image
uses: actions/cache/save@v3.3.2
uses: actions/cache/save@v4.0.1
with:
path: /tmp/webapp.tar
key: ${{ github.run_id }}-webapp-cache
@ -79,7 +79,7 @@ jobs:
uses: actions/checkout@v4
- name: Restore webapp cache
uses: actions/cache/restore@v3.3.2
uses: actions/cache/restore@v4.0.1
with:
path: /tmp/webapp.tar
key: ${{ github.run_id }}-webapp-cache
@ -90,6 +90,7 @@ jobs:
- name: Copy env files
run: |
cp webapp/.env.template webapp/.env
cp frontend/.env.dist frontend/.env
cp backend/.env.template backend/.env
- name: backend | docker-compose

View File

@ -1,4 +1,4 @@
name: "ocelot.social lint pull request CI"
name: "test:lint pull request CI"
on:
pull_request_target:
@ -7,6 +7,10 @@ on:
- edited
- synchronize
permissions:
pull-requests: write
statuses: write
jobs:
main:
name: Validate PR title
@ -26,8 +30,12 @@ jobs:
scopes: |
backend
webapp
frontend
database
docu
docker
release
workflow
other
# Configure that a scope must always be provided.
requireScope: true

6
.gitignore vendored
View File

@ -8,12 +8,18 @@ yarn-error.log*
.yarn-integrity
.eslintcache
kubeconfig.yaml
backup-cron-job.log
node_modules/
cypress/videos
cypress/screenshots/
cypress.env.json
.vuepress/.cache/
.vuepress/.temp/
.vuepress/dist/
!.gitkeep
**/coverage

12
.vuepress/config.js Normal file
View File

@ -0,0 +1,12 @@
import { defineUserConfig } from 'vuepress'
import { viteBundler } from '@vuepress/bundler-vite'
import meta from './config/meta'
import theme from './config/theme'
export default defineUserConfig({
pagePatterns: ['**/*.md', '!.vuepress', '!node_modules', '!backend/node_modules', '!webapp/node_modules', '!deployment/src/old'],
bundler: viteBundler(),
...meta,
theme,
})

8
.vuepress/config/meta.js Normal file
View File

@ -0,0 +1,8 @@
export default {
base: '/',
title: 'Ocelot.Social Documentation',
description: 'Ocelot.Social Documentation',
head: [
['meta', {name: 'viewport', content: 'width=device-width,initial-scale=1'}],
],
}

114
.vuepress/config/theme.js Normal file
View File

@ -0,0 +1,114 @@
import path from 'path'
import fs from 'fs'
import { hopeTheme } from 'vuepress-theme-hope'
export default hopeTheme({
favicon: 'favicon.ico',
logo: '/logo.svg',
docsRepo: 'https://github.com/Ocelot-Social-Community/Ocelot-Social',
docsBranch: 'master',
docsDir: '.',
editLink: true,
lastUpdated: false,
contributors: false,
print: false,
pure: true,
navbarLayout: {
start: ['Brand'],
center: ['Links'],
end: ['Repo', 'Outlook', 'Search'],
},
repo: 'Ocelot-Social-Community/Ocelot-Social',
repoLabel: 'GitHub',
repoDisplay: true,
displayFooter: true,
copyright: '&copy; by <a href="https://busfaktor.org" target="_blank">busFaktor() e.V.</a> & Authors | <a href="https://ocelot.social/en/impressum/">Imprint</a>',
footer: 'Released under the <a class="vt-link link link" href="https://opensource.org/licenses/MIT" target="_blank" rel="noopener noreferrer"><!--[-->MIT License<!--]--><!----></a>.',
sidebar: generateSidebar('../../SUMMARY.md'),
navbar: [
{
text: 'Demo',
link: 'https://stage.ocelot.social/',
target: '_self',
},
],
plugins: {
mdEnhance: {
align: true,
demo: true,
imgLazyload: true,
imgMark: true,
imgSize: true,
sub: true,
sup: true,
tabs: true,
vPre: true,
},
searchPro: {
indexContent: true,
autoSuggestions: true,
customFields: [
{
getter: (page) => page.frontmatter.category,
formatter: "Category: $content",
},
{
getter: (page) => page.frontmatter.tag,
formatter: "Tag: $content",
},
],
}
}
})
function generateSidebar(summaryFileName) {
const summaryFile = path.resolve(__dirname, summaryFileName)
try {
return getSummaryData(summaryFile)
} catch (err) {
console.error(`Error generating sidebar from file ${summaryFileName}:`, err)
process.exit(1)
}
}
function getSummaryData(file) {
const lines = fs.readFileSync(file, 'utf8').split('\n')
const sidebarStructure = []
let currentParent = null
lines.forEach((line, i) => {
const level = line.search(/\S|$/) / 2
const match = line.match(/^\s*\*\s*\[([^\]]+)\]\(([^)]+)\)/)
if (match) {
const newEntry = { text: match[1], link: `/${match[2]}`, children: [] }
if (level === 0) {
sidebarStructure.push(newEntry)
currentParent = sidebarStructure[sidebarStructure.length - 1]
} else {
let parent = currentParent
for (let i = 1; i < level; i++) {
parent = parent.children[parent.children.length - 1]
}
parent.children.push(newEntry)
}
}
})
sidebarStructure.forEach(removeEmptyArrays)
return sidebarStructure
}
function removeEmptyArrays(item) {
if (item.children && item.children.length === 0) {
delete item.children;
} else if (item.children) {
item.children.forEach(removeEmptyArrays);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

65
.vuepress/public/logo.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1 @@
$theme-color: #17b53f;

View File

@ -4,10 +4,176 @@ 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).
#### [3.1.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.1.0...3.1.2)
#### [3.2.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.1.2...3.2.0)
- feat(webapp): implement config for `date-time` format [`#6985`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6985)
- build(other): bump eslint-plugin-n from 15.7.0 to 16.6.2 in /backend [`#6962`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6962)
- feat(other): frontend workflows & test suites [`#6987`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6987)
- feat(other): new frontend [`#6970`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6970)
- feat(webapp): redesign post teaser date [`#6978`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6978)
- Bump cypress from 13.6.3 to 13.6.4 [`#6984`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6984)
- build(other): bump multiple-cucumber-html-reporter from 3.6.0 to 3.6.1 [`#6983`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6983)
- fix(webapp): fix wrong content menu position on group profile page [`#6956`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6956)
- fix(other): revert "remove temporarily some *.ocelot.social link from the readmes…" [`#6972`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6972)
- fix(other): update and fix vuepress [`#6974`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6974)
- docs(other): add description for a 1-click install and usage of kubernetes dashboard [`#6957`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6957)
- fix(webapp): fix footer links [`#6971`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6971)
- feat(frontend): per page title [`#69`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/69)
- Bump dorny/paths-filter from 2.11.1 to 3.0.0 [`#62`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/62)
- chore(frontend): update packages 28.01 [`#68`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/68)
- Bump @babel/preset-env from 7.23.6 to 7.23.9 [`#6968`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6968)
- Bump @faker-js/faker from 8.3.1 to 8.4.0 [`#6969`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6969)
- Bump cypress from 13.6.2 to 13.6.3 [`#6967`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6967)
- Bump pkgdeps/git-tag-action from 2 to 3 [`#6965`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6965)
- Bump dorny/paths-filter from 2.11.1 to 3.0.0 [`#6964`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6964)
- feat(webapp): add chat item to avatar navigation menu and change title of notification by removing `All …` [`#6953`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6953)
- refactor(other): fix build command in docs deploy workflow [`#6955`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6955)
- chore(other): revert pr - improve structure and readability of auto-generated changelog [`#6954`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6954)
- feat(other): add documentation deployment [`#6863`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6863)
- refactor(other): fix broken links in documentation [`#6825`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6825)
- docs(other): add new neo4j env for default database name to readmes [`#6940`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6940)
- Bump vue-advanced-chat from 2.0.7 to 2.0.10 in /webapp [`#6947`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6947)
- chore(frontend): update packages 20 01 2024 [`#61`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/61)
- Bump @babel/plugin-proposal-throw-expressions from 7.22.5 to 7.23.3 in /backend [`#6944`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6944)
- Bump eslint-plugin-import from 2.29.0 to 2.29.1 in /backend [`#6946`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6946)
- Bump @babel/preset-env from 7.22.20 to 7.23.8 in /backend [`#6945`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6945)
- Bump @cucumber/cucumber from 10.1.0 to 10.3.1 [`#6943`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6943)
- Bump @badeball/cypress-cucumber-preprocessor from 20.0.0 to 20.0.1 [`#6942`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6942)
- Bump actions/cache from 3.3.3 to 4.0.0 [`#6941`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6941)
- feat(webapp): improve registration slide nonce text [`#6850`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6850)
- build(other): bump @babel/core from 7.23.6 to 7.23.7 [`#6920`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6920)
- Bump linkify-it from 3.0.2 to 5.0.0 in /webapp [`#6932`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6932)
- Bump ts-node from 10.9.1 to 10.9.2 in /backend [`#6926`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6926)
- Bump @typescript-eslint/eslint-plugin from 5.60.0 to 5.62.0 in /backend [`#6929`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6929)
- Bump eslint-config-prettier from 9.0.0 to 9.1.0 in /backend [`#6927`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6927)
- Bump vuepress-theme-hope from 2.0.0-rc.6 to 2.0.0-rc.11 [`#6936`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6936)
- Bump actions/cache from 3.3.2 to 3.3.3 [`#6937`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6937)
- docs(frontend): fix readme [`#55`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/55)
- feat(frontend): stories [`#54`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/54)
- chore(frontend): update packages 13 01 2024 [`#53`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/53)
- chore(other): add deployment script 'clusters.cron-backups.sh' [`#6813`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6813)
- feat(frontend): snapshot tests [`#47`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/47)
- refactor(other): ignore changelog file in markdown link checker [`#6933`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6933)
- feat(frontend): test vike button [`#46`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/46)
- feat(frontend): build server [`#45`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/45)
- feat(frontend): utilize vike-navigate [`#44`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/44)
- chore(frontend): update packages [`#43`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/43)
- feat(other): change group description length min [`#6924`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6924)
- Bump multiple-cucumber-html-reporter from 3.5.0 to 3.6.0 [`#6922`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6922)
- Bump cypress from 13.6.1 to 13.6.2 [`#6919`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6919)
- fix(frontend): deleted unused debug handlers [`#35`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/35)
- Bump actions/checkout from 3 to 4 [`#33`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/33)
- chore(workflow): dependabot support [`#32`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/32)
- chore(frontend): apply vike fix [`#31`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/31)
- chore(frontend): package updates [`#30`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/30)
- fix(frontend): optimization [`#29`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/29)
- Bump jest-environment-jsdom from 29.4.2 to 29.7.0 in /webapp [`#6907`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6907)
- Bump vuepress-plugin-search-pro from 2.0.0-rc.4 to 2.0.0-rc.6 [`#6914`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6914)
- Bump vuepress-theme-hope from 2.0.0-rc.4 to 2.0.0-rc.6 [`#6913`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6913)
- Bump @badeball/cypress-cucumber-preprocessor from 19.2.0 to 20.0.0 [`#6911`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6911)
- Bump @cucumber/cucumber from 10.0.1 to 10.1.0 [`#6912`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6912)
- Bump @mapbox/mapbox-gl-geocoder from 5.0.1 to 5.0.2 in /webapp [`#6900`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6900)
- Bump @vue/vue2-jest from 29.2.4 to 29.2.6 in /webapp [`#6899`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6899)
- Bump @babel/preset-env from 7.23.5 to 7.23.6 [`#6895`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6895)
- Bump @babel/core from 7.23.5 to 7.23.6 [`#6896`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6896)
- Bump actions/download-artifact from 3 to 4 [`#6897`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6897)
- Bump actions/upload-artifact from 3 to 4 [`#6898`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6898)
- refactor(frontend): import order + sbcomp + some types [`#28`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/28)
- feat(frontend): typechecks & type cleanups [`#27`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/27)
- 6812 script auto backups for kubernetes servers database name as variable [`#6893`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6893)
- fix(frontend): eslint relativ eparsing [`#26`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/26)
- fix(other): eslint typescript strict [`#25`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/25)
- build(other): bump eslint-plugin-vue from 6.2.2 to 9.19.2 in /webapp [`#6891`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6891)
- ci(other): improve structure and readability of auto-generated changelog [`#6654`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6654)
- fix(frontend): tests from dreammall [`#24`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/24)
- Bump vuepress-theme-hope from 2.0.0-rc.1 to 2.0.0-rc.4 [`#6889`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6889)
- Bump vuepress-plugin-search-pro from 2.0.0-rc.0 to 2.0.0-rc.4 [`#6888`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6888)
- Bump @babel/preset-env from 7.23.3 to 7.23.5 [`#6883`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6883)
- Bump @babel/core from 7.23.3 to 7.23.5 [`#6884`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6884)
- Bump cypress from 13.6.0 to 13.6.1 [`#6881`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6881)
- feat(frontend): test store [`#23`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/23)
- Bump migrate from 2.0.0 to 2.0.1 in /backend [`#6876`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6876)
- Bump vuepress-theme-hope from 2.0.0-rc.0 to 2.0.0-rc.1 [`#6871`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6871)
- Bump @badeball/cypress-cucumber-preprocessor from 19.1.0 to 19.2.0 [`#6873`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6873)
- fix(docu): include LICENSE file in docu build [`#22`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/22)
- fix(docu): fix type error vuepress base [`#21`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/21)
- fix(workflow): docs base configurable [`#20`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/20)
- chore(other): upgrade cert-manager version [`#6848`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6848)
- feat(other): include working vuepress for documentation automation [`#6836`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6836)
- docs(other): remove temp `*.ocelot.social` links [`#6867`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6867)
- Bump eslint-plugin-import from 2.27.5 to 2.29.0 in /backend [`#6860`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6860)
- refactor(other): remove unused packages and scripts [`#6857`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6857)
- Bump cypress from 13.5.1 to 13.6.0 [`#6859`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6859)
- build(other): fix cucumber dependency deprecation [`#6856`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6856)
- fix(backend): expired jwt in unit test [`#6864`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6864)
- fix(docu): added docu for commit after subtree pull [`#19`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/19)
- fix(docu): document how to update the subtree [`#18`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/18)
- feat(other): document how to use as git subtree [`#17`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/17)
- fix(frontend): cleanup [`#16`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/16)
- feat(frontend): switch TopBar from DefaultLayout to PageShell [`#15`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/15)
- feat(frontend): package updates [`#14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/14)
- feat(frontend): boilerplate function & layout [`#13`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/13)
- docs(frontend): chromatic readme [`#11`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/11)
- feat(frontend): chromatic + workflow [`#10`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/10)
- refactor(frontend): clean structure & introduce aliases [`#9`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/9)
- fix(workflow): lint & docu fixes [`#8`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/8)
- feat(frontend): lint locales [`#7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/7)
- feat(frontend): stylelint & workflow build storybook [`#6`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6)
- feat(workflow): deploy docs to github - workflow [`#5`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/5)
- feat(workflow): build test workflow [`#4`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/4)
- feat(workflow): test:unit workflow [`#3`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/3)
- feat(workflow): test:lint code - workflow [`#2`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/2)
- Bump cropperjs from 1.5.6 to 1.6.1 in /webapp [`#6772`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6772)
- Bump @faker-js/faker from 8.2.0 to 8.3.1 [`#6841`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6841)
- build(other): bump sanitize-html from 1.22.1 to 2.11.0 in /backend [`#6819`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6819)
- build(other): bump cypress from 13.5.0 to 13.5.1 [`#6840`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6840)
- build(other): bump @badeball/cypress-cucumber-preprocessor from 19.1.0 to 19.1.1 [`#6842`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6842)
- Bump wait-on from 7.1.0 to 7.2.0 [`#6839`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6839)
- build(other): bump wait-on from 7.0.1 to 7.1.0 [`#6817`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6817)
- build(other): bump dotenv from 8.2.0 to 16.3.1 in /backend [`#6827`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6827)
- build(other): bump @babel/preset-env from 7.23.2 to 7.23.3 [`#6831`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6831)
- build(other): bump @babel/core from 7.23.2 to 7.23.3 [`#6830`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6830)
- build(other): bump cypress from 13.4.0 to 13.5.0 [`#6829`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6829)
- Bump @badeball/cypress-cucumber-preprocessor from 19.0.0 to 19.1.0 [`#6832`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6832)
- feat(other): add documentation check to CI [`#6824`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6824)
- build(other): bump cypress from 13.3.1 to 13.4.0 [`#6820`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6820)
- build(other): bump @badeball/cypress-cucumber-preprocessor from 18.0.6 to 19.0.0 [`#6818`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6818)
- feat(backend): coverage backend to 90% [`#6814`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6814)
- build(other): bump validator from 13.9.0 to 13.11.0 in /backend [`#6771`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6771)
- build(other): bump eslint-import-resolver-typescript from 3.5.5 to 3.6.1 in /backend [`#6769`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6769)
- fix(webapp): event date format [`#6784`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6784)
- build(other): bump @babel/preset-env from 7.22.20 to 7.23.2 [`#6788`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6788)
- build(other): bump @babel/core from 7.23.0 to 7.23.2 [`#6790`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6790)
- build(other): bump @faker-js/faker from 8.1.0 to 8.2.0 [`#6799`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6799)
- docs(other): fix divers links in readmes [`#6802`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6802)
- chore(other): add script to set neo4j in offline-mode and back in online-mode [`#6182`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6182)
- fix(other): fix and refine docs and add kubernetes cluster installation script [`#6796`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6796)
- refactor(webapp): replace deprecated jest methods in webapp unit tests [`#6808`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6808)
- fix(webapp): make filter menu visible if categories are inactive [`#6807`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6807)
- fix(other): increase cypress timeouts [`#6809`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6809)
- docs(other): refine deployments `docker-compose.yml` in deployment and main folder [`#6786`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6786)
- fix(other): fix link in `deployment/TODO-next-update.md` to `deployment/deployment-values.md` [`#6729`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6729)
- Bump cypress from 13.2.0 to 13.3.1 [`#6789`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6789)
- fix(other): remove buggy space in filename 'neo4j-data-snapshot.yaml ' to 'neo4j-data-snapshot.yaml' [`#6777`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6777)
- storybook tests [`ff7a1c5`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/ff7a1c548405c3a60341844679e70d93aebb2e3c)
- update vuepress [`cbf7bdc`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/cbf7bdc84ccf02c9658748b945dac7ebc405e5b2)
- update storybook [`a0b77d7`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/a0b77d78a3e7a483d204337e3d42dd9dd56ad69a)
#### [3.1.2](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.1.1...3.1.2)
> 3 October 2023
- chore(release): release v3.1.2 - fix kubernetes deployment by degrade Node version from v20.7.0 to v20.2.0 [`#6782`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6782)
- fix(other): kubernetes error by degrading node version from v20.7.0 to v20.2.0 [`#6779`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6779)
- fix(backend): cypher statement in user locales unit test [`#6780`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6780)
- Release v3.1.2 - Fix Kubernetes Deployment by degrade Node version from v20.7.0 to v20.2.0 [`aa2d27e`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/aa2d27e8caefeac578fb30fc5b426dbd51e84b34)
- Fix Dockerfile labels [`5d2c41d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/5d2c41d12ec9c892a38d8f8e2325194618fc35e4)
- Degrade Node version from v20.7.0 to v20.2.0 [`988e874`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/988e874934dcf0caa060600e843138664fb367c5)
#### [3.1.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/3.1.0...3.1.1)
> 27 September 2023
- chore(release): release v3.1.1 move dkim to secrets and fix search etc. [`#6763`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6763)
- chore(other): move kubrnetes dkim from confmap to secret yaml [`#6761`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6761)
- build(other): bump @babel/preset-env from 7.22.9 to 7.22.20 in /backend [`#6741`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6741)

View File

@ -4,7 +4,7 @@ Thank you so much for thinking of contributing to the [ocelot.social](https://oc
## Getting Set Up
Instructions for how to install all the necessary software and some code guidelines can be found in our main [Readme](/README.md) or in our [documentation](/SUMMARY.md).
Instructions for how to install all the necessary software and some code guidelines can be found in our main [Readme](./README.md) or in our [documentation](./SUMMARY.md).
To get you started we recommend that you join forces with a regular contributor. Please join [our Discord instance](https://discord.gg/AJSX9DCSUA) to chat with developers or just get in touch directly on an issue on either [Github](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues) or [Zenhub](https://app.zenhub.com/workspaces/ocelotsocial-5fb21ff922cb410015dd6535/board?filterLogic=any&repos=301151089):
@ -36,7 +36,7 @@ Every pull request needs to:
## Contribution Flow For Open Source Contributors
See [contributing in main README.md](/README.md#contributing)
See [contributing in main README.md](./README.md#contributing)
## The Team
@ -48,6 +48,9 @@ You can talk to our core team on [Discord](https://discord.gg/AJSX9DCSUA). And o
* Moriz (@Mogge)
* Wolle (@Tirokk)
* Alex (@ogerly)
* Hannes (@elweyn5803)
* Mathias (@mahula)
* Markus (@maeckes#1133)
<!-- * Robert (@roschaefer)
* Matt (@mattwr18)
@ -168,11 +171,11 @@ Please copy and paste the following quotes for the languages:
## Docker More Closely
### Apple M1 Platform
### Apple Silicon Platform
***Attention:** For using Docker commands in Apple M1 environments!*
***ATTENTION:** For using Docker commands in Apple Silicon environments!*
#### Environment Variable For Apple M1 Platform
#### Environment Variable For Apple Silicon Platform (M1, M2 Chips)
If you encounter trouble building the docker containers on an Apple M1 chip you can try to explicitly define the target platform docker builds and pulls images for:

181
README.md
View File

@ -1,16 +1,19 @@
# Ocelot.Social
[![Build Status Test](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions/workflows/test.yml/badge.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions)
[![Backend Test CI](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions/workflows/test-backend.yml/badge.svg?branch=master)](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions/workflows/test-backend.yml)
[![Webapp Test CI](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions/workflows/test-webapp.yml/badge.svg?branch=master)](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions/workflows/test-webapp.yml)
[![E2E Test CI](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions/workflows/test-e2e.yml/badge.svg?branch=master)](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions/workflows/test-e2e.yml)
[![Build Status Publish](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions/workflows/publish.yml/badge.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social/actions)
[![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/LICENSE.md)
[![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/LICENSE.md)
[![Discord Channel](https://img.shields.io/discord/489522408076738561.svg)](https://discord.gg/AJSX9DCSUA)
[![Open Source Helpers](https://www.codetriage.com/ocelot-social-community/ocelot-social/badges/users.svg)](https://www.codetriage.com/ocelot-social-community/ocelot-social)
[ocelot.social](https://ocelot.social) is free and open source software program code to run social networks. Its development is supported by a community of programmers and interested network operators.
[Ocelot.social](https://ocelot.social) is free and open source software program code to run social networks. Its development is supported by a community of programmers and interested network operators.
<!-- markdownlint-disable MD033 -->
<p align="center">
<a href="https://ocelot.social" target="_blank"><img src="webapp/static/img/custom/logo-squared.svg" alt="ocelot.social" width="40%" height="40%"></a>
<!-- <p align="center"> -->
<p style="text-align: center;">
<a href="https://ocelot.social" target="_blank"><img src="https://raw.githubusercontent.com/Ocelot-Social-Community/Ocelot-Social/master/webapp/static/img/custom/logo-squared.svg" alt="ocelot.social" width="40%" height="40%"></a>
</p>
<!-- markdownlint-enable MD033 -->
@ -18,36 +21,45 @@ Our goal is to enable people to participate fairly and equally in online social
We therefore consider it desirable that operators offer such networks so that people can choose where they want to be on the move.
At the same time, it should be possible in the future to link these networks with each other (ActivityPub, Fediverse), so that users can also connect with people from other networks - for example by making friends or following posts or other contributions.
Our vision for the future is that at some point it should be possible to link these networks together (ActivityPub, Fediverse) so that users can also connect with people from other networks - for example, by friending them or following posts or other contributions.
If you would like to help set up this capability with us, please contact us.
In other words, we are interested in a network of networks and in keeping the data as close as possible to the user and the operator they trusts.
## Screenshots
<!-- markdownlint-disable MD033 -->
<img src="https://user-images.githubusercontent.com/17728384/218597429-554e4082-3906-4721-8f68-0c13146fc218.png" alt="Post feed" title="Post feed" />
<!-- markdownlint-enable MD033 -->
Check out more screenshots [here](/wiki/en:Screenshots).
Check out more screenshots [here](https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki/en:Screenshots).
## Features
Ocelot.social networks feature:
* <strong>user accounts</strong>
* <strong>user roles</strong>
* <strong>posts</strong> and <strong>comments</strong>
* <strong>groups</strong>
* <strong>maps</strong>
* <strong>search</strong>
* <strong>filters</strong>
* and more …
Ocelot.social networks features:
Check out the [full feature list](/wiki/en:FAQ#what-are-the-features).
- **news feed**
- **posts**
- as **articles** and **events**
- **comments**
- **filter**
- **search**
- **groups**
- **map**
- **user accounts**
- **user roles**
- make your own **branded network**
- and more …
Check out the [full feature list](https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki/en:FAQ#what-are-the-features).
## User Guide and Frequently Asked Questions
In the [wiki](/wiki) you can find more information.
In the [wiki](https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki) you can find more information.
* [User Guide](/wiki/en:User-Guide)
* [Frequently Asked Questions](/wiki/en:FAQ)
- [User Guide](https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki/en:User-Guide)
- [Frequently Asked Questions](https://github.com/Ocelot-Social-Community/Ocelot-Social/wiki/en:FAQ)
## Demo
@ -57,27 +69,28 @@ Try out our live demo network, see [here](#live-demo-and-developer-logins).
If you're wondering how you could help, there are plenty of ways, e.g.:
* Spread the good word about ocelot.social to make it more popular:
* Add the link [ocelot.social](https://ocelot.social) to your website.
* Give ocelot.social a Like at https://alternativeto.net/software/ocelot-social/.
* Star our project on GitHub at https://github.com/Ocelot-Social-Community/Ocelot-Social/.
* Promote it on your social networks.
* Tell your friends about it by word-of-mouth.
* Write a press article on ocelot.social or contact the editorial office of your local newspage or radio station.
* Take a [good first issue](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) or issues that need help. Make sure to read [CONTRIBUTING.md](/CONTRIBUTING.md) first though.
* Testing and [reporting](/issues/new/choose) bugs.
* Translating: Please [contact us](#contact).
* Reviewing and testing pull requests.
- Spread the good word about ocelot.social to make it more popular:
- Add the link [ocelot.social](https://ocelot.social) to your website.
- Give ocelot.social a Like at <https://alternativeto.net/software/ocelot-social/>.
- Star our project on GitHub at <https://github.com/Ocelot-Social-Community/Ocelot-Social/>.
- Promote it on your social networks.
- Tell your friends about it by word-of-mouth.
- Write a press article on ocelot.social or contact the editorial office of your local news page or radio station.
- Take a [good first issue](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) or issues that need help. Make sure to read [CONTRIBUTING.md](./CONTRIBUTING.md) first though.
- Testing and [reporting](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/new/choose) bugs.
- Translating: Please [contact us](#contact).
- Reviewing and testing pull requests.
## Donate
Your donation is very welcome and helps to enhance and improve the network. This software is mostly developped and maintained by the association [busFaktor() e.V.](https://www.busfaktor.org/en). Please support us with a [donation](https://www.busfaktor.org/en/donations) to busFaktor() e.V.. Thanks a lot! ❤️
Your donation is very welcome and helps to enhance and improve the network. This software is mostly developed and maintained by the association [busFaktor() e.V.](https://www.busfaktor.org/en) . Please support us with a [donation](https://www.busfaktor.org/en/donations) to busFaktor() e.V. . Thanks a lot! ❤️
## Contact
Are you interested in operating your own ocelot.social network or becoming a user? Please contact us here:
* [hello@ocelot.social](mailto:hello@ocelot.social)
* [Discord](https://discord.com/invite/DFSjPaX)
- [hello@ocelot.social](mailto:hello@ocelot.social)
- our developer chat on [Discord](https://discord.gg/AJSX9DCSUA)
## For Developers and Contributors
@ -90,17 +103,17 @@ Have a look into our short video:
There are three important directories:
* [Backend](./backend) runs on the server and is a middleware between database and frontend
* [Frontend](./webapp) is a server-side-rendered and client-side-rendered web frontend
* [Cypress](./cypress) contains end-to-end tests and executable feature specifications
- [Backend](./backend) runs on the server and is a middleware between database and frontend
- [Frontend](./webapp) is a server-side-rendered and client-side-rendered web frontend
- [Cypress](./cypress) contains end-to-end tests and executable feature specifications
In order to setup the application and start to develop features you have to
setup **frontend** and **backend**.
setup **webapp** and **backend**.
There are two approaches:
1. [Local](#local-installation) installation, which means you have to take care of dependencies yourself.
2. **Or** Install everything through [Docker](#docker-installation) which takes care of dependencies for you.
2. **Or** install everything through [Docker](#docker-installation) which takes care of dependencies for you.
### Installation
@ -126,13 +139,13 @@ Change into the new folder.
$ cd Ocelot-Social
```
### Live Demo And Developer Logins
### Live Demo and Developer Logins
**Try out our deployed [development environment](https://stage.ocelot.social).**
Visit our staging networks:
* central staging network: [stage.ocelot.social](https://stage.ocelot.social)
- central staging network: [stage.ocelot.social](https://stage.ocelot.social)
<!-- - rebranded staging network: [rebrand.ocelot.social](https://stage.ocelot.social). -->
#### Login
@ -151,22 +164,19 @@ Docker is a software development container tool that combines software and its d
##### General Installation of Docker
There are [several ways to install Docker CE](https://docs.docker.com/install/) on your computer or server.
* [install Docker Desktop on macOS](https://docs.docker.com/docker-for-mac/install/)
* [install Docker Desktop on Windows](https://docs.docker.com/docker-for-windows/install/)
* [install Docker CE on Linux](https://docs.docker.com/install/)
There are [several ways to install Docker](https://docs.docker.com/get-docker/) on your computer or server.
Check the correct Docker installation by checking the version before proceeding. E.g. we have the following versions:
```bash
# use Docker version 24.0.6 or newer
# includes Docker Compose
$ docker --version
Docker version 18.09.2
$ docker-compose --version
docker-compose version 1.23.2
```
##### Start Ocelot-Social via Docker-Compose
##### Start Ocelot-Social via Docker Compose
***ATTENTION:** For using Docker commands in Apple Silicon environments see [here](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/CONTRIBUTING.md#apple-silicon-platform).*
Prepare ENVs once beforehand:
@ -182,14 +192,14 @@ For Development:
```bash
# in main folder
$ docker-compose up
$ docker compose up
```
For Production:
```bash
# in main folder
$ docker-compose -f docker-compose.yml up
$ docker compose -f docker-compose.yml up
```
This will start all required Docker containers.
@ -198,7 +208,7 @@ Make sure your database is running on `http://localhost:7474/browser/`.
Prepare database once before you start by running the following command in a second terminal:
```bash
# in main folder while docker-compose is up
# in main folder while docker compose is up
$ docker compose exec backend yarn run db:migrate init
$ docker compose exec backend yarn run db:migrate up
```
@ -206,17 +216,17 @@ $ docker compose exec backend yarn run db:migrate up
Then clear and seed database by running the following command as well in the second terminal:
```bash
# in main folder while docker-compose is up
$ docker-compose exec backend yarn run db:reset
$ docker-compose exec backend yarn run db:seed
# in main folder while docker compose is up
$ docker compose exec backend yarn run db:reset
$ docker compose exec backend yarn run db:seed
```
For a closer description see [backend README.md](./backend/README.md).
For a full documentation see [SUMMARY](./SUMMARY.md).
For a closer description see [backend](./backend/README.md).
For a full documentation of the Docker installation see [summary](./SUMMARY.md).
#### Local Installation
For a full documentation see [SUMMARY](./SUMMARY.md).
For a full documentation of the local installation see [summary](./SUMMARY.md).
### Contributing
@ -225,7 +235,9 @@ To have the necessary permission to push directly to this repository, please acc
We are happy if you fork our repository, but we don't recommend it for development. You do not need a fork.
Clone this repository locally as [described above](#clone-the-repository), create your branch named `<issue-number>-<description>`, add your code and push your branch to this repository. Then create a PR by comparing it to our `master`.
Clone this repository locally as [described above](#clone-the-repository), create your branch named `<issue-number>-<description>`, add your code and push your branch direct to this repository. Then create a PR by comparing it to our `master`.
***!!! Be aware:*** Please don't compare from a fork, because the tests are breaking caused by credential problems.
Please run the following commands before you push:
@ -242,37 +254,52 @@ $ yarn locales --fix
$ yarn test
```
Check out our [contribution guideline](./CONTRIBUTING.md), too!
Check out our [contribution guideline](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/CONTRIBUTING.md), too!
#### Developer Chat
Join our friendly open-source community on [Discord](https://discord.gg/AJSX9DCSUA) :heart_eyes_cat:
Just introduce yourself at `#introduce-yourself` and mention a mentor or `@@Mentors` to get you onboard :neckbeard:
Join our friendly open-source community on [Discord](https://discord.gg/AJSX9DCSUA) 😻
Just introduce yourself at `#introduce-yourself` and mention a mentor or `@@Mentors` to get you onboard 🤓
We give write permissions to every developer who asks for it. Just text us on
[Discord](https://discord.gg/AJSX9DCSUA).
### Deployment
Deployment methods can be found in the [Ocelot-Social-Deploy-Rebranding](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding) repository.
Deployment methods can be found in our `deployment` folder described in the [README](./deployment/README.md).
Our branding template is our [stage.ocelot.social](https://github.com/Ocelot-Social-Community/stage.ocelot.social) repository.
Place your branding repository inside `deployment/configurations`.
The only deployment method in this repository for development purposes as described above is `docker-compose`.
The only deployment method in this repository for production purposes is [Kubernetes](https://kubernetes.io) for now.
But we just started to develop a deployment for [Docker Compose](https://docs.docker.com/compose/) as well.
The only deployment method with branding in this repository for development purposes as described above is [Docker Compose](https://docs.docker.com/compose/):
```bash
# in folder deployment/
# set your branding folder name in .env
# then run
$ docker compose up
```
The code is branded automatically.
To setup the Neo4j database see above.
### Technology Stack
* [VueJS](https://vuejs.org/)
* [NuxtJS](https://nuxtjs.org/)
* [GraphQL](https://graphql.org/)
* [NodeJS](https://nodejs.org/en/)
* [Neo4J](https://neo4j.com/)
- [VueJS](https://vuejs.org/)
- [NuxtJS](https://nuxtjs.org/)
- [GraphQL](https://graphql.org/)
- [NodeJS](https://nodejs.org/en/)
- [Neo4J](https://neo4j.com/)
#### For Testing
* [Cypress](https://docs.cypress.io/)
* [Storybook](https://storybook.js.org/)
* [Jest](https://jestjs.io/)
* [Vue Test Utils](https://vue-test-utils.vuejs.org/)
* [ESLint](https://eslint.org/)
- [Cypress](https://docs.cypress.io/)
- [Storybook](https://storybook.js.org/)
- [Jest](https://jestjs.io/)
- [Vue Test Utils](https://vue-test-utils.vuejs.org/)
- [ESLint](https://eslint.org/)
### Attributions
@ -280,7 +307,9 @@ Locale Icons made by [Freepik](http://www.freepik.com/) from [www.flaticon.com](
Browser compatibility testing with [BrowserStack](https://www.browserstack.com/).
<img alt="BrowserStack Logo" src=".gitbook/assets/browserstack-logo.svg" width="256">
<!-- markdownlint-disable MD033 -->
<img alt="BrowserStack Logo" src="https://raw.githubusercontent.com/Ocelot-Social-Community/Ocelot-Social/master/.gitbook/assets/browserstack-logo.svg" width="256">
<!-- markdownlint-enable MD033 -->
### License

View File

@ -1,24 +1,22 @@
# Table of contents
* [Introduction](README.md)
* [Edit this Documentation](edit-this-documentation.md)
* [Neo4J](neo4j/README.md)
* [Backend](backend/README.md)
* [GraphQL](backend/graphql.md)
* [neo4j-graphql-js](backend/neo4j-graphql-js.md)
* [Webapp](webapp/README.md)
* [Webapp (Frontend)](webapp/README.md)
* [Components](webapp/components.md)
* [HTML](webapp/html.md)
* [SCSS](webapp/scss.md)
* [Vue](webapp/vue.md)
* [Testing Guide](testing.md)
* [End-to-end tests](cypress/README.md)
* [Frontend tests](webapp/testing.md)
* [Backend tests](backend/testing.md)
* [Docker More Closely](DOCKER_MORE_CLOSELY.md)
* [End-to-end Tests](cypress/README.md)
* [Webapp (Frontend) Tests](webapp/testing.md)
* [Backend Tests](backend/testing.md)
* [Deployment](deployment/README.md)
* [Contributing](CONTRIBUTING.md)
* [Feature Specification](cypress/features.md)
* [Code of conduct](CODE_OF_CONDUCT.md)
* [Code of Conduct](CODE_OF_CONDUCT.md)
* [Documentation](documentation.md)
* [License](LICENSE.md)

View File

@ -83,8 +83,8 @@ More details about our GraphQL playground and how to use it with ocelot.social c
Database indexes and constraints need to be created and upgraded when the database and the backend are running:
{% tabs %}
{% tab title="Docker" %}
::: tabs
@tab:active Docker
```bash
# in main folder while docker-compose is running
@ -102,8 +102,7 @@ $ docker compose exec backend /bin/sh -c "yarn prod:migrate init"
$ docker exec backend yarn run db:migrate up
```
{% endtab %}
{% tab title="Without Docker" %}
@tab Without Docker
```bash
# in folder backend/ while database is running
@ -116,16 +115,15 @@ yarn run db:migrate init
yarn run db:migrate up
```
{% endtab %}
{% endtabs %}
:::
#### Seed Database
If you want your backend to return anything else than an empty response, you
need to seed your database:
{% tabs %}
{% tab title="Docker" %}
::: tabs
@tab:active Docker
In another terminal run:
@ -147,8 +145,7 @@ $ docker exec backend yarn run db:migrate init
$ docker exec backend yarn run db:migrate up
```
{% endtab %}
{% tab title="Without Docker" %}
@tab Without Docker
Run:
@ -164,16 +161,15 @@ To reset the database run:
$ yarn run db:reset
```
{% endtab %}
{% endtabs %}
:::
### Data migrations
Although Neo4J is schema-less,you might find yourself in a situation in which
you have to migrate your data e.g. because your data modeling has changed.
{% tabs %}
{% tab title="Docker" %}
::: tabs
@tab:active Docker
Generate a data migration file:
@ -190,8 +186,7 @@ To run the migration:
$ docker exec backend yarn run db:migrate up
```
{% endtab %}
{% tab title="Without Docker" %}
@tab Without Docker
Generate a data migration file:
@ -208,16 +203,15 @@ To run the migration:
$ yarn run db:migrate up
```
{% endtab %}
{% endtabs %}
:::
## Testing
**Beware**: We have no multiple database setup at the moment. We clean the
database after each test, running the tests will wipe out all your data!
{% tabs %}
{% tab title="Docker" %}
::: tabs
@tab:active Docker
Run the unit tests:
@ -226,9 +220,7 @@ Run the unit tests:
$ docker exec backend yarn run test
```
{% endtab %}
{% tab title="Without Docker" %}
@tab Without Docker
Run the unit tests:
@ -237,5 +229,4 @@ Run the unit tests:
$ yarn run test
```
{% endtab %}
{% endtabs %}
:::

View File

@ -2,12 +2,13 @@
GraphQL is a data query language which provides an alternative to REST and ad-hoc web service architectures. It allows clients to define the structure of the data required, and exactly the same structure of the data is returned from the server.
![GraphQL Playground](../../../.gitbook/assets/graphql-playground%20%281%29.png)
We have a closer description for the [GraphQL Playground](./src/graphql/GraphQL-Playground.md).
![GraphQL Playground](../.gitbook/assets/graphql-playground%20%281%29.png)
## Middleware keeps resolvers clean
![](../.gitbook/assets/grafik-4.png)
![Middleware schema](../.gitbook/assets/grafik-4.png)
A well-organized codebase is key for the ability to maintain and easily introduce changes into an app. Figuring out the right structure for your code remains a continuous challenge - especially as an application grows and more developers are joining a project.

View File

@ -7,11 +7,12 @@ module.exports = {
'!**/node_modules/**',
'!**/test/**',
'!**/build/**',
'!**/src/**/?(*.)+(spec|test).ts?(x)'
'!**/src/**/?(*.)+(spec|test).ts?(x)',
'!**/src/db/**'
],
coverageThreshold: {
global: {
lines: 67,
lines: 90,
},
},
testMatch: ['**/src/**/?(*.)+(spec|test).ts?(x)'],

View File

@ -1,6 +1,6 @@
{
"name": "ocelot-social-backend",
"version": "3.1.2",
"version": "3.2.0",
"description": "GraphQL Backend for ocelot.social",
"repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social",
"author": "ocelot.social Community",
@ -24,10 +24,10 @@
},
"dependencies": {
"@babel/cli": "~7.8.4",
"@babel/core": "~7.9.0",
"@babel/core": "^7.23.7",
"@babel/node": "~7.8.7",
"@babel/plugin-proposal-throw-expressions": "^7.22.5",
"@babel/preset-env": "~7.22.20",
"@babel/plugin-proposal-throw-expressions": "^7.23.3",
"@babel/preset-env": "~7.23.8",
"@babel/register": "^7.9.0",
"@sentry/node": "^5.15.4",
"apollo-cache-inmemory": "~1.6.5",
@ -39,13 +39,13 @@
"aws-sdk": "^2.1425.0",
"babel-core": "~7.0.0-0",
"babel-eslint": "~10.1.0",
"babel-jest": "~25.2.6",
"babel-jest": "~29.7.0",
"babel-plugin-transform-runtime": "^6.23.0",
"bcryptjs": "~2.4.3",
"cheerio": "~1.0.0-rc.3",
"cors": "~2.8.5",
"cross-env": "~7.0.3",
"dotenv": "~8.2.0",
"dotenv": "~16.3.1",
"express": "^4.17.1",
"graphql": "^14.6.0",
"graphql-middleware": "~4.0.2",
@ -74,41 +74,39 @@
"metascraper-url": "^5.34.2",
"metascraper-video": "^5.33.5",
"metascraper-youtube": "^5.33.5",
"migrate": "^2.0.0",
"migrate": "^2.0.1",
"mime-types": "^2.1.26",
"minimatch": "^3.0.4",
"mustache": "^4.2.0",
"neo4j-driver": "^4.0.2",
"neo4j-graphql-js": "^2.11.5",
"neode": "^0.4.9",
"node-fetch": "~2.6.1",
"node-fetch": "^2.7.0",
"nodemailer": "^6.4.4",
"nodemailer-html-to-text": "^3.2.0",
"request": "~2.88.2",
"sanitize-html": "~1.22.0",
"sanitize-html": "~2.11.0",
"slug": "~6.0.0",
"subscriptions-transport-ws": "^0.9.19",
"trunc-html": "~1.1.2",
"uuid": "~8.3.2",
"validator": "^13.9.0",
"validator": "^13.11.0",
"xregexp": "^4.3.0"
},
"devDependencies": {
"@faker-js/faker": "7.6.0",
"@types/jest": "^27.0.2",
"@types/node": "^20.2.5",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.57.1",
"apollo-server-testing": "~2.11.0",
"chai": "~4.3.8",
"cucumber": "~6.0.5",
"eslint": "^8.37.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.0.0",
"eslint-import-resolver-typescript": "^3.5.4",
"eslint-plugin-import": "^2.27.5",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-n": "^15.7.0",
"eslint-plugin-n": "^16.6.2",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-security": "^1.7.1",
@ -117,7 +115,7 @@
"prettier": "^2.8.7",
"rosie": "^2.0.1",
"ts-jest": "^27.0.5",
"ts-node": "^10.9.1",
"ts-node": "^10.9.2",
"typescript": "^4.9.4"
},
"resolutions": {

View File

@ -1,3 +1,3 @@
// this file is duplicated in `backend/src/constants/group` and `webapp/constants/group.js`
export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 50 // with removed HTML tags
export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 3 // with removed HTML tags
export const DESCRIPTION_EXCERPT_HTML_LENGTH = 250 // with removed HTML tags

View File

@ -0,0 +1,68 @@
import { getDriver } from '../../db/neo4j'
export const description = `
Transform event start and end date of format 'YYYY-MM-DD HH:MM:SS' in CEST
to ISOString in UTC.
`
export async function up(next) {
const driver = getDriver()
const session = driver.session()
const transaction = session.beginTransaction()
try {
const events = await transaction.run(`
MATCH (event:Event)
WHERE NOT event.eventStart CONTAINS 'T'
RETURN event.id, event.eventStart, event.eventEnd
`)
for (const event of events.records) {
let [id, eventStart, eventEnd] = event
let date = new Date(eventStart)
date.setHours(date.getHours() - 1)
eventStart = date.toISOString()
if (eventEnd) {
date = new Date(eventEnd)
date.setHours(date.getHours() - 1)
eventEnd = date.toISOString()
}
await transaction.run(`
MATCH (e:Event { id: '${id}' })
SET e.eventStart = '${eventStart}'
SET (CASE WHEN exists(e.eventEnd) THEN e END).eventEnd = '${eventEnd}'
RETURN e
`)
}
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 {
// No sense in running this down
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()
}
}

View File

@ -1,5 +1,7 @@
# GraphQL Playground
![GraphQL Playground](../../../.gitbook/assets/graphql-playground%20%281%29.png)
***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:

View File

@ -1,35 +1,11 @@
import Factory, { cleanDatabase } from '../db/factories'
import { getDriver, getNeode } from '../db/neo4j'
import decode from './decode'
import encode from './encode'
const driver = getDriver()
const neode = getNeode()
// here is the decoded JWT token:
// {
// role: 'user',
// locationName: null,
// name: 'Jenny Rostock',
// about: null,
// avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/sasha_shestakov/128.jpg',
// id: 'u3',
// email: 'user@example.org',
// slug: 'jenny-rostock',
// iat: 1550846680,
// exp: 1637246680,
// aud: 'http://localhost:3000',
// iss: 'http://localhost:4000',
// sub: 'u3'
// }
// !!! if the token expires go into the GraphQL Playground in the browser at 'http://localhost:4000' with a running backend and a seeded Neo4j database
// now do the login mutation:
// mutation {
// login(email:"user@example.org", password:"1234")
// }
// replace this token here with the one you received as the result
export const validAuthorizationHeader =
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InUzIiwibmFtZSI6Ikplbm55IFJvc3RvY2siLCJzbHVnIjoiamVubnktcm9zdG9jayIsImlhdCI6MTYzNzY0NDMwMCwiZXhwIjoxNzAwNzU5NTAwLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQwMDAiLCJzdWIiOiJ1MyJ9.ispIfRfgkXuYoIhKx7x2jPxgvHDJVv1ogMycLmfUnsk'
beforeAll(async () => {
await cleanDatabase()
})
@ -75,14 +51,8 @@ describe('decode', () => {
})
describe('given valid JWT Bearer token', () => {
beforeEach(() => {
authorizationHeader = validAuthorizationHeader
})
it('returns null', returnsNull)
describe('and corresponding user in the database', () => {
let user
let user, validAuthorizationHeader
beforeEach(async () => {
user = await Factory.build(
'user',
@ -99,10 +69,11 @@ describe('decode', () => {
email: 'user@example.org',
},
)
validAuthorizationHeader = encode(await user.toJson())
})
it('returns user object without email', async () => {
await expect(decode(driver, authorizationHeader)).resolves.toMatchObject({
await expect(decode(driver, validAuthorizationHeader)).resolves.toMatchObject({
role: 'user',
name: 'Jenny Rostock',
id: 'u3',
@ -113,7 +84,7 @@ describe('decode', () => {
it('sets `lastActiveAt`', async () => {
let user = await neode.first('User', { id: 'u3' })
await expect(user.toJson()).resolves.not.toHaveProperty('lastActiveAt')
await decode(driver, authorizationHeader)
await decode(driver, validAuthorizationHeader)
user = await neode.first('User', { id: 'u3' })
await expect(user.toJson()).resolves.toMatchObject({
lastActiveAt: expect.any(String),
@ -129,7 +100,7 @@ describe('decode', () => {
await expect(user.toJson()).resolves.toMatchObject({
lastActiveAt: '2019-10-03T23:33:08.598Z',
})
await decode(driver, authorizationHeader)
await decode(driver, validAuthorizationHeader)
user = await neode.first('User', { id: 'u3' })
await expect(user.toJson()).resolves.toMatchObject({
// should be a different time by now ;)
@ -152,6 +123,15 @@ describe('decode', () => {
it('returns null', returnsNull)
})
describe('and NO corresponding user in the database', () => {
beforeEach(async () => {
await cleanDatabase()
authorizationHeader = validAuthorizationHeader
})
it('returns null', returnsNull)
})
})
})
})

View File

@ -328,15 +328,15 @@ describe('in mode', () => {
describe('description', () => {
describe('length without HTML', () => {
describe('less then 100 chars', () => {
describe('less then 3 chars', () => {
it('throws error: "Description too short!"', async () => {
const { errors } = await mutate({
mutation: createGroupMutation(),
variables: {
...variables,
description:
'0123456789' +
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0123456789</a>',
'0' +
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0</a>',
},
})
expect(errors![0]).toHaveProperty('message', 'Description too short!')
@ -2850,15 +2850,15 @@ describe('in mode', () => {
describe('description', () => {
describe('length without HTML', () => {
describe('less then 100 chars', () => {
describe('less then 3 chars', () => {
it('throws error: "Description too short!"', async () => {
const { errors } = await mutate({
mutation: updateGroupMutation(),
variables: {
id: 'my-group',
description:
'0123456789' +
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0123456789</a>',
'0' +
'<a href="https://domain.org/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789">0</a>',
},
})
expect(errors![0]).toHaveProperty('message', 'Description too short!')

View File

@ -34,6 +34,8 @@ const validateEventDate = (dateString) => {
const date = new Date(dateString)
if (date.toString() === 'Invalid Date')
throw new UserInputError('Event start date must be a valid date!')
if (date.toISOString() !== dateString)
throw new UserInputError('Event start date must be in ISO format!')
const now = new Date()
if (date.getTime() < now.getTime()) {
throw new UserInputError('Event start date must be in the future!')
@ -44,6 +46,8 @@ 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!')
if (endDate.toISOString() !== end)
throw new UserInputError('Event end date must be in ISO format!')
const startDate = new Date(start)
if (endDate < startDate)
throw new UserInputError('Event end date must be a after event start date!')

View File

@ -56,98 +56,97 @@ describe('given some notifications', () => {
Factory.build('user', { id: 'neighbor' }),
Factory.build('category', { id: 'cat1' }),
])
const [post1, post2, post3] = await Promise.all([
Factory.build('post', { id: 'p1', content: 'Not for you' }, { author, categoryIds }),
Factory.build(
'post',
{
id: 'p2',
content: 'Already seen post mention',
},
{
author,
categoryIds,
},
),
Factory.build(
'post',
{
id: 'p3',
content: 'You have been mentioned in a post',
},
{
author,
categoryIds,
},
),
])
const [comment1, comment2, comment3] = await Promise.all([
Factory.build(
'comment',
{
id: 'c1',
content: 'You have seen this comment mentioning already',
},
{
author,
postId: 'p3',
},
),
Factory.build(
'comment',
{
id: 'c2',
content: 'You have been mentioned in a comment',
},
{
author,
postId: 'p3',
},
),
Factory.build(
'comment',
{
id: 'c3',
content: 'Somebody else was mentioned in a comment',
},
{
author,
postId: 'p3',
},
),
])
await Promise.all([
post1.relateTo(neighbor, 'notified', {
createdAt: '2019-08-29T17:33:48.651Z',
read: false,
reason: 'mentioned_in_post',
}),
post2.relateTo(user, 'notified', {
createdAt: '2019-08-30T17:33:48.651Z',
read: true,
reason: 'mentioned_in_post',
}),
post3.relateTo(user, 'notified', {
createdAt: '2019-08-31T17:33:48.651Z',
read: false,
reason: 'mentioned_in_post',
}),
comment1.relateTo(user, 'notified', {
createdAt: '2019-08-30T15:33:48.651Z',
read: true,
reason: 'mentioned_in_comment',
}),
comment2.relateTo(user, 'notified', {
createdAt: '2019-08-30T19:33:48.651Z',
read: false,
reason: 'mentioned_in_comment',
}),
comment3.relateTo(neighbor, 'notified', {
createdAt: '2019-09-01T17:33:48.651Z',
read: false,
reason: 'mentioned_in_comment',
}),
])
const post1 = await Factory.build(
'post',
{ id: 'p1', content: 'Not for you' },
{ author, categoryIds },
)
const post2 = await Factory.build(
'post',
{
id: 'p2',
content: 'Already seen post mention',
},
{
author,
categoryIds,
},
)
const post3 = await Factory.build(
'post',
{
id: 'p3',
content: 'You have been mentioned in a post',
},
{
author,
categoryIds,
},
)
const comment1 = await Factory.build(
'comment',
{
id: 'c1',
content: 'You have seen this comment mentioning already',
},
{
author,
postId: 'p3',
},
)
const comment2 = await Factory.build(
'comment',
{
id: 'c2',
content: 'You have been mentioned in a comment',
},
{
author,
postId: 'p3',
},
)
const comment3 = await Factory.build(
'comment',
{
id: 'c3',
content: 'Somebody else was mentioned in a comment',
},
{
author,
postId: 'p3',
},
)
await post1.relateTo(neighbor, 'notified', {
createdAt: '2019-08-29T17:33:48.651Z',
read: false,
reason: 'mentioned_in_post',
})
await post2.relateTo(user, 'notified', {
createdAt: '2019-08-30T17:33:48.651Z',
read: true,
reason: 'mentioned_in_post',
})
await post3.relateTo(user, 'notified', {
createdAt: '2019-08-31T17:33:48.651Z',
read: false,
reason: 'mentioned_in_post',
})
await comment1.relateTo(user, 'notified', {
createdAt: '2019-08-30T15:33:48.651Z',
read: true,
reason: 'mentioned_in_comment',
})
await comment2.relateTo(user, 'notified', {
createdAt: '2019-08-30T19:33:48.651Z',
read: false,
reason: 'mentioned_in_comment',
})
await comment3.relateTo(neighbor, 'notified', {
createdAt: '2019-09-01T17:33:48.651Z',
read: false,
reason: 'mentioned_in_comment',
})
})
describe('notifications', () => {

View File

@ -374,6 +374,31 @@ describe('CreatePost', () => {
})
})
describe('with event start in no ISO format', () => {
it('throws an error', async () => {
const now = new Date()
const eventStart = new Date(now.getFullYear(), now.getMonth() - 1).toISOString()
await expect(
mutate({
mutation: createPostMutation(),
variables: {
...variables,
postType: 'Event',
eventInput: {
eventStart: eventStart.split('T')[0],
},
},
}),
).resolves.toMatchObject({
errors: [
{
message: 'Event start date must be in ISO format!',
},
],
})
})
})
describe('with event start date in the past', () => {
it('throws an error', async () => {
const now = new Date()
@ -423,6 +448,32 @@ describe('CreatePost', () => {
})
})
describe('with valid start date and not ISO formated end date', () => {
it('throws an error', async () => {
const now = new Date()
const eventEnd = new Date(now.getFullYear(), now.getMonth() + 2).toISOString()
await expect(
mutate({
mutation: createPostMutation(),
variables: {
...variables,
postType: 'Event',
eventInput: {
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
eventEnd: eventEnd.split('T')[0],
},
},
}),
).resolves.toMatchObject({
errors: [
{
message: 'Event end date must be in ISO format!',
},
],
})
})
})
describe('with valid start date and end date before start date', () => {
it('throws an error', async () => {
const now = new Date()

View File

@ -1,2 +1,3 @@
# Unit Testing
***TODO:** To be filled in*

File diff suppressed because it is too large Load Diff

View File

@ -31,13 +31,16 @@ const { parsed } = dotenv.config({ path: '../backend/.env' })
module.exports = defineConfig({
e2e: {
projectId: "qa7fe2",
defaultCommandTimeout: 10000,
defaultCommandTimeout: 60000,
pageLoadTimeout:180000,
chromeWebSecurity: false,
baseUrl: "http://localhost:3000",
specPattern: "cypress/e2e/**/*.feature",
supportFile: "cypress/support/e2e.js",
retries: 0,
video: false,
viewportHeight: 720,
viewportWidth: 1290,
setupNodeEvents,
},
env: parsed

View File

@ -14,9 +14,9 @@ The following features will be implemented. This gets done in three steps:
2. In a second step we will make our prototype publicly available with an advanced feature set including the technology and organizational structure to drive a bigger public social network.
3. In a third step all the remaining features will be implemented to build the full product.
### User Account
The implemented features can be found [here](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/e2e)
[Cucumber Features](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/integration/user_account)
### User Account
* Sign-up
* Agree to Data Privacy Statement
@ -34,8 +34,6 @@ The following features will be implemented. This gets done in three steps:
### User Profile
[Cucumber Features](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/integration/user_profile)
* Upload and Change Avatar
* Upload and Change Profile Picture
* Edit Social Media Accounts
@ -46,8 +44,6 @@ The following features will be implemented. This gets done in three steps:
### Dashboard
[Clickdummy](https://preview.uxpin.com/24a2ab8adcd84f9a763d87ed27251351225e0ecd#/pages/99768919/simulate/sitemap?mode=i)
* Show Link to own Profile
* Show Friends Widget
* Show Favorites Widget
@ -59,8 +55,6 @@ The following features will be implemented. This gets done in three steps:
### Posts
[Cucumber Features](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/integration/post)
* Creating Posts
* Persistent Links
* Upload Teaser Picture for Post
@ -85,8 +79,6 @@ The following features will be implemented. This gets done in three steps:
### Notifications
[Cucumber features](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/integration/notifications)
* User @-mentionings
* Notify authors for comments
* Administrative notifications to all users
@ -108,8 +100,6 @@ The following features will be implemented. This gets done in three steps:
### Blacklist
[Video](https://www.youtube.com/watch?v=-uDvvmN8hLQ)
* Blacklist Users
* Blacklist specific Terms
* Blacklist Tags
@ -117,8 +107,6 @@ The following features will be implemented. This gets done in three steps:
### Search
[Cucumber Features](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/integration/search)
* Search for Categories
* Search for Tags
* Fulltext Search
@ -238,8 +226,6 @@ Shows automatically related actions for existing post.
### Moderation
[Cucumber Features](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/integration/moderation)
* Report Button for users for doubtful Content
* Moderator Panel
* List of reported Content \(later replaced by User-Moderation\)
@ -250,8 +236,6 @@ Shows automatically related actions for existing post.
### Administration
[Cucumber Features](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/integration/administration)
* Provide Admin-Interface to send Users Invite Code
* Static Pages for Data Privacy Statement ...
* Create, edit and delete Announcements
@ -265,8 +249,6 @@ Shows automatically related actions for existing post.
### Internationalization
[Cucumber Features](https://github.com/Ocelot-Social-Community/Ocelot-Social/tree/master/cypress/integration/internationalization)
* Frontend UI
* Backend Error Messages

View File

@ -1,6 +1,8 @@
import { Then } from "@badeball/cypress-cucumber-preprocessor";
import 'cypress-network-idle';
Then("I click the checkbox show donations progress bar and save", () => {
cy.get("#showDonations").click()
cy.get(".donations-info-button").click()
cy.waitForNetworkIdle(2000)
})

View File

@ -1 +1,7 @@
CONFIGURATION=example
# branding folder used for "docker compose up" run in deployment folder
CONFIGURATION=stage.ocelot.social
# used in "scripts/clusters.backup-multiple-servers.sh"
BACKUP_CONFIGURATIONS="stage.ocelot.social stage.wir.social"
# if '<= 0' no backups will be deleted
BACKUP_SAVED_BACKUPS_NUMBER=7

View File

@ -9,8 +9,6 @@
$ export DOCKER_DEFAULT_PLATFORM=linux/amd64
```
For even more informations, see [Docker More Closely](#docker-more-closely)
### Docker Compose Override File For Apple M1 Platform
For Docker compose `up` or `build` commands, you can use our Apple M1 override file that specifies the M1 platform:
@ -27,7 +25,3 @@ $ docker compose -f docker-compose.ocelotsocial-branded.yml -f docker-compose.ap
# only once: init admin user and create indexes and constraints in Neo4j database
$ docker compose exec backend /bin/sh -c "yarn prod:migrate init"
```
## Docker More Closely In Main Code
To get more informations about the Apple M1 platform and to analyze the Docker builds etc. you find our documentation in our main code, [here](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/DOCKER_MORE_CLOSELY.md).

View File

@ -11,7 +11,7 @@ $ minikube dashboard
This will give you an overview. Some of the steps below need some timing to make resources available to other dependent deployments. Keeping an eye on the dashboard is a great way to check that.
Follow the installation instruction for [Kubernetes with Helm](./kubernetes/README.md).
Follow the installation instruction for [Kubernetes with Helm](./src/kubernetes/README.md).
If all the pods and services have settled and everything looks green in your
minikube dashboard, expose the services you want on your host system.

View File

@ -1,7 +1,7 @@
# Ocelot.Social Deploy And Rebranding
[![Build Status Publish](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/actions/workflows/publish.yml/badge.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/actions)
[![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/blob/LICENSE.md)
[![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Ocelot-Social-Community/Ocelot-Social-Deploy-Rebranding/blob/master/LICENSE.md)
[![Discord Channel](https://img.shields.io/discord/489522408076738561.svg)](https://discord.gg/AJSX9DCSUA)
[![Open Source Helpers](https://www.codetriage.com/ocelot-social-community/ocelot-social-deploy-rebranding/badges/users.svg)](https://www.codetriage.com/ocelot-social-community/ocelot-social-deploy-rebranding)
@ -9,8 +9,8 @@ This repository is an in use template to rebrand, configure, and deploy [ocelot.
The forked original repository is [stage.ocelot.social](https://github.com/Ocelot-Social-Community/stage.ocelot.social).
<!-- markdownlint-disable MD033 -->
<p align="center">
<a href="https://ocelot.social" target="_blank"><img src="../webapp/static/img/custom/logo-squared.svg" alt="ocelot.social" width="40%" height="40%"></a>
<p style="text-align: center;">
<a href="https://ocelot.social" target="_blank"><img src="https://raw.githubusercontent.com/Ocelot-Social-Community/Ocelot-Social/master/webapp/static/img/custom/logo-squared.svg" alt="ocelot.social" width="40%" height="40%"></a>
</p>
<!-- markdownlint-enable MD033 -->
@ -39,16 +39,18 @@ Fork this repository to configure and rebrand it for your own [ocelot.social](ht
Write your own data into the main configuration file:
- [package.json](/package.json)
- [package.json](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/package.json)
Since all deployment methods described here depend on [Docker](https://docker.com) and [DockerHub](https://hub.docker.com), you need to create your own organisation on DockerHub and put its name in the [package.json](/package.json) file as your `dockerOrganisation`.
Since all deployment methods described here depend on [Docker](https://docker.com) and [DockerHub](https://hub.docker.com), you need to create your own organisation on DockerHub and put its name in the [package.json](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/package.json) file as your `dockerOrganisation`.
### Configure And Branding
The next step is:
- [Set Environment Variables and Configurations](./deployment-values.md)
<!-- markdown-link-check-disable -->
- [Configure And Branding](./configurations/stage.ocelot.social/branding/README.md)
<!-- markdown-link-check-enable -->
### Optional: Locally Testing Configuration And Branding
@ -71,7 +73,7 @@ For the maintenance page have a look in your browser at `http://localhost:5000/`
### Push Changes To GitHub
Before merging these changes into the "master" branch on your GitHub fork repository, you need to configure the GitHub repository secrets. This is necessary to [publish](/.github/workflows/publish.yml) the Docker images by pushing them via GitHub actions to repositories belonging to your DockerHub organisation.
Before merging these changes into the "master" branch on your GitHub fork repository, you need to configure the GitHub repository secrets. This is necessary to [publish](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/.github/workflows/publish.yml) the Docker images by pushing them via GitHub actions to repositories belonging to your DockerHub organisation.
First, go to your DockerHub profile under `Account Settings` and click on the `Security` tab. There you create an access token called `<your-organisation>-access-token` and copy the token to a safe place.
@ -100,9 +102,9 @@ See the login details and browser addresses above.
### Deployment
Afterwards you can [deploy](/deployment/deployment.md) it on your server:
Afterwards you can [deploy](./deployment.md) it on your server:
- [Kubernetes with Helm](/deployment/kubernetes/README.md)
- [Kubernetes with Helm](./src/kubernetes/README.md)
## Developer Chat
@ -131,7 +133,6 @@ Browser compatibility testing with [BrowserStack](https://www.browserstack.com/)
## License
See the [LICENSE](/LICENSE.md) file for license rights and limitations (MIT).
See the [LICENSE](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/LICENSE.md) file for license rights and limitations (MIT).
We need `DOCKER_BUILDKIT=0` for this to work.

View File

@ -2,9 +2,26 @@
When you introduce a new version and branding and deploy it on your network, you need to consider the following changes and actions:
## Version >= 3.3.0 with 'ocelotDockerVersionTag' 3.3.0-XXX
## Version >= 3.2.0 with 'ocelotDockerVersionTag' 3.2.0-XXX
- We have the new option to configure DKIM for sent e-mails in environment variables (`.env` or `values.yaml`), see [here](deployment.md):
### Backend and Kubernetes Config `DBMS_DEFAULT_DATABASE`
- We have the new option to configure the default name of the Neo4j database to be used for operations and commands in environment variables (`.env`, `docker-compose.yml` or `values.yaml`).
For more details see [deployment-values.md](deployment-values.md):
```yaml
DBMS_DEFAULT_DATABASE: "graph.db"
```
The default value is `neo4j` if it is not set.
### Webapp Config `dateTime`
- You can set `RELATIVE_DATETIME` and `ABSOLUT_DATETIME_FORMAT` in `branding/constants/dateTime.js` originally in main code file `webapp/constants/dateTime.js` to your preferred values.
## Version >= 3.1.0 with 'ocelotDockerVersionTag' 3.1.0-555
- We have the new option to configure DKIM for sent e-mails in environment variables (`.env`, `docker-compose.yml` or `values.yaml`), see [deployment-values.md](deployment-values.md):
- `SMTP_DKIM_DOMAINNAME=`
- `SMTP_DKIM_KEYSELECTOR=`
- `SMTP_DKIM_PRIVATKEY=`
@ -15,7 +32,7 @@ When you introduce a new version and branding and deploy it on your network, you
## 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.
- 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 values.
### Main Code PR feat(webapp): map #5843

View File

@ -3,6 +3,21 @@
For each deployment, you need to set the environment variables and configurations.
Here is some specific information on how to set the values.
## Webapp
We have several configuration possibilities just in the frontend.
### Date Time
In file `branding/constants/dateTime.js`.
- `RELATIVE_DATETIME`
- `true` (default) or `false`
- `ABSOLUT_DATETIME_FORMAT`
- definition see [date-fns, format](https://date-fns.org/v3.3.1/docs/format):
- `P`: just localized date
- `Pp`: just localized date and time
## E-Mails
You need to set environment variables to send registration and invitation information or notifications to users, for example.
@ -17,7 +32,7 @@ Sometimes it is enough to create an SPF record in your DNS.
### DKIM
However, if you need DKIM authorization and verification, you must set the appropriate environment variables:
However, if you need DKIM authorization and verification, you must set the appropriate environment variables in: `.env`, `docker-compose.yml` or Helm script `values.yaml`:
```bash
SMTP_DKIM_DOMAINNAME=<your e-mail sender domain>
@ -36,3 +51,23 @@ To create the private and public DKIM key, see here:
Information about the required PEM format can be found here:
<https://docs.progress.com/bundle/datadirect-hybrid-data-pipeline-installation-46/page/PEM-file-format.html>
## Neo4j Database
We have several configuration options for our Neo4j database.
### DBMS_DEFAULT_DATABASE Default Database Name to be Used
If you need to set the default database name in Neo4j to be used for all operations and terminal commands like our backup scripts, you must set the appropriate environment variable in: `.env`, `docker-compose.yml` or Helm script `values.yaml`:
```yaml
DBMS_DEFAULT_DATABASE: "graph.db"
```
The default value is `neo4j` if it is not set.
As example see files:
- `neo4j/.env.template`
- `deployment/docker-compose.yml`
- `deployment/configurations/stage.ocelot.social/kubernetes/values.yaml.template`

View File

@ -4,14 +4,14 @@ Before you start the deployment you have to do preparations.
## Deployment Preparations
Since all deployment methods described here depend on [Docker](https://docker.com) and [DockerHub](https://hub.docker.com), you need to create your own organisation on DockerHub and put its name in the [package.json](/package.json) file as your `dockerOrganisation`.
Read more details in the [main README](/README.md) under [Usage](/README.md#usage).
Since all deployment methods described here depend on [Docker](https://docker.com) and [DockerHub](https://hub.docker.com), you need to create your own organisation on DockerHub and put its name in the [package.json](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/package.json) file as your `dockerOrganisation`.
Read more details in the [main README](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/README.md) under [Usage](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/README.md#usage).
## Deployment Methods
You have the following options for a deployment:
- [Kubernetes with Helm](./kubernetes/README.md)
- [Kubernetes with Helm](./src/kubernetes/README.md)
## After Deployment
@ -22,15 +22,15 @@ After the first deployment of the new network on your server, the database is in
***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
## Using the Scripts
To use all the scripts you have to set the variable `CONFIGURATION` in your terminal by entering:
To use most of 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>`
$ export CONFIGURATION=<your-configuration-name>
# to check this
$ echo $CONFIGURATION
```
@ -64,9 +64,13 @@ $ scripts/cluster.maintenance.sh on
$ scripts/cluster.maintenance.sh off
```
### Backup Script
### Backup Scripts
To save a locale backup of the database and uploaded images:
Save backups.
#### Single Backup
To save a local backup of the database and uploaded images:
```bash
# in deployment folder
@ -76,3 +80,58 @@ $ scripts/cluster.backup.sh
```
The backup will be saved into your network folders `backup` folder in a new folder with the date and time.
#### Multiple Networks Backup
In order to save several network backups locally, you must define the configuration names of all networks in `.env`. The template for this is `deployment/.env.dist`:
```bash
# in the deployment folders '.env' set as example
BACKUP_CONFIGURATIONS="stage.ocelot.social stage.wir.social"
BACKUP_SAVED_BACKUPS_NUMBER=7
```
If `BACKUP_SAVED_BACKUPS_NUMBER <= 0` then no backups will be deleted.
To actually save all the backups run:
```bash
# in deployment folder
# save all backups listed in 'BACKUP_CONFIGURATIONS'
# delete all backups older then the 'BACKUP_SAVED_BACKUPS_NUMBER' newest ones
$ scripts/clusters.backup-multiple-servers.sh
```
The backups will be saved into your networks folders `backup` folder in a new folder with the date and time.
#### Automated Backups
⚠️ *Attention: Please check carefully whether really the oldest backups have been deleted. As shells on different systems behave differently with regard to the commands used in this script.*
Install automated backups by a [cron job](https://en.wikipedia.org/wiki/Cron).
Be aware of having the bash shell installed to run the script.
The environment variables for the automated backups are described above.
Installing a cron job by editing the cron table file:
```bash
# edit cron job table
$ crontab -e
```
In the editor add the line:
```bash
# in cron job table file
# set a cron job every night at 04am server time
# min hour day month weekday command
00 04 * * * /root/Ocelot-Social/deployment/scripts/clusters.backup-multiple-servers.sh >> /root/Ocelot-Social/deployment/backup-cron-job.log
```
This way the terminal output is written into a log file named `backup-cron-job.log` located in the deployment folder.
Be aware that the server datetime can differ from your local time.
Especially by the change between summer and winter time, because servers usually have UTC.
Find out the actual difference by running the command `date` on your server.

View File

@ -142,19 +142,38 @@ services:
- 3001:80
neo4j:
# Neo4j v3.5.14-community
# image: wollehuss/neo4j-community-branded:latest
# Neo4j 4.4-community
image: ocelotsocialnetwork/neo4j-community:latest
container_name: neo4j-branded
networks:
- test-network
ports:
- 7687:7687
# only for development
# - 7474:7474
- 7474:7474
volumes:
- neo4j_data:/data
environment:
# settings reference: https://neo4j.com/docs/operations-manual/4.4/docker/ref-settings/
# TODO: This sounds scary for a production environment
- NEO4J_AUTH=none
- NEO4J_dbms_security_procedures_unrestricted=algo.*,apoc.*
- NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
ports:
- 7687:7687
- 7474:7474
- NEO4J_dbms_allow__format__migration=true
- NEO4J_dbms_allow__upgrade=true
# TODO: clarify if that is the only thing needed to unlock the Enterprise version
# - NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
# Uncomment following line for Neo4j Enterprise version instead of Community version
# TODO: clarify if that is the only thing needed to unlock the Enterprise version
# - NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
# set the name of the database to be used
# - NEO4J_dbms_default__database=graph.db
# - NEO4J_dbms_default__database=neo4j
# TODO: Remove the playground from production
# bring the database in offline mode to export or load dumps
# command: ["tail", "-f", "/dev/null"]
mailserver:
image: djfarrelly/maildev

View File

@ -1,52 +1,46 @@
#!/bin/bash
# time stamp
printf "Backup started at:\n "
date
# base setup
SCRIPT_PATH=$(realpath $0)
SCRIPT_DIR=$(dirname $SCRIPT_PATH)
# check CONFIGURATION
if [ -z ${CONFIGURATION} ]; then
echo "You must provide a `CONFIGURATION` via environment variable"
if [[ -z "$CONFIGURATION" ]]; then
echo "!!! You must provide a CONFIGURATION via environment variable !!!"
exit 1
fi
printf " Cluster: %s\n" $CONFIGURATION
# configuration
KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeconfig.yaml}
BACKUP_DATE=$(date "+%F_%H-%M-%S")
BACKUP_FOLDER=${BACKUP_FOLDER:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/backup/${BACKUP_DATE}}
# create backup fodler
printf "Backup folder name: %s\n" $BACKUP_DATE
# create backup folder
mkdir -p ${BACKUP_FOLDER}
# maintenance mode on
${SCRIPT_DIR}/cluster.maintenance.sh on
# shutdown database
kubectl --kubeconfig=${KUBECONFIG} get deployment ocelot-neo4j -o json \
| jq '.spec.template.spec.containers[] += {"command": ["tail", "-f", "/dev/null"]}' \
| kubectl --kubeconfig=${KUBECONFIG} apply -f -
# wait for the container to restart
sleep 60
# cluster maintenance mode on && Neo4j maintenance mode on
${SCRIPT_DIR}/cluster.neo4j.sh maintenance on
# database backup
echo "Dumping database ..."
kubectl --kubeconfig=${KUBECONFIG} -n default exec -it \
$(kubectl --kubeconfig=${KUBECONFIG} -n default get pods | grep ocelot-neo4j | awk '{ print $1 }') \
-- neo4j-admin dump --database=graph.db --to=/var/lib/neo4j/$BACKUP_DATE-neo4j-dump
-- neo4j-admin dump --to=/var/lib/neo4j/$BACKUP_DATE-neo4j-dump
# copy neo4j backup to local drive
echo "Copying database to local file system ..."
kubectl --kubeconfig=${KUBECONFIG} cp \
default/$(kubectl --kubeconfig=${KUBECONFIG} -n default get pods | grep ocelot-neo4j |awk '{ print $1 }'):/var/lib/neo4j/$BACKUP_DATE-neo4j-dump $BACKUP_FOLDER/neo4j-dump
# copy image data
echo "Copying public uploads to local file system ..."
kubectl --kubeconfig=${KUBECONFIG} cp \
default/$(kubectl --kubeconfig=${KUBECONFIG} -n default get pods | grep ocelot-backend |awk '{ print $1 }'):/app/public/uploads $BACKUP_FOLDER/public-uploads
# restart database
kubectl --kubeconfig=${KUBECONFIG} get deployment ocelot-neo4j -o json \
| jq 'del(.spec.template.spec.containers[].command)' \
| kubectl --kubeconfig=${KUBECONFIG} apply -f -
# wait for the container to restart
sleep 60
# maintenance mode off
${SCRIPT_DIR}/cluster.maintenance.sh off
# Neo4j maintenance mode off && cluster maintenance mode off
${SCRIPT_DIR}/cluster.neo4j.sh maintenance off

View File

@ -0,0 +1,56 @@
#!/bin/bash
# base setup
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}"
# configuration
KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeconfig.yaml}
VALUES=${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubernetes/values.yaml
DOCKERHUB_OCELOT_TAG=${DOCKERHUB_OCELOT_TAG:-"latest"}
## install Ingress-Nginx
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install \
ingress-nginx ingress-nginx/ingress-nginx \
--kubeconfig=${KUBECONFIG} \
-f ${SCRIPT_DIR}/../src/kubernetes/nginx.values.yaml
## install Cert-Manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install \
cert-manager jetstack/cert-manager \
--kubeconfig=${KUBECONFIG} \
--namespace cert-manager \
--create-namespace \
--version v1.13.2 \
--set installCRDs=true
## install Ocelot with helm
helm install \
ocelot \
--kubeconfig=${KUBECONFIG} \
--values ${VALUES} \
--set appVersion="${DOCKERHUB_OCELOT_TAG}" \
${SCRIPT_DIR}/../src/kubernetes/ \
--timeout 10m
## set Neo4j database indexes, constrains, and initial admin account plus run migrate up
kubectl --kubeconfig=${KUBECONFIG} \
-n default \
exec -it \
$(kubectl --kubeconfig=${KUBECONFIG} -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- \
/bin/sh -c "yarn prod:migrate init && yarn prod:migrate up"
# /bin/sh -c "node --experimental-repl-await build/src/db/clean.js && node --experimental-repl-await build/src/db/seed.js"
echo "!!! You must install a firewall or similar !!! (for DigitalOcean see: deployment/src/kubernetes/README.md)"

View File

@ -5,7 +5,7 @@ SCRIPT_PATH=$(realpath $0)
SCRIPT_DIR=$(dirname $SCRIPT_PATH)
# check CONFIGURATION
if [ -z ${CONFIGURATION} ]; then
if [[ -z "$CONFIGURATION" ]]; then
echo "You must provide a `CONFIGURATION` via environment variable"
exit 1
fi
@ -16,9 +16,11 @@ KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeco
case $1 in
on)
echo "Network maintenance: on"
kubectl --kubeconfig=${KUBECONFIG} patch ingress ingress-ocelot-webapp --type merge --patch-file ${SCRIPT_DIR}/../src/kubernetes/patches/patch.ingress.maintenance.on.yaml
;;
off)
echo "Network maintenance: off"
kubectl --kubeconfig=${KUBECONFIG} patch ingress ingress-ocelot-webapp --type merge --patch-file ${SCRIPT_DIR}/../src/kubernetes/patches/patch.ingress.maintenance.off.yaml
;;
*)

View File

@ -0,0 +1,57 @@
#!/bin/bash
# base setup
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
# configuration
KUBECONFIG=${KUBECONFIG:-${SCRIPT_DIR}/../configurations/${CONFIGURATION}/kubeconfig.yaml}
case $1 in
maintenance)
case $2 in
on)
# maintenance mode on
${SCRIPT_DIR}/cluster.maintenance.sh on
# set Neo4j in offline mode (maintenance)
echo "Neo4j maintenance: on"
kubectl --kubeconfig=${KUBECONFIG} get deployment ocelot-neo4j -o json \
| jq '.spec.template.spec.containers[] += {"command": ["tail", "-f", "/dev/null"]}' \
| kubectl --kubeconfig=${KUBECONFIG} apply -f -
# wait for the container to restart
echo "Wait 60s ..."
sleep 60
;;
off)
# set Neo4j in online mode
echo "Neo4j maintenance: off"
kubectl --kubeconfig=${KUBECONFIG} get deployment ocelot-neo4j -o json \
| jq 'del(.spec.template.spec.containers[].command)' \
| kubectl --kubeconfig=${KUBECONFIG} apply -f -
# wait for the container to restart
echo "Wait 60s ..."
sleep 60
# maintenance mode off
${SCRIPT_DIR}/cluster.maintenance.sh off
;;
*)
echo -e "Run this script with first argument either 'off' or 'on'"
exit
;;
esac
;;
*)
echo -e "Run this script with first argument 'maintenance'"
exit
;;
esac

View File

@ -0,0 +1,91 @@
#!/bin/bash
# time stamp
printf "\n\nMultiple backups started at:\n "
date
# base setup
SCRIPT_PATH=$(realpath $0)
SCRIPT_DIR=$(dirname $SCRIPT_PATH)
# save old CONFIGURATION for later reset
export SAVE_CONFIGURATION=$CONFIGURATION
# export all variables in "../.env"
set -a
source ${SCRIPT_DIR}/../.env
set +a
# check BACKUP_CONFIGURATIONS
if [[ -z "$BACKUP_CONFIGURATIONS" ]]; then
#%! echo "You must provide a BACKUP_CONFIGURATIONS via environment variable"
printf "!!! You must provide a BACKUP_CONFIGURATIONS via environment variable !!!\n"
exit 1
fi
# check BACKUP_SAVED_BACKUPS_NUMBER
if [[ -z ${BACKUP_SAVED_BACKUPS_NUMBER} ]]; then
#%! echo "You must provide a BACKUP_SAVED_BACKUPS_NUMBER via environment variable"
printf "!!! You must provide a BACKUP_SAVED_BACKUPS_NUMBER via environment variable !!!\n"
exit 1
fi
# convert configurations to array
IFS=' ' read -a CONFIGURATIONS_ARRAY <<< "$BACKUP_CONFIGURATIONS"
# display the clusters
printf "Backup the clusters:\n"
for i in "${CONFIGURATIONS_ARRAY[@]}"
do
echo " $i"
done
# deleting backups?
if (( BACKUP_SAVED_BACKUPS_NUMBER >= 1 )); then
printf "Keep the last %d backups for all networks.\n" $BACKUP_SAVED_BACKUPS_NUMBER
else
echo "!!! ATTENTION: No backups are deleted !!!"
fi
echo "Cancel by ^C. You have 15 seconds"
# wait for the admin to react
sleep 15
printf "\n"
for i in "${CONFIGURATIONS_ARRAY[@]}"
do
export CONFIGURATION=$i
# individual cluster backup
${SCRIPT_DIR}/cluster.backup.sh
# deleting backups?
if (( BACKUP_SAVED_BACKUPS_NUMBER >= 1 )); then
# delete all oldest backups, but leave the last BACKUP_SAVED_BACKUPS_NUMBER
keep=$BACKUP_SAVED_BACKUPS_NUMBER
path="$SCRIPT_DIR/../configurations/$CONFIGURATION/backup/"
cd $path
printf "In\n '$path'\n remove:\n"
while [ `ls -1 | wc -l` -gt $keep ]; do
oldest=`ls -c1 | sort -n | head -1`
printf " %s\n" $oldest
rm -rf $oldest
done
printf "Keep the last %d backups:\n" $BACKUP_SAVED_BACKUPS_NUMBER
ls -c1 | sort -n | awk '{print " " $0}'
cd $SCRIPT_DIR
else
echo "!!! ATTENTION: No backups are deleted !!!"
fi
printf "\n"
done
# reset CONFIGURATION to old
export CONFIGURATION=$SAVE_CONFIGURATION
echo "Reset to CONFIGURATION=$CONFIGURATION"

View File

@ -145,6 +145,9 @@ neo4j% exit
$ kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-neo4j | awk '{ print $1 }') -- ls
```
If you need a specific database name, add the option `--database=<name>` to the command `neo4j-admin dump`.
To find out the default database name, see the [Neo4j readme](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/neo4j/README.md).
Lets copy the dump backup
```bash

View File

@ -49,6 +49,49 @@ Skip `Patch & Minor Version Upgrades` for now.
You don't need a 1-click app. Our helmet script will install the required NGINXs.
Therefore, skip this step as well.
For a 1-click Kubernetes Dashboard or alternatives, follow the next steps.
## Install Kubernetes Dashboard
We recommend installing a Kubernetes Dashboard, as DigitalOcean no longer offers a pre-installed dashboard.
- 1-click-deployment of [Kubernetes Dashboard on DigitalOcean marketplace](https://marketplace.digitalocean.com/apps/kubernetes-dashboard)
There you will also find a section entitled `Getting Started`, which describes how you can log in from your local computer.
Very short description:
### In your DigitalOcean Account
For authentication, download the current cluster configuration file from DigitalOcean.
### In Terminal
Set the context of the cluster by command:
```bash
$ kubectl config use-context <context-name>
```
Port-forward the Kubernetes Dashboard to your local machine:
```bash
# save pod name
$ export POD_NAME=$(kubectl get pods -n kubernetes-dashboard -l "app.kubernetes.io/name=kubernetes-dashboard,app.kubernetes.io/instance=kubernetes-dashboard" -o jsonpath="{.items[0].metadata.name}")
# forward port
$ kubectl -n kubernetes-dashboard port-forward $POD_NAME 8443:8443
```
### Log-In to Kubernetes Dashboard
Access the URL in your local web browser at `https://127.0.0.1:8443/`, and log in using your Kubernetes cluster credentials downloaded config file. You may encounter a certificate warning, so make sure to override it.
## Alternatives to Kubernetes Dashboard
DigitalOcean has a website about Kubernetes Dashboard and alternatives:
- <https://www.digitalocean.com/community/conceptual-articles/kubernetes-visualization-tools?mkt_tok=MTEzLURUTi0yNjYAAAGQ0YS-wbZaWn5th-m86-fM7vgiLvxNipWpAsUrgd2z4YgiMB0aRgCIDYEiC0Y2c0H9tBsICZQ5ORKgssOgeSjOKSEfN3i7xUpzqXbdZiYxNL2Q>
## DNS Configuration
There are the following two ways to set up the DNS.
@ -68,17 +111,17 @@ Take one of the IPs of perhaps two or more droplets in your cluster from the lis
To understand what makes sense to do when managing your DNS with DigitalOcean, you need to know how DNS works:
DNS means `Domain Name System`. It resolves domains like `example.com` into an IP like `123.123.123.123`.
DigitalOcean is not a domain registrar, but provides a DNS management service. If you use DigitalOcean's DNS management service, you can configure [your cluster](/deployment/kubernetes/README.md#dns) to always resolve the domain to the correct IP and automatically update it for that.
DigitalOcean is not a domain registrar, but provides a DNS management service. If you use DigitalOcean's DNS management service, you can configure [your cluster](./README.md#dns) to always resolve the domain to the correct IP and automatically update it for that.
The IPs of the DigitalOcean machines are not necessarily stable, so the cluster's DNS service will update the DNS records managed by DigitalOcean to the new IP as needed.
***CAUTION:** If you are using an external DNS, you currently have to do this manually, which can cause downtime.*
## Deploy
Yeah, you're done here. Back to [Deployment with Helm for Kubernetes](/deployment/kubernetes/README.md).
Yeah, you're done here. Back to [Deployment with Helm for Kubernetes](./README.md).
## Backups On DigitalOcean
You can and should do [backups](/deployment/kubernetes/Backup.md) with Kubernetes for sure.
You can and should do [backups](./Backup.md) with Kubernetes for sure.
Additional to backup and copying the Neo4j database dump and the backend images you can do a volume snapshot on DigitalOcean at the moment you have the database in sleep mode.

View File

@ -9,7 +9,7 @@ Please contact us if you are interested in options not listed below.
Managed Kubernetes:
- [DigitalOcean](/deployment/kubernetes/DigitalOcean.md)
- [DigitalOcean](./DigitalOcean.md)
## Configuration
@ -46,29 +46,20 @@ Please have a look here:
- [Installing with Helm](https://cert-manager.io/docs/installation/helm/#installing-with-helm)
Our Helm installation is optimized for cert-manager version `v1.9.1` and `kubectl` version `"v1.24.2`.
Our Helm installation is optimized for cert-manager version `v1.13.1` and `kubectl` version `"v1.28.2`.
Please search here for cert-manager versions that are compatible with your `kubectl` version on the cluster and on the client: [cert-manager Supported Releases](https://cert-manager.io/docs/installation/supported-releases/#supported-releases).
***ATTENTION:*** *When uninstalling cert-manager, be sure to use the same method as for installation! Otherwise, we could end up in a broken state, see [Uninstall](https://cert-manager.io/docs/installation/kubectl/#uninstalling).*
<!-- #### 1. Create Namespace
```bash
# kubeconfig.yaml set globaly
$ kubectl create namespace cert-manager
# or kubeconfig.yaml in your repo, then adjust
$ kubectl --kubeconfig=/../kubeconfig.yaml create namespace cert-manager
```
#### 2. Add Helm repository and update
<!-- #### 1. Add Helm repository and update
```bash
$ helm repo add jetstack https://charts.jetstack.io
$ helm repo update
```
#### 3. Install Cert-Manager Helm chart
#### 2. Install Cert-Manager Helm chart
```bash
# option 1
@ -76,16 +67,24 @@ $ helm repo update
# $ kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.crds.yaml
# option 2
# !!! untested for now for new deployment structure !!!
# in configuration/<deployment-name>
# kubeconfig.yaml set globaly
$ helm install cert-manager jetstack/cert-manager \
$ helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.9.1 \
--create-namespace \
--version v1.13.2 \
--set installCRDs=true
# or kubeconfig.yaml in your repo, then adjust
$ helm --kubeconfig=/../kubeconfig.yaml \
install cert-manager jetstack/cert-manager \
$ helm install \
cert-manager jetstack/cert-manager \
--kubeconfig ./kubeconfig.yaml \
--namespace cert-manager \
--version v1.9.1 \
--create-namespace \
--version v1.13.2 \
--set installCRDs=true
``` -->
@ -101,10 +100,15 @@ $ helm repo update
#### 2. Install ingress-nginx
```bash
# in configuration/<deployment-name>
# kubeconfig.yaml set globaly
$ helm install ingress-nginx ingress-nginx/ingress-nginx -f nginx.values.yaml
helm install ingress-nginx ingress-nginx/ingress-nginx -f ../../src/kubernetes/nginx.values.yaml
# or kubeconfig.yaml in your repo, then adjust
$ helm --kubeconfig=/../kubeconfig.yaml install ingress-nginx ingress-nginx/ingress-nginx -f nginx.values.yaml
helm install \
ingress-nginx ingress-nginx/ingress-nginx -f ../../src/kubernetes/nginx.values.yaml \
--kubeconfig ./kubeconfig.yaml
```
### DigitalOcean Firewall
@ -159,7 +163,9 @@ $ doctl compute firewall get <ID> --context <context-name>
### DNS
***TODO:** I thought this is necessary if we use the DigitalOcean DNS management service? See [Manage DNS With DigitalOcean](/deployment/kubernetes/DigitalOcean.md#manage-dns-with-digitalocean)*
***ATTENTION:** This seems not to work at all so we leave it away at the moment*
***TODO:** I thought this is necessary if we use the DigitalOcean DNS management service? See [Manage DNS With DigitalOcean](./DigitalOcean.md#manage-dns-with-digitalocean)*
This chart is only necessary (recommended is more precise) if you run DigitalOcean without load balancer.
You need to generate an access token with read + write for the `dns.values.yaml` at <https://cloud.digitalocean.com/account/api/tokens> and fill it in.
@ -174,6 +180,8 @@ $ helm repo update
#### 2. Install DNS
```bash
# !!! untested for now for new deployment structure !!!
# kubeconfig.yaml set globaly
$ helm install dns bitnami/external-dns -f dns.values.yaml
# or kubeconfig.yaml in your repo, then adjust
@ -191,10 +199,22 @@ All commands for ocelot need to be executed in the kubernetes folder. Therefore
Only run once for the first time of installation:
```bash
# in configuration/<deployment-name>
# kubeconfig.yaml set globaly
$ helm install ocelot ./
helm install ocelot \
--values ./kubernetes/values.yaml \
--set appVersion="latest" \
../../src/kubernetes/ \
--timeout 10m
# or kubeconfig.yaml in your repo, then adjust
$ helm --kubeconfig=/../kubeconfig.yaml install ocelot ./
helm install ocelot \
--kubeconfig ./kubeconfig.yaml \
--values ./kubernetes/values.yaml \
--set appVersion="latest" \
../../src/kubernetes/ \
--timeout 10m
```
#### Upgrade & Update
@ -202,10 +222,24 @@ $ helm --kubeconfig=/../kubeconfig.yaml install ocelot ./
Run for all upgrades and updates:
```bash
# !!! untested for now for new deployment structure !!!
# in configuration/<deployment-name>
# kubeconfig.yaml set globaly
$ helm upgrade ocelot ./
helm upgrade ocelot \
--values ./kubernetes/values.yaml \
--set appVersion="latest" \
../../src/kubernetes/ \
--timeout 10m
# or kubeconfig.yaml in your repo, then adjust
$ helm --kubeconfig=/../kubeconfig.yaml upgrade ocelot ./
helm upgrade ocelot \
--kubeconfig ./kubeconfig.yaml \
--values ./kubernetes/values.yaml \
--set appVersion="latest" \
../../src/kubernetes/ \
--timeout 10m
```
#### Rollback
@ -213,10 +247,17 @@ $ helm --kubeconfig=/../kubeconfig.yaml upgrade ocelot ./
Run for a rollback, in case something went wrong:
```bash
# !!! untested for now for new deployment structure !!!
# in configuration/<deployment-name>
# kubeconfig.yaml set globaly
$ helm rollback ocelot
helm rollback ocelot --timeout 10m
# or kubeconfig.yaml in your repo, then adjust
$ helm --kubeconfig=/../kubeconfig.yaml rollback ocelot
helm rollback ocelot \
--kubeconfig ./kubeconfig.yaml \
--timeout 10m
```
#### Uninstall
@ -224,17 +265,24 @@ $ helm --kubeconfig=/../kubeconfig.yaml rollback ocelot
Be aware that if you uninstall ocelot the formerly bound volumes become unbound. Those volumes contain all data from uploads and database. You have to manually free their reference in order to bind them again when reinstalling. Once unbound from their former container references they should automatically be rebound (considering the sizes did not change)
```bash
# !!! untested for now for new deployment structure !!!
# in configuration/<deployment-name>
# kubeconfig.yaml set globaly
$ helm uninstall ocelot
helm uninstall ocelot --timeout 10m
# or kubeconfig.yaml in your repo, then adjust
$ helm --kubeconfig=/../kubeconfig.yaml uninstall ocelot
helm uninstall ocelot \
--kubeconfig ./kubeconfig.yaml \
--timeout 10m
```
## Backups
You can and should do [backups](/deployment/kubernetes/Backup.md) with Kubernetes for sure.
You can and should do [backups](./Backup.md) with Kubernetes for sure.
## Error Reporting
<!-- ## Error Reporting
We use [Sentry](https://github.com/getsentry/sentry) for error reporting in both
our backend and web frontend. You can either use a hosted or a self-hosted
@ -249,7 +297,7 @@ If you are lucky enough to have a kubernetes cluster with the required hardware
support, try this [helm chart](https://github.com/helm/charts/tree/master/stable/sentry).
On our kubernetes cluster we get "mult-attach" errors for persistent volumes.
Apparently DigitalOcean's kubernetes clusters do not fulfill the requirements.
Apparently DigitalOcean's kubernetes clusters do not fulfill the requirements. -->
## Kubernetes Commands (Without Helm) To Deploy New Docker Images To A Kubernetes Cluster
@ -292,8 +340,11 @@ $ kubectl -n default rollout status deployment/ocelot-neo4j --timeout=240s
# !!! be aware of the correct kube context !!!
$ kubectl config get-contexts
# reset and seed Neo4j database via backend for staging
# for staging: reset and seed Neo4j database via backend
$ kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "node --experimental-repl-await build/src/db/clean.js && node --experimental-repl-await build/src/db/seed.js"
# or alternatively
# for production: set Neo4j database indexes, constrains, and initial admin account plus run migrate up via backend
$ kubectl -n default exec -it $(kubectl -n default get pods | grep ocelot-backend | awk '{ print $1 }') -- /bin/sh -c "yarn prod:migrate init && yarn prod:migrate up"
```

View File

@ -20,4 +20,5 @@ data:
NEO4J_dbms_security_procedures_unrestricted: "{{ .Values.NEO4J.DBMS_SECURITY_PROCEDURES_UNRESTRICTED }}"
NEO4J_dbms_allow__format__migration: "true"
NEO4J_dbms_allow__upgrade: "true"
NEO4J_dbms_default__database: "{{ .Values.NEO4J.DBMS_DEFAULT_DATABASE }}"
NEO4J_apoc_import_file_enabled: "{{ .Values.NEO4J.APOC_IMPORT_FILE_ENABLED }}"

View File

@ -23,13 +23,12 @@ CAUTION: It seems that the behaviour of DigitalOcean has changed and the load ba
And to create a load balancer costs money. Please refine the following documentation if required.
{% endhint %}
{% tabs %}
{% tab title="Without Load Balancer" %}
::: tabs
@tab:active Without Load Balancer
A solution without a load balance you can find [here](../no-loadbalancer/README.md).
{% endtab %}
{% tab title="With DigitalOcean Load Balancer" %}
@tab With DigitalOcean Load Balancer
{% hint style="info" %}
CAUTION: It seems that the behaviour of DigitalOcean has changed and the load balancer is not created automatically anymore.
@ -44,8 +43,7 @@ address. On DigitalOcean, this is how it should look like:
If the load balancer isn't created automatically you have to create it your self on DigitalOcean under Networks.
In case you don't need a DigitalOcean load balancer (which costs money by the way) have a look in the tab `Without Load Balancer`.
{% endtab %}
{% endtabs %}
:::
Check the ingress server is working correctly:

View File

@ -79,8 +79,8 @@ $ kubectl -n ocelot-social get pods
$ kubectl cp ./neo4j-backup human-connection/<POD-ID>:/root/
$ kubectl -n ocelot-social exec -it <POD-ID> bash
# Once you're in the pod restore the backup and overwrite the default database
# called `graph.db` with `--force`.
# This will delete all existing data in database `graph.db`!
# called `neo4j` with `--force`.
# This will delete all existing data in database `neo4j`!
> neo4j-admin load --from=/root/neo4j-backup --force
> exit
```

View File

@ -21,6 +21,26 @@ services:
# bind the local folder to the docker to allow live reload
- ./webapp:/app
########################################################
# FRONTEND #############################################
########################################################
frontend:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: ocelotsocialnetwork/frontend:local-development
build:
target: development
environment:
- NODE_ENV=development
ports:
# port required for npm run dev
- 24678:24678
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- frontend_node_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./frontend:/app
########################################################
# BACKEND ##############################################
########################################################
@ -77,4 +97,5 @@ services:
volumes:
webapp_node_modules:
frontend_node_modules:
backend_node_modules:

View File

@ -39,6 +39,36 @@ services:
env_file:
- ./webapp/.env
########################################################
# FRONTEND #############################################
########################################################
frontend:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: ocelotsocialnetwork/frontend:local-production
container_name: frontend
build:
context: ./frontend
target: production
networks:
- external-net
depends_on:
- backend
ports:
- 3002:3002
environment:
# Envs used in Dockerfile
# - DOCKER_WORKDIR="/app"
# - PORT="3002"
- BUILD_DATE
- BUILD_VERSION
- BUILD_COMMIT
- NODE_ENV="production"
# Application only envs
#- HOST=0.0.0.0 # This is nuxt specific, alternative value is HOST=webapp
#- GRAPHQL_URI=http://backend:4000
env_file:
- ./frontend/.env
########################################################
# BACKEND ##############################################
########################################################
@ -108,14 +138,18 @@ services:
volumes:
- neo4j_data:/data
environment:
# settings reference: https://neo4j.com/docs/operations-manual/4.4/docker/ref-settings/
# TODO: This sounds scary for a production environment
- NEO4J_AUTH=none
- NEO4J_dbms_security_procedures_unrestricted=algo.*,apoc.*
- NEO4J_dbms_allow__format__migration=true
- NEO4J_dbms_allow__upgrade=true
# Uncomment following line for Neo4j Enterprise version instead of Community version
# uncomment following line for Neo4j Enterprise version instead of Community version
# TODO: clarify if that is the only thing needed to unlock the Enterprise version
# - NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
# set the name of the database to be used
# - NEO4J_dbms_default__database=graph.db
# - NEO4J_dbms_default__database=neo4j
# TODO: Remove the playground from production
# bring the database in offline mode to export or load dumps
# command: ["tail", "-f", "/dev/null"]

View File

@ -1,46 +1,46 @@
# Edit this Documentation
# Documentation
## Edit this Documentation
Find the [**table of contents** for this documentation on GitHub](https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/SUMMARY.md) and navigate to the file you need to update.
Click on the **edit pencil** on the right side directly above the text to edit this file on your fork of Human Connection \(HC\).
Click on the **edit pencil** on the right side directly above the text to edit this file in our repository.
You can see a preview of your changes by clicking the **Preview changes** tab aside the **Edit file** tab.
If you are ready, fill in the **Propose file change** at the end of the webpage.
After that you have to send your change to the HC basis with a pull request. Here make a comment which issue you have fixed. (If you are working on one of our [open issues](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues) please include the number.)
After that you have to compare your change branch to our `master` branch with a pull request. Here make a comment which issue you have fixed. (If you are working on one of our [open issues](https://github.com/Ocelot-Social-Community/Ocelot-Social/issues) please include the number.)
## Markdown your documentation
### Markdown your documentation
To design your documentation see the syntax description at GitBook:
[https://toolchain.gitbook.com/syntax/markdown.html](https://toolchain.gitbook.com/syntax/markdown.html)
### Some quick Examples
#### Some quick Examples
#### Headlines
##### Headlines
```markdown
# Main headline
## Smaller headlines
### Small headlines
# Main Headline
## Smaller Headlines
### Small Headlines
```
#### Tabs
##### Tabs
```markdown
{% tabs %}
{% tab title="XXX" %}
XXX
{% endtab %}
{% tab title="XXX" %}
XXX
{% endtab %}
{% endtabs %}
::: tabs
@tab:active First tab's title <!-- this tab is setactive -->
@tab Second tab's title
:::
```
#### Commands
##### Commands
~~~markdown
```<LANGUAGE> (for text highlighting)
@ -48,33 +48,34 @@ XXX
```
~~~
#### Links
##### Links
```markdown
[XXX](https://XXX)
```
For the documentation to work in both frameworks - Github and Vuepress - please use absolute path for Github internal documentation links (e.g. /README.md over ../../README.mdetc.)
#### Screenshots or other Images
##### Screenshots or other Images
```markdown
![XXX](https://XXX)
```
#### Hints For ToDos
##### Hints for ToDos
```markdown
{% hint style="info" %} TODO: XXX {% endhint %}
```
## Host The Screenshots
### Host the Screenshots
### Host On Ocelot-Social \(GitHub\) repository
#### Host on Ocelot-Social \(GitHub\) Repository
{% hint style="info" %}
TODO: How to host on Ocelot-Social \(GitHub\) repository ...
{% endhint %}
### Quick Solution
#### Quick Solution
To quickly host the screenshots go to:
@ -88,26 +89,41 @@ Right click on it and choose kind of **Open link in new tab**.
Copy the URL and paste it were you need it.
## Screenshot modification
### Screenshot Modification
### Add an arrow or some other marking stuff
#### Add an Arrow or some other Marking Stuff
{% tabs %}
{% tab title="macOS" %}
#### In the Preview App
::: tabs
@tab:active macOS
##### In the Preview App
Got to: **Menu** + **Tools** \(GER: Werkzeuge\) + **Annotate** \(GER: Anmerkungen\) + etc.
{% endtab %}
{% tab title="Windows" %}
@tab Windows
{% hint style="info" %}
TODO: How to modify screenshots in Windows ...
{% endhint %}
{% endtab %}
{% tab title="Linux" %}
@tab Linux
{% hint style="info" %}
TODO: How to modify screenshots in Linux ...
{% endhint %}
{% endtab %}
{% endtabs %}
:::
## Deploy this Documentation
TODO
```bash
# set configured Node version
nvm use
# install Vuepress
npm install
# run vuepress
npm run docs:dev
```

5
frontend/.dockerignore Normal file
View File

@ -0,0 +1,5 @@
node_modules/
build/
coverage/
.vuepress/.temp/
.vuepress/.cache/

5
frontend/.env.dist Normal file
View File

@ -0,0 +1,5 @@
# META
PUBLIC_ENV__META__BASE_URL="http://localhost:3000"
PUBLIC_ENV__META__DEFAULT_AUTHOR="IT Team 4 Change"
PUBLIC_ENV__META__DEFAULT_DESCRIPTION="IT4C Frontend Boilerplate"
PUBLIC_ENV__META__DEFAULT_TITLE="IT4C"

5
frontend/.eslintignore Normal file
View File

@ -0,0 +1,5 @@
node_modules/
build/
coverage/
.storybook/
.vuepress/

182
frontend/.eslintrc.cjs Normal file
View File

@ -0,0 +1,182 @@
// eslint-disable-next-line import/no-commonjs
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'standard',
'eslint:recommended',
'plugin:@eslint-community/eslint-comments/recommended',
'plugin:@typescript-eslint/recommended',
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:promise/recommended',
'plugin:security/recommended-legacy',
'plugin:vue/vue3-recommended',
'plugin:@intlify/vue-i18n/recommended',
'plugin:storybook/recommended',
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'import', 'promise', 'security', 'vue', 'storybook'],
settings: {
'import/resolver': {
typescript: true,
node: true,
},
'vue-i18n': {
localeDir: './src/locales/*.json',
},
},
rules: {
'no-console': 'error',
'no-debugger': 'error',
camelcase: 'error',
indent: ['error', 2],
'linebreak-style': ['error', 'unix'],
semi: ['error', 'never'],
// This makes sure our vike router does not throw errors
'vue/multi-word-component-names': [
'error',
{
ignores: ['+Page'],
},
],
// Optional eslint-comments rule
'@eslint-community/eslint-comments/no-unused-disable': 'error',
'@eslint-community/eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }],
// import
'import/export': 'error',
'import/no-deprecated': 'error',
'import/no-empty-named-blocks': 'error',
'import/no-extraneous-dependencies': 'error',
'import/no-mutable-exports': 'error',
'import/no-unused-modules': 'error',
'import/no-named-as-default': 'error',
'import/no-named-as-default-member': 'error',
'import/no-amd': 'error',
'import/no-commonjs': 'error',
'import/no-import-module-exports': 'error',
'import/no-nodejs-modules': 'off',
'import/unambiguous': 'off', // not compatible with scriptless vue files
'import/default': 'error',
'import/named': 'error',
'import/namespace': 'error',
'import/no-absolute-path': 'error',
'import/no-cycle': 'error',
'import/no-dynamic-require': 'error',
'import/no-internal-modules': 'off',
'import/no-relative-packages': 'error',
'import/no-relative-parent-imports': [
'error',
{ ignore: ['#[src,root,components,pages,assets,layouts,stores,plugins,context,types]/*'] },
],
'import/no-self-import': 'error',
'import/no-unresolved': 'error',
'import/no-useless-path-segments': 'error',
'import/no-webpack-loader-syntax': 'error',
'import/consistent-type-specifier-style': 'error',
'import/exports-last': 'off',
'import/extensions': [
'error',
'never',
{
json: 'always',
},
],
'import/first': 'error',
'import/group-exports': 'off',
'import/newline-after-import': 'error',
'import/no-anonymous-default-export': 'off', // todo - consider to enable again
'import/no-default-export': 'off', // incompatible with vite & vike
'import/no-duplicates': 'error',
'import/no-named-default': 'error',
'import/no-namespace': 'error',
'import/no-unassigned-import': 'error',
'import/order': [
'error',
{
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'],
'newlines-between': 'always',
alphabetize: {
order: 'asc', // sort in ascending order. Options: ["ignore", "asc", "desc"]
caseInsensitive: true, // ignore case. Options: [true, false]
},
distinctGroup: true,
},
],
'import/prefer-default-export': 'off',
// promise
'promise/catch-or-return': 'error',
'promise/no-return-wrap': 'error',
'promise/param-names': 'error',
'promise/always-return': 'error',
'promise/no-native': 'off',
'promise/no-nesting': 'warn',
'promise/no-promise-in-callback': 'warn',
'promise/no-callback-in-promise': 'warn',
'promise/avoid-new': 'warn',
'promise/no-new-statics': 'error',
'promise/no-return-in-finally': 'warn',
'promise/valid-params': 'warn',
'promise/prefer-await-to-callbacks': 'error',
'promise/no-multiple-resolved': 'error',
},
overrides: [
{
files: ['*.ts', '*.tsx'],
parser: '@typescript-eslint/parser',
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json', '**/tsconfig.json'],
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
plugins: ['@typescript-eslint'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
'plugin:@typescript-eslint/strict',
],
rules: {
// allow explicitly defined dangling promises
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
'no-void': ['error', { allowAsStatement: true }],
},
},
{
files: ['!*.json'],
plugins: ['prettier'],
extends: ['plugin:prettier/recommended'],
rules: {
'prettier/prettier': 'error',
},
},
{
files: ['*.json'],
plugins: ['json'],
extends: ['plugin:json/recommended-with-comments'],
},
{
files: ['*.vue'],
plugins: ['vuetify'],
extends: ['plugin:vuetify/recommended'],
},
{
files: ['*.[test,spec].[tj]s'],
plugins: ['vitest'],
extends: ['plugin:vitest/all'],
},
{
files: ['*.yaml', '*.yml'],
parser: 'yaml-eslint-parser',
plugins: ['yml'],
extends: ['plugin:yml/prettier'],
},
],
}

1
frontend/.github/.remarkignore vendored Normal file
View File

@ -0,0 +1 @@
*

13
frontend/.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,13 @@
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
<!--
Please take a look at the issue templates at https://github.com/[ORGA/USER]/[REPO]/issues/new/choose
before submitting a new issue. Following one of the issue templates will ensure maintainers can route your request efficiently.
Thanks!
-->
## 💬 Issue
<!-- Describe your Issue in detail. -->
<!-- Attach screenshots and drawings if needed. -->

10
frontend/.github/ISSUE_TEMPLATE/bug.md vendored Normal file
View File

@ -0,0 +1,10 @@
---
name: 🐛 Bug
about: Create a report to help us improve
labels: bug
title: 🐛 [Bug]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## 🐛 Bug
<!-- Describe your issue in detail. Include screenshots if needed. Give us as much information as possible. Use a clear and concise description of what the bug is.-->

View File

@ -0,0 +1,10 @@
---
name: 💥 DevOp
about: Help us manage our deployed Software.
labels: devops
title: 💥 [DevOps]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## 💥 DevOps
<!-- Describe your issue in detail. Include screenshots if needed. Give us as much information as possible. Use a clear and concise description of what the problem is.-->

13
frontend/.github/ISSUE_TEMPLATE/epic.md vendored Normal file
View File

@ -0,0 +1,13 @@
---
name: 🌟 Epic
about: Define a big development Step
labels: epic
title: 🌟 [EPIC]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
<!-- THIS ISSUE-TYPE IS NOT FOR YOU! -->
<!-- Proceed only if you know what you are doing - have a chat with Project's Team first -->
## 🌟 EPIC
<!-- Describe your Epic in detail. Include screenshots and drawings -->

View File

@ -0,0 +1,10 @@
---
name: 🚀 Feature
about: Suggest an idea for this project
labels: feature
title: 🚀 [Feature]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## 🚀 Feature
<!-- Give a short summary of the Feature. Use Screenshots if you want. -->

View File

@ -0,0 +1,13 @@
---
name: 💬 Question
about: If you need help understanding our Software.
labels: question
title: 💬 [Question]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
<!-- Question the project's team -->
<!-- If you need an answer right away, consider to take other means of communication with the project's team -->
## 💬 Question
<!-- Describe your Question in detail. Include screenshots and drawings if needed. -->

View File

@ -0,0 +1,10 @@
---
name: 🔧 Refactor
about: Help us improve our code by refactoring it.
labels: refactor
title: 🔧 [Refactor]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## 🔧 Refactor
<!-- Describe your issue in detail. Include screenshots if needed. Give us as much information as possible. Use a clear and concise description of what the problem is.-->

View File

@ -0,0 +1,13 @@
---
name: 🎂 Release
about: Define a Release
labels: release
title: 🎂 [RELEASE]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
<!-- THIS ISSUE-TYPE IS NOT FOR YOU! -->
<!-- Proceed only if you know what you are doing - have a chat with Project's Team first -->
## 🎂 RELEASE
<!-- Describe your Release in detail. Include screenshots and drawings -->

View File

@ -0,0 +1,15 @@
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## 🍰 Pullrequest
<!-- Describe the Pullrequest. Use Screenshots if possible. -->
### Issues
<!-- Which Issues does this fix, which are related?
- fixes #XXX
- relates #XXX
-->
- None
### Todo
<!-- In case some parts are still missing, list them here. -->
- [X] None

View File

@ -0,0 +1,21 @@
name: "frontend:deploy:docs to github"
on:
push:
branches:
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: vuepress-deploy
uses: jenkey2011/vuepress-deploy@master
env:
ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
#TARGET_REPO: username/repo
#TARGET_BRANCH: master
BUILD_SCRIPT: npm install && npm run docs:build
BUILD_DIR: build/docs/
VUEPRESS_BASE: "boilerplate-frontend"

9
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
node_modules/
build/
coverage/
!.storybook/
!.vuepress/
.vuepress/.temp/
.vuepress/.cache/
build-storybook.log
.env

14
frontend/.prettierrc.json Normal file
View File

@ -0,0 +1,14 @@
{
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"quoteProps": "as-needed",
"jsxSingleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "always",
"endOfLine": "auto"
}

16
frontend/.remarkrc.json Normal file
View File

@ -0,0 +1,16 @@
{
"plugins": [
"remark-gfm",
"remark-preset-lint-consistent",
"remark-preset-lint-markdown-style-guide",
"remark-preset-lint-recommended",
[
"remark-lint-maximum-line-length",
false
],
[
"remark-lint-list-item-indent",
"space"
]
]
}

View File

@ -0,0 +1,26 @@
<!-- .storybook/StoryWrapper.vue -->
<template>
<v-app :theme="themeName">
<v-main>
<slot name="story"></slot>
</v-main>
</v-app>
</template>
<script>
export const DEFAULT_THEME = 'light'
export default {
props: {
themeName: {
default: DEFAULT_THEME,
type: String,
},
},
}
</script>
<style>
.v-application .v-application__wrap {
min-height: unset;
}
</style>

View File

@ -0,0 +1,22 @@
import type { StorybookConfig } from '@storybook/vue3-vite'
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/vue3-vite',
options: {},
},
docs: {
autodocs: 'tag',
},
core: {
disableTelemetry: true, // 👈 Disables telemetry
},
}
export default config

View File

@ -0,0 +1,54 @@
import { setup } from '@storybook/vue3'
import { createPinia } from 'pinia'
import { setPageContext } from '#context/usePageContext'
import i18n from '#plugins/i18n'
import CreateVuetify from '#plugins/vuetify'
import { withVuetifyTheme } from './withVuetifyTheme.decorator'
import type { Preview } from '@storybook/vue3'
setup((app) => {
// Registers your app's plugins into Storybook
const pinia = createPinia()
app.use(pinia)
app.use(i18n)
app.use(CreateVuetify(i18n))
setPageContext(app, { urlPathname: '' })
})
export const decorators = [withVuetifyTheme]
export const globalTypes = {
theme: {
name: 'Theme',
description: 'Global theme for components',
defaultValue: 'light',
toolbar: {
icon: 'paintbrush',
// Array of plain string values or MenuItem shape
items: [
{ value: 'light', title: 'Light', left: '🌞' },
{ value: 'dark', title: 'Dark', left: '🌛' },
],
// Change title based on selected value
dynamicTitle: true,
},
},
}
const preview: Preview = {
parameters: {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
}
export default preview

View File

@ -0,0 +1,20 @@
import { h } from 'vue'
import StoryWrapper, { DEFAULT_THEME } from './StoryWrapper.vue'
export const withVuetifyTheme = (storyFn, context) => {
// Pull our global theme variable, fallback to DEFAULT_THEME
const themeName = context.globals.theme || DEFAULT_THEME
const story = storyFn()
return () => {
return h(
StoryWrapper,
{ themeName }, // Props for StoryWrapper
{
// Puts your story into StoryWrapper's "story" slot with your story args
story: () => h(story, { ...context.args }),
},
)
}
}

View File

@ -0,0 +1,9 @@
{
"extends": [
"stylelint-config-standard",
"stylelint-config-standard-scss",
"stylelint-config-recommended-vue",
"stylelint-config-recess-order",
"stylelint-config-css-modules"
]
}

View File

@ -0,0 +1,13 @@
import { defaultTheme } from '@vuepress/theme-default'
import { viteBundler } from '@vuepress/bundler-vite'
import { defineUserConfig } from 'vuepress'
export default defineUserConfig({
title: 'IT4C Frontend Boilerplate Documentation',
description: 'IT4C Frontend Boilerplate Documentation',
dest: 'build/docs',
base: process.env.VUEPRESS_BASE ? `/${process.env.VUEPRESS_BASE}/` : '/',
pagePatterns: ['**/*.md', '**/LICENSE', '!.vuepress', '!node_modules'],
bundler: viteBundler({}),
theme: defaultTheme({}),
})

122
frontend/Dockerfile Normal file
View File

@ -0,0 +1,122 @@
FROM node:21-alpine3.17 as base
# ENVs (available in production aswell, can be overwritten by commandline or env file)
## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame
ENV DOCKER_WORKDIR="/app"
## We Cannot do `$(date -u +'%Y-%m-%dT%H:%M:%SZ')` here so we use unix timestamp=0
ENV BUILD_DATE="1970-01-01T00:00:00.00Z"
## We cannot do $(npm run version).${BUILD_NUMBER} here so we default to 0.0.0.0
ENV BUILD_VERSION="0.0.0.0"
## We cannot do `$(git rev-parse --short HEAD)` here so we default to 0000000
ENV BUILD_COMMIT="0000000"
## SET NODE_ENV
ENV NODE_ENV="production"
## App relevant Envs
ENV PORT="3002"
# Labels
LABEL org.label-schema.build-date="${BUILD_DATE}"
LABEL org.label-schema.name="it4c:frontend"
LABEL org.label-schema.description="IT4C Frontend Boilerplate"
LABEL org.label-schema.usage="https://github.com/IT4Change/boilerplate-frontend/blob/master/README.md"
LABEL org.label-schema.url="https://github.com/IT4Change/boilerplate-frontend"
LABEL org.label-schema.vcs-url="https://github.com/IT4Change/boilerplate-frontend/tree/master/"
LABEL org.label-schema.vcs-ref="${BUILD_COMMIT}"
LABEL org.label-schema.vendor="IT4C"
LABEL org.label-schema.version="${BUILD_VERSION}"
LABEL org.label-schema.schema-version="1.0"
LABEL maintainer="info@it4c.dev"
# Install Additional Software
## install: node-gyp dependencies
# RUN apk --no-cache add g++ make python3
# Settings
## Expose Container Port
EXPOSE ${PORT}
EXPOSE 24678
## Workdir
RUN mkdir -p ${DOCKER_WORKDIR}
WORKDIR ${DOCKER_WORKDIR}
##################################################################################
# DEVELOPMENT (Connected to the local environment, to reload on demand) ##########
##################################################################################
FROM base as development
# We don't need to copy or build anything since we gonna bind to the
# local filesystem which will need a rebuild anyway
# Run command
# (for development we need to execute npm install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "npm install && npm run dev"
##################################################################################
# STORYBOOK ######################################################################
##################################################################################
FROM base as storybook
# We don't need to copy or build anything since we gonna bind to the
# local filesystem which will need a rebuild anyway
# Run command
# (for development we need to execute npm install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "npm install && npm run storybook"
##################################################################################
# DOCUMENTATION ##################################################################
##################################################################################
FROM base as documentation
# We don't need to copy or build anything since we gonna bind to the
# local filesystem which will need a rebuild anyway
# Run command
# (for development we need to execute npm install since the
# node_modules are on another volume and need updating)
CMD /bin/sh -c "npm install && npm run docs:dev"
##################################################################################
# BUILD (Does contain all files and is therefore bloated) ########################
##################################################################################
FROM base as build
# Copy everything
COPY . .
# npm install
RUN npm install --include=dev --frozen-lockfile --non-interactive
# npm build
RUN npm run build
##################################################################################
# TEST ###########################################################################
##################################################################################
#FROM build as test
# Install Additional Software
# RUN apk add --no-cache bash jq
# Run command
#CMD /bin/sh -c "yarn run dev"
##################################################################################
# PRODUCTION (Does contain only "binary"- and static-files to reduce image size) #
##################################################################################
FROM base as production
# Copy "binary"-files from build image
COPY --from=build ${DOCKER_WORKDIR}/build ./build
# Copy server
COPY --from=build ${DOCKER_WORKDIR}/server ./server
# Copy package.json & tsconfig.json
COPY --from=build ${DOCKER_WORKDIR}/package.json ./package.json
COPY --from=build ${DOCKER_WORKDIR}/package-lock.json ./package-lock.json
COPY --from=build ${DOCKER_WORKDIR}/tsconfig.json ./tsconfig.json
# Install production packages
RUN npm install --omit=dev --frozen-lockfile --non-interactive
# Run command
CMD /bin/sh -c "npm run server:prod"

201
frontend/LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2023 Ulf Gebhardt
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

197
frontend/README.md Normal file
View File

@ -0,0 +1,197 @@
# boilerplate-frontend
[![nodejs][badge-nodejs-img]][badge-nodejs-href]
[![npm][badge-npm-img]][badge-npm-href]
[![docker][badge-docker-img]][badge-docker-href]
[![jq][badge-jq-img]][badge-jq-href]
[![vue][badge-vue-img]][badge-vue-href]
[![vike][badge-vike-img]][badge-vike-href]
[![vuetify][badge-vuetify-img]][badge-vuetify-href]
[![pinia][badge-pinia-img]][badge-pinia-href]
[![vue-i18n][badge-vue-i18n-img]][badge-vue-i18n-href]
[![eslint][badge-eslint-img]][badge-eslint-href]
[![remark-cli][badge-remark-cli-img]][badge-remark-cli-href]
[![stylelint][badge-stylelint-img]][badge-stylelint-href]
[![vitest][badge-vitest-img]][badge-vitest-href]
[![storybook][badge-storybook-img]][badge-storybook-href]
[![vuepress][badge-vuepress-img]][badge-vuepress-href]
[![chromatic][badge-chromatic-img]][badge-chromatic-href]
The IT4C Boilerplate for frontends
![](src/assets/it4c-logo2-clean-bg_alpha-128x128.png)
## Requirements & Technology
To be able to build this project you need `nodejs`, `npm` and optional `docker` and `jq`.
The project uses `vite` as builder, `vike` to do the SSR. The design framework is `vuetify` which requires the frontend framework `vue3`. For localization `vue-i18n` is used; Session storage is handled with `pinia`.
Testing is done with `vitest` and code style is enforced with `eslint`, `remark-cli` and `stylelint`.
This projects utilizes `storybook` and `chromatic` to develop, document & test frontend components and `vuepress` for static documentation generation.
## Commands
The following commands are available:
| Command | Description |
|-----------------------------|--------------------------------------------------|
| `npm install` | Project setup |
| `npm run build` | Compiles and minifies for production |
| `npm run server:prod` | Runs productions server |
| **Develop** | |
| `npm run dev` | Compiles and hot-reloads for development |
| `npm run server:dev` | Run development server |
| `npm run server:prod:ts` | Run production server without build (ts-node) |
| `npm run server:build` | Build Server into an executable cjs file |
| **Test** | |
| `npm run test:lint` | Run all linters |
| `npm run test:lint:eslint` | Run linter eslint |
| `npm run test:lint:locales` | Run linter locales |
| `npm run test:lint:remark` | Run linter remark |
| `npm run test:lint:style` | Run linter stylelint |
| `npm run test:unit` | Run all unit tests and generate coverage report |
| `npm run test:unit:update` | Run unit tests, coverage and update snapshots |
| `npm run test:unit:dev` | Run all unit tests in watch mode |
| `npm test` | Run all tests & linters |
| **Storybook** | |
| `npm run storybook` | Run Storybook |
| `npm run storybook:build` | Build static storybook |
| `npm run storybook:test` | Run tests against all storybook stories |
| **Documentation** | |
| `npm run docs:dev` | Run Documentation in development mode |
| `npm run docs:build` | Build static documentation |
| **Chromatic** | |
| `npm run chromatic` | Run Chromatic. See Chromatic section for details |
| **Maintenance** | |
| `npm run update` | Check for updates |
### Docker
Docker can be run in development mode utilizing `docker-compose.overwrite.yml`:
```bash
docker compose up
```
Docker can be run in production mode:
```bash
docker compose -f docker-compose.yml up
```
### Chromatic
In order to use the chromatic workflow you need to provide a `CHROMATIC_PROJECT_TOKEN` in the repository secrets.
If you want to run chromatic from the command line you either have to provide this variable as well
```bash
export CHROMATIC_PROJECT_TOKEN=...
npm run chromatic
```
or you have to append it via parameter:
```bash
npm run chromatic -- --project-token=...
```
### Update
You can get a list of packes to update by running `npm run update`.
Appending `-u ` will also update the packages in the `package.json`. You have to run `npm install` again after.
```bash
npm run update -- -u
npm install
```
## Endpoints
The following endpoints are provided given the right command is executed or all three if `docker compose` is used:
| Endpoint | Description |
|------------------------------------------------|---------------|
| [http://localhost:3000](http://localhost:3000) | Web |
| [http://localhost:6006](http://localhost:6006) | Storybook |
| [http://localhost:8080](http://localhost:8080) | Documentation |
## How to use as part of a project
If you want to use this as part of a larger project, e.g. in conjunction with a backend also utilizing a boilerplate you cannot use the template mechanic provided by github for this repository.
You can use the following commands to include the whole git history of the boilerplate and be able to update according to changes to this repo using another remote.
```bash
git remote add xxx_boilerplate_frontend git@github.com:IT4Change/boilerplate-frontend.git
git fetch xxx_boilerplate_frontend
git merge -s ours --no-commit --allow-unrelated-histories xxx_boilerplate_frontend/master
git read-tree --prefix=xxx/ -u xxx_boilerplate_frontend/master
git commit -m "Imported boilerplate_frontend as a subtree under xxx/."
```
To update the subtree you can use
```bash
git subtree pull -P xxx/ xxx_boilerplate_frontend master
git commit -m "Updated boilerplate_frontend in subtree under xxx/."
```
Where `xxx` refers to the folder and product part you want to use the boilerplate in. This assumes that you might need several copies of the frontend boilerplate for you product.
This mechanic was taken from this [source](https://stackoverflow.com/questions/1683531/how-to-import-existing-git-repository-into-another/8396318#8396318)
## Known Problems
- [ ] [Image flicker](https://github.com/vuetifyjs/vuetify/issues/18772)
- [ ] [Black Buttons](https://github.com/vuetifyjs/vuetify/issues/18773)
## License
[Apache 2.0](./LICENSE)
<!-- Badges -->
[badge-nodejs-img]: https://img.shields.io/badge/nodejs-%3E%3D20.5.0-blue
[badge-nodejs-href]: https://nodejs.org/
[badge-npm-img]: https://img.shields.io/badge/npm-latest-blue
[badge-npm-href]: https://www.npmjs.com/package/npm
[badge-docker-img]: https://img.shields.io/badge/docker-latest-blue
[badge-docker-href]: https://www.docker.com/
[badge-jq-img]: https://img.shields.io/badge/jq-latest-blue
[badge-jq-href]: https://jqlang.github.io/jq/
[badge-vue-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=dependencies.vue&label=vue&color=green
[badge-vue-href]: https://vuejs.org/
[badge-vike-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=dependencies.vike&label=vike&color=green
[badge-vike-href]: https://vike.dev/
[badge-vuetify-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=dependencies.vuetify&label=vuetify&color=green
[badge-vuetify-href]: https://vuetifyjs.com/
[badge-pinia-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=dependencies.pinia&label=pinia&color=green
[badge-pinia-href]: https://pinia.vuejs.org/
[badge-vue-i18n-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=dependencies%5B%27vue-i18n%27%5D&label=vue-i18n&color=green
[badge-vue-i18n-href]: https://vue-i18n.intlify.dev/
[badge-eslint-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=devDependencies.eslint&label=eslint&color=yellow
[badge-eslint-href]: https://eslint.org/
[badge-remark-cli-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=devDependencies%5B%27remark-cli%27%5D&label=remark-cli&color=yellow
[badge-remark-cli-href]: https://remark.js.org/
[badge-stylelint-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=devDependencies.stylelint&label=stylelint&color=yellow
[badge-stylelint-href]: https://stylelint.io/
[badge-vitest-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=devDependencies.vitest&label=vitest&color=yellow
[badge-vitest-href]: https://vitest.dev/
[badge-storybook-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=devDependencies.storybook&label=storybook&color=orange
[badge-storybook-href]: https://storybook.js.org/
[badge-vuepress-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=devDependencies.vuepress&label=vuepress&color=orange
[badge-vuepress-href]: https://vuepress.vuejs.org/
[badge-chromatic-img]: https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2FIT4Change%2Fboilerplate-frontend%2Fmaster%2Fpackage.json&query=devDependencies.chromatic&label=chromatic&color=orange
[badge-chromatic-href]: https://www.chromatic.com/

View File

@ -0,0 +1,64 @@
version: '3.4'
services:
# ######################################################
# FRONTEND #############################################
# ######################################################
frontend:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: it4c/frontend:local-development
build:
target: development
environment:
- NODE_ENV="development"
# - DEBUG=true
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- frontend_node_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./:/app
# ######################################################
# STORYBOOK ############################################
# ######################################################
storybook:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: it4c/frontend:local-storybook
build:
target: storybook
environment:
- NODE_ENV="development"
# - DEBUG=true
ports:
- 6006:6006
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- storybook_node_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./:/app
# ######################################################
# DOCUMENTATION ########################################
# ######################################################
documentation:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: it4c/frontend:local-documentation
build:
target: documentation
environment:
- NODE_ENV="development"
# - DEBUG=true
ports:
- 8080:8080
volumes:
# This makes sure the docker container has its own node modules.
# Therefore it is possible to have a different node version on the host machine
- documentation_node_modules:/app/node_modules
# bind the local folder to the docker to allow live reload
- ./:/app
volumes:
frontend_node_modules:
storybook_node_modules:
documentation_node_modules:

View File

@ -0,0 +1,33 @@
# This file defines the production settings. It is overwritten by docker-compose.override.yml,
# which defines the development settings. The override.yml is loaded by default. Therefore it
# is required to explicitly define if you want an production build:
# > docker-compose -f docker-compose.yml up
version: '3.4'
services:
frontend:
# name the image so that it cannot be found in a DockerHub repository, otherwise it will not be built locally from the 'dockerfile' but pulled from there
image: it4c/frontend:local-production
build:
context: .
target: production
networks:
- external-net
- internal-net
ports:
- 3000:3000
environment:
# Envs used in Dockerfile
# - DOCKER_WORKDIR="/app"
# - PORT=3000
# - BUILD_DATE="1970-01-01T00:00:00.00Z"
# - BUILD_VERSION="0.0.0.0"
# - BUILD_COMMIT="0000000"
- NODE_ENV="production"
# env_file:
# - ./.env
# - ./frontend/.env
networks:
external-net:
internal-net:
internal: true

31621
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

156
frontend/package.json Normal file
View File

@ -0,0 +1,156 @@
{
"name": "ocelot-social-frontend",
"version": "3.2.0",
"description": "ocelot.social new Frontend (in development and not fully implemented) by IT4C Boilerplate for frontends",
"main": "build/index.js",
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/IT4Change/boilerplate-frontend.git"
},
"keywords": [
"nodejs",
"npm",
"docker",
"jq",
"vue",
"vike",
"vuetify",
"pinia",
"vue-i18n",
"eslint",
"remark-cli",
"stylelint",
"vitest",
"storybook",
"vuepress",
"chromatic"
],
"author": {
"name": "Ulf Gebhardt"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/IT4Change/boilerplate-frontend/issues"
},
"homepage": "https://github.com/IT4Change/boilerplate-frontend#readme",
"scripts": {
"dev": "npm run server:dev",
"prod": "npm run build && npm run server:prod",
"build": "vite build && npm run server:build",
"server": "node --loader ts-node/esm ./server/index.ts",
"server:dev": "npm run server",
"server:prod": "node ./build/index.cjs",
"server:prod:ts": "cross-env NODE_ENV=production npm run server",
"server:build": "tsx scripts/buildServer/buildServer",
"storybook": "storybook dev -p 6006",
"storybook:build": "storybook build -o build/storybook",
"storybook:test": "test-storybook",
"test:lint": "npm run test:lint:eslint && npm run test:lint:remark && npm run test:lint:style && npm run test:lint:locales",
"test:lint:eslint": "eslint --ext .vue,.ts,.tsx,.js,.jsx,.cjs,.mjs,.json,.yml,.yaml --max-warnings 0 .",
"test:lint:locales": "scripts/locales/locales.sh src/locales",
"test:lint:remark": "remark . --quiet --frail",
"test:lint:style": "stylelint --max-warnings 0 --ignore-path .gitignore \"**/*.{css,scss,vue,vuex}\"",
"test:unit": "npm run test:unit:dev -- run --coverage",
"test:unit:update": "npm run test:unit:dev -- run --coverage -u",
"test:unit:dev": "vitest",
"test": "npm run test:lint && npm run test:unit",
"docs:dev": "vuepress dev .",
"docs:build": "vuepress build .",
"chromatic": "npx chromatic --build-script-name storybook:build",
"update": "npx npm-check-updates"
},
"dependencies": {
"@intlify/unplugin-vue-i18n": "^2.0.0",
"@mdi/font": "^7.4.47",
"@types/compression": "^1.7.5",
"@types/express": "^4.17.21",
"@types/node": "^20.11.20",
"@vitejs/plugin-vue": "^5.0.4",
"@vue/compiler-sfc": "^3.4.19",
"@vue/server-renderer": "3.4.19",
"@vuepress/theme-default": "^2.0.0-rc.17",
"compression": "^1.7.4",
"cross-env": "^7.0.3",
"express": "^4.18.2",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"sass": "^1.71.1",
"sass-loader": "^14.1.1",
"sirv": "^2.0.4",
"ts-node": "^10.9.2",
"typescript": "^5.3.3",
"vike": "^0.4.163",
"vite": "^5.1.4",
"vue": "3.4.19",
"vue-i18n": "^9.9.1",
"vuetify": "^3.5.6"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "^4.1.0",
"@intlify/eslint-plugin-vue-i18n": "^2.0.0",
"@storybook/addon-essentials": "^7.6.17",
"@storybook/addon-interactions": "^7.6.17",
"@storybook/addon-links": "^7.6.17",
"@storybook/blocks": "^7.6.17",
"@storybook/test-runner": "^0.16.0",
"@storybook/testing-library": "^0.2.2",
"@storybook/vue3": "^7.6.17",
"@storybook/vue3-vite": "^7.6.17",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"@vitest/coverage-v8": "^1.3.1",
"@vue/test-utils": "^2.4.4",
"@vuepress/bundler-vite": "^2.0.0-rc.8",
"chromatic": "^11.0.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-security": "^2.1.1",
"eslint-plugin-storybook": "^0.8.0",
"eslint-plugin-vitest": "^0.3.22",
"eslint-plugin-vue": "^9.22.0",
"eslint-plugin-vuetify": "^2.1.1",
"eslint-plugin-yml": "^1.12.2",
"happy-dom": "^13.5.0",
"prettier": "^3.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"remark-cli": "^12.0.0",
"remark-gfm": "^4.0.0",
"remark-preset-lint-consistent": "^5.1.2",
"remark-preset-lint-markdown-style-guide": "^5.1.3",
"remark-preset-lint-recommended": "^6.1.3",
"storybook": "^7.6.17",
"stylelint": "^16.2.1",
"stylelint-config-css-modules": "^4.4.0",
"stylelint-config-recess-order": "^4.6.0",
"stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard": "^36.0.0",
"stylelint-config-standard-scss": "^13.0.0",
"tsx": "^4.7.1",
"vite-plugin-checker": "^0.6.4",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-vuetify": "^2.0.1",
"vitest": "^1.3.1",
"vue-tsc": "^1.8.27",
"vuepress": "^2.0.0-rc.8"
},
"imports": {
"#components/*": "./src/components/*",
"#pages/*": "./src/pages/*",
"#assets/*": "./src/assets/*",
"#layouts/*": "./src/layouts/*",
"#stores/*": "./src/stores/*",
"#src/*": "./src/*",
"#plugins/*": "./renderer/plugins/*",
"#context/*": "./renderer/context/*",
"#types/*": "./types/*",
"#root/*": "./*"
}
}

View File

@ -0,0 +1,16 @@
// See https://vike.dev/data-fetching
export default {
clientRouting: true,
prefetchStaticAssets: 'viewport',
passToClient: ['pageProps', /* 'urlPathname', */ 'routeParams'],
meta: {
title: {
// Make the value of `title` available on both the server- and client-side
env: { server: true, client: true },
},
description: {
// Make the value of `description` available only on the server-side
env: { server: true },
},
},
}

View File

@ -0,0 +1,18 @@
import { PageContext } from 'vike/types'
import { createApp } from './app'
import { getTitle } from './utils'
let instance: ReturnType<typeof createApp>
/* async */ function render(pageContext: PageContext) {
if (!instance) {
instance = createApp(pageContext)
instance.app.mount('#app')
} else {
instance.app.changePage(pageContext)
}
document.title = getTitle(pageContext)
}
export default render

Some files were not shown because too many files have changed in this diff Show More