diff --git a/.github/file-filters.yml b/.github/file-filters.yml new file mode 100644 index 000000000..d7f9cb6c0 --- /dev/null +++ b/.github/file-filters.yml @@ -0,0 +1,9 @@ +backend: &backend + - 'backend/**/*' + - 'neo4j/**/*' + +docker: &docker + - 'docker-compose.*' + +webapp: &webapp + - 'webapp/**/*' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ca5e52945..e386b7efa 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -306,4 +306,12 @@ jobs: token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository event-type: trigger-ocelot-build-success repository: 'Ocelot-Social-Community/stage.ocelot.social' + client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "GITHUB_RUN_NUMBER": "${{ env.GITHUB_RUN_NUMBER }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}' + + - name: Repository Dispatch stage.yunite.me + uses: peter-evans/repository-dispatch@v2 + with: + token: ${{ secrets.OCELOT_PUBLISH_EVENT_PAT }} # this token is required to access the other repository + event-type: trigger-ocelot-build-success + repository: 'Yunite-Net/stage.yunite.me' client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "GITHUB_RUN_NUMBER": "${{ env.GITHUB_RUN_NUMBER }}", "VERSION": "${VERSION}", "BUILD_DATE": "${BUILD_DATE}", "BUILD_COMMIT": "${BUILD_COMMIT}", "BUILD_VERSION": "${BUILD_VERSION}"}' \ No newline at end of file diff --git a/.github/workflows/test-backend.yml b/.github/workflows/test-backend.yml new file mode 100644 index 000000000..84d87c770 --- /dev/null +++ b/.github/workflows/test-backend.yml @@ -0,0 +1,120 @@ +name: ocelot.social backend test CI + + +on: [push] + +jobs: + files-changed: + name: Detect File Changes - Backend + runs-on: ubuntu-latest + outputs: + backend: ${{ steps.changes.outputs.backend }} + docker: ${{ steps.changes.outputs.docker }} + steps: + - uses: actions/checkout@v3.3.0 + + - name: Check for frontend file changes + uses: dorny/paths-filter@v2.11.1 + id: changes + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + list-files: shell + + build_test_neo4j: + name: Docker Build Test - Neo4J + if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true' + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Neo4J | Build 'community' image + run: | + docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/ + docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: docker-neo4j-image + path: /tmp/neo4j.tar + + build_test_backend: + name: Docker Build Test - Backend + if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true' + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: backend | Build 'test' image + run: | + docker build --target test -t "ocelotsocialnetwork/backend:test" backend/ + docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: docker-backend-test + path: /tmp/backend.tar + + lint_backend: + name: Lint Backend + if: needs.files-changed.outputs.backend == 'true' + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: backend | Lint + run: cd backend && yarn && yarn run lint + + unit_test_backend: + name: Unit tests - Backend + if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true' + needs: [files-changed, build_test_neo4j, build_test_backend] + runs-on: ubuntu-latest + permissions: + checks: write + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Download Docker Image (Neo4J) + uses: actions/download-artifact@v3 + with: + name: docker-neo4j-image + path: /tmp + + - name: Load Docker Image + run: docker load < /tmp/neo4j.tar + + - name: Download Docker Image (Backend) + uses: actions/download-artifact@v3 + with: + name: docker-backend-test + path: /tmp + + - name: Load Docker Image + run: docker load < /tmp/backend.tar + + - name: backend | copy env files webapp + run: cp webapp/.env.template webapp/.env + - name: backend | copy env files backend + run: cp backend/.env.template backend/.env + + - name: backend | docker-compose + run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps neo4j backend + + - name: backend | Initialize Database + run: docker-compose exec -T backend yarn db:migrate init + + - name: backend | Migrate Database Up + run: docker-compose exec -T backend yarn db:migrate up + + - name: backend | Unit test incl. coverage check + run: docker-compose exec -T backend yarn test diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml new file mode 100644 index 000000000..d76ab129f --- /dev/null +++ b/.github/workflows/test-e2e.yml @@ -0,0 +1,41 @@ +name: ocelot.social end-to-end test CI +on: push + +jobs: + fullstack_tests: + name: Fullstack tests + runs-on: ubuntu-latest + env: + jobs: 8 + strategy: + matrix: + # run copies of the current job in parallel + job: [1, 2, 3, 4, 5, 6, 7, 8] + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: webapp | copy env file + run: cp webapp/.env.template webapp/.env + + - name: backend | copy env file + run: cp backend/.env.template backend/.env + + - name: boot up test system | docker-compose + run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend + + - name: cypress | Fullstack tests + id: e2e-tests + run: | + yarn install + yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} ) + + ########################################################################## + # UPLOAD SCREENSHOTS - IF TESTS FAIL ##################################### + ########################################################################## + - name: Full stack tests | if any test failed, upload screenshots + if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} + uses: actions/upload-artifact@v3 + with: + name: cypress-screenshots + path: cypress/screenshots/ diff --git a/.github/workflows/test-webapp.yml b/.github/workflows/test-webapp.yml new file mode 100644 index 000000000..9ca3023cc --- /dev/null +++ b/.github/workflows/test-webapp.yml @@ -0,0 +1,101 @@ +name: ocelot.social webapp test CI + + +on: [push] + +jobs: + files-changed: + name: Detect File Changes - Webapp + runs-on: ubuntu-latest + outputs: + docker: ${{ steps.changes.outputs.docker }} + webapp: ${{ steps.changes.outputs.webapp }} + steps: + - uses: actions/checkout@v3.3.0 + + - name: Check for frontend file changes + uses: dorny/paths-filter@v2.11.1 + id: changes + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + list-files: shell + + prepare: + name: Prepare + if: needs.files-changed.outputs.webapp + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Check translation files + run: | + scripts/translations/sort.sh + scripts/translations/missing-keys.sh + + build_test_webapp: + name: Docker Build Test - Webapp + if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp + needs: [files-changed, prepare] + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: webapp | Build 'test' image + run: | + docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/ + docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: docker-webapp-test + path: /tmp/webapp.tar + + lint_webapp: + name: Lint Webapp + if: needs.files-changed.outputs.webapp + needs: files-changed + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: webapp | Lint + run: cd webapp && yarn && yarn run lint + + unit_test_webapp: + name: Unit Tests - Webapp + if: needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp + needs: [files-changed, build_test_webapp] + runs-on: ubuntu-latest + permissions: + checks: write + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Download Docker Image (Webapp) + uses: actions/download-artifact@v3 + with: + name: docker-webapp-test + path: /tmp + + - name: Load Docker Image + run: docker load < /tmp/webapp.tar + + - name: backend | copy env files webapp + run: cp webapp/.env.template webapp/.env + + - name: backend | copy env files backend + run: cp backend/.env.template backend/.env + + - name: backend | docker-compose + run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp + + - name: webapp | Unit tests incl. coverage check + run: docker-compose exec -T webapp yarn test + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 1740c09fe..000000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,344 +0,0 @@ -name: ocelot.social test CI - - -on: [push] - -jobs: - ############################################################################## - # JOB: PREPARE ##################################################### - ############################################################################## - prepare: - name: Prepare - runs-on: ubuntu-latest - # needs: [nothing] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # TODO: DO STUFF ??? ##################################################### - ########################################################################## - - name: Check translation files - run: | - scripts/translations/sort.sh - scripts/translations/missing-keys.sh - - ############################################################################## - # JOB: DOCKER BUILD TEST NEO4J ############################################### - ############################################################################## - build_test_neo4j: - name: Docker Build Test - Neo4J - runs-on: ubuntu-latest - needs: [prepare] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # NEO4J ################################################################## - ########################################################################## - - name: Neo4J | Build `community` image - run: | - docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/ - docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: docker-neo4j-image - path: /tmp/neo4j.tar - - ############################################################################## - # JOB: DOCKER BUILD TEST BACKEND ############################################# - ############################################################################## - build_test_backend: - name: Docker Build Test - Backend - runs-on: ubuntu-latest - needs: [prepare] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # BUILD BACKEND DOCKER IMAGE (build) ##################################### - ########################################################################## - - name: backend | Build `test` image - run: | - docker build --target test -t "ocelotsocialnetwork/backend:test" backend/ - docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: docker-backend-test - path: /tmp/backend.tar - - ############################################################################## - # JOB: DOCKER BUILD TEST WEBAPP ############################################## - ############################################################################## - build_test_webapp: - name: Docker Build Test - WebApp - runs-on: ubuntu-latest - needs: [prepare] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # BUILD WEBAPP DOCKER IMAGE (build) ###################################### - ########################################################################## - - name: webapp | Build `test` image - run: | - docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/ - docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: docker-webapp-test - path: /tmp/webapp.tar - - ############################################################################## - # JOB: LINT BACKEND ########################################################## - ############################################################################## - lint_backend: - name: Lint backend - runs-on: ubuntu-latest - needs: [build_test_backend] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGE ################################################## - ########################################################################## - - name: Download Docker Image (Backend) - uses: actions/download-artifact@v3 - with: - name: docker-backend-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/backend.tar - ########################################################################## - # LINT BACKEND ########################################################### - ########################################################################## - - name: backend | Lint - run: docker run --rm ocelotsocialnetwork/backend:test yarn run lint - - ############################################################################## - # JOB: LINT WEBAPP ########################################################### - ############################################################################## - lint_webapp: - name: Lint webapp - runs-on: ubuntu-latest - needs: [build_test_webapp] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGE ################################################## - ########################################################################## - - name: Download Docker Image (Webapp) - uses: actions/download-artifact@v3 - with: - name: docker-webapp-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/webapp.tar - ########################################################################## - # LINT WEBAPP ############################################################ - ########################################################################## - - name: webapp | Lint - run: docker run --rm ocelotsocialnetwork/webapp:test yarn run lint - - ############################################################################## - # JOB: UNIT TEST BACKEND ##################################################### - ############################################################################## - unit_test_backend: - name: Unit tests - backend - runs-on: ubuntu-latest - needs: [build_test_neo4j,build_test_backend] - permissions: - checks: write - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGES ################################################# - ########################################################################## - - name: Download Docker Image (Neo4J) - uses: actions/download-artifact@v3 - with: - name: docker-neo4j-image - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/neo4j.tar - - name: Download Docker Image (Backend) - uses: actions/download-artifact@v3 - with: - name: docker-backend-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/backend.tar - ########################################################################## - # UNIT TESTS BACKEND ##################################################### - ########################################################################## - - name: backend | copy env files webapp - run: cp webapp/.env.template webapp/.env - - name: backend | copy env files backend - run: cp backend/.env.template backend/.env - - name: backend | docker-compose - run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps neo4j backend - - name: backend | Initialize Database - run: docker-compose exec -T backend yarn db:migrate init - - name: backend | Migrate Database Up - run: docker-compose exec -T backend yarn db:migrate up - - name: backend | Unit test - run: docker-compose exec -T backend yarn test - ########################################################################## - # COVERAGE CHECK BACKEND ################################################# - ########################################################################## - - name: backend | Coverage check - uses: webcraftmedia/coverage-check-action@master - with: - report_name: Coverage Backend - type: lcov - result_path: ./coverage/lcov.info - min_coverage: 57 - token: ${{ github.token }} - - ############################################################################## - # JOB: UNIT TEST WEBAPP ###################################################### - ############################################################################## - unit_test_webapp: - name: Unit tests - webapp - runs-on: ubuntu-latest - needs: [build_test_webapp] - permissions: - checks: write - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGES ################################################# - ########################################################################## - - name: Download Docker Image (Webapp) - uses: actions/download-artifact@v3 - with: - name: docker-webapp-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/webapp.tar - ########################################################################## - # UNIT TESTS WEBAPP ###################################################### - ########################################################################## - - name: backend | copy env files webapp - run: cp webapp/.env.template webapp/.env - - name: backend | copy env files backend - run: cp backend/.env.template backend/.env - - name: backend | docker-compose - run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp - - name: webapp | Unit tests - run: docker-compose exec -T webapp yarn test - ########################################################################## - # COVERAGE REPORT FRONTEND ################################################ - ########################################################################## - #- name: frontend | Coverage report - # uses: romeovs/lcov-reporter-action@v0.2.21 - # with: - # github-token: ${{ secrets.GITHUB_TOKEN }} - # lcov-file: ./coverage/lcov.info - ########################################################################## - # COVERAGE CHECK WEBAPP ################################################## - ########################################################################## - - name: webapp | Coverage check - uses: webcraftmedia/coverage-check-action@master - with: - report_name: Coverage Webapp - type: lcov - result_path: ./coverage/lcov.info - min_coverage: 83 - token: ${{ github.token }} - - ############################################################################## - # JOB: FULLSTACK TESTS ####################################################### - ############################################################################## - fullstack_tests: - name: Fullstack tests - runs-on: ubuntu-latest - needs: [build_test_webapp, build_test_backend, build_test_neo4j] - env: - jobs: 8 - strategy: - matrix: - # run copies of the current job in parallel - job: [1, 2, 3, 4, 5, 6, 7, 8] - steps: - ########################################################################## - # CHECKOUT CODE ########################################################## - ########################################################################## - - name: Checkout code - uses: actions/checkout@v3 - ########################################################################## - # DOWNLOAD DOCKER IMAGES ################################################# - ########################################################################## - - name: Download Docker Image (Neo4J) - uses: actions/download-artifact@v3 - with: - name: docker-neo4j-image - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/neo4j.tar - - name: Download Docker Image (Backend) - uses: actions/download-artifact@v3 - with: - name: docker-backend-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/backend.tar - - name: Download Docker Image (Webapp) - uses: actions/download-artifact@v3 - with: - name: docker-webapp-test - path: /tmp - - name: Load Docker Image - run: docker load < /tmp/webapp.tar - ########################################################################## - # FULLSTACK TESTS CYPRESS ################################################ - ########################################################################## - - name: webapp | copy env files webapp - run: cp webapp/.env.template webapp/.env - - name: backend | copy env files backend - run: cp backend/.env.template backend/.env - - name: backend | docker-compose - run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend - - name: cypress | Fullstack tests - id: e2e-tests - run: | - yarn install - yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} ) - ########################################################################## - # UPLOAD SCREENSHOTS - IF TESTS FAIL ##################################### - ########################################################################## - - name: Full stack tests | if any test failed, upload screenshots - if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} - uses: actions/upload-artifact@v3 - with: - name: cypress-screenshots - path: cypress/screenshots/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 361ccb183..7030227c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,49 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [2.6.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.1...2.6.0) + +- fix(other): docker-compose for rebranding deployment [`#6265`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6265) +- feat(webapp): default categories of group for posts in group [`#6259`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6259) +- refactor(webapp): make action radius select in group form a reusable component [`#6244`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6244) +- fix(webapp): show avatar for group members [`#6258`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6258) +- fix(webapp): fix search for 3 chars [`#6256`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6256) +- fix(backend): group posts cannot be pinned [`#6242`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6242) +- Bump metascraper-soundcloud from 5.33.5 to 5.34.2 in /backend [`#6213`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6213) +- refactor(other): refactor test workflows [`#6151`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6151) +- fix(other): deployment fix typo, update stage.ocelot.social reference [`#6230`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6230) +- fix(other): bump metascraper-url from 5.33.5 to 5.34.2 in /backend [`#6217`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6217) +- fix(other): workflow typo [`#6235`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6235) +- feat(other): publish stage.yunite.me hook [`#6234`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6234) +- fix(other): reduce kubernetes memory limits [`#6229`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6229) +- fix(other): deployment for branded image with custom names [`#6228`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6228) +- Bump node from 19.8.1-alpine3.17 to 19.9.0-alpine3.17 in /backend [`#6219`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6219) +- Bump node from 19.8.1-alpine3.17 to 19.9.0-alpine3.17 in /webapp [`#6220`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6220) +- feat(other): deployment pod resources [`#6132`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6132) +- Bump @babel/core from 7.12.17 to 7.21.4 in /webapp [`#6215`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6215) +- Bump jsonwebtoken from 8.5.1 to 9.0.0 in /webapp [`#6079`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6079) +- Bump jest from 29.4.2 to 29.5.0 in /webapp [`#6094`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6094) +- Bump babel-jest from 29.4.2 to 29.5.0 in /webapp [`#6095`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6095) +- Bump neode from 0.4.8 to 0.4.9 in /backend [`#6075`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6075) +- Bump node from 19.4.0-alpine3.17 to 19.8.1-alpine3.17 in /webapp [`#6155`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6155) +- Bump node from 19.4.0-alpine3.17 to 19.8.1-alpine3.17 in /backend [`#6156`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6156) +- Bump @babel/core from 7.9.0 to 7.21.4 [`#6200`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6200) +- Bump @babel/preset-env from 7.12.7 to 7.21.4 [`#6204`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6204) +- Bump expect from 25.3.0 to 29.5.0 [`#6098`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6098) +- separate test workflows [`3533a36`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3533a36cdc811c0e1dae218fbc2184f7c4bc3951) +- get it working [`8df7d5d`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/8df7d5d265b0c5ba16f167a213631d765d2f985e) +- feat(webapp): group categories on posts [`3244f3f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/3244f3f86d1e8c09e0fd49f43c49f0a3aa8b85ab) + #### [2.5.1](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.5.0...2.5.1) +> 23 March 2023 + +- chore(other): release v2.5.1 – fix filter menu width [`#6180`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6180) - feat(webapp): add tooltips to all menu icons [`#6185`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6185) - fix(webapp): popup filter max-width [`#6177`](https://github.com/Ocelot-Social-Community/Ocelot-Social/pull/6177) - Add tooltip to header notifications menu [`28505a5`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/28505a5b181008ebcde6fa58b7a4a8459a492018) - Add tooltip to header avatar menu [`4c0469f`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/4c0469f61a3c2fae23e50c6a5a2a91b63fac149a) -- Add tooltip to locale switch menu [`26b90fc`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/26b90fce4704e537126fd15ad950ea04e14890ba) +- Release v2.5.1 - fix filter menu width [`08def14`](https://github.com/Ocelot-Social-Community/Ocelot-Social/commit/08def14cafef7816d8e43f1896430400bda9635d) #### [2.5.0](https://github.com/Ocelot-Social-Community/Ocelot-Social/compare/2.4.0...2.5.0) diff --git a/backend/Dockerfile b/backend/Dockerfile index c04cd9bc9..cd9bcdd3c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,7 +1,7 @@ ################################################################################## # BASE (Is pushed to DockerHub for rebranding) ################################### ################################################################################## -FROM node:19.4.0-alpine3.17 as base +FROM node:19.9.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame diff --git a/backend/jest.config.js b/backend/jest.config.js index aabb59083..0f8017fb1 100644 --- a/backend/jest.config.js +++ b/backend/jest.config.js @@ -8,7 +8,11 @@ module.exports = { '!**/dist/**', '!**/src/**/?(*.)+(spec|test).js?(x)' ], - coverageReporters: ['lcov', 'text'], + coverageThreshold: { + global: { + lines: 57, + }, + }, testMatch: ['**/src/**/?(*.)+(spec|test).js?(x)'], setupFilesAfterEnv: ['/test/setup.js'] } diff --git a/backend/package.json b/backend/package.json index 0b6e6beb7..27c6fb4fc 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social-backend", - "version": "2.5.1", + "version": "2.6.0", "description": "GraphQL Backend for ocelot.social", "repository": "https://github.com/Ocelot-Social-Community/Ocelot-Social", "author": "ocelot.social Community", @@ -58,7 +58,7 @@ "graphql-redis-subscriptions": "^2.2.1", "graphql-shield": "~7.2.2", "graphql-tag": "~2.10.3", - "helmet": "~3.22.0", + "helmet": "~7.0.0", "ioredis": "^4.16.1", "jsonwebtoken": "~8.5.1", "languagedetect": "^2.0.0", @@ -76,9 +76,9 @@ "metascraper-lang-detector": "^4.10.2", "metascraper-logo": "^5.33.5", "metascraper-publisher": "^5.33.5", - "metascraper-soundcloud": "^5.33.5", + "metascraper-soundcloud": "^5.34.2", "metascraper-title": "^5.33.5", - "metascraper-url": "^5.33.5", + "metascraper-url": "^5.34.2", "metascraper-video": "^5.33.5", "metascraper-youtube": "^5.33.5", "migrate": "^1.7.0", @@ -87,7 +87,7 @@ "mustache": "^4.2.0", "neo4j-driver": "^4.0.2", "neo4j-graphql-js": "^2.11.5", - "neode": "^0.4.8", + "neode": "^0.4.9", "node-fetch": "~2.6.1", "nodemailer": "^6.4.4", "nodemailer-html-to-text": "^3.2.0", diff --git a/backend/src/graphql/posts.js b/backend/src/graphql/posts.js index f1b62a286..d1dc3ee45 100644 --- a/backend/src/graphql/posts.js +++ b/backend/src/graphql/posts.js @@ -38,8 +38,10 @@ export const createPostMutation = () => { id } eventStart + eventEnd eventLocationName eventVenue + eventIsOnline eventLocation { lng lat @@ -70,6 +72,7 @@ export const filterPosts = () => { id title content + eventStart } } ` diff --git a/backend/src/schema/resolvers/embeds.spec.js b/backend/src/schema/resolvers/embeds.spec.js index 0f0d41357..b22927d1b 100644 --- a/backend/src/schema/resolvers/embeds.spec.js +++ b/backend/src/schema/resolvers/embeds.spec.js @@ -126,7 +126,7 @@ describe('Query', () => { author: null, date: expect.any(String), description: - 'Human Connection, Weilheim an der Teck. Gefällt 24.407 Mal. An upcoming non-profit social network focused on local and global positive change. Twitter accounts : @hc_world (EN), @hc_deutschland (GE),...', + 'Human Connection, Weilheim an der Teck. Gefällt 24.407 Mal. An upcoming non-profit social network focused on local and global positive change. Twitter accounts : @hc_world (EN), @hc_deutschland (GE),…', html: null, image: 'https://scontent.ftxl3-1.fna.fbcdn.net/v/t1.0-1/c5.0.200.200a/p200x200/12108307_997373093648222_70057205881020137_n.jpg?_nc_cat=110&_nc_oc=AQnPPYQlR0dU556gOfl4xkXr7IPZdRIAUfQeXl3fpUv4DAsFN8T4PfgOjPwuq85GPKGZ5S5E5mWQ8IVV1UiRBAIZ&_nc_ht=scontent.ftxl3-1.fna&oh=90309adddaab38839782f16e7d4b7bcf&oe=5DEEDFE5', @@ -196,7 +196,7 @@ Have all the information for the brand in separate config files. Set these defau publisher: 'YouTube', date: expect.any(String), description: - 'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al...', + 'She’s incapable of controlling her limbs when her kitty is around. The obsession grows every day. Ps. That’s a sleep sack she’s in. Not a starfish outfit. Al…', url: 'https://www.youtube.com/watch?v=qkdXAtO40Fo', image: 'https://i.ytimg.com/vi/qkdXAtO40Fo/maxresdefault.jpg', audio: null, diff --git a/backend/src/schema/resolvers/filter-posts.spec.js b/backend/src/schema/resolvers/filter-posts.spec.js new file mode 100644 index 000000000..0b96e001f --- /dev/null +++ b/backend/src/schema/resolvers/filter-posts.spec.js @@ -0,0 +1,230 @@ +import { createTestClient } from 'apollo-server-testing' +import Factory, { cleanDatabase } from '../../db/factories' +import { getNeode, getDriver } from '../../db/neo4j' +import createServer from '../../server' +import CONFIG from '../../config' +import { filterPosts, createPostMutation } from '../../graphql/posts' + +CONFIG.CATEGORIES_ACTIVE = false + +const driver = getDriver() +const neode = getNeode() + +let query +let mutate +let authenticatedUser +let user + +beforeAll(async () => { + await cleanDatabase() + + const { server } = createServer({ + context: () => { + return { + driver, + neode, + user: authenticatedUser, + } + }, + }) + query = createTestClient(server).query + mutate = createTestClient(server).mutate +}) + +afterAll(async () => { + await cleanDatabase() + driver.close() +}) + +describe('Filter Posts', () => { + const now = new Date() + + beforeAll(async () => { + user = await Factory.build('user', { + id: 'user', + name: 'User', + about: 'I am a user.', + }) + authenticatedUser = await user.toJson() + await mutate({ + mutation: createPostMutation(), + variables: { + id: 'a1', + title: 'I am an article', + content: 'I am an article written by user.', + }, + }) + await mutate({ + mutation: createPostMutation(), + variables: { + id: 'a2', + title: 'I am anonther article', + content: 'I am another article written by user.', + }, + }) + await mutate({ + mutation: createPostMutation(), + variables: { + id: 'e1', + title: 'Illegaler Kindergeburtstag', + content: 'Elli wird fünf. Wir feiern ihren Geburtstag.', + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventVenue: 'Garten der Familie Maier', + }, + }, + }) + await mutate({ + mutation: createPostMutation(), + variables: { + id: 'e2', + title: 'Räuber-Treffen', + content: 'Planung der nächsten Räuberereien', + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(), + eventVenue: 'Wirtshaus im Spessart', + }, + }, + }) + }) + + describe('no filters set', () => { + it('finds all posts', async () => { + const { + data: { Post: result }, + } = await query({ query: filterPosts() }) + expect(result).toHaveLength(4) + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: 'a1' }), + expect.objectContaining({ id: 'a2' }), + expect.objectContaining({ id: 'e1' }), + expect.objectContaining({ id: 'e2' }), + ]), + ) + }) + }) + + describe('post type filter set to ["Article"]', () => { + it('finds the articles', async () => { + const { + data: { Post: result }, + } = await query({ query: filterPosts(), variables: { filter: { postType_in: ['Article'] } } }) + expect(result).toHaveLength(2) + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: 'a1' }), + expect.objectContaining({ id: 'a2' }), + ]), + ) + }) + }) + + describe('post type filter set to ["Event"]', () => { + it('finds the articles', async () => { + const { + data: { Post: result }, + } = await query({ query: filterPosts(), variables: { filter: { postType_in: ['Event'] } } }) + expect(result).toHaveLength(2) + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: 'e1' }), + expect.objectContaining({ id: 'e2' }), + ]), + ) + }) + }) + + describe('post type filter set to ["Article", "Event"]', () => { + it('finds all posts', async () => { + const { + data: { Post: result }, + } = await query({ + query: filterPosts(), + variables: { filter: { postType_in: ['Article', 'Event'] } }, + }) + expect(result).toHaveLength(4) + expect(result).toEqual( + expect.arrayContaining([ + expect.objectContaining({ id: 'a1' }), + expect.objectContaining({ id: 'a2' }), + expect.objectContaining({ id: 'e1' }), + expect.objectContaining({ id: 'e2' }), + ]), + ) + }) + }) + + describe('order events by event start descending', () => { + it('finds the events orderd accordingly', async () => { + const { + data: { Post: result }, + } = await query({ + query: filterPosts(), + variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_desc'] }, + }) + expect(result).toHaveLength(2) + expect(result).toEqual([ + expect.objectContaining({ + id: 'e1', + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }), + expect.objectContaining({ + id: 'e2', + eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(), + }), + ]) + }) + }) + + describe('order events by event start ascending', () => { + it('finds the events orderd accordingly', async () => { + const { + data: { Post: result }, + } = await query({ + query: filterPosts(), + variables: { filter: { postType_in: ['Event'] }, orderBy: ['eventStart_asc'] }, + }) + expect(result).toHaveLength(2) + expect(result).toEqual([ + expect.objectContaining({ + id: 'e2', + eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(), + }), + expect.objectContaining({ + id: 'e1', + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }), + ]) + }) + }) + + describe('filter events by event start date', () => { + it('finds only events after given date', async () => { + const { + data: { Post: result }, + } = await query({ + query: filterPosts(), + variables: { + filter: { + postType_in: ['Event'], + eventStart_gte: new Date( + now.getFullYear(), + now.getMonth(), + now.getDate() + 2, + ).toISOString(), + }, + }, + }) + expect(result).toHaveLength(1) + expect(result).toEqual([ + expect.objectContaining({ + id: 'e1', + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }), + ]) + }) + }) +}) diff --git a/backend/src/schema/resolvers/helpers/events.js b/backend/src/schema/resolvers/helpers/events.js index b2f204f1d..84e64299d 100644 --- a/backend/src/schema/resolvers/helpers/events.js +++ b/backend/src/schema/resolvers/helpers/events.js @@ -5,22 +5,25 @@ export const validateEventParams = (params) => { const { eventInput } = params validateEventDate(eventInput.eventStart) params.eventStart = eventInput.eventStart - if (eventInput.eventLocation && !eventInput.eventVenue) { + if (eventInput.eventEnd) { + validateEventEnd(eventInput.eventStart, eventInput.eventEnd) + params.eventEnd = eventInput.eventEnd + } + if (eventInput.eventLocationName && !eventInput.eventVenue) { throw new UserInputError('Event venue must be present if event location is given!') } params.eventVenue = eventInput.eventVenue - params.eventLocation = eventInput.eventLocation + params.eventLocationName = eventInput.eventLocationName + params.eventIsOnline = !!eventInput.eventIsOnline } delete params.eventInput let locationName - if (params.eventLocation) { - params.eventLocationName = params.eventLocation - locationName = params.eventLocation + if (params.eventLocationName) { + locationName = params.eventLocationName } else { params.eventLocationName = null locationName = null } - delete params.eventLocation return locationName } @@ -33,3 +36,12 @@ const validateEventDate = (dateString) => { throw new UserInputError('Event start date must be in the future!') } } + +const validateEventEnd = (start, end) => { + const endDate = new Date(end) + if (endDate.toString() === 'Invalid Date') + throw new UserInputError('Event end date must be a valid date!') + const startDate = new Date(start) + if (endDate < startDate) + throw new UserInputError('Event end date must be a after event start date!') +} diff --git a/backend/src/schema/resolvers/notifications.js b/backend/src/schema/resolvers/notifications.js index 117b9b530..c3b882146 100644 --- a/backend/src/schema/resolvers/notifications.js +++ b/backend/src/schema/resolvers/notifications.js @@ -51,7 +51,7 @@ export default { OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(relatedUser) WITH user, notification, resource, membership, relatedUser, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author)} ] AS posts + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post {.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts WITH resource, user, notification, authors, posts, relatedUser, membership, resource {.*, __typename: labels(resource)[0], @@ -90,7 +90,7 @@ export default { SET notification.read = TRUE WITH user, notification, resource, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(user) WITH resource, user, notification, authors, posts, membership, resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], myRole: membership.role } AS finalResource @@ -120,7 +120,7 @@ export default { SET notification.read = TRUE WITH user, notification, resource, [(resource)<-[:WROTE]-(author:User) | author {.*}] AS authors, - [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author)} ] AS posts + [(resource)-[:COMMENTS]->(post:Post)<-[:WROTE]-(author:User) | post{.*, author: properties(author), postType: filter(l IN labels(post) WHERE NOT l = "Post")} ] AS posts OPTIONAL MATCH (resource)<-[membership:MEMBER_OF]-(user) WITH resource, user, notification, authors, posts, membership, resource {.*, __typename: labels(resource)[0], author: authors[0], post: posts[0], myRole: membership.role} AS finalResource diff --git a/backend/src/schema/resolvers/posts.js b/backend/src/schema/resolvers/posts.js index 42a755e8f..c7d2eebdb 100644 --- a/backend/src/schema/resolvers/posts.js +++ b/backend/src/schema/resolvers/posts.js @@ -334,6 +334,7 @@ export default { ` MATCH (user:User {id: $userId}) WHERE user.role = 'admin' MATCH (post:Post {id: $params.id}) + WHERE NOT((post)-[:IN]->(:Group)) MERGE (user)-[pinned:PINNED {createdAt: toString(datetime())}]->(post) SET post.pinned = true RETURN post, pinned.createdAt as pinnedAt @@ -346,10 +347,12 @@ export default { })) }) const [transactionResult] = await writeTxResultPromise - const { pinnedPost, pinnedAt } = transactionResult - pinnedPostWithNestedAttributes = { - ...pinnedPost, - pinnedAt, + if (transactionResult) { + const { pinnedPost, pinnedAt } = transactionResult + pinnedPostWithNestedAttributes = { + ...pinnedPost, + pinnedAt, + } } } finally { session.close() @@ -416,6 +419,8 @@ export default { 'eventLocation', 'eventLocationName', 'eventStart', + 'eventEnd', + 'eventIsOnline', ], hasMany: { tags: '-[:TAGGED]->(related:Tag)', diff --git a/backend/src/schema/resolvers/posts.spec.js b/backend/src/schema/resolvers/posts.spec.js index b3dd28f38..87d09e262 100644 --- a/backend/src/schema/resolvers/posts.spec.js +++ b/backend/src/schema/resolvers/posts.spec.js @@ -398,7 +398,7 @@ describe('CreatePost', () => { }) }) - describe('event location is given but event venue is missing', () => { + describe('with valid start date and invalid end date', () => { it('throws an error', async () => { const now = new Date() await expect( @@ -409,7 +409,114 @@ describe('CreatePost', () => { postType: 'Event', eventInput: { eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), - eventLocation: 'Berlin', + eventEnd: 'not-valid', + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event end date must be a valid date!', + }, + ], + }) + }) + }) + + describe('with valid start date and end date before start date', () => { + it('throws an error', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(), + eventEnd: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + }, + }, + }), + ).resolves.toMatchObject({ + errors: [ + { + message: 'Event end date must be a after event start date!', + }, + ], + }) + }) + }) + + describe('with valid start date and valid end date', () => { + it('creates the event', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventEnd: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(), + }, + }, + }), + ).resolves.toMatchObject({ + data: { + CreatePost: { + postType: ['Event'], + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventEnd: new Date(now.getFullYear(), now.getMonth() + 2).toISOString(), + eventIsOnline: false, + }, + }, + errors: undefined, + }) + }) + }) + + describe('with valid start date and event is online', () => { + it('creates the event', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventIsOnline: true, + }, + }, + }), + ).resolves.toMatchObject({ + data: { + CreatePost: { + postType: ['Event'], + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventIsOnline: true, + }, + }, + errors: undefined, + }) + }) + }) + + describe('event location name is given but event venue is missing', () => { + it('throws an error', async () => { + const now = new Date() + await expect( + mutate({ + mutation: createPostMutation(), + variables: { + ...variables, + postType: 'Event', + eventInput: { + eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventLocationName: 'Berlin', }, }, }), @@ -442,6 +549,7 @@ describe('CreatePost', () => { CreatePost: { postType: ['Event'], eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), + eventIsOnline: false, }, }, errors: undefined, @@ -449,7 +557,7 @@ describe('CreatePost', () => { }) }) - describe('valid event input with location', () => { + describe('valid event input with location name', () => { it('has label "Event" set', async () => { const now = new Date() await expect( @@ -460,7 +568,7 @@ describe('CreatePost', () => { postType: 'Event', eventInput: { eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), - eventLocation: 'Leipzig', + eventLocationName: 'Leipzig', eventVenue: 'Connewitzer Kreuz', }, }, @@ -713,7 +821,7 @@ describe('UpdatePost', () => { }) }) - describe('event location is given but event venue is missing', () => { + describe('event location name is given but event venue is missing', () => { it('throws an error', async () => { const now = new Date() await expect( @@ -724,7 +832,7 @@ describe('UpdatePost', () => { postType: 'Event', eventInput: { eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), - eventLocation: 'Berlin', + eventLocationName: 'Berlin', }, }, }), @@ -738,7 +846,7 @@ describe('UpdatePost', () => { }) }) - describe('valid event input without location', () => { + describe('valid event input without location name', () => { it('has label "Event" set', async () => { const now = new Date() await expect( @@ -764,7 +872,7 @@ describe('UpdatePost', () => { }) }) - describe('valid event input with location', () => { + describe('valid event input with location name', () => { it('has label "Event" set', async () => { const now = new Date() await expect( @@ -775,7 +883,7 @@ describe('UpdatePost', () => { postType: 'Event', eventInput: { eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(), - eventLocation: 'Leipzig', + eventLocationName: 'Leipzig', eventVenue: 'Connewitzer Kreuz', }, }, diff --git a/backend/src/schema/resolvers/postsInGroups.spec.js b/backend/src/schema/resolvers/postsInGroups.spec.js index 86a278207..ba9041090 100644 --- a/backend/src/schema/resolvers/postsInGroups.spec.js +++ b/backend/src/schema/resolvers/postsInGroups.spec.js @@ -818,11 +818,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -846,11 +848,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -874,11 +878,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -902,11 +908,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -930,21 +938,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1319,16 +1331,19 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, ]), }, @@ -1361,21 +1376,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1410,16 +1429,19 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1452,11 +1474,13 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, ]), }, @@ -1489,21 +1513,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1534,21 +1562,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1579,21 +1611,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1628,21 +1664,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1675,21 +1715,25 @@ describe('Posts in Groups', () => { id: 'post-to-public-group', title: 'A post to a public group', content: 'I am posting into a public group as a member of the group', + eventStart: null, }, { id: 'post-without-group', title: 'A post without a group', content: 'I am a user who does not belong to a group yet.', + eventStart: null, }, { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, @@ -1739,11 +1783,13 @@ describe('Posts in Groups', () => { id: 'post-to-closed-group', title: 'A post to a closed group', content: 'I am posting into a closed group as a member of the group', + eventStart: null, }, { id: 'post-to-hidden-group', title: 'A post to a hidden group', content: 'I am posting into a hidden group as a member of the group', + eventStart: null, }, ]), }, diff --git a/backend/src/schema/resolvers/searches.js b/backend/src/schema/resolvers/searches.js index 3fdf22da3..a67abe90d 100644 --- a/backend/src/schema/resolvers/searches.js +++ b/backend/src/schema/resolvers/searches.js @@ -223,8 +223,7 @@ export default { }, searchResults: async (_parent, args, context, _resolveInfo) => { const { query, limit } = args - let userId = null - if (context.user) userId = context.user.id + const userId = context.user?.id || null const searchType = query.replace(/^([!@#&]?).*$/, '$1') const searchString = query.replace(/^([!@#&])/, '') diff --git a/backend/src/schema/resolvers/searches/queryString.js b/backend/src/schema/resolvers/searches/queryString.js index 5ef84cdce..8f415c5e6 100644 --- a/backend/src/schema/resolvers/searches/queryString.js +++ b/backend/src/schema/resolvers/searches/queryString.js @@ -33,7 +33,7 @@ const matchSomeWordsExactly = (str, boost = 2) => { const matchBeginningOfWords = (str) => { return str .split(' ') - .filter((s) => s.length > 3) + .filter((s) => s.length >= 2) .map((s) => s + '*') .join(' ') } diff --git a/backend/src/schema/resolvers/searches/queryString.spec.js b/backend/src/schema/resolvers/searches/queryString.spec.js index 23a746be1..fe3c91d3c 100644 --- a/backend/src/schema/resolvers/searches/queryString.spec.js +++ b/backend/src/schema/resolvers/searches/queryString.spec.js @@ -37,7 +37,7 @@ describe('queryString', () => { describe('globbing for longer words', () => { it('globs words with more than three characters', () => { - expect(queryString('a couple of words')).toContain('couple* words*') + expect(queryString('a couple of words')).toContain('couple* of* words*') }) }) }) diff --git a/backend/src/schema/resolvers/users/location.js b/backend/src/schema/resolvers/users/location.js index 9d8a11f89..54d73560b 100644 --- a/backend/src/schema/resolvers/users/location.js +++ b/backend/src/schema/resolvers/users/location.js @@ -22,7 +22,7 @@ const locales = ['en', 'de', 'fr', 'nl', 'it', 'es', 'pt', 'pl', 'ru'] const createLocation = async (session, mapboxData) => { const data = { - id: mapboxData.id, + id: mapboxData.id + (mapboxData.address ? `-${mapboxData.address}` : ''), nameEN: mapboxData.text_en, nameDE: mapboxData.text_de, nameFR: mapboxData.text_fr, @@ -33,6 +33,7 @@ const createLocation = async (session, mapboxData) => { namePL: mapboxData.text_pl, nameRU: mapboxData.text_ru, type: mapboxData.id.split('.')[0].toLowerCase(), + address: mapboxData.address, lng: mapboxData.center && mapboxData.center.length ? mapboxData.center[0] : null, lat: mapboxData.center && mapboxData.center.length ? mapboxData.center[1] : null, } @@ -54,6 +55,10 @@ const createLocation = async (session, mapboxData) => { if (data.lat && data.lng) { mutation += ', l.lat = $lat, l.lng = $lng' } + if (data.address) { + mutation += ', l.address = $address' + } + mutation += ' RETURN l.id' await session.writeTransaction((transaction) => { @@ -72,7 +77,7 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s locationName, )}.json?access_token=${ CONFIG.MAPBOX_TOKEN - }&types=region,place,country&language=${locales.join(',')}`, + }&types=region,place,country,address&language=${locales.join(',')}`, ) debug(res) @@ -103,6 +108,10 @@ export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, s let parent = data + if (parent.address) { + parent.id += `-${parent.address}` + } + if (data.context) { await asyncForEach(data.context, async (ctx) => { await createLocation(session, ctx) diff --git a/backend/src/schema/types/type/Post.gql b/backend/src/schema/types/type/Post.gql index c35ee7054..5a5d57b9a 100644 --- a/backend/src/schema/types/type/Post.gql +++ b/backend/src/schema/types/type/Post.gql @@ -83,6 +83,8 @@ input _PostFilter { emotions_every: _PostEMOTEDFilter group: _GroupFilter postsInMyGroups: Boolean + postType_in: [PostType] + eventStart_gte: String } enum _PostOrdering { @@ -104,6 +106,8 @@ enum _PostOrdering { language_desc pinned_asc pinned_desc + eventStart_asc + eventStart_desc } @@ -179,6 +183,8 @@ type Post { eventLocation: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l") eventVenue: String eventStart: String + eventEnd: String + eventIsOnline: Boolean } input _PostInput { @@ -187,8 +193,10 @@ input _PostInput { input _EventInput { eventStart: String! - eventLocation: String + eventEnd: String eventVenue: String + eventLocationName: String + eventIsOnline: Boolean } type Mutation { diff --git a/backend/src/server.js b/backend/src/server.js index bcbd84617..d0b205035 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -82,7 +82,13 @@ const createServer = (options) => { const app = express() app.set('driver', driver) - app.use(helmet()) + // TODO: this exception is required for the graphql playground, since the playground loads external resources + // See: https://github.com/graphql/graphql-playground/issues/1283 + app.use( + helmet( + (CONFIG.DEBUG && { contentSecurityPolicy: false, crossOriginEmbedderPolicy: false }) || {}, + ), + ) app.use('/.well-known/', webfinger()) app.use(express.static('public')) app.use(bodyParser.json({ limit: '10mb' })) diff --git a/backend/yarn.lock b/backend/yarn.lock index c2fb0d28c..18887b92a 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -1516,13 +1516,13 @@ url-regex "~4.1.1" video-extensions "~1.1.0" -"@metascraper/helpers@^5.33.5": - version "5.33.5" - resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-5.33.5.tgz#f980b41b3b7d7e67e11f849664727ef9d4802740" - integrity sha512-gcULKpM00CNxlf7iWRTi4hQQIXWQUjeFal0V5U60C4P4YyfLXfjuQVBk6mmKSYENSRh7oBQhAR+YVnMalVWBcw== +"@metascraper/helpers@^5.33.5", "@metascraper/helpers@^5.34.2": + version "5.34.2" + resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-5.34.2.tgz#3c6ef10c1ab7e8b09b67219c91c7b8d30fedd0c1" + integrity sha512-7mlQ1uYCUGw5OZU52leHbbjO8UrmmTvLCt6p4E4yWAvEW1oi9t7Pq1AmizX4hNUW+FgMvXCcv4t5BCfxiY8LhA== dependencies: audio-extensions "0.0.0" - chrono-node "~2.5.0" + chrono-node "~2.6.2" condense-whitespace "~2.0.0" entities "~4.4.0" file-extension "~4.0.5" @@ -1532,7 +1532,7 @@ is-uri "~1.2.4" iso-639-3 "~2.2.0" isostring "0.0.1" - jsdom "~21.1.0" + jsdom "~21.1.1" lodash "~4.17.21" memoize-one "~6.0.0" microsoft-capitalize "~1.0.5" @@ -1540,7 +1540,7 @@ normalize-url "~6.1.0" re2 "~1.18.0" smartquotes "~2.3.2" - tldts "~5.7.103" + tldts "~6.0.1" url-regex-safe "~3.0.0" video-extensions "~1.2.0" @@ -2166,7 +2166,7 @@ acorn@^7.1.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.1.0, acorn@^8.8.1: +acorn@^8.1.0, acorn@^8.8.2: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== @@ -3022,11 +3022,6 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= -bowser@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.9.0.tgz#3bed854233b419b9a7422d9ee3e85504373821c9" - integrity sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA== - boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" @@ -3243,11 +3238,6 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -camelize@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" - integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= - caniuse-lite@^1.0.30001219: version "1.0.30001230" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71" @@ -3424,10 +3414,10 @@ chrono-node@~1.3.11: dependencies: moment "2.21.0" -chrono-node@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/chrono-node/-/chrono-node-2.5.0.tgz#c4d5f4f4db9d72604a5beb79fdc5fd57be4b212f" - integrity sha512-GasdFCw4tsb8UKlwyJW1S+3bdN06vsyGR2cEDMlhEGI7ic4SQRnLyl/hbItwSum6pPkkUTrzFcaR3C2tZnnO5Q== +chrono-node@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/chrono-node/-/chrono-node-2.6.3.tgz#fa257cffb2dfc33fa5a01b26bd86f93741ca6dc5" + integrity sha512-VkWaaZnNulqzNH9i4XCdyI05OX6MFEnCMNKdZOR4w//wS5/E2qkwAss/O5sj6SfTZK84fX4SSOG4pzqjqIseiA== dependencies: dayjs "^1.10.0" @@ -3672,11 +3662,6 @@ content-disposition@0.5.3: dependencies: safe-buffer "5.1.2" -content-security-policy-builder@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz#0a2364d769a3d7014eec79ff7699804deb8cfcbb" - integrity sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ== - content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -3858,22 +3843,12 @@ cssfilter@0.0.10: resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae" integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= -cssom@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" - integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== - -cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" - integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== +cssstyle@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-3.0.0.tgz#17ca9c87d26eac764bb8cfd00583cff21ce0277a" + integrity sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg== dependencies: - cssom "~0.3.6" + rrweb-cssom "^0.6.0" cucumber-expressions@^8.1.0: version "8.2.1" @@ -3936,19 +3911,14 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -dasherize@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dasherize/-/dasherize-2.0.0.tgz#6d809c9cd0cf7bb8952d80fc84fa13d47ddb1308" - integrity sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg= - -data-urls@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" - integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== +data-urls@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-4.0.0.tgz#333a454eca6f9a5b7b0f1013ff89074c3f522dd4" + integrity sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g== dependencies: abab "^2.0.6" whatwg-mimetype "^3.0.0" - whatwg-url "^11.0.0" + whatwg-url "^12.0.0" date-fns@2.22.1: version "2.22.1" @@ -3993,7 +3963,7 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.3: dependencies: ms "2.1.2" -decimal.js@^10.4.2: +decimal.js@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== @@ -4103,11 +4073,6 @@ denque@^1.1.0: resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - depd@^1.1.2, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -4157,11 +4122,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dns-prefetch-control@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz#73988161841f3dcc81f47686d539a2c702c88624" - integrity sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q== - doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -4317,11 +4277,6 @@ domutils@^3.0.1: domelementtype "^2.3.0" domhandler "^5.0.1" -dont-sniff-mimetype@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz#c7d0427f8bcb095762751252af59d148b0a623b2" - integrity sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug== - dot-prop@^4.1.0: version "4.2.1" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" @@ -4881,11 +4836,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect-ct@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/expect-ct/-/expect-ct-0.2.0.tgz#3a54741b6ed34cc7a93305c605f63cd268a54a62" - integrity sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g== - expect@^29.4.2: version "29.4.2" resolved "https://registry.yarnpkg.com/expect/-/expect-29.4.2.tgz#2ae34eb88de797c64a1541ad0f1e2ea8a7a7b492" @@ -5046,11 +4996,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -feature-policy@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/feature-policy/-/feature-policy-0.3.0.tgz#7430e8e54a40da01156ca30aaec1a381ce536069" - integrity sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ== - figures@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9" @@ -5213,11 +5158,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -frameguard@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/frameguard/-/frameguard-3.1.0.tgz#bd1442cca1d67dc346a6751559b6d04502103a22" - integrity sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g== - franc@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/franc/-/franc-4.0.0.tgz#365951bc787b92ffbb1c63c1c492d6b76cbd3a56" @@ -5744,46 +5684,10 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -helmet-crossdomain@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e" - integrity sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA== - -helmet-csp@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.10.0.tgz#685dde1747bc16c5e28ad9d91e229a69f0a85e84" - integrity sha512-Rz953ZNEFk8sT2XvewXkYN0Ho4GEZdjAZy4stjiEQV3eN7GDxg1QKmYggH7otDyIA7uGA6XnUMVSgeJwbR5X+w== - dependencies: - bowser "2.9.0" - camelize "1.0.0" - content-security-policy-builder "2.1.0" - dasherize "2.0.0" - -helmet@~3.22.0: - version "3.22.0" - resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.22.0.tgz#3a6f11d931799145f0aff15dbc563cff9e13131f" - integrity sha512-Xrqicn2nm1ZIUxP3YGuTBmbDL04neKsIT583Sjh0FkiwKDXYCMUqGqC88w3NUvVXtA75JyR2Jn6jw6ZEMOD+ZA== - dependencies: - depd "2.0.0" - dns-prefetch-control "0.2.0" - dont-sniff-mimetype "1.1.0" - expect-ct "0.2.0" - feature-policy "0.3.0" - frameguard "3.1.0" - helmet-crossdomain "0.4.0" - helmet-csp "2.10.0" - hide-powered-by "1.1.0" - hpkp "2.0.0" - hsts "2.2.0" - ienoopen "1.1.0" - nocache "2.1.0" - referrer-policy "1.2.0" - x-xss-protection "1.3.0" - -hide-powered-by@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hide-powered-by/-/hide-powered-by-1.1.0.tgz#be3ea9cab4bdb16f8744be873755ca663383fa7a" - integrity sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg== +helmet@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/helmet/-/helmet-7.0.0.tgz#ac3011ba82fa2467f58075afa58a49427ba6212d" + integrity sha512-MsIgYmdBh460ZZ8cJC81q4XJknjG567wzEmv46WOBblDb6TUd3z8/GhgmsM9pn8g2B80tAJ4m5/d3Bi1KrSUBQ== homedir-polyfill@^1.0.1: version "1.0.3" @@ -5797,18 +5701,6 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.4.tgz#44119abaf4bc64692a16ace34700fed9c03e2546" integrity sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ== -hpkp@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hpkp/-/hpkp-2.0.0.tgz#10e142264e76215a5d30c44ec43de64dee6d1672" - integrity sha1-EOFCJk52IVpdMMROxD3mTe5tFnI= - -hsts@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/hsts/-/hsts-2.2.0.tgz#09119d42f7a8587035d027dda4522366fe75d964" - integrity sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ== - dependencies: - depd "2.0.0" - html-encoding-sniffer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" @@ -5991,11 +5883,6 @@ ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ienoopen@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.1.0.tgz#411e5d530c982287dbdc3bb31e7a9c9e32630974" - integrity sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ== - ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -7008,18 +6895,17 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsdom@~21.1.0: - version "21.1.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.1.0.tgz#d56ba4a84ed478260d83bd53dc181775f2d8e6ef" - integrity sha512-m0lzlP7qOtthD918nenK3hdItSd2I+V3W9IrBcB36sqDwG+KnUs66IF5GY7laGWUnlM9vTsD0W1QwSEBYWWcJg== +jsdom@~21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.1.1.tgz#ab796361e3f6c01bcfaeda1fea3c06197ac9d8ae" + integrity sha512-Jjgdmw48RKcdAIQyUD1UdBh2ecH7VqwaXPN3ehoZN6MqgVbMn+lRm1aAT1AsdJRAJpwfa4IpwgzySn61h2qu3w== dependencies: abab "^2.0.6" - acorn "^8.8.1" + acorn "^8.8.2" acorn-globals "^7.0.0" - cssom "^0.5.0" - cssstyle "^2.3.0" - data-urls "^3.0.2" - decimal.js "^10.4.2" + cssstyle "^3.0.0" + data-urls "^4.0.0" + decimal.js "^10.4.3" domexception "^4.0.0" escodegen "^2.0.0" form-data "^4.0.0" @@ -7028,7 +6914,8 @@ jsdom@~21.1.0: https-proxy-agent "^5.0.1" is-potential-custom-element-name "^1.0.1" nwsapi "^2.2.2" - parse5 "^7.1.1" + parse5 "^7.1.2" + rrweb-cssom "^0.6.0" saxes "^6.0.0" symbol-tree "^3.2.4" tough-cookie "^4.1.2" @@ -7036,8 +6923,8 @@ jsdom@~21.1.0: webidl-conversions "^7.0.0" whatwg-encoding "^2.0.0" whatwg-mimetype "^3.0.0" - whatwg-url "^11.0.0" - ws "^8.11.0" + whatwg-url "^12.0.1" + ws "^8.13.0" xml-name-validator "^4.0.0" jsesc@^2.5.1: @@ -7624,12 +7511,12 @@ metascraper-publisher@^5.33.5: dependencies: "@metascraper/helpers" "^5.33.5" -metascraper-soundcloud@^5.33.5: - version "5.33.5" - resolved "https://registry.yarnpkg.com/metascraper-soundcloud/-/metascraper-soundcloud-5.33.5.tgz#9cd39e7ff432e715f8ecdca5256e7ea67f485557" - integrity sha512-hkDhRfTKEUugIN9Gxh/l9HuWlkNAOKEBXov/9fYKbIMgaj7e2UU7bkNYjaDOXzMikCRWEIrrGP3UzwwIcs6Gjg== +metascraper-soundcloud@^5.34.2: + version "5.34.2" + resolved "https://registry.yarnpkg.com/metascraper-soundcloud/-/metascraper-soundcloud-5.34.2.tgz#ee1077b4836321ccfb22bcab4bfae7360dd571a3" + integrity sha512-1VafeFnlzJaYUlq8XbppQauz0i9xM8QycJU8k4ONftZwRtikQBIjRe5BMXr/s5n32831vBooRz8ksz0CXkjVlQ== dependencies: - "@metascraper/helpers" "^5.33.5" + "@metascraper/helpers" "^5.34.2" metascraper-title@^5.33.5: version "5.33.5" @@ -7638,12 +7525,12 @@ metascraper-title@^5.33.5: dependencies: "@metascraper/helpers" "^5.33.5" -metascraper-url@^5.33.5: - version "5.33.5" - resolved "https://registry.yarnpkg.com/metascraper-url/-/metascraper-url-5.33.5.tgz#eb0ba736f47aef7c9a511ca04e509d11ee51c95d" - integrity sha512-bXKfsfxCfy6uhhnb9lMlIu1Uwqkn9eXa4QVcHdq/+1UWTOE8b2u4NTH4YgJMjcPmdth7s3cKXBxG1yBnsAoN0w== +metascraper-url@^5.34.2: + version "5.34.2" + resolved "https://registry.yarnpkg.com/metascraper-url/-/metascraper-url-5.34.2.tgz#1136dbf1177d08835d6b8677a64d9f10f0517fb0" + integrity sha512-ijPe3G64kyxFRWPA7YmH01dt5JImqBgWV07WIpgPj8wuD4ThwteGqV1CtjNYJN8yo/tCQeFNJPoubwiv9RsrJw== dependencies: - "@metascraper/helpers" "^5.33.5" + "@metascraper/helpers" "^5.34.2" metascraper-video@^5.33.5: version "5.33.5" @@ -8034,17 +7921,7 @@ neo4j-driver-core@^4.4.7: resolved "https://registry.yarnpkg.com/neo4j-driver-core/-/neo4j-driver-core-4.4.7.tgz#d2475e107b3fea2b9d1c36b0c273da5c5a291c37" integrity sha512-NhvVuQYgG7eO/vXxRaoJfkWUNkjvIpmCIS9UWU9Bbhb4V+wCOyX/MVOXqD0Yizhs4eyIkD7x90OXb79q+vi+oA== -neo4j-driver@^4.0.1, neo4j-driver@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/neo4j-driver/-/neo4j-driver-4.0.2.tgz#78de3b91e91572bcbd9d2e02554322fe1ab399ea" - integrity sha512-xQN4BZZsweaNNac7FDYAV6f/JybghwY3lk4fwblS8V5KQ+DBMPe4Pthh672mp+wEYZGyzPalq5CfpcBrWaZ4Gw== - dependencies: - "@babel/runtime" "^7.5.5" - rxjs "^6.5.2" - text-encoding-utf-8 "^1.0.2" - uri-js "^4.2.2" - -neo4j-driver@^4.2.2: +neo4j-driver@^4.0.1, neo4j-driver@^4.0.2, neo4j-driver@^4.2.2: version "4.4.7" resolved "https://registry.yarnpkg.com/neo4j-driver/-/neo4j-driver-4.4.7.tgz#51b3fb48241e66eb3be94e90032cc494c44e59f3" integrity sha512-N7GddPhp12gVJe4eB84u5ik5SmrtRv8nH3rK47Qy7IUKnJkVEos/F1QjOJN6zt1jLnDXwDcGzCKK8XklYpzogw== @@ -8067,10 +7944,10 @@ neo4j-graphql-js@^2.11.5: lodash "^4.17.15" neo4j-driver "^4.0.1" -neode@^0.4.8: - version "0.4.8" - resolved "https://registry.yarnpkg.com/neode/-/neode-0.4.8.tgz#0889b4fc7f1bf0b470b01fa5b8870373b5d47ad6" - integrity sha512-pb91NfCOg4Fj5o+98H+S2XYC+ByQfbdhwcc1UVuzuUQ0Ezzj+jWz8NmKWU8ZfCH6l4plk71yDAPd2eTwpt+Xvg== +neode@^0.4.9: + version "0.4.9" + resolved "https://registry.yarnpkg.com/neode/-/neode-0.4.9.tgz#11c46c50d0348751dc6db828f3ca59252e7c247f" + integrity sha512-3RufLD2cmTXrPpvsgkEAqS3maRjXJ89vjbyYmyqJMJl5uv6gcUa32N6hRwHcqfjWRWUaFKaoGLEJLaOQobs4eA== dependencies: "@hapi/joi" "^15.1.1" dotenv "^4.0.0" @@ -8102,11 +7979,6 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" -nocache@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f" - integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q== - node-environment-flags@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" @@ -8669,7 +8541,7 @@ parse5@^3.0.1: dependencies: "@types/node" "*" -parse5@^7.0.0, parse5@^7.1.1: +parse5@^7.0.0, parse5@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== @@ -8977,7 +8849,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== @@ -9178,11 +9050,6 @@ redis-parser@^3.0.0: dependencies: redis-errors "^1.0.0" -referrer-policy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/referrer-policy/-/referrer-policy-1.2.0.tgz#b99cfb8b57090dc454895ef897a4cc35ef67a98e" - integrity sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA== - regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" @@ -9479,6 +9346,11 @@ rosie@^2.0.1: resolved "https://registry.yarnpkg.com/rosie/-/rosie-2.0.1.tgz#c250c4787ce450b72aa9eff26509f68589814fa2" integrity sha1-wlDEeHzkULcqqe/yZQn2hYmBT6I= +rrweb-cssom@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1" + integrity sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw== + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -9496,7 +9368,7 @@ run-parallel@^1.1.9: resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== -rxjs@^6.4.0, rxjs@^6.5.2, rxjs@^6.5.4: +rxjs@^6.4.0, rxjs@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== @@ -10311,11 +10183,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-encoding-utf-8@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" - integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -10378,17 +10245,17 @@ tlds@^1.228.0: resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.236.0.tgz#a118eebe33261c577e3a3025144faeabb7dd813c" integrity sha512-oP2PZ3KeGlgpHgsEfrtva3/K9kzsJUNliQSbCfrJ7JMCWFoCdtG+9YMq/g2AnADQ1v5tVlbtvKJZ4KLpy/P6MA== -tldts-core@^5.7.104: - version "5.7.104" - resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-5.7.104.tgz#4313a9663e4085332750a5fb04bfa0b0d91b826d" - integrity sha512-8vhSgc2nzPNT0J7XyCqcOtQ6+ySBn+gsPmj5h95YytIZ7L2Xl40paUmj0T6Uko42HegHGQxXieunHIQuABWSmQ== +tldts-core@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.0.3.tgz#b59d87507c51cd2488c322b92020b973b608b59a" + integrity sha512-PLiEM2aCkfGifyr8npbd93eWIW4isFRB44vTiup5DRie6e2Qy3+9quwHb252v12JyoM+RmF1cxtDgwD2PVBOjA== -tldts@~5.7.103: - version "5.7.104" - resolved "https://registry.yarnpkg.com/tldts/-/tldts-5.7.104.tgz#c964cf8a194936b086fa4c72994e92d4cd4d2562" - integrity sha512-PlziEIVPH/ogbqOhS35K6MOeD09rd9U5g2NHO5n9NZeMC1PGpXgsjQpoJ1KiRnjhZsWDkzN8EoX3xQZuz5ZyFQ== +tldts@~6.0.1: + version "6.0.3" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.0.3.tgz#6a4a8bb550f396d6d72818606150e0e0263ae826" + integrity sha512-rcdUIwrcGuMWe5+fg5FFBrmWTYdbfpHwkk1AjBKoSDbpsdAsYqJYKoZOVOHn8MQCYatADKGAx/SU+jpSKxSYNw== dependencies: - tldts-core "^5.7.104" + tldts-core "^6.0.3" tmp@^0.0.33: version "0.0.33" @@ -10479,12 +10346,12 @@ tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" -tr46@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" - integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== +tr46@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" + integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== dependencies: - punycode "^2.1.1" + punycode "^2.3.0" trigram-utils@^1.0.0: version "1.0.2" @@ -10946,12 +10813,12 @@ whatwg-mimetype@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== -whatwg-url@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" - integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== +whatwg-url@^12.0.0, whatwg-url@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-12.0.1.tgz#fd7bcc71192e7c3a2a97b9a8d6b094853ed8773c" + integrity sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ== dependencies: - tr46 "^3.0.0" + tr46 "^4.1.1" webidl-conversions "^7.0.0" which@^1.2.9: @@ -11062,15 +10929,10 @@ ws@^6.0.0: dependencies: async-limiter "~1.0.0" -ws@^8.11.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" - integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== - -x-xss-protection@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/x-xss-protection/-/x-xss-protection-1.3.0.tgz#3e3a8dd638da80421b0e9fff11a2dbe168f6d52c" - integrity sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg== +ws@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== xdg-basedir@^3.0.0: version "3.0.0" diff --git a/deployment/configurations/stage.ocelot.social b/deployment/configurations/stage.ocelot.social index 540bd503b..be3ac7ad2 160000 --- a/deployment/configurations/stage.ocelot.social +++ b/deployment/configurations/stage.ocelot.social @@ -1 +1 @@ -Subproject commit 540bd503b9401c1608ccda77bdd23fe47ba008fb +Subproject commit be3ac7ad29f37d6a00fb3203db302cd91cebb9fa diff --git a/deployment/docker-compose.yml b/deployment/docker-compose.yml index a0dda4dc0..973dc6ac5 100644 --- a/deployment/docker-compose.yml +++ b/deployment/docker-compose.yml @@ -65,10 +65,10 @@ services: backend: image: ocelotsocialnetwork/backend-branded:local-${CONFIGURATION} - container_name: backend + container_name: backend-branded build: dockerfile: src/docker/backend.Dockerfile - target: branded-branded + target: branded context: . args: - CONFIGURATION=$CONFIGURATION @@ -143,7 +143,7 @@ services: neo4j: image: ocelotsocialnetwork/neo4j-community:latest - container_name: neo4j + container_name: neo4j-branded networks: - test-network volumes: diff --git a/deployment/scripts/branded-images.build.sh b/deployment/scripts/branded-images.build.sh index bb86b29a6..fa9da67d1 100755 --- a/deployment/scripts/branded-images.build.sh +++ b/deployment/scripts/branded-images.build.sh @@ -16,6 +16,13 @@ if [ -z ${CONFIGURATION} ]; then fi echo "Using CONFIGURATION=${CONFIGURATION}" +# check DOCKERHUB_BRAND_VARRIANT +if [ -z ${DOCKERHUB_BRAND_VARRIANT} ]; then + echo "You must provide a `DOCKERHUB_BRAND_VARRIANT` via environment variable" + exit 1 +fi +echo "Using DOCKERHUB_BRAND_VARRIANT=${DOCKERHUB_BRAND_VARRIANT}" + # configuration DOCKERHUB_ORGANISATION=${DOCKERHUB_ORGANISATION:-"ocelotsocialnetwork"} OCELOT_VERSION=${OCELOT_VERSION:-$(node -p -e "require('${SCRIPT_DIR}/../../package.json').version")} @@ -29,11 +36,11 @@ BUILD_COMMIT=${GITHUB_SHA:-"0000000"} # backend docker build --target branded \ - -t "${DOCKERHUB_ORGANISATION}/backend-branded:latest" \ - -t "${DOCKERHUB_ORGANISATION}/backend-branded:${OCELOT_VERSION}" \ - -t "${DOCKERHUB_ORGANISATION}/backend-branded:${OCELOT_VERSION_BUILD}" \ - -t "${DOCKERHUB_ORGANISATION}/backend-branded:${BUILD_VERSION_BASE}" \ - -t "${DOCKERHUB_ORGANISATION}/backend-branded:${BUILD_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:latest" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \ + -t "${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \ -f "${SCRIPT_DIR}/../src/docker/backend.Dockerfile" \ --build-arg "CONFIGURATION=${CONFIGURATION}" \ --build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \ @@ -42,11 +49,11 @@ docker build --target branded \ # webapp docker build --target branded \ - -t "${DOCKERHUB_ORGANISATION}/webapp-branded:latest" \ - -t "${DOCKERHUB_ORGANISATION}/webapp-branded:${OCELOT_VERSION}" \ - -t "${DOCKERHUB_ORGANISATION}/webapp-branded:${OCELOT_VERSION_BUILD}" \ - -t "${DOCKERHUB_ORGANISATION}/webapp-branded:${BUILD_VERSION_BASE}" \ - -t "${DOCKERHUB_ORGANISATION}/webapp-branded:${BUILD_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:latest" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \ + -t "${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \ -f "${SCRIPT_DIR}/../src/docker/webapp.Dockerfile" \ --build-arg "CONFIGURATION=${CONFIGURATION}" \ --build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \ @@ -55,11 +62,11 @@ docker build --target branded \ # mainteance docker build --target branded \ - -t "${DOCKERHUB_ORGANISATION}/maintenance-branded:latest" \ - -t "${DOCKERHUB_ORGANISATION}/maintenance-branded:${OCELOT_VERSION}" \ - -t "${DOCKERHUB_ORGANISATION}/maintenance-branded:${OCELOT_VERSION_BUILD}" \ - -t "${DOCKERHUB_ORGANISATION}/maintenance-branded:${BUILD_VERSION_BASE}" \ - -t "${DOCKERHUB_ORGANISATION}/maintenance-branded:${BUILD_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:latest" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION}" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD}" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE}" \ + -t "${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION}" \ -f "${SCRIPT_DIR}/../src/docker/maintenance.Dockerfile" \ --build-arg "CONFIGURATION=${CONFIGURATION}" \ --build-arg "APP_IMAGE_TAG_CODE=${OCELOT_VERSION}-code" \ diff --git a/deployment/scripts/branded-images.upload.sh b/deployment/scripts/branded-images.upload.sh index 0d3fdb6d6..83e27496b 100755 --- a/deployment/scripts/branded-images.upload.sh +++ b/deployment/scripts/branded-images.upload.sh @@ -10,6 +10,13 @@ SCRIPT_PATH=$(realpath $0) SCRIPT_DIR=$(dirname $SCRIPT_PATH) +# check DOCKERHUB_BRAND_VARRIANT +if [ -z ${DOCKERHUB_BRAND_VARRIANT} ]; then + echo "You must provide a `DOCKERHUB_BRAND_VARRIANT` via environment variable" + exit 1 +fi +echo "Using DOCKERHUB_BRAND_VARRIANT=${DOCKERHUB_BRAND_VARRIANT}" + # configuration DOCKERHUB_ORGANISATION=${DOCKERHUB_ORGANISATION:-"ocelotsocialnetwork"} OCELOT_VERSION=${OCELOT_VERSION:-$(node -p -e "require('${SCRIPT_DIR}/../../package.json').version")} @@ -23,22 +30,22 @@ BUILD_VERSION=${BRANDED_VERSION}-ocelot.social${OCELOT_VERSION_BUILD} echo "${DOCKERHUB_TOKEN}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin # push backend images -docker push ${DOCKERHUB_ORGANISATION}/backend-branded:latest -docker push ${DOCKERHUB_ORGANISATION}/backend-branded:${OCELOT_VERSION} -docker push ${DOCKERHUB_ORGANISATION}/backend-branded:${OCELOT_VERSION_BUILD} -docker push ${DOCKERHUB_ORGANISATION}/backend-branded:${BUILD_VERSION_BASE} -docker push ${DOCKERHUB_ORGANISATION}/backend-branded:${BUILD_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:latest +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD} +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE} +docker push ${DOCKERHUB_ORGANISATION}/backend-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION} # push webapp images -docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:latest -docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:${OCELOT_VERSION} -docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:${OCELOT_VERSION_BUILD} -docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:${BUILD_VERSION_BASE} -docker push ${DOCKERHUB_ORGANISATION}/webapp-branded:${BUILD_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:latest +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD} +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE} +docker push ${DOCKERHUB_ORGANISATION}/webapp-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION} # push maintenance images -docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:latest -docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:${OCELOT_VERSION} -docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:${OCELOT_VERSION_BUILD} -docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:${BUILD_VERSION_BASE} -docker push ${DOCKERHUB_ORGANISATION}/maintenance-branded:${BUILD_VERSION} \ No newline at end of file +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:latest +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION} +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${OCELOT_VERSION_BUILD} +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION_BASE} +docker push ${DOCKERHUB_ORGANISATION}/maintenance-${DOCKERHUB_BRAND_VARRIANT}:${BUILD_VERSION} \ No newline at end of file diff --git a/deployment/src/kubernetes/templates/backend/Deployment.yaml b/deployment/src/kubernetes/templates/backend/Deployment.yaml index f475a0173..4d0f66dbc 100644 --- a/deployment/src/kubernetes/templates/backend/Deployment.yaml +++ b/deployment/src/kubernetes/templates/backend/Deployment.yaml @@ -39,6 +39,11 @@ spec: name: configmap-{{ .Release.Name }}-backend - secretRef: name: secret-{{ .Release.Name }}-backend + resources: + requests: + memory: {{ .Values.BACKEND.RESOURCE_REQUESTS_MEMORY | default "500M" | quote }} + limits: + memory: {{ .Values.BACKEND.RESOURCE_LIMITS_MEMORY | default "1G" | quote }} ports: - containerPort: 4000 protocol: TCP diff --git a/deployment/src/kubernetes/templates/maintenance/Deployment.yaml b/deployment/src/kubernetes/templates/maintenance/Deployment.yaml index fd1aa311a..ec37552d1 100644 --- a/deployment/src/kubernetes/templates/maintenance/Deployment.yaml +++ b/deployment/src/kubernetes/templates/maintenance/Deployment.yaml @@ -34,6 +34,11 @@ spec: name: configmap-{{ .Release.Name }}-webapp - secretRef: name: secret-{{ .Release.Name }}-webapp + resources: + requests: + memory: {{ .Values.MAINTENANCE.RESOURCE_REQUESTS_MEMORY | default "500M" | quote }} + limits: + memory: {{ .Values.MAINTENANCE.RESOURCE_LIMITS_MEMORY | default "1G" | quote }} ports: - containerPort: 80 restartPolicy: {{ .Values.MAINTENANCE.CONTAINER_RESTART_POLICY }} diff --git a/deployment/src/kubernetes/templates/webapp/Deployment.yaml b/deployment/src/kubernetes/templates/webapp/Deployment.yaml index a334738ec..41221185c 100644 --- a/deployment/src/kubernetes/templates/webapp/Deployment.yaml +++ b/deployment/src/kubernetes/templates/webapp/Deployment.yaml @@ -40,5 +40,10 @@ spec: name: configmap-{{ .Release.Name }}-webapp - secretRef: name: secret-{{ .Release.Name }}-webapp + resources: + requests: + memory: {{ .Values.WEBAPP.RESOURCE_REQUESTS_MEMORY | default "500M" | quote }} + limits: + memory: {{ .Values.WEBAPP.RESOURCE_LIMITS_MEMORY | default "1G" | quote }} restartPolicy: {{ .Values.WEBAPP.CONTAINER_RESTART_POLICY }} terminationGracePeriodSeconds: {{ .Values.WEBAPP.CONTAINER_TERMINATION_GRACE_PERIOD_SECONDS }} \ No newline at end of file diff --git a/package.json b/package.json index df3ba2a81..a1a6336df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ocelot-social", - "version": "2.5.1", + "version": "2.6.0", "description": "Free and open source software program code available to run social networks.", "author": "ocelot.social Community", "license": "MIT", @@ -22,8 +22,8 @@ "release": "yarn version --no-git-tag-version --no-commit-hooks --no-commit && auto-changelog --latest-version $(node -p -e \"require('./package.json').version\") && cd backend && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp/maintenance/source && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../../../package.json').version\")" }, "devDependencies": { - "@babel/core": "^7.9.0", - "@babel/preset-env": "^7.12.7", + "@babel/core": "^7.21.8", + "@babel/preset-env": "^7.21.5", "@babel/register": "^7.12.10", "@faker-js/faker": "5.1.0", "auto-changelog": "^2.3.0", @@ -34,9 +34,9 @@ "cypress": "^7.0.1", "cypress-cucumber-preprocessor": "^2.2.1", "cypress-file-upload": "^3.5.3", - "date-fns": "^2.25.0", + "date-fns": "^2.30.0", "dotenv": "^8.2.0", - "expect": "^25.3.0", + "expect": "^29.5.0", "graphql-request": "^2.0.0", "import": "^0.0.6", "jsonwebtoken": "^8.5.1", diff --git a/webapp/Dockerfile b/webapp/Dockerfile index 7952d02c1..b0ecbdd37 100644 --- a/webapp/Dockerfile +++ b/webapp/Dockerfile @@ -1,7 +1,7 @@ ################################################################################## # BASE (Is pushed to DockerHub for rebranding) ################################### ################################################################################## -FROM node:19.4.0-alpine3.17 as base +FROM node:20.2.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame diff --git a/webapp/Dockerfile.maintenance b/webapp/Dockerfile.maintenance index e148da555..a6db9e612 100644 --- a/webapp/Dockerfile.maintenance +++ b/webapp/Dockerfile.maintenance @@ -1,7 +1,7 @@ ################################################################################## # BASE ########################################################################### ################################################################################## -FROM node:19.4.0-alpine3.17 as base +FROM node:20.2.0-alpine3.17 as base # ENVs ## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame diff --git a/webapp/assets/_new/icons/svgs/book.svg b/webapp/assets/_new/icons/svgs/book.svg new file mode 100644 index 000000000..305e367ac --- /dev/null +++ b/webapp/assets/_new/icons/svgs/book.svg @@ -0,0 +1,5 @@ + + +book + + diff --git a/webapp/assets/_new/icons/svgs/calendar.svg b/webapp/assets/_new/icons/svgs/calendar.svg new file mode 100644 index 000000000..5a67a8299 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/calendar.svg @@ -0,0 +1,5 @@ + + +calendar + + diff --git a/webapp/assets/_new/styles/mixins/buttonStates.css b/webapp/assets/_new/styles/mixins/buttonStates.css new file mode 100644 index 000000000..27b24b9ce --- /dev/null +++ b/webapp/assets/_new/styles/mixins/buttonStates.css @@ -0,0 +1 @@ +/*# sourceMappingURL=buttonStates.css.map */ \ No newline at end of file diff --git a/webapp/assets/_new/styles/mixins/buttonStates.css.map b/webapp/assets/_new/styles/mixins/buttonStates.css.map new file mode 100644 index 000000000..aa1b02a29 --- /dev/null +++ b/webapp/assets/_new/styles/mixins/buttonStates.css.map @@ -0,0 +1 @@ +{"version":3,"sources":[],"names":[],"mappings":"","file":"buttonStates.css"} \ No newline at end of file diff --git a/webapp/assets/_new/styles/resets.css b/webapp/assets/_new/styles/resets.css new file mode 100644 index 000000000..b9aeaa72e --- /dev/null +++ b/webapp/assets/_new/styles/resets.css @@ -0,0 +1,29 @@ +* { + box-sizing: border-box; +} + +button { + padding: 0; + background: transparent; + border: none; + font-family: inherit; + font-size: inherit; +} + +h1, +h2, +h3, +h4, +h5, +h6, +p, +li { + margin: 0; +} + +ol, +ul { + list-style-type: none; + margin: 0; + padding: 0; +}/*# sourceMappingURL=resets.css.map */ \ No newline at end of file diff --git a/webapp/assets/_new/styles/resets.css.map b/webapp/assets/_new/styles/resets.css.map new file mode 100644 index 000000000..e759c9680 --- /dev/null +++ b/webapp/assets/_new/styles/resets.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["resets.scss","resets.css"],"names":[],"mappings":"AAAA;EACE,sBAAA;ACCF;;ADEA;EACE,UAAA;EACA,uBAAA;EACA,YAAA;EACA,oBAAA;EACA,kBAAA;ACCF;;ADEA;;;;;;;;EAQE,SAAA;ACCF;;ADEA;;EAEE,qBAAA;EACA,SAAA;EACA,UAAA;ACCF","file":"resets.css"} \ No newline at end of file diff --git a/webapp/assets/_new/styles/tokens.css b/webapp/assets/_new/styles/tokens.css new file mode 100644 index 000000000..45bac6085 --- /dev/null +++ b/webapp/assets/_new/styles/tokens.css @@ -0,0 +1,122 @@ +/** + * @tokens Color Brand + * @presenter Color + */ +/** + * @tokens Color Neutral + * @presenter Color + */ +/** + * @tokens Color Text + * @presenter Color + */ +/** + * @tokens Color Background + * @presenter Color + */ +/** + * @tokens Color Border + * @presenter Color + */ +/** + * @tokens Border Size + * @presenter Border + */ +/** + * @tokens Border Radius + * @presenter BorderRadius + */ +/** + * @tokens Font Size + * @presenter FontSize + */ +/** + * @tokens Font Space + * @presenter Spacing + */ +/** + * @tokens Font Family + * @presenter FontFamily + */ +/** + * @tokens Font Weight + * @presenter FontWeight + */ +/** + * @tokens Line Height + * @presenter LineHeight + */ +/** + * @tokens Letter Spacing + * @presenter Spacing + */ +/** + * @tokens Opacity + * @presenter Opacity + */ +/** + * @tokens Space + * @presenter Spacing + */ +/** + * @tokens Size Height + * @presenter Spacing + */ +/** + * @tokens Size Width + * @presenter Spacing + */ +/** + * @tokens Size Avatar + * @presenter Spacing + */ +/** + * @tokens Size Buttons + * @presenter Spacing + */ +/** + * @tokens Size Images + * @presenter Spacing + */ +/** + * @tokens Size Icons + * @presenter Spacing + */ +/** + * @tokens Shadow + * @presenter Shadow + */ +/** + * @tokens Effects + */ +/** + * @tokens Animation Duration + */ +/** + * @tokens Animation Ease + * @presenter Easing + */ +/** + * @tokens Z-Index + */ +/** + * @tokens Media Query + */ +/** + * @tokens Background Images + */ +/** + * @tokens Header Color + */ +/** + * @tokens Footer Color + */ +/** + * @tokens Locale Menu Color + */ +/** + * @tokens Donation Bar Color + */ +/** + * @tokens Toast Color + *//*# sourceMappingURL=tokens.css.map */ \ No newline at end of file diff --git a/webapp/assets/_new/styles/tokens.css.map b/webapp/assets/_new/styles/tokens.css.map new file mode 100644 index 000000000..5111f4b00 --- /dev/null +++ b/webapp/assets/_new/styles/tokens.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["tokens.scss"],"names":[],"mappings":"AAAA;;;EAAA;AA4BA;;;EAAA;AAmBA;;;EAAA;AAuBA;;;EAAA;AAgCA;;;EAAA;AAeA;;;EAAA;AASA;;;EAAA;AAYA;;;EAAA;AAgBA;;;EAAA;AAgBA;;;EAAA;AAUA;;;EAAA;AAQA;;;EAAA;AAUA;;;EAAA;AAWA;;;EAAA;AASA;;;EAAA;AAgBA;;;EAAA;AAaA;;;EAAA;AASA;;;EAAA;AASA;;;EAAA;AASA;;;EAAA;AAUA;;;EAAA;AAQA;;;EAAA;AAcA;;EAAA;AAMA;;EAAA;AAUA;;;EAAA;AAWA;;EAAA;AAaA;;EAAA;AAUA;;EAAA;AAIA;;EAAA;AAMA;;EAAA;AAOA;;EAAA;AAMA;;EAAA;AAOA;;EAAA","file":"tokens.css"} \ No newline at end of file diff --git a/webapp/assets/_new/styles/tokens.scss b/webapp/assets/_new/styles/tokens.scss index 66bd03ecc..863e0e0b7 100644 --- a/webapp/assets/_new/styles/tokens.scss +++ b/webapp/assets/_new/styles/tokens.scss @@ -336,10 +336,12 @@ $ease-in-sharp: cubic-bezier(0.895, 0.03, 0.685, 0.22); */ $z-index-modal: 9999; +$z-index-overlay: 9000; $z-index-dropdown: 8888; $z-index-page-submenu: 2500; $z-index-page-header: 2000; $z-index-page-sidebar: 1500; +$z-index-sticky-float: 150; $z-index-sticky: 100; $z-index-post-teaser-link: 5; $z-index-surface: 1; diff --git a/webapp/assets/styles/main.scss b/webapp/assets/styles/main.scss index 144701f83..b726758c7 100644 --- a/webapp/assets/styles/main.scss +++ b/webapp/assets/styles/main.scss @@ -95,7 +95,7 @@ blockquote { box-shadow: $box-shadow-base; position: fixed; width: 100%; - z-index: 10; + z-index: $z-index-page-submenu; a { outline: none; @@ -131,7 +131,7 @@ hr { left: 0; position: fixed; background: rgba(0, 0, 0, 0.15); - z-index: 99; + z-index: $z-index-overlay; pointer-events: none; transition: opacity 150ms ease-out; transition-delay: 50ms; diff --git a/webapp/components/CategoriesSelect/CategoriesSelect.vue b/webapp/components/CategoriesSelect/CategoriesSelect.vue index 4f7a555a3..91fb7704c 100644 --- a/webapp/components/CategoriesSelect/CategoriesSelect.vue +++ b/webapp/components/CategoriesSelect/CategoriesSelect.vue @@ -43,6 +43,14 @@ export default { selectedCategoryIds: this.existingCategoryIds, } }, + watch: { + existingCategoryIds() { + if (!this.selectedCategoryIds.length && this.existingCategoryIds.length) { + this.selectedCategoryIds = this.existingCategoryIds + this.$forceUpdate() + } + }, + }, computed: { selectedCount() { return this.selectedCategoryIds.length diff --git a/webapp/components/ContentMenu/ContentMenu.vue b/webapp/components/ContentMenu/ContentMenu.vue index 60bcccf43..d723a9667 100644 --- a/webapp/components/ContentMenu/ContentMenu.vue +++ b/webapp/components/ContentMenu/ContentMenu.vue @@ -80,7 +80,7 @@ export default { }) } - if (this.isAdmin) { + if (this.isAdmin && !this.resource.group) { if (!this.resource.pinnedBy) { routes.push({ label: this.$t(`post.menu.pin`), diff --git a/webapp/components/ContributionForm/ContributionForm.vue b/webapp/components/ContributionForm/ContributionForm.vue index 8863fbc8a..584e3597a 100644 --- a/webapp/components/ContributionForm/ContributionForm.vue +++ b/webapp/components/ContributionForm/ContributionForm.vue @@ -30,6 +30,7 @@ + + + +
+
+ + + + +
+ +
+
+ + + +
+
+ + + + + +
+ + + +
+ + {{ formData.eventVenue.length }}/{{ formSchema.eventVenue.max }} + + +
+
+ + +
+ + {{ formData.eventLocationName.length }}/{{ formSchema.eventLocationName.max }} + + +
+
+
+ +
+ + {{ $t('post.viewEvent.eventIsOnline') }} +
+
+ + - diff --git a/webapp/components/FilterMenu/CategoriesFilter.vue b/webapp/components/FilterMenu/CategoriesFilter.vue index bcbfc7d1c..8b96245fd 100644 --- a/webapp/components/FilterMenu/CategoriesFilter.vue +++ b/webapp/components/FilterMenu/CategoriesFilter.vue @@ -17,18 +17,22 @@ @@ -95,3 +99,13 @@ export default { }, } + diff --git a/webapp/components/FilterMenu/FilterMenuComponent.vue b/webapp/components/FilterMenu/FilterMenuComponent.vue index 7a582a7c4..708c3bc7c 100644 --- a/webapp/components/FilterMenu/FilterMenuComponent.vue +++ b/webapp/components/FilterMenu/FilterMenuComponent.vue @@ -3,6 +3,7 @@

{{ $t('filter-menu.filter-by') }}

+
@@ -13,6 +14,7 @@ diff --git a/webapp/components/Group/GroupForm.vue b/webapp/components/Group/GroupForm.vue index cb407a3d9..52437d644 100644 --- a/webapp/components/Group/GroupForm.vue +++ b/webapp/components/Group/GroupForm.vue @@ -37,8 +37,6 @@ {{ $t('group.type') }} - - - - + - + @@ -43,4 +47,11 @@ export default { } } } +.eventBg { + background-color: $color-success-active; + + &::before { + border-color: $color-success-active transparent transparent $color-success-active; + } +} diff --git a/webapp/components/Select/ActionRadiusSelect.spec.js b/webapp/components/Select/ActionRadiusSelect.spec.js new file mode 100644 index 000000000..7629ac788 --- /dev/null +++ b/webapp/components/Select/ActionRadiusSelect.spec.js @@ -0,0 +1,37 @@ +import { shallowMount } from '@vue/test-utils' +import ActionRadiusSelect from './ActionRadiusSelect' + +const localVue = global.localVue +const propsData = { value: 'regional' } + +describe('ActionRadiusSelect.', () => { + let wrapper + let mocks + + beforeEach(() => { + mocks = { + $t: jest.fn(), + } + }) + + describe('mount', () => { + const Wrapper = () => { + return shallowMount(ActionRadiusSelect, { propsData, mocks, localVue }) + } + + beforeEach(() => { + wrapper = Wrapper() + }) + it('renders the select', () => { + expect(wrapper.findComponent(ActionRadiusSelect).exists()).toBe(true) + }) + + describe('when an option is selected', () => { + it('emits a change event with the new value', () => { + const select = wrapper.find('select') + select.trigger('change') + expect(wrapper.emitted().change[0]).toEqual(['regional']) + }) + }) + }) +}) diff --git a/webapp/components/Select/ActionRadiusSelect.vue b/webapp/components/Select/ActionRadiusSelect.vue new file mode 100644 index 000000000..0a090e0a5 --- /dev/null +++ b/webapp/components/Select/ActionRadiusSelect.vue @@ -0,0 +1,33 @@ + + + diff --git a/webapp/components/generic/SearchableInput/SearchableInput.spec.js b/webapp/components/generic/SearchableInput/SearchableInput.spec.js index cda9150b8..223ee6186 100644 --- a/webapp/components/generic/SearchableInput/SearchableInput.spec.js +++ b/webapp/components/generic/SearchableInput/SearchableInput.spec.js @@ -63,13 +63,6 @@ describe('SearchableInput.vue', () => { expect(select.element.value).toBe('abcd') }) - it('calls onDelete when the delete key is pressed', () => { - const spy = jest.spyOn(wrapper.vm, 'onDelete') - select.trigger('input') - select.trigger('keyup.delete') - expect(spy).toHaveBeenCalledTimes(1) - }) - describe('navigating to resource', () => { beforeEach(() => { propsData = { options: searchResults } diff --git a/webapp/components/generic/SearchableInput/SearchableInput.vue b/webapp/components/generic/SearchableInput/SearchableInput.vue index 2149732c5..b0e813b45 100644 --- a/webapp/components/generic/SearchableInput/SearchableInput.vue +++ b/webapp/components/generic/SearchableInput/SearchableInput.vue @@ -1,9 +1,10 @@