diff --git a/.env.dev b/.env.dev index a0f1e2eb7..372407f3c 100644 --- a/.env.dev +++ b/.env.dev @@ -21,8 +21,12 @@ SECRET_KEY='secret' DEBUG='1' ACTIVIST_EMAIL="noreply@activist.org" -EMAIL_HOST="smtp.activist.org" -EMAIL_PORT="587" -EMAIL_HOST_USER="activist@activist.org" -EMAIL_HOST_PASSWORD="activist123!?" -EMAIL_USE_TLS="True" +EMAIL_BACKEND="django.core.mail.backends.smtp.EmailBackend" +EMAIL_HOST="mailhog" +EMAIL_PORT="1025" +EMAIL_HOST_USER="" +EMAIL_HOST_PASSWORD="" +EMAIL_USE_TLS="False" + +NUXT_SESSION_PASSWORD="password-with-at-least-32-characters" +VITE_BACKEND_URL_PROXY="http://backend:8000" diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index c631429de..e2fda1cbe 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -55,7 +55,7 @@ This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. +representative at an online or physical event. ## Enforcement diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a9169253f..025c0b18a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -14,15 +14,22 @@ Thank you for your pull request! 🚀 ### Description +Description of the proposed change... + ### Related issue - + - #ISSUE_NUMBER diff --git a/.github/workflows/check_dependency_updates.yaml b/.github/workflows/check_dependency_updates.yaml index c61486e49..d71bc1a9b 100644 --- a/.github/workflows/check_dependency_updates.yaml +++ b/.github/workflows/check_dependency_updates.yaml @@ -1,7 +1,7 @@ name: check_dependency_updates on: schedule: - - cron: '0 0 15 */2 *' + - cron: "0 0 15 */2 *" workflow_dispatch: jobs: @@ -26,10 +26,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Node Environment - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: 20 @@ -39,9 +39,9 @@ jobs: echo "## Available Update ⚙️" >> reports.md - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: - python-version: '3.11' + python-version: "3.12" - name: Setup Yarn working-directory: ./frontend diff --git a/.github/workflows/pr_ci_backend.yaml b/.github/workflows/ci_backend_pytest.yaml similarity index 53% rename from .github/workflows/pr_ci_backend.yaml rename to .github/workflows/ci_backend_pytest.yaml index fa0831b47..53c3ebf92 100644 --- a/.github/workflows/pr_ci_backend.yaml +++ b/.github/workflows/ci_backend_pytest.yaml @@ -1,4 +1,4 @@ -name: pr_ci_backend +name: ci_backend_pytest on: workflow_dispatch: pull_request: @@ -25,7 +25,7 @@ env: DATABASE_PASSWORD: postgres jobs: - backend: + backend_tests: services: postgres: image: postgres:15 @@ -42,45 +42,32 @@ jobs: checks: write pull-requests: write - name: Run PR Backend Check + name: Run PR Backend Tests runs-on: ubuntu-latest + defaults: + run: + working-directory: ./backend steps: - name: Checkout Project - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Python Environment - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: - python-version: "3.11" - - - name: Create Environment and Install Dependencies - run: | - python -m pip install --upgrade uv - uv venv - . .venv/bin/activate - echo PATH=$PATH >> $GITHUB_ENV - uv pip install -r backend/requirements-dev.txt - - - name: Run Ruff Format - Formatting Check - run: ruff format ./backend + python-version: "3.13" - - name: Run Ruff - Linting and Import Sorting Check - if: always() - run: ruff check ./backend + - name: Install uv + uses: astral-sh/setup-uv@v7 - - name: Run mypy - Static Type Checking - if: always() - run: mypy ./backend --config-file ./backend/pyproject.toml + - name: Install Dependencies + run: uv sync --frozen --all-extras - name: Run Django Migrations - Database Migrations Check - if: always() run: | - . .venv/bin/activate - python ./backend/manage.py makemigrations - python ./backend/manage.py migrate + uv run manage.py makemigrations + uv run manage.py migrate - name: Run pytest - Unit Tests if: always() - working-directory: ./backend run: | - pytest . --cov=. --cov-report=term-missing --cov-fail-under=90 --cov-config=./pyproject.toml -vv + uv run pytest . --cov=. --cov-report=term-missing --cov-fail-under=90 --cov-config=./pyproject.toml -vv diff --git a/.github/workflows/ci_backend_static_analysis.yaml b/.github/workflows/ci_backend_static_analysis.yaml new file mode 100644 index 000000000..5af28b061 --- /dev/null +++ b/.github/workflows/ci_backend_static_analysis.yaml @@ -0,0 +1,50 @@ +name: ci_backend_static_analysis +on: + workflow_dispatch: + pull_request: + branches: + - main + types: + - opened + - reopened + - synchronize + paths: + - "backend/**" + push: + branches: + - main + paths: + - "backend/**" + +jobs: + backend_static_analysis: + name: Run PR Backend Static Check + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./backend + steps: + - name: Checkout Project + uses: actions/checkout@v6 + + - name: Set up Python Environment + uses: actions/setup-python@v6 + with: + python-version: "3.13" + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Install Dependencies + run: uv sync --frozen --all-extras + + - name: Run Ruff Format - Formatting Check + run: uv run ruff format . + + - name: Run Ruff - Linting and Import Sorting Check + if: always() + run: uv run ruff check . + + - name: Run mypy - Static Type Checking + if: always() + run: uv run mypy . --config-file ./pyproject.toml diff --git a/.github/workflows/pr_ci_playwright_e2e.yaml b/.github/workflows/ci_e2e_playwright_desktop.yaml similarity index 56% rename from .github/workflows/pr_ci_playwright_e2e.yaml rename to .github/workflows/ci_e2e_playwright_desktop.yaml index 2fce581e8..d2b42adb8 100644 --- a/.github/workflows/pr_ci_playwright_e2e.yaml +++ b/.github/workflows/ci_e2e_playwright_desktop.yaml @@ -1,19 +1,46 @@ -name: pr_ci_playwright_e2e +name: ci_e2e_playwright_desktop on: workflow_dispatch: + pull_request: + branches: + - main + types: + - opened + - reopened + - synchronize + paths: + # Note: We run only the desktop e2e tests for backend changes to catch regressions. + - "backend/**" + - "!backend/**/tests/**/*.py" + - "frontend/**" + - "!frontend/test/**" + - "!frontend/i18n/**" + - ".github/workflows/ci_e2e_playwright_desktop.yaml" + - ".github/workflows/ci_e2e_playwright_mobile.yaml" + push: + branches: + - main + paths: + # Note: We run only the desktop e2e tests for backend changes to catch regressions. + - "backend/**" + - "!backend/**/tests/**/*.py" + - "frontend/**" + - "!frontend/test/**" + - "!frontend/i18n/**" + - ".github/workflows/ci_e2e_playwright_desktop.yaml" + - ".github/workflows/ci_e2e_playwright_mobile.yaml" jobs: - frontend: - name: Run PR Frontend E2E Check + frontend-e2e-desktop: + name: E2E Desktop Chrome runs-on: ubuntu-latest - environment: dev steps: - name: Cleanup Old Checkout run: chmod +w -R ${GITHUB_WORKSPACE}; rm -rf ${GITHUB_WORKSPACE}/*; - name: Checkout Project - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Clean Any Existing Containers run: | @@ -35,10 +62,10 @@ jobs: - name: Wait for Backend run: | - timeout 90 bash -c 'until curl -s http://localhost:8000 >/dev/null; do sleep 2; done' + timeout 180 bash -c 'until curl -s http://localhost:8000/v1/auth/sign_in -o /dev/null -w "%{http_code}" | grep -qE "^(200|405)"; do sleep 3; done' - name: Setup Node Environment - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: 24 @@ -49,16 +76,18 @@ jobs: - name: Install Dependencies and Build working-directory: ./frontend env: + USE_PREVIEW: true VITE_FRONTEND_URL: http://localhost:3000 VITE_BACKEND_URL: http://localhost:8000 VITE_API_URL: http://localhost:8000/v1 + VITE_BACKEND_URL_PROXY: http://localhost:8000 run: | sudo corepack enable sudo yarn install sudo -E yarn build - if [ ! -f "dist/index.html" ]; then - echo "Build failed: dist/index.html not found" + if [ ! -d ".output" ]; then + echo "Build failed: .output directory not found" exit 1 fi @@ -71,13 +100,18 @@ jobs: sudo -E yarn playwright install --with-deps chromium sudo chmod -R 755 /opt/playwright-browsers - - name: Start Static Server + - name: Start Preview Server working-directory: ./frontend + env: + NUXT_SESSION_PASSWORD: "password-with-at-least-32-characters" + VITE_BACKEND_URL: http://localhost:8000 + VITE_API_URL: http://localhost:8000/v1 + VITE_BACKEND_URL_PROXY: http://localhost:8000 + PORT: 3000 run: | - npm install -g serve - nohup serve dist -l 3000 > server.log 2>&1 & + nohup sudo -E yarn preview --port 3000 > server.log 2>&1 & echo $! > server.pid - sleep 3 + sleep 5 if ! ps -p $(cat server.pid) > /dev/null; then echo "Server failed to start:" @@ -102,18 +136,22 @@ jobs: curl -s http://localhost:8000/v1/entities/events/ > /dev/null || true sleep 3 - - name: Run Playwright Tests + - name: Run Playwright Tests (Desktop Chrome) working-directory: ./frontend env: - FAST_TESTS: true # only Desktop Chrome + Mobile Chrome - SKIP_WEBSERVER: true # Server already started manually + FAST_TESTS: true + SKIP_WEBSERVER: true PLAYWRIGHT_BROWSERS_PATH: /opt/playwright-browsers - run: sudo -E yarn playwright test + NUXT_SESSION_PASSWORD: "password-with-at-least-32-characters" + VITE_BACKEND_URL: http://localhost:8000 + VITE_API_URL: http://localhost:8000/v1 + VITE_BACKEND_URL_PROXY: http://localhost:8000 + run: sudo -E yarn playwright test --project="Desktop Chrome" - name: Upload Playwright Report if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: - name: playwright-report + name: playwright-report-desktop path: frontend/playwright-report/ retention-days: 30 diff --git a/.github/workflows/ci_e2e_playwright_mobile.yaml b/.github/workflows/ci_e2e_playwright_mobile.yaml new file mode 100644 index 000000000..e0c77006c --- /dev/null +++ b/.github/workflows/ci_e2e_playwright_mobile.yaml @@ -0,0 +1,157 @@ +name: ci_e2e_playwright_mobile +on: + workflow_dispatch: + pull_request: + branches: + - main + types: + - opened + - reopened + - synchronize + paths: + # Note: We run only the desktop e2e tests for backend changes to catch regressions. + # - "backend/**" + # - "!backend/**/tests/**/*.py" + - "frontend/**" + - "!frontend/test/**" + - "!frontend/i18n/**" + - ".github/workflows/ci_e2e_playwright_desktop.yaml" + - ".github/workflows/ci_e2e_playwright_mobile.yaml" + push: + branches: + - main + paths: + # Note: We run only the desktop e2e tests for backend changes to catch regressions. + # - "backend/**" + # - "!backend/**/tests/**/*.py" + - "frontend/**" + - "!frontend/test/**" + - "!frontend/i18n/**" + - ".github/workflows/ci_e2e_playwright_desktop.yaml" + - ".github/workflows/ci_e2e_playwright_mobile.yaml" + +jobs: + frontend-e2e-mobile: + name: E2E Mobile Chrome + runs-on: ubuntu-latest + + steps: + - name: Cleanup Old Checkout + run: chmod +w -R ${GITHUB_WORKSPACE}; rm -rf ${GITHUB_WORKSPACE}/*; + + - name: Checkout Project + uses: actions/checkout@v6 + + - name: Clean Any Existing Containers + run: | + docker stop $(docker ps -aq) || true + docker rm $(docker ps -aq) || true + + - name: Check Port Availability + run: | + ! nc -z localhost 3000 && \ + ! nc -z localhost 8000 && \ + ! nc -z localhost 5432 + + - name: Run Docker Compose + run: docker compose --env-file .env.dev up --build -d backend db + + - name: Wait for Database + run: | + timeout 60 bash -c 'until docker compose --env-file .env.dev exec -T db pg_isready -U postgres; do sleep 2; done' + + - name: Wait for Backend + run: | + timeout 180 bash -c 'until curl -s http://localhost:8000/v1/auth/sign_in -o /dev/null -w "%{http_code}" | grep -qE "^(200|405)"; do sleep 3; done' + + - name: Setup Node Environment + uses: actions/setup-node@v5 + with: + node-version: 24 + + - uses: c-py/action-dotenv-to-setenv@v5 + with: + env-file: .env.dev + + - name: Install Dependencies and Build + working-directory: ./frontend + env: + USE_PREVIEW: true + VITE_FRONTEND_URL: http://localhost:3000 + VITE_BACKEND_URL: http://localhost:8000 + VITE_API_URL: http://localhost:8000/v1 + VITE_BACKEND_URL_PROXY: http://localhost:8000 + run: | + sudo corepack enable + sudo yarn install + sudo -E yarn build + + if [ ! -d ".output" ]; then + echo "Build failed: .output directory not found" + exit 1 + fi + + - name: Install Playwright Browsers + working-directory: ./frontend + env: + PLAYWRIGHT_BROWSERS_PATH: /opt/playwright-browsers + run: | + sudo mkdir -p /opt/playwright-browsers + sudo -E yarn playwright install --with-deps chromium + sudo chmod -R 755 /opt/playwright-browsers + + - name: Start Preview Server + working-directory: ./frontend + env: + NUXT_SESSION_PASSWORD: "password-with-at-least-32-characters" + VITE_BACKEND_URL: http://localhost:8000 + VITE_API_URL: http://localhost:8000/v1 + VITE_BACKEND_URL_PROXY: http://localhost:8000 + PORT: 3000 + run: | + nohup sudo -E yarn preview --port 3000 > server.log 2>&1 & + echo $! > server.pid + sleep 5 + + if ! ps -p $(cat server.pid) > /dev/null; then + echo "Server failed to start:" + cat server.log + exit 1 + fi + + - name: Wait for Frontend + working-directory: ./frontend + run: | + yarn wait-on http://localhost:3000 --timeout 60000 || { + echo "Frontend server not responding:" + cat server.log + exit 1 + } + + - name: Warm Up Backend + run: | + curl -s -X OPTIONS http://localhost:8000/v1/auth/sign_in > /dev/null || true + curl -s http://localhost:8000/v1/entities/users/ > /dev/null || true + curl -s http://localhost:8000/v1/entities/organizations/ > /dev/null || true + curl -s http://localhost:8000/v1/entities/events/ > /dev/null || true + sleep 3 + + - name: Run Playwright Tests (Mobile Chrome) + working-directory: ./frontend + env: + FAST_TESTS: true + SKIP_WEBSERVER: true + PLAYWRIGHT_BROWSERS_PATH: /opt/playwright-browsers + NUXT_SESSION_PASSWORD: "password-with-at-least-32-characters" + VITE_BACKEND_URL: http://localhost:8000 + VITE_API_URL: http://localhost:8000/v1 + VITE_BACKEND_URL_PROXY: http://localhost:8000 + run: sudo -E yarn playwright test --project="Mobile Chrome" + + - name: Upload Playwright Report + if: always() + uses: actions/upload-artifact@v6 + with: + name: playwright-report-mobile + path: frontend/playwright-report/ + retention-days: 30 diff --git a/.github/workflows/pr_ci_frontend.yaml b/.github/workflows/ci_frontend_static_analysis.yaml similarity index 70% rename from .github/workflows/pr_ci_frontend.yaml rename to .github/workflows/ci_frontend_static_analysis.yaml index 90cfff807..85c787121 100644 --- a/.github/workflows/pr_ci_frontend.yaml +++ b/.github/workflows/ci_frontend_static_analysis.yaml @@ -1,4 +1,4 @@ -name: pr_ci_frontend +name: ci_frontend_static_analysis on: workflow_dispatch: pull_request: @@ -17,15 +17,15 @@ on: - "frontend/**" jobs: - frontend: - name: Run PR Frontend Check + frontend_static_analysis: + name: Run PR Frontend Static Check runs-on: ubuntu-latest steps: - name: Checkout Project - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Node environment - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 - name: Install dependencies via Yarn working-directory: ./frontend @@ -33,10 +33,6 @@ jobs: corepack enable sudo yarn install - - name: Install Prettier - working-directory: ./frontend - run: sudo yarn add prettier - - name: Run Prettier - Formatting Check working-directory: ./frontend run: | @@ -51,8 +47,3 @@ jobs: if: always() working-directory: ./frontend run: sudo yarn lint - - - name: Run Vitest - Component Testing - if: always() - working-directory: ./frontend - run: sudo yarn test --coverage --silent diff --git a/.github/workflows/ci_frontend_vitest.yaml b/.github/workflows/ci_frontend_vitest.yaml new file mode 100644 index 000000000..d9931cff5 --- /dev/null +++ b/.github/workflows/ci_frontend_vitest.yaml @@ -0,0 +1,40 @@ +name: ci_frontend_vitest +on: + workflow_dispatch: + pull_request: + branches: + - main + types: + - opened + - reopened + - synchronize + paths: + - "frontend/**" + - "!frontend/test-e2e" + push: + branches: + - main + paths: + - "frontend/**" + - "!frontend/test-e2e" + +jobs: + frontend_tests: + name: Run PR Frontend Tests + runs-on: ubuntu-latest + steps: + - name: Checkout Project + uses: actions/checkout@v6 + + - name: Setup Node environment + uses: actions/setup-node@v5 + + - name: Install dependencies via Yarn + working-directory: ./frontend + run: | + corepack enable + sudo yarn install + + - name: Run Vitest - Component Testing + working-directory: ./frontend + run: sudo yarn test --coverage --silent diff --git a/.github/workflows/ci_i18n_check.yaml b/.github/workflows/ci_i18n_check.yaml new file mode 100644 index 000000000..4665d46bf --- /dev/null +++ b/.github/workflows/ci_i18n_check.yaml @@ -0,0 +1,39 @@ +name: ci_i18n_check +on: + workflow_dispatch: + pull_request: + branches: + - main + types: + - opened + - reopened + - synchronize + paths: + - "frontend/**" + push: + branches: + - main + paths: + - "frontend/**" + +jobs: + i18n_check: + runs-on: ubuntu-latest + steps: + - name: Checkout Project + uses: actions/checkout@v6 + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Install Dependencies + run: uv sync --frozen --all-extras + working-directory: ./backend + + - name: Execute All i18n-check Key-Value Checks + run: uv run --project ./backend i18n-check -a diff --git a/.github/workflows/pr_ci_license_header_check.yaml b/.github/workflows/ci_license_header_check.yaml similarity index 84% rename from .github/workflows/pr_ci_license_header_check.yaml rename to .github/workflows/ci_license_header_check.yaml index f4e37913c..41c7166e4 100644 --- a/.github/workflows/pr_ci_license_header_check.yaml +++ b/.github/workflows/ci_license_header_check.yaml @@ -1,4 +1,4 @@ -name: pr_ci_license_header_check +name: ci_license_header_check on: workflow_dispatch: pull_request: @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Project - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Verify License Headers uses: apache/skywalking-eyes/header@main diff --git a/.github/workflows/ci_ts_backend_check.yaml b/.github/workflows/ci_ts_backend_check.yaml new file mode 100644 index 000000000..b27a51fe1 --- /dev/null +++ b/.github/workflows/ci_ts_backend_check.yaml @@ -0,0 +1,42 @@ +name: ci_ts_backend_check +on: + workflow_dispatch: + pull_request: + branches: + - main + types: + - opened + - reopened + - synchronize + paths: + - "backend/**/model.py" + - "frontend/shared/types/**/*.{ts, d.ts}" + push: + branches: + - main + paths: + - "backend/**/model.py" + - "frontend/shared/types/**/*.{ts, d.ts}" + +jobs: + ts_backend_check: + runs-on: ubuntu-latest + steps: + - name: Checkout Project + uses: actions/checkout@v6 + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + + - name: Install uv + uses: astral-sh/setup-uv@v7 + + - name: Install Dependencies + run: uv sync --frozen --all-extras + working-directory: ./backend + + - name: Check Django Models Against TypeScript Interfaces + run: | + # ts-backend-check -a diff --git a/.github/workflows/owasp_zap_full_scan.yaml b/.github/workflows/owasp_zap_full_scan.yaml index eb7f58826..6c7250ce1 100644 --- a/.github/workflows/owasp_zap_full_scan.yaml +++ b/.github/workflows/owasp_zap_full_scan.yaml @@ -2,7 +2,7 @@ name: OWASP ZAP Optimized Security Scan on: workflow_dispatch: schedule: - - cron: '0 2 * * 1' # Run weekly on Mondays at 2 AM UTC + - cron: "0 2 * * 1" # Run weekly on Mondays at 2 AM UTC jobs: zap_scan: @@ -10,7 +10,7 @@ jobs: name: Security Scan with OWASP ZAP steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Create reports directory with proper permissions run: | @@ -32,7 +32,7 @@ jobs: ls -la zap-reports/ - name: Upload ZAP Scan Results - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: zap-scan-results path: zap-reports/ diff --git a/.github/workflows/pr_ci_i18n.yaml b/.github/workflows/pr_ci_i18n.yaml deleted file mode 100644 index 98b5ae278..000000000 --- a/.github/workflows/pr_ci_i18n.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: pr_ci_i18n -on: - workflow_dispatch: - pull_request: - branches: - - main - types: - - opened - - reopened - - synchronize - paths: - - "frontend/**" - push: - branches: - - main - paths: - - "frontend/**" - -jobs: - i18n_check: - runs-on: ubuntu-latest - steps: - - name: Checkout Project - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - - name: Create Environment and Install Dependencies - run: | - python -m pip install --upgrade uv - uv venv - . .venv/bin/activate - uv pip install -r backend/requirements-dev.txt - echo "$PWD/.venv/bin" >> $GITHUB_PATH - - - name: Execute All i18n-check Key-Value Checks - run: | - i18n-check -a diff --git a/.github/workflows/pr_ci_ts_backend_check.yaml b/.github/workflows/pr_ci_ts_backend_check.yaml deleted file mode 100644 index d109a5ccb..000000000 --- a/.github/workflows/pr_ci_ts_backend_check.yaml +++ /dev/null @@ -1,46 +0,0 @@ -name: pr_ci_ts_backend_check -on: - workflow_dispatch: - pull_request: - branches: - - main - types: - - opened - - reopened - - synchronize - paths: - - "backend/**/model.py" - - "frontend/types/**/*.{ts, d.ts}" - push: - branches: - - main - paths: - - "backend/**/model.py" - - "frontend/types/**/*.{ts, d.ts}" - -jobs: - ts_backend_check: - runs-on: ubuntu-latest - steps: - - name: Checkout Project - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - - name: Create Environment and Install Dependencies - run: | - python -m pip install --upgrade uv - uv venv - . .venv/bin/activate - echo PATH=$PATH >> $GITHUB_ENV - uv pip install -r backend/requirements-dev.txt - - - name: Check Django Models Against TypeScript Interfaces - run: | - # ts-backend-check -bmf backend/authentication/models.py -tsf frontend/types/auth/user.d.ts - # ts-backend-check -bmf backend/communities/groups/models.py -tsf frontend/types/communities/groups.d.ts - # ts-backend-check -bmf backend/communities/organizations/models.py -tsf frontend/types/communities/organizations.d.ts - # ts-backend-check -bmf backend/events/models.py -tsf frontend/types/events/events.d.ts diff --git a/.github/workflows/pr_maintainer_checklist.yaml b/.github/workflows/pr_maintainer_checklist.yaml index f8f189a02..922642d59 100644 --- a/.github/workflows/pr_maintainer_checklist.yaml +++ b/.github/workflows/pr_maintainer_checklist.yaml @@ -14,25 +14,32 @@ jobs: pull-requests: write steps: - name: Thank You Message - uses: thollander/actions-comment-pull-request@v2 + uses: thollander/actions-comment-pull-request@v3 with: message: | ## Thank you for the pull request! ❤️ - The activist team will do our best to address your contribution as soon as we can. If you're not already a member of our [public Matrix community](https://matrix.to/#/#activist_community:matrix.org), please consider joining! We'd suggest that you use the [Element](https://element.io/) client as well as [Element X](https://element.io/app) for a mobile app, and definitely join the `General` and `Development` rooms once you're in. Also consider attending our [bi-weekly Saturday developer syncs](https://etherpad.wikimedia.org/p/activist-dev-sync)! It'd be great to meet you 😊 + The activist team will do our best to address your contribution as soon as we can. The following are some important points: + - Those interested in developing their skills and expanding their role in the community should read the [mentorship and growth section of the contribution guide](CONTRIBUTING.md#mentorship-and-growth-) + - If you're not already a member of our [public Matrix community](https://matrix.to/#/#activist_community:matrix.org), please consider joining! + - We'd suggest that you use the [Element](https://element.io/) client as well as [Element X](https://element.io/app) for a mobile app + - Join the `General` and `Development` rooms once you're in + - Also consider attending our bi-weekly Saturday developer syncs! + - Details are shared in the `Development` room on Matrix each Wednesday before the sync + - It would be great to meet you 😊 > [!NOTE] > activist uses [Conventional Comments](https://conventionalcomments.org/) in reviews to make sure that communication is as clear as possible. - name: Add Checklist - uses: thollander/actions-comment-pull-request@v2 + uses: thollander/actions-comment-pull-request@v3 with: message: | ## Maintainer Checklist The following is a checklist for maintainers to make sure this process goes as well as possible. Feel free to address the points below yourself in further commits if you realize that actions are needed :) - - [ ] The TypeScript, pytest and formatting workflows within the [PR checks](https://github.com/activist-org/activist/pull/${{ github.event.pull_request.number }}/checks) do not indicate new errors in the files changed + - [ ] Tests for changes have been written and the TypeScript, pytest and formatting workflows within the [PR checks](https://github.com/activist-org/activist/pull/${{ github.event.pull_request.number }}/checks) do not indicate new errors in the files changed - [ ] The Playwright end to end and Zap penetration tests have been ran and are passing (if necessary) diff --git a/.gitignore b/.gitignore index 1a496bfe5..e4c8310fc 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,7 @@ frontend/!.yarn/plugins frontend/!.yarn/releases frontend/!.yarn/sdks frontend/!.yarn/versions +**/package-lock.json # Media backend/media/images/* @@ -79,3 +80,6 @@ backend/media/images/* # ZAP Security Reports zap-reports/ frontend/test-e2e/.auth/ + +# Snyk Security Extension +.cursor/rules/snyk_rules.mdc diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5a96a9643..6a19b36a2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,21 +28,12 @@ repos: files: ^backend/ exclude: ^backend/(.*/?(tests(/.*)?|views\.py|__init__\.py))$ - - repo: https://github.com/to-sta/spdx-checker-pre-commit - rev: 0.1.3 - hooks: - - id: spdx-license-checker - name: run spdx-checker license check - exclude: ^(?:.*/)?__init__\.py$ - args: [-l, AGPL-3.0-or-later] - types_or: [python, ts, javascript, vue, css, html] - - repo: local hooks: - id: mypy-check name: run mypy static type checking files: ^backend/ - entry: mypy ./backend --config-file ./backend/pyproject.toml + entry: uv run mypy ./backend --config-file ./backend/pyproject.toml language: python types: [python] pass_filenames: false @@ -57,8 +48,17 @@ repos: - id: run-i18n-check name: run i18n-check key-value checks files: ^frontend/ - entry: i18n-check -a + entry: uv run i18n-check -a language: python pass_filenames: false additional_dependencies: - i18n-check + + - repo: https://github.com/to-sta/spdx-checker-pre-commit + rev: 0.1.7 + hooks: + - id: spdx-license-checker + name: run spdx-checker license check + exclude: ^(?:.*/)?__init__\.py$ + args: [-l, AGPL-3.0-or-later, --fix, --continue-on-error] + types_or: [python, ts, javascript, vue, css, html] diff --git a/.prettierignore b/.prettierignore index 90b5b4b4d..9bc57f501 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,6 +4,7 @@ node_modules/ venv/ dist/ +coverage/ playwright-report/ tests-examples/ test-results/ diff --git a/BACKEND_TESTING.md b/BACKEND_TESTING.md index d93f0c0d6..54daf3f6c 100644 --- a/BACKEND_TESTING.md +++ b/BACKEND_TESTING.md @@ -1,16 +1,14 @@ + + # Backend Testing This documentation details standards for writing pytest based backend testing files. - - -## **Contents** +## Contents - [Standards](#standards-) - - -## Standards [`⇧`](#contents) +## Standards - All tests for backend applications should be in a `tests` sub directory - Testing files should be named `test_ENTITY_{MODEL_SUB_CLASS}_CRUD_METHOD`, with the `MODEL_SUB_CLASS` being optional @@ -30,3 +28,5 @@ This documentation details standards for writing pytest based backend testing fi - Start with the name of the file - End with the response code that is being tested if there is only one - If there is only one API endpoint used in a testing file, it should be defined as a `SCREAMING_SNAKE_CASE` variable at the top of the file + +Back to top. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 231cc566e..0ec4e2ef0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,38 +1,36 @@ + + # Contributing to activist.org Thank you for contributing to activist! Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved. -Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open-source project. In return, and in accordance with this project's [code of conduct](.github/CODE_OF_CONDUCT.md), other contributors will reciprocate that respect in addressing your issue or assessing patches and features. +Following this guide helps to communicate that you respect the time of the developers managing and developing this open-source project. In return, and in accordance with this project's [code of conduct](.github/CODE_OF_CONDUCT.md), other contributors will reciprocate that respect in addressing your issue or assessing patches and features. If you have questions or would like to communicate with the team, please [join us in our public Matrix chat rooms](https://matrix.to/#/#activist_community:matrix.org). We'd be happy to hear from you! - - -## **Contents** - -- [First steps as a contributor](#first-steps-) -- [Tech stack](#tech-stack-) -- [Learning the tech stack](#learning-the-tech-stack-) -- [Development environment](#dev-env-) -- [Style guide](#style-guide-) -- [Linting](#linting-) -- [Testing](#testing-) -- [Issues and projects](#issues-projects-) -- [Bug reports](#bug-reports-) -- [Feature requests](#feature-requests-) -- [Pull requests](#pull-requests-) -- [Localization](#localization-) -- [Documentation](#documentation-) -- [Accessibility](#accessibility-) -- [Internationalization](#internationalization-) -- [Design](#design-) -- [Troubleshooting](#troubleshooting-) - - - -## First steps as a contributor [`⇧`](#contents) +## Contents + +- [First steps as a contributor](#first-steps-as-a-contributor) +- [Mentorship and growth](#mentorship-and-growth) +- [Tech stack](#tech-stack) +- [Learning the tech stack](#learning-the-tech-stack) +- [Development environment](#development-environment) +- [Style guide](#style-guide) +- [Linting](#linting) +- [Testing](#testing) +- [Issues and projects](#issues-and-projects) +- [Bug reports](#bug-reports) +- [Feature requests](#feature-requests) +- [Pull requests](#pull-requests) +- [Internationalization](#internationalization) +- [Documentation](#documentation) +- [Accessibility](#accessibility) +- [Design](#design) +- [Troubleshooting](#troubleshooting) + +## First steps as a contributor Thank you for your interest in contributing to activist.org! We look forward to welcoming you to the community and working with you to build a global platform for political action :) The following are some suggested steps for people interested in joining our community: @@ -44,11 +42,23 @@ Thank you for your interest in contributing to activist.org! We look forward to - Read through this contributing guide and the [style guide](STYLEGUIDE.md) for all the information you need to contribute - Look into issues marked [`good first issue`](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) and the [Projects board](https://github.com/orgs/activist-org/projects/1) to get a better understanding of what you can work on - Check out our [public designs on Figma](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_public_designs?type=design&node-id=10%3A18&mode=design&t=tdQyOtl5lU1n7oLN-1) to understand activist's goals and direction -- Consider joining our [bi-weekly developer sync](https://etherpad.wikimedia.org/p/activist-dev-sync)! +- Consider joining our bi-weekly developer sync — new joiners are always welcome! + +Back to top. - +## Mentorship and growth -## Tech Stack [`⇧`](#contents) +Onboarding and mentoring new members are integral parts of any healthy open-source community. We need those who are onboarded to gain new skills and take on greater roles of triaging issues, reviewing contributions and maintaining the project. We also need them to help those who follow do the same. Please let us know if you have such goals and we'll work with you to achieve them. + +The above includes expectations on the behavior of those who want to grow with us. Mentorship is earned, not given. To be blunt, those who are mainly sending AI generated contributions are not demonstrating an interest in growing their skills and are not helping to develop the project. This is not to say that all uses of AI for contributions are bad, but it should be a tool, not the contributor itself. + +Continued constructive contributions, new open issues and communication that provides context for maintainers help them do their work immensely. We would be happy to help such community members expand their skills and take on further responsibilities. + +If the above resonates with you, then we look forward to working with you! + +Back to top. + +## Tech stack The following are the current and planned technologies for [activist.org](https://activist.org): @@ -62,7 +72,11 @@ The following are the current and planned technologies for [activist.org](https: ### Deployment -- [Docker](https://www.docker.com) • [Netlify](https://www.netlify.com) • [Vitest](https://vitest.dev/) +- [Docker](https://www.docker.com) • [Netlify](https://www.netlify.com) + +### Deployment + +[pytest](https://docs.pytest.org/en/stable/) (backend) • [Vitest](https://vitest.dev/) (frontend) • [Playwright](https://playwright.dev/) (end to end) ### Localization @@ -75,9 +89,9 @@ The following are the current and planned technologies for [activist.org](https: > [!NOTE] > Those new to any frameworks or technologies who want to work on their skills are more than welcome to contribute! - +Back to top. -## Learning the tech stack [`⇧`](#contents) +## Learning the tech stack activist is very open to contributions from people in the early stages of their coding journey! The following is a select list of documentation pages to help you understand the technologies we use. @@ -123,9 +137,9 @@ activist is very open to contributions from people in the early stages of their

