initial commit

This commit is contained in:
nxglabs
2023-10-22 01:37:25 +05:30
parent 80327652c3
commit 97fd28697a
182 changed files with 55033 additions and 122 deletions
+6
View File
@@ -0,0 +1,6 @@
[tool.commitizen]
version = "0.1.0" # This should be your current semver version
version_files = [
"package.json:\"version\":",
"package-lock.json:\"version\":",
]
+33
View File
@@ -0,0 +1,33 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended"
],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["react"],
"rules": {
"react/prop-types": 0,
"no-unused-vars": 0,
"no-empty": 0,
"no-case-declarations": 0,
"react/no-deprecated": 0,
"no-undef": 0
},
"ignorePatterns": ["**/build/**", "**/*.config.js"],
"settings": {
"react": {
"version": "detect"
}
}
}
+44
View File
@@ -0,0 +1,44 @@
name: ci
on:
push:
branches:
- 'monorepo'
jobs:
docker:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- image: amolshejole/OpenSign
dockerfile: apps/OpenSign/Dockerfile
- image: amolshejole/OpenSignServer
dockerfile: apps/OpenSignServer/Dockerfile
steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ matrix.image }}
-
name: Debug - List files
run: ls -R apps/OpenSign/ # Adjust the path as needed
-
name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: ${{ matrix.dockerfile }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+15 -121
View File
@@ -1,130 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# dependencies
/node_modules
/.pnp
.pnp.js
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# testing
/coverage
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# production
/build
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
# misc
.env
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx eslint '**/*.{js,jsx}'
npx pretty-quick --staged '**/*.{js,jsx}'
+7
View File
@@ -0,0 +1,7 @@
node_modules/
public/
build/
package.json
package-lock.json
dist/
docs/
+7
View File
@@ -0,0 +1,7 @@
{
"bracketSpacing": true,
"semi": true,
"trailingComma": "none",
"printWidth": 80,
"tabWidth": 2
}
+1 -1
View File
@@ -17,4 +17,4 @@ OpenSign application consistes of 3 components -
You can install all 3 components on digital ocean using the button below -
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/OpenSignLabs/OpenSign/tree/updatedocumentation&refcode=30db1c901ab0)
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/OpenSignLabs/OpenSign/tree/monorepo&refcode=30db1c901ab0)
+6
View File
@@ -0,0 +1,6 @@
[tool.commitizen]
version = "0.1.0" # This should be your current semver version
version_files = [
"package.json:\"version\":",
"package-lock.json:\"version\":",
]
+2
View File
@@ -0,0 +1,2 @@
node_modules
npm-debug.log
+33
View File
@@ -0,0 +1,33 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended"
],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["react"],
"rules": {
"react/prop-types": 0,
"no-unused-vars": 0,
"no-empty": 0,
"no-case-declarations": 0,
"react/no-deprecated": 0,
"no-undef": 0
},
"ignorePatterns": ["**/build/**", "**/*.config.js"],
"settings": {
"react": {
"version": "detect"
}
}
}
+24
View File
@@ -0,0 +1,24 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.env
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx eslint '**/*.{js,jsx}'
npx pretty-quick --staged '**/*.{js,jsx}'
+7
View File
@@ -0,0 +1,7 @@
node_modules/
public/
build/
package.json
package-lock.json
dist/
docs/
+7
View File
@@ -0,0 +1,7 @@
{
"bracketSpacing": true,
"semi": true,
"trailingComma": "none",
"printWidth": 80,
"tabWidth": 2
}
+24
View File
@@ -0,0 +1,24 @@
# Use an official Node runtime as the base image
FROM node:16
# 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/ .
# 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"]
+31
View File
@@ -0,0 +1,31 @@
# Open Sign
Open source is true platform to sign pdf with digital signature
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
# Remote Deployment
## DigitalOcean
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/prafullnavkar-nxg/open_sign/tree/master&refcode=30db1c901ab0)
+29
View File
@@ -0,0 +1,29 @@
const { dependencies } = require("./package.json");
module.exports = {
name: "shell_app", // change me
filename: "remoteEntry.js",
exposes: {},
remotes: {},
shared: {
...dependencies,
react: {
singleton: true,
import: "react", // fallback is also react
shareScope: "default",
requiredVersion: dependencies.react
},
"react-dom": {
singleton: true,
requiredVersion: dependencies["react-dom"]
},
"react-router-dom": {
singleton: true,
requiredVersion: dependencies["react-router-dom"]
},
"rjsf-conditionals": {
singleton: true,
requiredVersion: dependencies["rjsf-conditionals"]
}
}
};
+21023
View File
File diff suppressed because it is too large Load Diff
+84
View File
@@ -0,0 +1,84 @@
{
"name": "open_sign",
"version": "0.1.0",
"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",
"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",
"mf-cra": "^0.0.5",
"moment": "^2.29.4",
"parse": "^4.2.0",
"react": "^18.2.0",
"react-bootstrap": "^2.9.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dnd-multi-backend": "^8.0.3",
"react-dnd-touch-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-drag-listview": "^2.0.0",
"react-helmet": "^6.1.0",
"react-modal": "^3.16.1",
"react-redux": "^8.1.3",
"react-router-dom": "^6.16.0",
"react-scripts": "5.0.1",
"react-select": "^5.7.7",
"reactour": "^1.19.1",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2",
"rjsf-conditionals": "github:prafullnavkar-nxg/rjsf-conditionals",
"styled-components": "^4.4.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "mf-cra start",
"build": "CI=false && mf-cra build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"release": "standard-version",
"commit": "cz"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"devDependencies": {
"@babel/runtime-corejs2": "^7.23.2",
"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",
"prettier": "^2.8.0",
"pretty-quick": "^3.1.3",
"tailwindcss": "^3.3.3"
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
};
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+53
View File
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<!-- <link rel="icon" type="image/png"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAALlJREFUaEPtmN0NwjAMBpNxYDKYiM1Yp90g93CKStH1NbIdfz921Dker2Pc+Js1cDF7MXAxASMGYkAigBI6vh9ZwoXP53uZoAYcvhwdA3mAVbI2aSb+9zFKU4IURB6j/HoPUIEa2G3iGIAhQQDlAUIoE2diabIklISS0NoFPebo77RF6OenEF3QntOm128he0GKrwHyACFoz2MgBqSGkpAEcHs47oHtN5AFakACqMNjQEMoE8SABFCHn4HE2zGHSLeEAAAAAElFTkSuQmCC"
sizes="40x40" /> -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="The fastest way to sign PDFs & request signatures from others" />
<!-- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> -->
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"
integrity="sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
<title>Open sign</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+25
View File
@@ -0,0 +1,25 @@
{
"short_name": "Open sign",
"name": "Open sign",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
+3
View File
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
+140
View File
@@ -0,0 +1,140 @@
import React, { useState, useEffect } from "react";
import { Routes, Route, BrowserRouter } from "react-router-dom";
import Pgsignup from "./routes/Pgsignup";
import Login from "./routes/Login";
import Microapp from "./routes/RemoteApp";
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 HomeLayout from "./layout/HomeLayout";
import UserProfile from "./routes/UserProfile";
import PageNotFound from "./routes/PageNotFound";
import ForgetPassword from "./routes/ForgetPassword";
import ChangePassword from "./routes/ChangePassword";
import ReportMicroapp from "./components/ReportMicroapp";
function App() {
const [isloading, setIsLoading] = useState(true);
useEffect(() => {
handleCredentials();
}, []);
const handleCredentials = () => {
const appId = process.env.REACT_APP_APPID;
const baseurl = process.env.REACT_APP_SEVERURL;
const appName = "contracts";
try {
localStorage.setItem("BaseUrl12", `${baseurl}/`);
localStorage.setItem("AppID12", appId);
localStorage.setItem("domain", appName);
setIsLoading(false);
} catch (error) {
console.log("err ", error);
}
};
return (
<div className="bg-[#eef1f5]">
{isloading ? (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
) : (
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Login />} />
<Route exact path="/signup" element={<Signup />} />
<Route exact path="/pgsignup" element={<Pgsignup />} />
<Route exact path="/forgetpassword" element={<ForgetPassword />} />
<Route exact path="/subscription" element={<PlanSubscriptions />} />
<Route
exact
path="/changepassword"
element={
<HomeLayout>
<ChangePassword />
</HomeLayout>
}
/>
<Route
path="/mf/:remoteApp/*"
element={
<HomeLayout>
<Microapp />
</HomeLayout>
}
/>
<Route
path="/asmf/:remoteApp/*"
element={
<HomeLayout>
<Microapp />
</HomeLayout>
}
/>
<Route
path="/rpmf/:remoteApp/*"
element={
<HomeLayout>
<ReportMicroapp />
</HomeLayout>
}
/>
<Route
path="/form/:id"
element={
<HomeLayout>
<Form />
</HomeLayout>
}
/>
<Route
path="/report/:id"
element={
<HomeLayout>
<Report />
</HomeLayout>
}
/>
<Route
path="/dashboard/:id"
element={
<HomeLayout>
<Dashboard />
</HomeLayout>
}
/>
<Route
path="/profile"
element={
<HomeLayout>
<UserProfile />
</HomeLayout>
}
/>
<Route path="*" element={<PageNotFound />} />
{/* <Route exact path="/ForgotPassword" element={<ForgotPassword />} /> */}
</Routes>
</BrowserRouter>
)}
</div>
);
}
export default App;
+54
View File
@@ -0,0 +1,54 @@
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux";
import { store } from "./redux/store";
import { HTML5Backend } from "react-dnd-html5-backend";
import { TouchBackend } from "react-dnd-touch-backend";
import {
DndProvider,
TouchTransition,
MouseTransition,
Preview
} from "react-dnd-multi-backend";
import DragElement from "./microappComponent/DragElement";
const HTML5toTouch = {
backends: [
{
id: "html5",
backend: HTML5Backend,
transition: MouseTransition
},
{
id: "touch",
backend: TouchBackend,
options: { enableMouseEvents: true },
preview: true,
transition: TouchTransition
}
]
};
const generatePreview = (props) => {
const { item, style } = props;
const newStyle = {
...style
};
return (
<div style={newStyle}>
<DragElement {...item} />
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<DndProvider options={HTML5toTouch}>
<Preview>{generatePreview}</Preview>
<App />
</DndProvider>
</Provider>
);
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

@@ -0,0 +1,184 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="691.365" height="586.346" viewBox="0 0 691.365 586.346">
<defs>
<linearGradient id="linear-gradient" x1="0.5" y1="1" x2="0.5" y2="-0.001" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="gray" stop-opacity="0.251"/>
<stop offset="0.54" stop-color="gray" stop-opacity="0.122"/>
<stop offset="1" stop-color="gray" stop-opacity="0.102"/>
</linearGradient>
</defs>
<g id="Group_644" data-name="Group 644" transform="translate(-588.635 -80)">
<g id="Group_642" data-name="Group 642" transform="translate(22538.635 6999)">
<path id="Path_472" data-name="Path 472" d="M482.764,637.675c51.612-29.22,67.336-29.693,124.954-17.169,81.646,17.758,88.43-49.93,108.306-186.933,33.946-233.98-108.306-295.737-108.306-295.737s-94.6-8.1-150.536-38.963C377.726,55.027,286.9,49.443,207.046,86.542c-51.069,23.7-93.125,56.714-100.31,102.034-20.09,126.746,12.9,196.58-48.819,237.954S48.944,581.5,96.263,577.564c34.968-2.906,80.842,52.415,130.687,60.111,17.382,2.684,88.7-13.043,99.578,0C341.327,655.4,464.763,647.87,482.764,637.675Z" transform="translate(-21979.895 -6980.982)" fill="#00ddf1" opacity="0.1"/>
<g id="Group_641" data-name="Group 641" transform="translate(-21545.08 -6816.88)">
<rect id="Rectangle_263" data-name="Rectangle 263" width="217.867" height="15.073" transform="translate(0 39.052)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_264" data-name="Rectangle 264" width="217.867" height="15.073" transform="translate(0 104.137)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_265" data-name="Rectangle 265" width="217.867" height="15.073" transform="translate(0 171.964)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_266" data-name="Rectangle 266" width="13.702" height="39.052" transform="translate(19.183)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_267" data-name="Rectangle 267" width="13.702" height="2.74" transform="translate(19.183 6.166)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_268" data-name="Rectangle 268" width="13.702" height="2.74" transform="translate(19.183 27.405)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_269" data-name="Rectangle 269" width="13.702" height="39.052" transform="translate(39.737)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_270" data-name="Rectangle 270" width="13.702" height="2.74" transform="translate(39.737 6.166)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_271" data-name="Rectangle 271" width="13.702" height="2.74" transform="translate(39.737 27.405)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_272" data-name="Rectangle 272" width="13.702" height="39.052" transform="translate(60.29)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_273" data-name="Rectangle 273" width="13.702" height="2.74" transform="translate(60.29 6.166)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_274" data-name="Rectangle 274" width="13.702" height="2.74" transform="translate(60.29 27.405)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_275" data-name="Rectangle 275" width="13.702" height="39.052" transform="translate(80.844)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_276" data-name="Rectangle 276" width="13.702" height="2.74" transform="translate(80.844 6.166)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_277" data-name="Rectangle 277" width="13.702" height="2.74" transform="translate(80.844 27.405)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_278" data-name="Rectangle 278" width="13.702" height="39.052" transform="translate(101.397)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_279" data-name="Rectangle 279" width="13.702" height="2.74" transform="translate(101.397 6.166)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_280" data-name="Rectangle 280" width="13.702" height="2.74" transform="translate(101.397 27.405)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_281" data-name="Rectangle 281" width="13.702" height="39.052" transform="translate(121.95)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_282" data-name="Rectangle 282" width="13.702" height="2.74" transform="translate(121.95 6.166)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_283" data-name="Rectangle 283" width="13.702" height="2.74" transform="translate(121.95 27.405)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_284" data-name="Rectangle 284" width="13.702" height="39.052" transform="translate(142.504)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_285" data-name="Rectangle 285" width="13.702" height="2.74" transform="translate(142.504 6.166)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_286" data-name="Rectangle 286" width="13.702" height="2.74" transform="translate(142.504 27.405)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_287" data-name="Rectangle 287" width="13.702" height="39.052" transform="matrix(0.894, -0.448, 0.448, 0.894, 135.847, 138.025)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_288" data-name="Rectangle 288" width="13.702" height="2.74" transform="matrix(0.894, -0.448, 0.448, 0.894, 138.614, 143.541)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_289" data-name="Rectangle 289" width="13.702" height="2.74" transform="matrix(0.894, -0.448, 0.448, 0.894, 148.128, 162.529)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_290" data-name="Rectangle 290" width="13.702" height="39.052" transform="translate(19.183 65.771)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_291" data-name="Rectangle 291" width="13.702" height="2.74" transform="translate(19.183 71.937)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_292" data-name="Rectangle 292" width="13.702" height="2.74" transform="translate(19.183 93.176)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_293" data-name="Rectangle 293" width="13.702" height="39.052" transform="translate(39.737 65.771)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_294" data-name="Rectangle 294" width="13.702" height="2.74" transform="translate(39.737 71.937)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_295" data-name="Rectangle 295" width="13.702" height="2.74" transform="translate(39.737 93.176)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_296" data-name="Rectangle 296" width="13.702" height="39.052" transform="translate(60.29 65.771)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_297" data-name="Rectangle 297" width="13.702" height="2.74" transform="translate(60.29 71.937)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_298" data-name="Rectangle 298" width="13.702" height="2.74" transform="translate(60.29 93.176)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_299" data-name="Rectangle 299" width="13.702" height="39.052" transform="translate(145.93 65.771)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_300" data-name="Rectangle 300" width="13.702" height="2.74" transform="translate(145.93 71.937)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_301" data-name="Rectangle 301" width="13.702" height="2.74" transform="translate(145.93 93.176)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_302" data-name="Rectangle 302" width="13.702" height="39.052" transform="translate(166.483 65.771)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_303" data-name="Rectangle 303" width="13.702" height="2.74" transform="translate(166.483 71.937)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_304" data-name="Rectangle 304" width="13.702" height="2.74" transform="translate(166.483 93.176)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_305" data-name="Rectangle 305" width="13.702" height="39.052" transform="translate(187.036 65.771)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_306" data-name="Rectangle 306" width="13.702" height="2.74" transform="translate(187.036 71.937)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_307" data-name="Rectangle 307" width="13.702" height="2.74" transform="translate(187.036 93.176)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_308" data-name="Rectangle 308" width="13.702" height="39.052" transform="translate(19.183 132.912)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_309" data-name="Rectangle 309" width="13.702" height="2.74" transform="translate(19.183 139.078)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_310" data-name="Rectangle 310" width="13.702" height="2.74" transform="translate(19.183 160.317)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_311" data-name="Rectangle 311" width="13.702" height="39.052" transform="translate(39.737 132.912)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_312" data-name="Rectangle 312" width="13.702" height="2.74" transform="translate(39.737 139.078)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_313" data-name="Rectangle 313" width="13.702" height="2.74" transform="translate(39.737 160.317)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_314" data-name="Rectangle 314" width="13.702" height="39.052" transform="translate(60.29 132.912)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_315" data-name="Rectangle 315" width="13.702" height="2.74" transform="translate(60.29 139.078)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_316" data-name="Rectangle 316" width="13.702" height="2.74" transform="translate(60.29 160.317)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_317" data-name="Rectangle 317" width="13.702" height="39.052" transform="translate(80.844 132.912)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_318" data-name="Rectangle 318" width="13.702" height="2.74" transform="translate(80.844 139.078)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_319" data-name="Rectangle 319" width="13.702" height="2.74" transform="translate(80.844 160.317)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_320" data-name="Rectangle 320" width="13.702" height="39.052" transform="translate(101.397 132.912)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_321" data-name="Rectangle 321" width="13.702" height="2.74" transform="translate(101.397 139.078)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_322" data-name="Rectangle 322" width="13.702" height="2.74" transform="translate(101.397 160.317)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_323" data-name="Rectangle 323" width="13.702" height="39.052" transform="translate(121.95 132.912)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_324" data-name="Rectangle 324" width="13.702" height="2.74" transform="translate(121.95 139.078)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_325" data-name="Rectangle 325" width="13.702" height="2.74" transform="translate(121.95 160.317)" fill="#00ddf1" opacity="0.1"/>
<path id="Path_473" data-name="Path 473" d="M797.862,159.09v35.571h-13.7V156.48Q791.039,157.693,797.862,159.09Z" transform="translate(-621.103 -155.61)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_326" data-name="Rectangle 326" width="13.702" height="2.74" transform="translate(163.057 6.166)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_327" data-name="Rectangle 327" width="13.702" height="2.74" transform="translate(163.057 27.405)" fill="#00ddf1" opacity="0.1"/>
<path id="Path_474" data-name="Path 474" d="M827.862,165.719v30.83h-13.7V162.43c1.781.391,3.556.8,5.33,1.22Q823.7,164.636,827.862,165.719Z" transform="translate(-630.549 -157.483)" fill="#00ddf1" opacity="0.1"/>
<path id="Path_475" data-name="Path 475" d="M827.862,166.285v.685h-13.7v-2.74h5.33Q823.7,165.2,827.862,166.285Z" transform="translate(-630.549 -158.05)" fill="#00ddf1" opacity="0.1"/>
<rect id="Rectangle_328" data-name="Rectangle 328" width="13.702" height="2.74" transform="translate(183.611 27.405)" fill="#00ddf1" opacity="0.1"/>
<path id="Path_476" data-name="Path 476" d="M691.358,287.276s-4.152-1.411-6.166,2.254a6.68,6.68,0,0,0,.089,6.426,9.4,9.4,0,0,0,9.146,5.179c4.35-.233,5.8-3.549,6.166-6.639a6.851,6.851,0,0,0-9.057-7.3Z" transform="translate(-589.693 -196.649)" fill="#00ddf1"/>
<path id="Path_477" data-name="Path 477" d="M686.2,296.239a6.68,6.68,0,0,1-.089-6.426c2-3.659,6.166-2.254,6.166-2.254l.212-.075a6.762,6.762,0,0,1,4.885.11,6.762,6.762,0,0,0-5.762-.548l-.212.075s-4.152-1.411-6.166,2.254a6.68,6.68,0,0,0,.089,6.426,9.982,9.982,0,0,0,4.7,4.446A10.277,10.277,0,0,1,686.2,296.239Z" transform="translate(-589.706 -196.595)" fill="#00ddf1" opacity="0.1"/>
<path id="Path_478" data-name="Path 478" d="M691.42,290.06s1.542,1.213,5.282,0" transform="translate(-591.9 -197.672)" fill="#00ddf1" opacity="0.2"/>
<path id="Path_479" data-name="Path 479" d="M690.93,277.21s2.638,7.153,2.418,9.023l2.09-.219s-3.521-6.269-2.638-8.8Z" transform="translate(-591.746 -193.626)" fill="#00ddf1"/>
<path id="Path_480" data-name="Path 480" d="M690.93,277.21s2.638,7.153,2.418,9.023l2.09-.219s-3.521-6.269-2.638-8.8Z" transform="translate(-591.746 -193.626)" fill="#00ddf1" opacity="0.2"/>
<path id="Path_481" data-name="Path 481" d="M702.92,277.6s-4.159-2.124-6.015-.37-2.144,6.241-2.144,6.241S701.536,284.391,702.92,277.6Z" transform="translate(-592.952 -193.414)" fill="#00ddf1"/>
<path id="Path_482" data-name="Path 482" d="M702.92,277.6s-4.159-2.124-6.015-.37-2.144,6.241-2.144,6.241S701.536,284.391,702.92,277.6Z" transform="translate(-592.952 -193.414)" fill="#00ddf1" opacity="0.1"/>
<path id="Path_483" data-name="Path 483" d="M694.75,283.958s1.089-5.207,8.16-5.878" transform="translate(-592.949 -193.9)" fill="#00ddf1"/>
<path id="Path_484" data-name="Path 484" d="M819.358,386.276s-4.152-1.411-6.166,2.254a6.68,6.68,0,0,0,.089,6.426,9.4,9.4,0,0,0,9.146,5.18c4.35-.233,5.8-3.549,6.166-6.639a6.851,6.851,0,0,0-9.057-7.3Z" transform="translate(-629.999 -227.823)" fill="#00ddf1"/>
<path id="Path_485" data-name="Path 485" d="M814.2,395.239a6.68,6.68,0,0,1-.089-6.426c2-3.659,6.166-2.254,6.166-2.254l.212-.075a6.762,6.762,0,0,1,4.885.11,6.762,6.762,0,0,0-5.762-.548l-.212.075s-4.152-1.411-6.166,2.254a6.68,6.68,0,0,0,.089,6.426,9.982,9.982,0,0,0,4.7,4.446A10.276,10.276,0,0,1,814.2,395.239Z" transform="translate(-630.011 -227.769)" fill="#00ddf1" opacity="0.1"/>
<path id="Path_486" data-name="Path 486" d="M819.42,389.06s1.542,1.213,5.282,0" transform="translate(-632.206 -228.846)" fill="#00ddf1" opacity="0.2"/>
<path id="Path_487" data-name="Path 487" d="M818.93,376.21s2.638,7.153,2.419,9.023l2.09-.219s-3.522-6.269-2.638-8.8Z" transform="translate(-632.051 -224.799)" fill="#00ddf1"/>
<path id="Path_488" data-name="Path 488" d="M818.93,376.21s2.638,7.153,2.419,9.023l2.09-.219s-3.522-6.269-2.638-8.8Z" transform="translate(-632.051 -224.799)" fill="#00ddf1" opacity="0.2"/>
<path id="Path_489" data-name="Path 489" d="M830.92,376.6s-4.159-2.124-6.015-.37-2.144,6.241-2.144,6.241S829.536,383.391,830.92,376.6Z" transform="translate(-633.257 -224.588)" fill="#00ddf1"/>
<path id="Path_490" data-name="Path 490" d="M830.92,376.6s-4.159-2.124-6.015-.37-2.144,6.241-2.144,6.241S829.536,383.391,830.92,376.6Z" transform="translate(-633.257 -224.588)" fill="#00ddf1" opacity="0.1"/>
<path id="Path_491" data-name="Path 491" d="M822.75,382.958s1.089-5.207,8.16-5.878" transform="translate(-633.254 -225.073)" fill="#00ddf1"/>
</g>
</g>
<g id="Group_643" data-name="Group 643" transform="translate(7 -63)">
<g id="Group_639" data-name="Group 639" transform="translate(21233 8372)">
<ellipse id="Ellipse_73" data-name="Ellipse 73" cx="49.851" cy="8.007" rx="49.851" ry="8.007" transform="translate(-20118.443 -7772.555)" fill="#00abf6" opacity="0.1"/>
<rect id="Rectangle_182" data-name="Rectangle 182" width="3.208" height="72.224" transform="translate(-20070.199 -7917.934)" fill="#535461"/>
<path id="Path_268" data-name="Path 268" d="M1025.906,587.251l-.2,3.254-.287,4.6-.118,1.913-.281,4.6-.123,1.913-.286,4.6-3.233,52.22a8.851,8.851,0,0,1-8.83,8.268H995.731a8.841,8.841,0,0,1-8.82-8.3l-3.244-52.225-.281-4.6-.117-1.913-.292-4.6-.117-1.913-.281-4.6-.2-3.254a4.6,4.6,0,0,1,4.574-4.865h34.391a4.6,4.6,0,0,1,4.569,4.9Z" transform="translate(-21072.734 -8433.181)" fill="#565661"/>
<path id="Path_269" data-name="Path 269" d="M990.949,517.36l-.287,4.589H948.106l-.286-4.589Z" transform="translate(-21037.977 -8360.036)" fill="#9d9cb5"/>
<path id="Path_270" data-name="Path 270" d="M990.93,530.08l-.281,4.594H948.9l-.286-4.594Z" transform="translate(-21038.363 -8366.248)" fill="#9d9cb5"/>
<path id="Path_271" data-name="Path 271" d="M990.912,542.8l-.287,4.589H949.686L949.4,542.8Z" transform="translate(-21038.748 -8372.46)" fill="#9d9cb5"/>
<path id="Path_272" data-name="Path 272" d="M933.875,490.464c18.684,13.517,26.466,34.656,26.466,34.656s-22.511-.773-41.2-14.289-26.46-34.651-26.46-34.651S915.2,476.953,933.875,490.464Z" transform="translate(-21028.934 -8381.328)" fill="#00abf6"/>
<path id="Path_273" data-name="Path 273" d="M892.68,476.18s23.365,12.969,30.865,23.708,36.8,25.233,36.8,25.233" transform="translate(-21028.934 -8381.328)" fill="none" stroke="#535461" stroke-miterlimit="10" stroke-width="2"/>
<path id="Path_274" data-name="Path 274" d="M975.393,443.457c10.171,7.352,14.407,18.863,14.407,18.863s-12.279-.425-22.424-7.776S953,435.68,953,435.68,965.227,436.1,975.393,443.457Z" transform="translate(-21058.393 -8361.549)" fill="#00abf6"/>
<path id="Path_275" data-name="Path 275" d="M953,435.68s12.719,7.06,16.8,12.9,20.03,13.737,20.03,13.737" transform="translate(-21058.393 -8361.549)" fill="none" stroke="#535461" stroke-miterlimit="10" stroke-width="2"/>
<path id="Path_276" data-name="Path 276" d="M1040.3,470.483c-11.68,12.836-14.151,29.612-14.151,29.612s16.469-4.042,28.139-16.883,14.151-29.612,14.151-29.612S1051.981,457.647,1040.3,470.483Z" transform="translate(-21094.119 -8370.301)" fill="#00abf6"/>
<path id="Path_277" data-name="Path 277" d="M1068.45,453.61s-15.215,13.159-19.083,22.224S1026.15,500.1,1026.15,500.1" transform="translate(-21094.119 -8370.306)" fill="none" stroke="#535461" stroke-miterlimit="10" stroke-width="2"/>
</g>
<g id="Group_638" data-name="Group 638" transform="translate(-40 36)">
<rect id="Rectangle_254" data-name="Rectangle 254" width="12.343" height="37.459" transform="translate(741.459 392.675)" fill="#3f3d56"/>
<rect id="Rectangle_255" data-name="Rectangle 255" width="12.343" height="39.629" transform="translate(1073.647 390.726)" fill="#3f3d56"/>
<path id="Path_418" data-name="Path 418" d="M597.889,523.665v8.446l-98.7.909-1.052.02-37.511.344-.9.013-11.4.1h-.338l-69.5.643L264.408,535.2h-.1l-29.007.273-.312.007L106.1,536.658v-9.745l30.306-18.19,60.808-.507,1.3-.007.429-.007,1.3-.019,29.2-.24,1.306-.007.416-.007,1.3-.006,9.362-.078.247-.006,23.1-.195h.188l180.214-1.52,4.411-.032h.442l3.365-.033,24.459-.2,1.3-.02,1.2-.013h.624l7.607-.058,1.507-.02,2.02-.013,6.334-.058,10.05-.084,1.3-.013,2.261-.013h.422l48.536-.416Z" transform="translate(566.82 43)" fill="#65617d"/>
<path id="Path_419" data-name="Path 419" d="M597.889,523.665v8.446l-98.7.909-1.052.02-37.511.344-.9.013-11.4.1h-.338l-69.5.643L264.408,535.2h-.1l-29.007.273-.312.007L106.1,536.658v-9.745l30.306-18.19,60.808-.507,1.3-.007.429-.007,1.3-.019,29.2-.24,1.306-.007.416-.007,1.3-.006,9.362-.078.247-.006,23.1-.195h.188l180.214-1.52,4.411-.032h.442l3.365-.033,24.459-.2,1.3-.02,1.2-.013h.624l7.607-.058,1.507-.02,2.02-.013,6.334-.058,10.05-.084,1.3-.013,2.261-.013h.422l48.536-.416Z" transform="translate(566.82 43)" opacity="0.2"/>
<path id="Path_420" data-name="Path 420" d="M358.914,656.57v15.91a3.982,3.982,0,0,1-2.274,3.6,3.9,3.9,0,0,1-1.624.39l-22.673.481a3.9,3.9,0,0,1-1.754-.37,3.976,3.976,0,0,1-2.319-3.619V656.57Z" transform="translate(437.441 -122.381)" fill="#3f3d56"/>
<path id="Path_421" data-name="Path 421" d="M358.914,656.57v15.91a3.982,3.982,0,0,1-2.274,3.6,3.9,3.9,0,0,1-1.624.39l-22.673.481a3.9,3.9,0,0,1-1.754-.37,3.976,3.976,0,0,1-2.319-3.619V656.57Z" transform="translate(437.441 -122.381)" opacity="0.1"/>
<path id="Path_422" data-name="Path 422" d="M360.914,656.57v15.91a3.982,3.982,0,0,1-2.274,3.6,3.9,3.9,0,0,1-1.624.39l-22.673.481a3.9,3.9,0,0,1-1.754-.37,3.976,3.976,0,0,1-2.319-3.619V656.57Z" transform="translate(436.74 -122.381)" fill="#3f3d56"/>
<rect id="Rectangle_256" data-name="Rectangle 256" width="30.644" height="20.464" transform="translate(1046.362 534.189)" fill="#3f3d56"/>
<rect id="Rectangle_257" data-name="Rectangle 257" width="30.644" height="20.464" transform="translate(1046.362 534.189)" opacity="0.1"/>
<rect id="Rectangle_258" data-name="Rectangle 258" width="30.644" height="20.464" transform="translate(1045.062 534.189)" fill="#3f3d56"/>
<path id="Path_423" data-name="Path 423" d="M223.943,265.82v3.723l-12.343-.318v-3.4Z" transform="translate(529.859 126.848)" opacity="0.1"/>
<path id="Path_424" data-name="Path 424" d="M358.741,271.246,343.909,377.789a2.794,2.794,0,0,1-2.839,2.41L222.314,377.12l-2.254-.058a2.794,2.794,0,0,1-2.7-3.164l16.651-111.533a2.794,2.794,0,0,1,2.949-2.358l119.186,8.069a2.787,2.787,0,0,1,2.6,3.17Z" transform="translate(476.307 16.556)" fill="#65617d"/>
<path id="Path_425" data-name="Path 425" d="M169.158,99.16,156.6,197.472l109.142,3.463,13.422-94.85Z" transform="translate(549.128 185.237)" fill="#00ddf1"/>
<rect id="Rectangle_259" data-name="Rectangle 259" width="132.965" height="112.605" rx="5.33" transform="translate(853.849 282.877)" fill="#65617d"/>
<rect id="Rectangle_260" data-name="Rectangle 260" width="120.836" height="93.765" transform="translate(860.125 290.458)" fill="#00ddf1"/>
<path id="Path_426" data-name="Path 426" d="M735.273,262.82v2.462l-12.343.253V262.82Z" transform="translate(350.717 127.899)" opacity="0.1"/>
<path id="Path_427" data-name="Path 427" d="M833.626,371a2,2,0,0,1-1.949,2.131l-121.615,2.514a2,2,0,0,1-2.033-1.813L697.575,265.156a2,2,0,0,1,1.9-2.189l120.693-6,1.3-.065a1.994,1.994,0,0,1,2.092,1.819Z" transform="translate(308.06 17.643)" fill="#65617d"/>
<path id="Path_428" data-name="Path 428" d="M628.93,100.238,739.157,94.82l9.31,98.748-109.356,2.6Z" transform="translate(383.65 186.757)" fill="#00ddf1"/>
<path id="Path_429" data-name="Path 429" d="M899.741,371a2,2,0,0,1-1.949,2.131L886.28,256.963l1.3-.065a2,2,0,0,1,2.092,1.819Z" transform="translate(241.945 17.643)" opacity="0.1"/>
<rect id="Rectangle_261" data-name="Rectangle 261" width="12.343" height="11.096" transform="translate(741.459 419.038)" opacity="0.1"/>
<path id="Path_431" data-name="Path 431" d="M281.574,483.65v3.229l-30.644.819V483.65Z" transform="translate(516.08 50.533)" opacity="0.1"/>
<path id="Path_432" data-name="Path 432" d="M390.8,483.886V593.158a2.6,2.6,0,0,1-2.5,2.566l-124.506,3.313h-.033a2.6,2.6,0,0,1-2.566-2.566V483.886a2.6,2.6,0,0,1,2.566-2.566H388.23A2.6,2.6,0,0,1,390.8,483.886Z" transform="translate(460.942 -60.983)" fill="#65617d"/>
<path id="Path_434" data-name="Path 434" d="M194.6,319.15H309.914v96.311L194.6,418.06Z" transform="translate(535.815 108.164)" fill="#d4dfec"/>
<rect id="Rectangle_262" data-name="Rectangle 262" width="12.343" height="11.317" transform="translate(1073.647 419.038)" opacity="0.1"/>
<path id="Path_435" data-name="Path 435" d="M709.574,483.65v4.164L678.93,487V483.65Z" transform="translate(366.132 50.533)" opacity="0.1"/>
<path id="Path_436" data-name="Path 436" d="M797.782,483.886V596.471a2.6,2.6,0,0,1-2.6,2.566h0l-124.532-3.313a2.6,2.6,0,0,1-2.5-2.566V483.886a2.6,2.6,0,0,1,2.566-2.566H795.19a2.6,2.6,0,0,1,2.592,2.566Z" transform="translate(318.365 -60.983)" fill="#65617d"/>
<path id="Path_437" data-name="Path 437" d="M866.289,483.886V596.471a2.6,2.6,0,0,1-2.6,2.566h0V481.32h0a2.6,2.6,0,0,1,2.6,2.566Z" transform="translate(249.859 -60.983)" opacity="0.1"/>
<path id="Path_438" data-name="Path 438" d="M713.414,319.15H598.1v96.311l115.314,2.6Z" transform="translate(394.451 108.164)" fill="#d4dfec"/>
<path id="Path_439" data-name="Path 439" d="M593.3,483.886V593.158a2.6,2.6,0,0,1-2.5,2.566l-124.506,3.313h0a2.6,2.6,0,0,1-2.6-2.566V483.886a2.6,2.6,0,0,1,2.566-2.566H590.73A2.6,2.6,0,0,1,593.3,483.886Z" transform="translate(389.997 -60.983)" fill="#65617d"/>
<path id="Path_440" data-name="Path 440" d="M397.1,319.15H512.414v96.311L397.1,418.06Z" transform="translate(464.87 108.164)" fill="#d4dfec"/>
<path id="Path_441" data-name="Path 441" d="M597.889,533.65V542.1l-98.7.909-1.052.02-37.511.344-.9.013-11.4.1h-.338l-69.5.643-114.086,1.059h-.1l-29.007.273-.312.007L106.1,546.643V536.9l131.562-.864h.312l26.629-.182h.123l183.9-1.215h.188l.11-.006h.305l3.112-.019h.948l48.393-.325,2.858-.013.637-.007Z" transform="translate(566.82 33.015)" opacity="0.1"/>
<circle id="Ellipse_99" data-name="Ellipse 99" cx="33.347" cy="33.347" r="33.347" transform="translate(887.196 363.44)" fill="#fbbebe"/>
<path id="Path_442" data-name="Path 442" d="M383.74,592.973a.806.806,0,0,1,.065-.227c.65-2.332,1.806-6.276,2.67-9.427.11-.39.214-.773.312-1.137.955-3.554,2.813-11.876,3.846-17.066.364-1.826.65-3.248.708-3.963.13-1.1,2.085-5.795,4.3-11.194,1.553-3.794,3.248-7.939,4.489-11.434a39.876,39.876,0,0,0,1.9-6.4,3.313,3.313,0,0,0,0-1.384,9.543,9.543,0,0,1-.312-2.274h0c-.149-4.028,1.052-10.394,2.91-13.065,2.274-3.248,3.9-15.371,3.9-15.371s3.365.487,3.9-2.293a4,4,0,0,0,.065-.91,4.815,4.815,0,0,0-.058-.721c-.578-4.054,9.563-8.368,15.267-9.3a12.769,12.769,0,0,1,1.949-.182,17.694,17.694,0,0,0,4.06-.935q.909-.279,1.949-.65c2.391-.806,5.249-1.871,8.283-3.04,11.408-4.424,25.22-10.394,25.22-10.394.1-.461.208-.9.331-1.338a18,18,0,0,1,10.622-12.3h0v-1.3c0-2.241-.1-4.548-.195-6.847,0-.448-.039-.9-.065-1.345v-.734c0-.455-.046-.91-.071-1.358l-.117-.091a10.66,10.66,0,0,1-2.534-2.729,9.916,9.916,0,0,1-.923-1.949c-.812-2.2-1-4.658-1.546-6.984l-.117-.481a54.579,54.579,0,0,0-2.6-6.873c-1.436-3.521-2.54-7.146-3.638-10.817q-1-3.333-2.02-6.678l-1.026-3.4c-.195-.65-.39-1.3-.539-1.949h0a8.627,8.627,0,0,1-.169-.91h0a6.5,6.5,0,0,1,.156-2.995,20.854,20.854,0,0,1,.858-1.949,5.113,5.113,0,0,0,.325-.9h0a1.947,1.947,0,0,0,.052-.208,3.667,3.667,0,0,0,.071-.7,11.993,11.993,0,0,0-.338-2.527.045.045,0,0,1,0-.032,1.661,1.661,0,0,0-.032-.175,16.564,16.564,0,0,1-.234-1.949,18.483,18.483,0,0,1,2.254-10.115l.123-.234a16.383,16.383,0,0,1,1.2-1.806h0a9.122,9.122,0,0,1,.65-.793,2.594,2.594,0,0,1-3.606-.936,2.475,2.475,0,0,1-.149-.292c-.033-.078-.059-.162-.085-.247-.455-1.592.338-3.287,1.377-4.58a12.012,12.012,0,0,1,3.729-3.053h0a2.51,2.51,0,0,1,.26-.136,11.125,11.125,0,0,1,1.715-.689h0a9.781,9.781,0,0,1,1.059-.286l-2.41-.221-.974-.091A9.414,9.414,0,0,1,479,361.527h.7a7.625,7.625,0,0,1,1.02.084A2.885,2.885,0,0,1,479,358.8a9.362,9.362,0,0,0,5.97,1.988h.247a19.494,19.494,0,0,1-.221-2.124h0a21.545,21.545,0,0,1,0-2.9,5.483,5.483,0,0,0,4.4,1.468l-1.351-1.884a6.165,6.165,0,0,0,4.262,1.332l.312-.033a4.547,4.547,0,0,0,.773-.149h.058c-.123-.156-.234-.318-.344-.487l-.039-.078a6.282,6.282,0,0,1-.65-1.358,4.284,4.284,0,0,1-.156-.565h0a5.684,5.684,0,0,1,.292-3.541c2.1,1.754,4.4,4.151,7.146,2.339s2.839-5.139,7.146-4.8a6.626,6.626,0,0,1,5.464,3.976,4.385,4.385,0,0,1,4.983-1.137,4.45,4.45,0,0,1,2.521,4.476c1.786-.448,3.71-.89,5.425-.214s2.82,2.865,1.845,4.327a.931.931,0,0,1-.091.13c-.8,1.033-2.566,1.6-2.378,2.9l.273.195.845.611q4.97,3.586,9.68,7.536c1.611,1.351,3.326,2.975,3.437,5.087a5.617,5.617,0,0,1-.156,1.54h0c-.1.507-.247,1.013-.357,1.52a12.676,12.676,0,0,0-.221,3.93h0c.045.383.1.76.175,1.143.994,5.022,5.009,9.167,5.405,14.292v.364a11.546,11.546,0,0,1-.045,1.644c-.3,3.118-1.741,6.113-2.91,9.1-.072.182-.143.364-.208.546a90.5,90.5,0,0,0-4.548,18.294,65.14,65.14,0,0,1-1.3,6.555,17.365,17.365,0,0,1-3.307,6.776,10.536,10.536,0,0,1-2.183,1.949,12.132,12.132,0,0,1-1.722.916v.039c.071.4.13.793.2,1.189.039.208.071.416.11.65h0a.089.089,0,0,0,0,.039c.546,3.073,1.169,6.081,1.826,8.939l.331,1.423c8.186,2.956,9.154,9.011,9.212,11.33a6.259,6.259,0,0,1,0,.929s12.343.325,17.216,3.9a13.21,13.21,0,0,0,2.93,1.494,53.917,53.917,0,0,0,6.009,1.877c1.046.273,2.137.539,3.248.8,1.949.448,4.015.884,6.009,1.3,5.321,1.072,10.33,1.949,12.87,2.6,6.061,1.533,19.925,14.825,19.925,14.825s1.624,13.409,3.248,15.364,4.548,8.829,4.548,8.829l10.745,19.106,4.548,8.036h2.923a4.97,4.97,0,0,1,2.085,1.364c.773.689,1.631,1.546,2.384,2.326l1.247,1.332.78.864s4.723.117,6,3.852c3.846-.11,8.569.143,11.876,1.624a9.187,9.187,0,0,1,1.3.7,5.639,5.639,0,0,1,2.683,3.677,5.422,5.422,0,0,1,.117.935c0,.37,0,.741,0,1.1-.234,4.918-3.437,9.011-6.38,11.765l.208.37s-.1.234-.286.65c-.052.123-.117.26-.188.416h0c-.383.819-.994,2.046-1.793,3.482a41.136,41.136,0,0,1-6.217,8.556l-.188.195-37.511.344-.11-.13-7.276-8.679-3.619-4.314-.11-.136-.1,1.033-.351,3.443-.845,8.322-.045.416v.11l-.1.961.071-.961h-.188l-69.513.65-114.092,1.26v.546h-.091v-.546l-29.072.312Z" transform="translate(418.007 -14.269)" fill="url(#linear-gradient)"/>
<path id="Path_443" data-name="Path 443" d="M586.185,511.522s-64.641,7.8-58.469,0c2.235-2.82,2.852-11.174,2.729-20.691-.039-2.891-.143-5.886-.292-8.868-.715-14.292-2.436-28.26-2.436-28.26s56.52-26.636,50.023-5.522c-2.6,8.53-1.748,20.51.227,31.755.578,3.281,1.247,6.5,1.949,9.55a223.892,223.892,0,0,0,6.269,22.036Z" transform="translate(367.711 -46.521)" fill="#fbbebe"/>
<path id="Path_444" data-name="Path 444" d="M586.185,537.354s-64.641,7.8-58.469,0c2.235-2.82,2.852-11.174,2.729-20.692,9.855-4.21,22.394-1.072,22.394-1.072,13.2-2.631,21.666-2.118,27.078-.273A223.888,223.888,0,0,0,586.185,537.354Z" transform="translate(367.711 -72.353)" opacity="0.1"/>
<path id="Path_445" data-name="Path 445" d="M413.346,651.973v-.546l114.092-1.241,69.513-.65h.195l-.071.961.1-.961h.123v-.11l.89-8.738.338-3.307.1-1.033.091-.864,4.015-13.389,4.015-13.37,3.378-11.258,5.158-17.2s-2.923-6.821-4.548-8.77-3.248-15.267-3.248-15.267-13.864-13.208-19.925-14.728c-2.54-.65-7.555-1.514-12.883-2.6-1.994-.4-4.041-.832-6.009-1.3-1.111-.253-2.2-.52-3.248-.786a57.086,57.086,0,0,1-6.009-1.858,13.448,13.448,0,0,1-2.924-1.488c-4.775-3.5-16.742-3.9-17.2-3.9h0a.269.269,0,0,1,0-.045v-.058a6.66,6.66,0,0,0,0-.819,5.208,5.208,0,0,0-.059-.91.82.82,0,0,0-.045-.325c-.032-.234-.071-.481-.13-.741a3.226,3.226,0,0,0-.078-.344,11.181,11.181,0,0,0-.812-2.267c-.045-.1-.1-.214-.156-.318a11.861,11.861,0,0,0-1.1-1.709c-.084-.11-.175-.227-.273-.338a12.721,12.721,0,0,0-1.767-1.715c-.175-.136-.357-.279-.546-.409a3.026,3.026,0,0,0-.331-.234l-.578-.377-.539-.312c-.474-.26-.974-.513-1.52-.754-.169-.078-.351-.149-.533-.221s-.468-.182-.708-.273h-.039l-.487-.195c-.37-.123-.747-.234-1.143-.344l-.6-.156-.65-.149-.65-.136c-.65-.13-1.345-.247-2.072-.338l-.741-.091-.76-.078-.786-.065-1.117-.065-1.3-.045a81.017,81.017,0,0,0-17.054,1.814,46.946,46.946,0,0,0-11.855-1.093h-.565l-.65.039h-.416l-.838.078a6.224,6.224,0,0,0-.845.1c-.279.039-.572.071-.851.117l-.429.071c-.422.071-.851.149-1.3.24q-.214.039-.429.1c-.565.123-1.13.273-1.689.442-.279.078-.559.169-.838.266-.143.039-.279.091-.416.143l-.416.149-.409.162-.487.195c-.247.1-.487.214-.728.331-.136.058-.273.123-.4.195s-.266.13-.39.2a18.03,18.03,0,0,0-4.034,2.846l-.331.318-.325.331c-.11.11-.214.227-.318.344a15.473,15.473,0,0,0-1.182,1.462c-.1.136-.2.273-.3.416a17.335,17.335,0,0,0-1.117,1.9c-.084.156-.162.318-.24.474a21.243,21.243,0,0,0-1.3,3.411q-.182.65-.331,1.3s-13.753,6.068-25.161,10.46c-3.034,1.169-5.892,2.228-8.283,3.027-.7.234-1.345.448-1.949.65a17.347,17.347,0,0,1-4.06.935,12.778,12.778,0,0,0-1.949.182c-5.243.851-14.227,4.548-15.208,8.257a2.4,2.4,0,0,0-.065.91v.071c.65,4.548-3.9,3.9-3.9,3.9s-1.624,12.019-3.9,15.267c-1.644,2.339-2.768,7.555-2.91,11.492h0a12.741,12.741,0,0,0,.286,3.658v.091c.26.871-.364,3.248-1.423,6.3-1.15,3.346-2.826,7.5-4.437,11.427-2.43,5.925-4.716,11.3-4.859,12.486-.058.526-.227,1.468-.461,2.683-.948,4.95-3.053,14.377-4.093,18.19-.773,2.845-1.9,6.743-2.67,9.42a.91.91,0,0,1-.065.227l29.124-.286v.546h.091Z" transform="translate(417.856 -73.042)" fill="#00ddf1"/>
<path id="Path_446" data-name="Path 446" d="M445.44,607.57s37.03,19.165,50.348,16.891Z" transform="translate(396.391 -105.214)" opacity="0.1"/>
<path id="Path_447" data-name="Path 447" d="M561.44,595.57s36.056,11.694,48.074,13.318S561.44,595.57,561.44,595.57Z" transform="translate(355.751 -101.01)" opacity="0.1"/>
<path id="Path_448" data-name="Path 448" d="M585.443,530.686c-18.84,3.469-54.311,2.722-69.643,2.2,5.62-20.139,33.022-13.292,33.022-13.292C582.74,512.821,585.339,526.866,585.443,530.686Z" transform="translate(371.74 -73.754)" opacity="0.1"/>
<path id="Path_449" data-name="Path 449" d="M585.443,528.686c-18.84,3.469-54.311,2.722-69.643,2.2,5.62-20.139,33.022-13.292,33.022-13.292C582.74,510.821,585.339,524.866,585.443,528.686Z" transform="translate(371.74 -73.053)" fill="#00ddf1"/>
<path id="Path_450" data-name="Path 450" d="M776.94,672.008s22.192-3.411,22.628,6.334S788.25,694.9,788.25,694.9Z" transform="translate(280.251 -127.587)" fill="#fbbebe"/>
<path id="Path_451" data-name="Path 451" d="M578.17,479.936a30.558,30.558,0,0,1-2.923,1.13c-7,2.417-14.065,4.853-21.439,5.736s-15.111.1-21.543-3.573a18.685,18.685,0,0,1-1.949-1.267c-.715-14.292-2.436-28.26-2.436-28.26s56.52-26.636,50.023-5.522C575.318,456.711,576.195,468.69,578.17,479.936Z" transform="translate(367.508 -46.521)" opacity="0.1"/>
<path id="Path_452" data-name="Path 452" d="M536.9,360.29a6.153,6.153,0,0,1-5.405-1.137l1.351,1.878a5.5,5.5,0,0,1-4.4-1.462,22.146,22.146,0,0,0,.208,5.035,9.433,9.433,0,0,1-6.211-1.949,2.872,2.872,0,0,0,1.715,2.8,9.316,9.316,0,0,0-10.135,6.958l3.391.312a12,12,0,0,0-6.782,4.138c-1.039,1.3-1.832,2.962-1.377,4.548s2.651,2.6,3.846,1.468a18.151,18.151,0,0,0-3.963,14.806,9.4,9.4,0,0,1,.3,3.417,28.993,28.993,0,0,1-1.228,3.047c-.65,1.9-.032,3.956.546,5.847l3.047,10.018c1.1,3.619,2.2,7.244,3.645,10.745a53.328,53.328,0,0,1,2.6,6.828c.819,3.144.851,6.588,2.6,9.336a12.948,12.948,0,0,0,4.665,4.112c6.425,3.677,14.188,4.457,21.542,3.573s14.409-3.32,21.406-5.736a20.141,20.141,0,0,0,4.444-1.949c4.84-3.17,5.918-9.654,6.821-15.364a87.242,87.242,0,0,1,4.736-18.71c1.416-3.567,3.248-7.185,2.936-11.005-.4-5.074-4.411-9.186-5.405-14.175a12.344,12.344,0,0,1,.045-5.048,11.473,11.473,0,0,0,.513-3.053c-.11-2.092-1.826-3.7-3.437-5.048q-5.243-4.379-10.823-8.277c-.188-1.3,1.579-1.858,2.378-2.884,1.13-1.449-.039-3.748-1.754-4.424s-3.638-.234-5.425.214a4.281,4.281,0,0,0-7.5-3.32,6.627,6.627,0,0,0-5.47-3.95c-4.307-.338-4.392,2.956-7.146,4.768s-5.028-.578-7.146-2.319A6.029,6.029,0,0,0,536.9,360.29Z" transform="translate(374.5 -15.625)" fill="#3f3d56"/>
<path id="Path_453" data-name="Path 453" d="M768.171,669.128s-.578,1.377-1.644,3.372a44.83,44.83,0,0,1-5.847,8.556l-.175.188h-1.052l-37.511.344h-.9l-.11-.13-7.276-8.634-2.741-3.255-.11-.136-.234-.273-.13-.156-.169-.2-5.334-6.328,1.949-8.121,3.32-13.682.084-.331.65-2.6.461-1.949,1.546-6.354,5.3-21.861,9.42,4.872,9.933,17.541,5.334,9.42h2.923c.552,0,1.819,1.065,3.092,2.293.455.435.91.9,1.3,1.3,1.156,1.2,2.072,2.222,2.072,2.222s4.736.1,6.009,3.833a4.537,4.537,0,0,1,.162.552,26.191,26.191,0,0,0,1.644,4.262c.838,1.826,1.891,3.9,2.956,5.97,1.981,3.8,4,7.419,4.736,8.731l.091.162Z" transform="translate(305.476 -105.217)" fill="#00ddf1"/>
<path id="Path_454" data-name="Path 454" d="M615.681,653.093l-.065.929v.065l-.11,1.494-.864,12.025L613.6,682.093l-.3,4.08-.65,8.731v.11l-69.513.65L429.061,696.9v.546h-.091v-.728l.292-9.329.559-18.229L430.3,653.7l.045-1.54a6.841,6.841,0,0,1,7.419-6.607c3.066.26,7.049.578,11.811.916l1.949.143c27.5,1.91,78.322,4.379,129.606,1.3,1.078-.059,2.163-.123,3.248-.2,7.952-.5,15.9-1.143,23.764-1.949a6.841,6.841,0,0,1,7.536,7.3Z" transform="translate(402.161 -118.514)" opacity="0.1"/>
<path id="Path_455" data-name="Path 455" d="M429.08,698.857v-.546l114.092-1.241,69.513-.65h.195v-.11l.65-8.731.279-3.9,1.065-14.689.838-11.629v-.286a6.893,6.893,0,0,0-.071-1.6.2.2,0,0,0,0-.065,6.751,6.751,0,0,0-1.3-3.014,6.847,6.847,0,0,0-6.12-2.6c-7.867.806-15.813,1.449-23.764,1.949-1.085.078-2.17.143-3.248.2-51.284,3.047-102.106.578-129.606-1.3l-1.949-.143c-4.762-.338-8.744-.65-11.811-.916a6.847,6.847,0,0,0-7.3,5.542,7.146,7.146,0,0,0-.117,1.065l-.442,14.4-.6,18.236-.286,9.329v.728Z" transform="translate(402.122 -119.926)" fill="#3f3d56"/>
<path id="Path_456" data-name="Path 456" d="M615.925,661.692l-.8,9.959L613.937,686.5l-.3,3.716-.65,8.322-.039.416v.11h0l-.1.961.071-.961h-.188l-69.513.65L429.11,700.944v-.182l.318-9.329.65-18.229.416-12.116a4.132,4.132,0,0,1,1.988-3.411,4.061,4.061,0,0,1,2.456-.585c1.364.11,3.04.24,5,.383,3.177.234,7.094.507,11.655.793,8.445.533,19.041,1.1,31.183,1.572,33.782,1.3,79.388,1.735,122.707-2.059,1.949-.169,3.963-.357,5.931-.546a4.066,4.066,0,0,1,2.261.429,3.346,3.346,0,0,1,.559.351,3.989,3.989,0,0,1,1.3,1.6,2.315,2.315,0,0,1,.162.4A4.08,4.08,0,0,1,615.925,661.692Z" transform="translate(402.112 -122.559)" opacity="0.1"/>
<path id="Path_457" data-name="Path 457" d="M360.914,677.87v2.072a3.982,3.982,0,0,1-2.274,3.6l-26.051.5a3.976,3.976,0,0,1-2.319-3.619v-1.949Z" transform="translate(436.74 -129.843)" opacity="0.1"/>
<path id="Path_458" data-name="Path 458" d="M280.294,512.532l-33.944.65V507.55l33.944-.65Z" transform="translate(517.685 42.387)" fill="#3f3d56"/>
<path id="Path_459" data-name="Path 459" d="M280.294,512.532l-33.944.65V507.55l33.944-.65Z" transform="translate(517.685 42.387)" opacity="0.1"/>
<path id="Path_460" data-name="Path 460" d="M282.294,512.532l-33.944.65V507.55l33.944-.65Z" transform="translate(516.984 42.387)" fill="#3f3d56"/>
<path id="Path_461" data-name="Path 461" d="M552.228,360.039A6.334,6.334,0,0,1,551,357.22a6.165,6.165,0,0,0,.273,2.988A5.847,5.847,0,0,0,552.228,360.039Z" transform="translate(359.434 -17.505)"/>
<path id="Path_462" data-name="Path 462" d="M540.1,366.9a22.83,22.83,0,0,1-.24-2.4c0,.8,0,1.6,0,2.41Z" transform="translate(363.311 -20.056)"/>
<path id="Path_463" data-name="Path 463" d="M621.706,398.627a11.912,11.912,0,0,1,.234-1.722,11.7,11.7,0,0,0,.52-3.047,4.008,4.008,0,0,0-.1-.689c-.11.6-.286,1.2-.416,1.787a12.433,12.433,0,0,0-.234,3.671Z" transform="translate(334.652 -30.1)"/>
<path id="Path_464" data-name="Path 464" d="M600.922,368.894l.708.513a12.8,12.8,0,0,0,1.67-1.442,2.384,2.384,0,0,0,.247-2.365,1.95,1.95,0,0,1-.247.416C602.5,367.042,600.734,367.607,600.922,368.894Z" transform="translate(341.923 -20.441)"/>
<path id="Path_465" data-name="Path 465" d="M518.455,380.29a8,8,0,0,0-.565,1.481,11.8,11.8,0,0,1,3.248-1.228Z" transform="translate(371.008 -25.587)"/>
<path id="Path_466" data-name="Path 466" d="M531.888,368.979a9.637,9.637,0,0,1-1.221-.8,2.758,2.758,0,0,0,.058.767,7.7,7.7,0,0,1,1.163.033Z" transform="translate(366.534 -21.345)"/>
<path id="Path_467" data-name="Path 467" d="M587.579,428.33c-.266,3.151-1.735,6.185-2.923,9.173a87.2,87.2,0,0,0-4.736,18.717c-.9,5.71-1.949,12.194-6.821,15.358a19.488,19.488,0,0,1-4.437,1.949c-7,2.423-14.065,4.853-21.439,5.736s-15.111.11-21.543-3.567a12.993,12.993,0,0,1-4.664-4.112c-1.735-2.748-1.767-6.191-2.6-9.336a53.424,53.424,0,0,0-2.6-6.834c-1.436-3.5-2.54-7.146-3.638-10.739q-1.527-5.009-3.047-10.024a18.716,18.716,0,0,1-.741-3.086,11.644,11.644,0,0,0,.741,5.035q1.52,5.022,3.047,10.024c1.1,3.619,2.2,7.244,3.638,10.739a53.417,53.417,0,0,1,2.6,6.834c.819,3.144.851,6.587,2.6,9.336a12.993,12.993,0,0,0,4.664,4.112c6.432,3.677,14.188,4.45,21.543,3.567s14.409-3.313,21.439-5.736a19.487,19.487,0,0,0,4.437-1.949c4.84-3.164,5.918-9.647,6.821-15.358a87.2,87.2,0,0,1,4.736-18.717c1.416-3.56,3.248-7.179,2.936-11.005C587.592,428.408,587.579,428.369,587.579,428.33Z" transform="translate(374.359 -42.418)"/>
<path id="Path_468" data-name="Path 468" d="M510.318,421.419v-.071a9.1,9.1,0,0,0-.3-3.411,17.272,17.272,0,0,1-.253-2.157,17.769,17.769,0,0,0,.253,4.106C510.123,420.393,510.24,420.906,510.318,421.419Z" transform="translate(373.864 -38.021)"/>
<path id="Path_469" data-name="Path 469" d="M512.452,397.929a18.02,18.02,0,0,1,1.7-2.384c-1.189,1.137-3.385.123-3.846-1.455a3.788,3.788,0,0,0,0,1.949,2.852,2.852,0,0,0,2.15,1.89Z" transform="translate(373.712 -30.422)"/>
<path id="Path_470" data-name="Path 470" d="M762.946,656.57s2.059,7.471,0,13.968S762.946,656.57,762.946,656.57Z" transform="translate(285.475 -122.381)" opacity="0.1"/>
<path id="Path_471" data-name="Path 471" d="M776,668.3s.864,9.485-1.085,11.168S776,668.3,776,668.3Z" transform="translate(281.189 -126.49)" opacity="0.1"/>
<line id="Line_88" data-name="Line 88" y1="0.65" x2="66.011" transform="translate(733.267 442.068)" fill="none" stroke="#00ddf1" stroke-miterlimit="10" stroke-width="2"/>
<line id="Line_89" data-name="Line 89" y1="0.643" x2="66.011" transform="translate(733.267 450.176)" fill="none" stroke="#00ddf1" stroke-miterlimit="10" stroke-width="2"/>
<line id="Line_90" data-name="Line 90" y1="0.65" x2="66.011" transform="translate(733.267 458.277)" fill="none" stroke="#00ddf1" stroke-miterlimit="10" stroke-width="2"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.0 KiB

File diff suppressed because it is too large Load Diff
@@ -0,0 +1,50 @@
import React, { Component } from "react";
export class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return {
hasError: true
};
}
componentDidCatch(error, info) {
console.log(error);
console.log(info);
}
render() {
if (this.state.hasError) {
return (
<div className="p-2">
<div
style={{
height: "100vh",
display: "flex",
flexFlow: "column"
}}
>
{/* <img src="./images/1210964-link.jpg" alt="" /> */}
<h1
style={{
fontSize: "2em",
fontFamily: "sans-serif",
textShadow: "0 0 20px black"
}}
>
Something went wrong.
</h1>
</div>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
+49
View File
@@ -0,0 +1,49 @@
import React, { useEffect, useState } from "react";
import Package from "../../package.json";
const Footer = () => {
let footer = localStorage.getItem("_appName");
const [showButton, setShowButton] = useState(false);
const handleScroll = () => {
if (window.pageYOffset >= 50) {
setShowButton(true);
} else {
setShowButton(false);
}
};
const scrollToTop = () => {
window.scrollTo(0, 0);
setShowButton(false);
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<>
<div className="bg-[#222c3c] text-[#98a6ba] text-center text-[13px] py-3">
All Rights Reserved &copy; {new Date().getFullYear()} &nbsp;
{footer && `${footer.charAt(0).toUpperCase()}${footer.slice(1)}`}{" "}
(version:{" "}
{localStorage.getItem("appVersion") &&
`${Package.version}.${localStorage.getItem("appVersion")}`}
)
</div>
<button
className={`${
showButton ? "block" : "hidden"
} fixed bottom-4 right-4 px-3 p-2 text-xl bg-blue-500 text-white rounded focus:outline-none`}
onClick={scrollToTop}
>
<i className="fa-solid fa-angle-up"></i>
</button>
</>
);
};
export default Footer;
@@ -0,0 +1,82 @@
// FullScreenButton.js
import React, { useState, useEffect } from "react";
const FullScreenButton = () => {
const [isFullScreen, setIsFullScreen] = useState(false);
useEffect(() => {
document.addEventListener("fullscreenchange", handleFullScreenChange);
document.addEventListener("webkitfullscreenchange", handleFullScreenChange);
document.addEventListener("mozfullscreenchange", handleFullScreenChange);
document.addEventListener("MSFullscreenChange", handleFullScreenChange);
return () => {
document.removeEventListener("fullscreenchange", handleFullScreenChange);
document.removeEventListener(
"webkitfullscreenchange",
handleFullScreenChange
);
document.removeEventListener(
"mozfullscreenchange",
handleFullScreenChange
);
document.removeEventListener(
"MSFullscreenChange",
handleFullScreenChange
);
};
}, []);
const handleFullScreenChange = () => {
setIsFullScreen(!!document.fullscreenElement);
};
const toggleFullScreen = () => {
if (isFullScreen) {
exitFullScreen();
} else {
requestFullScreen();
}
};
const requestFullScreen = () => {
if (document.documentElement.requestFullscreen) {
document.documentElement.requestFullscreen();
} else if (document.documentElement.mozRequestFullScreen) {
document.documentElement.mozRequestFullScreen();
} else if (document.documentElement.webkitRequestFullscreen) {
document.documentElement.webkitRequestFullscreen();
} else if (document.documentElement.msRequestFullscreen) {
document.documentElement.msRequestFullscreen();
}
};
const exitFullScreen = () => {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
};
return (
<div className="flex items-center">
<button
onClick={toggleFullScreen}
className="text-black p-2 text-sm focus:outline-none"
>
{isFullScreen ? (
<i className="fa-solid fa-compress"></i>
) : (
<i className="fa fa-maximize"></i>
)}
</button>
</div>
);
};
export default FullScreenButton;
+148
View File
@@ -0,0 +1,148 @@
import React, { useState, useEffect } from "react";
import dp from "../assets/images/dp.png";
import FullScreenButton from "./FullScreenButton";
import { useNavigate } from "react-router-dom";
import Parse from "parse";
import { useWindowSize } from "../hook/useWindowSize";
const Header = ({ showSidebar }) => {
const navigation = useNavigate();
const { width } = useWindowSize();
let applogo = localStorage.getItem("appLogo") || "";
let username = localStorage.getItem("username");
const image = localStorage.getItem("profileImg") || dp;
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [isOpen, setIsOpen] = useState(false);
const toggleDropdown = () => {
setIsOpen(!isOpen);
};
const closeDropdown = () => {
setIsOpen(false);
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
Parse.User.logOut();
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 baseUrr = localStorage.getItem("BaseUrl12");
let appidd = 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", baseUrr);
localStorage.setItem("AppID12", appidd);
navigation("/");
};
//handle to close profile drop down menu onclick screen
useEffect(() => {
const closeMenuOnOutsideClick = (e) => {
if (isOpen && !e.target.closest("#profile-menu")) {
setIsOpen(false);
}
};
document.addEventListener("click", closeMenuOnOutsideClick);
return () => {
// Cleanup the event listener when the component unmounts
document.removeEventListener("click", closeMenuOnOutsideClick);
};
}, [isOpen]);
return (
<div className="flex flex-row justify-between items-center gap-x-3 md:gap-x-4 bg-white md:px-4 px-2 shadow h-[50px] md:w-full ">
<button
className="cursor-pointer focus:outline-none"
onClick={showSidebar}
>
<i className={`fa-solid fa-bars text-xl `}></i>
</button>
<div className="flex-1">
<div className="h-[25px] md:h-[40px] w-auto overflow-hidden">
<img
className="object-contain h-full w-auto"
src={applogo}
alt="img"
/>
</div>
</div>
<div className="flex justify-between items-center gap-x-3">
<div>
<FullScreenButton />
</div>
{width >= 768 && (
<div
onClick={toggleDropdown}
className="cursor-pointer w-[35px] h-[35px] rounded-full ring-[1px] ring-offset-2 ring-gray-400 overflow-hidden"
>
<img
className="w-[35px] h-[35px] object-contain"
src={image}
alt="img"
/>
</div>
)}
{width >= 768 && (
<div onClick={toggleDropdown} className="cursor-pointer text-sm">
{username && username}
</div>
)}
<div className="relative" id="profile-menu">
<div className="cursor-pointer">
<i onClick={toggleDropdown} className="fa-solid fa-angle-down"></i>
</div>
<div
className={`dropdown absolute text-sm text-gray-700 font-light right-0 mt-4 p-1 w-48 bg-white border rounded-lg shadow-lg z-10 ${
isOpen ? "block" : "hidden"
}`}
>
<ul>
<li
className="hover:bg-gray-100 rounded-t-lg py-1 px-2 cursor-pointer font-normal"
onClick={() => {
setIsOpen(false);
navigation("/profile");
}}
>
<i className="fa-regular fa-user"></i> Profile
</li>
<li
className="hover:bg-gray-100 py-1 px-2 cursor-pointer font-normal"
onClick={() => {
setIsOpen(false);
navigation("/changepassword");
}}
>
<i className="fa-solid fa-lock"></i> Change Password
</li>
<li
className="hover:bg-gray-100 rounded-b-lg py-1 px-2 cursor-pointer font-normal"
onClick={closeDropdown}
>
<i className="fa-solid fa-arrow-right-from-bracket"></i> Log Out
</li>
</ul>
</div>
</div>
</div>
</div>
);
};
export default Header;
@@ -0,0 +1,236 @@
import React, { useState } from "react";
import Parse from "parse";
// import FacebookLogin from "react-facebook-login";
const LoginFacebook = ({
FBCred,
thirdpartyLoginfn,
thirdpartyLoader,
setThirdpartyLoader
}) => {
const [isModal, setIsModal] = useState(false);
const [userDetails, setUserDetails] = useState({
Phone: "",
Company: "",
Name: "",
Email: ""
});
const [fBDetails, setFBDetails] = useState({
Id: "",
AccessToken: "",
Name: "",
Email: ""
});
// const responseFacebook = async (response) => {
// // console.log("response ", response);
// if (response.userID) {
// setThirdpartyLoader(true);
// const details = {
// Email: response.email,
// Name: response.name,
// };
// setUserDetails({ ...userDetails, ...details });
// const fDetails = {
// Id: response.userID,
// AccessToken: response.accessToken,
// Name: response.name,
// Email: response.email,
// };
// setFBDetails({ ...fBDetails, ...fDetails });
// const res = await checkExtUser(fDetails);
// }
// };
const checkExtUser = async (details) => {
const extUser = new Parse.Query("contracts_Users");
extUser.equalTo("Email", details.Email);
const extRes = await extUser.first();
// console.log("extRes ", extRes);
if (extRes) {
const params = { ...details, Phone: extRes.get("Phone") };
const payload = await Parse.Cloud.run("facebooksign", params);
// console.log("payload ", payload);
if (payload && payload.sessiontoken) {
const billingDate =
extRes.get("Next_billing_date") && extRes.get("Next_billing_date");
// console.log("billingDate expired", billingDate > new Date());
const LocalUserDetails = {
name: details.Name,
email: details.Email,
phone: extRes.get("Phone"),
company: extRes.get("Company")
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
thirdpartyLoginfn(payload.sessiontoken, billingDate);
}
return { msg: "exist" };
} else {
setIsModal(true);
setThirdpartyLoader(false);
return { msg: "notexist" };
}
};
const handleSubmitbtn = async () => {
if (userDetails.Phone && userDetails.Company) {
setThirdpartyLoader(true);
const params = { ...fBDetails, Phone: userDetails.Phone };
const payload = await Parse.Cloud.run("facebooksign", params);
// console.log("payload ", payload);
if (payload && payload.sessiontoken) {
const params = {
userDetails: {
name: userDetails.Name,
email: userDetails.Email,
// "passsword":userDetails.Phone,
phone: userDetails.Phone,
role: "contracts_Admin",
company: userDetails.Company
}
};
const userSignUp = await Parse.Cloud.run("usersignup", params);
// console.log("userSignUp ", userSignUp);
if (userSignUp && userSignUp.sessionToken) {
const LocalUserDetails = {
name: userDetails.Name,
email: userDetails.Email,
phone: userDetails.Phone,
company: userDetails.Company
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
thirdpartyLoginfn(userSignUp.sessionToken);
} else {
alert(userSignUp.message);
}
} else {
alert("Internal server error !");
}
} else {
alert("Please fill required details!");
}
};
return (
<div style={{ position: "relative" }}>
{thirdpartyLoader && (
<div
style={{
position: "fixed",
width: "100vw",
height: "100vh",
backgroundColor: "rgba(0,0,0,0.2)",
top: 0,
left: 0,
zIndex: 2
}}
>
<div
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
}}
className="loader-37"
></div>
</div>
)}
{/* <FacebookLogin
appId={FBCred}
fields="name,email,picture"
callback={responseFacebook}
cssClass="btn btn-info btn-md btn-fb"
icon="fa fa-facebook-f"
/> */}
{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>
<button
type="button"
className="btn btn-secondary"
onClick={() => setIsModal(false)}
style={{ marginRight: 10, width: 90 }}
>
Cancel
</button>
<button
type="button"
onClick={() => handleSubmitbtn()}
className="btn btn-info"
>
Sign up
</button>
</div>
</form>
</div>
</div>
</div>
</div>
)}
</div>
);
};
export default LoginFacebook;
+286
View File
@@ -0,0 +1,286 @@
import React, { useState, useRef } from "react";
import Parse from "parse";
import jwtDecode from "jwt-decode";
import { useScript } from "../hook/useScript";
/*
* `GoogleSignInBtn`as it's name indicates it render google sign in button
* and in this `useScript` in which we have created for generate google sign button
* and when user click on sign in with google it will be verify on server side
* and then generate token
*/
const GoogleSignInBtn = ({
GoogleCred,
thirdpartyLoginfn,
thirdpartyLoader,
setThirdpartyLoader
}) => {
const [isModal, setIsModal] = useState(false);
const googleBtn = useRef();
const [userDetails, setUserDetails] = useState({
Phone: "",
Company: "",
Name: "",
Email: "",
Destination: ""
});
const [googleDetails, setGoogleDetails] = useState({
Id: "",
TokenId: "",
Gmail: "",
Name: ""
});
useScript("https://accounts.google.com/gsi/client", () => {
window.google.accounts.id.initialize({
client_id: GoogleCred,
callback: responseGoogle,
auto_select: false
});
window.google.accounts.id.renderButton(googleBtn.current, {
theme: "outline",
size: "large",
width: "187px"
});
});
const responseGoogle = async (response) => {
setThirdpartyLoader(true);
// console.log("response ", response);
if (response.credential) {
const data = jwtDecode(response.credential);
// console.log("data ", data);
if (data.sub && data.email) {
const details = {
Email: data.email,
Name: data.name
};
setUserDetails({ ...userDetails, ...details });
const Gdetails = {
Id: data.sub,
TokenId: response.credential,
Gmail: data.email,
Name: data.name
};
setGoogleDetails({ ...googleDetails, ...Gdetails });
await checkExtUser(Gdetails);
}
}
};
const checkExtUser = async (details) => {
const extUser = new Parse.Query("contracts_Users");
extUser.equalTo("Email", details.Gmail);
const extRes = await extUser.first();
// console.log("extRes ", extRes);
if (extRes) {
const params = { ...details, Phone: extRes.get("Phone") };
const payload = await Parse.Cloud.run("googlesign", params);
// console.log("payload ", payload);
if (payload && payload.sessiontoken) {
// setThirdpartyLoader(true);
const billingDate =
extRes.get("Next_billing_date") && extRes.get("Next_billing_date");
// console.log("billingDate expired", billingDate > new Date());
const LocalUserDetails = {
name: details.Name,
email: details.Gmail,
phone: extRes.get("Phone"),
company: extRes.get("Company")
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
thirdpartyLoginfn(payload.sessiontoken, billingDate);
}
return { msg: "exist" };
} else {
setIsModal(true);
setThirdpartyLoader(false);
return { msg: "notexist" };
}
};
const handleSubmitbtn = async () => {
if (userDetails.Phone && userDetails.Company) {
setThirdpartyLoader(true);
// e.preventDefault()
// console.log("handelSubmit", userDetails);
const params = { ...googleDetails, Phone: userDetails.Phone };
const payload = await Parse.Cloud.run("googlesign", params);
// console.log("payload ", payload);
if (payload && payload.sessiontoken) {
const params = {
userDetails: {
name: userDetails.Name,
email: userDetails.Email,
// "passsword":userDetails.Phone,
phone: userDetails.Phone,
role: "contracts_Admin",
company: userDetails.Company,
jobTitle: userDetails.Destination
}
};
const userSignUp = await Parse.Cloud.run("usersignup", params);
// console.log("userSignUp ", userSignUp);
if (userSignUp && userSignUp.sessionToken) {
const LocalUserDetails = {
name: userDetails.Name,
email: userDetails.Email,
phone: userDetails.Phone,
company: userDetails.Company
// jobTitle: userDetails.JobTitle
};
localStorage.setItem("userDetails", JSON.stringify(LocalUserDetails));
thirdpartyLoginfn(userSignUp.sessionToken);
} else {
alert(userSignUp.message);
}
} else if (
payload &&
payload.message.replace(/ /g, "_") === "Internal_server_err"
) {
alert("Internal server error !");
}
} else {
alert("Please fill required details!");
}
};
return (
<div style={{ position: "relative" }}>
{thirdpartyLoader && (
<div
style={{
position: "fixed",
width: "100vw",
height: "100vh",
backgroundColor: "rgba(0,0,0,0.2)",
top: 0,
left: 0,
zIndex: 2
}}
>
<div
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
}}
className="loader-37"
></div>
</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="Destination"
style={{ display: "flex" }}
className="col-form-label"
>
Destination{" "}
<span style={{ fontSize: 13, color: "red" }}>*</span>
</label>
<input
type="text"
className="form-control"
id="Destination"
value={userDetails.Destination}
onChange={(e) =>
setUserDetails({
...userDetails,
Destination: e.target.value
})
}
required
/>
</div>
<div>
<button
type="button"
className="btn btn-secondary"
onClick={() => setIsModal(false)}
style={{ marginRight: 10, width: 90 }}
>
Cancel
</button>
<button
type="button"
onClick={() => handleSubmitbtn()}
className="btn btn-info"
>
Sign up
</button>
</div>
</form>
</div>
</div>
</div>
</div>
)}
</div>
);
};
export default GoogleSignInBtn;
@@ -0,0 +1,83 @@
import useFederatedComponent from "mf-cra";
import React, { Suspense, useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
const MicroappModal = ({ app }) => {
const { remoteApp } = useParams();
useEffect(() => {
return () => localStorage.removeItem("rowlevel");
}, []);
let paramString = remoteApp;
let queryString = new URLSearchParams(paramString);
let obj = {};
for (const [key, value] of queryString.entries()) {
// console.log("value ", key + ":" + value);
if (key === "remoteUrl") {
obj = { ...obj, [key]: atob(value) };
} else {
if (key === "moduleToLoad") {
obj = { ...obj, [key]: "./" + value };
} else {
obj = { ...obj, [key]: value };
}
}
}
// console.log("app ", remoteApp);
const { Component: RemoteComponent } = useFederatedComponent(obj);
const navigate = useNavigate();
// console.log("RemoteComponent ", RemoteComponent);
return (
<div className="w-full h-full flex items-center justify-center ">
{/* <!-- Modal Container --> */}
<div className="bg-white rounded-lg shadow-lg w-full">
{/* <!-- Modal Header --> */}
<div className="flex w-full items-center border-b-2 mb-2 p-4">
<button
className="focus:outline-none bg-blue-500 text-white shadow px-3 py-2 rounded"
id="closeModal"
onClick={(e) => {
e.preventDefault();
// setIsModal(false);
navigate(-1);
}}
>
Back
</button>
</div>
{/* <!-- Modal Body --> */}
<div className="w-full">
<Suspense
fallback={
<div style={{ height: "300px" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<div
style={{
backgroundColor: "#ffffff",
width: "100%",
overflow: "hidden",
minHeight: "50vh"
}}
>
{RemoteComponent && <RemoteComponent />}
</div>
</Suspense>
</div>
</div>
</div>
);
};
export default MicroappModal;
+24
View File
@@ -0,0 +1,24 @@
import React from "react";
import { Helmet } from "react-helmet";
function Title(props) {
return (
<Helmet>
<title>{`${
localStorage.getItem("appTitle") ? localStorage.getItem("appTitle") : ""
} - ${props.title}`}</title>
<meta
name="description"
content={`${localStorage.getItem("appTitle")} - ${props.title}`}
/>
<link
rel="icon"
type="image/png"
href={localStorage.getItem("fev_Icon")}
sizes="40x40"
/>
</Helmet>
);
}
export default Title;
@@ -0,0 +1,387 @@
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) => {
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 (Array.isArray(val.properties[k].data)) {
} else 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[0] !== undefined) {
} else 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) {}
},
(error) => {
setloading(false);
setactive(true);
}
);
});
} catch (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="btn btn-info pull-right" type="submit">
Update
</button>
) : (
<button className="btn btn-info" type="submit" disabled>
Update
</button>
)}
</div>
</Form>
);
};
export default TreeEditForm;
@@ -0,0 +1,237 @@
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;
+892
View File
@@ -0,0 +1,892 @@
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 {
var emp = Parse.Object.extend(
localStorage.getItem("extended_class")
);
var q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
res = await q.first();
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 {
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();
}
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) {}
} 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();
}
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) => {
// 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, i) => {
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;
let condition = false;
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[0] !== undefined) {
} else 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
);
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) => {
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: "40%",
left: "50%",
right: "20%",
bottom: "20%",
marginRight: "-50%",
transform: "translate(-50%, -50%)",
zIndex: "50",
backgroundColor: "white",
padding: "0px",
maxWidth: "100%", // Set a maximum width for the modal
maxHeight: "100vh",
height: "300px"
}
};
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)}
contentLabel="Modal"
style={customStyles}
>
<div>
{/* 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">&times;</span>
</button>
</div>
</div>
<hr />
{/* body */}
<div className="pt-3 pb-3 pl-6 pr-6 space-y-6">
<div
style={{
height: "40px",
color: "#ac4848",
cursor: "pointer",
fontSize: "14px",
fontWeight: "500"
}}
>
<a
onClick={(e) => {
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",
marginRight: "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={(e) => {
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-6 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);
@@ -0,0 +1,337 @@
import React, { useState, useEffect } from "react";
import axios from "axios";
import Parse from "parse";
import onSearchFilter from "../../constant/searchQuery";
import getReplacedHashQuery from "../../constant/getReplacedHashQuery";
import "../../styles/loader.css";
import { useNavigate } from "react-router-dom";
const DashboardCard = (props) => {
const navigate = useNavigate();
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [response, setresponse] = useState("");
const [loading, setLoading] = useState(false);
const renderData = async () => {
if (props.Data.queryType === "function") {
setLoading(true);
try {
let url = `${parseBaseUrl}${props.Data.class}`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: localStorage.getItem("accesstoken")
};
let body = {};
let currentUser;
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
let currentUser1 = Parse.User.current();
currentUser = currentUser1.id;
let res;
if (localStorage.getItem("Extand_Class")) {
let data = JSON.parse(localStorage.getItem("Extand_Class"));
res = data[0];
} else {
var emp = Parse.Object.extend(localStorage.getItem("extended_class"));
var q = new Parse.Query(emp);
q.equalTo("UserId", {
__type: "Pointer",
className: "_User",
objectId: currentUser
});
res = await q.first();
if (res) res = res.toJSON();
}
if (res) {
let json = res;
var reg = /(\#.*?\#)/gi; // eslint-disable-line
var str = props.Data.query;
var test = "";
if (str.includes("#filterCondition#")) {
str = str.replace(
"#filterCondition#",
onSearchFilter(props.DefaultQuery)
);
}
if (props.Data.extendkey) {
let a = props.Data.extendkey.split(".");
if (a.length > 0) {
test = str.replace(reg, json[a[0]][a[1]]);
} else {
test = str.replace(reg, json[a[0]]);
}
} else {
test = str.replace(reg, json.objectId);
}
if (str.replace(reg, json.objectId)) {
body = test;
} else {
body = props.Data.query;
}
} else {
body = props.Data.query;
}
await axios.post(url, body, { headers: headers }).then((res) => {
if (res) {
if (res.data.result.length > 0) {
setresponse(res.data.result[0][props.Data.key]);
} else {
setresponse(0);
}
setLoading(false);
} else {
setLoading(false);
}
});
} catch (e) {
console.error("Problem", e.message);
setLoading(false);
}
} else {
setLoading(true);
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
const currentUser = Parse.User.current();
let reg1 = /(\#.*?\#)/gi; // eslint-disable-line
let _query = props.Data.query;
let str = _query;
var test1;
str = str.split("#$").join("$");
str = str.split("#*").join("$");
str = str.split("_DOT_").join(".");
if (str.includes("#")) {
let resr;
if (localStorage.getItem("Extand_Class")) {
let data = JSON.parse(localStorage.getItem("Extand_Class"));
resr = data[0];
} else {
let emp = Parse.Object.extend(
localStorage.getItem("extended_class")
);
let q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
let t = await q.first();
resr = t.toJSON();
}
let json = resr;
let output = str.match(reg1);
const HashCount = str.match(reg1);
if (HashCount.length > 1) {
// `getReplacedHashQuery` is used to replace multiple hash keyword with actual values from query
test1 = getReplacedHashQuery(str, json);
} else {
output = output.join();
output = output.substring(1, output.length - 1);
output = output.split(".");
if (output.length > 1) {
test1 = str.replace(reg1, json[output[0]][output[1]]);
} else if (json[output[0]]) {
if (typeof json[output[0]] === "object") {
test1 = str.replace(reg1, JSON.stringify(json[output[0]]));
} else {
test1 = str.replace(reg1, json[output[0]]);
}
} else {
test1 = str.replace(reg1, currentUser.id);
}
}
} else {
test1 = str.replace(reg1, currentUser.id);
}
let url = `${parseBaseUrl}classes/${props.Data.class}?${test1}`;
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.data.results.length > 0) {
setLoading(false);
if (props.Data.key !== "count") {
setresponse(res.data.results[0][props.Data.key]);
} else {
setresponse(res.data[props.Data.key]);
}
} else {
setresponse(0);
setLoading(false);
}
});
} catch (e) {
console.error("Problem", e);
setLoading(false);
}
}
};
const filterRender = async () => {
if (props.FilterData && props.FilterData.queryType === "function") {
setLoading(true);
try {
let url = `${parseBaseUrl}${props.FilterData.class}`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: localStorage.getItem("accesstoken")
};
let body = {};
var str = props.FilterData.query;
let restr = JSON.stringify(props.FilterData.query);
var reg = /(\#.*?\#)/gi; // eslint-disable-line
restr = restr.split("#$").join("$");
restr = restr.split("#*").join("$");
restr = restr.split("_DOT_").join(".");
if (restr.includes("#")) {
try {
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 {
var emp = Parse.Object.extend(
localStorage.getItem("extended_class")
);
var q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
let resr = await q.first();
res = resr.toJSON();
}
let json = res;
let output = restr.match(reg);
if (output.length === 1) {
output = output.filter((x) => x === "#filterCondition#");
if (output.length === 1) {
str = str.replace("#filterCondition#", props.Filter);
} else {
output = output.join();
output = output.substring(1, output.length - 1);
output = output.split(".");
if (output.length > 0) {
str = str.replace(reg, json[output[0]][output[1]]);
} else {
str = str.replace(reg, json[output[0]]);
}
}
} else if (output.length === 2) {
output = output.filter((x) => x !== "#filterCondition#");
if (output.length === 1) {
str = str.replace("#filterCondition#", props.Filter);
output = output.join();
output = output.substring(1, output.length - 1);
output = output.split(".");
if (output.length > 1) {
str = str.replace(reg, json[output[0]][output[1]]);
} else {
str = str.replace(reg, json[output[0]]);
}
}
}
body = str;
await axios
.post(url, body, { headers: headers })
.then((response) => {
try {
if (response.data.result.length > 0) {
setresponse(response.data.result[0][props.FilterData.key]);
setLoading(false);
} else {
setresponse("0");
setLoading(false);
}
} catch (error) {
setLoading(false);
}
});
} catch (error) {
setLoading(false);
}
}
} catch (e) {
console.error("Problem", e);
setLoading(false);
}
}
};
const setFormat = (val) => {
switch (props.Format) {
case "INR":
if (val)
return Number(val)
.toFixed(2)
.toString()
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return 0;
default:
return val;
}
};
useEffect(() => {
renderData();
//eslint-disable-next-line
}, []);
useEffect(() => {
if (props.Filter) {
filterRender();
}
//eslint-disable-next-line
}, [props.Filter]);
function openReport() {
if (props.Data && props.Data.Redirect_type) {
const Redirect_type = props.Data.Redirect_type;
const id = props.Data.Redirect_id;
if (Redirect_type === "Form") {
navigate(`/form/${id}`);
} else if (Redirect_type === "Report") {
navigate(`/report/${id}`);
} else if (Redirect_type === "Url") {
window.location = id;
} else if (Redirect_type === "Microapp") {
navigate(`/microapp/${id}`);
}
}
}
return (
<div
onClick={() => openReport()}
className={`${
props.Data && props.Data.Redirect_type
? "cursor-pointer"
: "cursor-default"
} w-full h-[140px] px-3 pt-4 pb-10 text-white rounded-md shadow overflow-hidden`}
>
<div className="flex items-center justify-start gap-5">
<span className="rounded-full bg-black bg-opacity-20 w-[60px] h-[60px] self-start flex justify-center items-center">
<i
className={`${
props.Icon ? props.Icon : "fa fa-solid fa-info"
} text-[25px] lg:text-[30px]`}
></i>
</span>
<div className="">
<div className="text-base lg:text-lg"> {props.Label}</div>
<div className="text-2xl font-light">
{loading ? <div className="loader-01"></div> : setFormat(response)}
</div>
</div>
</div>
</div>
);
};
export default DashboardCard;
@@ -0,0 +1,91 @@
import React, { useEffect, useState } from "react";
import Parse from "parse";
import ReportTable from "../../primitives/GetReportDisplay";
import reportJson from "../../json/ReportJson";
import axios from "axios";
function DashboardReport(props) {
// console.log("props ", props)
const [List, setList] = useState([]);
const [isLoader, setIsLoader] = useState(true);
const [reportName, setReportName] = useState("");
const [actions, setActions] = useState([]);
useEffect(() => {
setReportName("");
getReportData(props.Record.reportId);
}, [props.Record.reportId]);
const getReportData = async (id) => {
setIsLoader(true);
const json = reportJson(id);
if (json) {
setActions(json.actions);
setReportName(json.reportName);
const { className, params, keys, orderBy } = json;
Parse.serverURL = localStorage.getItem("BaseUrl12");
Parse.initialize(localStorage.getItem("AppID12"));
const serverURL =
localStorage.getItem("BaseUrl12") + "classes/" + className;
const strParams = JSON.stringify(params);
const strKeys = keys.join();
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
};
try {
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}`;
const res = await axios.get(url, { headers: headers });
// console.log("res ", res.data?.results);
setList(res.data?.results);
setIsLoader(false);
} catch (err) {
console.log("err ", err);
setIsLoader(false);
}
} else {
setIsLoader(false);
}
};
return (
<>
{isLoader ? (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
) : (
<>
{reportName ? (
<ReportTable
ReportName={reportName}
List={List}
act={"Sign"}
actions={actions}
/>
) : (
<div className="flex items-center justify-center h-[100px] w-full bg-white rounded">
<div className="text-center">
<p className="text-xl text-black">Report Not Found</p>
</div>
</div>
)}
</>
)}
</>
);
}
export default DashboardReport;
@@ -0,0 +1,416 @@
import React, { useState, Suspense, lazy } from "react";
import moment from "moment";
import ErrorBoundary from "../ErrorBoundary";
const DashboardCard = lazy(() => import("./DashboardCard"));
const DashboardReport = lazy(() => import("./DashboardReport"));
const GetDashboard = (props) => {
const [filter, setfilter] = useState("");
const [option, setoption] = useState("");
const onSearchFilter = (e) => {
let _search = e.target.value;
localStorage.setItem("DashboardDefaultFilter", _search);
switch (_search) {
case "Today":
let d = new Date();
let formDate = new Date(
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0)
).toISOString();
let Todate = new Date(
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59)
).toISOString();
let Query = `'$gte':'${formDate}','$lte':'${Todate}'`;
setfilter(Query);
setoption(_search);
break;
case "Yesterday":
let d1 = new Date();
d1.setDate(d1.getDate() - 1);
let yesFrDate = new Date(
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 0, 0, 0)
).toISOString();
let YesTodate = new Date(
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 23, 59, 59)
).toISOString();
let Query1 = `'$gte':'${yesFrDate}','$lte':'${YesTodate}'`;
setfilter(Query1);
setoption(_search);
break;
case "This week":
let oneDay = 24 * 60 * 60 * 1000;
let curr = new Date(); // get current date
let first = curr.getDate() - curr.getDay(); // First day is the day of the month - the day of the week
let firstday = new Date(
new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
0,
0,
0
)
).setDate(first)
).toISOString();
let diffDays = Math.round(
Math.abs(
(new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
23,
59,
59
)
) -
new Date(firstday)) /
oneDay
)
); //Days since last week
let last = first + diffDays;
let lastday = new Date(
new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
23,
59,
59
)
).setDate(last)
).toISOString();
let Query2 = `'$gte':'${firstday}','$lte':'${lastday}'`;
setfilter(Query2);
setoption(_search);
break;
case "Last 7 days":
let d7 = new Date();
let d7l = new Date();
d7.setDate(d7.getDate() - 7);
let l7t = new Date(
Date.UTC(d7l.getFullYear(), d7l.getMonth(), d7l.getDate(), 23, 59, 59)
).toISOString();
let date7 = new Date(
Date.UTC(d7.getFullYear(), d7.getMonth(), d7.getDate(), 0, 0, 0)
).toISOString();
let Query7 = `'$gte':'${date7}','$lte':'${l7t}'`;
setfilter(Query7);
setoption(_search);
break;
case "Last 14 days":
let d14 = new Date();
let d14l = new Date();
let l14t = new Date(
Date.UTC(
d14l.getFullYear(),
d14l.getMonth(),
d14l.getDate(),
23,
59,
59
)
).toISOString();
d14.setDate(d14.getDate() - 14);
let date14 = new Date(
Date.UTC(d14.getFullYear(), d14.getMonth(), d14.getDate(), 0, 0, 0)
).toISOString();
let Query14 = `'$gte':'${date14}','$lte':'${l14t}'`;
setfilter(Query14);
setoption(_search);
break;
case "Last 30 days":
let d30 = new Date();
let d30l = new Date();
let l30t = new Date(
Date.UTC(
d30l.getFullYear(),
d30l.getMonth(),
d30l.getDate(),
23,
59,
59
)
).toISOString();
d30.setDate(d30.getDate() - 30);
let date30 = new Date(
Date.UTC(d30.getFullYear(), d30.getMonth(), d30.getDate(), 0, 0, 0)
).toISOString();
let Query30 = `'$gte':'${date30}','$lte':'${l30t}'`;
setfilter(Query30);
setoption(_search);
break;
case "Last week":
const from_date = moment().startOf("week").subtract(7, "days");
const to_date = moment().endOf("week").subtract(7, "days");
let Queryl = `'$gte':'${from_date.toISOString()}','$lte':'${to_date.toISOString()}'`;
setfilter(Queryl);
setoption(_search);
break;
case "This month":
var tdate = new Date();
var tfirstDay = new Date(
tdate.getFullYear(),
tdate.getMonth(),
1
).toISOString();
var tlastDay = new Date(
tdate.getFullYear(),
tdate.getMonth() + 1,
0
).toISOString();
let Querylt = `'$gte':'${tfirstDay}','$lte':'${tlastDay}'`;
setfilter(Querylt);
setoption(_search);
break;
case "Last month":
var ldate = new Date();
var lfirstDay = new Date(
ldate.getFullYear(),
ldate.getMonth() - 1,
2
).toISOString();
var llastDay = new Date(
ldate.getFullYear(),
ldate.getMonth(),
1
).toISOString();
let Queryltl = `'$gte':'${lfirstDay}','$lte':'${llastDay}'`;
setfilter(Queryltl);
setoption(_search);
break;
case "All":
let fall = new Date(
new Date().getFullYear() - 100,
0,
1,
0,
0,
0
).toISOString();
let fall_year = `'$gte':'${fall}'`;
setfilter(fall_year);
setoption(_search);
break;
case "This year":
let fcy = new Date(
new Date().getFullYear(),
0,
1,
0,
0,
0
).toISOString();
let lcy = new Date(
new Date().getFullYear(),
11,
31,
23,
59,
59
).toISOString();
let cur_year = `'$gte':'${fcy}','$lte':'${lcy}'`;
setfilter(cur_year);
setoption(_search);
break;
case "Last year":
let fly = new Date(
new Date().getFullYear() - 1,
0,
1,
0,
0,
0
).toISOString();
let lly = new Date(
new Date().getFullYear() - 1,
11,
31,
23,
59,
59
).toISOString();
let last_year = `'$gte':'${fly}','$lte':'${lly}'`;
setfilter(last_year);
setoption(_search);
break;
default:
setoption(_search);
break;
}
};
const renderSwitchWithTour = (col) => {
switch (col.widget.type) {
case "Card":
return (
<div
className={"bg-[#2ed8b6] rounded-md shadow mb-4 md:mb-0"}
data-tut={col.widget.data.tourSection}
style={{ background: col.widget.bgColor }}
>
<Suspense fallback={<div>please wait</div>}>
<DashboardCard
Icon={col.widget.icon}
Label={col.widget.label}
Filter={filter}
Format={col.widget.format && col.widget.format}
Data={col.widget.data}
FilterData={col.widget.filter}
DefaultQuery={props.DefaultQuery}
/>
</Suspense>
</div>
);
case "customeHtml":
return (
<div data-tut={col.widget.data.tourSection}>
<select
id="searchFiltr"
className="form-control"
value={
option ||
localStorage.getItem("DashboardDefaultFilter") ||
col.widget.data[0].default
}
onChange={onSearchFilter}
>
{col.widget.data[0].options.map((opt) => (
<option key={opt} value={opt}>
{opt}
</option>
))}
</select>
<br />
</div>
);
case "customeTag":
return (
<h3
data-tut={col.widget.data.tourSection}
style={{
marginBottom: "4px",
color: "currentColor",
marginLeft: "4px"
}}
>
{col.widget.label}
</h3>
);
case "report":
let _filter = `${col.widget.filterKey}:${filter}`;
return (
<div data-tut={col.widget.data.tourSection}>
<Suspense fallback={<div>please wait</div>}>
<div className="mb-4 md:mb-0">
<DashboardReport Filter={_filter} Record={col.widget} />
</div>
</Suspense>
</div>
);
default:
return null;
}
};
const renderSwitch = (col) => {
switch (col.widget.type) {
case "Card":
return (
<div
className={"bg-[#2ed8b6] rounded-md shadow mb-4 md:mb-0"}
style={{ background: col.widget.bgColor }}
>
<Suspense fallback={<div>please wait</div>}>
<DashboardCard
Icon={col.widget.icon}
Label={col.widget.label}
Filter={filter}
Format={col.widget.format && col.widget.format}
Data={col.widget.data}
FilterData={col.widget.filter}
DefaultQuery={props.DefaultQuery}
/>
</Suspense>
</div>
);
case "customeHtml":
return (
<div>
<select
id="searchFiltr"
className="form-control"
value={
option ||
localStorage.getItem("DashboardDefaultFilter") ||
col.widget.data[0].default
}
onChange={onSearchFilter}
>
{col.widget.data[0].options.map((opt) => (
<option key={opt} value={opt}>
{opt}
</option>
))}
</select>
<br />
</div>
);
case "customeTag":
return (
<h3
style={{
marginBottom: "4px",
color: "currentColor",
marginLeft: "4px"
}}
>
{col.widget.label}
</h3>
);
case "report":
let _filter = `${col.widget.filterKey}:${filter}`;
return (
<Suspense fallback={<div>please wait</div>}>
<div className="mb-4 md:mb-0">
<DashboardReport Filter={_filter} Record={col.widget} />
</div>
</Suspense>
);
default:
return null;
}
};
return (
<ErrorBoundary>
<div>
{props.dashboard.map((val, key) => (
<div key={"a" + key} className="row">
{val.columns.map((col, i) =>
col.widget.data && col.widget.data.tourSection ? (
<div key={i} className={props.classnameArray[key][i]}>
{renderSwitchWithTour(col)}
</div>
) : (
<div key={i} className={props.classnameArray[key][i]}>
{renderSwitch(col)}
</div>
)
)}
</div>
))}
</div>
</ErrorBoundary>
);
};
export default GetDashboard;
@@ -0,0 +1,254 @@
import React, { useState, useEffect } from "react";
import { SaveFileSize } from "../../constant/saveFileSize";
import Parse from "parse";
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 [localValue, setLocalValue] = useState("");
const [Message] = useState(false);
const [percentage] = 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;
setLocalValue(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) {
} 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
) {
} else {
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);
const size = file.size;
// console.log("file ", file)
setfileload(true);
const tenant = localStorage.getItem("TenetId");
const pdfFile = file;
const parseFile = new Parse.File(pdfFile.name, pdfFile);
try {
const response = await parseFile.save();
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) {
console.error("Error uploading file:", error);
}
};
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="progress pull-right">
<div
className="progress__bar"
style={{ width: `${percentage}%` }}
></div>
<span className="progress__value">{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>
<>
{localValue ? (
<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}
/>
) : props.formData ? (
<div
style={{
border: "1px solid #ccc",
color: "gray",
backgroundColor: "white",
padding: "5px 10px",
borderRadius: "4px",
fontSize: "13px",
width: "100%",
fontWeight: "bold"
}}
>
file selected : {props.formData.split("/")[3]}
</div>
) : (
<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}
/>
)}
</>
</React.Fragment>
);
};
export default FileUpload;
@@ -0,0 +1,83 @@
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 });
});
}
}
} catch (error) {}
}
};
componentDidMount() {
this.loadData();
}
/* componentWillReceiveProps() {
this.loadData();
} */
render() {
return (
<input
type="hidden"
value={this.state._fields}
onChange={this.props.onChange(this.state._fields)}
/>
);
}
}
export default HiddenField;
@@ -0,0 +1,70 @@
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;
@@ -0,0 +1,483 @@
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 {
var emp = Parse.Object.extend(
localStorage.getItem("extended_class")
);
var q = new Parse.Query(emp);
q.equalTo("UserId", currentUser);
res = await q.first();
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) {}
}
};
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);
@@ -0,0 +1,696 @@
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) => {
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) {}
};
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([data]);
} else {
setSelected([...selected, 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}
contentLabel="Modal"
style={{
overlay: {
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: "rgba(255, 255, 255, 0.75)",
zIndex: 10
}
}}
>
<div
type="button"
style={{ display: "flex", justifyContent: "space-between" }}
>
<div style={{ color: "transparent", width: "100%" }}>.</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}
/>
)}
</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);
@@ -0,0 +1,92 @@
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;
@@ -0,0 +1,26 @@
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;
@@ -0,0 +1,104 @@
import React, { useState, useEffect } from "react";
import { Link, NavLink } from "react-router-dom";
import Submenu from "./SubMenu";
import dp from "../../assets/images/dp.png";
import Parse from "parse";
const Sidebar = ({ isOpen, closeSidebar }) => {
let username = localStorage.getItem("username");
const image = localStorage.getItem("profileImg") || dp;
const tenantname = localStorage.getItem("TenantName");
const [menuList, setmenuList] = useState([]);
useEffect(() => {
if (localStorage.getItem("accesstoken")) {
menuItem();
}
}, []);
const menuItem = async () => {
const parseBaseUrl = localStorage.getItem("baseUrl");
const parseAppId = localStorage.getItem("parseAppId");
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
var sideMenu = Parse.Object.extend("w_menu");
var query = new Parse.Query(sideMenu);
query.equalTo("objectId", localStorage.getItem("defaultmenuid"));
// query.equalTo("objectId", "46X9z6lAv2");
const results = await query.first();
const resultjson = results.toJSON();
// console.log("resultjson ", resultjson);
let result = resultjson;
setmenuList(result.menuItems);
} catch (e) {
console.error("Problem", e);
}
};
return (
<div
className={`${
isOpen ? "block" : "hidden"
} bg-white text-[#444] h-screen w-full md:w-[300px] overflow-y-auto transform transition-transform ${
isOpen ? "translate-x-0" : "-translate-x-full"
}`}
>
<div className="flex px-2 py-3 gap-2 items-center shadow-md">
<div className="w-[75px] h-[75px] rounded-full ring-[2px] ring-offset-2 ring-gray-400 overflow-hidden">
<img className="w-full h-full object-contain" src={image} alt="img" />
</div>
<div>
<p className="text-[14px] font-bold">{username && username}</p>
<p
className={`text-[12px] ${tenantname && tenantname ? "mt-2" : ""}`}
>
{tenantname && tenantname}
</p>
</div>
</div>
<ul className="text-sm">
{menuList.length > 0 && (
<>
{menuList.map((item) =>
!item.children ? (
<li key={item.title} onClick={() => closeSidebar()}>
<Link
className={`mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 hover:no-underline`}
to={`/${item.pageType}/${item.objectId}`}
>
<i className={item.icon + " text-[18px]"}></i>
<span title={item.description} className="ml-3 lg:ml-4">
{item.title}
</span>
</Link>
</li>
) : (
<Submenu key={item.title} icon={item.icon} title={item.title}>
{item.children.map((item) => (
<li key={item.title} onClick={() => closeSidebar()}>
<Link
className={`mx-auto flex items-center hover:bg-[#eef1f5] p-2 lg:p-3 hover:no-underline`}
to={`/${item.pageType}/${item.objectId}`}
>
<i className={item.icon + " text-[18px]"}></i>
<span title={item.description} className="ml-3 lg:ml-4">
{item.title}
</span>
</Link>
</li>
))}
</Submenu>
)
)}
</>
)}
</ul>
<div className="mt-4 flex justify-center items-center text-[25px] text-black">
<NavLink to="https://github.com/opensignlabs/opensign" target="_blank">
<i className="fa-brands fa-github cursor-pointer"></i>
</NavLink>
</div>
</div>
);
};
export default Sidebar;
@@ -0,0 +1,31 @@
import React, { useState } from "react";
const Submenu = ({ icon, title, children }) => {
const [isOpen, setIsOpen] = useState(false);
const toggleSubmenu = () => {
setIsOpen(!isOpen);
};
return (
<div>
<button
onClick={toggleSubmenu}
className="w-full mx-auto flex items-center text-left text-[#444] p-3 lg:p-4 hover:bg-[#eef1f5] focus:outline-none"
>
<i className={icon + " text-[18px]"}></i>
<div className="flex justify-between items-center w-full">
<span className="ml-3 lg:ml-4">{title}</span>
<i
className={
isOpen ? "fa-solid fa-angle-down" : "fa-solid fa-angle-right"
}
></i>
</div>
</button>
{isOpen && <ul className="pl-6 lg:pl-8">{children}</ul>}
</div>
);
};
export default Submenu;
+36
View File
@@ -0,0 +1,36 @@
import logo from "../assets/images/logo.png";
export const appInfo = {
appTitle: "contracts",
applogo: logo,
appname: "contracts",
baseurl: process.env.REACT_APP_SEVERURL,
defaultRole: "contracts_User",
fbAppId: process.env.REACT_APP_FBAPPID
? `${process.env.REACT_APP_FBAPPID}`
: "",
fev_Icon:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAALlJREFUaEPtmN0NwjAMBpNxYDKYiM1Yp90g93CKStH1NbIdfz921Dker2Pc+Js1cDF7MXAxASMGYkAigBI6vh9ZwoXP53uZoAYcvhwdA3mAVbI2aSb+9zFKU4IURB6j/HoPUIEa2G3iGIAhQQDlAUIoE2diabIklISS0NoFPebo77RF6OenEF3QntOm128he0GKrwHyACFoz2MgBqSGkpAEcHs47oHtN5AFakACqMNjQEMoE8SABFCHn4HE2zGHSLeEAAAAAElFTkSuQmCC",
googleClietId: process.env.REACT_APP_GOOGLECLIENTID
? `${process.env.REACT_APP_GOOGLECLIENTID}`
: "",
metaDescription:
"The fastest way to sign PDFs & request signatures from others.",
objectId: "aIPmIvMzGM",
settings: [
{
role: "contracts_User",
menuId: "H9vRfEYKhT",
pageType: "dashboard",
pageId: "35KBoSgoAK",
extended_class: "contracts_Users"
},
{
role: "contracts_Admin",
menuId: "VPh91h0ZHk",
pageType: "dashboard",
pageId: "35KBoSgoAK",
extended_class: "contracts_Users"
}
],
version: "0.1"
};
@@ -0,0 +1,40 @@
import Parse from "parse";
/**
* Function returning the queryString in which multiple hash replaced with actual values
* @param str query string
* @param json localstroage data in json
*/
export default function getReplacedHashQuery(str, json) {
// eslint-disable-next-line
let reg = /(\#.*?\#)/gi;
const currentUser = Parse.User.current();
const multiHash = str.match(reg);
let values = {};
let key = "";
multiHash.forEach((x) => {
key = x;
key = key.substring(1, key.length - 1);
key = key.split(".");
if (key.length > 1) {
key = x.replace(reg, json[key[0]][key[1]]);
} else if (json[key[0]]) {
key = x.replace(reg, json[key[0]]);
} else if (key[0] === "Date") {
key = x.replace(reg, "Date");
} else if (key[0] === "today") {
key = x.replace(reg, new Date().toISOString());
} else {
key = x.replace(reg, currentUser.id);
}
values = { ...values, [x]: key };
});
const querySplit = str.split(reg);
const replacedHashWithValuesArr = querySplit.map((hash) =>
values[hash] ? values[hash] : hash
);
const HashFreeQuery = replacedHashWithValuesArr.join("");
// console.log("HashFreeQuery ", HashFreeQuery);
return HashFreeQuery;
}
+4
View File
@@ -0,0 +1,4 @@
export default function linkURL(url) {
let newURL = (url && decodeURIComponent(url)) || "";
return newURL.substring(newURL.indexOf(".com/") + 5, newURL.indexOf("_"));
}
+101
View File
@@ -0,0 +1,101 @@
import axios from "axios";
import Parse from "parse";
const parseAppId = localStorage.getItem("AppID12");
const serverUrl = localStorage.getItem("BaseUrl12");
Parse.serverURL = serverUrl;
Parse.initialize(parseAppId);
export const SaveFileSize = async (size, imageUrl) => {
//checking server url and save file's size
try {
const response = await axios
.get(`${serverUrl}classes/partners_TenantCredits`, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId
}
})
.then((result) => {
const res = result.data;
// console.log("res", res);
return res.results;
})
.catch((err) => {
console.log("axois err ", err);
});
let data;
// console.log("response", response);
if (response && response.length > 0) {
data = {
usedStorage: response[0].usedStorage
? response[0].usedStorage + size
: size
};
await axios
.put(
`${serverUrl}classes/partners_TenantCredits/${response[0].objectId}`,
data,
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId
}
}
)
.then((result) => {
// const res = result.data;
// console.log("save res", res);
})
.catch((err) => {
console.log("axois err ", err);
});
} else {
data = {
usedStorage: size
};
await axios
.post(`${serverUrl}classes/partners_TenantCredits`, data, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId
}
})
.then((result) => {
// const res = result.data;
// console.log("res", res);
})
.catch((err) => {
console.log("axois err ", err);
});
}
} catch (e) {
console.log("org app error", e);
}
saveDataFile(size, imageUrl);
};
//function for save fileUrl and file size in particular client db class partners_DataFiles
const saveDataFile = async (size, imageUrl) => {
const data = {
FileUrl: imageUrl,
FileSize: size
};
// console.log("data save",file, data)
await axios
.post(`${serverUrl}classes/partners_DataFiles`, data, {
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId
}
})
.then((result) => {
// const res = result.data;
// console.log("res", res);
})
.catch((err) => {
console.log("axois err ", err);
});
};
+206
View File
@@ -0,0 +1,206 @@
import moment from "moment";
export default function onSearchFilter(_search) {
switch (_search) {
case "Today":
let d = new Date();
let formDate = new Date(
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0)
).toISOString();
let Todate = new Date(
Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59)
).toISOString();
let Query = `'$gte':'${formDate}','$lte':'${Todate}'`;
return Query;
case "Yesterday":
let d1 = new Date();
d1.setDate(d1.getDate() - 1);
let yesFrDate = new Date(
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 0, 0, 0)
).toISOString();
let YesTodate = new Date(
Date.UTC(d1.getFullYear(), d1.getMonth(), d1.getDate(), 23, 59, 59)
).toISOString();
let Query1 = `'$gte':'${yesFrDate}','$lte':'${YesTodate}'`;
return Query1;
case "This week":
let oneDay = 24 * 60 * 60 * 1000;
let curr = new Date(); // get current date
let first = curr.getDate() - curr.getDay(); // First day is the day of the month - the day of the week
let firstday = new Date(
new Date(
Date.UTC(curr.getFullYear(), curr.getMonth(), curr.getDate(), 0, 0, 0)
).setDate(first)
).toISOString();
let diffDays = Math.round(
Math.abs(
(new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
23,
59,
59
)
) -
new Date(firstday)) /
oneDay
)
); //Days since last week
let last = first + diffDays;
let lastday = new Date(
new Date(
Date.UTC(
curr.getFullYear(),
curr.getMonth(),
curr.getDate(),
23,
59,
59
)
).setDate(last)
).toISOString();
let Query2 = `'$gte':'${firstday}','$lte':'${lastday}'`;
return Query2;
case "Last 7 days":
let d7 = new Date();
let d7l = new Date();
d7.setDate(d7.getDate() - 7);
let l7t = new Date(
Date.UTC(d7l.getFullYear(), d7l.getMonth(), d7l.getDate(), 23, 59, 59)
).toISOString();
let date7 = new Date(
Date.UTC(d7.getFullYear(), d7.getMonth(), d7.getDate(), 0, 0, 0)
).toISOString();
let Query7 = `'$gte':'${date7}','$lte':'${l7t}'`;
return Query7;
case "Last 14 days":
let d14 = new Date();
let d14l = new Date();
let l14t = new Date(
Date.UTC(
d14l.getFullYear(),
d14l.getMonth(),
d14l.getDate(),
23,
59,
59
)
).toISOString();
d14.setDate(d14.getDate() - 14);
let date14 = new Date(
Date.UTC(d14.getFullYear(), d14.getMonth(), d14.getDate(), 0, 0, 0)
).toISOString();
let Query14 = `'$gte':'${date14}','$lte':'${l14t}'`;
return Query14;
case "Last 30 days":
let d30 = new Date();
let d30l = new Date();
let l30t = new Date(
Date.UTC(
d30l.getFullYear(),
d30l.getMonth(),
d30l.getDate(),
23,
59,
59
)
).toISOString();
d30.setDate(d30.getDate() - 30);
let date30 = new Date(
Date.UTC(d30.getFullYear(), d30.getMonth(), d30.getDate(), 0, 0, 0)
).toISOString();
return `'$gte':'${date30}','$lte':'${l30t}'`;
case "Last week":
const from_date = moment().startOf("week").subtract(7, "days");
const to_date = moment().endOf("week").subtract(7, "days");
return `'$gte':'${from_date.toISOString()}','$lte':'${to_date.toISOString()}'`;
case "This month":
var tdate = new Date();
var tfirstDay = new Date(
tdate.getFullYear(),
tdate.getMonth(),
1
).toISOString();
var tlastDay = new Date(
tdate.getFullYear(),
tdate.getMonth() + 1,
0
).toISOString();
let Querylt = `'$gte':'${tfirstDay}','$lte':'${tlastDay}'`;
return Querylt;
case "Last month":
var ldate = new Date();
var lfirstDay = new Date(
ldate.getFullYear(),
ldate.getMonth() - 1,
2
).toISOString();
var llastDay = new Date(
ldate.getFullYear(),
ldate.getMonth(),
1
).toISOString();
let Queryltl = `'$gte':'${lfirstDay}','$lte':'${llastDay}'`;
return Queryltl;
case "All":
let fall = new Date(
new Date().getFullYear() - 100,
0,
1,
0,
0,
0
).toISOString();
let fall_year = `'$gte':'${fall}'`;
return fall_year;
case "This year":
let fcy = new Date(new Date().getFullYear(), 0, 1, 0, 0, 0).toISOString();
let lcy = new Date(
new Date().getFullYear(),
11,
31,
23,
59,
59
).toISOString();
let cur_year = `'$gte':'${fcy}','$lte':'${lcy}'`;
return cur_year;
case "Last year":
let fly = new Date(
new Date().getFullYear() - 1,
0,
1,
0,
0,
0
).toISOString();
let lly = new Date(
new Date().getFullYear() - 1,
11,
31,
23,
59,
59
).toISOString();
let last_year = `'$gte':'${fly}','$lte':'${lly}'`;
return last_year;
default:
return "";
}
}
+17
View File
@@ -0,0 +1,17 @@
import { useEffect } from "react";
/**`useScript` hook is generated scripte for google sign in button */
export const useScript = (url, onload) => {
useEffect(() => {
const script = document.createElement("script");
//add url parameter to the script src, for load and it will remove after load in return
script.src = url;
script.async = true;
script.defer = true;
script.onload = onload;
document.head.appendChild(script);
return () => {
document.head.removeChild(script);
};
}, [url, onload]);
};
+27
View File
@@ -0,0 +1,27 @@
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;
}
+7
View File
@@ -0,0 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
body{
background-color: white;
}
+1
View File
@@ -0,0 +1 @@
import("./Bootstrap");
+577
View File
@@ -0,0 +1,577 @@
export const formJson = (id) => {
let formData;
//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: "5000",
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=="
};
return formData;
}
//json form for request signature
else if (id === "8mZzFxbG1z") {
formData = {
jsonSchema: {
title: "New Document",
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: 50
},
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: "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;
}
};
+406
View File
@@ -0,0 +1,406 @@
import Parse from "parse";
export default function reportJson(id) {
const currentUserId = Parse.User.current().id;
// console.log("userId", currentUserId)
switch (id) {
case "ByHuevtCFY":
return {
reportName: "Draft Documents",
className: "contracts_Document",
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null }
],
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "sign",
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-plus",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
}
]
};
case "4Hhwbp482K":
return {
reportName: "Need your sign",
className: "contracts_Document",
params: {
Type: { $ne: "Folder" },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
ExpiryDate: {
$gt: { __type: "Date", iso: new Date().toISOString() }
},
$and: [
{
"AuditTrail.UserPtr": {
$ne: {
__type: "Pointer",
className: "contracts_Users",
objectId: "CkpaR0F6mj"
}
}
},
{ "AuditTrail.Activity": { $ne: "Signed" } }
],
Placeholders: { $ne: null },
Signers: {
$in: [
{
__type: "Pointer",
className: "contracts_Users",
objectId: "CkpaR0F6mj"
}
]
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "sign",
btnColor: "#3ac9d6",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
}
]
};
case "1MwEuxLEkF":
return {
reportName: "InProgress Document",
className: "contracts_Document",
params: {
Type: { $ne: "Folder" },
Signers: { $ne: null },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
},
ExpiryDate: {
$gt: { __type: "Date", iso: new Date().toISOString() }
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "View",
btnColor: "#3ac9d6",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
}
]
};
case "kQUoW4hUXz":
return {
reportName: "Completed Documents",
className: "contracts_Document",
params: {
Type: null,
IsCompleted: true,
$or: [{ IsDeclined: null }, { IsDeclined: false }]
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name",
"TimeToCompleteDays"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "View",
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
}
]
};
case "VRFDmUmw5B":
return {
reportName: "OpenSignDrive™ Drafts",
className: "contracts_Document",
params: {
Type: "AIDoc",
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null }
],
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "edit",
btnColor: "#3ac9d6",
textColor: "white",
btnIcon: "fa fa-plus",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9MZWdhR2VuaWUtTWljcm9hcHBWMi9yZW1vdGVFbnRyeS5qcw==&moduleToLoad=AppRoutes&remoteName=legageniemicroapp/legagenie"
}
]
};
case "UPr2Fm5WY3":
return {
reportName: "Declined Documents",
className: "contracts_Document",
params: { Type: null, IsDeclined: true },
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "View",
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
}
]
};
case "zNqBHXHsYH":
return {
reportName: "Expired Documents",
className: "contracts_Document",
params: {
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
Type: { $ne: "Folder" },
$and: [
{
$or: [
{ Signers: { $ne: null }, SignedUrl: { $ne: null } },
{ Placeholders: { $ne: null } }
]
},
{
ExpiryDate: {
$lt: { __type: "Date", iso: new Date().toISOString() }
}
}
],
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "View",
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
}
]
};
case "d9k3UfYHBc":
return {
reportName: "Recently sent for signatures",
className: "contracts_Document",
params: {
Type: { $ne: "Folder" },
Signers: { $ne: null },
Placeholders: { $ne: null },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
},
ExpiryDate: {
$gt: { __type: "Date", iso: new Date().toISOString() }
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "View",
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
}
]
};
case "5Go51Q7T8r":
return {
reportName: "Recent signature requests",
className: "contracts_Document",
params: {
Type: { $ne: "Folder" },
IsCompleted: { $ne: true },
IsDeclined: { $ne: true },
ExpiryDate: {
$gt: { __type: "Date", iso: new Date().toISOString() }
},
$and: [
{
"AuditTrail.UserPtr": {
$ne: {
__type: "Pointer",
className: "contracts_Users",
objectId: "CkpaR0F6mj"
}
}
},
{ "AuditTrail.Activity": { $ne: "Signed" } }
],
Placeholders: { $ne: null },
Signers: {
$in: [
{
__type: "Pointer",
className: "contracts_Users",
objectId: "CkpaR0F6mj"
}
]
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "Sign",
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-eye",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/pdfRequestFiles"
}
]
};
case "kC5mfynCi4":
return {
reportName: "Drafts",
className: "contracts_Document",
params: {
Type: null,
$or: [
{ Signers: null, SignedUrl: null },
{ Signers: { $exists: true }, Placeholders: null }
],
CreatedBy: {
__type: "Pointer",
className: "_User",
objectId: currentUserId
}
},
keys: [
"Name",
"Note",
"Folder.Name",
"URL",
"ExtUserPtr.Name",
"Signers.Name"
],
orderBy: "-updatedAt",
actions: [
{
btnLabel: "sign",
btnColor: "#4bd396",
textColor: "white",
btnIcon: "fa fa-plus",
redirectUrl:
"remoteUrl=aHR0cHM6Ly9xaWstYWktb3JnLmdpdGh1Yi5pby9TaWduLU1pY3JvYXBwVjIvcmVtb3RlRW50cnkuanM=&moduleToLoad=AppRoutes&remoteName=signmicroapp/draftDocument"
}
]
};
default:
return null;
}
}
+197
View File
@@ -0,0 +1,197 @@
import React, { useState, useEffect } from "react";
import Header from "../components/Header";
import Footer from "../components/Footer";
import Sidebar from "../components/sidebar/Sidebar";
import { useWindowSize } from "../hook/useWindowSize";
import Tour from "reactour";
import axios from "axios";
import { useSelector } from "react-redux";
const HomeLayout = ({ children }) => {
const { width } = useWindowSize();
const [isOpen, setIsOpen] = useState(false);
const arr = useSelector((state) => state.TourSteps);
// reactour state
const [isCloseBtn, setIsCloseBtn] = useState(true);
const [isTour, setIsTour] = useState(false);
const [tourStatusArr, setTourStatusArr] = useState([]);
const [tourConfigs, setTourConfigs] = useState([]);
const showSidebar = () => {
setIsOpen(!isOpen);
};
useEffect(() => {
if (width && width <= 768) {
setIsOpen(false);
} else {
setIsOpen(true);
}
}, [width]);
useEffect(() => {
if (localStorage.getItem("domain") === "sign" && arr && arr.length > 0) {
handleDynamicSteps();
} else if (
localStorage.getItem("domain") === "contracts" &&
arr &&
arr.length > 0
) {
handleDynamicSteps();
} else {
setIsTour(false);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [arr]);
const handleDynamicSteps = () => {
if (arr && arr.length > 0) {
// const resArr = arr;
const resArr = arr.map((obj, index) => {
if (arr.length - 1 === index) {
return {
...obj
// actions: () => {
// setIsCloseBtn(true);
// },
};
} else {
return {
...obj,
actions: () => {
setIsCloseBtn(false);
}
};
}
});
setTourConfigs([
{
selector: '[data-tut="reactourFirst"]',
content: `You have logged in successfully! Let's take a look.`,
position: "top"
// style: { backgroundColor: "#abd4d2" },
},
...resArr,
{
selector: '[data-tut="reactourLast"]',
content: `You are good to go`,
position: "top"
// style: { backgroundColor: "#abd4d2" },
}
]);
checkTourStatus();
// console.log("resArr ", resArr);
}
};
const closeTour = async () => {
// console.log("closeTour");
setIsTour(false);
const serverUrl = localStorage.getItem("baseUrl");
const appId = localStorage.getItem("AppID12");
const extUserClass = localStorage.getItem("extended_class");
const json = JSON.parse(localStorage.getItem("Extand_Class"));
const extUserId = json && json.length > 0 && json[0].objectId;
// console.log("extUserId ", extUserId)
let updatedTourStatus = [];
if (tourStatusArr.length > 0) {
updatedTourStatus = [...tourStatusArr];
const loginTourIndex = tourStatusArr.findIndex(
(obj) => obj["loginTour"] === false || obj["loginTour"] === true
);
if (loginTourIndex !== -1) {
updatedTourStatus[loginTourIndex] = { loginTour: true };
} else {
updatedTourStatus.push({ loginTour: true });
}
} else {
updatedTourStatus = [{ loginTour: true }];
}
// console.log("updatedTourStatus ", updatedTourStatus);
await axios.put(
serverUrl + "classes/" + extUserClass + "/" + extUserId,
{
TourStatus: updatedTourStatus
},
{
headers: {
"X-Parse-Application-Id": appId
}
}
);
// console.log("updatedRes ", updatedRes);
};
async function checkTourStatus() {
const serverUrl = localStorage.getItem("baseUrl");
const appId = localStorage.getItem("AppID12");
const extUserClass = localStorage.getItem("extended_class");
const json = JSON.parse(localStorage.getItem("Extand_Class"));
const extUserId = json && json.length > 0 && json[0].objectId;
// console.log("extUserId ", extUserId);
const res = await axios.get(
serverUrl + "classes/" + extUserClass + "/" + extUserId,
{
headers: {
"X-Parse-Application-Id": appId
}
}
);
if (res.data && res.data.TourStatus && res.data.TourStatus.length > 0) {
const tourStatus = res.data.TourStatus;
// console.log("res ", res.data.TourStatus);
setTourStatusArr(tourStatus);
const filteredtourStatus = tourStatus.filter((obj) => obj["loginTour"]);
if (filteredtourStatus.length > 0) {
const loginTour = filteredtourStatus[0]["loginTour"];
// console.log("loginTour", loginTour);
if (loginTour) {
setIsTour(false);
} else {
setIsTour(true);
}
} else {
setIsTour(true);
}
} else {
setIsTour(true);
}
}
const closeSidebar = () => {
if (width <= 768) {
setIsOpen(false);
}
};
return (
<div>
<div className="sticky top-0 z-30">
<Header showSidebar={showSidebar} />
</div>
<div className="flex md:flex-row flex-col">
<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>
<Footer footer="xap" />
</div>
</div>
</div>
<Tour
onRequestClose={closeTour}
steps={tourConfigs}
isOpen={isTour}
closeWithMask={false}
disableKeyboardNavigation={["esc"]}
// disableInteraction={true}
scrollOffset={-100}
rounded={5}
showCloseButton={isCloseBtn}
/>
</div>
);
};
export default HomeLayout;
@@ -0,0 +1,58 @@
import React from "react";
import stamp from "./stamp2.png";
import sign from "./sign3.png";
import { themeColor } from "./IconColor.js";
function DragElement({ type, id }) {
const selectedId = id;
return (
<div>
{selectedId === 3 ? (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
userSelect: "none"
}}
>
<img
alt="sign img"
style={{
width: "25px",
height: "23px",
background: themeColor()
}}
src={sign}
/>
<span style={{ color: themeColor(), fontSize: "12px" }}>
Signature
</span>
</div>
) : (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
userSelect: "none"
}}
>
<img
alt="stamp img"
style={{
width: "25px",
height: "23px",
background: themeColor()
}}
src={stamp}
/>
<span style={{ color: themeColor(), fontSize: "12px" }}>Stamp</span>
</div>
)}
</div>
);
}
export default DragElement;
@@ -0,0 +1,3 @@
export const themeColor = () => {
return "#47a3ad";
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

@@ -0,0 +1,120 @@
import React from "react";
import pad from "../assets/images/pad.svg";
import { useNavigate } from "react-router-dom";
const ReportTable = ({ ReportName, List, actions }) => {
const navigate = useNavigate();
const formatRow = (row) => {
if (Array.isArray(row)) {
let updateArr = row.map((x) => x.Name);
return updateArr.join(", ");
} else if (typeof row === "object" && row !== null) {
return row?.Name || "-";
} else {
return "-";
}
};
const handlemicroapp = (item, url) => {
localStorage.removeItem("rowlevel");
navigate("/rpmf/" + url);
localStorage.setItem("rowlevel", JSON.stringify(item));
// localStorage.setItem("rowlevelMicro")
};
const handlebtn = () => {
console.log("clicked");
};
return (
<div className="p-2 overflow-x-scroll w-full bg-white rounded-md">
<h2 className="text-[23px] font-light my-2">{ReportName}</h2>
<table className="table-auto w-full border-collapse">
<thead className="text-[14px]">
<tr className="border-y-[1px]">
<th className="px-4 py-2 font-thin">Sr.No</th>
<th className="px-4 py-2 font-thin">Name</th>
<th className="px-4 py-2 font-thin">Note</th>
<th className="px-4 py-2 font-thin">Folder</th>
<th className="px-4 py-2 font-thin">File</th>
<th className="px-4 py-2 font-thin">Owner</th>
<th className="px-4 py-2 font-thin">Signers</th>
{actions?.length > 0 && (
<th className="px-4 py-2 font-thin">Action</th>
)}
</tr>
</thead>
<tbody className="text-[12px]">
{List?.length > 0 ? (
<>
{List.map((item, index) => (
<tr className="border-t-[1px]" key={index}>
<td className="px-4 py-2">{index + 1}</td>
<td className="px-4 py-2 font-semibold">{item?.Name} </td>
<td className="px-4 py-2">{item?.Note || "-"}</td>
<td className="px-4 py-2">
{item?.Folder?.Name || "OpenSignDrive"}
</td>
<td className="px-4 py-2">
<a
target="_blank"
rel="noopener noreferrer"
title={item?.URL}
href={item?.URL}
download={item?.URL}
className="text-[blue] hover:text-[blue] hover:underline"
>
{item?.URL ? "Download" : "-"}
</a>
</td>
<td className="px-4 py-2">{formatRow(item?.ExtUserPtr)}</td>
<td className="px-4 py-2">
{item?.Signers ? formatRow(item?.Signers) : "-"}
</td>
<td className="px-4 py-2 flex flex-col justify-center items-center gap-2 text-white">
{actions?.length > 0 &&
actions.map((act, index) => (
<button
key={index}
onClick={() =>
act?.redirectUrl
? handlemicroapp(item, act.redirectUrl)
: handlebtn(item)
}
className={`flex justify-center items-center w-full gap-1 px-2 py-1 rounded shadow`}
style={{
backgroundColor: act.btnColor
? act.btnColor
: "#3ac9d6",
color: act?.textColor ? act?.textColor : "white"
}}
>
<span>
{act?.btnIcon && <i className={act.btnIcon}></i>}
</span>
<span className="uppercase">
{act?.btnLabel ? act.btnLabel : "view"}
</span>
</button>
// )
))}
</td>
</tr>
))}
</>
) : (
<></>
)}
</tbody>
</table>
{List?.length <= 0 && (
<div className="flex flex-col items-center justify-center w-full bg-white roundedm py-4">
<div className="w-[60px] h-[60px] overflow-hidden">
<img className="w-full h-full object-contain" src={pad} alt="img" />
</div>
<div className="text-sm font-semibold">No Data Available</div>
</div>
)}
</div>
);
};
export default ReportTable;
+313
View File
@@ -0,0 +1,313 @@
import Parse from "parse";
import axios from "axios";
import { appInfo } from "../../constant/appinfo";
//For fetching application Information
export const fetchAppInfo = (str, burl, app_id) => async (dispatch) => {
Parse.serverURL = burl;
Parse.initialize(app_id);
const response = appInfo;
let _base = response.baseurl.charAt(response.baseurl.length - 1);
localStorage.removeItem("baseUrl");
localStorage.setItem("_appName", response.appname);
localStorage.setItem("_app_objectId", response.objectId);
if (_base === "/") {
localStorage.setItem("baseUrl", response.baseurl);
} else {
localStorage.setItem("baseUrl", `${response.baseurl}/`);
}
localStorage.setItem("appLogo", response.applogo);
localStorage.setItem("appVersion", response.version);
if (response.enableWebNotification) {
localStorage.setItem(
"enableWebNotification",
response.enableWebNotification
);
}
localStorage.setItem("parseAppId", app_id);
localStorage.removeItem("userSettings");
localStorage.setItem("userSettings", JSON.stringify(response.settings));
localStorage.setItem("appTitle", response.appTitle);
localStorage.setItem("fev_Icon", response.fev_Icon);
// console.log("response ", response);
dispatch({ type: "FATCH_APPINFO", payload: response });
};
//for simple login
export const login = (username, password) => async (dispatch) => {
let res = {};
let baseUrl = localStorage.getItem("baseUrl");
let parseAppId = localStorage.getItem("parseAppId");
try {
Parse.serverURL = baseUrl;
Parse.initialize(parseAppId);
await Parse.User.logIn(username, password).then(
async function (res1) {
var resultjson = res1.toJSON();
res = res1.toJSON();
localStorage.setItem("userEmail", username);
localStorage.setItem("username", resultjson.name);
localStorage.setItem("accesstoken", resultjson.sessionToken);
localStorage.setItem("scriptId", true);
if (resultjson.ProfilePic) {
localStorage.setItem("profileImg", resultjson.ProfilePic);
} else {
localStorage.setItem("profileImg", "");
}
let url = `${baseUrl}functions/UserGroups`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: resultjson.sessionToken
};
let body = {
appname: localStorage.getItem("domain")
};
let userGroup = "",
userGroup1 = "";
await axios
.post(url, JSON.stringify(body), { headers: headers })
.then(async (response) => {
userGroup = response.data.result[0];
userGroup1 = response.data.result[1];
localStorage.setItem("_userGroup", userGroup);
});
let appSetings = JSON.parse(localStorage.getItem("userSettings"));
let defaultmenuid = "",
PageLanding = "",
pageType = "";
appSetings.forEach(async (element) => {
if (`${localStorage.getItem("_appName")}_appeditor` === userGroup) {
if (element.role === userGroup1) {
defaultmenuid = element.menuId;
PageLanding = element.pageId;
pageType = element.pageType;
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("pageType", pageType);
let _role = userGroup1.replace(
`${localStorage.getItem("_appName")}_`,
""
);
if (userGroup1) {
localStorage.setItem("_user_role", _role);
} else {
localStorage.setItem("_user_role", _role);
}
}
} else if (element.role === userGroup) {
defaultmenuid = element.menuId;
PageLanding = element.pageId;
pageType = element.pageType;
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("pageType", pageType);
localStorage.setItem("extended_class", element.extended_class);
localStorage.setItem("userpointer", element.userpointer);
let _role = userGroup.replace(
`${localStorage.getItem("domain")}_`,
""
);
if (userGroup) {
localStorage.setItem("_user_role", _role);
} else {
localStorage.setItem("_user_role", _role);
}
try {
const tour = Parse.Object.extend(
localStorage.getItem("extended_class")
);
let _tour = new Parse.Query(tour);
_tour.equalTo("UserId", {
__type: "Pointer",
className: "_User",
objectId: resultjson.objectId
});
await _tour.first().then(
(results) => {
let userinfo = results.toJSON();
if (userinfo.TenantId) {
localStorage.setItem("TenetId", userinfo.TenantId.objectId);
}
// console.log("tour found", results);
},
(error) => {
console.error("Error while fetching tour", error);
}
);
} catch (error) {}
}
});
dispatch({ type: "APP_LOGIN", payload: res });
if (pageType !== "") {
window.location = `/${pageType}/${PageLanding}`;
} else {
alert("You dont have access to this application.");
localStorage.setItem("accesstoken", null);
}
},
function () {
alert("Invalid Login");
localStorage.setItem("accesstoken", null);
}
);
} catch (err) {
console.log(err);
alert("You dont have access to this application.");
localStorage.setItem("accesstoken", null);
}
};
//for reset password
export const forgetPassword = (username) => async (dispatch) => {
// let res = {};
let baseUrl = localStorage.getItem("BaseUrl12");
let parseAppId = localStorage.getItem("AppID12");
try {
Parse.serverURL = baseUrl;
Parse.initialize(parseAppId);
await Parse.User.requestPasswordReset(username).then(
async function (res1) {
// var resultjson = res1;
// console.log("post data", resultjson.length);
if (res1.data === undefined) {
alert("Reset password link has been sent to your email id ");
}
},
function () {
// alert("Password Reset Done")
}
);
} catch (err) {
console.log(err);
}
};
// Role field wizard
export const fetchRoleEnum = (name) => async (dispatch) => {
let response = [];
let baseUrl = localStorage.getItem("baseUrl");
let parseAppId = localStorage.getItem("parseAppId");
try {
let url = `${baseUrl}roles?where={"name":{"$regex":"${name}","$ne":"${localStorage.getItem(
"domain"
)}_appeditor"}}`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId
};
await axios.get(url, { headers: headers }).then((res) => {
let temp = [];
res.data.results.forEach((x) => {
temp.push(x["name"]);
});
response = temp;
});
} catch (e) {
console.error("Problem", e);
}
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 });
};
export const remove_tourSteps = () => async (dispatch) => {
dispatch({ type: "REMOVE_TOURSTEPS", payload: [] });
};
@@ -0,0 +1,9 @@
const ShowTenant = (state = "", action) => {
switch (action.type) {
case "SHOW_TENANT":
return action.payload;
default:
return state;
}
};
export default ShowTenant;
@@ -0,0 +1,11 @@
const tourStepReducer = (state = "", action) => {
switch (action.type) {
case "SAVE_TOURSTEPS":
return action.payload;
case "REMOVE_TOURSTEPS":
return [];
default:
return state;
}
};
export default tourStepReducer;
+12
View File
@@ -0,0 +1,12 @@
import { combineReducers } from "redux";
import infoReducer from "./infoReducer";
import loginReducer from "./loginReducer";
import ShowTenant from "./ShowTenant";
import TourStepsReducer from "./TourStepsReducer";
export default combineReducers({
appInfo: infoReducer,
login: loginReducer,
ShowTenant,
TourSteps: TourStepsReducer
});
@@ -0,0 +1,9 @@
const infoReducer = (state = {}, action) => {
switch (action.type) {
case "FATCH_APPINFO":
return action.payload;
default:
return state;
}
};
export default infoReducer;
@@ -0,0 +1,9 @@
const loginReducer = (state = {}, action) => {
switch (action.type) {
case "APP_LOGIN":
return action.payload;
default:
return state;
}
};
export default loginReducer;
+5
View File
@@ -0,0 +1,5 @@
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import reducers from "./reducers";
export const store = createStore(reducers, applyMiddleware(thunk));
+111
View File
@@ -0,0 +1,111 @@
import React, { useState } from "react";
import Parse from "parse";
import { Navigate } from "react-router-dom";
function ChangePassword() {
const [currentpassword, setCurrentPassword] = useState("");
const [newpassword, setnewpassword] = useState("");
const [confirmpassword, setconfirmpassword] = useState("");
const handleSubmit = async (evt) => {
evt.preventDefault();
try {
if (newpassword === confirmpassword) {
Parse.serverURL = localStorage.getItem("baseUrl");
Parse.initialize(localStorage.getItem("parseAppId"));
Parse.User.logIn(localStorage.getItem("userEmail"), currentpassword)
.then(async (user) => {
if (user) {
const User = new Parse.User();
const query = new Parse.Query(User);
await query.get(user.id).then((user) => {
// Updates the data we want
user.set("password", newpassword);
user
.save()
.then((response) => {
alert("Password updated successfully.");
})
.catch((error) => {
alert("Something went wrong.");
});
});
} else {
alert("Your current password is missing or incorrect.");
}
console.log("Logged in user", user);
})
.catch((error) => {
alert("Your current password is missing or incorrect.");
console.error("Error while logging in user", error);
});
} else {
alert("Your password and confirmation password do not match.");
}
} catch (error) {}
};
if (localStorage.getItem("accesstoken") === null) {
return <Navigate to="/" />;
}
return (
<div className="w-full bg-white shadow rounded p-2">
<div className="text-xl font-bold border-b-[1px] border-gray-300">
Change Password
</div>
<div className="m-2">
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="currentpassword" className="block text-xs ml-1">
Current Password
</label>
<input
type="password"
name="currentpassword"
value={currentpassword}
onChange={(e) => setCurrentPassword(e.target.value)}
className="px-3 py-2 mb-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
placeholder="Current Password"
required
/>
</div>
<div>
<label htmlFor="newpassword" className="text-xs block ml-1">
New Password
</label>
<input
type="password"
name="newpassword"
value={newpassword}
onChange={(e) => setnewpassword(e.target.value)}
className="px-3 py-2 mb-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
placeholder="New Password"
required
/>
</div>
<div>
<label htmlFor="newpassword" className="text-xs block ml-1">
Confirm Password
</label>
<input
type="password"
name="confirmpassword"
className="px-3 py-2 mb-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
value={confirmpassword}
onChange={(e) => setconfirmpassword(e.target.value)}
placeholder="Confirm Password"
required
/>
</div>
<button
type="submit"
className="bg-[#188ae2] m-2 px-4 py-3 rounded-sm shadow-md text-white text-xs font-semibold uppercase"
>
Change Password
</button>
</form>
</div>
</div>
);
}
export default ChangePassword;
+142
View File
@@ -0,0 +1,142 @@
import React, { useState, useEffect } from "react";
import Parse from "parse";
import "../styles/loader.css";
import GetDashboard from "../components/dashboard/GetDashboard";
import { Navigate, useParams } from "react-router-dom";
import Title from "../components/Title";
import { save_tourSteps } from "../redux/actions";
import { connect } from "react-redux";
const Dashboard = (props) => {
const { id } = useParams();
const [dashboard, setdashboard] = useState([]);
const [classnameArray, setclassnameArray] = useState([]);
const [loading, setloading] = useState(false);
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [defaultQuery, setDefaultQuery] = useState("");
const getDashboard = async (id) => {
setloading(true);
try {
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
var forms = Parse.Object.extend("w_dashboard");
var query = new Parse.Query(forms);
query.equalTo("objectId", id);
const results = await query.first();
const resultjson = results.toJSON();
let classArray = [];
let DefaultQuery = "";
resultjson.rows.forEach((x) => {
let col_lg = "",
col_md = "",
col_xs = "",
col_sm = "",
col_ = "",
obj = {};
let subItem = [];
let item = "";
x.columns.forEach((y) => {
if (y.widget.type === "customeHtml") {
DefaultQuery = y.widget.data[0].default;
}
if (Number(y["collg"]) > 0) {
col_lg = "col-lg-" + y["collg"];
}
if (Number(y["colmd"]) > 0) {
col_md = "col-md-" + y["colmd"];
}
if (Number(y["colxs"]) > 0) {
col_xs = "col-xs-" + y["colxs"];
}
if (Number(y["colsm"]) > 0) {
col_sm = "col-sm-" + y["colsm"];
}
if (Number(y["col"]) > 0) {
col_ = "col-" + y["col"];
}
item =
col_lg + " " + col_md + " " + col_xs + " " + col_sm + " " + col_;
subItem.push(item);
});
obj = subItem;
classArray.push(obj);
});
setdashboard(resultjson.rows);
// console.log("resultjson.rows ", resultjson.rows);
const arr = resultjson.rows[0].columns
.filter((col) => {
if (col.widget.data && col.widget.data.tourSection) {
return col;
}
})
.map((col) => {
return {
selector: `[data-tut=${col.widget.data.tourSection}]`,
content: col.widget.data.tourMessage,
position: "top"
// style: { backgroundColor: "#abd4d2" },
};
});
props.save_tourSteps(arr);
// console.log("arr ", arr);
setclassnameArray(classArray);
if (localStorage.getItem("DashboardDefaultFilter")) {
setDefaultQuery(localStorage.getItem("DashboardDefaultFilter"));
} else {
setDefaultQuery(DefaultQuery);
}
setloading(false);
} catch (e) {
console.error("Problem", e);
setloading(false);
}
};
useEffect(() => {
if (id !== undefined) {
getDashboard(id);
} else {
getDashboard(localStorage.getItem("PageLanding"));
}
// eslint-disable-next-line
}, [id]);
if (localStorage.getItem("accesstoken") === "" || null) {
return <Navigate to="/" />;
}
let _dash = (
<GetDashboard
dashboard={dashboard}
classnameArray={classnameArray}
DefaultQuery={defaultQuery}
/>
);
if (loading) {
_dash = (
<div style={{ height: "300px", backgroundColor: "white" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
);
}
return (
<React.Fragment>
<Title title="Dashboard" />
{_dash}
</React.Fragment>
);
};
export default connect(null, {
save_tourSteps
})(Dashboard);
+129
View File
@@ -0,0 +1,129 @@
import React, { Component } from "react";
import { connect } from "react-redux";
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";
class forgotPassword extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
hideNav: ""
};
}
handleChange = (event) => {
const { name, value } = event.target;
this.setState({ [name]: value });
};
resize = () => {
let currentHideNav = window.innerWidth <= 760;
if (currentHideNav !== this.state.hideNav) {
this.setState({ hideNav: currentHideNav });
}
};
handleSubmit = (event) => {
event.preventDefault();
localStorage.setItem("appLogo", this.props.appInfo.applogo);
localStorage.setItem("appName", this.props.appInfo.appname);
localStorage.setItem("defaultmenuid", this.props.appInfo.defaultmenuid);
localStorage.setItem("PageLanding", this.props.appInfo.LandingPageId);
localStorage.setItem(
"userSettings",
JSON.stringify(this.props.appInfo.settings)
);
const { email } = this.state;
if (email) {
this.props.forgetPassword(email);
}
};
componentWillMount() {
this.props.fetchAppInfo(localStorage.getItem("domain"));
}
componentDidMount() {
window.addEventListener("resize", this.resize.bind(this));
this.resize();
}
render() {
const { email } = this.state;
let image = this.props.appInfo.applogo;
return (
<div className="bg-white">
<Title title="Forgot password page" />
<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">
{this.state.hideNav ? (
<img src={image} width="100%" alt="" />
) : (
<img src={image} width="100%" alt="" />
)}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
<div className="">
<form onSubmit={this.handleSubmit}>
<h2 className="text-[30px] mt-6">Welcome Back !</h2>
<span className="text-[12px] text-[#878787]">
Reset Your Password
</span>
<div className="shadow-md rounded my-4">
<div className="px-6 py-4">
<label className="block text-xs">Email</label>
<input
type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
name="email"
value={email}
onChange={this.handleChange}
required
/>
<hr className="my-2 border-none" />
</div>
</div>
<div className="flex justify-between items-center px-4">
<button
type="submit"
className="rounded-sm bg-[#3ac9d6] text-white px-4 py-3 text-xs font-semibold shadow uppercase"
>
Submit
</button>
<NavLink
to="/"
className="rounded-sm bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] px-4 py-3 text-xs font-semibold shadow uppercase"
>
Login
</NavLink>
</div>
</form>
</div>
{!this.state.hideNav && (
<div className="self-center">
<div className="mx-auto md:w-[300px] lg:w-[500px]">
<img src={login_img} alt="bisec" width="100%" />
</div>
</div>
)}
</div>
</div>
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return { appInfo: state.appInfo, forgotPassword: state.forgotPassword };
};
export default connect(mapStateToProps, { fetchAppInfo, forgetPassword })(
forgotPassword
);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
// NotFound.js
import React from "react";
const PageNotFound = () => {
return (
<div className="flex items-center justify-center h-screen w-full bg-white rounded">
<div className="text-center">
<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>
</div>
</div>
);
};
export default PageNotFound;
+524
View File
@@ -0,0 +1,524 @@
import React, { useState, useEffect } from "react";
import "../styles/pgsignup.css";
import Parse from "parse";
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";
const appId = localStorage.getItem("AppID12");
const server = localStorage.getItem("BaseUrl12");
Parse.serverURL = server;
Parse.initialize(appId);
const PgSignUp = (props) => {
const navigate = useNavigate();
const [parseBaseUrl] = useState(localStorage.getItem("BaseUrl12"));
const [parseAppId] = useState(localStorage.getItem("AppID12"));
const [formData, setFormData] = useState({
password: "",
confirmPassword: ""
});
const [validationMessage, setValidationMessage] = useState("");
const [isLoader, setIsLoader] = useState(true);
// below useEffect is used to fetch App data and save to redux state
useEffect(() => {
// Parse.User.logOut()
props.fetchAppInfo(
localStorage.getItem("domain"),
localStorage.getItem("BaseUrl12"),
localStorage.getItem("AppID12")
);
handleSignedUpUser();
// eslint-disable-next-line
}, []);
//`handleSignedUpUser` is called first time and it only work for user who comes from login with google, facebook or normal sign up flow
const handleSignedUpUser = async () => {
const userDetails = JSON.parse(localStorage.getItem("userDetails"));
if (userDetails && userDetails.email) {
try {
const url = window.location.href;
let paramString = url.split("?")[1];
let queryString = new URLSearchParams(paramString);
// console.log("url ", queryString);
let obj = { ...formData };
for (let pair of queryString.entries()) {
// console.log("Key is: " + pair[0]);
// console.log("Value is: " + pair[1]);
obj = { ...obj, [pair[0]]: pair[1] };
}
const zohoRes = await axios.post(
parseBaseUrl + "functions/zohodetails",
{
hostedpagesId: obj.hostedpage_id
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId
}
}
);
// console.log("zohoRes ", zohoRes);
const userSettings = JSON.parse(localStorage.getItem("userSettings"));
const extClass = userSettings[0].extended_class;
// console.log("extClass ", extClass);
const checkUser = new Parse.Query(extClass);
checkUser.equalTo("Email", userDetails.email);
const res = await checkUser.first();
// console.log("res", res);
if (res) {
const checkUser = new Parse.Query(extClass);
const updateQuery = await checkUser.get(res.id);
updateQuery.set(
"Next_billing_date",
new Date(zohoRes.data.result.nextBillingDate)
);
updateQuery.set("Plan", zohoRes.data.result.plan);
updateQuery.set("Customer_id", zohoRes.data.result.customer_id);
updateQuery.set(
"Subscription_id",
zohoRes.data.result.subscription_id
);
const updateRes = await updateQuery.save();
if (updateRes) {
localStorage.removeItem("userDetails");
navigate(
"/" + userSettings[0].pageType + "/" + userSettings[0].pageId
);
setIsLoader(false);
}
}
} catch (err) {
console.log("err ", err);
setIsLoader(false);
}
} else {
setIsLoader(false);
}
};
// "handleSubmit" is used to save user details signup him/her who come from plan-pricing page
const handleSubmit = (e) => {
e.preventDefault();
setIsLoader(true);
if (formData.password === formData.confirmPassword) {
const url = window.location.href;
let paramString = url.split("?")[1];
let queryString = new URLSearchParams(paramString);
// console.log("url ", queryString);
let obj = { ...formData };
for (let pair of queryString.entries()) {
// console.log("Key is: " + pair[0]);
// console.log("Value is: " + pair[1]);
obj = { ...obj, [pair[0]]: pair[1] };
}
saveUser(obj);
// console.log("obj ", obj);}
}
};
const saveUser = async (obj) => {
// const domain = localStorage.getItem("domain");
// console.log("domain", domain)
try {
const zohoRes = await axios.post(
parseBaseUrl + "functions/zohodetails",
{
hostedpagesId: obj.hostedpage_id
},
{
headers: {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId
}
}
);
const user = new Parse.User();
user.set("username", zohoRes.data.result.email);
user.set("password", obj.password);
user.set("email", zohoRes.data.result.email);
user.set("phone", zohoRes.data.result.phone);
user.set("name", zohoRes.data.result.name);
const res = await user.signUp();
// console.log("res ", res);
if (res) {
const params = {
userDetails: {
company: zohoRes.data.result.company,
name: zohoRes.data.result.name,
email: zohoRes.data.result.email,
phone: zohoRes.data.result.phone,
role: obj.role
// "pincode": "",
// "address": "",
// "country": "",
// "state": "",
// "city": ""
},
planDetails: {
plan: zohoRes.data.result.plan || {},
nextBillingDate: zohoRes.data.result.nextBillingDate || "",
customer_id: zohoRes.data.result.customer_id || "",
subscription_id: zohoRes.data.result.subscription_id || ""
}
};
const usersignup = await Parse.Cloud.run("usersignup", params);
// console.log("usersignup ", usersignup);
if (usersignup && usersignup.sessionToken) {
handleNavigation(usersignup.sessionToken);
}
}
// setIsLoader(false);
} catch (error) {
console.log("err ", error);
if (error.message === "Account already exists for this username.") {
alert("Account already exists!");
navigate("/");
} else {
setIsLoader(false);
alert("Something went wrong, please try again later!");
}
}
};
const handlePassowordChange = (e) => {
const newPassword = e.target.value;
setFormData({ ...formData, [e.target.name]: e.target.value });
validatePasswords(newPassword, formData.confirmPassword);
};
const handleConFirmPassowordChange = (e) => {
const newConfirmPassword = e.target.value;
setFormData({ ...formData, [e.target.name]: e.target.value });
validatePasswords(formData.password, newConfirmPassword);
};
const validatePasswords = (newPassword, newConfirmPassword) => {
if (newPassword === newConfirmPassword) {
setValidationMessage("Passwords match!");
} else {
setValidationMessage("Passwords not match!");
}
};
const handleNavigation = async (sessionToken) => {
const baseUrl = localStorage.getItem("BaseUrl12");
const parseAppId = localStorage.getItem("AppID12");
const res = await axios.get(baseUrl + "users/me", {
headers: {
"X-Parse-Session-Token": sessionToken,
"X-Parse-Application-Id": parseAppId
}
});
await Parse.User.become(sessionToken).then(() => {
window.localStorage.setItem("accesstoken", sessionToken);
});
// console.log("me res ", res);
if (res.data) {
let _user = res.data;
localStorage.setItem("UserInformation", JSON.stringify(_user));
localStorage.setItem("userEmail", _user.email);
localStorage.setItem("username", _user.name);
localStorage.setItem("accesstoken", _user.sessionToken);
localStorage.setItem("scriptId", true);
if (_user.ProfilePic) {
localStorage.setItem("profileImg", _user.ProfilePic);
} else {
localStorage.setItem("profileImg", "");
}
// Check extended class user role and tenentId
try {
let userRoles = [];
if (props.appInfo.settings) {
let userSettings = props.appInfo.settings;
//Get Current user roles
let url = `${baseUrl}functions/UserGroups`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: _user.sessionToken
};
let body = {
appname: localStorage.getItem("_appName")
};
await axios
.post(url, JSON.stringify(body), { headers: headers })
.then((roles) => {
if (roles) {
userRoles = roles.data.result;
let _currentRole = "";
if (userRoles.length > 1) {
if (
userRoles[0] ===
`${localStorage.getItem("_appName")}_appeditor`
) {
_currentRole = userRoles[1];
} else {
_currentRole = userRoles[0];
}
} else {
_currentRole = userRoles[0];
}
if (
_currentRole !==
`${localStorage.getItem("_appName")}_appeditor`
) {
userSettings.forEach(async (element) => {
if (element.role === _currentRole) {
let _role = _currentRole.replace(
`${localStorage.getItem("_appName")}_`,
""
);
localStorage.setItem("_user_role", _role);
if (element.enableCart) {
localStorage.setItem("EnableCart", element.enableCart);
props.setEnableCart(element.enableCart);
} else {
localStorage.removeItem("EnableCart");
}
// Get TenentID from Extendend Class
localStorage.setItem(
"extended_class",
element.extended_class
);
localStorage.setItem("userpointer", element.userpointer);
const extendedClass = Parse.Object.extend(
element.extended_class
);
let query = new Parse.Query(extendedClass);
query.equalTo("UserId", Parse.User.current());
query.include("TenantId");
await query.find().then(
(results) => {
let tenentInfo = [];
if (results) {
let extendedInfo_stringify =
JSON.stringify(results);
localStorage.setItem(
"Extand_Class",
extendedInfo_stringify
);
let extendedInfo = JSON.parse(
extendedInfo_stringify
);
if (extendedInfo.length > 1) {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName: x.TenantId.TenantName || ""
};
tenentInfo.push(obj);
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
);
localStorage.setItem(
"TenantName",
tenentInfo[0].tenentName || ""
);
}
localStorage.setItem("showpopup", true);
localStorage.setItem(
"IncludedApps",
JSON.stringify(tenentInfo)
);
localStorage.setItem(
"PageLanding",
element.pageId
);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem(
"pageType",
element.pageType
);
setIsLoader(false);
navigate("/");
} else {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName: x.TenantId.TenantName || ""
};
localStorage.setItem(
"TenetId",
x.TenantId.objectId
);
tenentInfo.push(obj);
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
);
localStorage.setItem(
"TenantName",
tenentInfo[0].tenentName || ""
);
}
localStorage.setItem(
"PageLanding",
element.pageId
);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem(
"pageType",
element.pageType
);
setIsLoader(false);
alert("Registered user successfully");
navigate(
`/${element.pageType}/${element.pageId}`
);
}
} else {
alert("Registered user successfully");
localStorage.setItem("PageLanding", element.pageId);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem("pageType", element.pageType);
setIsLoader(false);
navigate(`/${element.pageType}/${element.pageId}`);
}
},
(error) => {
setIsLoader(false);
console.error("Error while fetching Follow", error);
}
);
}
});
} else {
setIsLoader(false);
}
} else {
setIsLoader(false);
}
})
.catch((err) => {
setIsLoader(false);
});
}
} catch (error) {
setIsLoader(false);
console.log(error);
}
}
};
return (
<div className="bg-white">
<Title title={"Pgsignup page"} />
{isLoader ? (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
) : (
<form id="signup" className="pgsignup-content" onSubmit={handleSubmit}>
<div className="pgsignup-container">
<h1 className="text-4xl font-bold">Choose Password</h1>
<hr className="hrt" />
<label htmlFor="password">
<b>Password</b>
</label>
<input
type="password"
placeholder="Enter Password"
name="password"
className="inputt"
value={formData.password}
onChange={handlePassowordChange}
required
/>
<label htmlFor="confirmPassword">
<b>Confirm Password</b>
</label>
<input
type="password"
placeholder="Confirm Password"
name="confirmPassword"
className="confirmInputt"
style={{
border: validationMessage
? validationMessage === "Passwords match!"
? "2px solid green"
: "2px solid red"
: "2px solid transparent",
outline: "none"
}}
value={formData.confirmPassword}
onChange={handleConFirmPassowordChange}
required
/>
<div
className="icon"
style={{
margin: validationMessage ? "0 2px 0 2px" : "0 2px 22px 2px",
color:
validationMessage === "Passwords match!" ? "green" : "red",
fontSize: 11
}}
>
{validationMessage}
</div>
<div className="clearfix">
<button type="submit" className="signupbtn">
Submit
</button>
</div>
</div>
</form>
)}
</div>
);
};
const mapStateToProps = (state) => {
if (Object.keys(state.appInfo).length !== 0) {
return { appInfo: state.appInfo, isloginVisible: true };
} else {
return { appInfo: state.appInfo, isloginVisible: false };
}
};
export default connect(mapStateToProps, {
fetchAppInfo,
showTenantName
})(PgSignUp);
@@ -0,0 +1,704 @@
import React, { useState, useEffect } from "react";
import "../styles/plansubscription.css";
import { useNavigate } from "react-router";
const PlanSubscriptions = () => {
const navigate = useNavigate();
const [yearlyVisible, setYearlyVisible] = useState(false);
const [isLoader, setIsLoader] = useState(true);
const userDetails = JSON.parse(localStorage.getItem("userDetails"));
const name =
userDetails && userDetails.name ? "first_name=" + userDetails.name : "";
const email =
userDetails && userDetails.email ? "&email=" + userDetails.email : "";
const company =
userDetails && userDetails.company
? "&company_name=" + userDetails.company
: "";
const phone =
userDetails && userDetails.phone ? "&mobile=" + userDetails.phone : "";
const details = "?" + name + email + company + phone;
useEffect(() => {
if (localStorage.getItem("accesstoken")) {
setIsLoader(false);
setYearlyVisible(false);
} else {
navigate("/");
}
// eslint-disable-next-line
}, []);
const toggleFrequency = () => {
setYearlyVisible(!yearlyVisible);
};
return (
<>
{isLoader ? (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
) : (
<div
style={{
overflowY: "auto",
maxHeight: "600px",
"--theme-color": "#7952b3",
"--plan-width": 30
}}
>
<div
id="monthlyPlans"
style={{ display: yearlyVisible ? "none" : "block" }}
>
<div id="app">
<div className="pricing-table-main">
<div className="">
<div className="pricing-table-frequency clearfix">
<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>
<div className="pricing-table-body">
<div className="pricing-table popular">
<ul
// className="clearfix Elegant Pro"
className="plans-custom"
>
<li className="plan-item">
<div className="plan-block ">
<h3 id="plan-name">Free</h3>
<div className="pricing-img">
<img
className="icon-basic"
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
alt="freeimg"
/>
</div>
<div className="main-price">
<span className="price-figure">
<small></small>
<span className="basic-plan price-value">
<span
className="otherCurrency"
id="plan-amount"
>
{" "}
0{" "}
</span>
</span>
</span>
<span className="price-term">
<span>Billed Monthly </span>
</span>
<span className="goal">
<a
href={
"https://subscriptions.zoho.in/subscribe/3caf22e54c684d69f22ba6640f3961501c018beadbc1c771dbde1ccf1c7a189d/008" +
details
}
className="rounded"
target="_self"
>
Subscribe
</a>
</span>
</div>
<ul
id="price-features"
className="price-features"
style={{
borderTop: "1px solid rgb(237, 237, 237)",
paddingBottom: 7
}}
>
<li>
<p style={{ position: "relative" }}>
Sign upto 5 documents per month
</p>
</li>
<li>
<p style={{ position: "relative" }}>
5GB secure storage on OpenSignDrive
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Import from Google Drive & Dropbox
</p>
</li>
</ul>
</div>
</li>
<li className="plan-item">
<div className="plan-block">
<h3 id="plan-name">PROFESSIONAL</h3>
<div className="pricing-img">
<img
className="icon-basic"
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
alt="professionalimg"
/>
</div>
<div className="main-price">
<span className="price-figure">
<small></small>
<span className="basic-plan price-value">
<span
className="otherCurrency"
id="plan-amount"
>
{" "}
999{" "}
</span>
</span>
</span>
<span className="price-term">
<span>Billed Monthly </span>
</span>
<span className="goal">
<a
href={
"https://subscriptions.zoho.in/subscribe/3caf22e54c684d69f22ba6640f3961501c018beadbc1c771dbde1ccf1c7a189d/004" +
details
}
className="rounded"
target="_self"
>
Subscribe
</a>
</span>
</div>
<ul
id="price-features"
className="price-features"
style={{
borderTop: "1px solid rgb(237, 237, 237)",
paddingBottom: 7
}}
>
<li>
<p style={{ position: "relative" }}>
Sign upto 50 documents per month
</p>
</li>
<li>
<p style={{ position: "relative" }}>
50GB secure storage on OpenSignDrive
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Import from Google Drive & Dropbox
</p>
</li>
</ul>
</div>
</li>
<li className="plan-item">
<div className="plan-block ">
<h3 id="plan-name">PREMIUM</h3>
<div className="pricing-img">
<img
className="icon-basic"
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
alt="premiumimg"
/>
</div>
<div className="main-price">
<span className="price-figure">
<small></small>
<span className="basic-plan price-value">
<span
className="otherCurrency"
id="plan-amount"
>
{" "}
1999{" "}
</span>
</span>
</span>
<span className="price-term">
<span>Billed Monthly </span>
</span>
<span className="goal">
<a
href={
"https://subscriptions.zoho.in/subscribe/3caf22e54c684d69f22ba6640f3961501c018beadbc1c771dbde1ccf1c7a189d/003" +
details
}
className="rounded"
target="_self"
>
Subscribe
</a>
</span>
</div>
<ul
id="price-features"
className="price-features"
style={{
borderTop: "1px solid rgb(237, 237, 237)",
paddingBottom: 7
}}
>
<li>
<p style={{ position: "relative" }}>
Sign unlimited documents
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Unlimited secure storage on OpenSignDrive
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Import from Google Drive & Dropbox
</p>
</li>
</ul>
</div>
</li>
<li className="plan-item">
<div className="plan-block ">
<h3 id="plan-name">ELITE</h3>
<div className="pricing-img">
<img
className="icon-basic"
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
alt="eliteimg"
/>
</div>
<div className="main-price">
<span className="price-figure">
<small></small>
<span className="basic-plan price-value">
<span
className="otherCurrency"
id="plan-amount"
>
{" "}
3999{" "}
</span>
</span>
</span>
<span className="price-term">
<span>Billed Monthly </span>
</span>
<span className="goal">
<a
href={
"https://subscriptions.zoho.in/subscribe/3caf22e54c684d69f22ba6640f3961501c018beadbc1c771dbde1ccf1c7a189d/006" +
details
}
className="rounded"
target="_self"
>
Subscribe
</a>
</span>
</div>
<ul
id="price-features"
className="price-features"
style={{
borderTop: "1px solid rgb(237, 237, 237)",
paddingBottom: 7
}}
>
<li>
<p style={{ position: "relative" }}>
Sign upto 50 documents per month
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Unlimited secure storage on OpenSignDrive
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Import from Google Drive & Dropbox
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Premium support included{" "}
</p>
</li>
<li>
<p style={{ position: "relative" }}>
SSO supported
</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div
id="yearlyPlans"
style={{ display: yearlyVisible ? "block" : "none" }}
>
<div id="app">
<div className="pricing-table-main">
<div className="">
<div className="pricing-table-frequency clearfix">
<ul
className="navs"
style={{
listStyle: "none",
display: "flex",
alignItems: "baseline"
}}
>
<li className="nav-item">
<a
className="nav-link frequency "
onClick={toggleFrequency}
name="1_months"
>
Monthly
</a>
</li>
<li className="nav-item">
<a className="nav-link frequency active" name="1_years">
Yearly
</a>
</li>
</ul>
</div>
</div>
<div className="pricing-table-body">
<div className="pricing-table popular">
<ul
// className="clearfix Elegant Pro"
className="plans-custom"
>
<li className="plan-item">
<div className="plan-block ">
<h3 id="plan-name">Free</h3>
<div className="pricing-img">
<img
className="icon-basic"
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
alt="freeyimg"
/>
</div>
<div className="main-price">
<span className="price-figure">
<small></small>
<span className="basic-plan price-value">
<span
className="otherCurrency"
id="plan-amount"
>
{" "}
0{" "}
</span>
</span>
</span>
<span className="price-term">
<span>Billed Yearly </span>
</span>
<span className="goal">
<a
href={
"https://subscriptions.zoho.in/subscribe/ef798486e6a0a11ea65f2bae8f2af9019cd1d0c8dd2e4a1818972435fd62a5da/009" +
details
}
className="rounded"
target="_self"
>
Subscribe
</a>
</span>
</div>
<ul
id="price-features"
className="price-features"
style={{
borderTop: "1px solid rgb(237, 237, 237)",
paddingBottom: 7
}}
>
<li>
<p style={{ position: "relative" }}>
Sign upto 5 documents per month
</p>
</li>
<li>
<p style={{ position: "relative" }}>
5GB secure storage on OpenSignDrive
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Import from Google Drive & Dropbox
</p>
</li>
</ul>
</div>
</li>
<li className="plan-item">
<div className="plan-block ">
<h3 id="plan-name">PROFESSIONAL</h3>
<div className="pricing-img">
<img
className="icon-basic"
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
alt="professionalyimg"
/>
</div>
<div className="main-price">
<span className="price-figure">
<small></small>
<span className="basic-plan price-value">
<span
className="otherCurrency"
id="plan-amount"
>
{" "}
5999{" "}
</span>
</span>
</span>
<span className="price-term">
<span>Billed Yearly </span>
</span>
<span className="goal">
<a
href={
"https://subscriptions.zoho.in/subscribe/3caf22e54c684d69f22ba6640f3961501c018beadbc1c771dbde1ccf1c7a189d/005" +
details
}
className="rounded"
target="_self"
>
Subscribe
</a>
</span>
</div>
<ul
id="price-features"
className="price-features"
style={{
borderTop: "1px solid rgb(237, 237, 237)",
paddingBottom: 7
}}
>
<li>
<p style={{ position: "relative" }}>
Sign upto 50 documents per month
</p>
</li>
<li>
<p style={{ position: "relative" }}>
50GB secure storage on OpenSignDrive
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Import from Google Drive & Dropbox
</p>
</li>
</ul>
</div>
</li>
<li className="plan-item">
<div className="plan-block ">
<h3 id="plan-name">PREMIUM</h3>
<div className="pricing-img">
<img
className="icon-basic"
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
alt="premiumyimg"
/>
</div>
<div className="main-price">
<span className="price-figure">
<small></small>
<span className="basic-plan price-value">
<span
className="otherCurrency"
id="plan-amount"
>
{" "}
11999{" "}
</span>
</span>
</span>
<span className="price-term">
<span>Billed Yearly </span>
</span>
<span className="goal">
<a
href={
"https://subscriptions.zoho.in/subscribe/3caf22e54c684d69f22ba6640f3961501c018beadbc1c771dbde1ccf1c7a189d/002" +
details
}
className="rounded"
target="_self"
>
Subscribe
</a>
</span>
</div>
<ul
id="price-features"
className="price-features"
style={{
borderTop: "1px solid rgb(237, 237, 237)",
paddingBottom: 7
}}
>
<li>
<p style={{ position: "relative" }}>
Sign unlimited documents
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Unlimited secure storage on OpenSignDrive
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Import from Google Drive & Dropbox
</p>
</li>
</ul>
</div>
</li>
<li className="plan-item">
<div className="plan-block ">
<h3 id="plan-name">ELITE</h3>
<div className="pricing-img">
<img
className="icon-basic"
src="https://js.zohostatic.com/books/zfwidgets/assets/images/plan.png"
alt="eliteyimg"
/>
</div>
<div className="main-price">
<span className="price-figure">
<small></small>
<span className="basic-plan price-value">
<span
className="otherCurrency"
id="plan-amount"
>
{" "}
23999{" "}
</span>
</span>
</span>
<span className="price-term">
<span>Billed Yearly </span>
</span>
<span className="goal">
<a
href={
"https://subscriptions.zoho.in/subscribe/3caf22e54c684d69f22ba6640f3961501c018beadbc1c771dbde1ccf1c7a189d/007" +
details
}
className="rounded"
target="_self"
>
Subscribe
</a>
</span>
</div>
<ul
id="price-features"
className="price-features"
style={{
borderTop: "1px solid rgb(237, 237, 237)",
paddingBottom: 7
}}
>
<li>
<p style={{ position: "relative" }}>
Sign upto 50 documents per month
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Unlimited secure storage on OpenSignDrive
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Import from Google Drive & Dropbox
</p>
</li>
<li>
<p style={{ position: "relative" }}>
Premium support included{" "}
</p>
</li>
<li>
<p style={{ position: "relative" }}>
SSO supported
</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
)}
</>
);
};
export default PlanSubscriptions;
+83
View File
@@ -0,0 +1,83 @@
import { Suspense } from "react";
import { useParams } from "react-router-dom";
import useFederatedComponent from "mf-cra";
import React from "react";
function RemoteApp({ app }) {
// console.log("app ", app);
const { Component: RemoteComponent } = useFederatedComponent(app);
// console.log("RemoteComponent ", RemoteComponent);
return (
<>
<Suspense
fallback={
<div style={{ height: "300px" }}>
<div
style={{
marginLeft: "45%",
marginTop: "150px",
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
}
>
<div
style={{
boxShadow: "0 1px 3px 0 rgba(0, 0, 0, 0.33)",
backgroundColor: "#ffffff",
width: "100%",
overflow: "hidden",
borderRadius: 3,
minHeight: "70vh"
}}
>
{RemoteComponent && <RemoteComponent />}
</div>
</Suspense>
</>
);
}
function checkObjectProperties(obj) {
// Check if all three properties exist in the object
if (
obj &&
obj.remoteName !== undefined &&
obj.remoteUrl !== undefined &&
obj.moduleToLoad !== undefined
) {
return true; // All properties are present
} else {
return false; // At least one property is missing
}
}
export default function RemoteAppContainer() {
const { remoteApp } = useParams();
// console.log("remoteApp ", remoteApp);
let paramString = remoteApp;
let queryString = new URLSearchParams(paramString);
let obj = {};
for (const [key, value] of queryString.entries()) {
// console.log("value ", key + ":" + value);
if (key === "remoteUrl") {
obj = { ...obj, [key]: atob(value) };
} else {
if (key === "moduleToLoad") {
obj = { ...obj, [key]: "./" + value };
} else {
obj = { ...obj, [key]: value };
}
}
}
// console.log("obj ", obj);
const isMf = checkObjectProperties(obj);
if (isMf) {
const appToLoad = obj;
return <RemoteApp app={appToLoad} />;
} else {
return <div>App not found</div>;
}
}
+97
View File
@@ -0,0 +1,97 @@
import React, { useEffect, useState } from "react";
import ReportTable from "../primitives/GetReportDisplay";
import Parse from "parse";
import axios from "axios";
import reportJson from "../json/ReportJson";
import { useParams } from "react-router-dom";
import Title from "../components/Title";
const Report = () => {
const { id } = useParams();
const [List, setList] = useState([]);
const [isLoader, setIsLoader] = useState(true);
const [reportName, setReportName] = useState("");
const [actions, setActions] = useState([]);
useEffect(() => {
setReportName("");
getReportData();
// eslint-disable-next-line
}, [id]);
const getReportData = async () => {
setIsLoader(true);
const json = reportJson(id);
if (json) {
setActions(json.actions);
setReportName(json.reportName);
const { className, params, keys, orderBy } = json;
Parse.serverURL = localStorage.getItem("BaseUrl12");
Parse.initialize(localStorage.getItem("AppID12"));
const serverURL =
localStorage.getItem("BaseUrl12") + "classes/" + className;
const strParams = JSON.stringify(params);
const strKeys = keys.join();
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("AppID12"),
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
};
try {
const url = `${serverURL}?where=${strParams}&keys=${strKeys}&order=${orderBy}`;
const res = await axios.get(url, { headers: headers });
// console.log("res ", res.data?.results);
setList(res.data?.results);
setIsLoader(false);
} catch (err) {
console.log("err ", err);
setIsLoader(false);
}
} else {
setIsLoader(false);
}
};
return (
<>
<Title title={"Pgsignup page"} />
{isLoader ? (
<div
style={{
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center"
}}
>
<div
style={{
fontSize: "45px",
color: "#3dd3e0"
}}
className="loader-37"
></div>
</div>
) : (
<>
{reportName ? (
<ReportTable
ReportName={reportName}
List={List}
actions={actions}
/>
) : (
<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>
)}
</>
)}
</>
);
};
export default Report;
+680
View File
@@ -0,0 +1,680 @@
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import Parse from "parse";
import axios from "axios";
import Title from "../components/Title";
import { fetchAppInfo, showTenantName } from "../redux/actions";
import { useNavigate, NavLink } from "react-router-dom";
import login_img from "../assets/images/login_img.svg";
const Signup = (props) => {
const navigate = useNavigate();
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [password, setPassword] = useState("");
const [email, setEmail] = useState("");
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [company, setCompany] = useState("");
const [jobTitle, setJobTitle] = useState("");
const [state, setState] = useState({
hideNav: "",
loading: false,
toastColor: "#5cb85c",
toastDescription: ""
});
const [showPassword, setShowPassword] = useState(false);
const togglePasswordVisibility = () => setShowPassword(!showPassword);
const settings = props.appInfo.settings;
const image = props.appInfo.applogo;
const handleSubmit = (event) => {
setState({ loading: true });
const userDetails = {
name: name,
email: email,
phone: phone,
company: company,
jobTitle: jobTitle
};
localStorage.setItem("userDetails", JSON.stringify(userDetails));
try {
event.preventDefault();
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
event.preventDefault();
var user = new Parse.User();
user.set("name", name);
user.set("email", email);
user.set("password", password);
user.set("phone", phone);
user.set("username", email);
let res = user.save();
res
.then(async (r) => {
if (r) {
let roleurl = `${parseBaseUrl}functions/AddUserToRole`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken:
r.getSessionToken() || localStorage.getItem("accesstoken")
};
let body = {
appName: props.appInfo.appname,
roleName: props.appInfo.defaultRole,
userId: r.id
};
await axios.post(roleurl, body, { headers: headers });
let roleData = props.appInfo.settings;
if (roleData && roleData.length > 0) {
roleData.forEach((rld) => {
if (rld.role === props.appInfo.defaultRole) {
const extCls = Parse.Object.extend(rld.extended_class);
const newObj = new extCls();
newObj.set("UserId", {
__type: "Pointer",
className: "_User",
objectId: r.id
});
newObj.set("UserRole", props.appInfo.defaultRole);
newObj.set("Email", email);
newObj.set("Name", name);
newObj.set("Phone", phone);
newObj.set("Company", company);
newObj.set("JobTitle", jobTitle);
newObj
.save()
.then((ex) => {
if (ex) {
handleNavigation(r.getSessionToken());
}
})
.catch((err) => {
alert(err.message);
setState({ loading: false });
});
}
});
}
}
})
.catch((err) => {
alert(err.message);
setState({ loading: false });
});
} catch (error) {
console.log("err ", error);
}
};
const setLocalIframe = (iframeUrl) => {
try {
let data = {
accesstoken: localStorage.getItem("accesstoken"),
baseUrl: localStorage.getItem("baseUrl"),
parseAppId: localStorage.getItem("parseAppId"),
extended_class: localStorage.getItem("extended_class"),
extend_details: localStorage.getItem("Extand_Class"),
userSettings: localStorage.getItem("userSettings"),
username: localStorage.getItem("username"),
_appName: localStorage.getItem("_appName"),
TenetId: localStorage.getItem("TenetId")
};
let storage = JSON.stringify({
key: "storage",
method: "set",
data: data
});
var iframe = document.getElementById("def_iframe");
iframe.contentWindow.postMessage(storage, "*");
setTimeout(() => {
navigate(`/microapp/${iframeUrl}`);
}, 4000);
} catch (error) {
console.log(error);
}
};
const handleNavigation = async (sessionToken) => {
const baseUrl = localStorage.getItem("BaseUrl12");
const parseAppId = localStorage.getItem("AppID12");
const res = await axios.get(baseUrl + "users/me", {
headers: {
"X-Parse-Session-Token": sessionToken,
"X-Parse-Application-Id": parseAppId
}
});
await Parse.User.become(sessionToken).then(() => {
window.localStorage.setItem("accesstoken", sessionToken);
});
// console.log("me res ", res);
if (res.data) {
let _user = res.data;
localStorage.setItem("UserInformation", JSON.stringify(_user));
localStorage.setItem("userEmail", _user.email);
localStorage.setItem("username", _user.name);
localStorage.setItem("accesstoken", _user.sessionToken);
localStorage.setItem("scriptId", true);
if (_user.ProfilePic) {
localStorage.setItem("profileImg", _user.ProfilePic);
} else {
localStorage.setItem("profileImg", "");
}
// Check extended class user role and tenentId
try {
let userRoles = [];
if (props.appInfo.settings) {
let userSettings = props.appInfo.settings;
//Get Current user roles
let url = `${baseUrl}functions/UserGroups`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": parseAppId,
sessionToken: _user.sessionToken
};
let body = {
appname: localStorage.getItem("_appName")
};
await axios
.post(url, JSON.stringify(body), { headers: headers })
.then((roles) => {
if (roles) {
userRoles = roles.data.result;
let _currentRole = "";
if (userRoles.length > 1) {
if (
userRoles[0] ===
`${localStorage.getItem("_appName")}_appeditor`
) {
_currentRole = userRoles[1];
} else {
_currentRole = userRoles[0];
}
} else {
_currentRole = userRoles[0];
}
if (
_currentRole !==
`${localStorage.getItem("_appName")}_appeditor`
) {
userSettings.forEach(async (element) => {
if (element.role === _currentRole) {
let _role = _currentRole.replace(
`${localStorage.getItem("_appName")}_`,
""
);
localStorage.setItem("_user_role", _role);
if (element.enableCart) {
localStorage.setItem("EnableCart", element.enableCart);
props.setEnableCart(element.enableCart);
} else {
localStorage.removeItem("EnableCart");
}
// Get TenentID from Extendend Class
localStorage.setItem(
"extended_class",
element.extended_class
);
localStorage.setItem("userpointer", element.userpointer);
const extendedClass = Parse.Object.extend(
element.extended_class
);
let query = new Parse.Query(extendedClass);
query.equalTo("UserId", Parse.User.current());
query.include("TenantId");
await query.find().then(
(results) => {
let tenentInfo = [];
if (results) {
let extendedInfo_stringify =
JSON.stringify(results);
localStorage.setItem(
"Extand_Class",
extendedInfo_stringify
);
let extendedInfo = JSON.parse(
extendedInfo_stringify
);
if (extendedInfo.length > 1) {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName: x.TenantId.TenantName || ""
};
tenentInfo.push(obj);
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
);
localStorage.setItem(
"TenantName",
tenentInfo[0].tenentName || ""
);
}
localStorage.setItem("showpopup", true);
localStorage.setItem(
"IncludedApps",
JSON.stringify(tenentInfo)
);
localStorage.setItem(
"PageLanding",
element.pageId
);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem(
"pageType",
element.pageType
);
setState({ loading: false });
navigate("/login");
} else {
extendedInfo.forEach((x) => {
if (x.TenantId) {
let obj = {
tenentId: x.TenantId.objectId,
tenentName: x.TenantId.TenantName || ""
};
localStorage.setItem(
"TenetId",
x.TenantId.objectId
);
tenentInfo.push(obj);
}
});
if (tenentInfo.length) {
props.showTenantName(
tenentInfo[0].tenentName || ""
);
localStorage.setItem(
"TenantName",
tenentInfo[0].tenentName || ""
);
}
localStorage.setItem(
"PageLanding",
element.pageId
);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem(
"pageType",
element.pageType
);
setState({ loading: false });
if (
localStorage.getItem("domain") === "contracts"
) {
navigate("/subscription");
} else {
alert("Registered user successfully");
if (element.pageType === "microapp") {
setLocalIframe(element.pageId);
} else {
navigate(
`/${element.pageType}/${element.pageId}`
);
}
}
}
} else {
alert("Registered user successfully");
localStorage.setItem("PageLanding", element.pageId);
localStorage.setItem(
"defaultmenuid",
element.menuId
);
localStorage.setItem("pageType", element.pageType);
setState({ loading: false });
if (
localStorage.getItem("domain") === "contracts"
) {
navigate("/subscription");
} else {
if (element.pageType === "microapp") {
setLocalIframe(element.pageId);
} else {
navigate(
`/${element.pageType}/${element.pageId}`
);
}
}
}
},
(error) => {
/* alert(
"You dont have access to this application."
); */
setState(
{
loading: false,
toastColor: "#d9534f",
toastDescription:
"You dont have access to this application."
},
() => {
var x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 5000);
localStorage.setItem("accesstoken", null);
}
);
console.error("Error while fetching Follow", error);
}
);
}
});
} else {
setState(
{
loading: false,
toastColor: "#d9534f",
toastDescription: "User Role Not Found."
},
() => {
var x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 5000);
}
);
}
} else {
setState(
{
loading: false,
toastColor: "#d9534f",
toastDescription: "User Role Not Found."
},
() => {
var x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 5000);
}
);
}
})
.catch((err) => {
setState(
{
loading: false,
toastColor: "#d9534f",
toastDescription: `Does not have permissions to access this application.`
},
() => {
var x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 5000);
}
);
});
}
} catch (error) {
// alert(`${error.message}`);
setState(
{
loading: false,
toastColor: "#d9534f",
toastDescription: `${error.message}`
},
() => {
var x = document.getElementById("snackbar");
x.className = "show";
setTimeout(function () {
x.className = x.className.replace("show", "");
}, 5000);
}
);
console.log(error);
}
}
};
useEffect(() => {
window.addEventListener("resize", resize);
props.fetchAppInfo(
localStorage.getItem("domain"),
localStorage.getItem("BaseUrl12"),
localStorage.getItem("AppID12")
);
return () => {
window.removeEventListener("resize", resize);
};
// eslint-disable-next-line
}, []);
const resize = () => {
let currentHideNav = window.innerWidth <= 760;
if (currentHideNav !== state.hideNav) {
setState({ hideNav: currentHideNav });
}
};
return (
<div className="bg-white">
{state.loading && (
<div
style={{
position: "fixed",
width: "100vw",
height: "100vh",
backgroundColor: "rgba(0,0,0,0.2)",
top: 0,
left: 0,
zIndex: 2
}}
>
<div
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
}}
className="loader-37"
></div>
</div>
)}
{settings &&
settings.map((x) => {
return x.pageType === "microapp" ? (
<iframe
key={x.pageId}
id="def_iframe"
src={x.pageId}
height="0px"
width="0px"
title="signi"
/>
) : null;
})}
<Title title={"Signup page"} />
{props.isloginVisible && props.isloginVisible ? (
<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">
{state.hideNav ? (
<img src={image} width="100%" alt="" />
) : (
<img src={image} width="100%" alt="" />
)}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
<div className="">
<form onSubmit={handleSubmit}>
<h2 className="text-[30px] mt-6">Create Account !</h2>
<div className="shadow-md rounded my-4">
<div className="px-6 py-4 text-xs">
<label className="block ">
Name{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label>
<input
type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
<hr className="my-2 border-none" />
<label>
Email{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label>
<input
type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<hr className="my-2 border-none" />
<label>
Phone{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label>
<input
type="tel"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
value={phone}
onChange={(e) => setPhone(e.target.value)}
required
/>
<hr className="my-2 border-none" />
<label>
Company{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label>
<input
type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
value={company}
onChange={(e) => setCompany(e.target.value)}
required
/>
<hr className="my-2 border-none" />
<label>
Job Title{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label>
<input
type="text"
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
value={jobTitle}
onChange={(e) => setJobTitle(e.target.value)}
required
/>
<hr className="my-2 border-none" />
<label>
Password{" "}
<span style={{ color: "red", fontSize: 13 }}>*</span>
</label>
<div className="relative">
<input
type={showPassword ? "text" : "password"}
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded focus:outline-none text-xs"
name="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<span
className={`absolute top-[50%] right-[10px] -translate-y-[50%] cursor-pointer ${
showPassword ? "text-[#007bff]" : "text-black"
}`}
onClick={togglePasswordVisibility}
>
{showPassword ? (
<i className="fa fa-eye-slash" /> // Close eye icon
) : (
<i className="fa fa-eye" /> // Open eye icon
)}
</span>
</div>
</div>
</div>
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2">
<button
type="submit"
className="rounded-sm bg-[#3ac9d6] text-white w-full py-3 shadow uppercase"
disabled={state.loading}
>
{state.loading ? "Loading..." : "Register"}
</button>
<NavLink
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
to="/"
style={state.hideNav ? { textAlign: "center" } : {}}
>
Login
</NavLink>
</div>
</form>
</div>
{!state.hideNav && (
<div className="self-center">
<div className="mx-auto md:w-[300px] lg:w-[500px]">
<img src={login_img} alt="bisec" width="100%" />
</div>
</div>
)}
</div>
</div>
<div id="snackbar" style={{ backgroundColor: state.toastColor }}>
{state.toastDescription}
</div>
</div>
) : (
<div
style={{
position: "fixed",
fontSize: "50px",
color: "#3ac9d6",
top: "50%",
left: "45%"
}}
className="loader-37"
></div>
)}
</div>
);
};
const mapStateToProps = (state) => {
if (Object.keys(state.appInfo).length !== 0) {
return { appInfo: state.appInfo, isloginVisible: true };
} else {
return { appInfo: state.appInfo, isloginVisible: false };
}
};
export default connect(mapStateToProps, {
fetchAppInfo,
showTenantName
})(Signup);
+253
View File
@@ -0,0 +1,253 @@
import React, { useState } from "react";
import { Navigate, useNavigate } from "react-router-dom";
import Parse from "parse";
import { SaveFileSize } from "../constant/saveFileSize";
import dp from "../assets/images/dp.png";
function UserProfile() {
const navigate = useNavigate();
let UserProfile = JSON.parse(localStorage.getItem("UserInformation"));
const [parseBaseUrl] = useState(localStorage.getItem("baseUrl"));
const [parseAppId] = useState(localStorage.getItem("parseAppId"));
const [editmode, setEditMode] = useState(false);
const [name, SetName] = useState(localStorage.getItem("username"));
const [Phone, SetPhone] = useState(UserProfile && UserProfile.phone);
const [Image, setImage] = useState(localStorage.getItem("profileImg"));
const [isLoader, setIsLoader] = useState(false);
Parse.serverURL = parseBaseUrl;
Parse.initialize(parseAppId);
const handleSubmit = async (e) => {
e.preventDefault();
setIsLoader(true);
let phn = Phone;
try {
const tour = Parse.Object.extend("_User");
const query = new Parse.Query(tour);
await query.get(UserProfile.objectId).then((object) => {
object.set("name", name);
object.set("ProfilePic", Image);
object.set("phone", phn);
object.save().then(
async (response) => {
if (response) {
let res = response.toJSON();
let rr = JSON.stringify(res);
localStorage.setItem("UserInformation", rr);
SetName(res.name);
SetPhone(res.phone);
setImage(res.ProfilePic);
localStorage.setItem("username", res.name);
await updateExtUser({ Name: res.name, Phone: res.phone });
alert("Profile updated successfully.");
setEditMode(false);
navigate("/");
}
},
(error) => {
alert("Something went wrong.");
console.error("Error while updating tour", error);
setIsLoader(false);
}
);
});
} catch (error) {
console.log("err", error);
}
};
// `updateExtUser` is used to update user details in extended class
const updateExtUser = async (obj) => {
const extClass = localStorage.getItem("extended_class");
const extData = JSON.parse(localStorage.getItem("Extand_Class"));
const ExtUserId = extData[0].objectId;
// console.log("extData ", extData);
// console.log("UserId ", ExtUserId);
const extQuery = new Parse.Query(extClass);
const update = await extQuery.get(ExtUserId);
// console.log("update ", update);
update.set("Phone", obj.Phone);
update.set("Name", obj.Name);
const updateRes = await update.save();
const json = JSON.parse(JSON.stringify([updateRes]));
const extRes = JSON.stringify(json);
localStorage.setItem("Extand_Class", extRes);
// console.log("updateRes ", updateRes);
};
// file upload function
const fileUpload = async (file) => {
if (file) {
await handleFileUpload(file);
}
};
const handleFileUpload = async (file) => {
const size = file.size;
const pdfFile = file;
const parseFile = new Parse.File(pdfFile.name, pdfFile);
try {
const response = await parseFile.save();
// // 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()) {
setImage(response.url());
localStorage.setItem("profileImg", response.url());
SaveFileSize(size, response.url());
return response.url();
}
} catch (error) {
console.error("Error uploading file:", error);
}
};
if (
localStorage.getItem("accesstoken") === null &&
localStorage.getItem("pageType") === null
) {
let _redirect = `/`;
return <Navigate to={_redirect} />;
}
return (
<React.Fragment>
{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">
<div className="flex flex-col justify-center items-center my-4">
<div className="w-[200px] h-[200px] overflow-hidden rounded-full">
<img
className="object-contain w-full h-full"
src={Image === "" ? dp : Image}
alt="dp"
/>
</div>
{editmode && (
<input
type="file"
className="max-w-[270px] text-sm py-1 px-2 mt-4 border-[1px] border-[#15b4e9] text-black rounded"
onChange={(e) => {
let files = e.target.files;
fileUpload(files[0]);
}}
/>
)}
<div className="text-base font-semibold pt-4">
{" "}
{localStorage.getItem("_user_role")}
</div>
</div>
<ul className="w-full flex flex-col p-2 text-sm">
<li
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
editmode ? "py-1" : "py-2"
}`}
>
<span>Name:</span>{" "}
{editmode ? (
<input
type="text"
value={name}
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded"
onChange={(e) => SetName(e.target.value)}
/>
) : (
<span>{localStorage.getItem("username")}</span>
)}
</li>
<li
className={`flex justify-between items-center border-t-[1px] border-gray-300 break-all ${
editmode ? "py-1" : "py-2"
}`}
>
<span>Phone:</span>{" "}
{editmode ? (
<input
type="text"
className="py-1 px-2 text-sm border-[1px] border-[#15b4e9] text-black rounded"
onChange={(e) => SetPhone(e.target.value)}
value={Phone}
/>
) : (
<span>{UserProfile && UserProfile.phone}</span>
)}
</li>
<li className="flex justify-between items-center border-t-[1px] border-gray-300 py-2 break-all">
<span>Email:</span>{" "}
<span>{UserProfile && UserProfile.email}</span>
</li>
<li className="flex justify-between items-center border-y-[1px] border-gray-300 py-2 break-all">
<span>Is Email verified:</span>{" "}
<span>
{UserProfile && UserProfile.emailVerified
? "Verified"
: "Not verified"}
</span>
</li>
</ul>
<div className="flex justify-center pb-4">
<button
type="button"
onClick={() => {
if (editmode) {
setEditMode(false);
} else {
navigate("/changepassword");
}
}}
className={`rounded shadow text-white bg-[#3598dc] mr-4 ${
editmode ? "px-4 py-2 " : "p-2"
}`}
>
{editmode ? "Cancel" : "Change Password"}
</button>
{editmode ? (
<button
type="button"
onClick={handleSubmit}
className="rounded bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] px-4 py-2"
>
Save
</button>
) : (
<button
type="button"
onClick={() => {
setEditMode(true);
}}
className="rounded shadow text-white bg-[#e7505a] px-4 py-2"
>
Edit
</button>
)}
</div>
</div>
)}
</React.Fragment>
);
}
export default UserProfile;
+57
View File
@@ -0,0 +1,57 @@
.submiBtn {
background: #1ab6ce;
border-radius: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
border: none;
text-transform: uppercase;
font-size: 13px;
font-weight: 600;
}
.submiBtn:hover {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
background: #028fa5;
color: white;
}
.resetBtn {
background: #188ae2;
border-radius: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
border: none;
color: white;
text-transform: uppercase;
font-size: 13px;
font-weight: 600;
}
.resetBtn:hover {
box-shadow: 0 2px 4px rgba(27, 26, 26, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
background: #0362aa;
color: white;
}
.form-group {
margin-bottom: 0.5rem;
}
.required{
color: red;
}
.form-control {
height: 35px;
font-size: 12px;
}
.form-group.field.field-object {
margin-left: 5px;
}
legend{
font-size: 17px;
font-weight: 500;
}
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
.modal-backdrop {
position: relative;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1040;
background-color: #000;
}
.createFolder {
background-color: rgb(0, 128, 128);
color: #fff;
width: auto;
padding: 3px 17px
}
.createFolder:hover {
box-shadow: 0 2px 4px rgba(27, 26, 26, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
background-color: rgb(2, 146, 146);
}
.deleteFolder {
background-color: rgb(0, 51, 128);
color: #fff;
margin-left: 4px;
width: auto;
padding: 2px 17px
}
.deleteFolder:hover {
box-shadow: 0 2px 4px rgba(36, 35, 35, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
background-color: rgb(6, 68, 161);
}
.saveFolder {
background-color: rgb(51, 51, 51);
color: #fff;
margin-left: 4px;
width: auto;
padding: 4px 17px;
}
.saveFolder:hover{
box-shadow: 0 2px 4px rgba(36, 35, 35, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18);
background-color: rgb(63, 62, 62);
}
+118
View File
@@ -0,0 +1,118 @@
/* Full-width input fields */
.inputt {
width: 100%;
padding: 15px;
margin: 5px 0 22px 0;
display: inline-block;
border: none;
background: #f1f1f1;
color: black;
}
/* Add a background color when the inputs get focus */
.inputt:focus {
background-color: #ddd;
outline: none;
}
.confirmInputt {
width: 100%;
padding: 15px;
margin: 5px 0 1px 0;
display: inline-block;
background: #f1f1f1;
color: black;
}
.inputt::placeholder,
.confirmInputt::placeholder {
color: #474e5d;
opacity: 1;
/* Firefox */
}
.inputt:-ms-input-placeholder,
.confirmInputt:-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: #474e5d;
}
/* Set a style for all buttons */
.signupbtn {
background-color: #15b4e9;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
cursor: pointer;
width: 100%;
opacity: 0.9;
float: left;
width: 50%;
}
.signupbtn:hover {
opacity: 1;
}
/* Add padding to pgsignup-container elements */
.pgsignup-container {
padding: 16px;
}
/* The pgsignup (background) */
.pgsignup {
display: none;
/* Hidden by default */
position: fixed;
/* Stay in place */
z-index: 1;
/* Sit on top */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
overflow: auto;
/* Enable scroll if needed */
background-color: #474e5d;
padding-top: 50px;
}
/* pgsignup Content/Box */
.pgsignup-content {
background-color: #fefefe;
margin: 5% auto 15% auto;
/* 5% from the top, 15% from the bottom and centered */
border: 1px solid #888;
width: 80%;
/* Could be more or less, depending on screen size */
}
/* Style the horizontal ruler */
.hrt {
border: 1px solid #f1f1f1;
margin-bottom: 25px;
}
.clearfix {
display: flex;
justify-content: center;
align-items: center;
}
/* Clear floats */
.clearfix::after {
content: "";
clear: both;
display: table;
}
/* Change styles for cancel button and signup button on extra small screens */
@media screen and (max-width: 300px) {
.signupbtn {
width: 100%;
}
}
File diff suppressed because it is too large Load Diff
+59
View File
@@ -0,0 +1,59 @@
.Loader,
.Loader:before,
.Loader:after {
background: #fff;
-webkit-animation: load1 1s infinite ease-in-out;
animation: load1 1s infinite ease-in-out;
width: 1em;
height: 4em;
}
.Loader {
color: #e62d2d;
text-indent: -9999em;
margin: 88px auto;
position: relative;
font-size: 11px;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
.Loader:before,
.Loader:after {
position: absolute;
top: 0;
content: '';
}
.Loader:before {
left: -1.5em;
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.Loader:after {
left: 1.5em;
}
@-webkit-keyframes load1 {
0%,
80%,
100% {
box-shadow: 0 0;
height: 4em;
}
40% {
box-shadow: 0 -2em;
height: 5em;
}
}
@keyframes load1 {
0%,
80%,
100% {
box-shadow: 0 0;
height: 4em;
}
40% {
box-shadow: 0 -2em;
height: 5em;
}
}

Some files were not shown because too many files have changed in this diff Show More