diff --git a/.github/workflows/compare_translations.py b/.github/workflows/compare_translations.py new file mode 100644 index 0000000000..f6f22e843c --- /dev/null +++ b/.github/workflows/compare_translations.py @@ -0,0 +1,170 @@ +"""Script to encourage more efficient coding practices. +Methodology: + + Utility for comparing translations between default and other languages. + + This module defines a function to compare two translations + and print any missing keys in the other language's translation. +Attributes: + + FileTranslation : Named tuple to represent a combination + of file and missing translations. + + Fields: + - file (str): The file name. + - missing_translations (list): List of missing translations. + +Functions: + compare_translations(default_translation, other_translation): + Compare two translations and print missing keys. + + load_translation(filepath): + Load translation from a file. + + check_translations(): + Load the default translation and compare it with other translations. + + main(): + The main function to run the script. + Parses command-line arguments, checks for the + existence of the specified directory, and then + calls check_translations with the provided or default directory. + + +Usage: + This script can be executed to check and print missing + translations in other languages based on the default English translation. + +Example: + python compare_translations.py +NOTE: + This script complies with our python3 coding and documentation standards + and should be used as a reference guide. It complies with: + + 1) Pylint + 2) Pydocstyle + 3) Pycodestyle + 4) Flake8 + +""" +# standard imports +import argparse +import json +import os +import sys +from collections import namedtuple + +# Named tuple for file and missing +# translations combination +FileTranslation = namedtuple("FileTranslation", + ["file", "missing_translations"]) + + +def compare_translations(default_translation, + other_translation, default_file, other_file): + """Compare two translations and return detailed info about missing/mismatched keys. + + Args: + default_translation (dict): The default translation (en.json). + other_translation (dict): The other language translation. + default_file (str): The name of the default translation file. + other_file (str): The name of the other + translation file. + + Returns: + list: A list of detailed error messages for each missing/mismatched key. + """ + errors = [] + + # Check for missing keys in other_translation + for key in default_translation: + if key not in other_translation: + error_msg = f"Missing Key: '{key}' - This key from '{default_file}' is missing in '{other_file}'." + errors.append(error_msg) + # Check for keys in other_translation that don't match any in default_translation + for key in other_translation: + if key not in default_translation: + error_msg = f"Error Key: '{key}' - This key in '{other_file}' does not match any key in '{default_file}'." + errors.append(error_msg) + return errors + + +def load_translation(filepath): + """Load translation from a file. + + Args: + filepath: Path to the translation file + + Returns: + translation: Loaded translation + """ + with open(filepath, "r", encoding="utf-8") as file: + translation = json.load(file) + return translation + + +def check_translations(directory): + """Load default translation and compare with other translations. + + Args: + directory (str): The directory containing translation files. + + Returns: + None + """ + default_file = "en.json" + default_translation = load_translation(os.path.join(directory, default_file)) + translations = os.listdir(directory) + translations.remove(default_file) # Exclude default translation + + error_found = False + + for translation_file in translations: + other_file = os.path.join(directory, translation_file) + other_translation = load_translation(other_file) + + # Compare translations and get detailed error messages + errors = compare_translations( + default_translation, other_translation, default_file, translation_file + ) + if errors: + error_found = True + print(f"File {translation_file} has missing translations for:") + for error in errors: + print(f" - {error}") + + if error_found: + sys.exit(1) # Exit with an error status code + else: + print("All translations are present") + sys.exit(0) + + +def main(): + """ + + Parse command-line arguments, check for the existence of the specified directory + and call check_translations with the provided or default directory. + + """ + parser = argparse.ArgumentParser( + description="Check and print missing translations for all non-default languages." + ) + parser.add_argument( + "--directory", + type=str, + nargs="?", + default=os.path.join(os.getcwd(), "public/locales"), + help="Directory containing translation files(relative to the root directory).", + ) + args = parser.parse_args() + + if not os.path.exists(args.directory): + print(f"Error: The specified directory '{args.directory}' does not exist.") + sys.exit(1) + + check_translations(args.directory) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/count_changed_files.py b/.github/workflows/count_changed_files.py new file mode 100644 index 0000000000..64fbc8bbfa --- /dev/null +++ b/.github/workflows/count_changed_files.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +"""Script to limit number of file changes in single PR. + +Methodology: + + Analyses the Pull request to find if the count of file changed in a pr + exceeds a pre-defined nummber 20 + + This scripts encourages contributors to align with project practices, + reducing the likelihood of unintentional merges into incorrect branches. + +NOTE: + + This script complies with our python3 coding and documentation standards. + It complies with: + + 1) Pylint + 2) Pydocstyle + 3) Pycodestyle + 4) Flake8 + +""" + +import sys +import argparse +import subprocess + + +def _count_changed_files(base_branch, pr_branch): + """ + Count the number of changed files between two branches. + + Args: + base_branch (str): The base branch. + pr_branch (str): The PR branch. + + Returns: + int: The number of changed files. + + Raises: + SystemExit: If an error occurs during execution. + """ + base_branch = f"origin/{base_branch}" + pr_branch = f"origin/{pr_branch}" + + command = f"git diff --name-only {base_branch}...{pr_branch} | wc -l" + + try: + # Run git command to get the list of changed files + process = subprocess.Popen( + command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + output, error = process.communicate() + except Exception as e: + print(f"Error: {e}") + sys.exit(1) + + file_count = int(output.strip()) + return file_count + +def _arg_parser_resolver(): + """Resolve the CLI arguments provided by the user. + + Args: + None + + Returns: + result: Parsed argument object + + """ + parser = argparse.ArgumentParser() + parser.add_argument( + "--base_branch", + type=str, + required=True, + help="Base branch where pull request should be made." + ), + parser.add_argument( + "--pr_branch", + type=str, + required=True, + help="PR branch from where the pull request is made.", + ), + parser.add_argument( + "--file_count", + type=int, + default=20, + help="Number of files changes allowed in a single commit") + return parser.parse_args() + + +def main(): + """ + Execute the script's main functionality. + + This function serves as the entry point for the script. It performs + the following tasks: + 1. Validates and retrieves the base branch and PR commit from + command line arguments. + 2. Counts the number of changed files between the specified branches. + 3. Checks if the count of changed files exceeds the acceptable + limit (20). + 4. Provides informative messages based on the analysis. + + Raises: + SystemExit: If an error occurs during execution. + """ + + args = _arg_parser_resolver() + + base_branch = args.base_branch + pr_branch = args.pr_branch + + print(f"You are trying to merge on branch: {base_branch}") + print(f"You are making commit from your branch: {pr_branch}") + + # Count changed files + file_count = _count_changed_files(base_branch, pr_branch) + print(f"Number of changed files: {file_count}") + + # Check if the count exceeds 20 + if file_count > args.file_count: + print("Error: Too many files (greater than 20) changed in the pull request.") + print("Possible issues:") + print("- Contributor may be merging into an incorrect branch.") + print("- Source branch may be incorrect please use develop as source branch.") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/md_mpx_format_adjuster.py b/.github/workflows/md_mpx_format_adjuster.py new file mode 100644 index 0000000000..e1609b710b --- /dev/null +++ b/.github/workflows/md_mpx_format_adjuster.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# -*- coding: UTF-8 -*- +""" +Script to make Markdown files MPX compatible. + +This script scans Markdown files and escapes special characters (<, >, {, }) +to make them compatible with the MPX standard used in Docusaurus v3. + +This script complies with: + 1) Pylint + 2) Pydocstyle + 3) Pycodestyle + 4) Flake8 +""" + +import os +import argparse +import re + +def escape_mpx_characters(text): + """ + Escape special characters in a text string for MPX compatibility. + Avoids escaping already escaped characters. + + Args: + text: A string containing the text to be processed. + + Returns: + A string with special characters (<, >, {, }) escaped, avoiding + double escaping. + """ + # Regular expressions to find unescaped special characters + patterns = { + "<": r"(?": r"(?", + "{": r"(? + +- [Our Pledge](#our-pledge) +- [Our Standards](#our-standards) +- [Enforcement Responsibilities](#enforcement-responsibilities) +- [Scope](#scope) +- [Enforcement](#enforcement) +- [Enforcement Guidelines](#enforcement-guidelines) + - [1. Correction](#1-correction) + - [2. Warning](#2-warning) + - [3. Temporary Ban](#3-temporary-ban) + - [4. Permanent Ban](#4-permanent-ban) +- [Attribution](#attribution) + + + ## Our Pledge We as members, contributors, and leaders pledge to make participation in our diff --git a/CODE_STYLE.md b/CODE_STYLE.md index b93a8c0f57..160762f487 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -1,4 +1,3 @@ - # Talawa Admin Code Style For Talawa Admin, most of the rules for the code style have been enforced with ESLint, but this document serves to provide an overview of the Code style used in Talawa Admin and the Rationale behind it. @@ -7,6 +6,21 @@ The code style must be strictly adhered to, to ensure that there is consistency code style should not be changed and must be followed. +# Table of Contents + + + +- [Tech Stack](#tech-stack) +- [Component Structure](#component-structure) +- [Code Style and Naming Conventions](#code-style-and-naming-conventions) +- [Test and Code Linting](#test-and-code-linting) +- [Folder/Directory Structure](#folderdirectory-structure) + - [Sub Directories of `src`](#sub-directories-of-src) +- [Imports](#imports) +- [Customising Bootstrap](#customising-bootstrap) + + + ## Tech Stack - Typescript @@ -175,7 +189,7 @@ Follow this [link](https://getbootstrap.com/docs/5.3/customize/sass/) to learn h **File Structure** -- `src/assets/scss/components/{partialFile}.scss` - where the {partialFile} are the following files +- `src/assets/scss/components/{'{partialFile}'}.scss` - where the {'{partialFile}'} are the following files - **_accordion.scss** - **_alert.scss** - **_badge.scss** @@ -195,12 +209,12 @@ Follow this [link](https://getbootstrap.com/docs/5.3/customize/sass/) to learn h - **_progress.scss** - **_spinners.scss** -- `src/assets/scss/content/{partialFile}.scss` - where the {partialFile} are the following files +- `src/assets/scss/content/{'{partialFile}'}.scss` - where the {'{partialFile}'} are the following files - **_table.scss** - **_typography.scss** -- `src/assets/scss/forms/{partialFile}.scss` - where the {partialFile} are the following files +- `src/assets/scss/forms/{'{partialFile}'}.scss` - where the {'{partialFile}'} are the following files - **_check-radios.scss** - **_floating-label.scss** - **_form-control.scss** diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d3138a981..acb7d3b038 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,18 +6,20 @@ If you are new to contributing to open source, please read the Open Source Guide ## Table of Contents -- [Contributing to Talawa-Admin](#contributing-to-talawa-admin) - - [Table of Contents](#table-of-contents) - - [Code of Conduct](#code-of-conduct) - - [Ways to Contribute](#ways-to-contribute) - - [Our Development Process](#our-development-process) - - [Issues](#issues) - - [Pull Requests](#pull-requests) - - [Branching Strategy](#branching-strategy) - - [Conflict Resolution](#conflict-resolution) - - [Contributing Code](#contributing-code) - - [Internships](#internships) - - [Community](#community) + + +- [Code of Conduct](#code-of-conduct) +- [Ways to Contribute](#ways-to-contribute) + - [Our Development Process](#our-development-process) + - [Issues](#issues) + - [Pull Requests](#pull-requests) + - [Branching Strategy](#branching-strategy) + - [Conflict Resolution](#conflict-resolution) + - [Contributing Code](#contributing-code) +- [Internships](#internships) +- [Community](#community) + + ## Code of Conduct diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index aecf8cc132..7691b5d452 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -1,5 +1,16 @@ # Documentation Welcome to our documentation guide. Here are some useful tips you need to know! + +# Table of Contents + + + +- [Where to find our documentation](#where-to-find-our-documentation) +- [How to use Docusaurus](#how-to-use-docusaurus) +- [Other information](#other-information) + + + ## Where to find our documentation Our documentation can be found in ONLY TWO PLACES: diff --git a/INSTALLATION.md b/INSTALLATION.md index b351963b89..58555ec4b5 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -4,18 +4,18 @@ This document provides instructions on how to set up and start a running instanc # Table of Contents -- [Talawa-Admin Installation](#talawa-admin-installation) -- [Table of Contents](#table-of-contents) + + - [Prerequisites for Developers](#prerequisites-for-developers) - [Installation](#installation) - - [Clone This Repository](#clone-this-repository) - - [Change Directory into the Cloned Repo](#change-directory-into-the-cloned-repo) - - [Setting up NPM](#setting-up-npm) + - [Setting up this repository](#setting-up-this-repository) + - [Setting up npm](#setting-up-npm) + - [Setting up Typescript](#setting-up-typescript) - [Installing required packages/dependencies](#installing-required-packagesdependencies) - [Configuration](#configuration) - [Creating .env file](#creating-env-file) - - [Setting up REACT\_APP\_TALAWA\_URL in .env file](#setting-up-react_app_talawa_url-in-env-file) - - [Setting up REACT\_APP\_RECAPTCHA\_SITE\_KEY in .env file](#setting-up-react_app_recaptcha_site_key-in-env-file) + - [Setting up REACT_APP_TALAWA_URL in .env file](#setting-up-react_app_talawa_url-in-env-file) + - [Setting up REACT_APP_RECAPTCHA_SITE_KEY in .env file](#setting-up-react_app_recaptcha_site_key-in-env-file) - [Post Configuration Steps](#post-configuration-steps) - [Running Talawa-Admin](#running-talawa-admin) - [Accessing Talawa-Admin](#accessing-talawa-admin) @@ -29,6 +29,8 @@ This document provides instructions on how to set up and start a running instanc - [pre-commit hook](#pre-commit-hook) - [post-merge hook](#post-merge-hook) + + # Prerequisites for Developers We recommend that you follow these steps before beginning development work on Talawa-Admin: @@ -39,30 +41,41 @@ We recommend that you follow these steps before beginning development work on Ta The INSTALLATION.md files in both repositories show you how. The Talawa-API INSTALLATION.md will also show you the Organization URL to use access Talawa Admin. # Installation + You will need to have copies of your code on your local system. Here's how to do that. -## Clone This Repository + +## Setting up this repository First you need a local copy of `talawa-admin`. Run the following command in the directory of choice on your local system. +1. Navigate to the folder where you want to setup the repository. Here, I will set it up in a folder called `talawa`. +2. Navigate to the folder and open a terminal in this folder (you can right-click and choose appropiate option based onn your OS). Next, we'll fork and clone the `talawa-admin` repository. +3. Navigate to [https://github.com/PalisadoesFoundation/talawa-admin/](hhttps://github.com/PalisadoesFoundation/talawa-admin/) and click on the `fork` button. It is placed on the right corner opposite the repository name `PalisadoesFoundation/talawa-admin`. +4. You should now see `talawa-admin` under your repositories. It will be marked as forked from `PalisadoesFoundation/talawa-admin` +5. Clone the repository to your local computer (replacing the values in `{{}}`): + ``` -git clone https://github.com/PalisadoesFoundation/talawa-admin +$ git clone https://github.com/{{YOUR GITHUB USERNAME}}/talawa-admin.git ``` -This will download a local copy of `talawa-admin` in that directory. +This will setup the repository and the code files locally for you. For more detailed instructions on contributing code, and managing the versions of this repository with Git, checkout [CONTRIBUTING.md here](./CONTRIBUTING.md) -## Change Directory into the Cloned Repo +**NOTE:** `All the commands we're going to execute in the following instructions will assume you are in the root directory of the cloned talawa-admin project. If you fail to do so, the commands will not work.` -Right after cloning the repo you can change the directory of your current `terminal(shell)` to the root directory of cloned repository using this command: +## Setting up npm -``` -cd talawa-admin -``` +Best way to install and manage `node.js` is making use of node version managers. Two most popular node version managers right now are [fnm](https://github.com/Schniz/fnm) and [nvm](https://github.com/nvm-sh/nvm). We'd recommend `fnm` because it's written in `rust` and is much faster than `nvm`. Install whichever one you want and follow their guide to set up `node.js` on your system. -**NOTE:** `All the commands we're going to execute in the following instructions will assume you are in the root directory of the cloned talawa-admin project. If you fail to do so, the commands will not work.` +## Setting up Typescript -## Setting up NPM +As `talawa-admin` and `talawa-api` repositories are written using [Typescript](https://www.typescriptlang.org/), you will need to install typescript on your machine. +We recommend to install `Typescript` globally on your machine by running the following command in the terminal: -If you've followed the previous steps you should have already set up node.js on your system. [Click here](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) for the official setup guide for npm. +``` +npm install -g typescript +``` + +For more details please refer to the installation guidelines provided in the [official docs](https://www.typescriptlang.org/download). ## Installing required packages/dependencies @@ -71,8 +84,11 @@ Run the following command to install the packages and dependencies required by ` ``` npm install --legacy-peer-deps ``` + # Configuration + It's important to configure Talawa-Admin. Here's how to do it. + ## Creating .env file A file named .env is required in the root directory of talawa-admin for storing environment variables used at runtime. It is not a part of the repo and you will have to create it. For a sample of `.env` file there is a file named `.env.example` in the root directory. Create a new `.env` file by copying the contents of the `.env.example` into `.env` file. Use this command: @@ -93,7 +109,7 @@ Follow the instructions from section [Setting up REACT_APP_TALAWA_URL in .env fi ## Setting up REACT_APP_TALAWA_URL in .env file -Add the endpoint for accessing talawa-api graphql service to the variable named `REACT_APP_TALAWA_URL` in the `.env` file. +Add the endpoint for accessing talawa-api graphql service to the variable named `REACT_APP_TALAWA_URL` in the `.env` file. ``` REACT_APP_TALAWA_URL="http://API-IP-ADRESS:4000/graphql/" @@ -129,6 +145,7 @@ REACT_APP_RECAPTCHA_SITE_KEY="this_is_the_recaptcha_key" Set the `ALLOW_LOGS` to "YES" if you want warnings , info and error messages in your console or leave it blank if you dont need them or want to keep the console clean # Post Configuration Steps + It's now time to start Talawa-Admin and get it running ## Running Talawa-Admin @@ -151,12 +168,12 @@ http://localhost:3000/ The first time you navigate to the running talawa-admin's website you'll land at talawa-admin registration page. Sign up using whatever credentials you want and create the account. Make sure to remember the email and password you entered because they'll be used to sign you in later on. - ## Talawa-Admin Login Now sign in to talawa-admin using the `email` and `password` you used to sign up. # Testing + It is important to test our code. If you are a contributor, please follow these steps. ## Running tests @@ -180,7 +197,6 @@ You don't need to re-run the `npm run jest-preview` command each time, simply ru ![Debugging Test Demo](./public/images/jest-preview.webp) - ## Linting code files You can lint your code files using this command: @@ -191,30 +207,24 @@ npm run lint:fix ## Husky for Git Hooks - We are using the package `Husky` to run git hooks that run according to different git workflows. -
#### pre-commit hook -We run a pre-commit hook which automatically runs code quality checks each time you make a commit and also fixes some of the issues. This way you don't have to run them manually each time. +We run a pre-commit hook which automatically runs code quality checks each time you make a commit and also fixes some of the issues. This way you don't have to run them manually each time. If you don't want these pre-commit checks running on each commit, you can manually opt out of it using the `--no-verify` flag with your commit message as shown:- git commit -m "commit message" --no-verify -
- #### post-merge hook We are also running a post-merge(post-pull) hook which will automatically run "npm install --legacy-peer-deps" only if there is any change made to pakage.json file so that the developer has all the required dependencies when pulling files from remote. - If you don't want this hook to run, you can manually opt out of this using the `no verify` flag while using the merge command(git pull): - git pull --no-verify + git pull --no-verify
- diff --git a/ISSUE_GUIDELINES.md b/ISSUE_GUIDELINES.md index 18b93ee10b..d57420d983 100644 --- a/ISSUE_GUIDELINES.md +++ b/ISSUE_GUIDELINES.md @@ -6,18 +6,18 @@ In order to give everyone a chance to submit a issues reports and contribute to ___ ## Table of Contents - - -- [Issue Report Guidelines](#issue-report-guidelines) - - [Table of Contents](#table-of-contents) - - [Issue Management](#issue-management) - - [New Issues](#new-issues) - - [Existing Issues](#existing-issues) - - [Feature Request Issues](#feature-request-issues) - - [Monitoring the Creation of New Issues](#monitoring-the-creation-of-new-issues) - - [General Guidelines](#general-guidelines) - - + + + +- [Issue Management](#issue-management) + - [New Issues](#new-issues) + - [Existing Issues](#existing-issues) + - [Feature Request Issues](#feature-request-issues) + - [Monitoring the Creation of New Issues](#monitoring-the-creation-of-new-issues) +- [General Guidelines](#general-guidelines) + + + ___ ## Issue Management diff --git a/PR_GUIDELINES.md b/PR_GUIDELINES.md index d1c2a0b2d9..4c904c782d 100644 --- a/PR_GUIDELINES.md +++ b/PR_GUIDELINES.md @@ -4,6 +4,18 @@ In order to give everyone a chance to submit a pull request and contribute to the Talawa project, we have put restrictions in place. This section outlines the guidelines that should be imposed upon pull requests in the Talawa project. +# Table of Contents + + + +- [Pull Requests and Issues](#pull-requests-and-issues) +- [Linting and Formatting](#linting-and-formatting) +- [Testing](#testing) +- [Pull Request Processing](#pull-request-processing) + - [Only submit PRs against our `develop` branch, not the default `main` branch](#only-submit-prs-against-our-develop-branch-not-the-default-main-branch) + + + ## Pull Requests and Issues 1. Do not start working on any open issue and raise a PR unless the issue is assigned to you. PRs that don't meet these guidelines will be closed. diff --git a/README.md b/README.md index 39be8dbb3d..5ee7c6d04c 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,16 @@ Core features include: `talawa` is based on the original `quito` code created by the [Palisadoes Foundation][pfd] as part of its annual Calico Challenge program. Calico provides paid summer internships for Jamaican university students to work on selected open source projects. They are mentored by software professionals and receive stipends based on the completion of predefined milestones. Calico was started in 2015. Visit [The Palisadoes Foundation's website](http://www.palisadoes.org/) for more details on its origin and activities. +# Table of Contents + + + +- [Talawa Components](#talawa-components) +- [Documentation](#documentation) +- [Installation](#installation) + + + # Talawa Components `talawa` has these major software components: @@ -37,4 +47,4 @@ Core features include: # Installation -[Follow this guide](https://github.com/PalisadoesFoundation/talawa-admin/blob/develop/INSTALLATION.md) +[Follow this guide](https://github.com/PalisadoesFoundation/talawa-admin/blob/develop/INSTALLATION.md) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e96cd95feb..5f2c00f845 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,33 +15,15 @@ "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.8.3", "@mui/material": "^5.14.1", - "@mui/private-theming": "^5.14.13", "@mui/system": "^5.14.12", "@mui/x-charts": "^6.0.0-alpha.13", "@mui/x-data-grid": "^6.8.0", "@mui/x-date-pickers": "^6.6.0", "@pdfme/generator": "^1.2.6", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^11.1.0", - "@testing-library/user-event": "^12.1.10", - "@types/enzyme-adapter-react-16": "^1.0.6", - "@types/jest": "^26.0.24", - "@types/jquery": "^3.5.6", - "@types/node": "^12.20.16", - "@types/react-bootstrap": "^0.32.32", - "@types/react-datepicker": "^4.1.4", - "@types/react-dom": "^17.0.9", - "@types/react-google-recaptcha": "^2.1.5", - "@types/react-modal": "^3.12.1", "bootstrap": "^5.3.0", "customize-cra": "^1.0.0", "dayjs": "^1.10.7", - "detect-newline": "^4.0.0", "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.6", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-jest": "^25.3.4", - "eslint-plugin-prettier": "^3.4.0", "flag-icons": "^6.6.6", "graphql": "^15.5.1", "graphql-tag": "^2.12.6", @@ -49,8 +31,8 @@ "i18next": "^21.8.14", "i18next-browser-languagedetector": "^6.1.4", "i18next-http-backend": "^1.4.1", - "jest-docblock": "^27.4.0", "js-cookie": "^3.0.1", + "lint-staged": "^15.2.0", "markdown-toc": "^1.2.0", "node-sass": "^9.0.0", "prettier": "^2.3.2", @@ -69,25 +51,31 @@ "react-toastify": "^9.0.3", "redux": "^4.1.1", "redux-thunk": "^2.3.0", - "typedoc": "^0.24.8", - "typedoc-plugin-markdown": "^3.16.0", "typescript": "^4.3.5", - "web-vitals": "^1.0.1", - "yarn": "^1.22.17" + "web-vitals": "^1.0.1" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@fortawesome/fontawesome-svg-core": "^1.2.35", - "@fortawesome/free-brands-svg-icons": "^5.15.3", - "@fortawesome/react-fontawesome": "^0.1.14", + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^11.1.0", + "@testing-library/user-event": "^12.1.10", "@types/enzyme": "^3.10.9", + "@types/jest": "^26.0.24", "@types/js-cookie": "^3.0.2", + "@types/node": "^12.20.16", "@types/react": "^17.0.14", + "@types/react-bootstrap": "^0.32.32", + "@types/react-datepicker": "^4.1.4", + "@types/react-dom": "^17.0.9", + "@types/react-google-recaptcha": "^2.1.5", "@types/react-router-dom": "^5.1.8", "@typescript-eslint/eslint-plugin": "^5.9.0", "@typescript-eslint/parser": "^5.9.0", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "cross-env": "^7.0.3", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-jest": "^25.3.4", + "eslint-plugin-prettier": "^3.4.0", "husky": "^8.0.3", "identity-obj-proxy": "^3.0.0", "jest": "^27.4.5", @@ -95,7 +83,6 @@ "jest-localstorage-mock": "^2.4.19", "jest-location-mock": "^1.0.9", "jest-preview": "^0.3.1", - "jquery": "^3.2.1", "postcss-modules": "^6.0.0" }, "engines": { @@ -113,7 +100,8 @@ "node_modules/@adobe/css-tools": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.2.0.tgz", - "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==" + "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==", + "dev": true }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", @@ -2213,6 +2201,7 @@ "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.22.6.tgz", "integrity": "sha512-M+37LLIRBTEVjktoJjbw4KVhupF0U/3PYUCbBwgAd9k17hoKhRu1n935QiG7Tuxv0LJOMrb2vuKEeYUlv0iyiw==", + "dev": true, "dependencies": { "core-js-pure": "^3.30.2", "regenerator-runtime": "^0.13.11" @@ -2843,55 +2832,6 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz", "integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==" }, - "node_modules/@fortawesome/fontawesome-common-types": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", - "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", - "dev": true, - "hasInstallScript": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "1.2.36", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", - "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.36" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-brands-svg-icons": { - "version": "5.15.4", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz", - "integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.36" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/react-fontawesome": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz", - "integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==", - "dev": true, - "dependencies": { - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "@fortawesome/fontawesome-svg-core": "~1 || ~6", - "react": ">=16.x" - } - }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -4706,6 +4646,7 @@ "version": "7.31.2", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.31.2.tgz", "integrity": "sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -4724,6 +4665,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.10.2", "@babel/runtime-corejs3": "^7.10.2" @@ -4736,6 +4678,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4751,6 +4694,7 @@ "version": "5.16.5", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "dev": true, "dependencies": { "@adobe/css-tools": "^4.0.1", "@babel/runtime": "^7.9.2", @@ -4772,6 +4716,7 @@ "version": "11.2.7", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.7.tgz", "integrity": "sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==", + "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^7.28.1" @@ -4788,6 +4733,7 @@ "version": "12.8.3", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-12.8.3.tgz", "integrity": "sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==", + "dev": true, "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -4818,7 +4764,8 @@ "node_modules/@types/aria-query": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==" + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.1", @@ -4878,6 +4825,7 @@ "version": "0.22.31", "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz", "integrity": "sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -4903,23 +4851,17 @@ "version": "3.10.13", "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.13.tgz", "integrity": "sha512-FCtoUhmFsud0Yx9fmZk179GkdZ4U9B0GFte64/Md+W/agx0L5SxsIIbhLBOxIb9y2UfBA4WQnaG1Od/UsUQs9Q==", + "dev": true, "dependencies": { "@types/cheerio": "*", "@types/react": "^16" } }, - "node_modules/@types/enzyme-adapter-react-16": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.6.tgz", - "integrity": "sha512-VonDkZ15jzqDWL8mPFIQnnLtjwebuL9YnDkqeCDYnB4IVgwUm0mwKkqhrxLL6mb05xm7qqa3IE95m8CZE9imCg==", - "dependencies": { - "@types/enzyme": "*" - } - }, "node_modules/@types/enzyme/node_modules/@types/react": { "version": "16.14.43", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.43.tgz", "integrity": "sha512-7zdjv7jvoLLQg1tTvpQsm+hyNUMT2mPlNV1+d0I8fbGhkJl82spopMyBlu4wb1dviZAxpGdk5eHu/muacknnfw==", + "dev": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -5037,19 +4979,12 @@ "version": "26.0.24", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", + "dev": true, "dependencies": { "jest-diff": "^26.0.0", "pretty-format": "^26.0.0" } }, - "node_modules/@types/jquery": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz", - "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==", - "dependencies": { - "@types/sizzle": "*" - } - }, "node_modules/@types/js-cookie": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz", @@ -5130,6 +5065,7 @@ "version": "0.32.32", "resolved": "https://registry.npmjs.org/@types/react-bootstrap/-/react-bootstrap-0.32.32.tgz", "integrity": "sha512-GM9UtV7v+C2F0rbqgIpMWdCKBMdX3PQURoJQobPO4vDAeFadcExNtKffi13/MjaAks+riJKVGyiMe+6OmDYT2w==", + "dev": true, "dependencies": { "@types/react": "*" } @@ -5138,6 +5074,7 @@ "version": "4.11.2", "resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.11.2.tgz", "integrity": "sha512-ELYyX3lb3K1WltqdlF1hbnaDGgzlF6PIR5T4W38cSEcfrQDIrPE+Ioq5pwRe/KEJ+ihHMjvTVZQkwJx0pWMNHQ==", + "dev": true, "dependencies": { "@popperjs/core": "^2.9.2", "@types/react": "*", @@ -5149,6 +5086,7 @@ "version": "17.0.20", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.20.tgz", "integrity": "sha512-4pzIjSxDueZZ90F52mU3aPoogkHIoSIDG+oQ+wQK7Cy2B9S+MvOqY0uEA/qawKz381qrEDkvpwyt8Bm31I8sbA==", + "dev": true, "dependencies": { "@types/react": "^17" } @@ -5157,14 +5095,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@types/react-google-recaptcha/-/react-google-recaptcha-2.1.5.tgz", "integrity": "sha512-iWTjmVttlNgp0teyh7eBXqNOQzVq2RWNiFROWjraOptRnb1OcHJehQnji0sjqIRAk9K0z8stjyhU+OLpPb0N6w==", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-modal": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.0.tgz", - "integrity": "sha512-iphdqXAyUfByLbxJn5j6d+yh93dbMgshqGP0IuBeaKbZXx0aO+OXsvEkt6QctRdxjeM9/bR+Gp3h9F9djVWTQQ==", + "dev": true, "dependencies": { "@types/react": "*" } @@ -5259,11 +5190,6 @@ "@types/node": "*" } }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", - "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" - }, "node_modules/@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -5281,6 +5207,7 @@ "version": "5.14.8", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.8.tgz", "integrity": "sha512-NRfJE9Cgpmu4fx716q9SYmU4jxxhYRU1BQo239Txt/9N3EC745XZX1Yl7h/SBIDlo1ANVOCRB4YDXjaQdoKCHQ==", + "dev": true, "dependencies": { "@types/jest": "*" } @@ -5880,33 +5807,6 @@ "node": ">=8" } }, - "node_modules/airbnb-prop-types": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz", - "integrity": "sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==", - "dependencies": { - "array.prototype.find": "^2.1.1", - "function.prototype.name": "^1.1.2", - "is-regex": "^1.1.0", - "object-is": "^1.1.2", - "object.assign": "^4.1.0", - "object.entries": "^1.1.2", - "prop-types": "^15.7.2", - "prop-types-exact": "^1.2.0", - "react-is": "^16.13.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "react": "^0.14 || ^15.0.0 || ^16.0.0-alpha" - } - }, - "node_modules/airbnb-prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", @@ -5991,11 +5891,6 @@ "node": ">=8" } }, - "node_modules/ansi-sequence-parser": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", - "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==" - }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -6176,20 +6071,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.find": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.1.tgz", - "integrity": "sha512-I2ri5Z9uMpMvnsNrHre9l3PaX+z9D0/z6F7Yt2u15q7wt0I62g5kX6xUKR1SJiefgG+u2/gJUmM8B47XRvQR6w==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/array.prototype.flat": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", @@ -7355,6 +7236,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -7621,6 +7503,81 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", + "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -8389,7 +8346,8 @@ "node_modules/css.escape": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true }, "node_modules/cssdb": { "version": "7.6.0", @@ -8923,17 +8881,6 @@ "node": ">=0.10.0" } }, - "node_modules/detect-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.0.tgz", - "integrity": "sha512-1aXUEPdfGdzVPFpzGJJNgq9o81bGg1s09uxTWsqBlo9PI332uyJRQq13+LK/UN4JfxJbFdCXonUFQ9R/p7yCtw==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -8990,6 +8937,7 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true, "engines": { "node": ">= 10.14.2" } @@ -9045,7 +8993,8 @@ "node_modules/dom-accessibility-api": { "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true }, "node_modules/dom-converter": { "version": "0.2.0", @@ -9326,94 +9275,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/enzyme-adapter-react-16": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.7.tgz", - "integrity": "sha512-LtjKgvlTc/H7adyQcj+aq0P0H07LDL480WQl1gU512IUyaDo/sbOaNDdZsJXYW2XaoPqrLLE9KbZS+X2z6BASw==", - "dependencies": { - "enzyme-adapter-utils": "^1.14.1", - "enzyme-shallow-equal": "^1.0.5", - "has": "^1.0.3", - "object.assign": "^4.1.4", - "object.values": "^1.1.5", - "prop-types": "^15.8.1", - "react-is": "^16.13.1", - "react-test-renderer": "^16.0.0-0", - "semver": "^5.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "enzyme": "^3.0.0", - "react": "^16.0.0-0", - "react-dom": "^16.0.0-0" - } - }, - "node_modules/enzyme-adapter-react-16/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/enzyme-adapter-react-16/node_modules/react-test-renderer": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.14.0.tgz", - "integrity": "sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg==", - "dependencies": { - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "react-is": "^16.8.6", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/enzyme-adapter-react-16/node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/enzyme-adapter-react-16/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/enzyme-adapter-utils": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.1.tgz", - "integrity": "sha512-JZgMPF1QOI7IzBj24EZoDpaeG/p8Os7WeBZWTJydpsH7JRStc7jYbHE4CmNQaLqazaGFyLM8ALWA3IIZvxW3PQ==", - "dependencies": { - "airbnb-prop-types": "^2.16.0", - "function.prototype.name": "^1.1.5", - "has": "^1.0.3", - "object.assign": "^4.1.4", - "object.fromentries": "^2.0.5", - "prop-types": "^15.8.1", - "semver": "^5.7.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - }, - "peerDependencies": { - "react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0" - } - }, - "node_modules/enzyme-adapter-utils/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/enzyme-matchers": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/enzyme-matchers/-/enzyme-matchers-7.1.2.tgz", @@ -9705,6 +9566,7 @@ "version": "8.8.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -9917,6 +9779,7 @@ "version": "3.4.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0" }, @@ -10858,7 +10721,8 @@ "node_modules/fast-diff": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true }, "node_modules/fast-glob": { "version": "3.3.0", @@ -11500,6 +11364,17 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", @@ -11909,41 +11784,13 @@ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">=4" } }, "node_modules/har-validator": { @@ -13632,6 +13479,7 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^26.6.2", @@ -13646,6 +13494,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13661,6 +13510,7 @@ "version": "26.3.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true, "engines": { "node": ">= 10.14.2" } @@ -16012,12 +15862,6 @@ "jiti": "bin/jiti.js" } }, - "node_modules/jquery": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.0.tgz", - "integrity": "sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==", - "dev": true - }, "node_modules/js-base64": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", @@ -16184,11 +16028,6 @@ "node": ">=6" } }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -16355,6 +16194,191 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/lint-staged": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.0.tgz", + "integrity": "sha512-TFZzUEV00f+2YLaVPWBWGAMq7So6yQx+GG8YRMDeOEIf95Zn5RyiLMsEiX4KTNl9vq/w+NqRJkLA1kPIo15ufQ==", + "dependencies": { + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.0", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "engines": { + "node": ">=16" + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "engines": { + "node": ">=14" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "engines": { + "node": ">= 14" + } + }, "node_modules/list-item": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", @@ -16410,6 +16434,100 @@ "node": ">=0.10.0" } }, + "node_modules/listr2": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.0.tgz", + "integrity": "sha512-u8cusxAcyqAiQ2RhYvV7kRKNLgUvtObIbhOX2NCXqvp1UU32xIg5CT22ykS2TPKJXZWJwtK3IKLiqAGlGNE+Zg==", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + }, + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", + "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -16613,6 +16731,173 @@ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "dependencies": { + "type-fest": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", + "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" +======= + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -16649,15 +16934,11 @@ "yallist": "^3.0.2" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" - }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, "bin": { "lz-string": "bin/bin.js" } @@ -16825,10 +17106,10 @@ "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "bin": { - "marked": "bin/marked.js" + "markdown-toc": "cli.js" }, "engines": { - "node": ">= 12" + "node": ">=0.10.0" } }, "node_modules/math-random": { @@ -18340,6 +18621,17 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -19732,6 +20024,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, "dependencies": { "fast-diff": "^1.1.2" }, @@ -19763,6 +20056,7 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, "dependencies": { "@jest/types": "^26.6.2", "ansi-regex": "^5.0.0", @@ -19777,6 +20071,7 @@ "version": "26.6.2", "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", @@ -19792,6 +20087,7 @@ "version": "15.0.15", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz", "integrity": "sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==", + "dev": true, "dependencies": { "@types/yargs-parser": "*" } @@ -19800,6 +20096,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -19814,7 +20111,8 @@ "node_modules/pretty-format/node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true }, "node_modules/process-nextick-args": { "version": "2.0.1", @@ -19868,16 +20166,6 @@ "react-is": "^16.13.1" } }, - "node_modules/prop-types-exact": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", - "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", - "dependencies": { - "has": "^1.0.3", - "object.assign": "^4.1.0", - "reflect.ownkeys": "^0.2.0" - } - }, "node_modules/prop-types-extra": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", @@ -20830,11 +21118,6 @@ "redux": "^4" } }, - "node_modules/reflect.ownkeys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", - "integrity": "sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg==" - }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -21455,6 +21738,21 @@ "lowercase-keys": "^1.0.0" } }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/restructure": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.0.tgz", @@ -21485,6 +21783,11 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -22430,17 +22733,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shiki": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", - "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", - "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - } - }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -22486,6 +22778,43 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", @@ -23104,6 +23433,14 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-hash": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", @@ -24232,59 +24569,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typedoc": { - "version": "0.24.8", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", - "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.3.0", - "minimatch": "^9.0.0", - "shiki": "^0.14.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 14.14" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x" - } - }, - "node_modules/typedoc-plugin-markdown": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.16.0.tgz", - "integrity": "sha512-eeiC78fDNGFwemPIHiwRC+mEC7W5jwt3fceUev2gJ2nFnXpVHo8eRrpC9BLWZDee6ehnz/sPmNjizbXwpfaTBw==", - "dependencies": { - "handlebars": "^4.7.7" - }, - "peerDependencies": { - "typedoc": ">=0.24.0" - } - }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -24297,18 +24581,6 @@ "node": ">=4.2.0" } }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -24766,16 +25038,6 @@ "node": ">=0.10.0" } }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==" - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==" - }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -25212,11 +25474,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, "node_modules/workbox-background-sync": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", @@ -25601,19 +25858,6 @@ "node": ">=10" } }, - "node_modules/yarn": { - "version": "1.22.19", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz", - "integrity": "sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ==", - "hasInstallScript": true, - "bin": { - "yarn": "bin/yarn.js", - "yarnpkg": "bin/yarn.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 3d8b4b7941..3c215a27ff 100644 --- a/package.json +++ b/package.json @@ -12,33 +12,15 @@ "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.8.3", "@mui/material": "^5.14.1", - "@mui/private-theming": "^5.14.13", "@mui/system": "^5.14.12", "@mui/x-charts": "^6.0.0-alpha.13", "@mui/x-data-grid": "^6.8.0", "@mui/x-date-pickers": "^6.6.0", "@pdfme/generator": "^1.2.6", - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^11.1.0", - "@testing-library/user-event": "^12.1.10", - "@types/enzyme-adapter-react-16": "^1.0.6", - "@types/jest": "^26.0.24", - "@types/jquery": "^3.5.6", - "@types/node": "^12.20.16", - "@types/react-bootstrap": "^0.32.32", - "@types/react-datepicker": "^4.1.4", - "@types/react-dom": "^17.0.9", - "@types/react-google-recaptcha": "^2.1.5", - "@types/react-modal": "^3.12.1", "bootstrap": "^5.3.0", "customize-cra": "^1.0.0", "dayjs": "^1.10.7", - "detect-newline": "^4.0.0", "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.6", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-jest": "^25.3.4", - "eslint-plugin-prettier": "^3.4.0", "flag-icons": "^6.6.6", "graphql": "^15.5.1", "graphql-tag": "^2.12.6", @@ -46,8 +28,8 @@ "i18next": "^21.8.14", "i18next-browser-languagedetector": "^6.1.4", "i18next-http-backend": "^1.4.1", - "jest-docblock": "^27.4.0", "js-cookie": "^3.0.1", + "lint-staged": "^15.2.0", "markdown-toc": "^1.2.0", "node-sass": "^9.0.0", "prettier": "^2.3.2", @@ -66,11 +48,8 @@ "react-toastify": "^9.0.3", "redux": "^4.1.1", "redux-thunk": "^2.3.0", - "typedoc": "^0.24.8", - "typedoc-plugin-markdown": "^3.16.0", "typescript": "^4.3.5", - "web-vitals": "^1.0.1", - "yarn": "^1.22.17" + "web-vitals": "^1.0.1" }, "scripts": { "serve": "node ./scripts/config-overrides/custom_start.js", @@ -78,13 +57,14 @@ "test": "cross-env NODE_ENV=test node scripts/test.js --env=./scripts/custom-test-env.js --watchAll --coverage", "eject": "react-scripts eject", "lint:check": "eslint \"**/*.{ts,tsx}\" --max-warnings=0", - "lint:fix": "eslint \"**/*.{ts,tsx}\" --fix", - "format:fix": "prettier --write \"**/*.{ts,tsx,json,scss,css}\"", + "lint:fix": "eslint --fix **/*.{ts,tsx}", + "format:fix": "prettier --write **/*.{ts,tsx,json,scss,css}", "format:check": "prettier --check \"**/*.{ts,tsx,json,scss,css}\"", "typecheck": "tsc --project tsconfig.json --noEmit", "prepare": "husky install", "jest-preview": "jest-preview", - "update:toc": "node scripts/githooks/update-toc.js" + "update:toc": "node scripts/githooks/update-toc.js", + "lint-staged": "lint-staged --concurrent false" }, "eslintConfig": { "extends": [ @@ -106,15 +86,21 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@fortawesome/fontawesome-svg-core": "^1.2.35", - "@fortawesome/free-brands-svg-icons": "^5.15.3", - "@fortawesome/react-fontawesome": "^0.1.14", "@types/enzyme": "^3.10.9", "@types/js-cookie": "^3.0.2", "@types/react": "^17.0.14", "@types/react-router-dom": "^5.1.8", "@typescript-eslint/eslint-plugin": "^5.9.0", "@typescript-eslint/parser": "^5.9.0", + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^11.1.0", + "@testing-library/user-event": "^12.1.10", + "@types/jest": "^26.0.24", + "@types/node": "^12.20.16", + "@types/react-bootstrap": "^0.32.32", + "@types/react-datepicker": "^4.1.4", + "@types/react-dom": "^17.0.9", + "@types/react-google-recaptcha": "^2.1.5", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "cross-env": "^7.0.3", "husky": "^8.0.3", @@ -124,8 +110,10 @@ "jest-localstorage-mock": "^2.4.19", "jest-location-mock": "^1.0.9", "jest-preview": "^0.3.1", - "jquery": "^3.2.1", - "postcss-modules": "^6.0.0" + "postcss-modules": "^6.0.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-jest": "^25.3.4", + "eslint-plugin-prettier": "^3.4.0" }, "resolutions": { "@apollo/client": "^3.4.0-beta.19", diff --git a/public/locales/en.json b/public/locales/en.json index 17313741e3..8abb05c409 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -10,6 +10,11 @@ "email": "Email", "password": "Password", "atleast_8_char_long": "Atleast 8 Character long", + "atleast_6_char_long": "Atleast 6 Character long", + "firstName_invalid": "First name should contain only lower and upper case letters", + "lastName_invalid": "Last name should contain only lower and upper case letters", + "password_invalid": "Password should contain atleast one lowercase letter, one uppercase letter, one numeric value and one special character", + "email_invalid": "Email should have atleast 8 characters", "Password_and_Confirm_password_mismatches.": "Password and Confirm password mismatches.", "confirmPassword": "Confirm Password", "forgotPassword": "Forgot Password ?", @@ -25,7 +30,42 @@ "notAuthorised": "Sorry! you are not Authorised!", "notFound": "User not found!", "successfullyRegistered": "Successfully Registered. Please wait until you will be approved.", - "login_to_admin_portal": "Admin Portal Login", + "OR": "OR", + "admin": "ADMIN", + "user": "USER", + "lowercase_check": "Atleast one lowercase letter", + "uppercase_check": "Atleast one uppercase letter", + "numeric_value_check": "Atleaset one numeric value", + "special_char_check": "Atleast one special character" + }, + "userLoginPage": { + "title": "Talawa Admin", + "fromPalisadoes": "An open source application by Palisadoes Foundation volunteers", + "talawa_portal": "Talawa Admin Portal", + "login": "Login", + "register": "Register", + "firstName": "First Name", + "lastName": "Last Name", + "email": "Email", + "password": "Password", + "atleast_8_char_long": "Atleast 8 Character long", + "Password_and_Confirm_password_mismatches.": "Password and Confirm password mismatches.", + "confirmPassword": "Confirm Password", + "forgotPassword": "Forgot Password ?", + "enterEmail": "Enter Email", + "enterPassword": "Enter Password", + "doNotOwnAnAccount": "Do not own an account?", + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "captchaError": "Captcha Error!", + "Please_check_the_captcha": "Please, check the captcha.", + "Something_went_wrong": "Something went wrong, Please try after sometime.", + "passwordMismatches": "Password and Confirm password mismatches.", + "fillCorrectly": "Fill all the Details Correctly.", + "notAuthorised": "Sorry! you are not Authorised!", + "notFound": "User not found!", + "successfullyRegistered": "Successfully Registered. Please wait until you will be approved.", + "userLogin": "User Login", + "afterRegister": "Successfully registered. Please wait for admin to approve your request.", "OR": "OR" }, "latestEvents": { @@ -94,6 +134,8 @@ "displayImage": "Display Image", "enterName": "Enter Name", "sort": "Sort", + "Latest": "Latest", + "Earliest": "Earliest", "filter": "Filter", "cancel": "Cancel", "noOrgErrorTitle": "Organizations Not Found", @@ -147,7 +189,8 @@ "noOrgError": "Organizations not found, please create an organization through dashboard", "roleUpdated": "Role Updated.", "noResultsFoundFor": "No results found for ", - "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too." + "talawaApiUnavailable": "Talawa-API service is unavailable. Is it running? Check your network connectivity too.", + "cancel": "Cancel" }, "requests": { "title": "Talawa Requests", @@ -428,7 +471,8 @@ "deleteMsg": "Do you want to delete this organization?", "cancel": "Cancel", "confirmDelete": "Confirm Delete", - "longDelOrgMsg": "By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data." + "longDelOrgMsg": "By clicking on Delete Organization button the organization will be permanently deleted along with its events, tags and all related data.", + "successfullyDeletedSampleOrganization": "Successfully deleted sample Organization" }, "userUpdate": { "firstName": "First Name", @@ -599,7 +643,12 @@ "home": { "feed": "Feed", "pinnedPosts": "View Pinned Posts", - "somethingOnYourMind": "Something on your mind?" + "somethingOnYourMind": "Something on your mind?", + "addPost": "Add Post", + "startPost": "Start a post", + "media": "Media", + "event": "Event", + "article": "Article" }, "settings": { "profileSettings": "Profile Settings", @@ -607,7 +656,10 @@ "lastName": "Last Name", "emailAddress": "Email Address", "updateImage": "Update Image", - "save": "Save" + "saveChanges": "Save Changes", + "updateProfile": "Update Profile", + "otherSettings": "Other Settings", + "changeLanguage": "Change Language" }, "donate": { "donateTo": "Donate to", diff --git a/public/locales/fr.json b/public/locales/fr.json index ab23401603..7d60cda1fb 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -10,6 +10,11 @@ "email": "E-mail", "password": "Mot de passe", "atleast_8_char_long": "Au moins 8 caractères", + "atleast_6_char_long": "Au moins 6 caractères", + "firstName_invalid": "Le prénom ne doit contenir que des lettres minuscules et majuscules", + "lastName_invalid": "Le nom de famille ne doit contenir que des lettres minuscules et majuscules", + "password_invalid": "Le mot de passe doit contenir au moins une lettre minuscule, une lettre majuscule, une valeur numérique et un caractère spécial", + "email_invalid": "L'e-mail doit contenir au moins 8 caractères", "Password_and_Confirm_password_mismatches.": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", "confirmPassword": "Confirmez le mot de passe", "forgotPassword": "Mot de passe oublié ?", @@ -25,7 +30,42 @@ "notAuthorised": "Désolé ! vous n'êtes pas autorisé !", "notFound": "Utilisateur introuvable !", "successfullyRegistered": "Enregistré avec succès. Veuillez patienter jusqu'à ce que vous soyez approuvé.", - "login_to_admin_portal": "Connexion à l'administration du portail", + "OR": "OU", + "admin": "ADMIN", + "user": "UTILISATEUR", + "lowercase_check": "Au moins une lettre minuscule", + "uppercase_check": "Au moins une lettre majuscule", + "special_char_check": "Au moins un caractère spécial", + "numeric_value_check": "Au moins une valeur numérique" + }, + "userLoginPage": { + "title": "Administrateur Talawa", + "talawa_portal": "Portail D'Administrateur Talawa", + "fromPalisadoes": "Une application open source par les volontaires de la Fondation Palissades", + "login": "Connexion", + "register": "S'inscrire", + "firstName": "Prénom", + "lastName": "Nom de famille", + "email": "E-mail", + "password": "Mot de passe", + "atleast_8_char_long": "Au moins 8 caractères", + "Password_and_Confirm_password_mismatches.": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", + "confirmPassword": "Confirmez le mot de passe", + "forgotPassword": "Mot de passe oublié ?", + "enterEmail": "entrez l'e-mail", + "enterPassword": "Entrer le mot de passe", + "doNotOwnAnAccount": "Vous n'avez pas de compte ?", + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "captchaError": "Erreur de captcha !", + "Please_check_the_captcha": "Veuillez vérifier le captcha.", + "Something_went_wrong": "Quelque chose s'est mal passé, veuillez réessayer plus tard.", + "passwordMismatches": "Le mot de passe et la confirmation du mot de passe ne correspondent pas.", + "fillCorrectly": "Remplissez tous les détails correctement.", + "notAuthorised": "Désolé ! vous n'êtes pas autorisé !", + "notFound": "Utilisateur introuvable !", + "successfullyRegistered": "Enregistré avec succès. Veuillez patienter jusqu'à ce que vous soyez approuvé.", + "userLogin": "Utilisateur en ligne", + "afterRegister": "Enregistré avec succès. Veuillez attendre que l'administrateur approuve votre demande.", "OR": "OU" }, "latestEvents": { @@ -33,6 +73,11 @@ "eventCardSeeAll": "Voir Tout", "noEvents": "Aucun événement à venir" }, + "latestPosts": { + "latestPostsTitle": "Dernières Publications", + "seeAllLink": "Voir Tout", + "noPostsCreated": "Aucune Publication Créée" + }, "listNavbar": { "talawa_portal": "Portail D'Administrateur Talawa", "roles": "Les rôles", @@ -88,6 +133,8 @@ "displayImage": "Afficher l'image", "enterName": "Entrez le nom", "sort": "Trier", + "Earliest": "Le plus tôt", + "Latest": "Dernière", "filter": "Filtre", "cancel": "Annuler", "endOfResults": "Fin des résultats", @@ -137,7 +184,8 @@ "filter": "Filtre", "roleUpdated": "Rôle mis à jour.", "noResultsFoundFor": "Aucun résultat trouvé pour ", - "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau." + "talawaApiUnavailable": "Le service Talawa-API n'est pas disponible. Est-il en cours d'exécution ? Vérifiez également votre connectivité réseau.", + "cancel": "Annuler" }, "requests": { "title": "Demandes Talawa", @@ -420,7 +468,8 @@ "deleteMsg": "Voulez-vous supprimer cette organisation ?", "cancel": "Annuler", "confirmDelete": "Confirmer la suppression", - "longDelOrgMsg": "En cliquant sur le bouton Supprimer l'organisation, l'organisation sera définitivement supprimée ainsi que ses événements, balises et toutes les données associées." + "longDelOrgMsg": "En cliquant sur le bouton Supprimer l'organisation, l'organisation sera définitivement supprimée ainsi que ses événements, balises et toutes les données associées.", + "successfullyDeletedSampleOrganization": "Exemple d'organisation supprimé avec succès" }, "userUpdate": { "firstName": "Prénom", @@ -589,7 +638,12 @@ "home": { "feed": "Alimentation", "pinnedPosts": "Afficher les publications épinglées", - "somethingOnYourMind": "Quelque chose dans votre esprit?" + "somethingOnYourMind": "Quelque chose dans votre esprit?", + "addPost": "Ajouter une publication", + "startPost": "Commencer une publication", + "media": "Médias", + "event": "Événement", + "article": "Article" }, "settings": { "profileSettings": "Paramètres de profil", @@ -597,7 +651,10 @@ "lastName": "Nom de famille", "emailAddress": "Adresse e-mail", "updateImage": "Mettre à jour l'image", - "save": "Sauvegarder" + "saveChanges": "Sauvegarder les modifications", + "updateProfile": "Mettre à jour le profil", + "otherSettings": "Autres paramètres", + "changeLanguage": "Changer la langue" }, "donate": { "donateTo": "Faire un don à", diff --git a/public/locales/hi.json b/public/locales/hi.json index ce53bf4ff8..f23ed585f2 100644 --- a/public/locales/hi.json +++ b/public/locales/hi.json @@ -10,6 +10,11 @@ "email": "ईमेल", "password": "पासवर्ड", "atleast_8_char_long": "कम से कम 8 कैरेक्टर लंबा", + "atleast_6_char_long": "कम से कम 6 अक्षर लंबा", + "firstName_invalid": "प्रथम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", + "lastName_invalid": "अंतिम नाम में केवल छोटे और बड़े अक्षर होने चाहिए", + "password_invalid": "पासवर्ड में कम से कम एक लोअरकेस अक्षर, एक अपरकेस अक्षर, एक संख्यात्मक मान और एक विशेष अक्षर होना चाहिए", + "email_invalid": "ईमेल में कम से कम 8 अक्षर होने चाहिए", "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड बेमेल।", "confirmPassword": "पासवर्ड की पुष्टि कीजिये", "forgotPassword": "पासवर्ड भूल गए ?", @@ -25,7 +30,42 @@ "notAuthorised": "क्षमा करें! आप अधिकृत नहीं हैं!", "notFound": "उपयोगकर्ता नहीं मिला!", "successfullyRegistered": "सफलतापूर्वक पंजीकृत। कृपया स्वीकृत होने तक प्रतीक्षा करें।", - "login_to_admin_portal": "एडमिन पोर्टल लॉगिन", + "OR": "या", + "admin": "व्यवस्थापक", + "user": "उपयोगकर्ता", + "lowercase_check": "कम से कम एक छोटा अक्षर", + "uppercase_check": "कम से कम एक बड़ा अक्षर", + "numeric_value_check": "कम से कम एक संख्यात्मक मान", + "special_char_check": "कम से कम एक विशेष पात्र" + }, + "userLoginPage": { + "title": "तलवा व्यवस्थापक", + "fromPalisadoes": "पलिसाडो के स्वयंसेवकों द्वारा एक खुला स्रोत अनुप्रयोग", + "talawa_portal": "तलावा प्रशासन पोर्टल", + "login": "लॉग इन करें", + "register": "पंजीकरण करवाना", + "firstName": "पहला नाम", + "lastName": "उपनाम", + "email": "ईमेल", + "password": "पासवर्ड", + "atleast_8_char_long": "कम से कम 8 कैरेक्टर लंबा", + "Password_and_Confirm_password_mismatches.": "पासवर्ड और पुष्टि पासवर्ड बेमेल।", + "confirmPassword": "पासवर्ड की पुष्टि कीजिये", + "forgotPassword": "पासवर्ड भूल गए ?", + "enterEmail": "ईमेल दर्ज करें", + "enterPassword": "पास वर्ड दर्ज करें", + "doNotOwnAnAccount": "क्या आपके पास खाता नहीं है?", + "talawaApiUnavailable": "तलावा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रही है? अपनी नेटवर्क कनेक्टिविटी की भी जाँच करें।", + "captchaError": "कैप्चा त्रुटि!", + "Please_check_the_captcha": "कृपया, कैप्चा जांचें।", + "Something_went_wrong": "कुछ गलत हुआ, कृपया कुछ समय बाद प्रयास करें।", + "passwordMismatches": "पासवर्ड और पुष्टि पासवर्ड मेल नहीं खाते।", + "fillCorrectly": "सभी विवरण सही ढंग से भरें।", + "notAuthorised": "क्षमा करें! आप अधिकृत नहीं हैं!", + "notFound": "उपयोगकर्ता नहीं मिला!", + "successfullyRegistered": "सफलतापूर्वक पंजीकृत। कृपया स्वीकृत होने तक प्रतीक्षा करें।", + "afterRegister": "पंजीकरण सफलतापूर्वक हो गया है। कृपया आपके अनुरोध को स्वीकार करने के लिए व्यवस्थापक की प्रतीक्षा करें।", + "userLogin": "उपयोगकर्ता लॉगिन", "OR": "या" }, "latestEvents": { @@ -33,6 +73,11 @@ "eventCardSeeAll": "सभी देखें", "noEvents": "कोई आगामी घटनाएँ नहीं" }, + "latestPosts": { + "latestPostsTitle": "नवीनतम पोस्ट", + "seeAllLink": "सभी देखें", + "noPostsCreated": "कोई पोस्ट नहीं बनाई गई" + }, "listNavbar": { "talawa_portal": "तलावा प्रशासन पोर्टल", "roles": "भूमिकाएँ", @@ -88,6 +133,8 @@ "displayImage": "प्रदर्शन छवि", "enterName": "नाम दर्ज करें", "sort": "छांटें", + "Earliest": "सबसे पुराना", + "Latest": "सबसे नवीनतम", "filter": "फ़िल्टर", "cancel": "रद्द करना", "endOfResults": "परिणामों का अंत", @@ -136,7 +183,8 @@ "filter": "फ़िल्टर", "roleUpdated": "भूमिका अपडेट की गई।", "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", - "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।" + "talawaApiUnavailable": "तलवा-एपीआई सेवा उपलब्ध नहीं है। क्या यह चल रहा है? अपनी नेटवर्क कनेक्टिविटी भी जांचें।", + "cancel": "रद्द करें" }, "requests": { "title": "तलवा अनुरोध", @@ -419,7 +467,8 @@ "deleteMsg": "क्या आप इस संगठन को हटाना चाहते हैं?", "cancel": "रद्द करना", "confirmDelete": "हटाने की पुष्टि करें", - "longDelOrgMsg": "संगठन को हमेशा के लिए हटा देने के लिए संगठन हटाने के बटन पर क्लिक करके, उसके इवेंट्स, टैग्स और सभी संबंधित डेटा सहित सभी जानकारी हटा दी जाएगी।" + "longDelOrgMsg": "संगठन को हमेशा के लिए हटा देने के लिए संगठन हटाने के बटन पर क्लिक करके, उसके इवेंट्स, टैग्स और सभी संबंधित डेटा सहित सभी जानकारी हटा दी जाएगी।", + "successfullyDeletedSampleOrganization": "नमूना संगठन सफलतापूर्वक हटा दिया गया" }, "userUpdate": { "firstName": "पहला नाम", @@ -589,7 +638,12 @@ "home": { "feed": "फ़ीड", "pinnedPosts": "पिन किए गए पोस्ट देखें", - "somethingOnYourMind": "आपके मन में कुछ है?" + "somethingOnYourMind": "आपके मन में कुछ है?", + "addPost": "पोस्ट जोड़ें", + "startPost": "एक पोस्ट शुरू करें", + "media": "मीडिया", + "event": "घटना", + "article": "लेख" }, "settings": { "profileSettings": "पार्श्वचित्र समायोजन", @@ -597,7 +651,10 @@ "lastName": "उपनाम", "emailAddress": "मेल पता", "updateImage": "छवि अद्यतन करें", - "save": "बचाना" + "saveChanges": "परिवर्तनों को सुरक्षित करें", + "updateProfile": "प्रोफ़ाइल अपडेट करें", + "otherSettings": "अन्य सेटिंग्स", + "changeLanguage": "भाषा बदलें" }, "donate": { "donateTo": "दान दें", @@ -673,14 +730,14 @@ "selectContact": "बातचीत शुरू करने के लिए एक संपर्क चुनें", "sendMessage": "मेसेज भेजें" }, - "ऑर्गप्रोफ़ाइलफ़ील्ड": { - "लोड हो रहा है": "लोड हो रहा है...", - "noCustomField": "कोई कस्टम फ़ील्ड उपलब्ध नहीं", - "customFieldName": "फ़ील्ड नाम", - "enterCustomFieldName": "फ़ील्ड नाम दर्ज करें", - "customFieldType": "फ़ील्ड प्रकार", + "orgProfileField": { + "loading": "लोड हो रहा है...", + "noCustomField": "कोई कस्टम फ़ील्ड उपलब्ध नहीं है", + "customFieldName": "फ़ील्ड का नाम", + "enterCustomFieldName": "फ़ील्ड का नाम दर्ज करें", + "customFieldType": "फ़ील्ड का प्रकार", "saveChanges": "परिवर्तन सहेजें", - "कस्टम फ़ील्ड हटाएँ": "कस्टम फ़ील्ड हटाएँ", + "Remove Custom Field": "कस्टम फ़ील्ड हटाएँ", "fieldSuccessMessage": "फ़ील्ड सफलतापूर्वक जोड़ा गया", "fieldRemovalSuccess": "फ़ील्ड सफलतापूर्वक हटा दिया गया" } diff --git a/public/locales/sp.json b/public/locales/sp.json index 26f7288d8a..b36852e85d 100644 --- a/public/locales/sp.json +++ b/public/locales/sp.json @@ -10,6 +10,11 @@ "email": "Correo electrónico", "password": "Clave", "atleast_8_char_long": "Al menos 8 caracteres de largo", + "atleast_6_char_long": "Al menos 6 caracteres de largo", + "firstName_invalid": "El nombre debe contener solo letras minúsculas y mayúsculas.", + "lastName_invalid": "El apellido debe contener solo letras minúsculas y mayúsculas.", + "password_invalid": "La contraseña debe contener al menos una letra minúscula, una letra mayúscula, un valor numérico y un carácter especial.", + "email_invalid": "El correo electrónico debe tener al menos 8 caracteres.", "Password_and_Confirm_password_mismatches.": "Contraseña y Confirmar contraseña no coinciden.", "confirmPassword": "Confirmar contraseña", "forgotPassword": "Has olvidado tu contraseña ?", @@ -25,7 +30,42 @@ "notAuthorised": "¡Lo siento! ¡No estás autorizado!", "notFound": "¡Usuario no encontrado!", "successfullyRegistered": "Registrado con éxito. Espere hasta que sea aprobado", - "login_to_admin_portal": "Inicio de sesión en el portal de administración", + "OR": "O", + "admin": "ADMINISTRACIÓN", + "user": "USUARIO", + "lowercase_check": "Al menos una letra mayuscula", + "uppercase_check": "Al menos una letra minúscula", + "numeric_value_check": "Al menos un valor numérico", + "special_char_check": "Al menos un carácter especial" + }, + "userLoginPage": { + "title": "Administrador Talawa", + "fromPalisadoes": "Una aplicación de código abierto de los voluntarios de la Fundación palisados", + "talawa_portal": "Portal De Administración Talawa", + "login": "Acceso", + "register": "Registro", + "firstName": "Primer nombre", + "lastName": "Apellido", + "email": "Correo electrónico", + "password": "Clave", + "atleast_8_char_long": "Al menos 8 caracteres de largo", + "Password_and_Confirm_password_mismatches.": "Contraseña y Confirmar contraseña no coinciden.", + "confirmPassword": "Confirmar contraseña", + "forgotPassword": "Has olvidado tu contraseña ?", + "enterEmail": "ingrese correo electrónico", + "enterPassword": "introducir la contraseña", + "doNotOwnAnAccount": "¿No tienes una cuenta?", + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Verifica también la conectividad de tu red.", + "captchaError": "¡Error de captcha!", + "Please_check_the_captcha": "Por favor, revisa el captcha.", + "Something_went_wrong": "Algo salió mal. Inténtalo después de un tiempo", + "passwordMismatches": "Contraseña y Confirmar contraseña no coinciden.", + "fillCorrectly": "Complete todos los detalles correctamente.", + "notAuthorised": "¡Lo siento! ¡No estás autorizado!", + "notFound": "¡Usuario no encontrado!", + "successfullyRegistered": "Registrado con éxito. Espere hasta que sea aprobado", + "userLogin": "Inicio de sesión de usuario", + "afterRegister": "Registrado exitosamente. Espere a que el administrador apruebe su solicitud.", "OR": "O" }, "latestEvents": { @@ -33,6 +73,11 @@ "eventCardSeeAll": "Ver Todos", "noEvents": "No Hay Eventos Próximos" }, + "latestPosts": { + "latestPostsTitle": "Últimas Publicaciones", + "seeAllLink": "Ver Todo", + "noPostsCreated": "No se han creado publicaciones" + }, "listNavbar": { "talawa_portal": "Portal De Administración Talawa", "roles": "Roles", @@ -88,6 +133,8 @@ "displayImage": "Mostrar imagen", "enterName": "Ingrese su nombre", "sort": "Ordenar", + "Earliest": "Más Temprano", + "Latest": "El último", "filter": "Filtrar", "cancel": "Cancelar", "endOfResults": "Fin de los resultados", @@ -136,7 +183,8 @@ "filter": "Filtrar", "roleUpdated": "Rol actualizado.", "noResultsFoundFor": "No se encontraron resultados para ", - "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red." + "talawaApiUnavailable": "El servicio Talawa-API no está disponible. ¿Está funcionando? Compruebe también la conectividad de su red.", + "cancel": "Cancelar" }, "requests": { "title": "Solicitudes Talawa", @@ -419,7 +467,8 @@ "deleteMsg": "¿Desea eliminar esta organización?", "cancel": "Cancelar", "confirmDelete": "Confirmar eliminación", - "longDelOrgMsg": "Al hacer clic en el botón Eliminar organización, la organización se eliminará permanentemente junto con sus eventos, etiquetas y todos los datos relacionados." + "longDelOrgMsg": "Al hacer clic en el botón Eliminar organización, la organización se eliminará permanentemente junto con sus eventos, etiquetas y todos los datos relacionados.", + "successfullyDeletedSampleOrganization": "Organización de muestra eliminada correctamente" }, "userUpdate": { "firstName": "Primer nombre", @@ -589,7 +638,12 @@ "home": { "feed": "Alimentar", "pinnedPosts": "Ver publicaciones fijadas", - "somethingOnYourMind": "¿Algo en tu mente?" + "somethingOnYourMind": "¿Algo en tu mente?", + "addPost": "Agregar publicación", + "startPost": "Comenzar una publicación", + "media": "Medios", + "event": "Evento", + "article": "Artículo" }, "settings": { "profileSettings": "Configuración de perfil", @@ -597,7 +651,10 @@ "lastName": "Apellido", "emailAddress": "dirección de correo electrónico", "updateImage": "Actualizar imagen", - "save": "Ahorrar" + "saveChanges": "Guardar cambios", + "updateProfile": "Actualización del perfil", + "otherSettings": "Otras Configuraciones", + "changeLanguage": "Cambiar Idioma" }, "donate": { "donateTo": "Donar a", @@ -673,15 +730,16 @@ "selectContact": "Seleccione un contacto para iniciar una conversación", "sendMessage": "Enviar mensaje" }, - "campoPerfildeOrganización": { - "cargando": "Cargando...", + + "orgProfileField": { + "loading": "Cargando..", "noCustomField": "No hay campos personalizados disponibles", - "customFieldName": "Nombre de campo", - "enterCustomFieldName": "Ingrese el nombre del campo", - "customFieldType": "Tipo de campo", - "saveChanges": "Guardar cambios", - "Eliminar campo personalizado": "Eliminar campo personalizado", - "fieldSuccessMessage": "Campo agregado exitosamente", + "customFieldName": "Nombre del Campo", + "enterCustomFieldName": "Ingrese el Nombre del Campo", + "customFieldType": "Tipo de Campo", + "saveChanges": "Guardar Cambios", + "Remove Custom Field": "Eliminar Campo Personalizado", + "fieldSuccessMessage": "Campo añadido exitosamente", "fieldRemovalSuccess": "Campo eliminado exitosamente" } } diff --git a/public/locales/zh.json b/public/locales/zh.json index d782fd897e..60f0ec3ed2 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -10,6 +10,11 @@ "email": "電子郵件", "password": "密碼", "atleast_8_char_long": "至少 8 個字符長", + "atleast_6_char_long": "至少 6 個字元長", + "firstName_invalid": "名字只能包含小寫和大寫字母", + "lastName_invalid": "姓氏只能包含小寫和大寫字母", + "password_invalid": "密碼應至少包含1個小寫字母、1個大寫字母、1個數字和1個特殊字符", + "email_invalid": "電子郵件應至少包含 8 個字符", "Password_and_Confirm_password_mismatches.": "密碼和確認密碼不匹配。", "confirmPassword": "確認密碼", "forgotPassword": "忘記密碼 ?", @@ -25,7 +30,42 @@ "notAuthorised": "抱歉!你沒有被授權!", "notFound": "找不到用戶!", "successfullyRegistered": "註冊成功,請等待審核通過。", - "login_to_admin_portal": " 管理员门户登录 ", + "OR": "或者", + "admin": "行政", + "user": "用戶", + "lowercase_check": "至少一個小寫字母", + "uppercase_check": "至少有一個大寫字母", + "numeric_value_check": "至少一個數值", + "special_char_check": "至少一個特殊字符" + }, + "userLoginPage": { + "title": "塔拉瓦管理員", + "fromPalisadoes": "柵欄 基金会志愿者的开源应用程序", + "talawa_portal": "塔拉瓦管理門戶", + "login": "登錄", + "register": "登記", + "firstName": "名", + "lastName": "姓", + "email": "電子郵件", + "password": "密碼", + "atleast_8_char_long": "至少 8 個字符長", + "Password_and_Confirm_password_mismatches.": "密碼和確認密碼不匹配。", + "confirmPassword": "確認密碼", + "forgotPassword": "忘記密碼 ?", + "enterEmail": "输入电子邮件", + "enterPassword": "输入密码", + "doNotOwnAnAccount": "沒有帳戶嗎?", + "talawaApiUnavailable": "服務不可用。它正在運行嗎?還要檢查您的網絡連接。", + "captchaError": "驗證碼錯誤!", + "Please_check_the_captcha": "請檢查驗證碼。", + "Something_went_wrong": "出了點問題,請稍後再試。", + "passwordMismatches": "密碼和確認密碼不匹配。", + "fillCorrectly": "正確填寫所有細節。", + "notAuthorised": "抱歉!你沒有被授權!", + "notFound": "找不到用戶!", + "successfullyRegistered": "註冊成功,請等待審核通過。", + "userLogin": "用户登录", + "afterRegister": "註冊成功。 請等待管理員批准您的請求。", "OR": "或者" }, "latestEvents": { @@ -33,6 +73,11 @@ "eventCardSeeAll": "查看全部", "noEvents": "暂无即将举行的活动" }, + "latestPosts": { + "latestPostsTitle": "最新文章", + "seeAllLink": "查看全部", + "noPostsCreated": "暂无文章" + }, "listNavbar": { "talawa_portal": "塔拉瓦管理門戶", "roles": "角色", @@ -88,6 +133,8 @@ "displayImage": "顯示圖像", "enterName": "输入名字", "sort": "排序", + "Earliest": "最早的", + "Latest": "最新的", "filter": "過濾", "cancel": "取消", "endOfResults": "結果結束", @@ -136,7 +183,8 @@ "filter": "過濾", "roleUpdated": "角色已更新。", "noResultsFoundFor": "未找到结果 ", - "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。" + "talawaApiUnavailable": "服務不可用。它在運行嗎?還要檢查您的網絡連接。", + "cancel": "取消" }, "requests": { "title": "塔拉瓦請求", @@ -419,7 +467,8 @@ "deleteMsg": "您是否要删除此组织?", "cancel": "取消", "confirmDelete": "确认删除", - "longDelOrgMsg": "点击删除组织按钮,组织将被永久删除,包括其事件、标签和所有相关数据。" + "longDelOrgMsg": "点击删除组织按钮,组织将被永久删除,包括其事件、标签和所有相关数据。", + "successfullyDeletedSampleOrganization": "已成功刪除樣本組織" }, "userUpdate": { "firstName": "名", @@ -589,7 +638,12 @@ "home": { "feed": "餵養", "pinnedPosts": "查看固定帖子", - "somethingOnYourMind": "你有什麼心事嗎?" + "somethingOnYourMind": "你有什麼心事嗎?", + "addPost": "添加帖子", + "startPost": "开始一篇帖子", + "media": "媒体", + "event": "活动", + "article": "文章" }, "settings": { "profileSettings": "配置文件設置", @@ -597,7 +651,10 @@ "lastName": "姓", "emailAddress": "電子郵件地址", "updateImage": "更新圖片", - "save": "節省" + "saveChanges": "保存更改", + "updateProfile": "更新个人信息", + "otherSettings": "其他设置", + "changeLanguage": "更改语言" }, "donate": { "donateTo": "捐贈給", diff --git a/schema.graphql b/schema.graphql index d200ee7349..0d8c984c9f 100644 --- a/schema.graphql +++ b/schema.graphql @@ -585,6 +585,8 @@ input OrganizationInput { enum OrganizationOrderByInput { apiUrl_ASC apiUrl_DESC + createdAt_ASC + createdAt_DESC description_ASC description_DESC id_ASC diff --git a/scripts/githooks/update-toc.js b/scripts/githooks/update-toc.js new file mode 100644 index 0000000000..268becfd13 --- /dev/null +++ b/scripts/githooks/update-toc.js @@ -0,0 +1,14 @@ +import fs from 'fs'; +import { execSync } from 'child_process'; + +const markdownFiles = fs + .readdirSync('./') + .filter((file) => file.endsWith('.md')); + +markdownFiles.forEach((file) => { + const command = `markdown-toc -i "${file}" --bullets "-"`; + execSync(command, { stdio: 'inherit' }); + +}); + +console.log('Table of contents updated successfully.'); diff --git a/src/GraphQl/Queries/Queries.ts b/src/GraphQl/Queries/Queries.ts index 76db5206c2..95b149b187 100644 --- a/src/GraphQl/Queries/Queries.ts +++ b/src/GraphQl/Queries/Queries.ts @@ -40,13 +40,19 @@ export const ORGANIZATION_LIST = gql` } `; -// Query to take the Organization list with filter option +// Query to take the Organization list with filter and sort option export const ORGANIZATION_CONNECTION_LIST = gql` - query OrganizationsConnection($filter: String, $first: Int, $skip: Int) { + query OrganizationsConnection( + $filter: String + $first: Int + $skip: Int + $orderBy: OrganizationOrderByInput + ) { organizationsConnection( where: { name_contains: $filter } first: $first skip: $skip + orderBy: $orderBy ) { _id image diff --git a/src/assets/svgs/social-icons/Facebook-Logo.svg b/src/assets/svgs/social-icons/Facebook-Logo.svg new file mode 100644 index 0000000000..a70f112dc7 --- /dev/null +++ b/src/assets/svgs/social-icons/Facebook-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/Github-Logo.svg b/src/assets/svgs/social-icons/Github-Logo.svg new file mode 100644 index 0000000000..7679af859c --- /dev/null +++ b/src/assets/svgs/social-icons/Github-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/Instagram-Logo.svg b/src/assets/svgs/social-icons/Instagram-Logo.svg new file mode 100644 index 0000000000..cbf278ae75 --- /dev/null +++ b/src/assets/svgs/social-icons/Instagram-Logo.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/svgs/social-icons/Linkedin-Logo.svg b/src/assets/svgs/social-icons/Linkedin-Logo.svg new file mode 100644 index 0000000000..998dd1b826 --- /dev/null +++ b/src/assets/svgs/social-icons/Linkedin-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/Reddit-Logo.svg b/src/assets/svgs/social-icons/Reddit-Logo.svg new file mode 100644 index 0000000000..8111415030 --- /dev/null +++ b/src/assets/svgs/social-icons/Reddit-Logo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/svgs/social-icons/Slack-Logo.svg b/src/assets/svgs/social-icons/Slack-Logo.svg new file mode 100644 index 0000000000..29a9087d21 --- /dev/null +++ b/src/assets/svgs/social-icons/Slack-Logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/svgs/social-icons/Twitter-Logo.svg b/src/assets/svgs/social-icons/Twitter-Logo.svg new file mode 100644 index 0000000000..efa659339d --- /dev/null +++ b/src/assets/svgs/social-icons/Twitter-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/Youtube-Logo.svg b/src/assets/svgs/social-icons/Youtube-Logo.svg new file mode 100644 index 0000000000..112b9c2d3b --- /dev/null +++ b/src/assets/svgs/social-icons/Youtube-Logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/social-icons/index.tsx b/src/assets/svgs/social-icons/index.tsx new file mode 100644 index 0000000000..d698fc1376 --- /dev/null +++ b/src/assets/svgs/social-icons/index.tsx @@ -0,0 +1,17 @@ +import FacebookLogo from './Facebook-Logo.svg'; +import GithubLogo from './Github-Logo.svg'; +import InstagramLogo from './Instagram-Logo.svg'; +import LinkedInLogo from './Linkedin-Logo.svg'; +import SlackLogo from './Slack-Logo.svg'; +import TwitterLogo from './Twitter-Logo.svg'; +import YoutubeLogo from './Youtube-Logo.svg'; + +export { + FacebookLogo, + GithubLogo, + InstagramLogo, + LinkedInLogo, + SlackLogo, + TwitterLogo, + YoutubeLogo, +}; diff --git a/src/components/DeleteOrg/DeleteOrg.test.tsx b/src/components/DeleteOrg/DeleteOrg.test.tsx index e0a58351f7..f3cb9b492d 100644 --- a/src/components/DeleteOrg/DeleteOrg.test.tsx +++ b/src/components/DeleteOrg/DeleteOrg.test.tsx @@ -1,39 +1,103 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; -import { DELETE_ORGANIZATION_MUTATION } from 'GraphQl/Mutations/mutations'; +import { + DELETE_ORGANIZATION_MUTATION, + REMOVE_SAMPLE_ORGANIZATION_MUTATION, +} from 'GraphQl/Mutations/mutations'; import { act } from 'react-dom/test-utils'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import DeleteOrg from './DeleteOrg'; +import { ToastContainer, toast } from 'react-toastify'; +import { IS_SAMPLE_ORGANIZATION_QUERY } from 'GraphQl/Queries/Queries'; + +async function wait(ms = 1000): Promise { + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, ms)); + }); +} const MOCKS = [ + { + request: { + query: IS_SAMPLE_ORGANIZATION_QUERY, + variables: { + isSampleOrganizationId: '123', + }, + }, + result: { + data: { + isSampleOrganization: true, + }, + }, + }, + { + request: { + query: REMOVE_SAMPLE_ORGANIZATION_MUTATION, + }, + result: { + data: { + removeSampleOrganization: true, + }, + }, + }, { request: { query: DELETE_ORGANIZATION_MUTATION, variables: { - id: 123, + id: '456', }, }, result: { data: { - removeOrganization: [ - { - _id: 123, - }, - ], + removeOrganization: { + _id: '456', + }, }, }, }, ]; +const MOCKS_WITH_ERROR = [ + { + request: { + query: IS_SAMPLE_ORGANIZATION_QUERY, + variables: { + isSampleOrganizationId: '123', + }, + }, + result: { + data: { + isSampleOrganization: true, + }, + }, + }, + { + request: { + query: DELETE_ORGANIZATION_MUTATION, + variables: { + id: '456', + }, + }, + error: new Error('Failed to delete organization'), + }, + { + request: { + query: REMOVE_SAMPLE_ORGANIZATION_MUTATION, + }, + error: new Error('Failed to delete sample organization'), + }, +]; + const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(MOCKS_WITH_ERROR, true); afterEach(() => { localStorage.clear(); @@ -41,29 +105,31 @@ afterEach(() => { describe('Delete Organization Component', () => { test('should be able to Toggle Delete Organization Modal', async () => { - window.location.assign('/orgsetting/id=123'); + window.location.assign('/orgsetting/id=456'); localStorage.setItem('UserType', 'SUPERADMIN'); render( + ); + await wait(); screen.getByTestId(/openDeleteModalBtn/i).click(); expect(screen.getByTestId(/orgDeleteModal/i)).toBeInTheDocument(); screen.getByTestId(/closeDelOrgModalBtn/i).click(); await act(async () => { expect(screen.queryByTestId(/orgDeleteModal/i)).not.toHaveFocus(); }); - expect(window.location).toBeAt('/orgsetting/id=123'); + expect(window.location).toBeAt('/orgsetting/id=456'); }); - test('Delete organization functionality should work properly', async () => { + test('should be able to Toggle Delete Organization Modal When Organization is Sample Organization', async () => { window.location.assign('/orgsetting/id=123'); localStorage.setItem('UserType', 'SUPERADMIN'); render( @@ -71,18 +137,25 @@ describe('Delete Organization Component', () => { + ); + await wait(); screen.getByTestId(/openDeleteModalBtn/i).click(); - screen.getByTestId(/deleteOrganizationBtn/i).click(); - expect(window.location).not.toBeNull(); + expect(screen.getByTestId(/orgDeleteModal/i)).toBeInTheDocument(); + screen.getByTestId(/closeDelOrgModalBtn/i).click(); + await act(async () => { + expect(screen.queryByTestId(/orgDeleteModal/i)).not.toHaveFocus(); + }); + expect(window.location).toBeAt('/orgsetting/id=123'); }); - test('should handle deletion failure gracefully', async () => { - window.location.assign('/orgsetting/id=456'); // Using an ID that triggers a failure + + test('Delete organization functionality should work properly', async () => { + window.location.assign('/orgsetting/id=456'); localStorage.setItem('UserType', 'SUPERADMIN'); render( @@ -95,12 +168,14 @@ describe('Delete Organization Component', () => { ); - - fireEvent.click(screen.getByTestId('openDeleteModalBtn')); - fireEvent.click(screen.getByTestId('deleteOrganizationBtn')); - expect(screen.queryByText(/Deletion failed!/i)).toBeNull(); + await wait(); + screen.getByTestId(/openDeleteModalBtn/i).click(); + screen.getByTestId(/deleteOrganizationBtn/i).click(); + await wait(); + expect(window.location.replace).toHaveBeenCalledWith('/orglist'); }); - test('should close the Delete Organization Modal when "Cancel" button is clicked', async () => { + + test('Delete organization functionality should work properly for sample org', async () => { window.location.assign('/orgsetting/id=123'); localStorage.setItem('UserType', 'SUPERADMIN'); render( @@ -114,19 +189,19 @@ describe('Delete Organization Component', () => { ); - fireEvent.click(screen.getByTestId('openDeleteModalBtn')); - expect(screen.getByTestId('orgDeleteModal')).toBeInTheDocument(); - fireEvent.click(screen.getByTestId('closeDelOrgModalBtn')); - await waitFor(() => { - expect(screen.queryByTestId('orgDeleteModal')).toBeNull(); - }); - expect(window.location).toBeAt('/orgsetting/id=123'); + await wait(); + screen.getByTestId(/openDeleteModalBtn/i).click(); + screen.getByTestId(/deleteOrganizationBtn/i).click(); + await wait(2000); + expect(window.location.replace).toHaveBeenCalledWith('/orglist'); }); - test('should open the Delete Organization Modal when "Delete" button is clicked', async () => { + + test('Error handling for IS_SAMPLE_ORGANIZATION_QUERY mock', async () => { window.location.assign('/orgsetting/id=123'); localStorage.setItem('UserType', 'SUPERADMIN'); + jest.spyOn(toast, 'error'); render( - + @@ -136,15 +211,20 @@ describe('Delete Organization Component', () => { ); - fireEvent.click(screen.getByTestId('openDeleteModalBtn')); - expect(screen.getByTestId('orgDeleteModal')).toBeInTheDocument(); - expect(window.location).toBeAt('/orgsetting/id=123'); + await wait(); + screen.getByTestId(/openDeleteModalBtn/i).click(); + screen.getByTestId(/deleteOrganizationBtn/i).click(); + await wait(); + expect(toast.error).toHaveBeenCalledWith( + 'Failed to delete sample organization' + ); }); - test('render Delete Organization Modal when "Delete" button is clicked', async () => { - window.location.assign('/orgsetting/id=123'); + + test('Error handling for DELETE_ORGANIZATION_MUTATION mock', async () => { + window.location.assign('/orgsetting/id=456'); localStorage.setItem('UserType', 'SUPERADMIN'); render( - + @@ -154,8 +234,9 @@ describe('Delete Organization Component', () => { ); - fireEvent.click(screen.getByTestId('openDeleteModalBtn')); - expect(screen.getByTestId('orgDeleteModal')).toBeInTheDocument(); - expect(window.location).toBeAt('/orgsetting/id=123'); + await wait(); + screen.getByTestId(/openDeleteModalBtn/i).click(); + screen.getByTestId(/deleteOrganizationBtn/i).click(); + await wait(); }); }); diff --git a/src/components/DeleteOrg/DeleteOrg.tsx b/src/components/DeleteOrg/DeleteOrg.tsx index b7ceafbd5c..72fcf5ac03 100644 --- a/src/components/DeleteOrg/DeleteOrg.tsx +++ b/src/components/DeleteOrg/DeleteOrg.tsx @@ -33,12 +33,14 @@ function deleteOrg(): JSX.Element { if (data && data.isSampleOrganization) { removeSampleOrganization() .then(() => { - toast.success('Successfully deleted sample Organization'); + toast.success(t('successfullyDeletedSampleOrganization')); + setTimeout(() => { + window.location.replace('/orglist'); + }, 1000); }) .catch((error) => { toast.error(error.message); }); - window.location.replace('/orglist'); } else { try { await del({ @@ -82,7 +84,7 @@ function deleteOrg(): JSX.Element { onHide={toggleDeleteModal} data-testid="orgDeleteModal" > - +
{t('deleteOrganization')}
{t('deleteMsg')} diff --git a/src/components/EventStats/EventStats.module.css b/src/components/EventStats/EventStats.module.css new file mode 100644 index 0000000000..44ba75a0a8 --- /dev/null +++ b/src/components/EventStats/EventStats.module.css @@ -0,0 +1,35 @@ +.stackEvents { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: 10px 20px; + padding: 10px 20px; + overflow: hidden; + gap: 2px; + column-gap: 2px; +} + +@media screen and (min-width: 801px) { + .stackEvents { + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + padding: 0 2rem; + margin: 0 40px; + gap: 5px; + column-gap: 4px; + } +} + +@media screen and (min-width: 768px) and (max-width: 800px) { + .stackEvents { + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + padding: 0 2rem; + margin: 0 20px; + gap: 5px; + column-gap: 4px; + } +} diff --git a/src/components/EventStats/EventStats.tsx b/src/components/EventStats/EventStats.tsx index 6158c39075..c9f1a70e8d 100644 --- a/src/components/EventStats/EventStats.tsx +++ b/src/components/EventStats/EventStats.tsx @@ -3,8 +3,8 @@ import { Modal } from 'react-bootstrap'; import { FeedbackStats } from './Statistics/Feedback'; import { ReviewStats } from './Statistics/Review'; import { AverageRating } from './Statistics/AverageRating'; -import Stack from '@mui/material/Stack'; import styles from './Loader.module.css'; +import eventStatsStyles from './EventStats.module.css'; import { useQuery } from '@apollo/client'; import { EVENT_FEEDBACKS } from 'GraphQl/Queries/Queries'; @@ -44,14 +44,12 @@ export const EventStats = ({ Event Statistics - - - -
- - -
-
+ + +
+ + +
diff --git a/src/components/LeftDrawer/LeftDrawer.tsx b/src/components/LeftDrawer/LeftDrawer.tsx index 224cfeb2ec..94cbbf0367 100644 --- a/src/components/LeftDrawer/LeftDrawer.tsx +++ b/src/components/LeftDrawer/LeftDrawer.tsx @@ -167,12 +167,12 @@ const leftDrawer = ({ diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.module.css b/src/components/LoginPortalToggle/LoginPortalToggle.module.css new file mode 100644 index 0000000000..5983e20905 --- /dev/null +++ b/src/components/LoginPortalToggle/LoginPortalToggle.module.css @@ -0,0 +1,34 @@ +.navLinkClass { + display: inline-block; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.4; + text-align: center; + vertical-align: middle; + cursor: pointer; + color: var(--bs-gray-900); + border-radius: 0.3rem; + width: 100%; + box-sizing: border-box; + border: 1px solid var(--bs-gray-700); + font-weight: 500; + transition: all 0.25s ease; +} + +.navLinkClass:hover { + color: var(--bs-white); + background-color: var(--bs-gray); + border-color: var(--bs-gray); +} + +.activeLink { + color: var(--bs-white); + border: 1px solid var(--bs-primary); + background-color: var(--bs-primary); +} + +.activeLink:hover { + color: var(--bs-white); + background-color: var(--bs-primary); + border: 1px solid var(--bs-primary); +} diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx b/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx new file mode 100644 index 0000000000..357d6c2ad2 --- /dev/null +++ b/src/components/LoginPortalToggle/LoginPortalToggle.test.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { act, render } from '@testing-library/react'; +import { Provider } from 'react-redux'; +import { BrowserRouter } from 'react-router-dom'; +import { I18nextProvider } from 'react-i18next'; +import LoginPortalToggle from './LoginPortalToggle'; +import { store } from 'state/store'; +import i18nForTest from 'utils/i18nForTest'; + +async function wait(ms = 100): Promise { + await act(() => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }); +} + +describe('Testing LoginPortalToggle component', () => { + test('Component Should be rendered properly', async () => { + render( + + + + + + + + ); + + await wait(); + }); +}); diff --git a/src/components/LoginPortalToggle/LoginPortalToggle.tsx b/src/components/LoginPortalToggle/LoginPortalToggle.tsx new file mode 100644 index 0000000000..9d95a9f453 --- /dev/null +++ b/src/components/LoginPortalToggle/LoginPortalToggle.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import styles from './LoginPortalToggle.module.css'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import { NavLink } from 'react-router-dom'; + +function loginPortalToggle(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + + return ( + + + + {t('admin')} + + + + + {t('user')} + + + + ); +} + +export default loginPortalToggle; diff --git a/src/components/OrgListCard/OrgListCard.module.css b/src/components/OrgListCard/OrgListCard.module.css index 935bada4f4..15628052ce 100644 --- a/src/components/OrgListCard/OrgListCard.module.css +++ b/src/components/OrgListCard/OrgListCard.module.css @@ -21,13 +21,13 @@ border-radius: 4px; } -.orgCard .innerContainer .orgImgContainer img { +.orgCard .innerContainer .orgImgContainer { width: 125px; height: 120px; object-fit: contain; } -.orgCard .innerContainer .orgImgContainer .emptyImg { +.orgCard .innerContainer .orgImgContainer { width: 125px; height: 120px; background-color: var(--bs-gray-200); @@ -89,7 +89,7 @@ .manageBtn { display: flex; justify-content: space-around; - width: 150px; + width: 100px; } .orgName { diff --git a/src/components/OrgListCard/OrgListCard.tsx b/src/components/OrgListCard/OrgListCard.tsx index 403a3cb3f4..30ec8adc5e 100644 --- a/src/components/OrgListCard/OrgListCard.tsx +++ b/src/components/OrgListCard/OrgListCard.tsx @@ -42,18 +42,19 @@ function orgListCard(props: InterfaceOrgListCardProps): JSX.Element {
- {image ? ( - {`${name} - ) : ( -
- )} + word.charAt(0)) + .slice(0, 2) + .join('')}` + } + alt={`${name} image`} + data-testid={image ? '' : 'emptyContainerForImage'} + />
diff --git a/src/components/UserPortal/Login/Login.tsx b/src/components/UserPortal/Login/Login.tsx index 326d416c06..81c98d3e5f 100644 --- a/src/components/UserPortal/Login/Login.tsx +++ b/src/components/UserPortal/Login/Login.tsx @@ -52,10 +52,10 @@ export default function login(props: InterfaceLoginProps): JSX.Element { /* istanbul ignore next */ window.location.assign('/user/organizations'); } else { + /* istanbul ignore next */ toast.warn(t('notAuthorised')); } } catch (error: any) { - /* istanbul ignore next */ errorHandler(t, error); } } @@ -84,7 +84,6 @@ export default function login(props: InterfaceLoginProps): JSX.Element { return ( <>

{t('login')}

-
{t('loginIntoYourAccount')}
{t('emailAddress')}
diff --git a/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx b/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx index 57d478b8d0..841a858839 100644 --- a/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx +++ b/src/components/UserPortal/UserNavbar/UserNavbar.test.tsx @@ -174,4 +174,65 @@ describe('Testing UserNavbar Component [User Portal]', () => { expect(cookies.get('i18next')).toBe('zh'); }); + + test('User can see and interact with the dropdown menu', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('logoutDropdown')); + expect(screen.getByText('Settings')).toBeInTheDocument(); + expect(screen.getByText('My Tasks')).toBeInTheDocument(); + expect(screen.getByTestId('logoutBtn')).toBeInTheDocument(); + }); + + test('User can navigate to the "Settings" page', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('logoutDropdown')); + userEvent.click(screen.getByText('Settings')); + expect(window.location.pathname).toBe('/user/settings'); + }); + + test('User can navigate to the "My Tasks" page', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('logoutDropdown')); + userEvent.click(screen.getByText('My Tasks')); + expect(window.location.pathname).toBe('/user/tasks'); + }); }); diff --git a/src/components/UserPortal/UserNavbar/UserNavbar.tsx b/src/components/UserPortal/UserNavbar/UserNavbar.tsx index e10268e85e..04f4bd50fb 100644 --- a/src/components/UserPortal/UserNavbar/UserNavbar.tsx +++ b/src/components/UserPortal/UserNavbar/UserNavbar.tsx @@ -8,11 +8,13 @@ import cookies from 'js-cookie'; import PermIdentityIcon from '@mui/icons-material/PermIdentity'; import LanguageIcon from '@mui/icons-material/Language'; import { useTranslation } from 'react-i18next'; -import { Link } from 'react-router-dom'; import { useMutation } from '@apollo/client'; import { REVOKE_REFRESH_TOKEN } from 'GraphQl/Mutations/mutations'; +import { useHistory } from 'react-router-dom'; function userNavbar(): JSX.Element { + const history = useHistory(); + const { t } = useTranslation('translation', { keyPrefix: 'userNavbar', }); @@ -95,16 +97,21 @@ function userNavbar(): JSX.Element { {userName} - - - {t('settings')} - + + history.push('/user/settings')} + className={styles.link} + > + {t('settings')} - - - {t('myTasks')} - + + history.push('/user/tasks')} + className={styles.link} + > + {t('myTasks')} + {t('logout')} diff --git a/src/components/UsersTableItem/UserTableItem.test.tsx b/src/components/UsersTableItem/UserTableItem.test.tsx index 4d91fa88df..6767f73229 100644 --- a/src/components/UsersTableItem/UserTableItem.test.tsx +++ b/src/components/UsersTableItem/UserTableItem.test.tsx @@ -8,7 +8,6 @@ import i18nForTest from 'utils/i18nForTest'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import { MOCKS } from './UserTableItemMocks'; import UsersTableItem from './UsersTableItem'; - const link = new StaticMockLink(MOCKS, true); async function wait(ms = 100): Promise { @@ -370,10 +369,11 @@ describe('Testing User Table Item', () => { expect(screen.getByTestId(`changeRoleInOrgdef`)).toHaveValue('USER?def'); // Search for Joined Organization 1 + const searchBtn = screen.getByTestId(`searchBtnJoinedOrgs`); fireEvent.keyUp(inputBox, { - key: 'Enter', target: { value: 'Joined Organization 1' }, }); + fireEvent.click(searchBtn); expect(screen.getByText(/Joined Organization 1/i)).toBeInTheDocument(); expect( screen.queryByText(/Joined Organization 2/i) @@ -390,7 +390,8 @@ describe('Testing User Table Item', () => { // Now clear the search box fireEvent.keyUp(inputBox, { key: 'Enter', target: { value: '' } }); - + fireEvent.keyUp(inputBox, { target: { value: '' } }); + fireEvent.click(searchBtn); // Click on Creator Link fireEvent.click(screen.getByTestId(`creatorabc`)); expect(toast.success).toBeCalledWith('Profile Page Coming Soon !'); @@ -547,10 +548,11 @@ describe('Testing User Table Item', () => { expect(toast.success).toBeCalledWith('Profile Page Coming Soon !'); // Search for Blocked Organization 1 + const searchBtn = screen.getByTestId(`searchBtnOrgsBlockedBy`); fireEvent.keyUp(inputBox, { - key: 'Enter', target: { value: 'Blocked Organization 1' }, }); + fireEvent.click(searchBtn); expect(screen.getByText(/Blocked Organization 1/i)).toBeInTheDocument(); expect( screen.queryByText(/Blocked Organization 2/i) @@ -567,6 +569,8 @@ describe('Testing User Table Item', () => { // Now clear the search box fireEvent.keyUp(inputBox, { key: 'Enter', target: { value: '' } }); + fireEvent.keyUp(inputBox, { target: { value: '' } }); + fireEvent.click(searchBtn); // Click on Organization Link fireEvent.click(screen.getByText(/Blocked Organization 1/i)); diff --git a/src/components/UsersTableItem/UsersTableItem.tsx b/src/components/UsersTableItem/UsersTableItem.tsx index 59b3bef616..842329e44b 100644 --- a/src/components/UsersTableItem/UsersTableItem.tsx +++ b/src/components/UsersTableItem/UsersTableItem.tsx @@ -127,34 +127,53 @@ const UsersTableItem = (props: Props): JSX.Element => { function handleCreator(): void { toast.success('Profile Page Coming Soon !'); } - function handleSearchJoinedOrgs(e: any): void { + const searchJoinedOrgs = (value: string): void => { + setSearchByNameJoinedOrgs(value); + if (value == '') { + setJoinedOrgs(user.joinedOrganizations); + } else { + const filteredOrgs = user.joinedOrganizations.filter((org) => + org.name.toLowerCase().includes(value.toLowerCase()) + ); + setJoinedOrgs(filteredOrgs); + } + }; + const searchOrgsBlockedBy = (value: string): void => { + setSearchByNameOrgsBlockedBy(value); + if (value == '') { + setOrgsBlockedBy(user.organizationsBlockedBy); + } else { + const filteredOrgs = user.organizationsBlockedBy.filter((org) => + org.name.toLowerCase().includes(value.toLowerCase()) + ); + setOrgsBlockedBy(filteredOrgs); + } + }; + const handleSearchJoinedOrgs = (e: any): void => { if (e.key === 'Enter') { const { value } = e.target; - setSearchByNameJoinedOrgs(value); - if (value == '') { - setJoinedOrgs(user.joinedOrganizations); - } else { - const filteredOrgs = user.joinedOrganizations.filter((org) => - org.name.toLowerCase().includes(value.toLowerCase()) - ); - setJoinedOrgs(filteredOrgs); - } + searchJoinedOrgs(value); } - } - function handleSearcgByOrgsBlockedBy(e: any): void { + }; + const handleSearcgByOrgsBlockedBy = (e: any): void => { if (e.key === 'Enter') { const { value } = e.target; - setSearchByNameOrgsBlockedBy(value); - if (value == '') { - setOrgsBlockedBy(user.organizationsBlockedBy); - } else { - const filteredOrgs = user.organizationsBlockedBy.filter((org) => - org.name.toLowerCase().includes(value.toLowerCase()) - ); - setOrgsBlockedBy(filteredOrgs); - } + searchOrgsBlockedBy(value); } - } + }; + const handleSearchButtonClickJoinedOrgs = (): void => { + const inputValue = + (document.getElementById('orgname-joined-orgs') as HTMLInputElement) + ?.value || ''; + searchJoinedOrgs(inputValue); + }; + + const handleSearchButtonClickOrgsBlockedBy = (): void => { + const inputValue = + (document.getElementById('orgname-blocked-by') as HTMLInputElement) + ?.value || ''; + searchOrgsBlockedBy(inputValue); + }; /* istanbul ignore next */ function onHideRemoveUserModal(): void { @@ -223,7 +242,7 @@ const UsersTableItem = (props: Props): JSX.Element => {
{ @@ -396,7 +417,7 @@ const UsersTableItem = (props: Props): JSX.Element => {
{ tabIndex={-1} variant="danger" className={`position-absolute z-10 bottom-0 end-0 h-100 d-flex justify-content-center align-items-center`} + onClick={handleSearchButtonClickOrgsBlockedBy} + data-testid="searchBtnOrgsBlockedBy" > diff --git a/src/screens/BlockUser/BlockUser.test.tsx b/src/screens/BlockUser/BlockUser.test.tsx index 778a5ffa4e..ede51a9777 100644 --- a/src/screens/BlockUser/BlockUser.test.tsx +++ b/src/screens/BlockUser/BlockUser.test.tsx @@ -18,6 +18,7 @@ import { ToastContainer } from 'react-toastify'; import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; + import BlockUser from './BlockUser'; let userQueryCalled = false; @@ -630,4 +631,34 @@ describe('Testing Block/Unblock user screen', () => { ).toBeInTheDocument(); expect(window.location).toBeAt('/blockuser/id=orgid'); }); + + test('Testing Search functionality', async () => { + window.location.assign('/blockuser/id=orgid'); + + render( + + + + + + + + + + + ); + await wait(); + const searchBar = screen.getByTestId(/searchByName/i); + const searchBtn = screen.getByTestId(/searchBtn/i); + expect(searchBar).toBeInTheDocument(); + userEvent.type(searchBar, 'Dummy{enter}'); + await wait(); + userEvent.clear(searchBar); + userEvent.type(searchBar, 'Dummy'); + userEvent.click(searchBtn); + await wait(); + userEvent.clear(searchBar); + userEvent.type(searchBar, ''); + userEvent.click(searchBtn); + }); }); diff --git a/src/screens/BlockUser/BlockUser.tsx b/src/screens/BlockUser/BlockUser.tsx index 644044feb4..4bccd808a8 100644 --- a/src/screens/BlockUser/BlockUser.tsx +++ b/src/screens/BlockUser/BlockUser.tsx @@ -117,18 +117,29 @@ const Requests = (): JSX.Element => { toast.error(memberError.message); } - const handleSearch = (e: any): void => { + const handleSearch = (value: string): void => { + setSearchByName(value); + memberRefetch({ + orgId: currentUrl, + firstName_contains: searchByFirstName ? value : '', + lastName_contains: searchByFirstName ? '' : value, + }); + }; + + const handleSearchByEnter = (e: any): void => { if (e.key === 'Enter') { const { value } = e.target; - setSearchByName(value); - memberRefetch({ - orgId: currentUrl, - firstName_contains: searchByFirstName ? value : '', - lastName_contains: searchByFirstName ? '' : value, - }); + handleSearch(value); } }; + const handleSearchByBtnClick = (): void => { + const inputValue = + (document.getElementById('searchBlockedUsers') as HTMLInputElement) + ?.value || ''; + handleSearch(inputValue); + }; + const headerTitles: string[] = [ '#', t('name'), @@ -145,6 +156,7 @@ const Requests = (): JSX.Element => {
{ data-testid="searchByName" autoComplete="off" required - onKeyUp={handleSearch} + onKeyUp={handleSearchByEnter} /> diff --git a/src/screens/LoginPage/LoginPage.module.css b/src/screens/LoginPage/LoginPage.module.css index 8e8e314ba9..d5b9b755c7 100644 --- a/src/screens/LoginPage/LoginPage.module.css +++ b/src/screens/LoginPage/LoginPage.module.css @@ -34,14 +34,20 @@ margin: 0; position: absolute; top: 1rem; - left: 2rem; + left: 1rem; +} + +.langChangeBtnStyle { + width: 7.5rem; + height: 2.2rem; + padding: 0; } .row .right_portion .talawa_logo { - height: 150px; - width: 150px; + height: 5rem; + width: 5rem; display: block; - margin: 1rem auto; + margin: 1.5rem auto 1rem; -webkit-animation: zoomIn 0.3s ease-in-out; animation: zoomIn 0.3s ease-in-out; } @@ -49,10 +55,10 @@ .row .orText { display: block; position: absolute; - top: calc(-0.7rem - 0.5rem); + top: 0; left: calc(50% - 2.6rem); margin: 0 auto; - padding: 0.5rem 2rem; + padding: 0.35rem 2rem; z-index: 100; background: var(--bs-white); color: var(--bs-secondary); @@ -102,6 +108,10 @@ margin-bottom: 0; padding: 1rem; } + + .socialIcons { + margin-bottom: 1rem; + } } @media (max-width: 577px) { @@ -124,6 +134,10 @@ height: 120px; margin: 0 auto 2rem auto; } + + .socialIcons { + margin-bottom: 1rem; + } } .active_tab { @@ -186,3 +200,28 @@ transform: translateY(0); } } + +.socialIcons { + display: flex; + gap: 16px; + justify-content: center; +} + +.password_checks { + display: flex; + justify-content: space-between; + align-items: flex-start; + flex-direction: column; +} + +.password_check_element { + margin-top: -10px; +} + +.password_check_element_top { + margin-top: 18px; +} + +.password_check_element_bottom { + margin-bottom: -20px; +} diff --git a/src/screens/LoginPage/LoginPage.test.tsx b/src/screens/LoginPage/LoginPage.test.tsx index c92ba07e43..1b99cccf01 100644 --- a/src/screens/LoginPage/LoginPage.test.tsx +++ b/src/screens/LoginPage/LoginPage.test.tsx @@ -166,7 +166,7 @@ describe('Testing Login Page Screen', () => { await wait(); - expect(screen.getByText(/Admin Portal/i)).toBeInTheDocument(); + expect(screen.getByText(/Admin/i)).toBeInTheDocument(); expect(window.location).toBeAt('/orglist'); }); @@ -175,8 +175,8 @@ describe('Testing Login Page Screen', () => { firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', - password: 'johndoe', - confirmPassword: 'johndoe', + password: 'John@123', + confirmPassword: 'John@123', }; render( @@ -215,13 +215,57 @@ describe('Testing Login Page Screen', () => { userEvent.click(screen.getByTestId('registrationBtn')); }); + test('Testing registration functionality when all inputs are invalid', async () => { + const formData = { + firstName: '1234', + lastName: '8890', + email: 'j@l.co', + password: 'john@123', + confirmPassword: 'john@123', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + userEvent.click(screen.getByTestId('registrationBtn')); + }); + test('Testing registration functionality, when password and confirm password is not same', async () => { const formData = { firstName: 'John', lastName: 'Doe', email: 'johndoe@gmail.com', - password: 'johndoe', - confirmPassword: 'doeJohn', + password: 'johnDoe@1', + confirmPassword: 'doeJohn@2', }; render( @@ -301,6 +345,54 @@ describe('Testing Login Page Screen', () => { userEvent.click(screen.getByTestId('registrationBtn')); }); + test('switches to login tab on successful registration', async () => { + const formData = { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johndoe', + confirmPassword: 'johndoe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + + await wait(); + + // Check if the login tab is now active by checking for elements that only appear in the login tab + expect(screen.getByTestId('loginBtn')).toBeInTheDocument(); + expect(screen.getByTestId('goToRegisterPortion')).toBeInTheDocument(); + }); + test('Testing toggle login register portion', async () => { render( diff --git a/src/screens/LoginPage/LoginPage.tsx b/src/screens/LoginPage/LoginPage.tsx index b81b9c809c..64bbd7b36a 100644 --- a/src/screens/LoginPage/LoginPage.tsx +++ b/src/screens/LoginPage/LoginPage.tsx @@ -7,8 +7,19 @@ import Col from 'react-bootstrap/Col'; import Row from 'react-bootstrap/Row'; import ReCAPTCHA from 'react-google-recaptcha'; import { useTranslation } from 'react-i18next'; -import { Link } from 'react-router-dom'; +import { Link, useHistory } from 'react-router-dom'; import { toast } from 'react-toastify'; +import { Check, Clear } from '@mui/icons-material'; + +import { + FacebookLogo, + LinkedInLogo, + GithubLogo, + InstagramLogo, + SlackLogo, + TwitterLogo, + YoutubeLogo, +} from 'assets/svgs/social-icons'; import { REACT_APP_USE_RECAPTCHA, RECAPTCHA_SITE_KEY } from 'Constant/constant'; import { @@ -19,6 +30,7 @@ import { import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; import { ReactComponent as PalisadoesLogo } from 'assets/svgs/palisadoes.svg'; import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; +import LoginPortalToggle from 'components/LoginPortalToggle/LoginPortalToggle'; import Loader from 'components/Loader/Loader'; import { errorHandler } from 'utils/errorHandler'; import styles from './LoginPage.module.css'; @@ -26,9 +38,16 @@ import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; function loginPage(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + const history = useHistory(); document.title = t('title'); + type PasswordValidation = { + lowercaseChar: boolean; + uppercaseChar: boolean; + numericValue: boolean; + specialChar: boolean; + }; const [showTab, setShowTab] = useState<'LOGIN' | 'REGISTER'>('LOGIN'); const [componentLoader, setComponentLoader] = useState(true); const [isInputFocused, setIsInputFocused] = useState(false); @@ -46,12 +65,51 @@ function loginPage(): JSX.Element { const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setShowConfirmPassword] = useState(false); + const [showAlert, setShowAlert] = useState({ + lowercaseChar: true, + uppercaseChar: true, + numericValue: true, + specialChar: true, + }); + + const passwordValidationRegExp = { + lowercaseCharRegExp: new RegExp('[a-z]'), + uppercaseCharRegExp: new RegExp('[A-Z]'), + numericalValueRegExp: new RegExp('\\d'), + specialCharRegExp: new RegExp('[!@#$%^&*()_+{}\\[\\]:;<>,.?~\\\\/-]'), + }; + const handleLowercasePassCheck = (pass: string): void => { + setShowAlert((prevAlert) => ({ + ...prevAlert, + lowercaseChar: !passwordValidationRegExp.lowercaseCharRegExp.test(pass), + })); + }; + + const handleUppercasePassCheck = (pass: string): void => { + setShowAlert((prevAlert) => ({ + ...prevAlert, + uppercaseChar: !passwordValidationRegExp.uppercaseCharRegExp.test(pass), + })); + }; + const handleNumericalValuePassCheck = (pass: string): void => { + setShowAlert((prevAlert) => ({ + ...prevAlert, + numericValue: !passwordValidationRegExp.numericalValueRegExp.test(pass), + })); + }; + const handleSpecialCharPassCheck = (pass: string): void => { + setShowAlert((prevAlert) => ({ + ...prevAlert, + specialChar: !passwordValidationRegExp.specialCharRegExp.test(pass), + })); + }; + const recaptchaRef = useRef(null); useEffect(() => { const isLoggedIn = localStorage.getItem('IsLoggedIn'); if (isLoggedIn == 'TRUE') { - window.location.assign('/orglist'); + history.push('/orglist'); } setComponentLoader(false); }, []); @@ -118,12 +176,28 @@ function loginPage(): JSX.Element { toast.error(t('Please_check_the_captcha')); return; } + const isValidatedString = (value: string): boolean => + /^[a-zA-Z]+$/.test(value); + + const validatePassword = (password: string): boolean => { + const lengthCheck = new RegExp('^.{6,}$'); + return ( + lengthCheck.test(password) && + passwordValidationRegExp.lowercaseCharRegExp.test(password) && + passwordValidationRegExp.uppercaseCharRegExp.test(password) && + passwordValidationRegExp.numericalValueRegExp.test(password) && + passwordValidationRegExp.specialCharRegExp.test(password) + ); + }; if ( + isValidatedString(signfirstName) && + isValidatedString(signlastName) && signfirstName.length > 1 && signlastName.length > 1 && signEmail.length >= 8 && - signPassword.length > 1 + signPassword.length > 1 && + validatePassword(signPassword) ) { if (cPassword == signPassword) { try { @@ -158,7 +232,18 @@ function loginPage(): JSX.Element { toast.warn(t('passwordMismatches')); } } else { - toast.warn(t('fillCorrectly')); + if (!isValidatedString(signfirstName)) { + toast.warn(t('firstName_invalid')); + } + if (!isValidatedString(signlastName)) { + toast.warn(t('lastName_invalid')); + } + if (!validatePassword(signPassword)) { + toast.warn(t('password_invalid')); + } + if (signEmail.length < 8) { + toast.warn(t('email_invalid')); + } } }; @@ -196,7 +281,7 @@ function loginPage(): JSX.Element { localStorage.setItem('IsLoggedIn', 'TRUE'); localStorage.setItem('UserType', loginData.login.user.userType); if (localStorage.getItem('IsLoggedIn') == 'TRUE') { - window.location.replace('/orglist'); + history.push('/orglist'); } } else { toast.warn(t('notAuthorised')); @@ -220,34 +305,95 @@ function loginPage(): JSX.Element {
- -

{t('fromPalisadoes')}

+ + +

{t('fromPalisadoes')}

+
+
+ +
+ + + {/* LOGIN FORM */}
-
-

- {t('login_to_admin_portal')} -

- {t('email')} + +

{t('login')}

+ {t('email')}
- {t('password')} + {t('password')}
-
+
{t('login')} -
+

{t('OR')}
+
+ {t('email')} +
+ { + setSignFormState({ + ...signformState, + signEmail: e.target.value.toLowerCase(), + }); + }} + /> + +
-
- {t('password')} +
+ {t('password')}
- {isInputFocused && - signformState.signPassword.length < 8 && ( -
+ {isInputFocused ? ( + signformState.signPassword.length < 6 ? ( +
+

+ + + + {t('atleast_6_char_long')} +

+
+ ) : ( +

+ + + + {t('atleast_6_char_long')} +

+ ) + ) : null} + + {!isInputFocused && + signformState.signPassword.length > 0 && + signformState.signPassword.length < 6 && ( +
+ + + + {t('atleast_6_char_long')} +
+ )} + {isInputFocused && ( +

- {t('atleast_8_char_long')} -

+ {showAlert.lowercaseChar ? ( + + + + ) : ( + + + + )} + {t('lowercase_check')} +

)} - {!isInputFocused && - signformState.signPassword.length > 0 && - signformState.signPassword.length < 8 && ( -
- {t('atleast_8_char_long')} -
+ {showAlert.uppercaseChar ? ( + + + + ) : ( + + + + )} + {t('uppercase_check')} +

+ )} + {isInputFocused && ( +

+ {showAlert.numericValue ? ( + + + + ) : ( + + + + )} + {t('numeric_value_check')} +

)} + {isInputFocused && ( +

+ {showAlert.specialChar ? ( + + + + ) : ( + + + + )} + {t('special_char_check')} +

+ )} +
-
+
{t('confirmPassword')}
@@ -541,7 +801,7 @@ function loginPage(): JSX.Element { -
-
- {state == 1 ? (
-

{t('title')}

+

+ {t('title')} +

-
@@ -465,10 +507,13 @@ function orgList(): JSX.Element { required value={formState.name} onChange={(e): void => { - setFormState({ - ...formState, - name: e.target.value, - }); + const inputText = e.target.value; + if (inputText.length < 50) { + setFormState({ + ...formState, + name: e.target.value, + }); + } }} /> {t('description')} @@ -481,10 +526,13 @@ function orgList(): JSX.Element { required value={formState.descrip} onChange={(e): void => { - setFormState({ - ...formState, - descrip: e.target.value, - }); + const descriptionText = e.target.value; + if (descriptionText.length < 200) { + setFormState({ + ...formState, + descrip: e.target.value, + }); + } }} /> {t('location')} @@ -497,10 +545,13 @@ function orgList(): JSX.Element { required value={formState.location} onChange={(e): void => { - setFormState({ - ...formState, - location: e.target.value, - }); + const locationText = e.target.value; + if (locationText.length < 100) { + setFormState({ + ...formState, + location: e.target.value, + }); + } }} /> @@ -611,8 +662,8 @@ function orgList(): JSX.Element { @@ -624,7 +675,7 @@ function orgList(): JSX.Element {
{t('goToStore')} @@ -635,7 +686,7 @@ function orgList(): JSX.Element { className={styles.greenregbtn} onClick={closeDialogModal} value="invite" - data-testid="submitOrganizationForm" + data-testid="enableEverythingForm" > {t('enableEverything')} diff --git a/src/screens/OrgList/OrgListMocks.ts b/src/screens/OrgList/OrgListMocks.ts index 1a1ab30ab7..833535f4aa 100644 --- a/src/screens/OrgList/OrgListMocks.ts +++ b/src/screens/OrgList/OrgListMocks.ts @@ -1,3 +1,7 @@ +import { + CREATE_ORGANIZATION_MUTATION, + CREATE_SAMPLE_ORGANIZATION_MUTATION, +} from 'GraphQl/Mutations/mutations'; import { ORGANIZATION_CONNECTION_LIST, USER_ORGANIZATION_LIST, @@ -84,6 +88,7 @@ const MOCKS = [ first: 8, skip: 0, filter: '', + orderBy: 'createdAt_ASC', }, notifyOnNetworkStatusChange: true, }, @@ -102,6 +107,39 @@ const MOCKS = [ data: superAdminUser, }, }, + { + request: { + query: CREATE_SAMPLE_ORGANIZATION_MUTATION, + }, + result: { + data: { + createSampleOrganization: { + id: '1', + name: 'Sample Organization', + }, + }, + }, + }, + { + request: { + query: CREATE_ORGANIZATION_MUTATION, + variables: { + description: 'This is a dummy organization', + location: 'Delhi, India', + name: 'Dummy Organization', + visibleInSearch: true, + isPublic: false, + image: '', + }, + }, + result: { + data: { + createOrganization: { + _id: '1', + }, + }, + }, + }, ]; const MOCKS_EMPTY = [ { @@ -111,6 +149,7 @@ const MOCKS_EMPTY = [ first: 8, skip: 0, filter: '', + orderBy: 'createdAt_ASC', }, notifyOnNetworkStatusChange: true, }, @@ -130,6 +169,40 @@ const MOCKS_EMPTY = [ }, }, ]; +const MOCKS_WITH_ERROR = [ + { + request: { + query: ORGANIZATION_CONNECTION_LIST, + variables: { + first: 8, + skip: 0, + filter: '', + orderBy: 'createdAt_ASC', + }, + notifyOnNetworkStatusChange: true, + }, + result: { + data: { + organizationsConnection: organizations, + }, + }, + }, + { + request: { + query: USER_ORGANIZATION_LIST, + variables: { id: '123' }, + }, + result: { + data: superAdminUser, + }, + }, + { + request: { + query: CREATE_SAMPLE_ORGANIZATION_MUTATION, + }, + error: new Error('Failed to create sample organization'), + }, +]; // MOCKS FOR ADMIN const MOCKS_ADMIN = [ @@ -140,6 +213,7 @@ const MOCKS_ADMIN = [ first: 8, skip: 0, filter: '', + orderBy: 'createdAt_ASC', }, notifyOnNetworkStatusChange: true, }, @@ -160,4 +234,4 @@ const MOCKS_ADMIN = [ }, ]; -export { MOCKS, MOCKS_ADMIN, MOCKS_EMPTY }; +export { MOCKS, MOCKS_ADMIN, MOCKS_EMPTY, MOCKS_WITH_ERROR }; diff --git a/src/screens/OrgPost/OrgPost.test.tsx b/src/screens/OrgPost/OrgPost.test.tsx index 5c8672e122..fecaa77169 100644 --- a/src/screens/OrgPost/OrgPost.test.tsx +++ b/src/screens/OrgPost/OrgPost.test.tsx @@ -245,7 +245,9 @@ describe('Organisation Post Page', () => { }); } await debounceWait(); + const searchBtn = screen.getByTestId('searchBtn'); userEvent.type(screen.getByPlaceholderText(/Search By/i), 'postone{enter}'); + userEvent.click(searchBtn); await debounceWait(); const sortDropdown = screen.getByTestId('sort'); userEvent.click(sortDropdown); diff --git a/src/screens/OrgPost/OrgPost.tsx b/src/screens/OrgPost/OrgPost.tsx index 3408f3f96c..f4dc98eee8 100644 --- a/src/screens/OrgPost/OrgPost.tsx +++ b/src/screens/OrgPost/OrgPost.tsx @@ -138,19 +138,28 @@ function orgPost(): JSX.Element { if (orgPostListError) { window.location.assign('/orglist'); } + const handleSearch = (value: string): void => { + const filterData = { + id: currentUrl, + title_contains: showTitle ? value : undefined, + text_contains: !showTitle ? value : undefined, + }; + refetch(filterData); + }; - const handleSearch = (e: any): void => { + const handleSearchByEnter = (e: any): void => { if (e.key === 'Enter') { const { value } = e.target; - const filterData = { - id: currentUrl, - title_contains: showTitle ? value : null, - text_contains: !showTitle ? value : null, - }; - refetch(filterData); + handleSearch(value); } }; + const handleSearchByBtnClick = (): void => { + const inputValue = + (document.getElementById('searchPosts') as HTMLInputElement)?.value || ''; + handleSearch(inputValue); + }; + const handleSorting = (option: string): void => { setSortingOption(option); }; @@ -196,17 +205,19 @@ function orgPost(): JSX.Element {
@@ -253,12 +264,9 @@ function orgPost(): JSX.Element { title="Sort Post" data-testid="sort" > - + - {t('sortPost')} + {sortingOption === 'latest' ? t('Latest') : t('Oldest')} { await wait(); const searchInput = screen.getByTestId('searchByName'); + const searchBtn = screen.getByTestId('searchBtn'); + userEvent.type(searchInput, ''); + userEvent.click(searchBtn); + await wait(); + userEvent.clear(searchInput); + userEvent.type(searchInput, 'l{enter}'); + await wait(); + await screen.findByTestId('searchAndNotFound'); + userEvent.clear(searchInput); + userEvent.type(searchInput, 'l'); + userEvent.click(searchBtn); + await wait(); await screen.findByTestId('searchAndNotFound'); }); diff --git a/src/screens/Requests/Requests.tsx b/src/screens/Requests/Requests.tsx index c991d5d05e..d5c52ef2a4 100644 --- a/src/screens/Requests/Requests.tsx +++ b/src/screens/Requests/Requests.tsx @@ -238,23 +238,34 @@ const Requests = (): JSX.Element => { } }; - /* istanbul ignore next */ - const handleSearchByName = async (e: any): Promise => { + const handleSearch = async (value: string): Promise => { + setSearchByName(value); + if (value === '') { + resetAndRefetch(); + return; + } + await refetchUsers({ + firstName_contains: value, + lastName_contains: '', + // Later on we can add several search and filter options + }); + }; + + const handleSearchByEnter = (e: any): void => { if (e.key === 'Enter') { const { value } = e.target; - setSearchByName(value); - if (value === '') { - resetAndRefetch(); - return; - } - await refetchUsers({ - firstName_contains: value, - lastName_contains: '', - // Later on we can add several search and filter options - }); + handleSearch(value); } }; + const handleSearchByBtnClick = (): void => { + const inputElement = document.getElementById( + 'searchRequests' + ) as HTMLInputElement; + const inputValue = inputElement?.value || ''; + handleSearch(inputValue); + }; + const headerTitles: string[] = [ '#', t('name'), @@ -307,16 +318,19 @@ const Requests = (): JSX.Element => { > diff --git a/src/screens/UserPortal/Chat/Chat.test.tsx b/src/screens/UserPortal/Chat/Chat.test.tsx index 6476e9ee40..a2f709d8a4 100644 --- a/src/screens/UserPortal/Chat/Chat.test.tsx +++ b/src/screens/UserPortal/Chat/Chat.test.tsx @@ -148,7 +148,7 @@ describe('Testing People Screen [User Portal]', () => { expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); }); - test('Search functionality works as expected', async () => { + test('Search functionality works as expected by pressing enter key', async () => { render( @@ -163,7 +163,31 @@ describe('Testing People Screen [User Portal]', () => { await wait(); + userEvent.type(screen.getByTestId('searchInput'), 'j{enter}'); + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('John Cena')).toBeInTheDocument(); + expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + }); + + test('Search functionality works as expected by clicking search Btn', async () => { + render( + + + + + + + + + + ); + + await wait(); + const searchBtn = screen.getByTestId('searchBtn'); userEvent.type(screen.getByTestId('searchInput'), 'j'); + userEvent.click(searchBtn); await wait(); expect(getOrganizationIdSpy).toHaveBeenCalled(); diff --git a/src/screens/UserPortal/Chat/Chat.tsx b/src/screens/UserPortal/Chat/Chat.tsx index 1ae9d5764d..aef6b24026 100644 --- a/src/screens/UserPortal/Chat/Chat.tsx +++ b/src/screens/UserPortal/Chat/Chat.tsx @@ -57,17 +57,23 @@ export default function chat(): JSX.Element { }, }); - const handleSearch = ( - event: React.ChangeEvent - ): void => { - const newFilter = event.target.value; - setFilterName(newFilter); + const handleSearch = (value: string): void => { + setFilterName(value); - const filter = { - firstName_contains: newFilter, - }; - - contactRefetch(filter); + contactRefetch({ + firstName_contains: value, + }); + }; + const handleSearchByEnter = (e: any): void => { + if (e.key === 'Enter') { + const { value } = e.target; + handleSearch(value); + } + }; + const handleSearchByBtnClick = (): void => { + const value = + (document.getElementById('searchChats') as HTMLInputElement)?.value || ''; + handleSearch(value); }; React.useEffect(() => { @@ -92,14 +98,17 @@ export default function chat(): JSX.Element { diff --git a/src/screens/UserPortal/Events/Events.test.tsx b/src/screens/UserPortal/Events/Events.test.tsx index 4243efa8ee..52e658a641 100644 --- a/src/screens/UserPortal/Events/Events.test.tsx +++ b/src/screens/UserPortal/Events/Events.test.tsx @@ -288,7 +288,7 @@ describe('Testing Events Screen [User Portal]', () => { expect(screen.queryByText(mockEventTitle)).toBeInTheDocument(); }); - test('Search works as expected when user types in search input', async () => { + test('Search works as expected when user types in search input and press enter key', async () => { const getOrganizationIdSpy = jest .spyOn(getOrganizationId, 'default') .mockImplementation(() => { @@ -311,7 +311,7 @@ describe('Testing Events Screen [User Portal]', () => { expect(getOrganizationIdSpy).toHaveBeenCalled(); - const randomSearchInput = 'test'; + const randomSearchInput = 'test{enter}'; userEvent.type(screen.getByTestId('searchInput'), randomSearchInput); await wait(); @@ -332,6 +332,55 @@ describe('Testing Events Screen [User Portal]', () => { expect(screen.queryByText(mockEventTitleAbsent)).not.toBeInTheDocument(); }); + test('Search works as expected when user types in search input and clicks search Btn', async () => { + const getOrganizationIdSpy = jest + .spyOn(getOrganizationId, 'default') + .mockImplementation(() => { + return ''; + }); + + render( + + + + + + + + + + ); + + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + const searchInput = screen.getByTestId('searchInput'); + const searchBtn = screen.getByTestId('searchBtn'); + userEvent.type(searchInput, ''); + userEvent.click(searchBtn); + await wait(); + userEvent.clear(searchInput); + userEvent.type(searchInput, 'test'); + userEvent.click(searchBtn); + + await wait(); + + let mockEventTitle = ''; + if (MOCKS[0].result?.data.eventsByOrganizationConnection) { + mockEventTitle = + MOCKS[0].result?.data.eventsByOrganizationConnection[0].title; + } + + let mockEventTitleAbsent = ''; + if (MOCKS[0].result?.data.eventsByOrganizationConnection) { + mockEventTitleAbsent = + MOCKS[0].result?.data.eventsByOrganizationConnection[1].title; + } + + expect(screen.queryByText(mockEventTitle)).toBeInTheDocument(); + expect(screen.queryByText(mockEventTitleAbsent)).not.toBeInTheDocument(); + }); + test('Create event works as expected when event is not an all day event.', async () => { const getOrganizationIdSpy = jest .spyOn(getOrganizationId, 'default') @@ -469,5 +518,6 @@ describe('Testing Events Screen [User Portal]', () => { const calenderView = 'Calendar View'; expect(screen.queryAllByText(calenderView)).not.toBeNull(); + expect(screen.getByText('Sun')).toBeInTheDocument(); }); }); diff --git a/src/screens/UserPortal/Events/Events.tsx b/src/screens/UserPortal/Events/Events.tsx index caf1d72fd2..13bf916b6c 100644 --- a/src/screens/UserPortal/Events/Events.tsx +++ b/src/screens/UserPortal/Events/Events.tsx @@ -5,7 +5,10 @@ import EventCard from 'components/UserPortal/EventCard/EventCard'; import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; import { Button, Dropdown, Form, InputGroup } from 'react-bootstrap'; import PaginationList from 'components/PaginationList/PaginationList'; -import { ORGANIZATION_EVENTS_CONNECTION } from 'GraphQl/Queries/Queries'; +import { + ORGANIZATION_EVENTS_CONNECTION, + ORGANIZATIONS_LIST, +} from 'GraphQl/Queries/Queries'; import { useMutation, useQuery } from '@apollo/client'; import { SearchOutlined } from '@mui/icons-material'; import styles from './Events.module.css'; @@ -18,6 +21,7 @@ import { CREATE_EVENT_MUTATION } from 'GraphQl/Mutations/mutations'; import dayjs from 'dayjs'; import { toast } from 'react-toastify'; import { errorHandler } from 'utils/errorHandler'; +import EventCalendar from 'components/EventCalendar/EventCalendar'; interface InterfaceEventCardProps { id: string; @@ -50,7 +54,6 @@ export default function events(): JSX.Element { const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(5); const [events, setEvents] = React.useState([]); - const [filterName, setFilterName] = React.useState(''); const [mode, setMode] = React.useState(0); const [showCreateEventModal, setShowCreateEventModal] = React.useState(false); const [eventTitle, setEventTitle] = React.useState(''); @@ -76,8 +79,15 @@ export default function events(): JSX.Element { }, }); + const { data: orgData } = useQuery(ORGANIZATIONS_LIST, { + variables: { id: organizationId }, + }); + const [create] = useMutation(CREATE_EVENT_MUTATION); + const userId = localStorage.getItem('id') as string; + const userRole = localStorage.getItem('UserType') as string; + const createEvent = async (): Promise => { try { const { data: createEventData } = await create({ @@ -109,6 +119,7 @@ export default function events(): JSX.Element { setStartTime('08:00:00'); setEndTime('10:00:00'); } + setShowCreateEventModal(false); } catch (error: any) { /* istanbul ignore next */ errorHandler(t, error); @@ -136,16 +147,23 @@ export default function events(): JSX.Element { setPage(0); }; - const handleSearch = ( - event: React.ChangeEvent - ): void => { - const newFilter = event.target.value; - setFilterName(newFilter); - const filter = { - title_contains: newFilter, - }; + const handleSearch = (value: string): void => { + refetch({ + title_contains: value, + }); setPage(0); - refetch(filter); + }; + const handleSearchByEnter = (e: any): void => { + if (e.key === 'Enter') { + const { value } = e.target; + handleSearch(value); + } + }; + const handleSearchByBtnClick = (): void => { + const value = + (document.getElementById('searchEvents') as HTMLInputElement)?.value || + ''; + handleSearch(value); }; const handleEventTitleChange = ( @@ -198,15 +216,18 @@ export default function events(): JSX.Element { > @@ -243,83 +264,95 @@ export default function events(): JSX.Element {
-
+ {mode === 0 && (
- {loading ? ( -
- Loading... -
- ) : ( - <> - {events && events.length > 0 ? ( - (rowsPerPage > 0 - ? events.slice( - page * rowsPerPage, - page * rowsPerPage + rowsPerPage - ) - : /* istanbul ignore next */ - events - ).map((event: any) => { - const attendees: any = []; - event.attendees.forEach((attendee: any) => { - const r = { - id: attendee._id, +
+ {loading ? ( +
+ Loading... +
+ ) : ( + <> + {events && events.length > 0 ? ( + (rowsPerPage > 0 + ? events.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ) + : /* istanbul ignore next */ + events + ).map((event: any) => { + const attendees: any = []; + event.attendees.forEach((attendee: any) => { + const r = { + id: attendee._id, + }; + + attendees.push(r); + }); + + const creator: any = {}; + creator.firstName = event.creator.firstName; + creator.lastName = event.creator.lastName; + creator.id = event.creator._id; + + const cardProps: InterfaceEventCardProps = { + id: event._id, + title: event.title, + description: event.description, + location: event.location, + startDate: event.startDate, + endDate: event.endDate, + isRegisterable: event.isRegisterable, + isPublic: event.isPublic, + endTime: event.endTime, + startTime: event.startTime, + recurring: event.recurring, + allDay: event.allDay, + registrants: attendees, + creator, }; - attendees.push(r); - }); - - const creator: any = {}; - creator.firstName = event.creator.firstName; - creator.lastName = event.creator.lastName; - creator.id = event.creator._id; - - const cardProps: InterfaceEventCardProps = { - id: event._id, - title: event.title, - description: event.description, - location: event.location, - startDate: event.startDate, - endDate: event.endDate, - isRegisterable: event.isRegisterable, - isPublic: event.isPublic, - endTime: event.endTime, - startTime: event.startTime, - recurring: event.recurring, - allDay: event.allDay, - registrants: attendees, - creator, - }; - - return ; - }) - ) : ( - {t('nothingToShow')} - )} - - )} + return ; + }) + ) : ( + {t('nothingToShow')} + )} + + )} +
+ + + + + + +
- - - - - - -
-
+ )} + {mode === 1 && ( +
+ +
+ )}
diff --git a/src/screens/UserPortal/Home/Home.module.css b/src/screens/UserPortal/Home/Home.module.css index 48643b3445..5a092dc6f0 100644 --- a/src/screens/UserPortal/Home/Home.module.css +++ b/src/screens/UserPortal/Home/Home.module.css @@ -58,14 +58,119 @@ } .postInput { - height: 200px !important; resize: none; border: none; + outline: none; box-shadow: none; background-color: white; margin-bottom: 10px; } +.postInput:focus { + box-shadow: none; +} + .imageInput { - background-color: white; + display: none; +} + +.postContainer { + margin: 1rem auto; + background-color: transparent; + padding: 1rem; + border-radius: 4px; + /* max-width: 40rem; */ + box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px; +} + +.userImage { + display: flex; + width: 50px; + height: 50px; + align-items: center; + justify-content: center; + overflow: hidden; + border-radius: 50%; + position: relative; + border: 2px solid #31bb6b; +} + +.userImage img { + position: absolute; + top: 0; + left: 0; + width: 100%; + scale: 1.5; +} + +.startPostBtn { + width: 100%; + border-radius: 25px; + background-color: transparent; + /* border: 1px solid #acacac; */ + box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px; + outline: none; + border: none; + color: #000; + font-weight: 900; +} + +.startPostBtn:hover { + background-color: #00000010; + border: 0; + color: #000 !important; +} + +.icons { + width: 25px; +} + +.icons svg { + stroke: #000; +} + +.icons.dark { + cursor: pointer; + border: none; + outline: none; + background-color: transparent; +} + +.icons.dark svg { + stroke: #000; +} + +.iconLabel { + margin: 0; + color: #000; + font-weight: 900; +} + +.uploadLink { + text-align: center; + width: min-content; + padding: 8px 4px; + border-radius: 4px; + cursor: pointer; +} + +.uploadLink:hover { + background-color: #00000010; +} + +.modal { + width: 100dvw; + margin: 0 auto; +} + +.previewImage { + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 1rem; +} + +.previewImage img { + border-radius: 8px; } diff --git a/src/screens/UserPortal/Home/Home.test.tsx b/src/screens/UserPortal/Home/Home.test.tsx index 105714cfc8..aafa779255 100644 --- a/src/screens/UserPortal/Home/Home.test.tsx +++ b/src/screens/UserPortal/Home/Home.test.tsx @@ -1,9 +1,12 @@ import React from 'react'; -import { act, render, screen } from '@testing-library/react'; +import { act, fireEvent, render, screen, within } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; -import { ORGANIZATION_POST_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; +import { + ORGANIZATION_POST_CONNECTION_LIST, + ADVERTISEMENTS_GET, +} from 'GraphQl/Queries/Queries'; import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import { store } from 'state/store'; @@ -24,6 +27,19 @@ jest.mock('react-toastify', () => ({ }, })); +const EMPTY_MOCKS = [ + { + request: { + query: ADVERTISEMENTS_GET, + }, + result: { + data: { + getAdvertisements: [], + }, + }, + }, +]; + const MOCKS = [ { request: { @@ -124,10 +140,9 @@ const MOCKS = [ request: { query: CREATE_POST_MUTATION, variables: { - title: '', - text: 'This is a test', - organizationId: '', - file: '', + title: 'Dummy Post', + text: 'This is dummy text', + organizationId: '123', }, result: { data: { @@ -138,9 +153,58 @@ const MOCKS = [ }, }, }, + { + request: { + query: ADVERTISEMENTS_GET, + variables: {}, + }, + result: { + data: { + getAdvertisements: [ + { + _id: '1234', + name: 'Ad 1', + type: 'Type 1', + orgId: 'orgId', + link: 'Link 1', + endDate: '2024-12-31', + startDate: '2022-01-01', + }, + { + _id: '2345', + name: 'Ad 2', + type: 'Type 1', + orgId: 'orgId', + link: 'Link 2', + endDate: '2024-09-31', + startDate: '2023-04-01', + }, + { + _id: '3456', + name: 'name3', + type: 'Type 2', + orgId: 'orgId', + link: 'link3', + startDate: '2023-01-30', + endDate: '2023-12-31', + }, + { + _id: '4567', + name: 'name4', + type: 'Type 2', + orgId: 'org1', + link: 'link4', + startDate: '2023-01-30', + endDate: '2023-12-01', + }, + ], + }, + }, + }, ]; const link = new StaticMockLink(MOCKS, true); +const link2 = new StaticMockLink(EMPTY_MOCKS, true); async function wait(ms = 100): Promise { await act(() => { @@ -150,6 +214,26 @@ async function wait(ms = 100): Promise { }); } +beforeEach(() => { + const url = 'http://localhost:3000/user/organization/id=orgId'; + Object.defineProperty(window, 'location', { + value: { + href: url, + }, + writable: true, + }); +}); + +let originalLocation: Location; + +beforeAll(() => { + originalLocation = window.location; +}); + +afterAll(() => { + window.location = originalLocation; +}); + describe('Testing Home Screen [User Portal]', () => { jest.mock('utils/getOrganizationId'); @@ -214,6 +298,8 @@ describe('Testing Home Screen [User Portal]', () => { expect(getOrganizationIdSpy).toHaveBeenCalled(); + userEvent.click(screen.getByTestId('startPostBtn')); + const randomPostInput = 'This is a test'; userEvent.type(screen.getByTestId('postInput'), randomPostInput); @@ -221,11 +307,7 @@ describe('Testing Home Screen [User Portal]', () => { }); test('Error toast should be visible when user tries to create a post with an empty body', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); + const toastSpy = jest.spyOn(toast, 'error'); render( @@ -240,23 +322,14 @@ describe('Testing Home Screen [User Portal]', () => { ); await wait(); + userEvent.click(screen.getByTestId('startPostBtn')); - expect(getOrganizationIdSpy).toHaveBeenCalled(); - - userEvent.click(screen.getByTestId('postAction')); + userEvent.click(screen.getByTestId('createPostBtn')); - expect(toast.error).toBeCalledWith( - "Can't create a post with an empty body." - ); + expect(toastSpy).toBeCalledWith("Can't create a post with an empty body."); }); test('Info toast should be visible when user tries to create a post with a valid body', async () => { - const getOrganizationIdSpy = jest - .spyOn(getOrganizationId, 'default') - .mockImplementation(() => { - return ''; - }); - render( @@ -271,15 +344,125 @@ describe('Testing Home Screen [User Portal]', () => { await wait(); - expect(getOrganizationIdSpy).toHaveBeenCalled(); + userEvent.click(screen.getByTestId('startPostBtn')); const randomPostInput = 'This is a test'; userEvent.type(screen.getByTestId('postInput'), randomPostInput); expect(screen.queryByText(randomPostInput)).toBeInTheDocument(); - userEvent.click(screen.getByTestId('postAction')); + userEvent.click(screen.getByTestId('createPostBtn')); expect(toast.error).not.toBeCalledWith(); expect(toast.info).toBeCalledWith('Processing your post. Please wait.'); }); + + test('Modal should open on clicking on start a post button', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('startPostBtn')); + const startPostModal = screen.getByTestId('startPostModal'); + expect(startPostModal).toBeInTheDocument(); + }); + + test('modal closes on clicking on the close button', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('startPostBtn')); + const modalHeader = screen.getByTestId('startPostModal'); + expect(modalHeader).toBeInTheDocument(); + + userEvent.type(screen.getByTestId('postInput'), 'some content'); + userEvent.upload( + screen.getByTestId('postImageInput'), + new File(['image content'], 'image.png', { type: 'image/png' }) + ); + + // Check that the content and image have been added + expect(screen.getByTestId('postInput')).toHaveValue('some content'); + await screen.findByAltText('Post Image Preview'); + expect(screen.getByAltText('Post Image Preview')).toBeInTheDocument(); + + const closeButton = within(modalHeader).getByRole('button', { + name: /close/i, + }); + userEvent.click(closeButton); + + const closedModalText = screen.queryByText(/somethingOnYourMind/i); + expect(closedModalText).not.toBeInTheDocument(); + + expect(screen.getByTestId('postInput')).toHaveValue(''); + expect(screen.getByTestId('postImageInput')).toHaveValue(''); + }); + + test('triggers file input when the icon is clicked', () => { + const clickSpy = jest.spyOn(HTMLInputElement.prototype, 'click'); + + render( + + + + + + + + + + ); + + userEvent.click(screen.getByTestId('startPostBtn')); + + // Check if the file input is hidden initially + const postImageInput = screen.getByTestId('postImageInput'); + expect(postImageInput).toHaveAttribute('type', 'file'); + expect(postImageInput).toHaveStyle({ display: 'none' }); + + // Trigger icon click event + const iconButton = screen.getByTestId('addMediaBtn'); + fireEvent.click(iconButton); + + // Check if the file input is triggered to open + expect(clickSpy).toHaveBeenCalled(); + clickSpy.mockRestore(); + }); + + test('promoted post is not rendered if there is no ad content', () => { + render( + + + + + + + + + + ); + + expect(screen.queryByText('Ad 1')).not.toBeInTheDocument(); + expect(screen.queryByText('Ad 2')).not.toBeInTheDocument(); + }); }); diff --git a/src/screens/UserPortal/Home/Home.tsx b/src/screens/UserPortal/Home/Home.tsx index ad02e1b26c..9c046ff9a6 100644 --- a/src/screens/UserPortal/Home/Home.tsx +++ b/src/screens/UserPortal/Home/Home.tsx @@ -1,19 +1,27 @@ -import React from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import type { ChangeEvent } from 'react'; import OrganizationNavbar from 'components/UserPortal/OrganizationNavbar/OrganizationNavbar'; import styles from './Home.module.css'; import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; import OrganizationSidebar from 'components/UserPortal/OrganizationSidebar/OrganizationSidebar'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; -import { Button, FloatingLabel, Form } from 'react-bootstrap'; +import { + Button, + Form, + Col, + Container, + Image, + Row, + Modal, +} from 'react-bootstrap'; import { Link } from 'react-router-dom'; import getOrganizationId from 'utils/getOrganizationId'; -import SendIcon from '@mui/icons-material/Send'; import PostCard from 'components/UserPortal/PostCard/PostCard'; import { useMutation, useQuery } from '@apollo/client'; import { ADVERTISEMENTS_GET, ORGANIZATION_POST_CONNECTION_LIST, + USER_DETAILS, } from 'GraphQl/Queries/Queries'; import { CREATE_POST_MUTATION } from 'GraphQl/Mutations/mutations'; import { errorHandler } from 'utils/errorHandler'; @@ -22,6 +30,7 @@ import convertToBase64 from 'utils/convertToBase64'; import { toast } from 'react-toastify'; import HourglassBottomIcon from '@mui/icons-material/HourglassBottom'; import PromotedPost from 'components/UserPortal/PromotedPost/PromotedPost'; +import UserDefault from '../../../assets/images/defaultImg.png'; interface InterfacePostCardProps { id: string; @@ -57,15 +66,28 @@ interface InterfacePostCardProps { }[]; } +interface InterfaceAdContent { + _id: string; + name: string; + type: string; + orgId: string; + link: string; + endDate: string; + startDate: string; +} + export default function home(): JSX.Element { const { t } = useTranslation('translation', { keyPrefix: 'home' }); const organizationId = getOrganizationId(window.location.href); const [posts, setPosts] = React.useState([]); - const [postContent, setPostContent] = React.useState(''); - const [postImage, setPostImage] = React.useState(''); + const [postContent, setPostContent] = React.useState(''); + const [postImage, setPostImage] = React.useState(''); + const [adContent, setAdContent] = React.useState([]); + const [filteredAd, setFilteredAd] = useState([]); + const [showStartPost, setShowStartPost] = useState(false); + const fileInputRef = useRef(null); const currentOrgId = window.location.href.split('/id=')[1] + ''; - const [adContent, setAdContent] = React.useState([]); const navbarProps = { currentPage: 'home', @@ -85,6 +107,12 @@ export default function home(): JSX.Element { variables: { id: organizationId }, }); + const userId: string | null = localStorage.getItem('userId'); + + const { data: userData } = useQuery(USER_DETAILS, { + variables: { id: userId }, + }); + const [create] = useMutation(CREATE_POST_MUTATION); const handlePost = async (): Promise => { @@ -109,6 +137,7 @@ export default function home(): JSX.Element { refetch(); setPostContent(''); setPostImage(''); + setShowStartPost(false); } } catch (error: any) { /* istanbul ignore next */ @@ -134,55 +163,133 @@ export default function home(): JSX.Element { } }, [data]); + useEffect(() => { + setFilteredAd(filterAdContent(adContent, currentOrgId)); + }, [adContent]); + + const filterAdContent = ( + adCont: InterfaceAdContent[], + currentOrgId: string, + currentDate: Date = new Date() + ): InterfaceAdContent[] => { + return adCont.filter( + (ad: InterfaceAdContent) => + ad.orgId === currentOrgId && new Date(ad.endDate) > currentDate + ); + }; + + const handlePostButtonClick = (): void => { + setShowStartPost(true); + }; + + const handleIconClick = (e: React.MouseEvent): void => { + e.preventDefault(); + + if (fileInputRef.current) { + fileInputRef.current.click(); + } + }; + + const handleModalClose = (): void => { + setPostContent(''); + setPostImage(''); + setShowStartPost(false); + }; + return ( <>
-
- - - -
- => { - const target = e.target as HTMLInputElement; - const file = target.files && target.files[0]; - if (file) { - const image = await convertToBase64(file); - setPostImage(image); - } - } - } - /> - -
-
+ + + + + + + + + + + +
+
+ + + +
+ +

{t('media')}

+
+ + +
+
+ + + +
+ +

{t('event')}

+
+ + +
+
+ + + +
+ +

{t('article')}

+
+ +
+
- {adContent - .filter((ad: any) => ad.orgId == currentOrgId) - .filter((ad: any) => new Date(ad.endDate) > new Date()).length == 0 - ? '' - : adContent - .filter((ad: any) => ad.orgId == currentOrgId) - .filter((ad: any) => new Date(ad.endDate) > new Date()) - .map((post: any) => ( - - ))} + {filteredAd.length === 0 ? ( + '' + ) : ( +
+ {filteredAd.map((post: any) => ( + + ))} +
+ )} {loadingPosts ? (
Loading... @@ -285,6 +392,107 @@ export default function home(): JSX.Element { )}
+ + + + + + + + {`${userData?.user?.firstName} ${userData?.user?.lastName}`} + + + + + + + + ): Promise => { + const file = e.target.files && e.target.files[0]; + if (file) { + const image = await convertToBase64(file); + setPostImage(image); + } + }} + /> + {postImage && ( +
+ Post Image Preview +
+ )} +
+ +
+
+ + + + +
); diff --git a/src/screens/UserPortal/Organizations/Organizations.test.tsx b/src/screens/UserPortal/Organizations/Organizations.test.tsx index 6d92831940..f206ccab8f 100644 --- a/src/screens/UserPortal/Organizations/Organizations.test.tsx +++ b/src/screens/UserPortal/Organizations/Organizations.test.tsx @@ -165,12 +165,16 @@ describe('Testing Organizations Screen [User Portal]', () => { ); await wait(); - - userEvent.type(screen.getByTestId('searchInput'), '2'); + const searchBtn = screen.getByTestId('searchBtn'); + userEvent.type(screen.getByTestId('searchInput'), '2{enter}'); await wait(); expect(screen.queryByText('anyOrganization2')).toBeInTheDocument(); expect(screen.queryByText('anyOrganization1')).not.toBeInTheDocument(); + + userEvent.clear(screen.getByTestId('searchInput')); + userEvent.click(searchBtn); + await wait(); }); test('Mode is changed to joined organizations', async () => { diff --git a/src/screens/UserPortal/Organizations/Organizations.tsx b/src/screens/UserPortal/Organizations/Organizations.tsx index c0b77f805e..f2a75b023c 100644 --- a/src/screens/UserPortal/Organizations/Organizations.tsx +++ b/src/screens/UserPortal/Organizations/Organizations.tsx @@ -74,17 +74,24 @@ export default function organizations(): JSX.Element { setPage(0); }; - const handleSearch = ( - event: React.ChangeEvent - ): void => { - const newFilter = event.target.value; - setFilterName(newFilter); - - const filter = { - filter: newFilter, - }; + const handleSearch = (value: string): void => { + setFilterName(value); - refetch(filter); + refetch({ + filter: value, + }); + }; + const handleSearchByEnter = (e: any): void => { + if (e.key === 'Enter') { + const { value } = e.target; + handleSearch(value); + } + }; + const handleSearchByBtnClick = (): void => { + const value = + (document.getElementById('searchUserOrgs') as HTMLInputElement)?.value || + ''; + handleSearch(value); }; /* istanbul ignore next */ @@ -124,14 +131,17 @@ export default function organizations(): JSX.Element { diff --git a/src/screens/UserPortal/People/People.test.tsx b/src/screens/UserPortal/People/People.test.tsx index b373a68e98..19af06123f 100644 --- a/src/screens/UserPortal/People/People.test.tsx +++ b/src/screens/UserPortal/People/People.test.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { act, render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; import { I18nextProvider } from 'react-i18next'; - import { ORGANIZATIONS_MEMBER_CONNECTION_LIST, ORGANIZATION_ADMINS_LIST, @@ -156,7 +155,7 @@ describe('Testing People Screen [User Portal]', () => { expect(screen.queryAllByText('Noble Mittal')).not.toBe([]); }); - test('Search works properly', async () => { + test('Search works properly by pressing enter', async () => { render( @@ -171,7 +170,34 @@ describe('Testing People Screen [User Portal]', () => { await wait(); + userEvent.type(screen.getByTestId('searchInput'), 'j{enter}'); + await wait(); + + expect(getOrganizationIdSpy).toHaveBeenCalled(); + expect(screen.queryByText('John Cena')).toBeInTheDocument(); + expect(screen.queryByText('Noble Mittal')).not.toBeInTheDocument(); + }); + + test('Search works properly by clicking search Btn', async () => { + render( + + + + + + + + + + ); + + await wait(); + const searchBtn = screen.getByTestId('searchBtn'); + userEvent.type(screen.getByTestId('searchInput'), ''); + userEvent.click(searchBtn); + await wait(); userEvent.type(screen.getByTestId('searchInput'), 'j'); + userEvent.click(searchBtn); await wait(); expect(getOrganizationIdSpy).toHaveBeenCalled(); diff --git a/src/screens/UserPortal/People/People.tsx b/src/screens/UserPortal/People/People.tsx index f8b4d7ca3d..5bf6991af5 100644 --- a/src/screens/UserPortal/People/People.tsx +++ b/src/screens/UserPortal/People/People.tsx @@ -31,7 +31,6 @@ export default function people(): JSX.Element { const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(5); const [members, setMembers] = React.useState([]); - const [filterName, setFilterName] = React.useState(''); const [mode, setMode] = React.useState(0); const organizationId = getOrganizationId(window.location.href); @@ -70,20 +69,26 @@ export default function people(): JSX.Element { setPage(0); }; - const handleSearch = ( - event: React.ChangeEvent - ): void => { - const newFilter = event.target.value; - setFilterName(newFilter); - - const filter = { + const handleSearch = (newFilter: string): void => { + refetch({ firstName_contains: newFilter, - }; + }); + }; - refetch(filter); + const handleSearchByEnter = (e: any): void => { + if (e.key === 'Enter') { + const { value } = e.target; + handleSearch(value); + } + }; + + const handleSearchByBtnClick = (): void => { + const inputValue = + (document.getElementById('searchPeople') as HTMLInputElement)?.value || + ''; + handleSearch(inputValue); }; - /* istanbul ignore next */ React.useEffect(() => { if (data) { setMembers(data.organizationsMemberConnection.edges); @@ -119,14 +124,17 @@ export default function people(): JSX.Element { diff --git a/src/screens/UserPortal/Settings/Settings.module.css b/src/screens/UserPortal/Settings/Settings.module.css index c8ca1e6091..2ac15983e2 100644 --- a/src/screens/UserPortal/Settings/Settings.module.css +++ b/src/screens/UserPortal/Settings/Settings.module.css @@ -1,7 +1,7 @@ .mainContainer { width: 50%; flex-grow: 3; - padding: 40px; + padding: 25px; max-height: 100%; overflow: auto; } @@ -10,17 +10,38 @@ height: calc(100vh - 66px); } -.content { +.cardHeader .cardTitle { + font-size: 1.2rem; + font-weight: 600; +} + +.cardHeader { + padding: 1.25rem 1rem 1rem 1rem; + border-bottom: 1px solid var(--bs-gray-200); + display: flex; + justify-content: space-between; + align-items: center; +} + +.cardBody { + padding: 1.25rem 1rem 1.5rem 1rem; display: flex; flex-direction: column; - max-width: 300px; - gap: 15px; } -.imageInput { - background-color: white; +.cardLabel { + font-weight: bold; + padding-bottom: 1px; + font-size: 14px; + color: #707070; + margin-bottom: 10px; +} + +.cardControl { + margin-bottom: 20px; } -.colorLight { - background-color: white; +.cardButton { + width: fit-content; + float: right; } diff --git a/src/screens/UserPortal/Settings/Settings.test.tsx b/src/screens/UserPortal/Settings/Settings.test.tsx index faec179acc..b096162e2d 100644 --- a/src/screens/UserPortal/Settings/Settings.test.tsx +++ b/src/screens/UserPortal/Settings/Settings.test.tsx @@ -136,4 +136,23 @@ describe('Testing Settings Screen [User Portal]', () => { userEvent.click(screen.getByTestId('updateUserBtn')); await wait(); }); + + test('Other settings card is rendered properly', async () => { + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByText('Other Settings')).toBeInTheDocument(); + expect(screen.getByText('Change Language')).toBeInTheDocument(); + }); }); diff --git a/src/screens/UserPortal/Settings/Settings.tsx b/src/screens/UserPortal/Settings/Settings.tsx index 35afd78790..2d48994e89 100644 --- a/src/screens/UserPortal/Settings/Settings.tsx +++ b/src/screens/UserPortal/Settings/Settings.tsx @@ -3,13 +3,14 @@ import { useTranslation } from 'react-i18next'; import styles from './Settings.module.css'; import UserSidebar from 'components/UserPortal/UserSidebar/UserSidebar'; import UserNavbar from 'components/UserPortal/UserNavbar/UserNavbar'; -import { Button, Form } from 'react-bootstrap'; +import { Button, Card, Col, Form, Row } from 'react-bootstrap'; import convertToBase64 from 'utils/convertToBase64'; import { UPDATE_USER_MUTATION } from 'GraphQl/Mutations/mutations'; import { useMutation, useQuery } from '@apollo/client'; import { errorHandler } from 'utils/errorHandler'; import { toast } from 'react-toastify'; import { CHECK_AUTH } from 'GraphQl/Queries/Queries'; +import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; export default function settings(): JSX.Element { const { t } = useTranslation('translation', { @@ -83,60 +84,109 @@ export default function settings(): JSX.Element {

{t('profileSettings')}

-
- {t('firstName')} - - {t('lastName')} - - {t('emailAddress')} - - {t('updateImage')} - => { - const target = e.target as HTMLInputElement; - const file = target.files && target.files[0]; - if (file) { - const image = await convertToBase64(file); - setImage(image); - } - } - } - /> - -
+ + + +
+
+ {t('updateProfile')} +
+
+ + + {t('firstName')} + + + + {t('lastName')} + + + + {t('emailAddress')} + + + + {t('updateImage')} + + => { + const target = e.target as HTMLInputElement; + const file = target.files && target.files[0]; + if (file) { + const image = await convertToBase64(file); + setImage(image); + } + } + } + /> +
+ +
+
+
+ + + +
+
{t('otherSettings')}
+
+ + + {t('changeLanguage')} + + + +
+ +
diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css b/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css index 840ceb8a0b..413df8cecd 100644 --- a/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css +++ b/src/screens/UserPortal/UserLoginPage/UserLoginPage.module.css @@ -1,48 +1,208 @@ -body::before { - content: none !important; +.login_background { + min-height: 100vh; } -.leftPane { +.row .left_portion { + display: flex; + justify-content: center; align-items: center; - width: 60%; - min-width: 300px; + flex-direction: column; + height: 100vh; +} + +.row .left_portion .inner .palisadoes_logo { + width: 600px; + height: auto; +} + +.row .right_portion { + min-height: 100vh; + position: relative; + overflow-y: scroll; display: flex; flex-direction: column; justify-content: center; + padding: 1rem 2.5rem; + background: var(--bs-white); } -.palisadoesImage { - width: 100%; - height: auto; - max-width: 700px; +.row .right_portion::-webkit-scrollbar { + display: none; } -.talawaImage { - width: 40%; - height: auto; - margin-left: 50%; - transform: translateX(-50%); +.row .right_portion .langChangeBtn { + margin: 0; + position: absolute; + top: 1rem; + left: 1rem; } -.mainContainer { - display: flex; - flex-direction: row; - flex-wrap: wrap; - gap: 10px; - min-height: 100vh; +.langChangeBtnStyle { + width: 7.5rem; + height: 2.2rem; + padding: 0; } -.contentContainer { - flex-grow: 1; - display: flex; - flex-direction: column; - justify-content: center; - padding: 20px 50px; - background-color: var(--bs-white); +.row .right_portion .talawa_logo { + height: 5rem; + width: 5rem; + display: block; + margin: 1.5rem auto 1rem; + -webkit-animation: zoomIn 0.3s ease-in-out; + animation: zoomIn 0.3s ease-in-out; +} + +.row .orText { + display: block; + position: absolute; + top: calc(-0.7rem - 0.5rem); + left: calc(50% - 2.6rem); + margin: 0 auto; + padding: 0.5rem 2rem; + z-index: 100; + background: var(--bs-white); + color: var(--bs-secondary); } -@media only screen and (max-width: 800px) { - .leftPane { +@media (max-width: 992px) { + .row .left_portion { + padding: 0 2rem; + } + + .row .left_portion .inner .palisadoes_logo { width: 100%; } } + +@media (max-width: 769px) { + .row { + flex-direction: column-reverse; + } + + .row .right_portion, + .row .left_portion { + height: unset; + } + + .row .right_portion { + min-height: 100vh; + overflow-y: unset; + } + + .row .left_portion .inner { + display: flex; + justify-content: center; + } + + .row .left_portion .inner .palisadoes_logo { + height: 70px; + width: unset; + position: absolute; + margin: 0.5rem; + top: 0; + right: 0; + z-index: 100; + } + + .row .left_portion .inner p { + margin-bottom: 0; + padding: 1rem; + } + + .socialIcons { + margin-bottom: 1rem; + } +} + +@media (max-width: 577px) { + .row .right_portion { + padding: 1rem 1rem 0 1rem; + } + + .row .right_portion .langChangeBtn { + position: absolute; + margin: 1rem; + left: 0; + top: 0; + } + + .marginTopForReg { + margin-top: 4rem !important; + } + + .row .right_portion .talawa_logo { + height: 120px; + margin: 0 auto 2rem auto; + } + + .socialIcons { + margin-bottom: 1rem; + } +} + +.active_tab { + -webkit-animation: fadeIn 0.3s ease-in-out; + animation: fadeIn 0.3s ease-in-out; +} + +@-webkit-keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale(0.5); + transform: scale(0.5); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@keyframes zoomIn { + 0% { + opacity: 0; + -webkit-transform: scale(0.5); + transform: scale(0.5); + } + + 100% { + opacity: 1; + -webkit-transform: scale(1); + transform: scale(1); + } +} + +@-webkit-keyframes fadeIn { + 0% { + opacity: 0; + -webkit-transform: translateY(2rem); + transform: translateY(2rem); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + -webkit-transform: translateY(2rem); + transform: translateY(2rem); + } + + 100% { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0); + } +} + +.socialIcons { + display: flex; + gap: 16px; + justify-content: center; +} diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx b/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx index d60e37c682..7b41dad875 100644 --- a/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx +++ b/src/screens/UserPortal/UserLoginPage/UserLoginPage.test.tsx @@ -1,14 +1,83 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render } from '@testing-library/react'; -import { I18nextProvider } from 'react-i18next'; +import { act, render, screen } from '@testing-library/react'; import { Provider } from 'react-redux'; import { BrowserRouter } from 'react-router-dom'; -import { store } from 'state/store'; +import userEvent from '@testing-library/user-event'; +import { I18nextProvider } from 'react-i18next'; +import 'jest-localstorage-mock'; +import 'jest-location-mock'; import { StaticMockLink } from 'utils/StaticMockLink'; +import LoginPage from './UserLoginPage'; +import { + LOGIN_MUTATION, + RECAPTCHA_MUTATION, + SIGNUP_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { store } from 'state/store'; import i18nForTest from 'utils/i18nForTest'; -import UserLoginPage from './UserLoginPage'; +const MOCKS = [ + { + request: { + query: LOGIN_MUTATION, + variables: { + email: 'johndoe@gmail.com', + password: 'johndoe', + }, + }, + result: { + data: { + login: { + user: { + _id: '1', + userType: 'ADMIN', + adminApproved: true, + }, + accessToken: 'accessToken', + refreshToken: 'refreshToken', + }, + }, + }, + }, + { + request: { + query: SIGNUP_MUTATION, + variables: { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johnDoe', + }, + }, + result: { + data: { + register: { + user: { + _id: '1', + }, + accessToken: 'accessToken', + refreshToken: 'refreshToken', + }, + }, + }, + }, + { + request: { + query: RECAPTCHA_MUTATION, + variables: { + recaptchaToken: null, + }, + }, + result: { + data: { + recaptcha: true, + }, + }, + }, +]; + +const link = new StaticMockLink(MOCKS, true); async function wait(ms = 100): Promise { await act(() => { @@ -18,22 +87,544 @@ async function wait(ms = 100): Promise { }); } -const link = new StaticMockLink([], true); +jest.mock('react-toastify', () => ({ + toast: { + success: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + }, +})); + +jest.mock('Constant/constant.ts', () => ({ + ...jest.requireActual('Constant/constant.ts'), + REACT_APP_USE_RECAPTCHA: 'yes', + RECAPTCHA_SITE_KEY: 'xxx', +})); + +describe('Talawa-API server fetch check', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('Checks if Talawa-API resource is loaded successfully', async () => { + global.fetch = jest.fn(() => Promise.resolve({} as unknown as Response)); + + await act(async () => { + render( + + + + + + + + + + ); + }); + + expect(fetch).toHaveBeenCalledWith('http://localhost:4000/graphql/'); + }); + + test('displays warning message when resource loading fails', async () => { + const mockError = new Error('Network error'); + global.fetch = jest.fn(() => Promise.reject(mockError)); + + await act(async () => { + render( + + + + + + + + + + ); + }); + + expect(fetch).toHaveBeenCalledWith('http://localhost:4000/graphql/'); + }); +}); + +describe('Testing Login Page Screen', () => { + test('Component Should be rendered properly', async () => { + window.location.assign('/user/organizations'); + + render( + + + + + + + + + + ); + + await wait(); + + expect(screen.getByText(/User Login/i)).toBeInTheDocument(); + expect(window.location).toBeAt('/user/organizations'); + }); + + test('Testing registration functionality', async () => { + const formData = { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johndoe', + confirmPassword: 'johndoe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + + await wait(); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + }); + + test('Testing registration functionality, when password and confirm password is not same', async () => { + const formData = { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johndoe', + confirmPassword: 'doeJohn', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last Name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + }); + + test('Testing registration functionality, when input is not filled correctly', async () => { + const formData = { + firstName: 'J', + lastName: 'D', + email: 'johndoe@gmail.com', + password: 'joe', + confirmPassword: 'joe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last Name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + }); + + test('switches to login tab on successful registration', async () => { + const formData = { + firstName: 'John', + lastName: 'Doe', + email: 'johndoe@gmail.com', + password: 'johndoe', + confirmPassword: 'johndoe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId(/goToRegisterPortion/i)); + userEvent.type( + screen.getByPlaceholderText(/First Name/i), + formData.firstName + ); + userEvent.type( + screen.getByPlaceholderText(/Last name/i), + formData.lastName + ); + userEvent.type(screen.getByTestId(/signInEmail/i), formData.email); + userEvent.type(screen.getByPlaceholderText('Password'), formData.password); + userEvent.type( + screen.getByPlaceholderText('Confirm Password'), + formData.confirmPassword + ); + + userEvent.click(screen.getByTestId('registrationBtn')); + + await wait(); + + // Check if the login tab is now active by checking for elements that only appear in the login tab + expect(screen.getByTestId('loginBtn')).toBeInTheDocument(); + expect(screen.getByTestId('goToRegisterPortion')).toBeInTheDocument(); + }); + + test('Testing toggle login register portion', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + userEvent.click(screen.getByTestId('goToLoginPortion')); + + await wait(); + }); + + test('Testing login functionality', async () => { + const formData = { + email: 'johndoe@gmail.com', + password: 'johndoe', + }; + + render( + + + + + + + + + + ); + + await wait(); + + userEvent.type(screen.getByTestId(/loginEmail/i), formData.email); + userEvent.type( + screen.getByPlaceholderText(/Enter Password/i), + formData.password + ); + + userEvent.click(screen.getByTestId('loginBtn')); + + await wait(); + }); + + test('Testing password preview feature for login', async () => { + render( + + + + + + + + + + ); + + await wait(); + + const input = screen.getByTestId('password') as HTMLInputElement; + const toggleText = screen.getByTestId('showLoginPassword'); + // password should be hidden + expect(input.type).toBe('password'); + // click the toggle button to show password + userEvent.click(toggleText); + expect(input.type).toBe('text'); + // click the toggle button to hide password + userEvent.click(toggleText); + expect(input.type).toBe('password'); + + await wait(); + }); + + test('Testing password preview feature for register', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + const input = screen.getByTestId('passwordField') as HTMLInputElement; + const toggleText = screen.getByTestId('showPassword'); + // password should be hidden + expect(input.type).toBe('password'); + // click the toggle button to show password + userEvent.click(toggleText); + expect(input.type).toBe('text'); + // click the toggle button to hide password + userEvent.click(toggleText); + expect(input.type).toBe('password'); + + await wait(); + }); + + test('Testing confirm password preview feature', async () => { + render( + + + + + + + + + + ); + + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + const input = screen.getByTestId('cpassword') as HTMLInputElement; + const toggleText = screen.getByTestId('showPasswordCon'); + // password should be hidden + expect(input.type).toBe('password'); + // click the toggle button to show password + userEvent.click(toggleText); + expect(input.type).toBe('text'); + // click the toggle button to hide password + userEvent.click(toggleText); + expect(input.type).toBe('password'); + + await wait(); + }); + + test('Testing for the password error warning when user firsts lands on a page', async () => { + render( + + + + + + + + + + ); + await wait(); + + expect(screen.queryByTestId('passwordCheck')).toBeNull(); + }); + + test('Testing for the password error warning when user clicks on password field and password is less than 8 character', async () => { + const password = { + password: '7', + }; -describe('Testing User Login Page Screen [User Portal]', () => { - test('Screen should be rendered properly', async () => { render( - + ); + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + userEvent.type(screen.getByPlaceholderText('Password'), password.password); + + expect(screen.getByTestId('passwordField')).toHaveFocus(); + + expect(password.password.length).toBeLessThan(8); + expect(screen.queryByTestId('passwordCheck')).toBeInTheDocument(); + }); + + test('Testing for the password error warning when user clicks on password field and password is greater than or equal to 8 character', async () => { + const password = { + password: '12345678', + }; + + render( + + + + + + + + + + ); await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + userEvent.type(screen.getByPlaceholderText('Password'), password.password); + + expect(screen.getByTestId('passwordField')).toHaveFocus(); + + expect(password.password.length).toBeGreaterThanOrEqual(8); + + expect(screen.queryByTestId('passwordCheck')).toBeNull(); + }); + + test('Testing for the password error warning when user clicks on fields except password field and password is less than 8 character', async () => { + const password = { + password: '7', + }; + + render( + + + + + + + + + + ); + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + expect(screen.getByPlaceholderText('Password')).not.toHaveFocus(); + + userEvent.type(screen.getByPlaceholderText('Password'), password.password); + + expect(password.password.length).toBeLessThan(8); + + expect(screen.queryByTestId('passwordCheck')).toBeInTheDocument(); + }); + + test('Testing for the password error warning when user clicks on fields except password field and password is greater than or equal to 8 character', async () => { + const password = { + password: '12345678', + }; + + render( + + + + + + + + + + ); + await wait(); + + userEvent.click(screen.getByTestId('goToRegisterPortion')); + + await wait(); + + expect(screen.getByPlaceholderText('Password')).not.toHaveFocus(); + + userEvent.type(screen.getByPlaceholderText('Password'), password.password); + + expect(password.password.length).toBeGreaterThanOrEqual(8); + + expect(screen.queryByTestId('passwordCheck')).toBeNull(); }); }); diff --git a/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx b/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx index ca4915d691..2e16f48bc1 100644 --- a/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx +++ b/src/screens/UserPortal/UserLoginPage/UserLoginPage.tsx @@ -1,49 +1,625 @@ -import React from 'react'; +import { useMutation } from '@apollo/client'; +import type { ChangeEvent } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; +import { Form } from 'react-bootstrap'; +import Button from 'react-bootstrap/Button'; +import Col from 'react-bootstrap/Col'; +import Row from 'react-bootstrap/Row'; +import ReCAPTCHA from 'react-google-recaptcha'; import { useTranslation } from 'react-i18next'; +import { Link, useHistory } from 'react-router-dom'; +import { toast } from 'react-toastify'; -import PalisadoesImage from 'assets/images/palisadoes_logo.png'; -import TalawaImage from 'assets/images/talawa-logo-200x200.png'; +import { + FacebookLogo, + LinkedInLogo, + GithubLogo, + InstagramLogo, + SlackLogo, + TwitterLogo, + YoutubeLogo, +} from 'assets/svgs/social-icons'; + +import { REACT_APP_USE_RECAPTCHA, RECAPTCHA_SITE_KEY } from 'Constant/constant'; +import { + LOGIN_MUTATION, + RECAPTCHA_MUTATION, + SIGNUP_MUTATION, +} from 'GraphQl/Mutations/mutations'; +import { ReactComponent as TalawaLogo } from 'assets/svgs/talawa.svg'; +import { ReactComponent as PalisadoesLogo } from 'assets/svgs/palisadoes.svg'; import ChangeLanguageDropDown from 'components/ChangeLanguageDropdown/ChangeLanguageDropDown'; -import Login from 'components/UserPortal/Login/Login'; -import Register from 'components/UserPortal/Register/Register'; +import LoginPortalToggle from 'components/LoginPortalToggle/LoginPortalToggle'; +import Loader from 'components/Loader/Loader'; +import { errorHandler } from 'utils/errorHandler'; import styles from './UserLoginPage.module.css'; +import EmailOutlinedIcon from '@mui/icons-material/EmailOutlined'; + +function loginPage(): JSX.Element { + const { t } = useTranslation('translation', { keyPrefix: 'userLoginPage' }); + const history = useHistory(); + + document.title = t('title'); + + const [showTab, setShowTab] = useState<'LOGIN' | 'REGISTER'>('LOGIN'); + const [componentLoader, setComponentLoader] = useState(true); + const [isInputFocused, setIsInputFocused] = useState(false); + const [signformState, setSignFormState] = useState({ + signfirstName: '', + signlastName: '', + signEmail: '', + signPassword: '', + cPassword: '', + }); + const [formState, setFormState] = useState({ + email: '', + password: '', + }); + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = + useState(false); + const recaptchaRef = useRef(null); + + useEffect(() => { + const isLoggedIn = localStorage.getItem('IsLoggedIn'); + if (isLoggedIn == 'TRUE') { + history.push('/user/organizations/'); + } + setComponentLoader(false); + }, []); + + const togglePassword = (): void => setShowPassword(!showPassword); + const toggleConfirmPassword = (): void => + setShowConfirmPassword(!showConfirmPassword); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [login, { loading: loginLoading }] = useMutation(LOGIN_MUTATION); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [signup, { loading: signinLoading }] = useMutation(SIGNUP_MUTATION); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [recaptcha, { loading: recaptchaLoading }] = + useMutation(RECAPTCHA_MUTATION); + + useEffect(() => { + async function loadResource(): Promise { + try { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const response = await fetch('http://localhost:4000/graphql/'); + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + } + + loadResource(); + }, []); -export default function userLoginPage(): JSX.Element { - const { t } = useTranslation('translation', { keyPrefix: 'loginPage' }); + const verifyRecaptcha = async ( + recaptchaToken: any + ): Promise => { + try { + /* istanbul ignore next */ + if (REACT_APP_USE_RECAPTCHA !== 'yes') { + return true; + } + const { data } = await recaptcha({ + variables: { + recaptchaToken, + }, + }); - const [currentMode, setCurrentMode] = React.useState('login'); - const loginRegisterProps = { - setCurrentMode: setCurrentMode, + return data.recaptcha; + } catch (error: any) { + /* istanbul ignore next */ + toast.error(t('captchaError')); + } }; - return ( -
-
- Palisadoes Branding -
-

{t('fromPalisadoes')}

-
-
-
- - Talawa Branding - { + const signupLink = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const { signfirstName, signlastName, signEmail, signPassword, cPassword } = + signformState; + + const recaptchaToken = recaptchaRef.current?.getValue(); + recaptchaRef.current?.reset(); + + const isVerified = await verifyRecaptcha(recaptchaToken); + /* istanbul ignore next */ + if (!isVerified) { + toast.error(t('Please_check_the_captcha')); + return; + } + + if ( + signfirstName.length > 1 && + signlastName.length > 1 && + signEmail.length >= 8 && + signPassword.length > 1 + ) { + if (cPassword == signPassword) { + try { + const { data: signUpData } = await signup({ + variables: { + firstName: signfirstName, + lastName: signlastName, + email: signEmail, + password: signPassword, + }, + }); + + /* istanbul ignore next */ + if (signUpData) { + toast.success(t('afterRegister')); + + setShowTab('LOGIN'); + + setSignFormState({ + signfirstName: '', + signlastName: '', + signEmail: '', + signPassword: '', + cPassword: '', + }); + } + } catch (error: any) { /* istanbul ignore next */ - currentMode === 'login' ? ( - - ) : ( - - ) + errorHandler(t, error); } -
-
+ } else { + toast.warn(t('passwordMismatches')); + } + } else { + toast.warn(t('fillCorrectly')); + } + }; + + const loginLink = async (e: ChangeEvent): Promise => { + e.preventDefault(); + + const recaptchaToken = recaptchaRef.current?.getValue(); + recaptchaRef.current?.reset(); + + const isVerified = await verifyRecaptcha(recaptchaToken); + /* istanbul ignore next */ + if (!isVerified) { + toast.error(t('Please_check_the_captcha')); + return; + } + + try { + const { data: loginData } = await login({ + variables: { + email: formState.email, + password: formState.password, + }, + }); + + /* istanbul ignore next */ + if (loginData) { + localStorage.setItem('token', loginData.login.accessToken); + localStorage.setItem('userId', loginData.login.user._id); + localStorage.setItem('refreshToken', loginData.login.refreshToken); + localStorage.setItem('IsLoggedIn', 'TRUE'); + navigator.clipboard.writeText(''); + if (localStorage.getItem('IsLoggedIn') == 'TRUE') { + history.push('/user/organizations/'); + } + } else { + toast.warn(t('notAuthorised')); + } + } catch (error: any) { + /* istanbul ignore next */ + errorHandler(t, error); + } + }; + + if (componentLoader || loginLoading || signinLoading || recaptchaLoading) { + return ; + } + + return ( + <> +
+ + +
+ +

{t('fromPalisadoes')}

+
+ + + + +
+ + + + + + {/* LOGIN FORM */} +
+
+

+ {t('userLogin')} +

+ {t('email')} +
+ { + setFormState({ + ...formState, + email: e.target.value, + }); + }} + autoComplete="username" + data-testid="loginEmail" + /> + +
+ {t('password')} +
+ { + setFormState({ + ...formState, + password: e.target.value, + }); + }} + autoComplete="current-password" + /> + +
+
+ + {t('forgotPassword')} + +
+ {REACT_APP_USE_RECAPTCHA === 'yes' ? ( +
+ +
+ ) : ( + /* istanbul ignore next */ + <> + )} + +
+
+ {t('OR')} +
+ +
+
+ {/* REGISTER FORM */} +
+
+

+ {t('register')} +

+ + +
+ {t('firstName')} + { + setSignFormState({ + ...signformState, + signfirstName: e.target.value, + }); + }} + /> +
+ + +
+ {t('lastName')} + { + setSignFormState({ + ...signformState, + signlastName: e.target.value, + }); + }} + /> +
+ +
+
+ {t('email')} +
+ { + setSignFormState({ + ...signformState, + signEmail: e.target.value.toLowerCase(), + }); + }} + /> + +
+
+ +
+ {t('password')} +
+ setIsInputFocused(true)} + onBlur={(): void => setIsInputFocused(false)} + required + value={signformState.signPassword} + onChange={(e): void => { + setSignFormState({ + ...signformState, + signPassword: e.target.value, + }); + }} + /> + +
+ {isInputFocused && + signformState.signPassword.length < 8 && ( +
+ {t('atleast_8_char_long')} +
+ )} + {!isInputFocused && + signformState.signPassword.length > 0 && + signformState.signPassword.length < 8 && ( +
+ {t('atleast_8_char_long')} +
+ )} +
+
+ {t('confirmPassword')} +
+ { + setSignFormState({ + ...signformState, + cPassword: e.target.value, + }); + }} + data-testid="cpassword" + autoComplete="new-password" + /> + +
+ {signformState.cPassword.length > 0 && + signformState.signPassword !== + signformState.cPassword && ( +
+ {t('Password_and_Confirm_password_mismatches.')} +
+ )} +
+ {REACT_APP_USE_RECAPTCHA === 'yes' ? ( +
+ +
+ ) : ( + /* istanbul ignore next */ + <> + )} + +
+
+ {t('OR')} +
+ +
+
+
+ +
+
+ ); } + +export default loginPage; diff --git a/src/screens/Users/Users.test.tsx b/src/screens/Users/Users.test.tsx index 4484518529..446fc57f7d 100644 --- a/src/screens/Users/Users.test.tsx +++ b/src/screens/Users/Users.test.tsx @@ -12,10 +12,11 @@ import { store } from 'state/store'; import { StaticMockLink } from 'utils/StaticMockLink'; import i18nForTest from 'utils/i18nForTest'; import Users from './Users'; -import { EMPTY_MOCKS, MOCKS } from './UsersMocks'; +import { EMPTY_MOCKS, MOCKS, MOCKS2 } from './UsersMocks'; const link = new StaticMockLink(MOCKS, true); const link2 = new StaticMockLink(EMPTY_MOCKS, true); +const link3 = new StaticMockLink(MOCKS2, true); async function wait(ms = 100): Promise { await act(() => { @@ -102,9 +103,11 @@ describe('Testing Users screen', () => { ); await wait(); - - const search1 = 'John{backspace}{backspace}{backspace}{backspace}'; + const searchBtn = screen.getByTestId('searchButton'); + const search1 = 'John'; userEvent.type(screen.getByTestId(/searchByName/i), search1); + userEvent.click(searchBtn); + await wait(); const search2 = 'Pete{backspace}{backspace}{backspace}{backspace}'; userEvent.type(screen.getByTestId(/searchByName/i), search2); @@ -118,7 +121,31 @@ describe('Testing Users screen', () => { const search5 = 'Xe'; userEvent.type(screen.getByTestId(/searchByName/i), search5); + userEvent.clear(screen.getByTestId(/searchByName/i)); userEvent.type(screen.getByTestId(/searchByName/i), ''); + userEvent.click(searchBtn); + await wait(); + }); + + test('testing search not found', async () => { + render( + + + + + + + + + + ); + + await wait(); + + const search = 'hello{enter}'; + await act(() => + userEvent.type(screen.getByTestId(/searchByName/i), search) + ); }); test('Testing User data is not present', async () => { @@ -179,7 +206,7 @@ describe('Testing Users screen', () => { ); }); - test('Testing sort Newest and oldest toggle', async () => { + test('Testing sorting functionality', async () => { await act(async () => { render( @@ -202,15 +229,96 @@ describe('Testing Users screen', () => { const inputText = screen.getByTestId('sortUsers'); fireEvent.click(inputText); - const toggleText = screen.getByTestId('newest'); + const toggleText = screen.getByTestId('oldest'); + fireEvent.click(toggleText); + + expect(searchInput).toBeInTheDocument(); + fireEvent.click(inputText); + const toggleTite = screen.getByTestId('newest'); + fireEvent.click(toggleTite); + + expect(searchInput).toBeInTheDocument(); + }); + }); + + test('Testing filter functionality', async () => { + await act(async () => { + render( + + + + + + + + + + + ); + + await wait(); + + const searchInput = screen.getByTestId('filter'); + expect(searchInput).toBeInTheDocument(); + + const inputText = screen.getByTestId('filterUsers'); + + fireEvent.click(inputText); + const toggleText = screen.getByTestId('admin'); fireEvent.click(toggleText); expect(searchInput).toBeInTheDocument(); + + fireEvent.click(inputText); + let toggleTite = screen.getByTestId('superAdmin'); + fireEvent.click(toggleTite); + + expect(searchInput).toBeInTheDocument(); + + fireEvent.click(inputText); + toggleTite = screen.getByTestId('user'); + fireEvent.click(toggleTite); + + expect(searchInput).toBeInTheDocument(); + fireEvent.click(inputText); - const toggleTite = screen.getByTestId('oldest'); + toggleTite = screen.getByTestId('cancel'); fireEvent.click(toggleTite); + + await wait(); + expect(searchInput).toBeInTheDocument(); }); }); + + test('check for rerendering', async () => { + const { rerender } = render( + + + + + + + + + + + ); + + await wait(); + rerender( + + + + + + + + + + + ); + await wait(); + }); }); diff --git a/src/screens/Users/Users.tsx b/src/screens/Users/Users.tsx index 0cdac832b5..86adefe967 100644 --- a/src/screens/Users/Users.tsx +++ b/src/screens/Users/Users.tsx @@ -31,7 +31,7 @@ const Users = (): JSX.Element => { const [isLoadingMore, setIsLoadingMore] = useState(false); const [searchByName, setSearchByName] = useState(''); const [sortingOption, setSortingOption] = useState('newest'); - + const [filteringOption, setFilteringOption] = useState('cancel'); const userType = localStorage.getItem('UserType'); const loggedInUserId = localStorage.getItem('id'); @@ -68,10 +68,11 @@ const Users = (): JSX.Element => { setHasMore(false); } if (usersData && usersData.users) { - const newDisplayedUsers = sortUsers(usersData.users, sortingOption); + let newDisplayedUsers = sortUsers(usersData.users, sortingOption); + newDisplayedUsers = filterUsers(newDisplayedUsers, filteringOption); setDisplayedUsers(newDisplayedUsers); } - }, [usersData, sortingOption]); + }, [usersData, sortingOption, filteringOption]); // To clear the search when the component is unmounted useEffect(() => { @@ -107,22 +108,33 @@ const Users = (): JSX.Element => { } }, [loading]); - const handleSearchByName = (e: any): void => { - /* istanbul ignore next */ + const handleSearch = (value: string): void => { + setSearchByName(value); + if (value === '') { + resetAndRefetch(); + return; + } + refetchUsers({ + firstName_contains: value, + lastName_contains: '', + // Later on we can add several search and filter options + }); + }; + + const handleSearchByEnter = (e: any): void => { if (e.key === 'Enter') { const { value } = e.target; - setSearchByName(value); - if (value.length === 0) { - resetAndRefetch(); - return; - } - refetchUsers({ - firstName_contains: value, - lastName_contains: '', - // Later on we can add several search and filter options - }); + handleSearch(value); } }; + + const handleSearchByBtnClick = (): void => { + const inputElement = document.getElementById( + 'searchUsers' + ) as HTMLInputElement; + const inputValue = inputElement?.value || ''; + handleSearch(inputValue); + }; /* istanbul ignore next */ const resetAndRefetch = (): void => { refetchUsers({ @@ -179,14 +191,44 @@ const Users = (): JSX.Element => { (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() ); - } else if (sortingOption === 'oldest') { + return sortedUsers; + } else { sortedUsers.sort( (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() ); + return sortedUsers; } + }; + + const handleFiltering = (option: string): void => { + setFilteringOption(option); + }; + + const filterUsers = ( + allUsers: InterfaceQueryUserListItem[], + filteringOption: string + ): InterfaceQueryUserListItem[] => { + const filteredUsers = [...allUsers]; - return sortedUsers; + if (filteringOption === 'cancel') { + return filteredUsers; + } else if (filteringOption === 'user') { + const output = filteredUsers.filter((user) => { + return user.userType === 'USER'; + }); + return output; + } else if (filteringOption === 'admin') { + const output = filteredUsers.filter((user) => { + return user.userType == 'ADMIN'; + }); + return output; + } else { + const output = filteredUsers.filter((user) => { + return user.userType == 'SUPERADMIN'; + }); + return output; + } }; const headerTitles: string[] = [ @@ -212,16 +254,19 @@ const Users = (): JSX.Element => { > @@ -234,12 +279,9 @@ const Users = (): JSX.Element => { title="Sort Users" data-testid="sort" > - + - {t('sort')} + {sortingOption === 'newest' ? t('Newest') : t('Oldest')} { -
@@ -293,7 +364,10 @@ const Users = (): JSX.Element => { /> ) : ( +▸ **fetchInstalled**(): `Promise`\<`any`\> #### Returns -`Promise`<`any`\> +`Promise`\<`any`\> #### Defined in @@ -40,11 +40,11 @@ ___ ### fetchStore -▸ **fetchStore**(): `Promise`<`any`\> +▸ **fetchStore**(): `Promise`\<`any`\> #### Returns -`Promise`<`any`\> +`Promise`\<`any`\> #### Defined in @@ -54,7 +54,7 @@ ___ ### generateLinks -▸ **generateLinks**(`plugins`): { `name`: `string` ; `url`: `string` }[] +▸ **generateLinks**(`plugins`): \{ `name`: `string` ; `url`: `string` \}[] #### Parameters @@ -64,7 +64,7 @@ ___ #### Returns -{ `name`: `string` ; `url`: `string` }[] +\{ `name`: `string` ; `url`: `string` \}[] #### Defined in diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md index b3aff6bcbb..de9645e2ec 100644 --- a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceAttendeeCheckIn.md @@ -26,7 +26,7 @@ ___ ### checkIn -• **checkIn**: ``null`` \| { `_id`: `string` ; `allotedRoom`: `string` ; `allotedSeat`: `string` ; `time`: `string` } +• **checkIn**: ``null`` \| \{ `_id`: `string` ; `allotedRoom`: `string` ; `allotedSeat`: `string` ; `time`: `string` \} #### Defined in diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceModalProp.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceModalProp.md index 9091e555bb..847ac48bcf 100644 --- a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceModalProp.md +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceModalProp.md @@ -26,7 +26,7 @@ ___ ### handleClose -• **handleClose**: () => `void` +• **handleClose**: () =\> `void` #### Type declaration diff --git a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableCheckIn.md b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableCheckIn.md index f44d4747f4..8aaa88f7c8 100644 --- a/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableCheckIn.md +++ b/talawa-admin-docs/interfaces/components_CheckIn_types.InterfaceTableCheckIn.md @@ -18,7 +18,7 @@ ### checkIn -• **checkIn**: ``null`` \| { `_id`: `string` ; `allotedRoom`: `string` ; `allotedSeat`: `string` ; `time`: `string` } +• **checkIn**: ``null`` \| \{ `_id`: `string` ; `allotedRoom`: `string` ; `allotedSeat`: `string` ; `time`: `string` \} #### Defined in diff --git a/talawa-admin-docs/interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md b/talawa-admin-docs/interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md index a087afb658..8af04f8ab5 100644 --- a/talawa-admin-docs/interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md +++ b/talawa-admin-docs/interfaces/components_LeftDrawerOrg_LeftDrawerOrg.InterfaceLeftDrawerProps.md @@ -48,7 +48,7 @@ ___ ### setHideDrawer -• **setHideDrawer**: `Dispatch`<`SetStateAction`<``null`` \| `boolean`\>\> +• **setHideDrawer**: `Dispatch`\<`SetStateAction`\<``null`` \| `boolean`\>\> #### Defined in diff --git a/talawa-admin-docs/interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md b/talawa-admin-docs/interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md index 8150b80c64..9a9cc6df87 100644 --- a/talawa-admin-docs/interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md +++ b/talawa-admin-docs/interfaces/components_LeftDrawer_LeftDrawer.InterfaceLeftDrawerProps.md @@ -36,7 +36,7 @@ ___ ### setHideDrawer -• **setHideDrawer**: `Dispatch`<`SetStateAction`<``null`` \| `boolean`\>\> +• **setHideDrawer**: `Dispatch`\<`SetStateAction`\<``null`` \| `boolean`\>\> #### Defined in diff --git a/talawa-admin-docs/modules/components_AddOn_AddOn.default.md b/talawa-admin-docs/modules/components_AddOn_AddOn.default.md index 1ae4e3dd2e..87e082c6a5 100644 --- a/talawa-admin-docs/modules/components_AddOn_AddOn.default.md +++ b/talawa-admin-docs/modules/components_AddOn_AddOn.default.md @@ -22,7 +22,7 @@ | Name | Type | | :------ | :------ | | `children` | ``null`` | -| `extras` | {} | +| `extras` | \{\} | | `name` | `string` | #### Defined in @@ -39,9 +39,9 @@ ___ | Name | Type | | :------ | :------ | -| `children` | `Requireable`<`any`\> | -| `extras` | `Requireable`<`InferProps`<{ `actions`: `Requireable`<`InferProps`<{}\>\> ; `components`: `Requireable`<`InferProps`<{}\>\> }\>\> | -| `name` | `Requireable`<`string`\> | +| `children` | `Requireable`\<`any`\> | +| `extras` | `Requireable`\<`InferProps`\<\{ `actions`: `Requireable`\<`InferProps`\<\{\}\>\> ; `components`: `Requireable`\<`InferProps`\<\{\}\>\> \}\>\> | +| `name` | `Requireable`\<`string`\> | #### Defined in diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md index a0331db813..ec8f804295 100644 --- a/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnEntry_AddOnEntry.default.md @@ -41,11 +41,11 @@ ___ | Name | Type | | :------ | :------ | -| `configurable` | `Requireable`<`boolean`\> | -| `description` | `Requireable`<`string`\> | -| `enabled` | `Requireable`<`boolean`\> | -| `isInstalled` | `Requireable`<`boolean`\> | -| `title` | `Requireable`<`string`\> | +| `configurable` | `Requireable`\<`boolean`\> | +| `description` | `Requireable`\<`string`\> | +| `enabled` | `Requireable`\<`boolean`\> | +| `isInstalled` | `Requireable`\<`boolean`\> | +| `title` | `Requireable`\<`string`\> | #### Defined in diff --git a/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md b/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md index 07f216c14c..4345c80034 100644 --- a/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md +++ b/talawa-admin-docs/modules/components_AddOn_core_AddOnRegister_AddOnRegister.default.md @@ -37,7 +37,7 @@ ___ | Name | Type | | :------ | :------ | -| `createdBy` | `Requireable`<`string`\> | +| `createdBy` | `Requireable`\<`string`\> | #### Defined in diff --git a/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md b/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md index 7ce929fecd..3229fe3ed2 100644 --- a/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md +++ b/talawa-admin-docs/modules/components_ChangeLanguageDropdown_ChangeLanguageDropDown.md @@ -13,7 +13,7 @@ ### changeLanguage -▸ **changeLanguage**(`languageCode`): `Promise`<`void`\> +▸ **changeLanguage**(`languageCode`): `Promise`\<`void`\> #### Parameters @@ -23,7 +23,7 @@ #### Returns -`Promise`<`void`\> +`Promise`\<`void`\> #### Defined in diff --git a/talawa-admin-docs/modules/components_CheckIn_TableRow.md b/talawa-admin-docs/modules/components_CheckIn_TableRow.md index 34921ffd77..4a61216986 100644 --- a/talawa-admin-docs/modules/components_CheckIn_TableRow.md +++ b/talawa-admin-docs/modules/components_CheckIn_TableRow.md @@ -20,7 +20,7 @@ | :------ | :------ | | `«destructured»` | `Object` | | › `data` | [`InterfaceTableCheckIn`](../interfaces/components_CheckIn_types.InterfaceTableCheckIn.md) | -| › `refetch` | () => `void` | +| › `refetch` | () =\> `void` | #### Returns diff --git a/talawa-admin-docs/modules/components_CheckIn_mocks.md b/talawa-admin-docs/modules/components_CheckIn_mocks.md index 67d7a2b123..24fee2ec60 100644 --- a/talawa-admin-docs/modules/components_CheckIn_mocks.md +++ b/talawa-admin-docs/modules/components_CheckIn_mocks.md @@ -14,7 +14,7 @@ ### checkInMutationSuccess -• `Const` **checkInMutationSuccess**: { `request`: { `query`: `DocumentNode` = MARK\_CHECKIN; `variables`: { `allotedRoom`: `string` = ''; `allotedSeat`: `string` = ''; `eventId`: `string` = 'event123'; `userId`: `string` = 'user123' } } ; `result`: { `data`: { `checkIn`: { `_id`: `string` = '123' } } } }[] +• `Const` **checkInMutationSuccess**: \{ `request`: \{ `query`: `DocumentNode` = MARK\_CHECKIN; `variables`: \{ `allotedRoom`: `string` = ''; `allotedSeat`: `string` = ''; `eventId`: `string` = 'event123'; `userId`: `string` = 'user123' \} \} ; `result`: \{ `data`: \{ `checkIn`: \{ `_id`: `string` = '123' \} \} \} \}[] #### Defined in @@ -24,7 +24,7 @@ ___ ### checkInMutationUnsuccess -• `Const` **checkInMutationUnsuccess**: { `error`: `Error` ; `request`: { `query`: `DocumentNode` = MARK\_CHECKIN; `variables`: { `allotedRoom`: `string` = ''; `allotedSeat`: `string` = ''; `eventId`: `string` = 'event123'; `userId`: `string` = 'user123' } } }[] +• `Const` **checkInMutationUnsuccess**: \{ `error`: `Error` ; `request`: \{ `query`: `DocumentNode` = MARK\_CHECKIN; `variables`: \{ `allotedRoom`: `string` = ''; `allotedSeat`: `string` = ''; `eventId`: `string` = 'event123'; `userId`: `string` = 'user123' \} \} \}[] #### Defined in @@ -34,7 +34,7 @@ ___ ### checkInQueryMock -• `Const` **checkInQueryMock**: { `request`: { `query`: `DocumentNode` = EVENT\_CHECKINS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: [`InterfaceAttendeeQueryResponse`](../interfaces/components_CheckIn_types.InterfaceAttendeeQueryResponse.md) = checkInQueryData } }[] +• `Const` **checkInQueryMock**: \{ `request`: \{ `query`: `DocumentNode` = EVENT\_CHECKINS; `variables`: \{ `id`: `string` = 'event123' \} \} ; `result`: \{ `data`: [`InterfaceAttendeeQueryResponse`](../interfaces/components_CheckIn_types.InterfaceAttendeeQueryResponse.md) = checkInQueryData \} \}[] #### Defined in diff --git a/talawa-admin-docs/modules/components_EventCalendar_EventCalendar.md b/talawa-admin-docs/modules/components_EventCalendar_EventCalendar.md index a6d00af0cb..b8e0171dc7 100644 --- a/talawa-admin-docs/modules/components_EventCalendar_EventCalendar.md +++ b/talawa-admin-docs/modules/components_EventCalendar_EventCalendar.md @@ -12,18 +12,18 @@ ### default -▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`<`any`, `any`\> +▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`\<`any`, `any`\> #### Parameters | Name | Type | | :------ | :------ | -| `props` | `PropsWithChildren`<`InterfaceCalendarProps`\> | +| `props` | `PropsWithChildren`\<`InterfaceCalendarProps`\> | | `context?` | `any` | #### Returns -``null`` \| `ReactElement`<`any`, `any`\> +``null`` \| `ReactElement`\<`any`, `any`\> #### Defined in diff --git a/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md b/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md index 593edf1a85..1f13fe806c 100644 --- a/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md +++ b/talawa-admin-docs/modules/components_TaskModals_UpdateTaskModal.md @@ -22,11 +22,11 @@ | Name | Type | | :------ | :------ | -| `handleClose` | () => `void` | -| `organization` | { `_id`: `string` ; `members`: `InterfaceUser`[] } | +| `handleClose` | () =\> `void` | +| `organization` | \{ `_id`: `string` ; `members`: `InterfaceUser`[] \} | | `organization._id` | `string` | | `organization.members` | `InterfaceUser`[] | -| `refetchData` | () => `void` | +| `refetchData` | () =\> `void` | | `show` | `boolean` | | `task` | `InterfaceTask` | diff --git a/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate.md b/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate.md index 8402744885..08f35fd90b 100644 --- a/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate.md +++ b/talawa-admin-docs/modules/components_UserPasswordUpdate_UserPasswordUpdate.md @@ -12,18 +12,18 @@ ### default -▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`<`any`, `any`\> +▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`\<`any`, `any`\> #### Parameters | Name | Type | | :------ | :------ | -| `props` | `PropsWithChildren`<`InterfaceUserPasswordUpdateProps`\> | +| `props` | `PropsWithChildren`\<`InterfaceUserPasswordUpdateProps`\> | | `context?` | `any` | #### Returns -``null`` \| `ReactElement`<`any`, `any`\> +``null`` \| `ReactElement`\<`any`, `any`\> #### Defined in diff --git a/talawa-admin-docs/modules/components_UserUpdate_UserUpdate.md b/talawa-admin-docs/modules/components_UserUpdate_UserUpdate.md index 4285a73143..5f7d23b6a0 100644 --- a/talawa-admin-docs/modules/components_UserUpdate_UserUpdate.md +++ b/talawa-admin-docs/modules/components_UserUpdate_UserUpdate.md @@ -12,18 +12,18 @@ ### default -▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`<`any`, `any`\> +▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`\<`any`, `any`\> #### Parameters | Name | Type | | :------ | :------ | -| `props` | `PropsWithChildren`<`InterfaceUserUpdateProps`\> | +| `props` | `PropsWithChildren`\<`InterfaceUserUpdateProps`\> | | `context?` | `any` | #### Returns -``null`` \| `ReactElement`<`any`, `any`\> +``null`` \| `ReactElement`\<`any`, `any`\> #### Defined in diff --git a/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_mocks.md b/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_mocks.md index d5ef0c33f7..b8d8d3b320 100644 --- a/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_mocks.md +++ b/talawa-admin-docs/modules/screens_EventDashboard_EventDashboard_mocks.md @@ -15,7 +15,7 @@ ### queryMockWithProject -• `Const` **queryMockWithProject**: { `request`: { `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: { `event`: { `allDay`: `boolean` = false; `attendees`: { `_id`: `string` = 'user1' }[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: { `_id`: `string` = 'org1'; `members`: { `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' }[] } ; `projects`: { `_id`: `string` = 'project1'; `description`: `string` = 'Project Description 1'; `tasks`: `never`[] = []; `title`: `string` = 'Project 1' }[] ; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' } } } }[] +• `Const` **queryMockWithProject**: \{ `request`: \{ `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: \{ `id`: `string` = 'event123' \} \} ; `result`: \{ `data`: \{ `event`: \{ `allDay`: `boolean` = false; `attendees`: \{ `_id`: `string` = 'user1' \}[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: \{ `_id`: `string` = 'org1'; `members`: \{ `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \}[] \} ; `projects`: \{ `_id`: `string` = 'project1'; `description`: `string` = 'Project Description 1'; `tasks`: `never`[] = []; `title`: `string` = 'Project 1' \}[] ; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' \} \} \} \}[] #### Defined in @@ -25,7 +25,7 @@ ___ ### queryMockWithProjectAndTask -• `Const` **queryMockWithProjectAndTask**: { `request`: { `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: { `event`: { `allDay`: `boolean` = false; `attendees`: { `_id`: `string` = 'user1' }[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: { `_id`: `string` = 'org1'; `members`: { `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' }[] } ; `projects`: { `_id`: `string` = 'project1'; `description`: `string` = 'Project Description 1'; `tasks`: { `_id`: `string` = 'task1'; `completed`: `boolean` = false; `deadline`: `string` = '22/12/23'; `description`: `string` = 'Description 1'; `title`: `string` = 'Task 1'; `volunteers`: `never`[] = [] }[] ; `title`: `string` = 'Project 1' }[] ; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' } } } }[] +• `Const` **queryMockWithProjectAndTask**: \{ `request`: \{ `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: \{ `id`: `string` = 'event123' \} \} ; `result`: \{ `data`: \{ `event`: \{ `allDay`: `boolean` = false; `attendees`: \{ `_id`: `string` = 'user1' \}[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: \{ `_id`: `string` = 'org1'; `members`: \{ `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \}[] \} ; `projects`: \{ `_id`: `string` = 'project1'; `description`: `string` = 'Project Description 1'; `tasks`: \{ `_id`: `string` = 'task1'; `completed`: `boolean` = false; `deadline`: `string` = '22/12/23'; `description`: `string` = 'Description 1'; `title`: `string` = 'Task 1'; `volunteers`: `never`[] = [] \}[] ; `title`: `string` = 'Project 1' \}[] ; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' \} \} \} \}[] #### Defined in @@ -35,7 +35,7 @@ ___ ### queryMockWithTime -• `Const` **queryMockWithTime**: { `request`: { `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: { `event`: { `allDay`: `boolean` = false; `attendees`: { `_id`: `string` = 'user1' }[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: { `_id`: `string` = 'org1'; `members`: { `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' }[] } ; `projects`: `never`[] = []; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' } } } }[] +• `Const` **queryMockWithTime**: \{ `request`: \{ `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: \{ `id`: `string` = 'event123' \} \} ; `result`: \{ `data`: \{ `event`: \{ `allDay`: `boolean` = false; `attendees`: \{ `_id`: `string` = 'user1' \}[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: `string` = '09:00:00'; `location`: `string` = 'India'; `organization`: \{ `_id`: `string` = 'org1'; `members`: \{ `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \}[] \} ; `projects`: `never`[] = []; `startDate`: `string` = '1/1/23'; `startTime`: `string` = '08:00:00'; `title`: `string` = 'Event Title' \} \} \} \}[] #### Defined in @@ -45,7 +45,7 @@ ___ ### queryMockWithoutTime -• `Const` **queryMockWithoutTime**: { `request`: { `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: { `id`: `string` = 'event123' } } ; `result`: { `data`: { `event`: { `allDay`: `boolean` = false; `attendees`: { `_id`: `string` = 'user1' }[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: ``null`` = null; `location`: `string` = 'India'; `organization`: { `_id`: `string` = 'org1'; `members`: { `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' }[] } ; `projects`: `never`[] = []; `startDate`: `string` = '1/1/23'; `startTime`: ``null`` = null; `title`: `string` = 'Event Title' } } } }[] +• `Const` **queryMockWithoutTime**: \{ `request`: \{ `query`: `DocumentNode` = EVENT\_DETAILS; `variables`: \{ `id`: `string` = 'event123' \} \} ; `result`: \{ `data`: \{ `event`: \{ `allDay`: `boolean` = false; `attendees`: \{ `_id`: `string` = 'user1' \}[] ; `description`: `string` = 'Event Description'; `endDate`: `string` = '2/2/23'; `endTime`: ``null`` = null; `location`: `string` = 'India'; `organization`: \{ `_id`: `string` = 'org1'; `members`: \{ `_id`: `string` = 'user1'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \}[] \} ; `projects`: `never`[] = []; `startDate`: `string` = '1/1/23'; `startTime`: ``null`` = null; `title`: `string` = 'Event Title' \} \} \} \}[] #### Defined in diff --git a/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail.md b/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail.md index 775b3e0dcd..7c265792b9 100644 --- a/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail.md +++ b/talawa-admin-docs/modules/screens_MemberDetail_MemberDetail.md @@ -14,18 +14,18 @@ ### default -▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`<`any`, `any`\> +▸ **default**(`props`, `context?`): ``null`` \| `ReactElement`\<`any`, `any`\> #### Parameters | Name | Type | | :------ | :------ | -| `props` | `PropsWithChildren`<`MemberDetailProps`\> | +| `props` | `PropsWithChildren`\<`MemberDetailProps`\> | | `context?` | `any` | #### Returns -``null`` \| `ReactElement`<`any`, `any`\> +``null`` \| `ReactElement`\<`any`, `any`\> #### Defined in diff --git a/talawa-admin-docs/modules/screens_OrgList_OrgListMocks.md b/talawa-admin-docs/modules/screens_OrgList_OrgListMocks.md index 3cee071055..c131c3224e 100644 --- a/talawa-admin-docs/modules/screens_OrgList_OrgListMocks.md +++ b/talawa-admin-docs/modules/screens_OrgList_OrgListMocks.md @@ -14,7 +14,7 @@ ### MOCKS -• `Const` **MOCKS**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` } ; `result`: { `data`: { `organizationsConnection`: `InterfaceOrgConnectionInfoType`[] = organizations } } } \| { `request`: { `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: { `id`: `string` = '123' } } ; `result`: { `data`: `InterfaceUserType` = superAdminUser } })[] +• `Const` **MOCKS**: (\{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` \} ; `result`: \{ `data`: \{ `organizationsConnection`: `InterfaceOrgConnectionInfoType`[] = organizations \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: \{ `id`: `string` = '123' \} \} ; `result`: \{ `data`: `InterfaceUserType` = superAdminUser \} \})[] #### Defined in @@ -24,7 +24,7 @@ ___ ### MOCKS\_ADMIN -• `Const` **MOCKS\_ADMIN**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` } ; `result`: { `data`: { `organizationsConnection`: `InterfaceOrgConnectionInfoType`[] = organizations } } } \| { `request`: { `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: { `id`: `string` = '123' } } ; `result`: { `data`: `InterfaceUserType` = adminUser } })[] +• `Const` **MOCKS\_ADMIN**: (\{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` \} ; `result`: \{ `data`: \{ `organizationsConnection`: `InterfaceOrgConnectionInfoType`[] = organizations \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: \{ `id`: `string` = '123' \} \} ; `result`: \{ `data`: `InterfaceUserType` = adminUser \} \})[] #### Defined in @@ -34,7 +34,7 @@ ___ ### MOCKS\_EMPTY -• `Const` **MOCKS\_EMPTY**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` } ; `result`: { `data`: { `organizationsConnection`: `never`[] = [] } } } \| { `request`: { `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: { `id`: `string` = '123' } } ; `result`: { `data`: `InterfaceUserType` = superAdminUser } })[] +• `Const` **MOCKS\_EMPTY**: (\{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_CONNECTION\_LIST; `variables?`: `undefined` \} ; `result`: \{ `data`: \{ `organizationsConnection`: `never`[] = [] \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = USER\_ORGANIZATION\_LIST; `variables`: \{ `id`: `string` = '123' \} \} ; `result`: \{ `data`: `InterfaceUserType` = superAdminUser \} \})[] #### Defined in diff --git a/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md b/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md index eeee46963b..f14ce241a3 100644 --- a/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md +++ b/talawa-admin-docs/modules/screens_OrganizationDashboard_OrganizationDashboardMocks.md @@ -14,7 +14,7 @@ ### MOCKS\_NO\_TAGS -• `Const` **MOCKS\_NO\_TAGS**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATIONS\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations`: { `_id`: `number` = 1; `admins`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `blockedUsers`: { `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' } ; `creator`: { `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' } ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = ''; `location`: `string` = 'New Delhi'; `members`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `membershipRequests`: { `_id`: `string` = '456'; `user`: { `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' } } ; `name`: `string` = 'Dummy Organization'; `spamCount`: { `_id`: `string` = '6954'; `groupchat`: { `_id`: `string` = '321'; `title`: `string` = 'Dummy' } ; `isReaded`: `boolean` = false; `user`: { `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' } }[] }[] ; `postsByOrganization?`: `undefined` } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: { `_id`: `number` = 1; `creator`: { `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' }[] } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST } ; `result`: { `data`: { `eventsByOrganization`: { `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' }[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` } } })[] +• `Const` **MOCKS\_NO\_TAGS**: (\{ `request`: \{ `query`: `DocumentNode` = ORGANIZATIONS\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization?`: `undefined` ; `organizations`: \{ `_id`: `number` = 1; `admins`: \{ `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `blockedUsers`: \{ `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' \} ; `creator`: \{ `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' \} ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = ''; `location`: `string` = 'New Delhi'; `members`: \{ `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `membershipRequests`: \{ `_id`: `string` = '456'; `user`: \{ `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' \} \} ; `name`: `string` = 'Dummy Organization'; `spamCount`: \{ `_id`: `string` = '6954'; `groupchat`: \{ `_id`: `string` = '321'; `title`: `string` = 'Dummy' \} ; `isReaded`: `boolean` = false; `user`: \{ `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' \} \}[] \}[] ; `postsByOrganization?`: `undefined` \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: \{ `_id`: `number` = 1; `creator`: \{ `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' \}[] \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization`: \{ `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' \}[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` \} \} \})[] #### Defined in @@ -24,7 +24,7 @@ ___ ### MOCKS\_WITHOUT\_IMAGE -• `Const` **MOCKS\_WITHOUT\_IMAGE**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATIONS\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations`: { `_id`: `number` = 1; `admins`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `blockedUsers`: { `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' } ; `creator`: { `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' } ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = ''; `location`: `string` = 'New Delhi'; `members`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `membershipRequests`: { `_id`: `string` = '456'; `user`: { `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' } } ; `name`: `string` = 'Dummy Organization'; `spamCount`: { `_id`: `string` = '6954'; `groupchat`: { `_id`: `string` = '321'; `title`: `string` = 'Dummy' } ; `isReaded`: `boolean` = false; `user`: { `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' } }[] }[] ; `postsByOrganization?`: `undefined` ; `removeOrganization?`: `undefined` } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: { `_id`: `number` = 1; `creator`: { `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' }[] ; `removeOrganization?`: `undefined` } } } \| { `request`: { `query`: `DocumentNode` = DELETE\_ORGANIZATION\_MUTATION } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` ; `removeOrganization`: { `_id`: `number` = 1 }[] } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST } ; `result`: { `data`: { `eventsByOrganization`: { `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' }[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` ; `removeOrganization?`: `undefined` } } })[] +• `Const` **MOCKS\_WITHOUT\_IMAGE**: (\{ `request`: \{ `query`: `DocumentNode` = ORGANIZATIONS\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization?`: `undefined` ; `organizations`: \{ `_id`: `number` = 1; `admins`: \{ `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `blockedUsers`: \{ `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' \} ; `creator`: \{ `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' \} ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = ''; `location`: `string` = 'New Delhi'; `members`: \{ `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `membershipRequests`: \{ `_id`: `string` = '456'; `user`: \{ `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' \} \} ; `name`: `string` = 'Dummy Organization'; `spamCount`: \{ `_id`: `string` = '6954'; `groupchat`: \{ `_id`: `string` = '321'; `title`: `string` = 'Dummy' \} ; `isReaded`: `boolean` = false; `user`: \{ `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' \} \}[] \}[] ; `postsByOrganization?`: `undefined` ; `removeOrganization?`: `undefined` \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: \{ `_id`: `number` = 1; `creator`: \{ `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' \}[] ; `removeOrganization?`: `undefined` \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = DELETE\_ORGANIZATION\_MUTATION \} ; `result`: \{ `data`: \{ `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` ; `removeOrganization`: \{ `_id`: `number` = 1 \}[] \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization`: \{ `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' \}[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` ; `removeOrganization?`: `undefined` \} \} \})[] #### Defined in @@ -34,7 +34,7 @@ ___ ### MOCKS\_WITH\_IMAGE -• `Const` **MOCKS\_WITH\_IMAGE**: ({ `request`: { `query`: `DocumentNode` = ORGANIZATIONS\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations`: { `_id`: `number` = 1; `admins`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `blockedUsers`: { `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' } ; `creator`: { `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' } ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = 'https://via.placeholder.com/200x200'; `location`: `string` = 'New Delhi'; `members`: { `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `membershipRequests`: { `_id`: `string` = '456'; `user`: { `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' } } ; `name`: `string` = 'Dummy Organization'; `spamCount`: { `_id`: `string` = '6954'; `groupchat`: { `_id`: `string` = '321'; `title`: `string` = 'Dummy' } ; `isReaded`: `boolean` = false; `user`: { `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' } }[] }[] ; `postsByOrganization?`: `undefined` } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST } ; `result`: { `data`: { `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: { `_id`: `number` = 1; `creator`: { `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' } ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' }[] } } } \| { `request`: { `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST } ; `result`: { `data`: { `eventsByOrganization`: { `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' }[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` } } })[] +• `Const` **MOCKS\_WITH\_IMAGE**: (\{ `request`: \{ `query`: `DocumentNode` = ORGANIZATIONS\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization?`: `undefined` ; `organizations`: \{ `_id`: `number` = 1; `admins`: \{ `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `blockedUsers`: \{ `_id`: `string` = '789'; `email`: `string` = 'stevesmith@gmail.com'; `firstName`: `string` = 'Steve'; `lastName`: `string` = 'Smith' \} ; `creator`: \{ `email`: `string` = ''; `firstName`: `string` = ''; `lastName`: `string` = '' \} ; `description`: `string` = 'This is a Dummy Organization'; `image`: `string` = 'https://via.placeholder.com/200x200'; `location`: `string` = 'New Delhi'; `members`: \{ `_id`: `string` = '123'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `membershipRequests`: \{ `_id`: `string` = '456'; `user`: \{ `email`: `string` = 'samsmith@gmail.com'; `firstName`: `string` = 'Sam'; `lastName`: `string` = 'Smith' \} \} ; `name`: `string` = 'Dummy Organization'; `spamCount`: \{ `_id`: `string` = '6954'; `groupchat`: \{ `_id`: `string` = '321'; `title`: `string` = 'Dummy' \} ; `isReaded`: `boolean` = false; `user`: \{ `_id`: `string` = '878'; `email`: `string` = 'joeroot@gmail.com'; `firstName`: `string` = 'Joe'; `lastName`: `string` = 'Root' \} \}[] \}[] ; `postsByOrganization?`: `undefined` \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_POST\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization?`: `undefined` ; `organizations?`: `undefined` ; `postsByOrganization`: \{ `_id`: `number` = 1; `creator`: \{ `_id`: `string` = '583'; `email`: `string` = 'johndoe@gmail.com'; `firstName`: `string` = 'John'; `lastName`: `string` = 'Doe' \} ; `imageUrl`: `string` = ''; `text`: `string` = 'Capture Jinchuriki'; `title`: `string` = 'Akatsuki'; `videoUrl`: `string` = '' \}[] \} \} \} \| \{ `request`: \{ `query`: `DocumentNode` = ORGANIZATION\_EVENT\_LIST \} ; `result`: \{ `data`: \{ `eventsByOrganization`: \{ `_id`: `number` = 1; `allDay`: `boolean` = false; `description`: `string` = 'Event Test'; `endDate`: `string` = ''; `endTime`: `string` = '06:00'; `isPublic`: `boolean` = true; `isRegisterable`: `boolean` = true; `location`: `string` = 'New Delhi'; `recurring`: `boolean` = false; `startDate`: `string` = ''; `startTime`: `string` = '02:00'; `title`: `string` = 'Event' \}[] ; `organizations?`: `undefined` ; `postsByOrganization?`: `undefined` \} \} \})[] #### Defined in