- +Back to top. -## Development environment [`⇧`](#contents) +## Development environment > [!NOTE] > Windows users should be aware that Docker development requires [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/windows/wsl/) version 2 or higher. The community would suggest that you clone the repository directly into your WSL environment. @@ -196,20 +210,19 @@ git remote add upstream https://github.com/activist-org/activist.git - `origin` (forked repository) - `upstream` (activist repository) -4. Create a virtual environment for the backend (Python `>=3.11`), activate it and install dependencies: +> [!NOTE] +> First, install `uv` if you don't already have it by following the [official installation guide](https://docs.astral.sh/uv/getting-started/installation/). + +4. Create a virtual environment for the backend (Python `>=3.12`), activate it and install dependencies: ```bash - python3 -m venv venv + cd backend && uv sync --all-extras # create .venv and install all dependencies from uv.lock - # Unix or MacOS: - source venv/bin/activate + # Unix or macOS: + source .venv/bin/activate # Windows: - venv\Scripts\activate.bat - - # After activating venv: - pip install --upgrade pip - pip install -r backend/requirements-dev.txt + .venv\Scripts\activate.bat # .venv\Scripts\activate.ps1 (PowerShell) ``` 5. Start your docker images with the following: @@ -231,8 +244,6 @@ git remote add upstream https://github.com/activist-org/activist.git > [!NOTE] > Feel free to contact the team in the [Development room on Matrix](https://matrix.to/#/!CRgLpGeOBNwxYCtqmK:matrix.org?via=matrix.org&via=acter.global&via=chat.0x7cd.xyz) if you're having problems getting your environment setup! - - ### Using Yarn or Python Dockerized environments are resource intensive - specifically for some Windows users - and may take a very long time to load. If you would like to get just the frontend or backend up and running, please follow the steps below: @@ -249,6 +260,9 @@ cd frontend # Set the environment variables: set -a && source ../.env.dev && set +a +# Install corepack on your machine globally: +npm install -g corepack + # Install and run the project: corepack enable yarn install @@ -292,22 +306,13 @@ From here we need the project's dependencies, with the practice being to create On Unix or MacOS, run: ```bash -python3 -m venv venv # make an environment named venv -source venv/bin/activate # activate the environment -``` +cd backend && uv sync --all-extras # create .venv and install all dependencies from uv.lock -On Windows (using Command Prompt), run: +# Unix or macOS: +source .venv/bin/activate -```bash -python -m venv venv -venv\Scripts\activate.bat -``` - -After activating the virtual environment, install the required dependencies by running: - -```bash -pip install --upgrade pip # make sure that pip is at the latest version -pip install -r backend/requirements-dev.txt # install dependencies +# Windows: +.venv\Scripts\activate.bat # .venv\Scripts\activate.ps1 (PowerShell) ``` Now you can apply the database migrations and fixtures, populate it with sample data, and start the local development server. @@ -335,9 +340,7 @@ You can then visit to see the development backend

