diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..0ef78f43dc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +node_modules +npm-debug.log +Dockerfile +.git +.gitignore +.env +.env.* +dist +coverage +.nyc_output +*.md +.github +tests +__tests__ +*.test.* +*.spec.* +# Development files +*.log +*.lock +.DS_Store +.idea +.vscode +# Build artifacts +build +out \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 26470f7aab..b3704d9aa1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -55,6 +55,7 @@ "import/no-duplicates": "error", "tsdoc/syntax": "error", "@typescript-eslint/ban-ts-comment": "error", + "@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-non-null-asserted-optional-chain": "error", diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9e3081d0ee..17c22056f7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -25,6 +25,11 @@ Fixes # **Did you add tests for your changes?** +**Snapshots/Videos:** + + + + **Snapshots/Videos:** @@ -44,6 +49,19 @@ Fixes # +## Checklist + +### CodeRabbit AI Review +- [ ] I have reviewed and addressed all critical issues flagged by CodeRabbit AI +- [ ] I have implemented or provided justification for each non-critical suggestion +- [ ] I have documented my reasoning in the PR comments where CodeRabbit AI suggestions were not implemented + +### Test Coverage +- [ ] I have written tests for all new changes/features +- [ ] I have verified that test coverage meets or exceeds 95% +- [ ] I have run the test suite locally and all tests pass + + **Other information** diff --git a/.github/workflows/pull-request-target.yml b/.github/workflows/pull-request-target.yml index af75effc13..d19d286f1e 100644 --- a/.github/workflows/pull-request-target.yml +++ b/.github/workflows/pull-request-target.yml @@ -24,13 +24,12 @@ jobs: comment_tag: pr_review_policy message: | ## Our Pull Request Approval Process - + Thanks for contributing! ### Testing Your Code - Remember, your PRs won't be reviewed until these criteria are met: - + 1. We don't merge PRs with poor code quality. 1. Follow coding best practices such that CodeRabbit.ai approves your PR. 1. We don't merge PRs with failed tests. diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index aaeebc8345..c717a53701 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -46,7 +46,7 @@ jobs: - name: Check formatting if: steps.changed-files.outputs.only_changed != 'true' run: npm run format:check - + - name: Run formatting if check fails if: failure() run: npm run format @@ -57,10 +57,9 @@ jobs: - name: Check for linting errors in modified files if: steps.changed-files.outputs.only_changed != 'true' - env: + env: CHANGED_FILES: ${{ steps.changed_files.outputs.all_changed_files }} run: npx eslint ${CHANGED_FILES} && python .github/workflows/eslint_disable_check.py - - name: Check for TSDoc comments run: npm run check-tsdoc # Run the TSDoc check script @@ -89,7 +88,6 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 - - name: Get Changed Unauthorized files id: changed-unauth-files uses: tj-actions/changed-files@v40 @@ -123,10 +121,10 @@ jobs: ISSUE_GUIDELINES.md PR_GUIDELINES.md README.md - + - name: List all changed unauthorized files if: steps.changed-unauth-files.outputs.any_changed == 'true' || steps.changed-unauth-files.outputs.any_deleted == 'true' - env: + env: CHANGED_UNAUTH_FILES: ${{ steps.changed-unauth-files.outputs.all_changed_files }} run: | for file in ${CHANGED_UNAUTH_FILES}; do @@ -147,7 +145,7 @@ jobs: uses: tj-actions/changed-files@v40 - name: Echo number of changed files - env: + env: CHANGED_FILES_COUNT: ${{ steps.changed-files.outputs.all_changed_files_count }} run: | echo "Number of files changed: $CHANGED_FILES_COUNT" @@ -194,15 +192,15 @@ jobs: - name: Install Dependencies run: npm install - + - name: Get changed TypeScript files id: changed-files uses: tj-actions/changed-files@v40 - + - name: Run tests if: steps.changed-files.outputs.only_changed != 'true' - run: npm run test -- --watchAll=false --coverage - + run: npm run test -- --watchAll=false --coverage + - name: TypeScript compilation for changed files run: | for file in ${{ steps.changed-files.outputs.all_files }}; do @@ -210,7 +208,7 @@ jobs: npx tsc --noEmit "$file" fi done - + - name: Present and Upload coverage to Codecov as ${{env.CODECOV_UNIQUE_NAME}} uses: codecov/codecov-action@v4 with: @@ -222,7 +220,7 @@ jobs: - name: Test acceptable level of code coverage uses: VeryGoodOpenSource/very_good_coverage@v2 with: - path: "./coverage/lcov.info" + path: './coverage/lcov.info' min_coverage: 95.0 Graphql-Inspector: @@ -240,19 +238,75 @@ jobs: - name: resolve dependency run: npm install -g @graphql-inspector/cli - + - name: Clone API Repository run: | # Retrieve the complete branch name directly from the GitHub context FULL_BRANCH_NAME=${{ github.base_ref }} echo "FULL_Branch_NAME: $FULL_BRANCH_NAME" - + # Clone the specified repository using the extracted branch name - git clone --branch $FULL_BRANCH_NAME https://github.com/PalisadoesFoundation/talawa-api && ls -a + git clone --branch $FULL_BRANCH_NAME https://github.com/PalisadoesFoundation/talawa-api && ls -a - name: Validate Documents run: graphql-inspector validate './src/GraphQl/**/*.ts' './talawa-api/schema.graphql' + Docker-Start-Check: + name: Check if Talawa Admin app starts in Docker + runs-on: ubuntu-latest + needs: [Code-Quality-Checks, Test-Application] + if: github.actor != 'dependabot' + steps: + - name: Checkout the Repository + uses: actions/checkout@v4 + + - name: Set up Docker + uses: docker/setup-buildx-action@v3 + with: + driver-opts: | + image=moby/buildkit:latest + + - name: Build Docker image + run: | + set -e + echo "Building Docker image..." + docker build -t talawa-admin-app . + echo "Docker image built successfully" + + - name: Run Docker Container + run: | + set -e + echo "Started Docker container..." + docker run -d --name talawa-admin-app-container -p 4321:4321 talawa-admin-app + echo "Docker container started successfully" + + - name: Check if Talawa Admin App is running + run: | + timeout="${HEALTH_CHECK_TIMEOUT:-120}" + echo "Starting health check with ${timeout}s timeout" + while ! nc -z localhost 4321 && [ $timeout -gt 0 ]; do + sleep 1 + + timeout=$((timeout-1)) + if [ $((timeout % 10)) -eq 0 ]; then + echo "Still waiting for app to start... ${timeout}s remaining" + fi + done + + if [ $timeout -eq 0 ]; then + echo "Timeout waiting for application to start" + echo "Container logs:" + docker logs talawa-admin-app-container + exit 1 + fi + echo "Port check passed, verifying health endpoint..." + + - name: Stop Docker Container + if: always() + run: | + docker stop talawa-admin-app-container + docker rm talawa-admin-app-container + Check-Target-Branch: if: ${{ github.actor != 'dependabot[bot]' }} name: Check Target Branch @@ -262,4 +316,7 @@ jobs: if: github.event.pull_request.base.ref != 'develop' run: | echo "Error: Pull request target branch must be 'develop'. Please refer PR_GUIDELINES.md" + if: github.event.pull_request.base.ref != 'develop-postgres' + run: | + echo "Error: Pull request target branch must be 'develop-postgres'. Please refer PR_GUIDELINES.md" exit 1 diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000..b58b603fea --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000..03d9549ea8 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000..120e01d8b4 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/talawa-admin.iml b/.idea/talawa-admin.iml new file mode 100644 index 0000000000..24643cc374 --- /dev/null +++ b/.idea/talawa-admin.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..35eb1ddfbb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..6b13a712b7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM node:20.10.0 AS build + +WORKDIR /usr/src/app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +RUN npm run build + +EXPOSE 4321 + +CMD ["npm", "run", "serve"] \ No newline at end of file diff --git a/INSTALLATION.md b/INSTALLATION.md index 5813b7d1cb..f392be93a2 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -32,6 +32,9 @@ This document provides instructions on how to set up and start a running instanc - [Husky for Git Hooks](#husky-for-git-hooks) - [pre-commit hook](#pre-commit-hook) - [post-merge hook](#post-merge-hook) +- [Installation using Docker](#installation-using-docker) + - [Prerequisites](#prerequisites-1) + - [Development Setup](#development-setup) @@ -145,15 +148,50 @@ npm install The prerequisites are now installed. The next step will be to get the app up and running. + +# Installation using Docker + +## Prerequisites + +1. Install Docker on your system: + - [Docker Desktop for Windows/Mac](https://www.docker.com/products/docker-desktop) + - [Docker Engine for Linux](https://docs.docker.com/engine/install/) + +### Development Setup + +If you prefer to use Docker, you can install the app using the following command: + +1. Create a `.env` file as described in the Configuration section + +2. Build the Docker Image: + +Run the following command to build the Docker image: + +````bash +docker build -t talawa-admin . +```bash + +3. Run the Docker container: + +After the build is complete, run the Docker container using this command: + +```bash +docker run -p 4321:4321 talawa-admin +```bash + +The application will be accessible at `http://localhost:4321` + + # Configuration It's important to configure Talawa-Admin. Here's how to do it. You can use our interactive setup script for the configuration. Use the following command for the same. -``` +```bash npm run setup -``` +```bash + All the options in "setup" can be done manually as well and here's how to do it. - [Creating .env file](#creating-env-file) @@ -163,7 +201,7 @@ A file named .env is required in the root directory of talawa-admin for storing ``` cp .env.example .env -``` +```` This `.env` file must be populated with the following environment variables for `talawa-admin` to work: diff --git a/config/vite.config.ts b/config/vite.config.ts index 71ce6c6f47..28cd47ae5a 100644 --- a/config/vite.config.ts +++ b/config/vite.config.ts @@ -23,8 +23,9 @@ export default defineConfig({ ], server: { // this ensures that the browser opens upon server start - open: true, - // this sets a default port to 3000 + open: false, + host: '0.0.0.0', + // this sets a default port to 4321 port: 4321, }, }); diff --git a/package-lock.json b/package-lock.json index 0add51da52..dfe806c432 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@mui/material": "^6.1.6", "@mui/private-theming": "^6.1.6", "@mui/system": "^6.1.6", - "@mui/x-charts": "^7.22.1", + "@mui/x-charts": "^7.22.2", "@mui/x-data-grid": "^7.22.1", "@mui/x-date-pickers": "^7.22.1", "@pdfme/generator": "^5.1.7", @@ -85,7 +85,7 @@ "@types/js-cookie": "^3.0.6", "@types/node": "^22.5.4", "@types/node-fetch": "^2.6.10", - "@types/react": "^18.3.3", + "@types/react": "^18.3.12", "@types/react-beautiful-dnd": "^13.1.8", "@types/react-bootstrap": "^0.32.37", "@types/react-chartjs-2": "^2.5.7", @@ -99,7 +99,7 @@ "babel-jest": "^29.7.0", "cross-env": "^7.0.3", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.30.0", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.1", @@ -112,7 +112,7 @@ "jest-preview": "^0.3.1", "lint-staged": "^15.2.8", "postcss-modules": "^6.0.0", - "sass": "^1.80.6", + "sass": "^1.80.7", "tsx": "^4.19.1", "vite-plugin-svgr": "^4.2.0", "whatwg-fetch": "^3.6.20" @@ -3938,9 +3938,9 @@ } }, "node_modules/@mui/x-charts": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.22.1.tgz", - "integrity": "sha512-zgr8CN4yLen5puqaX7Haj5+AoVG7E13HHsIiDoEAuQvuFDF0gKTxTTdLSKXqhd1qJUIIzJaztZtrr3YCVrENqw==", + "version": "7.22.2", + "resolved": "https://registry.npmjs.org/@mui/x-charts/-/x-charts-7.22.2.tgz", + "integrity": "sha512-0Y2du4Ed7gOT53l8vVJ4vKT+Jz4Dh/iHnLy8TtL3+XhbPH9Ndu9Q30WwyyzOn84yt37hSUru/njQ1BWaSvVPHw==", "dependencies": { "@babel/runtime": "^7.25.7", "@mui/utils": "^5.16.6 || ^6.0.0", @@ -5605,6 +5605,9 @@ "version": "18.3.3", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -8910,9 +8913,9 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", - "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, "dependencies": { "@rtsao/scc": "^1.1.0", @@ -8923,7 +8926,7 @@ "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.9.0", + "eslint-module-utils": "^2.12.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", @@ -8932,13 +8935,14 @@ "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -10617,9 +10621,9 @@ } }, "node_modules/immutable": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", - "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.2.tgz", + "integrity": "sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw==", "devOptional": true }, "node_modules/import-fresh": { @@ -16284,13 +16288,13 @@ } }, "node_modules/sass": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.6.tgz", - "integrity": "sha512-ccZgdHNiBF1NHBsWvacvT5rju3y1d/Eu+8Ex6c21nHp2lZGLBEtuwc415QfiI1PJa1TpCo3iXwwSRjRpn2Ckjg==", + "version": "1.80.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.7.tgz", + "integrity": "sha512-MVWvN0u5meytrSjsU7AWsbhoXi1sc58zADXFllfZzbsBT1GHjjar6JwBINYPRrkx/zqnQ6uqbQuHgE95O+C+eQ==", "devOptional": true, "dependencies": { "chokidar": "^4.0.0", - "immutable": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { diff --git a/package.json b/package.json index 892a1331e4..4560ea5d0e 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@mui/material": "^6.1.6", "@mui/private-theming": "^6.1.6", "@mui/system": "^6.1.6", - "@mui/x-charts": "^7.22.1", + "@mui/x-charts": "^7.22.2", "@mui/x-data-grid": "^7.22.1", "@mui/x-date-pickers": "^7.22.1", "@pdfme/schemas": "^5.1.6", @@ -119,7 +119,7 @@ "@types/js-cookie": "^3.0.6", "@types/node": "^22.5.4", "@types/node-fetch": "^2.6.10", - "@types/react": "^18.3.3", + "@types/react": "^18.3.12", "@types/react-beautiful-dnd": "^13.1.8", "@types/react-chartjs-2": "^2.5.7", "@types/react-bootstrap": "^0.32.37", @@ -133,7 +133,7 @@ "babel-jest": "^29.7.0", "cross-env": "^7.0.3", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.30.0", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-jest": "^28.8.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.1", @@ -146,7 +146,7 @@ "jest-preview": "^0.3.1", "lint-staged": "^15.2.8", "postcss-modules": "^6.0.0", - "sass": "^1.80.6", + "sass": "^1.80.7", "tsx": "^4.19.1", "vite-plugin-svgr": "^4.2.0", "whatwg-fetch": "^3.6.20" diff --git a/src/screens/SubTags/SubTags.module.css b/src/screens/SubTags/SubTags.module.css new file mode 100644 index 0000000000..0a210bdfa4 --- /dev/null +++ b/src/screens/SubTags/SubTags.module.css @@ -0,0 +1,145 @@ +.btnsContainer { + display: flex; + margin: 2rem 0; +} + +.btnsContainer .btnsBlock { + display: flex; + width: max-content; +} + +.btnsContainer .btnsBlock button { + margin-left: 1rem; + display: flex; + justify-content: center; + align-items: center; +} + +.btnsContainer .input { + flex: 1; + position: relative; + max-width: 60%; + justify-content: space-between; +} + +.btnsContainer input { + outline: 1px solid var(--bs-gray-400); +} + +.btnsContainer .input button { + width: 52px; +} + +@media (max-width: 1020px) { + .btnsContainer { + flex-direction: column; + margin: 1.5rem 0; + } + + .btnsContainer .btnsBlock { + margin: 1.5rem 0 0 0; + justify-content: space-between; + } + + .btnsContainer .btnsBlock button { + margin: 0; + } + + .btnsContainer .btnsBlock div button { + margin-right: 1.5rem; + } +} + +/* For mobile devices */ + +@media (max-width: 520px) { + .btnsContainer { + margin-bottom: 0; + } + + .btnsContainer .btnsBlock { + display: block; + margin-top: 1rem; + margin-right: 0; + } + + .btnsContainer .btnsBlock div { + flex: 1; + } + + .btnsContainer .btnsBlock div[title='Sort organizations'] { + margin-right: 0.5rem; + } + + .btnsContainer .btnsBlock button { + margin-bottom: 1rem; + margin-right: 0; + width: 100%; + } +} + +.errorContainer { + min-height: 100vh; +} + +.errorMessage { + margin-top: 25%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +.errorIcon { + transform: scale(1.5); + color: var(--bs-danger); + margin-bottom: 1rem; +} + +.tableHeader { + background-color: var(--bs-primary); + color: var(--bs-white); + font-size: 1rem; +} +.rowBackground { + background-color: var(--bs-white); + max-height: 120px; +} + +.subTagsLink { + color: var(--bs-blue); + font-weight: 500; + cursor: pointer; +} + +.subTagsLink i { + visibility: hidden; +} + +.subTagsLink:hover { + font-weight: 600; + text-decoration: underline; +} + +.subTagsLink:hover i { + visibility: visible; +} + +.tagsBreadCrumbs { + color: var(--bs-gray); + cursor: pointer; +} + +.tagsBreadCrumbs:hover { + color: var(--bs-blue); + font-weight: 600; + text-decoration: underline; +} + +.subTagsScrollableDiv { + scrollbar-width: auto; + scrollbar-color: var(--bs-gray-400) var(--bs-white); + + max-height: calc(100vh - 18rem); + overflow: auto; +}