diff --git a/.env.local_dev b/.env.local_dev index 2303bf980..93eff6132 100644 --- a/.env.local_dev +++ b/.env.local_dev @@ -52,7 +52,7 @@ SMTP_ENABLE= SMTP_HOST=smtp.yourhost.com SMTP_PORT=443 SMTP_USER_EMAIL=mailer@yourdomain.com -SMTP_PASS=password +SMTP_PASS=password # if your password includes spaces then write password in single quotes ('asdf pasd asdf bgds'). # Base64 encoded PFX or p12 document signing certificate file ********************************************************************************************************************* diff --git a/.github/workflows/Docker.yml b/.github/workflows/Docker.yml index f61d435ce..79ef3aa8a 100644 --- a/.github/workflows/Docker.yml +++ b/.github/workflows/Docker.yml @@ -2,7 +2,7 @@ name: ci on: push: branches: - - 'main' + - 'staging' jobs: docker: @@ -11,9 +11,9 @@ jobs: matrix: include: - image: amolshejole/OpenSign - dockerfile: apps/OpenSign/Dockerfile + dockerfile: apps/OpenSign/Dockerhubfile - image: amolshejole/OpenSignServer - dockerfile: apps/OpenSignServer/Dockerfile + dockerfile: apps/OpenSignServer/Dockerhubfile steps: - name: Checkout @@ -31,8 +31,11 @@ jobs: with: images: ${{ matrix.image }} - - name: Debug - List files + name: Debug - List files opensign run: ls -R apps/OpenSign/ # Adjust the path as needed + - + name: Debug - List files opensignserver + run: ls -R apps/OpenSignServer/ # Adjust the path as needed - name: Build and push uses: docker/build-push-action@v4 diff --git a/INSTALLATION.md b/INSTALLATION.md index c04dbd92c..f0ae591eb 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -1,149 +1,29 @@ -# INSTALLATON INSTRUCTIONS +# INSTALLATON INSTRUCTIONS HAS A NEW HOME -You can use our app as a cloud version from [OpenSignLabs](https://www.opensignlabs.com) +We've updated our installation instructions and moved them to our dedicated documentation portal to provide you with a better experience and updated guidance. Whether you're looking to self-host OpenSign™ or contribute to its development, you can find detailed instructions tailored to your needs at [docs.opensignlabs.com](https://docs.opensignlabs.com). -or follow below instructions to install it on your own infrastructure. +## Self Hosting -- Localhost(Frontend only) -- Digital Ocean -- Localhost(Docker) +If you're interested in self-hosting OpenSign™, our new documentation portal provides comprehensive, step-by-step instructions to help you set up OpenSign™ in your own environment. This section is designed for system administrators and those looking to deploy OpenSign™ within their organization or for personal use. -## Localhost(Frontend only) +- **Access Self Hosting Instructions:** [Self Hosting Guide](https://docs.opensignlabs.com/docs/category/docker) -This is the easiest way to run the frontend application for development or testing purpose without the hassle of installing backend & DB. All the features including document upload, signing, email notifications will work seamlessly from staging backend. +## Contributors -**Warning:** All data, including user accounts and documents, is stored in the staging backend. This data will be erased every time there is a merge to the main branch. As a result, you may need to recreate user accounts repeatedly. If you find that login attempts are failing, it is likely because the data has been cleared due to a recent merge. +For developers and contributors who are looking to build upon or contribute to OpenSign™, we've prepared a separate section that covers the setup, development environment configuration, and guidelines for contributing to the OpenSign™ project. -Below are the steps to follow - -- [Clone the repository](https://help.github.com/articles/cloning-a-repository/) to your local machine using below command - - ``` - git clone https://github.com/OpenSignLabs/OpenSign.git - ``` -- Copy the .env.frontend_dev file to apps/OpenSign/.env using below command(on mac & linux). For windows use COPY command instead. - ``` - cp .env.frontend_dev apps/OpenSign/.env - ``` -- CD to /apps/OpenSign directory -- Install NPM packages using - ``` - npm install - ``` -- Run the project locally using - ``` - npm run start - ``` -You should be able to access the application from http://localhost:3000 after this. -Create an account by signing-up and start contributing. +- **Access Contributor Instructions:** [Contributors Guide](https://docs.opensignlabs.com/docs/contribute/INSTALLATION) +## Additional Resources -## Digital Ocean +Should you need further assistance or have any questions, please feel free to reach out to us through our support channels: -OpenSign application consistes of 3 components - -- ReactJS frontend -- NodeJS API -- MongoDB database +- **Twitter:** [OpenSignHQ on Twitter](https://twitter.com/OpenSignHQ) +- **Facebook:** [OpenSign on Facebook](https://www.facebook.com/profile.php?id=61551030403669) +- **LinkedIn:** [OpenSign™ on LinkedIn](https://www.linkedin.com/company/opensign%E2%84%A2/) +- **Discord:** [Join our Discord Community](https://discord.com/invite/opensign) +- **YouTube:** [OpenSignHQ on YouTube](https://www.youtube.com/@opensignhq) -You can install all 3 components on digital ocean using the button below - +We are committed to providing you with the support you need to successfully install and use OpenSign™. Visit our website at [www.opensignlabs.com](https://www.opensignlabs.com) for more information about our project and its features. -[![Deploy on DigitalOcean](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/OpenSignLabs/Deploy-OpenSign-to-Digital-Ocean/tree/main&refcode=30db1c901ab0) - -## You will need to create an AWS S3 bucket or digital ocean space in order to store your uploaded documents - -### AWS S3 - -- Step 1 : Create a S3 bucket - - Login to AWS console - - Navigate to S3 under services - - Hit "Create Bucket" button on upper right corner - - Remove the check from "block all public access" checkbox(we need this in order to provide access to not-logged in users after OTP verification) - - Set bucket versioning and tags as per your requirements - - Hit "Create bucket" button -- Step 2 : Create IAM user and provide access to AWS bucket - - Search for "IAM" on the search bar in AWS console - - On IAM dashboard, click the number of users(count) under IAM resources table - - Hit "create user" button on the upper right corner of the page - - Enter the user name & click next - - Click create policy, search for S3 and provide the Read, Write & list permissions - - Click next and click "Create user" - - Step 3 : Generate Credentials - - Go to IAM/Users in AWS console - - Hit the hyperlink for the user created in the previous step - - Click the "Security credentials" tab - - Scroll down to "Access keys" and hit "Create access key" - - In the next step select "Application running outside AWS" - - Add a description tag if needed & hit "Create access key" - - In the next step you will see "Access key" and "Secret Access key". Copy both the values. - - Set the value of "Access key" to "DO_ACCESS_KEY_ID" environment variable - - Set the value of "Secret Access key" to "DO_SECRET_ACCESS_KEY" environment variable -- Step 3 : Copy bucket credentials - - Visit "Amazon S3 -> Buckets" in aws console - - Click the bucket created in previous steps & visit the properties tab - - Under "Bucket overview" you will find the value of AWS region(for ex. ap-south-1). Set that value to env variable "DO_REGION" - - You can create the value for "DO_ENDPOINT" env variable by appending the region value to amazonaws.com (for ex. s3.ap-south-1.amazonaws.com) - - You can create the value for "DO_BASEURL" by adding the bucketname in front of the endpoint value(for ex. https://bucketname.s3.ap-south-1.amazonaws.com) - - Visit below link if you face any issues while following the above instructions - - - https://repost.aws/knowledge-center/create-access-key - - -## Localhost(Docker) - -For local Setup we need to need following prerequisite: - -Environment Varaibles: - -| Environment Varibale | Value | Description | -| ------------- | ------------- | ------------- | -| CI | false | Set CI to false while running the app locally | -| PUBLIC_URL | http://localhost:3000 | Set it to the URL form where the app home page will be accessed | -| GENERATE_SOURCEMAP | false | Set it to true if you want to generate the Sourcemap for debugging | -| REACT_APP_SERVERURL | http://localhost:8080/app | Set it to the URL from where APIs will be accessible, for local development it should be localhost:3000/api/app (use your local port number instead) | -| REACT_APP_APPID | opensignstgn | A 12 character long random app identifier. The value of this should be same as APP_ID which is a variable used by backend API. | -| APP_ID | opensignstgn | A 12 character long random app identifier. The value of this should be same as REACT_APP_APPID which is a variable used by Frontend React App. | -| appName | open_sign_server | Name of the app. It will be visible in the verification emails sent out. | -| MASTER_KEY | XnAadwKxxByMr | A 12 character long random secret key that allows access to all the data. It is used in Parse dashboard config to view all the data in the database. | -| MONGODB_URI | mongodb://host.docker.internal:27017/OpenSignDB | Mongodb URI to connect to | -| PARSE_MOUNT |/app | Path on which APIs should be mounted. Do not change this. This variable shall be removed & value hardcoded in the source code in coming versions. | -| SERVER_URL | http://127.0.0.1:8080/app | Set it to the URL from where APIs will be accessible to the NodeJS functions, for local development it should be localhost:3000/api/app (use your local port number instead) | -| DO_SPACE | DOSPACENAME | Digital ocean space name or AWS S3 bucket name for uploading documents | -| DO_ENDPOINT | ams3.digitaloceanspaces.com | Digital ocean spaces endpoint or AWS S3 endpoint for uploading documents | -| DO_BASEURL |https://DOSPACENAME.ams3.digitaloceanspaces.com | Digital ocean baseurl or AWS S3 base URL | -| DO_ACCESS_KEY_ID | YOUR_S3_ACCESS_ID | Digital ocean spaces access key ID or AWS s3 Access key ID for uploading the docs | -| DO_SECRET_ACCESS_KEY | YOUR_S3_ACCESS_KEY | Digital ocean spaces secret access key or AWS s3 secret access key for uploading the docs | -| DO_REGION | YOUR_S3_REGION | Digital ocean spaces region or AWS s3 region | -| USE_LOCAL | FALSE | To use local file storage to save file | -| MAILGUN_API_KEY | YOUR_MAILGUNAPI_KEY | Mailgun API Key | -| MAILGUN_DOMAIN | YOUR_MAILGUNAPI_DOMAIN | Mailgun API Domain | -| MAILGUN_SENDER | - | Mailgun Sender Mail ID | -| PFX_BASE64 | - | Base64 encoded PFX or p12 document signing certificate file. You can generate base64 encoded self sign certificate using the passphrase `emudhra` | - -# Steps to Generate Self Sign Certificate -``` -# execute below command and use passphrase emudhra -openssl genrsa -des3 -out ./cert/local_dev.key 2048 -openssl req -key ./cert/local_dev.key -new -x509 -days 365 -out ./cert/local_dev.crt -openssl pkcs12 -inkey ./cert/local_dev.key -in ./cert/local_dev.crt -export -out ./cert/local_dev.pfx -openssl base64 -in ./cert/local_dev.pfx -out ./cert/base64_pfx -``` - -# CORS Configuration - -As document storage is delegated to S3-compatible services that reside in a different host than the OpenSign one, document operations (loading, storing, deleting) are subject to [Cross-Origin Resource Sharing](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) restriction policies; as a consequence, OpenSign app may fail with (browser console) errors like the following: -``` -Access to fetch at 'https://foo.nyc3.digitaloceanspaces.com/exported_file_4627_0000-00-00T00%3A45%3A43.344Z.pdf' -from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header -is present on the requested resource. If an opaque response serves your needs, set the request's mode to -'no-cors' to fetch the resource with CORS disabled. -``` - -In order to address this, your document storage system must be instructed to accept requests from other hosts; below the relevant documentation links: -- [How to Configure CORS on DigitalOcean Spaces](https://docs.digitalocean.com/products/spaces/how-to/configure-cors/) -- [Configuring cross-origin resource sharing on AWS S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html) - -# Build Local Environment - -Command to build project - -- Execute `make build` - -Command to run project - -- Execute `make run` \ No newline at end of file diff --git a/README.md b/README.md index 9c5d5b378..7a3ad6656 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,11 @@ 7. [Acknowledgments](#acknowledgments) --- +Please star ⭐ the repo to support us! 😀 ### Introduction -Welcome to OpenSign, an open-source document e-signing solution designed to provide a secure, reliable, and free alternative to commercial platforms like DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, HelloSign & Zoho sign. Developed under the OpenSignLabs organization, our mission is to democratize the e-signing process, making it accessible and straightforward for everyone. +Welcome to OpenSign, the premier open-source docusign alternative - document e-signing solution designed to provide a secure, reliable, and free alternative to commercial platforms like DocuSign, PandaDoc, SignNow, Adobe Sign, Smartwaiver, SignRequest, HelloSign & Zoho sign. Developed under the OpenSignLabs organization, our mission is to democratize the e-signing process, making it accessible and straightforward for everyone. --- diff --git a/apps/OpenSign/Dockerfile b/apps/OpenSign/Dockerfile index 57c815846..051503d52 100644 --- a/apps/OpenSign/Dockerfile +++ b/apps/OpenSign/Dockerfile @@ -1,5 +1,5 @@ # Use an official Node runtime as the base image -FROM node:16 +FROM node:18 # Set the working directory inside the container WORKDIR /usr/src/app diff --git a/apps/OpenSign/Dockerhubfile b/apps/OpenSign/Dockerhubfile new file mode 100644 index 000000000..3140d538f --- /dev/null +++ b/apps/OpenSign/Dockerhubfile @@ -0,0 +1,25 @@ +# Use an official Node runtime as the base image +FROM node:18 + +# Set the working directory inside the container +WORKDIR /usr/src/app + +# Copy package.json and package-lock.json first to leverage Docker cache +COPY apps/OpenSign/package*.json ./ + +# Install application dependencies +RUN npm install + +# Copy the current directory contents into the container +COPY apps/OpenSign/ . +COPY microfrontends/ . +COPY apps/OpenSign/.husky . + +# Make port 3000 available to the world outside this container +EXPOSE 3000 + +# Define environment variables if needed +# ENV NODE_ENV production + +# Run the application +CMD ["npm", "start"] diff --git a/apps/OpenSign/moduleFederation.config.js b/apps/OpenSign/moduleFederation.config.js index 5324d4c8c..9ba314cd1 100644 --- a/apps/OpenSign/moduleFederation.config.js +++ b/apps/OpenSign/moduleFederation.config.js @@ -20,10 +20,6 @@ module.exports = { "react-router-dom": { singleton: true, requiredVersion: dependencies["react-router-dom"] - }, - "rjsf-conditionals": { - singleton: true, - requiredVersion: dependencies["rjsf-conditionals"] } } }; diff --git a/apps/OpenSign/package-lock.json b/apps/OpenSign/package-lock.json index 4832ae0ee..d72a03ae5 100644 --- a/apps/OpenSign/package-lock.json +++ b/apps/OpenSign/package-lock.json @@ -9,18 +9,15 @@ "version": "0.1.0", "dependencies": { "@reduxjs/toolkit": "^1.9.7", - "@rjsf/core": "^5.13.0", - "@rjsf/utils": "^5.13.0", - "@rjsf/validator-ajv8": "^5.13.0", - "axios": "^1.5.1", + "axios": "^1.6.0", "daisyui": "^3.9.2", "file-saver": "^2.0.5", "html-react-parser": "^4.2.2", "json-rules-engine-simplified": "^0.1.17", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "mf-cra": "^0.0.5", "moment": "^2.29.4", - "parse": "^4.2.0", + "parse": "^4.3.1", "react": "^18.2.0", "react-bootstrap": "^2.9.0", "react-dnd": "^16.0.1", @@ -39,20 +36,19 @@ "reactour": "^1.19.2", "redux": "^4.2.1", "redux-thunk": "^2.4.2", - "rjsf-conditionals": "github:prafullnavkar-nxg/rjsf-conditionals", "serve": "^14.2.1", "styled-components": "^4.4.1", "web-vitals": "^2.1.4" }, "devDependencies": { - "@babel/runtime-corejs2": "^7.23.2", + "@babel/runtime-corejs2": "^7.23.9", "autoprefixer": "^10.4.16", "commitizen": "^4.3.0", "eslint": "^8.51.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.33.2", - "lint-staged": "^15.0.1", - "postcss": "^8.4.31", + "lint-staged": "^15.2.2", + "postcss": "^8.4.35", "prettier": "^2.8.0", "pretty-quick": "^3.1.3", "tailwindcss": "^3.3.3" @@ -90,11 +86,11 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -180,11 +176,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -463,9 +459,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } @@ -513,9 +509,9 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -526,9 +522,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1986,9 +1982,9 @@ } }, "node_modules/@babel/runtime-corejs2": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.23.2.tgz", - "integrity": "sha512-lTwRWGcAUBANnxD0A4c5/wKQ0eLhgdAy9kdY2rzTmmliumBQ8u8awykMnaQAnZR3PC47jLRjGoj+hozZqy9Bww==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.23.9.tgz", + "integrity": "sha512-lwwDy5QfMkO2rmSz9AvLj6j2kWt5a4ulMi1t21vWQEO0kNCFslHoszat8reU/uigIQSUDF31zraZG/qMkcqAlw==", "dev": true, "dependencies": { "core-js": "^2.6.12", @@ -1999,22 +1995,17 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz", - "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.23.2.tgz", + "integrity": "sha512-54cIh74Z1rp4oIjsHjqN+WM4fMyCBYe+LpZ9jWm51CZ1fbH3SkAzQD/3XLoNkjbJ7YEmjobLXyvQrFypRHOrXw==", "dependencies": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.11" + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/runtime-corejs3/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, "node_modules/@babel/template": { "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", @@ -2029,19 +2020,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", - "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -2049,11 +2040,11 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -3921,85 +3912,6 @@ "react": ">=16.14.0" } }, - "node_modules/@rjsf/core": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@rjsf/core/-/core-5.13.0.tgz", - "integrity": "sha512-rCpJGR0yPP/ip9LKcr3SmDMkbLx4QIaRA+ag0rcalSw1XLXBSzh53SpfgaB2HN++1xhUvWtIUERRHpWjQp1E7w==", - "dependencies": { - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "markdown-to-jsx": "^7.3.2", - "nanoid": "^3.3.6", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@rjsf/utils": "^5.12.x", - "react": "^16.14.0 || >=17" - } - }, - "node_modules/@rjsf/utils": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@rjsf/utils/-/utils-5.13.0.tgz", - "integrity": "sha512-tG2OuOJUJZ0W7VMZceD0I2SOjfMRRT1tRtG+SKbdNqhtH/gpg40aOMUj9cWgSQnYISEkNZjZq/z7NWln5RxW6A==", - "dependencies": { - "json-schema-merge-allof": "^0.8.1", - "jsonpointer": "^5.0.1", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "react-is": "^18.2.0" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^16.14.0 || >=17" - } - }, - "node_modules/@rjsf/utils/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, - "node_modules/@rjsf/validator-ajv8": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.13.0.tgz", - "integrity": "sha512-8j0xLsxJA/k1UADeDYZ2aMVrswvOCEYNC++YchoAgWRHqDiaGAUyRbbk7oxMi6QUXnhnlCIepzNeTclHnSfPXQ==", - "dependencies": { - "ajv": "^8.12.0", - "ajv-formats": "^2.1.1", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@rjsf/utils": "^5.12.x" - } - }, - "node_modules/@rjsf/validator-ajv8/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@rjsf/validator-ajv8/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -5612,9 +5524,9 @@ } }, "node_modules/axios": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", - "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -6675,16 +6587,16 @@ } }, "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "dependencies": { "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "string-width": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6702,18 +6614,24 @@ "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==", + "dev": true + }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6965,27 +6883,6 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/compute-gcd": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.1.tgz", - "integrity": "sha512-TwMbxBNz0l71+8Sc4czv13h4kEqnchV9igQZBi6QUaz09dnz13juGnnaWWJTRsP3brxOoxeB4SA2WELLw1hCtg==", - "dependencies": { - "validate.io-array": "^1.0.3", - "validate.io-function": "^1.0.2", - "validate.io-integer-array": "^1.0.0" - } - }, - "node_modules/compute-lcm": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.2.tgz", - "integrity": "sha512-OFNPdQAXnQhDSKioX8/XYT6sdUlXwpeMjfd6ApxMJfyZ4GxmLR1xvMERctlYhlHwIiz6CSpBc2+qYKjHGZw4TQ==", - "dependencies": { - "compute-gcd": "^1.2.1", - "validate.io-array": "^1.0.3", - "validate.io-function": "^1.0.2", - "validate.io-integer-array": "^1.0.0" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -7132,9 +7029,9 @@ } }, "node_modules/crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", "optional": true }, "node_modules/crypto-random-string": { @@ -7676,14 +7573,6 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, - "node_modules/deepcopy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/deepcopy/-/deepcopy-2.1.0.tgz", - "integrity": "sha512-8cZeTb1ZKC3bdSCP6XOM1IsTczIO73fdqtwa2B0N15eAz7gmyhQo+mc5gnFuulsgN3vIQYmTgbmQVKalH1dKvQ==", - "dependencies": { - "type-detect": "^4.0.8" - } - }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -9505,9 +9394,9 @@ "integrity": "sha512-bHWEmjLsTjGP9gVs7P3Hyl+oY5NlMW8aTSPdTJ+X2GKt6glDctt9fUCLbRV+d/l8NDC40+FxMjp9WlTQXaQALw==" }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", @@ -9810,6 +9699,18 @@ "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==", + "dev": true, + "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", @@ -10506,12 +10407,9 @@ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" }, "node_modules/idb-keyval": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz", - "integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==", - "dependencies": { - "safari-14-idb-fix": "^3.0.0" - } + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", + "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" }, "node_modules/identity-obj-proxy": { "version": "3.0.0", @@ -13418,27 +13316,6 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, - "node_modules/json-schema-compare": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz", - "integrity": "sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==", - "dependencies": { - "lodash": "^4.17.4" - } - }, - "node_modules/json-schema-merge-allof": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.8.1.tgz", - "integrity": "sha512-CTUKmIlPJbsWfzRRnOXz+0MjIqvnleIXwFTzz+t9T86HnYX/Rozria6ZVGLktAU9e+NygNljveP+yxqtQp/Q4w==", - "dependencies": { - "compute-lcm": "^1.1.2", - "json-schema-compare": "^0.2.2", - "lodash": "^4.17.20" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -13516,9 +13393,12 @@ } }, "node_modules/jwt-decode": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", - "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "engines": { + "node": ">=18" + } }, "node_modules/keyv": { "version": "4.5.4", @@ -13608,21 +13488,21 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/lint-staged": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.0.1.tgz", - "integrity": "sha512-2IU5OWmCaxch0X0+IBF4/v7sutpB+F3qoXbro43pYjQTOo5wumckjxoxn47pQBqqBsCWrD5HnI2uG/zJA7isew==", + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", "dev": true, "dependencies": { "chalk": "5.3.0", "commander": "11.1.0", "debug": "4.3.4", "execa": "8.0.1", - "lilconfig": "2.1.0", - "listr2": "7.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", "micromatch": "4.0.5", "pidtree": "0.6.0", "string-argv": "0.3.2", - "yaml": "2.3.2" + "yaml": "2.3.4" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -13711,6 +13591,15 @@ "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==", + "dev": true, + "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", @@ -13790,29 +13679,29 @@ } }, "node_modules/lint-staged/node_modules/yaml": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", - "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" } }, "node_modules/listr2": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-7.0.1.tgz", - "integrity": "sha512-nz+7hwgbDp8eWNoDgzdl4hA/xDSLrNRzPu1TLgOYs6l5Y+Ma6zVWWy9Oyt9TQFONwKoSPoka3H50D3vD5EuNwg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", "dev": true, "dependencies": { - "cli-truncate": "^3.1.0", + "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^5.0.1", + "log-update": "^6.0.0", "rfdc": "^1.3.0", - "wrap-ansi": "^8.1.0" + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/listr2/node_modules/ansi-regex": { @@ -13839,6 +13728,12 @@ "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==", + "dev": true + }, "node_modules/listr2/node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -13846,17 +13741,17 @@ "dev": true }, "node_modules/listr2/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -13878,17 +13773,17 @@ } }, "node_modules/listr2/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -13934,21 +13829,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, - "node_modules/lodash.isequalwith": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz", - "integrity": "sha512-dcZON0IalGBpRmJBmMkaoV7d3I80R2O+FrzsZyHdNSFrANq/cgDqKQNmAHE8UEj4+QYWwwhkQOVdLHiAopzlsQ==" - }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", @@ -14081,34 +13966,34 @@ } }, "node_modules/log-update": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", - "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", "dev": true, "dependencies": { - "ansi-escapes": "^5.0.0", + "ansi-escapes": "^6.2.0", "cli-cursor": "^4.0.0", - "slice-ansi": "^5.0.0", - "strip-ansi": "^7.0.1", - "wrap-ansi": "^8.0.1" + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, "dependencies": { - "type-fest": "^1.0.2" + "type-fest": "^3.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -14153,6 +14038,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/log-update/node_modules/restore-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", @@ -14169,18 +14075,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "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==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", + "dev": true, + "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" @@ -14202,29 +14124,29 @@ } }, "node_modules/log-update/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -14310,17 +14232,6 @@ "tmpl": "1.0.5" } }, - "node_modules/markdown-to-jsx": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.3.2.tgz", - "integrity": "sha512-B+28F5ucp83aQm+OxNrPkS8z0tMKaeHiy0lHJs3LqCyDQFtWuenaIrkaVTgAm1pf1AU85LXltva86hlaT17i8Q==", - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "react": ">= 0.14.0" - } - }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -14624,9 +14535,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -15128,14 +15039,14 @@ } }, "node_modules/parse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-4.2.0.tgz", - "integrity": "sha512-K8bWs0wM2qRhkSr6N16j8OvsF6Uallrynqng9e+tzR3RdKuB09vaJh48qrf9MbiJ1Ya4JZI7AfEHYF+ywEKs7Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/parse/-/parse-4.3.1.tgz", + "integrity": "sha512-ypLPhMPFsJY+C2MXg6HdrVu6ielsL+kUjcSqh7J01lPC5oBuLh70F9YMQSw51QBocEeMSVgB7eUorFOH+MkVpA==", "dependencies": { - "@babel/runtime-corejs3": "7.21.0", - "idb-keyval": "6.2.0", + "@babel/runtime-corejs3": "7.23.2", + "idb-keyval": "6.2.1", "react-native-crypto-js": "1.0.0", - "uuid": "9.0.0", + "uuid": "9.0.1", "ws": "8.13.0", "xmlhttprequest": "1.8.0" }, @@ -15143,7 +15054,7 @@ "node": ">=14.21.0 <17 || >=18 <20" }, "optionalDependencies": { - "crypto-js": "4.1.1" + "crypto-js": "4.2.0" } }, "node_modules/parse-json": { @@ -15173,9 +15084,13 @@ } }, "node_modules/parse/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -15445,9 +15360,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "funding": [ { "type": "opencollective", @@ -15463,7 +15378,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -18183,9 +18098,9 @@ } }, "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", "dev": true }, "node_modules/rimraf": { @@ -18202,26 +18117,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rjsf-conditionals": { - "version": "1.5.0", - "resolved": "git+ssh://git@github.com/prafullnavkar-nxg/rjsf-conditionals.git#439aa44e3ece077b1c8098278f86f454ad7185cf", - "license": "Apache-2.0", - "dependencies": { - "@rjsf/validator-ajv8": "^5.13.0", - "deepcopy": "^2.0.0", - "lodash.isequalwith": "^4.4.0", - "selectn": "^1.1.2" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@rjsf/core": ">=2.0.0", - "core-js": "^2.5.7", - "prop-types": "^15.7.2", - "react": "^18.2.0" - } - }, "node_modules/rollup": { "version": "2.79.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", @@ -18331,11 +18226,6 @@ "tslib": "^2.1.0" } }, - "node_modules/safari-14-idb-fix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/safari-14-idb-fix/-/safari-14-idb-fix-3.0.0.tgz", - "integrity": "sha512-eBNFLob4PMq8JA1dGyFn6G97q3/WzNtFK4RnzT1fnLq+9RyrGknzYiM/9B12MnKAxuj1IXr7UKYtTNtjyKMBog==" - }, "node_modules/safe-array-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", @@ -20423,38 +20313,6 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, - "node_modules/validate.io-array": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz", - "integrity": "sha512-DeOy7CnPEziggrOO5CZhVKJw6S3Yi7e9e65R1Nl/RTN1vTQKnzjfvks0/8kQ40FP/dsjRAOd4hxmJ7uLa6vxkg==" - }, - "node_modules/validate.io-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz", - "integrity": "sha512-LlFybRJEriSuBnUhQyG5bwglhh50EpTL2ul23MPIuR1odjO7XaMLFV8vHGwp7AZciFxtYOeiSCT5st+XSPONiQ==" - }, - "node_modules/validate.io-integer": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz", - "integrity": "sha512-22izsYSLojN/P6bppBqhgUDjCkr5RY2jd+N2a3DCAUey8ydvrZ/OkGvFPR7qfOpwR2LC5p4Ngzxz36g5Vgr/hQ==", - "dependencies": { - "validate.io-number": "^1.0.3" - } - }, - "node_modules/validate.io-integer-array": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz", - "integrity": "sha512-mTrMk/1ytQHtCY0oNO3dztafHYyGU88KL+jRxWuzfOmQb+4qqnWmI+gykvGp8usKZOM0H7keJHEbRaFiYA0VrA==", - "dependencies": { - "validate.io-array": "^1.0.3", - "validate.io-integer": "^1.0.4" - } - }, - "node_modules/validate.io-number": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz", - "integrity": "sha512-kRAyotcbNaSYoDnXvb4MHg/0a1egJdLwS6oJ38TJY7aw9n93Fl/3blIXdyYvPOp55CNxywooG/3BcrwNrBpcSg==" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/apps/OpenSign/package.json b/apps/OpenSign/package.json index d18085126..12d538ae8 100644 --- a/apps/OpenSign/package.json +++ b/apps/OpenSign/package.json @@ -4,18 +4,15 @@ "private": true, "dependencies": { "@reduxjs/toolkit": "^1.9.7", - "@rjsf/core": "^5.13.0", - "@rjsf/utils": "^5.13.0", - "@rjsf/validator-ajv8": "^5.13.0", - "axios": "^1.5.1", + "axios": "^1.6.0", "daisyui": "^3.9.2", "file-saver": "^2.0.5", "html-react-parser": "^4.2.2", "json-rules-engine-simplified": "^0.1.17", - "jwt-decode": "^3.1.2", + "jwt-decode": "^4.0.0", "mf-cra": "^0.0.5", "moment": "^2.29.4", - "parse": "^4.2.0", + "parse": "^4.3.1", "react": "^18.2.0", "react-bootstrap": "^2.9.0", "react-dnd": "^16.0.1", @@ -34,7 +31,6 @@ "reactour": "^1.19.2", "redux": "^4.2.1", "redux-thunk": "^2.4.2", - "rjsf-conditionals": "github:prafullnavkar-nxg/rjsf-conditionals", "serve": "^14.2.1", "styled-components": "^4.4.1", "web-vitals": "^2.1.4" @@ -45,6 +41,8 @@ "version": "curl -s https://api.github.com/repos/opensignlabs/opensign/releases/latest | grep '\"tag_name\":' | awk -F '\"' '{print $4}' > ./public/version.txt", "build": "npm run version && rm -rf public/mfbuild && npm run micro && CI=false && mf-cra build", "micro": "cd ../../microfrontends/SignDocuments && npm install && npm run build", + "docker-build": "npm run version && rm -rf public/mfbuild && npm run docker-micro && CI=false && mf-cra build", + "docker-micro": "cd ./SignDocuments && npm install && npm run docker-build", "test": "react-scripts test", "eject": "react-scripts eject", "release": "standard-version", @@ -74,14 +72,14 @@ } }, "devDependencies": { - "@babel/runtime-corejs2": "^7.23.2", + "@babel/runtime-corejs2": "^7.23.9", "autoprefixer": "^10.4.16", "commitizen": "^4.3.0", "eslint": "^8.51.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.33.2", - "lint-staged": "^15.0.1", - "postcss": "^8.4.31", + "lint-staged": "^15.2.2", + "postcss": "^8.4.35", "prettier": "^2.8.0", "pretty-quick": "^3.1.3", "tailwindcss": "^3.3.3" diff --git a/apps/OpenSign/public/version.txt b/apps/OpenSign/public/version.txt index e69de29bb..3c61df3f2 100644 --- a/apps/OpenSign/public/version.txt +++ b/apps/OpenSign/public/version.txt @@ -0,0 +1 @@ +v1.1.1-beta diff --git a/apps/OpenSign/src/App.js b/apps/OpenSign/src/App.js index cbfc5141a..c0920e2d7 100644 --- a/apps/OpenSign/src/App.js +++ b/apps/OpenSign/src/App.js @@ -7,7 +7,7 @@ import Signup from "./routes/Signup"; import Form from "./routes/Form"; import Report from "./routes/Report"; import Dashboard from "./routes/Dashboard"; -import PlanSubscriptions from "./routes/PlanSubscriptions"; +import Subscriptions from "./routes/PlanSubscriptions"; import HomeLayout from "./layout/HomeLayout"; import UserProfile from "./routes/UserProfile"; import PageNotFound from "./routes/PageNotFound"; @@ -15,7 +15,10 @@ import ForgetPassword from "./routes/ForgetPassword"; import ChangePassword from "./routes/ChangePassword"; import ReportMicroapp from "./components/ReportMicroapp"; import LoadMf from "./routes/LoadMf"; +import GenerateToken from "./routes/GenerateToken"; import ValidateRoute from "./primitives/ValidateRoute"; +import Webhook from "./routes/Webhook"; +import Validate from "./primitives/Validate"; function App() { const [isloading, setIsLoading] = useState(true); @@ -59,104 +62,34 @@ function App() { ) : ( - - - - } - /> - - - - } - /> + }> + } /> + } /> + + }> + } /> + } /> } /> {process.env.REACT_APP_ENABLE_SUBSCRIPTION && ( <> } /> - } - /> + } /> )} - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - -
- - } - /> - - - - } - /> - - - - } - /> - - - - - } - /> + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> - {/* } /> */} )} diff --git a/apps/OpenSign/src/components/AddUser.js b/apps/OpenSign/src/components/AddUser.js new file mode 100644 index 000000000..5861f6be6 --- /dev/null +++ b/apps/OpenSign/src/components/AddUser.js @@ -0,0 +1,283 @@ +import React, { useState } from "react"; +import Parse from "parse"; +import axios from "axios"; +import Title from "./Title"; +import Alert from "../primitives/Alert"; + +const AddUser = (props) => { + const [name, setName] = useState(""); + const [phone, setPhone] = useState(""); + const [email, setEmail] = useState(""); + const [isLoader, setIsLoader] = useState(false); + const [isUserExist, setIsUserExist] = useState(false); + const parseBaseUrl = localStorage.getItem("baseUrl"); + const parseAppId = localStorage.getItem("parseAppId"); + Parse.serverURL = parseBaseUrl; + Parse.initialize(parseAppId); + + const checkUserExist = async () => { + try { + const res = await Parse.Cloud.run("getUserDetails", { + email: email, + userId: Parse.User.current().id + }); + if (res) { + return true; + } else { + return false; + } + } catch (err) { + console.log("err", err); + } + }; + // Define a function to handle form submission + const handleSubmit = async (e) => { + e.preventDefault(); + e.stopPropagation(); + setIsLoader(true); + const res = await checkUserExist(); + if (res) { + setIsUserExist(true); + setIsLoader(false); + setTimeout(() => { + setIsUserExist(false); + }, 1000); + } else { + try { + const contactQuery = new Parse.Object("contracts_Users"); + contactQuery.set("Name", name); + contactQuery.set("Phone", phone); + contactQuery.set("Email", email); + contactQuery.set("UserRole", "contracts_User"); + + if (localStorage.getItem("TenetId")) { + contactQuery.set("TenantId", { + __type: "Pointer", + className: "partners_Tenant", + objectId: localStorage.getItem("TenetId") + }); + } + + try { + const _users = Parse.Object.extend("User"); + const _user = new _users(); + _user.set("name", name); + _user.set("username", email); + _user.set("email", email); + _user.set("phone", phone); + _user.set("password", phone); + + const user = await _user.save(); + if (user) { + const roleurl = `${parseBaseUrl}functions/AddUserToRole`; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessionToken: localStorage.getItem("accesstoken") + }; + const body = { + appName: localStorage.getItem("_appName"), + roleName: "contracts_User", + userId: user.id + }; + await axios.post(roleurl, body, { headers: headers }); + const currentUser = Parse.User.current(); + contactQuery.set( + "CreatedBy", + Parse.User.createWithoutData(currentUser.id) + ); + + contactQuery.set("UserId", user); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + acl.setPublicWriteAccess(true); + acl.setReadAccess(currentUser.id, true); + acl.setWriteAccess(currentUser.id, true); + + contactQuery.setACL(acl); + + const res = await contactQuery.save(); + + const parseData = JSON.parse(JSON.stringify(res)); + if (props.details) { + props.details({ + value: parseData[props.valueKey], + label: parseData[props.displayKey] + }); + } + if (props.closePopup) { + props.closePopup(); + } + if (props.handleUserData) { + props.handleUserData(parseData); + } + + setIsLoader(false); + + setName(""); + setPhone(""); + setEmail(""); + } + } catch (err) { + console.log("err ", err); + if (err.code === 202) { + const params = { email: email }; + const userRes = await Parse.Cloud.run("getUserId", params); + const roleurl = `${parseBaseUrl}functions/AddUserToRole`; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessionToken: localStorage.getItem("accesstoken") + }; + const body = { + appName: localStorage.getItem("_appName"), + roleName: "contracts_User", + userId: userRes.id + }; + await axios.post(roleurl, body, { headers: headers }); + const currentUser = Parse.User.current(); + contactQuery.set( + "CreatedBy", + Parse.User.createWithoutData(currentUser.id) + ); + + contactQuery.set("UserId", { + __type: "Pointer", + className: "_User", + objectId: userRes.id + }); + const acl = new Parse.ACL(); + acl.setPublicReadAccess(true); + acl.setPublicWriteAccess(true); + acl.setReadAccess(currentUser.id, true); + acl.setWriteAccess(currentUser.id, true); + + contactQuery.setACL(acl); + const res = await contactQuery.save(); + + const parseData = JSON.parse(JSON.stringify(res)); + if (props.details) { + props.details({ + value: parseData[props.valueKey], + label: parseData[props.displayKey] + }); + } + if (props.closePopup) { + props.closePopup(); + } + if (props.handleUserData) { + props.handleUserData(parseData); + } + setIsLoader(false); + setName(""); + setPhone(""); + setEmail(""); + } + } + } catch (err) { + // console.log("err", err); + setIsLoader(false); + alert("something went wrong!"); + } + } + }; + + // Define a function to handle the "add yourself" checkbox + const handleReset = () => { + setName(""); + setPhone(""); + setEmail(""); + }; + + return ( +
+ + {isUserExist && <Alert type="danger">User already exists!</Alert>} + {isLoader && ( + <div className="fixed inset-0 flex justify-center items-center bg-black bg-opacity-30 z-50"> + <div + style={{ + fontSize: "45px", + color: "#3dd3e0" + }} + className="loader-37" + ></div> + </div> + )} + <div className="w-full mx-auto"> + <form onSubmit={handleSubmit}> + <h1 className="text-[20px] font-semibold mb-4">Add User</h1> + <div className="mb-3"> + <label + htmlFor="name" + className="block text-xs text-gray-700 font-semibold" + > + Name + <span style={{ color: "red", fontSize: 13 }}> *</span> + </label> + <input + type="text" + id="name" + value={name} + onChange={(e) => setName(e.target.value)} + required + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + /> + </div> + <div className="mb-3"> + <label + htmlFor="email" + className="block text-xs text-gray-700 font-semibold" + > + Email + <span style={{ color: "red", fontSize: 13 }}> *</span> + </label> + <input + type="email" + id="email" + value={email} + onChange={(e) => setEmail(e.target.value)} + required + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + /> + </div> + <div className="mb-3"> + <label + htmlFor="phone" + className="block text-xs text-gray-700 font-semibold" + > + Phone + <span style={{ color: "red", fontSize: 13 }}> *</span> + </label> + <input + type="text" + id="phone" + value={phone} + onChange={(e) => setPhone(e.target.value)} + required + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + /> + </div> + + <div className="flex items-center mt-3 gap-2 text-white"> + <button + type="submit" + className="bg-[#1ab6ce] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 focus:outline-none" + > + Submit + </button> + <div + type="button" + onClick={() => handleReset()} + className="bg-[#188ae2] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 text-center ml-[2px] focus:outline-none" + > + Reset + </div> + </div> + </form> + </div> + </div> + ); +}; + +export default AddUser; diff --git a/apps/OpenSign/src/components/AppendFormInForm.js b/apps/OpenSign/src/components/AppendFormInForm.js index 47679d033..4f757e5bf 100644 --- a/apps/OpenSign/src/components/AppendFormInForm.js +++ b/apps/OpenSign/src/components/AppendFormInForm.js @@ -1,6 +1,7 @@ import React, { useState, useEffect } from "react"; import Parse from "parse"; import axios from "axios"; +import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const"; const AppendFormInForm = (props) => { const [name, setName] = useState(""); @@ -293,14 +294,16 @@ const AppendFormInForm = (props) => { <div className="mt-4 flex justify-start"> <button type="submit" - className="bg-[#1ab6ce] text-sm text-white px-4 py-2 rounded shadow focus:outline-none" + style={{ backgroundColor: modalSubmitBtnColor }} + className="mr-2 px-[20px] py-1.5 text-white rounded shadow-md text-center focus:outline-none " > Submit </button> <button type="button" onClick={() => handleReset()} - className="bg-[#188ae2] text-sm text-white px-4 py-2 rounded ml-2 shadow focus:outline-none" + style={{ backgroundColor: modalCancelBtnColor }} + className="px-4 py-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none" > Reset </button> diff --git a/apps/OpenSign/src/components/Footer.js b/apps/OpenSign/src/components/Footer.js index 92605da90..31753698c 100644 --- a/apps/OpenSign/src/components/Footer.js +++ b/apps/OpenSign/src/components/Footer.js @@ -1,6 +1,7 @@ import React, { useEffect, useState } from "react"; import Package from "../../package.json"; import axios from "axios"; +import { openInNewTab } from "../constant/Utils"; const Footer = () => { const [showButton, setShowButton] = useState(false); const [version, setVersion] = useState(""); @@ -37,12 +38,18 @@ const Footer = () => { }, []); const appName = "OpenSign™"; - + const openUrl = () => { + openInNewTab( + "https://github.com/OpenSignLabs/OpenSign/releases/tag/" + version + ); + }; return ( <> <div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3"> All Rights Reserved © {new Date().getFullYear()}   - {appName} ( version: {version ? version : `${Package.version} `}) + <span onClick={openUrl} className="hover:underline cursor-pointer"> + {appName} ( version: {version ? version : `${Package.version} `}) + </span> </div> <button className={`${ diff --git a/apps/OpenSign/src/components/Header.js b/apps/OpenSign/src/components/Header.js index f15af8a65..2ed4af269 100644 --- a/apps/OpenSign/src/components/Header.js +++ b/apps/OpenSign/src/components/Header.js @@ -4,6 +4,7 @@ import FullScreenButton from "./FullScreenButton"; import { useNavigate } from "react-router-dom"; import Parse from "parse"; import { useWindowSize } from "../hook/useWindowSize"; +import { openInNewTab } from "../constant/Utils"; const Header = ({ showSidebar }) => { const navigation = useNavigate(); const { width } = useWindowSize(); @@ -118,6 +119,12 @@ const Header = ({ showSidebar }) => { <ul> <li className="hover:bg-gray-100 rounded-t-lg py-1 px-2 cursor-pointer font-normal" + onClick={() => openInNewTab("https://docs.opensignlabs.com")} + > + <i className="fa-solid fa-book"></i> Docs + </li> + <li + className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal" onClick={() => { setIsOpen(false); navigation("/profile"); diff --git a/apps/OpenSign/src/components/LoginGoogle.js b/apps/OpenSign/src/components/LoginGoogle.js index a95f903bf..bd44d7f0d 100644 --- a/apps/OpenSign/src/components/LoginGoogle.js +++ b/apps/OpenSign/src/components/LoginGoogle.js @@ -1,7 +1,9 @@ import React, { useState, useRef } from "react"; import Parse from "parse"; -import jwtDecode from "jwt-decode"; +import { jwtDecode } from "jwt-decode"; import { useScript } from "../hook/useScript"; +import ModalUi from "../primitives/ModalUi"; +import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const"; /* * `GoogleSignInBtn`as it's name indicates it render google sign in button @@ -231,118 +233,94 @@ const GoogleSignInBtn = ({ </div> )} <div ref={googleBtn} className="text-sm"></div> - - {isModal && ( - <div - className="modal fade show" - id="exampleModal" - tabIndex="-1" - role="dialog" - style={{ display: "block", zIndex: 1 }} - > - <div className="modal-dialog" role="document"> - <div className="modal-content"> - <div className="modal-header"> - <h5 className="modal-title">Sign up form</h5> - <span> - <span></span> - </span> - </div> - <div className="modal-body"> - <form> - <div className="form-group"> - <label - htmlFor="Phone" - style={{ display: "flex" }} - className="col-form-label" - > - Phone{" "} - <span style={{ fontSize: 13, color: "red" }}>*</span> - </label> - <input - type="tel" - className="form-control" - id="Phone" - value={userDetails.Phone} - onChange={(e) => - setUserDetails({ - ...userDetails, - Phone: e.target.value - }) - } - required - /> - </div> - <div className="form-group"> - <label - htmlFor="Company" - style={{ display: "flex" }} - className="col-form-label" - > - Company{" "} - <span style={{ fontSize: 13, color: "red" }}>*</span> - </label> - <input - type="text" - className="form-control" - id="Company" - value={userDetails.Company} - onChange={(e) => - setUserDetails({ - ...userDetails, - Company: e.target.value - }) - } - required - /> - </div> - <div className="form-group"> - <label - htmlFor="JobTitle" - style={{ display: "flex" }} - className="col-form-label" - > - Job Title{" "} - <span style={{ fontSize: 13, color: "red" }}>*</span> - </label> - <input - type="text" - className="form-control" - id="JobTitle" - value={userDetails.Destination} - onChange={(e) => - setUserDetails({ - ...userDetails, - Destination: e.target.value - }) - } - required - /> - </div> - <div> - <button - type="button" - className="bg-[#17a2b8] p-2 text-white rounded" - onClick={() => handleSubmitbtn()} - style={{ marginRight: 10 }} - > - Sign up - </button> - <button - type="button" - className="bg-[#6c757d] p-2 text-white rounded" - onClick={handleCloseModal} - style={{ width: 90 }} - > - Cancel - </button> - </div> - </form> - </div> - </div> + <ModalUi showClose={false} isOpen={isModal} title="Sign up form"> + <form className="px-4 py-3"> + <div className="mb-3"> + <label + htmlFor="Phone" + style={{ display: "flex" }} + className="block text-xs text-gray-700 font-semibold" + > + Phone <span style={{ fontSize: 13, color: "red" }}>*</span> + </label> + <input + type="tel" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + id="Phone" + value={userDetails.Phone} + onChange={(e) => + setUserDetails({ + ...userDetails, + Phone: e.target.value + }) + } + required + /> </div> - </div> - )} + <div className="mb-3"> + <label + htmlFor="Company" + style={{ display: "flex" }} + className="block text-xs text-gray-700 font-semibold" + > + Company <span style={{ fontSize: 13, color: "red" }}>*</span> + </label> + <input + type="text" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + id="Company" + value={userDetails.Company} + onChange={(e) => + setUserDetails({ + ...userDetails, + Company: e.target.value + }) + } + required + /> + </div> + <div className="mb-3"> + <label + htmlFor="JobTitle" + style={{ display: "flex" }} + className="block text-xs text-gray-700 font-semibold" + > + Job Title <span style={{ fontSize: 13, color: "red" }}>*</span> + </label> + <input + type="text" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + id="JobTitle" + value={userDetails.Destination} + onChange={(e) => + setUserDetails({ + ...userDetails, + Destination: e.target.value + }) + } + required + /> + </div> + <div> + <button + type="button" + className="px-3 py-1.5 text-white rounded shadow-md text-center focus:outline-none " + onClick={() => handleSubmitbtn()} + style={{ marginRight: 10, backgroundColor: modalSubmitBtnColor }} + > + Sign up + </button> + <button + type="button" + className="p-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none" + onClick={handleCloseModal} + style={{ width: 90, backgroundColor: modalCancelBtnColor }} + > + Cancel + </button> + </div> + </form> + </ModalUi> </div> ); }; diff --git a/apps/OpenSign/src/components/TreeEditForm.js b/apps/OpenSign/src/components/TreeEditForm.js deleted file mode 100644 index 4de7e9c2f..000000000 --- a/apps/OpenSign/src/components/TreeEditForm.js +++ /dev/null @@ -1,391 +0,0 @@ -import React, { useState, useEffect } from "react"; -import Form from "@rjsf/core"; -import validator from "@rjsf/validator-ajv8"; -import Parse from "parse"; -import "../styles/loader.css"; -import LayoutField from "./fields/Rjsf-layout"; -import TimeWidget from "./fields/TimeWidget"; -import Level1Dropdown from "./fields/Level1Dropdown"; -import HiddenField from "./fields/HiddenField"; -import MultiSelectField from "./fields/MultiSelectField"; -import TreeWidget from "../components/TreeWidget"; -import { formJson } from "../json/FormJson"; -const TreeEditForm = (props) => { - const widget = { - TimeWidget: TimeWidget - }; - const fields = { - layout: LayoutField, - Level1Dropdown: Level1Dropdown, - HiddenField: HiddenField, - MultiSelectField: MultiSelectField, - FolderComponent: TreeWidget - }; - - const [schema, setschema] = useState({}); - const [ui_schema, setui_schema] = useState({}); - const [title, settitle] = useState(""); - const [schemaState, setschemaState] = useState({}); - const [formData, setformData] = useState({}); - const [active, setactive] = useState(true); - const [loading, setloading] = useState(false); - const [_validate, set_validate] = useState(null); - const [noValidate, setnoValidate] = useState(false); - const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); - const [parseAppId] = useState(localStorage.getItem("parseAppId")); - - const getForm = async (id) => { - setloading(true); - try { - //get json form data (schema ,uischema) - const results = formJson(id); - try { - let _record = Parse.Object.extend(results.class); - var query1 = new Parse.Query(_record); - await query1.get(props.objectId).then( - (x) => { - try { - if (x) { - let result = x.toJSON(); - let new_result = result; - for (let [key, value] of Object.entries(result)) { - if (value["__type"] === "Date") { - let todayTime1 = new Date(value.iso); - var month = String(todayTime1.getMonth() + 1); - var day = String(todayTime1.getDate()); - var year = String(todayTime1.getFullYear()); - if (month.length < 2) month = "0" + month; - if (day.length < 2) day = "0" + day; - let date1 = year + "-" + month + "-" + day; - let bindVar = date1; - if (!results.jsonSchema.properties[key].format) { - bindVar = todayTime1.toISOString(); - } - new_result[key] = bindVar; - } - } - setschemaState(results.jsonSchema); - setformData(new_result); - } - } catch (error) { - //alert(error.message); - - setloading(false); - } - }, - (error) => { - console.log("err", error); - setloading(false); - } - ); - setschema(results.jsonSchema); - setui_schema(results.uiSchema); - set_validate(results.validFunction); - setnoValidate(results.noValidate); - settitle(results.class); - setloading(false); - setactive(true); - } catch (error) { - setloading(false); - } - } catch (e) { - setloading(false); - console.error("Problem", e); - } - }; - - const wrap = (s) => "{ return " + s + " };"; - - const dynamicValidate = (formData, errors) => { - try { - let body = atob(_validate); - let res = new Function(wrap(body)) - .call(null) - .call(null, formData, errors); - return res; - } catch (error) { - console.log(error); - } - }; - - const handleSubmit = async ({ formData }) => { - setactive(false); - setloading(true); - let RowData = formData; - RowData && - Object.entries(RowData).forEach(([key, value]) => { - if (typeof value === "string") { - RowData[key] = value.trim(); - } - }); - let _scanData = schemaState; - if (_scanData.dependencies) { - Object.keys(_scanData.dependencies).forEach((key) => { - if (_scanData.dependencies[key].oneOf) { - _scanData.dependencies[key].oneOf.forEach((val) => { - Object.keys(val.properties).forEach((k) => { - if (typeof val.properties[k] === "object") { - if (val.properties[k].format === "date") { - if (RowData[k]) { - let newdate = new Date(RowData[k]); - RowData[k] = newdate; - } - } - if (val.properties[k].component === "HtmlEditor") { - if (RowData[k]) { - let newHtml = RowData[k] - .replace(/<p[^>]*>/g, "") - .replace(/<\/p>/g, " "); - RowData[k] = newHtml; - } - } - if (val.properties[k].component === "DateTime") { - if (RowData[k]) { - let newDate11 = new Date(RowData[k]); - RowData[k] = newDate11; - } - } - if (val.properties[k].component === "CurrencyInput") { - if (val.properties[k].currencyColumn) { - RowData[`${val.properties[k].currencyColumn}`] = - val.properties[k].defaultcurrency; - } - } - if (val.properties[k].type === "string") { - if (typeof RowData[k] === "string") - RowData[k] = RowData[k].trim(); - } - if (val.properties[k].data !== undefined) { - if (val.properties[k].data.isPointer) { - let pointer = undefined; - if (val.properties[k].data.class) { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: val.properties[k].data.class, - objectId: RowData[k] - }; - } - } else { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: localStorage.getItem("extended_class"), - objectId: RowData[k] - }; - } - } - RowData[k] = pointer; - } - if (val.properties[k].data.FolderTypeValue) { - if (RowData[k]) { - let obj = { - __type: "Pointer", - className: val.properties[k].data.ClassName, - objectId: RowData[k] - }; - RowData[k] = obj; - } - } - } - } - }); - }); - } - }); - } - let temp = []; - - let _dd = _scanData.properties; - let allowed = []; - if (_dd) { - Object.keys(_dd).forEach(function (k) { - allowed.push(k); - if (RowData[k]) { - let pointer = { - __type: "Pointer", - className: _dd[k].class, - objectId: RowData[k] - }; - RowData[k] = pointer; - } - if (_dd[k].format === "date") { - if (RowData[k]) { - let newdate = new Date(RowData[k]); - if (!isNaN(newdate.getTime())) { - RowData[k] = newdate; - } - } - } - if (_dd[k].component === "HtmlEditor") { - if (RowData[k]) { - let newHtml = RowData[k] - .replace(/<p[^>]*>/g, "") - .replace(/<\/p>/g, " "); - RowData[k] = newHtml; - } - } - if (_dd[k].component === "DateTime") { - if (RowData[k]) { - let newdate = new Date(RowData[k]); - if (!isNaN(newdate.getTime())) { - RowData[k] = newdate; - } - } - } - if (_dd[k].format === "date-time") { - let newdate = new Date(RowData[k]); - RowData[k] = newdate; - } - if (_dd[k].component === "CurrencyInput") { - if (_dd[k].currencyColumn) { - RowData[`${_dd[k].currencyColumn}`] = _dd[k].defaultcurrency; - } - } - if (_dd[k].data !== undefined) { - if (_dd[k].data.isPointer) { - let pointer = undefined; - if (typeof RowData[k] === "object") { - if (RowData[k]) { - if (RowData[k].objectId !== "Select") { - let obj = { - __type: "Pointer", - className: RowData[k].className, - objectId: RowData[k].objectId - }; - pointer = obj; - } - } - } else if (_dd[k].data.class) { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: _dd[k].data.class, - objectId: RowData[k] - }; - } - } else { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: localStorage.getItem("extended_class"), - objectId: RowData[k] - }; - } - } - - RowData[k] = pointer; - } - if (_dd[k].data.FolderTypeValue) { - if (RowData[k]) { - let obj = { - __type: "Pointer", - className: _dd[k].data.ClassName, - objectId: RowData[k] - }; - RowData[k] = obj; - } - } - } - if (_dd[k].type === "string") { - if (typeof RowData[k] === "string") RowData[k] = RowData[k].trim(); - } - }); - } - const filtered = Object.keys(RowData) - .filter((key) => allowed.includes(key)) - .reduce((obj, key) => { - obj[key] = RowData[key]; - return obj; - }, {}); - - try { - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - const currentUser = Parse.User.current(); - if (temp.length !== 0) { - let userPointer = { - __type: "Pointer", - className: "_User", - objectId: currentUser.id - }; - filtered[[temp[0]]] = userPointer; - } - var data = Parse.Object.extend(title); - var query = new Parse.Query(data); - query.get(props.objectId).then(async (object) => { - object.save(filtered).then( - () => { - try { - alert("Record updated successfully"); - props.HideView(false); - setloading(false); - setactive(true); - } catch (error) { - console.log("err", error); - } - }, - (error) => { - console.log("err", error); - setloading(false); - setactive(true); - } - ); - }); - } catch (error) { - console.log("err", error); - - alert(error.message); - setloading(false); - setactive(true); - } - }; - - useEffect(() => { - if (props.FormId) { - getForm(props.FormId); - } - // eslint-disable-next-line - }, [props.FormId]); - - if (loading) { - return ( - <div - className="loader-01" - style={{ - marginTop: "50px", - marginLeft: "50%", - color: "rgb(0,28,28)", - fontSize: "35px" - }} - ></div> - ); - } - return ( - <Form - schema={schema} - uiSchema={ui_schema} - formData={formData} - showErrorList={false} - widgets={widget} - fields={fields} - validate={noValidate && dynamicValidate} - onSubmit={handleSubmit} - validator={validator} - > - <div> - {active ? ( - <button className="bg-[#1ab6ce] px-3 py-2 rounded text-white text-sm" type="submit"> - Update - </button> - ) : ( - <button className="bg-[#1ab6ce] px-3 py-2 rounded text-white text-sm" type="submit" disabled> - Update - </button> - )} - </div> - </Form> - ); -}; - -export default TreeEditForm; diff --git a/apps/OpenSign/src/components/TreeFormComponent.js b/apps/OpenSign/src/components/TreeFormComponent.js deleted file mode 100644 index 7f7ad806c..000000000 --- a/apps/OpenSign/src/components/TreeFormComponent.js +++ /dev/null @@ -1,237 +0,0 @@ -import React, { useEffect, useState } from "react"; -import Form from "@rjsf/core"; -import validator from "@rjsf/validator-ajv8"; -import LayoutField from "./fields/Rjsf-layout"; -import Level1Dropdown from "./fields/Level1Dropdown"; -import HiddenField from "./fields/HiddenField"; -import MultiSelectField from "./fields/MultiSelectField"; -import "../styles/loader.css"; -import "../styles/form.css"; -import FileUpload from "./fields/FileUpload"; -import parse from "html-react-parser"; -import TimeWidget from "./fields/TimeWidget"; -import { formJson } from "../json/FormJson"; -function TreeFormComponent(props) { - const widget = { - TimeWidget: TimeWidget - }; - - const fields = { - layout: LayoutField, - FileUpload: FileUpload, - Level1Dropdown: Level1Dropdown, - HiddenField: HiddenField, - MultiSelectField: MultiSelectField - }; - - const [link, setLink] = useState(""); - const [help, setHelp] = useState(""); - const toastDescription = ""; - const toastColor = "#5cb85c"; - const [loading, setLoding] = useState(true); - const [schemaState, setSchemaState] = useState({}); - const [formData, setFormData] = useState({}); - const [ui_schema, setUi_schema] = useState({}); - const active = true; - - console.log("new form", props); - - const getForm = async (id) => { - setLoding(true); - try { - // get json from data(jsonschema, uischema) - const results = formJson(id); - // console.log("result", results); - if (results) { - let parentObject = {}, - childObject = {}; - const resultjson = results; - for (let [key, value] of Object.entries( - resultjson.jsonSchema.properties - )) { - if (key === props.ParentField) { - if (props.ParentValue[key]) { - parentObject = { [key]: props.ParentValue[key] }; - } - } else { - if (props.ParentValue && typeof props.ParentValue === "object") { - Object.entries(props.ParentValue).forEach(([k, value]) => { - if (k === key) { - let newO = { [k]: value }; - parentObject = { ...parentObject, ...newO }; - } - }); - } - } - if (props.ChildField) { - Object.entries(props.ChildField).forEach(([k, value]) => { - if (k === key) { - let newO = { [k]: value }; - childObject = { ...childObject, ...newO }; - } - }); - } - - if (typeof value === "object") { - for (let [k, v] of Object.entries(value)) { - if (k === "format" && v === "date") { - let today = new Date(); - let date = - today.getFullYear() + - "-" + - ("0" + (today.getMonth() + 1)).slice(-2) + - "-" + - ("0" + today.getDate()).slice(-2); - value.default = date; - } - } - } - } - if (props.ParentField) { - setFormData({ ...parentObject, ...childObject }); - } - - let txt, link; - if (resultjson.help) { - if (resultjson.help.htmlbody) { - txt = resultjson.help.htmlbody; - } - if (resultjson.help.link) { - link = resultjson.help.link; - } - } - setHelp(txt); - setLink(link); - - props.ClassName(resultjson.class); - props.SchemaState(resultjson.jsonSchema); - setSchemaState(resultjson.jsonSchema); - setUi_schema(resultjson.uiSchema); - setLoding(false); - } else { - alert("form not found"); - setLoding(false); - } - } catch (e) { - console.error("Problem", e); - setLoding(false); - } - }; - - useEffect(() => { - if (!props.IsEdit) { - getForm(props.Id); - } - // console.log("props tree", props); - // eslint-disable-next-line - }, []); - - let formView = ( - <React.Fragment> - <Form - schema={schemaState} - uiSchema={ui_schema} - showErrorList={false} - widgets={widget} - fields={fields} - formData={formData} - onSubmit={props.handleSubmit} - validator={validator} - > - {active ? ( - <button className="btn btn-info submiBtn" type="submit"> - {props.IsEdit ? "update folder" : "create folder"} - </button> - ) : ( - <button className="btn btn-info submiBtn " type="submit" disabled> - submitting... - </button> - )} - </Form> - </React.Fragment> - ); - - if (loading) { - formView = ( - <div style={{ height: "300px" }}> - <div - style={{ - marginLeft: "45%", - marginTop: "150px", - fontSize: "45px", - color: "#3dd3e0" - }} - className="loader-37" - ></div> - </div> - ); - } - - return ( - <React.Fragment> - <div className="row"> - <div className="col-md-12"> - <div className="card"> - <div className="card-body no-padding height-9"> - {help ? ( - <div className="dropdown" style={{ marginTop: "-30px" }}> - <i - className="far fa-question-circle dropdown-toggle hovereffect" - aria-hidden="true" - id="dropdownMenuButton" - data-toggle="dropdown" - aria-haspopup="true" - aria-expanded="false" - style={{ - fontSize: "18px", - color: "purple", - cursor: "pointer !important", - position: "relative", - top: "40px", - left: "98%" - }} - ></i> - <div - className="dropdown-menu" - aria-labelledby="dropdownMenuButton" - style={{ - marginleft: "-121px", - margintop: "-14px", - position: "absolute", - padding: "10px", - width: "300px", - top: "102px!important" - }} - > - {parse(` - ${help} - `)} - <br /> - {link ? ( - <a - onClick={(e) => { - e.preventDefault(); - window.location.href = link; - }} - target="_blank" - className="btn btn-xs btn-primary" - > - Read more.. - </a> - ) : null} - </div> - </div> - ) : null} - <div style={{ fontSize: "13px" }}>{formView}</div> - </div> - </div> - </div> - </div> - <div id="snackbar" style={{ backgroundColor: toastColor }}> - {toastDescription} - </div> - </React.Fragment> - ); -} - -export default TreeFormComponent; diff --git a/apps/OpenSign/src/components/TreeWidget.js b/apps/OpenSign/src/components/TreeWidget.js deleted file mode 100644 index 569112d71..000000000 --- a/apps/OpenSign/src/components/TreeWidget.js +++ /dev/null @@ -1,895 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { connect } from "react-redux"; -import LabelField from "./fields/LabelField"; -import Parse from "parse"; -import axios from "axios"; -import "../styles/spinner.css"; -import TreeFormComponent from "./TreeFormComponent"; -// import TreeEditForm from "./TreeEditForm"; -import "../styles/modal.css"; -import Modal from "react-modal"; - -const TreeWidget = (props) => { - const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); - const [parseAppId] = useState(localStorage.getItem("parseAppId")); - const [isAddField, setIsAddField] = useState(false); - const [folderList, setFolderList] = useState([]); - const [tabList, setTabList] = useState([]); - const [appId, setAppId] = useState(undefined); - const [selectedFolder, setSelectedFolder] = useState(undefined); - const [loader, setLoader] = useState(false); - const [className, setClassName] = useState(""); - const [schemaState, setSchemaState] = useState({}); - const [TabURL, setTabURL] = useState(""); - const [editable, setEditable] = useState(false); - // const [editId, setEditId] = useState(""); - const [defaultState, setDefaultState] = useState(false); - const [isShowModal, setIsShowModal] = useState(false); - const selectFolderHandle = async () => { - setIsShowModal(true); - setIsAddField(false); - setDefaultState(false); - setFolderList([]); - setLoader(true); - - if (tabList.length > 0) { - let len = tabList.length - 1; - selectedItemList(tabList[len]); - } else { - try { - var test; - if (props.schema.parent) { - try { - if (props.parent[props.schema.parent]) { - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - const currentUser = Parse.User.current(); - let res; - if (localStorage.getItem("Extand_Class")) { - let data = JSON.parse(localStorage.getItem("Extand_Class")); - res = data[0]; - } else { - res = await Parse.Cloud.run("getUserDetails", { - email: currentUser.get("email") - }); - if (res) res = res.toJSON(); - } - if (res) { - let json = res; - setAppId(json.AppId); - } - // eslint-disable-next-line - let reg = /(\#.*?\#)/gi; - let str = props.schema.data.Query; - if (str.includes("#")) { - test = str.replace(reg, props.parent[props.schema.parent]); - } else { - test = str; - } - } else { - if (props.child[props.schema.parent]) { - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - const currentUser = Parse.User.current(); - let res; - if (localStorage.getItem("Extand_Class")) { - let data = JSON.parse(localStorage.getItem("Extand_Class")); - res = data[0]; - } else { - res = await Parse.Cloud.run("getUserDetails", { - email: currentUser.get("email") - }); - if (res) res = res.toJSON(); - } - - if (res) { - let json = res; - setAppId(json.AppId); - } - // eslint-disable-next-line - let reg = /(\#.*?\#)/gi; - let str = props.schema.data.Query; - if (str.includes("#")) { - test = str.replace(reg, props.child[props.schema.parent]); - } else { - test = str; - } - } else { - alert(`Please select ${props.schema.parent}`); - setLoader(false); - return; - } - } - } catch (error) { - console.log("error ", error); - } - } else { - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - const currentUser = Parse.User.current(); - // eslint-disable-next-line - let reg = /(\#.*?\#)/gi; - let str = props.schema.data.Query; - let res; - if (localStorage.getItem("Extand_Class")) { - let data = JSON.parse(localStorage.getItem("Extand_Class")); - res = data[0]; - } else { - // emp = Parse.Object.extend(localStorage.getItem("extended_class")); - // q = new Parse.Query(emp); - // q.equalTo("UserId", currentUser); - // res = await q.first(); - // if (res) res = res.toJSON(); - const currentUser = Parse.User.current(); - res = await Parse.Cloud.run("getUserDetails", { - email: currentUser.get("email") - }); - if (res) res = res.toJSON(); - } - - if (res) { - let json = res; - setAppId(json.AppId); - } - if (str.includes("#")) { - if (res) { - let json = res.toJSON(); - let output = str.match(reg); - if (output.length === 1) { - output = output.join(); - output = output.substring(1, output.length - 1); - output = output.split("."); - if (output.length === 1) { - let out = output[0]; - if (json[out]) { - if (typeof json[out] === "object") { - test = str.replace(reg, JSON.stringify(json[out])); - } else { - test = str.replace(reg, json[out]); - } - } else { - test = str.replace(reg, currentUser.id); - } - } else if (output.length === 2) { - let out1 = json[output[0]][output[1]]; - if (out1) { - test = str.replace(reg, out1); - } - } - } - } - } else { - test = str; - } - } - - let url = `${parseBaseUrl}classes/${props.schema.data.ClassName}?${test}`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseAppId, - "X-Parse-Session-Token": localStorage.getItem("accesstoken") - }; - await axios - .get(url, { headers: headers }) - .then((res) => { - if (res) { - setFolderList(res.data.results); - setLoader(false); - } - }) - .catch((err) => { - setLoader(false); - console.log(err); - }); - } catch (error) { - setLoader(false); - } - } - }; - - const selectedItemList = async (folder) => { - setLoader(true); - setFolderList([]); - try { - let url = `${parseBaseUrl}classes/${props.schema.data.ClassName}?where={"${props.schema.data.ParentFolderField}":{"__type":"Pointer","className":"${props.schema.data.ClassName}","objectId":"${folder.objectId}"}}`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseAppId, - "X-Parse-Session-Token": localStorage.getItem("accesstoken") - }; - await axios.get(url, { headers: headers }).then((result) => { - if (result) { - setFolderList(result.data.results); - setLoader(false); - } - }); - } catch (error) { - setLoader(false); - } - }; - - const removeTabListItem = async (e, i) => { - e.preventDefault(); - setEditable(false); - setLoader(true); - setFolderList([]); - let list = tabList.filter((itm, j) => { - if (j <= i) { - return itm; - } - }); - setTabList(list); - setIsAddField(false); - try { - let _len = list.length - 1; - let url = `${parseBaseUrl}classes/${props.schema.data.ClassName}?where={"${props.schema.data.ParentFolderField}":{"__type":"Pointer","className":"${props.schema.data.ClassName}","objectId":"${list[_len].objectId}"}}`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseAppId, - "X-Parse-Session-Token": localStorage.getItem("accesstoken") - }; - await axios.get(url, { headers: headers }).then((result) => { - if (result) { - setFolderList(result.data.results); - setLoader(false); - } - setLoader(false); - }); - } catch (error) { - setLoader(false); - } - }; - - const onDeleteFolder = async (e) => { - e.preventDefault(); - if (folderList.length > 0) { - alert( - "Folder should not delete. To delete first delete sub items in it." - ); - } else if (window.confirm(`Are you sure you want to delete this record`)) { - try { - setLoader(true); - let len = tabList.length - 1; - - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - var deleted = Parse.Object.extend(props.schema.data.ClassName); - var query = new Parse.Query(deleted); - await query.get(tabList[len].objectId).then( - (del) => { - del.destroy().then( - (y) => { - if (y) { - setLoader(false); - let list = tabList.filter((itm, j) => { - if (j !== len) return itm; - }); - setTabList(list); - if (list.length > 0) { - let len = list.length - 1; - selectedItemList(list[len]); - } else { - selectFolderHandle(); - } - alert("Folder deleted successfully."); - } - }, - (error) => { - alert(error.message); - setLoader(false); - } - ); - }, - (error) => { - console.log("error ", error); - // The object was not retrieved successfully. - setLoader(false); - } - ); - } catch (error) { - setLoader(false); - console.log(error); - } - } - }; - - const onSubmitResult = async (e) => { - setIsShowModal(false); - e.preventDefault(); - //console.log("tabList ", tabList); - if (tabList.length > 0) { - try { - let len = tabList.length - 1; - setSelectedFolder({ - Topic: tabList[len][`${props.schema.data.FolderNameField}`], - description: tabList[len][`${props.schema.data.FolderDescription}`] - }); - props.onChange(tabList[len]["objectId"]); - let url = "Folders"; - tabList.forEach((t) => { - url = url + " / " + t[`${props.schema.data.FolderNameField}`]; - }); - setTabURL(url); - setIsAddField(false); - if (!props.formData) { - setTabList([]); - } - } catch (error) { - setIsAddField(false); - alert(error.message); - } - } else { - setIsAddField(false); - } - }; - - const editFolderDisplay = async (formData) => { - try { - let objectId = formData.objectId; - let className = formData.className; - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - const fldr = Parse.Object.extend(className); - let query = new Parse.Query(fldr); - query.equalTo("objectId", objectId); - const result = await query.first(); - let resultJson = result.toJSON(); - let CustomTabList = []; - if (resultJson) { - CustomTabList.push(resultJson); - if (resultJson[`${props.schema.data.ParentFolderField}`]) { - let tabsRes = resultJson[`${props.schema.data.ParentFolderField}`]; - let looping = false; - do { - let fldttr = Parse.Object.extend(tabsRes.className); - let query2 = new Parse.Query(fldttr); - query2.equalTo("objectId", tabsRes.objectId); - let custome_res = await query2.first(); - if (custome_res) { - let tabsData = custome_res.toJSON(); - CustomTabList.push(tabsData); - if (tabsData[`${props.schema.data.ParentFolderField}`]) { - tabsRes = tabsData[`${props.schema.data.ParentFolderField}`]; - looping = true; - } else { - looping = false; - } - } - } while (looping); - } - let url = "Folders"; - CustomTabList.length > 0 && - CustomTabList.reverse().forEach( - (t) => (url = url + " / " + t[props.schema.data.FolderNameField]) - ); - setTabURL(url); - setSelectedFolder({ - Topic: resultJson[`${props.schema.data.FolderNameField}`], - description: resultJson[`${props.schema.data.FolderDescription}`] - }); - setTabList(CustomTabList); - props.onChange(resultJson.objectId); - } - } catch (error) { - console.log(error); - } - }; - - const handleSubmit = async ({ formData }) => { - setLoader(true); - - try { - let RowData = formData; - let _scanData = schemaState; - Object.keys(_scanData).forEach(function (key) { - let _dd = _scanData[key]; - Object.keys(_dd).forEach(function (k) { - if (_dd[k].component === "AutoSuggest" && _dd[k].isPointer) { - let pointer = { - __type: "Pointer", - className: _dd[k].class, - objectId: RowData[k] - }; - RowData[k] = pointer; - } - if (_dd[k].format === "date") { - let newdate = new Date(RowData[k]); - RowData[k] = newdate; - } - if (_dd[k].component === "DateTime") { - let newDate11; - if (!RowData[k]) { - newDate11 = new Date(); - } else { - newDate11 = new Date(RowData[k]); - } - RowData[k] = newDate11; - } - if (_dd[k].component === "CurrencyInput") { - if (_dd[k].currencyColumn) { - RowData[`${_dd[k].currencyColumn}`] = _dd[k].defaultcurrency; - } - } - if (_dd[k].data !== undefined) { - if (_dd[k].data.isPointer) { - let pointer = {}; - if (RowData[k] && RowData[k] !== "Select") { - if (_dd[k].data.class) { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: _dd[k].data.class, - objectId: RowData[k] - }; - } - } else { - pointer = { - __type: "Pointer", - className: localStorage.getItem("extended_class"), - objectId: RowData[k] - }; - } - - RowData[k] = pointer; - } - } - if (_dd[k].data.FolderTypeValue) { - let obj = { - __type: "Pointer", - className: _dd[k].data.ClassName, - objectId: RowData[k] - }; - RowData[k] = obj; - } - } - if (_dd[k].type === "string") { - let d = RowData[k]; - if (typeof d === "string") { - RowData[k] = d.trim(); - } - } - }); - }); - - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - - var forms = Parse.Object.extend(className); - var folder = new forms(); - folder.set( - props.schema.data.FolderNameField, - formData[props.schema.data.FolderNameField] - ); - if (props.schema.data.FolderDescription) { - folder.set( - props.schema.data.FolderDescription, - formData[props.schema.data.FolderDescription] - ); - } - - folder.set("AppId", appId); - folder.set( - props.schema.data.FolderTypeField, - props.schema.data.FolderTypeValue - ); - const currentUser = Parse.User.current(); - folder.set("CreatedBy", Parse.User.createWithoutData(currentUser.id)); - if (tabList.length > 0) { - let len = tabList.length - 1; - folder.set(props.schema.data.ParentFolderField, { - __type: "Pointer", - className: props.schema.data.ClassName, - objectId: tabList[len]["objectId"] - }); - } - folder.save(RowData).then( - (result) => { - RowData = {}; - if (result) { - setIsAddField(false); - setLoader(false); - if (tabList.length > 0) { - let len = tabList.length - 1; - selectedItemList(tabList[len]); - } else { - selectFolderHandle(); - } - } - }, - (error) => { - console.log("error ", error); - setLoader(false); - } - ); - } catch (error) { - setLoader(false); - } - }; - - useEffect(() => { - if (props.formData) { - editFolderDisplay(props.formData); - } - - // eslint-disable-next-line - }, [props.formData]); - - useEffect(() => { - if (defaultState) { - selectFolderHandle(); - } - - // eslint-disable-next-line - }, [defaultState]); - const customStyles = { - content: { - top: "50%", - left: "50%", - right: "auto", - bottom: "auto", - marginRight: "-50%", - transform: "translate(-50%, -50%)", - backgroundColor: "white", - padding: 0 - }, - overlay: { - width: "100%", - backgroundColor: "rgba(0, 0, 0, 0.75)", - zIndex: 50 - } - }; - - return ( - <React.Fragment> - <LabelField - Title={props.schema.title} - Name={props.name} - Required={props.required} - HelpBody={props.schema.helpbody} - HelpLink={props.schema.helplink} - /> - <br /> - <div className="block max-w-sm bg-white border border-gray-200 shadow hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700"> - <div - style={{ - display: "flex", - color: "black", - fontWeight: "bold", - fontSize: "13px", - padding: "2%", - alignItems: "center" - }} - > - <div style={{ width: "20%" }}> - <div - className="pull-left" - title="Select Folder" - style={{ - color: "#33bbff", - margin: "auto", - padding: "10px 10px", - textAlign: "center" - }} - > - <i - className="far fa-folder-open" - style={{ fontSize: "40px" }} - aria-hidden="true" - ></i> - </div> - </div> - <div style={{ margin: "0px 10px 0 20px", width: "80%" }}> - <div> - {selectedFolder && selectedFolder.Topic - ? selectedFolder.Topic - : "Root"} - <i - className="fa fa-pencil" - title="Select Folder" - style={{ fontSize: 17, cursor: "pointer", marginLeft: 12 }} - onClick={selectFolderHandle} - ></i> - {selectedFolder && ( - <a - className="pull-right" - onClick={() => { - setSelectedFolder(undefined); - setTabURL(undefined); - props.onChange(undefined); - }} - > - <i - className="fa fa-times-circle-o" - aria-hidden="true" - style={{ fontSize: 17 }} - ></i> - </a> - )} - </div> - {TabURL && ( - <div - style={{ fontSize: "10px", color: "gray", fontWeight: "bold" }} - > - ({TabURL}) - </div> - )} - </div> - </div> - </div> - {/* save document in folder and add new folder modal */} - <Modal - isOpen={isShowModal} - onRequestClose={() => setIsShowModal(false)} - shouldCloseOnOverlayClick={false} - contentLabel="Modal" - style={customStyles} - > - <div className="w-full min-w-[300px] md:min-w-[500px]"> - {/* header */} - <div - style={{ - display: "flex", - justifyContent: "space-between", - alignItems: "center", - backgroundColor: "rgba(203, 200, 200, 0.09)" - }} - > - <div style={{ padding: "10px" }}> - <h4 className=" text-black">Select Folder</h4> - </div> - <div style={{ padding: "10px" }}> - <button - className="btn btn-sm pull-right" - data-dismiss="modal" - title="Select Folder" - style={{ - width: "auto", - backgroundColor: "white", - border: "1px solid gray", - boxshadow: "rgba(100, 100, 111, 0.2) 0px 7px 29px 0px" - }} - onClick={(e) => { - e.preventDefault(); - setIsAddField(false); - setFolderList([]); - setEditable(false); - if (!props.formData) { - setTabList([]); - } - setIsShowModal(false); - }} - > - <span aria-hidden="true">×</span> - </button> - </div> - </div> - <hr /> - {/* body */} - <div className="p-3 space-y-6"> - <div - style={{ - color: "#ac4848", - cursor: "pointer", - fontSize: "14px", - fontWeight: "500" - }} - > - <a - onClick={() => { - setTabList([]); - setIsAddField(false); - setDefaultState(true); - setEditable(false); - }} - > - Folders - </a> - {" / "} - - {tabList && - tabList.map((tab, i) => ( - <React.Fragment key={`${tab.objectId}-${i}`}> - <a - title={tab[`${props.schema.data.FolderNameField}`]} - onClick={(e) => removeTabListItem(e, i)} - > - {tab[`${props.schema.data.FolderNameField}`]} - </a> - {" / "} - </React.Fragment> - ))} - <hr /> - </div> - {/* {editable && ( - <TreeEditForm - FormId={props.schema.data.FormId} - objectId={editId} - HideView={(cl) => { - setEditable(cl); - selectFolderHandle(); - }} - /> - )} */} - {isAddField && !loader && !editable && ( - <TreeFormComponent - Id={props.schema.data.FormId} - handleSubmit={handleSubmit} - ParentField={props.schema.parent && props.schema.parent} - ParentValue={props.schema.parent && props.parent} - ChildField={props.child && props.child} - ClassName={(cls) => setClassName(cls)} - SchemaState={(cls) => setSchemaState(cls)} - /> - )} - {loader && ( - <div - className="loader-01" - style={{ - marginTop: "50px", - marginLeft: "50%", - color: "rgb(0,28,28)", - fontSize: "35px" - }} - ></div> - )} - - {!isAddField && !editable && ( - <div - style={{ - maxHeight: "280px", - overflowY: "auto", - marginTop: "5px" - }} - > - <ul> - {folderList && - folderList.map( - (fldr) => - fldr[props.schema.data.FolderTypeField] === - props.schema.data.FolderTypeValue && ( - <li - key={`${fldr.objectId}`} - style={{ - listStyle: "none", - padding: "10px 20px", - textTransform: "capitalize", - fontWeight: 300, - border: "1px solid gray", - borderRadius: "1px", - marginTop: "8px", - transition: "all 0.75s ease", - WebkitTransition: "all 0.5s ease", - MozTransition: "all 0.5s ease", - MsTransition: "all 0.5s ease", - OTransition: "all 0.5 ease", - display: "flex", - alignItems: "center", - justifyContent: "space-between" - }} - > - <div - style={{ - display: "flex", - alignItems: "center" - }} - > - <i - className={"fa fa-folder"} - style={{ - fontSize: "1.4rem", - color: "skyblue" - }} - aria-hidden="true" - ></i> - <a - style={{ - fontWeight: "bold", - fontSize: "12px", - marginLeft: "4px", - cursor: "pointer" - }} - onClick={() => { - setTabList((tabs) => tabs.concat(fldr)); - selectedItemList(fldr); - }} - > - {fldr[`${props.schema.data.FolderNameField}`]} - </a> - </div> - - {/* {fldr[props.schema.data.FolderTypeField] === - props.schema.data.FolderTypeValue && ( - <a - className="float-right" - onClick={() => { - setEditable(true); - setEditId(fldr.objectId); - }} - > - <i - className={"fa fa-pencil"} - title={"Edit Folder"} - style={{ - fontSize: "0.9rem", - color: "purple", - cursor: "pointer" - }} - aria-hidden="true" - ></i> - </a> - )} */} - </li> - ) - )} - </ul> - </div> - )} - </div> - {/* footer */} - - <div className="flex items-center p-3 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600 justify-between"> - <button - className="btn btn-sm float-left createFolder" - title="Create New Folder" - onClick={(e) => { - e.preventDefault(); - setIsAddField(true); - }} - > - {" "} - <i - className="fa fa-plus" - style={{ fontSize: "1.5rem" }} - aria-hidden="true" - ></i> - </button> - {!isAddField && !editable && ( - <div className="flex"> - {tabList.length > 0 && ( - <button - className="btn btn-sm float-right deleteFolder" - title="Delete Folder" - onClick={onDeleteFolder} - > - {" "} - <i - className="fa fa-trash" - style={{ fontSize: "1rem" }} - aria-hidden="true" - ></i> - </button> - )} - <button - className="btn btn-sm float-right saveFolder" - title="Save Here" - onClick={onSubmitResult} - > - {" "} - {/* <i - className="fa fa-floppy-o" - style={{ fontSize: "2rem" }} - aria-hidden="true" - ></i> */} - <i - className="fas fa-save" - aria-hidden="true" - style={{ fontSize: "20px" }} - ></i> - </button> - </div> - )} - </div> - </div> - </Modal> - </React.Fragment> - ); -}; - -const mapStateToProps = (state) => { - return { - parent: state.Level1_Dropdown, - child: state.Level2_Dropdown - }; -}; - -export default connect(mapStateToProps)(TreeWidget); diff --git a/apps/OpenSign/src/components/fields/FileUpload.js b/apps/OpenSign/src/components/fields/FileUpload.js deleted file mode 100644 index e6c632a02..000000000 --- a/apps/OpenSign/src/components/fields/FileUpload.js +++ /dev/null @@ -1,312 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { SaveFileSize } from "../../constant/saveFileSize"; -import Parse from "parse"; -import sanitizeFileName from "../../primitives/sanitizeFileName"; -import DropboxChooser from "./DropboxChoose"; -const FileUpload = (props) => { - const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); - const [parseAppId] = useState(localStorage.getItem("parseAppId")); - const [_fileupload, setFileUpload] = useState(""); - const [fileload, setfileload] = useState(false); - const [Message] = useState(false); - const [percentage, setpercentage] = useState(0); - - const REQUIRED_FIELD_SYMBOL = "*"; - - useEffect(() => { - if (!props.formData) { - setFileUpload([]); - props.onChange(undefined); - } - // eslint-disable-next-line - }, [props.formData]); - const onChange = (e) => { - try { - let files = e.target.files; - if (typeof files[0] !== "undefined") { - if (props.schema.filetypes && props.schema.filetypes.length > 0) { - var fileName = files[0].name; - var fileNameExt = fileName - .substr(fileName.lastIndexOf(".") + 1) - .toLowerCase(); - let Extensions = props.schema.filetypes.map((x) => x.toLowerCase()); - let arr = Extensions.filter((x) => x === fileNameExt); - if (arr.length > 0) { - console.log("multiple type"); - } else { - alert( - "Only these file types are accepted : " + Extensions.join(", ") - ); - } - } - if (props.schema.maxfilesizeKB && props.schema.maxfilesizeKB !== "") { - // console.log(Math.round(files[0].size / 1024)); - if ( - Math.round(Number(files[0].size) / 1024) >= - props.schema.maxfilesizeKB - ) { - alert( - `The selected file size is too large. Please select a file less than ${Math.round( - props.schema.maxfilesizeKB / 1024 - )} MB` - ); - return; - } - } - handleFileUpload(files[0]); - } else { - alert("Please select file."); - return false; - } - } catch (error) { - alert(error.message); - return false; - } - }; - - const handleFileUpload = async (file) => { - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - setfileload(true); - const size = file.size; - const fileName = file.name; - const name = sanitizeFileName(fileName); - const pdfFile = file; - const parseFile = new Parse.File(name, pdfFile); - - try { - const response = await parseFile.save({ - progress: (progressValue, loaded, total, { type }) => { - if (type === "upload" && progressValue !== null) { - const percentCompleted = Math.round((loaded * 100) / total); - // console.log("percentCompleted ", percentCompleted); - setpercentage(percentCompleted); - } - } - }); - - setFileUpload(response.url()); - props.onChange(response.url()); - setfileload(false); - // The response object will contain information about the uploaded file - // console.log("File uploaded:", response); - - // You can access the URL of the uploaded file using response.url() - // console.log("File URL:", response.url()); - if (response.url()) { - SaveFileSize(size, response.url()); - return response.url(); - } - } catch (error) { - setfileload(false); - setpercentage(0); - console.error("Error uploading file:", error); - } - }; - - const dropboxSuccess = async (files) => { - // console.log("file ", files); - setfileload(true); - const file = files[0]; - const url = file.link; - const size = file.bytes; - const mb = Math.round(file.bytes / Math.pow(1024, 2)); - - if (mb > 10) { - setTimeout(() => { - alert( - `The selected file size is too large. Please select a file less than 10 MB` - ); - }, 500); - return; - } else { - const name = sanitizeFileName(file.name); - - const parseFile = new Parse.File(name, { uri: url }); - - try { - const response = await parseFile.save({ - progress: (progressValue, loaded, total, { type }) => { - if (type === "upload" && progressValue !== null) { - const percentCompleted = Math.round((loaded * 100) / total); - // console.log("percentCompleted ", percentCompleted); - setpercentage(percentCompleted); - } - } - }); - // console.log("response.url() ", response.url()); - setFileUpload(response.url()); - props.onChange(response.url()); - setfileload(false); - - if (response.url()) { - SaveFileSize(size, response.url()); - return response.url(); - } - } catch (error) { - setfileload(false); - setpercentage(0); - console.error("Error uploading file:", error); - } - } - }; - const dropboxCancel = async () => { - console.log("cancel clicked "); - }; - let fileView = - props.formData && - props.schema.uploadtype === "s3viajw" ? null : props.formData && - props.formData ? ( - <React.Fragment> - <a - href={props.formData} - title={props.formData} - style={{ paddingBottom: "10px", color: "blue" }} - > - Download - </a> - </React.Fragment> - ) : fileload === false ? null : ( - <React.Fragment> - <a - href={_fileupload} - title={_fileupload} - style={{ paddingBottom: "10px" }} - > - Download - </a> - <br /> - </React.Fragment> - ); - - return ( - <React.Fragment> - <div style={{ display: "inline-block" }}> - <label htmlFor={props.name}> - {props.schema.title} - {props.required && ( - <span className="required">{REQUIRED_FIELD_SYMBOL}</span> - )} - {fileload ? ( - <div className="flex items-center gap-x-2"> - <div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200"> - <div - className="h-2 rounded-full bg-blue-500" - style={{ width: `${percentage}%` }} - ></div> - </div> - <span className="text-black text-sm">{percentage}%</span> - </div> - ) : ( - Message && ( - <span style={{ fontSize: "9px", marginLeft: "4px" }}> - Processing will take 5-10 mins.... - </span> - ) - )} - {props.schema.helpbody ? ( - <div className="dropdown pull-right"> - <i - className="far fa-question-circle dropdown-toggle hovereffect" - aria-hidden="true" - id="dropdownMenuButton" - data-toggle="dropdown" - aria-haspopup="true" - aria-expanded="false" - style={{ - fontSize: "12px", - color: "purple", - cursor: "pointer !important", - position: "relative", - bottom: "0px", - left: "0px", - paddingBottom: "4px", - paddingLeft: "4px" - }} - ></i> - <div - className="dropdown-menu" - aria-labelledby="dropdownMenuButton" - style={{ - marginleft: "-121px", - margintop: "-14px", - position: "absolute", - padding: "10px", - top: "102px!important" - }} - > - <br /> - {props.schema.helplink ? ( - <a - href={props.schema.helplink} - target="_blank" - rel="noreferrer" - className="btn btn-xs btn-primary" - > - Read more.. - </a> - ) : null} - </div> - </div> - ) : null} - <span style={{ marginLeft: "10px" }}>{fileView}</span> - </label> - </div> - - <> - {props.formData ? ( - <div className="flex gap-2 justify-center items-center"> - <div className="flex justify-between items-center px-2 py-[3px] w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]"> - <div className="break-all"> - file selected : {props.formData?.split("/")[3]?.split("_")[1]} - </div> - <div - onClick={() => { - console.log("clicked"); - setFileUpload([]); - props.onChange(undefined); - }} - className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500" - > - <i className="fa-solid fa-xmark"></i> - </div> - </div> - {process.env.REACT_APP_DROPBOX_API_KEY && ( - <DropboxChooser - onSuccess={dropboxSuccess} - onCancel={dropboxCancel} - /> - )} - </div> - ) : ( - <div className="flex gap-2 justify-center items-center"> - <input - type="file" - id="hashfile" - style={{ - border: "1px solid #ccc", - color: "gray", - backgroundColor: "white", - padding: "5px 10px", - borderRadius: "4px", - fontSize: "13px", - width: "100%", - fontWeight: "bold" - }} - accept="application/pdf,application/vnd.ms-excel" - onChange={onChange} - /> - {process.env.REACT_APP_DROPBOX_API_KEY && ( - <DropboxChooser - onSuccess={dropboxSuccess} - onCancel={dropboxCancel} - /> - )} - </div> - )} - </> - </React.Fragment> - ); -}; - -export default FileUpload; diff --git a/apps/OpenSign/src/components/fields/HiddenField.js b/apps/OpenSign/src/components/fields/HiddenField.js deleted file mode 100644 index 09d582ed4..000000000 --- a/apps/OpenSign/src/components/fields/HiddenField.js +++ /dev/null @@ -1,98 +0,0 @@ -import React, { Component } from "react"; -import Parse from "parse"; -// import axios from "axios"; - -export class HiddenField extends Component { - state = { - baseUrl: localStorage.getItem("baseUrl"), - parseAppId: localStorage.getItem("parseAppId"), - _fields: "" - }; - loadData = async () => { - if (this.props.schema.default) { - this.setState({ _fields: this.props.schema.default }); - } else { - try { - Parse.serverURL = this.state.baseUrl; - Parse.initialize(this.state.parseAppId); - let currentUser = await Parse.User.current(); - if (localStorage.getItem("Extand_Class")) { - let _rdata = JSON.parse(localStorage.getItem("Extand_Class")); - let custome_Filed = ""; - let splitArray = this.props.schema.data.valueKey.split("."); - if (splitArray.length > 1) { - custome_Filed = _rdata[0][splitArray[0]][splitArray[1]]; - } else { - let _Filed = _rdata[0][splitArray[0]]; - if (typeof _Filed === "object") { - custome_Filed = { - __type: "Pointer", - className: _Filed["className"], - objectId: _Filed["objectId"] - }; - } else { - custome_Filed = _rdata[0][splitArray[0]]; - } - } - this.setState({ _fields: custome_Filed }); - } else { - if (currentUser) { - // let url = `${this.state.baseUrl}classes/${localStorage.getItem( - // "extended_class" - // )}?where={"UserId":{"__type":"Pointer","className":"_User","objectId":"${ - // currentUser.id - // }"}}&keys=${this.props.schema.data.valueKey}`; - // const headers = { - // "Content-Type": "application/json", - // "X-Parse-Application-Id": this.state.parseAppId - // }; - // await axios.get(url, { headers: headers }).then((res) => { - // let custome_Filed = ""; - // let _rdata = res.data.results; - // let splitArray = this.props.schema.data.valueKey.split("."); - // if (splitArray.length > 1) { - // custome_Filed = _rdata[0][splitArray[0]][splitArray[1]]; - // } else { - // console.log(_rdata[0][splitArray[0]]); - // custome_Filed = _rdata[0][splitArray[0]]; - // } - // this.setState({ _fields: custome_Filed }); - // }); - - const res = await Parse.Cloud.run("getUserDetails", { - email: currentUser.get("email") - }); - let custome_Filed = ""; - const result = res.toJSON(); - let _rdata = [result]; - let splitArray = this.props.schema.data.valueKey.split("."); - if (splitArray.length > 1) { - custome_Filed = _rdata[0][splitArray[0]][splitArray[1]]; - } else { - console.log(_rdata[0][splitArray[0]]); - custome_Filed = _rdata[0][splitArray[0]]; - } - this.setState({ _fields: custome_Filed }); - } - } - } catch (error) { - console.log("err", error); - } - } - }; - componentDidMount() { - this.loadData(); - } - - render() { - return ( - <input - type="hidden" - value={this.state._fields} - onChange={this.props.onChange(this.state._fields)} - /> - ); - } -} - -export default HiddenField; diff --git a/apps/OpenSign/src/components/fields/LabelField.js b/apps/OpenSign/src/components/fields/LabelField.js deleted file mode 100644 index dfa71f3cc..000000000 --- a/apps/OpenSign/src/components/fields/LabelField.js +++ /dev/null @@ -1,70 +0,0 @@ -import React from "react"; -import parse from "html-react-parser"; -import PropTypes from "prop-types"; - -const LabelField = (props) => { - const { Title, Name, Required, HelpBody, HelpLink } = props; - const REQUIRED_FIELD_SYMBOL = "*"; - return ( - <div style={{ display: "inline-block" }}> - <label htmlFor={Name}> - {Title} - {Required && <span className="required">{REQUIRED_FIELD_SYMBOL}</span>} - {HelpBody ? ( - <div className="dropdown pull-right"> - <i - className="far fa-question-circle dropdown-toggle hovereffect pull-right" - aria-hidden="true" - id="dropdownMenuButton" - data-toggle="dropdown" - aria-haspopup="true" - aria-expanded="false" - style={{ - fontSize: "12px", - color: "purple", - cursor: "pointer !important", - position: "relative", - bottom: "0px", - left: "0px", - paddingBottom: "4px", - paddingLeft: "4px" - }} - ></i> - <div - className="dropdown-menu" - aria-labelledby="dropdownMenuButton" - style={{ - marginleft: "-121px", - margintop: "-14px", - position: "absolute", - padding: "10px", - top: "102px!important" - }} - > - {parse(` - ${HelpBody} - `)} - <br /> - {HelpLink ? ( - <a - href={HelpLink} - target="_blank" - rel="noreferrer" - className="btn btn-xs btn-primary" - > - Read more.. - </a> - ) : null} - </div> - </div> - ) : null} - </label> - </div> - ); -}; - -LabelField.propTypes = { - Name: PropTypes.string.isRequired, - Title: PropTypes.string.isRequired -}; -export default LabelField; diff --git a/apps/OpenSign/src/components/fields/Level1Dropdown.js b/apps/OpenSign/src/components/fields/Level1Dropdown.js deleted file mode 100644 index 42228a6f6..000000000 --- a/apps/OpenSign/src/components/fields/Level1Dropdown.js +++ /dev/null @@ -1,482 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { connect } from "react-redux"; -import { onChangeLevel1Dropdown } from "../../redux/actions/index"; -import axios from "axios"; -import Parse from "parse"; -import parse from "html-react-parser"; - -const Level1Dropdown = (props) => { - const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); - const [parseAppId] = useState(localStorage.getItem("parseAppId")); - const [Level1_DD, setLevel1_DD] = useState([]); - const [toastColor] = useState("#d9534f"); - const [toastDescription, setToastDescription] = useState(""); - const [active, setActive] = useState(false); - - const getParams = (offset) => { - const params = { - skip: offset - }; - return params; - }; - - const Level1DropdownData = async () => { - try { - if ( - props.formData && - props.uiSchema["ui:disabled"] && - props.formData !== "Select" - ) { - let url = `${parseBaseUrl}classes/${props.schema.data.class}/${props.formData}`; - if (typeof props.formData === "object") { - url = `${parseBaseUrl}classes/${props.schema.data.class}/${props.formData.objectId}`; - } - let headers1 = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseAppId, - "X-Parse-Session-Token": localStorage.getItem("accesstoken") - }; - let data = []; - let response = []; - await axios.get(url, { headers: headers1 }).then((res) => { - if (res) { - data.push(res.data); - } - }); - - if (data.length > 0) { - let temp = []; - data.forEach((x) => { - let opt = ""; - if (Array.isArray(x[props.schema.data.valueKey])) { - x[props.schema.data.valueKey].forEach((tt) => { - if (typeof tt === "object") { - opt = { - objectId: tt[props.schema.data.displayKey], - option: tt[props.schema.data.displayKey] - }; - } else { - opt = { - objectId: tt, - option: tt - }; - } - temp.push(opt); - }); - } else if (props.schema.data.isPointer) { - if (props.schema.data.valueKey.includes(".")) { - let newArr = props.schema.data.valueKey.split("."); - if (newArr.length === 2) { - opt = { - objectId: x[newArr[0]][newArr[1]], - option: x[props.schema.data.displayKey] - }; - } else { - opt = { - objectId: x[newArr[0]], - option: x[props.schema.data.displayKey] - }; - } - } else { - opt = { - objectId: x[props.schema.data.valueKey], - option: x[props.schema.data.displayKey] - }; - } - temp.push(opt); - } else { - opt = { - objectId: x[props.schema.data.valueKey], - option: x[props.schema.data.displayKey] - }; - temp.push(opt); - } - }); - response = temp; - setLevel1_DD(response); - setActive(false); - if (response.length === 1) { - props.onChangeLevel1Dropdown(response[0].objectId, props.name); - props.onChange(response[0].objectId); - } else if (response.length === 0) { - props.onChangeLevel1Dropdown("", props.name); - props.onChange(""); - } - } - } else { - let response = []; - setActive(true); - Parse.serverURL = parseBaseUrl; - Parse.initialize(parseAppId); - const currentUser = Parse.User.current(); - - // eslint-disable-next-line - var reg = /(\#.*?\#)/gi; - let str = props.schema.data.query; - var test; - if (str.includes("#")) { - let res; - if (localStorage.getItem("Extand_Class")) { - let data = JSON.parse(localStorage.getItem("Extand_Class")); - res = data[0]; - } else { - const currentUser = Parse.User.current(); - res = await Parse.Cloud.run("getUserDetails", { - email: currentUser.get("email") - }); - if (res) res = res.toJSON(); - } - - if (res) { - let json = res; - let output = str.match(reg); - if (output.length === 1) { - output = output.join(); - output = output.substring(1, output.length - 1); - output = output.split("."); - if (output.length === 1) { - let out = output[0]; - if (json[out]) { - if (typeof json[out] === "object") { - test = str.replace(reg, JSON.stringify(json[out])); - } else { - test = str.replace(reg, json[out]); - } - } else { - test = str.replace(reg, currentUser.id); - } - } else if (output.length === 2) { - let out1 = json[output[0]][output[1]]; - if (out1) { - test = str.replace(reg, out1); - } - } - } else if (output.length === 2) { - let output1 = output[0]; - output1 = output1.substring(1, output1.length - 1); - output1 = output1.split("."); - if (output1.length === 1) { - let out = output1[0]; - if (json[out]) { - if (typeof json[out] === "object") { - str = str.replace(output[0], JSON.stringify(json[out])); - } else { - str = str.replace(output[0], json[out]); - } - } else { - str = str.replace(output[0], currentUser.id); - } - } else if (output1.length === 2) { - let out1 = json[output1[0]][output1[1]]; - if (out1) { - str = str.replace(output[0], out1); - } - } - let output2 = output[1]; - output2 = output2.substring(1, output2.length - 1); - output2 = output2.split("."); - if (output2.length === 1) { - let out = output2[0]; - if (json[out]) { - if (typeof json[out] === "object") { - str = str.replace(output[1], JSON.stringify(json[out])); - } else { - str = str.replace(output[1], json[out]); - } - } else { - str = str.replace(output[1], currentUser.id); - } - } else if (output2.length === 2) { - let out1 = json[output2[0]][output2[1]]; - if (out1) { - str = str.replace(output[1], out1); - } - } - test = str; - } - } else { - setToastDescription( - `User not found in ${localStorage.getItem("extended_class")}` - ); - setActive(false); - var x = document.getElementById("Level_1"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 5000); - return; - } - } else { - test = str; - } - let url = `${parseBaseUrl}classes/${props.schema.data.class}?${test}`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseAppId, - "X-Parse-Session-Token": localStorage.getItem("accesstoken") - }; - let fetchCount = 0; - let offset = 0; - let data = []; - /* eslint-disable no-constant-condition */ - while (true) { - const params = getParams(offset); - await axios - .get(url, { params: params, headers: headers }) - .then((response) => { - fetchCount = response.data.results.length; - offset += response.data.results.length; - - if (fetchCount > 0) { - response.data.results.forEach((x) => { - data.push(x); - }); - } - }) - .catch((err) => { - console.error("Problem", err.response); - setToastDescription(err.response.data.message); - setActive(false); - var x = document.getElementById("Level_1"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 5000); - }); - if (fetchCount === 0 || fetchCount < 100) { - break; - } - } - if (data.length > 0) { - let temp = []; - data.forEach((x) => { - let opt = ""; - if (Array.isArray(x[props.schema.data.valueKey])) { - x[props.schema.data.valueKey].forEach((tt) => { - if (typeof tt === "object") { - if (props.schema.data.isPointer) { - opt = { - objectId: tt["objectId"], - option: tt[props.schema.data.displayKey] - }; - } else { - opt = { - objectId: tt[props.schema.data.displayKey], - option: tt[props.schema.data.displayKey] - }; - } - } else { - opt = { - objectId: tt, - option: tt - }; - } - temp.push(opt); - }); - } else if (props.schema.data.isPointer) { - if (props.schema.data.valueKey.includes(".")) { - let newArr = props.schema.data.valueKey.split("."); - if (newArr.length === 2) { - let _dis = props.schema.data.displayKey.split("."); - if (_dis.length === 2) { - opt = { - objectId: x[newArr[0]][newArr[1]], - option: x[_dis[0]][_dis[1]] - }; - } else { - opt = { - objectId: x[newArr[0]][newArr[1]], - option: x[props.schema.data.displayKey] - }; - } - } else { - opt = { - objectId: x[newArr[0]], - option: x[props.schema.data.displayKey] - }; - } - } else { - opt = { - objectId: x[props.schema.data.valueKey], - option: x[props.schema.data.displayKey] - }; - } - temp.push(opt); - } else { - opt = { - objectId: x[props.schema.data.valueKey], - option: x[props.schema.data.displayKey] - }; - temp.push(opt); - } - }); - response = temp; - setLevel1_DD(response); - setActive(false); - if (!props.formData) { - props.onChangeLevel1Dropdown("", props.name); - } - if (response.length === 1) { - props.onChangeLevel1Dropdown(response[0].objectId, props.name); - props.onChange(response[0].objectId); - } else if (response.length === 0) { - props.onChangeLevel1Dropdown("", props.name); - props.onChange(""); - } - } else { - setActive(false); - } - } - } catch (e) { - try { - setToastDescription(e.message); - setActive(false); - x = document.getElementById("Level_1"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 5000); - } catch (error) { - console.log("Err", error); - } - } - }; - - useEffect(() => { - Level1DropdownData(); - // eslint-disable-next-line - }, []); - - useEffect(() => { - if (props.formData && props.formData[`objectId`]) { - props.onChangeLevel1Dropdown(props.formData.objectId, props.name); - } else if (props.formData) { - props.onChangeLevel1Dropdown(props.formData, props.name); - } - - // eslint-disable-next-line - }, [props.formData]); - - const selectDefault = () => { - props.onChange(Level1_DD[0].objectId); - props.onChangeLevel1Dropdown(Level1_DD[0].objectId, props.name); - }; - - const REQUIRED_FIELD_SYMBOL = "*"; - return ( - <React.Fragment> - <div style={{ display: "inline-block" }}> - <label htmlFor={props.name}> - {props.schema.title} - {props.required && ( - <span className="required">{REQUIRED_FIELD_SYMBOL}</span> - )} - {props.schema.data.helpbody ? ( - <div className="dropdown pull-right"> - <i - className="far fa-question-circle dropdown-toggle hovereffect pull-right" - aria-hidden="true" - id="dropdownMenuButton" - data-toggle="dropdown" - aria-haspopup="true" - aria-expanded="false" - style={{ - fontSize: "12px", - color: "purple", - cursor: "pointer !important", - position: "relative", - bottom: "0px", - left: "0px", - paddingBottom: "4px", - paddingLeft: "4px" - }} - ></i> - <div - className="dropdown-menu" - aria-labelledby="dropdownMenuButton" - style={{ - marginleft: "-121px", - margintop: "-14px", - position: "absolute", - padding: "10px", - top: "102px!important" - }} - > - {parse(` - ${props.schema.data.helpbody} - `)} - <br /> - {props.schema.data.helplink ? ( - <a - href={props.schema.data.helplink} - target="_blank" - rel="noreferrer" - className="btn btn-xs btn-primary" - > - Read more.. - </a> - ) : null} - </div> - </div> - ) : null} - </label> - </div> - - {Level1_DD && ( - <select - className="form-control" - name={props.name} - value={props.value} - required={props.required} - disabled={props.uiSchema["ui:disabled"]} - onChange={(e) => { - if (!e.target.value) { - if (props.schema.data.isPointer) { - localStorage.setItem("Level1", undefined); - props.onChangeLevel1Dropdown(undefined, props.name); - return props.onChange(undefined); - } else { - localStorage.setItem("Level1", e.target.value); - props.onChangeLevel1Dropdown(e.target.value, props.name); - return props.onChange(e.target.value); - } - } else { - localStorage.setItem("Level1", e.target.value); - props.onChangeLevel1Dropdown(e.target.value, props.name); - return props.onChange(e.target.value); - } - }} - readOnly={props.uiSchema["ui:disabled"] ? true : false} - defaultValue={Level1_DD.length === 1 && selectDefault} - > - <option value="">{!active ? "Select" : "loading..."}</option> - {Level1_DD && - Level1_DD.map((x, i) => ( - <React.Fragment key={i}> - {props.formData && props.formData.objectId ? ( - props.formData.objectId === x.objectId ? ( - <option value={x.objectId} selected> - {x.option} - </option> - ) : ( - <option value={x.objectId}>{x.option}</option> - ) - ) : props.formData && props.formData === x.objectId ? ( - <option value={x.objectId} selected> - {x.option} - </option> - ) : ( - <option value={x.objectId}>{x.option}</option> - )} - </React.Fragment> - ))} - </select> - )} - <div id="Level_1" style={{ backgroundColor: toastColor }}> - {toastDescription} - </div> - </React.Fragment> - ); -}; - -export default connect(null, { onChangeLevel1Dropdown })(Level1Dropdown); diff --git a/apps/OpenSign/src/components/fields/MultiSelectField.js b/apps/OpenSign/src/components/fields/MultiSelectField.js deleted file mode 100644 index 520e9398f..000000000 --- a/apps/OpenSign/src/components/fields/MultiSelectField.js +++ /dev/null @@ -1,709 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { connect } from "react-redux"; -import Select from "react-select"; -import axios from "axios"; -import LabelField from "./LabelField"; -import ReactDragListView from "react-drag-listview"; -import AppendFormInForm from "../AppendFormInForm"; -import Modal from "react-modal"; -function arrayMove(array, from, to) { - array = array.slice(); - array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]); - return array; -} - -/** - * react-sortable-hoc is depcreated not usable from react 18.x.x - * need to replace it with @dnd-kit - * code changes required - */ - -const MultiSelectField = (props) => { - Modal.setAppElement("body"); - const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); - const [parseAppId] = useState(localStorage.getItem("parseAppId")); - const [state, setState] = useState(undefined); - // const [editFormData, setEditFormData] = useState([]); - const [selected, setSelected] = React.useState([]); - const [isModal, setIsModel] = useState(false); - const onChange = (selectedOptions) => setSelected(selectedOptions); - const [modalIsOpen, setModalIsOpen] = useState(false); - - const onSortEnd = ({ oldIndex, newIndex }) => { - const newValue = arrayMove(selected, oldIndex, newIndex); - setSelected(newValue); - }; - // console.log("props",props) - const GetSelectListData = async () => { - try { - let response = []; - let str = props.schema.data.query; - let _query; - /* eslint-disable no-useless-escape */ - let reg = /(\#.*?\#)/gi; - let extclass = - localStorage.getItem("Extand_Class") && - JSON.parse(localStorage.getItem("Extand_Class")); - let extRow = extclass.length && extclass[0]; - if (str.includes("#")) { - let output = str.match(reg); - output = output.join(); - output = output.substring(1, output.length - 1); - output = output.split("."); - - if (output.length === 2) { - let out1 = extRow[output[0]][output[1]]; - _query = str.replace(reg, out1 && out1); - } else { - let out1 = extRow[output[0]]; - _query = str.replace(reg, out1 && out1); - } - } else { - _query = str; - } - let url = `${parseBaseUrl}classes/${props.schema.data.class}?${_query}`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseAppId, - "X-Parse-Session-Token": localStorage.getItem("accesstoken") - }; - await axios.get(url, { headers: headers }).then((res) => { - let temp = []; - let formArray = []; - let _selected = []; - if (props.schema.uiLayout === "MultiDropdownList") { - if (props.formData) { - props.formData.forEach((x) => { - if (typeof x === "object") { - formArray.push(x.objectId); - } else { - formArray.push(x); - } - }); - } - res.data.results.forEach((x) => { - let obj = {}; - if (formArray.includes(x[props.schema.data.valueKey])) { - obj = { - name: x[props.schema.data.displayKey], - value: x[props.schema.data.valueKey], - isChecked: true - }; - } else { - if (props.schema.selectAll) { - obj = { - name: x[props.schema.data.displayKey], - value: x[props.schema.data.valueKey], - isChecked: true - }; - } else { - obj = { - name: x[props.schema.data.displayKey], - value: x[props.schema.data.valueKey], - isChecked: false - }; - } - } - temp.push(obj); - }); - response = temp; - if (props.formData) { - let checkData = []; - response.forEach((x) => { - if (x.isChecked) { - checkData.push(x.value); - } - }); - setSelected(checkData); - } - setState({ [`${props.name}_DD`]: response }); - } else { - res.data.results.forEach((x) => { - let obj = {}; - if (props.formData) { - props.formData.forEach((x) => { - if (typeof x === "object") { - formArray.push(x.objectId); - } else { - formArray.push(x); - } - }); - } - - obj = { - label: x[props.schema.data.displayKey], - value: x[props.schema.data.valueKey] - }; - if (formArray.includes(x[props.schema.data.valueKey])) { - _selected.push(obj); - } - if (props.schema.selectAll) { - _selected.push(obj); - } - temp.push(obj); - }); - response = temp; - setState({ [`${props.name}_DD`]: response }); - setSelected(_selected); - } - }); - } catch (error) { - console.log("err", error); - } - }; - - const handleCheckChieldElement = (event) => { - let SelectLists = state[`${props.name}_DD`]; - let List = []; - SelectLists.forEach((select) => { - if (select.value === event.target.value) { - select.isChecked = event.target.checked; - } - if (select.isChecked) { - List.push(select.value); - } - }); - setSelected(List); - setState({ [`${props.name}_DD`]: SelectLists }); - }; - - // const Level1CheckList = async (id) => { - // try { - // let response = []; - // // eslint-disable-next-line - // let reg = /(\#.*?\#)/gi; - // let _query = props.schema.data.query; - // let output = _query.match(reg); - // if (output.length === 2) { - // let res; - // if (localStorage.getItem("Extand_Class")) { - // let data = JSON.parse(localStorage.getItem("Extand_Class")); - // res = data[0]; - // } - // output = output.filter((x) => x !== "#queryString#"); - // if (output.length === 1) { - // _query = _query.replace("#queryString#", id); - // output = output.join(); - // output = output.substring(1, output.length - 1); - // output = output.split("."); - // if (output.length > 0) { - // _query = _query.replace(reg, res[output[0]][output[1]]); - // } else { - // _query = _query.replace(reg, res[output[0]]); - // } - // } - // } else { - // _query = props.schema.data.query.replace(reg, id); - // } - - // let url = `${parseBaseUrl}classes/${props.schema.data.class}?${_query}`; - // const headers = { - // "Content-Type": "application/json", - // "X-Parse-Application-Id": parseAppId, - // "X-Parse-Session-Token": localStorage.getItem("accesstoken") - // }; - // await axios.get(url, { headers: headers }).then(async (res) => { - // let temp = []; - // let formArray = []; - // let _selected = []; - // if (editFormData.length > 0) { - // editFormData.forEach((x) => { - // if (typeof x === "object") { - // formArray.push(x.objectId); - // } else { - // formArray.push(x); - // } - // }); - // } else if ( - // props.schema.selectedData && - // Object.keys(props.schema.selectedData).length !== 0 && - // props.schema.selectedData.constructor === Object - // ) { - // try { - // let selectedDataQuery = props.schema.selectedData.query.replace( - // reg, - // id - // ); - // let selectedDataUrl = `${parseBaseUrl}classes/${props.schema.selectedData.class}?${selectedDataQuery}`; - - // await axios.get(selectedDataUrl, { headers }).then((sltres) => { - // let sltData = sltres.data.results; - // sltData.forEach((x) => { - // if (props.schema.selectedData.valueKey.includes(".")) { - // let sltArr = props.schema.selectedData.valueKey.split("."); - - // if (Array.isArray(x[sltArr[0]])) { - // x[sltArr[0]].forEach((l) => { - // formArray.push(l[sltArr[1]]); - // }); - // } else { - // formArray.push(x[sltArr[0][sltArr[1]]]); - // } - // } else { - // formArray.push(x[props.schema.selectedData.valueKey]); - // } - // }); - // }); - // } catch (error) {} - // } - // res.data.results.forEach((x) => { - // let obj = {}; - // if (props.schema.data.valueKey.includes(".")) { - // let newArr = props.schema.data.valueKey.split("."); - // if (Array.isArray(x[newArr[0]])) { - // if (props.schema.data.displayKey.includes(".")) { - // let _dis = props.schema.data.displayKey.split("."); - // x[newArr[0]].forEach((l) => { - // if (formArray.includes(l[newArr[1]])) { - // obj = { - // label: l[_dis[1]], - // value: l[newArr[1]], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // if (props.schema.selectAll) { - // obj = { - // label: l[_dis[1]], - // value: l[newArr[1]], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // obj = { - // label: l[_dis[1]], - // value: l[newArr[1]], - // isChecked: false - // }; - // } - // } - // temp.push(obj); - // }); - // } else { - // x[newArr[0]].forEach((l) => { - // if (formArray.includes(l[newArr[1]])) { - // obj = { - // label: x[props.schema.data.displayKey], - // value: l[newArr[1]], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // if (props.schema.selectAll) { - // obj = { - // label: x[props.schema.data.displayKey], - // value: l[newArr[1]], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // obj = { - // label: x[props.schema.data.displayKey], - // value: l[newArr[1]], - // isChecked: false - // }; - // } - // } - // temp.push(obj); - // }); - // } - // } else { - // if (props.schema.data.displayKey.includes(".")) { - // let disArr = props.schema.data.displayKey.split("."); - // if (formArray.includes(x[newArr[0]][newArr[1]])) { - // obj = { - // label: x[disArr[0]][disArr[1]], - // value: x[newArr[0]][newArr[1]], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // if (props.schema.selectAll) { - // obj = { - // label: x[disArr[0]][disArr[1]], - // value: x[newArr[0]][newArr[1]], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // obj = { - // label: x[disArr[0]][disArr[1]], - // value: x[newArr[0]][newArr[1]], - // isChecked: false - // }; - // } - // } - // } else { - // if (formArray.includes(x[newArr[0]][newArr[1]])) { - // obj = { - // label: x[props.schema.data.displayKey], - // value: x[newArr[0]][newArr[1]], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // if (props.schema.selectAll) { - // obj = { - // label: x[props.schema.data.displayKey], - // value: x[newArr[0]][newArr[1]], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // obj = { - // label: x[props.schema.data.displayKey], - // value: x[newArr[0]][newArr[1]], - // isChecked: false - // }; - // } - // } - // } - // } - // } else { - // if (Array.isArray(x[props.schema.data.valueKey])) { - // x[props.schema.data.valueKey].forEach((t) => { - // if (formArray.includes(t)) { - // obj = { - // label: t, - // value: t, - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // if (props.schema.selectAll) { - // obj = { - // label: t, - // value: t, - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // obj = { - // label: t, - // value: t, - // isChecked: false - // }; - // } - // } - // temp.push(obj); - // }); - // } else if (formArray.includes(x[props.schema.data.valueKey])) { - // obj = { - // label: x[props.schema.data.displayKey], - // value: x[props.schema.data.valueKey], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // if (props.schema.selectAll) { - // obj = { - // label: x[props.schema.data.displayKey], - // value: x[props.schema.data.valueKey], - // isChecked: true - // }; - // _selected.push(obj); - // } else { - // obj = { - // label: x[props.schema.data.displayKey], - // value: x[props.schema.data.valueKey], - // isChecked: false - // }; - // } - // } - // temp.push(obj); - // } - // }); - // response = temp; - // if (props.schema.uiLayout === "MultiDropdownList") { - // if (editFormData) { - // let checkData = []; - // response.forEach((x) => { - // if (x.isChecked) { - // checkData.push(x.value); - // } - // }); - // setSelected(checkData); - // } - // setState({ [`${props.name}_DD`]: response }); - // } else { - // setState({ [`${props.name}_DD`]: response }); - // setSelected(_selected); - // } - // }); - // } catch (error) {} - // }; - - const dragProps = { - onDragEnd(fromIndex, toIndex) { - const data = [...state[`${props.name}_DD`]]; - const item = data.splice(fromIndex, 1)[0]; - data.splice(toIndex, 0, item); - let NewList = []; - data.forEach((x) => { - if (x.isChecked) { - NewList.push(x.value); - } - }); - - setState({ [`${props.name}_DD`]: data }); - setSelected(NewList); - }, - nodeSelector: "li", - handleSelector: "a" - }; - - useEffect(() => { - if (!props.schema.parent) GetSelectListData(); - // eslint-disable-next-line - }, []); - - useEffect(() => { - if (props.schema.uiLayout === "MultiDropdownList") { - props.onChange(selected); - } else { - if (selected && selected.length) { - let newData = []; - selected.forEach((x) => { - newData.push(x.value); - }); - props.onChange(newData); - } - } - // eslint-disable-next-line - }, [selected]); - - // useState(() => { - // if (props.formData) { - // if (props.formData === "Select") { - // } else { - // setEditFormData(props.formData); - // } - // } - // // eslint-disable-next-line - // }, [props.formData]); - - const handleModalCloseClick = () => { - setIsModel(false); - setModalIsOpen(false); - }; - - const openModal = () => { - setModalIsOpen(true); - }; - - // `handleNewDetails` is used to set just save from quick form to selected option in dropdown - const handleNewDetails = (data) => { - setState({ [`${props.name}_DD`]: [...state[`${props.name}_DD`], data] }); - if (selected.length > 0) { - setSelected([...selected, data]); - } else { - setSelected([data]); - } - }; - if (props.schema.uiLayout === "MultiDropdownList") { - return ( - <React.Fragment> - <LabelField - Title={props.schema.title} - Name={props.name} - Required={props.required} - HelpBody={props.schema.helpbody} - HelpLink={props.schema.helplink} - /> - <ReactDragListView {...dragProps}> - <ul - style={{ - listStyleType: "square", - listStylePosition: "outside", - maxHeight: "250px", - overflow: "auto", - paddingTop: "10px", - paddingBottom: "10px", - border: "0px solid #b3b3b3", - borderRadius: "5px" - }} - > - {state && state[`${props.name}_DD`].length > 0 ? ( - state[`${props.name}_DD`].map((x, i) => { - return ( - <li key={i} className="multiSelectList"> - <input - key={x.value} - onClick={handleCheckChieldElement} - type="checkbox" - checked={x.isChecked} - style={{ marginTop: "7px" }} - value={x.value} - disabled={props.disabled} - />{" "} - <span style={{ marginTop: "7px" }}>{x.name}</span> - {props.schema.isSortable && !props.disabled && ( - <a - onClick={(e) => e.preventDefault()} - className="pull-right" - title="Sort List" - style={{ textDecoration: "none" }} - > - <i - className="fa fa-bars" - style={{ - fontSize: "30px", - color: "skyblue", - paddingTop: "11px" - }} - ></i> - </a> - )} - </li> - ); - }) - ) : ( - <li className="multiSelectList">No Record Found</li> - )} - </ul> - </ReactDragListView> - </React.Fragment> - ); - } - - return ( - <React.Fragment> - <LabelField - Title={props.schema.title} - Name={props.name} - Required={props.required} - HelpBody={props.schema.helpbody} - HelpLink={props.schema.helplink} - /> - <div style={{ display: "flex", gap: 5 }}> - <div style={{ flexWrap: "wrap", width: "100%" }}> - <Select - onSortEnd={onSortEnd} - distance={4} - isMulti - options={(state && state[`${props.name}_DD`]) || []} - value={selected} - onChange={onChange} - closeMenuOnSelect={false} - /> - </div> - - {props.schema.data.quickAddFormId && ( - <div - onClick={() => { - setIsModel(true); - openModal(); - }} - style={{ - cursor: "pointer", - borderRadius: 4, - border: "1px solid #ccc", - minHeight: 38, - minWidth: 48, - display: "flex", - justifyContent: "center", - alignItems: "center" - }} - > - <i className="fas fa-plus"></i> - </div> - )} - {/* {props.schema.data.quickAddFormId && ( - <div - className="modal fade" - id={"multiSelectModal" + props.schema.data.quickAddFormId} - tabIndex="-1" - role="dialog" - aria-labelledby="exampleModalLabel" - aria-hidden="true" - > - <div className="modal-dialog modal-lg" role="document"> - <div className="modal-content"> - <div className="modal-header"> - <button - type="button" - className="close" - data-dismiss="modal" - aria-label="Close" - onClick={handleModalCloseClick} - > - <i className="fa fa-times-circle" aria-hidden="true"></i> - </button> - </div> - <div className="modal-body"> - {isModal && ( - <AppendFormInForm - id={props.schema.data.quickAddFormId} - valueKey={props.schema.data.valueKey} - displayKey={props.schema.data.displayKey} - details={handleNewDetails} - closePopup={handleModalCloseClick} - /> - )} - </div> - </div> - </div> - </div> - )} */} - <Modal - isOpen={modalIsOpen} - onRequestClose={handleModalCloseClick} - shouldCloseOnOverlayClick={false} - contentLabel="Modal" - style={{ - content: { - top: "50%", - left: "50%", - right: "auto", - bottom: "auto", - transform: "translate(-50%, -50%)", - padding: 0 - }, - overlay: { - width: "100%", - backgroundColor: "rgba(0, 0, 0, 0.75)", - zIndex: 50 - } - }} - > - <div className="min-w-full md:min-w-[500px]"> - <div - type="button" - className="flex justify-between items-center p-3 border-b-[1px] border-gray-300" - > - <div className=" text-black text-xl font-semibold pl-3"> - Add Signer - </div> - <button onClick={handleModalCloseClick}> - <i - style={{ fontSize: 25 }} - className="fa fa-times-circle" - aria-hidden="true" - ></i> - </button> - </div> - - {isModal && ( - <AppendFormInForm - id={props.schema.data.quickAddFormId} - valueKey={props.schema.data.valueKey} - displayKey={props.schema.data.displayKey} - details={handleNewDetails} - closePopup={handleModalCloseClick} - /> - )} - </div> - </Modal> - </div> - </React.Fragment> - ); -}; - -const mapStateToProps = (state) => { - return { - Level1_Dropdown: state.Level1_Dropdown, - Level2_Dropdown: state.Level2_Dropdown, - Level3_Dropdown: state.Level3_Dropdown - }; -}; -export default connect(mapStateToProps, null)(MultiSelectField); diff --git a/apps/OpenSign/src/components/fields/Rjsf-layout.js b/apps/OpenSign/src/components/fields/Rjsf-layout.js deleted file mode 100644 index a48be8190..000000000 --- a/apps/OpenSign/src/components/fields/Rjsf-layout.js +++ /dev/null @@ -1,92 +0,0 @@ -import React from "react"; -import ObjectField from "@rjsf/core/lib/components/fields/ObjectField"; -import validator from "@rjsf/validator-ajv8"; -import { Col } from "react-bootstrap"; -import { retrieveSchema } from "@rjsf/utils"; - -class GridField extends ObjectField { - state = {}; - render() { - const { - uiSchema, - errorSchema, - idSchema, - - disabled, - readonly, - onBlur, - formData - } = this.props; - const { fields, rootSchema } = this.props.registry; - - const { SchemaField } = fields; - const schema = retrieveSchema(validator, this.props.schema, rootSchema); - const title = schema.title === undefined ? "" : schema.title; - const description = - schema && schema.description === undefined ? "" : schema.description; - // console.log('this.props.schema ', this.props.schema) - // console.log("schema ", schema); - const layout = uiSchema["ui:layout"]; - - return ( - <fieldset> - {title ? <h4>{title}</h4> : null} - {description ? <h6>{description}</h6> : null} - {layout.map((row, index) => { - return ( - <div className="row" key={index}> - {Object.keys(row).map((name, index) => { - const { doShow, ...rowProps } = row[name]; - let style = {}; - if (doShow && !doShow({ formData })) { - style = { display: "none" }; - } - if (schema.properties[name]) { - return ( - <Col {...rowProps} key={index} style={style}> - <SchemaField - name={name} - required={this.isRequired(name)} - schema={schema.properties[name]} - uiSchema={uiSchema[name]} - errorSchema={errorSchema[name]} - idSchema={idSchema[name]} - formData={formData[name]} - onChange={this.onPropertyChange(name)} - onBlur={onBlur} - registry={this.props.registry} - disabled={disabled} - readonly={readonly} - /> - </Col> - ); - } else { - const { render, ...rowProps } = row[name]; - let UIComponent = () => null; - - if (render) { - UIComponent = render; - } - - return ( - <Col {...rowProps} key={index} style={style}> - <UIComponent - name={name} - formData={formData} - errorSchema={errorSchema} - uiSchema={uiSchema} - schema={schema} - registry={this.props.registry} - /> - </Col> - ); - } - })} - </div> - ); - })} - </fieldset> - ); - } -} -export default GridField; diff --git a/apps/OpenSign/src/components/fields/SignersInput.js b/apps/OpenSign/src/components/fields/SignersInput.js index 0e9697965..6cfb93dc0 100644 --- a/apps/OpenSign/src/components/fields/SignersInput.js +++ b/apps/OpenSign/src/components/fields/SignersInput.js @@ -113,6 +113,7 @@ const SignersInput = (props) => { value={selected} onChange={onChange} closeMenuOnSelect={false} + required={props.required} /> </div> <div @@ -146,6 +147,7 @@ const SignersInput = (props) => { right: "auto", bottom: "auto", transform: "translate(-50%, -50%)", + border: "1px transparent", padding: 0 }, overlay: { @@ -157,18 +159,15 @@ const SignersInput = (props) => { > <div className="min-w-full md:min-w-[500px]"> <div - type="button" - className="flex justify-between items-center p-3 border-b-[1px] border-gray-300" + className="flex justify-between rounded-t items-center py-[10px] px-[20px] text-white" + style={{ background: "#32a3ac" }} > - <div className=" text-black text-xl font-semibold pl-3"> - Add Signer - </div> - <button onClick={handleModalCloseClick}> - <i - style={{ fontSize: 25 }} - className="fa fa-times-circle" - aria-hidden="true" - ></i> + <div className="text-[1.2rem] font-normal">Add Signer</div> + <button + onClick={handleModalCloseClick} + className="text-[1.5rem] cursor-pointer focus:outline-none" + > + × </button> </div> diff --git a/apps/OpenSign/src/components/fields/TimeWidget.js b/apps/OpenSign/src/components/fields/TimeWidget.js deleted file mode 100644 index 660840fa7..000000000 --- a/apps/OpenSign/src/components/fields/TimeWidget.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from "react"; -import PropTypes from "prop-types"; - -function TimeWidget(props) { - const { - onChange, - registry: { - widgets: { BaseInput } - } - } = props; - return ( - <BaseInput - type="time" - {...props} - onChange={(value) => onChange(value || undefined)} - /> - ); -} - -if (process.env.NODE_ENV !== "production") { - TimeWidget.propTypes = { - value: PropTypes.string - }; -} - -export default TimeWidget; diff --git a/apps/OpenSign/src/constant/Utils.js b/apps/OpenSign/src/constant/Utils.js new file mode 100644 index 000000000..aa44a9b13 --- /dev/null +++ b/apps/OpenSign/src/constant/Utils.js @@ -0,0 +1,3 @@ +export const openInNewTab = (url) => { + window.open(url, "_blank", "noopener,noreferrer"); +}; diff --git a/apps/OpenSign/src/constant/const.js b/apps/OpenSign/src/constant/const.js index 4f2ea585b..4f7ded0f8 100644 --- a/apps/OpenSign/src/constant/const.js +++ b/apps/OpenSign/src/constant/const.js @@ -1,2 +1,9 @@ export const contactCls = "contracts_Contactbook"; export const templateCls = "contracts_Template"; +export const documentCls = "contracts_Document"; +export const rejectBtn = + "bg-[#ffffff] rounded-sm shadow-md text-[12px] font-semibold uppercase text-black py-1.5 px-4 focus:outline-none text-center border-[1px] border-[#b4b4b4]"; +export const submitBtn = + "bg-[#32a3ac] rounded-sm shadow-md text-[12px] font-semibold uppercase text-white py-1.5 px-4 focus:outline-none text-center"; +export const modalSubmitBtnColor = "#17a2b8"; +export const modalCancelBtnColor = "white"; diff --git a/apps/OpenSign/src/json/FormJson.js b/apps/OpenSign/src/json/FormJson.js index eaa5818b3..8e0b4f6a1 100644 --- a/apps/OpenSign/src/json/FormJson.js +++ b/apps/OpenSign/src/json/FormJson.js @@ -1,584 +1,26 @@ -import Parse from "parse"; -export const formJson = (id) => { - let formData; +import { documentCls, templateCls } from "../constant/const"; +export const formJson = { //json form for signYourself - if (id === "sHAnZphf69") { - formData = { - jsonSchema: { - title: "Sign Yourself", - description: "", - type: "object", - required: ["URL", "Name"], - properties: { - URL: { - type: "string", - title: "Select Document", - filetypes: [], - maxfilesizeKB: "10000", - uploadtype: "regular", - helpbody: "", - helplink: "" - }, - Name: { - type: "string", - title: "Title", - maxLength: 50 - }, - Description: { - type: "string", - title: "Description", - maxLength: 500 - }, - Folder: { - title: "Folder", - parent: null, - data: { - ClassName: "contracts_Document", - FolderNameField: "Name", - FolderTypeField: "Type", - FolderTypeValue: "Folder", - FolderDescription: "Description", - ParentFolderField: "Folder", - FormId: "YjIB7W7Xs6", - Query: 'where={"Folder":{"$exists":false},"Type":"Folder"}' - } - }, - ExtUserPtr: { - data: { - valueKey: "objectId", - isPointer: true - } - } - } - }, - uiSchema: { - URL: { - "ui:field": "FileUpload" - }, - Description: { - "ui:widget": "textarea", - "ui:options": { - rows: 2 - } - }, - Note: { - "ui:widget": "textarea", - "ui:options": { - rows: 2 - } - }, - Folder: { - "ui:field": "FolderComponent" - }, - ExtUserPtr: { - "ui:field": "HiddenField" - } - }, - userSchema: {}, - rules: null, - noValidate: false, - liveValidate: false, - isRegisterForm: false, - help: { htmlbody: "" }, - description: "", - class: "contracts_Document", - buttons: { - add: { - resetText: "Reset", - submitText: "Submit" - }, - edit: { submitText: "Update", cancelText: "Cancel" } - }, - formACL: { - "#currentUser#": { read: true, write: true }, - "*": { read: true, write: true } - }, - redirect_id: - "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/signaturePdf", - success_message: "Success!", - success_redirect: "Microapp", - validFunction: - "ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ==" - }; + sHAnZphf69: { + title: "Sign Yourself", + redirectRoute: "signaturePdf", + msgVar: "Document", + Cls: documentCls + }, - return formData; - } - //json form for request signature - else if (id === "8mZzFxbG1z") { - const user = Parse.User.current(); - const userPtr = JSON.stringify({ - __type: "Pointer", - className: "_User", - objectId: user.id - }); - formData = { - jsonSchema: { - title: "Request signatures", - description: "", - type: "object", - required: ["URL", "Name", "Note", "TimeToCompleteDays", "Signers"], - properties: { - URL: { - type: "string", - title: "Select Document", - filetypes: [], - maxfilesizeKB: "5000", - uploadtype: "regular", - helpbody: "", - helplink: "" - }, - Name: { - type: "string", - title: "Title", - maxLength: 100 - }, - Description: { - type: "string", - title: "Description", - maxLength: 500 - }, - Signers: { - type: "array", - title: "Signers", - isSortable: false, - selectAll: false, - selectedData: null, - data: { - class: "contracts_Contactbook", - displayKey: "Name", - valueKey: "objectId", - query: `where={"CreatedBy":${userPtr},"IsDeleted":{"$ne":true}}&keys=Name`, - isPointer: true, - helpbody: "", - helplink: "", - quickAddFormId: "qUGywSWd8e" - } - }, - Note: { - type: "string", - title: "Note", - default: "Please review and sign this document", - maxLength: 500 - }, - Folder: { - title: "Folder", - data: { - ClassName: "contracts_Document", - FolderNameField: "Name", - FolderTypeField: "Type", - FolderTypeValue: "Folder", - FolderDescription: "Description", - ParentFolderField: "Folder", - FormId: "YjIB7W7Xs6", - Query: 'where={"Folder":{"$exists":false},"Type":"Folder"}' - } - }, - TimeToCompleteDays: { - type: "number", - title: "Time To Complete (Days)", - default: 15, - maxLength: 5000 - }, - ExtUserPtr: { - data: { - valueKey: "objectId", - isPointer: true - } - } - } - }, - uiSchema: { - URL: { - "ui:field": "FileUpload" - }, - Description: { - "ui:widget": "textarea", - "ui:options": { - rows: 2 - } - }, - Note: { - "ui:widget": "textarea", - "ui:options": { - rows: 2 - } - }, - Signers: { - "ui:field": "MultiSelectField" - }, - Folder: { - "ui:field": "FolderComponent" - }, - TimeToCompleteDays: { - "ui:placeholder": "No. of days", - "ui:widget": "updown" - }, - ExtUserPtr: { - "ui:field": "HiddenField" - } - }, - userSchema: {}, - rules: null, - noValidate: false, - liveValidate: false, - isRegisterForm: false, - help: { htmlbody: "" }, - description: "", - class: "contracts_Document", - buttons: { - add: { - resetText: "Reset", - submitText: "Submit" - }, - edit: { submitText: "Update", cancelText: "Cancel" } - }, - formACL: { - "#currentUser#": { read: true, write: true }, - "*": { read: true, write: true } - }, - redirect_id: - "remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/placeHolderSign", - success_message: "Success!", - success_redirect: "Microapp", - validFunction: - "ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ==" - }; - - return formData; - } - //json form for create new folder - else if (id === "YjIB7W7Xs6") { - formData = { - jsonSchema: { - title: "New Folder", - description: "", - type: "object", - required: ["Name"], - properties: { - Name: { - type: "string", - title: "Name", - maxLength: 50 - }, - Type: { - type: "string", - data: { - valueKey: "Type", - isPointer: false - }, - default: "Folder" - }, - Folder: { - title: "Parent Folder", - data: { - class: "contracts_Document", - displayKey: "Name", - valueKey: "objectId", - query: 'where={"Type":"Folder"}&keys=Name', - isPointer: true, - savePointerClass: "", - helpbody: "", - helplink: "" - } - } - } - }, - uiSchema: { - Type: { - "ui:field": "HiddenField" - }, - Folder: { - "ui:field": "Level1Dropdown" - } - }, - userSchema: {}, - rules: null, - noValidate: false, - liveValidate: false, - isRegisterForm: false, - help: { htmlbody: "" }, - description: "", - class: "contracts_Document", - buttons: { - add: { - resetText: "Reset", - submitText: "Submit" - }, - edit: { submitText: "Update", cancelText: "Cancel" } - }, - formACL: { - "#currentUser#": { read: true, write: true }, - "*": { read: true, write: true } - }, - redirect_id: "", - success_message: "Success!", - success_redirect: "", - validFunction: - "ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ==" - }; - return formData; - } - //json form for add signers - else if (id === "fICciRuUcB") { - formData = { - jsonSchema: { - title: "Add Signer", - description: "", - type: "object", - required: ["Name", "Email", "Phone", "Company"], - properties: { - Name: { - type: "string", - title: "Name", - maxLength: 50 - }, - Email: { - type: "string", - title: "Email", - maxLength: 50 - }, - Phone: { - type: "string", - title: "Phone", - maxLength: 50 - }, - Company: { - type: "string", - title: "Company", - maxLength: 50 - }, - JobTitle: { - type: "string", - title: "JobTitle", - maxLength: 50 - }, - IsContactEntry: { - type: "boolean", - data: { - valueKey: "IsContactEntry", - isPointer: false - }, - default: true - } - } - }, - uiSchema: { - Email: { - "ui:widget": "email" - }, - IsContactEntry: { - "ui:field": "HiddenField" - } - }, - userSchema: { - email: "$Email", - name: "$Name", - password: "$Phone", - phone: "$Phone", - role: "contracts_User", - username: "$Email" - }, - rules: null, - noValidate: false, - liveValidate: false, - isRegisterForm: true, - help: {}, - description: "", - class: "contracts_Users", - buttons: { - add: { - resetText: "Reset", - submitText: "Submit" - }, - edit: { submitText: "Update", cancelText: "Cancel" } - }, - formACL: { - "#currentUser#": { read: true, write: true }, - "*": { read: true, write: true } - }, - redirect_id: "", - success_message: "Success!", - success_redirect: "", - validFunction: - "ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ==" - }; - return formData; - } - //json form for add users - else if (id === "lM0xRnM3iE") { - formData = { - jsonSchema: { - title: "Add User", - description: "", - type: "object", - required: ["Name", "Email", "Phone", "JobTitle"], - properties: { - Name: { - type: "string", - title: "Name", - maxLength: 50 - }, - Email: { - type: "string", - title: "Email", - maxLength: 50 - }, - Phone: { - type: "string", - title: "Phone", - maxLength: 50 - }, - JobTitle: { - type: "string", - title: "Job Title", - maxLength: 50 - }, - Company: { - type: "string", - title: "Company", - maxLength: 50 - } - } - }, - uiSchema: { - Email: { - "ui:widget": "email" - }, - Phone: { - "ui:options": { - inputType: "tel" - } - } - }, - userSchema: { - email: "$Email", - name: "$Name", - password: "$Phone", - phone: "$Phone", - role: "contracts_User", - username: "$Email" - }, - rules: null, - noValidate: false, - liveValidate: false, - isRegisterForm: true, - help: {}, - description: "", - class: "contracts_Users", - buttons: { - add: { - resetText: "Reset", - submitText: "Submit" - }, - edit: { submitText: "Update", cancelText: "Cancel" } - }, - formACL: { - "#currentUser#": { read: true, write: true }, - "*": { read: true, write: true } - }, - redirect_id: "", - success_message: "Success!", - success_redirect: "", - validFunction: - "ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ==" - }; - return formData; - } else if (id === "qUGywSWd8e") { - formData = { - jsonSchema: { - title: "Add Contact", - description: "", - type: "object", - required: ["Name", "Email", "Phone"], - properties: { - Name: { - type: "string", - title: "Name", - maxLength: 50 - }, - Email: { - type: "string", - title: "Email", - maxLength: 50 - }, - Phone: { - type: "string", - title: "Phone", - maxLength: 50 - } - } - }, - uiSchema: { - Email: { - "ui:widget": "email" - }, - Phone: { - "ui:options": { - inputType: "tel" - } - } - }, - userSchema: { - name: "$Name", - username: "$Email", - email: "$Email", - password: "$Phone", - phone: "$Phone", - role: "contracts_Guest" - }, - restrict_form_entry: { - enable_captcha: false, - allow_one_entry_per_ip_address: false, - allow_one_entry_per_user: false, - enable_geo_fence: false - }, - restrict_form_access: { - entryCount: "" - }, - help: {}, - email_template: { - from: "", - to: "", - subject: "", - message: "" - }, - buttons: { - add: { - submitText: "Submit", - resetText: "Reset" - }, - edit: { - submitText: "Update", - cancelText: "Cancel" - } - }, - appId: { - __type: "Pointer", - className: "w_appinfo", - objectId: "aIPmIvMzGM" - }, - formACL: { - "*": { - read: true, - write: true - }, - "#currentUser#": { - read: true, - write: true - } - }, - class: "contracts_Contactbook", - description: "", - success_message: "Success!", - form_permission: "private", - success_redirect: "", - redirect_id: "", - isRegisterForm: true, - liveValidate: false, - noValidate: false, - validFunction: - "ZnVuY3Rpb24gdmFsaWRhdGUoZm9ybURhdGEsIGVycm9ycykgeyBpZiAoZm9ybURhdGEucGFzczEgIT09IGZvcm1EYXRhLnBhc3MyKSB7IGVycm9ycy5wYXNzMi5hZGRFcnJvcignUGFzc3dvcmRzIGRvbid0IG1hdGNoJyk7IH0gcmV0dXJuIGVycm9yczsgfQ==" - }; - return formData; + //json form for request signatures + "8mZzFxbG1z": { + title: "Request Signatures", + msgVar: "Document", + redirectRoute: "placeHolderSign", + Cls: documentCls, + signers: true + }, + //json form for template + template: { + title: "New Template", + redirectRoute: "template", + msgVar: "Template", + Cls: templateCls } }; diff --git a/apps/OpenSign/src/json/plansArr.json b/apps/OpenSign/src/json/plansArr.json index d4ae65baa..90ab47bdc 100644 --- a/apps/OpenSign/src/json/plansArr.json +++ b/apps/OpenSign/src/json/plansArr.json @@ -27,13 +27,13 @@ "planName": "THANKS PLAN", "currency": "$", "price": "29.99", - "subtitle": "Use code 'FREEBETA' to get this for free(First 1000 users)", + "subtitle": "Use code <span style='background-color: yellow;'>'FREEBETA'</span> to get this for free(First 1000 users)", "btnText": "Subscribe", "url": "https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af901dbadf3175d495584fd25b9af5d2f2b9e/thanks", "target": "_self", "benefits": [ "Sign Unlimited Documents", - "Unlimited Secure Doc Storage with OpenSignDrive", + "Unlimited Secure Doc Storage with OpenSign™ Drive", "Unlimited Guest Signers", "Unlimited completion certificates", "Unique Code(OTP) verification for guest signers", diff --git a/apps/OpenSign/src/layout/HomeLayout.js b/apps/OpenSign/src/layout/HomeLayout.js index a0ca72170..5fbf2f84f 100644 --- a/apps/OpenSign/src/layout/HomeLayout.js +++ b/apps/OpenSign/src/layout/HomeLayout.js @@ -8,15 +8,16 @@ import axios from "axios"; import { useSelector } from "react-redux"; import Parse from "parse"; import ModalUi from "../primitives/ModalUi"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useLocation, Outlet } from "react-router-dom"; -const HomeLayout = ({ children }) => { +const HomeLayout = () => { const navigate = useNavigate(); + const location = useLocation(); const { width } = useWindowSize(); const [isOpen, setIsOpen] = useState(true); const arr = useSelector((state) => state.TourSteps); const [isUserValid, setIsUserValid] = useState(true); - + const [isLoader, setIsLoader] = useState(true); useEffect(() => { (async () => { try { @@ -27,6 +28,7 @@ const HomeLayout = ({ children }) => { }); if (user) { setIsUserValid(true); + setIsLoader(false); } else { setIsUserValid(false); } @@ -184,7 +186,7 @@ const HomeLayout = ({ children }) => { console.log("err ", err); } finally { localStorage.removeItem("accesstoken"); - navigate("/", { replace: true }); + navigate("/", { replace: true, state: { from: location } }); } }; return ( @@ -194,27 +196,48 @@ const HomeLayout = ({ children }) => { </div> {isUserValid ? ( <> - <div className="flex md:flex-row flex-col z-50"> - <Sidebar isOpen={isOpen} closeSidebar={closeSidebar} /> - - <div className="relative h-screen flex flex-col justify-between w-full overflow-y-auto"> - <div className="bg-[#eef1f5] p-3">{children}</div> - <div className="z-30"> - <Footer /> - </div> + {isLoader ? ( + <div + style={{ + height: "100vh", + display: "flex", + alignItems: "center", + justifyContent: "center" + }} + > + <div + style={{ + fontSize: "45px", + color: "#3dd3e0" + }} + className="loader-37" + ></div> </div> - </div> - <Tour - onRequestClose={closeTour} - steps={tourConfigs} - isOpen={isTour} - closeWithMask={false} - disableKeyboardNavigation={["esc"]} - // disableInteraction={true} - scrollOffset={-100} - rounded={5} - showCloseButton={isCloseBtn} - /> + ) : ( + <> + <div className="flex md:flex-row flex-col z-50"> + <Sidebar isOpen={isOpen} closeSidebar={closeSidebar} /> + + <div className="relative h-screen flex flex-col justify-between w-full overflow-y-auto"> + <div className="bg-[#eef1f5] p-3">{<Outlet />}</div> + <div className="z-30"> + <Footer /> + </div> + </div> + </div> + <Tour + onRequestClose={closeTour} + steps={tourConfigs} + isOpen={isTour} + closeWithMask={false} + disableKeyboardNavigation={["esc"]} + // disableInteraction={true} + scrollOffset={-100} + rounded={5} + showCloseButton={isCloseBtn} + /> + </> + )} </> ) : ( <ModalUi title={"Session Expired"} isOpen={true} showClose={false}> diff --git a/apps/OpenSign/src/primitives/GetReportDisplay.js b/apps/OpenSign/src/primitives/GetReportDisplay.js index b9786d55d..8450c2657 100644 --- a/apps/OpenSign/src/primitives/GetReportDisplay.js +++ b/apps/OpenSign/src/primitives/GetReportDisplay.js @@ -5,6 +5,7 @@ import axios from "axios"; import "../styles/report.css"; import ModalUi from "./ModalUi"; import AppendFormInForm from "../components/AppendFormInForm"; +import { modalSubmitBtnColor, modalCancelBtnColor } from "../constant/const"; const ReportTable = ({ ReportName, List, @@ -342,13 +343,15 @@ const ReportTable = ({ <div className="flex items-center mt-3 gap-2 text-white"> <button onClick={() => handleDelete(item)} - className="bg-[#1ab6ce] rounded-sm shadow-md text-[12px] font-semibold uppercase text-white py-1.5 px-3 focus:outline-none" + className="px-4 py-1.5 text-white rounded shadow-md text-center focus:outline-none " + style={{ backgroundColor: modalSubmitBtnColor }} > Yes </button> <button onClick={handleCloseDeleteModal} - className="bg-[#188ae2] rounded-sm shadow-md text-[12px] font-semibold uppercase text-white py-1.5 px-3 text-center ml-[2px] focus:outline-none" + className="px-4 py-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none" + style={{ backgroundColor: modalCancelBtnColor }} > No </button> @@ -371,7 +374,7 @@ const ReportTable = ({ )} {heading.includes("Folder") && ( <td className="px-4 py-2"> - {item?.Folder?.Name || "OpenSignDrive"} + {item?.Folder?.Name || "OpenSign™ Drive"} </td> )} <td className="px-4 py-2"> diff --git a/apps/OpenSign/src/primitives/TemplateForm.js b/apps/OpenSign/src/primitives/TemplateForm.js deleted file mode 100644 index 5fa592870..000000000 --- a/apps/OpenSign/src/primitives/TemplateForm.js +++ /dev/null @@ -1,336 +0,0 @@ -import React, { useState } from "react"; -import sanitizeFileName from "./sanitizeFileName"; -import Parse from "parse"; -import DropboxChooser from "../components/fields/DropboxChoose"; -import Alert from "./Alert"; -import SelectFolder from "../components/fields/SelectFolder"; -// import SignersInput from "../components/fields/SignersInput"; -import Title from "../components/Title"; -import { useNavigate } from "react-router-dom"; -import { templateCls } from "../constant/const"; - -const TemplateForm = () => { - const navigate = useNavigate(); - const [signers, setSigners] = useState([]); - const [folder, setFolder] = useState({ ObjectId: "", Name: "" }); - const [formData, setFormData] = useState({ - Name: "", - Description: "", - Note: "Please review and sign this document" - }); - const [fileupload, setFileUpload] = useState([]); - const [fileload, setfileload] = useState(false); - const [percentage, setpercentage] = useState(0); - const [isAlert, setIsAlert] = useState(false); - const [isSubmit, setIsSubmit] = useState(false); - const [isErr, setIsErr] = useState(""); - const handleStrInput = (e) => { - setFormData({ ...formData, [e.target.name]: e.target.value }); - }; - - const handleFileInput = (e) => { - setpercentage(0); - try { - let files = e.target.files; - if (typeof files[0] !== "undefined") { - const mb = Math.round(files[0].bytes / Math.pow(1024, 2)); - if (mb > 10) { - alert( - `The selected file size is too large. Please select a file less than ${Math.round( - 10 - )} MB` - ); - return; - } - - handleFileUpload(files[0]); - } else { - alert("Please select file."); - return false; - } - } catch (error) { - alert(error.message); - return false; - } - }; - - const handleFileUpload = async (file) => { - Parse.serverURL = process.env.REACT_APP_SERVERURL; - Parse.initialize(process.env.REACT_APP_APPID); - setfileload(true); - const fileName = file.name; - const name = sanitizeFileName(fileName); - const pdfFile = file; - const parseFile = new Parse.File(name, pdfFile); - - try { - const response = await parseFile.save({ - progress: (progressValue, loaded, total, { type }) => { - if (type === "upload" && progressValue !== null) { - const percentCompleted = Math.round((loaded * 100) / total); - setpercentage(percentCompleted); - } - } - }); - - // The response object will contain information about the uploaded file - // You can access the URL of the uploaded file using response.url() - setFileUpload(response.url()); - setfileload(false); - if (response.url()) { - return response.url(); - } - } catch (error) { - setfileload(false); - setpercentage(0); - console.error("Error uploading file:", error); - } - }; - - const dropboxSuccess = async (files) => { - setfileload(true); - const file = files[0]; - const url = file.link; - const mb = Math.round(file.bytes / Math.pow(1024, 2)); - - if (mb > 10) { - setTimeout(() => { - alert( - `The selected file size is too large. Please select a file less than 10 MB` - ); - }, 500); - return; - } else { - const name = sanitizeFileName(file.name); - - const parseFile = new Parse.File(name, { uri: url }); - - try { - const response = await parseFile.save({ - progress: (progressValue, loaded, total, { type }) => { - if (type === "upload" && progressValue !== null) { - const percentCompleted = Math.round((loaded * 100) / total); - setpercentage(percentCompleted); - } - } - }); - setFileUpload(response.url()); - setfileload(false); - - if (response.url()) { - return response.url(); - } - } catch (error) { - setfileload(false); - setpercentage(0); - console.error("Error uploading file:", error); - } - } - }; - const dropboxCancel = async () => {}; - const handleSubmit = async (e) => { - e.preventDefault(); - setIsSubmit(true); - try { - const currentUser = Parse.User.current(); - const template = new Parse.Object(templateCls); - Object.entries(formData).forEach((item) => - template.set(item[0], item[1]) - ); - template.set("URL", fileupload); - template.set("CreatedBy", Parse.User.createWithoutData(currentUser.id)); - if (folder && folder.ObjectId) { - template.set("Folder", { - __type: "Pointer", - className: templateCls, - objectId: folder.ObjectId - }); - } - if (signers && signers.length > 0) { - template.set("Signers", signers); - } - const ExtCls = JSON.parse(localStorage.getItem("Extand_Class")); - template.set("ExtUserPtr", { - __type: "Pointer", - className: "contracts_Users", - objectId: ExtCls[0].objectId - }); - - const res = await template.save(); - if (res) { - setSigners([]); - setFolder({ ObjectId: "", Name: "" }); - setFormData({ - Name: "", - Description: "", - Note: "" - }); - setFileUpload([]); - setpercentage(0); - navigate( - "/asmf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/template/" + - res.id - ); - } - } catch (err) { - console.log("err ", err); - setIsErr(true); - } finally { - setIsAlert(true); - setTimeout(() => { - setIsAlert(false); - }, 1000); - setIsSubmit(false); - } - }; - - const handleFolder = (data) => { - setFolder(data); - }; - // const handleSigners = (data) => { - // if (data && data.length > 0) { - // const updateSigners = data.map((x) => ({ - // __type: "Pointer", - // className: "contracts_Contactbook", - // objectId: x - // })); - // setSigners(updateSigners); - // } - // }; - - const handleReset = () => { - setSigners([]); - setFolder({ ObjectId: "", Name: "" }); - setFormData({ - Name: "", - Description: "", - Note: "" - }); - setFileUpload([]); - setpercentage(0); - }; - return ( - <div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50"> - <Title title="New Template" /> - {isAlert && ( - <Alert type={isErr ? "danger" : "success"}> - {isErr - ? "Something went wrong please try again!" - : "Template created successfully!"} - </Alert> - )} - <form onSubmit={handleSubmit}> - <h1 className="text-[20px] font-semibold mb-4">New Template</h1> - {fileload && ( - <div className="flex items-center gap-x-2"> - <div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200"> - <div - className="h-2 rounded-full bg-blue-500" - style={{ width: `${percentage}%` }} - ></div> - </div> - <span className="text-black text-sm">{percentage}%</span> - </div> - )} - <div className="text-xs"> - <label className="block"> - File<span className="text-red-500 text-[13px]">*</span> - </label> - {fileupload.length > 0 ? ( - <div className="flex gap-2 justify-center items-center"> - <div className="flex justify-between items-center px-2 py-2 w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]"> - <div className="break-all"> - file selected : {fileupload?.split("/")[3]?.split("_")[1]} - </div> - <div - onClick={() => { - setFileUpload([]); - }} - className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500" - > - <i className="fa-solid fa-xmark"></i> - </div> - </div> - {process.env.REACT_APP_DROPBOX_API_KEY && ( - <DropboxChooser - onSuccess={dropboxSuccess} - onCancel={dropboxCancel} - /> - )} - </div> - ) : ( - <div className="flex gap-2 justify-center items-center"> - <input - type="file" - className="bg-white px-2 py-1.5 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" - onChange={(e) => handleFileInput(e)} - accept="application/pdf,application/vnd.ms-excel" - required - /> - {process.env.REACT_APP_DROPBOX_API_KEY && ( - <DropboxChooser - onSuccess={dropboxSuccess} - onCancel={dropboxCancel} - /> - )} - </div> - )} - </div> - <div className="text-xs mt-2"> - <label className="block"> - Title<span className="text-red-500 text-[13px]">*</span> - </label> - <input - name="Name" - className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" - value={formData.Name} - onChange={(e) => handleStrInput(e)} - required - /> - </div> - <div className="text-xs mt-2"> - <label className="block"> - Note<span className="text-red-500 text-[13px]">*</span> - </label> - <input - name="Note" - className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" - value={formData.Note} - onChange={(e) => handleStrInput(e)} - required - /> - </div> - <div className="text-xs mt-2"> - <label className="block">Description</label> - <input - name="Description" - className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" - value={formData.Description} - onChange={(e) => handleStrInput(e)} - /> - </div> - {/* <SignersInput onChange={handleSigners} /> */} - <SelectFolder onSuccess={handleFolder} folderCls={templateCls} /> - <div className="flex items-center mt-3 gap-2 text-white"> - <button - className={`${ - isSubmit && "cursor-progress" - } bg-[#1ab6ce] rounded-sm shadow-md text-[14px] font-semibold uppercase text-white py-1.5 px-2.5 focus:outline-none`} - type="submit" - disabled={isSubmit} - > - Submit - </button> - <div - className="bg-[#188ae2] rounded-sm shadow-md text-[14px] font-semibold uppercase text-white py-1.5 px-2.5 text-center ml-[2px] focus:outline-none" - onClick={() => handleReset()} - > - Reset - </div> - </div> - </form> - </div> - ); -}; - -export default TemplateForm; diff --git a/apps/OpenSign/src/primitives/Validate.js b/apps/OpenSign/src/primitives/Validate.js new file mode 100644 index 000000000..86993d8b3 --- /dev/null +++ b/apps/OpenSign/src/primitives/Validate.js @@ -0,0 +1,57 @@ +import React, { useState, useEffect } from "react"; +import Parse from "parse"; +import { Outlet, useNavigate, useLocation } from "react-router-dom"; +import ModalUi from "./ModalUi"; +const Validate = () => { + const navigate = useNavigate(); + const location = useLocation(); + const [isUserValid, setIsUserValid] = useState(true); + useEffect(() => { + (async () => { + try { + // Use the session token to validate the user + const userQuery = new Parse.Query(Parse.User); + const user = await userQuery.get(Parse.User.current().id, { + sessionToken: localStorage.getItem("accesstoken") + }); + if (user) { + setIsUserValid(true); + } else { + setIsUserValid(false); + } + } catch (error) { + // Session token is invalid or there was an error + setIsUserValid(false); + } + })(); + }, []); + const handleLoginBtn = () => { + try { + Parse.User.logOut(); + } catch (err) { + console.log("err ", err); + } finally { + localStorage.removeItem("accesstoken"); + navigate("/", { replace: true, state: { from: location } }); + } + }; + return isUserValid ? ( + <div> + <Outlet /> + </div> + ) : ( + <ModalUi title={"Session Expired"} isOpen={true} showClose={false}> + <div className="flex flex-col justify-center items-center py-4 md:py-5 gap-5"> + <p className="text-xl font-normal">Your session has expired.</p> + <button + onClick={handleLoginBtn} + className="text-base px-3 py-1.5 rounded shadow-md text-white bg-[#1ab6ce]" + > + Login + </button> + </div> + </ModalUi> + ); +}; + +export default Validate; diff --git a/apps/OpenSign/src/primitives/ValidateRoute.js b/apps/OpenSign/src/primitives/ValidateRoute.js index 62202dfe6..9c4f01e07 100644 --- a/apps/OpenSign/src/primitives/ValidateRoute.js +++ b/apps/OpenSign/src/primitives/ValidateRoute.js @@ -1,7 +1,7 @@ import React, { useEffect } from "react"; import Parse from "parse"; - -const ValidateRoute = ({ children }) => { +import { Outlet } from "react-router-dom"; +const ValidateRoute = () => { useEffect(() => { (async () => { try { @@ -28,7 +28,7 @@ const ValidateRoute = ({ children }) => { localStorage.removeItem("accesstoken"); } }; - return <div>{children}</div>; + return <div>{<Outlet />}</div>; }; export default ValidateRoute; diff --git a/apps/OpenSign/src/primitives/sanitizeFileName.js b/apps/OpenSign/src/primitives/sanitizeFileName.js index 0d0be1abc..7c1126e35 100644 --- a/apps/OpenSign/src/primitives/sanitizeFileName.js +++ b/apps/OpenSign/src/primitives/sanitizeFileName.js @@ -1,5 +1,7 @@ function sanitizeFileName(fileName) { // Remove spaces and invalid characters - return fileName.replace(/[^a-zA-Z0-9._-]/g, ""); + const file = fileName.replace(/[^a-zA-Z0-9._-]/g, ""); + const removedot = file.replace(/\.(?=.*\.)/g, ""); + return removedot.replace(/[^a-zA-Z0-9._-]/g, ""); } export default sanitizeFileName; diff --git a/apps/OpenSign/src/redux/actions/index.js b/apps/OpenSign/src/redux/actions/index.js index afec8161d..3e9e2816a 100644 --- a/apps/OpenSign/src/redux/actions/index.js +++ b/apps/OpenSign/src/redux/actions/index.js @@ -124,8 +124,7 @@ export const login = (username, password) => async (dispatch) => { const currentUser = Parse.User.current(); await Parse.Cloud.run("getUserDetails", { email: currentUser.get("email") - }) - .then( + }).then( (results) => { let userinfo = results.toJSON(); if (userinfo.TenantId) { @@ -215,95 +214,10 @@ export const fetchRoleEnum = (name) => async (dispatch) => { dispatch({ type: "FETCH_ROLE", payload: response }); }; -export const setEnableCart = (val) => async (dispatch) => { - dispatch({ - type: "ENABLE_CART", - payload: val - }); -}; - -export const setCartUpdateData = (val) => async (dispatch) => { - dispatch({ - type: "UPDATE_CART", - payload: val - }); -}; - -export const addItemsToCart = (val) => async (dispatch) => { - dispatch({ - type: "ADD_CART", - payload: val - }); -}; - -export const clearCartData = () => async (dispatch) => { - dispatch({ - type: "CLEAR_CART", - payload: [] - }); -}; - -export const SaveMultipleCart = (val) => async (dispatch) => { - dispatch({ - type: "MULTI_CART", - payload: val - }); -}; - -export const removeFromCart = (val) => async (dispatch) => { - dispatch({ - type: "REMOVE_CART", - payload: val - }); -}; - -export const onChangeLevel1Dropdown = (id, name) => async (dispatch) => { - localStorage.setItem(`_dd${name}`, id); - let _data = { [name]: `${id}` }; - dispatch({ type: "Level1_Dropdown", payload: _data }); -}; - -export const onChangeLevel2Dropdown = (id, name) => async (dispatch) => { - localStorage.setItem(`_dd${name}`, id); - let _data = { [name]: `${id}` }; - dispatch({ type: "Level2_Dropdown", payload: _data }); -}; - -export const onChangeLevel3Dropdown = (id, name) => async (dispatch) => { - localStorage.setItem(`_dd${name}`, id); - let _data = { [name]: `${id}` }; - dispatch({ type: "Level3_Dropdown", payload: _data }); -}; - -export const removeState = () => async (dispatch) => { - dispatch({ type: "REMOVE_STATE", payload: {} }); -}; -export const removeLevel2State = () => async (dispatch) => { - dispatch({ type: "removeLevel2", payload: {} }); -}; - -export const removeLevel3State = () => async (dispatch) => { - dispatch({ type: "removeLevel3", payload: {} }); -}; - export const showTenantName = (name) => async (dispatch) => { dispatch({ type: "SHOW_TENANT", payload: name || null }); }; -export const saveDependantDDValue = (id, value) => async (dispatch) => { - let _data = { [`${id}_dd`]: value }; - dispatch({ type: "SAVE_DEPENDANTDD", payload: _data }); -}; - -export const removeDependantDDValue = (id, value) => async (dispatch) => { - let _data = { [`${id}_dd`]: value }; - dispatch({ type: "REMOVE_DEPENDANTDD", payload: _data }); -}; - -export const remove_AlldependantDD = () => async (dispatch) => { - dispatch({ type: "REMOVE_ALLDEPENDANTDD", payload: {} }); -}; - export const save_tourSteps = (steps) => async (dispatch) => { dispatch({ type: "SAVE_TOURSTEPS", payload: steps }); }; diff --git a/apps/OpenSign/src/routes/Dashboard.js b/apps/OpenSign/src/routes/Dashboard.js index 2bc3d9bc7..e381cf364 100644 --- a/apps/OpenSign/src/routes/Dashboard.js +++ b/apps/OpenSign/src/routes/Dashboard.js @@ -24,7 +24,7 @@ const Dashboard = (props) => { getDashboard(localStorage.getItem("PageLanding")); } } else { - navigate("/", { replace: true }); + navigate("/", { replace: true, state: { from: location } }); } // eslint-disable-next-line }, [id]); diff --git a/apps/OpenSign/src/routes/ForgetPassword.js b/apps/OpenSign/src/routes/ForgetPassword.js index 86cb9a6a8..e77ee1149 100644 --- a/apps/OpenSign/src/routes/ForgetPassword.js +++ b/apps/OpenSign/src/routes/ForgetPassword.js @@ -4,13 +4,15 @@ import { fetchAppInfo, forgetPassword } from "../redux/actions"; import Title from "../components/Title"; import { NavLink } from "react-router-dom"; import login_img from "../assets/images/login_img.svg"; - +import Parse from "parse"; +import Alert from "../primitives/Alert"; function ForgotPassword(props) { const [state, setState] = useState({ email: "", password: "", hideNav: "" }); + const [sentStatus, setSentStatus] = useState(""); const handleChange = (event) => { const { name, value } = event.target; setState({ ...state, [name]: value }); @@ -23,7 +25,7 @@ function ForgotPassword(props) { } }; - const handleSubmit = (event) => { + const handleSubmit = async (event) => { event.preventDefault(); localStorage.setItem("appLogo", props.appInfo.applogo); localStorage.setItem("appName", props.appInfo.appname); @@ -33,9 +35,21 @@ function ForgotPassword(props) { "userSettings", JSON.stringify(props.appInfo.settings) ); - if (state.email) { - props.forgetPassword(state.email); + const username = state.email; + let baseUrl = localStorage.getItem("BaseUrl12"); + let parseAppId = localStorage.getItem("AppID12"); + try { + Parse.serverURL = baseUrl; + Parse.initialize(parseAppId); + await Parse.User.requestPasswordReset(username); + setSentStatus("success"); + } catch (err) { + console.log("err ", err.code); + setSentStatus("failed"); + } finally { + setTimeout(() => setSentStatus(""), 1000); + } } }; @@ -51,6 +65,14 @@ function ForgotPassword(props) { return ( <div className="bg-white"> <Title title="Forgot password page" /> + {sentStatus === "success" && ( + <Alert type="success"> + Reset password link has been sent to your email id + </Alert> + )} + {sentStatus === "failed" && ( + <Alert type={"danger"}>Please setup email adapter </Alert> + )} <div> <div className="md:m-10 lg:m-16 md:p-4 lg:p-10 p-5 bg-[#ffffff] md:border-[1px] md:border-gray-400 "> <div className="w-[250px] h-[66px] inline-block"> diff --git a/apps/OpenSign/src/routes/Form.js b/apps/OpenSign/src/routes/Form.js index 2c6c67709..d6c30fc35 100644 --- a/apps/OpenSign/src/routes/Form.js +++ b/apps/OpenSign/src/routes/Form.js @@ -1,1244 +1,252 @@ -import React, { Component } from "react"; -import { connect } from "react-redux"; -import { - removeState, - removeLevel2State, - removeLevel3State -} from "../redux/actions/index"; -import Engine from "json-rules-engine-simplified"; -import applyRules from "rjsf-conditionals"; -import Form from "@rjsf/core"; -import validator from "@rjsf/validator-ajv8"; -import LayoutField from "../components/fields/Rjsf-layout"; -import "../styles/form.css"; -import "../styles/toast.css"; -import Parse from "parse"; -import "../styles/loader.css"; -import TimeWidget from "../components/fields/TimeWidget"; -import axios from "axios"; +import React, { useState } from "react"; import { useNavigate, useParams } from "react-router-dom"; -import HiddenField from "../components/fields/HiddenField"; -import MultiSelectField from "../components/fields/MultiSelectField"; -import ErrorBoundary from "../components/ErrorBoundary"; -import FileUpload from "../components/fields/FileUpload"; -import TreeWidget from "../components/TreeWidget"; -import parse from "html-react-parser"; -import Title from "../components/Title"; import { formJson } from "../json/FormJson"; -import TemplateForm from "../primitives/TemplateForm"; -const widget = { - TimeWidget: TimeWidget -}; -const fields = () => { - return { - layout: LayoutField, - FileUpload: FileUpload, - HiddenField: HiddenField, - MultiSelectField: MultiSelectField, - FolderComponent: TreeWidget - }; -}; +import AddUser from "../components/AddUser"; +import sanitizeFileName from "../primitives/sanitizeFileName"; +import Parse from "parse"; +import DropboxChooser from "../components/fields/DropboxChoose"; +import Alert from "../primitives/Alert"; +import SelectFolder from "../components/fields/SelectFolder"; +import SignersInput from "../components/fields/SignersInput"; +import Title from "../components/Title"; +import PageNotFound from "./PageNotFound"; -function FormBuilderFn(props) { +function Form() { const { id } = useParams(); - const navigate = useNavigate(); - if (id === "template") { - return <TemplateForm />; + + if (id === "lM0xRnM3iE") { + return <AddUser />; } else { - return ( - <FormBuilder - removeState={props.removeState} - removeLevel2State={props.removeLevel2State} - removeLevel3State={props.removeLevel3State} - id={id} - navigate={navigate} - /> - ); + const config = formJson[id]; + if (config) { + return <Forms {...config} />; + } else { + return <PageNotFound prefix={"Form"} />; + } } } -class FormBuilder extends Component { - state = { - schema: {}, - ui_schema: {}, - extraActions: undefined, - rules: [], - isAppRequest: false, - formData: {}, - persistentFields: [], - successMassage: "Record inserted successfully.", - title: "", - active: true, - buttons: {}, - schemaState: {}, - noValidate: false, - liveValidate: false, - _validate: null, - userSchema: {}, - loading: false, - parseBaseUrl: localStorage.getItem("baseUrl"), - parseAppId: localStorage.getItem("parseAppId"), - toastColor: "#5cb85c", - toastDescription: "", - redirect_type: "", - redirect_id: "", - FormACL: null, - help: "", - link: "" + +const Forms = (props) => { + const navigate = useNavigate(); + const [signers, setSigners] = useState([]); + const [folder, setFolder] = useState({ ObjectId: "", Name: "" }); + const [formData, setFormData] = useState({ + Name: "", + Description: "", + Note: "Please review and sign this document", + TimeToCompleteDays: 15, + SendinOrder: "false" + }); + const [fileupload, setFileUpload] = useState([]); + const [fileload, setfileload] = useState(false); + const [percentage, setpercentage] = useState(0); + const [isAlert, setIsAlert] = useState(false); + const [isSubmit, setIsSubmit] = useState(false); + const [isErr, setIsErr] = useState(""); + const handleStrInput = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); }; - async getForm(id) { - this.setState({ - loading: true - }); + const handleFileInput = (e) => { + setpercentage(0); try { - const results = formJson(id); - // console.log("custom result",results) - if (results) { - const resultjson = results; - if (resultjson.userSchema !== undefined) { - this.setState({ - userSchema: resultjson.userSchema - }); + let files = e.target.files; + if (typeof files[0] !== "undefined") { + const mb = Math.round(files[0].bytes / Math.pow(1024, 2)); + if (mb > 10) { + alert( + `The selected file size is too large. Please select a file less than ${Math.round( + 10 + )} MB` + ); + return; } - for (let [value] of Object.entries(resultjson.jsonSchema.properties)) { - if (typeof value === "object") { - for (let [k, v] of Object.entries(value)) { - if (k === "format" && v === "date") { - let today = new Date(); - let date = - today.getFullYear() + - "-" + - ("0" + (today.getMonth() + 1)).slice(-2) + - "-" + - ("0" + today.getDate()).slice(-2); - value.default = date; - } - if (k === "component" && v === "DateTime") { - value.default = new Date().toISOString(); - } - } - } - } - let txt, - link, - successMsg, - _rules = [], - persistentFields = [], - _extraActions = {}; - if (resultjson.help) { - if (resultjson.help.htmlbody) { - txt = resultjson.help.htmlbody; - } - if (resultjson.help.link) { - link = resultjson.help.link; - } - } - if (resultjson.rules) { - _rules = resultjson.rules; - } - if (resultjson.persistentFields) { - persistentFields = resultjson.persistentFields; - } - if (resultjson.extraActions) { - _extraActions = this.setExtraActions(resultjson.extraActions); - } - if (resultjson.success_message) { - successMsg = resultjson.success_message; - } else { - successMsg = this.state.successMassage; - } - let _jsonSchema = JSON.stringify(resultjson.jsonSchema); - _jsonSchema = _jsonSchema.replace("#$", "$"); - _jsonSchema = _jsonSchema.replace("#*", "$"); - _jsonSchema = _jsonSchema.replace("_DOT_", "."); - let _replaceJSONSchema = JSON.parse(_jsonSchema); - this.setState({ - redirect_type: resultjson.success_redirect, - redirect_id: resultjson.redirect_id, - FormACL: resultjson.formACL, - help: txt, - link: link, - persistentFields: persistentFields, - successMassage: successMsg, - buttons: resultjson.buttons.add, - schemaState: _replaceJSONSchema, - ui_schema: resultjson.uiSchema, - rules: _rules, - extraActions: _extraActions, - title: resultjson.class, - _validate: resultjson.validFunction, - noValidate: resultjson.noValidate, - liveValidate: resultjson.liveValidate && resultjson.liveValidate, - loading: false - }); - localStorage.setItem( - "jsonschema", - JSON.stringify(resultjson.jsonSchema) - ); + handleFileUpload(files[0]); } else { - alert("form not found"); + alert("Please select file."); + return false; } - } catch (e) { - if (e.message === "Invalid session token") { - let appdata = localStorage.getItem("userSettings"); - let applogo = localStorage.getItem("appLogo"); - let appName = localStorage.getItem("appName"); - let defaultmenuid = localStorage.getItem("defaultmenuid"); - let PageLanding = localStorage.getItem("PageLanding"); - let domain = localStorage.getItem("domain"); - let _appName = localStorage.getItem("_appName"); - let baseUrl = localStorage.getItem("BaseUrl12"); - let appid = localStorage.getItem("AppID12"); - localStorage.clear(); - localStorage.setItem("appLogo", applogo); - localStorage.setItem("appName", appName); - localStorage.setItem("_appName", _appName); - localStorage.setItem("defaultmenuid", defaultmenuid); - localStorage.setItem("PageLanding", PageLanding); - localStorage.setItem("domain", domain); - localStorage.setItem("userSettings", appdata); - localStorage.setItem("BaseUrl12", baseUrl); - localStorage.setItem("AppID12", appid); - this.props.navigate(`/`); - } - console.log(e.message); - console.error("Problem", e); - this.setState({ - loading: false - }); - } - } - - wrap = (s) => "{ return " + s + " };"; - - // func = new Function(wrap(body)); - - dynamicValidate = (formData, errors) => { - try { - let body = atob(this.state._validate); - let res = new Function(this.wrap(body)) - .call(null) - .call(null, formData, errors); - return res; } catch (error) { - console.log(error); + alert(error.message); + return false; } }; - setExtraActions = (actions) => { + const handleFileUpload = async (file) => { + Parse.serverURL = process.env.REACT_APP_SERVERURL; + Parse.initialize(process.env.REACT_APP_APPID); + setfileload(true); + const fileName = file.name; + const name = sanitizeFileName(fileName); + const pdfFile = file; + const parseFile = new Parse.File(name, pdfFile); + try { - let result = {}; - Object.entries(actions).forEach(([key, value]) => { - let body = atob(value); - let res = new Function(this.wrap(body)).call(null); - result[key] = res; + const response = await parseFile.save({ + progress: (progressValue, loaded, total, { type }) => { + if (type === "upload" && progressValue !== null) { + const percentCompleted = Math.round((loaded * 100) / total); + setpercentage(percentCompleted); + } + } }); - return result; + + // The response object will contain information about the uploaded file + // You can access the URL of the uploaded file using response.url() + setFileUpload(response.url()); + setfileload(false); + if (response.url()) { + return response.url(); + } } catch (error) { - console.log(error); + setfileload(false); + setpercentage(0); + console.error("Error uploading file:", error); } }; - handleSubmit = async ({ formData }) => { - this.setState({ active: false, loading: true }); - if ( - this.state.userSchema && - Object.entries(this.state.userSchema).length !== 0 && - this.state.userSchema.constructor === Object - ) { - try { - let RowData = formData; - RowData && - Object.entries(RowData).forEach(([key, value]) => { - if (typeof value === "string") { - RowData[key] = value.trim(); - } - }); - let UserData = {}; - let RoleField = ""; - let _scanData = this.state.schemaState; - if (_scanData.dependencies) { - Object.keys(_scanData.dependencies).forEach((key) => { - if (_scanData.dependencies[key].oneOf) { - _scanData.dependencies[key].oneOf.forEach((val) => { - Object.keys(val.properties).forEach((k) => { - if (typeof val.properties[k] === "object") { - if (val.properties[k].format === "date") { - if (RowData[k]) { - let newdate = new Date(RowData[k]); - RowData[k] = newdate; - } - } - if (val.properties[k].component === "HtmlEditor") { - if (RowData[k]) { - let newHtml = RowData[k] - .replace(/<p[^>]*>/g, "") - .replace(/<\/p>/g, " "); - RowData[k] = newHtml; - } - } - if (val.properties[k].component === "DateTime") { - if (RowData[k]) { - let newDate11 = new Date(RowData[k]); - RowData[k] = newDate11; - } - } - if (val.properties[k].component === "CurrencyInput") { - if (val.properties[k].currencyColumn) { - RowData[`${val.properties[k].currencyColumn}`] = - val.properties[k].defaultcurrency; - } - } - if (val.properties[k].type === "string") { - if (typeof RowData[k] === "string") - RowData[k] = RowData[k].trim(); - } - if (val.properties[k].data !== undefined) { - if (val.properties[k].data.isPointer) { - let pointer = undefined; - if (val.properties[k].data.class) { - if (val.properties[k].data.savePointerClass) { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: - val.properties[k].data.savePointerClass, - objectId: RowData[k] - }; - } - } else { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: val.properties[k].data.class, - objectId: RowData[k] - }; - } - } - } else { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: localStorage.getItem("extended_class"), - objectId: RowData[k] - }; - } - } - RowData[k] = pointer; - } - if (val.properties[k].data.FolderTypeValue) { - if (RowData[k]) { - let obj = { - __type: "Pointer", - className: val.properties[k].data.ClassName, - objectId: RowData[k] - }; - RowData[k] = obj; - } - } - } - } - }); - }); - } - }); - } - let _userScheama = this.state.userSchema; - Object.keys(_scanData).forEach(function (key) { - let _dd = _scanData[key]; - typeof _dd === "object" && - Object.keys(_dd).forEach(function (k) { - if (_dd[k].type === "array" && _dd[k].items) { - let _prop = _dd[k].items.properties; + const dropboxSuccess = async (files) => { + setfileload(true); + const file = files[0]; + const url = file.link; + const mb = Math.round(file.bytes / Math.pow(1024, 2)); - if (_prop && Array.isArray(RowData[k])) { - let newRow = []; - RowData[k].forEach((t) => { - let _newObj = t; - if (typeof t === "object") { - Object.keys(_prop).forEach(function (l) { - if (_prop[l].data && _prop[l].data.isPointer) { - if (typeof t[l] === "object") { - let obj = { - __type: "Pointer", - className: _prop[l].data.class, - objectId: t[l].objectId - }; - _newObj = { ..._newObj, [l]: obj }; - } else { - let obj = { - __type: "Pointer", - className: _prop[l].data.class, - objectId: t[l] - }; - _newObj = { ..._newObj, [l]: obj }; - } - } - }); - } - newRow.push(_newObj); - }); - RowData[k] = newRow; - } - } - - if (_dd[k].component === "AutoSuggest" && _dd[k].isPointer) { - if (RowData[k]) { - let pointer = { - __type: "Pointer", - className: _dd[k].class, - objectId: RowData[k] - }; - RowData[k] = pointer; - } - } - if (_dd[k].format === "date") { - let newdate = new Date(RowData[k]); - RowData[k] = newdate; - } - if (_dd[k].component === "CurrencyInput") { - RowData[`${_dd[k].currencyColumn}`] = _dd[k].defaultcurrency; - } - if (_dd[k].component === "HtmlEditor") { - if (RowData[k]) { - let newHtml = RowData[k] - .replace(/<p[^>]*>/g, "") - .replace(/<\/p>/g, " "); - RowData[k] = newHtml; - } - } - if (_dd[k].component === "DateTime") { - let newDate; - if (!RowData[k]) { - newDate = new Date(); - } else { - newDate = new Date(RowData[k]); - } - RowData[k] = newDate; - } - if (_dd[k].data !== undefined) { - if (_dd[k].data.isPointer) { - let pointer = undefined; - if (_dd[k].data.savePointerClass) { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: _dd[k].data.savePointerClass, - objectId: RowData[k] - }; - RowData[k] = pointer; - } - } else if (RowData[k]) { - if (_dd[k].data.class) { - pointer = { - __type: "Pointer", - className: _dd[k].data.class, - objectId: RowData[k] - }; - } else { - pointer = { - __type: "Pointer", - className: localStorage.getItem("extended_class"), - objectId: RowData[k] - }; - } - - RowData[k] = pointer; - } - } - if (_dd[k].data.FolderTypeValue) { - if (RowData[k]) { - let obj = { - __type: "Pointer", - className: _dd[k].data.ClassName, - objectId: RowData[k] - }; - RowData[k] = obj; - } - } - } - if (_dd[k].type === "string") { - let d = RowData[k]; - if (typeof d === "string") { - RowData[k] = d.trim(); - } - } - }); - }); - - Object.keys(_userScheama).forEach(function (kkey) { - Object.keys(RowData).forEach(function (_k) { - if (_userScheama[kkey].startsWith("$")) { - let _uuu = _userScheama[kkey].replace("$", ""); - if (kkey === "Role" || kkey === "role") { - if (RowData[_uuu] === RowData[_k]) { - RoleField = RowData[_uuu]; - } - } else if (_uuu === _k) { - UserData[kkey] = RowData[_k]; - } - } else { - RoleField = _userScheama[kkey]; - } - }); - }); - Parse.serverURL = this.state.parseBaseUrl; - Parse.initialize(this.state.parseAppId); - var _users = Parse.Object.extend("User"); - var _user = new _users(); - let _uname = UserData.name; - _user.set("name", _uname.toString().trim()); - if (UserData.username) { - let _u_un = UserData.username; - _user.set("username", _u_un.toString().trim()); - if (UserData.email) { - let _email = UserData.email; - _user.set("email", _email.trim()); - } - } else if (UserData.email) { - let _email = UserData.email; - _user.set("email", _email.trim()); - _user.set("username", _email.trim()); - } else { - _user.set("username", UserData.phone.toString().trim()); - } - _user.set("phone", UserData.phone); - _user.set("password", UserData.password); - _user.save().then( - (u) => { - let roleurl = `${this.state.parseBaseUrl}functions/AddUserToRole`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": this.state.parseAppId, - sessionToken: localStorage.getItem("accesstoken") - }; - let body = { - appName: localStorage.getItem("_appName"), - roleName: RoleField, - userId: u.id - }; - axios.post(roleurl, body, { headers: headers }).then(() => { - const currentUser = Parse.User.current(); - let _fname = this.state.title; - var forms = Parse.Object.extend(_fname); - var form = new forms(); - form.set( - "CreatedBy", - Parse.User.createWithoutData(currentUser.id) - ); - if (localStorage.getItem("TenetId")) { - form.set("TenantId", { - __type: "Pointer", - className: "partners_Tenant", - objectId: localStorage.getItem("TenetId") - }); - } - form.set("UserId", u); - form.set("UserRole", RoleField); - if (this.state["FormACL"]) { - let ACL = {}; - for (let [key, value] of Object.entries( - this.state["FormACL"] - )) { - if (key === "*") { - ACL[key] = value; - } - if (key === "#currentUser#") { - ACL[Parse.User.current().id] = value; - } - if (key.startsWith("role")) { - ACL[key] = value; - } - } - form.setACL(new Parse.ACL(ACL)); - } - form.save(RowData).then( - () => { - let filtered = {}; - if (this.state.redirect_type === "clearData") { - if ( - this.state.persistentFields && - this.state.persistentFields.length - ) { - filtered = Object.keys(RowData) - .filter((key) => - this.state.persistentFields.includes(key) - ) - .reduce((obj, key) => { - obj[key] = RowData[key]; - return obj; - }, {}); - } - } else { - RowData = {}; - } - this.setState( - { - formData: filtered, - active: true, - loading: false, - toastColor: "#5cb85c", - toastDescription: this.state.successMassage - }, - () => { - let redirect_type = this.state.redirect_type; - let redirect_id = this.state.redirect_id; - this.props.removeState(); - this.props.removeLevel2State(); - this.props.removeLevel3State(); - var x = document.getElementById("snackbar"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - if (redirect_type === "Form") { - this.props.navigate(`/form/${redirect_id}`); - } else if (redirect_type === "Report") { - this.props.navigate(`/report/${redirect_id}`); - } else if (redirect_type === "Dashboard") { - this.props.navigate(`/dashboard/${redirect_id}`); - } else if (redirect_type === "Url") { - window.location = redirect_id; - } else if (redirect_type === "Microapp") { - this.props.navigate(`/asmf/${redirect_id}`); - } - }, 2000); - } - ); - }, - (error) => { - console.log("error", error.message); - this.setState({ - loading: false, - active: true, - toastColor: "#d9534f", - toastDescription: error.message - }); - - var x = document.getElementById("snackbar"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 2000); - } - ); - }); - }, - async (error) => { - if (error.code === 202) { - let params; - if (UserData.username) { - params = { username: UserData.username }; - } else if (UserData.email) { - params = { email: UserData.email }; - } else { - params = { username: UserData.phone }; - } - const userRes = await Parse.Cloud.run("getUserId", params); - try { - let _emp = { - __type: "Pointer", - className: "_User", - objectId: userRes.id - }; - let roleurl = `${this.state.parseBaseUrl}functions/AddUserToRole`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": this.state.parseAppId, - sessionToken: localStorage.getItem("accesstoken") - }; - let body = { - appName: localStorage.getItem("_appName"), - roleName: RoleField, - userId: userRes.id - }; - await axios - .post(roleurl, body, { headers: headers }) - .then(() => { - const currentUser = Parse.User.current(); - let _fname = this.state.title; - var forms = Parse.Object.extend(_fname); - var form = new forms(); - form.set( - "CreatedBy", - Parse.User.createWithoutData(currentUser.id) - ); - if (localStorage.getItem("TenetId")) { - form.set("TenantId", { - __type: "Pointer", - className: "partners_Tenant", - objectId: localStorage.getItem("TenetId") - }); - } - form.set("UserId", _emp); - form.set("UserRole", RoleField); - if (this.state["FormACL"]) { - let ACL = {}; - for (let [key, value] of Object.entries( - this.state["FormACL"] - )) { - if (key === "*") { - ACL[key] = value; - } - if (key === "#currentUser#") { - ACL[Parse.User.current().id] = value; - } - if (key.startsWith("role")) { - ACL[key] = value; - } - } - form.setACL(new Parse.ACL(ACL)); - } - form.save(RowData).then( - () => { - let filtered = {}; - if (this.state.redirect_type === "clearData") { - if ( - this.state.persistentFields && - this.state.persistentFields.length - ) { - filtered = Object.keys(RowData) - .filter((key) => - this.state.persistentFields.includes(key) - ) - .reduce((obj, key) => { - obj[key] = RowData[key]; - return obj; - }, {}); - } - } else { - RowData = {}; - } - this.setState( - { - formData: filtered, - active: true, - loading: false, - toastColor: "#5cb85c", - toastDescription: this.state.successMassage - }, - () => { - let redirect_type = this.state.redirect_type; - let redirect_id = this.state.redirect_id; - this.props.removeState(); - this.props.removeLevel2State(); - this.props.removeLevel3State(); - var x = document.getElementById("snackbar"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - if (redirect_type === "Form") { - this.props.navigate(`/form/${redirect_id}`); - } else if (redirect_type === "Report") { - this.props.navigate(`/report/${redirect_id}`); - } else if (redirect_type === "Dashboard") { - this.props.navigate( - `/dashboard/${redirect_id}` - ); - } else if (redirect_type === "Url") { - window.location = redirect_id; - } else if (redirect_type === "Microapp") { - this.props.navigate(`/asmf/${redirect_id}`); - } - }, 2000); - } - ); - }, - (error) => { - this.setState({ - loading: false, - active: true, - toastColor: "#d9534f", - toastDescription: error.message - }); - - var x = document.getElementById("snackbar"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 2000); - } - ); - }); - } catch (error) { - this.setState({ - loading: false, - active: true, - toastColor: "#d9534f", - toastDescription: error.message - }); - - var x = document.getElementById("snackbar"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 2000); - } - } - } + if (mb > 10) { + setTimeout(() => { + alert( + `The selected file size is too large. Please select a file less than 10 MB` ); - } catch (e) { - console.log("Problem", e.message); - this.setState({ loading: false, active: true }); - } + }, 500); + return; } else { + const name = sanitizeFileName(file.name); + + const parseFile = new Parse.File(name, { uri: url }); + try { - let RowData = formData; - let _scanData = this.state.schemaState; - if (_scanData.dependencies) { - Object.keys(_scanData.dependencies).forEach((key) => { - if (_scanData.dependencies[key].oneOf) { - _scanData.dependencies[key].oneOf.forEach((val) => { - Object.keys(val.properties).forEach((k) => { - if (typeof val.properties[k] === "object") { - if (val.properties[k].format === "date") { - if (RowData[k]) { - let newdate = new Date(RowData[k]); - RowData[k] = newdate; - } - } - if (val.properties[k].component === "HtmlEditor") { - if (RowData[k]) { - let newHtml = RowData[k] - .replace(/<p[^>]*>/g, "") - .replace(/<\/p>/g, " "); - RowData[k] = newHtml; - } - } - if (val.properties[k].component === "DateTime") { - if (RowData[k]) { - let newDate11 = new Date(RowData[k]); - RowData[k] = newDate11; - } - } - if (val.properties[k].component === "CurrencyInput") { - if (val.properties[k].currencyColumn) { - RowData[`${val.properties[k].currencyColumn}`] = - val.properties[k].defaultcurrency; - } - } - if (val.properties[k].type === "string") { - if (typeof RowData[k] === "string") - RowData[k] = RowData[k].trim(); - } - if (val.properties[k].data !== undefined) { - if (val.properties[k].data.isPointer) { - let pointer = undefined; - if (val.properties[k].data.savePointerClass) { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: - val.properties[k].data.savePointerClass, - objectId: RowData[k] - }; - } - } else if (val.properties[k].data.class) { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: val.properties[k].data.class, - objectId: RowData[k] - }; - } - } else { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: localStorage.getItem("extended_class"), - objectId: RowData[k] - }; - } - } - - RowData[k] = pointer; - } - if (val.properties[k].data.FolderTypeValue) { - if (RowData[k]) { - let obj = { - __type: "Pointer", - className: val.properties[k].data.ClassName, - objectId: RowData[k] - }; - RowData[k] = obj; - } - } - } - } - }); - }); + const response = await parseFile.save({ + progress: (progressValue, loaded, total, { type }) => { + if (type === "upload" && progressValue !== null) { + const percentCompleted = Math.round((loaded * 100) / total); + setpercentage(percentCompleted); } - }); - } - Object.keys(_scanData).forEach(function (key) { - let _dd = _scanData[key]; - if (typeof _dd === "object") { - Object.keys(_dd).forEach(function (k) { - if (_dd[k].type === "array" && _dd[k].items) { - let _prop = _dd[k].items.properties; - if (_prop && Array.isArray(RowData[k])) { - let newRow = []; - RowData[k].forEach((t) => { - let _newObj = t; - if (typeof t === "object") { - Object.keys(_prop).forEach(function (l) { - if (_prop[l].data && _prop[l].data.isPointer) { - if (typeof t[l] === "object") { - let obj = { - __type: "Pointer", - className: _prop[l].data.class, - objectId: t[l].objectId - }; - _newObj = { ..._newObj, [l]: obj }; - } else { - let obj = { - __type: "Pointer", - className: _prop[l].data.class, - objectId: t[l] - }; - _newObj = { ..._newObj, [l]: obj }; - } - } - }); - } - newRow.push(_newObj); - }); - RowData[k] = newRow; - } - } - - if (_dd[k].component === "AutoSuggest" && _dd[k].isPointer) { - if (RowData[k]) { - let pointer = { - __type: "Pointer", - className: _dd[k].class, - objectId: RowData[k] - }; - RowData[k] = pointer; - } - } - if (_dd[k].format === "date") { - let newdate = new Date(RowData[k]); - RowData[k] = newdate; - } - if (_dd[k].component === "HtmlEditor") { - if (RowData[k]) { - let newHtml = RowData[k] - .replace(/<p[^>]*>/g, "") - .replace(/<\/p>/g, " "); - RowData[k] = newHtml; - } - } - if (_dd[k].component === "DateTime") { - let newDate11; - if (!RowData[k]) { - newDate11 = new Date(); - } else { - newDate11 = new Date(RowData[k]); - } - RowData[k] = newDate11; - } - if (_dd[k].component === "CurrencyInput") { - if (_dd[k].currencyColumn) { - RowData[`${_dd[k].currencyColumn}`] = _dd[k].defaultcurrency; - } - } - if (_dd[k].data !== undefined) { - if (_dd[k].data.isPointer) { - let pointer = undefined; - if (RowData[k] && RowData[k] !== "Select") { - if (_dd[k].type === "array") { - pointer = []; - RowData[k] && - RowData[k].forEach((a) => { - let _kk = {}; - if (_dd[k].data.savePointerClass) { - _kk = { - __type: "Pointer", - className: _dd[k].data.savePointerClass, - objectId: a - }; - } else { - _kk = { - __type: "Pointer", - className: _dd[k].data.class, - objectId: a - }; - } - - pointer.push(_kk); - }); - } else if (_dd[k].data.class) { - if (_dd[k].data.savePointerClass) { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: _dd[k].data.savePointerClass, - objectId: RowData[k] - }; - } - } else if (RowData[k]) { - pointer = { - __type: "Pointer", - className: _dd[k].data.class, - objectId: RowData[k] - }; - } - } else { - if (RowData[k]) { - pointer = { - __type: "Pointer", - className: localStorage.getItem("extended_class"), - objectId: RowData[k] - }; - } - } - - RowData[k] = pointer; - } - } - if (_dd[k].data.FolderTypeValue) { - if (RowData[k]) { - let obj = { - __type: "Pointer", - className: _dd[k].data.ClassName, - objectId: RowData[k] - }; - RowData[k] = obj; - } - } - } - if (_dd[k].type === "string") { - let d = RowData[k]; - if (typeof d === "string") { - RowData[k] = d.trim(); - } - } - }); } }); - Parse.serverURL = this.state.parseBaseUrl; - Parse.initialize(this.state.parseAppId); - const currentUser = Parse.User.current(); - let _fname = this.state.title; - var forms = Parse.Object.extend(_fname); + setFileUpload(response.url()); + setfileload(false); - var form = new forms(); - - form.set("CreatedBy", Parse.User.createWithoutData(currentUser.id)); - - if (this.state["FormACL"]) { - let ACL = {}; - for (let [key, value] of Object.entries(this.state["FormACL"])) { - if (key === "*") { - ACL[key] = value; - } - if (key === "#currentUser#") { - ACL[Parse.User.current().id] = value; - } else if (key.startsWith("#")) { - let arr = key.split("#"); - let new_arr = arr.filter((x) => x !== ""); - if (new_arr.length === 2) { - let l = RowData[new_arr[0]]; - try { - const Agent = Parse.Object.extend(l.className); - const qu = new Parse.Query(Agent); - qu.equalTo("objectId", l.objectId); - qu.include(new_arr[1]); - await qu.first(); - } catch (err) { - console.error("Error while fetching Agent", err.massage); - } - } - } - if (key.startsWith("role")) { - ACL[key] = value; - } - } - form.setACL(new Parse.ACL(ACL)); + if (response.url()) { + return response.url(); } - - form.save(RowData).then( - (form) => { - let filtered = {}; - if (this.state.redirect_type === "clearData") { - if ( - this.state.persistentFields && - this.state.persistentFields.length - ) { - filtered = Object.keys(RowData) - .filter((key) => this.state.persistentFields.includes(key)) - .reduce((obj, key) => { - obj[key] = RowData[key]; - return obj; - }, {}); - } - } else { - RowData = {}; - } - - this.setState( - { - formData: filtered, - active: true, - loading: false, - toastColor: "#5cb85c", - toastDescription: this.state.successMassage - }, - () => { - let redirect_type = this.state.redirect_type; - let redirect_id = this.state.redirect_id; - var x = document.getElementById("snackbar"); - this.props.removeState(); - this.props.removeLevel2State(); - this.props.removeLevel3State(); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 2000); - if (redirect_type === "Form") { - this.props.navigate(`/form/${redirect_id}`); - } else if (redirect_type === "Report") { - this.props.navigate(`/report/${redirect_id}`); - } else if (redirect_type === "Dashboard") { - this.props.navigate(`/dashboard/${redirect_id}`); - } else if (redirect_type === "Url") { - window.location = redirect_id; - } else if (redirect_type === "Microapp") { - window.localStorage.setItem( - "rowlevel", - JSON.stringify({ ...formData, ...form }) - ); - this.props.navigate(`/asmf/${redirect_id}`); - } - } - ); - }, - (error) => { - this.setState({ - loading: false, - active: true, - toastColor: "#d9534f", - toastDescription: error.message - }); - - var x = document.getElementById("snackbar"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 2000); - } - ); } catch (error) { - this.setState({ - loading: false, - active: true, - toastColor: "#d9534f", - toastDescription: error.message - }); - - var x = document.getElementById("snackbar"); - x.className = "show"; - setTimeout(function () { - x.className = x.className.replace("show", ""); - }, 2000); + setfileload(false); + setpercentage(0); + console.error("Error uploading file:", error); } } }; + const dropboxCancel = async () => {}; + const handleSubmit = async (e) => { + e.preventDefault(); + e.stopPropagation(); + setIsSubmit(true); + try { + const currentUser = Parse.User.current(); + const object = new Parse.Object(props.Cls); + object.set("Name", formData?.Name); + object.set("Description", formData?.Description); + object.set("Note", formData?.Note); + if (props.title === "Request Signatures") { + object.set( + "TimeToCompleteDays", + parseInt(formData?.TimeToCompleteDays) + ); + const isChecked = formData.SendinOrder === "true" ? true : false; + object.set("SendinOrder", isChecked); + } + object.set("URL", fileupload); + object.set("CreatedBy", Parse.User.createWithoutData(currentUser.id)); + if (folder && folder.ObjectId) { + object.set("Folder", { + __type: "Pointer", + className: props.Cls, + objectId: folder.ObjectId + }); + } + if (signers && signers.length > 0) { + object.set("Signers", signers); + } + const ExtCls = JSON.parse(localStorage.getItem("Extand_Class")); + object.set("ExtUserPtr", { + __type: "Pointer", + className: "contracts_Users", + objectId: ExtCls[0].objectId + }); - saveUrlParamToFormdata = () => { - let url = window.location.hash; - let paramString = url.split("?")[1]; - let queryString = new URLSearchParams(paramString); - let obj = {}; - for (const [key, value] of queryString.entries()) { - obj = { ...obj, [key]: value }; + const res = await object.save(); + if (res) { + setSigners([]); + setFolder({ ObjectId: "", Name: "" }); + setFormData({ + Name: "", + Description: "", + Note: "" + }); + setFileUpload([]); + setpercentage(0); + navigate( + `/asmf/remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/${props?.redirectRoute}/${res.id}` + ); + } + } catch (err) { + console.log("err ", err); + setIsErr(true); + } finally { + setIsAlert(true); + setTimeout(() => { + setIsAlert(false); + }, 1000); + setIsSubmit(false); } - this.setState({ formData: obj }); }; - componentDidMount() { - let url = window.location.hash; - if (url.includes("_app")) { - this.setState({ isAppRequest: true }); + const handleFolder = (data) => { + setFolder(data); + }; + const handleSigners = (data) => { + if (data && data.length > 0) { + const updateSigners = data.map((x) => ({ + __type: "Pointer", + className: "contracts_Contactbook", + objectId: x + })); + setSigners(updateSigners); } - let id = this.props.id; - this.getForm(id); - this.saveUrlParamToFormdata(); - } + }; - UNSAFE_componentWillReceiveProps(newProps) { - let id = newProps.id; - this.getForm(id); - } - - render() { - if (localStorage.getItem("accesstoken") === null) { - this.props.navigate(`/`); - } - - let schema = this.state.schemaState; - let uiSchema = this.state.ui_schema; - let rules = this.state.rules; - let extraActions = this.state.extraActions; - - let FormToDisplay = applyRules( - schema, - uiSchema, - rules, - Engine, - extraActions - )(Form); - let formView = ( - <React.Fragment> - <FormToDisplay - validate={this.state.noValidate && this.dynamicValidate} - showErrorList={false} - widgets={widget} - fields={fields()} - formData={this.state.formData} - liveValidate={this.state.liveValidate} - onSubmit={this.handleSubmit} - validator={validator} - > - <div> - {this.state.active && this.state.buttons.submitText ? ( - <button className="btn btn-info submiBtn" type="submit"> - {this.state.buttons.submitText} - </button> - ) : ( - this.state.buttons.submitText && ( - <button className="btn submiBtn" type="submit" disabled> - {this.state.buttons.submitText} - </button> - ) - )} -    - {this.state.buttons.resetText && ( - <button - className="btn resetBtn" - onClick={(e) => { - e.preventDefault(); - this.setState({ - loading: true, - formData: {} - }); - setTimeout(() => { - this.setState({ loading: false }); - }, 1000); - }} - type="button" - > - {this.state.buttons.resetText} - </button> - )} - </div> - </FormToDisplay> - </React.Fragment> - ); - - if (this.state.loading) { - formView = ( + const handleReset = () => { + setSigners([]); + setFolder({ ObjectId: "", Name: "" }); + setFormData({ + Name: "", + Description: "", + Note: "" + }); + setFileUpload([]); + setpercentage(0); + }; + return ( + <div className="shadow-md rounded my-2 p-3 bg-[#ffffff] md:border-[1px] md:border-gray-600/50"> + <Title title={props?.title} /> + {isAlert && ( + <Alert type={isErr ? "danger" : "success"}> + {isErr + ? "Something went wrong please try again!" + : `${props.msgVar} created successfully!`} + </Alert> + )} + {isSubmit ? ( <div style={{ height: "300px" }}> <div style={{ @@ -1250,85 +258,162 @@ class FormBuilder extends Component { className="loader-37" ></div> </div> - ); - } - return ( - <React.Fragment> - <Title - title={ - this.state.schemaState.title ? this.state.schemaState.title : "" - } - /> - <ErrorBoundary> - <div className="row"> - <div className="col-md-12"> - <div className="card"> - <div className="card-body no-padding height-9"> - {this.state.help ? ( - <div className="dropdown" style={{ marginTop: "-30px" }}> - <i - className="far fa-question-circle dropdown-toggle hovereffect" - aria-hidden="true" - id="dropdownMenuButton" - data-toggle="dropdown" - aria-haspopup="true" - aria-expanded="false" - style={{ - fontSize: "18px", - color: "purple", - cursor: "pointer !important", - position: "relative", - top: "40px", - left: "98%" - }} - ></i> - <div - className="dropdown-menu" - aria-labelledby="dropdownMenuButton" - style={{ - marginleft: "-121px", - margintop: "-14px", - position: "absolute", - padding: "10px", - width: "300px", - top: "102px!important" - }} - > - {parse(` - ${this.state.help} - `)} - <br /> - {this.state.link ? ( - <a - onClick={(e) => { - e.preventDefault(); - window.location.href = this.state.link; - }} - target="_blank" - className="btn btn-xs btn-primary" - > - Read more.. - </a> - ) : null} - </div> - </div> - ) : null} - <div style={{ fontSize: "13px" }}>{formView}</div> + ) : ( + <form onSubmit={handleSubmit}> + <h1 className="text-[20px] font-semibold mb-4">{props?.title}</h1> + {fileload && ( + <div className="flex items-center gap-x-2"> + <div className="h-2 rounded-full w-[200px] md:w-[400px] bg-gray-200"> + <div + className="h-2 rounded-full bg-blue-500" + style={{ width: `${percentage}%` }} + ></div> + </div> + <span className="text-black text-sm">{percentage}%</span> + </div> + )} + <div className="text-xs"> + <label className="block"> + File<span className="text-red-500 text-[13px]">*</span> + </label> + {fileupload.length > 0 ? ( + <div className="flex gap-2 justify-center items-center"> + <div className="flex justify-between items-center px-2 py-2 w-full font-bold rounded border-[1px] border-[#ccc] text-gray-500 bg-white text-[13px]"> + <div className="break-all"> + file selected : {fileupload?.split("/")?.pop()?.split("_")[1]} + </div> + <div + onClick={() => { + setFileUpload([]); + }} + className="cursor-pointer px-[10px] text-[20px] font-bold bg-white text-red-500" + > + <i className="fa-solid fa-xmark"></i> + </div> </div> + {process.env.REACT_APP_DROPBOX_API_KEY && ( + <DropboxChooser + onSuccess={dropboxSuccess} + onCancel={dropboxCancel} + /> + )} + </div> + ) : ( + <div className="flex gap-2 justify-center items-center"> + <input + type="file" + className="bg-white px-2 py-1.5 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + onChange={(e) => handleFileInput(e)} + accept="application/pdf" + required + /> + {process.env.REACT_APP_DROPBOX_API_KEY && ( + <DropboxChooser + onSuccess={dropboxSuccess} + onCancel={dropboxCancel} + /> + )} + </div> + )} + </div> + <div className="text-xs mt-2"> + <label className="block"> + Title<span className="text-red-500 text-[13px]">*</span> + </label> + <input + name="Name" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + value={formData.Name} + onChange={(e) => handleStrInput(e)} + required + /> + </div> + <div className="text-xs mt-2"> + <label className="block">Description</label> + <input + name="Description" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + value={formData.Description} + onChange={(e) => handleStrInput(e)} + /> + </div> + {props.signers && <SignersInput onChange={handleSigners} required />} + <div className="text-xs mt-2"> + <label className="block"> + Note<span className="text-red-500 text-[13px]">*</span> + </label> + <input + name="Note" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + value={formData.Note} + onChange={(e) => handleStrInput(e)} + required + /> + </div> + <SelectFolder onSuccess={handleFolder} folderCls={props.Cls} /> + + {props.title === "Request Signatures" && ( + <div className="text-xs mt-2"> + <label className="block"> + Time To Complete (Days) + <span className="text-red-500 text-[13px]">*</span> + </label> + <input + type="number" + name="TimeToCompleteDays" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + value={formData.TimeToCompleteDays} + onChange={(e) => handleStrInput(e)} + required + /> + </div> + )} + {props.title !== "Sign Yourself" && ( + <div className="text-xs mt-2"> + <label className="block">Send In Order</label> + <div className="flex items-center gap-2 ml-2 mb-1"> + <input + type="radio" + value={"true"} + name="SendinOrder" + checked={formData.SendinOrder === "true"} + className="" + onChange={handleStrInput} + /> + <div className="text-center">Yes</div> + </div> + <div className="flex items-center gap-2 ml-2 mb-1"> + <input + type="radio" + value={"false"} + name="SendinOrder" + checked={formData.SendinOrder === "false"} + onChange={handleStrInput} + /> + <div className="text-center">No</div> </div> </div> + )} + <div className="flex items-center mt-3 gap-2 text-white"> + <button + className={`${ + isSubmit && "cursor-progress" + } bg-[#1ab6ce] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 focus:outline-none`} + type="submit" + disabled={isSubmit} + > + Submit + </button> + <div + className="bg-[#188ae2] rounded-sm shadow-md text-[13px] font-semibold uppercase text-white py-1.5 px-2.5 text-center ml-[2px] focus:outline-none" + onClick={() => handleReset()} + > + Reset + </div> </div> - <div id="snackbar" style={{ backgroundColor: this.state.toastColor }}> - {this.state.toastDescription} - </div> - </ErrorBoundary> - </React.Fragment> - ); - } -} - -export default connect(null, { - removeState, - removeLevel2State, - removeLevel3State -})(FormBuilderFn); + </form> + )} + </div> + ); +}; +export default Form; diff --git a/apps/OpenSign/src/routes/GenerateToken.js b/apps/OpenSign/src/routes/GenerateToken.js new file mode 100644 index 000000000..d112f15c3 --- /dev/null +++ b/apps/OpenSign/src/routes/GenerateToken.js @@ -0,0 +1,184 @@ +import React, { useEffect, useState } from "react"; +import Title from "../components/Title"; +import axios from "axios"; +import Alert from "../primitives/Alert"; +import ModalUi from "../primitives/ModalUi"; +import { rejectBtn, submitBtn } from "../constant/const"; +import { openInNewTab } from "../constant/Utils"; + +function GenerateToken() { + const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); + const [parseAppId] = useState(localStorage.getItem("parseAppId")); + const [apiToken, SetApiToken] = useState(""); + const [isLoader, setIsLoader] = useState(true); + const [copied, setCopied] = useState(false); + const [isGenerate, setIsGenerate] = useState(false); + const [isErr, setIsErr] = useState(false); + const [isModal, setIsModal] = useState(false); + + useEffect(() => { + fetchToken(); + // eslint-disable-next-line + }, []); + + const fetchToken = async () => { + try { + const url = parseBaseUrl + "functions/getapitoken"; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessiontoken: localStorage.getItem("accesstoken") + }; + const res = await axios.post(url, {}, { headers: headers }); + if (res) { + SetApiToken(res.data.result.result); + } + setIsLoader(false); + } catch (err) { + SetApiToken(); + setIsLoader(false); + console.log("Err", err); + } + }; + const handleSubmit = async (e) => { + e.preventDefault(); + setIsLoader(true); + setIsModal(false); + try { + const url = parseBaseUrl + "functions/generateapitoken"; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessiontoken: localStorage.getItem("accesstoken") + }; + await axios.post(url, {}, { headers: headers }).then((res) => { + if (res) { + SetApiToken(res.data.result.token); + // localStorage.setItem("apiToken", res.data.result.token); + setIsGenerate(true); + setTimeout(() => { + setIsGenerate(false); + }, 1500); + setIsLoader(false); + } else { + console.error("Error while generating Token"); + setIsLoader(false); + setIsErr(true); + setTimeout(() => { + setIsErr(false); + }, 1500); + } + }); + } catch (error) { + setIsLoader(false); + setIsErr(true); + setTimeout(() => { + setIsErr(false); + }, 1500); + + console.log("err", error); + } + }; + + const copytoclipboard = (text) => { + navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => { + setCopied(false); + }, 1500); // Reset copied state after 1.5 seconds + }; + const handleModal = () => setIsModal(!isModal); + return ( + <React.Fragment> + <Title title={"API Token"} /> + {isGenerate && ( + <Alert type="success">Token generated successfully!</Alert> + )} + {copied && <Alert type="success">Copied</Alert>} + {isErr && <Alert type="danger">Something went wrong!</Alert>} + {isLoader ? ( + <div + style={{ + height: "100vh", + display: "flex", + alignItems: "center", + justifyContent: "center" + }} + > + <div + style={{ + fontSize: "45px", + color: "#3dd3e0" + }} + className="loader-37" + ></div> + </div> + ) : ( + <div className="bg-white flex flex-col justify-center shadow rounded"> + <h1 className="ml-4 mt-3 mb-2 font-semibold">API Token</h1> + <ul className="w-full flex flex-col p-2 text-sm"> + <li + className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`} + > + <span className="w-[40%]">Api Token:</span>{" "} + <span + id="token" + className="w-[60%] md:text-end cursor-pointer" + onClick={() => copytoclipboard(apiToken)} + > + {apiToken && apiToken} + </span> + </li> + </ul> + <div className="flex flex-col md:flex-row items-center justify-center gap-2 pb-4"> + <button + type="button" + onClick={apiToken ? handleModal : handleSubmit} + className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none" + > + {apiToken ? "Regenerate Token" : "Generate Token"} + </button> + <button + type="button" + onClick={() => + openInNewTab( + "https://docs.opensignlabs.com/docs/API-docs/opensign-api-v-1" + ) + } + className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none" + > + View Docs + </button> + </div> + + <ModalUi + isOpen={isModal} + title={"Regenerate Token"} + handleClose={handleModal} + > + <div className="m-[20px]"> + <div className="text-lg font-normal text-black"> + Are you sure you want to regenerate token it will expire old + token? + </div> + <hr className="bg-[#ccc] mt-4 " /> + <div className="flex items-center mt-3 gap-2 text-white"> + <button + onClick={handleSubmit} + className={submitBtn + "ml-[2px]"} + > + Yes + </button> + <button onClick={handleModal} className={rejectBtn}> + No + </button> + </div> + </div> + </ModalUi> + </div> + )} + </React.Fragment> + ); +} + +export default GenerateToken; diff --git a/apps/OpenSign/src/routes/LoadMf.js b/apps/OpenSign/src/routes/LoadMf.js index 2f8a43a1f..aac217d98 100644 --- a/apps/OpenSign/src/routes/LoadMf.js +++ b/apps/OpenSign/src/routes/LoadMf.js @@ -30,9 +30,9 @@ function RemoteApp({ app }) { boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.33)", backgroundColor: "#ffffff", width: "100%", - overflow: "hidden", borderRadius: 3, - minHeight: "70vh" + height: "100%", + minHeight: "100vh" }} > {RemoteComponent && <RemoteComponent />} diff --git a/apps/OpenSign/src/routes/Login.js b/apps/OpenSign/src/routes/Login.js index b9584b243..04c49ac2f 100644 --- a/apps/OpenSign/src/routes/Login.js +++ b/apps/OpenSign/src/routes/Login.js @@ -8,12 +8,15 @@ import axios from "axios"; import Title from "../components/Title"; import GoogleSignInBtn from "../components/LoginGoogle"; // import LoginFacebook from "../components/LoginFacebook"; -import { NavLink, useNavigate } from "react-router-dom"; +import { NavLink, useNavigate, useLocation } from "react-router-dom"; import login_img from "../assets/images/login_img.svg"; import { useWindowSize } from "../hook/useWindowSize"; +import ModalUi from "../primitives/ModalUi"; +import { modalCancelBtnColor, modalSubmitBtnColor } from "../constant/const"; function Login(props) { const navigate = useNavigate(); + const location = useLocation(); const { width } = useWindowSize(); const [state, setState] = useState({ email: "", @@ -132,6 +135,9 @@ function Login(props) { `${localStorage.getItem("_appName")}_appeditor` ) { userSettings.forEach(async (element) => { + const redirectUrl = + location?.state?.from || + `/${element.pageType}/${element.pageId}`; if (element.role === _currentRole) { let _role = _currentRole.replace( `${localStorage.getItem("_appName")}_`, @@ -260,9 +266,8 @@ function Login(props) { localStorage.removeItem( "userDetails" ); - navigate( - `/${element.pageType}/${element.pageId}` - ); + // Redirect to the appropriate URL after successful login + navigate(redirectUrl); } else { navigate(`/subscription`, { replace: true @@ -274,9 +279,8 @@ function Login(props) { }); } } else { - navigate( - `/${element.pageType}/${element.pageId}` - ); + // Redirect to the appropriate URL after successful login + navigate(redirectUrl); } } } else { @@ -313,9 +317,8 @@ function Login(props) { }); } } else { - navigate( - `/${element.pageType}/${element.pageId}` - ); + // Redirect to the appropriate URL after successful login + navigate(redirectUrl); } } }, @@ -462,6 +465,9 @@ function Login(props) { `${localStorage.getItem("_appName")}_appeditor` ) { userSettings.forEach(async (element) => { + const redirectUrl = + location?.state?.from || + `/${element.pageType}/${element.pageId}`; if (element.role === _currentRole) { let _role = _currentRole.replace( `${localStorage.getItem("_appName")}_`, @@ -569,9 +575,7 @@ function Login(props) { if (billingDate) { if (billingDate > new Date()) { localStorage.removeItem("userDetails"); - navigate( - `/${element.pageType}/${element.pageId}` - ); + navigate(redirectUrl); } else { navigate(`/subscription`, { replace: true @@ -581,9 +585,7 @@ function Login(props) { navigate(`/subscription`, { replace: true }); } } else { - navigate( - `/${element.pageType}/${element.pageId}` - ); + navigate(redirectUrl); } } } else { @@ -599,9 +601,8 @@ function Login(props) { if (billingDate) { if (billingDate > new Date()) { localStorage.removeItem("userDetails"); - navigate( - `/${element.pageType}/${element.pageId}` - ); + // Redirect to the appropriate URL after successful login + navigate(redirectUrl); } else { navigate(`/subscription`, { replace: true }); } @@ -609,9 +610,7 @@ function Login(props) { navigate(`/subscription`, { replace: true }); } } else { - navigate( - `/${element.pageType}/${element.pageId}` - ); + navigate(redirectUrl); } } }, @@ -1134,100 +1133,76 @@ function Login(props) { {state.toastDescription} </div> </div> - {isModal && ( - <div - className="modal fade show" - id="exampleModal" - tabIndex="-1" - role="dialog" - style={{ - display: "block", - zIndex: 1, - backgroundColor: "rgba(0,0,0,0.5)" - }} - > - <div className="modal-dialog" role="document"> - <div className="modal-content"> - <div className="modal-header"> - <h5 className="modal-title font-semibold"> - Additional Info - </h5> - <span> - <span></span> - </span> - </div> - <div className="modal-body"> - <form className="text-sm"> - <div className="form-group"> - <label - htmlFor="Company" - style={{ display: "flex" }} - className="col-form-label" - > - Company{" "} - <span style={{ fontSize: 13, color: "red" }}>*</span> - </label> - <input - type="text" - className="form-control" - id="Company" - value={userDetails.Company} - onChange={(e) => - setUserDetails({ - ...userDetails, - Company: e.target.value - }) - } - required - /> - </div> - <div className="form-group"> - <label - htmlFor="JobTitle" - style={{ display: "flex" }} - className="col-form-label" - > - Job Title - <span style={{ fontSize: 13, color: "red" }}>*</span> - </label> - <input - type="text" - className="form-control" - id="JobTitle" - value={userDetails.Destination} - onChange={(e) => - setUserDetails({ - ...userDetails, - Destination: e.target.value - }) - } - required - /> - </div> - <div className="mt-4"> - <button - type="button" - className="bg-[#17a2b8] text-sm p-2 text-white rounded uppercase" - onClick={(e) => handleSubmitbtn(e)} - style={{ marginRight: 10 }} - > - Login - </button> - <button - type="button" - className="bg-[#6c757d] text-sm p-2 text-white rounded uppercase" - onClick={handleCloseModal} - style={{ width: 90 }} - > - Cancel - </button> - </div> - </form> - </div> - </div> + <ModalUi isOpen={isModal} title="Additional Info" showClose={false}> + <form className="px-4 py-3"> + <div className="mb-3"> + <label + htmlFor="Company" + style={{ display: "flex" }} + className="block text-xs text-gray-700 font-semibold" + > + Company <span style={{ fontSize: 13, color: "red" }}>*</span> + </label> + <input + type="text" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + id="Company" + value={userDetails.Company} + onChange={(e) => + setUserDetails({ + ...userDetails, + Company: e.target.value + }) + } + required + /> </div> - </div> - )} + <div className="mb-3"> + <label + htmlFor="JobTitle" + style={{ display: "flex" }} + className="block text-xs text-gray-700 font-semibold" + > + Job Title + <span style={{ fontSize: 13, color: "red" }}>*</span> + </label> + <input + type="text" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + id="JobTitle" + value={userDetails.Destination} + onChange={(e) => + setUserDetails({ + ...userDetails, + Destination: e.target.value + }) + } + required + /> + </div> + <div className="mt-4"> + <button + type="button" + className="px-3 py-1.5 text-white rounded shadow-md text-center focus:outline-none " + onClick={(e) => handleSubmitbtn(e)} + style={{ + marginRight: 10, + backgroundColor: modalSubmitBtnColor + }} + > + Login + </button> + <button + type="button" + className="py-1.5 text-black border-[1px] border-[#ccc] shadow-md rounded focus:outline-none" + onClick={handleCloseModal} + style={{ width: 75, backgroundColor: modalCancelBtnColor }} + > + Cancel + </button> + </div> + </form> + </ModalUi> </> ) : ( <div diff --git a/apps/OpenSign/src/routes/PageNotFound.js b/apps/OpenSign/src/routes/PageNotFound.js index be8d10e6d..825cb98fb 100644 --- a/apps/OpenSign/src/routes/PageNotFound.js +++ b/apps/OpenSign/src/routes/PageNotFound.js @@ -2,7 +2,7 @@ import React from "react"; import Title from "../components/Title"; -const PageNotFound = () => { +const PageNotFound = ({ prefix }) => { return ( <div className="flex items-center justify-center h-screen w-full bg-white rounded"> <Title title={"Page Not Found"} /> @@ -10,7 +10,9 @@ const PageNotFound = () => { <h1 className="text-[60px] lg:text-[120px] font-semibold text-black"> 404 </h1> - <p className="text-[30px] lg:text-[50px] text-black">Page Not Found</p> + <p className="text-[30px] lg:text-[50px] text-black"> + {prefix ? prefix : "Page"} Not Found + </p> </div> </div> ); diff --git a/apps/OpenSign/src/routes/Pgsignup.js b/apps/OpenSign/src/routes/Pgsignup.js index af4cc0108..f3d12437d 100644 --- a/apps/OpenSign/src/routes/Pgsignup.js +++ b/apps/OpenSign/src/routes/Pgsignup.js @@ -5,7 +5,7 @@ import axios from "axios"; import { fetchAppInfo, showTenantName } from "../redux/actions/index"; import { connect } from "react-redux"; import Title from "../components/Title"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useLocation } from "react-router-dom"; const appId = localStorage.getItem("AppID12"); const server = localStorage.getItem("BaseUrl12"); @@ -13,6 +13,7 @@ Parse.serverURL = server; Parse.initialize(appId); const PgSignUp = (props) => { const navigate = useNavigate(); + const location = useLocation(); const [parseBaseUrl] = useState(localStorage.getItem("BaseUrl12")); const [parseAppId] = useState(localStorage.getItem("AppID12")); const [formData, setFormData] = useState({ @@ -187,7 +188,7 @@ const PgSignUp = (props) => { console.log("err ", error); if (error.message === "Account already exists for this username.") { alert("Account already exists!"); - navigate("/"); + navigate("/", { replace: true }); } else { setIsLoader(false); alert("Something went wrong, please try again later!"); @@ -351,7 +352,7 @@ const PgSignUp = (props) => { element.pageType ); setIsLoader(false); - navigate("/"); + navigate("/", { replace: true }); } else { extendedInfo.forEach((x) => { if (x.TenantId) { @@ -389,9 +390,12 @@ const PgSignUp = (props) => { ); setIsLoader(false); alert("Registered user successfully"); - navigate( - `/${element.pageType}/${element.pageId}` - ); + const redirectUrl = + location?.state?.from || + `/${element.pageType}/${element.pageId}`; + + // Redirect to the appropriate URL after successful login + navigate(redirectUrl); } } else { alert("Registered user successfully"); @@ -402,7 +406,12 @@ const PgSignUp = (props) => { ); localStorage.setItem("pageType", element.pageType); setIsLoader(false); - navigate(`/${element.pageType}/${element.pageId}`); + const redirectUrl = + location?.state?.from || + `/${element.pageType}/${element.pageId}`; + + // Redirect to the appropriate URL after successful login + navigate(redirectUrl); } }, (error) => { diff --git a/apps/OpenSign/src/routes/PlanSubscriptions.js b/apps/OpenSign/src/routes/PlanSubscriptions.js index 00ad2fa62..db39ee465 100644 --- a/apps/OpenSign/src/routes/PlanSubscriptions.js +++ b/apps/OpenSign/src/routes/PlanSubscriptions.js @@ -39,7 +39,7 @@ const PlanSubscriptions = () => { setIsLoader(false); setYearlyVisible(false); } else { - navigate("/"); + navigate("/", { replace: true }); } // eslint-disable-next-line }, []); @@ -78,31 +78,6 @@ const PlanSubscriptions = () => { id="monthlyPlans" className={`${yearlyVisible ? "none" : "block my-2"}`} > - {/* <div className=" my-2 w-full flex justify-center"> - <ul - className="navs" - style={{ - listStyle: "none", - display: "flex", - alignItems: "baseline" - }} - > - <li className="nav-item"> - <button className="nav-link frequency active" name="1_months"> - Monthly - </button> - </li> - <li className="nav-item"> - <button - className="nav-link frequency " - onClick={toggleFrequency} - name="1_years" - > - Yearly - </button> - </li> - </ul> - </div> */} <div className="flex justify-center w-full my-2"> <ul className=" flex flex-col md:flex-row h-full bg-white justify-center border-collapse border-[1px] border-gray-300"> {plansArr.map((item) => ( @@ -129,11 +104,27 @@ const PlanSubscriptions = () => { <div className={`${ item.subtitle.length <= 32 - ? "w-[150px] text-center" + ? "w-[150px] text-center" : "" } text-sm text-center my-2`} > - <p>{item.subtitle}</p> + <p + style={{ + backgroundColor: item.subtitlecolor + ? item.subtitlecolor + : "white" + }} + > + {item.subtitle.includes("<") ? ( + <div + dangerouslySetInnerHTML={{ + __html: item.subtitle + }} + /> + ) : ( + <span>{item.subtitle}</span> + )} + </p> </div> </div> diff --git a/apps/OpenSign/src/routes/Report.js b/apps/OpenSign/src/routes/Report.js index af3273095..b47be1f34 100644 --- a/apps/OpenSign/src/routes/Report.js +++ b/apps/OpenSign/src/routes/Report.js @@ -5,6 +5,7 @@ import axios from "axios"; import reportJson from "../json/ReportJson"; import { useParams } from "react-router-dom"; import Title from "../components/Title"; +import PageNotFound from "./PageNotFound"; const Report = () => { const { id } = useParams(); @@ -15,7 +16,7 @@ const Report = () => { const [heading, setHeading] = useState([]); const [isNextRecord, setIsNextRecord] = useState(false); const [isMoreDocs, setIsMoreDocs] = useState(true); - const [form, setForm]= useState("") + const [form, setForm] = useState(""); const abortController = new AbortController(); const docPerPage = 10; @@ -51,7 +52,7 @@ const Report = () => { setActions(json.actions); setHeading(json.heading); setReportName(json.reportName); - setForm(json.form) + setForm(json.form); Parse.serverURL = localStorage.getItem("BaseUrl12"); Parse.initialize(localStorage.getItem("AppID12")); const currentUser = Parse.User.current().id; @@ -159,13 +160,7 @@ const Report = () => { form={form} /> ) : ( - <div className="flex items-center justify-center h-screen w-full bg-white rounded"> - <div className="text-center"> - <p className="text-[30px] lg:text-[50px] text-black"> - Report Not Found - </p> - </div> - </div> + <PageNotFound prefix={"Report"} /> )} </> )} diff --git a/apps/OpenSign/src/routes/Webhook.js b/apps/OpenSign/src/routes/Webhook.js new file mode 100644 index 000000000..22cf04ec5 --- /dev/null +++ b/apps/OpenSign/src/routes/Webhook.js @@ -0,0 +1,171 @@ +import React, { useEffect, useState } from "react"; +import Title from "../components/Title"; +import axios from "axios"; +import Alert from "../primitives/Alert"; +import ModalUi from "../primitives/ModalUi"; +import { rejectBtn, submitBtn } from "../constant/const"; +import { openInNewTab } from "../constant/Utils"; +import Parse from "parse"; + +function Webhook() { + const [parseBaseUrl] = useState(localStorage.getItem("baseUrl")); + const [parseAppId] = useState(localStorage.getItem("parseAppId")); + const [webhook, setWebhook] = useState(); + const [isLoader, setIsLoader] = useState(true); + const [isGenerate, setIsGenerate] = useState(false); + const [isErr, setIsErr] = useState(false); + const [isModal, setIsModal] = useState(false); + + useEffect(() => { + fetchWebhook(); + // eslint-disable-next-line + }, []); + + const fetchWebhook = async () => { + const email = Parse.User.current().getEmail(); + const params = { email: email }; + try { + const extRes = await Parse.Cloud.run("getUserDetails", params); + if (extRes) { + setWebhook(extRes.get("Webhook")); + } + setIsLoader(false); + } catch (err) { + setWebhook(); + setIsLoader(false); + console.log("Err", err); + } + }; + const handleSubmit = async (e) => { + e.preventDefault(); + setIsLoader(true); + setIsModal(false); + try { + const params = { url: webhook }; + const url = parseBaseUrl + "functions/savewebhook"; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": parseAppId, + sessiontoken: localStorage.getItem("accesstoken") + }; + await axios.post(url, params, { headers: headers }).then((res) => { + if (res.data && res.data.result && res.data.result.Webhook) { + setWebhook(res.data.result.Webhook); + setIsGenerate(true); + setTimeout(() => { + setIsGenerate(false); + }, 1500); + setIsLoader(false); + } else { + console.error("Error while generating webhook"); + setIsLoader(false); + setIsErr(true); + setTimeout(() => { + setIsErr(false); + }, 1500); + } + }); + } catch (error) { + setIsLoader(false); + setIsErr(true); + setTimeout(() => { + setIsErr(false); + }, 1500); + + console.log("err", error); + } + }; + + const handleModal = () => setIsModal(!isModal); + return ( + <React.Fragment> + <Title title={"Webhook"} /> + {isGenerate && <Alert type="success">Webhook added successfully!</Alert>} + {isErr && <Alert type="danger">Something went wrong!</Alert>} + {isLoader ? ( + <div + style={{ + height: "100vh", + display: "flex", + alignItems: "center", + justifyContent: "center" + }} + > + <div + style={{ + fontSize: "45px", + color: "#3dd3e0" + }} + className="loader-37" + ></div> + </div> + ) : ( + <div className="bg-white flex flex-col justify-center shadow rounded"> + <h1 className="ml-4 mt-3 mb-2 font-semibold">Webhook</h1> + <ul className="w-full flex flex-col p-2 text-sm"> + <li + className={`flex justify-between items-center border-y-[1px] border-gray-300 break-all py-2`} + > + <span className="w-[40%]">Webhook:</span>{" "} + <span id="token" className="w-[60%] md:text-end cursor-pointer"> + {webhook && webhook} + </span> + </li> + </ul> + <div className="flex flex-col md:flex-row items-center justify-center gap-2 pb-4"> + <button + type="button" + onClick={handleModal} + className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-4 py-2 text-xs md:text-base focus:outline-none" + > + {webhook ? "Update Webhook" : "Add Webhook"} + </button> + <button + type="button" + onClick={() => + openInNewTab( + "https://docs.opensignlabs.com/docs/API-docs/save-update-webhook" + ) + } + className="rounded hover:bg-[#15b4e9] border-[1px] border-[#15b4e9] text-[#15b4e9] hover:text-white px-11 py-2 text-xs md:text-base focus:outline-none" + > + View Docs + </button> + </div> + + <ModalUi + isOpen={isModal} + title={"Regenerate Token"} + handleClose={handleModal} + > + <div className="m-[20px]"> + <div className="text-lg font-normal text-black"> + <label className="text-sm ml-2">Webhook</label> + <input + value={webhook} + onChange={(e) => setWebhook(e.target.value)} + placeholder="Enter webhook url" + className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs" + /> + </div> + <hr className="bg-[#ccc] mt-4 " /> + <div className="flex items-center mt-3 gap-2 text-white"> + <button + onClick={handleSubmit} + className={submitBtn + "ml-[2px]"} + > + Yes + </button> + <button onClick={handleModal} className={rejectBtn}> + No + </button> + </div> + </div> + </ModalUi> + </div> + )} + </React.Fragment> + ); +} + +export default Webhook; diff --git a/apps/OpenSign/src/styles/loader.css b/apps/OpenSign/src/styles/loader.css index e6e1624f8..940d1c557 100644 --- a/apps/OpenSign/src/styles/loader.css +++ b/apps/OpenSign/src/styles/loader.css @@ -1,2215 +1,66 @@ - fieldset { - border: 0 !important; - margin: 0 !important; - padding: 0 !important; - } - - [class*="loader-"] { - display: inline-block; - width: 1em; - height: 1em; - color: inherit; - vertical-align: middle; - pointer-events: none; - } - - .loader-01 { - border: 0.2em dotted currentcolor; - border-radius: 50%; - -webkit-animation: 1s loader-01 linear infinite; - animation: 1s loader-01 linear infinite; - } - - @-webkit-keyframes loader-01 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-01 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-02 { - border: 0.2em solid transparent; - border-left-color: currentcolor; - border-right-color: currentcolor; - border-radius: 50%; - -webkit-animation: 1s loader-02 linear infinite; - animation: 1s loader-02 linear infinite; - } - - @-webkit-keyframes loader-02 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-02 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-03 { - border: 0.2em solid currentcolor; - border-bottom-color: transparent; - border-radius: 50%; - -webkit-animation: 1s loader-03 linear infinite; - animation: 1s loader-03 linear infinite; - position: relative; - } - - @-webkit-keyframes loader-03 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-03 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-04 { - border: 1px solid currentcolor; - border-radius: 50%; - -webkit-animation: 1s loader-04 linear infinite; - animation: 1s loader-04 linear infinite; - position: relative; - } - .loader-04:before { - content: ""; - display: block; - width: 0; - height: 0; - position: absolute; - top: -0.2em; - left: 50%; - border: 0.2em solid currentcolor; - border-radius: 50%; - } - - @-webkit-keyframes loader-04 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-04 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-05 { - border: 0.2em solid transparent; - border-top-color: currentcolor; - border-radius: 50%; - -webkit-animation: 1s loader-05 linear infinite; - animation: 1s loader-05 linear infinite; - position: relative; - } - .loader-05:before { - content: ""; - display: block; - width: inherit; - height: inherit; - position: absolute; - top: -0.2em; - left: -0.2em; - border: 0.2em solid currentcolor; - border-radius: 50%; - opacity: 0.5; - } - - @-webkit-keyframes loader-05 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-05 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-06 { - border: 0.2em solid currentcolor; - border-radius: 50%; - -webkit-animation: loader-06 1s ease-out infinite; - animation: loader-06 1s ease-out infinite; - } - - @-webkit-keyframes loader-06 { - 0% { - -webkit-transform: scale(0); - transform: scale(0); - opacity: 0; - } - 50% { - opacity: 1; - } - 100% { - -webkit-transform: scale(1); - transform: scale(1); - opacity: 0; - } - } - - @keyframes loader-06 { - 0% { - -webkit-transform: scale(0); - transform: scale(0); - opacity: 0; - } - 50% { - opacity: 1; - } - 100% { - -webkit-transform: scale(1); - transform: scale(1); - opacity: 0; - } - } - .loader-07 { - border: 0 solid transparent; - border-radius: 50%; - position: relative; - } - .loader-07:before, .loader-07:after { - content: ""; - border: 0.2em solid currentcolor; - border-radius: 50%; - width: inherit; - height: inherit; - position: absolute; - top: 0; - left: 0; - -webkit-animation: loader-07 1s linear infinite; - animation: loader-07 1s linear infinite; - opacity: 0; - } - .loader-07:before { - -webkit-animation-delay: 1s; - animation-delay: 1s; - } - .loader-07:after { - -webkit-animation-delay: 0.5s; - animation-delay: 0.5s; - } - - @-webkit-keyframes loader-07 { - 0% { - -webkit-transform: scale(0); - transform: scale(0); - opacity: 0; - } - 50% { - opacity: 1; - } - 100% { - -webkit-transform: scale(1); - transform: scale(1); - opacity: 0; - } - } - - @keyframes loader-07 { - 0% { - -webkit-transform: scale(0); - transform: scale(0); - opacity: 0; - } - 50% { - opacity: 1; - } - 100% { - -webkit-transform: scale(1); - transform: scale(1); - opacity: 0; - } - } - .loader-08 { - position: relative; - } - .loader-08:before, .loader-08:after { - content: ""; - width: inherit; - height: inherit; - border-radius: 50%; - background-color: currentcolor; - opacity: 0.6; - position: absolute; - top: 0; - left: 0; - -webkit-animation: loader-08 2s infinite ease-in-out; - animation: loader-08 2s infinite ease-in-out; - } - .loader-08:after { - -webkit-animation-delay: -1s; - animation-delay: -1s; - } - - @-webkit-keyframes loader-08 { - 0%, - 100% { - -webkit-transform: scale(0); - transform: scale(0); - } - 50% { - -webkit-transform: scale(1); - transform: scale(1); - } - } - - @keyframes loader-08 { - 0%, - 100% { - -webkit-transform: scale(0); - transform: scale(0); - } - 50% { - -webkit-transform: scale(1); - transform: scale(1); - } - } - .loader-09 { - background-color: currentcolor; - border-radius: 50%; - -webkit-animation: loader-09 1s infinite ease-in-out; - animation: loader-09 1s infinite ease-in-out; - } - - @-webkit-keyframes loader-09 { - 0% { - -webkit-transform: scale(0); - transform: scale(0); - } - 100% { - -webkit-transform: scale(1); - transform: scale(1); - opacity: 0; - } - } - - @keyframes loader-09 { - 0% { - -webkit-transform: scale(0); - transform: scale(0); - } - 100% { - -webkit-transform: scale(1); - transform: scale(1); - opacity: 0; - } - } - .loader-10 { - position: relative; - -webkit-animation: loader-10-1 2s infinite linear; - animation: loader-10-1 2s infinite linear; - } - .loader-10:before, .loader-10:after { - content: ""; - width: 0; - height: 0; - border: 0.5em solid currentcolor; - display: block; - position: absolute; - border-radius: 100%; - -webkit-animation: loader-10-2 2s infinite ease-in-out; - animation: loader-10-2 2s infinite ease-in-out; - } - .loader-10:before { - top: 0; - left: 50%; - } - .loader-10:after { - bottom: 0; - right: 50%; - -webkit-animation-delay: -1s; - animation-delay: -1s; - } - - @-webkit-keyframes loader-10-1 { - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-10-1 { - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - @-webkit-keyframes loader-10-2 { - 0%, - 100% { - -webkit-transform: scale(0); - transform: scale(0); - } - 50% { - -webkit-transform: scale(1); - transform: scale(1); - } - } - @keyframes loader-10-2 { - 0%, - 100% { - -webkit-transform: scale(0); - transform: scale(0); - } - 50% { - -webkit-transform: scale(1); - transform: scale(1); - } - } - .loader-11 { - background-color: currentcolor; - -webkit-animation: loader-11 1.2s infinite ease-in-out; - animation: loader-11 1.2s infinite ease-in-out; - } - - @-webkit-keyframes loader-11 { - 0% { - -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg); - transform: perspective(120px) rotateX(0deg) rotateY(0deg); - } - 50% { - -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); - transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); - } - 100% { - -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); - transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); - } - } - - @keyframes loader-11 { - 0% { - -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg); - transform: perspective(120px) rotateX(0deg) rotateY(0deg); - } - 50% { - -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); - transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg); - } - 100% { - -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); - transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg); - } - } - .loader-12 { - position: relative; - } - .loader-12:before, .loader-12:after { - content: ""; - display: block; - position: absolute; - background-color: currentcolor; - left: 50%; - right: 0; - top: 0; - bottom: 50%; - box-shadow: -0.5em 0 0 currentcolor; - -webkit-animation: loader-12 1s linear infinite; - animation: loader-12 1s linear infinite; - } - .loader-12:after { - top: 50%; - bottom: 0; - -webkit-animation-delay: 0.25s; - animation-delay: 0.25s; - } - - @-webkit-keyframes loader-12 { - 0%, - 100% { - box-shadow: -0.5em 0 0 transparent; - background-color: currentcolor; - } - 50% { - box-shadow: -0.5em 0 0 currentcolor; - background-color: transparent; - } - } - - @keyframes loader-12 { - 0%, - 100% { - box-shadow: -0.5em 0 0 transparent; - background-color: currentcolor; - } - 50% { - box-shadow: -0.5em 0 0 currentcolor; - background-color: transparent; - } - } - .loader-13:before, - .loader-13:after, - .loader-13 { - border-radius: 50%; - -webkit-animation-fill-mode: both; - animation-fill-mode: both; - -webkit-animation: loader-13 1.8s infinite ease-in-out; - animation: loader-13 1.8s infinite ease-in-out; - } - - .loader-13 { - color: currentcolor; - position: relative; - -webkit-transform: translateZ(0); - transform: translateZ(0); - -webkit-animation-delay: -0.16s; - animation-delay: -0.16s; - top: -1em; - } - .loader-13:before { - right: 100%; - -webkit-animation-delay: -0.32s; - animation-delay: -0.32s; - } - .loader-13:after { - left: 100%; - } - .loader-13:before, .loader-13:after { - content: ""; - display: block; - position: absolute; - top: 0; - width: inherit; - height: inherit; - } - - @-webkit-keyframes loader-13 { - 0%, - 80%, - 100% { - box-shadow: 0 1em 0 -1em; - } - 40% { - box-shadow: 0 1em 0 -0.2em; - } - } - - @keyframes loader-13 { - 0%, - 80%, - 100% { - box-shadow: 0 1em 0 -1em; - } - 40% { - box-shadow: 0 1em 0 -0.2em; - } - } - .loader-14 { - border-radius: 50%; - box-shadow: 0 1em 0 -0.2em currentcolor; - position: relative; - -webkit-animation: loader-14 0.8s ease-in-out alternate infinite; - animation: loader-14 0.8s ease-in-out alternate infinite; - -webkit-animation-delay: 0.32s; - animation-delay: 0.32s; - top: -1em; - } - .loader-14:after, .loader-14:before { - content: ""; - position: absolute; - width: inherit; - height: inherit; - border-radius: inherit; - box-shadow: inherit; - -webkit-animation: inherit; - animation: inherit; - } - .loader-14:before { - left: -1em; - -webkit-animation-delay: 0.48s; - animation-delay: 0.48s; - } - .loader-14:after { - right: -1em; - -webkit-animation-delay: 0.16s; - animation-delay: 0.16s; - } - - @-webkit-keyframes loader-14 { - 0% { - box-shadow: 0 2em 0 -0.2em currentcolor; - } - 100% { - box-shadow: 0 1em 0 -0.2em currentcolor; - } - } - - @keyframes loader-14 { - 0% { - box-shadow: 0 2em 0 -0.2em currentcolor; - } - 100% { - box-shadow: 0 1em 0 -0.2em currentcolor; - } - } - .loader-15 { - background: currentcolor; - position: relative; - -webkit-animation: loader-15 1s ease-in-out infinite; - animation: loader-15 1s ease-in-out infinite; - -webkit-animation-delay: 0.4s; - animation-delay: 0.4s; - width: 0.25em; - height: 0.5em; - margin: 0 0.5em; - } - .loader-15:after, .loader-15:before { - content: ""; - position: absolute; - width: inherit; - height: inherit; - background: inherit; - -webkit-animation: inherit; - animation: inherit; - } - .loader-15:before { - right: 0.5em; - -webkit-animation-delay: 0.2s; - animation-delay: 0.2s; - } - .loader-15:after { - left: 0.5em; - -webkit-animation-delay: 0.6s; - animation-delay: 0.6s; - } - - @-webkit-keyframes loader-15 { - 0%, - 100% { - box-shadow: 0 0 0 currentcolor, 0 0 0 currentcolor; - } - 50% { - box-shadow: 0 -0.25em 0 currentcolor, 0 0.25em 0 currentcolor; - } - } - - @keyframes loader-15 { - 0%, - 100% { - box-shadow: 0 0 0 currentcolor, 0 0 0 currentcolor; - } - 50% { - box-shadow: 0 -0.25em 0 currentcolor, 0 0.25em 0 currentcolor; - } - } - .loader-16 { - -webkit-transform: rotateZ(45deg); - transform: rotateZ(45deg); - -webkit-perspective: 1000px; - perspective: 1000px; - border-radius: 50%; - } - .loader-16:before, .loader-16:after { - content: ""; - display: block; - position: absolute; - top: 0; - left: 0; - width: inherit; - height: inherit; - border-radius: 50%; - -webkit-animation: 1s spin linear infinite; - animation: 1s spin linear infinite; - } - .loader-16:before { - -webkit-transform: rotateX(70deg); - transform: rotateX(70deg); - } - .loader-16:after { - -webkit-transform: rotateY(70deg); - transform: rotateY(70deg); - -webkit-animation-delay: 0.4s; - animation-delay: 0.4s; - } - - @-webkit-keyframes rotate { - 0% { - -webkit-transform: translate(-50%, -50%) rotateZ(0deg); - transform: translate(-50%, -50%) rotateZ(0deg); - } - 100% { - -webkit-transform: translate(-50%, -50%) rotateZ(360deg); - transform: translate(-50%, -50%) rotateZ(360deg); - } - } - - @keyframes rotate { - 0% { - -webkit-transform: translate(-50%, -50%) rotateZ(0deg); - transform: translate(-50%, -50%) rotateZ(0deg); - } - 100% { - -webkit-transform: translate(-50%, -50%) rotateZ(360deg); - transform: translate(-50%, -50%) rotateZ(360deg); - } - } - @-webkit-keyframes rotateccw { - 0% { - -webkit-transform: translate(-50%, -50%) rotate(0deg); - transform: translate(-50%, -50%) rotate(0deg); - } - 100% { - -webkit-transform: translate(-50%, -50%) rotate(-360deg); - transform: translate(-50%, -50%) rotate(-360deg); - } - } - @keyframes rotateccw { - 0% { - -webkit-transform: translate(-50%, -50%) rotate(0deg); - transform: translate(-50%, -50%) rotate(0deg); - } - 100% { - -webkit-transform: translate(-50%, -50%) rotate(-360deg); - transform: translate(-50%, -50%) rotate(-360deg); - } - } - @-webkit-keyframes spin { - 0%, - 100% { - box-shadow: 0.2em 0px 0 0px currentcolor; - } - 12% { - box-shadow: 0.2em 0.2em 0 0 currentcolor; - } - 25% { - box-shadow: 0 0.2em 0 0px currentcolor; - } - 37% { - box-shadow: -0.2em 0.2em 0 0 currentcolor; - } - 50% { - box-shadow: -0.2em 0 0 0 currentcolor; - } - 62% { - box-shadow: -0.2em -0.2em 0 0 currentcolor; - } - 75% { - box-shadow: 0px -0.2em 0 0 currentcolor; - } - 87% { - box-shadow: 0.2em -0.2em 0 0 currentcolor; - } - } - @keyframes spin { - 0%, - 100% { - box-shadow: 0.2em 0px 0 0px currentcolor; - } - 12% { - box-shadow: 0.2em 0.2em 0 0 currentcolor; - } - 25% { - box-shadow: 0 0.2em 0 0px currentcolor; - } - 37% { - box-shadow: -0.2em 0.2em 0 0 currentcolor; - } - 50% { - box-shadow: -0.2em 0 0 0 currentcolor; - } - 62% { - box-shadow: -0.2em -0.2em 0 0 currentcolor; - } - 75% { - box-shadow: 0px -0.2em 0 0 currentcolor; - } - 87% { - box-shadow: 0.2em -0.2em 0 0 currentcolor; - } - } - .loader-17 { - position: relative; - background-color: currentcolor; - border-radius: 50%; - } - .loader-17:after, .loader-17:before { - content: ""; - position: absolute; - width: 0.25em; - height: 0.25em; - border-radius: 50%; - opacity: 0.8; - } - .loader-17:after { - left: -0.5em; - top: -0.25em; - background-color: currentcolor; - -webkit-transform-origin: 0.75em 1em; - transform-origin: 0.75em 1em; - -webkit-animation: loader-17 1s linear infinite; - animation: loader-17 1s linear infinite; - opacity: 0.6; - } - .loader-17:before { - left: -1.25em; - top: -0.75em; - background-color: currentcolor; - -webkit-transform-origin: 1.5em 1em; - transform-origin: 1.5em 1em; - -webkit-animation: loader-17 2s linear infinite; - animation: loader-17 2s linear infinite; - } - - @-webkit-keyframes loader-17 { - 0% { - -webkit-transform: rotateZ(0deg) translate3d(0, 0, 0); - transform: rotateZ(0deg) translate3d(0, 0, 0); - } - 100% { - -webkit-transform: rotateZ(360deg) translate3d(0, 0, 0); - transform: rotateZ(360deg) translate3d(0, 0, 0); - } - } - - @keyframes loader-17 { - 0% { - -webkit-transform: rotateZ(0deg) translate3d(0, 0, 0); - transform: rotateZ(0deg) translate3d(0, 0, 0); - } - 100% { - -webkit-transform: rotateZ(360deg) translate3d(0, 0, 0); - transform: rotateZ(360deg) translate3d(0, 0, 0); - } - } - .loader-18 { - position: relative; - } - .loader-18:before, .loader-18:after { - content: ""; - display: block; - position: absolute; - border-radius: 50%; - border: 0.1em solid transparent; - border-bottom-color: currentcolor; - top: 0; - left: 0; - -webkit-animation: 1s loader-18 linear infinite; - animation: 1s loader-18 linear infinite; - } - .loader-18:before { - width: 1em; - height: 1em; - } - .loader-18:after { - width: 0.8em; - height: 0.8em; - top: 0.1em; - left: 0.1em; - animation-direction: reverse; - } - - @-webkit-keyframes loader-18 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-18 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-19 { - border-top: 0.2em solid currentcolor; - border-right: 0.2em solid transparent; - -webkit-animation: loader-19 1s linear infinite; - animation: loader-19 1s linear infinite; - border-radius: 100%; - position: relative; - } - - @-webkit-keyframes loader-19 { - to { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-19 { - to { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-20 { - background-color: transparent; - box-shadow: inset 0px 0px 0px 0.1em currentcolor; - border-radius: 50%; - position: relative; - } - .loader-20:after, .loader-20:before { - position: absolute; - content: ""; - background-color: currentcolor; - top: 0.5em; - left: 0.5em; - height: 0.1em; - -webkit-transform-origin: left center; - transform-origin: left center; - } - .loader-20:after { - width: 0.4em; - -webkit-animation: loader-20 2s linear infinite; - animation: loader-20 2s linear infinite; - } - .loader-20:before { - width: 0.3em; - -webkit-animation: loader-20 8s linear infinite; - animation: loader-20 8s linear infinite; - } - - @-webkit-keyframes loader-20 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-20 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-21 { - position: relative; - } - .loader-21:before, .loader-21:after { - position: absolute; - content: ""; - } - .loader-21:before { - width: 80%; - height: 80%; - left: 10%; - bottom: 10%; - border-radius: 100% 100% 100% 0; - box-shadow: 0px 0px 0px 0.1em currentcolor; - -webkit-animation: loader-21 1s linear infinite; - animation: loader-21 1s linear infinite; - -webkit-transform: rotate(-46deg); - transform: rotate(-46deg); - } - .loader-21:after { - width: 1em; - height: 0.3em; - border-radius: 100%; - left: 0; - background-color: rgba(255, 255, 255, 0.2); - bottom: -0.2em; - z-index: -1; - } - - @-webkit-keyframes loader-21 { - 0% { - top: 0; - } - 50% { - top: -5px; - } - 100% { - top: 0; - } - } - - @keyframes loader-21 { - 0% { - top: 0; - } - 50% { - top: -5px; - } - 100% { - top: 0; - } - } - .loader-22 { - border: 0.1em currentcolor solid; - border-radius: 100%; - position: relative; - overflow: hidden; - z-index: 1; - } - .loader-22:after, .loader-22:before { - position: absolute; - content: ""; - background-color: currentcolor; - } - .loader-22:after { - width: 50%; - height: 0.1em; - left: 50%; - top: 50%; - -webkit-transform-origin: left center; - transform-origin: left center; - -webkit-animation: loader-22 2s linear infinite alternate; - animation: loader-22 2s linear infinite alternate; - } - .loader-22:before { - width: 100%; - height: 40%; - left: 0; - bottom: 0; - } - - @-webkit-keyframes loader-22 { - 0% { - -webkit-transform: rotate(-160deg); - transform: rotate(-160deg); - } - 100% { - -webkit-transform: rotate(-20deg); - transform: rotate(-20deg); - } - } - - @keyframes loader-22 { - 0% { - -webkit-transform: rotate(-160deg); - transform: rotate(-160deg); - } - 100% { - -webkit-transform: rotate(-20deg); - transform: rotate(-20deg); - } - } - .loader-23 { - height: 0.5em; - border: 0.1em currentcolor solid; - border-radius: 0.1em; - position: relative; - -webkit-animation: loader-23 5s linear infinite; - animation: loader-23 5s linear infinite; - } - .loader-23:after { - width: 0.07em; - height: 100%; - background-color: currentcolor; - border-radius: 0px 0.5em 0.5em 0px; - position: absolute; - content: ""; - top: 0; - left: calc(100% + 0.1em); - } - - @-webkit-keyframes loader-23 { - 0% { - box-shadow: inset 0px 0px 0px currentcolor; - } - 100% { - box-shadow: inset 1em 0px 0px currentcolor; - } - } - - @keyframes loader-23 { - 0% { - box-shadow: inset 0px 0px 0px currentcolor; - } - 100% { - box-shadow: inset 1em 0px 0px currentcolor; - } - } - .loader-24 { - width: 0.8em; - height: 1em; - border: 0.1em currentcolor solid; - border-radius: 0px 0px 0.2em 0.2em; - position: relative; - } - .loader-24:after, .loader-24:before { - position: absolute; - content: ""; - } - .loader-24:after { - width: 0.2em; - height: 50%; - border: 0.1em currentcolor solid; - border-left: none; - border-radius: 0px 0.5em 0.5em 0px; - left: calc(100% + 0.1em); - top: 0.1em; - } - .loader-24:before { - width: 0.1em; - height: 0.3em; - background-color: currentcolor; - top: -0.3em; - left: 0.05em; - box-shadow: 0.2em 0px 0px 0px currentcolor, 0.2em -0.2em 0px 0px currentcolor, 0.4em 0px 0px 0px currentcolor; - -webkit-animation: loader-24 1s linear infinite alternate; - animation: loader-24 1s linear infinite alternate; - } - - @-webkit-keyframes loader-24 { - 0% { - height: 0px; - } - 100% { - height: 6px; - } - } - - @keyframes loader-24 { - 0% { - height: 0px; - } - 100% { - height: 6px; - } - } - .loader-25 { - border: 0.1em currentcolor solid; - position: relative; - -webkit-animation: loader-25-1 5s linear infinite; - animation: loader-25-1 5s linear infinite; - } - .loader-25:after { - width: 0.2em; - height: 0.2em; - position: absolute; - content: ""; - background-color: currentcolor; - bottom: calc(100% + 0.2em); - left: -0.4em; - -webkit-animation: loader-25-2 1s ease-in-out infinite; - animation: loader-25-2 1s ease-in-out infinite; - } - - @-webkit-keyframes loader-25-1 { - 0% { - box-shadow: inset 0 0 0 0 currentcolor; - } - 100% { - box-shadow: inset 0 -1em 0 0 currentcolor; - } - } - - @keyframes loader-25-1 { - 0% { - box-shadow: inset 0 0 0 0 currentcolor; - } - 100% { - box-shadow: inset 0 -1em 0 0 currentcolor; - } - } - @-webkit-keyframes loader-25-2 { - 25% { - left: calc(100% + 0.2em); - bottom: calc(100% + 0.2em); - } - 50% { - left: calc(100% + 0.2em); - bottom: -0.4em; - } - 75% { - left: -0.4em; - bottom: -0.4em; - } - 100% { - left: -0.4em; - bottom: calc(100% + 0.2em); - } - } - @keyframes loader-25-2 { - 25% { - left: calc(100% + 0.2em); - bottom: calc(100% + 0.2em); - } - 50% { - left: calc(100% + 0.2em); - bottom: -0.4em; - } - 75% { - left: -0.4em; - bottom: -0.4em; - } - 100% { - left: -0.4em; - bottom: calc(100% + 0.2em); - } - } - .loader-26 { - width: 0.5em; - height: 0.5em; - background-color: currentcolor; - box-shadow: 1em 0px 0px currentcolor; - border-radius: 50%; - -webkit-animation: loader-26 1s ease-in-out infinite alternate; - animation: loader-26 1s ease-in-out infinite alternate; - } - - @-webkit-keyframes loader-26 { - 0% { - opacity: 0.1; - -webkit-transform: rotate(0deg) scale(0.5); - transform: rotate(0deg) scale(0.5); - } - 100% { - opacity: 1; - -webkit-transform: rotate(360deg) scale(1.2); - transform: rotate(360deg) scale(1.2); - } - } - - @keyframes loader-26 { - 0% { - opacity: 0.1; - -webkit-transform: rotate(0deg) scale(0.5); - transform: rotate(0deg) scale(0.5); - } - 100% { - opacity: 1; - -webkit-transform: rotate(360deg) scale(1.2); - transform: rotate(360deg) scale(1.2); - } - } - .loader-27 { - box-shadow: inset 0 0 0 0.1em currentcolor; - border-radius: 50%; - position: relative; - margin-left: 1.2em; - } - .loader-27:before { - content: ""; - display: block; - width: inherit; - height: inherit; - border-radius: 50%; - position: absolute; - right: 1.2em; - top: 0; - box-shadow: inset 0 0 0 0.1em currentcolor; - } - .loader-27:after { - border: 0.2em solid currentcolor; - box-shadow: -1.2em 0 0 0 currentcolor; - width: 0; - height: 0; - border-radius: 50%; - left: 50%; - top: 25%; - position: absolute; - content: ""; - -webkit-animation: loader-27 2s linear infinite alternate; - animation: loader-27 2s linear infinite alternate; - } - - @-webkit-keyframes loader-27 { - 0% { - left: 0; - } - 100% { - left: 0.5em; - } - } - - @keyframes loader-27 { - 0% { - left: 0; - } - 100% { - left: 0.5em; - } - } - .loader-28 { - position: relative; - -webkit-animation: 2s loader-28-1 infinite; - animation: 2s loader-28-1 infinite; - } - .loader-28:before { - content: ""; - display: block; - width: inherit; - height: inherit; - border-radius: 80% 20%; - border: 0.1em solid currentcolor; - -webkit-transform: rotate(45deg); - transform: rotate(45deg); - border-width: 0.1em 0.05em 0.05em 0.1em; - } - .loader-28:after { - content: ""; - display: block; - width: 0.2em; - height: 0.2em; - position: absolute; - top: 0.4em; - left: 50%; - border-radius: 50%; - box-shadow: -0.07em 0.07em 0 0.1em currentcolor; - -webkit-animation: 2s loader-28-2 linear infinite; - animation: 2s loader-28-2 linear infinite; - } - - @-webkit-keyframes loader-28-1 { - 0%, - 100% { - -webkit-transform: scaleY(1); - transform: scaleY(1); - } - 10% { - -webkit-transform: scaleY(0); - transform: scaleY(0); - } - 20% { - -webkit-transform: scaleY(1); - transform: scaleY(1); - } - } - - @keyframes loader-28-1 { - 0%, - 100% { - -webkit-transform: scaleY(1); - transform: scaleY(1); - } - 10% { - -webkit-transform: scaleY(0); - transform: scaleY(0); - } - 20% { - -webkit-transform: scaleY(1); - transform: scaleY(1); - } - } - @-webkit-keyframes loader-28-2 { - 0%, - 100% { - -webkit-transform: translateX(0); - transform: translateX(0); - } - 30% { - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - } - 50% { - -webkit-transform: transalteX(200%); - transform: transalteX(200%); - } - } - @keyframes loader-28-2 { - 0%, - 100% { - -webkit-transform: translateX(0); - transform: translateX(0); - } - 30% { - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - } - 50% { - -webkit-transform: transalteX(200%); - transform: transalteX(200%); - } - } - .loader-29 { - border-radius: 50%; - box-shadow: inset 0 0 0 0.1em currentcolor, -0.5em -0.5em 0 -0.4em currentcolor, 0 -0.7em 0 -0.4em currentcolor, 0.5em -0.5em 0 -0.4em currentcolor, -0.5em 0.5em 0 -0.4em currentcolor, 0 0.7em 0 -0.4em currentcolor, 0.5em 0.5em 0 -0.4em currentcolor, -0.7em 0 0 -0.4em currentcolor, 0.7em 0 0 -0.4em currentcolor; - -webkit-animation: 5s loader-29 linear infinite; - animation: 5s loader-29 linear infinite; - } - - @-webkit-keyframes loader-29 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-29 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-30 { - border: 0.2em solid transparent; - border-top-color: currentcolor; - border-bottom-color: currentcolor; - border-radius: 50%; - position: relative; - -webkit-animation: 1s loader-30 linear infinite; - animation: 1s loader-30 linear infinite; - } - .loader-30:before, .loader-30:after { - content: ""; - display: block; - width: 0; - height: 0; - position: absolute; - border: 0.2em solid transparent; - border-bottom-color: currentcolor; - } - .loader-30:before { - -webkit-transform: rotate(135deg); - transform: rotate(135deg); - right: -0.3em; - top: -0.05em; - } - .loader-30:after { - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); - left: -0.3em; - bottom: -0.05em; - } - - @-webkit-keyframes loader-30 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-30 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - .loader-31 { - box-shadow: 0 0 2em currentcolor; - background-color: currentcolor; - position: relative; - border-radius: 50%; - -webkit-transform: rotateX(-60deg) perspective(1000px); - transform: rotateX(-60deg) perspective(1000px); - } - .loader-31:before, .loader-31:after { - content: ""; - display: block; - position: absolute; - top: 0; - left: 0; - width: inherit; - height: inherit; - border-radius: inherit; - -webkit-animation: 1s loader-31 ease-out infinite; - animation: 1s loader-31 ease-out infinite; - } - .loader-31:after { - -webkit-animation-delay: 0.4s; - animation-delay: 0.4s; - } - - @-webkit-keyframes loader-31 { - 0% { - opacity: 1; - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - box-shadow: 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor; - } - 100% { - opacity: 0; - -webkit-transform: rotate(180deg); - transform: rotate(180deg); - box-shadow: -1em -1em 0 -0.35em currentcolor, 0 -1.5em 0 -0.35em currentcolor, 1em -1em 0 -0.35em currentcolor, -1.5em 0 0 -0.35em currentcolor, 1.5em -0 0 -0.35em currentcolor, -1em 1em 0 -0.35em currentcolor, 0 1.5em 0 -0.35em currentcolor, 1em 1em 0 -0.35em currentcolor; - } - } - - @keyframes loader-31 { - 0% { - opacity: 1; - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - box-shadow: 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor, 0 0 0 -0.5em currentcolor; - } - 100% { - opacity: 0; - -webkit-transform: rotate(180deg); - transform: rotate(180deg); - box-shadow: -1em -1em 0 -0.35em currentcolor, 0 -1.5em 0 -0.35em currentcolor, 1em -1em 0 -0.35em currentcolor, -1.5em 0 0 -0.35em currentcolor, 1.5em -0 0 -0.35em currentcolor, -1em 1em 0 -0.35em currentcolor, 0 1.5em 0 -0.35em currentcolor, 1em 1em 0 -0.35em currentcolor; - } - } - .loader-32 { - position: relative; - border-radius: 50%; - box-shadow: 0 0 1em 0 currentcolor, inset 0 0 1em 0 currentcolor; - -webkit-animation: 1s loader-32 linear infinite; - animation: 1s loader-32 linear infinite; - } - .loader-32:before, .loader-32:after { - content: ""; - display: block; - width: inherit; - height: inherit; - position: absolute; - border-radius: 50%; - } - .loader-32:before { - border-top: 0.2em solid currentcolor; - border-right: 0.2em solid transparent; - top: 0.28em; - right: calc(50% - 0.22em); - } - .loader-32:after { - border-bottom: 0.2em solid currentcolor; - border-left: 0.2em solid transparent; - bottom: 0.28em; - left: calc(50% - 0.22em); - } - - @-webkit-keyframes loader-32 { - 0% { - -webkit-transform: rotateX(-60deg) rotateZ(0deg); - transform: rotateX(-60deg) rotateZ(0deg); - } - 100% { - -webkit-transform: rotateX(-60deg) rotateZ(360deg); - transform: rotateX(-60deg) rotateZ(360deg); - } - } - - @keyframes loader-32 { - 0% { - -webkit-transform: rotateX(-60deg) rotateZ(0deg); - transform: rotateX(-60deg) rotateZ(0deg); - } - 100% { - -webkit-transform: rotateX(-60deg) rotateZ(360deg); - transform: rotateX(-60deg) rotateZ(360deg); - } - } - .loader-33 { - border-radius: 50%; - position: relative; - } - .loader-33:after, .loader-33:before { - position: absolute; - content: ""; - } - .loader-33:after { - height: 0.1em; - width: 1em; - background-color: currentcolor; - border-radius: 0.1em; - bottom: 0; - left: 0; - -webkit-transform-origin: bottom center; - transform-origin: bottom center; - -webkit-animation: loader-33-1 0.8s ease-in-out infinite alternate; - animation: loader-33-1 0.8s ease-in-out infinite alternate; - } - .loader-33:before { - height: 0.2em; - width: 0.2em; - background-color: currentcolor; - border-radius: 50%; - top: 0; - left: calc(50% - 0.1em); - -webkit-animation: loader-33-2 0.4s ease-in-out infinite alternate; - animation: loader-33-2 0.4s ease-in-out infinite alternate; - } - - @-webkit-keyframes loader-33-2 { - 0% { - height: 0.24em; - -webkit-transform: translateY(0px); - transform: translateY(0px); - } - 75% { - height: 0.2em; - width: 0.2em; - } - 100% { - height: 0.1em; - width: 0.24em; - -webkit-transform: translateY(0.8em); - transform: translateY(0.8em); - } - } - - @keyframes loader-33-2 { - 0% { - height: 0.24em; - -webkit-transform: translateY(0px); - transform: translateY(0px); - } - 75% { - height: 0.2em; - width: 0.2em; - } - 100% { - height: 0.1em; - width: 0.24em; - -webkit-transform: translateY(0.8em); - transform: translateY(0.8em); - } - } - @-webkit-keyframes loader-33-1 { - 0% { - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); - } - 100% { - -webkit-transform: rotate(45deg); - transform: rotate(45deg); - } - } - @keyframes loader-33-1 { - 0% { - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); - } - 100% { - -webkit-transform: rotate(45deg); - transform: rotate(45deg); - } - } - .loader-34 { - position: relative; - width: 1em; - height: 0.5em; - } - .loader-34:after, .loader-34:before { - position: absolute; - content: ""; - height: 0.4em; - width: 0.4em; - top: 0; - background-color: currentcolor; - border-radius: 50%; - } - .loader-34:after { - right: 0; - -webkit-animation: loader-34-2 0.5s ease-in-out infinite; - animation: loader-34-2 0.5s ease-in-out infinite; - -webkit-animation-direction: alternate; - animation-direction: alternate; - } - .loader-34:before { - left: 0; - -webkit-animation: loader-34-1 0.5s ease-in-out infinite; - animation: loader-34-1 0.5s ease-in-out infinite; - -webkit-animation-direction: alternate; - animation-direction: alternate; - } - - @-webkit-keyframes loader-34-1 { - 0% { - -webkit-transform: translatex(0px); - transform: translatex(0px); - } - 65% { - height: 0.4em; - width: 0.4em; - } - 100% { - height: 0.5em; - width: 0.3em; - -webkit-transform: translatex(0.2em); - transform: translatex(0.2em); - } - } - - @keyframes loader-34-1 { - 0% { - -webkit-transform: translatex(0px); - transform: translatex(0px); - } - 65% { - height: 0.4em; - width: 0.4em; - } - 100% { - height: 0.5em; - width: 0.3em; - -webkit-transform: translatex(0.2em); - transform: translatex(0.2em); - } - } - @-webkit-keyframes loader-34-2 { - 0% { - -webkit-transform: translatex(0px); - transform: translatex(0px); - } - 65% { - height: 0.4em; - width: 0.4em; - } - 100% { - height: 0.5em; - width: 0.3em; - -webkit-transform: translatex(-0.2em); - transform: translatex(-0.2em); - } - } - @keyframes loader-34-2 { - 0% { - -webkit-transform: translatex(0px); - transform: translatex(0px); - } - 65% { - height: 0.4em; - width: 0.4em; - } - 100% { - height: 0.5em; - width: 0.3em; - -webkit-transform: translatex(-0.2em); - transform: translatex(-0.2em); - } - } - .loader-35 { - margin: 0 0.5em; - position: relative; - } - .loader-35:before { - border-radius: 50%; - background-color: currentcolor; - -webkit-animation: loader-35 3s cubic-bezier(0.77, 0, 0.175, 1) infinite; - animation: loader-35 3s cubic-bezier(0.77, 0, 0.175, 1) infinite; - content: ""; - width: inherit; - height: inherit; - top: 0; - left: 0; - position: absolute; - } - - @-webkit-keyframes loader-35 { - 0% { - -webkit-transform: translateX(0) scale(1); - transform: translateX(0) scale(1); - } - 25% { - -webkit-transform: translateX(-100%) scale(0.3); - transform: translateX(-100%) scale(0.3); - } - 50% { - -webkit-transform: translateX(0) scale(1); - transform: translateX(0) scale(1); - } - 75% { - -webkit-transform: translateX(100%) scale(0.3); - transform: translateX(100%) scale(0.3); - } - 100% { - -webkit-transform: translateX(0) scale(1); - transform: translateX(0) scale(1); - } - } - - @keyframes loader-35 { - 0% { - -webkit-transform: translateX(0) scale(1); - transform: translateX(0) scale(1); - } - 25% { - -webkit-transform: translateX(-100%) scale(0.3); - transform: translateX(-100%) scale(0.3); - } - 50% { - -webkit-transform: translateX(0) scale(1); - transform: translateX(0) scale(1); - } - 75% { - -webkit-transform: translateX(100%) scale(0.3); - transform: translateX(100%) scale(0.3); - } - 100% { - -webkit-transform: translateX(0) scale(1); - transform: translateX(0) scale(1); - } - } - .loader-36 { - position: relative; - } - .loader-36:before, .loader-36:after { - content: ""; - position: absolute; - top: 0; - left: 0; - } - .loader-36:before { - width: 1em; - height: 1em; - border: 0.1em solid currentcolor; - border-radius: 50%; - -webkit-animation: loader-36-1 1.15s infinite -0.3s; - animation: loader-36-1 1.15s infinite -0.3s; - } - .loader-36:after { - right: 0; - bottom: 0; - margin: auto; - width: 0; - height: 0; - border: 0.1em solid currentcolor; - border-radius: 50%; - -webkit-transform: translate(-0.2em); - transform: translate(-0.2em); - -webkit-animation: loader-36-2 4.6s infinite steps(1); - animation: loader-36-2 4.6s infinite steps(1); - } - - @-webkit-keyframes loader-36-1 { - to { - -webkit-transform: rotateX(180deg); - transform: rotateX(180deg); - } - } - - @keyframes loader-36-1 { - to { - -webkit-transform: rotateX(180deg); - transform: rotateX(180deg); - } - } - @-webkit-keyframes loader-36-2 { - 0% { - opacity: 0; - } - 25% { - opacity: 1; - } - 50% { - box-shadow: 0.2em 0 0 currentcolor; - } - 75% { - box-shadow: 0.2em 0 0 currentcolor, 0.4em 0 0 currentcolor; - } - } - @keyframes loader-36-2 { - 0% { - opacity: 0; - } - 25% { - opacity: 1; - } - 50% { - box-shadow: 0.2em 0 0 currentcolor; - } - 75% { - box-shadow: 0.2em 0 0 currentcolor, 0.4em 0 0 currentcolor; - } - } - .loader-37 { - border-right: 0.1em solid currentcolor; - border-radius: 100%; - -webkit-animation: loader-37 800ms linear infinite; - animation: loader-37 800ms linear infinite; - } - .loader-37:before, .loader-37:after { - content: ""; - width: 0.8em; - height: 0.8em; - display: block; - position: absolute; - top: calc(50% - 0.4em); - left: calc(50% - 0.4em); - border-left: 0.08em solid currentcolor; - border-radius: 100%; - animation: loader-37 400ms linear infinite reverse; - } - .loader-37:after { - width: 0.6em; - height: 0.6em; - top: calc(50% - 0.3em); - left: calc(50% - 0.3em); - border: 0; - border-right: 0.05em solid currentcolor; - -webkit-animation: none; - animation: none; - } - - @-webkit-keyframes loader-37 { - from { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - to { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - } - - @keyframes loader-37 { - from { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - to { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - } - .loader-38 { - height: 0.1em; - width: 0.1em; - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor; - -webkit-animation: loader-38 6s infinite; - animation: loader-38 6s infinite; - } - - @-webkit-keyframes loader-38 { - 0% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor; - } - 8.33% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor; - } - 16.66% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor; - } - 24.99% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 33.32% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor; - } - 41.65% { - box-shadow: 0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor; - } - 49.98% { - box-shadow: 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor; - } - 58.31% { - box-shadow: -0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 66.64% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 74.97% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 83.3% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 91.63% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 100% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor; - } - } - - @keyframes loader-38 { - 0% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor; - } - 8.33% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor; - } - 16.66% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor; - } - 24.99% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 33.32% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor; - } - 41.65% { - box-shadow: 0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor; - } - 49.98% { - box-shadow: 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor; - } - 58.31% { - box-shadow: -0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 66.64% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 74.97% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 83.3% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, 0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 91.63% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor, -0.2em 0.2em 0 0.1em currentcolor; - } - 100% { - box-shadow: -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor, -0.2em -0.2em 0 0.1em currentcolor; - } - } - .loader-39 { - position: relative; - width: 0.15em; - height: 0.15em; - background-color: currentcolor; - border-radius: 100%; - -webkit-animation: loader-39-1 30s infinite linear; - animation: loader-39-1 30s infinite linear; - } - .loader-39:before, .loader-39:after { - content: ""; - border-radius: 100%; - position: absolute; - top: 50%; - left: 50%; - -webkit-transform: translate(-50%, -50%); - transform: translate(-50%, -50%); - } - .loader-39:before { - width: 0.3em; - height: 1em; - -webkit-animation: loader-39-2 0.8s linear infinite; - animation: loader-39-2 0.8s linear infinite; - } - .loader-39:after { - width: 1em; - height: 0.3em; - -webkit-animation: loader-39-2 1.2s linear infinite; - animation: loader-39-2 1.2s linear infinite; - } - - @-webkit-keyframes loader-39-1 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - - @keyframes loader-39-1 { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(360deg); - transform: rotate(360deg); - } - } - @-webkit-keyframes loader-39-2 { - 0% { - box-shadow: 0.04em -0.04em 0 0.02em currentcolor; - } - 25% { - box-shadow: 0.04em 0.04em 0 0.02em currentcolor; - } - 50% { - box-shadow: -0.04em 0.04em 0 0.02em currentcolor; - } - 75% { - box-shadow: -0.04em -0.04em 0 0.02em currentcolor; - } - 100% { - box-shadow: 0.04em -0.04em 0 0.02em currentcolor; - } - } - @keyframes loader-39-2 { - 0% { - box-shadow: 0.04em -0.04em 0 0.02em currentcolor; - } - 25% { - box-shadow: 0.04em 0.04em 0 0.02em currentcolor; - } - 50% { - box-shadow: -0.04em 0.04em 0 0.02em currentcolor; - } - 75% { - box-shadow: -0.04em -0.04em 0 0.02em currentcolor; - } - 100% { - box-shadow: 0.04em -0.04em 0 0.02em currentcolor; - } - } - .loader-40 { - border: 0.05em currentcolor solid; - border-radius: 0.2em; - overflow: hidden; - position: relative; - } - .loader-40:after, .loader-40:before { - content: ""; - border-radius: 50%; - position: absolute; - width: inherit; - height: inherit; - -webkit-animation: loader-40 2s infinite linear; - animation: loader-40 2s infinite linear; - } - .loader-40:before { - border-top: 0.2em currentcolor solid; - top: -0.15em; - left: calc(-50% - 0.15em); - -webkit-transform-origin: right center; - transform-origin: right center; - } - .loader-40:after { - border-bottom: 0.2em currentcolor solid; - top: 0.15em; - right: calc(-50% - 0.15em); - -webkit-transform-origin: left center; - transform-origin: left center; - } - - @-webkit-keyframes loader-40 { - from { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - to { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } - } - - @keyframes loader-40 { - from { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - to { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } - } - .loader-41 { - border: 0.05em currentcolor solid; - border-radius: 0.2em; - position: relative; - background: linear-gradient(45deg, transparent 48%, currentcolor 50%, currentcolor 50%, transparent 52%, transparent), linear-gradient(-45deg, transparent 48%, currentcolor 50%, currentcolor 50%, transparent 52%, transparent); - background-size: 0.5em 0.5em; - background-position: 0% 0%; - -webkit-animation: loader-41 1s infinite linear; - animation: loader-41 1s infinite linear; - } - - @-webkit-keyframes loader-41 { - from { - background-position: 0 0; - } - to { - background-position: -1em 0; - } - } - - @keyframes loader-41 { - from { - background-position: 0 0; - } - to { - background-position: -1em 0; - } - } - .loader-42 { - width: 2em; - height: 0.66em; - border: 0.05em currentcolor solid; - border-radius: 0.1em; - background: linear-gradient(-60deg, transparent 0%, transparent 50%, currentcolor 50%, currentcolor 75%, transparent 75%, transparent); - background-size: 1em 2em; - background-position: 0 0; - -webkit-animation: loader-42 0.8s infinite linear; - animation: loader-42 0.8s infinite linear; - } - - @-webkit-keyframes loader-42 { - from { - background-position: 0 0; - } - to { - background-position: -2em 0; - } - } - - @keyframes loader-42 { - from { - background-position: 0 0; - } - to { - background-position: -2em 0; - } - } +fieldset { + border: 0 !important; + margin: 0 !important; + padding: 0 !important; +} - +[class*="loader-"] { + display: inline-block; + width: 1em; + height: 1em; + color: inherit; + vertical-align: middle; + pointer-events: none; +} + +.loader-37 { + border-right: 0.1em solid currentcolor; + border-radius: 100%; + -webkit-animation: loader-37 800ms linear infinite; + animation: loader-37 800ms linear infinite; +} +.loader-37:before, +.loader-37:after { + content: ""; + width: 0.8em; + height: 0.8em; + display: block; + position: absolute; + top: calc(50% - 0.4em); + left: calc(50% - 0.4em); + border-left: 0.08em solid currentcolor; + border-radius: 100%; + animation: loader-37 400ms linear infinite reverse; +} +.loader-37:after { + width: 0.6em; + height: 0.6em; + top: calc(50% - 0.3em); + left: calc(50% - 0.3em); + border: 0; + border-right: 0.05em solid currentcolor; + -webkit-animation: none; + animation: none; +} + +@-webkit-keyframes loader-37 { + from { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + to { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } +} + +@keyframes loader-37 { + from { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } + to { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } +} diff --git a/apps/OpenSign/src/styles/toast.css b/apps/OpenSign/src/styles/toast.css index 4e3ff0bc9..409833af9 100644 --- a/apps/OpenSign/src/styles/toast.css +++ b/apps/OpenSign/src/styles/toast.css @@ -1,209 +1,64 @@ #snackbar { - visibility: hidden; - min-width: 250px; - margin-left: -125px; - background-color: #333; - color: #fff; - text-align: center; - border-radius: 2px; - padding: 16px; - position: fixed; - z-index: 99999; - left: 50%; + visibility: hidden; + min-width: 250px; + margin-left: -125px; + background-color: #333; + color: #fff; + text-align: center; + border-radius: 2px; + padding: 16px; + position: fixed; + z-index: 99999; + left: 50%; + top: 30px; + font-size: 14px; +} + +#snackbar.show { + visibility: visible; + -webkit-animation: fadein 0.5s; +} + +@-webkit-keyframes fadein { + from { + top: 0; + opacity: 0; + } + to { top: 30px; - font-size: 14px; + opacity: 1; } - - #_editsnackbar { - visibility: hidden; - min-width: 250px; - margin-left: -125px; - background-color: #333; - color: #fff; - text-align: center; - border-radius: 2px; - padding: 16px; - position: fixed; - z-index: 99999; - left: 50%; +} + +@keyframes fadein { + from { + top: 0; + opacity: 0; + } + to { top: 30px; - font-size: 14px; + opacity: 1; } - - #_editsnackbar.show { - visibility: visible; - -webkit-animation: fadein 0.5s; - } - - #UpdateColumnValue.show { - visibility: visible; - -webkit-animation: fadein 0.5s; - } - #DeleteUser.show { - visibility: visible; - -webkit-animation: fadein 0.5s; - } - #DeleteUser { - visibility: hidden; - min-width: 250px; - margin-left: -125px; - background-color: #333; - color: #fff; - text-align: center; - border-radius: 2px; - padding: 16px; - position: fixed; - z-index: 99999; - left: 50%; +} + +@-webkit-keyframes fadeout { + from { top: 30px; - font-size: 14px; + opacity: 1; } - - #deleteObj.show { - visibility: visible; - -webkit-animation: fadein 0.5s; + to { + top: 0; + opacity: 0; } - #deleteObj { - visibility: hidden; - min-width: 250px; - margin-left: -125px; - background-color: #333; - color: #fff; - text-align: center; - border-radius: 2px; - padding: 16px; - position: fixed; - z-index: 99999; - left: 50%; +} + +@keyframes fadeout { + from { top: 30px; - font-size: 14px; + opacity: 1; } - - #UpdateColumnValue { - visibility: hidden; - min-width: 250px; - margin-left: -125px; - background-color: #333; - color: #fff; - text-align: center; - border-radius: 2px; - padding: 16px; - position: fixed; - z-index: 99999; - left: 50%; - top: 30px; - font-size: 14px; + to { + top: 0; + opacity: 0; } - - #snackbar.show { - visibility: visible; - -webkit-animation: fadein 0.5s; - } - - #snackbar1 { - visibility: hidden; - min-width: 250px; - margin-left: -125px; - background-color: #333; - color: #fff; - text-align: center; - border-radius: 2px; - padding: 16px; - position: fixed; - z-index: 99999; - left: 50%; - top: 30px; - font-size: 14px; - } - - #snackbar1.show { - visibility: visible; - -webkit-animation: fadein 0.5s; - } - - #snackbar10 { - visibility: hidden; - min-width: 250px; - margin-left: -125px; - background-color: #333; - color: #fff; - text-align: center; - border-radius: 2px; - padding: 16px; - position: fixed; - z-index: 99999; - left: 50%; - top: 30px; - font-size: 14px; - } - - #snackbar10.show { - visibility: visible; - -webkit-animation: fadein 0.5s; - } - - #snackbarCol { - visibility: hidden; - min-width: 250px; - margin-left: -125px; - background-color: #333; - color: #fff; - text-align: center; - border-radius: 2px; - padding: 16px; - position: fixed; - z-index: 99999; - left: 50%; - top: 30px; - font-size: 14px; - } - - #snackbarCol.show { - visibility: visible; - -webkit-animation: fadein 0.5s; - } - - @-webkit-keyframes fadein { - from { - top: 0; - opacity: 0; - } - to { - top: 30px; - opacity: 1; - } - } - - @keyframes fadein { - from { - top: 0; - opacity: 0; - } - to { - top: 30px; - opacity: 1; - } - } - - @-webkit-keyframes fadeout { - from { - top: 30px; - opacity: 1; - } - to { - top: 0; - opacity: 0; - } - } - - @keyframes fadeout { - from { - top: 30px; - opacity: 1; - } - to { - top: 0; - opacity: 0; - } - } - \ No newline at end of file +} diff --git a/apps/OpenSignServer/Dockerfile b/apps/OpenSignServer/Dockerfile index 68962a8be..f56d3c5cf 100644 --- a/apps/OpenSignServer/Dockerfile +++ b/apps/OpenSignServer/Dockerfile @@ -1,5 +1,5 @@ # Use an official Node runtime as the base image -FROM node:16 +FROM node:18 # Set the working directory inside the container WORKDIR /usr/src/app diff --git a/apps/OpenSignServer/Dockerhubfile b/apps/OpenSignServer/Dockerhubfile new file mode 100644 index 000000000..700fb692d --- /dev/null +++ b/apps/OpenSignServer/Dockerhubfile @@ -0,0 +1,27 @@ +# Use an official Node runtime as the base image +FROM node:18 + +# Set the working directory inside the container +WORKDIR /usr/src/app + +# Copy package.json and package-lock.json first to leverage Docker cache +COPY apps/OpenSignServer/package*.json ./ + +# Install application dependencies +RUN npm install + +# If you have native dependencies, you'll need extra tools. Uncomment the following line if needed. +# RUN apk add --no-cache make gcc g++ python3 + +# Copy the current directory contents into the container +COPY apps/OpenSignServer/ . + +# Make port 8080 available to the world outside this container +EXPOSE 8080 + +# Define environment variables if needed +# ENV NODE_ENV production +# ENV DATABASE_URL mongodb://db:27017 + +# Run the application +CMD ["npm", "start"] diff --git a/apps/OpenSignServer/Utils.js b/apps/OpenSignServer/Utils.js new file mode 100644 index 000000000..8fc705ceb --- /dev/null +++ b/apps/OpenSignServer/Utils.js @@ -0,0 +1,40 @@ +export function customAPIurl() { + const url = new URL(process.env.SERVER_URL); + return url.pathname === '/api/app' ? url.origin + '/api' : url.origin; +} + +export const color = [ + '#93a3db', + '#e6c3db', + '#c0e3bc', + '#bce3db', + '#b8ccdb', + '#ceb8db', + '#ffccff', + '#99ffcc', + '#cc99ff', + '#ffcc99', + '#66ccff', + '#ffffcc', +]; + +export function replaceMailVaribles(subject, body, variables) { + let replacedSubject = subject; + let replacedBody = body; + + for (const variable in variables) { + const regex = new RegExp(`{{${variable}}}`, 'g'); + if (subject) { + replacedSubject = replacedSubject.replace(regex, variables[variable]); + } + if (body) { + replacedBody = replacedBody.replace(regex, variables[variable]); + } + } + + const result = { + subject: replacedSubject, + body: replacedBody, + }; + return result; +} diff --git a/apps/OpenSignServer/cloud/customRoute/uploadFile.js b/apps/OpenSignServer/cloud/customRoute/uploadFile.js index b0152e1bd..352f7711b 100644 --- a/apps/OpenSignServer/cloud/customRoute/uploadFile.js +++ b/apps/OpenSignServer/cloud/customRoute/uploadFile.js @@ -47,53 +47,78 @@ async function uploadFile(req, res) { const DO_ACCESS_KEY_ID = process.env.DO_ACCESS_KEY_ID; const DO_SECRET_ACCESS_KEY = process.env.DO_SECRET_ACCESS_KEY; const DO_SPACE = process.env.DO_SPACE; - const spacesEndpoint = new aws.Endpoint(DO_ENDPOINT); - const s3 = new aws.S3({ - endpoint: spacesEndpoint, - accessKeyId: DO_ACCESS_KEY_ID, - secretAccessKey: DO_SECRET_ACCESS_KEY, - signatureVersion: 'v4', - region: process.env.DO_REGION, - }); const parseBaseUrl = process.env.SERVER_URL; const parseAppId = process.env.APP_ID; - - if (process.env.USE_LOCAL == "TRUE") { - var fileStorage = multer.diskStorage({ - destination: function(req, file, cb) { - cb(null, "files/files"); + let fileStorage; + if (process.env.USE_LOCAL == 'TRUE') { + fileStorage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, 'files/files'); }, metadata: function (req, file, cb) { cb(null, { fieldName: 'OPENSIGN_METADATA' }); }, - filename: function(req, file, cb) { + filename: function (req, file, cb) { let filename = file.originalname; let newFileName = filename.split('.')[0]; let extension = filename.split('.')[1]; - newFileName = sanitizeFileName(newFileName + '_' + new Date().toISOString() + '.' + extension) + newFileName = sanitizeFileName( + newFileName + '_' + new Date().toISOString() + '.' + extension + ); console.log(newFileName); cb(null, newFileName); - } + }, }); } else { - var fileStorage = multerS3({ - acl: 'public-read', - s3, - bucket: DO_SPACE, - metadata: function (req, file, cb) { - cb(null, { fieldName: 'OPENSIGN_METADATA' }); - }, - key: function (req, file, cb) { - //console.log(file); - let filename = file.originalname; - let newFileName = filename.split('.')[0]; - let extension = filename.split('.')[1]; - newFileName = sanitizeFileName(newFileName + '_' + new Date().toISOString() + '.' + extension) - console.log(newFileName); - cb(null, newFileName); - } - }); + try { + const spacesEndpoint = new aws.Endpoint(DO_ENDPOINT); + const s3 = new aws.S3({ + endpoint: spacesEndpoint, + accessKeyId: DO_ACCESS_KEY_ID, + secretAccessKey: DO_SECRET_ACCESS_KEY, + signatureVersion: 'v4', + region: process.env.DO_REGION, + }); + fileStorage = multerS3({ + acl: 'public-read', + s3, + bucket: DO_SPACE, + metadata: function (req, file, cb) { + cb(null, { fieldName: 'OPENSIGN_METADATA' }); + }, + key: function (req, file, cb) { + //console.log(file); + let filename = file.originalname; + let newFileName = filename.split('.')[0]; + let extension = filename.split('.')[1]; + newFileName = sanitizeFileName( + newFileName + '_' + new Date().toISOString() + '.' + extension + ); + console.log(newFileName); + cb(null, newFileName); + }, + }); + } catch (err) { + fileStorage = multer.diskStorage({ + destination: function (req, file, cb) { + cb(null, 'files/files'); + }, + metadata: function (req, file, cb) { + cb(null, { fieldName: 'OPENSIGN_METADATA' }); + }, + filename: function (req, file, cb) { + let filename = file.originalname; + let newFileName = filename.split('.')[0]; + let extension = filename.split('.')[1]; + newFileName = sanitizeFileName( + newFileName + '_' + new Date().toISOString() + '.' + extension + ); + console.log(newFileName); + cb(null, newFileName); + }, + }); + } } // const s3 = new aws.S3(); @@ -122,7 +147,7 @@ async function uploadFile(req, res) { const status = 'Success'; //res.header("Access-Control-Allow-Headers", "Content-Type"); //res.setHeader("Access-Control-Allow-Origin", "*"); - if (process.env.USE_LOCAL == "TRUE") { + if (process.env.USE_LOCAL == 'TRUE') { console.log(req.file); var fileUrl = `${parseBaseUrl}/files/${parseAppId}/${req.file.filename}`; } else { diff --git a/apps/OpenSignServer/cloud/customRoute/v1/apiV1.js b/apps/OpenSignServer/cloud/customRoute/v1/apiV1.js new file mode 100644 index 000000000..343db0d3c --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/apiV1.js @@ -0,0 +1,104 @@ +//--npm modules +import express from 'express'; +import cors from 'cors'; +export const app = express(); +import dotenv from 'dotenv'; +import getUser from './routes/getUser.js'; +import getDocumentList from './routes/getDocumentList.js'; +import getDocument from './routes/getDocument.js'; +import getContact from './routes/getContact.js'; +import deleteContact from './routes/deleteContact.js'; +import getContactList from './routes/getContactList.js'; +import draftDocument from './routes/draftDocument.js'; +import createTemplate from './routes/createTemplate.js'; +import getTemplate from './routes/getTemplate.js'; +import deletedTemplate from './routes/deleteTemplate.js'; +import getTemplatetList from './routes/getTemplateList.js'; +import updateTemplate from './routes/updateTemplate.js'; +import createContact from './routes/createContact.js'; +import multer from 'multer'; +// import fs from 'node:fs'; +import updateDocument from './routes/updateDocument.js'; +import deleteDocument from './routes/deleteDocument.js'; +import createDocumentWithTemplate from './routes/CreateDocumentWithTemplate.js'; +import saveWebhook from './routes/saveWebhook.js'; +import deleteWebhook from './routes/deleteWebhook.js'; +import getWebhook from './routes/getWebhook.js'; +import createDocumentwithCoordinate from './routes/createDocumentwithCoordinate.js'; +import createTemplatewithCoordinate from './routes/createTemplatewithCoordinate.js'; +dotenv.config(); +const storage = multer.memoryStorage(); +const upload = multer({ storage: storage }); + +app.use(cors()); +app.use(express.json({ limit: '50mb' })); +app.use(express.urlencoded({ limit: '50mb', extended: true })); + +// get user details whose api token used +app.get('/getuser', getUser); + +// get contact on the basis of id +app.post('/createcontact', createContact); + +// get contact on the basis of id +app.get('/contact/:contact_id', getContact); + +// soft delete contact +app.delete('/contact/:contact_id', deleteContact); + +// get list of contacts +app.get('/contactlist', getContactList); + +// create Document +app.post('/createdocumentwithbinary', upload.array('file', 1), createDocumentwithCoordinate); + +// create Document with co-ordinate +app.post('/createdocument', createDocumentwithCoordinate); + +// create Document with base64 without placeholder +app.post('/draftdocument', draftDocument); + +// create Document with templateId +app.post('/createdocument/:template_id', createDocumentWithTemplate); + +// get Document on the basis of id +app.get('/document/:document_id', getDocument); + +// get document on the basis of id +app.put('/document/:document_id', updateDocument); + +// get document on the basis of id +app.delete('/document/:document_id', deleteDocument); + +// get all types of documents on the basis of doctype +app.get('/documentlist/:doctype', getDocumentList); + +// create Template with co-ordinate +app.post('/createtemplate', createTemplatewithCoordinate); + +// create Template +app.post('/drafttemplate', createTemplate); + +// create Template with binary +app.post('/createtemplatewithbinary', upload.array('file', 1), createTemplatewithCoordinate); + +// get template on the basis of id +app.get('/template/:template_id', getTemplate); + +// get template on the basis of id +app.put('/template/:template_id', updateTemplate); + +// get template on the basis of id +app.delete('/template/:template_id', deletedTemplate); + +// get all types of documents on the basis of doctype +app.get('/templatelist', getTemplatetList); + +// set and update webhook +app.get('/webhook', getWebhook); + +// set and update webhook +app.post('/webhook', saveWebhook); + +// set and update webhook +app.delete('/webhook', deleteWebhook); diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js new file mode 100644 index 000000000..6ef70f07a --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/CreateDocumentWithTemplate.js @@ -0,0 +1,367 @@ +import axios from 'axios'; +import { customAPIurl, replaceMailVaribles } from '../../../../Utils.js'; + +// `sendDoctoWebhook` is used to send res data of document on webhook +async function sendDoctoWebhook(doc, WebhookUrl, userId) { + if (WebhookUrl) { + const params = { + event: 'created', + ...doc, + }; + await axios + .post(WebhookUrl, params, { + headers: { 'Content-Type': 'application/json' }, + }) + .then(res => { + try { + // console.log('res ', res); + const webhook = new Parse.Object('contracts_Webhook'); + webhook.set('Log', res?.status); + webhook.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: userId, + }); + webhook.save(null, { useMasterKey: true }); + } catch (err) { + console.log('err save in contracts_Webhook', err); + } + }) + .catch(err => { + console.log('Err send data to webhook', err); + try { + const webhook = new Parse.Object('contracts_Webhook'); + webhook.set('Log', err?.status); + webhook.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: userId, + }); + webhook.save(null, { useMasterKey: true }); + } catch (err) { + console.log('err save in contracts_Webhook', err); + } + }); + // console.log('res ', res.data); + } +} +export default async function createDocumentWithTemplate(request, response) { + const signers = request.body.signers; + const folderId = request.body.folderId; + const templateId = request.params.template_id; + const protocol = customAPIurl(); + const baseUrl = new URL(process.env.SERVER_URL); + const send_email = request.body.send_email; + const email_subject = request.body.email_subject; + const email_body = request.body.email_body; + const sendInOrder = request.body.sendInOrder || false; + + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + const templateQuery = new Parse.Query('contracts_Template'); + templateQuery.include('ExtUserPtr'); + const templateRes = await templateQuery.get(templateId, { useMasterKey: true }); + if (templateRes) { + const template = JSON.parse(JSON.stringify(templateRes)); + if (template?.Placeholders?.length > 0) { + const emptyplaceholder = template?.Placeholders.filter(x => !x.signerObjId); + const isValid = + signers.length >= emptyplaceholder.length && + signers.length <= template?.Placeholders?.length; + const placeholder = + signers.length > emptyplaceholder.length ? template.Placeholders : emptyplaceholder; + const updateSigners = placeholder.every(y => signers?.some(x => x.role === y.Role)); + // console.log('isValid ', isValid); + if (isValid && updateSigners) { + const folderPtr = { + __type: 'Pointer', + className: 'contracts_Document', + objectId: folderId, + }; + const template = JSON.parse(JSON.stringify(templateRes)); + const object = new Parse.Object('contracts_Document'); + object.set('Name', template.Name); + if (template?.Note) { + object.set('Note', template.Note); + } + if (template?.Description) { + object.set('Description', template.Description); + } + object.set('IsSendMail', send_email); + if (sendInOrder) { + object.set('SendinOrder', sendInOrder); + } else if (template?.SendinOrder && template?.SendinOrder) { + object.set('SendinOrder', template?.SendinOrder); + } + let templateSigner = template?.Signers ? template?.Signers : []; + let contact = []; + if (signers && signers.length > 0) { + let parseSigners = [...signers]; + let createContactUrl = protocol + '/v1/createcontact'; + + for (const obj of parseSigners) { + const body = { + name: obj?.name || '', + email: obj?.email || '', + phone: obj?.phone || '', + }; + try { + const res = await axios.post(createContactUrl, body, { + headers: { 'Content-Type': 'application/json', 'x-api-token': reqToken }, + }); + const contactPtr = { + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: res.data?.objectId, + }; + const newObj = { ...obj, contactPtr: contactPtr }; + contact.push(newObj); + } catch (err) { + // console.log('err ', err); + if (err?.response?.data?.objectId) { + const contactPtr = { + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: err.response.data?.objectId, + }; + const newObj = { ...obj, contactPtr: contactPtr }; + contact.push(newObj); + } else { + console.log('err ', err); + } + } + } + const contactPtrs = contact.map(x => x.contactPtr); + object.set('Signers', [...templateSigner, ...contactPtrs]); + + let updatedPlaceholder = template?.Placeholders?.map(x => { + let matchingSigner = contact.find(y => x.Role && x.Role === y.role); + + if (matchingSigner) { + return { + ...x, + signerObjId: matchingSigner?.contactPtr?.objectId, + signerPtr: matchingSigner?.contactPtr, + }; + } else { + return { + ...x, + }; + } + }); + object.set('Placeholders', updatedPlaceholder); + } else { + object.set('Signers', templateSigner); + } + object.set('URL', template.URL); + object.set('CreatedBy', template.CreatedBy); + object.set('ExtUserPtr', { + __type: 'Pointer', + className: 'contracts_Users', + objectId: template.ExtUserPtr.objectId, + }); + if (folderId) { + object.set('Folder', folderPtr); + } + const newACL = new Parse.ACL(); + newACL.setPublicReadAccess(false); + newACL.setPublicWriteAccess(false); + newACL.setReadAccess(userPtr.objectId, true); + newACL.setWriteAccess(userPtr.objectId, true); + object.setACL(newACL); + const res = await object.save(null, { useMasterKey: true }); + + const newDate = new Date(); + newDate.setDate(newDate.getDate() + 15); + const localExpireDate = newDate.toLocaleDateString('en-US', { + day: 'numeric', + month: 'long', + year: 'numeric', + }); + let sender = template.ExtUserPtr.Email; + let sendMail; + const serverUrl = process.env.SERVER_URL; + const newServer = serverUrl.replaceAll('/', '%2F'); + const serverParams = `${newServer}%2F&${process.env.APP_ID}&contracts`; + if (send_email === false) { + console.log("don't send mail"); + } else { + let contactMail = contact; + if (sendInOrder) { + contactMail = contact.slice(); + contactMail.splice(1); + } + for (let i = 0; i < contactMail.length; i++) { + try { + const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png'; + let url = `${process.env.SERVER_URL}/functions/sendmailv3/`; + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': process.env.APP_ID, + 'X-Parse-Master-Key': process.env.MASTER_KEY, + }; + + const objectId = contactMail[i].contactPtr.objectId; + + const hostUrl = baseUrl.origin + '/loadmf/signmicroapp'; + let signPdf = `${hostUrl}/login/${res.id}/${contactMail[i].email}/${objectId}/${serverParams}`; + const openSignUrl = 'https://www.opensignlabs.com/contact-us'; + const orgName = template.ExtUserPtr.Company ? template.ExtUserPtr.Company : ''; + const themeBGcolor = '#47a3ad'; + const email_html = + "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src='" + + imgPng + + "' height='50' style='padding:20px; width:170px; height:40px;' /></div><div style='padding: 2px;font-family: system-ui;background-color:" + + themeBGcolor + + ";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " + + template.ExtUserPtr.Name + + ' has requested you to review and sign <strong> ' + + template.Name + + "</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" + + sender + + "</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " + + orgName + + "</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" + + localExpireDate + + "</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" + + signPdf + + "> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px;'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " + + sender + + ' directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=' + + openSignUrl + + ' target=_blank>here</a>.</p> </div></div></body> </html>'; + + let replaceVar; + const variables = { + document_title: template.Name, + sender_name: template.ExtUserPtr.Name, + sender_mail: template.ExtUserPtr.Email, + sender_phone: template.ExtUserPtr.Phone, + receiver_name: contactMail[i].name, + receiver_email: contactMail[i].email, + receiver_phone: contactMail[i].phone, + expiry_date: localExpireDate, + company_name: orgName, + signing_url: signPdf, + }; + if (email_subject && email_body) { + replaceVar = replaceMailVaribles(email_subject, email_body, variables); + } else if (email_subject) { + replaceVar = replaceMailVaribles(email_subject, '', variables); + replaceVar = { subject: replaceVar.subject, body: email_html }; + } else if (email_body) { + replaceVar = replaceMailVaribles( + `${template.ExtUserPtr.Name} has requested you to sign ${template.Name}`, + email_body, + variables + ); + } else { + replaceVar = { + subject: `${template.ExtUserPtr.Name} has requested you to sign ${template.Name}`, + body: email_html, + }; + } + + const subject = replaceVar.subject; + const html = replaceVar.body; + let params = { + recipient: contactMail[i].email, + subject: subject, + from: sender, + html: html, + }; + sendMail = await axios.post(url, params, { headers: headers }); + } catch (error) { + console.log('error', error); + } + } + } + // if (sendMail.data.result.status === 'success') { + try { + const doc = { + objectId: res.id, + file: template?.URL, + name: template?.Name, + note: template?.Note || '', + description: template?.Description || '', + signers: contact?.map(x => ({ name: x.name, email: x.email, phone: x.phone })), + createdAt: res.createdAt, + }; + if (template.ExtUserPtr && template.ExtUserPtr?.Webhook) { + sendDoctoWebhook(doc, template.ExtUserPtr?.Webhook, userPtr?.objectId); + } + } catch (err) { + console.log('Err', err); + } + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_document_with_templateid', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: res.id, + signurl: contact.map(x => ({ + email: x.email, + url: `${baseUrl.origin}/loadmf/signmicroapp/login/${res.id}/${x.email}/${x.contactPtr.objectId}/${serverParams}`, + })), + message: 'Document sent successfully!', + }); + // } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_document_with_templateid', + properties: { response_code: 400 }, + }); + } + return response.status(400).json({ error: 'Please provide signers properly!' }); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_document_with_templateid', + properties: { response_code: 400 }, + }); + } + return response.status(400).json({ error: 'Please setup template properly!' }); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_document_with_templateid', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Invalid template id!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + if (err.code === 101) { + return response.status(404).json({ error: 'Invalid template id!' }); + } + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/createContact.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/createContact.js new file mode 100644 index 000000000..32d4683f5 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/createContact.js @@ -0,0 +1,216 @@ +import axios from 'axios'; +export default async function createContact(request, response) { + const serverUrl = process.env.SERVER_URL; + const appId = process.env.APP_ID; + const name = request.body.name; + const phone = request.body.phone; + const email = request.body.email; + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + + try { + const contactbook = new Parse.Query('contracts_Contactbook'); + contactbook.equalTo('Email', email); + contactbook.equalTo('CreatedBy', userPtr); + contactbook.notEqualTo('IsDeleted', true); + const userExists = await contactbook.first({ useMasterKey: true }); + + if (userExists) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_contact', + properties: { response_code: 401 }, + }); + } + return response + .status(401) + .json({ error: 'Contact already exists!', objectId: userExists.id }); + } else { + try { + const Tenant = new Parse.Query('partners_Tenant'); + Tenant.equalTo('UserId', userPtr); + const tenantRes = await Tenant.first({ useMasterKey: true }); + + const contactQuery = new Parse.Object('contracts_Contactbook'); + contactQuery.set('Name', name); + contactQuery.set('Phone', phone); + contactQuery.set('Email', email); + contactQuery.set('UserRole', 'contracts_Guest'); + if (tenantRes && tenantRes.id) { + contactQuery.set('TenantId', { + __type: 'Pointer', + className: 'partners_Tenant', + objectId: tenantRes.id, + }); + } + try { + const _users = Parse.Object.extend('User'); + const _user = new _users(); + _user.set('name', name); + _user.set('username', email); + _user.set('email', email); + _user.set('phone', phone); + _user.set('password', phone); + + const user = await _user.save(); + if (user) { + const roleurl = `${serverUrl}/functions/AddUserToRole`; + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': appId, + // sessionToken: localStorage.getItem('accesstoken'), + }; + const body = { + appName: 'contracts', + roleName: 'contracts_Guest', + userId: user.id, + }; + await axios.post(roleurl, body, { headers: headers }); + const currentUser = userPtr; + contactQuery.set('CreatedBy', currentUser); + contactQuery.set('UserId', user); + + const acl = new Parse.ACL(); + acl.setReadAccess(userPtr.objectId, true); + acl.setWriteAccess(userPtr.objectId, true); + acl.setReadAccess(user.id, true); + acl.setWriteAccess(user.id, true); + contactQuery.setACL(acl); + + const contactRes = await contactQuery.save(); + const parseRes = JSON.parse(JSON.stringify(contactRes)); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_contact', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: parseRes.objectId, + name: parseRes.Name, + email: parseRes.Email, + phone: parseRes.Phone, + createdAt: parseRes.createdAt, + updatedAt: parseRes.updatedAt, + }); + } + } catch (err) { + console.log('err in', err); + if (err.code === 202) { + const params = { email: email }; + const userRes = await Parse.Cloud.run('getUserId', params); + const roleurl = `${serverUrl}/functions/AddUserToRole`; + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': appId, + // sessionToken: localStorage.getItem('accesstoken'), + }; + const body = { + appName: 'contracts', + roleName: 'contracts_Guest', + userId: userRes.objectId, + }; + await axios.post(roleurl, body, { headers: headers }); + contactQuery.set('CreatedBy', userPtr.objectId); + contactQuery.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: userRes.id, + }); + const acl = new Parse.ACL(); + acl.setReadAccess(userPtr.objectId, true); + acl.setWriteAccess(userPtr.objectId, true); + acl.setReadAccess(userRes.id, true); + acl.setWriteAccess(userRes.id, true); + + contactQuery.setACL(acl); + const contactRes = await contactQuery.save(); + if (contactRes) { + const parseRes = JSON.parse(JSON.stringify(contactRes)); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_contact', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: parseRes.objectId, + name: parseRes.Name, + email: parseRes.Email, + phone: parseRes.Phone, + createdAt: parseRes.createdAt, + updatedAt: parseRes.updatedAt, + }); + } + } else { + if (err.code === 137) { + return response.status(401).json({ error: 'Contact already exists!' }); + } + return response + .status(400) + .json({ error: 'Something went wrong, please try again later!' }); + } + } + } catch (err) { + console.log('err ', err); + if (err.code === 137) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_contact', + properties: { response_code: 401 }, + }); + } + return response.status(401).json({ error: 'Contact already exists!' }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_contact', + properties: { response_code: 400 }, + }); + } + return response + .status(400) + .json({ error: 'Something went wrong, please try again later!' }); + } + } + } + } catch (err) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_contact', + properties: { response_code: 400 }, + }); + } + return response + .status(400) + .json({ error: 'Something went wrong, please try again later!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('Err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js new file mode 100644 index 000000000..0ca92d067 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/createDocumentwithCoordinate.js @@ -0,0 +1,379 @@ +import axios from 'axios'; +import { color, customAPIurl, replaceMailVaribles } from '../../../../Utils.js'; + +// `sendDoctoWebhook` is used to send res data of document on webhook +async function sendDoctoWebhook(doc, WebhookUrl, userId) { + if (WebhookUrl) { + const params = { + event: 'created', + ...doc, + }; + await axios + .post(WebhookUrl, params, { + headers: { 'Content-Type': 'application/json' }, + }) + .then(res => { + try { + // console.log('res ', res); + const webhook = new Parse.Object('contracts_Webhook'); + webhook.set('Log', res?.status); + webhook.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: userId, + }); + webhook.save(null, { useMasterKey: true }); + } catch (err) { + console.log('err save in contracts_Webhook', err); + } + }) + .catch(err => { + console.log('Err send data to webhook', err); + try { + const webhook = new Parse.Object('contracts_Webhook'); + webhook.set('Log', err?.status); + webhook.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: userId, + }); + webhook.save(null, { useMasterKey: true }); + } catch (err) { + console.log('err save in contracts_Webhook', err); + } + }); + // console.log('res ', res.data); + } +} +const randomId = () => Math.floor(1000 + Math.random() * 9000); +export default async function createDocumentwithCoordinate(request, response) { + const name = request.body.title; + const note = request.body.note; + const description = request.body.description; + const send_email = request.body.send_email; + const signers = request.body.signers; + const folderId = request.body.folderId; + const base64File = request.body.file; + const fileData = request.files?.[0] ? request.files[0].buffer : null; + const email_subject = request.body.email_subject; + const email_body = request.body.email_body; + const sendInOrder = request.body.sendInOrder || false; + // console.log('fileData ', fileData); + const protocol = customAPIurl(); + const baseUrl = new URL(process.env.SERVER_URL); + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + if (signers && signers.length > 0) { + let fileUrl; + if (request.files?.[0]) { + const file = new Parse.File(request.files?.[0]?.originalname, { + base64: fileData?.toString('base64'), + }); + await file.save({ useMasterKey: true }); + fileUrl = file.url(); + } else { + const file = new Parse.File(`${name}.pdf`, { + base64: base64File, + }); + await file.save({ useMasterKey: true }); + fileUrl = file.url(); + } + const contractsUser = new Parse.Query('contracts_Users'); + contractsUser.equalTo('UserId', userPtr); + const extUser = await contractsUser.first({ useMasterKey: true }); + const parseExtUser = JSON.parse(JSON.stringify(extUser)); + + const extUserPtr = { + __type: 'Pointer', + className: 'contracts_Users', + objectId: extUser.id, + }; + + const object = new Parse.Object('contracts_Document'); + object.set('Name', name); + + if (note) { + object.set('Note', note); + } + if (description) { + object.set('Description', description); + } + if (sendInOrder) { + object.set('SendinOrder', sendInOrder); + } + object.set('URL', fileUrl); + object.set('CreatedBy', userPtr); + object.set('ExtUserPtr', extUserPtr); + object.set('IsSendMail', send_email); + let contact = []; + if (signers && signers.length > 0) { + let parseSigners; + if (base64File) { + parseSigners = signers; + } else { + parseSigners = JSON.parse(signers); + } + let createContactUrl = protocol + '/v1/createcontact'; + + for (const [index, element] of parseSigners.entries()) { + const body = { + name: element?.name || '', + email: element?.email || '', + phone: element?.phone || '', + }; + try { + const res = await axios.post(createContactUrl, body, { + headers: { 'Content-Type': 'application/json', 'x-api-token': reqToken }, + }); + // console.log('res ', res.data); + const contactPtr = { + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: res.data?.objectId, + }; + const newObj = { ...element, contactPtr: contactPtr, index: index }; + contact.push(newObj); + } catch (err) { + // console.log('err ', err.response); + if (err?.response?.data?.objectId) { + const contactPtr = { + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: err.response.data?.objectId, + }; + const newObj = { ...element, contactPtr: contactPtr, index: index }; + contact.push(newObj); + } + } + } + object.set( + 'Signers', + contact?.map(x => x.contactPtr) + ); + let updatePlaceholders = contact.map((signer, index) => { + const placeHolder = []; + + for (const widget of signer.widgets) { + const pageNumber = widget.page; + const page = placeHolder.find(page => page.pageNumber === pageNumber); + + const widgetData = { + xPosition: widget.x, + yPosition: widget.y, + isStamp: widget.type === 'stamp', + key: randomId(), + isDrag: false, + firstXPos: widget.x, + firstYPos: widget.y, + yBottom: 0, + scale: 1, + isMobile: false, + zIndex: 1, + type: widget.type, + widgetValue: '', + Width: widget.w, + Height: widget.h, + }; + + if (page) { + page.pos.push(widgetData); + } else { + placeHolder.push({ + pageNumber, + pos: [widgetData], + }); + } + } + + return { + signerObjId: signer?.contactPtr?.objectId, + signerPtr: signer?.contactPtr, + Role: signer.role, + Id: randomId(), + blockColor: color[signer?.index], + placeHolder, + }; + }); + object.set('Placeholders', updatePlaceholders); + } + if (folderId) { + object.set('Folder', { + __type: 'Pointer', + className: 'contracts_Document', + objectId: folderId, + }); + } + const newACL = new Parse.ACL(); + newACL.setPublicReadAccess(false); + newACL.setPublicWriteAccess(false); + newACL.setReadAccess(userPtr.objectId, true); + newACL.setWriteAccess(userPtr.objectId, true); + object.setACL(newACL); + const res = await object.save(null, { useMasterKey: true }); + const doc = { + objectId: res.id, + file: fileUrl, + name: name, + note: note || '', + description: description || '', + signers: contact?.map(x => ({ name: x.name, email: x.email, phone: x.phone })), + createdAt: res.createdAt, + }; + if (parseExtUser && parseExtUser.Webhook) { + sendDoctoWebhook(doc, parseExtUser?.Webhook, userPtr?.objectId); + } + const newDate = new Date(); + newDate.setDate(newDate.getDate() + 15); + const localExpireDate = newDate.toLocaleDateString('en-US', { + day: 'numeric', + month: 'long', + year: 'numeric', + }); + let sender = parseExtUser.Email; + let sendMail; + const serverUrl = process.env.SERVER_URL; + const newServer = serverUrl.replaceAll('/', '%2F'); + const serverParams = `${newServer}%2F&${process.env.APP_ID}&contracts`; + if (send_email === false) { + console.log("don't send mail"); + } else { + let contactMail = contact; + if (sendInOrder) { + contactMail = contact.slice(); + contactMail.splice(1); + } + for (let i = 0; i < contactMail.length; i++) { + try { + const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png'; + let url = `${process.env.SERVER_URL}/functions/sendmailv3/`; + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': process.env.APP_ID, + 'X-Parse-Master-Key': process.env.MASTER_KEY, + }; + + const objectId = contactMail[i].contactPtr.objectId; + + const hostUrl = baseUrl.origin + '/loadmf/signmicroapp'; + let signPdf = `${hostUrl}/login/${res.id}/${contactMail[i].email}/${objectId}/${serverParams}`; + const openSignUrl = 'https://www.opensignlabs.com/contact-us'; + const orgName = parseExtUser.Company ? parseExtUser.Company : ''; + const themeBGcolor = '#47a3ad'; + const email_html = + "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" + + imgPng + + " height='50' style='padding:20px; width:170px; height:40px;' /></div> <div style='padding:2px; font-family: system-ui;background-color:" + + themeBGcolor + + ";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " + + parseExtUser.Name + + ' has requested you to review and sign <strong> ' + + name + + "</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" + + sender + + "</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " + + orgName + + "</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" + + localExpireDate + + "</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" + + signPdf + + "> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " + + sender + + ' directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=' + + openSignUrl + + ' target=_blank>here</a>.</p> </div></div></body> </html>'; + let replaceVar; + const variables = { + document_title: name, + sender_name: parseExtUser.Name, + sender_mail: parseExtUser.Email, + sender_phone: parseExtUser.Phone, + receiver_name: contactMail[i].name, + receiver_email: contactMail[i].email, + receiver_phone: contactMail[i].phone, + expiry_date: localExpireDate, + company_name: orgName, + signing_url: signPdf, + }; + if (email_subject && email_body) { + replaceVar = replaceMailVaribles(email_subject, email_body, variables); + } else if (email_subject) { + replaceVar = replaceMailVaribles(email_subject, '', variables); + replaceVar = { subject: replaceVar.subject, body: email_html }; + } else if (email_body) { + replaceVar = replaceMailVaribles( + `${parseExtUser.Name} has requested you to sign ${name}`, + email_body, + variables + ); + } else { + replaceVar = { + subject: `${parseExtUser.Name} has requested you to sign ${parseExtUser.Name}`, + body: email_html, + }; + } + const subject = replaceVar.subject; + const html = replaceVar.body; + + let params = { + recipient: contactMail[i].email, + subject: subject, + from: sender, + html: html, + }; + + sendMail = await axios.post(url, params, { headers: headers }); + } catch (error) { + console.log('error', error); + } + } + } + // if (sendMail.data.result.status === 'success') { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_document', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: res.id, + signurl: contact.map(x => ({ + email: x.email, + url: `${baseUrl.origin}/loadmf/signmicroapp/login/${res.id}/${x.email}/${x.contactPtr.objectId}/${serverParams}`, + })), + message: 'Document sent successfully!', + }); + // } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_document', + properties: { response_code: 400 }, + }); + } + return response.status(400).json({ error: 'Please provide signers!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplate.js new file mode 100644 index 000000000..df8b6eacd --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplate.js @@ -0,0 +1,135 @@ +import { customAPIurl } from '../../../../Utils.js'; + +const randomId = () => Math.floor(1000 + Math.random() * 9000); +export default async function createTemplate(request, response) { + const name = request.body?.title; + const note = request.body?.note; + const description = request.body?.description; + const signers = request.body?.signers; + const folderId = request.body?.folderId; + const base64File = request.body.file; + const SendinOrder = request.body.sendInOrder || false; + const fileData = request.files?.[0] ? request.files[0].buffer : null; + const baseUrl = new URL(process.env.SERVER_URL); + + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + let fileUrl; + if (base64File) { + const file = new Parse.File(`${name}.pdf`, { + base64: base64File, + }); + await file.save({ useMasterKey: true }); + fileUrl = file.url(); + } else { + const file = new Parse.File(request.files?.[0]?.originalname, { + base64: fileData?.toString('base64'), + }); + await file.save({ useMasterKey: true }); + fileUrl = file.url(); + } + + const contractsUser = new Parse.Query('contracts_Users'); + contractsUser.equalTo('UserId', userPtr); + const extUser = await contractsUser.first({ useMasterKey: true }); + const extUserPtr = { __type: 'Pointer', className: 'contracts_Users', objectId: extUser.id }; + + const folderPtr = { __type: 'Pointer', className: 'contracts_Template', objectId: folderId }; + + const object = new Parse.Object('contracts_Template'); + object.set('Name', name); + if (note) { + object.set('Note', note); + } + if (description) { + object.set('Description', description); + } + object.set('URL', fileUrl); + object.set('CreatedBy', userPtr); + object.set('ExtUserPtr', extUserPtr); + if (SendinOrder) { + object.set('SendinOrder', SendinOrder); + } + if (signers && signers.length > 0) { + let parseSigners; + if (base64File) { + parseSigners = signers; + } else { + parseSigners = JSON.parse(signers); + } + let createContactUrl = protocol + '/v1/createcontact'; + + let contact = []; + for (const obj of parseSigners) { + const body = { + name: obj?.name || '', + email: obj?.email || '', + phone: obj?.phone || '', + }; + try { + const res = await axios.post(createContactUrl, body, { + headers: { 'Content-Type': 'application/json', 'x-api-token': reqToken }, + }); + // console.log('res ', res.data); + contact.push({ + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: res.data?.objectId, + }); + } catch (err) { + // console.log('err ', err.response); + if (err?.response?.data?.objectId) { + contact.push({ + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: err.response.data?.objectId, + }); + } + } + } + object.set('Signers', contact); + } + if (folderId) { + object.set('Folder', folderPtr); + } + const newACL = new Parse.ACL(); + newACL.setPublicReadAccess(false); + newACL.setPublicWriteAccess(false); + newACL.setReadAccess(userPtr.objectId, true); + newACL.setWriteAccess(userPtr.objectId, true); + object.setACL(newACL); + const res = await object.save(null, { useMasterKey: true }); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_draft_template', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: res.id, + url: baseUrl.origin + '/load/signmicroapp/template/' + res.id, + }); + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplatewithCoordinate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplatewithCoordinate.js new file mode 100644 index 000000000..62cab68da --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/createTemplatewithCoordinate.js @@ -0,0 +1,214 @@ +import axios from 'axios'; +import { color, customAPIurl } from '../../../../Utils.js'; + +const randomId = () => Math.floor(1000 + Math.random() * 9000); +export default async function createTemplatewithCoordinate(request, response) { + const name = request.body.title; + const note = request.body.note; + const description = request.body.description; + const signers = request.body.signers; + const folderId = request.body.folderId; + const base64File = request.body.file; + const fileData = request.files?.[0] ? request.files[0].buffer : null; + const SendinOrder = request.body.sendInOrder || false; + // console.log('fileData ', fileData); + const protocol = customAPIurl(); + + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + if (signers && signers.length > 0) { + let fileUrl; + if (request.files?.[0]) { + const file = new Parse.File(request.files?.[0]?.originalname, { + base64: fileData?.toString('base64'), + }); + await file.save({ useMasterKey: true }); + fileUrl = file.url(); + } else { + const file = new Parse.File(`${name}.pdf`, { + base64: base64File, + }); + await file.save({ useMasterKey: true }); + fileUrl = file.url(); + } + const contractsUser = new Parse.Query('contracts_Users'); + contractsUser.equalTo('UserId', userPtr); + const extUser = await contractsUser.first({ useMasterKey: true }); + const extUserPtr = { + __type: 'Pointer', + className: 'contracts_Users', + objectId: extUser.id, + }; + + const object = new Parse.Object('contracts_Template'); + object.set('Name', name); + + if (note) { + object.set('Note', note); + } + if (description) { + object.set('Description', description); + } + if (SendinOrder) { + object.set('SendinOrder', SendinOrder); + } + object.set('URL', fileUrl); + object.set('CreatedBy', userPtr); + object.set('ExtUserPtr', extUserPtr); + let contact = []; + if (signers && signers.length > 0) { + let parseSigners; + if (base64File) { + parseSigners = signers; + } else { + parseSigners = JSON.parse(signers); + } + let createContactUrl = protocol + '/v1/createcontact'; + + for (const [index, element] of parseSigners.entries()) { + if (element?.name && element.phone && element?.email) { + const body = { + name: element?.name || '', + email: element?.email || '', + phone: element?.phone || '', + }; + try { + const res = await axios.post(createContactUrl, body, { + headers: { 'Content-Type': 'application/json', 'x-api-token': reqToken }, + }); + // console.log('res ', res.data); + const contactPtr = { + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: res.data?.objectId, + }; + const newObj = { ...element, contactPtr: contactPtr, index: index }; + contact.push(newObj); + } catch (err) { + // console.log('err ', err.response); + if (err?.response?.data?.objectId) { + const contactPtr = { + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: err.response.data?.objectId, + }; + const newObj = { ...element, contactPtr: contactPtr, index: index }; + contact.push(newObj); + } + } + } else { + const newObj = { ...element, contactPtr: {}, index: index }; + contact.push(newObj); + } + } + const updatedSigners = contact?.filter(x => x.contactPtr && x.contactPtr.objectId); + if (updatedSigners && updatedSigners.length > 0) { + object.set( + 'Signers', + updatedSigners?.map(x => x.contactPtr) + ); + } + let updatePlaceholders = contact.map((signer, index) => { + const placeHolder = []; + + for (const widget of signer.widgets) { + const pageNumber = widget.page; + const page = placeHolder.find(page => page.pageNumber === pageNumber); + + const widgetData = { + xPosition: widget.x, + yPosition: widget.y, + isStamp: widget.type === 'stamp', + key: randomId(), + isDrag: false, + firstXPos: widget.x, + firstYPos: widget.y, + yBottom: 0, + scale: 1, + isMobile: false, + zIndex: 1, + type: widget.type, + widgetValue: '', + Width: widget.w, + Height: widget.h, + }; + + if (page) { + page.pos.push(widgetData); + } else { + placeHolder.push({ + pageNumber, + pos: [widgetData], + }); + } + } + + return { + signerObjId: signer?.contactPtr?.objectId, + signerPtr: signer?.contactPtr, + Role: signer.role, + Id: randomId(), + blockColor: color[signer?.index], + placeHolder, + }; + }); + object.set('Placeholders', updatePlaceholders); + } + if (folderId) { + object.set('Folder', { + __type: 'Pointer', + className: 'contracts_Template', + objectId: folderId, + }); + } + const newACL = new Parse.ACL(); + newACL.setPublicReadAccess(false); + newACL.setPublicWriteAccess(false); + newACL.setReadAccess(userPtr.objectId, true); + newACL.setWriteAccess(userPtr.objectId, true); + object.setACL(newACL); + const res = await object.save(null, { useMasterKey: true }); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_template', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: res.id, + message: 'Template created successfully!', + }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_create_template', + properties: { response_code: 400 }, + }); + } + return response.status(400).json({ error: 'Please provide signers!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteContact.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteContact.js new file mode 100644 index 000000000..4926eceba --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteContact.js @@ -0,0 +1,65 @@ +export default async function deleteContact(request, response) { + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + + const Contactbook = new Parse.Query('contracts_Contactbook'); + Contactbook.equalTo('objectId', request.params.contact_id); + Contactbook.equalTo('CreatedBy', userPtr); + const res = await Contactbook.first({ useMasterKey: true }); + if (res) { + const isDeleted = res.get('IsDeleted'); + if (isDeleted && isDeleted) { + return response.status(404).json({ error: 'Contact not found!' }); + } else { + const Contactbook = Parse.Object.extend('contracts_Contactbook'); + const deleteQuery = new Contactbook(); + deleteQuery.id = request.params.contact_id; + deleteQuery.set('IsDeleted', true); + const deleteRes = await deleteQuery.save(null, { useMasterKey: true }); + if (deleteRes) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_contact', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: request.params.contact_id, + deletedAt: deleteRes.get('updatedAt'), + }); + } + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_contact', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Contact not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteDocument.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteDocument.js new file mode 100644 index 000000000..b166ec2ef --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteDocument.js @@ -0,0 +1,65 @@ +export default async function deleteDocument(request, response) { + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + + const Document = new Parse.Query('contracts_Document'); + Document.equalTo('objectId', request.params.document_id); + Document.equalTo('CreatedBy', userPtr); + const res = await Document.first({ useMasterKey: true }); + if (res) { + const isArchive = res.get('IsArchive'); + if (isArchive && isArchive) { + return response.status(404).json({ error: 'Document not found!' }); + } else { + const Document = Parse.Object.extend('contracts_Document'); + const deleteQuery = new Document(); + deleteQuery.id = request.params.document_id; + deleteQuery.set('IsArchive', true); + const deleteRes = await deleteQuery.save(null, { useMasterKey: true }); + if (deleteRes) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_document', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: request.params.document_id, + deletedAt: deleteRes.get('updatedAt'), + }); + } + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_document', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Document not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteTemplate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteTemplate.js new file mode 100644 index 000000000..4011795e4 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteTemplate.js @@ -0,0 +1,71 @@ +export default async function deletedTemplate(request, response) { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + const template = new Parse.Query('contracts_Template'); + template.equalTo('objectId', request.params.template_id); + template.equalTo('CreatedBy', userPtr); + const res = await template.first({ useMasterKey: true }); + if (res) { + const isArchive = res.get('IsArchive'); + if (isArchive && isArchive) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_template', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Template not found!' }); + } else { + const template = Parse.Object.extend('contracts_Template'); + const deleteQuery = new template(); + deleteQuery.id = request.params.template_id; + deleteQuery.set('IsArchive', true); + const deleteRes = await deleteQuery.save(null, { useMasterKey: true }); + if (deleteRes) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_template', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: request.params.template_id, + deletedAt: deleteRes.get('updatedAt'), + }); + } + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_template', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Template not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteWebhook.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteWebhook.js new file mode 100644 index 000000000..ac82b521f --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/deleteWebhook.js @@ -0,0 +1,57 @@ +export default async function deleteWebhook(request, response) { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + + const query = new Parse.Query('contracts_Users'); + query.equalTo('UserId', userPtr); + const user = await query.first({ useMasterKey: true }); + if (user) { + const updateQuery = new Parse.Object('contracts_Users'); + updateQuery.id = user.id; + updateQuery.unset('Webhook'); + const res = await updateQuery.save(null, { useMasterKey: true }); + if (res) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_webhook', + properties: { response_code: 200 }, + }); + } + return response.json({ + result: 'Webhook deleted successfully!', + }); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_delete_webhook', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'User not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/draftDocument.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/draftDocument.js new file mode 100644 index 000000000..a2ba41d3c --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/draftDocument.js @@ -0,0 +1,157 @@ +import axios from 'axios'; +import { customAPIurl } from '../../../../Utils.js'; + +// const randomId = () => Math.floor(1000 + Math.random() * 9000); +export default async function draftDocument(request, response) { + const name = request.body.title; + const note = request.body.note; + const description = request.body.description; + const signers = request.body.signers; + const folderId = request.body.folderId; + const base64File = request.body.file; + const send_email = request.body.send_email || true; + const fileData = request.files?.[0] ? request.files[0].buffer : null; + const SendinOrder = request.body.sendInOrder || false; + // console.log('fileData ', fileData); + const protocol = customAPIurl(); + + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + // Valid Token then proceed request + if (signers && signers.length > 0) { + let fileUrl; + if (request.files?.[0]) { + const file = new Parse.File(request.files?.[0]?.originalname, { + base64: fileData?.toString('base64'), + }); + await file.save({ useMasterKey: true }); + fileUrl = file.url(); + } else { + const file = new Parse.File(`${name}.pdf`, { + base64: base64File, + }); + await file.save({ useMasterKey: true }); + fileUrl = file.url(); + } + const contractsUser = new Parse.Query('contracts_Users'); + contractsUser.equalTo('UserId', userPtr); + const extUser = await contractsUser.first({ useMasterKey: true }); + const extUserPtr = { + __type: 'Pointer', + className: 'contracts_Users', + objectId: extUser.id, + }; + + const folderPtr = { + __type: 'Pointer', + className: 'contracts_Document', + objectId: folderId, + }; + + const object = new Parse.Object('contracts_Document'); + object.set('Name', name); + if (note) { + object.set('Note', note); + } + if (description) { + object.set('Description', description); + } + if (SendinOrder) { + object.set('SendinOrder', SendinOrder); + } + object.set('URL', fileUrl); + object.set('CreatedBy', userPtr); + object.set('ExtUserPtr', extUserPtr); + object.set('IsSendMail', send_email); + if (signers && signers.length > 0) { + let parseSigners; + if (base64File) { + parseSigners = signers; + } else { + parseSigners = JSON.parse(signers); + } + let createContactUrl = protocol + '/v1/createcontact'; + + let contact = []; + for (const obj of parseSigners) { + const body = { + name: obj?.name || '', + email: obj?.email || '', + phone: obj?.phone || '', + }; + try { + const res = await axios.post(createContactUrl, body, { + headers: { 'Content-Type': 'application/json', 'x-api-token': reqToken }, + }); + // console.log('res ', res.data); + contact.push({ + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: res.data?.objectId, + }); + } catch (err) { + // console.log('err ', err.response); + if (err?.response?.data?.objectId) { + contact.push({ + __type: 'Pointer', + className: 'contracts_Contactbook', + objectId: err.response.data?.objectId, + }); + } + } + } + object.set('Signers', contact); + } + if (folderId) { + object.set('Folder', folderPtr); + } + const newACL = new Parse.ACL(); + newACL.setPublicReadAccess(false); + newACL.setPublicWriteAccess(false); + newACL.setReadAccess(userPtr.objectId, true); + newACL.setWriteAccess(userPtr.objectId, true); + object.setACL(newACL); + const res = await object.save(null, { useMasterKey: true }); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_draft_document', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: res.id, + url: protocol + '/load/signmicroapp/placeholdersign/' + res.id, + }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_draft_document', + properties: { response_code: 400 }, + }); + } + return response.status(400).json({ error: 'Please provide signers!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/getContact.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/getContact.js new file mode 100644 index 000000000..e3d288586 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/getContact.js @@ -0,0 +1,61 @@ +export default async function getContact(request, response) { + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + + const Contactbook = new Parse.Query('contracts_Contactbook'); + Contactbook.equalTo('objectId', request.params.contact_id); + Contactbook.equalTo('CreatedBy', userPtr); + Contactbook.notEqualTo('IsDeleted', true); + Contactbook.select('Name,Email,Phone'); + + const res = await Contactbook.first({ useMasterKey: true }); + if (res) { + const parseRes = JSON.parse(JSON.stringify(res)); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_contact', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: parseRes.objectId, + name: parseRes.Name, + email: parseRes.Email, + phone: parseRes.Phone, + createdAt: parseRes.createdAt, + updatedAt: parseRes.updatedAt, + }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_contact', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Contact not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/getContactList.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/getContactList.js new file mode 100644 index 000000000..f20682c63 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/getContactList.js @@ -0,0 +1,63 @@ +export default async function getContactList(request, response) { + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + const limit = request?.query?.limit ? parseInt(request.query.limit) : 100; + const skip = request?.query?.skip ? parseInt(request.query.skip) : 0; + const Contactbook = new Parse.Query('contracts_Contactbook'); + Contactbook.equalTo('CreatedBy', userPtr); + Contactbook.notEqualTo('IsDeleted', true); + Contactbook.limit(limit); + Contactbook.skip(skip); + Contactbook.descending('createdAt'); + const res = await Contactbook.find({ useMasterKey: true }); + if (res && res.length > 0) { + const parseRes = JSON.parse(JSON.stringify(res)); + const contactlist = parseRes.map(x => ({ + objectId: x.objectId, + name: x.Name, + email: x.Email, + phone: x.Phone, + createdAt: x.createdAt, + updatedAt: x.updatedAt, + })); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_contact_list', + properties: { response_code: 200 }, + }); + } + return response.json({ result: contactlist }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_contact_list', + properties: { response_code: 200 }, + }); + } + return response.json({ result: [] }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/getDocument.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/getDocument.js new file mode 100644 index 000000000..cc1e1e03c --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/getDocument.js @@ -0,0 +1,84 @@ +export default async function getDocument(request, response) { + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + const Document = new Parse.Query('contracts_Document'); + Document.equalTo('objectId', request.params.document_id); + Document.equalTo('CreatedBy', userPtr); + Document.notEqualTo('IsArchive', true); + Document.include('Signers'); + Document.include('Folder'); + Document.include('ExtUserPtr'); + Document.include('Placeholders.signerPtr'); + const res = await Document.first({ useMasterKey: true }); + if (res) { + const document = JSON.parse(JSON.stringify(res)); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_document', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: document.objectId, + title: document.Name, + note: document.Note || '', + folder: { objectId: document?.Folder?.objectId, name: document?.Folder?.Name } || '', + file: document?.SignedUrl || document.URL, + owner: document?.ExtUserPtr?.Name, + signers: + document?.Placeholders?.map(y => ({ + role: y.Role, + name: y?.signerPtr?.Name || '', + email: y?.signerPtr?.Email || '', + phone: y?.signerPtr?.Phone || '', + widgets: y.placeHolder?.flatMap(x => + x?.pos.map(w => ({ + type: w?.type ? w.type : w.isStamp ? 'stamp' : 'signature', + x: w.xPosition, + y: w.yPosition, + w: w?.Width || 150, + h: w?.Height || 60, + page: x?.pageNumber, + })) + ), + })) || + document?.Signers?.map(y => ({ name: y?.Name, email: y?.Email, phone: y?.Phone })) || + [], + sendInOrder: document?.SendinOrder || false, + createdAt: document.createdAt, + updatedAt: document.updatedAt, + }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_document', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Document not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/getDocumentList.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/getDocumentList.js new file mode 100644 index 000000000..5f5b49e71 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/getDocumentList.js @@ -0,0 +1,138 @@ +import axios from 'axios'; +import reportJson from '../../../parsefunction/reportsJson.js'; +import dotenv from 'dotenv'; +dotenv.config(); + +export default async function getDocumentList(request, response) { + const reqToken = request.headers['x-api-token']; + const appId = process.env.APP_ID; + const serverUrl = process.env.SERVER_URL; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + const docType = request.params.doctype; + const limit = request?.query?.limit ? request.query.limit : 100; + const skip = request?.query?.skip ? request.query.skip : 0; + let reportId; + switch (docType) { + case 'draft': + reportId = 'ByHuevtCFY'; + break; + case 'signaturerequest': + reportId = '4Hhwbp482K'; + break; + case 'inprogress': + reportId = '1MwEuxLEkF'; + break; + case 'completed': + reportId = 'kQUoW4hUXz'; + break; + case 'expired': + reportId = 'zNqBHXHsYH'; + break; + case 'declined': + reportId = 'UPr2Fm5WY3'; + break; + default: + reportId = ''; + } + const json = reportId && reportJson(reportId, userPtr.objectId); + const clsName = 'contracts_Document'; + if (reportId && json) { + const { params, keys } = json; + const orderBy = '-updatedAt'; + const strParams = JSON.stringify(params); + const strKeys = keys.join(); + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': appId, + 'X-Parse-Master-Key': process.env.MASTER_KEY, + }; + const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys},Placeholders&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr,Placeholders.signerPtr`; + try { + const res = await axios.get(url, { headers: headers }); + if (res.data && res.data.results.length > 0) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: `api_get_document_list_${docType}`, + properties: { response_code: 200, doc_type: docType }, + }); + } + const updateRes = res.data.results.map(x => ({ + objectId: x.objectId, + title: x.Name, + note: x.Note || '', + folder: { objectId: x?.Folder?.objectId, name: x?.Folder?.Name } || '', + file: x?.SignedUrl || x.URL, + owner: x?.ExtUserPtr?.Name, + signers: + x?.Placeholders?.map(y => ({ + role: y.Role, + name: y?.signerPtr?.Name || '', + email: y?.signerPtr?.Email || '', + phone: y?.signerPtr?.Phone || '', + widgets: y.placeHolder?.flatMap(x => + x?.pos.map(w => ({ + type: w?.type ? w.type : w.isStamp ? 'stamp' : 'signature', + x: w.xPosition, + y: w.yPosition, + w: w?.Width || 150, + h: w?.Height || 60, + page: x?.pageNumber, + })) + ), + })) || + x?.Signers?.map(y => ({ name: y?.Name, email: y?.Email, phone: y?.Phone })) || + [], + sendInOrder: x?.SendinOrder || false, + createdAt: x.createdAt, + updatedAt: x.updatedAt, + })); + return response.json({ result: updateRes }); + } else { + return response.json({ result: [] }); + } + } catch (err) { + console.log('err in getdocument list', err); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: `api_get_document_list_${docType}`, + properties: { response_code: 400, doc_type: docType }, + }); + } + return response + .status(400) + .json({ error: 'Something went wrong, please try again later!' }); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: `api_get_document_list_${docType}`, + properties: { response_code: 404, doc_type: docType }, + }); + } + return response.status(404).json({ error: 'Report not available!' }); + } + } + return response.status(405).json({ error: 'Invalid API Token!' }); + } catch (err) { + console.log('Err', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/getTemplate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/getTemplate.js new file mode 100644 index 000000000..7b3daa28d --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/getTemplate.js @@ -0,0 +1,84 @@ +export default async function getTemplate(request, response) { + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + + const Template = new Parse.Query('contracts_Template'); + Template.equalTo('objectId', request.params.template_id); + Template.equalTo('CreatedBy', userPtr); + Template.notEqualTo('IsArchive', true); + Template.include('Signers'); + Template.include('Folder'); + Template.include('ExtUserPtr'); + Template.include('Placeholders.signerPtr'); + const res = await Template.first({ useMasterKey: true }); + if (res) { + const template = JSON.parse(JSON.stringify(res)); + + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_template', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: template.objectId, + title: template.Name, + note: template.Note || '', + folder: { objectId: template?.Folder?.objectId, name: template?.Folder?.Name } || '', + file: template?.SignedUrl || template?.URL, + owner: template?.ExtUserPtr?.Name, + signers: + template?.Placeholders?.map(y => ({ + role: y.Role, + name: y?.signerPtr?.Name || '', + email: y?.signerPtr?.Email || '', + phone: y?.signerPtr?.Phone || '', + widgets: y.placeHolder?.flatMap(x => + x?.pos.map(w => ({ + type: w?.type ? w.type : w.isStamp ? 'stamp' : 'signature', + x: w.xPosition, + y: w.yPosition, + w: w?.Width || 150, + h: w?.Height || 60, + page: x?.pageNumber, + })) + ), + })) || [], + sendInOrder: template?.SendinOrder || false, + createdAt: template.createdAt, + updatedAt: template.updatedAt, + }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_template', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Template not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/getTemplateList.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/getTemplateList.js new file mode 100644 index 000000000..fb1e1ae74 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/getTemplateList.js @@ -0,0 +1,111 @@ +import axios from 'axios'; +import dotenv from 'dotenv'; +dotenv.config(); +export default async function getTemplatetList(request, response) { + const reqToken = request.headers['x-api-token']; + const appId = process.env.APP_ID; + const serverUrl = process.env.SERVER_URL; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + + const limit = request?.query?.limit ? request.query.limit : 100; + const skip = request?.query?.skip ? request.query.skip : 0; + + const clsName = 'contracts_Template'; + const params = { + Type: { $ne: 'Folder' }, + CreatedBy: userPtr, + IsArchive: { $ne: true }, + }; + const keys = [ + 'Name', + 'Note', + 'Description', + 'Folder.Name', + 'URL', + 'SignedUrl', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', + 'Placeholders', + ]; + const orderBy = '-updatedAt'; + const strParams = JSON.stringify(params); + const strKeys = keys.join(); + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': appId, + 'X-Parse-Master-Key': process.env.MASTER_KEY, + }; + const url = `${serverUrl}/classes/${clsName}?where=${strParams}&keys=${strKeys}&order=${orderBy}&skip=${skip}&limit=${limit}&include=AuditTrail.UserPtr,Placeholders.signerPtr`; + const res = await axios.get(url, { headers: headers }); + if (res.data && res.data.results.length > 0) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_template_list', + properties: { response_code: 200 }, + }); + } + const updateRes = res.data.results.map(template => ({ + objectId: template.objectId, + title: template.Name, + note: template.Note || '', + folder: { objectId: template?.Folder?.objectId, name: template?.Folder?.Name } || '', + file: template?.SignedUrl || template.URL, + owner: template?.ExtUserPtr?.Name, + signers: + template?.Placeholders?.map(y => ({ + role: y.Role, + name: y?.signerPtr?.Name || '', + email: y?.signerPtr?.Email || '', + phone: y?.signerPtr?.Phone || '', + widgets: y.placeHolder?.flatMap(x => + x?.pos.map(w => ({ + type: w?.type ? w.type : w.isStamp ? 'stamp' : 'signature', + x: w.xPosition, + y: w.yPosition, + w: w?.Width || 150, + h: w?.Height || 60, + page: x?.pageNumber, + })) + ), + })) || [], + sendInOrder: template?.SendinOrder || false, + createdAt: template.createdAt, + updatedAt: template.updatedAt, + })); + + return response.json({ result: updateRes }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_template_list', + properties: { response_code: 200 }, + }); + } + return response.json({ result: [] }); + } + } + return response.status(405).json({ error: 'Invalid API Token!' }); + } catch (err) { + console.log('err', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/getUser.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/getUser.js new file mode 100644 index 000000000..45776036e --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/getUser.js @@ -0,0 +1,62 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +export default async function getUser(request, response) { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + + const query = new Parse.Query('contracts_Users'); + query.equalTo('UserId', userPtr); + query.exclude('IsContactEntry,TourStatus,UserRole,TenantId,UserId,CreatedBy,Plan'); + const user = await query.first({ useMasterKey: true }); + if (user) { + const parseRes = JSON.parse(JSON.stringify(user)); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_your_account_details', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: parseRes.objectId, + name: parseRes.Name, + email: parseRes.Email, + phone: parseRes.Phone, + jobTitle: parseRes.JobTitle, + company: parseRes.Company, + createdAt: parseRes.createdAt, + updatedAt: parseRes.updatedAt, + }); + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_your_account_details', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'User not found!' }); + } + } + return response.status(405).json({ error: 'Invalid API Token!' }); + } catch (err) { + console.log('Err', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/getWebhook.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/getWebhook.js new file mode 100644 index 000000000..1dc692942 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/getWebhook.js @@ -0,0 +1,55 @@ +export default async function getWebhook(request, response) { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + const query = new Parse.Query('contracts_Users'); + query.equalTo('UserId', userPtr); + const user = await query.first({ useMasterKey: true }); + if (user) { + const extUser = JSON.parse(JSON.stringify(user)); + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_webhook', + properties: { response_code: 200 }, + }); + } + if (extUser && extUser.Webhook) { + return response.json({ + webhook: extUser.Webhook, + }); + } else { + return response.json({}); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_get_webhook', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'User not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('Err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/saveWebhook.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/saveWebhook.js new file mode 100644 index 000000000..9c6b4b9ba --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/saveWebhook.js @@ -0,0 +1,85 @@ +export default async function saveWebhook(request, response) { + const Url = request.body.url; + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + try { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + const query = new Parse.Query('contracts_Users'); + query.equalTo('UserId', userPtr); + const user = await query.first({ useMasterKey: true }); + if (user) { + const extUser = JSON.parse(JSON.stringify(user)); + const isUrlExist = extUser?.Webhook && extUser?.Webhook === Url; + + if (!isUrlExist) { + try { + const updateQuery = new Parse.Object('contracts_Users'); + updateQuery.id = user.id; + updateQuery.set('Webhook', Url); + const res = await updateQuery.save(null, { useMasterKey: true }); + if (res) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_save_webhook', + properties: { response_code: 200 }, + }); + } + return response.json({ + result: 'Webhook updated successfully!', + }); + } + } catch (err) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_save_webhook', + properties: { response_code: 400 }, + }); + } + console.log('Err ', err); + return response + .status(400) + .json({ error: 'Something went wrong, please try again later!' }); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_save_webhook', + properties: { response_code: 401 }, + }); + } + return response.status(401).json({ error: 'Webhook url already exists!' }); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_save_webhook', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'User not found!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('Err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/updateDocument.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/updateDocument.js new file mode 100644 index 000000000..4e5246f0a --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/updateDocument.js @@ -0,0 +1,93 @@ +export default async function updateDocument(request, response) { + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const allowedKeys = ['name', 'note', 'description', 'folderId']; + const objectKeys = Object.keys(request.body); + const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0; + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + if (isValid) { + const document = new Parse.Query('contracts_Document'); + document.equalTo('objectId', request.params.document_id); + document.equalTo('CreatedBy', userPtr); + const res = await document.first({ useMasterKey: true }); + if (res) { + const isArchive = res.get('IsArchive'); + if (isArchive && isArchive) { + return response.status(404).json({ message: 'Document not found!' }); + } else { + const document = Parse.Object.extend('contracts_Document'); + const updateQuery = new document(); + updateQuery.id = request.params.document_id; + if (request?.body?.name) { + updateQuery.set('Name', request?.body?.name); + } + if (request?.body?.note) { + updateQuery.set('Note', request?.body?.note); + } + if (request?.body?.description) { + updateQuery.set('Description', request?.body?.description); + } + if (request?.body?.folderId) { + updateQuery.set('Folder', { + __type: 'Pointer', + className: 'contracts_Document', + objectId: request?.body?.folderId, + }); + } + const updatedRes = await updateQuery.save(null, { useMasterKey: true }); + if (updatedRes) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_update_document', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: updatedRes.id, + updatedAt: updatedRes.get('updatedAt'), + }); + } + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_update_document', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Document not found!' }); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_update_document', + properties: { response_code: 400 }, + }); + } + return response.status(400).json({ error: 'Please provide valid field names!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/customRoute/v1/routes/updateTemplate.js b/apps/OpenSignServer/cloud/customRoute/v1/routes/updateTemplate.js new file mode 100644 index 000000000..466721610 --- /dev/null +++ b/apps/OpenSignServer/cloud/customRoute/v1/routes/updateTemplate.js @@ -0,0 +1,93 @@ +export default async function updateTemplate(request, response) { + try { + const reqToken = request.headers['x-api-token']; + if (!reqToken) { + return response.status(400).json({ error: 'Please Provide API Token' }); + } + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('token', reqToken); + tokenQuery.include('userId'); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // Valid Token then proceed request + const allowedKeys = ['name', 'note', 'description', 'folderId']; + const objectKeys = Object.keys(request.body); + const isValid = objectKeys.every(key => allowedKeys.includes(key)) && objectKeys.length > 0; + const parseUser = JSON.parse(JSON.stringify(token)); + const userPtr = { + __type: 'Pointer', + className: '_User', + objectId: parseUser.userId.objectId, + }; + if (isValid) { + const template = new Parse.Query('contracts_Template'); + template.equalTo('objectId', request.params.template_id); + template.equalTo('CreatedBy', userPtr); + const res = await template.first({ useMasterKey: true }); + if (res) { + const isArchive = res.get('IsArchive'); + if (isArchive && isArchive) { + return response.status(404).json({ message: 'Template not found!' }); + } else { + const template = Parse.Object.extend('contracts_Template'); + const updateQuery = new template(); + updateQuery.id = request.params.template_id; + if (request?.body?.name) { + updateQuery.set('Name', request?.body?.name); + } + if (request?.body?.note) { + updateQuery.set('Note', request?.body?.note); + } + if (request?.body?.description) { + updateQuery.set('Description', request?.body?.description); + } + if (request?.body?.folderId) { + updateQuery.set('Folder', { + __type: 'Pointer', + className: 'contracts_Template', + objectId: request?.body?.folderId, + }); + } + const updatedRes = await updateQuery.save(null, { useMasterKey: true }); + if (updatedRes) { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_update_template', + properties: { response_code: 200 }, + }); + } + return response.json({ + objectId: updatedRes.id, + updatedAt: updatedRes.get('updatedAt'), + }); + } + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_update_template', + properties: { response_code: 404 }, + }); + } + return response.status(404).json({ error: 'Template not found!' }); + } + } else { + if (request.posthog) { + request.posthog?.capture({ + distinctId: parseUser.userId.email, + event: 'api_update_template', + properties: { response_code: 400 }, + }); + } + return response.status(400).json({ error: 'Please provide valid field names!' }); + } + } else { + return response.status(405).json({ error: 'Invalid API Token!' }); + } + } catch (err) { + console.log('err ', err); + return response.status(400).json({ error: 'Something went wrong, please try again later!' }); + } +} diff --git a/apps/OpenSignServer/cloud/main.js b/apps/OpenSignServer/cloud/main.js index 7532bc00d..d0838e72f 100644 --- a/apps/OpenSignServer/cloud/main.js +++ b/apps/OpenSignServer/cloud/main.js @@ -17,8 +17,12 @@ import getUserDetails from './parsefunction/getUserDetails.js'; import getDocument from './parsefunction/getDocument.js'; import getDrive from './parsefunction/getDrive.js'; import getReport from './parsefunction/getReport.js'; +import generateApiToken from './parsefunction/generateApiToken.js'; +import getapitoken from './parsefunction/getapitoken.js'; import TemplateAfterSave from './parsefunction/TemplateAfterSave.js'; import GetTemplate from './parsefunction/GetTemplate.js'; +import savewebhook from './parsefunction/saveWebhook.js'; +import callWebhook from './parsefunction/callWebhook.js'; Parse.Cloud.define('AddUserToRole', addUserToGroups); Parse.Cloud.define('UserGroups', getUserGroups); @@ -34,10 +38,14 @@ Parse.Cloud.define('AuthLoginAsMail', AuthLoginAsMail); Parse.Cloud.define('getUserId', getUserId); Parse.Cloud.define('getUserDetails', getUserDetails); Parse.Cloud.define('getDocument', getDocument); -Parse.Cloud.define('getDrive', getDrive) -Parse.Cloud.define('getReport', getReport) -Parse.Cloud.define("getTemplate", GetTemplate) +Parse.Cloud.define('getDrive', getDrive); +Parse.Cloud.define('getReport', getReport); +Parse.Cloud.define('generateapitoken', generateApiToken); +Parse.Cloud.define('getapitoken', getapitoken); +Parse.Cloud.define('getTemplate', GetTemplate); +Parse.Cloud.define('savewebhook', savewebhook); +Parse.Cloud.define('callwebhook', callWebhook); Parse.Cloud.afterSave('contracts_Document', DocumentAftersave); Parse.Cloud.afterSave('contracts_Contactbook', ContactbookAftersave); Parse.Cloud.afterSave('contracts_Users', ContractUsersAftersave); -Parse.Cloud.afterSave("contracts_Template", TemplateAfterSave) \ No newline at end of file +Parse.Cloud.afterSave('contracts_Template', TemplateAfterSave); diff --git a/apps/OpenSignServer/cloud/parsefunction/ContactBookAftersave.js b/apps/OpenSignServer/cloud/parsefunction/ContactBookAftersave.js index 644a2a763..fa476e60f 100644 --- a/apps/OpenSignServer/cloud/parsefunction/ContactBookAftersave.js +++ b/apps/OpenSignServer/cloud/parsefunction/ContactBookAftersave.js @@ -3,13 +3,13 @@ async function ContactbookAftersave(request) { you can check as follows */ if (!request.original) { const user = request.user; - const object = request.object; - + // Retrieve the current ACL const acl = new Parse.ACL(); - + // Ensure the current user has read access - if (acl) { + if (acl && request?.user) { + const object = request.object; acl.setReadAccess(user, true); acl.setWriteAccess(user, true); acl.setReadAccess(object.get('UserId'), true); diff --git a/apps/OpenSignServer/cloud/parsefunction/DocumentAftersave.js b/apps/OpenSignServer/cloud/parsefunction/DocumentAftersave.js index 3fd3ad125..dc26a3e09 100644 --- a/apps/OpenSignServer/cloud/parsefunction/DocumentAftersave.js +++ b/apps/OpenSignServer/cloud/parsefunction/DocumentAftersave.js @@ -4,20 +4,11 @@ async function DocumentAftersave(request) { console.log('new entry is insert in contracts_Document'); const createdAt = request.object.get('createdAt'); const Folder = request.object.get('Type'); - // console.log("createdAt") - // console.log(createdAt) - // console.log("Folder") - // console.log(Folder) - // console.log("before If condition") if (createdAt && Folder === undefined) { // console.log("IN If condition") const TimeToCompleteDays = request.object.get('TimeToCompleteDays'); const ExpiryDate = new Date(createdAt); - // console.log("ExpiryDate") - // console.log(ExpiryDate) ExpiryDate.setDate(ExpiryDate.getDate() + TimeToCompleteDays); - // console.log("ExpiryDate date after update") - // console.log(ExpiryDate) const documentQuery = new Parse.Query('contracts_Document'); const updateQuery = await documentQuery.get(request.object.id, { useMasterKey: true }); updateQuery.set('ExpiryDate', ExpiryDate); @@ -37,21 +28,23 @@ async function DocumentAftersave(request) { } const signers = request.object.get('Signers'); - // console.log("Signers") - // console.log(signers.length) // update acl of New Document If There are signers present in array if (signers && signers.length > 0) { await updateAclDoc(request.object.id); } else { - await updateSelfDoc(request.object.id); + if (request?.object?.id && request.user) { + await updateSelfDoc(request.object.id); + } } } else { - if (request.user) { + if (request?.user) { const signers = request.object.get('Signers'); if (signers && signers.length > 0) { await updateAclDoc(request.object.id); } else { - await updateSelfDoc(request.object.id); + if (request?.object?.id) { + await updateSelfDoc(request.object.id); + } } } } @@ -65,6 +58,7 @@ async function DocumentAftersave(request) { // console.log(objId) const Query = new Parse.Query('contracts_Document'); Query.include('Signers'); + Query.include('CreatedBy'); const updateACL = await Query.get(objId, { useMasterKey: true }); const res = JSON.parse(JSON.stringify(updateACL)); // console.log("res"); @@ -87,9 +81,10 @@ async function DocumentAftersave(request) { const newACL = new Parse.ACL(); newACL.setPublicReadAccess(false); newACL.setPublicWriteAccess(false); - newACL.setReadAccess(request.user, true); - newACL.setWriteAccess(request.user, true); - + if (res?.CreatedBy) { + newACL.setReadAccess(res?.CreatedBy?.objectId, true); + newACL.setWriteAccess(res?.CreatedBy?.objectId, true); + } UsersPtr.forEach(x => { newACL.setReadAccess(x.objectId, true); newACL.setWriteAccess(x.objectId, true); @@ -100,9 +95,9 @@ async function DocumentAftersave(request) { } async function updateSelfDoc(objId) { - // console.log("In side updateSelfDoc func") // console.log(objId) const Query = new Parse.Query('contracts_Document'); + Query.include('CreatedBy'); const updateACL = await Query.get(objId, { useMasterKey: true }); const res = JSON.parse(JSON.stringify(updateACL)); // console.log("res"); @@ -110,8 +105,10 @@ async function DocumentAftersave(request) { const newACL = new Parse.ACL(); newACL.setPublicReadAccess(false); newACL.setPublicWriteAccess(false); - newACL.setReadAccess(request.user, true); - newACL.setWriteAccess(request.user, true); + if (res?.CreatedBy) { + newACL.setReadAccess(res?.CreatedBy?.objectId, true); + newACL.setWriteAccess(res?.CreatedBy?.objectId, true); + } updateACL.setACL(newACL); updateACL.save(null, { useMasterKey: true }); } diff --git a/apps/OpenSignServer/cloud/parsefunction/TemplateAfterSave.js b/apps/OpenSignServer/cloud/parsefunction/TemplateAfterSave.js index 7d22ccb86..a1d8e7417 100644 --- a/apps/OpenSignServer/cloud/parsefunction/TemplateAfterSave.js +++ b/apps/OpenSignServer/cloud/parsefunction/TemplateAfterSave.js @@ -8,15 +8,19 @@ export default async function TemplateAfterSave(request) { if (signers && signers.length > 0) { await updateAclDoc(request.object.id); } else { - await updateSelfDoc(request.object.id); + if (request?.object?.id && request?.user) { + await updateSelfDoc(request.object.id); + } } } else { - if (request.user) { + if (request?.user) { const signers = request.object.get('Signers'); if (signers && signers.length > 0) { await updateAclDoc(request.object.id); } else { - await updateSelfDoc(request.object.id); + if (request?.object?.id) { + await updateSelfDoc(request.object.id); + } } } } @@ -30,6 +34,7 @@ export default async function TemplateAfterSave(request) { // console.log(objId) const Query = new Parse.Query('contracts_Template'); Query.include('Signers'); + Query.include('CreatedBy'); const updateACL = await Query.get(objId, { useMasterKey: true }); const res = JSON.parse(JSON.stringify(updateACL)); // console.log("res"); @@ -52,8 +57,10 @@ export default async function TemplateAfterSave(request) { const newACL = new Parse.ACL(); newACL.setPublicReadAccess(false); newACL.setPublicWriteAccess(false); - newACL.setReadAccess(request.user, true); - newACL.setWriteAccess(request.user, true); + if (res?.CreatedBy) { + newACL.setReadAccess(res?.CreatedBy?.objectId, true); + newACL.setWriteAccess(res?.CreatedBy?.objectId, true); + } UsersPtr.forEach(x => { newACL.setReadAccess(x.objectId, true); @@ -66,17 +73,20 @@ export default async function TemplateAfterSave(request) { async function updateSelfDoc(objId) { // console.log("Inside updateSelfDoc func") - + const Query = new Parse.Query('contracts_Template'); + Query.include('CreatedBy'); const updateACL = await Query.get(objId, { useMasterKey: true }); - // const res = JSON.parse(JSON.stringify(updateACL)); + const res = JSON.parse(JSON.stringify(updateACL)); // console.log("res"); // console.log(JSON.stringify(res)); const newACL = new Parse.ACL(); newACL.setPublicReadAccess(false); newACL.setPublicWriteAccess(false); - newACL.setReadAccess(request.user, true); - newACL.setWriteAccess(request.user, true); + if (res?.CreatedBy) { + newACL.setReadAccess(res?.CreatedBy?.objectId, true); + newACL.setWriteAccess(res?.CreatedBy?.objectId, true); + } updateACL.setACL(newACL); updateACL.save(null, { useMasterKey: true }); } diff --git a/apps/OpenSignServer/cloud/parsefunction/callWebhook.js b/apps/OpenSignServer/cloud/parsefunction/callWebhook.js new file mode 100644 index 000000000..7e2fa4056 --- /dev/null +++ b/apps/OpenSignServer/cloud/parsefunction/callWebhook.js @@ -0,0 +1,66 @@ +import axios from 'axios'; +export default async function callWebhook(request) { + const event = request.params.event; + const body = request.params.body; + const serverUrl = process.env.SERVER_URL; + const appId = process.env.APP_ID; + const userRes = await axios.get(serverUrl + '/users/me', { + headers: { + 'X-Parse-Application-Id': appId, + 'X-Parse-Session-Token': request.headers['sessiontoken'], + }, + }); + + const userId = userRes.data && userRes.data.objectId; + if (userId) { + const extendcls = new Parse.Query('contracts_Users'); + extendcls.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: userId }); + const res = await extendcls.first({ useMasterKey: true }); + if (res) { + const extUser = JSON.parse(JSON.stringify(res)); + if (extUser?.Webhook) { + const params = { + event: event, + ...body, + }; + await axios + .post(extUser?.Webhook, params, { + headers: { 'Content-Type': 'application/json' }, + }) + .then(res => { + try { + // console.log('res ', res); + const webhook = new Parse.Object('contracts_Webhook'); + webhook.set('Log', res?.status); + webhook.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: userId, + }); + webhook.save(null, { useMasterKey: true }); + } catch (err) { + console.log('err save in contracts_Webhook', err); + } + }) + .catch(err => { + console.log('Err send data to webhook', err); + try { + const webhook = new Parse.Object('contracts_Webhook'); + webhook.set('Log', err?.status); + webhook.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: userId, + }); + webhook.save(null, { useMasterKey: true }); + } catch (err) { + console.log('err save in contracts_Webhook', err); + } + }); + } + return { message: 'webhook called!' }; + } + } else { + return { message: 'User not found!' }; + } +} diff --git a/apps/OpenSignServer/cloud/parsefunction/generateApiToken.js b/apps/OpenSignServer/cloud/parsefunction/generateApiToken.js new file mode 100644 index 000000000..8f39ccfdb --- /dev/null +++ b/apps/OpenSignServer/cloud/parsefunction/generateApiToken.js @@ -0,0 +1,44 @@ +import { generateApiKey } from 'generate-api-key'; +import axios from 'axios'; +export default async function generateApiToken(request) { + const serverUrl = process.env.SERVER_URL; + try { + const userRes = await axios.get(serverUrl + '/users/me', { + headers: { + 'X-Parse-Application-Id': process.env.APP_ID, + 'X-Parse-Session-Token': request.headers['sessiontoken'], + }, + }); + const userId = userRes.data && userRes.data.objectId; + if (userId) { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('userId', { __type: 'Pointer', className: '_User', objectId: userId }); + const token = await tokenQuery.first({ useMasterKey: true }); + if (token !== undefined) { + // return exsiting Token + console.log('Regenerate API Token'); + const AppToken = Parse.Object.extend('appToken'); + const updateToken = new AppToken(); + updateToken.id = token.id; + const newToken = generateApiKey({ method: 'base62', prefix: 'opensign' }); + updateToken.set('token', newToken); + const updatedRes = await updateToken.save(null, { useMasterKey: true }); + return updatedRes; + } else { + // Create New Token + console.log('New API Token Generation'); + const appToken = Parse.Object.extend('appToken'); + const appTokenQuery = new appToken(); + const token = generateApiKey({ method: 'base62', prefix: 'opensign' }); + appTokenQuery.set('token', token); + appTokenQuery.set('userId', { __type: 'Pointer', className: '_User', objectId: userId }); + const newRes = await appTokenQuery.save(null, { useMasterKey: true }); + return newRes; + } + } else { + return 'User not found!'; + } + } catch (err) { + console.log('err ', err); + } +} diff --git a/apps/OpenSignServer/cloud/parsefunction/getUserDetails.js b/apps/OpenSignServer/cloud/parsefunction/getUserDetails.js index 2e50b25a8..671b91d9d 100644 --- a/apps/OpenSignServer/cloud/parsefunction/getUserDetails.js +++ b/apps/OpenSignServer/cloud/parsefunction/getUserDetails.js @@ -1,9 +1,13 @@ async function getUserDetails(request) { try { + const userId = request.params.userId; const userQuery = new Parse.Query('contracts_Users'); userQuery.equalTo('Email', request.params.email); userQuery.include('TenantId'); - userQuery.include('UserId') + userQuery.include('UserId'); + if (userId) { + userQuery.equalTo('CreatedBy', { __type: 'Pointer', className: '_User', objectId: userId }); + } const res = await userQuery.first({ useMasterKey: true }); return res; } catch (err) { diff --git a/apps/OpenSignServer/cloud/parsefunction/getapitoken.js b/apps/OpenSignServer/cloud/parsefunction/getapitoken.js new file mode 100644 index 000000000..570679f57 --- /dev/null +++ b/apps/OpenSignServer/cloud/parsefunction/getapitoken.js @@ -0,0 +1,29 @@ +import axios from 'axios'; +export default async function getapitoken(request) { + const serverUrl = process.env.SERVER_URL; + try { + const userRes = await axios.get(serverUrl + '/users/me', { + headers: { + 'X-Parse-Application-Id': process.env.APP_ID, + 'X-Parse-Session-Token': request.headers['sessiontoken'], + }, + }); + const userId = userRes.data && userRes.data.objectId; + if (userId) { + const tokenQuery = new Parse.Query('appToken'); + tokenQuery.equalTo('userId', { __type: 'Pointer', className: '_User', objectId: userId }); + const res = await tokenQuery.first({ useMasterKey: true }); + if (res) { + return { status: 'success', result: res.get('token') }; + } + } + } catch (err) { + console.log('Err', err); + console.log('err', err); + if (err.code == 209) { + return { error: 'Invalid session token' }; + } else { + return { error: "You don't have access!" }; + } + } +} diff --git a/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js b/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js index b6f989cb7..85d56af52 100644 --- a/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js +++ b/apps/OpenSignServer/cloud/parsefunction/pdf/PDF.min.js @@ -1,22 +1,18 @@ import SignPDF from './SignPDF.min.cjs'; import fs from 'node:fs'; import axios from 'axios'; -import FormData from 'form-data'; -// import plainplaceholder from './customSignPdf/plainplaceholder.min.js'; import { plainAddPlaceholder } from 'node-signpdf/dist/helpers/index.js'; const serverUrl = process.env.SERVER_URL, APPID = process.env.APP_ID, masterKEY = process.env.MASTER_KEY; -async function uploadFile(a) { +async function uploadFile(e, a) { try { - var e = new FormData(), - t = - (e.append('file', fs.createReadStream(a)), - { 'content-type': 'multipart/form-data', 'X-Parse-Application-Id': process.env.APP_ID }), - s = process.env.SERVER_URL.slice(0, -4) + '/file_upload'; - return (await axios.post(s, e, { headers: t })).data; + var t = fs.readFileSync(a), + s = new Parse.File(e, [...t]), + r = (await s.save({ useMasterKey: !0 }), s.url()); + return { imageUrl: r }; } catch (e) { - console.log('err ', e), fs.unlinkSync(a); + console.log('Err ', e), fs.unlinkSync(a); } } async function updateDoc(t, s, r, i, n, o) { @@ -33,8 +29,8 @@ async function updateDoc(t, s, r, i, n, o) { ); let a = !1; !((n.Signers && 0 < n.Signers.length && l.length !== n.Signers.length) || !(a = !0)); - var p = { SignedUrl: s, AuditTrail: e, IsCompleted: a }; - await axios.put(serverUrl + '/classes/contracts_Document/' + t, p, { + var c = { SignedUrl: s, AuditTrail: e, IsCompleted: a }; + await axios.put(serverUrl + '/classes/contracts_Document/' + t, c, { headers: { 'Content-Type': 'application/json', 'X-Parse-Application-Id': APPID, @@ -59,9 +55,9 @@ async function sendMail(e) { html: "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=https://qikinnovation.ams3.digitaloceanspaces.com/logo.png height='50' style='padding:20px'/> </div><div style='padding:2px;font-family:system-ui; background-color: #47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',> Document Copy</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>A copy of the document " + s + - ' Standard is attached to this email. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from Open Sign. For any queries regarding this email, please contact the sender ' + + ' Standard is attached to this email. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' + t.Mail + - ' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>' + ' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>', }; await axios.post(serverUrl + '/functions/sendmailv3', a, { headers: { @@ -84,9 +80,9 @@ async function sendCompletedMail(e) { html: "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /></head><body> <div style='background-color:#f5f5f5;padding:20px'> <div style='box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background-color:white;'> <div><img src=https://qikinnovation.ams3.digitaloceanspaces.com/logo.png height='50' style='padding:20px'/> </div><div style='padding:2px;font-family:system-ui; background-color: #47a3ad;'> <p style='font-size:20px;font-weight:400;color:white;padding-left:20px',> Document sign successfully</p></div><div><p style='padding:20px;font-family:system-ui;font-size:14px'>All parties have successfully signed the document" + s + - '. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from Open Sign. For any queries regarding this email, please contact the sender ' + + '. Kindly download the document from the attachment.</p></div> </div><div><p>This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender ' + t.Mail + - ' directly. If you think this email is inappropriate or spam, you may file a complaint with Open Sign <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>', + ' directly. If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href=www.opensignlabs.com target=_blank>here</a>.</p></div></div></body></html>', }; await axios.post(serverUrl + '/functions/sendmailv3', a, { headers: { @@ -96,6 +92,64 @@ async function sendCompletedMail(e) { }, }); } +async function sendDoctoWebhook(t, e, a, s) { + let r = []; + (r = s + ? { name: s?.Name, email: s?.Email, phone: s?.Phone } + : t?.data?.Signers?.map(e => ({ name: e.Name, email: e.Email, phone: e.Phone })) || [ + { + name: t?.data?.ExtUserPtr?.Name, + email: t?.data?.ExtUserPtr?.Email, + phone: t?.data?.ExtUserPtr?.Phone, + }, + ]), + t.data.ExtUserPtr?.Webhook && + ((s = + 'signed' === a + ? { signer: r, signedAt: new Date() } + : { signers: r, completedAt: new Date() }), + (a = { + event: a, + objectId: t?.data?.objectId, + file: e || '', + name: t?.data?.Name, + note: t?.data?.Note || '', + description: t?.data?.Description || '', + ...s, + createdAt: t?.data?.createdAt, + }), + await axios + .post(t?.data?.ExtUserPtr?.Webhook, a, { headers: { 'Content-Type': 'application/json' } }) + .then(e => { + try { + var a = new Parse.Object('contracts_Webhook'); + a.set('Log', e?.status), + a.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: t.data.ExtUserPtr.UserId.objectId, + }), + a.save(null, { useMasterKey: !0 }); + } catch (e) { + console.log('err save in contracts_Webhook', e); + } + }) + .catch(e => { + console.log('Err send data to webhook', e); + try { + var a = new Parse.Object('contracts_Webhook'); + a.set('Log', e?.status), + a.set('UserId', { + __type: 'Pointer', + className: '_User', + objectId: t.data.ExtUserPtr.UserId.objectId, + }), + a.save(null, { useMasterKey: !0 }); + } catch (e) { + console.log('err save in contracts_Webhook', e); + } + })); +} async function PDF(i, n) { try { i.params.sign; @@ -121,28 +175,28 @@ async function PDF(i, n) { { var d, l, - p, - c = JSON.stringify({ objectId: a }); + c, + p = JSON.stringify({ objectId: a }); let s, r; r = a - ? (d = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + c, { + ? (d = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + p, { headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Session-Token': i.headers.sessiontoken, }, })).data && 0 < d.data.results.length ? ((s = d), 'contracts_Contactbook') - : ((s = await axios.get(serverUrl + '/classes/contracts_Users?where=' + c, { + : ((s = await axios.get(serverUrl + '/classes/contracts_Users?where=' + p, { headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY }, })), 'contracts_Users') : ((l = JSON.stringify({ UserId: { __type: 'Pointer', className: '_User', objectId: t.data.objectId }, })), - (p = await axios.get(serverUrl + '/classes/contracts_Users?where=' + l, { + (c = await axios.get(serverUrl + '/classes/contracts_Users?where=' + l, { headers: { 'X-Parse-Application-Id': APPID, 'X-Parse-Master-Key': masterKEY }, - })).data && 0 < p.data.results.length - ? ((s = p), 'contracts_Users') + })).data && 0 < c.data.results.length + ? ((s = c), 'contracts_Users') : ((s = await axios.get(serverUrl + '/classes/contracts_Contactbook?where=' + l, { headers: { 'X-Parse-Application-Id': APPID, @@ -155,8 +209,8 @@ async function PDF(i, n) { if (!i.params.pdfFile) return { status: 'error', message: 'pdf file not present!' }; { let e = Buffer.from(i.params.pdfFile, 'base64'); - var u = process.env.PFX_BASE64, - h = Buffer.from(u, 'base64'), + var h = process.env.PFX_BASE64, + u = Buffer.from(h, 'base64'), f = { UserPtr: { __type: 'Pointer', className: r, objectId: s.data.results[0].objectId }, SignedUrl: '', @@ -175,56 +229,66 @@ async function PDF(i, n) { ); var v, P, - x = `./exports/exported_file_${Math.floor(5e3 * Math.random())}.pdf`, - A = + b = `exported_file_${Math.floor(5e3 * Math.random())}.pdf`, + x = './exports/' + b, + U = (t ? ((v = o.data.Signers?.map(e => e.Name + ' <' + e.Email + '>')), (e = v && 0 < v.length ? plainAddPlaceholder({ pdfBuffer: e, - reason: 'Digitally signed by Open sign for ' + v?.join(', '), + reason: 'Digitally signed by OpenSign for ' + v?.join(', '), location: 'location', signatureLength: 1e4, }) : plainAddPlaceholder({ pdfBuffer: e, - reason: 'Digitally signed by Open sign for ' + m + ' <' + g + '>', + reason: 'Digitally signed by OpenSign for ' + m + ' <' + g + '>', location: 'location', signatureLength: 1e4, })), - (P = await new SignPDF(e, h).signPDF()), + (P = await new SignPDF(e, u).signPDF()), fs.writeFileSync(x, P)) : fs.writeFileSync(x, e), - await uploadFile(x)); - if (A && A.imageUrl) { + await uploadFile(b, x)); + if (U && U.imageUrl) { const n = await updateDoc( i.params.docId, - A.imageUrl, + U.imageUrl, s.data.results[0].objectId, i.headers['x-real-ip'], o.data, r ); - return ( - sendMail({ - url: A.imageUrl, + var I, + w = { + url: U.imageUrl, sender: { Mail: o.data.ExtUserPtr.Email, Name: o.data.ExtUserPtr.Name }, pdfName: o.data.Name, receiver: g, - }), + }; + return ( + o.data.IsSendMail && !1 === o.data.IsSendMail + ? console.log("don't send mail") + : sendMail(w), + sendDoctoWebhook(o, U.imageUrl, 'signed', s?.data.results?.[0]), n && n.isCompleted && - sendCompletedMail({ - url: A.imageUrl, - sender: { Mail: o.data.ExtUserPtr.Email, Name: 'Open sign' }, + ((I = { + url: U.imageUrl, + sender: { Mail: o.data.ExtUserPtr.Email, Name: 'OpenSign™' }, pdfName: o.data.Name, receiver: o.data.ExtUserPtr.Email, }), + o.data.IsSendMail && !1 === o.data.IsSendMail + ? console.log("don't send mail") + : sendCompletedMail(I), + sendDoctoWebhook(o, U.imageUrl, 'completed')), fs.unlinkSync(x), console.log('New Signed PDF created called: ' + x), 'success' === n.message - ? { status: 'success', data: A.imageUrl } + ? { status: 'success', data: U.imageUrl } : { status: 'error', message: 'please provide required parameters!' } ); } diff --git a/apps/OpenSignServer/cloud/parsefunction/reportsJson.js b/apps/OpenSignServer/cloud/parsefunction/reportsJson.js index 2031cd076..199210639 100644 --- a/apps/OpenSignServer/cloud/parsefunction/reportsJson.js +++ b/apps/OpenSignServer/cloud/parsefunction/reportsJson.js @@ -11,14 +11,27 @@ export default function reportJson(id, userId) { IsCompleted: { $ne: true }, IsDeclined: { $ne: true }, IsArchive: { $ne: true }, - $or: [{Signers:{$eq:[]}}, { Signers: null }, { Signers: { $exists: true }, Placeholders: null }], + $or: [ + { Signers: { $eq: [] } }, + { Signers: null }, + { Signers: { $exists: true }, Placeholders: null }, + ], CreatedBy: { __type: 'Pointer', className: '_User', objectId: currentUserId, }, }, - keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'], + keys: [ + 'Name', + 'Note', + 'Folder.Name', + 'URL', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', + ], }; // Need your sign report case '4Hhwbp482K': @@ -53,6 +66,8 @@ export default function reportJson(id, userId) { 'URL', 'ExtUserPtr.Name', 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', 'Signers.UserId', 'AuditTrail', ], @@ -77,7 +92,16 @@ export default function reportJson(id, userId) { $gt: { __type: 'Date', iso: new Date().toISOString() }, }, }, - keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'], + keys: [ + 'Name', + 'Note', + 'Folder.Name', + 'URL', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', + ], }; // completed documents report case 'kQUoW4hUXz': @@ -99,8 +123,11 @@ export default function reportJson(id, userId) { 'Note', 'Folder.Name', 'URL', + 'SignedUrl', 'ExtUserPtr.Name', 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', 'TimeToCompleteDays', ], }; @@ -120,7 +147,16 @@ export default function reportJson(id, userId) { }, }, - keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'], + keys: [ + 'Name', + 'Note', + 'Folder.Name', + 'URL', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', + ], }; // Expired Documents report case 'zNqBHXHsYH': @@ -150,7 +186,16 @@ export default function reportJson(id, userId) { objectId: currentUserId, }, }, - keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'], + keys: [ + 'Name', + 'Note', + 'Folder.Name', + 'URL', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', + ], }; // Recently sent for signatures report show on dashboard case 'd9k3UfYHBc': @@ -172,7 +217,15 @@ export default function reportJson(id, userId) { $gt: { __type: 'Date', iso: new Date().toISOString() }, }, }, - keys: ['Name', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'], + keys: [ + 'Name', + 'Folder.Name', + 'URL', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', + ], }; // Recent signature requests report show on dashboard case '5Go51Q7T8r': @@ -200,7 +253,16 @@ export default function reportJson(id, userId) { }, }, }, - keys: ['Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name', 'Signers.UserId', 'AuditTrail'], + keys: [ + 'Name', + 'URL', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.UserId', + 'AuditTrail', + 'Signers.Email', + 'Signers.Phone', + ], }; // Drafts report show on dashboard case 'kC5mfynCi4': @@ -211,14 +273,27 @@ export default function reportJson(id, userId) { IsCompleted: { $ne: true }, IsDeclined: { $ne: true }, IsArchive: { $ne: true }, - $or: [{Signers:{$eq:[]}}, { Signers: null }, { Signers: { $exists: true }, Placeholders: null }], + $or: [ + { Signers: { $eq: [] } }, + { Signers: null }, + { Signers: { $exists: true }, Placeholders: null }, + ], CreatedBy: { __type: 'Pointer', className: '_User', objectId: currentUserId, }, }, - keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'], + keys: [ + 'Name', + 'Note', + 'Folder.Name', + 'URL', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', + ], }; // contact book report case '5KhaPr482K': @@ -249,7 +324,16 @@ export default function reportJson(id, userId) { objectId: currentUserId, }, }, - keys: ['Name', 'Note', 'Folder.Name', 'URL', 'ExtUserPtr.Name', 'Signers.Name'], + keys: [ + 'Name', + 'Note', + 'Folder.Name', + 'URL', + 'ExtUserPtr.Name', + 'Signers.Name', + 'Signers.Email', + 'Signers.Phone', + ], }; default: return null; diff --git a/apps/OpenSignServer/cloud/parsefunction/saveWebhook.js b/apps/OpenSignServer/cloud/parsefunction/saveWebhook.js new file mode 100644 index 000000000..1beff7c4b --- /dev/null +++ b/apps/OpenSignServer/cloud/parsefunction/saveWebhook.js @@ -0,0 +1,29 @@ +import axios from 'axios'; +export default async function savewebhook(request) { + const serverUrl = process.env.SERVER_URL; + try { + const userRes = await axios.get(serverUrl + '/users/me', { + headers: { + 'X-Parse-Application-Id': process.env.APP_ID, + 'X-Parse-Session-Token': request.headers['sessiontoken'], + }, + }); + const userId = userRes.data && userRes.data.objectId; + const contractuser = new Parse.Query('contracts_Users'); + contractuser.equalTo('UserId', { __type: 'Pointer', className: '_User', objectId: userId }); + const user = await contractuser.first({ useMasterKey: true }); + + if (user) { + const updateUser = new Parse.Object('contracts_Users'); + updateUser.id = user.id; + updateUser.set('Webhook', request.params.url); + const updatedRes = await updateUser.save(null, { useMasterKey: true }); + if (updatedRes) { + return { code: 200, Webhook: updatedRes.get('Webhook') }; + } + } + } catch (err) { + console.log('update user', err); + return err; + } +} diff --git a/apps/OpenSignServer/cloud/parsefunction/sendMail.js b/apps/OpenSignServer/cloud/parsefunction/sendMail.js index c607c2822..f8fb5f8da 100644 --- a/apps/OpenSignServer/cloud/parsefunction/sendMail.js +++ b/apps/OpenSignServer/cloud/parsefunction/sendMail.js @@ -4,30 +4,29 @@ import formData from 'form-data'; import Mailgun from 'mailgun.js'; import { createTransport } from 'nodemailer'; -let transporterSMTP; -let mailgunClient; -let mailgunDomain; -if (process.env.SMTP_ENABLE) { - transporterSMTP = createTransport({ - host: process.env.SMTP_HOST, - port: process.env.SMTP_PORT || 465, - secure: process.env.SMTP_SECURE || true, - auth: { - user: process.env.SMTP_USER_EMAIL, - pass: process.env.SMTP_PASS, - }, - }); -} else { - const mailgun = new Mailgun(formData); - mailgunClient = mailgun.client({ - username: 'api', - key: process.env.MAILGUN_API_KEY, - }); - mailgunDomain = process.env.MAILGUN_DOMAIN; -} - async function sendmail(req) { try { + let transporterSMTP; + let mailgunClient; + let mailgunDomain; + if (process.env.SMTP_ENABLE) { + transporterSMTP = createTransport({ + host: process.env.SMTP_HOST, + port: process.env.SMTP_PORT || 465, + secure: process.env.SMTP_SECURE || true, + auth: { + user: process.env.SMTP_USER_EMAIL, + pass: process.env.SMTP_PASS, + }, + }); + } else { + const mailgun = new Mailgun(formData); + mailgunClient = mailgun.client({ + username: 'api', + key: process.env.MAILGUN_API_KEY, + }); + mailgunDomain = process.env.MAILGUN_DOMAIN; + } if (req.params.url) { let Pdf = fs.createWriteStream('test.pdf'); const writeToLocalDisk = () => { diff --git a/apps/OpenSignServer/databases/migrations/20240116170302-add_generatetoken_menu_cjs.cjs b/apps/OpenSignServer/databases/migrations/20240116170302-add_generatetoken_menu_cjs.cjs new file mode 100644 index 000000000..555dd4e77 --- /dev/null +++ b/apps/OpenSignServer/databases/migrations/20240116170302-add_generatetoken_menu_cjs.cjs @@ -0,0 +1,652 @@ +/** + * + * @param {Parse} Parse + */ +exports.up = async Parse => { + const className = 'w_menu'; + const userMenu = new Parse.Query(className); + const updateUserMenu = await userMenu.get('H9vRfEYKhT'); + updateUserMenu.set('menuItems', [ + { + icon: 'fas fa-tachometer-alt', + title: 'Dashboard', + target: '', + pageType: 'dashboard', + description: '', + objectId: '35KBoSgoAK', + }, + { + icon: 'far fa-newspaper', + title: 'New Document', + target: '_self', + pageType: null, + description: null, + objectId: null, + children: [ + { + icon: 'fas fa-pen-nib', + title: 'Sign yourself', + target: '_self', + pageType: 'form', + description: '', + objectId: 'sHAnZphf69', + }, + { + icon: 'fa-solid fa-paper-plane', + title: 'Request signatures', + target: '_self', + pageType: 'form', + description: '', + objectId: '8mZzFxbG1z', + }, + { + icon: 'fas fa-file-signature', + title: 'New template', + target: '_self', + pageType: 'form', + description: '', + objectId: 'template', + }, + ], + }, + { + icon: 'fa-solid fa-file-contract', + title: 'Templates', + target: '_self', + pageType: 'report', + description: '', + objectId: '6TeaPr321t', + }, + { + icon: 'fas fa-folder', + title: 'OpenSign™ Drive', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive', + }, + { + icon: 'fas fa-address-card', + title: 'Reports', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-signature', + title: 'Need your sign', + target: '_self', + pageType: 'report', + description: '', + objectId: '4Hhwbp482K', + }, + { + icon: 'fas fa-tasks', + title: 'In Progress', + target: '_self', + pageType: 'report', + description: '', + objectId: '1MwEuxLEkF', + }, + { + icon: 'fas fa-check-circle', + title: 'Completed', + target: '_self', + pageType: 'report', + description: '', + objectId: 'kQUoW4hUXz', + }, + { + icon: 'fas fa-edit', + title: 'Drafts', + target: '_self', + pageType: 'report', + description: '', + objectId: 'ByHuevtCFY', + }, + { + icon: 'fas fa-times-circle', + title: 'Declined', + target: '_self', + pageType: 'report', + description: '', + objectId: 'UPr2Fm5WY3', + }, + { + icon: 'fas fa-hourglass-end', + title: 'Expired', + target: '_self', + pageType: 'report', + description: '', + objectId: 'zNqBHXHsYH', + }, + { + icon: 'fa-solid fa-address-book', + title: 'Contactbook', + target: '_self', + pageType: 'report', + description: '', + objectId: '5KhaPr482K', + }, + ], + }, + { + icon: 'fas fa-cog', + title: 'Settings', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-pen-fancy', + title: 'My Signature', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign', + }, + { + icon: 'fa-solid fa-key', + title: 'API Token', + target: '_self', + pageType: 'generatetoken', + description: '', + objectId: '', + }, + ], + }, + ]); + + const AdminMenu = new Parse.Query(className); + const updateAdminMenu = await AdminMenu.get('VPh91h0ZHk'); + updateAdminMenu.set('menuItems', [ + { + icon: 'fas fa-tachometer-alt', + title: 'Dashboard', + target: '', + pageType: 'dashboard', + description: '', + objectId: '35KBoSgoAK', + }, + { + icon: 'far fa-newspaper', + title: 'New Document', + target: '_self', + pageType: null, + description: null, + objectId: null, + children: [ + { + icon: 'fas fa-pen-nib', + title: 'Sign yourself', + target: '_self', + pageType: 'form', + description: '', + objectId: 'sHAnZphf69', + }, + { + icon: 'fa-solid fa-paper-plane', + title: 'Request signatures', + target: '_self', + pageType: 'form', + description: '', + objectId: '8mZzFxbG1z', + }, + { + icon: 'fas fa-file-signature', + title: 'New template', + target: '_self', + pageType: 'form', + description: '', + objectId: 'template', + }, + ], + }, + { + icon: 'fa-solid fa-file-contract', + title: 'Templates', + target: '_self', + pageType: 'report', + description: '', + objectId: '6TeaPr321t', + }, + { + icon: 'fas fa-folder', + title: 'OpenSign™ Drive', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive', + }, + { + icon: 'fas fa-address-card', + title: 'Reports', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-signature', + title: 'Need your sign', + target: '_self', + pageType: 'report', + description: '', + objectId: '4Hhwbp482K', + }, + { + icon: 'fas fa-tasks', + title: 'In Progress', + target: '_self', + pageType: 'report', + description: '', + objectId: '1MwEuxLEkF', + }, + { + icon: 'fas fa-check-circle', + title: 'Completed', + target: '_self', + pageType: 'report', + description: '', + objectId: 'kQUoW4hUXz', + }, + { + icon: 'fas fa-edit', + title: 'Drafts', + target: '_self', + pageType: 'report', + description: '', + objectId: 'ByHuevtCFY', + }, + { + icon: 'fas fa-times-circle', + title: 'Declined', + target: '_self', + pageType: 'report', + description: '', + objectId: 'UPr2Fm5WY3', + }, + { + icon: 'fas fa-hourglass-end', + title: 'Expired', + target: '_self', + pageType: 'report', + description: '', + objectId: 'zNqBHXHsYH', + }, + { + icon: 'fa-solid fa-address-book', + title: 'Contactbook', + target: '_self', + pageType: 'report', + description: '', + objectId: '5KhaPr482K', + }, + ], + }, + { + icon: 'fas fa-cog', + title: 'Settings', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-pen-fancy', + title: 'My Signature', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign', + }, + { + icon: 'far fa-user', + title: 'Add User', + target: '_self', + pageType: 'form', + description: '', + objectId: 'lM0xRnM3iE', + }, + { + icon: 'fa-solid fa-key', + title: 'API Token', + target: '_self', + pageType: 'generatetoken', + description: '', + objectId: '', + }, + ], + }, + ]); + // TODO: Set the schema here + // Example: + // schema.addString('name').addNumber('cash'); + const batch = [updateUserMenu, updateAdminMenu]; + return Parse.Object.saveAll(batch, { useMasterKey: true }); +}; + +/** + * + * @param {Parse} Parse + */ +exports.down = async Parse => { + // TODO: set className here + const className = 'w_menu'; + const userMenu = new Parse.Query(className); + const revertUserMenu = await userMenu.get('H9vRfEYKhT'); + revertUserMenu.set('menuItems', [ + { + icon: 'fas fa-tachometer-alt', + title: 'Dashboard', + target: '', + pageType: 'dashboard', + description: '', + objectId: '35KBoSgoAK', + }, + { + icon: 'far fa-newspaper', + title: 'New Document', + target: '_self', + pageType: null, + description: null, + objectId: null, + children: [ + { + icon: 'fas fa-pen-nib', + title: 'Sign yourself', + target: '_self', + pageType: 'form', + description: '', + objectId: 'sHAnZphf69', + }, + { + icon: 'fa-solid fa-paper-plane', + title: 'Request signatures', + target: '_self', + pageType: 'form', + description: '', + objectId: '8mZzFxbG1z', + }, + { + icon: 'fas fa-file-signature', + title: 'New template', + target: '_self', + pageType: 'form', + description: '', + objectId: 'template', + }, + ], + }, + { + icon: 'fa-solid fa-file-contract', + title: 'Templates', + target: '_self', + pageType: 'report', + description: '', + objectId: '6TeaPr321t', + }, + { + icon: 'fas fa-folder', + title: 'OpenSign™ Drive', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive', + }, + { + icon: 'fas fa-address-card', + title: 'Reports', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-signature', + title: 'Need your sign', + target: '_self', + pageType: 'report', + description: '', + objectId: '4Hhwbp482K', + }, + { + icon: 'fas fa-tasks', + title: 'In Progress', + target: '_self', + pageType: 'report', + description: '', + objectId: '1MwEuxLEkF', + }, + { + icon: 'fas fa-check-circle', + title: 'Completed', + target: '_self', + pageType: 'report', + description: '', + objectId: 'kQUoW4hUXz', + }, + { + icon: 'fas fa-edit', + title: 'Drafts', + target: '_self', + pageType: 'report', + description: '', + objectId: 'ByHuevtCFY', + }, + { + icon: 'fas fa-times-circle', + title: 'Declined', + target: '_self', + pageType: 'report', + description: '', + objectId: 'UPr2Fm5WY3', + }, + { + icon: 'fas fa-hourglass-end', + title: 'Expired', + target: '_self', + pageType: 'report', + description: '', + objectId: 'zNqBHXHsYH', + }, + { + icon: 'fa-solid fa-address-book', + title: 'Contactbook', + target: '_self', + pageType: 'report', + description: '', + objectId: '5KhaPr482K', + }, + ], + }, + { + icon: 'fas fa-cog', + title: 'Settings', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-pen-fancy', + title: 'My Signature', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign', + }, + ], + }, + ]); + + const adminMenu = new Parse.Query(className); + const revertAdminMenu = await adminMenu.get('VPh91h0ZHk'); + revertAdminMenu.set('menuItems', [ + { + icon: 'fas fa-tachometer-alt', + title: 'Dashboard', + target: '', + pageType: 'dashboard', + description: '', + objectId: '35KBoSgoAK', + }, + { + icon: 'far fa-newspaper', + title: 'New Document', + target: '_self', + pageType: null, + description: null, + objectId: null, + children: [ + { + icon: 'fas fa-pen-nib', + title: 'Sign yourself', + target: '_self', + pageType: 'form', + description: '', + objectId: 'sHAnZphf69', + }, + { + icon: 'fa-solid fa-paper-plane', + title: 'Request signatures', + target: '_self', + pageType: 'form', + description: '', + objectId: '8mZzFxbG1z', + }, + { + icon: 'fas fa-file-signature', + title: 'New template', + target: '_self', + pageType: 'form', + description: '', + objectId: 'template', + }, + ], + }, + { + icon: 'fa-solid fa-file-contract', + title: 'Templates', + target: '_self', + pageType: 'report', + description: '', + objectId: '6TeaPr321t', + }, + { + icon: 'fas fa-folder', + title: 'OpenSign™ Drive', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive', + }, + { + icon: 'fas fa-address-card', + title: 'Reports', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-signature', + title: 'Need your sign', + target: '_self', + pageType: 'report', + description: '', + objectId: '4Hhwbp482K', + }, + { + icon: 'fas fa-tasks', + title: 'In Progress', + target: '_self', + pageType: 'report', + description: '', + objectId: '1MwEuxLEkF', + }, + { + icon: 'fas fa-check-circle', + title: 'Completed', + target: '_self', + pageType: 'report', + description: '', + objectId: 'kQUoW4hUXz', + }, + { + icon: 'fas fa-edit', + title: 'Drafts', + target: '_self', + pageType: 'report', + description: '', + objectId: 'ByHuevtCFY', + }, + { + icon: 'fas fa-times-circle', + title: 'Declined', + target: '_self', + pageType: 'report', + description: '', + objectId: 'UPr2Fm5WY3', + }, + { + icon: 'fas fa-hourglass-end', + title: 'Expired', + target: '_self', + pageType: 'report', + description: '', + objectId: 'zNqBHXHsYH', + }, + { + icon: 'fa-solid fa-address-book', + title: 'Contactbook', + target: '_self', + pageType: 'report', + description: '', + objectId: '5KhaPr482K', + }, + ], + }, + { + icon: 'fas fa-cog', + title: 'Settings', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-pen-fancy', + title: 'My Signature', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign', + }, + { + icon: 'far fa-user', + title: 'Add User', + target: '_self', + pageType: 'form', + description: '', + objectId: 'lM0xRnM3iE', + }, + ], + }, + ]); + // TODO: Set the schema here + // Example: + // schema.addString('name').addNumber('cash'); + const batch = [revertUserMenu, revertAdminMenu]; + return Parse.Object.saveAll(batch, { useMasterKey: true }); +}; diff --git a/apps/OpenSignServer/databases/migrations/20240123122932-add_webhook_menu.cjs b/apps/OpenSignServer/databases/migrations/20240123122932-add_webhook_menu.cjs new file mode 100644 index 000000000..01f30c910 --- /dev/null +++ b/apps/OpenSignServer/databases/migrations/20240123122932-add_webhook_menu.cjs @@ -0,0 +1,684 @@ +/** + * + * @param {Parse} Parse + */ +exports.up = async Parse => { + const className = 'w_menu'; + const userMenu = new Parse.Query(className); + const updateUserMenu = await userMenu.get('H9vRfEYKhT'); + updateUserMenu.set('menuItems', [ + { + icon: 'fas fa-tachometer-alt', + title: 'Dashboard', + target: '', + pageType: 'dashboard', + description: '', + objectId: '35KBoSgoAK', + }, + { + icon: 'far fa-newspaper', + title: 'New Document', + target: '_self', + pageType: null, + description: null, + objectId: null, + children: [ + { + icon: 'fas fa-pen-nib', + title: 'Sign yourself', + target: '_self', + pageType: 'form', + description: '', + objectId: 'sHAnZphf69', + }, + { + icon: 'fa-solid fa-paper-plane', + title: 'Request signatures', + target: '_self', + pageType: 'form', + description: '', + objectId: '8mZzFxbG1z', + }, + { + icon: 'fas fa-file-signature', + title: 'New template', + target: '_self', + pageType: 'form', + description: '', + objectId: 'template', + }, + ], + }, + { + icon: 'fa-solid fa-file-contract', + title: 'Templates', + target: '_self', + pageType: 'report', + description: '', + objectId: '6TeaPr321t', + }, + { + icon: 'fas fa-folder', + title: 'OpenSign™ Drive', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive', + }, + { + icon: 'fas fa-address-card', + title: 'Reports', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-signature', + title: 'Need your sign', + target: '_self', + pageType: 'report', + description: '', + objectId: '4Hhwbp482K', + }, + { + icon: 'fas fa-tasks', + title: 'In Progress', + target: '_self', + pageType: 'report', + description: '', + objectId: '1MwEuxLEkF', + }, + { + icon: 'fas fa-check-circle', + title: 'Completed', + target: '_self', + pageType: 'report', + description: '', + objectId: 'kQUoW4hUXz', + }, + { + icon: 'fas fa-edit', + title: 'Drafts', + target: '_self', + pageType: 'report', + description: '', + objectId: 'ByHuevtCFY', + }, + { + icon: 'fas fa-times-circle', + title: 'Declined', + target: '_self', + pageType: 'report', + description: '', + objectId: 'UPr2Fm5WY3', + }, + { + icon: 'fas fa-hourglass-end', + title: 'Expired', + target: '_self', + pageType: 'report', + description: '', + objectId: 'zNqBHXHsYH', + }, + { + icon: 'fa-solid fa-address-book', + title: 'Contactbook', + target: '_self', + pageType: 'report', + description: '', + objectId: '5KhaPr482K', + }, + ], + }, + { + icon: 'fas fa-cog', + title: 'Settings', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-pen-fancy', + title: 'My Signature', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign', + }, + { + icon: 'fa-solid fa-key', + title: 'API Token', + target: '_self', + pageType: 'generatetoken', + description: '', + objectId: '', + }, + { + icon: 'fa-solid fa-globe', + title: 'Webhook', + target: '_self', + pageType: 'webhook', + description: '', + objectId: '', + }, + ], + }, + ]); + + const AdminMenu = new Parse.Query(className); + const updateAdminMenu = await AdminMenu.get('VPh91h0ZHk'); + updateAdminMenu.set('menuItems', [ + { + icon: 'fas fa-tachometer-alt', + title: 'Dashboard', + target: '', + pageType: 'dashboard', + description: '', + objectId: '35KBoSgoAK', + }, + { + icon: 'far fa-newspaper', + title: 'New Document', + target: '_self', + pageType: null, + description: null, + objectId: null, + children: [ + { + icon: 'fas fa-pen-nib', + title: 'Sign yourself', + target: '_self', + pageType: 'form', + description: '', + objectId: 'sHAnZphf69', + }, + { + icon: 'fa-solid fa-paper-plane', + title: 'Request signatures', + target: '_self', + pageType: 'form', + description: '', + objectId: '8mZzFxbG1z', + }, + { + icon: 'fas fa-file-signature', + title: 'New template', + target: '_self', + pageType: 'form', + description: '', + objectId: 'template', + }, + ], + }, + { + icon: 'fa-solid fa-file-contract', + title: 'Templates', + target: '_self', + pageType: 'report', + description: '', + objectId: '6TeaPr321t', + }, + { + icon: 'fas fa-folder', + title: 'OpenSign™ Drive', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive', + }, + { + icon: 'fas fa-address-card', + title: 'Reports', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-signature', + title: 'Need your sign', + target: '_self', + pageType: 'report', + description: '', + objectId: '4Hhwbp482K', + }, + { + icon: 'fas fa-tasks', + title: 'In Progress', + target: '_self', + pageType: 'report', + description: '', + objectId: '1MwEuxLEkF', + }, + { + icon: 'fas fa-check-circle', + title: 'Completed', + target: '_self', + pageType: 'report', + description: '', + objectId: 'kQUoW4hUXz', + }, + { + icon: 'fas fa-edit', + title: 'Drafts', + target: '_self', + pageType: 'report', + description: '', + objectId: 'ByHuevtCFY', + }, + { + icon: 'fas fa-times-circle', + title: 'Declined', + target: '_self', + pageType: 'report', + description: '', + objectId: 'UPr2Fm5WY3', + }, + { + icon: 'fas fa-hourglass-end', + title: 'Expired', + target: '_self', + pageType: 'report', + description: '', + objectId: 'zNqBHXHsYH', + }, + { + icon: 'fa-solid fa-address-book', + title: 'Contactbook', + target: '_self', + pageType: 'report', + description: '', + objectId: '5KhaPr482K', + }, + ], + }, + { + icon: 'fas fa-cog', + title: 'Settings', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-pen-fancy', + title: 'My Signature', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign', + }, + { + icon: 'far fa-user', + title: 'Add User', + target: '_self', + pageType: 'form', + description: '', + objectId: 'lM0xRnM3iE', + }, + { + icon: 'fa-solid fa-key', + title: 'API Token', + target: '_self', + pageType: 'generatetoken', + description: '', + objectId: '', + }, + { + icon: 'fa-solid fa-globe', + title: 'Webhook', + target: '_self', + pageType: 'webhook', + description: '', + objectId: '', + }, + ], + }, + ]); + // TODO: Set the schema here + // Example: + // schema.addString('name').addNumber('cash'); + const batch = [updateUserMenu, updateAdminMenu]; + return Parse.Object.saveAll(batch, { useMasterKey: true }); +}; + +/** + * + * @param {Parse} Parse + */ +exports.down = async Parse => { + // TODO: set className here + const className = 'w_menu'; + const userMenu = new Parse.Query(className); + const revertUserMenu = await userMenu.get('H9vRfEYKhT'); + revertUserMenu.set('menuItems', [ + { + icon: 'fas fa-tachometer-alt', + title: 'Dashboard', + target: '', + pageType: 'dashboard', + description: '', + objectId: '35KBoSgoAK', + }, + { + icon: 'far fa-newspaper', + title: 'New Document', + target: '_self', + pageType: null, + description: null, + objectId: null, + children: [ + { + icon: 'fas fa-pen-nib', + title: 'Sign yourself', + target: '_self', + pageType: 'form', + description: '', + objectId: 'sHAnZphf69', + }, + { + icon: 'fa-solid fa-paper-plane', + title: 'Request signatures', + target: '_self', + pageType: 'form', + description: '', + objectId: '8mZzFxbG1z', + }, + { + icon: 'fas fa-file-signature', + title: 'New template', + target: '_self', + pageType: 'form', + description: '', + objectId: 'template', + }, + ], + }, + { + icon: 'fa-solid fa-file-contract', + title: 'Templates', + target: '_self', + pageType: 'report', + description: '', + objectId: '6TeaPr321t', + }, + { + icon: 'fas fa-folder', + title: 'OpenSign™ Drive', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive', + }, + { + icon: 'fas fa-address-card', + title: 'Reports', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-signature', + title: 'Need your sign', + target: '_self', + pageType: 'report', + description: '', + objectId: '4Hhwbp482K', + }, + { + icon: 'fas fa-tasks', + title: 'In Progress', + target: '_self', + pageType: 'report', + description: '', + objectId: '1MwEuxLEkF', + }, + { + icon: 'fas fa-check-circle', + title: 'Completed', + target: '_self', + pageType: 'report', + description: '', + objectId: 'kQUoW4hUXz', + }, + { + icon: 'fas fa-edit', + title: 'Drafts', + target: '_self', + pageType: 'report', + description: '', + objectId: 'ByHuevtCFY', + }, + { + icon: 'fas fa-times-circle', + title: 'Declined', + target: '_self', + pageType: 'report', + description: '', + objectId: 'UPr2Fm5WY3', + }, + { + icon: 'fas fa-hourglass-end', + title: 'Expired', + target: '_self', + pageType: 'report', + description: '', + objectId: 'zNqBHXHsYH', + }, + { + icon: 'fa-solid fa-address-book', + title: 'Contactbook', + target: '_self', + pageType: 'report', + description: '', + objectId: '5KhaPr482K', + }, + ], + }, + { + icon: 'fas fa-cog', + title: 'Settings', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-pen-fancy', + title: 'My Signature', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign', + }, + { + icon: 'fa-solid fa-key', + title: 'API Token', + target: '_self', + pageType: 'generatetoken', + description: '', + objectId: '', + }, + ], + }, + ]); + + const adminMenu = new Parse.Query(className); + const revertAdminMenu = await adminMenu.get('VPh91h0ZHk'); + revertAdminMenu.set('menuItems', [ + { + icon: 'fas fa-tachometer-alt', + title: 'Dashboard', + target: '', + pageType: 'dashboard', + description: '', + objectId: '35KBoSgoAK', + }, + { + icon: 'far fa-newspaper', + title: 'New Document', + target: '_self', + pageType: null, + description: null, + objectId: null, + children: [ + { + icon: 'fas fa-pen-nib', + title: 'Sign yourself', + target: '_self', + pageType: 'form', + description: '', + objectId: 'sHAnZphf69', + }, + { + icon: 'fa-solid fa-paper-plane', + title: 'Request signatures', + target: '_self', + pageType: 'form', + description: '', + objectId: '8mZzFxbG1z', + }, + { + icon: 'fas fa-file-signature', + title: 'New template', + target: '_self', + pageType: 'form', + description: '', + objectId: 'template', + }, + ], + }, + { + icon: 'fa-solid fa-file-contract', + title: 'Templates', + target: '_self', + pageType: 'report', + description: '', + objectId: '6TeaPr321t', + }, + { + icon: 'fas fa-folder', + title: 'OpenSign™ Drive', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/legadrive', + }, + { + icon: 'fas fa-address-card', + title: 'Reports', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-signature', + title: 'Need your sign', + target: '_self', + pageType: 'report', + description: '', + objectId: '4Hhwbp482K', + }, + { + icon: 'fas fa-tasks', + title: 'In Progress', + target: '_self', + pageType: 'report', + description: '', + objectId: '1MwEuxLEkF', + }, + { + icon: 'fas fa-check-circle', + title: 'Completed', + target: '_self', + pageType: 'report', + description: '', + objectId: 'kQUoW4hUXz', + }, + { + icon: 'fas fa-edit', + title: 'Drafts', + target: '_self', + pageType: 'report', + description: '', + objectId: 'ByHuevtCFY', + }, + { + icon: 'fas fa-times-circle', + title: 'Declined', + target: '_self', + pageType: 'report', + description: '', + objectId: 'UPr2Fm5WY3', + }, + { + icon: 'fas fa-hourglass-end', + title: 'Expired', + target: '_self', + pageType: 'report', + description: '', + objectId: 'zNqBHXHsYH', + }, + { + icon: 'fa-solid fa-address-book', + title: 'Contactbook', + target: '_self', + pageType: 'report', + description: '', + objectId: '5KhaPr482K', + }, + ], + }, + { + icon: 'fas fa-cog', + title: 'Settings', + target: '_self', + pageType: null, + description: '', + objectId: null, + children: [ + { + icon: 'fas fa-pen-fancy', + title: 'My Signature', + target: '_self', + pageType: 'mf', + description: '', + objectId: + 'remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/managesign', + }, + { + icon: 'far fa-user', + title: 'Add User', + target: '_self', + pageType: 'form', + description: '', + objectId: 'lM0xRnM3iE', + }, + { + icon: 'fa-solid fa-key', + title: 'API Token', + target: '_self', + pageType: 'generatetoken', + description: '', + objectId: '', + }, + ], + }, + ]); + // TODO: Set the schema here + // Example: + // schema.addString('name').addNumber('cash'); + const batch = [revertUserMenu, revertAdminMenu]; + return Parse.Object.saveAll(batch, { useMasterKey: true }); +}; diff --git a/apps/OpenSignServer/files/verification_email_subject.txt b/apps/OpenSignServer/files/verification_email_subject.txt index 07ca5a6ef..0f8684f2f 100644 --- a/apps/OpenSignServer/files/verification_email_subject.txt +++ b/apps/OpenSignServer/files/verification_email_subject.txt @@ -1 +1 @@ -Email Address Verification \ No newline at end of file +OpenSign™ Email Address Verification \ No newline at end of file diff --git a/apps/OpenSignServer/index.js b/apps/OpenSignServer/index.js index ae3e75bce..896a11bdd 100644 --- a/apps/OpenSignServer/index.js +++ b/apps/OpenSignServer/index.js @@ -19,25 +19,34 @@ import AWS from 'aws-sdk'; import { app as customRoute } from './cloud/customRoute/customApp.js'; import { exec } from 'child_process'; import { createTransport } from 'nodemailer'; - -const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT); +import { app as v1 } from './cloud/customRoute/v1/apiV1.js'; +import { PostHog } from 'posthog-node'; // console.log("configuration ", configuration); +let fsAdapter; if (process.env.USE_LOCAL !== 'TRUE') { - const s3Options = { - bucket: process.env.DO_SPACE, // globalConfig.S3FilesAdapter.bucket, - baseUrl: process.env.DO_BASEURL, - region: process.env.DO_REGION, - directAccess: true, - preserveFileName: true, - s3overrides: { - accessKeyId: process.env.DO_ACCESS_KEY_ID, - secretAccessKey: process.env.DO_SECRET_ACCESS_KEY, - endpoint: spacesEndpoint, - }, - }; - var fsAdapter = new S3Adapter(s3Options); + try { + const spacesEndpoint = new AWS.Endpoint(process.env.DO_ENDPOINT); + const s3Options = { + bucket: process.env.DO_SPACE, // globalConfig.S3FilesAdapter.bucket, + baseUrl: process.env.DO_BASEURL, + region: process.env.DO_REGION, + directAccess: true, + preserveFileName: true, + s3overrides: { + accessKeyId: process.env.DO_ACCESS_KEY_ID, + secretAccessKey: process.env.DO_SECRET_ACCESS_KEY, + endpoint: spacesEndpoint, + }, + }; + fsAdapter = new S3Adapter(s3Options); + } catch (err) { + console.log('Please provide AWS credintials in env file! Defaulting to local storage.'); + fsAdapter = new FSFilesAdapter({ + filesSubDirectory: 'files', // optional, defaults to ./files + }); + } } else { - var fsAdapter = new FSFilesAdapter({ + fsAdapter = new FSFilesAdapter({ filesSubDirectory: 'files', // optional, defaults to ./files }); } @@ -65,7 +74,6 @@ if (process.env.SMTP_ENABLE) { mailgunDomain = process.env.MAILGUN_DOMAIN; } - export const config = { databaseURI: process.env.DATABASE_URI || process.env.MONGODB_URI || 'mongodb://localhost:27017/dev', @@ -73,17 +81,20 @@ export const config = { import('./cloud/main.js'); }, appId: process.env.APP_ID || 'myAppId', - masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it secret! + maxLimit: 500, + masterKey: process.env.MASTER_KEY, //Add your master key here. Keep it secret! masterKeyIps: ['0.0.0.0/0', '::1'], // '::1' serverURL: process.env.SERVER_URL || 'http://localhost:8080/app', // Don't forget to change to https if needed - verifyUserEmails: true, + verifyUserEmails: process.env.SMTP_ENABLE || process.env.MAILGUN_API_KEY ? true : false, publicServerURL: process.env.SERVER_URL || 'http://localhost:8080/app', // Your apps name. This will appear in the subject and body of the emails that are sent. appName: 'Open Sign', allowClientClassCreation: false, - emailAdapter: - process.env.SMTP_ENABLE || process.env.MAILGUN_API_KEY - ? { + allowExpiredAuthDataToken: false, + encodeParseObjectInCloudFunction: true, + ...(process.env.SMTP_ENABLE || process.env.MAILGUN_API_KEY + ? { + emailAdapter: { module: 'parse-server-api-mail-adapter', options: { // The email address from which emails are sent. @@ -114,8 +125,9 @@ export const config = { } else if (transporterMail) await transporterMail.sendMail(payload); }, }, - } - : null, + }, + } + : {}), filesAdapter: fsAdapter, auth: { google: { @@ -129,7 +141,8 @@ export const config = { export const app = express(); app.use(cors()); - +app.use(express.json({ limit: '50mb' })); +app.use(express.urlencoded({ limit: '50mb', extended: true })); app.use(function (req, res, next) { // console.log("req ", req.headers); // console.log("x-forwarded-for", req.headers["x-forwarded-for"]); @@ -151,19 +164,36 @@ function getUserIP(request) { return request.socket.remoteAddress; } } +app.use(function (req, res, next) { + const ph_project_api_key = process.env.PH_PROJECT_API_KEY; + try { + req.posthog = new PostHog(ph_project_api_key); + } catch (err) { + // console.log('Err', err); + req.posthog = ''; + } + next(); +}); // Serve static assets from the /public folder app.use('/public', express.static(path.join(__dirname, '/public'))); // Serve the Parse API on the /parse URL prefix if (!process.env.TESTING) { const mountPath = process.env.PARSE_MOUNT || '/app'; - const server = new ParseServer(config); - await server.start(); - app.use(mountPath, server.app); + try { + const server = new ParseServer(config); + await server.start(); + app.use(mountPath, server.app); + } catch (err) { + console.log(err); + } } // Mount your custom express app app.use('/', customRoute); +// Mount v1 +app.use('/v1', v1); + // Parse Server plays nicely with the rest of your web routes app.get('/', function (req, res) { // res.statusCode = 200; @@ -180,8 +210,12 @@ if (!process.env.TESTING) { httpServer.headersTimeout = 100000; // in milliseconds httpServer.listen(port, function () { console.log('parse-server-example running on port ' + port + '.'); - const migrate = `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=http://localhost:8080/app MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`; + const isWindows = process.platform === 'win32'; + // console.log('isWindows', isWindows); + const migrate = isWindows + ? `set APPLICATION_ID=${process.env.APP_ID}&& set SERVER_URL=http://localhost:8080/app&& set MASTER_KEY=${process.env.MASTER_KEY}&& npx parse-dbtool migrate` + : `APPLICATION_ID=${process.env.APP_ID} SERVER_URL=http://localhost:8080/app MASTER_KEY=${process.env.MASTER_KEY} npx parse-dbtool migrate`; exec(migrate, (error, stdout, stderr) => { if (error) { console.error(`Error: ${error.message}`); @@ -195,6 +229,4 @@ if (!process.env.TESTING) { console.log(`Command output: ${stdout}`); }); }); - // This will enable the Live Query real-time server - await ParseServer.createLiveQueryServer(httpServer); } diff --git a/apps/OpenSignServer/package-lock.json b/apps/OpenSignServer/package-lock.json index e57104d95..09d17a4a3 100644 --- a/apps/OpenSignServer/package-lock.json +++ b/apps/OpenSignServer/package-lock.json @@ -10,23 +10,23 @@ "license": "MIT", "dependencies": { "aws-sdk": "^2.1475.0", - "axios": "1.3.5", + "axios": "1.6.7", "cors": "^2.8.5", "crypto": "^1.0.1", "dotenv": "^16.0.3", "express": "4.18.2", "express-sse": "^0.5.3", "form-data": "^4.0.0", + "generate-api-key": "^1.0.2", "jsonschema": "^1.4.1", "mailgun.js": "^9.3.0", - "mongoose": "^7.2.1", + "mongoose": "^8.1.3", "multer": "^1.4.5-lts.1", "multer-s3": "^2.10.0", "node-forge": "^1.3.1", "node-signpdf": "^1.5.1", "nodemailer": "^6.9.7", - "openai": "^4.8.0", - "parse": "4.1.0", + "parse": "4.3.1", "parse-dbtool": "^1.2.0", "parse-server": "6.3.1", "parse-server-api-mail-adapter": "^3.0.0", @@ -34,6 +34,7 @@ "parse-server-s3-adapter": "^1.2.0", "pdf-lib": "^1.16.0", "pdfkit": "^0.13.0", + "posthog-node": "^3.6.2", "razorpay": "^2.8.6", "request": "^2.88.2" }, @@ -41,7 +42,7 @@ "@babel/eslint-parser": "7.21.3", "eslint": "8.38.0", "jasmine": "4.6.0", - "mongodb-runner": "4.10.0", + "mongodb-runner": "5.5.3", "nodemon": "^2.0.22", "nyc": "15.1.0", "prettier": "2.8.7" @@ -63,11 +64,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" @@ -129,11 +131,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.9.tgz", - "integrity": "sha512-F3fZga2uv09wFdEjEQIJxXALXfz0+JaOb7SabvVMmjHxeVTuGW8wgE8Vp1Hd7O+zMTYtcfEISGRzPkeiaPPsvg==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dependencies": { - "@babel/types": "^7.21.5", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -161,31 +163,31 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", - "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -232,28 +234,28 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } @@ -280,12 +282,12 @@ } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -293,9 +295,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.9.tgz", - "integrity": "sha512-q5PNg/Bi1OpGgx5jYlvWZwAorZepEudDMCLtj967aeS7WMont7dUZI46M2XwcIQqvUlMxWfdLFu4S/qSxeUu5g==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -315,44 +317,49 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz", - "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.23.2.tgz", + "integrity": "sha512-54cIh74Z1rp4oIjsHjqN+WM4fMyCBYe+LpZ9jWm51CZ1fbH3SkAzQD/3XLoNkjbJ7YEmjobLXyvQrFypRHOrXw==", "dependencies": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.11" + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/runtime-corejs3/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/@babel/template": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", - "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/parser": "^7.21.9", - "@babel/types": "^7.21.5" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.5.tgz", - "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.5", - "@babel/helper-environment-visitor": "^7.21.5", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.5", - "@babel/types": "^7.21.5", - "debug": "^4.1.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -360,12 +367,12 @@ } }, "node_modules/@babel/types": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", - "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dependencies": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -877,6 +884,27 @@ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, + "node_modules/@mongodb-js/mongodb-downloader": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.2.10.tgz", + "integrity": "sha512-nM0vUGUcC8DsR6x3AU6032I8b5OaTqAdq9JmanVecq2NyLZu1aacIS9Yqo3QiE2dIlrkn9hcaUg9Z/tL+3QbNA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "decompress": "^4.2.1", + "mongodb-download-url": "^1.3.0", + "node-fetch": "^2.6.11", + "tar": "^6.1.15" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz", + "integrity": "sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@napi-rs/triples": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.1.0.tgz", @@ -1573,15 +1601,6 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.3.tgz", "integrity": "sha512-pg9d0yC4rVNWQzX8U7xb4olIOFuuVL9za3bzMT2pu2SU0SNEi66i2qrvhE2qt0HvkhuCaWJu7pLNOt/Pj8BIrw==" }, - "node_modules/@types/node-fetch": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.5.tgz", - "integrity": "sha512-OZsUlr2nxvkqUFLSaY2ZbA+P1q22q+KrlxWOn/38RX+u5kTkYL2mTujEpzUhGkS+K/QCYp9oagfXG39XOzyySg==", - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, "node_modules/@types/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", @@ -1720,17 +1739,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -1759,45 +1767,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ampersand-events": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ampersand-events/-/ampersand-events-2.0.2.tgz", - "integrity": "sha512-pPnVEJviRxXi9YhZA9j3GwGGBTlDLi+YIoBvrpKXgce+CO1nMlZU2aOV8OJogNuR2YPbptAUHNz7SKX+MvLj8A==", - "dev": true, - "dependencies": { - "ampersand-version": "^1.0.2", - "lodash": "^4.6.1" - } - }, - "node_modules/ampersand-state": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/ampersand-state/-/ampersand-state-5.0.3.tgz", - "integrity": "sha512-sr904K5zvw6mkGjFHhTcfBIdpoJ6mn/HrFg7OleRmBpw3apLb3Z0gVrgRTb7kK1wOLI34vs4S+IXqNHUeqWCzw==", - "dev": true, - "dependencies": { - "ampersand-events": "^2.0.1", - "ampersand-version": "^1.0.0", - "array-next": "~0.0.1", - "key-tree-store": "^1.3.0", - "lodash": "^4.12.0" - } - }, - "node_modules/ampersand-version": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ampersand-version/-/ampersand-version-1.0.2.tgz", - "integrity": "sha512-FVVLY7Pghtgc8pQl0rF3A3+OS/CZ+/ILLMIYIaO1cA9v5SRkainqUMfSot3fu32svuThIsYK3q9iCsH9W5+mWQ==", - "dev": true, - "dependencies": { - "find-root": "^0.1.1", - "through2": "^0.6.3" - } - }, - "node_modules/ansi": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", - "integrity": "sha512-iFY7JCgHbepc0b82yLaw4IMortylNb6wG4kL+4R0C3iv6i+RHGHux/yUX5BTiRvSX/shMnngjR1YyNMnXEFh5A==", - "dev": true - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1889,12 +1858,6 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "node_modules/array-next": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-next/-/array-next-0.0.1.tgz", - "integrity": "sha512-sBOC/Iaz2hCcYi2XlyRfyZCRUxamlE5NJXEFjE9BTx23HALnWAFsPjGtfrAclt9o3G/38Het2yyeyOd3CEY7lg==", - "dev": true - }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -2002,15 +1965,34 @@ "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "node_modules/axios": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.5.tgz", - "integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, + "node_modules/axios/node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -2037,6 +2019,11 @@ "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==" }, + "node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -2079,9 +2066,9 @@ } }, "node_modules/bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", "dev": true, "dependencies": { "readable-stream": "^2.3.5", @@ -2129,12 +2116,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2191,12 +2172,11 @@ } }, "node_modules/bson": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", - "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", - "dev": true, + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.3.0.tgz", + "integrity": "sha512-balJfqwwTBddxfnidJZagCBPP/f48zj9Sdp3OJswREOgsJzHiQSaOIAtApSgDQFYgHqAvFkp53AFSqjMDZoTFw==", "engines": { - "node": ">=0.6.19" + "node": ">=16.20.1" } }, "node_modules/buffer": { @@ -2373,21 +2353,6 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, - "node_modules/caw": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", - "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", - "dev": true, - "dependencies": { - "get-proxy": "^2.0.0", - "isurl": "^1.0.0-alpha5", - "tunnel-agent": "^0.6.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -2401,40 +2366,10 @@ "node": ">=4" } }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "engines": { - "node": "*" - } - }, - "node_modules/cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA==", - "dev": true, - "dependencies": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - }, - "engines": { - "node": ">= 0.6" - } + "node_modules/chance": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.11.tgz", + "integrity": "sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA==" }, "node_modules/chokidar": { "version": "3.5.3", @@ -2475,6 +2410,15 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -2484,18 +2428,6 @@ "node": ">=6" } }, - "node_modules/cli-color": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz", - "integrity": "sha512-Ys/nDhHNRcxrS4EUI2RS/QCUE+61AMuEOj3sWDX+EIHkJWj+4XkRbOdwdxJteAJKjXYBbeFJMtfaEPd1MBF9pQ==", - "dev": true, - "dependencies": { - "d": "~0.1.1", - "es5-ext": "~0.10.2", - "memoizee": "0.3.x", - "timers-ext": "0.1.x" - } - }, "node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -2515,15 +2447,6 @@ "node": ">=0.8" } }, - "node_modules/clui": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/clui/-/clui-0.3.6.tgz", - "integrity": "sha512-Z4UbgZILlIAjkEkZiDOa2aoYjohKx7fa6DxIh6cE9A6WNWZ61iXfQc6CmdC9SKdS5nO0P0UyQ+WfoXfB65e3HQ==", - "dev": true, - "dependencies": { - "cli-color": "0.3.2" - } - }, "node_modules/cluster-key-slot": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", @@ -2624,22 +2547,6 @@ "typedarray": "^0.0.6" } }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/connected-domain": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz", - "integrity": "sha512-lHlohUiJxlpunvDag2Y0pO20bnvarMjnrdciZeuJUqRwrf/5JHNhdpiPIr5GQ8IkqrFj5TDMQwcCjblGo1oeuA==", - "dev": true - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -2736,14 +2643,6 @@ "web-streams-polyfill": "^3.2.0" } }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "engines": { - "node": "*" - } - }, "node_modules/crypto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", @@ -2755,36 +2654,6 @@ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" }, - "node_modules/css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==", - "dev": true, - "dependencies": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "node_modules/css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/d": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", - "integrity": "sha512-0SdM9V9pd/OXJHoWmTfNPTAeD+lw6ZqHg+isPyBFuJsZLSE0Ygg1cYZ/0l6DrKQXMOqGOu1oWupMoOfoRfMZrQ==", - "dev": true, - "dependencies": { - "es5-ext": "~0.10.2" - } - }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -2871,18 +2740,6 @@ "node": ">=4" } }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/decompress-tar": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", @@ -2960,37 +2817,6 @@ "node": ">=0.10.0" } }, - "node_modules/decompress-unzip/node_modules/get-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", - "dev": true, - "dependencies": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-unzip/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/deep-equal": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", @@ -3080,15 +2906,6 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, - "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -3111,29 +2928,6 @@ "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" }, - "node_modules/digest-fetch": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/digest-fetch/-/digest-fetch-1.3.0.tgz", - "integrity": "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==", - "dependencies": { - "base-64": "^0.1.0", - "md5": "^2.3.0" - } - }, - "node_modules/digest-fetch/node_modules/base-64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", - "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==" - }, - "node_modules/docopt": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz", - "integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -3145,41 +2939,6 @@ "node": ">=6.0.0" } }, - "node_modules/dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "dev": true, - "dependencies": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true - }, - "node_modules/domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, - "dependencies": { - "domelementtype": "1" - } - }, - "node_modules/domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", - "dev": true, - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, "node_modules/dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -3188,55 +2947,6 @@ "node": ">=12" } }, - "node_modules/downcache": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/downcache/-/downcache-0.0.9.tgz", - "integrity": "sha512-AssoVsNYu5DnPY0Ro67lkbiAr66sk5IHuiIGm3pzFzWmTzkcEoFjDlG8szzP4x+ZN2OHehKTZbwDrC7l2Q52+g==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "graceful-fs": "^4.1.3", - "limiter": "^1.1.0", - "mkdirp": "^0.5.1", - "npmlog": "^2.0.3", - "request": "^2.69.0", - "rimraf": "^2.5.2" - } - }, - "node_modules/downcache/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/download": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz", - "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==", - "dev": true, - "dependencies": { - "caw": "^2.0.0", - "content-disposition": "^0.5.2", - "decompress": "^4.0.0", - "ext-name": "^5.0.0", - "file-type": "5.2.0", - "filenamify": "^2.0.0", - "get-stream": "^3.0.0", - "got": "^7.0.0", - "make-dir": "^1.0.0", - "p-event": "^1.0.0", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/dset": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", @@ -3245,12 +2955,6 @@ "node": ">=4" } }, - "node_modules/duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", - "dev": true - }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3305,12 +3009,6 @@ "once": "^1.4.0" } }, - "node_modules/entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - }, "node_modules/es-get-iterator": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", @@ -3402,39 +3100,6 @@ "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, - "node_modules/es6-weak-map": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", - "integrity": "sha512-P+N5Cd2TXeb7G59euFiM7snORspgbInS29Nbf3KNO2JQp/DyhvMCDWd58nsVAXwYJ6W3Bx7qDdy6QQ3PCJ7jKQ==", - "dev": true, - "dependencies": { - "d": "~0.1.1", - "es5-ext": "~0.10.6", - "es6-iterator": "~0.1.3", - "es6-symbol": "~2.0.1" - } - }, - "node_modules/es6-weak-map/node_modules/es6-iterator": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", - "integrity": "sha512-6TOmbFM6OPWkTe+bQ3ZuUkvqcWUjAnYjKUCLdbvRsAUz2Pr+fYIibwNXNkLNtIK9PPFbNMZZddaRNkyJhlGJhA==", - "dev": true, - "dependencies": { - "d": "~0.1.1", - "es5-ext": "~0.10.5", - "es6-symbol": "~2.0.1" - } - }, - "node_modules/es6-weak-map/node_modules/es6-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", - "integrity": "sha512-wjobO4zO8726HVU7mI2OA/B6QszqwHJuKab7gKHVx+uRfVVYGcWJkCIFxV2Madqb9/RUSrhJ/r6hPfG7FsWtow==", - "dev": true, - "dependencies": { - "d": "~0.1.1", - "es5-ext": "~0.10.5" - } - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3890,31 +3555,6 @@ "type": "^2.7.2" } }, - "node_modules/ext-list": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", - "dev": true, - "dependencies": { - "mime-db": "^1.28.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ext-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", - "dev": true, - "dependencies": { - "ext-list": "^2.0.0", - "sort-keys-length": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -3991,18 +3631,6 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, - "node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -4031,29 +3659,6 @@ "node": ">=4" } }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", - "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", - "dev": true, - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.0", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -4127,12 +3732,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-root": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-0.1.2.tgz", - "integrity": "sha512-GyDxVgA61TZcrgDJPqOqGBpi80Uf2yIstubgizi7AjC9yPdRrqBR+Y0MvK4kXnYlaoz3d+SGxDHMYVkwI/yd2w==", - "dev": true - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -4314,20 +3913,36 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "minipass": "^3.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">= 8" } }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4360,17 +3975,18 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "integrity": "sha512-fVbU2wRE91yDvKUnrIaQlHKAWKY5e08PmztCrwuH5YVQ+Z/p3d0ny2T48o6uvAAXHIUnfaQdHkmxYbQft1eHVA==", - "dev": true, + "node_modules/generate-api-key": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/generate-api-key/-/generate-api-key-1.0.2.tgz", + "integrity": "sha512-4rPSpXyboIXfugOTN3/0Qaoqpzbk0sepzPS0XyxPh3UMuu+Trk+0JMyJ6mB/7FEgp7oZ1juqsRW+8wSYeKDbfA==", "dependencies": { - "ansi": "^0.3.0", - "has-unicode": "^2.0.0", - "lodash.pad": "^4.1.0", - "lodash.padend": "^4.1.0", - "lodash.padstart": "^4.1.0" + "base-x": "^4.0.0", + "chance": "^1.1.8", + "rfc4648": "^1.5.2", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14" } }, "node_modules/generic-pool": { @@ -4411,35 +4027,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-mongodb-version": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/get-mongodb-version/-/get-mongodb-version-2.0.1.tgz", - "integrity": "sha512-yTN0UY7VJSSt01QH/aCiqiBjfxcDrEdKeM3uXY6QR3sRARoftx36QT0YNsCQm7FDTgrmDje7bK2C9ClM7SGKDA==", - "dev": true, - "dependencies": { - "lodash.startswith": "^4.2.1", - "minimist": "^1.1.1", - "which": "^1.1.1" - }, - "bin": { - "get-mongodb-version": "bin/get-mongodb-version.js" - }, - "optionalDependencies": { - "mongodb": "*" - } - }, - "node_modules/get-mongodb-version/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -4449,25 +4036,17 @@ "node": ">=8.0.0" } }, - "node_modules/get-proxy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", - "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", "dev": true, "dependencies": { - "npm-conf": "^1.1.0" + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/getpass": { @@ -4527,31 +4106,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, - "dependencies": { - "decompress-response": "^3.2.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-plain-obj": "^1.1.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "p-cancelable": "^0.3.0", - "p-timeout": "^1.1.1", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "url-parse-lax": "^1.0.0", - "url-to-options": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4671,15 +4225,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -4691,18 +4236,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "dev": true, - "dependencies": { - "has-symbol-support-x": "^1.4.1" - }, - "engines": { - "node": "*" - } - }, "node_modules/has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", @@ -4761,34 +4294,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dev": true, - "dependencies": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - } - }, - "node_modules/htmlparser2/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -4818,14 +4323,6 @@ "npm": ">=1.3.7" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -4838,12 +4335,9 @@ } }, "node_modules/idb-keyval": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz", - "integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==", - "dependencies": { - "safari-14-idb-fix": "^3.0.0" - } + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", + "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" }, "node_modules/ieee754": { "version": "1.2.1", @@ -4924,12 +4418,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, "node_modules/internal-slot": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", @@ -5040,11 +4528,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -5119,25 +4602,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-mongodb-running": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-mongodb-running/-/is-mongodb-running-1.0.2.tgz", - "integrity": "sha512-EslN8MErcBPExb+iK4RnG1n28JGjByA2Rm3YPmdHDGCRd7Hc2uvqshyVMAJXxbDSxRMy8vhxims2oRqQUeGJeA==", - "dev": true, - "dependencies": { - "chalk": "^2.4.1", - "debug": ">= 2.6.9", - "figures": "^2.0.0", - "lodash": "^4.17.10", - "lsof": "^0.1.0", - "minimist": "^1.2.0", - "node-netstat": "^1.4.2", - "ps-node": "^0.1.6" - }, - "bin": { - "is-mongodb-running": "bin/is-mongodb-running.js" - } - }, "node_modules/is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", @@ -5166,15 +4630,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -5183,15 +4638,6 @@ "node": ">=8" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -5212,15 +4658,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-set": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", @@ -5329,15 +4766,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -5483,19 +4911,6 @@ "node": ">=8" } }, - "node_modules/isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "dev": true, - "dependencies": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - }, - "engines": { - "node": ">= 4" - } - }, "node_modules/iterall": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", @@ -5614,15 +5029,6 @@ "node": ">=6" } }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/jsonschema": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", @@ -5658,9 +5064,9 @@ } }, "node_modules/jsonwebtoken/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -5751,21 +5157,6 @@ "node": ">=12.0.0" } }, - "node_modules/key-tree-store": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/key-tree-store/-/key-tree-store-1.3.0.tgz", - "integrity": "sha512-qXk+lR+LXvGos3wqMxIMWweKDgCx8ZKWM6BEPm7iZkOKug5ggi66vUt+3vbtKJLBrAyOxQ4S8JRwK++Q4XZRmw==", - "dev": true - }, - "node_modules/klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.9" - } - }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -5853,59 +5244,17 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha512-yX/rx6d/UTVh7sSVWVSIMjfnz95evAgDFdb1ZozC35I9mSFCkmzptOzevxjgbQUsc78NR44LVHWjsoMQXy9FDg==", - "dev": true - }, - "node_modules/lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha512-lxdsn7xxlCymgLYo1gGvVrfHmkjDiyqVv62FAeF2i5ta72BipE1SLxw8hPEPLhD4/247Ijw07UQH7Hq/chT5LA==", - "dev": true - }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "dev": true - }, - "node_modules/lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha512-pXYUy7PR8BCLwX5mgJ/aNtyOvuJTdZAo9EQFUvMIYugqmJxnrYaANvTbgndOzHSCSR0wnlBBfRXJL5SbWxo3FQ==", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true - }, "node_modules/lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, - "node_modules/lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==", - "dev": true - }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -5936,12 +5285,6 @@ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, - "node_modules/lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -5952,54 +5295,6 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, - "node_modules/lodash.pad": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", - "integrity": "sha512-mvUHifnLqM+03YNzeTBS1/Gr6JRFjd3rRx88FHWUvamVaT9k2O/kXha3yBSOwB9/DTQrSTLJNHvLBBt2FdX7Mg==", - "dev": true - }, - "node_modules/lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==", - "dev": true - }, - "node_modules/lodash.padstart": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", - "integrity": "sha512-sW73O6S8+Tg66eY56DBk85aQzzUJDtpoXFBgELMd5P/SotAguo+1kYO6RuYgXxA4HJH3LFTFPASX6ET6bjfriw==", - "dev": true - }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==", - "dev": true - }, - "node_modules/lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha512-6raRe2vxCYBhpBu+B+TtNGUzah+hQjVdu3E17wfusjyrXBka2nBS8OH/gjVZ5PvHOhWmIZTYri09Z6n/QfnNMw==", - "dev": true - }, - "node_modules/lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha512-qkTuvgEzYdyhiJBx42YPzPo71R1aEr0z79kAv7Ixg8wPFEjgRgJdUsGMG3Hf3OYSF/kHI79XhNlt+5Ar6OzwxQ==", - "dev": true - }, - "node_modules/lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ==", - "dev": true - }, - "node_modules/lodash.startswith": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz", - "integrity": "sha512-XClYR1h4/fJ7H+mmCKppbiBmljN/nGs73iq2SjCT9SF4CBPoUHzLvWmH1GtZMhMBZSiRkHXfeA2RY1eIlJ75ww==", - "dev": true - }, "node_modules/logform": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", @@ -6013,15 +5308,6 @@ "triple-beam": "^1.3.0" } }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -6061,16 +5347,6 @@ "es5-ext": "~0.10.2" } }, - "node_modules/lsof": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lsof/-/lsof-0.1.0.tgz", - "integrity": "sha512-RlNW3s4gQ0CIlDM3jwfx/Ogdwpa8PHySyd5FnKKXfi2NPXEjqgwONyA0y9ax33ur1G+K+f192zzKNQljupSgNA==", - "deprecated": "No longer maintained", - "dev": true, - "engines": { - "node": ">= 0.2.0" - } - }, "node_modules/mailgun.js": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-9.3.0.tgz", @@ -6093,14 +5369,13 @@ "node": ">=4" } }, - "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" + "node_modules/make-dir/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" } }, "node_modules/media-typer": { @@ -6111,32 +5386,10 @@ "node": ">= 0.6" } }, - "node_modules/memoizee": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", - "integrity": "sha512-LLzVUuWwGBKK188spgOK/ukrp5zvd9JGsiLDH41pH9vt5jvhZfsu5pxDuAnYAMG8YEGce72KO07sSBy9KkvOfw==", - "dev": true, - "dependencies": { - "d": "~0.1.1", - "es5-ext": "~0.10.11", - "es6-weak-map": "~0.1.4", - "event-emitter": "~0.3.4", - "lru-queue": "0.1", - "next-tick": "~0.2.2", - "timers-ext": "0.1" - } - }, - "node_modules/memoizee/node_modules/next-tick": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", - "integrity": "sha512-f7h4svPtl+QidoBv4taKXUjJ70G2asaZ8G28nS0OkqaalX8dwwrtWtyxEDPK62AC00ur/+/E0pUwBwY5EPn15Q==", - "dev": true - }, "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" }, "node_modules/merge-descriptors": { "version": "1.0.1", @@ -6201,15 +5454,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6229,6 +5473,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -6249,28 +5533,34 @@ } }, "node_modules/mongodb": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", - "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", - "dev": true, + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz", + "integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==", "dependencies": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.1.8", - "safe-buffer": "^5.1.2" + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^6.2.0", + "mongodb-connection-string-url": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=16.20.1" }, - "optionalDependencies": { - "saslprep": "^1.0.0" + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" }, "peerDependenciesMeta": { - "aws4": { + "@aws-sdk/credential-providers": { "optional": true }, - "bson-ext": { + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { "optional": true }, "kerberos": { @@ -6279,10 +5569,10 @@ "mongodb-client-encryption": { "optional": true }, - "mongodb-extjson": { + "snappy": { "optional": true }, - "snappy": { + "socks": { "optional": true } } @@ -6327,73 +5617,10 @@ "node": ">=12" } }, - "node_modules/mongodb-core": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.7.tgz", - "integrity": "sha512-WypKdLxFNPOH/Jy6i9z47IjG2wIldA54iDZBmHMINcgKOUcWJh8og+Wix76oGd7EyYkHJKssQ2FAOw5Su/n4XQ==", - "dev": true, - "dependencies": { - "bson": "^1.1.1", - "require_optional": "^1.0.1", - "safe-buffer": "^5.1.2" - }, - "optionalDependencies": { - "saslprep": "^1.0.0" - } - }, - "node_modules/mongodb-dbpath": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/mongodb-dbpath/-/mongodb-dbpath-0.0.1.tgz", - "integrity": "sha512-JljM2Gci3LQgECY4Wnp8tRx6eDNSoTnqiz4TIaOfqLuPr3SAbSdZEAQomHniH8DQJpn97gxdYkW/XomxYPZM2w==", - "dev": true, - "dependencies": { - "async": "^1.4.0", - "debug": "^2.1.1", - "minimist": "^1.1.1", - "mkdirp": "^0.5.1", - "untildify": "^1.0.0" - }, - "bin": { - "mongodb-dbpath": "bin/mongodb-dbpath.js" - } - }, - "node_modules/mongodb-dbpath/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true - }, - "node_modules/mongodb-dbpath/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mongodb-dbpath/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/mongodb-dbpath/node_modules/untildify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-1.0.0.tgz", - "integrity": "sha512-LSU5BVpAncfzB2UBQaqfNww36wRSehWHs2grMM0ueYctZYxAhntiMvqDBhezYCYvbLeejeZ1nUWSl3mmkdPp+g==", - "dev": true, - "dependencies": { - "user-home": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/mongodb-download-url": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.3.0.tgz", - "integrity": "sha512-N7mRi3/LIAHCeTa+JtJVrVno4BNHVYF+6/WUamVFsbvCxtljDmQA1n9FSQxV4dfdiknR9zaoFcXAmd1gtg3Elg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.4.1.tgz", + "integrity": "sha512-OC0EGXiYTwZNcLq2U7Hbt1MDSPQR57/Kput4+W0F2kwVOa0HwWW4oY6DS1gOLlIeVOsihRKKH9EPNnc/BxF7UA==", "dev": true, "dependencies": { "debug": "^4.1.1", @@ -6418,9 +5645,9 @@ } }, "node_modules/mongodb-download-url/node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -6439,270 +5666,244 @@ "dev": true }, "node_modules/mongodb-runner": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-4.10.0.tgz", - "integrity": "sha512-6hE4nA4+LMBPwLMXr/jQNRNtUdQgfmZOJE/4u5JX952hdUa0lPc+26Y45PdgbdMbfCYUfZK1cOBObZOBmTdQ6Q==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.5.3.tgz", + "integrity": "sha512-26xVH/Z0nMrSvQX2xAU70VW2fAEhhywgnORnCllEsCHfuP064rvPKLGxl+m7sDh4vVxE1hY/MAyhbRKoy3xlIw==", "dev": true, "dependencies": { - "async": "^3.1.0", - "clui": "^0.3.6", - "debug": "^4.1.1", - "fs-extra": "^8.1.0", - "is-mongodb-running": "^1.0.1", - "lodash.defaults": "^4.2.0", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "mongodb": "^3.4.0", - "mongodb-dbpath": "^0.0.1", - "mongodb-tools": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0", - "mongodb-version-manager": "^1.5.0", - "untildify": "^4.0.0", - "which": "^2.0.1" + "@mongodb-js/mongodb-downloader": "^0.2.10", + "@mongodb-js/saslprep": "^1.1.4", + "debug": "^4.3.4", + "mongodb": "^6.3.0", + "mongodb-connection-string-url": "^3.0.0", + "yargs": "^17.7.2" }, "bin": { - "mongodb-runner": "bin/mongodb-runner.js" + "mongodb-runner": "bin/runner.js" } }, - "node_modules/mongodb-tools": { - "version": "1.2.0", - "resolved": "git+ssh://git@github.com/mongodb-js/mongodb-tools.git#0d1a90f49796c41f6d47c7c7999fe384014a16a0", - "integrity": "sha512-DNJJQYg1/VcE4gNP7zpKeWGIezwcpkI8XzG4YFL3WybY6cuKWMz3d1CIp3uKKEpva1qOHk2LI8mKWJX1Vpw4Sg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^2.2.0", - "lodash": "^4.17.12", - "mkdirp": "0.5.0", - "mongodb-core": "*", - "rimraf": "2.2.6" - } - }, - "node_modules/mongodb-tools/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/mongodb-runner/node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", "dev": true, "dependencies": { - "ms": "2.0.0" + "@types/webidl-conversions": "*" } }, - "node_modules/mongodb-tools/node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", - "dev": true - }, - "node_modules/mongodb-tools/node_modules/mkdirp": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", - "integrity": "sha512-xjjNGy+ry1lhtIKcr2PT6ok3aszhQfgrUDp4OZLHacgRgFmF6XR9XCOJVcXlVGQonIqXcK1DvqgKKQOPWYGSfw==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "node_modules/mongodb-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mongodb-tools/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/mongodb-tools/node_modules/rimraf": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", - "integrity": "sha512-33Fa/MIw/3F9KcDE/uJ2OuYUyxY+fkmw1c20DFnyhP7dfo2+BexeE1thjluPiJaG8sW6CcaqnTffwpRd4NAiTg==", - "dev": true, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/mongodb-version-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mongodb-version-list/-/mongodb-version-list-1.0.0.tgz", - "integrity": "sha512-F3kIABEMNjg3ZAX4SRbO1QPmhpP4NX2IgJq+lcUKidducTOVJafXJ+E+pMkgpU0xumC8QYbIZJ+8y4GZys9E4g==", - "dev": true, - "dependencies": { - "cheerio": "^0.22.0", - "debug": "^2.2.0", - "downcache": "^0.0.9", - "fs-extra": "^1.0.0", - "minimist": "^1.1.1", - "semver": "^5.0.1" - }, - "bin": { - "mongodb-version-list": "bin/mongodb-version-list.js" - } - }, - "node_modules/mongodb-version-list/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mongodb-version-list/node_modules/fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha512-VerQV6vEKuhDWD2HGOybV6v5I73syoc/cXAbKlgTC7M/oFVEtklWlp9QH2Ijw3IaWDOQcMkldSPa7zXy79Z/UQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - } - }, - "node_modules/mongodb-version-list/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/mongodb-version-list/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/mongodb-version-list/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/mongodb-version-manager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/mongodb-version-manager/-/mongodb-version-manager-1.5.0.tgz", - "integrity": "sha512-VHijlQXvQFnX/9MzfGePyBNr9qHLHRHg6sM2ChFO+05Htf6JY50WzvDWZmtXUNGXEor80fXxhswwDJevGlZkyA==", - "dev": true, - "dependencies": { - "ampersand-state": "^5.0.3", - "async": "^3.1.0", - "chalk": "^2.1.0", - "debug": ">= 2.6.9 < 3.0.0 || >= ^3.1.0", - "docopt": "^0.6.2", - "download": "^6.2.5", - "figures": "^3.2.0", - "fs-extra": "^8.1.0", - "get-mongodb-version": "^2.0.1", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.1.1", - "mongodb-download-url": "^1.0.0", - "mongodb-version-list": "^1.0.0", - "semver": "^5.3.0", - "tildify": "^2.0.0", - "untildify": "^4.0.0" - }, - "bin": { - "m": "bin/m.js", - "mongodb-version-manager": "bin/mongodb-version-manager.js" - } - }, - "node_modules/mongodb-version-manager/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mongodb-version-manager/node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/mongodb-version-manager/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/mongodb-runner/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/mongodb-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/mongodb-runner/node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dev": true, + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongodb-runner/node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dev": true, + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/mongodb-runner/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-runner/node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dev": true, + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mongodb-runner/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/mongodb-runner/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/mongodb-runner/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-runner/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb/node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/mongodb/node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongodb/node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/mongodb/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb/node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" } }, "node_modules/mongoose": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.2.1.tgz", - "integrity": "sha512-c2OOl+ch9NlmPeJw7UjSb2jHNjoOw1XXHyzwygIf4z1GmaBx1OYb8OYqHkYPivvEmfY/vUWZFCgePsDqZgFn2w==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.1.3.tgz", + "integrity": "sha512-a5MajZSDJiQgy0iQcR+MIpFe7zehGJI4doJ6Dh1MvnGh8/HNNhr5pn07RPA86KCTjP2vuKdffpFmvXxcHiUOjw==", "dependencies": { - "bson": "^5.3.0", + "bson": "^6.2.0", "kareem": "2.5.1", - "mongodb": "5.5.0", + "mongodb": "6.3.0", "mpath": "0.9.0", "mquery": "5.0.0", "ms": "2.1.3", "sift": "16.0.1" }, "engines": { - "node": ">=14.20.1" + "node": ">=16.20.1" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mongoose" } }, - "node_modules/mongoose/node_modules/bson": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.3.0.tgz", - "integrity": "sha512-ukmCZMneMlaC5ebPHXIkP8YJzNl5DC41N5MAIvKDqLggdao342t4McltoJBQfQya/nHBWAcSsYRqlXPoQkTJag==", - "engines": { - "node": ">=14.20.1" - } - }, - "node_modules/mongoose/node_modules/mongodb": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.5.0.tgz", - "integrity": "sha512-XgrkUgAAdfnZKQfk5AsYL8j7O99WHd4YXPxYxnh8dZxD+ekYWFRA3JktUsBnfg+455Smf75/+asoU/YLwNGoQQ==", - "dependencies": { - "bson": "^5.3.0", - "mongodb-connection-string-url": "^2.6.0", - "socks": "^2.7.1" - }, - "engines": { - "node": ">=14.20.1" - }, - "optionalDependencies": { - "saslprep": "^1.0.3" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.201.0", - "mongodb-client-encryption": ">=2.3.0 <3", - "snappy": "^7.2.2" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - } - } - }, "node_modules/mongoose/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -6838,15 +6039,6 @@ "node": ">= 6.13.0" } }, - "node_modules/node-netstat": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/node-netstat/-/node-netstat-1.8.0.tgz", - "integrity": "sha512-P1a5Sh9FfjTXxI6hC9q/Nqre8kT63FQxBCr1qz5ffk76EkQBH62+XEhIhlzfz6Bz+FRwOFqidW2FDGXnOXvyJQ==", - "dev": true, - "dependencies": { - "is-wsl": "^1.1.0" - } - }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -6921,9 +6113,9 @@ } }, "node_modules/nodemon/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -6953,39 +6145,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "dev": true, - "dependencies": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npmlog": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", - "integrity": "sha512-DaL6RTb8Qh4tMe2ttPT1qWccETy2Vi5/8p+htMpLBeXJTr2CAqnF5WQtSP2eFpvaNbhLZ5uilDb98mRm4Q+lZQ==", - "dev": true, - "dependencies": { - "ansi": "~0.3.1", - "are-we-there-yet": "~1.1.2", - "gauge": "~1.2.5" - } - }, - "node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dev": true, - "dependencies": { - "boolbase": "~1.0.0" - } - }, "node_modules/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -7210,46 +6369,6 @@ "fn.name": "1.x.x" } }, - "node_modules/openai": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.8.0.tgz", - "integrity": "sha512-CnLZvHi2x4pIoGAWCaj3jHi1a6NA4oFBL6mJDSXkIR5A/wv6lven7uL2gxMevjGBLA7OqYqis3Z2PMluiGauVw==", - "dependencies": { - "@types/node": "^18.11.18", - "@types/node-fetch": "^2.6.4", - "abort-controller": "^3.0.0", - "agentkeepalive": "^4.2.1", - "digest-fetch": "^1.3.0", - "form-data-encoder": "1.7.2", - "formdata-node": "^4.3.2", - "node-fetch": "^2.6.7" - }, - "bin": { - "openai": "bin/cli" - } - }, - "node_modules/openai/node_modules/@types/node": { - "version": "18.17.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.18.tgz", - "integrity": "sha512-/4QOuy3ZpV7Ya1GTRz5CYSz3DgkKpyUptXuQ5PPce7uuyJAOR7r9FhkmxJfvcNUXyklbC63a+YvB3jxy7s9ngw==" - }, - "node_modules/openai/node_modules/form-data-encoder": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", - "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" - }, - "node_modules/optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "dev": true, - "dependencies": { - "require-at": "^1.0.6" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -7266,36 +6385,6 @@ "node": ">= 0.8.0" } }, - "node_modules/p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-event": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz", - "integrity": "sha512-hV1zbA7gwqPVFcapfeATaNjQ3J0NuzorHPyG8GPL9g/Y/TplWVBVoCKCXL6Ej2zscrCEv195QNWJXuBH6XZuzA==", - "dev": true, - "dependencies": { - "p-timeout": "^1.1.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -7336,18 +6425,6 @@ "node": ">=8" } }, - "node_modules/p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA==", - "dev": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -7394,22 +6471,22 @@ } }, "node_modules/parse": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-4.1.0.tgz", - "integrity": "sha512-s0Ti+nWrKWj9DlFcmkEE05fGwa/K5ycZSdqCz01F8YL7Hevqv4WLXAmYGOwzq5UJSZ005seKgb20KwVwLdy/Zg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/parse/-/parse-4.3.1.tgz", + "integrity": "sha512-ypLPhMPFsJY+C2MXg6HdrVu6ielsL+kUjcSqh7J01lPC5oBuLh70F9YMQSw51QBocEeMSVgB7eUorFOH+MkVpA==", "dependencies": { - "@babel/runtime-corejs3": "7.21.0", - "idb-keyval": "6.2.0", + "@babel/runtime-corejs3": "7.23.2", + "idb-keyval": "6.2.1", "react-native-crypto-js": "1.0.0", - "uuid": "9.0.0", - "ws": "8.12.0", + "uuid": "9.0.1", + "ws": "8.13.0", "xmlhttprequest": "1.8.0" }, "engines": { "node": ">=14.21.0 <17 || >=18 <20" }, "optionalDependencies": { - "crypto-js": "4.1.1" + "crypto-js": "4.2.0" } }, "node_modules/parse-dbtool": { @@ -7755,6 +6832,18 @@ "semver": "bin/semver.js" } }, + "node_modules/parse-server/node_modules/@babel/runtime-corejs3": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz", + "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==", + "dependencies": { + "core-js-pure": "^3.25.1", + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/parse-server/node_modules/@graphql-tools/merge": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.1.tgz", @@ -7829,6 +6918,14 @@ "node": ">=0.10" } }, + "node_modules/parse-server/node_modules/idb-keyval": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz", + "integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==", + "dependencies": { + "safari-14-idb-fix": "^3.0.0" + } + }, "node_modules/parse-server/node_modules/lru-cache": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", @@ -7859,6 +6956,45 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/parse-server/node_modules/parse": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-4.1.0.tgz", + "integrity": "sha512-s0Ti+nWrKWj9DlFcmkEE05fGwa/K5ycZSdqCz01F8YL7Hevqv4WLXAmYGOwzq5UJSZ005seKgb20KwVwLdy/Zg==", + "dependencies": { + "@babel/runtime-corejs3": "7.21.0", + "idb-keyval": "6.2.0", + "react-native-crypto-js": "1.0.0", + "uuid": "9.0.0", + "ws": "8.12.0", + "xmlhttprequest": "1.8.0" + }, + "engines": { + "node": ">=14.21.0 <17 || >=18 <20" + }, + "optionalDependencies": { + "crypto-js": "4.1.1" + } + }, + "node_modules/parse-server/node_modules/parse/node_modules/ws": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", + "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/parse-server/node_modules/path-to-regexp": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", @@ -7911,35 +7047,25 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/parse-server/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/parse-server/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/parse/node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "optional": true + }, "node_modules/parse/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -8207,12 +7333,12 @@ } }, "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/pinkie": { @@ -8348,6 +7474,18 @@ "node": ">=0.10.0" } }, + "node_modules/posthog-node": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-3.6.2.tgz", + "integrity": "sha512-tVIaShR3SxBx17AlAUS86jQTweKuJIFRedBB504fCz7YPnXJTYSrVcUHn5IINE2wu4jUQimQK6ihQr90Djrdrg==", + "dependencies": { + "axios": "^1.6.2", + "rusha": "^0.8.14" + }, + "engines": { + "node": ">=15.0.0" + } + }, "node_modules/precond": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", @@ -8364,15 +7502,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/prettier": { "version": "2.8.7", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", @@ -8413,12 +7542,6 @@ "asap": "~2.0.6" } }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -8436,15 +7559,6 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "node_modules/ps-node": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz", - "integrity": "sha512-w7QJhUTbu70hpDso0YXDRNKCPNuchV8UTUZsAv0m7Qj5g85oHOJfr9drA1EjvK4nQK/bG8P97W4L6PJ3IQLoOA==", - "dev": true, - "dependencies": { - "table-parser": "^0.1.3" - } - }, "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -8731,43 +7845,6 @@ "uuid": "bin/uuid" } }, - "node_modules/require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "dev": true, - "dependencies": { - "resolve-from": "^2.0.0", - "semver": "^5.1.0" - } - }, - "node_modules/require_optional/node_modules/resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require_optional/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8804,6 +7881,11 @@ "node": ">=0.10.0" } }, + "node_modules/rfc4648": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.3.tgz", + "integrity": "sha512-MjOWxM065+WswwnmNONOT+bD1nXzY9Km6u3kzvnx8F8/HXGZdz3T6e6vZJ8Q/RIMUSp/nxqjH3GwvJDy8ijeQQ==" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -8840,6 +7922,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rusha": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", + "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==" + }, "node_modules/safari-14-idb-fix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/safari-14-idb-fix/-/safari-14-idb-fix-3.0.0.tgz", @@ -8914,9 +8001,9 @@ "dev": true }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -9090,30 +8177,6 @@ "npm": ">= 3.0.0" } }, - "node_modules/sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", - "dev": true, - "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sort-keys-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", - "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", - "dev": true, - "dependencies": { - "sort-keys": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -9127,7 +8190,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "optional": true, "dependencies": { "memory-pager": "^1.0.2" } @@ -9319,18 +8381,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/subscriptions-transport-ws": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.11.0.tgz", @@ -9386,13 +8436,21 @@ "node": ">=0.10.0" } }, - "node_modules/table-parser": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz", - "integrity": "sha512-LCYeuvqqoPII3lzzYaXKbC3Forb+d2u4bNwhk/9FlivuGRxPE28YEWAYcujeSlLLDlMfvy29+WPybFJZFiKMYg==", + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dev": true, "dependencies": { - "connected-domain": "^1.0.0" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, "node_modules/tar-stream": { @@ -9413,16 +8471,24 @@ "node": ">= 0.8.0" } }, - "node_modules/tar-stream/node_modules/bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -9453,58 +8519,6 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, - "node_modules/through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==", - "dev": true, - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "node_modules/through2/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true - }, - "node_modules/tildify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", - "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", @@ -9581,18 +8595,6 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -9753,15 +8755,6 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -9770,15 +8763,6 @@ "node": ">= 0.8" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", @@ -9830,44 +8814,11 @@ "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" }, - "node_modules/url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==", - "dev": true, - "dependencies": { - "prepend-http": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/url/node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" }, - "node_modules/user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==", - "dev": true, - "bin": { - "user-home": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -9897,7 +8848,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -10152,9 +9102,9 @@ } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "engines": { "node": ">=0.10.0" } @@ -10224,9 +9174,9 @@ } }, "node_modules/ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "engines": { "node": ">=10.0.0" }, diff --git a/apps/OpenSignServer/package.json b/apps/OpenSignServer/package.json index 4725d28d5..828ba66e9 100644 --- a/apps/OpenSignServer/package.json +++ b/apps/OpenSignServer/package.json @@ -19,23 +19,23 @@ }, "dependencies": { "aws-sdk": "^2.1475.0", - "axios": "1.3.5", + "axios": "1.6.7", "cors": "^2.8.5", "crypto": "^1.0.1", "dotenv": "^16.0.3", "express": "4.18.2", "express-sse": "^0.5.3", "form-data": "^4.0.0", + "generate-api-key": "^1.0.2", "jsonschema": "^1.4.1", "mailgun.js": "^9.3.0", - "mongoose": "^7.2.1", + "mongoose": "^8.1.3", "multer": "^1.4.5-lts.1", "multer-s3": "^2.10.0", "node-forge": "^1.3.1", "node-signpdf": "^1.5.1", "nodemailer": "^6.9.7", - "openai": "^4.8.0", - "parse": "4.1.0", + "parse": "4.3.1", "parse-dbtool": "^1.2.0", "parse-server": "6.3.1", "parse-server-api-mail-adapter": "^3.0.0", @@ -43,6 +43,7 @@ "parse-server-s3-adapter": "^1.2.0", "pdf-lib": "^1.16.0", "pdfkit": "^0.13.0", + "posthog-node": "^3.6.2", "razorpay": "^2.8.6", "request": "^2.88.2" }, @@ -51,7 +52,7 @@ "@babel/eslint-parser": "7.21.3", "eslint": "8.38.0", "jasmine": "4.6.0", - "mongodb-runner": "4.10.0", + "mongodb-runner": "5.5.3", "nodemon": "^2.0.22", "nyc": "15.1.0", "prettier": "2.8.7" diff --git a/apps/OpenSignServer/public/openapi.json b/apps/OpenSignServer/public/openapi.json new file mode 100644 index 000000000..de11c91e4 --- /dev/null +++ b/apps/OpenSignServer/public/openapi.json @@ -0,0 +1,934 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "OpenSign API v1", + "description": "This is API documentation for OpenSign API v1 based on the OpenAPI 3.1 specification. \n\nSome useful links:\n- [Official Website](https://www.opensignlabs.com)\n- [Github repo](https://github.com/opensignlabs/opensign)", + "termsOfService": "http://www.opensignlabs.com/terms/", + "contact": { + "email": "contact@opensignlabs.com" + }, + "license": { + "name": "AGPL 3.0", + "url": "http://github.com/opensignlabs/opensign/LICENSE" + }, + "version": "1.0.0" + }, + "externalDocs": { + "description": "Find out more about OpenSign", + "url": "http://docs.opensignlabs.com" + }, + "servers": [ + { + "url": "https://app.opensignlabs.com/api/v1" + } + ], + "tags": [ + { + "name": "OpenSign", + "description": "OpenSource DocuSign alternative", + "externalDocs": { + "description": "Find out more", + "url": "http://www.opensignlabs.com" + } + }, + { + "name": "Github repo", + "description": "Access the source code", + "externalDocs": { + "description": "Visit github", + "url": "http://github.com/opensignlabs/opensign" + } + }, + { + "name": "templates", + "description": "Operations about templates" + }, + { + "name": "users", + "description": "Operations about users" + }, + { + "name": "documents", + "description": "Operations about documents" + } + ], + "paths": { + "/getuser": { + "put": { + "tags": [ + "users" + ], + "summary": "Update an existing pet", + "description": "Update an existing pet by Id", + "operationId": "updatePet", + "requestBody": { + "description": "Update an existent pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + }, + "405": { + "description": "Validation exception" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "tags": [ + "users" + ], + "summary": "Add a new pet to the store", + "description": "Add a new pet to the store", + "operationId": "addPet", + "requestBody": { + "description": "Create a new pet in the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/documentlist": { + "get": { + "tags": [ + "documents" + ], + "summary": "Finds Pets by status", + "description": "Multiple status values can be provided with comma separated strings", + "operationId": "findPetsByStatus", + "parameters": [ + { + "name": "status", + "in": "query", + "description": "Status values that need to be considered for filter", + "required": false, + "explode": true, + "schema": { + "type": "string", + "default": "available", + "enum": [ + "available", + "pending", + "sold" + ] + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid status value" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/document/": { + "get": { + "tags": [ + "documents" + ], + "summary": "Finds Pets by tags", + "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", + "operationId": "findPetsByTags", + "parameters": [ + { + "name": "tags", + "in": "query", + "description": "Tags to filter by", + "required": false, + "explode": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "application/xml": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "400": { + "description": "Invalid tag value" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contact/{contact_id}": { + "get": { + "tags": [ + "contacts" + ], + "summary": "Find pet by ID", + "description": "Returns a single pet", + "operationId": "getPetById", + "parameters": [ + { + "name": "contact_id", + "in": "path", + "description": "ID of pet to return", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Pet not found" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "post": { + "tags": [ + "contacts" + ], + "summary": "Updates a pet in the store with form data", + "description": "", + "operationId": "updatePetWithForm", + "parameters": [ + { + "name": "contact_id", + "in": "path", + "description": "ID of pet that needs to be updated", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "name", + "in": "query", + "description": "Name of pet that needs to be updated", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "in": "query", + "description": "Status of pet that needs to be updated", + "schema": { + "type": "string" + } + } + ], + "responses": { + "405": { + "description": "Invalid input" + } + }, + "security": [ + { + "api_key": [] + } + ] + }, + "delete": { + "tags": [ + "contacts" + ], + "summary": "Deletes a pet", + "description": "delete a pet", + "operationId": "deletePet", + "parameters": [ + { + "name": "api_key", + "in": "header", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "contact_id", + "in": "path", + "description": "Pet id to delete", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid pet value" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/contactlist": { + "post": { + "tags": [ + "contacts" + ], + "summary": "uploads an image", + "description": "", + "operationId": "uploadFile", + "requestBody": { + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiResponse" + } + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/createdocument": { + "get": { + "tags": [ + "documents" + ], + "summary": "Returns pet inventories by status", + "description": "Returns a map of status codes to quantities", + "operationId": "getInventory", + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, + "/createtemplate": { + "post": { + "tags": [ + "templates" + ], + "summary": "Place an order for a pet", + "description": "Place a new order in the store", + "operationId": "placeOrder", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "405": { + "description": "Invalid input" + } + } + } + }, + "/template/{template_id}": { + "get": { + "tags": [ + "templates" + ], + "summary": "Find purchase order by ID", + "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.", + "operationId": "getOrderById", + "parameters": [ + { + "name": "template_id", + "in": "path", + "description": "ID of order that needs to be fetched", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Order" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Order" + } + } + } + }, + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + }, + "delete": { + "tags": [ + "templates" + ], + "summary": "Delete purchase order by ID", + "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "operationId": "deleteOrder", + "parameters": [ + { + "name": "template_id", + "in": "path", + "description": "ID of the order that needs to be deleted", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "400": { + "description": "Invalid ID supplied" + }, + "404": { + "description": "Order not found" + } + } + } + }, + "/templatelist": { + "post": { + "tags": [ + "templates" + ], + "summary": "Create user", + "description": "This can only be done by the logged in user.", + "operationId": "createUser", + "requestBody": { + "description": "Created user object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "responses": { + "default": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Order": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "petId": { + "type": "integer", + "format": "int64", + "example": 198772 + }, + "quantity": { + "type": "integer", + "format": "int32", + "example": 7 + }, + "shipDate": { + "type": "string", + "format": "date-time" + }, + "status": { + "type": "string", + "description": "Order Status", + "example": "approved", + "enum": [ + "placed", + "approved", + "delivered" + ] + }, + "complete": { + "type": "boolean" + } + }, + "xml": { + "name": "order" + } + }, + "Customer": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 100000 + }, + "username": { + "type": "string", + "example": "fehguy" + }, + "address": { + "type": "array", + "xml": { + "name": "addresses", + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Address" + } + } + }, + "xml": { + "name": "customer" + } + }, + "Address": { + "type": "object", + "properties": { + "street": { + "type": "string", + "example": "437 Lytton" + }, + "city": { + "type": "string", + "example": "Palo Alto" + }, + "state": { + "type": "string", + "example": "CA" + }, + "zip": { + "type": "string", + "example": "94301" + } + }, + "xml": { + "name": "address" + } + }, + "Category": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 1 + }, + "name": { + "type": "string", + "example": "Dogs" + } + }, + "xml": { + "name": "category" + } + }, + "User": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "username": { + "type": "string", + "example": "theUser" + }, + "firstName": { + "type": "string", + "example": "John" + }, + "lastName": { + "type": "string", + "example": "James" + }, + "email": { + "type": "string", + "example": "john@email.com" + }, + "password": { + "type": "string", + "example": "12345" + }, + "phone": { + "type": "string", + "example": "12345" + }, + "userStatus": { + "type": "integer", + "description": "User Status", + "format": "int32", + "example": 1 + } + }, + "xml": { + "name": "user" + } + }, + "Tag": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + }, + "xml": { + "name": "tag" + } + }, + "Pet": { + "required": [ + "name", + "photoUrls" + ], + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "example": 10 + }, + "name": { + "type": "string", + "example": "doggie" + }, + "category": { + "$ref": "#/components/schemas/Category" + }, + "photoUrls": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "type": "string", + "xml": { + "name": "photoUrl" + } + } + }, + "tags": { + "type": "array", + "xml": { + "wrapped": true + }, + "items": { + "$ref": "#/components/schemas/Tag" + } + }, + "status": { + "type": "string", + "description": "pet status in the store", + "enum": [ + "available", + "pending", + "sold" + ] + } + }, + "xml": { + "name": "pet" + } + }, + "ApiResponse": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "xml": { + "name": "##default" + } + } + }, + "requestBodies": { + "Pet": { + "description": "Pet object that needs to be added to the store", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + }, + "application/xml": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "UserArray": { + "description": "List of user object", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + } + } + } + } + }, + "securitySchemes": { + "api_key": { + "type": "apiKey", + "name": "X-Parse-ApiKey", + "in": "header" + } + } + } +} \ No newline at end of file diff --git a/microfrontends/SignDocuments/package-lock.json b/microfrontends/SignDocuments/package-lock.json index 7ff11f516..4d86ba058 100644 --- a/microfrontends/SignDocuments/package-lock.json +++ b/microfrontends/SignDocuments/package-lock.json @@ -9,16 +9,16 @@ "version": "0.1.0", "dependencies": { "@radix-ui/themes": "^1.1.2", - "@react-pdf/renderer": "^3.1.9", + "@react-pdf/renderer": "^3.3.8", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", - "axios": "^1.5.1", + "axios": "^1.6.0", "file-saver": "^2.0.5", "gh-pages": "^6.0.0", "mf-cra": "^0.0.5", "moment": "^2.30.1", - "parse": "^4.2.0", + "parse": "^4.3.1", "pdf-lib": "^1.17.1", "print-js": "^1.6.0", "radix-ui": "^1.0.1", @@ -32,7 +32,8 @@ "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-helmet": "^6.1.0", - "react-pdf": "^7.4.0", + "react-konva": "^18.2.10", + "react-pdf": "^7.7.0", "react-rnd": "^10.4.1", "react-router-dom": "^6.16.0", "react-scripts": "5.0.1", @@ -81,11 +82,11 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -171,11 +172,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -454,9 +455,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } @@ -504,9 +505,9 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -517,9 +518,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1977,22 +1978,17 @@ } }, "node_modules/@babel/runtime-corejs3": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz", - "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.23.2.tgz", + "integrity": "sha512-54cIh74Z1rp4oIjsHjqN+WM4fMyCBYe+LpZ9jWm51CZ1fbH3SkAzQD/3XLoNkjbJ7YEmjobLXyvQrFypRHOrXw==", "dependencies": { - "core-js-pure": "^3.25.1", - "regenerator-runtime": "^0.13.11" + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/runtime-corejs3/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, "node_modules/@babel/template": { "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", @@ -2007,19 +2003,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", - "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -2027,11 +2023,11 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -5111,114 +5107,116 @@ "integrity": "sha512-/RVXdLvJxLg4QKvMoM5WlwNR9ViO9z8B/qPcc+C0Sa/teJY7QG7kJ441DwzOjMYEY7GmU4dj5EcGHIkKZiQZCA==" }, "node_modules/@react-pdf/fns": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.0.1.tgz", - "integrity": "sha512-/vgecczzFYBQFkgUupH+sxXhLWQtBwdwCgweyh25XOlR4NZuaMD/UVUDl4loFHhRQqDMQq37lkTcchh7zzW6ug==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-2.2.1.tgz", + "integrity": "sha512-s78aDg0vDYaijU5lLOCsUD+qinQbfOvcNeaoX9AiE7+kZzzCo6B/nX+l48cmt9OosJmvZvE9DWR9cLhrhOi2pA==", "dependencies": { "@babel/runtime": "^7.20.13" } }, "node_modules/@react-pdf/font": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-2.3.6.tgz", - "integrity": "sha512-JYV+KmVyG2tPdpCK0/iFiBy1V7VHz2fETttKCgTRsLAo+w8RpM0pUGSAYROSuRl7yqbhiKGw/A24PYWhBReiOQ==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-2.4.4.tgz", + "integrity": "sha512-yjK5eSY+LcbxS0m+sOYln8GdgIbUgti4xjwf14kx8OSsOMJQJyHFALHMh2cLcKJR9yZeqVDo1FwCsY6gw1yCkg==", "dependencies": { "@babel/runtime": "^7.20.13", - "@react-pdf/types": "^2.3.3", + "@react-pdf/types": "^2.4.1", "cross-fetch": "^3.1.5", "fontkit": "^2.0.2", "is-url": "^1.2.4" } }, "node_modules/@react-pdf/image": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-2.2.1.tgz", - "integrity": "sha512-f0+cEP6pSBmk8eS/wP2tMsJcv2c7xjzca6cr1kwcapr1nzkPrh6fMdEeFl6kR2/HlJK/JoHo+xxlzRiQ8V2lrw==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-2.3.4.tgz", + "integrity": "sha512-IE34l7gfTdaxXe3XR9240xMZsFdxF1myIwmEWK28XoeTaucUPAUyOiNcFSGRT59vNuZVBuakYz3BlGGrkvAPVQ==", "dependencies": { "@babel/runtime": "^7.20.13", - "@react-pdf/png-js": "^2.2.0", - "cross-fetch": "^3.1.5" + "@react-pdf/png-js": "^2.3.1", + "cross-fetch": "^3.1.5", + "jay-peg": "^1.0.0" } }, "node_modules/@react-pdf/layout": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-3.6.2.tgz", - "integrity": "sha512-YD3/tDC6p5XPCXI04zH79bgX8LytjxEYfeCtsIzEFk0A2VvIHoRnRRDZ2OhZmO5g112ykyjY8vn9//ubTt+Ktg==", + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-3.11.2.tgz", + "integrity": "sha512-5EiHJ+Eb0odqnkWll9pWbTp+dwH1QRm7mOXDMiklqIWK98eI7e3cEae5Dgr0TtdnB7KgPW9Tvul2CwRJTwq54A==", "dependencies": { "@babel/runtime": "^7.20.13", - "@react-pdf/fns": "2.0.1", - "@react-pdf/image": "^2.2.1", - "@react-pdf/pdfkit": "^3.0.2", - "@react-pdf/primitives": "^3.0.0", - "@react-pdf/stylesheet": "^4.1.7", - "@react-pdf/textkit": "^4.2.0", - "@react-pdf/types": "^2.3.3", - "@react-pdf/yoga": "^4.1.2", + "@react-pdf/fns": "2.2.1", + "@react-pdf/image": "^2.3.4", + "@react-pdf/pdfkit": "^3.1.6", + "@react-pdf/primitives": "^3.1.1", + "@react-pdf/stylesheet": "^4.2.4", + "@react-pdf/textkit": "^4.4.1", + "@react-pdf/types": "^2.4.1", "cross-fetch": "^3.1.5", - "emoji-regex": "^10.2.1", - "queue": "^6.0.1" + "emoji-regex": "^10.3.0", + "queue": "^6.0.1", + "yoga-layout": "^2.0.1" } }, "node_modules/@react-pdf/layout/node_modules/emoji-regex": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", - "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==" + "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/@react-pdf/pdfkit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-3.0.2.tgz", - "integrity": "sha512-+m5rwNCwyEH6lmnZWpsQJvdqb6YaCCR0nMWrc/KKDwznuPMrGmGWyNxqCja+bQPORcHZyl6Cd/iFL0glyB3QGw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-3.1.6.tgz", + "integrity": "sha512-U96VVhphniDBsLbmeJHgEml15nng8cr90mmEfPATh98gsqg6wev0avBr4k9XPjLdaN1f2xTXD4VdlaMYJZ+n7Q==", "dependencies": { "@babel/runtime": "^7.20.13", - "@react-pdf/png-js": "^2.2.0", + "@react-pdf/png-js": "^2.3.1", "browserify-zlib": "^0.2.0", - "crypto-js": "^4.0.0", + "crypto-js": "^4.2.0", "fontkit": "^2.0.2", + "jay-peg": "^1.0.0", "vite-compatible-readable-stream": "^3.6.1" } }, "node_modules/@react-pdf/png-js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-2.2.0.tgz", - "integrity": "sha512-csZU5lfNW73tq7s7zB/1rWXGro+Z9cQhxtsXwxS418TSszHUiM6PwddouiKJxdGhbVLjRIcuuFVa0aR5cDOC6w==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-2.3.1.tgz", + "integrity": "sha512-pEZ18I4t1vAUS4lmhvXPmXYP4PHeblpWP/pAlMMRkEyP7tdAeHUN7taQl9sf9OPq7YITMY3lWpYpJU6t4CZgZg==", "dependencies": { "browserify-zlib": "^0.2.0" } }, "node_modules/@react-pdf/primitives": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-3.0.1.tgz", - "integrity": "sha512-0HGcknrLNwyhxe+SZCBL29JY4M85mXKdvTZE9uhjNbADGgTc8wVnkc5+e4S/lDvugbVISXyuIhZnYwtK9eDnyQ==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-3.1.1.tgz", + "integrity": "sha512-miwjxLwTnO3IjoqkTVeTI+9CdyDggwekmSLhVCw+a/7FoQc+gF3J2dSKwsHvAcVFM0gvU8mzCeTofgw0zPDq0w==" }, "node_modules/@react-pdf/render": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-3.2.6.tgz", - "integrity": "sha512-nsd1sleWMzBdrYGv5BwChPgVwoTZilfdiadE5wQiblFqG1C7EYINadalnEl1tjldKAzofSPBLKJbnSGR5r2lIQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-3.4.3.tgz", + "integrity": "sha512-9LL059vfwrK1gA0uIA4utpQ/pUH9EW/yia4bb7pCoARs8IlupY5UP265jgax15ua0p+MdUwShZzQ9rilu7kGsw==", "dependencies": { "@babel/runtime": "^7.20.13", - "@react-pdf/fns": "2.0.1", - "@react-pdf/primitives": "^3.0.0", - "@react-pdf/textkit": "^4.2.0", - "@react-pdf/types": "^2.3.3", + "@react-pdf/fns": "2.2.1", + "@react-pdf/primitives": "^3.1.1", + "@react-pdf/textkit": "^4.4.1", + "@react-pdf/types": "^2.4.1", "abs-svg-path": "^0.1.1", - "color-string": "^1.5.3", + "color-string": "^1.9.1", "normalize-svg-path": "^1.1.0", "parse-svg-path": "^0.1.2", "svg-arc-to-cubic-bezier": "^3.2.0" } }, "node_modules/@react-pdf/renderer": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-3.1.12.tgz", - "integrity": "sha512-y4H2ELH0okJP7+ig+uNjFAfuAanWiF3mxsKsE7ZBuhF4tabbMt9fX+pQ7qn4xrzEWX0vlso6s6ebkkeGdSGWzA==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-3.3.8.tgz", + "integrity": "sha512-wJESEZCNNbog4MxDjRgKtgdmyGm+lDce9cMX2THRs1Jltckq3M8N0yt/fkvGyB8nwiDPtEBOsz9JKlw5vLidbw==", "dependencies": { "@babel/runtime": "^7.20.13", - "@react-pdf/font": "^2.3.6", - "@react-pdf/layout": "^3.6.2", - "@react-pdf/pdfkit": "^3.0.2", - "@react-pdf/primitives": "^3.0.0", - "@react-pdf/render": "^3.2.6", - "@react-pdf/types": "^2.3.3", + "@react-pdf/font": "^2.4.4", + "@react-pdf/layout": "^3.11.2", + "@react-pdf/pdfkit": "^3.1.6", + "@react-pdf/primitives": "^3.1.1", + "@react-pdf/render": "^3.4.3", + "@react-pdf/types": "^2.4.1", "events": "^3.3.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", @@ -5226,7 +5224,7 @@ "scheduler": "^0.17.0" }, "peerDependencies": { - "react": "^16.8.6 || ^17.0.0 || ^18.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/@react-pdf/renderer/node_modules/scheduler": { @@ -5239,42 +5237,35 @@ } }, "node_modules/@react-pdf/stylesheet": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-4.1.7.tgz", - "integrity": "sha512-3n0Vg0XFszPyo0MpH75DkLRvsS4JOE0HzBH6XqFHDiquZDrC4mNgmMhZEbsOED+8xDGoCeVh8fLU3L6Tu0HWqg==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-4.2.4.tgz", + "integrity": "sha512-CgRfDzeMtnV0GL7zSn381NubmgwqKhFKcK1YrWX3azl/KWVh52jjFd3HWi6dvcETNT862mjWz5MnExe4WOBJXA==", "dependencies": { "@babel/runtime": "^7.20.13", - "@react-pdf/fns": "2.0.1", - "@react-pdf/types": "^2.3.3", - "color-string": "^1.5.3", + "@react-pdf/fns": "2.2.1", + "@react-pdf/types": "^2.4.1", + "color-string": "^1.9.1", "hsl-to-hex": "^1.0.0", "media-engine": "^1.0.3", "postcss-value-parser": "^4.1.0" } }, "node_modules/@react-pdf/textkit": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-4.2.0.tgz", - "integrity": "sha512-R90pEOW6NdhUx4p99iROvKmwB06IRYdXMhh0QcmUeoPOLe64ZdMfs3LZliNUWgI5fCmq71J+nv868i/EakFPDg==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-4.4.1.tgz", + "integrity": "sha512-Jl9wdTqIvJ5pX+vAGz0EOhP7ut5Two9H6CzTKo/YYPeD79cM2yTXF3JzTERBC28y7LR0Waq9D2LHQjI+b/EYUQ==", "dependencies": { "@babel/runtime": "^7.20.13", - "@react-pdf/fns": "2.0.1", + "@react-pdf/fns": "2.2.1", + "bidi-js": "^1.0.2", "hyphen": "^1.6.4", "unicode-properties": "^1.4.1" } }, "node_modules/@react-pdf/types": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.3.3.tgz", - "integrity": "sha512-I3BVu5vF0xxX6rvqZHt4gCjFAt6X+mak5bwYQyf6bm21IIMDXXBtgXqWEl1wosWizArox7fcN/XbEnysrf/8Dw==" - }, - "node_modules/@react-pdf/yoga": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@react-pdf/yoga/-/yoga-4.1.2.tgz", - "integrity": "sha512-OlMZkFrJDj4GyKZ70thiObwwPVZ52B7mlPyfzwa+sgwsioqHXg9nMWOO+7SQFNUbbOGagMUu0bCuTv+iXYZuaQ==", - "dependencies": { - "@babel/runtime": "^7.20.13" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.4.1.tgz", + "integrity": "sha512-w8pk7svhjVj5f7d7kjEGXSk26ffCqRSQcgWR4DwcFltNpSM18ZJmzmM6WrNeeP437y48LlykLnmGDA3oATakgw==" }, "node_modules/@remix-run/router": { "version": "1.9.0", @@ -6459,6 +6450,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.7", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.7.tgz", @@ -7458,9 +7457,9 @@ } }, "node_modules/axios": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", - "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -7828,6 +7827,14 @@ "node": ">= 8.0.0" } }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -8578,9 +8585,9 @@ } }, "node_modules/crypto-js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", - "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" }, "node_modules/crypto-random-string": { "version": "2.0.0", @@ -10817,9 +10824,9 @@ "integrity": "sha512-bHWEmjLsTjGP9gVs7P3Hyl+oY5NlMW8aTSPdTJ+X2GKt6glDctt9fUCLbRV+d/l8NDC40+FxMjp9WlTQXaQALw==" }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", @@ -11824,9 +11831,9 @@ } }, "node_modules/hyphen": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.6.6.tgz", - "integrity": "sha512-XtqmnT+b9n5MX+MsqluFAVTIenbtC25iskW0Z+jLd+awfhA+ZbWKWQMIvLJccGoa2bM1R6juWJ27cZxIFOmkWw==" + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.10.4.tgz", + "integrity": "sha512-SejXzIpv9gOVdDWXd4suM1fdF1k2dxZGvuTdkOVLoazYfK7O4DykIQbdrvuyG+EaTNlXAGhMndtKrhykgbt0gg==" }, "node_modules/iconv-lite": { "version": "0.6.3", @@ -11856,12 +11863,9 @@ "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" }, "node_modules/idb-keyval": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz", - "integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==", - "dependencies": { - "safari-14-idb-fix": "^3.0.0" - } + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", + "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" }, "node_modules/identity-obj-proxy": { "version": "3.0.0", @@ -12555,6 +12559,17 @@ "set-function-name": "^2.0.1" } }, + "node_modules/its-fine": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.1.1.tgz", + "integrity": "sha512-v1Ia1xl20KbuSGlwoaGsW0oxsw8Be+TrXweidxD9oT/1lAh6O3K3/GIM95Tt6WCiv6W+h2M7RB1TwdoAjQyyKw==", + "dependencies": { + "@types/react-reconciler": "^0.28.0" + }, + "peerDependencies": { + "react": ">=18.0" + } + }, "node_modules/jake": { "version": "10.8.7", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", @@ -12636,6 +12651,14 @@ "node": ">=8" } }, + "node_modules/jay-peg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jay-peg/-/jay-peg-1.0.1.tgz", + "integrity": "sha512-zBfjkGbuuNXk8JW+rEePpPEbRRjupS8q+5yPak7kjy3e2GvvNwsLle9okEFvfGyZA6HvtSSiYrVd1/jgnYebaQ==", + "dependencies": { + "restructure": "^3.0.0" + } + }, "node_modules/jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -14717,6 +14740,26 @@ "node": ">= 8" } }, + "node_modules/konva": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/konva/-/konva-9.3.2.tgz", + "integrity": "sha512-I4CFGVbWKpzgYi1I0pmoHz8iYfmGc/A61yfltzcuBHMFuBwDsR2VnQo4+eFQ1dGyEAmHcdvTumJ871KqkhuGng==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "peer": true + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -15775,14 +15818,14 @@ } }, "node_modules/parse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-4.2.0.tgz", - "integrity": "sha512-K8bWs0wM2qRhkSr6N16j8OvsF6Uallrynqng9e+tzR3RdKuB09vaJh48qrf9MbiJ1Ya4JZI7AfEHYF+ywEKs7Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/parse/-/parse-4.3.1.tgz", + "integrity": "sha512-ypLPhMPFsJY+C2MXg6HdrVu6ielsL+kUjcSqh7J01lPC5oBuLh70F9YMQSw51QBocEeMSVgB7eUorFOH+MkVpA==", "dependencies": { - "@babel/runtime-corejs3": "7.21.0", - "idb-keyval": "6.2.0", + "@babel/runtime-corejs3": "7.23.2", + "idb-keyval": "6.2.1", "react-native-crypto-js": "1.0.0", - "uuid": "9.0.0", + "uuid": "9.0.1", "ws": "8.13.0", "xmlhttprequest": "1.8.0" }, @@ -15790,7 +15833,7 @@ "node": ">=14.21.0 <17 || >=18 <20" }, "optionalDependencies": { - "crypto-js": "4.1.1" + "crypto-js": "4.2.0" } }, "node_modules/parse-json": { @@ -15816,9 +15859,13 @@ "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==" }, "node_modules/parse/node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -17960,6 +18007,36 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-konva": { + "version": "18.2.10", + "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-18.2.10.tgz", + "integrity": "sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "dependencies": { + "@types/react-reconciler": "^0.28.2", + "its-fine": "^1.1.1", + "react-reconciler": "~0.29.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "konva": "^8.0.1 || ^7.2.5 || ^9.0.0", + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -17984,18 +18061,19 @@ } }, "node_modules/react-pdf": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-7.4.0.tgz", - "integrity": "sha512-L2GIUc9eBLdb51DRqUe3zlkTmvOq7KQN5cKmgcrWdnWNwhYgrOGgpJQ3f56kG26G+B5GoasAHI6RjQrLfTjTnw==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-7.7.0.tgz", + "integrity": "sha512-704ObLnRDm5lixL4e6NXNLaincBHGNLo+NGdbO3rEXE963NlNzwLxFpmKcbdXHAMQL4rYJQWb1L0w5IL6y8Osw==", "dependencies": { "clsx": "^2.0.0", + "dequal": "^2.0.3", "make-cancellable-promise": "^1.3.1", "make-event-props": "^1.6.0", "merge-refs": "^1.2.1", "pdfjs-dist": "3.11.174", "prop-types": "^15.6.2", "tiny-invariant": "^1.0.0", - "tiny-warning": "^1.0.0" + "warning": "^4.0.0" }, "funding": { "url": "https://github.com/wojtekmaj/react-pdf?sponsor=1" @@ -18019,6 +18097,21 @@ "node": ">=6" } }, + "node_modules/react-reconciler": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz", + "integrity": "sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -18799,11 +18892,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safari-14-idb-fix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/safari-14-idb-fix/-/safari-14-idb-fix-3.0.0.tgz", - "integrity": "sha512-eBNFLob4PMq8JA1dGyFn6G97q3/WzNtFK4RnzT1fnLq+9RyrGknzYiM/9B12MnKAxuj1IXr7UKYtTNtjyKMBog==" - }, "node_modules/safe-array-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", @@ -20209,11 +20297,6 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -21789,6 +21872,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoga-layout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-2.0.1.tgz", + "integrity": "sha512-tT/oChyDXelLo2A+UVnlW9GU7CsvFMaEnd9kVFsaiCQonFAXd3xrHhkLYu+suwwosrAEQ746xBU+HvYtm1Zs2Q==" + }, "node_modules/zoom-level": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/zoom-level/-/zoom-level-2.5.0.tgz", diff --git a/microfrontends/SignDocuments/package.json b/microfrontends/SignDocuments/package.json index aa8f72a0b..a1a69abfc 100644 --- a/microfrontends/SignDocuments/package.json +++ b/microfrontends/SignDocuments/package.json @@ -5,16 +5,16 @@ "homepage": "./mfbuild", "dependencies": { "@radix-ui/themes": "^1.1.2", - "@react-pdf/renderer": "^3.1.9", + "@react-pdf/renderer": "^3.3.8", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", - "axios": "^1.5.1", + "axios": "^1.6.0", "file-saver": "^2.0.5", "gh-pages": "^6.0.0", "mf-cra": "^0.0.5", "moment": "^2.30.1", - "parse": "^4.2.0", + "parse": "^4.3.1", "pdf-lib": "^1.17.1", "print-js": "^1.6.0", "radix-ui": "^1.0.1", @@ -28,7 +28,8 @@ "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-helmet": "^6.1.0", - "react-pdf": "^7.4.0", + "react-konva": "^18.2.10", + "react-pdf": "^7.7.0", "react-rnd": "^10.4.1", "react-router-dom": "^6.16.0", "react-scripts": "5.0.1", @@ -42,6 +43,7 @@ "scripts": { "start": "mf-cra start", "build": "CI=false && PUBLIC_URL=./mfbuild BUILD_PATH='./mfbuild' mf-cra build && mv mfbuild ../../apps/OpenSign/public", + "docker-build": "CI=false && PUBLIC_URL=./mfbuild BUILD_PATH='./mfbuild' mf-cra build && mv mfbuild ../public", "test": "react-scripts test", "eject": "react-scripts eject" }, diff --git a/microfrontends/SignDocuments/src/Component/DebugUi.js b/microfrontends/SignDocuments/src/Component/DebugUi.js new file mode 100644 index 000000000..3423abd04 --- /dev/null +++ b/microfrontends/SignDocuments/src/Component/DebugUi.js @@ -0,0 +1,429 @@ +import React, { useEffect, useState } from "react"; +import RenderAllPdfPage from "./component/renderAllPdfPage"; +import "../css/./signature.css"; +import "../css/AddUser.css"; +import Title from "./component/Title"; +import ModalUi from "../premitives/ModalUi"; +import RenderDebugPdf from "./component/RenderDebugPdf"; +import { pdfjs } from "react-pdf"; +import Alert from "../premitives/Alert"; +import HandleError from "./component/HandleError"; +import { useWindowSize } from "../hook/useWindowSize"; + +function processDimensions(x, y, width, height) { + if (width < 0) { + x -= Math.abs(width); + width = Math.abs(width); + } + + if (height < 0) { + y -= Math.abs(height); + height = Math.abs(height); + } + + return { + x: Math.floor(x), + y: Math.floor(y), + width: Math.floor(width), + height: Math.floor(height) + }; +} +const DebugUi = () => { + const { width } = useWindowSize(); + const [pdf, setPdf] = useState(""); + const [isModal, setIsModal] = useState(true); + const [allPages, setAllPages] = useState(null); + const [pageNumber, setPageNumber] = useState(1); + const [pdfLoadFail, setPdfLoadFail] = useState({ + status: false, + type: "load" + }); + const [pdfDetails, setPdfDetails] = useState({ + name: "", + pdftype: "", + totalPages: "", + currentPage: 1, + x: 0, + y: 0, + base64: "" + }); + const [hoverCoordinates, setHoverCoordinates] = useState({ x: 0, y: 0 }); + const [pdfDimension, setPdfDimension] = useState({ width: 0, height: 0 }); + const [annotations, setAnnotations] = useState([]); + const [newAnnotation, setNewAnnotation] = useState([]); + const [copied, setCopied] = useState(false); + + useEffect(() => { + if (pdf && pdf.name) { + const fetchPdfMetadata = async () => { + try { + const pdfDataURL = URL.createObjectURL(pdf); // Convert File to data URL + console.log("pdfDataURL ", pdfDataURL); + const pdfInfo = await pdfjs.getDocument({ url: pdfDataURL }).promise; + const pdfType = await inferPdfType(pdfInfo); + setPdfDetails((prevDetails) => ({ + ...prevDetails, + pdftype: pdfType + })); + } catch (error) { + console.error("Error fetching PDF metadata:", error); + } + }; + + fetchPdfMetadata(); + } + }, [pdf]); + + const inferPdfType = async (pdf) => { + try { + const firstPage = await pdf.getPage(1); + const scale = 1; + const { width, height } = firstPage.getViewport({ scale }); + setPdfDimension({ width: width, height: height }); + + // Assuming a standard DPI of 72, you can adjust this value if needed + const dpi = 72; + + const widthInInches = width / dpi; + const heightInInches = height / dpi; + + const isA1 = widthInInches > 23.39 && heightInInches > 16.54; + const isA2 = widthInInches > 16.54 && heightInInches > 11.69; + const isA3 = widthInInches > 11.69 && heightInInches > 8.27; + const isA4 = widthInInches > 8.27 && heightInInches > 5.83; + const isLegal = widthInInches > 8.5 && heightInInches > 14; + const isLetter = widthInInches > 8.5 && heightInInches > 11; + const isLedger = widthInInches > 11 && heightInInches > 17; + + if (isA1) return "A1"; + if (isA2) return "A2"; + if (isA3) return "A3"; + if (isA4) return "A4"; + if (isLegal) return "Legal"; + if (isLetter) return "Letter"; + if (isLedger) return "Ledger"; + + return "Unknown"; + } catch (error) { + console.error("Error getting page dimensions:", error); + return "Unknown"; + } + }; + + const handleSubmit = (e) => { + e.preventDefault(); + setIsModal(false); + setPdfDetails((prevData) => ({ ...prevData, name: pdf?.name })); + }; + + //function for get pdf page details + const pageDetails = async ({ numPages }) => { + const load = { + status: true + }; + setPdfDetails((prevDetails) => ({ ...prevDetails, totalPages: numPages })); + setPdfLoadFail(load); + }; + + const handleMouseMoveDiv = (event) => { + setHoverCoordinates({ + x: event.nativeEvent.offsetX, + y: event.nativeEvent.offsetY + }); + }; + const handleMouseDown = (event) => { + if (newAnnotation.length === 0) { + const { x, y } = event.target.getStage().getPointerPosition(); + setNewAnnotation([ + { x, y, width: 0, height: 0, key: "0", page: pageNumber } + ]); + } + }; + + const handleMouseUp = (event) => { + if (newAnnotation.length === 1) { + const sx = newAnnotation[0].x; + const sy = newAnnotation[0].y; + const { x, y } = event.target.getStage().getPointerPosition(); + const result = processDimensions(sx, sy, x - sx, y - sy); + const annotationToAdd = { + ...result, + key: annotations.length + 1, + page: pageNumber + }; + annotations.push(annotationToAdd); + setNewAnnotation([]); + setAnnotations(annotations); + setPdfDetails((prevDetails) => ({ + ...prevDetails, + x: result.x, + y: result.y + })); + } + }; + + const handleMouseMove = (event) => { + if (newAnnotation.length === 1) { + const sx = newAnnotation[0].x; + const sy = newAnnotation[0].y; + const { x, y } = event.target.getStage().getPointerPosition(); + setNewAnnotation([ + { + x: sx, + y: sy, + width: x - sx, + height: y - sy, + page: pageNumber, + key: "0" + } + ]); + } + }; + + const annotationsToDraw = [...annotations, ...newAnnotation]; + + const handlePageLoadSuccess = (page) => { + setPdfDetails((prevDetails) => ({ + ...prevDetails, + currentPage: page.pageNumber + })); + }; + + const copytoclipboard = (text) => { + navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => { + setCopied(false); + }, 1500); // Reset copied state after 1.5 seconds + }; + const handleFileChange = (files) => { + const file = files[0]; + setPdf(file); + + if (file && file.type === "application/pdf") { + const reader = new FileReader(); + + reader.onloadend = () => { + const base64String = reader.result.split(",")[1]; + setPdfDetails((prevdata) => ({ ...prevdata, base64: base64String })); + }; + + reader.readAsDataURL(file); + } + }; + const handleDelete = (key) => { + const updateAnnotations = annotations.filter((x) => x.key !== key); + setAnnotations(updateAnnotations); + }; + return ( + <div> + {copied && <Alert type="success">Copied</Alert>} + <Title title={"Debug Pdf"} /> + {width < 800 ? ( + <HandleError handleError={"Debug PDF only availble for PC"} /> + ) : ( + <> + {!isModal && ( + <div className="signatureContainer"> + {/* this component used to render all pdf pages in left side */} + <RenderAllPdfPage + signPdfUrl={pdf} + allPages={allPages} + setAllPages={setAllPages} + setPageNumber={setPageNumber} + pageNumber={pageNumber} + /> + {/* pdf render view */} + <div> + <div data-tut="reactourThird"> + <RenderDebugPdf + pdfUrl={pdf} + pageDetails={pageDetails} + pageNumber={pageNumber} + setPdfLoadFail={setPdfLoadFail} + pdfLoadFail={pdfLoadFail} + handlePageLoadSuccess={handlePageLoadSuccess} + handleMouseMove={handleMouseMove} + handleMouseUp={handleMouseUp} + handleMouseDown={handleMouseDown} + hoverCoordinates={hoverCoordinates} + annotations={annotationsToDraw} + pdfDimension={pdfDimension} + handleMouseMoveDiv={handleMouseMoveDiv} + /> + </div> + </div> + <div style={{ backgroundColor: "white", width: 220 }}> + <div + style={{ + fontSize: 18, + fontWeight: 500, + padding: "10px 12px", + borderBottom: "1px solid grey" + }} + > + PDF details + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Name: {pdfDetails?.name} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Pdf type: {pdfDetails?.pdftype} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Total Pages: {pdfDetails?.totalPages} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Current Page: {pdfDetails?.currentPage} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Base64 : {pdfDetails?.base64.slice(0, 10)}... + <span + style={{ + borderRadius: 4, + padding: "3px 5px", + border: "1px solid gray", + fontSize: 12, + margin: 2, + cursor: "pointer" + }} + onClick={() => copytoclipboard(pdfDetails?.base64)} + > + <i className="fa-solid fa-copy"></i> + </span> + </div> + <div + style={{ + fontSize: 18, + fontWeight: 500, + padding: "10px 12px", + borderBottom: "1px solid grey" + }} + > + Last click + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + x co-ordinate: {pdfDetails?.x} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + y co-ordinate: {pdfDetails?.y} + </div> + + <div + style={{ + fontSize: 18, + fontWeight: 500, + padding: "10px 12px", + borderBottom: "1px solid grey", + borderTop: "1px solid grey" + }} + > + Annotation + </div> + <ul + style={{ + listStyle: "none", + padding: 10, + height: 500, + overflowY: "auto", + scrollbarWidth: 5 + }} + > + {annotations.map((coord, index) => ( + <li key={index}> + <span style={{ fontSize: 13, fontWeight: 500 }}>{`Box ${ + index + 1 + }:`}</span> + <code + style={{ + fontSize: 12, + color: "black", + cursor: "pointer" + }} + > + {` ["page":${coord?.page}, "x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}]`} + </code> + <div> + <span + style={{ + borderRadius: 4, + padding: "3px 5px", + border: "1px solid gray", + fontSize: 12, + margin: 2, + cursor: "pointer" + }} + onClick={() => + copytoclipboard( + `"page":${coord?.page}, "x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}` + ) + } + > + <i className="fa-solid fa-copy"></i> + </span> + <span + style={{ + borderRadius: 4, + padding: "3px 5px", + border: "1px solid gray", + fontSize: 12, + margin: 2, + cursor: "pointer" + }} + onClick={() => handleDelete(coord.key)} + > + <i className="fa-solid fa-trash-can"></i> + </span> + </div> + </li> + ))} + </ul> + </div> + </div> + )} + <ModalUi title={"Select PDF"} isOpen={isModal}> + <form onSubmit={handleSubmit} style={{ margin: "10px" }}> + <input + type="file" + onChange={(e) => handleFileChange(e.target.files)} + style={{ + width: "100%", + border: "1px solid grey", + borderRadius: "4px", + padding: "5px", + fontSize: 12 + }} + accept=".pdf" + required + /> + <div + style={{ borderTop: "1px solid grey", margin: "10px 0" }} + ></div> + <button + style={{ + background: "#32a3ac", + borderRadius: "2px", + boxShadow: + "0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18)", + border: "none", + textTransform: "uppercase", + fontSize: "13px", + fontWeight: "600", + padding: "0.375rem 0.75rem", + textAlign: "center", + color: "#ffffff", + outline: "none" + }} + type="submit" + > + Submit + </button> + </form> + </ModalUi> + </> + )} + </div> + ); +}; + +export default DebugUi; diff --git a/microfrontends/SignDocuments/src/Component/PdfRequestFiles.js b/microfrontends/SignDocuments/src/Component/PdfRequestFiles.js index 6442a6c8d..005cc4cb2 100644 --- a/microfrontends/SignDocuments/src/Component/PdfRequestFiles.js +++ b/microfrontends/SignDocuments/src/Component/PdfRequestFiles.js @@ -89,6 +89,7 @@ function PdfRequestFiles() { const [validateAlert, setValidateAlert] = useState(false); const [widgetsTour, setWidgetsTour] = useState(false); const [minRequiredCount, setminRequiredCount] = useState(); + const [sendInOrder, setSendInOrder] = useState(false); const divRef = useRef(null); const isMobile = window.innerWidth < 767; const rowLevel = @@ -191,6 +192,52 @@ function PdfRequestFiles() { checkAlreadySign.length > 0 ) { setAlreadySign(true); + } else { + const obj = documentData?.[0]; + setSendInOrder(obj?.SendinOrder || false); + if ( + obj && + obj.Signers && + obj.Signers.length > 0 && + obj.Placeholders && + obj.Placeholders.length > 0 + ) { + const params = { + event: "viewed", + body: { + objectId: documentData?.[0].objectId, + file: documentData?.[0]?.SignedUrl || documentData?.[0]?.URL, + name: documentData?.[0].Name, + note: documentData?.[0].Note || "", + description: documentData?.[0].Description || "", + signers: documentData?.[0].Signers?.map((x) => ({ + name: x?.Name, + email: x?.Email, + phone: x?.Phone + })), + viewedBy: jsonSender.email, + viewedAt: new Date(), + createdAt: documentData?.[0].createdAt + } + }; + + try { + await axios.post( + `${localStorage.getItem("baseUrl")}functions/callwebhook`, + params, + { + headers: { + "Content-Type": "application/json", + "X-Parse-Application-Id": + localStorage.getItem("parseAppId"), + sessiontoken: localStorage.getItem("accesstoken") + } + } + ); + } catch (err) { + console.log("Err ", err); + } + } } let signers = []; @@ -295,8 +342,36 @@ function PdfRequestFiles() { }); }; + const checkSendInOrder = () => { + if (sendInOrder) { + const index = pdfDetails?.[0].Signers.findIndex( + (x) => x.Email === jsonSender.email + ); + const newIndex = index - 1; + if (newIndex !== -1) { + const user = pdfDetails?.[0].Signers[newIndex]; + const isPrevUserSigned = + pdfDetails?.[0].AuditTrail && + pdfDetails?.[0].AuditTrail.some( + (x) => + x.UserPtr.objectId === user.objectId && x.Activity === "Signed" + ); + if (isPrevUserSigned) { + return true; + } else { + return false; + } + } else { + return true; + } + } else { + return true; + } + }; //function for embed signature or image url in pdf async function embedImages() { + const validateSigning = checkSendInOrder(); + if (validateSigning) { const checkUser = signerPos.filter( (data) => data.signerObjId === signerObjectId ); @@ -365,7 +440,8 @@ function PdfRequestFiles() { } else if (!checkboxExist && unSignUrlData && unSignUrlData.length > 0) { setUnSignedWidgetId(unSignUrlData[0].key); setWidgetsTour(true); - } else { + } + else { setIsUiLoading(true); const pngUrl = checkUser[0].placeHolder; // Load a PDFDocument from the existing PDF bytes @@ -375,16 +451,102 @@ function PdfRequestFiles() { const pdfDoc = await PDFDocument.load(existingPdfBytes, { ignoreEncryption: true }); + // let pdfBase64; + //checking if signature is only one then send image url in jpeg formate to server + // if (pngUrl.length === 1 && pngUrl[0].pos.length === 1) { + // if (isDocId) { + // try { + // pdfBase64 = await getBase64FromUrl(pdfUrl); + // } catch (err) { + // console.log(err); + // } + // } else { + // //embed document's object id to all pages in pdf document + // try { + // await embedDocId(pdfDoc, documentId, allPages); + // } catch (err) { + // console.log(err); + // } + // try { + // pdfBase64 = await pdfDoc.saveAsBase64({ + // useObjectStreams: false + // }); + // } catch (err) { + // console.log(err); + // } + // } + // for (let pngData of pngUrl) { + // const imgUrlList = pngData.pos; + // const pageNo = pngData.pageNumber; + // imgUrlList.map(async (data) => { + // //cheking signUrl is defau;t signature url of custom url + // let ImgUrl = data.SignUrl; + // const checkUrl = urlValidator(ImgUrl); + // //if default signature url then convert it in base 64 + // if (checkUrl) { + // ImgUrl = await getBase64FromIMG(ImgUrl + "?get"); + // } + // //function for called convert png signatre to jpeg in base 64 + // convertPNGtoJPEG(ImgUrl) + // .then((jpegBase64Data) => { + // const removeBase64Fromjpeg = "data:image/jpeg;base64,"; + // const newImgUrl = jpegBase64Data.replace( + // removeBase64Fromjpeg, + // "" + // ); + + // //function for call to embed signature in pdf and get digital signature pdf + // signPdfFun( + // newImgUrl, + // documentId, + // signerObjectId, + // pdfOriginalWidth, + // pngUrl, + // containerWH, + // setIsAlert, + // data, + // pdfBase64, + // pageNo + // ) + // .then((res) => { + // if (res && res.status === "success") { + // setPdfUrl(res.data); + // setIsSigned(true); + // setSignedSigners([]); + // setUnSignedSigners([]); + // getDocumentDetails(); + // } else { + // setIsAlert({ + // isShow: true, + // alertMessage: "something went wrong" + // }); + // } + // }) + // .catch((err) => { + // setIsAlert({ + // isShow: true, + // alertMessage: "something went wrong" + // }); + // }); + // }) + // .catch((error) => { + // console.error("Error:", error); + // }); + // }); + // } + // } + // //else if signature is more than one then embed all sign with the use of pdf-lib + // else if (pngUrl.length > 0 && pngUrl[0].pos.length > 0) { const flag = false; const extUserPtr = pdfDetails[0].ExtUserPtr; const HeaderDocId = extUserPtr?.HeaderDocId; //embed document's object id to all pages in pdf document if (!HeaderDocId) { - if (!isDocId) { - await embedDocId(pdfDoc, documentId, allPages); - } + if (!isDocId) { + await embedDocId(pdfDoc, documentId, allPages); } + } //embed multi signature in pdf const pdfBytes = await multiSignEmbed( pngUrl, @@ -393,7 +555,6 @@ function PdfRequestFiles() { flag, containerWH ); - //function for call to embed signature in pdf and get digital signature pdf try { const res = await signPdfFun( @@ -411,6 +572,88 @@ function PdfRequestFiles() { setSignedSigners([]); setUnSignedSigners([]); getDocumentDetails(); + if (sendInOrder) { + const index = pdfDetails?.[0].Signers.findIndex( + (x) => x.Email === jsonSender.email + ); + const newIndex = index + 1; + const user = pdfDetails?.[0].Signers[newIndex]; + if (user) { + let sendMail; + // console.log("pdfDetails", pdfDetails); + const expireDate = pdfDetails?.[0].ExpiryDate.iso; + const newDate = new Date(expireDate); + const localExpireDate = newDate.toLocaleDateString("en-US", { + day: "numeric", + month: "long", + year: "numeric" + }); + let sender = pdfDetails?.[0].ExtUserPtr.Email; + + try { + const imgPng = + "https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"; + let url = `${localStorage.getItem( + "baseUrl" + )}functions/sendmailv3/`; + const headers = { + "Content-Type": "application/json", + "X-Parse-Application-Id": + localStorage.getItem("parseAppId"), + sessionToken: localStorage.getItem("accesstoken") + }; + const serverUrl = localStorage.getItem("baseUrl"); + const newServer = serverUrl.replaceAll("/", "%2F"); + const objectId = user.objectId; + const serverParams = `${newServer}&${localStorage.getItem( + "parseAppId" + )}&${localStorage.getItem("_appName")}`; + + const hostUrl = + window.location.origin + "/loadmf/signmicroapp"; + let signPdf = `${hostUrl}/login/${pdfDetails?.[0].objectId}/${user.Email}/${objectId}/${serverParams}`; + const openSignUrl = + "https://www.opensignlabs.com/contact-us"; + const orgName = pdfDetails[0]?.ExtUserPtr.Company + ? pdfDetails[0].ExtUserPtr.Company + : ""; + const themeBGcolor = themeColor(); + let params = { + recipient: user.Email, + subject: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`, + from: sender, + + html: + "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'=> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" + + imgPng + + " height='50' style='padding: 20px,width:170px,height:40px' /></div> <div style=' padding: 2px;font-family: system-ui;background-color:" + + themeBGcolor + + ";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " + + pdfDetails?.[0].ExtUserPtr.Name + + " has requested you to review and sign <strong> " + + pdfDetails?.[0].Name + + "</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" + + sender + + "</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " + + orgName + + "</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expires on</td><td> </td> <td style='color:#626363;font-weight:bold'>" + + localExpireDate + + "</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" + + signPdf + + "> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " + + sender + + " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= " + + openSignUrl + + " target=_blank>here</a>.</p> </div></div></body> </html>" + }; + sendMail = await axios.post(url, params, { + headers: headers + }); + } catch (error) { + console.log("error", error); + } + } + } } else { setIsAlert({ isShow: true, @@ -424,7 +667,6 @@ function PdfRequestFiles() { }); } } - setIsSignPad(false); } else { setIsAlert({ @@ -432,8 +674,14 @@ function PdfRequestFiles() { alertMessage: "something went wrong" }); } + } else { + setIsAlert({ + isShow: true, + alertMessage: + "Please wait for your turn to sign this document, as it has been set up by the creator to be signed in a specific order; you'll be notified when it's your turn." + }); } - +} //function for update TourStatus const closeTour = async () => { setWidgetsTour(false); @@ -607,7 +855,7 @@ function PdfRequestFiles() { } } ) - .then((result) => { + .then(async (result) => { const res = result.data; if (res) { const currentDecline = { @@ -616,6 +864,40 @@ function PdfRequestFiles() { }; setIsDecline(currentDecline); setIsUiLoading(false); + const params = { + event: "declined", + body: { + objectId: pdfDetails?.[0].objectId, + file: pdfDetails?.[0]?.SignedUrl || pdfDetails?.[0]?.URL, + name: pdfDetails?.[0].Name, + note: pdfDetails?.[0].Note || "", + description: pdfDetails?.[0].Description || "", + signers: pdfDetails?.[0].Signers?.map((x) => ({ + name: x?.Name, + email: x?.Email, + phone: x?.Phone + })), + declinedBy: jsonSender.email, + declinedAt: new Date(), + createdAt: pdfDetails?.[0].createdAt + } + }; + + try { + await axios.post( + `${localStorage.getItem("baseUrl")}functions/callwebhook`, + params, + { + headers: { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + sessiontoken: localStorage.getItem("accesstoken") + } + } + ); + } catch (err) { + console.log("Err ", err); + } } }) .catch((err) => { diff --git a/microfrontends/SignDocuments/src/Component/TemplatePlaceholder.js b/microfrontends/SignDocuments/src/Component/TemplatePlaceholder.js index 0ece67960..761a7047b 100644 --- a/microfrontends/SignDocuments/src/Component/TemplatePlaceholder.js +++ b/microfrontends/SignDocuments/src/Component/TemplatePlaceholder.js @@ -667,7 +667,8 @@ const TemplatePlaceholder = () => { Signers: signers, Name: pdfDetails[0]?.Name || "", Note: pdfDetails[0]?.Note || "", - Description: pdfDetails[0]?.Description || "" + Description: pdfDetails[0]?.Description || "", + SendinOrder: pdfDetails[0]?.SendinOrder || false }; await axios @@ -725,7 +726,7 @@ const TemplatePlaceholder = () => { selector: '[data-tut="reactourFirst"]', content: () => ( <TourContentWithBtn - message={`Select a recipient from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.`} + message={`Select a role from this list to add a place-holder where he is supposed to sign.The placeholder will appear in the same colour as the recipient name once you drop it on the document.`} isChecked={handleDontShow} /> ), @@ -748,7 +749,7 @@ const TemplatePlaceholder = () => { selector: '[data-tut="reactourThird"]', content: () => ( <TourContentWithBtn - message={`Drag the placeholder for a recipient anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.`} + message={`Drag the placeholder for a role anywhere on the document.Remember, it will appear in the same colour as the name of the recipient for easy reference.`} isChecked={handleDontShow} /> ), @@ -1213,11 +1214,11 @@ const TemplatePlaceholder = () => { <ModalUi headerColor={"#dc3545"} isOpen={!IsReceipent} - title={"Receipent required"} + title={"Roles"} handleClose={() => setIsReceipent(true)} > <div style={{ height: "100%", padding: 20 }}> - <p>Please add receipent.</p> + <p>Please add a role</p> </div> </ModalUi> {/* this modal is used show send mail message and after send mail success message */} diff --git a/microfrontends/SignDocuments/src/Component/component/EditTemplate.js b/microfrontends/SignDocuments/src/Component/component/EditTemplate.js index 2236ca7b5..c69543bf1 100644 --- a/microfrontends/SignDocuments/src/Component/component/EditTemplate.js +++ b/microfrontends/SignDocuments/src/Component/component/EditTemplate.js @@ -7,7 +7,8 @@ const EditTemplate = ({ template, onSuccess }) => { const [formData, setFormData] = useState({ Name: template?.Name || "", Note: template?.Note || "", - Description: template?.Description || "" + Description: template?.Description || "", + SendinOrder: template?.SendinOrder ? `${template?.SendinOrder}` : "false" }); const handleStrInput = (e) => { @@ -22,7 +23,8 @@ const EditTemplate = ({ template, onSuccess }) => { const handleSubmit = async (e) => { e.preventDefault(); e.stopPropagation(); - const data = { ...formData }; + const isChecked = formData.SendinOrder === "true" ? true : false; + const data = { ...formData, SendinOrder: isChecked }; onSuccess(data); }; @@ -86,6 +88,45 @@ const EditTemplate = ({ template, onSuccess }) => { className="addUserInput" /> </div> + <div className="form-section"> + <label style={{ fontSize: 13 }}>Send In Order</label> + <div + style={{ + display: "flex", + alignItems: "center", + gap: 8, + marginLeft: 8, + marginBottom: 5 + }} + > + <input + type="radio" + value={"true"} + name="SendinOrder" + checked={formData.SendinOrder === "true"} + onChange={handleStrInput} + /> + <div style={{ fontSize: 12 }}>Yes</div> + </div> + <div + style={{ + display: "flex", + alignItems: "center", + gap: 8, + marginLeft: 8, + marginBottom: 5 + }} + > + <input + type="radio" + value={"false"} + name="SendinOrder" + checked={formData.SendinOrder === "false"} + onChange={handleStrInput} + /> + <div style={{ fontSize: 12 }}>No</div> + </div> + </div> {/* <SelectFolder onSuccess={handleFolder} folderCls={"contracts_Template"} /> */} <div className="buttoncontainer"> <button type="submit" className="submitbutton"> diff --git a/microfrontends/SignDocuments/src/Component/component/RenderDebugPdf.js b/microfrontends/SignDocuments/src/Component/component/RenderDebugPdf.js new file mode 100644 index 000000000..89ddd03f5 --- /dev/null +++ b/microfrontends/SignDocuments/src/Component/component/RenderDebugPdf.js @@ -0,0 +1,85 @@ +import React from "react"; +import { Document, Page, pdfjs } from "react-pdf"; +import { Stage, Layer, Rect } from "react-konva"; +const RenderDebugPdf = (props) => { + pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; + + return ( + <div> + <div + style={{ + position: "sticky", + top: 0, + padding: 10, + zIndex: 1, + backgroundColor: "white", + border: "1px solid grey", + margin: "5px 0" + }} + > + {`Co-ordinates: X - ${props.hoverCoordinates.x}, Y - ${props.hoverCoordinates.y}`} + </div> + <div + style={{ + flex: 1, + position: "relative", + border: "1px solid grey", + overflow: "auto" + }} + onMouseMove={props.handleMouseMoveDiv} + > + <Document + onLoadError={(e) => { + const load = { + status: false, + type: "failed" + }; + props.setPdfLoadFail(load); + }} + loading={"Loading Document.."} + onLoadSuccess={props.pageDetails} + ref={props.pdfRef} + file={props.pdfUrl} + > + <Page + onLoadSuccess={props.handlePageLoadSuccess} + pageNumber={props.pageNumber} + renderAnnotationLayer={false} + renderTextLayer={false} + onGetAnnotationsError={(error) => { + console.log("annotation error", error); + }} + /> + </Document> + + <Stage + onMouseMove={props.handleMouseMove} + onMouseDown={props.handleMouseDown} + onMouseUp={props.handleMouseUp} + width={props.pdfDimension.width} + height={props.pdfDimension.height} + style={{ position: "absolute", top: 0, left: 0 }} + > + <Layer> + {props.annotations + .filter((value) => value.page === props.pageNumber) + .map((value) => { + return ( + <Rect + x={value.x} + y={value.y} + width={value.width} + height={value.height} + fill="transparent" + stroke="black" + /> + ); + })} + </Layer> + </Stage> + </div> + </div> + ); +}; + +export default RenderDebugPdf; diff --git a/microfrontends/SignDocuments/src/Component/component/fieldsComponent.js b/microfrontends/SignDocuments/src/Component/component/fieldsComponent.js index a2d244c89..4cc1ec4ce 100644 --- a/microfrontends/SignDocuments/src/Component/component/fieldsComponent.js +++ b/microfrontends/SignDocuments/src/Component/component/fieldsComponent.js @@ -379,7 +379,7 @@ function FieldsComponent({ )} {isSignersModal && ( <ModalUi - title={"Recipients"} + title={"Roles"} isOpen={isSignersModal} handleClose={handleModal} > @@ -407,7 +407,7 @@ function FieldsComponent({ textAlign: "center" }} > - Please add Recipient + Please add a role </div> )} </ModalUi> diff --git a/microfrontends/SignDocuments/src/Component/placeHolderSign.js b/microfrontends/SignDocuments/src/Component/placeHolderSign.js index 30770e9af..4e9c86b57 100644 --- a/microfrontends/SignDocuments/src/Component/placeHolderSign.js +++ b/microfrontends/SignDocuments/src/Component/placeHolderSign.js @@ -99,6 +99,7 @@ function PlaceHolderSign() { const [isCheckbox, setIsCheckbox] = useState(false); const [isNameModal, setIsNameModal] = useState(false); const [widgetName, setWidgetName] = useState(false); + const [mailStatus, setMailStatus] = useState(""); const color = [ "#93a3db", "#e6c3db", @@ -759,8 +760,11 @@ function PlaceHolderSign() { year: "numeric" }); let sender = pdfDetails?.[0].ExtUserPtr.Email; - const signerMail = signersdata; + let signerMail = signersdata.slice(); + if (pdfDetails?.[0]?.SendinOrder && pdfDetails?.[0]?.SendinOrder === true) { + signerMail.splice(1); + } for (let i = 0; i < signerMail.length; i++) { try { const imgPng = @@ -789,7 +793,6 @@ function PlaceHolderSign() { recipient: signerMail[i].Email, subject: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`, from: sender, - html: "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'=> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" + imgPng + @@ -820,6 +823,72 @@ function PlaceHolderSign() { } if (sendMail.data.result.status === "success") { + setMailStatus("success"); + const signers = signersdata?.map((x) => { + return { + __type: "Pointer", + className: "contracts_Contactbook", + objectId: x.objectId + }; + }); + const addExtraDays = pdfDetails[0]?.TimeToCompleteDays + ? pdfDetails[0].TimeToCompleteDays + : 15; + const currentUser = signersdata.find((x) => x.Email === currentId); + setCurrentId(currentUser?.objectId); + let updateExpiryDate, data; + updateExpiryDate = new Date(); + updateExpiryDate.setDate(updateExpiryDate.getDate() + addExtraDays); + + try { + if (updateExpiryDate) { + data = { + Placeholders: signerPos, + SignedUrl: pdfDetails[0].URL, + Signers: signers, + ExpiryDate: { + iso: updateExpiryDate, + __type: "Date" + } + }; + } else { + data = { + Placeholders: signerPos, + SignedUrl: pdfDetails[0].URL, + Signers: signers + }; + } + + await axios + .put( + `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( + "_appName" + )}_Document/${documentId}`, + data, + { + headers: { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + "X-Parse-Session-Token": localStorage.getItem("accesstoken") + } + } + ) + .then((result) => { + setIsSend(true); + setIsMailSend(true); + const loadObj = { + isLoad: false + }; + setIsLoading(loadObj); + }) + .catch((err) => { + console.log("axois err ", err); + }); + } catch (e) { + console.log("error", e); + } + } else { + setMailStatus("failed"); const signers = signersdata?.map((x) => { return { __type: "Pointer", @@ -1370,7 +1439,11 @@ function PlaceHolderSign() { }} > <div style={{ height: "100%", padding: 20 }}> - <p>You have successfully sent mails to all recipients!</p> + {mailStatus === "success" ? ( + <p>You have successfully sent mails to all recipients!</p> + ) : ( + <p>Please setup mail adapter to send mail!</p> + )} {currentId && ( <p>Do you want to sign documents right now ?</p> )} diff --git a/microfrontends/SignDocuments/src/Routes.js b/microfrontends/SignDocuments/src/Routes.js index 1b1cba4d5..117ea04fe 100644 --- a/microfrontends/SignDocuments/src/Routes.js +++ b/microfrontends/SignDocuments/src/Routes.js @@ -10,6 +10,7 @@ import LegaDrive from "./Component/LegaDrive/LegaDrive"; import PageNotFound from "./Component/PageNotFound"; import TemplatePlaceHolder from "./Component/TemplatePlaceholder"; import Parse from "parse"; +import DebugUi from "./Component/DebugUi"; Parse.serverURL = localStorage.getItem("baseUrl"); Parse.initialize(localStorage.getItem("parseAppId")); // `AppRoutes` is used to define route path of app and @@ -50,6 +51,7 @@ function AppRoutes() { <Route path="/legadrive" element={<LegaDrive />} /> {/* Page Not Found */} <Route path="/template/:templateId" element={<TemplatePlaceHolder />} /> + <Route path="/debugpdf" element={<DebugUi />} /> <Route path="*" element={<PageNotFound />} /> </Routes> </div> diff --git a/microfrontends/SignDocuments/src/hook/useWindowSize.js b/microfrontends/SignDocuments/src/hook/useWindowSize.js new file mode 100644 index 000000000..0c84d6f13 --- /dev/null +++ b/microfrontends/SignDocuments/src/hook/useWindowSize.js @@ -0,0 +1,25 @@ +import { useEffect, useState } from "react"; + +export function useWindowSize() { + const [size, setSize] = useState({ + width: 0, + height: 0 + }); + + const onResize = () => { + setSize({ + width: window.innerWidth, + height: window.innerHeight + }); + }; + + useEffect(() => { + onResize(); + window.addEventListener("resize", onResize); + return () => { + window.removeEventListener("resize", onResize); + }; + }, []); + + return size; +} diff --git a/microfrontends/SignDocuments/src/premitives/Alert.js b/microfrontends/SignDocuments/src/premitives/Alert.js index 72e3d1458..0f10cf3c8 100644 --- a/microfrontends/SignDocuments/src/premitives/Alert.js +++ b/microfrontends/SignDocuments/src/premitives/Alert.js @@ -5,20 +5,47 @@ const Alert = ({ children, type }) => { function theme(color) { switch (color) { case "success": - return "border-[#c3e6cb] bg-[#d4edda] text-[#155724]"; + return { + border: `1px solid #c3e6cb`, // Border color + backgroundColor: "#d4edda", // Background color + color: "#155724" // Text color + }; + case "info": - return "border-[#adcdeb] bg-[#c1daf0] text-[#153756]"; + return { + border: `1px solid #adcdeb`, // Border color + backgroundColor: "#c1daf0", // Background color + color: "#153756" // Text color + }; case "danger": - return "border-[#f0a8a8] bg-[#f4bebe] text-[#c42121]"; + return { + border: `1px solid #f0a8a8`, // Border color + backgroundColor: "#f4bebe", // Background color + color: "#c42121" // Text color + }; default: - return "border-[#d6d6d6] bg-[#d9d9d9] text-[#575757]"; + return { + border: `1px solid #d6d6d6`, // Border color + backgroundColor: "#d9d9d9", // Background color + color: "#575757" // Text color + }; } } return ( <> {children && ( <div - className={`z-40 fixed top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm ${textcolor} rounded py-[.75rem] px-[1.25rem] `} + style={{ + ...textcolor, + position: "fixed", + top: "20px", + left: "50%", + transform: "translateX(-50%)", + fontSize: "0.875rem", // Corresponds to text-sm in Tailwind CSS + borderRadius: "5px", // Rounded corners + padding: "10px 15px", // Padding + zIndex: 40 + }} > {children} </div> diff --git a/microfrontends/SignDocuments/src/premitives/GuestSign.js b/microfrontends/SignDocuments/src/premitives/GuestSign.js new file mode 100644 index 000000000..99bc0e11f --- /dev/null +++ b/microfrontends/SignDocuments/src/premitives/GuestSign.js @@ -0,0 +1,1002 @@ +import React, { useState, useRef, useEffect } from "react"; +import { themeColor } from "../utils/ThemeColor/backColor"; +import { PDFDocument } from "pdf-lib"; +import "../css/signature.css"; +import axios from "axios"; +import loader from "../assests/loader2.gif"; +import { DndProvider } from "react-dnd"; +import { HTML5Backend } from "react-dnd-html5-backend"; +import { useParams } from "react-router-dom"; +import SignPad from "../Component/component/signPad"; +import RenderAllPdfPage from "../Component/component/renderAllPdfPage"; +import { + contractDocument, + multiSignEmbed, + embedDocId, + pdfNewWidthFun, + signPdfFun, + onImageSelect, + onSaveSign, + onSaveImage, + addDefaultSignatureImg +} from "../utils/Utils"; +import Loader from "../Component/component/loader"; +import HandleError from "../Component/component/HandleError"; +import Nodata from "../Component/component/Nodata"; +import Header from "../Component/component/header"; +import RenderPdf from "../Component/component/renderPdf"; +import CustomModal from "../Component/component/CustomModal"; +import Title from "../Component/component/Title"; +import DefaultSignature from "../Component/component/defaultSignature"; +import ModalUi from "./ModalUi"; + +function GuestSign() { + const { docId } = useParams(); + const [pdfDetails, setPdfDetails] = useState([]); + const [signedSigners, setSignedSigners] = useState([]); + const [unsignedSigners, setUnSignedSigners] = useState([]); + const [isSignPad, setIsSignPad] = useState(false); + const [pdfUrl, setPdfUrl] = useState(); + const [allPages, setAllPages] = useState(null); + const numPages = 1; + const [pageNumber, setPageNumber] = useState(1); + const [image, setImage] = useState(null); + const [isImageSelect, setIsImageSelect] = useState(false); + const [signature, setSignature] = useState(); + const [isStamp, setIsStamp] = useState(false); + const [signKey, setSignKey] = useState(); + const [imgWH, setImgWH] = useState({}); + const imageRef = useRef(null); + const [handleError, setHandleError] = useState(); + const [isLoading, setIsLoading] = useState({ + isLoad: true, + message: "This might take some time" + }); + const [defaultSignImg, setDefaultSignImg] = useState(); + const [isDocId, setIsDocId] = useState(false); + const [pdfNewWidth, setPdfNewWidth] = useState(); + const [pdfOriginalWidth, setPdfOriginalWidth] = useState(); + const [signerPos, setSignerPos] = useState([]); + const [noData, setNoData] = useState(false); + const [signerObjectId, setSignerObjectId] = useState(); + const [isUiLoading, setIsUiLoading] = useState(false); + const [isDecline, setIsDecline] = useState({ isDeclined: false }); + const [currentSigner, setCurrentSigner] = useState(false); + const [isAlert, setIsAlert] = useState({ isShow: false, alertMessage: "" }); + const [defaultSignAlert, setDefaultSignAlert] = useState({ + isShow: false, + alertMessage: "" + }); + const [isCompleted, setIsCompleted] = useState({ + isCertificate: false, + isModal: false + }); + const [pdfLoadFail, setPdfLoadFail] = useState({ + status: false, + type: "load" + }); + const [isSigned, setIsSigned] = useState(false); + const [isExpired, setIsExpired] = useState(false); + const [alreadySign, setAlreadySign] = useState(false); + const [containerWH, setContainerWH] = useState({}); + const divRef = useRef(null); + const isMobile = window.innerWidth < 767; + const rowLevel = + localStorage.getItem("rowlevel") && + JSON.parse(localStorage.getItem("rowlevel")); + + const objectId = + rowLevel && rowLevel.id + ? rowLevel.id + : rowLevel?.objectId && rowLevel.objectId; + const documentId = "uKymQWaYL6"//docId ? docId : objectId && objectId; + + const senderUser = + localStorage.getItem( + `Parse/${localStorage.getItem("parseAppId")}/currentUser` + ) && + localStorage.getItem( + `Parse/${localStorage.getItem("parseAppId")}/currentUser` + ); + const jsonSender = JSON.parse(senderUser); + + useEffect(() => { + if (documentId) { + getDocumentDetails(); + } + }, []); + useEffect(() => { + if (divRef.current) { + const pdfWidth = pdfNewWidthFun(divRef); + setPdfNewWidth(pdfWidth); + setContainerWH({ + width: divRef.current.offsetWidth, + height: divRef.current.offsetHeight + }); + } + }, [divRef.current]); + + //function for get document details for perticular signer with signer'object id + const getDocumentDetails = async () => { + //getting document details + const documentData = await contractDocument(documentId); + if (documentData && documentData.length > 0) { + const isCompleted = + documentData[0].IsCompleted && documentData[0].IsCompleted; + const expireDate = documentData[0].ExpiryDate.iso; + const declined = documentData[0].IsDeclined && documentData[0].IsDeclined; + const expireUpdateDate = new Date(expireDate).getTime(); + const currDate = new Date().getTime(); + const getSigners = documentData[0].Signers; + const getCurrentSigner = + getSigners && + getSigners.filter( + (data) => data.UserId.objectId === jsonSender.objectId + ); + + const currUserId = getCurrentSigner[0] + ? getCurrentSigner[0].objectId + : ""; + setSignerObjectId(currUserId); + if (documentData[0].SignedUrl) { + setPdfUrl(documentData[0].SignedUrl); + } else { + setPdfUrl(documentData[0].URL); + } + if (isCompleted) { + setIsSigned(true); + const data = { + isCertificate: true, + isModal: true + }; + setAlreadySign(true); + setIsCompleted(data); + } else if (declined) { + const currentDecline = { + currnt: "another", + isDeclined: true + }; + setIsDecline(currentDecline); + } else if (currDate > expireUpdateDate) { + setIsExpired(true); + } + + if (documentData.length > 0) { + const checkDocIdExist = + documentData[0].AuditTrail && + documentData[0].AuditTrail.length > 0 && + documentData[0].AuditTrail.filter( + (data) => data.Activity === "Signed" + ); + + const checkAlreadySign = + documentData[0].AuditTrail && + documentData[0].AuditTrail.length > 0 && + documentData[0].AuditTrail.filter( + (data) => + data.UserPtr.objectId === currUserId && data.Activity === "Signed" + ); + if ( + checkAlreadySign && + checkAlreadySign[0] && + checkAlreadySign.length > 0 + ) { + setAlreadySign(true); + } + + let signers = []; + let unSignedSigner = []; + + //check document is signed or not + if (checkDocIdExist && checkDocIdExist.length > 0) { + setIsDocId(true); + const signerRes = documentData[0].Signers; + //comparison auditTrail user details with signers user details + for (let i = 0; i < signerRes.length; i++) { + const signerId = signerRes[i].objectId; + + let isSignedSignature = false; + for (let j = 0; j < checkDocIdExist.length; j++) { + const signedExist = + checkDocIdExist[j] && checkDocIdExist[j].UserPtr.objectId; + //checking signerObjId and auditTrail User objId + // if match then add signed data in signer array and break loop + + if (signerId === signedExist) { + signers.push({ ...signerRes[i], ...signerRes[i] }); + isSignedSignature = true; + break; + } + // if does not match then add unsigned data in unSignedSigner array + } + if (!isSignedSignature) { + unSignedSigner.push({ ...signerRes[i], ...signerRes[i] }); + } + } + setSignedSigners(signers); + setUnSignedSigners(unSignedSigner); + + setSignerPos(documentData[0].Placeholders); + } else { + let unsigned = []; + for (let i = 0; i < documentData.length; i++) { + unsigned.push(documentData[i].Signers); + } + setUnSignedSigners(unsigned[0]); + setSignerPos(documentData[0].Placeholders); + } + setPdfDetails(documentData); + setIsUiLoading(false); + } else { + alert("No data found!"); + } + } else if ( + documentData === "Error: Something went wrong!" || + (documentData.result && documentData.result.error) + ) { + const loadObj = { + isLoad: false + }; + setHandleError("Error: Something went wrong!"); + setIsLoading(loadObj); + } else { + setNoData(true); + const loadObj = { + isLoad: false + }; + setIsLoading(loadObj); + setIsUiLoading(false); + } +if(jsonSender?.objectId){ await axios + .get( + `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( + "_appName" + )}_Signature?where={"UserId": {"__type": "Pointer","className": "_User", "objectId":"${ + jsonSender?.objectId + }"}}`, + { + headers: { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + "X-Parse-Session-Token": localStorage.getItem("accesstoken") + } + } + ) + .then((Listdata) => { + const json = Listdata.data; + const res = json.results; + + if (res[0] && res.length > 0) { + setDefaultSignImg(res[0].ImageURL); + } + const loadObj = { + isLoad: false + }; + setIsLoading(loadObj); + }) + .catch((err) => { + const loadObj = { + isLoad: false + }; + setHandleError("Error: Something went wrong!"); + setIsLoading(loadObj); + });} + }; + + //function for embed signature or image url in pdf + async function embedImages() { + const checkUser = signerPos.filter( + (data) => data.signerObjId === signerObjectId + ); + if (checkUser && checkUser.length > 0) { + let checkSignUrl = []; + const checkSign = checkUser[0].placeHolder.filter( + (data, ind) => data.pos + ); + for (let i = 0; i < checkSign.length; i++) { + const posData = checkSign[i].pos.filter((pos) => !pos.SignUrl); + if (posData && posData.length > 0) { + checkSignUrl.push(posData); + } + } + + if (checkSignUrl && checkSignUrl.length > 0) { + setIsAlert({ + isShow: true, + alertMessage: "Please complete your signature!" + }); + } else { + setIsUiLoading(true); + const pngUrl = checkUser[0].placeHolder; + // Load a PDFDocument from the existing PDF bytes + const existingPdfBytes = await fetch(pdfUrl).then((res) => + res.arrayBuffer() + ); + const pdfDoc = await PDFDocument.load(existingPdfBytes, { + ignoreEncryption: true + }); + // let pdfBase64; + // //else if signature is more than one then embed all sign with the use of pdf-lib + // else if (pngUrl.length > 0 && pngUrl[0].pos.length > 0) { + const flag = false; + //embed document's object id to all pages in pdf document + if (!isDocId) { + await embedDocId(pdfDoc, documentId, allPages); + } + //embed multi signature in pdf + const pdfBytes = await multiSignEmbed( + pngUrl, + pdfDoc, + pdfOriginalWidth, + flag, + containerWH + ); + //function for call to embed signature in pdf and get digital signature pdf + try { + const res = await signPdfFun( + pdfBytes, + documentId, + signerObjectId, + pdfOriginalWidth, + pngUrl, + containerWH, + setIsAlert + ); + if (res && res.status === "success") { + setPdfUrl(res.data); + setIsSigned(true); + setSignedSigners([]); + setUnSignedSigners([]); + getDocumentDetails(); + } else { + setIsAlert({ + isShow: true, + alertMessage: "something went wrong" + }); + } + } catch (err) { + setIsAlert({ + isShow: true, + alertMessage: "something went wrong" + }); + } + } + + setIsSignPad(false); + // } + } else { + setIsAlert({ + isShow: true, + alertMessage: "something went wrong" + }); + } + } + + //function for get pdf page details + const pageDetails = async (pdf) => { + const load = { + status: true + }; + setPdfLoadFail(load); + pdf.getPage(1).then((pdfPage) => { + const pageWidth = pdfPage.view[2]; + + setPdfOriginalWidth(pageWidth); + }); + }; + + //function for change page + function changePage(offset) { + setPageNumber((prevPageNumber) => prevPageNumber + offset); + } + + const getFirstLetter = (name) => { + const firstLetter = name.charAt(0); + return firstLetter; + }; + //function for image upload or update + const onImageChange = (event) => { + if (event.target.files && event.target.files[0]) { + onImageSelect(event, setImgWH, setImage); + } + }; + //function for upload stamp image + const saveImage = () => { + //get current signers placeholder position data + const currentSigner = signerPos.filter( + (data) => data.signerObjId === signerObjectId + ); + //get current pagenumber placeholder index + const getIndex = currentSigner[0].placeHolder.findIndex((object) => { + return object.pageNumber === pageNumber; + }); + //get current signer placeholder position data + const placeholderPosition = currentSigner[0].placeHolder; + //function of save image and get updated position with image url + const getUpdatePosition = onSaveImage( + placeholderPosition, + getIndex, + signKey, + imgWH, + image + ); + + //replace updated placeholder position with old data + placeholderPosition.splice( + 0, + placeholderPosition.length, + ...getUpdatePosition + ); + //get current signers placeholder position data index number in array + const indexofSigner = signerPos.findIndex((object) => { + return object.signerObjId === signerObjectId; + }); + //update current signers data with new placeholder position array data + setSignerPos((prevState) => { + const newState = [...prevState]; // Create a copy of the state + newState.splice(indexofSigner, 1, ...currentSigner); // Modify the copy + return newState; // Update the state with the modified copy + }); + }; + + //function for save button to save signature or image url + const saveSign = (isDefaultSign, width, height) => { + const isTypeText = width && height ? true : false; + const signatureImg = isDefaultSign ? defaultSignImg : signature; + let imgWH = { width: width ? width : "", height: height ? height : "" }; + setIsSignPad(false); + setIsImageSelect(false); + setImage(); + + //get current signers placeholder position data + const currentSigner = signerPos.filter( + (data) => data.signerObjId === signerObjectId + ); + //get current pagenumber placeholder index + const getIndex = currentSigner[0].placeHolder.findIndex((object) => { + return object.pageNumber === pageNumber; + }); + + //set default signature image width and height + if (isDefaultSign) { + const img = new Image(); + img.src = defaultSignImg; + if (img.complete) { + imgWH = { + width: img.width, + height: img.height + }; + } + } + //get current signer placeholder position data + const placeholderPosition = currentSigner[0].placeHolder; + //function of save signature image and get updated position with signature image url + const getUpdatePosition = onSaveSign( + placeholderPosition, + getIndex, + signKey, + signatureImg, + imgWH, + isDefaultSign, + isTypeText + ); + + const updateSignerData = currentSigner.map((obj, ind) => { + if (obj.signerObjId === signerObjectId) { + return { ...obj, placeHolder: getUpdatePosition }; + } + return obj; + }); + + const index = signerPos.findIndex( + (data) => data.signerObjId === signerObjectId + ); + setSignerPos((prevState) => { + const newState = [...prevState]; + newState.splice(index, 1, ...updateSignerData); + return newState; + }); + }; + + const checkSignerBackColor = (obj) => { + const data = signerPos.filter((data) => data.signerObjId === obj.objectId); + return data && data.length > 0 && data[0].blockColor; + }; + + //function for set decline true on press decline button + const declineDoc = async () => { + setIsDecline({ isDeclined: false }); + const data = { + IsDeclined: true + }; + setIsUiLoading(true); + + await axios + .put( + `${localStorage.getItem("baseUrl")}classes/${localStorage.getItem( + "_appName" + )}_Document/${documentId}`, + data, + { + headers: { + "Content-Type": "application/json", + "X-Parse-Application-Id": localStorage.getItem("parseAppId"), + "X-Parse-Session-Token": localStorage.getItem("accesstoken") + } + } + ) + .then((result) => { + const res = result.data; + if (res) { + const currentDecline = { + currnt: "YouDeclined", + isDeclined: true + }; + setIsDecline(currentDecline); + setIsUiLoading(false); + } + }) + .catch((err) => { + console.log("error updating field is decline ", err); + }); + }; + //function to add default signature for all requested placeholder of sign + const addDefaultSignature = () => { + //get current signers placeholder position data + const currentSignerPosition = signerPos.filter( + (data) => data.signerObjId === signerObjectId + ); + //function for save default signature url for all placeholder position + const updatePlace = addDefaultSignatureImg( + currentSignerPosition[0].placeHolder, + defaultSignImg + ); + + const updatesignerPos = signerPos.map((x) => + x.signerObjId === signerObjectId ? { ...x, placeHolder: updatePlace } : x + ); + setSignerPos(updatesignerPos); + setDefaultSignAlert({ + isShow: false, + alertMessage: "" + }); + }; + + return ( + <DndProvider backend={HTML5Backend}> + <Title title={"Request Sign"} /> + {isLoading.isLoad ? ( + <Loader isLoading={isLoading} /> + ) : handleError ? ( + <HandleError handleError={handleError} /> + ) : noData ? ( + <Nodata /> + ) : ( + <div> + {isUiLoading && ( + <div + style={{ + position: "absolute", + height: "100vh", + width: "100%", + display: "flex", + justifyContent: "center", + flexDirection: "column", + alignItems: "center", + zIndex: "20", + backgroundColor: "#e6f2f2", + opacity: 0.8 + }} + > + <img + alt="no img" + src={loader} + style={{ width: "100px", height: "100px" }} + /> + <span style={{ fontSize: "13px", fontWeight: "bold" }}> + This might take some time + </span> + </div> + )} + + <div className="signatureContainer" ref={divRef}> + <ModalUi + headerColor={"#dc3545"} + isOpen={isAlert.isShow} + title={"Alert message"} + handleClose={() => { + setIsAlert({ + isShow: false, + alertMessage: "" + }); + }} + > + <div style={{ height: "100%", padding: 20 }}> + <p>{isAlert.alertMessage}</p> + + <div + style={{ + height: "1px", + backgroundColor: "#9f9f9f", + width: "100%", + marginTop: "15px", + marginBottom: "15px" + }} + ></div> + + <button + onClick={() => { + setIsAlert({ + isShow: false, + alertMessage: "" + }); + }} + type="button" + className="finishBtn cancelBtn" + > + Ok + </button> + </div> + </ModalUi> + {/* this modal is used to show decline alert */} + <CustomModal + containerWH={containerWH} + show={isDecline.isDeclined} + headMsg="Document Declined" + bodyMssg={ + isDecline.currnt === "Sure" ? ( + <p className="pTagBody"> + Are you sure want to decline this document ? + </p> + ) : isDecline.currnt === "YouDeclined" ? ( + <p className="pTagBody">You have declined this document!</p> + ) : ( + isDecline.currnt === "another" && ( + <p className="pTagBody"> + You cannot sign this document as it has been declined by + one or more person(s). + </p> + ) + ) + } + footerMessage={isDecline.currnt === "Sure"} + declineDoc={declineDoc} + setIsDecline={setIsDecline} + /> + {/* this modal is used for show expired alert */} + <CustomModal + containerWH={containerWH} + show={isExpired} + headMsg="Document Expired!" + bodyMssg="This Document is no longer available." + /> + <ModalUi + headerColor={defaultSignImg ? themeColor() : "#dc3545"} + isOpen={defaultSignAlert.isShow} + title={"Auto sign"} + handleClose={() => { + setDefaultSignAlert({ + isShow: false, + alertMessage: "" + }); + }} + > + <div style={{ height: "100%", padding: 20 }}> + <p>{defaultSignAlert.alertMessage}</p> + + <div + style={{ + height: "1px", + backgroundColor: "#9f9f9f", + width: "100%", + marginTop: "15px", + marginBottom: "15px" + }} + ></div> + {defaultSignImg ? ( + <> + <button + onClick={() => addDefaultSignature()} + style={{ + background: themeColor() + }} + type="button" + className="finishBtn" + > + Yes + </button> + <button + onClick={() => { + setDefaultSignAlert({ + isShow: false, + alertMessage: "" + }); + }} + type="button" + className="finishBtn cancelBtn" + > + Close + </button> + </> + ) : ( + <button + onClick={() => { + setIsAlert({ + isShow: false, + alertMessage: "" + }); + }} + type="button" + className="finishBtn cancelBtn" + > + Ok + </button> + )} + </div> + </ModalUi> + {/* this component used to render all pdf pages in left side */} + <RenderAllPdfPage + signPdfUrl={pdfDetails[0].URL || "https://api.printnode.com/static/test/pdf/multipage.pdf"} + allPages={allPages} + setAllPages={setAllPages} + setPageNumber={setPageNumber} + pageNumber={pageNumber} + /> + + {/* pdf render view */} + <div + style={{ + marginLeft: !isMobile && pdfOriginalWidth > 500 && "20px", + marginRight: !isMobile && pdfOriginalWidth > 500 && "20px" + }} + > + {/* this modal is used show this document is already sign */} + <ModalUi + isOpen={isCompleted.isModal} + title={"Sign Documents"} + handleClose={() => { + setIsCompleted({ isModal: false, isCertificate: true }); + }} + > + <div style={{ height: "100%", padding: 20 }}> + <p>This document has been signed by all Signers.</p> + + <div + style={{ + height: "1px", + backgroundColor: "#9f9f9f", + width: "100%", + marginTop: "15px", + marginBottom: "15px" + }} + ></div> + <button + type="button" + className="finishBtn cancelBtn" + onClick={() => + setIsCompleted({ isModal: false, isCertificate: true }) + } + > + Close + </button> + </div> + </ModalUi> + + {/* this component is used for signature pad modal */} + <SignPad + isSignPad={isSignPad} + isStamp={isStamp} + setIsImageSelect={setIsImageSelect} + setIsSignPad={setIsSignPad} + setImage={setImage} + isImageSelect={isImageSelect} + imageRef={imageRef} + onImageChange={onImageChange} + setSignature={setSignature} + image={image} + onSaveImage={saveImage} + onSaveSign={saveSign} + defaultSign={defaultSignImg} + /> + {/* pdf header which contain funish back button */} + <Header + isPdfRequestFiles={true} + pageNumber={pageNumber} + allPages={allPages} + changePage={changePage} + pdfDetails={pdfDetails} + signerPos={signerPos} + isSigned={isSigned} + isCompleted={isCompleted} + embedImages={embedImages} + isShowHeader={true} + setIsDecline={setIsDecline} + decline={true} + currentSigner={currentSigner} + pdfUrl={pdfUrl} + alreadySign={alreadySign} + /> + {containerWH && ( + <RenderPdf + pageNumber={pageNumber} + pdfOriginalWidth={pdfOriginalWidth} + pdfNewWidth={pdfNewWidth} + setIsSignPad={setIsSignPad} + setIsStamp={setIsStamp} + setSignKey={setSignKey} + pdfDetails={pdfDetails} + signerPos={signerPos} + successEmail={false} + pdfUrl={pdfUrl} + numPages={numPages} + pageDetails={pageDetails} + pdfRequest={true} + signerObjectId={signerObjectId} + signedSigners={signedSigners} + setCurrentSigner={setCurrentSigner} + setPdfLoadFail={setPdfLoadFail} + pdfLoadFail={pdfLoadFail} + setSignerPos={setSignerPos} + containerWH={containerWH} + /> + )} + </div> + <div> + <div className="signerComponent"> + <div + style={{ maxHeight: window.innerHeight - 70 + "px" }} + className="autoSignScroll" + > + {signedSigners.length > 0 && ( + <> + <div + style={{ + background: themeColor() + }} + className="signedStyle" + > + Signed by + </div> + <div style={{ marginTop: "2px" }}> + {signedSigners.map((obj, ind) => { + return ( + <div + style={{ + display: "flex", + flexDirection: "row", + alignItems: "center", + padding: "10px 0", + background: checkSignerBackColor(obj) + }} + key={ind} + > + <div + className="signerStyle" + style={{ + background: "#abd1d0", + width: 30, + height: 30, + display: "flex", + borderRadius: 30 / 2, + justifyContent: "center", + alignItems: "center", + margin: "0 10px 0 5px" + }} + > + <span + style={{ + fontSize: "12px", + textAlign: "center", + fontWeight: "bold", + color: "black", + textTransform: "uppercase" + }} + > + {getFirstLetter(obj.Name)} + </span> + </div> + <div + style={{ + display: "flex", + flexDirection: "column" + }} + > + <span className="userName">{obj.Name}</span> + <span className="useEmail">{obj.Email}</span> + </div> + </div> + ); + })} + </div> + </> + )} + + {unsignedSigners.length > 0 && ( + <> + <div + style={{ + background: themeColor(), + color: "white", + padding: "5px", + fontFamily: "sans-serif", + marginTop: signedSigners.length > 0 && "20px" + }} + > + Yet to sign + </div> + <div style={{ marginTop: "5px" }}> + {unsignedSigners.map((obj, ind) => { + return ( + <div + style={{ + display: "flex", + flexDirection: "row", + alignItems: "center", + padding: "10px 0", + background: checkSignerBackColor(obj) + }} + key={ind} + > + <div + className="signerStyle" + style={{ + background: "#abd1d0", + width: 30, + height: 30, + display: "flex", + borderRadius: 30 / 2, + justifyContent: "center", + alignItems: "center", + margin: "0 10px 0 5px" + }} + > + <span + style={{ + fontSize: "12px", + textAlign: "center", + fontWeight: "bold", + color: "black", + textTransform: "uppercase" + }} + > + {getFirstLetter(obj.Name)} + </span> + </div> + <div + style={{ + display: "flex", + flexDirection: "column" + }} + > + <span className="userName">{obj.Name}</span> + <span className="useEmail">{obj.Email}</span> + </div> + <hr /> + </div> + ); + })} + </div> + </> + )} + {defaultSignImg && !alreadySign && ( + <DefaultSignature + themeColor={themeColor} + defaultSignImg={defaultSignImg} + setDefaultSignImg={setDefaultSignImg} + userObjectId={signerObjectId} + setIsLoading={setIsLoading} + xyPostion={signerPos} + setDefaultSignAlert={setDefaultSignAlert} + /> + )} + </div> + </div> + </div> + </div> + </div> + )} + </DndProvider> + ); +} + +export default GuestSign; diff --git a/microfrontends/SignDocuments/src/utils/Utils.js b/microfrontends/SignDocuments/src/utils/Utils.js index 6acf10338..a23288340 100644 --- a/microfrontends/SignDocuments/src/utils/Utils.js +++ b/microfrontends/SignDocuments/src/utils/Utils.js @@ -1391,7 +1391,8 @@ export const createDocument = async (template, placeholders, signerData) => { className: "_User", objectId: Doc.CreatedBy.objectId }, - Signers: signers + Signers: signers, + SendinOrder: Doc?.SendinOrder || false }; try {