- - +Back to top. -## Style guide [`⇧`](#contents) +## Style guide -Please see the [activist style guide](STYLEGUIDE.md) for details about how to follow the code style for the project. We made these guidelines to assure that we as a community write clean, cohesive code that's easy to write and review. Suggestions for the style guide are welcome. +Please see the [activist style guide](STYLEGUIDE.md) for details about how to follow the code style for the project. We made this guide to assure that we as a community write clean, cohesive code that's easy to write and review. Suggestions for the style guide are welcome. - +Back to top. -## Linting [`⇧`](#contents) +## Linting For the backend [Ruff](https://github.com/astral-sh/ruff) is installed via the required packages to assure that errors are reported correctly. We'd also suggest that VS Code users install the [Ruff extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff). For the frontend [eslint](https://eslint.org/), [eslint-vue](https://eslint.vuejs.org/) and [vue-a11y](https://vue-a11y.github.io/eslint-plugin-vuejs-accessibility/) are added via the dependencies to provide linting support. - +Back to top. -## Testing [`⇧`](#contents) +## Testing ### Backend @@ -383,13 +386,13 @@ docker compose --env-file .env.dev up backend --build -d # -d to hide logs docker exec -it django_backend sh # Run backend tests: -pytest +uv run pytest # To run a specific test: -pytest path/to/test_file.py::test_function +uv run pytest path/to/test_file.py::test_function # To run with a coverage report as is done in PRs: -pytest --cov --cov-report=term-missing --cov-config=pyproject.toml -vv +uv run pytest --cov --cov-report=term-missing --cov-config=pyproject.toml -vv # Once tests are finished: exit @@ -434,7 +437,7 @@ yarn test --silent If you would like to run a specific test, please run the following command: ```bash -yarn vitest FILE.spec.ts --run +yarn test FILE.spec.ts --run ``` Please see the [frontend testing guide](FRONTEND_TESTING.md) for information on how to write component tests. @@ -446,14 +449,14 @@ Please see the [frontend testing guide](FRONTEND_TESTING.md) for information on #### Run Local E2E Tests -activist uses [Playwright](https://playwright.dev/) for end to end testing. You'll first need to install/update the browsers installed for Playwright as described in their [updating Playwright documentation](https://playwright.dev/docs/intro#updating-playwright). Please run the following command in the frontend: +activist uses [Playwright](https://playwright.dev/) for end to end testing. You'll first need to install/update the browsers installed for Playwright as described in their [updating Playwright documentation](https://playwright.dev/docs/intro#updating-playwright). Run the following command in the frontend: ```bash # This and all following steps need to be ran each time Playwright is updated. yarn playwright install --with-deps ``` -Please run the following to run the end to end testing suite: +Run the following to run the end to end testing suite: ```bash # Note: There may be an installation prompts in the build logs. Hit 'n' to say no. @@ -467,21 +470,22 @@ yarn playwright show-report # Note: If you stop the script before it finishes, please run the following to stop all background processes: docker compose --env-file .env.dev down -yarn kill-port 3000 +lsof -ti tcp:3000 | xargs kill -9 2>/dev/null || true ``` -Alternatively, to run the end to end tests using the separate commands, please run the following: +> [!NOTE] +> VS Code users can use the [Playwright extension](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) to run the tests. Go to the testing view and then run the test suite. You can also select options including which devices to run and whether to view the browser. -```bash -docker compose --env-file .env.dev up backend db # run backend and db in docker +Alternatively, to run the end to end tests using separate shells, please run the following: + +In a first shell, start the backend and database: -# To run tests in the preview mode (much faster and uses less resources): +```bash +# Start backend and db (USE_PREVIEW skips the full build inside Docker): USE_PREVIEW=true docker compose --env-file .env.dev up backend db ``` -In order to test locally, you need to build the production version of the frontend as directed in the [local build directions](#using-yarn-or-python-). - -In a second shell: +In a second shell, build and serve the frontend in preview mode: ```bash cd frontend @@ -489,28 +493,35 @@ cd frontend # Set the environment variables: set -a && source ../.env.dev && set +a -# Install and run the project in production mode: +# USE_PREVIEW=true switches Nitro to node-server preset (outputs to .output/) +# so that `yarn preview` works. Without it the build uses netlify-static (dist/). +export USE_PREVIEW=true + +# Install dependencies and build + serve the frontend in preview mode: corepack enable yarn install -yarn build # answer no to all package installation prompts +# Remove any previous static build so nuxi preview uses .output/ not dist/. +rm -rf dist +yarn build:local # answer no to all package installation prompts # Note: There may be an installation prompt high in the build logs. Hit 'n' to say no. - -# Note: You may be asked to install extra dependencies in the next command. -npx serve dist/ # start the frontend +# Start the node server directly - this ensures NUXT_SESSION_PASSWORD and NUXT_API_SECRET +# are passed correctly (yarn preview can strip env vars in some shells). +nohup env NUXT_SESSION_PASSWORD="$NUXT_SESSION_PASSWORD" NUXT_API_SECRET="" node .output/server/index.mjs > /dev/null 2>&1 & ``` -In a third shell: +In a third shell, run the test suite: ```bash cd frontend -yarn test:local +# SKIP_WEBSERVER tells Playwright to reuse the running preview server: +SKIP_WEBSERVER=true yarn test:local # After the tests finish, run the following to see the Playwright HTML report: yarn playwright show-report ``` -Or, instead of the third shell, you can also run the whole suite or run individual tests using Playwright's VS Code extension. You can find a link in the [Development environment](#dev-env-) section, under Suggested IDE setup. +Or, instead of the third shell, you can also run the whole suite or run individual tests using Playwright's VS Code extension. You can find a link in the [Development environment](#development-environment) section, under Suggested IDE setup. Thank you for testing locally! ✨ @@ -526,7 +537,7 @@ For testing on your remote forked repository, first create a branch from the rem git push upstream : ``` -You can then navigate to the remote versions of the [actions of the repository](https://github.com/activist-org/activist/actions) in your fork and trigger [pr_ci_playwright_e2e](https://github.com/activist-org/activist/actions/workflows/pr_ci_playwright_e2e.yaml). +You can then navigate to the remote versions of the [actions of the repository](https://github.com/activist-org/activist/actions) in your fork and trigger [ci_playwright_e2e](https://github.com/activist-org/activist/actions/workflows/ci_playwright_e2e.yaml). For maintainers of the activist main repo, testing PRs is done via the following to make sure that origin has a copy of the branch that can be tested against: @@ -536,13 +547,13 @@ git branch # to find the name of the branch git push -u origin LOCAL_NAME_OF_BRANCH ``` -You can then visit the [actions of the repository](https://github.com/activist-org/activist/actions) to run the the [pr_ci_playwright_e2e](https://github.com/activist-org/activist/actions/workflows/pr_ci_playwright_e2e.yaml) test against the new branch on origin. +You can then visit the [actions of the repository](https://github.com/activist-org/activist/actions) to run the the [ci_playwright_e2e](https://github.com/activist-org/activist/actions/workflows/ci_playwright_e2e.yaml) test against the new branch on origin. Thank you for testing your PRs! 🎉 - +Back to top. -## Issues and projects [`⇧`](#contents) +## Issues and projects The [issue tracker for activist](https://github.com/activist-org/activist/issues) is the preferred channel for [bug reports](#bug-reports), [features requests](#feature-requests) and [submitting pull requests](#pull-requests). activist also organizes related issues into [projects](https://github.com/activist-org/activist/projects). @@ -553,7 +564,7 @@ Be sure to check the [`-next release-`](https://github.com/activist-org/activist -## Bug reports [`⇧`](#contents) +## Bug reports A bug is a _demonstrable problem_ that is caused by the code in the repository. Good bug reports are extremely helpful — thank you! @@ -577,15 +588,15 @@ To make the above steps easier, the activist team asks that contributors report Again, thank you for your time in reporting issues! - +Back to top. -## Feature requests [`⇧`](#contents) +## Feature requests Feature requests are more than welcome! Please take a moment to find out whether your idea fits with the scope and aims of the project. When making a suggestion, provide as much detail and context as possible, and further make clear the degree to which you would like to contribute in its development. Feature requests are marked with the [`Feature`](https://github.com/activist-org/activist/issues?q=is%3Aissue%20state%3Aopen%20type%3AFeature) type in the [issues](https://github.com/activist-org/activist/issues). - +Back to top. -## Pull requests [`⇧`](#contents) +## Pull requests Good pull requests — patches, improvements and new features — are the foundation of our community making activist. They should remain focused in scope and avoid containing unrelated commits. Note that all contributions to this project will be made under [the specified license](LICENSE.txt) and should follow the coding indentation and style standards (contact us if unsure). @@ -606,25 +617,21 @@ When making a contribution, adhering to the [GitHub flow](https://docs.github.co git checkout -b ``` -3. Install [pre-commit](https://pre-commit.com/) to ensure that each of your commits is properly checked against our linter and formatters: +3. Install [prek](https://prek.j178.dev/) to ensure that each of your commits is properly checked against our linter and formatters: ```bash # In the project root: - pre-commit install + prek install # Then test the pre-commit hooks to see how it works: - pre-commit run --all-files + prek run --all-files ``` > [!NOTE] -> pre-commit is Python package that can be installed via pip or any other Python package manager. You can also find it in our [requirements-dev.txt](backend/requirements-dev.txt) file. -> -> ```bash -> pip install pre-commit -> ``` +> prek is Python package that can be installed via pip or any other Python package manager. You can also find it in our [uv.lock](backend/uv.lock) file. > [!NOTE] -> If you are having issues with pre-commit and want to send along your changes regardless, you can ignore the pre-commit hooks via the following: +> If you are having issues with prek and want to send along your changes regardless, you can ignore the pre-commit hooks via the following: > > ```bash > git commit --no-verify -m "COMMIT_MESSAGE" @@ -654,41 +661,53 @@ When making a contribution, adhering to the [GitHub flow](https://docs.github.co Thank you in advance for your contributions! - +Back to top. -## Localization [`⇧`](#contents) +## Documentation - - Visit Weblate project - +Documentation is an invaluable way to contribute to coding projects as it allows others to more easily understand the project structure and contribute. Issues related to documentation are marked with the [`documentation`](https://github.com/activist-org/activist/labels/documentation) label in the [issues](https://github.com/activist-org/activist/issues). -Localization for activist happens on our [public localization project on Weblate](https://hosted.weblate.org/projects/activist/activist). Join us there if you'd like to help bring activist to other languages! +### Backend Function Docstrings -To find issues related to localization, please see the [`localization`](https://github.com/activist-org/activist/issues?q=is%3Aopen+is%3Aissue+label%3Alocalization) label in the [issues](https://github.com/activist-org/activist/issues), and to report a localization issue use the [localization issue form](https://github.com/activist-org/activist/issues/new?assignees=&labels=localization&projects=activist-org%2F1&template=localization.yml). Please also see the [style guide](STYLEGUIDE.md) for more information on how to create new localization keys. +activist follows [numpydoc conventions](https://numpydoc.readthedocs.io/en/latest/format.html) for documenting functions and Python code. -> [!IMPORTANT] -> If you're having issues with the vue/nuxt i18n `$t` local property not being picked up by TypeScript and being reported as invalid/not existing across the codebase, then please add the following file at `frontend/types/vue-i18n.d.ts`: -> -> ```ts -> // frontend/types/vue-i18n.d.ts -> // Attn: Fixes Property '$t' does not exist on type ... errors. -> // Note: This file is git ignored, but can be used as a local fix for excessive TypeScript errors. -> declare module "vue" { -> interface ComponentCustomProperties { -> $t: (key: string) => string; -> } -> } -> ``` +You can use [prek](https://prek.j178.dev/) to run the numpydoc docstring linting: + +```bash +prek run numpydoc-validation --all-files +``` - +Function docstrings should have this format: -## Documentation [`⇧`](#contents) +```py +def example_function(argument: argument_type) -> return_type: + """ + An example docstring for a function so others understand your work. -Documentation is an invaluable way to contribute to coding projects as it allows others to more easily understand the project structure and contribute. Issues related to documentation are marked with the [`documentation`](https://github.com/activist-org/activist/labels/documentation) label in the [issues](https://github.com/activist-org/activist/issues). + Parameters + ---------- + argument : argument_type + Description of your argument. - + Returns + ------- + return_value : return_type + Description of your return value. -## Accessibility [`⇧`](#contents) + Raises + ------ + ErrorType + Description of the error and the condition that raises it. + """ + + ... + + return return_value +``` + +Back to top. + +## Accessibility Thank you for your interest in improving activist's accessibility. We want our platform to not only be usable for all people, but also to provide a welcoming environment within the development community for all. This section lists a few points to account for when checking accessibility constraints during development: @@ -717,31 +736,51 @@ Tab focusing sadly doesn't work out of the box for many browsers. Chrome works g Once the above steps are finished you should be able to use tab to navigate web pages :) - +Back to top. + +## Internationalization + +### Weblate + + + Visit Weblate project + + +Localization for activist happens on our [public localization project on Weblate](https://hosted.weblate.org/projects/activist/activist). Join us there if you'd like to help bring activist to other languages! + +To find issues related to localization, please see the [`localization`](https://github.com/activist-org/activist/issues?q=is%3Aopen+is%3Aissue+label%3Alocalization) label in the [issues](https://github.com/activist-org/activist/issues), and to report a localization issue use the [localization issue form](https://github.com/activist-org/activist/issues/new?assignees=&labels=localization&projects=activist-org%2F1&template=localization.yml). Please also see the [style guide](STYLEGUIDE.md) for more information on how to create new localization keys. + +> [!IMPORTANT] +> If you're having issues with the vue/nuxt i18n `$t` local property not being picked up by TypeScript and being reported as invalid/not existing across the codebase, then please add the following file at `frontend/types/vue-i18n.d.ts`: +> +> ```ts +> // frontend/types/vue-i18n.d.ts +> // Attn: Fixes Property '$t' does not exist on type ... errors. +> // Note: This file is git ignored, but can be used as a local fix for excessive TypeScript errors. +> declare module "vue" { +> interface ComponentCustomProperties { +> $t: (key: string) => string; +> } +> } +> ``` -## Internationalization [`⇧`](#contents) +### i18n-check activist uses [i18n-check](https://github.com/activist-org/i18n-check) to validate our internationalization key-value pairs. The basic commands to check the i18n keys and values are: ```bash -# Note: You need to have installed the backend/requirements-dev.txt file in your virtual environment. +# Note: You need to have installed the uv.lock file in your virtual environment. +i18n-check -h # see the help i18n-check -a # run all checks -i18n-check -ki # run key identifiers check -i18n-check -ik # run invalid keys check -i18n-check -uk # run unused keys check -i18n-check -nsk # run non-source keys check -i18n-check -rk # run repeat keys check -i18n-check -rv # run repeat values check -i18n-check -nk # run nested keys check ``` You can also run individual checks. Please see the [documentation for i18n-check](https://i18n-check.readthedocs.io/en/latest/) to learn more. If you do need to edit the directories and files skipped by certain checks, then these edits can be made in the [.i18n-check.yaml](./.i18n-check.yaml) file. If you're having issues using `i18n-check`, please feel free to contact the team for support! - +Back to top. -## Design [`⇧`](#contents) +## Design Public Figma Designs @@ -753,9 +792,9 @@ Note that the linked Figma file above is the [public facing designs](https://www All branding elements such as logos, icons, colors and fonts should follow those that are set out in [activist-org/Organization](https://github.com/activist-org/Organization). As the project is fully open source, these elements are also open for discussion. Your efforts in making activist products professional with a distinct and cohesive identity are much appreciated. - +Back to top. -## Troubleshooting [`⇧`](#contents) +## Troubleshooting ### Nuxt Auto Import Errors @@ -811,8 +850,10 @@ brew services stop postgresql 2. Locate **PostgreSQL** in the list 3. Right-click and choose **Stop** -Once stopped, you can safely run Docker services like the Docker Compose commands in the [Development Environment](#dev-env-) section. +Once stopped, you can safely run Docker services like the Docker Compose commands in the [Development Environment](#development-environment) section. ### Still experiencing problems? Please feel free to reach out to the team in the [Development room on Matrix](https://matrix.to/#/!CRgLpGeOBNwxYCtqmK:matrix.org?via=matrix.org&via=systemli.org&via=librezo.fr) if you have a question! + +Back to top. diff --git a/FRONTEND_TESTING.md b/FRONTEND_TESTING.md index a2f30f321..4adbc3511 100644 --- a/FRONTEND_TESTING.md +++ b/FRONTEND_TESTING.md @@ -1,14 +1,17 @@ -# Frontend Testing + - +# Frontend Testing -## **Contents** -- [End to End Tests](#end-to-end-tests-) -- [Component and Unit Tests](#component-and-unit-tests-) +## Contents - +- [End to End Tests](#end-to-end-tests) + - [What to Test](#what-to-test) + - [Where to Write Tests](#where-to-write-tests) + - [Best Practices](#best-practices) + - [Checking E2E coverage](#checking-e2e-coverage) +- [Component and Unit Tests](#component-and-unit-tests) -## End to End Tests [`⇧`](#contents) +## End to End Tests End to End Tests (E2E) are used to ensure that the whole application (frontend, backend, database, etc.) functions together correctly. E2E tests are very useful, but they have some important drawbacks: @@ -29,6 +32,8 @@ Not every test belongs in the E2E test suite. Tests that should go in the E2E te - Putting a url in the user's clipboard 4. Browser-specific bugs +Back to top. + ### Where to write tests Write your tests under `frontend/test-e2e/specs`. Inside this folder are more folders based on the environment the tests are meant to run in: @@ -51,11 +56,13 @@ test.describe("Home Page", { tag: ["@desktop"] }, () => { }); ``` -### Best practices +Back to top. + +### Best Practices We recommend following [playwright's best practices](https://playwright.dev/docs/best-practices) and locating UI elements by their accessible names when possible. -### Avoid complicated design patterns +#### Avoid complicated design patterns We want the E2E test suite to be as easy to read as possible. That means most of the logic of a test should be in the test itself, and not hidden in classes or methods. @@ -80,9 +87,35 @@ The steps to do this are: 2. Move that function into a file in `frontend/test-e2e/actions` and name it based on the action being performed 3. Import the function into the test files where you use it - +Back to top. + +### Checking E2E coverage + +To see which application routes are covered by the E2E test suite, run the coverage script from the `frontend/` directory: + +```bash +# Terminal output (colored, with coverage summary): +node test-e2e/scripts/e2e-coverage.mjs + +# GitHub-flavored markdown (for pasting into issues or PRs): +node test-e2e/scripts/e2e-coverage.mjs --markdown + +# Only show uncovered testable routes: +node test-e2e/scripts/e2e-coverage.mjs --uncovered -## Component and Unit Tests [`⇧`](#contents) +# Machine-readable JSON output: +node test-e2e/scripts/e2e-coverage.mjs --json +``` + +The script distinguishes between: + +- **Covered routes** — routes with at least one `goto`, `waitForURL`, or `toHaveURL` assertion in specs, actions, or page objects +- **Stub routes** — pages marked `:underDevelopment="true"` with no implemented UI (excluded from the testable coverage calculation) +- **Uncovered testable routes** — implemented routes that have no E2E coverage yet + +Back to top. + +## Component and Unit Tests For component and unit tests we are using Vitest and Vue Testing Library. For a general overview on how to write these tests, see the documentation for the [Testing Library Frameworks](https://testing-library.com/docs/). @@ -109,3 +142,190 @@ We recommend using mocking for dependencies that are unreliable and/or slow, lik * We provide a global mock for `useColorMode`. This is necessary because `useColorMode` currently does not work in Vitest. See example use in [useColor.spec.ts](frontend/test/composables/useColor.spec.ts). * Nuxt provides a `registerEndpoint` function to mock network requests. See example use in [sign-in.spec.ts](frontend/test/pages/auth/sign-in.spec.ts). + +### 4. Mocking Composables + +When testing components or composables that use Nuxt composables (like `useRoute`, `useRouter`, `useLocalePath`, `useAuth`, etc.), we use a factory-based mocking approach to make test dependencies explicit and maintainable. + +#### Factory Functions + +All composable mock factories are located in [`frontend/test/mocks/composableMocks.ts`](frontend/test/mocks/composableMocks.ts). These factories allow tests to explicitly define their mock needs using reusable functions. + +**Available factories:** +- `createUseRouteMock()` - For mocking `useRoute()` +- `createUseRouterMock()` - For mocking `useRouter()` +- `createUseLocalePathMock()` - For mocking `useLocalePath()` +- `createUseAuthMock()` - For mocking `useAuth()` +- `createUseUserMock()` - For mocking `useUser()` +- `createUseDeviceMock()` - For mocking `useDevice()` +- `createUseColorModeSpy()` - For mocking `useColorMode()` (returns a spy function) +- `createUseSidebarSpy()` - For mocking `useSidebar()` (returns a spy function) +- And more... + +#### Mocking Patterns + +We use five main patterns for mocking composables: + +##### Pattern 1: Use Auto-Mock (Default Behavior) + +When a composable doesn't affect your test behavior, you can rely on the automatic `{}` mock provided by `setupAutoImportMocks()`. This is the simplest approach and requires no explicit setup. + +**When to use:** The composable is used by the component but doesn't affect test assertions. + +**Example:** +```typescript +// No explicit mock needed - auto-mock {} is sufficient. +describe("MyComponent", () => { + it("renders correctly", async () => { + await render(MyComponent); + // Component uses useRoute() internally, but test doesn't check route behavior. + }); +}); +``` + +##### Pattern 2: Import Factory and Use It + +When you need specific return values but don't need to track calls, use the factory functions directly. + +**When to use:** You need specific mock data (e.g., route params, user data) but don't need to verify calls. + +**Example:** +```typescript +import { createUseRouteMock } from "../../mocks/composableMocks"; + +// Set up useRoute with specific params. +globalThis.useRoute = createUseRouteMock( + { id: "123" }, // params + { filter: "active" }, // query + "/events/123", // path + "events-id" // name (optional) +); + +describe("MyComponent", () => { + it("displays event ID from route", async () => { + await render(MyComponent); + expect(screen.getByText("123")).toBeTruthy(); + }); +}); +``` + +**Real example:** See [ModalBase.spec.ts](frontend/test/components/modal/ModalBase.spec.ts) + +##### Pattern 3: Override with Spy for Call Tracking + +When you need to verify that a composable was called with specific arguments, use `vi.stubGlobal()` with a spy function. + +**When to use:** You need to assert that a composable was called with specific parameters. + +**Example:** +```typescript +import { beforeEach, describe, expect, it, vi } from "vitest"; + +describe("BtnRouteInternal", () => { + const mockLocalePath = vi.fn((path: string) => `/en${path}`); + + beforeEach(() => { + vi.stubGlobal("useLocalePath", () => mockLocalePath); + mockLocalePath.mockClear(); + }); + + it("calls useLocalePath with correct path", async () => { + await render(BtnRouteInternal, { props: { linkTo: "/test" } }); + expect(mockLocalePath).toHaveBeenCalledWith("/test"); + }); +}); +``` + +**Real example:** See [BtnRouteInternal.spec.ts](frontend/test/components/btn/route/BtnRouteInternal.spec.ts) + +##### Pattern 4: Use mockImplementation() on Spy Functions + +When a composable is set up as a spy function in `setup.ts` (like `useColorMode`), you can use `mockImplementation()` to change return values per test. + +**When to use:** You need different return values for different test cases, and the composable is already set up as a spy. + +**Example:** +```typescript +describe("useColor", () => { + it("handles light mode", () => { + globalThis.useColorModeMock.mockImplementation(() => ({ + preference: "light", + value: "light", + })); + + const { getColorModeImages } = useColor(); + expect(getColorModeImages("/path/to/image")).toEqual("/path/to/image_light.png"); + }); + + it("handles dark mode", () => { + globalThis.useColorModeMock.mockImplementation(() => ({ + preference: "dark", + value: "dark", + })); + + const { getColorModeImages } = useColor(); + expect(getColorModeImages("/path/to/image")).toEqual("/path/to/image_dark.png"); + }); +}); +``` + +**Real example:** See [useColor.spec.ts](frontend/test/composables/useColor.spec.ts) + +##### Pattern 5: Set Defaults in beforeEach, Override Per-Test + +Combine factory functions in `beforeEach` with per-test overrides when needed. + +**When to use:** Most tests need the same mock, but some tests need different values. + +**Example:** +```typescript +import { createUseRouteMock } from "../../mocks/composableMocks"; + +describe("MyComponent", () => { + beforeEach(() => { + // Default setup for most tests. + globalThis.useRoute = createUseRouteMock({}, {}, "/default"); + }); + + it("handles default route", async () => { + await render(MyComponent); + // Uses default mock. + }); + + it("handles specific route params", async () => { + // Override for this specific test. + globalThis.useRoute = createUseRouteMock({ id: "456" }, {}, "/specific"); + await render(MyComponent); + // Uses specific mock. + }); +}); +``` + +#### Decision Guide + +**Which pattern should I use?** + +1. **Pattern 1 (Auto-mock)**: Composable doesn't affect test behavior +2. **Pattern 2 (Factory)**: Need specific mock data, no call tracking needed +3. **Pattern 3 (Spy)**: Need to verify composable was called with specific args +4. **Pattern 4 (mockImplementation)**: Composable is already a spy, need different values per test +5. **Pattern 5 (beforeEach + override)**: Most tests share defaults, some need overrides + +#### Best Practices + +- **Make dependencies explicit**: If a composable affects your test, explicitly mock it using a factory +- **Use factories for reusability**: Import from `composableMocks.ts` rather than creating inline mocks +- **Keep it simple**: Use Pattern 1 when defaults are sufficient +- **Document your choice**: Add a comment explaining why you chose a specific pattern if it's not obvious + +#### Infrastructure-Dependent Mocks + +Some composables are set up globally in `setup.ts` because they require infrastructure setup: +- `useI18n` - Requires i18n instance +- `useColorMode` - Set up as spy for per-test overrides +- `useSidebar` - Set up as spy for per-test overrides +- `useAuthState` - Requires global data reference + +These don't need explicit setup in individual tests unless you need to override their behavior. + +Back to top. diff --git a/README.md b/README.md index a384b3eea..62d247443 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ + +
activist Logo
@@ -16,47 +18,58 @@ [![matrix](https://img.shields.io/badge/Matrix-000000.svg?logo=matrix&logoColor=ffffff)](https://matrix.to/#/#activist_community:matrix.org) [![testing](https://img.shields.io/badge/Testing-F0F0EB.svg?logo=github&logoColor=000000)](https://github.com/activist-org/activist/actions) -[![ci_backend](https://img.shields.io/github/actions/workflow/status/activist-org/activist/pr_ci_backend.yaml?branch=main&label=backend)](https://github.com/activist-org/activist/actions/workflows/pr_ci_backend.yaml) -[![ci_frontend](https://img.shields.io/github/actions/workflow/status/activist-org/activist/pr_ci_frontend.yaml?branch=main&label=frontend)](https://github.com/activist-org/activist/actions/workflows/pr_ci_frontend.yaml) -[![ci_i18n](https://img.shields.io/github/actions/workflow/status/activist-org/activist/pr_ci_i18n.yaml?branch=main&label=i18n)](https://github.com/activist-org/activist/actions/workflows/pr_ci_i18n.yaml) - - - -### An open-source activism platform +[![ci_e2e_playwright_desktop](https://img.shields.io/github/actions/workflow/status/activist-org/activist/ci_e2e_playwright_desktop.yaml?branch=main&label=e2e%20desktop)](https://github.com/activist-org/activist/actions/workflows/ci_e2e_playwright_desktop.yaml) +[![ci_e2e_playwright_mobile](https://img.shields.io/github/actions/workflow/status/activist-org/activist/ci_e2e_playwright_mobile.yaml?branch=main&label=e2e%20mobile)](https://github.com/activist-org/activist/actions/workflows/ci_e2e_playwright_mobile.yaml) +[![ci_backend_static_analysis](https://img.shields.io/github/actions/workflow/status/activist-org/activist/ci_backend_static_analysis.yaml?branch=main&label=backend%20static)](https://github.com/activist-org/activist/actions/workflows/ci_backend_static_analysis.yaml) +[![ci_backend_pytest](https://img.shields.io/github/actions/workflow/status/activist-org/activist/ci_backend_pytest.yaml?branch=main&label=backend%20pytest)](https://github.com/activist-org/activist/actions/workflows/ci_backend_pytest.yaml) +[![ci_frontend_static_analysis](https://img.shields.io/github/actions/workflow/status/activist-org/activist/ci_frontend_static_analysis.yaml?branch=main&label=frontend%20static)](https://github.com/activist-org/activist/actions/workflows/ci_frontend_static_analysis.yaml) +[![ci_frontend_vitest](https://img.shields.io/github/actions/workflow/status/activist-org/activist/ci_frontend_vitest.yaml?branch=main&label=frontend%20vitest)](https://github.com/activist-org/activist/actions/workflows/ci_frontend_vitest.yaml) +[![ci_i18n_check](https://img.shields.io/github/actions/workflow/status/activist-org/activist/ci_i18n_check.yaml?branch=main&label=i18n)](https://github.com/activist-org/activist/actions/workflows/ci_i18n_check.yaml) + +# Contents + +- [About activist](#about-activist) +- [Our Mission](#our-mission) +- [Topics](#topics) +- [Features](#features) +- [Preview Video](#preview-video) +- [Design and Accessibility](#design-and-accessibility) +- [Securely Hosted](#securely-hosted) +- [Community Governance](#community-governance) +- [Localization](#localization) +- [Contributing](#contributing) +- [Supporters and Partners](#supporters-and-partners) +- [Disclosure](#disclosure) -[**activist.org**](https://activist.org) is a platform that enables more people to safely engage in activism by making it easy to discover organizations and events, as well as coordinate and collaborate on political action. We want to enable activists to learn proven and novel strategies from each other for social and ecological change. Free, open-source, privacy-focused and governed by our community. +# About activist - +> [!IMPORTANT] +> Before you contribute, read the [contributing guide](CONTRIBUTING.md). -> [!NOTE] -> The [contributing](#contributing) section has information for those interested. +[activist.org](https://activist.org) is a platform that makes it easy and safe to: - +- Engage in activism. +- Discover organizations and events. +- Coordinate and collaborate on political action. -# **Contents** +Our mission is to help activists connect and share strategies for social and ecological change. -- [Our goals](#our-goals) -- [Preview video](#preview-video) -- [Contributing](#contributing) -- [Environment setup](#environment-setup) -- [Design and accessibility](#design-a11y) -- [Platform features](#platform-features) -- [Securely hosted](#securely-hosted) -- [Community governance](#community-governance) -- [Localization](#localization) -- [Supporters and partners](#supporters-partners) +activist is: - +- Free. +- Open-source. +- Privacy-focused. +- Governed by our community. -# Our goals [`⇧`](#contents) +# Our Mission -The activist community is creating a global platform where movements grow and people are inspired to join in political actions. We want to update how power is distributed in our society by removing barriers and enabling more people to safely engage in activism. +We're creating a global platform where movements grow and people are inspired to join in political action. - +We want to change how power is distributed in society by removing barriers and enabling more people to safely engage in activism. -## Topics [`⇧`](#contents) +# Topics -The following are the working topics that activist could include: +These are some of the topics that activist includes: | | | | | :-------------------------- | :--------------------- | :----------------------- | @@ -66,341 +79,221 @@ The following are the working topics that activist could include: | LGBTQIA+ | Peace and Resolution | Racial Justice | | Refugees and Migration | Technology and Privacy | Women's Rights | -
-Beyond clustering by topics, tags will also be used to draw community attention to more specific issues. +In addition to clustering by topics, tags indicate more specific issues. - +Back to top. -# Preview video [`⇧`](#contents) +# Features -The following is a recording of the [Creating and Joining Events prototype](https://www.figma.com/proto/I9McFfaLu1RiiWp5IP3YjE/activist_public_designs?node-id=1998%3A2577&scaling=contain&page-id=1986%3A1046&starting-point-node-id=1998%3A2577) found on [Figma](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_designs?node-id=805%3A231): +The [project board](https://github.com/orgs/activist-org/projects/1) is where we organize our work and plan out what's next. -https://user-images.githubusercontent.com/24387426/215117858-96b0d3ac-4d11-449e-bcc0-2b7ec330a6e1.mp4 +This section gives a general overview of the planned features for activist. -Further prototypes and designs are available in the [designs for activist](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_designs?node-id=805%3A231). +## Organization Profiles - +_Easy-to-use microsites with multiple subpages, for organizations of all sizes._ -# Contributing [`⇧`](#contents) +- Describe your organizational structure and goals. +- Explain how your groups collaborate. +- Safely onboard new team members. +- Respond to frequently asked questions. -Public Matrix Chat +## Events -activist uses [Matrix](https://matrix.org/) for internal communication. You're more than welcome to [join us in our public chat rooms](https://matrix.to/#/#activist_community:matrix.org) to share ideas, ask questions or just say hi to the team :) We'd suggest that you use the [Element](https://element.io/) client and [Element X](https://element.io/app) for a mobile app. +_Collaborative event pages made for activists and their needs._ -Please see the [contribution guidelines](CONTRIBUTING.md) and [style guide](STYLEGUIDE.md) if you are interested in contributing. Work that is in progress or could be implemented is tracked in the [issues](https://github.com/activist-org/activist/issues) and [projects](https://github.com/activist-org/activist/projects). +Create flexible event pages for two event types: -> [!NOTE] -> Just because an issue is assigned on GitHub doesn't mean the team isn't open to your contribution! Feel free to write [in the issues](https://github.com/activist-org/activist/issues) and we can potentially reassign it to you. +**Learn** -Also check the [`-next release-`](https://github.com/activist-org/activist/labels/-next%20release-) and [`-priority-`](https://github.com/activist-org/activist/labels/-priority-) labels in the [issues](https://github.com/activist-org/activist/issues) for those that are most important, as well as those marked [`good first issue`](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) that are tailored for first-time contributors. For those new to coding or our tech stack, we've collected [links to helpful documentation pages](CONTRIBUTING.md#learning-the-tech-stack-) in the [contribution guidelines](CONTRIBUTING.md). +- Seminars +- Meetings +- Panel discussions -We would be happy to discuss granting you further rights as a contributor after your first pull requests, with a maintainer role then being possible after continued interest in the project. activist seeks to be an inclusive, diverse and supportive organization. We'd love to have you on the team! +**Action** - +- Protests +- Volunteering +- Canvassing -## How you can help [`⇧`](#contents) +Also: -- [Reporting bugs](https://github.com/activist-org/activist/issues/new?assignees=&labels=bug&template=bug_report.yml) as they're found 🐞 -- Working with us on [new features](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3Afeature) ✨ -- [Localizing](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3Alocalization) content for the platform 🌐 - - Please join our [public localization project on Weblate](https://hosted.weblate.org/projects/activist/activist)! -- [Documentation](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3Adocumentation) for onboarding and project cohesion 📝 -- [Sharing activist.org](https://github.com/activist-org/activist/issues/23) with others! 🚀 +- A feed for organizers to share real-time information with participants. +- Event templates that organizations can create and share them with allies. +- Transform event pages into flyers or posters and link them via QR codes. +- Add legal notes to warn participants of the risks involved. - +## Resources -# Environment setup [`⇧`](#contents) +_A simple link hub for organizations._ -1. First and foremost, please see the suggested IDE setup in the dropdown below to make sure that your editor is ready for development. +- Saved under organizations, their working groups and events. +- Keep important links in one place. +- Private by default. +- Make public to share information and best practices. -> [!IMPORTANT] -> ->
Suggested IDE setup -> ->

-> -> VS Code -> -> Install the following extensions: -> -> - [batisteo.vscode-django](https://marketplace.visualstudio.com/items?itemName=batisteo.vscode-django) -> - [bradlc.vscode-tailwindcss](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) -> - [charliermarsh.ruff](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff) -> - [esbenp.prettier-vscode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) -> - [ms-playwright.playwright](https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright) -> - [streetsidesoftware.code-spell-checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) -> - [Vue.volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) -> -> WebStorm -> -> - Check out the [Vue.js development docs](https://www.jetbrains.com/help/webstorm/vue-js.html) -> - Make sure a [local Node.js interpreter](https://www.jetbrains.com/help/webstorm/developing-node-js-applications.html#ws_node_configure_local_node_interpreter) is configured in your project -> - Make sure the [Vue.js plugin](https://github.com/JetBrains/intellij-plugins/tree/master/vuejs) and [JavaScript Debugger](https://www.jetbrains.com/help/webstorm/configuring-javascript-debugger.html) are enabled in the plugins page of the settings -> ->

->
+## Search -2. To setup your development environment, first install [Docker](https://docs.docker.com/install) and [Docker Compose](https://docs.docker.com/compose). +_Easily find, filter, and share._ -> [!NOTE] -> If you are new to Docker, activist recommends installing [Docker Desktop](https://docs.docker.com/desktop/). Docker Desktop comes with many Docker tools and a straightforward user interface. +- Display search results in list, map, and calendar views. +- Save searches for later. +- Set up notifications for newly published events, resources, and discussions. -3. [Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) the repo, clone your fork, and configure the remotes: +## Onboarding -> [!NOTE] -> ->
Consider using SSH -> ->

-> -> Alternatively to using HTTPS as in the instructions below, consider SSH to interact with GitHub from the terminal. SSH allows you to connect without a user-pass authentication flow. -> -> To run git commands with SSH, remember then to substitute the HTTPS URL, `https://github.com/...`, with the SSH one, `git@github.com:...`. -> -> - e.g. Cloning now becomes `git clone git@github.com:/activist.git` -> -> GitHub also has their documentation on how to [Generate a new SSH key](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) 🔑 -> ->

->
+_Safe methods to onboard new members._ -```bash -# Clone your fork of the repo into the current directory. -git clone https://github.com//activist.git -# Navigate to the newly cloned directory. -cd activist -# Assign the original repo to a remote called "upstream". -git remote add upstream https://github.com/activist-org/activist.git -``` +- A conversational onboarding interface based on the [Matrix protocol](https://matrix.org/). +- Operate across messengers without compromising data sovereignty for organizations or individuals. +- Organizations can include their existing processes if preferred. -- Now, if you run `git remote -v` you should see two remote repositories named: - - `origin` (forked repository) - - `upstream` (activist repository) +## Discussions -4. Create a virtual environment for the backend (Python `>=3.11`), activate it and install dependencies: +_Forums for organizations and events._ - ```bash - python3 -m venv venv +- Send notifications to supporters about organizations, groups, and events. +- Democratic decision making to enable asynchronous planning. - # Unix or MacOS: - source venv/bin/activate +## Tasks - # Windows: - venv\Scripts\activate.bat +_Organize work to be done with kanban boards._ - # After activating venv: - pip install --upgrade pip - pip install -r backend/requirements-dev.txt - ``` +- Attach kanban boards to every organization, group, and event to plan and track progress. +- Templates to guide organizers with best practices from our community. -5. Start your docker images with the following: +## Affiliates - ```bash - # --build only necessary with new dependencies or backend model changes - docker compose --env-file .env.dev up --build +_Relationships between organizations, people, and events._ - # And to stop the containers when you're done working: - # docker compose --env-file .env.dev down - ``` +Organizations and users can support each other and events: - Sometimes changes to the database can cause the database population to fail in your environment. If this happens, you can destroy the deployment and rebuild it: +- **Supporter:** A one-way relationship of support. +- **Ally:** A relationship of mutual support. - ```bash - # Destroy your current docker compose deployment: - docker compose rm -f -v --env-file .env.dev - ``` +Also: -6. You can then visit to see the development frontend build once the container is up and running. From there click `View organizations` or `View events` to explore the platform. +- Find similar organizations through relationships. +- Easily connect with actions when in a new location. +- Affiliations determine notifications and access to restricted content. -7. To view the backend admin UI and Swagger UI, visit and respectively. +## Votes -8. If you'd like to sign in to the frontend via or the Django admin panel via , then you can use the fixtures `admin` user with the password `admin`. +_Link events and organizations to decision making._ -> [!NOTE] -> Feel free to contact the team in the [Development room on Matrix](https://matrix.to/#/!CRgLpGeOBNwxYCtqmK:matrix.org?via=matrix.org&via=acter.global&via=chat.0x7cd.xyz) if you're having problems getting your environment setup! If you're having issues with Docker and just want to get the frontend or backend up and running, please see [the section on this in the contributing guide](CONTRIBUTING.md#using-yarn-or-python). +- Subscribe to updates on events and organizations related to legislation and elections. +- Based on data from [Wikidata](https://www.wikidata.org). +- Open data generates the vote pages that our community maintains. -9. Install [pre-commit](https://pre-commit.com/) to ensure that each of your commits is properly checked against our linter and formatters: +Back to top. - ```bash - # In the project root: - pre-commit install +# Preview Video - # Then test the pre-commit hooks to see how it works: - pre-commit run --all-files - ``` +This is a demo of the [Creating and Joining Events prototype](https://www.figma.com/proto/I9McFfaLu1RiiWp5IP3YjE/activist_public_designs?node-id=1998%3A2577&scaling=contain&page-id=1986%3A1046&starting-point-node-id=1998%3A2577) found on [Figma](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_designs?node-id=805%3A231): -> [!NOTE] -> pre-commit is Python package that can be installed via pip or any other Python package manager. You can also find it in our [requirements-dev.txt](backend/requirements-dev.txt) file. -> -> ```bash -> pip install pre-commit -> ``` - - - -## Tech Stack [`⇧`](#contents) - -The following are the current and planned technologies for [activist.org](https://activist.org): - -### Frontend - -- [Nuxt.js](https://nuxt.com) • [Vue.js](https://vuejs.org) • [TypeScript](https://www.typescriptlang.org) • [Tailwind CSS](https://tailwindcss.com) • [Headless UI](https://headlessui.com) - -### Backend - -- [Django](https://www.djangoproject.com) • [PostgreSQL](https://www.postgresql.org) - -### Deployment - -- [Docker](https://www.docker.com) • [Netlify](https://www.netlify.com) • [Vitest](https://vitest.dev/) - -### Internationalization - -- [Nuxt I18n](https://github.com/nuxt-modules/i18n) • [Weblate](https://weblate.org) ([activist on Weblate](https://hosted.weblate.org/projects/activist/activist)) - -### Analytics +https://user-images.githubusercontent.com/24387426/215117858-96b0d3ac-4d11-449e-bcc0-2b7ec330a6e1.mp4 -- [Plausible](https://plausible.io/) +Further prototypes and designs are available in the [designs for activist](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_designs?node-id=805%3A231). -> [!NOTE] -> Those new to any frameworks or technologies who want to work on their skills are more than welcome to contribute! +Back to top. - +# Design and Accessibility -# Design and accessibility [`⇧`](#contents) +> [!IMPORTANT] +> If you're interested in contributing, contact the team on GitHub or via the email on the [designs welcome page](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_designs?node-id=805%3A231). We'd love to see a sample of your work! If everything looks good, we'll schedule a time to get connected. Public Figma Designs -The [designs for activist](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_designs?node-id=805%3A231) are made using [Figma](https://www.figma.com). You can use the [issues](https://github.com/activist-org/activist/issues) to make suggestions for improvements. Design related issues are marked with the [`design`](https://github.com/activist-org/activist/issues?q=is%3Aopen+is%3Aissue+label%3Adesign) label. - -We want our tools to look great, feel easy to use and function flawlessly on any device while at the same time including good security practices wherever possible. We also consistently make decisions that put a11y at the center of what we’re building. - -> [!NOTE] -> Please contact the team on GitHub or via the email on the [designs welcome page](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_designs?node-id=805%3A231) if you're interested in contributing. We'd love to see a sample of your work and if everything looks good we'll schedule a time to get connected! - - - -# Platform features [`⇧`](#contents) - -The [project board](https://github.com/orgs/activist-org/projects/1) is where we organize our work and plan out what's next. The following sections give a general overview of the various planned features of [activist.org](https://activist.org). - -### Organizations profiles [`⇧`](#contents) - -> Easy-to-use microsites for organizations of all sizes with multiple subpages. - -Describe your organization’s aims and structure as well as answer frequently asked questions. Explain how your groups collaborate and safely onboard new people to the team. - -### Events [`⇧`](#contents) - -> Collaborative event pages made for activists and their needs. - -Organizations can create flexible event pages for different formats of events. There are two types of events: - -- **Learn**: seminars, meetings, panel discussions -- **Action**: protests, volunteering, canvassing - -Other event features include: - -- A feed will allow organizers to share information in real time with participants -- Organizations can create event templates and share them with allies -- Event pages can be transformed into flyers or posters and linked to via QR codes -- Legal notes can be added to warn participants of the risks involved - -### Resources [`⇧`](#contents) - -> A simple link hub for organizations. - -Organizations can keep important links (chats, articles, pads, etc.) in one place and are split into working groups to present structure. Private by default, resources can also be made public to share information and best practices. - -### Onboarding [`⇧`](#contents) - -> Safe methods to onboard new members. - -We are working on a conversational onboarding interface based on the [Matrix protocol](https://matrix.org/) that operates across messengers without compromising data sovereignty for organizations or individuals. Organizations will also have the option to include their existing processes if preferred. - -### Search [`⇧`](#contents) - -> Easily find, filter and share. - -Display search results in list, map and calendar views. Users can also save searches for later or set up notifications for newly published events, resources, and discussions. +We want our tools to look great, be easy to use, and function on any device, while including good security practices. We also consistently put accessibility at the center of what we build. -### Discussions [`⇧`](#contents) +We make the [designs for activist](https://www.figma.com/file/I9McFfaLu1RiiWp5IP3YjE/activist_designs?node-id=805%3A231) using [Figma](https://www.figma.com). -> Dedicated forums for organizations and their events. +You can use the [issues](https://github.com/activist-org/activist/issues) to suggest improvements. We mark design-related issues with the [`design`](https://github.com/activist-org/activist/issues?q=is%3Aopen+is%3Aissue+label%3Adesign) label. -Discussions will also allow organizations, groups and events to send notifications to supporters. Included features for democratic decision making will further enable asynchronous planning. +Back to top. -### Tasks [`⇧`](#contents) +# Securely Hosted -> Kanban boards for organizing the work to be done. +We host our data in Iceland with [FlokiNET](https://flokinet.is/), a reputable hosting provider trusted by whistleblowers, activists, and investigative journalists. -Users will be able to attach kanban boards to every organization, group and event. This will allow those involved to easily plan and keep an overview of progress while templates guide organizers with best practices from our community. +Iceland is a strong supporter for net neutrality with strict privacy protection laws and freedom of the press. These factors have contributed to making Iceland a preferred destination for data centers. -### Affiliates [`⇧`](#contents) +You can learn more about FlokiNET on [their blog](https://blog.flokinet.is). -> Relationships between organizations, people and events. +Back to top. -Organizations and users can give support to each other as well as events: +# Community Governance -- **Supporter**: a one-way relationship of support -- **Ally**: a relationship of mutual support +We not only value, but _need_ open discourse. Our initial feature set was developed together with our growing community of activists. -Relationships between organizations will help users find similar organizations or easily connect with actions when they’re in a new place. Affiliations will also determine notifications and access to restricted content. +Our aim is to secure a progressive community by design, while putting platform health before platform growth. -### Votes [`⇧`](#contents) +Only organizations that are already on activist will be able to vouch for new organizations that apply to join. Together with experienced activists, we're selecting an initial group of organizations that have a proven track record of inclusivity and elevating underrepresented groups. -> Linking events and organizations to decision making. +We are still developing our operating principles and will always update them based on community decisions. Processes for flagging, banning, guidelines, and rules will always be determined collectively. -Users will be able to subscribe for updates on events and organizations that work in relation to legislation and elections. This feature will be based on data from [Wikidata](https://www.wikidata.org), with open data generating the vote pages that our community then maintains. +Back to top. - +# Localization -# Securely hosted [`⇧`](#contents) + + Visit the Weblate project + -We are hosting our data in Iceland with a reputable hosting provider that is trusted by whistleblowers, activists and investigative journalists: [FlokiNET](https://flokinet.is/). +> [!IMPORTANT] +> Want to join our translators working group? Join us in the [localization project on Weblate](https://hosted.weblate.org/projects/activist/activist) and the [Localization channel on Matrix](https://matrix.to/#/!DzbdYyfhjinQBWXgQe:matrix.org?via=matrix.org) to get involved! +> +> See the [localization guide](LOCALIZATION.md) for information on how to get started. -Iceland is a strong supporter for net neutrality with strict privacy protection laws and freedom of the press. All these factors have contributed to making Iceland a preferred destination for data centers. +In order to mobilize larger and more diverse coalitions, we need to break down language barriers. -> You can learn more about FlokiNET on [their blog](https://blog.flokinet.is). +We're growing our network of volunteer contributors to facilitate translation requests for these parts of the platform: - +- Organization profiles +- Events +- Resources -# Community governance [`⇧`](#contents) +We use [Weblate](https://weblate.org) for localization. -We not only value, but need open discourse. Our initial feature set for the MVP and future releases was developed together with our growing community of activists. +## Localization Coverage -Our aim is to secure a progressive community by design while putting platform health before platform growth. Only organizations that are already on activist will be able to vouch for new organizations that apply to join. Together with experienced activists we are selecting an initial group of organizations that have a proven track record of inclusivity and elevating underrepresented groups. + + Translation status + -We are still developing our operating principles and will always update them based on community decisions. Questions around flagging, banning, guidelines and rules will always be answered collectively. +Back to top. - +# Contributing -# Localization [`⇧`](#contents) +Public Matrix Chat - - Visit the Weblate project - +activist uses [Matrix](https://matrix.org/) for internal communication. You're more than welcome to [join us in our public chat rooms](https://matrix.to/#/#activist_community:matrix.org) to share ideas, ask questions or just say hi to the team :) We'd suggest that you use the [Element](https://element.io/) client and [Element X](https://element.io/app) for a mobile app. -We need to break down language barriers in order to mobilize larger and more diverse coalitions. Translation requests will be available for several assets on the platform - organization profiles, events and resources - and we are growing our network of volunteer contributors to facilitate this. +Please see the [contribution guide](CONTRIBUTING.md) and [style guide](STYLEGUIDE.md) if you are interested in contributing. Work that is in progress or could be implemented is tracked in the [issues](https://github.com/activist-org/activist/issues) and [projects](https://github.com/activist-org/activist/projects). > [!NOTE] -> Want to join our translators working group? Please join us in the [localization project on Weblate](https://hosted.weblate.org/projects/activist/activist) and the [Localization channel on Matrix](https://matrix.to/#/!DzbdYyfhjinQBWXgQe:matrix.org?via=matrix.org) to get involved! +> Just because an issue is assigned on GitHub doesn't mean the team isn't open to your contribution! Feel free to write [in the issues](https://github.com/activist-org/activist/issues) and we can potentially reassign it to you. -Localization of activist is done via [Weblate](https://weblate.org). Please see the [localization guide](LOCALIZATION.md) for information on how to get started! +Also check the [`-next release-`](https://github.com/activist-org/activist/labels/-next%20release-) and [`-priority-`](https://github.com/activist-org/activist/labels/-priority-) labels in the [issues](https://github.com/activist-org/activist/issues) for those that are most important, as well as those marked [`good first issue`](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) that are tailored for first-time contributors. For those new to coding or our tech stack, we've collected [links to helpful documentation pages](CONTRIBUTING.md#learning-the-tech-stack-) in the [contribution guide](CONTRIBUTING.md). -### Localization coverage [`⇧`](#contents) +We would be happy to discuss granting you further rights as a contributor after your first pull requests, with a maintainer role then being possible after continued interest in the project. activist seeks to be an inclusive, diverse and supportive organization. We'd love to have you on the team! Please see the [mentorship and growth section of the contribution guide](CONTRIBUTING.md#mentorship-and-growth-) for further information. - - Translation status - +## How you can help - +- [Reporting bugs](https://github.com/activist-org/activist/issues/new?assignees=&labels=bug&template=bug_report.yml) as they're found 🐞 +- Working with us on [new features](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3Afeature) ✨ +- [Localizing](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3Alocalization) content for the platform 🌐 + - Please join our [public localization project on Weblate](https://hosted.weblate.org/projects/activist/activist)! +- [Documentation](https://github.com/activist-org/activist/issues?q=is%3Aissue+is%3Aopen+label%3Adocumentation) for onboarding and project cohesion 📝 +- [Sharing activist.org](https://github.com/activist-org/activist/issues/23) with others! 🚀 + +Back to top. -# Supporters and partners [`⇧`](#contents) +# Supporters and Partners -### Contributors +## Contributors Thanks to all our amazing [contributors](https://github.com/activist-org/activist/graphs/contributors)! ❤️ @@ -408,27 +301,27 @@ Thanks to all our amazing [contributors](https://github.com/activist-org/activis -### Code and dependencies +## Code and Dependencies -We would like to thank all the great software that made activist's development possible 🙏 +We want to thank all the great software that made activist possible. 🙏 - Countless [Nuxt modules](https://nuxt.com/modules) - [OpenStreetMap](https://www.openstreetmap.org) - [MapLibre](https://maplibre.org/) -### Our supporters +## Licensed Software Providers -#### Licensed software providers - -The following organizations have supported activist with licenses to use their technology for free: +These organizations have supported activist with free licenses to use their technology: - [Weblate](https://weblate.org/) - [GitBook](https://www.gitbook.com/) - [Formbricks](https://formbricks.com/) -#### The Wikimedia UNLOCK Accelerator +## Wikimedia UNLOCK Accelerator + +These organizations have supported activist via the 2022 edition of the Wikimedia UNLOCK accelerator. -These organizations have supported activist via the 2022 edition of the Wikimedia UNLOCK accelerator. UNLOCK supported open-source software projects and non-technical projects under free licenses. UNLOCK Accelerator was committed to promoting solutions that make the world's knowledge more diverse, more accessible and inclusive for everyone. +UNLOCK supported open-source software projects and non-technical projects under free licenses. UNLOCK Accelerator was committed to promoting solutions that make the world's knowledge more diverse, more accessible, and inclusive for everyone.

@@ -443,4 +336,6 @@ These organizations have supported activist via the 2022 edition of the Wikimedi # Disclosure -activist is not directly affiliated with any corporation, political party or government. +activist is not directly affiliated with any corporation, political party, or government. + +Back to top. diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md index ffceb633c..28c0a9c4f 100644 --- a/STYLEGUIDE.md +++ b/STYLEGUIDE.md @@ -1,14 +1,14 @@ -# Style Guidelines for activist.org + + +# Style Guide Thank you for following our style guide! The team asks that you familiarize yourself with this guide and follow it for any contributions. Doing so makes PRs and general code collaboration much more effective :) -We'll also link to this document in cases where these guidelines have not been followed. If that's what brought you here, no stress! Thanks for your interest and your drive to contribute to open-source and activist in particular! ❤️ +We'll also link to this document in cases where this guide has not been followed. If that's what brought you here, no stress! Thanks for your interest and your drive to contribute to open-source and activist in particular! ❤️ If you have questions or would like to communicate with the team, please [join us in our public Matrix chat rooms](https://matrix.to/#/#activist_community:matrix.org). We'd be happy to hear from you! - - -## **Contents** +## Contents - [Vue and Nuxt](#vue-and-nuxt) - [Page routing](#page-routing) @@ -28,9 +28,7 @@ If you have questions or would like to communicate with the team, please [join u - [Padding](#padding) - [Comments](#comments) - - -## Vue and Nuxt [`⇧`](#contents) +## Vue and Nuxt > [!NOTE] > For VS Code users: it is recommended to install [Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to enable in-editor type-checking. @@ -65,15 +63,11 @@ Vue files (`.vue`) are Single-File Components that have ` diff --git a/frontend/app/components/card/CardDonate.vue b/frontend/app/components/card/CardDonate.vue index 4f1a6e335..253cc44bb 100644 --- a/frontend/app/components/card/CardDonate.vue +++ b/frontend/app/components/card/CardDonate.vue @@ -5,22 +5,22 @@

{{ $t("i18n.components.card_donate.donate") }}

-
- - -
+ + +

{{ donationPrompt }} diff --git a/frontend/app/components/card/CardFAQEntry.vue b/frontend/app/components/card/CardFAQEntry.vue index dea0554b9..82a5e6451 100644 --- a/frontend/app/components/card/CardFAQEntry.vue +++ b/frontend/app/components/card/CardFAQEntry.vue @@ -1,7 +1,7 @@ diff --git a/frontend/app/components/dropdown/DropdownItemsLayout.vue b/frontend/app/components/dropdown/DropdownItemsLayout.vue index 3002ed36d..4be06b38f 100644 --- a/frontend/app/components/dropdown/DropdownItemsLayout.vue +++ b/frontend/app/components/dropdown/DropdownItemsLayout.vue @@ -10,6 +10,7 @@ :id="opt.id" v-for="opt in options" :key="opt.id" + @click="opt?.onClick" :data-testid="opt['data-testid']" :isAddStyles="false" :selected="opt.selected" diff --git a/frontend/app/components/dropdown/DropdownLanguage.vue b/frontend/app/components/dropdown/DropdownLanguage.vue index 4998f92b9..b8e28b746 100644 --- a/frontend/app/components/dropdown/DropdownLanguage.vue +++ b/frontend/app/components/dropdown/DropdownLanguage.vue @@ -40,7 +40,7 @@ defineProps<{ const { locale, locales } = useI18n(); const switchLocalePath = useSwitchLocalePath(); -const localesValues: LocaleObject[] = locales.value; +const localesValues = computed(() => locales.value); function getLocaleCode(locale: LocaleObject) { return typeof locale === "string" ? locale : locale.code; @@ -51,10 +51,9 @@ function getLocaleName(locale: LocaleObject) { } const availableLocales = computed(() => { - return localesValues.filter((i) => getLocaleCode(i) !== locale.value); + return localesValues.value.filter((i) => getLocaleCode(i) !== locale.value); }); -// Function to update HTML lang attribute immediately. const updateLangAttribute = (newLocale: string) => { if (import.meta.client) { document.documentElement.setAttribute("lang", newLocale); diff --git a/frontend/app/components/dropdown/DropdownUserOptions.vue b/frontend/app/components/dropdown/DropdownUserOptions.vue index e336d7c77..9b42302d9 100644 --- a/frontend/app/components/dropdown/DropdownUserOptions.vue +++ b/frontend/app/components/dropdown/DropdownUserOptions.vue @@ -23,10 +23,13 @@ diff --git a/frontend/app/components/footer/flex/FooterFlexCol.vue b/frontend/app/components/footer/flex/FooterFlexCol.vue deleted file mode 100644 index b5df3c9a0..000000000 --- a/frontend/app/components/footer/flex/FooterFlexCol.vue +++ /dev/null @@ -1,201 +0,0 @@ - - - - diff --git a/frontend/app/components/form/Form.vue b/frontend/app/components/form/Form.vue index 3a37dc8fc..b2b180eef 100644 --- a/frontend/app/components/form/Form.vue +++ b/frontend/app/components/form/Form.vue @@ -9,19 +9,33 @@ >

- + +
+
+ +
-
@@ -32,7 +46,8 @@ import type { z } from "zod"; import { toTypedSchema } from "@vee-validate/zod"; import { useForm } from "vee-validate"; - +import { unref } from "vue"; +type Btn = BtnAction & { [key: string]: unknown }; const props = withDefaults( defineProps<{ schema: z.Schema; @@ -43,6 +58,8 @@ const props = withDefaults( initialValues?: Record; sendOnChange?: boolean; isThereSubmitButton?: boolean; + actionButtons?: Btn[]; + isLoading?: boolean; }>(), { isThereSubmitButton: true, @@ -54,10 +71,27 @@ const labelForSubmit = props.submitLabel ?? "i18n.components.submit"; const id = props.id || "form-id"; const submitId = props.id ? `${props.id}-submit` : "form-submit-id"; -const { handleSubmit, values } = useForm({ +const { handleSubmit, values, ...rest } = useForm({ validationSchema: toTypedSchema(props.schema), initialValues: props.initialValues, }); + +let pendingReset: ReturnType | null = null; + +watch( + () => props.initialValues, + (newValues, oldValues) => { + if (JSON.stringify(newValues) === JSON.stringify(oldValues)) return; + + if (pendingReset !== null) clearTimeout(pendingReset); + pendingReset = setTimeout(() => { + pendingReset = null; + rest.resetForm({ values: newValues || {} }); + }, 0); + }, + { deep: true } +); + const emit = defineEmits<{ (e: "submit", values: Record): void; }>(); @@ -74,7 +108,12 @@ if (props.sendOnChange) { } ); } + const onSubmit = handleSubmit((values) => { emit("submit", values); }); + +defineExpose({ + getValues: () => ({ ...(unref(values) ?? {}) }), +}); diff --git a/frontend/app/components/form/FormErrorMessage.vue b/frontend/app/components/form/FormErrorMessage.vue index e77e98cb2..a266d9ccf 100644 --- a/frontend/app/components/form/FormErrorMessage.vue +++ b/frontend/app/components/form/FormErrorMessage.vue @@ -1,8 +1,8 @@ diff --git a/frontend/app/components/form/FormSearch.vue b/frontend/app/components/form/FormSearch.vue index 5ba164ec4..daf885d11 100644 --- a/frontend/app/components/form/FormSearch.vue +++ b/frontend/app/components/form/FormSearch.vue @@ -1,13 +1,9 @@