From b381ace8357cb6def4fe86aab503d90347ef2406 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 26 Dec 2023 12:51:51 +0530 Subject: [PATCH 001/303] refactor: table and apply filter Signed-off-by: karan --- package-lock.json | 16 +- package.json | 4 +- src/commonComponents/datatable/dummytable.tsx | 653 ++++++++++++++++++ src/commonComponents/datatable/index.tsx | 305 ++++++-- src/components/Issuance/IssuedCrdentials.tsx | 110 ++- src/components/SearchInput/index.tsx | 66 +- 6 files changed, 1026 insertions(+), 128 deletions(-) create mode 100644 src/commonComponents/datatable/dummytable.tsx diff --git a/package-lock.json b/package-lock.json index f310511ed..5811ff266 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,8 +28,8 @@ "crypto-js": "^4.1.1", "dom-to-image": "^2.6.0", "downloadjs": "^1.4.7", - "flowbite": "^1.7.0", - "flowbite-react": "^0.4.10", + "flowbite": "^1.8.1", + "flowbite-react": "^0.4.11", "flowbite-typography": "^1.0.3", "formik": "^2.4.5", "html2canvas": "^1.4.1", @@ -4380,9 +4380,9 @@ } }, "node_modules/flowbite-react": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/flowbite-react/-/flowbite-react-0.4.10.tgz", - "integrity": "sha512-VGtOJDOSk3VF6MODerKQ9AbP9Um0MdkI8YMJOUkL/Gou4/mnAOYMNuheUqF/tqg6WkxWsqcDybPgl87bYRI4LQ==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/flowbite-react/-/flowbite-react-0.4.11.tgz", + "integrity": "sha512-QB0PWB/kiogL0YQlT+X1x4Ue0D3cpd+WaiCbGsMqo2LCYySRsctHxEciRQji3JELGuc6O1OaBtK9ZUSErQkJEg==", "dependencies": { "@floating-ui/react": "^0.24.3", "flowbite": "^1.6.6", @@ -15720,9 +15720,9 @@ } }, "flowbite-react": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/flowbite-react/-/flowbite-react-0.4.10.tgz", - "integrity": "sha512-VGtOJDOSk3VF6MODerKQ9AbP9Um0MdkI8YMJOUkL/Gou4/mnAOYMNuheUqF/tqg6WkxWsqcDybPgl87bYRI4LQ==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/flowbite-react/-/flowbite-react-0.4.11.tgz", + "integrity": "sha512-QB0PWB/kiogL0YQlT+X1x4Ue0D3cpd+WaiCbGsMqo2LCYySRsctHxEciRQji3JELGuc6O1OaBtK9ZUSErQkJEg==", "requires": { "@floating-ui/react": "^0.24.3", "flowbite": "^1.6.6", diff --git a/package.json b/package.json index 0334396c0..1405581ee 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "crypto-js": "^4.1.1", "dom-to-image": "^2.6.0", "downloadjs": "^1.4.7", - "flowbite": "^1.7.0", - "flowbite-react": "^0.4.10", + "flowbite": "^1.8.1", + "flowbite-react": "^0.4.11", "flowbite-typography": "^1.0.3", "formik": "^2.4.5", "html2canvas": "^1.4.1", diff --git a/src/commonComponents/datatable/dummytable.tsx b/src/commonComponents/datatable/dummytable.tsx new file mode 100644 index 000000000..5020c8040 --- /dev/null +++ b/src/commonComponents/datatable/dummytable.tsx @@ -0,0 +1,653 @@ +{ + /*
+
+ +
+
+
+
+ +
+
+ +
+ +
+
+
+
+ +
+ +
+ + +
+ +
+
Choose brand
+
    +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
  • + + +
  • +
+
+
+
+
+ + + + +
+ + + + {Headers && + Headers.length > 0 && + Headers.map((ele) => ( + +// ))} +// +// + +// {loading ? ( +//
+// +//
+// ) : ( +// +// {data.length ? ( +// data.map((ele, index) => ( +// +// {ele.data.map((subEle, index) => ( +// +// ))} +// {displaySelect || +// (showBtn && ( +// +// ))} +// +// )) +// ) : ( +// +// +// +// )} +// +// )} +//
+
{ele.columnName}
+ {ele.subColumnName && ( +
+ {ele.subColumnName}{' '}// <> + //
+ //
+ //
+ // + //
+ //
+ // + //
+ // + //
+ //
+ //
+ //
+ // + //
+ // + //
+ // + // + //
+ // + //
+ //
+ //
+ //
+ + // {/*
*/ +} + +//
+//
+//
+//
+ +//
+//
+//
+//
+//
+// +//
+// )} +//
+//
{subEle.data}
+// {subEle.subData && subEle.subData} +//
+// Empty data +//
+//
+ +// +//
+//
+//
+ +// <> +//
+//
+//
+// +//
+//
+// +//
+// +//
+//
+//
+//
+// +//
+// +//
+// +// +//
+// +//
+//
+//
+//
+ +// {/*
*/} + +//
+//
+//
+//
+ +//
+//
+//
+//
+//
+// + +// ================================================ + +// <> +//
+//
+//
+// +//
+//
+// +//
+// +//
+//
+//
+//
+// +//
+// +//
+// +// +//
+// +//
+//
+//
+//
+ +// {/*
*/} + +//
+//
+//
+//
+ +//
+//
+//
+//
+//
+// diff --git a/src/commonComponents/datatable/index.tsx b/src/commonComponents/datatable/index.tsx index e03116289..eb7a5a1d6 100644 --- a/src/commonComponents/datatable/index.tsx +++ b/src/commonComponents/datatable/index.tsx @@ -1,72 +1,269 @@ -import type { TableData, TableHeader } from "./interface" +import type { TableData, TableHeader } from './interface'; -import CustomSpinner from "../../components/CustomSpinner"; +import CustomSpinner from '../../components/CustomSpinner'; +import SearchInput from '../../components/SearchInput'; +import { Pagination } from 'flowbite-react'; +import { useState } from 'react'; interface DataTableProps { header: TableHeader[]; data: TableData[]; loading: boolean; callback?: (clickId: string | null | undefined) => void; - displaySelect?:boolean; - showBtn?:boolean + displaySelect?: boolean; + showBtn?: boolean; + onInputChange: () => void; + refresh: () => void; + currentPage: any; + onPageChange: () => void; + totalPages: number; + pageInfo: { totalItem: number; nextPage: number; lastPage: number }; + searchSortByValue: () => void; + statusValues: []; + filterByValue: ()=>void } -const DataTable: React.FC = ({ header,displaySelect, data, loading, callback ,showBtn}) => { +const DataTable: React.FC = ({ + header, + displaySelect, + data, + loading, + callback, + showBtn, + onInputChange, + refresh, + currentPage, + onPageChange, + totalPages, + pageInfo, + searchSortByValue, + statusValues, + filterByValue +}) => { + const [selectedValue, setSelectedValue] = useState(''); + const [filterValue, setFilerValue]= useState('') + + console.log("filterValue",filterValue); + + const handleSortByValues = (event: { target: { value: any } }) => { + const newSelectedFruit = event.target.value; + setSelectedValue(newSelectedFruit); + searchSortByValue(newSelectedFruit); + }; + const handleFilterByValues = (event: { target: { value: any } }) => { + const newFilteredValue = event.target.value; + setFilerValue(newFilteredValue); + filterByValue(newFilteredValue); + }; + const { totalItem, nextPage, lastPage } = pageInfo; + const startItem = (nextPage - 2) * 10 + 1; + const endItem = Math.min((nextPage - 1) * 10, totalItem); + + const sortValues = [ + { + label: 'latest', + value: 'DESC', + }, + { label: 'oldest', value: 'AESC' }, + ]; return ( -
- {loading - ?
- - -
- :
-
-
- +
+
+
+
+
+ +
+
+ +
+ +
+ +
+
+
- - {header && header.length > 0 && - header.map(ele => ( - - ))} - - - - {data.length ? data.map((ele, index) => ( - - + + + + - {ele.data.map((subEle,index) => ( - + )} + + + )} +
-
{ele.columnName}
- {ele.subColumnName &&
{ele.subColumnName}
} + + refresh + +
+ {/* className="w-full md:w-auto flex items-center justify-center py-2 px-4 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700" */} + -
-
{subEle.data}
- {subEle.subData && subEle.subData} +
+ + + + {header && + header.length > 0 && + header.map((ele) => ( + + ))} + + + + {loading ? ( +
+ +
+ ) : ( + <> + + {data.length ? ( + data.map((ele, index) => ( + + {ele.data.map((subEle, index) => ( + + ))} + {displaySelect || + (showBtn && ( + + ))} + + )) + ) : ( + + - ))} - {displaySelect || showBtn && - - } - - )) : } - -
+
{ele.columnName}
+ {ele.subColumnName && ( +
+ {ele.subColumnName}{' '} +
+ )} +
+
{subEle.data}
+ {subEle.subData && subEle.subData} +
+ Empty data
Empty data
-
+
+ {loading ? ( + '' + ) : ( + + )}
- } -
- ) -} - +
+ + ); +}; -export default DataTable +export default DataTable; diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 5f5f6a02f..5b967475b 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -29,7 +29,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: '', allSearch: '', }; @@ -41,6 +41,15 @@ const CredentialList = () => { const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [totalItem, setTotalItem] = useState(0); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); + const [statusValues, setStatusValues] = useState([]); + console.log('statusValues::', statusValues); + + console.log('listAPIParameter::', listAPIParameter.sortingOrder); const getIssuedCredDefs = async ( listAPIParameter: IConnectionListAPIParameter, @@ -59,12 +68,22 @@ const CredentialList = () => { if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setTotalItem(data?.data.totalItems); + const { totalItems, nextPage, lastPage } = data.data; + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, + }); const credentialList = data?.data?.data?.map( (issuedCredential: IssuedCredential) => { const schemaName = issuedCredential.schemaId ? issuedCredential.schemaId.split(':').slice(2).join(':') : 'Not available'; - + setStatusValues((prevStatusValues) => [ + ...prevStatusValues, + issuedCredential?.state + ]); return { data: [ { @@ -141,7 +160,6 @@ const CredentialList = () => { }; }, ); - setIssuedCredList(credentialList); setError(null); } else { @@ -154,10 +172,23 @@ const CredentialList = () => { } finally { setLoading(false); } - } + }; useEffect(() => { - getIssuedCredDefs(listAPIParameter); + let getData: NodeJS.Timeout; + + if (listAPIParameter.search.length >= 1) { + getData = setTimeout(() => { + getIssuedCredDefs(listAPIParameter); + }, 1000); + return () => clearTimeout(getData); + } else { + getIssuedCredDefs(listAPIParameter); + } + + return () => clearTimeout(getData); + + // getIssuedCredDefs(listAPIParameter); }, [listAPIParameter]); //onChange of Search input text @@ -169,6 +200,22 @@ const CredentialList = () => { }); }; + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + + const filterByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortBy: value, + }); + }; + const schemeSelection = () => { window.location.href = pathRoutes.organizations.Issuance.issue; }; @@ -194,9 +241,7 @@ const CredentialList = () => {

Credentials

-
- -
+
{/* */}
) : (
- {loading ? ( -
- -
- ) : issuedCredList && issuedCredList.length > 0 ? ( + {issuedCredList && (
- {issuedCredList && issuedCredList.length > 0 && ( - - )} + {/* {issuedCredList && issuedCredList.length > 0 && ( */} + { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + totalPages={Math.ceil( + totalItem / listAPIParameter?.itemPerPage, + )} + pageInfo={pageInfo} + searchSortByValue={searchSortByValue} + statusValues={statusValues} + filterByValue={filterByValue} + > + {/* )} */}
{Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && (
- { setListAPIParameter((prevState) => ({ @@ -289,16 +346,10 @@ const CredentialList = () => { totalPages={Math.ceil( totalItem / listAPIParameter?.itemPerPage, )} - /> + /> */}
)}
- ) : ( -
- - There isn't any data available. - -
)}
)} @@ -308,4 +359,5 @@ const CredentialList = () => { ); }; -export default CredentialList; + +export default CredentialList diff --git a/src/components/SearchInput/index.tsx b/src/components/SearchInput/index.tsx index 9b9392352..31d6f2827 100644 --- a/src/components/SearchInput/index.tsx +++ b/src/components/SearchInput/index.tsx @@ -1,37 +1,33 @@ - - -const SearchInput = ({onInputChange}) => { - - return ( -
- -
-
- +const SearchInput = ({ onInputChange }: any) => { + return ( +
+ +
+
+ + + +
+ +
- -
-
- ); - -} + ); +}; -export default SearchInput \ No newline at end of file +export default SearchInput; From 32c8434633770be7f725ee49ed68e7cf27198b38 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Fri, 29 Dec 2023 00:26:51 +0530 Subject: [PATCH 002/303] refactor get proof presentation api routes Signed-off-by: bhavanakarwade --- src/api/verification.ts | 4 ++-- src/components/Verification/VerificationCredentialList.tsx | 6 +++--- src/config/apiRoutes.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api/verification.ts b/src/api/verification.ts index 4bbc98eb4..150f09775 100644 --- a/src/api/verification.ts +++ b/src/api/verification.ts @@ -79,8 +79,8 @@ export const verifyPresentation = async (proofId:string) => { }; -export const getProofAttributes=async (proofId:string, orgId: string)=>{ - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.proofRequestAttributesVerification}/${proofId}/form`; +export const getVerifiedProofDetails=async (proofId:string, orgId: string)=>{ + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.proofRequestAttributesVerification}/${proofId}`; const axiosPayload = { url, config: await getHeaderConfigs(), diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 3c600eccd..4f737637e 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -8,7 +8,7 @@ import { } from '../../common/enums'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { - getProofAttributes, + getVerifiedProofDetails, getVerificationList, verifyPresentation, } from '../../api/verification'; @@ -55,10 +55,10 @@ const VerificationCredentialList = () => { useState(initialPageState); const [totalItem, setTotalItem] = useState(0); - const getProofPresentationData = async (id: string) => { + const getProofPresentationData = async (proofId: string) => { try { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const response = await getProofAttributes(id, orgId); + const response = await getVerifiedProofDetails(proofId, orgId); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes?.API_STATUS_SUCCESS) { diff --git a/src/config/apiRoutes.ts b/src/config/apiRoutes.ts index 0e6f3b72a..361dea32a 100644 --- a/src/config/apiRoutes.ts +++ b/src/config/apiRoutes.ts @@ -66,7 +66,7 @@ export const apiRoutes = { getAllRequestList: '/credentials/proofs', verifyCredential: '/proofs', presentationVerification: '/proofs', - proofRequestAttributesVerification: '/proofs', + proofRequestAttributesVerification: '/verified-proofs', verificationCredDef: '/verifiation/cred-defs' }, Agent: { From b90d37c61b8aaeb0574de4773dbac961539409ea Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 29 Dec 2023 12:27:34 +0530 Subject: [PATCH 003/303] table changes Signed-off-by: karan --- src/api/connection.ts | 1 + src/api/issuance.ts | 3 +- src/commonComponents/datatable/index.tsx | 37 ++++++++------------ src/components/Issuance/IssuedCrdentials.tsx | 22 ++---------- 4 files changed, 19 insertions(+), 44 deletions(-) diff --git a/src/api/connection.ts b/src/api/connection.ts index 464c1040d..900947f0e 100644 --- a/src/api/connection.ts +++ b/src/api/connection.ts @@ -9,6 +9,7 @@ export interface IConnectionListAPIParameter { search: string, sortBy: string, sortingOrder: string, + filter?: string } export const getConnectionsByOrg = async ({ diff --git a/src/api/issuance.ts b/src/api/issuance.ts index e502b364d..512f54ed5 100644 --- a/src/api/issuance.ts +++ b/src/api/issuance.ts @@ -12,7 +12,8 @@ export const getIssuedCredentials = async ({page, itemPerPage, search, sortBy, - sortingOrder}: IConnectionListAPIParameter) => { + sortingOrder, +filter}: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getIssuedCredentials}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortByValue=${sortingOrder}&sorting=${sortBy}`; diff --git a/src/commonComponents/datatable/index.tsx b/src/commonComponents/datatable/index.tsx index eb7a5a1d6..c38538db9 100644 --- a/src/commonComponents/datatable/index.tsx +++ b/src/commonComponents/datatable/index.tsx @@ -20,7 +20,6 @@ interface DataTableProps { pageInfo: { totalItem: number; nextPage: number; lastPage: number }; searchSortByValue: () => void; statusValues: []; - filterByValue: ()=>void } const DataTable: React.FC = ({ @@ -37,24 +36,15 @@ const DataTable: React.FC = ({ totalPages, pageInfo, searchSortByValue, - statusValues, - filterByValue }) => { const [selectedValue, setSelectedValue] = useState(''); - const [filterValue, setFilerValue]= useState('') - console.log("filterValue",filterValue); - const handleSortByValues = (event: { target: { value: any } }) => { - const newSelectedFruit = event.target.value; - setSelectedValue(newSelectedFruit); - searchSortByValue(newSelectedFruit); - }; - const handleFilterByValues = (event: { target: { value: any } }) => { - const newFilteredValue = event.target.value; - setFilerValue(newFilteredValue); - filterByValue(newFilteredValue); + const newSelectedValue = event.target.value; + setSelectedValue(newSelectedValue); + searchSortByValue(newSelectedValue); }; + const { totalItem, nextPage, lastPage } = pageInfo; const startItem = (nextPage - 2) * 10 + 1; const endItem = Math.min((nextPage - 1) * 10, totalItem); @@ -128,28 +118,29 @@ const DataTable: React.FC = ({ onChange={handleSortByValues} > {/* */} - + {sortValues.map((sort) => { return ( <> - + ); })} - + {options.map((option) => ( + + ))} + */}
diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 5b967475b..6341dcd47 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -31,6 +31,7 @@ const initialPageState = { sortBy: 'createDateTime', sortingOrder: '', allSearch: '', + filter: '', }; const CredentialList = () => { @@ -46,10 +47,6 @@ const CredentialList = () => { nextPage: '', lastPage: '', }); - const [statusValues, setStatusValues] = useState([]); - console.log('statusValues::', statusValues); - - console.log('listAPIParameter::', listAPIParameter.sortingOrder); const getIssuedCredDefs = async ( listAPIParameter: IConnectionListAPIParameter, @@ -80,10 +77,6 @@ const CredentialList = () => { const schemaName = issuedCredential.schemaId ? issuedCredential.schemaId.split(':').slice(2).join(':') : 'Not available'; - setStatusValues((prevStatusValues) => [ - ...prevStatusValues, - issuedCredential?.state - ]); return { data: [ { @@ -208,14 +201,6 @@ const CredentialList = () => { }); }; - const filterByValue = (value: any) => { - setListAPIParameter({ - ...listAPIParameter, - page: 1, - sortBy: value, - }); - }; - const schemeSelection = () => { window.location.href = pathRoutes.organizations.Issuance.issue; }; @@ -328,8 +313,6 @@ const CredentialList = () => { )} pageInfo={pageInfo} searchSortByValue={searchSortByValue} - statusValues={statusValues} - filterByValue={filterByValue} > {/* )} */} @@ -359,5 +342,4 @@ const CredentialList = () => { ); }; - -export default CredentialList +export default CredentialList; From 78578a4853152543fc0e87cd93ca2e10d1ba248b Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 3 Jan 2024 12:20:05 +0530 Subject: [PATCH 004/303] refactor: datatable for updated design Signed-off-by: karan --- src/api/connection.ts | 20 +- src/api/issuance.ts | 2 +- src/api/verification.ts | 15 +- .../datatable/SortDataTable.tsx | 299 ++++++++ src/commonComponents/datatable/dummytable.tsx | 653 ------------------ src/commonComponents/datatable/index.tsx | 301 ++------ src/components/ConnectionsList/index.tsx | 100 ++- src/components/Issuance/IssuedCrdentials.tsx | 98 +-- .../VerificationCredentialList.tsx | 97 +-- 9 files changed, 527 insertions(+), 1058 deletions(-) create mode 100644 src/commonComponents/datatable/SortDataTable.tsx delete mode 100644 src/commonComponents/datatable/dummytable.tsx diff --git a/src/api/connection.ts b/src/api/connection.ts index 900947f0e..1573a6763 100644 --- a/src/api/connection.ts +++ b/src/api/connection.ts @@ -4,24 +4,24 @@ import { getHeaderConfigs } from '../config/GetHeaderConfigs'; import { axiosGet } from '../services/apiRequests'; import { getFromLocalStorage } from './Auth'; export interface IConnectionListAPIParameter { - itemPerPage: number, - page: number, - search: string, - sortBy: string, - sortingOrder: string, - filter?: string - } + itemPerPage: number; + page: number; + search: string; + sortBy: string; + sortingOrder: string; + filter?: string; +} export const getConnectionsByOrg = async ({ page, itemPerPage, search, sortBy, - sortingOrder + sortingOrder, }: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getAllConnections}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortByValue=${sortingOrder}&sorting=${sortBy}`; - + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getAllConnections}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; + const axiosPayload = { url, config: await getHeaderConfigs(), diff --git a/src/api/issuance.ts b/src/api/issuance.ts index 512f54ed5..365e98e36 100644 --- a/src/api/issuance.ts +++ b/src/api/issuance.ts @@ -15,7 +15,7 @@ export const getIssuedCredentials = async ({page, sortingOrder, filter}: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getIssuedCredentials}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortByValue=${sortingOrder}&sorting=${sortBy}`; + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getIssuedCredentials}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; const axiosPayload = { url, diff --git a/src/api/verification.ts b/src/api/verification.ts index 4bbc98eb4..3653c92b7 100644 --- a/src/api/verification.ts +++ b/src/api/verification.ts @@ -47,7 +47,7 @@ export const getVerificationList = async ({ sortingOrder, }: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.verifyCredential}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortByValue=${sortingOrder}&sorting=${sortBy}`; + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.verifyCredential}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; const axiosPayload = { url, @@ -62,7 +62,7 @@ export const getVerificationList = async ({ } }; -export const verifyPresentation = async (proofId:string) => { +export const verifyPresentation = async (proofId: string) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.presentationVerification}/${proofId}/verify`; const axiosPayload = { @@ -78,8 +78,7 @@ export const verifyPresentation = async (proofId:string) => { } }; - -export const getProofAttributes=async (proofId:string, orgId: string)=>{ +export const getProofAttributes = async (proofId: string, orgId: string) => { const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.proofRequestAttributesVerification}/${proofId}/form`; const axiosPayload = { url, @@ -92,11 +91,13 @@ export const getProofAttributes=async (proofId:string, orgId: string)=>{ const err = error as Error; return err?.message; } -} +}; -export const getCredentialDefinitionsForVerification = async (schemaId: string) => { +export const getCredentialDefinitionsForVerification = async ( + schemaId: string, +) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url= `${apiRoutes.Verification.verificationCredDef}/${schemaId}`; + const url = `${apiRoutes.Verification.verificationCredDef}/${schemaId}`; const axiosPayload = { url, diff --git a/src/commonComponents/datatable/SortDataTable.tsx b/src/commonComponents/datatable/SortDataTable.tsx new file mode 100644 index 000000000..20e20440d --- /dev/null +++ b/src/commonComponents/datatable/SortDataTable.tsx @@ -0,0 +1,299 @@ +import type { TableData, TableHeader } from './interface'; + +import CustomSpinner from '../../components/CustomSpinner'; +import SearchInput from '../../components/SearchInput'; +import { Pagination } from 'flowbite-react'; +import { useState } from 'react'; +import { EmptyListMessage } from '../../components/EmptyListComponent'; + +interface DataTableProps { + header: TableHeader[]; + data: TableData[]; + loading: boolean; + callback?: (clickId: string | null | undefined) => void; + displaySelect?: boolean; + showBtn?: boolean; + onInputChange: () => void; + refresh: () => void; + currentPage: any; + onPageChange: () => void; + totalPages: number; + pageInfo?: + | { + totalItem: number | undefined; + nextPage: number | undefined; + lastPage: number | undefined; + } + | {}; + searchSortByValue: (value: any) => void; + statusValues: []; + isPagination: boolean; + isSearch: boolean; + isRefresh: boolean; + isSort: boolean; + isHeader: boolean; + message: string; + discription: string; +} + +const SortDataTable: React.FC = ({ + header, + displaySelect, + data, + loading, + callback, + showBtn, + onInputChange, + refresh, + currentPage, + onPageChange, + totalPages, + pageInfo, + searchSortByValue, + isPagination, + isSearch, + isRefresh, + isSort, + isHeader, + message, + discription, +}) => { + const [selectedValue, setSelectedValue] = useState(''); + + const handleSortByValues = (event: { target: { value: any } }) => { + const newSelectedValue = event.target.value; + setSelectedValue(newSelectedValue); + searchSortByValue(newSelectedValue); + }; + + const { + totalItem = 0, + nextPage = 0, + lastPage = 0, + } = (pageInfo || {}) as { + totalItem?: number; + nextPage?: number; + lastPage?: number; + }; + + const startItem = (nextPage - 2) * 10 + 1; + const endItem = Math.min((nextPage - 1) * 10, totalItem); + + const sortValues = [ + { + label: 'Descending', + value: 'DESC', + }, + { label: 'Ascending', value: 'ASC' }, + ]; + + return ( +
+
+
+ {isHeader && ( +
+
+ {isSearch && ( +
+ +
+
+ +
+ {isSearch && ( + + )} +
+
+ )} +
+ +
+ {isRefresh && ( + + )} + + {isSort && ( +
+ +
+ )} +
+
+ )} +
+ + + + {header && + header.length > 0 && + header.map((ele) => ( + + ))} + + + + {loading ? ( + + + + ) : ( + + {data.length ? ( + data.map((ele, index) => ( + + {ele.data.map((subEle, index) => ( + + ))} + {displaySelect || + (showBtn && ( + + ))} + + )) + ) : ( + + + + )} + + )} +
+
{ele.columnName}
+ {ele.subColumnName && ( +
+ {ele.subColumnName}{' '} +
+ )} +
+ {' '} +
+ +
+
+
{subEle.data}
+ {subEle.subData && subEle.subData} +
+ {' '} +
+ +
+
+
+ {loading && isPagination && data.length > 0 ? ( + '' + ) : ( + + )} +
+
+
+ ); +}; + +export default SortDataTable; diff --git a/src/commonComponents/datatable/dummytable.tsx b/src/commonComponents/datatable/dummytable.tsx deleted file mode 100644 index 5020c8040..000000000 --- a/src/commonComponents/datatable/dummytable.tsx +++ /dev/null @@ -1,653 +0,0 @@ -{ - /*
-
- -
-
-
-
- -
-
- -
- -
-
-
-
- -
- -
- - -
- -
-
Choose brand
-
    -
  • - - -
  • -
  • - - -
  • -
  • - - -
  • -
  • - - -
  • -
  • - - -
  • -
-
-
-
-
- - - - -
- - - - {Headers && - Headers.length > 0 && - Headers.map((ele) => ( - -// ))} -// -// - -// {loading ? ( -//
-// -//
-// ) : ( -// -// {data.length ? ( -// data.map((ele, index) => ( -// -// {ele.data.map((subEle, index) => ( -// -// ))} -// {displaySelect || -// (showBtn && ( -// -// ))} -// -// )) -// ) : ( -// -// -// -// )} -// -// )} -//
-
{ele.columnName}
- {ele.subColumnName && ( -
- {ele.subColumnName}{' '}// <> - //
- //
- //
- // - //
- //
- // - //
- // - //
- //
- //
- //
- // - //
- // - //
- // - // - //
- // - //
- //
- //
- //
- - // {/*
*/ -} - -//
-//
-//
-//
- -//
-//
-//
-//
-//
-// -//
-// )} -//
-//
{subEle.data}
-// {subEle.subData && subEle.subData} -//
-// Empty data -//
-//
- -// -//
-//
-//
- -// <> -//
-//
-//
-// -//
-//
-// -//
-// -//
-//
-//
-//
-// -//
-// -//
-// -// -//
-// -//
-//
-//
-//
- -// {/*
*/} - -//
-//
-//
-//
- -//
-//
-//
-//
-//
-// - -// ================================================ - -// <> -//
-//
-//
-// -//
-//
-// -//
-// -//
-//
-//
-//
-// -//
-// -//
-// -// -//
-// -//
-//
-//
-//
- -// {/*
*/} - -//
-//
-//
-//
- -//
-//
-//
-//
-//
-// diff --git a/src/commonComponents/datatable/index.tsx b/src/commonComponents/datatable/index.tsx index c38538db9..b53a8ed4d 100644 --- a/src/commonComponents/datatable/index.tsx +++ b/src/commonComponents/datatable/index.tsx @@ -1,9 +1,6 @@ import type { TableData, TableHeader } from './interface'; import CustomSpinner from '../../components/CustomSpinner'; -import SearchInput from '../../components/SearchInput'; -import { Pagination } from 'flowbite-react'; -import { useState } from 'react'; interface DataTableProps { header: TableHeader[]; @@ -12,14 +9,6 @@ interface DataTableProps { callback?: (clickId: string | null | undefined) => void; displaySelect?: boolean; showBtn?: boolean; - onInputChange: () => void; - refresh: () => void; - currentPage: any; - onPageChange: () => void; - totalPages: number; - pageInfo: { totalItem: number; nextPage: number; lastPage: number }; - searchSortByValue: () => void; - statusValues: []; } const DataTable: React.FC = ({ @@ -29,231 +18,89 @@ const DataTable: React.FC = ({ loading, callback, showBtn, - onInputChange, - refresh, - currentPage, - onPageChange, - totalPages, - pageInfo, - searchSortByValue, }) => { - const [selectedValue, setSelectedValue] = useState(''); - - const handleSortByValues = (event: { target: { value: any } }) => { - const newSelectedValue = event.target.value; - setSelectedValue(newSelectedValue); - searchSortByValue(newSelectedValue); - }; - - const { totalItem, nextPage, lastPage } = pageInfo; - const startItem = (nextPage - 2) * 10 + 1; - const endItem = Math.min((nextPage - 1) * 10, totalItem); - - const sortValues = [ - { - label: 'latest', - value: 'DESC', - }, - { label: 'oldest', value: 'AESC' }, - ]; - return ( -
-
-
-
-
-
- -
-
- -
- -
-
-
-
- -
- {/* className="w-full md:w-auto flex items-center justify-center py-2 px-4 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700" */} - - - {/* */} -
-
-
- -
- - - - {header && - header.length > 0 && - header.map((ele) => ( - - ))} - - - - {loading ? ( -
- -
- ) : ( - <> - - {data.length ? ( - data.map((ele, index) => ( - + {loading ? ( +
+ +
+ ) : ( +
+
+
+
-
{ele.columnName}
- {ele.subColumnName && ( -
- {ele.subColumnName}{' '} -
- )} -
+ + + {header && + header.length > 0 && + header.map((ele) => ( + + + + {data.length ? ( + data.map((ele, index) => ( + + {ele.data.map((subEle, index) => ( + + ))} + {displaySelect || + (showBtn && ( + ))} - {displaySelect || - (showBtn && ( - - ))} - - )) - ) : ( - - - )} - - - )} -
- {ele.data.map((subEle, index) => ( - {ele.columnName} + {ele.subColumnName && ( +
+ {ele.subColumnName}{' '} +
+ )} + + ))} +
+
{subEle.data}
+ {subEle.subData && subEle.subData} +
- Empty data -
+ )) + ) : ( + + + Empty data + + + )} + + +
- {loading ? ( - '' - ) : ( - - )}
-
- + )} +
); }; diff --git a/src/components/ConnectionsList/index.tsx b/src/components/ConnectionsList/index.tsx index 4b5ce4460..f704ebb18 100644 --- a/src/components/ConnectionsList/index.tsx +++ b/src/components/ConnectionsList/index.tsx @@ -6,20 +6,16 @@ import { IConnectionListAPIParameter, getConnectionsByOrg, } from '../../api/connection'; -import DataTable from '../../commonComponents/datatable'; import type { TableData } from '../../commonComponents/datatable/interface'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; import BreadCrumbs from '../BreadCrumbs'; -import CustomSpinner from '../CustomSpinner'; -import { EmptyListMessage } from '../EmptyListComponent'; import { getFromLocalStorage } from '../../api/Auth'; import { getOrgDetails } from '../../config/ecosystem'; -import { Pagination } from 'flowbite-react'; -import SearchInput from '../SearchInput'; -import type { IConnectionList } from '../../components/Issuance/interface' +import type { IConnectionList } from '../../components/Issuance/interface'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { itemPerPage: 10, @@ -35,6 +31,11 @@ const ConnectionList = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [totalItem, setTotalItem] = useState(0); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); const getConnections = async (apiParameter: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); @@ -48,6 +49,13 @@ const ConnectionList = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setTotalItem(data?.data.totalItems); + const { totalItems, nextPage, lastPage } = data.data; + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, + }); const connections = data?.data?.data?.map((ele: IConnectionList) => { const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; const connectionId = ele.connectionId @@ -103,6 +111,18 @@ const ConnectionList = () => { }); }; + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + + const refreshPage = () => { + getConnections(listAPIParameter); + }; + useEffect(() => { getConnections(listAPIParameter); }, [listAPIParameter]); @@ -117,9 +137,6 @@ const ConnectionList = () => {

Connections

-
- -
{error && ( { }} /> )} - {loading ? ( -
- -
- ) : connectionList && connectionList?.length > 0 ? ( - <> -
- -
- - {Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && ( -
- { - setListAPIParameter((prevState) => ({ - ...prevState, - page: page, - })); - }} - totalPages={Math.ceil( - totalItem / listAPIParameter?.itemPerPage, - )} - /> -
- )} - - ) : ( -
- -
- )} + { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + pageInfo={pageInfo} + searchSortByValue={searchSortByValue} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={true} + message={'No Connections'} + discription={"You don't have any connections yet"} + > ); }; diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 6341dcd47..db65f2726 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -7,13 +7,8 @@ import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; import { Button, Pagination } from 'flowbite-react'; -import CustomSpinner from '../CustomSpinner'; -import DataTable from '../../commonComponents/datatable'; import DateTooltip from '../Tooltip'; import { EmptyListMessage } from '../EmptyListComponent'; -import { Features } from '../../utils/enums/features'; -import RoleViewButton from '../RoleViewButton'; -import SearchInput from '../SearchInput'; import type { TableData } from '../../commonComponents/datatable/interface'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { dateConversion } from '../../utils/DateConversion'; @@ -23,15 +18,17 @@ import { getFromLocalStorage } from '../../api/Auth'; import { getOrgDetails } from '../../config/ecosystem'; import type { IConnectionListAPIParameter } from '../../api/connection'; import type { IssuedCredential } from './interface'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; +import RoleViewButton from '../RoleViewButton'; +import { Features } from '../../utils/enums/features'; const initialPageState = { itemPerPage: 10, page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: '', + sortingOrder: 'DESC', allSearch: '', - filter: '', }; const CredentialList = () => { @@ -60,7 +57,6 @@ const CredentialList = () => { if (orgId && isWalletCreated) { const response = await getIssuedCredentials(listAPIParameter); - setLoading(false); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { @@ -226,25 +222,7 @@ const CredentialList = () => {

Credentials

-
{/* */}
- {walletCreated && ( { )}
+
-
+
{ className="Flex-wrap" style={{ display: 'flex', flexDirection: 'column' }} > -
- {/* {issuedCredList && issuedCredList.length > 0 && ( */} - { - setListAPIParameter((prevState) => ({ - ...prevState, - page, - })); - }} - totalPages={Math.ceil( - totalItem / listAPIParameter?.itemPerPage, - )} - pageInfo={pageInfo} - searchSortByValue={searchSortByValue} - > - {/* )} */} -
- {Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && ( -
- {/* { - setListAPIParameter((prevState) => ({ - ...prevState, - page, - })); - }} - totalPages={Math.ceil( - totalItem / listAPIParameter?.itemPerPage, - )} - /> */} -
- )} + { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + totalPages={Math.ceil( + totalItem / listAPIParameter?.itemPerPage, + )} + pageInfo={pageInfo} + searchSortByValue={searchSortByValue} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={true} + isPagination={true} + message={'No Issuance Records'} + discription={'You have no issuance record yet'} + >
)}
diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index bf1d7aff5..b5dddd5f9 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -1,6 +1,6 @@ 'use client'; -import { Alert, Button, Pagination } from 'flowbite-react'; +import { Alert, Button } from 'flowbite-react'; import React, { ChangeEvent, useEffect, useState } from 'react'; import { ProofRequestState, @@ -15,21 +15,19 @@ import { import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; -import CustomSpinner from '../CustomSpinner'; -import DataTable from '../../commonComponents/datatable'; import DateTooltip from '../Tooltip'; import { EmptyListMessage } from '../EmptyListComponent'; import { Features } from '../../utils/enums/features'; import ProofRequest from './ProofRequestPopup'; import type { RequestProof } from './interface'; import RoleViewButton from '../RoleViewButton'; -import SearchInput from '../SearchInput'; import type { TableData } from '../../commonComponents/datatable/interface'; import { dateConversion } from '../../utils/DateConversion'; import { pathRoutes } from '../../config/pathRoutes'; import { getFromLocalStorage, removeFromLocalStorage } from '../../api/Auth'; import { getOrgDetails } from '../../config/ecosystem'; import type { IConnectionListAPIParameter } from '../../api/connection'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { itemPerPage: 10, @@ -54,6 +52,11 @@ const VerificationCredentialList = () => { const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [totalItem, setTotalItem] = useState(0); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); const getProofPresentationData = async (id: string) => { try { @@ -98,6 +101,14 @@ const VerificationCredentialList = () => { const response = await getVerificationList(apiParameter); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const { totalItems, nextPage, lastPage } = data.data; + console.log('data.data', data.data); + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, + }); setTotalItem(data?.data.totalItems); const credentialList = data?.data?.data?.map( (requestProof: RequestProof) => { @@ -288,6 +299,14 @@ const VerificationCredentialList = () => { } }; + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + useEffect(() => { getproofRequestList(listAPIParameter); }, [listAPIParameter]); @@ -296,6 +315,10 @@ const VerificationCredentialList = () => { window.location.href = pathRoutes.organizations.verification.schema; }; + const refreshPage = () => { + getproofRequestList(listAPIParameter); + }; + const header = [ { columnName: 'Request Id' }, { columnName: 'Connection Id' }, @@ -313,9 +336,6 @@ const VerificationCredentialList = () => {

Verification List

-
- -
{walletCreated && ( {
-
+
{(proofReqSuccess || errMsg) && (
{
) : (
- {loading ? ( -
- -
- ) : verificationList && verificationList.length > 0 ? ( + {verificationList && (
-
- {verificationList && verificationList.length > 0 && ( - + { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + totalPages={Math.ceil( + totalItem / listAPIParameter?.itemPerPage, )} -
- {Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && ( -
- { - setListAPIParameter((prevState) => ({ - ...prevState, - page, - })); - }} - totalPages={Math.ceil( - totalItem / listAPIParameter?.itemPerPage, - )} - /> -
- )} -
- ) : ( -
- - There isn't any data available. - + pageInfo={pageInfo} + searchSortByValue={searchSortByValue} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={true} + isPagination={true} + message={'No Verification Records'} + discription={'You have no verification record yet'} + >
)}
From a705ffaa6dd84718bce3f343e87db79e5ddef515 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 3 Jan 2024 12:38:29 +0530 Subject: [PATCH 005/303] fix: sonar lint issue Signed-off-by: karan --- .../datatable/SortDataTable.tsx | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/commonComponents/datatable/SortDataTable.tsx b/src/commonComponents/datatable/SortDataTable.tsx index 20e20440d..100723681 100644 --- a/src/commonComponents/datatable/SortDataTable.tsx +++ b/src/commonComponents/datatable/SortDataTable.tsx @@ -5,6 +5,7 @@ import SearchInput from '../../components/SearchInput'; import { Pagination } from 'flowbite-react'; import { useState } from 'react'; import { EmptyListMessage } from '../../components/EmptyListComponent'; +import React from 'react'; interface DataTableProps { header: TableHeader[]; @@ -109,9 +110,9 @@ const SortDataTable: React.FC = ({ xmlns="http://www.w3.org/2000/svg" >
@@ -155,11 +156,9 @@ const SortDataTable: React.FC = ({ > {sortValues.map((sort) => { return ( - <> - - + ); })} @@ -178,9 +177,7 @@ const SortDataTable: React.FC = ({
{ele.columnName}
{ele.subColumnName && ( @@ -221,7 +218,7 @@ const SortDataTable: React.FC = ({ className={`p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white align-middle `} >
{subEle.data}
- {subEle.subData && subEle.subData} + {subEle.subData} ))} {displaySelect || @@ -244,7 +241,6 @@ const SortDataTable: React.FC = ({ className="p-2 text-center text-gray-500" colSpan={header.length} > - {' '}
Date: Wed, 3 Jan 2024 12:49:04 +0530 Subject: [PATCH 006/303] fix: sonar lint issue Signed-off-by: karan --- src/commonComponents/datatable/index.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/commonComponents/datatable/index.tsx b/src/commonComponents/datatable/index.tsx index b53a8ed4d..c0a85d39b 100644 --- a/src/commonComponents/datatable/index.tsx +++ b/src/commonComponents/datatable/index.tsx @@ -1,6 +1,7 @@ import type { TableData, TableHeader } from './interface'; import CustomSpinner from '../../components/CustomSpinner'; +import React from 'react'; interface DataTableProps { header: TableHeader[]; @@ -38,9 +39,7 @@ const DataTable: React.FC = ({
{ele.columnName}
{ele.subColumnName && ( @@ -67,7 +66,7 @@ const DataTable: React.FC = ({ className={` p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white align-middle `} >
{subEle.data}
- {subEle.subData && subEle.subData} + {subEle.subData} ))} {displaySelect || From dd79fe2c9161f5babcdeec4831ae2481339d77e1 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 3 Jan 2024 12:58:42 +0530 Subject: [PATCH 007/303] fix: sonar lint issue Signed-off-by: karan --- src/commonComponents/datatable/SortDataTable.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commonComponents/datatable/SortDataTable.tsx b/src/commonComponents/datatable/SortDataTable.tsx index 100723681..33e56f36d 100644 --- a/src/commonComponents/datatable/SortDataTable.tsx +++ b/src/commonComponents/datatable/SortDataTable.tsx @@ -27,7 +27,6 @@ interface DataTableProps { } | {}; searchSortByValue: (value: any) => void; - statusValues: []; isPagination: boolean; isSearch: boolean; isRefresh: boolean; From 5ec882f9e2b01ea1df9bd9a76ca2fa04e7697a27 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 3 Jan 2024 13:00:44 +0530 Subject: [PATCH 008/303] fix: sonar lint issue Signed-off-by: karan --- src/components/Verification/VerificationCredentialList.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 48bd9a755..3aa11cd70 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -292,10 +292,6 @@ const VerificationCredentialList = () => { setView(state === 'done'); }; - const refreshPage = () => { - getproofRequestList(listAPIParameter); - }; - const requestProof = async (proofVericationId: string) => { if (proofVericationId) { setOpenModal(false); From 9cbd23a5897d8999854dc2748096f247c447de1c Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 3 Jan 2024 13:03:43 +0530 Subject: [PATCH 009/303] fix: sonar lint issue Signed-off-by: karan --- .../VerificationCredentialList.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 3aa11cd70..4aea06bc1 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -402,6 +402,15 @@ const VerificationCredentialList = () => { style={{ display: 'flex', flexDirection: 'column' }} > { totalPages={Math.ceil( totalItem / listAPIParameter?.itemPerPage, )} - pageInfo={pageInfo} - searchSortByValue={searchSortByValue} - isHeader={true} - isSearch={true} - isRefresh={true} - isSort={true} - isPagination={true} - message={'No Verification Records'} - discription={'You have no verification record yet'} >
)} From ea0f723100a66de1968e457fd73760d3aa77647b Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 3 Jan 2024 13:10:00 +0530 Subject: [PATCH 010/303] fix: sonar lint issue Signed-off-by: karan --- src/commonComponents/datatable/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/commonComponents/datatable/index.tsx b/src/commonComponents/datatable/index.tsx index c0a85d39b..79990d6d9 100644 --- a/src/commonComponents/datatable/index.tsx +++ b/src/commonComponents/datatable/index.tsx @@ -41,7 +41,7 @@ const DataTable: React.FC = ({ scope="col" className={`p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white ${ele.width}`} > -
{ele.columnName}
+
{ele.columnName}
{ele.subColumnName && (
{ele.subColumnName}{' '} @@ -65,13 +65,14 @@ const DataTable: React.FC = ({ key={index} className={` p-4 text-sm font-normal text-gray-900 whitespace-nowrap dark:text-white align-middle `} > -
{subEle.data}
+
{subEle.data}
{subEle.subData} ))} {displaySelect || (showBtn && (
-
-
+
+
-

- Organizations -

+
+
+

+ Organizations{' '} +

+ +

What is organisation?

{' '} + Contacts are people or organizations you've
+ interacted with. +
+ You're connected over a secure and private +
line that no one but you or them can see. +
Nothing is shared without your permission. +
You can: +
+
    +
  • Direct message your Contacts
  • +
  • Get offered new credentials
  • +
  • + Get notified of updates to your credentials
    + issued by them +
  • +
  • + Request for information from your Contact
    + or they request information from you +
  • +
+ You can always remove Contacts at any
+ time from your Contacts list. +
+ } + placement="bottom" + className="items-center text-center dark:text-white" + > + + + + +
+
+ + {orgCount ? orgCount : 0} + +
+
+
{organizationsList?.map((org) => { const roles: string[] = org.userOrgRoles.map( @@ -206,34 +263,175 @@ const UserDashBoard = () => { org.roles = roles; return (
+
+ + {' '} + + + + + + + {' '} + + + + {' '} + + +
); })} @@ -241,43 +439,39 @@ const UserDashBoard = () => { {organizationsList && organizationsList?.length > 0 && ( - View More.. + View All )}
- {/*
+

Ecosystems

-

Coming Soon..

+

+ Coming Soon.. +

- -
*/} +
{/*
-
-

- DID Methods -

+ className="p-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800" + > +
+

+ DID Methods +

-

Coming Soon..

-
-
-
*/} +

Coming Soon..

+
+
+
*/}
-
@@ -285,7 +479,7 @@ const UserDashBoard = () => { Recent Activity {activityList && activityList?.length === 0 && ( -
+
Looks like there is no activity to display at the moment.
)} @@ -307,8 +501,7 @@ const UserDashBoard = () => { {activity.details}

- ) - )} + ))} ) : ( activityList && ( From 96ced2a8b0cca5aa642d6b0a39113ce3e1605f3c Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Thu, 4 Jan 2024 11:41:03 +0530 Subject: [PATCH 012/303] fix:validate email functionality for check user exist Signed-off-by: pranalidhanavade --- src/components/Authentication/SignUpUser.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/Authentication/SignUpUser.tsx b/src/components/Authentication/SignUpUser.tsx index d96c96c6c..efe80853b 100644 --- a/src/components/Authentication/SignUpUser.tsx +++ b/src/components/Authentication/SignUpUser.tsx @@ -65,15 +65,14 @@ const SignUpUser = () => { const ValidateEmail = async (values: emailValue) => { setLoading(true) const userRsp = await checkUserExist(values?.email) - const { data } = userRsp as AxiosResponse - setLoading(false) + const { data } = userRsp as AxiosResponse + setLoading(false) if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - if (data?.data?.isExist === false) { - console.log('email data::', data.data) + if (data?.data?.isRegistrationCompleted === false && data.data.isEmailVerified === false) { setEmail(values?.email) await VerifyMail(values?.email) } - else if (data.data.isEmailVerified === true && data?.data?.isSupabase !== true) { + else if (data.data.isEmailVerified === true && data?.data?.isRegistrationCompleted !== true) { setEmail(values?.email) await setToLocalStorage(storageKeys.USER_EMAIL, values?.email) setNextFlag(true) From 99d9707c77f7025794577802679856ee57e07410 Mon Sep 17 00:00:00 2001 From: Nishad Date: Thu, 4 Jan 2024 17:42:16 +0530 Subject: [PATCH 013/303] removed the update user details message from passkey popup Signed-off-by: Nishad --- src/commonComponents/PasseyAddDevicePopup.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commonComponents/PasseyAddDevicePopup.tsx b/src/commonComponents/PasseyAddDevicePopup.tsx index 030011825..a6a7707e9 100644 --- a/src/commonComponents/PasseyAddDevicePopup.tsx +++ b/src/commonComponents/PasseyAddDevicePopup.tsx @@ -43,7 +43,6 @@ const PasskeyAddDevice = (props: { const passkeyUserDetailsResp = await addPasskeyUserDetails(payload, storedEmail) const { data } = passkeyUserDetailsResp as AxiosResponse if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setSuccess('User details updated successfully') setNextFlag(true) } else { setFidoUserError(passkeyUserDetailsResp as string) From 381a76a7cdf9a24e3924211972fb0dfa18a97331 Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 5 Jan 2024 11:12:57 +0530 Subject: [PATCH 014/303] added empty state message Signed-off-by: karan --- .../Resources/Schema/ViewSchema.tsx | 7 +- src/components/User/UserDashBoard.tsx | 819 +++++++++++++----- 2 files changed, 617 insertions(+), 209 deletions(-) diff --git a/src/components/Resources/Schema/ViewSchema.tsx b/src/components/Resources/Schema/ViewSchema.tsx index 4eb96ee24..f5da0a2bf 100644 --- a/src/components/Resources/Schema/ViewSchema.tsx +++ b/src/components/Resources/Schema/ViewSchema.tsx @@ -197,9 +197,8 @@ const ViewSchemas = () => { } } - const credDefSelectionCallback = async (schemaId: string, credentialDefinitionId: string) => { - await setToLocalStorage(storageKeys.CRED_DEF_ID, credentialDefinitionId) - window.location.href = `${pathRoutes.organizations.Issuance.connections}` + const credDefSelectionCallback = async () => { + window.location.href = `${pathRoutes.organizations.Issuance.issue}` } const fetchLedgerPlatformUrl = async (indyNamespace: string) => { @@ -509,7 +508,7 @@ const ViewSchemas = () => { />
) : ( diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index cc1e844f5..5db2a028f 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -19,7 +19,12 @@ import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; import { Roles } from '../../utils/enums/roles'; import { Tooltip } from 'flowbite-react'; - +import { getAllSchemasByOrgId } from '../../api/Schema'; +import type { GetAllSchemaListParameter } from '../Resources/Schema/interfaces'; +import { getEcosystems } from '../../api/ecosystem'; +import { getEcosystemId } from '../../config/ecosystem'; +import { getSchemaCredDef } from '../../api/BulkIssuance'; +import type { ICredentials } from '../Issuance/interface'; const initialPageState = { pageNumber: 1, pageSize: 10, @@ -39,6 +44,24 @@ const UserDashBoard = () => { null, ); const [orgCount, setOrgCount] = useState(0); + const [schemaCount, setSchemaCount] = useState(0); + const [schemaList, setSchemaList] = + useState | null>(null); + const [schemaListAPIParameter, setSchemaListAPIParameter] = useState({ + itemPerPage: 9, + page: 1, + search: '', + sortBy: 'id', + sortingOrder: 'DESC', + allSearch: '', + }); + const [ecoCount, setEcoCount] = useState(0); + const [ecosystemList, setEcosystemList] = useState([]); + const [credDefList, setCredDefList] = useState([]); + const [credDefCount, setCredDefCount] = useState(0); + + console.log('schemaList1212', schemaList); + console.log('1212', organizationsList); const getAllInvitations = async () => { setLoading(true); @@ -148,6 +171,93 @@ const UserDashBoard = () => { await getAllEcosystemInvitations(); } }; + const getSchemaList = async ( + schemaListAPIParameter: GetAllSchemaListParameter, + flag: boolean, + ) => { + try { + const organizationId = await getFromLocalStorage(storageKeys.ORG_ID); + setLoading(true); + let schemaList; + + schemaList = await getAllSchemasByOrgId( + schemaListAPIParameter, + organizationId, + ); + + const { data } = schemaList as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (data?.data?.data) { + setSchemaCount(data?.data?.data?.length); + const schemaData = data?.data?.data?.filter( + (schema: any, index: number) => index < 3, + ); + setSchemaList(schemaData); + setLoading(false); + } else { + setLoading(false); + } + } else { + setLoading(false); + } + } catch (error) { + console.error('Error while fetching schema list:', error); + setLoading(false); + } + }; + + const fetchEcosystems = async () => { + const id = await getFromLocalStorage(storageKeys.ORG_ID); + if (id) { + const response = await getEcosystems( + id, + currentPage.pageNumber, + currentPage.pageSize, + '', + ); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setEcoCount(data?.data?.length); + const ecosystemData = data?.data?.filter( + (ecosystem: Organisation, index: number) => index < 3, + ); + if (ecosystemData) { + setEcosystemList(ecosystemData); + } else { + setError(response as string); + } + } else { + setError(response as string); + } + } + setLoading(false); + }; + + const getSchemaCredentials = async () => { + try { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + if (orgId) { + const response = await getSchemaCredDef(); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setCredDefCount(data.data.length); + console.log('credentialDefs', data.data); + const credentialDefs = data?.data?.filter( + (ecosystem: Organisation, index: number) => index < 3, + ); + setCredDefList(credentialDefs); + } + setLoading(false); + } + } catch (error) { + console.log('error----'); + + // setFailure(response as string) + } + }; const getAllResponses = async () => { const role = await getFromLocalStorage(storageKeys.ORG_ROLES); @@ -157,6 +267,9 @@ const UserDashBoard = () => { getAllOrganizations(); getAllInvitations(); getUserRecentActivity(); + getSchemaList(schemaListAPIParameter, false); + fetchEcosystems(); + getSchemaCredentials(); }; useEffect(() => { @@ -168,6 +281,20 @@ const UserDashBoard = () => { window.location.href = pathRoutes.organizations.dashboard; }; + const goToSchemaCredDef = async (schemaId: string) => { + // await setToLocalStorage(storageKeys.ORG_ID, orgId); + console.log('schemaId11', schemaId); + + const url = `${ + pathRoutes.organizations.viewSchema + }?schemaId=${encodeURIComponent(schemaId)}`; + window.location.href = url; + }; + const goToEcoDashboard = async (ecosystemId: string) => { + await setToLocalStorage(storageKeys.ECOSYSTEM_ID, ecosystemId); + window.location.href = pathRoutes.ecosystem.dashboard; + }; + return (
@@ -194,9 +321,12 @@ const UserDashBoard = () => { }} />
-
-
-
+
+
+

@@ -255,229 +385,508 @@ const UserDashBoard = () => {


- - {organizationsList?.map((org) => { - const roles: string[] = org.userOrgRoles.map( - (role) => role.orgRole.name, - ); - org.roles = roles; - return ( -
-
- - {' '} - - - -
+
+ - - - - - { + window.location.href = + pathRoutes.organizations.createSchema; + }} + className="hover:bg-secondary-700 p-1 rounded-md" + > + + + + + + + + + + {' '} + + + + {' '} + + +
+ + ); + })} + {organizationsList && organizationsList?.length > 0 && ( + + View All + + )}{' '} + + ) : ( +
+

You have no organisations created or joined

+
+ )} +
+
+
+
+
+
+

+ Schemas +

+ +

What is schema?

Schemas + define the attributes that +
can be included in a credential. +
+ } + placement="bottom" + className="items-center text-center dark:text-white" + > + + + + +
+
+ + {schemaCount ? schemaCount : 0} + +
+
+
+ {schemaList?.length > 0 ? ( + <> + {' '} + {schemaList?.map((schema) => { + return ( + - - + {schema?.name} + + +
+
+ v.{schema?.version} +
+ + ); + })} + {schemaList && schemaList?.length > 0 && ( + + View All + + )} + + ) : ( +
+

You have no schemas created

+
+ )} +
+
+
+
+
+
+
+
+

+ Ecosystems{' '} +

+ +

What is ecosystem?

Contacts + are people or organizations you've
+ interacted with. +
+ You're connected over a secure and private +
line that no one but you or them can see. +
Nothing is shared without your permission. +
You can: +
+
    +
  • Direct message your Contacts
  • +
  • Get offered new credentials
  • +
  • + Get notified of updates to your credentials
    + issued by them +
  • +
  • + Request for information from your Contact
    + or they request information from you +
  • +
+ You can always remove Contacts at any
+ time from your Contacts list. +
+ } + placement="bottom" + className="items-center text-center dark:text-white" + > + + + + +
+
+ + {ecoCount ? ecoCount : 0} + +
+
+
+ + {ecosystemList.length > 0 ? ( + <> + {ecosystemList?.map((ecosystem: any) => { + return ( + - -
- - ); - })} - - {organizationsList && organizationsList?.length > 0 && ( - - View All - + )} + + + {ecosystem?.name} + + +
+ + ); + })} + + {ecosystemList && ecosystemList?.length > 0 && ( + + View All + + )} + + ) : ( +
+

You have no ecosystems created or joined

+
)}
-
-
-

- Ecosystems -

-

- Coming Soon.. -

+
+
+
+
+

+ Cred - def +

+ +

What is Cred-def?

A + credential is a set of one or more
+ claims made by an issuer. A verifiable
+ credential is a tamper-evident
credential that has + authorship +
that can be cryptographically verified. +
+ } + placement="bottom" + className="items-center text-center dark:text-white" + > + + + + +
+
+ + {credDefCount ? credDefCount : 0} + +
+
+
+ {credDefList.length > 0 ? ( + <> + {' '} + {credDefList?.map((cred) => { + return ( + + ); + })} + {credDefList && credDefList?.length > 0 && ( + + View All + + )} + + ) : ( +
+

You have no cred-defs created

+
+ )}
- - {/*
-
-

- DID Methods -

- -

Coming Soon..

-
-
-
*/}
-

+

Recent Activity

+
{activityList && activityList?.length === 0 && (
Looks like there is no activity to display at the moment. From 279205feff80b74abf9a1ec9d30dcea4fe915521 Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 5 Jan 2024 15:23:53 +0530 Subject: [PATCH 015/303] added image for wallet Signed-off-by: karan --- public/images/Frame.png | Bin 0 -> 58888 bytes src/components/User/UserDashBoard.tsx | 8 +++++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 public/images/Frame.png diff --git a/public/images/Frame.png b/public/images/Frame.png new file mode 100644 index 0000000000000000000000000000000000000000..42ddb81b4973c140b7d2e0f07d4c5bebab9d923f GIT binary patch literal 58888 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�TH*++$b0ca-(AXuUk+BXRH{?QP>{rsAn_-4EgjuN5%}vhVT8xYz85qpEam zm)meDw|D(ls`RDQP-o3=fwKp-D9Ky?8Mfs2i4zsLr{S9?ja4g2{MZYVCFLi%%Pob9 z@0e&sH~>sYkctbRlT9#^+anAfwgedYuVl!c-!ZT=G-tA@p@Z%Y-gDIdY$iNHnji(UCbnai<${^(F0$m+;F+ z%6$ygMTgi|q%Hw5Y&?_c@FaO<3kn6-#@hS(;DTX0f*m#l+Y*m8QJDD9Yd<|^s>zy$ zQj!Fmt*o|YwDdnbgW0z#Yg^OB0L{5Fy@#CWHbnT~m;xCS)J13REK<1{mbjx_ATF0_ z!z`AXugR$OXxZL^{@%3Vr<6qIR}xus!0nt=o1tT2>5Y-7tPAGjY|ZW8>R8M$-6>>L zamJG7eeQ9!S`^7R4?+5TZ=BnezcsQC>_~26ex?JEQwTKP;2e!aT1pdFNiTRhF{4aE z1WR`O93>|vf$GaATdv67mbRt>-+!aUQ-5(AxToBxntw(-2|abBrpL{`nJAJ{MWu&b zk#+!^aGN@tiHa!9mGy0*7h^pn-20T6mtu5CB?c1vaQxx>g|$ues=x9H4dtvg5B&t+ z+iJS(uS&rlyT0NFPalEeS>E*|R?NC>-iv||>}aq3x(awAc4=NB%{)mq(&m+6h;mlO zI$EQ-kxw{<-z(iX(uEjNm^i(l&|g<&*rsFgFS9O|rhr{-$vQbyU5@K)Hzyb!QJ^0b z;*%_ncBEx0Qy2&yw0|?>An>`93H3TiOlQ_e>5UMBF!9zcQhwn;O*k*d2rkq{Jd&=G zVP>gdnhqKu6J8CDX81aUcA3|+U|(f*L86H{Qa~htO16y$rmRdGfl0e@L^k1~09U?O z1&g6YY}-P~M0R7y%Ad@KwRz6(kY|_mi|&{n_JW8Ew80QDIKakky(+0==bsfr866H` zTs%CmmQhotPOe=VAmc$k>m2=OCF&jHD1Dvhi2Yr~d$W#na=qWk2#Nm{xn0D(MZt$hX z)A$r?!6jV66*bEeEBR+5HjB1)sdIN&J%WZyo#OG#-UsWnc7FBWg@mPO8%ey%{K53F z1S)~p;Rs+&H8aWKi(CjiNx5#9Ug5L}XPJmDW-k^W{& zu7s=0k%!g7Qe@X| zR!tp`dVdMwo44i3T-kC+ZjiNaq~wifOT+U=gtWi-z5r;OS0W?kRMUGRHfCi$a_Ejs zc+33ybvRMR+83J>_5HC?0qcnX2hrS7@;$62(xKrhN!T>~$~|3nOqXT#XC$a1ya59u zW#a+{PYXg9*;;8;KMUN`cx4G2%IQ7)yr>B^&*23ZSi5!3fXr6`Vqz~8?&jE}Ok`4C=Z*gvCK=A{I2&KC)epa3!-Vk!;Q*OUj1Fkr ztZgW4B1|}&7@bKRY)V)w_H$47mtRd2tBU3)8XZRA0&C?YTA|xxcG3F!5W#*LL-_Xj z7iaZTxkQX%p-R7}?AFlDXdsmZ0tPw3iv zmkM?i9n&5^TH*NGniG(h(NId-KBYfL#BOQT7tin2#N#nL*KLgH3jjh~67HFwVas zmtX@8r5HO|p@h9r`T`|w=CU9U-tN~1gDHQ1B|Sq`mt#kSslg`0@${5GyE9*0qSU&S zOJK1}mS&dHAULSK_Y?$Z=A9MX$4Yg7Z%sCljZ{(>r|mIY=`69K{Qw-Io?X3|x* zpV-^jN(l!8#fP&4wU;hOP6DF`9YM}w1psn(yPzmN(FMvM4=D<04*c6Yc*M~YabPc5 z&*M)g$7DTr%54-Qf97j{&^Sl6s?T=`xm%6tRzV;%;ya!71iL2ej25V zJjq)bx~elu%$`2H#}97wcz?J6dJ=keWwU+LdH689QUAZ|j`{u=QKfXy`%EYQhz23# zvuzO@mL(zG$~9BUYS81W0V8k$+D4|+=M7X0ErTu9DZ8;G3b_)-RN=E_TYutr+D}5I z_!PCy&c>d6!5t&D&F=ut&x=~Mr|S)?7uI}%lX0x|E3ET@u|NF?w|p<0zKK{!Aq>(l{3{;SLv9M7FU6)f5Y1`}*U+G1G(w7L z0iXEO;lQ$--!0UDXAvXc6!>jac#W@p_-%MW#v4~i_X6JVgAqw(CJN5t@gT{T)c>kY zqq1LwKk1-{a7&d@Pbgc&0r3d^dN`2XC*t~d>{;DOUo^;DPOe;#hrRWnGA*e zKMhA=i-UlXCA%CmyLvA^8M!sAFXcpfS&fHv#AT!V)0-EJZ zfsb!c0lS&0EI$)}XHJXc{9yL19(iyaCKKDi_K6~Wx+uyyia29h{N}y-vq&kwJLEpg zC|^p;TG~x)h_uJVR*^8NC>-hr???51@UIHZ zb9xD+fPxE^DU_E6>dYE~4{7im=~&Wj(oP-eU?^{LX)_RMLMxAKjNfb%*D^?C*Z9F3 zD1?+>B*|W^tx2*}Z&*rKqy@EEy;_gyMFax!6bTGO%iWWepo6JIZ!PgKbD# zW#vnNX~KGMC`WQ)ny}@B$1xi8``Ir%ob3Z=h70=H43fG$AoU)ygm$z$DiOSM;w80a zCvzch_(PvyKI~$2r&C*LT0|$2uX8b&TZ<0mSKPCcC=ywG+7+nN4O+;skB=AGO&UX> zi2!jF(RAq-FfaaLUdM;sf5A6$3*VT>q`w@&4<~J=D($qcpK#xFVc?zcM-Ddo1UWv{ zxj!osz?QncADtxik>c9og^rsmbyPW&swIOMz;<3dI=UyX+RcDkeW{UOebiYxNOG9# z+t1so#r#dT`&O3V4e+W5@_-1D$M00>Xfv<7Tz~@SqkWQtEOSqDc6={J38|2h;G--T zpD|YjI2UYtvnG1G* zgkiYtIBap0YM2bFoHt6_MNuiK$dJ$5I91V8(z16o@VX|EgXQ!17H6#0F2HC-Hv_H2 z_1S(NAMVq&#b(fTjZyH?7#m&J+AXANjHKEEnxH%mv+9K*3I8jYWt$P@n_ z4O`X1rLaq)6vD*cugL1*x)RN1W}QP{0Qn8T$x)34;v=gJdR|sS)#rQ_qvU-NAh{_1 zLiZiHn2aF_@r(lrHa=H!S^w6>hzq;Rd~O7LRK6LL_}`kCZNL`~(vzf|8C~o4XaiB%H9HvTCGK8O9)$7Qq=1A!7$TYp;wXm_PX#erbSzAifgFPSr zxn*7!LpEB;eoi`IyBWgOKFOBD*)`W0l?|=sV0co@-`$Sh9)ghmScJwN8s?;id(h=W%u|D*R_5e2QgzqOx=a#L9zf~2m_GfpA^Rhabm&u>})xvn#+FW5|UmGLfeGl(u4 zZsuP$TQVa*RLI@g)h2>eR-CD=TL7)}D)Y*0j?T)MiOy<6aHK{uO3Lxxrv2QXofeer z3IAYS>0*;Rz)1|UDNoeRVVElRi$?r0>{BL2X>Be2OC}c;rU*M_%9_Lwq)vn-(_;*Pr!8vgL&Wp)&;;(nOTXo$7d%)u++_lXOCtdpr_i2W=|;54_- z!-$aDYrlB2si zJjs~)v!Pr3L4K~-jW8h=x+pYL?904M^8LqBf$;#B>snY}%3LdvWcIpk@6wfOc^6LU zsR_znH*JR8Huk1x8sNDVlv)|w)rp+`X;f9MRTt!-hXA9*nYR2a0lQJ;uQaDkEiAhA zBFY{7r}~rqL{x>(u@fA2|;&5gc|;D^@iMC{vjA zFfyj6cJtP9K4nw6Mf1^cu5o#YRWzNzpOYj|g3cEr-C5-Z`HBbHGGG6-6h>6;1l*9< z*J`u=OK>dWDp^9t)Y+i4T#J{n{$5ktt{k5PUt5QGQbzH&>F3Vn?Y&KBBRCz&qq=-k z63r+Em3b^^@Eg!V;ZV}|wv(hA z?9f}G7OmmWfH@Y@Z!;_#extZ%H>It&nVi4UK2(k|$1iGDI6m#>5X~!JS6tGqi)H=2 z<7Fha`Pni2#ZZ0PWp!1gy=PAc0ey|LY>ur_%-1BJpvxUD3F)geCAG6gN5h<$;&K>< zZ9D&%Nn%f%Ow396cNsnj3^)1d{M+OAtb%f1L!c0^wta z!LF6IJx5mWa3P<0f3#eEyMKxadB=bPAa}2AR6$8PZ_6FqeBnmyLlinkEff(K-{FY8 zsE!DiUrPHK4Z-bqv4}`+=i&-?W9SiQSvWRXJuC?Z0)c-}HTIEL*?9q6KXMt|~Gq+n?yDV@n#=&pe zFj@g6npkM1O%MwAQ~q^*u`h9%PgBwO#Ef)As4|6=>aTL@_8EvrFb}N@t4F4rRxZA(W>D%$xJN2b> z`BjoU5-X~N8e?Nas$=G?x&DmFLAs5`b^<$$iRmBfFx@Qe+4rP7MNfNFtj>KL0%P!t zw24}X381X-dNV(ralQgL3&m5?+Bay}{&4UZn6$dn9vLPQr?nY&fgM@AWhXX8!%Uxs zY5Fo{T6AobS3R)P=DQJJAn*uz4MI$R0a{th@4@hM6FI+P=BD+)YR0N|r=0s1OPrO> zu<6`#{pAtO2AYih7r4A=SFlz&-%9q{lVF1=pFCU-*g(=H_Qayg|D)ZN@Q1q(Co+u+ zo4Q^+wM@favn8h2$tS#LmbzmS`R{Hv(~llDyZ@$(cHbYk#bq92>W{SlPPN!F0bH2f zbo7bR@87K#zOP$I)QxHRoFp#zS?vDyeIb4|I_*J43o@oUc3jl;xLBqu|+pI5a9q<%?WxqT#KG17<)!~DGt z+4MRSbj@bhSOC#K0cgwtI1 zubC(Ch#?9KUNe8I5m^!G?Rp}6I+y1=Q*0%F)GM?VG6JdE;h%l~Q_Ay_ZNEu);uZ z>BfHv6g;AGW49|r~U%Np)FK-(r$QEi{iON8t1nW+D7_Z zIhXocVm%)^;WLaUQvA{*>gF#c5Qz=$yN{d3cxda%K8at}>LoC?!YiV%t@@&+e0BB{ zKv8hUJi{Fnm*T{J<+`s+%8|k$ejk#1&5)~gW$(B{ZALPd@SZ0xpWBlsDllOBw@RCs zN#B&0wXE*x|E6D?!33$XDIJ>}tA*gG+`{9{19t0TW2K1K2WRy#KUvmPQ1HwP3^(jOR9HF=RxM3s z2@PF=!qO^)6~i|tx&25c6)_w$s0;4&#pj4JC?;CCK3btGs*}}tS@BPIV3qRj7uBV3 z`mUYp3!=SD$!UV9WKp}NSIF%Num0el>rYpyiw0zU|9Z9<@9RCgu{V1Al*=N0p{z5G z)w|AIYeW5!Mo9`2FgpD`QNeH^nZ*C1@2kC$ZcyRX?*9;b=JT!IPm=6_St^n-JtZgF~FojMJAr+og|-d9-35~E|^a0-WZfFs4nOe$FgxrE?K(oVikEui3CI9 z{0NP1{l3C!{`-Aq#NNaINP`%nEp=n83?sM~)L-*kLS?ZdAaNJ<*g3=fS&sxC7mKXm zqh4d|*~X4B?4=uz)sytN!*Zg2am^6t5e?|Fe1{wjt_yMbd+!I=CXijS|162fyq)(= z;)T4pNExP2AN?8+HM}ess4LMo%J{%Q{BFz-(0NA>2dV?Z`klAjQjHP-3TmSTm{y|uuI-4~`RDok=2UB`hAY3eE$@NVH_iI$s zl5;O5Pt!f#?_;4#vVt<=_&Elic9@h4o_`Nqdw})H)(gGmNKF^dD)(GN$zllm(+JNh z%AEnu1oiqOaG@g!2hoI2+!*ZF;Pflm2!l|Vs#m;3hTU}j`ahX_*!W^xmRnNJ0fsq6UP6H0pvU!7! z74PCFNSN@&ck*=*Y#!0Ue`NHP${R1_YT~)wJl7LMze~3&P|mpI)0m@mmMp+HN+_%1 z)mm`tirS*2T-lDrPYA^<1qSuCYr`${{v;WcYa0c8s|OTl3BDs>mwBf-*K^rxoLl7G zOaTX1|AC?^)y~=z3CKBL36Bh>ZXxi~DZr~$wL855XLfqhw%VeVI1ERviRK+;^rDKmL zFS1tE@`6(ENT9hw&ejcNw}Ib#%(8uC-~GKlL9hJX5`9Z7in(PfD_;*fZTi2ahLzQl zp!{#54Ky}tqWeJh=P}zRv#Wrv5=%|Ug895XOX2~oknW7gy3V6f_2rVbiZ5(DAkU3n zlYisr=uf?Z_8paHT$dicPd+o@`MEMccFtugE7)a;|bcmFe zF1%}%1{3@^Zce)JkfXfKVqn*ec4;GZOb<{J8%fFZzisKo6rmF&6(N8hL(?`9^0D&- zdOTiyZgLHdD%KWkTMD@DvS)|{59Qy-VvXvs(tUQ1VjNq8Yx2EUD>%It`+R?=gho*c zUkZ5p!$kFNmqK$EsD2e&C=z(RJ~xVyatrTNmBT;yWhfkgOw82#F_@mN$e~*qna;=S zXd2*(B|oN}dA{_2Wu&qgom{VZ_vbI>%%?WIeUEMH;W{C~?Nasp0A{BCM8UV&tGikC ztD1J`6WT&7SQCTeaV6S{3anGMkvGC^NI?UN*nS~wugL5$Nf*JJ+m~SgpG|;eU|qy( z7Kn2mcP_I2h{>_hNNu-g?ikA6(Uu*k(@2FFEDvz%>;`lzji#`wVQ%|&t#sd2{v!47 zI?r*$43AK_Xw5C-UIpiS)jBK%#fH#sKNf<1Y638Rj_JWG>Ju<#;^h9zIlr>0e<^~WT0;ee0GA37RU<}ixHa_&?AsSm1sQG^Te){*do;ZZO6X#_~S{Ij_0ysjjN z@cn!-j(t35%8akX8|kFHq|b{=r5GUP_LU3-@PjH03uH}S2en$#yrq4jn5eCs^-$u z-Q-PWAEFVKAqY&x)lx?4(dswPvEstKxF$>K#f*zVo_46typE0U=|PnJjiui>Sn92n zOFQXsb~^@uSEqr1*wfzzG{Mz=54y9dmEsjBc#-i~elgpr?X4@7xwt!?>d^VFVVufva*XOveb@ZOjIEw{b<{)zJxD!nJHv!fxb zn|)7k#JIenVYXwwR*4k(pW5($V-;%}H!h-`c=`nmOMdNb;1B}^i4Va7`^YEQDJ4(4 zI8Uartr!2~V-~GfwY2Iae~6OV)*RE<14pq~5xUD5^0I;PrZvsed|vN2%Jf@ono)^T zNSpqgivdb8)+7iu0vPc$Y1%SdE`cV|zWIy(&;DS{15NxmOk_)`Fl9C|dBIZiuj6t6 z7QnGP5m33!Q&ry~`qHqg)2aMn(_WHelXHCdrLKF3-%jFseV~ILd%wRQZJ78NnnxD#}xys@pjARwh@B-iIRX~Xt;=x_BBxFRr>Y7daw4`OJ-RUS5Bn7ZmPvxG0oMUwAh?H zF*JXe@-_w2i~ny3(fLRVj7&)u&$>QrR}QZFMv@8WP>48Xk6A|xaW2$2Kh_R!2+YEB zY93?DR#5v2n5qz#T&7N-{gnM#OUX?G?xV$| zSOL5M|Hm{Qp^z@|6p7Q~O4?Jf_FH?m!pZM8t`Jakml9-M&$`RtmYG7bKo+j$ca)h% zS9)XCE|TF(uQ%>1X~X?=f-0V4uJ@hh=xb>tyrn`BV3QipEyw38e@#{U<*acnW*~vN z+yCKjJC~#G@c;K%?pWK<#*qmy-mj`(aYDqL;&?=?0R*K%96upxbp=Mpl>NP7!u9-n zFlZ4$W;{a%+KCgSrk=V`fwt~X<`~fKxW3#M>6d=6$JN z@HJC7HmW>aa6|y-`@IZKQW09`cA~&Ik<;Y`+-|P=g?I(jJiW7#V`!q(uzX^+gF`Kn zxc*>~@2};{as$21*mu-hIFQn>R?LopvYygASJMJ>IT!=Qw9qVkvD&^-ufBH3MZY5a zS!E3xMK_J`k@;dQjxqfFB70%+?%wAl|6%H#aq!(i>;G@Ppm{_j;dZ2=CUnkWzDph= z+E>8SUdHCUA+sR~x`K|#`|BRUR}&g5N$fX_M)S>fWNdtK4wDCB{~w~>!lB9bfByzS zr9nbQhtvRtjjo{#kZuqVM4Hjvp`;+48!6o-jdaHd=|;Md?)dG#@6Y#n&c6V5UDx@p z<9)pBM(*k5zrb%cNg3q3P-(606LSNA>UV`?)zCH4cL{TafiXC79(~lx?66mE@>%Oz z_;J7*Q_m6}PMuYZL2~|7jUv6PkLL0}F%=ETfV@v_>o71Q9d~J_^PdJ*=#9h(YBbib zS@k6N}jvMjL8uEr5!6BBp$~G5&S8`Fg&&hiK4GMcY zDB1t^Ff6nAv)WXu1Mn^?jnfOlzDB=LuQk8aYZ$dip2pHyG zpj+U);whzoZ`@B&WR+vd!r5Dl052+0QpVN)?wz_fjzrnZom4!m##OzJqP(NuQ^)c7 z9|m4V29C-5s87I+pU5;4O;lt*UuiNJAE*dlgz>$oWb7>cA|yjKwKg`O#lo3CSZruH zp&Es_rOI(NG>Y|;eSexfooWXKyldL$xqqE}&gf{lV%JSn0C$v*9l%PH0wJd+z}GdGCCCTT z*f+WOLtrKg5l;2nRSk$q6>&PBaG*Se#4}AwV`ue< z5XvxEn`hPjVwnDHoI0B#2FsTOdA7 zN?%OewPzH0IFr*2+h+opflji53;n0C1+RwfzfuEM##tX5MpLE)+oWLWhRbxZ#WAOIk&rIXl%otr>R&x1?q;h%#(W|NVxww;W zG?v%T{0hT&rHcGj2&!Z%sbNg}L2nV~d4*E-2@JaIze?EmUcO_F`8ZPglt&fYQKU)w zDD@*}n2l5fig)-=H8L1nAWQq7UHCtq;c@=bozdYL5q(F2?+$gKXLxCk+?ZB49l@A` znX_qg>?u1<)>ulPWpduas`{#A_o55-ZewPF(($RuP3VWlaJ3KfO^o!kWzKl9lC_Gl zf^+pX7cF#P1(_m;$lpEs4_wxDOimptEaMN?STy53{Dm0Nqeq4U$1W5% zG|6$4u7}G zg289-n27e;2Y~8|QPjKFG8A5sn$12+E$aDnZ?gf7faZQ@DNSu9 z6|;@MT`CQ@cb$y|lk;m%*On>3FE$7CqmX^^AJw$uRBM5d@!03k=z*~~nS{l6MV9em z!^o2^r0UWa_qo#}LawFX*_#K`27W%LC?d6AiLT@jYKgNwQ+ZSRqSZ9r{!8VjyCIuz zO}PTQ*zJz!h;1eu2ZyTh@$>ZtW6<&9#B-7VOZpfhpVVU|_vU#3scevb(1R z$e$_M;Pp|2S;8Pi-PG0614*swf`Kx6-Q~t=vBT^Kj;RpBvNcwZ1mzy%jf)***tbJ{ zm0OdHgSmrjG%e>R$fM;5e(A~|W6Joye|*`iQzW}yrqb;nt&z=Li4!BE9e0**H1naJ zc3eN(0Q8Bchun;z$*jX(mY54q3f$9@0Qq1|f@L~QT3{#%SI<+(W9wk+WOp03aNifg zF8{{h5VGfJ*zZ81YkJeU-*@@o_b~rqSKx7-Bp9;DcW@q-T;6hHd3{i~e8@{;R#d2{ zBXTj&9aM?YkDsk2*aLRTd;8WfqdQh=gw<@qs$CeszA* zFrDwK{U7TJ)%pl;6Wre{n^>#J+)akwn-eg5chr^$m|5ekJ`Z?+_FihVS1dH#ndQuF zY9P{#ic)S9WkXNVioQnX_HA2cu+S@|1~=j|pfL01yI3)=65jMON_W&w(J(0J2NH0z zM4X=;up-tj-#^xN#a}B0Ul%0i<3h+?%Zgzy3R4U3h0&nl?n{>PwWE3;fXcpqmNZ4v z|hh=w6-NsMRc&D;$;+*;FVyWoqGJX!f>>8@;vo z>vw&jdtdjsUxktbpp7|Y0I6=6)Q=OGnN?b$xdbp)HXhh)N|wHXlp3LKWwW6%C^>Qt&X zVaY|^l!X%UuDPiYzOOtQD~`Lh!IDZc;rl19F@uqdW`%t-rmMJJ6K~S@`)f71DH?)c zm!$;IWWeyNE^N_5-X}eNCrbjD-z*CaE6VY3I~ocPymfrbh5S=76N!tchY<%~2j?Uy zRy3s&v5>OwZ5fgN+-h?wQ5R{)swe1 zMa#$K+v4-}UI#}#)%19U2&Dcc5Wft?R!)LMkeAWOu5#CM0UiD?pIL2#V%B@mLogn*1E?&JPB)YhRavA z%Af!P>i5a$JQ|_B6_zhp2Nva%-3xazG=$py)hA6>Z_1mxLr*hayx_>wuN~qaS4*7q z-v-})Dd=mPdC2Gcfv=YSpmtr(^ zcu`{;i(h|RFjUvZoH`W%z(y|hsr>7<=ks&P{IXAnv$#188SVb} zlp$u+S!L)1=jDb}CV=sYo%$q|2W0$gDCR&VkB9@YYZy}Li$;ClzS1Q_fLciec+pv5 z*3l9b4mJxKa}VtXyewCt?0S|jT5|m49p68$VAB>__IKFlYUSmjT63%Ybam@(4}mR} z38#sUdG#0R^ZaNRJD`rXiL_G3bA!h?E{NaN5d$gT-ln$aeHM&yfKw03%m|2%!{&Vqq6(8YdV0tkNW{Uc=Y!k3zm8F3eR{|EqQT@F;%wAcxp}D z=$G&(1C*;eri{gcRfk{vX%J{O_U`hI%7WtZCE{c@#+yy!lSvl-ftA{!)5b8*9*;HY zEybEaoCsaYrI;j)!27Z@;%4VY>3%nk=iVB{COwzx>~D(6RG!P;EPuQyzcllqd_q30 zb&ZQtX?|kng8WFo7`vTN_RCg8ckci*zyQ-vL?`6{;GM|YdKZt?pAzB2QBmQ@efn~9 z&4l(Ju_Nk0Xl1fYEX)e*Z=p#4Tt?|Qj;Z<+6>IA;0un}XW#L2kTrh;ESEZ?1L%?<4 zZA^(O{7Co~%H3{lTHRGOwvYrM@ZZ&w`-Y!eG+n znY0wURUjE?&C#}sN)_K&&9wOS2m=vV!6{8g4M`-(_$uBuoYg_YW^-MK<<5u`*vTn( zxgqRDcXXJi@woBV0EPQ3oyhg6yv?j*<%0MPROj8msj zH$ogZl5ZvIT)6#OgAY__6GKe*>}r=uq)eHoisxaC9w17s6K7cCwX46O`juig{&U>^ zeWCv~dZ3t{h@)WF8bKdnTeHu}18i`Uu*;O|3LcRl2D#TKJ!WA*CEhZ8GC>eupAU{A zqwb1~=C4H%nDs0L{V+h7Rg%*LmJj5@{xQcP-!Yn7+NuetB^A%VB^Zj9*RmwpmD5q{ zMp05UIevk~qK=+q-0p8q=3y$%^a+(~OjM6qnizx8V-I=AXl38`-GbC(lS_5WD=fxux}#mXDj{nd)gXCzHZ>=}4a1I2I6;q&pWAPV1gNgOOe^thWeFArS6#J=-$2*Zqd-dnZkS1UD{09$S$EuRr_!H zv+>AF2UJba?wAppMpW}n#4_fUA)DIdgHkZ4yLP9{N?hjIR1M!_jX#=?s6)m_hOd#* z?UzBviNAZ=TJTYsHc!Ls=lcIJZgexQ``M`ywvmfMC<+} zE9Oy1KmELX^v`!c*aOF3Ahr6O ze*9FgWY;vzGLUBd8fhSqLqusr-J9?xM`C_Bitt59WM6g zpU{-g&Ih1^CQ5uwA9_R}IAsXX%_7 zJGAM4H~1}n##D_fLUJMS>k7-8eu;VW(K~+JZN9#9i7t&Mm*%t`$r}rJYjYC)pJx93 z`PHHWRID7x13%yZ?ig46kF@~&Wr*a873Bsx1Dzx~iYX@p{Tdu>JSb!U0fgGjHq5E+kww{@CcKpZ<#F_TWJJ zZ}G6Sk!F|9lrMIzvMQ&#d5XjIN(+w-7ZpikHT=qyn)OR?y->?Ld#SPVGn>p-B(R@q z7Lwof!caE0D@JnI2VeGyi97DSrKao$S?Qd3;J-9SoDaYLE^T`Vc*EXMIz9_Nb8k4h$kX_M zFME1(@GMhVVPuiO$MR)aS$X-tJn!aYBA0{Zz#|)cu09pWFD^|126b1r((Gvx!aR8O zlq`1D0q^2v_ec;sKz2z5oyWA6)tSEFdl&vBKX;G(68}F%KT0f3qHxy+dg9AH%t~QA zfzgo6UXo@kRM_W$^L?QBv&n_>mw{AQ;YA0o;M#s#@u@C{Hf`zP@7tluX|u<9uz5#V zXo^&skFCU$=Nqu6jxekgV7ULDr%2Vf9!oouO@X^1T*J4^TJHAFR4E}@Bv9k0Oxz!B z8RAI}!^XASaP283b6$?aSNHP|JWR&1qJ9jaL?Zk~l;qtr5W}rYIjKo+Vn-zkcIW!C zUx^$}HtJ;Rqw94SEG?-YcSnYnH}XzcI^@g@f9|FP?c|du#>?U$2r-yo(UDYgl+j>% z*pWhmO*)9)X7oe0_}zO0?~8wMd@fV0!4ULpGCpd00Ao+jDt4T{{=3c7UtUHgA0Z+x zMTbYhxVbgqb(_#nE$1MQjrpC1PTs|Qdgq*z;5_x2Vs6dL%(g#)3~Fq2jiE<4@c+jX9Wec9&7YeAwuc2zFWs0kM}Uk6r}dj_PR9moluxPXjslw#$>3-{r!IN zy&0e<{5N%t|9EWFOdSNQ9fJ1~u}TMF$O?;Mgmr`$;_Vnl__I=)%Z_cLn6M@VV})Rm z%GZ!8b^^KcM%0fvtMJDN>&?nqOa;mo2r?HRt#Y!zk0{tU*;wNz-Yi#KRf%z-_> zf#$vCu_({WD`aN^#x;)i&`NAHg|K48DcEqZ0UKz9z=EEU0 zb?S5Lv%kS29#Ir2Pu$I%RsjVlCddiIV-PJCISaXT=}VNfEDf&EIl`s zFOcd?<;SyPgPpU5*6Sg=LlnnmYT%~2sj;!~ZlyQFz*?+=CnGQAq%8h$_Lai84aCbs z55Cb)By#G~=DpTqjfIz#>|Y;)dc~&MY>>+Ti`VXbTLPhojSiU=n6#J7Y;1hPyv7?z zxf{Asj1?m1=0CV(LMP00+)3>D%78d;q37{hE*K+Z)^1)Oi$01y0QKvW1}x8yj56O) z5O3wOWG56&2P5l8mVoGTalt;7ozV>%Q27osMT-G{*Y)%Pm-`MDyYiwhpi_?zP&hTNv@ zrjzSo>8~=xeebRgPPaz>qB!T#>9>C$u2zFUWc!I5HaAIK#5gRuNERJpn@6rnN1CO-p5xrCUVWfC$*ebBk#OzxXo$vjdP%=`5q<8kO=j0~C@SvW{ z5{gE!@~>|gB_3TL3rdet6fn_UJo=nhMo*i$N`QC5cbs*0HQj~L>x^E*r?n#l(>n9f z?`b58$Zw46E9In{e~LZKZNXOJegSF>lUZ4-9qwJTA0BS&ZXWK=EDJ-uotKlydj#vh z=LiX`)FN-HZCFyroao3k7DnxY1E>qz-X-@J_EQlHj0HRkAajNkcMG2WiLP#!g2(?a z2+X%R5s!Q>O;#N!R3}uek}+b@SX0Q1pXDZ{SJ5kfd2mz!?a$!$si)?c?6~DtprO5? zeOam!%URILX07lt??JjH~Th(t2hwNGqi3nxrOMVlafMc>AnTw!VqNhrn zRpTIhf2$W4%1}+E&!!e*KJ*eYf4U@MiU=1zn33mf;SrsB&UNQ%+#)kCJ{vq%98i(? zwt9ITW}H>WP8T!K+Gx|@4<{TaXQ~Z*^v|@|s9tf8cl9&vcSLd7O^V+gDT#kTP1klN z=IhId*l#!W3#&wT%xmaj_7P$hiI3jR(o^{(DMp`J@T7)VG$s_%&w+-5R~Hgy-f9Sq z<$uzMvh%sF_vE$dm7DEAQTBfep-lW(o@lW(3MEYrUjkrU*lgjXAm?<*AGpIe)wT8K z9A&2N8Ypq@cu01OsCpdGQCr~4%?cgbYJiK(;BUwEoHH5?em8E8H|OSNPAibLdUp9I zpN$IoQ*v4DwTgo*l&P7hd130e)>^&8`|G5yB_@f@+)xvt$Ux);6Eu2vox_RiPrSXH zP&YN1<6)|-1j;NIiyy(i6wR%brU5KhtCFLjF|r6fAZ?82#;or_eI#i&*XL;$4)^;j zat7*W9vCr?f3obk)QND;cNJ4|zV@xOcS~?s{(q)w9DC!YPRAqC6B>+%(<$|ur70!x zdA6(9Y`MkI(S$6jBZpBv0k=H>|M`_pS|j~)@Sb8y6KF*~B;^?iwSwH~XFY3UiDV{N zKx^C!hkv_4y-&hFE-h-kDJEiB2ZTq^d>l0o4kWB1HH`JcTH&dqe4or1cNOyxq8>ay zc(%gJ?z-b_wINZ3Ryfe^1}GO)hD#l`VBAFGF}+?lcPf*+H}2z&JAS$X7$|bEt^SMO z+khB)k^oyBVvCQEqX_Q#9w|vy$_;$CkjjV}zjVf;q8Uv}!MmgPs~oQ`)zf?7b>W^P zq+*WgJ!`od;>++UyGfS5jtUl^d&x3HBMZ7-gT>Rl4lRidt(l76co(1{PE+%2fw-^V z_}Lnj%k0^2nf8dmJ7QR!%?!IJa;a&4+lpXN7Wr9${?Rr)NM&NXMER&dr!TCmtZYJC z5M$ADCO|dM6?3>=v>w*eA~lkM;9+V|LmmL>lIdo@(ORE;C<(zCDcxL;J zJ8ec=6P@5^Xv{bHd`KQ1x*0tKeysaw;2kum@DxE#AU5#!@XACk?VmgCh~b@hk{z;( z8kT;{V#66D;rNV8^lcVriRETh@di^M;k}g%(mP8%P^q{F6+V)l2fJ4i1i!b*C9LC` z(|&#d9GTnf{?$fq1fY6zk~Q8Xpg{FzQh@ry6M6=Ew_f+>dlt%6)Ta?BnC;8PChkrL zo~0rh(3ih_F;2fOW)VLX=mx8D2|)tVc?V}pu}loA?ntCkgDEx6)73$)q|EoJ8Xr<@ z3@Bhk$dP>i^yk~+3&i^~O7?z50Bl1p!u?-&!`|h3CdAmd%aOIM;d&6(#-+FrUmnm1 z;NHBpnV_t76R)mir2E*0gj?d;q&%hQ3|J|DTSpkxrIwOuWBBTYAeUT@LWg9V%k^4u z&COx2+szzGd?=Uyr^n|jgl<6YY$$1n`f4&I;#05{Q5PQSPq>A4NYBo1?u_R*639;M zClv3?j}JZ1_Qk^U<{l2JSd!?TtModOJQadyTYRefl(btLnZJ|wd#)qTHZ`CR7>0bo ziuqhRT3g@FGD+I8!l z_LeGQ0p?Ww@u$z%hR!=xfbo~#zi+hD@^iO5ebIiz(X=BX83C=qTl&NkM=F~El%Xi> zS*eekEdqp@uCI-=Ic_U{y>GBx`m*Z2;p+cfWkr$EUv59~h6ONaqO(Z~7G}13{i%A< zcH-b8JDlgh^v5K|&`2q>P2yml;y`#d@|fGEcsV)K%gnrc#xJ}wQDwPpbf&0IP$?cl zDc_5F(!BjMUVPulUuUsc98h1P9%ucVN+oo|IZ!6FLY86 zRSZn7^{Y@c;N5KW-T+Y{$WW2VPelvN@Q+Yl#yx``JGsi#EF)lTk_RuL!`;R-AwMLV zhu%|#HhorjEqhqT84h!ROL*7tu649n&O=N?7}SIn46_`}x1*p{t4H10sv73D)cLZ6 z=4d4>UkPo>Yj}P26LlRN@}OxrJ}vC>yB4Mjnkl4hQ>VdU6hu0JsU+7d`QanT{&Qzt5vb!-bl z)NY7c#H!D^xBxbVqId_CPId;5wx?3BJ%wYhh520fa9Bg`&*DbtAl?PzP67rtUK4jm zCl_8Vg`eMC0axQlCZ;}rkp%RUhyirgtB3`Mb7lwvRW36rGPK`3!||;6+-wm{{ASa} zV1DEoxKa}H-@(^{K(q#ki-O>l#*t_XY@p*i8RZe3#D$EbnQ4DEw8sHZwNU1RP)EG1 z(o^Kew4^>Ds}j_UAmQU2*5LKIYB_$!^9Et9iWq!GGNltr?gG-}pT;mrlLi^j$=Ico z%wqWpZF$oFogA|0UF^9f-N93Lu}SLeno;&vZM}G2WO>^-b@y@oL6kA!3UPkW=E@|o z#On09&7*JsI4+aHrl2bZ!nS#O;ikh;vUN|BEf=JOR1e+-(Vu;CGzqWgMxW5+>p}yzIMXol?)}D_0mGTr;sLJ>)rbPzk;Ug^K!rDhx@;Nt%lSS z|44!9E#D+Z-bp0`=*ZRDNnhD-3qi-MaedvnQW&!g8;kqTN2Bs%+c7@;(M+slhK&MbwwK2Z6Mmm?wu zErun5e^nZl(3ewNKN`k{^Q)wxUHdXOS-;&}*OCfYb2WIgCun0U$@GxK* z17r63Eg5_6J-|o+hBMmMk6WTFl|%*h2x~4`)Vj~Sx>?e(!=X%ZN%pV}qcnSlW3Q{u zlX2n{dW#t@(y2!DOD)O=)>NGB_pMe~$w||0(n8sta`>_VzGU~no+sO-|tHE`t$Px7kQ8af6qgCxTsAr`EcB#LiJw-~Vt zYtn4Cv_hPG%|30W&01k>RsNJrNR5so>Wd%QU6)DqO5cEScI;Pc60VxabwzGnn4-L8 z^MAXLMRUt}7*KrtK2pSSpJuI%vQjQePShGoP%~y-ApdjY{goT#g(Ce9ks@@AvVBwZ zRR8VnP&;}LKE!u#F%-EPvjF!J^9RR+x(GUdL}yWrfV_L$pO}h!o^5~M+p|hbzeT;I zZ_Wy@c8klkmVIvzRKF$9^^51m)%g+iV|1N&4wn_(TsnUY?)X?@Kb5$DP)=x@6 z&E&z8dlDQ#8q1Ft2ksg=LLbd6Y-|vV=eNM^$cjb(FFjmnt9l*)#2X+ohPX0<$lkr` zkD4^1G@y>9g@2=y7!E9=NPbBtcNGn1Km;=MA% zLI^=)EDFeX{Y}Vd_BaRB5C3-D$lEXb{vMg46Z}2x<2mj?bJZ59_UsWboUn4=Rlo5V zE+mkbhUCukiRCQJ+M067tIA#~QDi@sBN7f`F6FJPtF}u`;^(nUuMssZYP1ca?FYH1 zdyvI`u*o4xYN$-`ZQ5KIB;mes)3>9zRg-#pBq|gXej=G)oUg@SQrQ4`$%3JyHpsfb z`bYS2XG7QLaXf;3PcDs%e5$}FlU7U*{?Ob|oB72QJ{~l*9k?aZ(s@eLR*ybHP+*A^ z%yQO2gK7>H3s{}cX7ePaf5eVT&b@CCj4!}8c0$k;CFIR7tq1u4x@jff{*Ed7$VGMZ zmOwVmk;Al(HLSix55lDA=J154SjD5NGT5FMKYidd*se5Z&dj=&#dGd05c+DB!Iw7^ z-9c^kzuN>~)Btpp<$X6G*-ftBTCwlNl7iT{&&WZ0cKy|{mghH>$J=(P3cG;bm_ zv+u|p2^CU8GYl|QnfT$?RsR)}p!bEEW&pW(Jr&^QEUM*d|8%qP=ELScctFa8hh837!piW^YlQ8oZtsK)bf2VA}vLNk6BCGXP1y`!!qJuCSct&G6 zT03*sj9r#nmTKVTZQibJ%_P2AN%&<+s~St8^}iFxO|*WpWVA>RGb8UW;GKJX$B-w@sdt08R=YHuk}W`pxlEX3&S@PoOkK?%L#cOAz!X8z7l3d(J)!d z6|y+`6>BBt2Swzjcd`ivo@Ic5R73MGk}+t(Dmu8i_+;RaoLy<1por31j}0%o6pjB{ zAR%a*rS$Yf>X2YPhu}^?g%08rAmiWDR7mxKfOQMNOPj12HsXaRlh5dt8WN%Qye`UA zt|OmlzA5&SuLMZ%*alPs|2U7{`Sdmgq82`<-sk83e!d5YdpMeIEJUUSZ@z zko^7^55A6!qbzx^JGPBa>xS0ajrJ94e@`j!GLl%B!S+tS95OX~?j{4pC>~?xd_M>U z5$M*K^|gpiEB!7**^Rn0d^HxuRun$Y#X6vK8rDuS*nC`i9~ro({IzV*jt)jz6pZ|7 z*qcN9`K-8&&h2)mgYOJ3k5_V${uuS>qKyGQXYo#^11chhyl7u5>Q zFD@^5@9+#LMOy(=cnNsIHG6K-d{AS*!lIar7dL?iZ~u6E*6i~B!v_1?^0@Pq?k!O9 zQj{KDYZqW}8oh=Q)9W^@po|Gc@Ka?RhjtAygi#@iysW2K(J;P)Sh_$7iUWXze@fU2 zLU+h3D-0I6*%9wu!&mdYK>;hVhNdR%aQ5tG3dd~(szflyKs=UGfE_+5}BKksX7k_QDwEf#WEC+ z$WT0-*zm?y7-4`)P4auo!ThjT=PZ1=k`QHHroDkp&+@VUJ`!oPkzVhP2GkYPiL@Ll<}$DWxB%`^AbISLU>PqJS5Wqx=g`t_IC6OvR#bD2PV@t zTKCM<7{Z~+SKrDl{X_SIukT&A`J94ww?syA#^7Gv-rxLaf0pn7R-0OEYUM*`8+A&oS z`}+ahugI@7SCQ7BqYabuq%k&q%=Y>JTF< zvMi|H0KAK$u$|9TX4jYy^|^6A-k+^nLdjoy-vgJlxJe`IUT>-`_wD1T=kNB|6-EFD7-Vd=(`nUVCf)Vg0`TFZ99S+_ThL3qde*k1dq=;NW_pYi#BLCnK z-Dom;$hH&snR?1g`JW*hG+D{8Alna?Y6hu^hL!ZD!E6&0krF`x^4|=TtTJBa>cN`{ zXxP0iCf;~GQ4sx+rITbM5j<)aSK6r4%GT*p!41rHUL_*0H5=ygaZ@S3+ymL=yx7g{ zE!No8ex-Zh2J3YW(j*2cUg-vEy~bIy`0i6+Jr=IeZ!J}WOVX(pO?sttv!6O!api4B z7O5~!lYGm*(OGH&PtapMOUo?BOOkCxlp(cCxtUjZ)-?D+qh+tKzC7$~od45B)V);S z4vaf0A5$yPeM1A%H|-~gf!tf7d2EJXF*;noBx9*9Xj3AxZ7nImD# zj^&;zlM9iBjdX@HMeH6>NJu=ha|IRjP?^*wNq5h&%|!CO@UO0BH|3EYE~$%@CCF4P zKe+EYPN2R-#Q#C?5%MoD&mI+|i11tqK!T)gj7gPP0$$cm(jprA-{z8-#|L9|cyOnS zAsEW#meU7r&|w>)^cCAM?Rpa`k3D#I9(ko{tn)uFw~dp*wT~I}TYPMeykAGo;F$oE z@j73OL?SW78BWe>b+6az`>WP4Ziol#UUB@diuVx~rmU@KO?YU@1VTS^=!JpZk^$qh#lF#$3@OaHTl6Z-Dd9ax3D zBeNT@ktZW^zFRK&sYe@A2#v!2>vuDW!V-slN(p(oK4Z>R5kYYzH!~|ii=pb>gK{U* z2JX4P8`WGo;k(cmD7)hVn~tLbR7Sb*NqoU>@SRR}#i9r+h)YfTUpJrk!BAOBy!xY; z;XgMj&$&L%GWXP=TjIkhX=BrNRZy1@m9n8OGF)x*wFL+UpU9*r5}Yyu5QZWOy&VR| z*hAQ%eJFe+#jP9O;@QbqH$BHawZmZ2Si6q^PZ^*w{-7t-1ch?u``U2_%3P!<#jS z9=I~N zpD_KDUen%B271>)%&!;hf|h|kLfre+pQSduC>a1FG5cz=P0~^~qF-9z@xKL_W3!I` zIcs?nslMt5h^ovqL^|a8Wf0}<@M9`%j5%Y(7sQS-ATUn)y&>ts?}HVO6$!Bu^b3hX zzJPkwY8fUr zg@XPX>K;z=7JK?WGovm zK`U~0Dd-I8WKpz{r?Kr{@J8w?=bh-W#wA*=sr(C}xp0WLb#OP($J$6P71gwf71J0} z!SVa%7lGHD$WHk?3aouPL(_6%4u_I&NkKAaXe4Yb6vS@pu&goP)L8M?h3w^Q-z zajdpF@cnE!M-s;k1Rk!5s3G{lNg~8_9KV=nY4@}_m7Z-Ted^pPpO<6yEMvu(} zMZnWkV)@ZBGPYT%-#L9~BwgfP%3sy=90}rrF~LrECK0$kmKT%m6TIS2$@uUQNB)(% zhRL?XU{oII{9`VtOVNTf)pWqrGnq$IV8n$}^OB(}Lj6R02e2HE$NbiarNd_sko&Xp zJaef2SpC0yCIo}%H6Y%{vqlZ-fF;|BR0GJ1H35_&N2>v?plvE17I;UsAd^K;k;=6r z=B-mLWqCUGxQ}vam(I3q+lm}@IM9Tp5Q*)HQv=W{s# z%aa8iM=@neK7qmd#oi0+N)aK2^%=3POq%+fL?GP_OWQss(yw_SNX|@?f#ILJ9IKUo zb;@*?qFK_kHaqeL#>`DtA69SB3*}a^ZKQ(PBaczi)J9dEjjdvm6JR1m_6u8zUPpU&OkPFi8cKfFbK9jGGq z`{tHnXMafwq&o=m`e39R)k1EG-uIFl_n|y$SK0wK`vPja0J_Ei(PsZpJ7Xq?wV{h1 zLM;oKa5`gBfz;}lE?iSfABAtd1=icfP`Y%`ir&9D=jC(wmzJhaQH;8_2UJy+OhXL5 zf=t>y$uE^(urm(=JaQMEA=8$*07Xz`zw@-CeEk7!1BzOZDT^wlluEjGCxnvl_R1~5#>AqVf^uTVjYGfdfFpG`g(G!BoLJ^ zBV2}rrD56X>05}FyxFC(DcL75^Txm3f){J(m}EYn=BcdRWi-C&o>NBD zUIm2dPfMED@J1@Tfe-sy;$^LmQWb7k*(j;3b-@@n?xmJMQ%bvo1p{d?Mkv3$(6$ zC=qQ0>l83;=1WhoJmNNdHXNl?WCU$~d-d-1x+q;r##rRwkb6Tdm*zo3SJxP^fNpcT zDgTR5M6ZR*ZKLy2qV~5RQ9+ukC4rUTPpM@kVFhf5)6~oi44B^*QZ^e7p``}w3{YIcN_wbnBkN$eX^=al7II+fhuvpC9-X=(_KS!D4Lz1^o3;YdpYZ0K zWw*^y!)StEYL6noGlp!e#Ols+G(-PWbwtRHKyQh1!B`MvC?-9H{&yA`{Tq>3p_!Di z{PqhLU4(pZMA}K~(4|MMh-Mw;V2LY{FvDyWmtx&~aN)7;PIt2*Wo}e{xOna{g2`@E zVY0cBkTKX4M$+(NBP2(0*?E5DVucFf^W*DcBQJ_F(8B9DD%iCx_|Gt4<%)jxr2kt5 zbAf$NAZMnMNg^e5tfJW%nsy}G`Gd%YHhVR+dz|p;^UM%pUUifBR`adX);Te35( zXh)}OxaYNDX~(5c^E-M$ba7g7{ip%BIX9mDj`YJ zQR`;+9!W)cdmGU2KVInkF!JR)VIBy;T@!fDn9mULcA`z;N^7=6`3l&Rvz5sD1=c9r zg%SY9bHsH0Ksmuv{pAo1UE>k)xb%MfY;5UBku484caYrl`cQNT1Vhj{QwTGm6a2B& z6qby5eF9*gKJw26T=>&lZ(mUm{xj%W5dZu|hGdE1i(K1PW4QXtADg*ZICrtYnnW%j zFA#kbKC$9>TbZdfR&k}`|LkBV+cm;a?i{s+lhc9SmRUp**#H<;pYaikhi9@5GnjQ} zCMn8?swJQN1^7$HsYJ&m&1b6m5X%SRPz2-0SgeRjd2N*lwP^64720D`C~-{vs_Nw( zjK_^yy+;z=>2tAfz~O6hN|+Sj_R$J%T#or4p|9kL$Xp-LKDX{HR@EAsdf$g{JoZ(R>A7_L`jJvALYF>5_@qHw@seu%zh!^?;34_+CQd35c?`>Wf&jRK@4PU>(MW z?(nW>FJ&%TZ={N@*xGXkcbMe9ka-(@6HR8VpiWEzc$W~xSA+dUu~RDF;4!y# z4k>X6Rq}HWkS!+<^5XMvn|tl75p+EHQ3^;IWi>;z{8<& zQd?W$OXo#{C8CMO24OV1D2;|K&5lF#MOf81LK+;x!3Fq>5<{AMELrZ@25Q6IlgD3Z z@rM^?UVABz0$cV5Fws7jqJt9<$)qUA-X=lUQC9!_xRba;L;rosuHFZS7wRqY5wAyK z7u893Gi@w(zxsOKv9NIYob=}Mclv{xF$SgHp@HW_g|42us6MQZdAa=_558Gs4q&A+ zbeAh^ESGSd}T0wbc`YLt0e*3P!x>}i=I#56bEm>IoB5c>vKPxnqc{rkvR+uBoI z)jcTa;Z|gWk9W%;`Q+QC+OHd#%~dA;H25-BvT^3SlH9qbg*lkEIo__{G+%wCx)E4c zL9t);Kc^#6)|0?=fM)Us*Q6aA0@x~j!^7YqW_oYvU&4i7RKB4i)(sauk zYl(FsvphLAQqu=wMUf^@lCaAv7=OZwNyNy-|39jrL(wBc*a zie&~V$;9!XMeQbH!B>!($V2Z*cwdv-5x_#_gBj!7qzUiK04Z_Jv=!B)We&TPHZ2nqrMO$hvO>~hYYO5eK)BC`Y-nUR4Da+Eg6sSf3JuCuVLDo&{7ykN^R zEB{%|a;^gAyeqN;_uFsXCPvNqy?ggAVJ7SdF;sub`tI9k6QWnlyv*Ba2aF&7> z$IeQHiSdoya^{R)1zu}bJS34?1I)QER>Q;>EPgD`QCnbDo34+0 z2NMi_DSN_uW$HZ*K#|M#;+QX0c%PQ+cQ+ZMG8;dU10zQQG8D-01jctNE9#Ifz$UN- zIzHFVNu3;1s0Q;Ode}(of|e7ofCUc&xhPdjwUE* z9JADNHm0p-%P=R#AgdaT%6B^kOt?QfaE6Hnn6J@&qOwFzu&%EKwT`%tz(+~~z%WIZ z5>MQVv=`~J*6Fxkk z9v4vN+Yv*lx^=dvN|=-#Bcz-Oj2pcIu(V99VgRt2D{Ycx$kmd$@*{0%my@o0PPV9= zZA+9WQKH20g6{8MAApGOy|J6U&r+!r?)A5CZL=oQNd3J8q#=-nUS0{L$u;~XP-&?b zjRZ%Qm<>z){&!CO7BbB%LKxf-$s@OLe{RX?~Gt!)2OnJC*=>`46#OP7Y<> zJn6qbVsR1W?KUyvl59sQk&++~odbL=aWOM90q_k z4B)_gIf6G`V7b&hfyEp_ZUfeh2a|j`kY)j>Lc$bcM=-?W`ngL8!=PMb+8`@0nYuPX zZsoJ}5}M=Fkh@G=ypP+O0UMI8Z7Kje5$N->uoEno>+e#A!gQ<@K%-N2yre6AZ^NJ??~oLPUfh&nF?g+blqde$??1?QKCeN66=FNnwrgD zbM^rMF*lImi9nhh&;p(`xpF6ZU;65sy?fqJR;io`4Au3k!!fCz1k&W}yH@4|<3xHn zKE1I_riB;Yr2q}+>pn&Fau$w$$(Pjm-1>wG!4ZI-V@jk@9@rptCC!i5XQskrtrpe_ z6abgTq*1Aa69hhBArtSy`+WpF=z0?vLm63gw$79haSDvVc2D^|)3-_OCaSa*tPCUw zMD=jYl1&x-F>s%7-WyHybCmDVk|{rCJS?SBn7Bsi8N4TbGMBD1p?&DME;}xf9oVQi zu#3cm+Re@AI&Hk)4uL6tH$K)^m$XFq(;WlvhQTFzs-t;<>55Rz-_Qzb0f&fo2PvYFH<@vN{u2ja) z3%#!_`x03b+7w;g^5_0|hS@OQqsTE-__#g;nwPs_z6Eb4$H-!N9soixWzg4J_MX9b zZJE6#0bod(B7-loZeS8j^_BNO^nGd8j(Y85Xo^n7CdZyDp#K6gUw;)CgjO6DAm^ODipg8+L53*tPd3LZ61Muy2ePo8Q%hnD44bPWR#MX8wi zZ_FDz1{nA>+`sk=EFF$uoZuwP%Y0qDDYA(lS{r;%YGx8)&IX{OWKHz1O%I(})3CS6Zu>q_(FChj$=zpz=$ENN4{MlV$Lywfs#4KUf z0Gx^0mb_^%+S&%c7Wf!d%z%P1b=#ngO#tL-9>16uOHW%Q8QKYk3kU_c7fAnGFy}nD z)Ag7)lD(&a8O^FmZ6p0?BzTQ`9;A?10Kk1|%v3%|GnH}u5I~cXK2bd7?7{DG)~CZq zQTlX<&E30qC$m0H#Za2=0K%}Fv$d~Znr_@snpQG``l-5+?J1__jyH+;`^C}v@POMl zZ7@WW8K2e~2g_sNVKVkmoD(pXlbN69f;Lh|n0nw3g{P?cL4_5YV`YE3}V-x@)N-*@qjc6b94Glqy;LMjDz7-qsP(Q#YzBB z)Gq;IcyPdj9j%ZaVJ?A5F02haAXf)=KNvDFCx(}$UXaB^IT{fA_kU#Lf#)U6jvFC$ zi{K6a)E?*{S<}9W-Z#P1q>gErt12#bw=J^ZGFT(F1qkK<9R@NwEbcen=LE~^=04X>@_Fc5{>+HqKksDhb6W~qnhGn8j@QX~0DRUaqMayGAMm1$7EZxNmU{j(*i4w<&CE1>cO_SqIv((S#>>Dr1dJ!Ov z%j$IAEb_8}G>hKna%ECfUwR4kz}GT>hkSJCkV}A(WBAV;tBfI&%BAHvdG;<+`f~z+ zkt_>9&k`06CR#EzuAV&QhAdNNec3Rb9$>>*3UAHI#``9fv2XhmLwYF(gMt2oUt#Kf zOiHeX79e2`e9nxVt1HjY_wpSZ(vnBEy=C@E;{Xp_3oU=b@g<9DD||boS0sS9^GmQ_ z+Q=dii^h(@(Abv@PWsVzcvC0VUWcA8=zPhRTPr(qXQU=1aaK90<(cM zEY`d09ZS~7pFh`CfH2fw0$^yp*|VhZbgWCVENL=A<*{KVkrmh5Fd+%xAJ|b%8<|!B zE#Vsz`a)%cWX;c8`@{^11pvT-;dhYSwO!9AN`f*tE&!%6R*eK^q;J-cQMzUx?vSZ% z0K7@bo`%4Bue)!?#qeqWgTxPlp(OV38)coDy z_wV82_by^{9grz$x{n`oQ+0#dcuc>UR9&QwSUwO^50BikFRo%XDK}8J`Drkd58@0X zVr?WmhwT$&PJFz%*`KDQPB6Wk+O9;25+zDZ2i;F;<$dnG6kt4oE;+~WVEp|1H8ET0 z`EmPJzQOSl2F_BM6fuRKUMx%bjeY6mlwN3a0^o?$?=RVZDY)_~Nu)5jpuS152Al!C zUuHyE!f=rjBc0lNDPv}6rF<$~xRkeRrnOAEfrT^YmCh@f*luiZ@tR)j_kzu`-NcFD7&8akZW;XAFf+w3`gRN&HOz|Yd|P!Uu;X{z zDoA3Q7XBvDdZK0{V+r`Uc4)eo`L*dMEYY5qQwdIjlAyMMVL%i7O9lwwW#T{?DMGB zO(`>V^l^Qk2Fp>FA^pQN2!nm8{wKR>fJS<>=@j0NpFI2L-}#NZe{lQu?Pni+@WE98 zY92m(SRH=oDSG0fA*R!gk2a5w(x^7Ye)xQ?kJuH#Z+k*`@Feo5t z11Qrr9WyqJm+({oBfO*tb++7|4iIU&;0uGgBNLUww6yY|LqGKFn&_e8&joBBcTH?$ zuXvVJ8~j9DR)zTOga<04GCMX&t}5GO-biK*m^-LXWX5zoA5;H3+GBu;0#;2twrsN~ zX|kqo_#2rlZ2&jCe9J}#kYR}tpU2KIHB5L0S{oDd^nG!-$s!;BhZ z`w}M!$Vfm>vub4KC&_Y=+mCr%r6f-PkR^k0%G2vbGHYb^#LCux^6sy_^Rq9$_~IEA zMVAG44F_Hxes&Lk`ipn|?1#Voi$jHO7naPoD>U+r8yh-tKNa8cLb}jv#?8`WA*~{4 zY$sdqo3kWcxAdf$3;al*nK`~R6w+^IN*3h@a^uqB%>`_39bR~keeFt=C{f~dj>k_f z%$?gOv$pkFn=Z}UZ_eAEBA2nV)I4~JQ86S-l=Aarmk;jHi)k(c#~C6L11Hm{c&*X! zT7c#l44k!Dq^2eZb7LsIcdn%A*zzbjIg*)(*2=A#CYtjGuqOZ}(@bj#n9vUaJX>Zx z&^xrwRzp)JWYO`gpK3HKRm!hsgZc^U1F&K6x66XX*=Qo0$Ee9>Y*R2?wEXGXIr4r0 zIJ}h1r}S=wHG>0>cpd>y6D-_sVf-rE(;67vdf?p3}sbX0`3q?h+ZRdSu|^mhN1JP^F3Xd#R>qA zXT;`#E7H(+DSHMBN=OwevyIFR&A?d-^7JMnZOo3cM9w4`IFd256qu2$kDSa=L-P0? zw~dxtK!QVa3+jtEoa`^{F*xSC2&oLp^eKV;gsnsRVa`H|cUn1*K-v3!OxZ1gEqy)w z{i}=S!~iF%IB#)#Sj=_eWSRh(y<_QczoGZ_ZC{Qh=M%^ZHO1zahP3YdubRNVz&15c z^o>Zt4Idi-MraQS8o1*)29FJLDgZHH*C5Lhm^3|hOVL=+L+h;33= z%qr>p{-|qj{>osKpQm<#%>pJ2aFxIiV)je~RifR63;;9;04=_3(>q6BC)ADmE(1f@ z7JZ|#{Ukp_iGKjxNYh{mx&hDwtELvdHQ0Y{2BW z68BY|4Qej423eov=Vwo^{`5Eh@b7>2A3y&iuxYLi+jjD*gH?0IC;2yrUq3O=AtYt0 z;{gYHo75Xtl^iTwNgL@{R_O6$XI+!3dniq}uebk04s>h|M7HgsOFQZsJ9pJXH(%yt z8>YdH(C%)6R`EC)pD6TT8B0evw>-J>k(>F6Lb7EbSDLebF3U!n3HuBI)o9ss0h{d% zz^Fut5+(jW2PWZj{bq=@a^vKBO5LG2BZJ*-mF0g!_iqA@=1x+Pr7340fHZGpW_DVd z5o)QA%^IWOA)Wu+kaTmJgzvWVk1h8rBqFzsdfGV_|IMWPsB9fh{w}tQj&Bjf)6hErrQ*Jo0Z7oqjKGLo|C?Np#`)2lH||B6_M7|OLHkkabNZd@VAgKi|=k zC;%{YPo(f5OKg|G5Hd(r?aM(joCxBeJl|eO+e9FiFUtg0Mr5)?CJh$Zaj%o(MN7@P zPWQ>VDZHox$K)|Rb ztKe%qYlbFn$SyO7fg|4`0eYa1fe|iQ02GjIOf5P}Hu$px*wD3INPFF}5v-Pr_<4bs zNkNvBG6O~g3CUF(Cc7}}r8aOAyeV@N}Y*3i1$a+fP=8Efy za&Z0|?n9ah0^q^5d*>k;SMM%nWoiRB(~3oK-^OTDFpuiW_KbvajU;H%busf1{!XeX zL?1+01*`zjJ4U3~HMz{1zJ*6*_vkSqeQ8?ZStAuN4mh;abABmxiW#N5(M(V{Ux1w< z(UBd_2p7S~xNXW?E5#(FjB3)zT;DTO;LQ;5KFO@PXr6p|e);2H|JCpQ0|PWJ4j@ha z=+PsGb<*Fnd(HXz<&Roh{r-O6ynEQ~w@RAs7ZaVjp$6F)qs?=W>0<^YQ*)f;b3;4e zuVLG)0d1sYiAKtlF)-rUWfMGb2s9Z3o96o1%mr+uY%0fWvP6jzC0^H{mG3PZeNF}W zz|gZ|4yZ%V;s5>W(y?jgfCWo3Ls9uTQlcfm&eDufjtz5o=G^*D9^kQ5BDDr&S+j4* zK(%jI85}QV&%hLTEx@C}8M@v%@9CQAU$2yE!PjApGz#7lxqdZcCDk|%G78{B7y z5?UlpgUKg_B{AAe)!Jwv3x>)KW=5sjLQ6ZGUBM=Lhg8-ob7Hqs@Ie9Fq2@V*I~KEt zbfiF-Dr98BTm!x#ebs=!CiG(hSVZ9_?(7@0;rSv>jNNxZ9#lDC%3lu;Qc)wpOg8`l z)pc`W-JgAZOvvyAX%q+s06UNgN`e(p*%4(@(r~x3)1IW7QL~0kqa($xnHtZsKJxs* zu+dqdI$=SAJ{F~0QexL{hm>!PlsbWtGlUrcz`5G@$shFqyDrI`vr!@`L6;$EW(vR= zyJzA!sr$0LS5n30civRE{rAJd$iE%R`j_+Svjs; z^6?DX2ixOwQNL8Zt{ns4a~(rnWcj>Jubsqp*VQ_Tv2HHfHSDMqN+UcSD%6;FXP{sGX9OZKK|)@mk^DA z=-+$sx$ZBcL4{kQ;2eH$-+%vo5@Mh7&rSOI{`bFs6aS{4yLa!N;&c6--ahrc+*f~} z`dt2-jy-hT#Qvv4brbua;(Vrl=A2jRXRLfGXXtxbSDZKMthVX3$w=K!b-m<1djF~4 zx}Nepruv1fyUAsKY~wQi%lJ2W?On!y8UJPcC;IZ-exut`U(30_bv?`YFXMmY zx+UBAH6Q;}?hVFNNC!O`WgU zrq+M!>y)~NLqBEwU+)8D{F}k+R>uGEc4hqEPkvX%e{!EP{?q4B#(&~`%lOZ)&qO<3 z>pNxqm+?PR*E0Uc+vjx||FyU_0BD{|*u>v<<~DX@o3S!;%Cm`W>_9nFF}44kb07PB zPI*&h=+CFlaj1Rt=VoBLp|Vn+5B;6`d`?+Y=Q&jOp<|4ltKKJdEHm+4s;!M#*0-nn z@tkAn@`m;wizQi2wiq07*qoM6N<$f@w%!*#H0l literal 0 HcmV?d00001 diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 5db2a028f..93ab8638f 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -25,6 +25,7 @@ import { getEcosystems } from '../../api/ecosystem'; import { getEcosystemId } from '../../config/ecosystem'; import { getSchemaCredDef } from '../../api/BulkIssuance'; import type { ICredentials } from '../Issuance/interface'; +import React from 'react'; const initialPageState = { pageNumber: 1, pageSize: 10, @@ -321,6 +322,11 @@ const UserDashBoard = () => { }} />
+
+
{
-
+
v.{schema?.version}
From 750a7058bccc6f93b847711c91bf14d003382a9d Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 5 Jan 2024 17:15:14 +0530 Subject: [PATCH 016/303] fix: popup close and navigation Signed-off-by: karan --- src/components/Resources/Schema/Create.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Resources/Schema/Create.tsx b/src/components/Resources/Schema/Create.tsx index 4dfc929b8..b90ec4c53 100644 --- a/src/components/Resources/Schema/Create.tsx +++ b/src/components/Resources/Schema/Create.tsx @@ -105,13 +105,13 @@ const CreateSchema = () => { setLoading(true) setTimeout(() => { setSuccess(null); - }, 2000); + window.location.href = pathRoutes?.organizations?.schemas; + }, 1500); setTimeout(() => { setShowPopup({ type: "create", show: false }); - window.location.href = pathRoutes?.organizations?.schemas; }, 2000); } else { setFailure(createSchema as string); From 33874db443a5e51487fe4712bfb61e8f9a25dafc Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 8 Jan 2024 16:21:19 +0530 Subject: [PATCH 017/303] refactor: dashboard ui Signed-off-by: karan --- public/images/Frame.png | Bin 58888 -> 0 bytes public/images/bg-darkwallet.png | Bin 0 -> 70073 bytes public/images/bg-lightwallet.png | Bin 0 -> 225461 bytes src/components/User/UserDashBoard.tsx | 876 +++++++++++++++----------- 4 files changed, 497 insertions(+), 379 deletions(-) delete mode 100644 public/images/Frame.png create mode 100644 public/images/bg-darkwallet.png create mode 100644 public/images/bg-lightwallet.png diff --git a/public/images/Frame.png b/public/images/Frame.png deleted file mode 100644 index 42ddb81b4973c140b7d2e0f07d4c5bebab9d923f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58888 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�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 diff --git a/public/images/bg-darkwallet.png b/public/images/bg-darkwallet.png new file mode 100644 index 0000000000000000000000000000000000000000..606b4be50cfba4652847d497a1f5cdfc7b295d56 GIT binary patch literal 70073 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 KMNUMnLSTYa$@e?} literal 0 HcmV?d00001 diff --git a/public/images/bg-lightwallet.png b/public/images/bg-lightwallet.png new file mode 100644 index 0000000000000000000000000000000000000000..dbef3df16218b320532f65827b5cafd5af1f1937 GIT binary patch literal 225461 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�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�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 { const [viewButton, setViewButton] = useState(false); const [error, setError] = useState(null); const [currentPage, setCurrentPage] = useState(initialPageState); - const [loading, setLoading] = useState(false); const [organizationsList, setOrganizationList] = useState | null>(null); const [activityList, setActivityList] = useState | null>( @@ -60,9 +57,13 @@ const UserDashBoard = () => { const [ecosystemList, setEcosystemList] = useState([]); const [credDefList, setCredDefList] = useState([]); const [credDefCount, setCredDefCount] = useState(0); - - console.log('schemaList1212', schemaList); - console.log('1212', organizationsList); + const [walletData, setWalletData] = useState([]); + const [loading, setLoading] = useState(true); + const [ecoLoading, setEcoLoading] = useState(true); + const [credDefLoading, setCredDefLoading] = useState(true); + const [orgLoading, setOrgLoading] = useState(true); + const [schemaLoading, setSchemaLoading] = useState(true); + const [walletLoading, setWalletLoading] = useState(true); const getAllInvitations = async () => { setLoading(true); @@ -123,14 +124,13 @@ const UserDashBoard = () => { }; //Fetch the user organization list const getAllOrganizations = async () => { - setLoading(true); + setOrgLoading(true); const response = await getOrganizations( currentPage.pageNumber, currentPage.pageSize, '', ); const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const totalPages = data?.data?.totalPages; setOrgCount(data?.data?.organizations?.length); @@ -147,7 +147,7 @@ const UserDashBoard = () => { setError(response as string); } - setLoading(false); + setOrgLoading(false); }; //Fetch the user recent activity @@ -158,12 +158,12 @@ const UserDashBoard = () => { if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const activityList = data?.data; - setActivityList(activityList); + setLoading(false); } else { setError(response as string); + setLoading(false); } - setLoading(false); }; const checkOrgId = async () => { @@ -178,7 +178,7 @@ const UserDashBoard = () => { ) => { try { const organizationId = await getFromLocalStorage(storageKeys.ORG_ID); - setLoading(true); + setSchemaLoading(true); let schemaList; schemaList = await getAllSchemasByOrgId( @@ -189,28 +189,29 @@ const UserDashBoard = () => { const { data } = schemaList as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setSchemaCount(data?.data?.totalItems); + if (data?.data?.data) { - setSchemaCount(data?.data?.data?.length); const schemaData = data?.data?.data?.filter( (schema: any, index: number) => index < 3, ); setSchemaList(schemaData); - setLoading(false); + setSchemaLoading(false); } else { - setLoading(false); + setSchemaLoading(false); } } else { - setLoading(false); + setSchemaLoading(false); } } catch (error) { - console.error('Error while fetching schema list:', error); - setLoading(false); + setSchemaLoading(false); } }; const fetchEcosystems = async () => { const id = await getFromLocalStorage(storageKeys.ORG_ID); if (id) { + setEcoLoading(true); const response = await getEcosystems( id, currentPage.pageNumber, @@ -233,31 +234,49 @@ const UserDashBoard = () => { setError(response as string); } } - setLoading(false); + setEcoLoading(false); }; const getSchemaCredentials = async () => { try { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); if (orgId) { + setCredDefLoading(true); const response = await getSchemaCredDef(); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setCredDefCount(data.data.length); - console.log('credentialDefs', data.data); const credentialDefs = data?.data?.filter( (ecosystem: Organisation, index: number) => index < 3, ); setCredDefList(credentialDefs); } - setLoading(false); + setCredDefLoading(false); } } catch (error) { - console.log('error----'); + setCredDefLoading(false); + } finally { + setCredDefLoading(false); + } + }; - // setFailure(response as string) + const fetchOrganizationDetails = async () => { + setWalletLoading(true); + let orgId = await getFromLocalStorage(storageKeys.ORG_ID); + if (!orgId && organizationsList) { + orgId = organizationsList[0].id; + } + const response = await getOrganizationById(orgId); + const { data } = response as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (data?.data?.org_agents) { + setWalletData(data?.data?.org_agents); + } else { + setWalletData([]); + } } + setWalletLoading(false); }; const getAllResponses = async () => { @@ -277,15 +296,19 @@ const UserDashBoard = () => { getAllResponses(); }, []); + useEffect(() => { + if (organizationsList && organizationsList?.length > 0) { + fetchOrganizationDetails(); + } + }, [organizationsList]); + const goToOrgDashboard = async (orgId: string, roles: string[]) => { await setToLocalStorage(storageKeys.ORG_ID, orgId); window.location.href = pathRoutes.organizations.dashboard; }; const goToSchemaCredDef = async (schemaId: string) => { - // await setToLocalStorage(storageKeys.ORG_ID, orgId); - console.log('schemaId11', schemaId); - + await setToLocalStorage(storageKeys.ORG_ID, orgId); const url = `${ pathRoutes.organizations.viewSchema }?schemaId=${encodeURIComponent(schemaId)}`; @@ -322,16 +345,69 @@ const UserDashBoard = () => { }} />

-
- + {walletData && walletData.length > 0 ? ( + <> + ) : ( +
+ {walletLoading ? ( + <> + ) : ( + <> +
+
+
+

+ Wallet lets you create schemas and credential-definitions +

+ + Please create wallet for your organisation which would + help you to issue and verify credentials for your users. + +
+
+
+
+ +
+ + )} +
+ )}
-
+
@@ -391,205 +467,221 @@ const UserDashBoard = () => {

- {organizationsList?.length > 0 ? ( + {!orgLoading ? ( <> - {' '} - {organizationsList?.map((org) => { - const roles: string[] = org.userOrgRoles.map( - (role) => role.orgRole.name, - ); - org.roles = roles; - return ( -
- - -
+
+ - - - - - - {' '} - + + - - - - - - - - {' '} - + + - - - - - - - - - - - - -
- - ); - })} - {organizationsList && organizationsList?.length > 0 && ( - - View All - - )}{' '} + {' '} + + + + {' '} + + +
+ + ); + })} + {organizationsList && organizationsList?.length > 0 && ( + + View All + + )}{' '} + + ) : ( +
+

You have no organisations created or joined

+
+ )} ) : (
-

You have no organisations created or joined

+
)}
-
+
@@ -629,48 +721,57 @@ const UserDashBoard = () => {

- {schemaList?.length > 0 ? ( + + {!schemaLoading ? ( <> - {' '} - {schemaList?.map((schema) => { - return ( -
-
- v.{schema?.version} -
- - ); - })} - {schemaList && schemaList?.length > 0 && ( - - View All - +
+ goToSchemaCredDef(schema?.schemaLedgerId) + } + > + + + {schema?.name} + + +
+
+ v.{schema?.version} +
+ + ); + })} + {schemaList && schemaList?.length > 0 && ( + + View All + + )} + + ) : ( +
+

You have no schemas created

+
)} ) : ( -
-

You have no schemas created

+
+
)}
@@ -680,7 +781,10 @@ const UserDashBoard = () => { className="grid w-full grid-cols-1 gap-4 mt-0 mb-4 xl:grid-cols-3" style={{ minHeight: '300px' }} > -
+
@@ -741,64 +845,75 @@ const UserDashBoard = () => {

- {ecosystemList.length > 0 ? ( + {!ecoLoading ? ( <> - {ecosystemList?.map((ecosystem: any) => { - return ( -
- - ); - })} - - {ecosystemList && ecosystemList?.length > 0 && ( - - View All - + + + ); + })} + + {ecosystemList && ecosystemList?.length > 0 && ( + + View All + + )} + + ) : ( +
+

You have no ecosystems created or joined

+
)} ) : ( -
-

You have no ecosystems created or joined

+
+
)}
-
+
@@ -841,46 +956,57 @@ const UserDashBoard = () => {

- {credDefList.length > 0 ? ( + + {!credDefLoading ? ( <> - {' '} - {credDefList?.map((cred) => { - return ( -
- {/*
- {cred?.credentialDefinitionId} -
*/} - - ); - })} - {credDefList && credDefList?.length > 0 && ( +
goToSchemaCredDef(cred?.schemaLedgerId)} + > + + + {cred?.credentialDefinition} + + +
+
+ + {cred?.credentialDefinitionId.slice(0, 5)}... + +
+ + ); + })} + {/* {credDefList && credDefList?.length > 0 && ( View All - )} + )} */} + + ) : ( +
+

You have no cred-defs created

+
+ )}{' '} ) : ( -
-

You have no cred-defs created

+
+
)}
@@ -893,52 +1019,44 @@ const UserDashBoard = () => { Recent Activity
- {activityList && activityList?.length === 0 && ( + {/* {activityList && activityList?.length === 0 && (
Looks like there is no activity to display at the moment.
- )} + )} */}
- {activityList ? ( -
    - {activityList.map((activity) => ( -
  1. -
    - -

    - {activity.action} -

    -

    - {activity.details} -

    -
  2. - ))} -
+ + {!loading ? ( + <> + {activityList && activityList?.length > 0 ? ( +
    + {activityList.map((activity) => ( +
  1. +
    + +

    + {activity.action} +

    +

    + {activity.details} +

    +
  2. + ))} +
+ ) : ( +
+

Looks like there is no activity yet

+
+ )} + ) : ( - activityList && ( - - - - } - /> - ) +
+ +
)}
From db11c4526e88fa5306debce2d725d345438f62b1 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 9 Jan 2024 18:35:35 +0530 Subject: [PATCH 018/303] redirection and interface Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 98 ++++++++++++++++++--------- 1 file changed, 67 insertions(+), 31 deletions(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 5bec2a349..5932f381c 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -30,6 +30,21 @@ const initialPageState = { total: 0, }; +interface ISchema { + version: string; + name: string; + schemaLedgerId: string; + id: string; +} + +interface ICredDef { + credentialDefinition: string; + schemaVersion: string; + schemaName: string; + credentialDefinitionId: string; + id: string; +} + const UserDashBoard = () => { const [message, setMessage] = useState(null); const [ecoMessage, setEcoMessage] = useState(null); @@ -43,8 +58,7 @@ const UserDashBoard = () => { ); const [orgCount, setOrgCount] = useState(0); const [schemaCount, setSchemaCount] = useState(0); - const [schemaList, setSchemaList] = - useState | null>(null); + const [schemaList, setSchemaList] = useState | null>(null); const [schemaListAPIParameter, setSchemaListAPIParameter] = useState({ itemPerPage: 9, page: 1, @@ -302,18 +316,47 @@ const UserDashBoard = () => { } }, [organizationsList]); - const goToOrgDashboard = async (orgId: string, roles: string[]) => { + const goToOrgDashboard = async (orgId: string, rogRoles: string[]) => { await setToLocalStorage(storageKeys.ORG_ID, orgId); window.location.href = pathRoutes.organizations.dashboard; }; const goToSchemaCredDef = async (schemaId: string) => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); await setToLocalStorage(storageKeys.ORG_ID, orgId); const url = `${ pathRoutes.organizations.viewSchema }?schemaId=${encodeURIComponent(schemaId)}`; window.location.href = url; }; + + const goToCredDef = async ( + credentialDefinitionId: string, + schemaName: string, + schemaVersion: string, + ) => { + const schemaId = + credentialDefinitionId.split(':')[0] + + ':2:' + + schemaName + + ':' + + schemaVersion; + console.log( + credentialDefinitionId.split(':')[0] + + ':2:' + + schemaName + + ':' + + schemaVersion, + ); + + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + await setToLocalStorage(storageKeys.ORG_ID, orgId); + const url = `${ + pathRoutes.organizations.viewSchema + }?schemaId=${encodeURIComponent(schemaId)}`; + window.location.href = url; + }; + const goToEcoDashboard = async (ecosystemId: string) => { await setToLocalStorage(storageKeys.ECOSYSTEM_ID, ecosystemId); window.location.href = pathRoutes.ecosystem.dashboard; @@ -372,7 +415,7 @@ const UserDashBoard = () => {
-
+

@@ -725,7 +768,7 @@ const UserDashBoard = () => { {!schemaLoading ? ( <> {schemaList && schemaList?.length > 0 ? ( - <> +
{' '} {schemaList?.map((schema) => { return ( @@ -757,12 +800,12 @@ const UserDashBoard = () => { {schemaList && schemaList?.length > 0 && ( View All )} - +
) : (

You have no schemas created

@@ -785,7 +828,7 @@ const UserDashBoard = () => { className="xl:col-span-2 justify-between p-4 bg-white border border-gray-200 rounded-md shadow-sm sm:flex dark:border-gray-700 sm:p-6 dark:bg-gray-800" style={{ minHeight: '300px' }} > -
+

@@ -891,7 +934,7 @@ const UserDashBoard = () => { {ecosystemList && ecosystemList?.length > 0 && ( View All @@ -914,7 +957,7 @@ const UserDashBoard = () => { className="xl:col-span-1 justify-between p-4 bg-white border border-gray-200 rounded-md shadow-sm sm:flex dark:border-gray-700 sm:p-6 dark:bg-gray-800" style={{ minHeight: '300px' }} > -
+

@@ -962,7 +1005,7 @@ const UserDashBoard = () => { {credDefList && credDefList.length > 0 ? ( <> {' '} - {credDefList?.map((cred) => { + {credDefList?.map((cred: ICredDef) => { return ( ); })} - {/* {credDefList && credDefList?.length > 0 && ( - - View All - - )} */} ) : (
@@ -1019,11 +1060,6 @@ const UserDashBoard = () => { Recent Activity


- {/* {activityList && activityList?.length === 0 && ( -
- Looks like there is no activity to display at the moment. -
- )} */}
{!loading ? ( From 02437265d664cc8687f330854d83938b16ce69b8 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 10 Jan 2024 15:47:10 +0530 Subject: [PATCH 019/303] added cred-def total items count Signed-off-by: karan --- src/api/Schema.ts | 18 ++++++++++++ src/components/User/UserDashBoard.tsx | 42 +++++++-------------------- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/api/Schema.ts b/src/api/Schema.ts index 2ff54940b..acf1ea9a6 100644 --- a/src/api/Schema.ts +++ b/src/api/Schema.ts @@ -4,6 +4,7 @@ import { axiosGet, axiosPost } from "../services/apiRequests"; import { apiRoutes } from "../config/apiRoutes"; import { getFromLocalStorage } from "./Auth"; import { storageKeys } from "../config/CommonConstant"; +import { getHeaderConfigs } from "../config/GetHeaderConfigs"; export const getAllSchemas = async ({itemPerPage, page, allSearch }: GetAllSchemaListParameter) => { const token = await getFromLocalStorage(storageKeys.TOKEN) @@ -120,6 +121,23 @@ export const createCredentialDefinition = async (payload: createCredDeffFieldNam } } +export const getAllCredDef = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.schema.createCredentialDefinition}`; + const axiosPayload = { + url, + config: await getHeaderConfigs(), + }; + + try { + return await axiosGet(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } +}; + + export const getCredDeffById = async (schemaId: string, orgId: string) => { const token = await getFromLocalStorage(storageKeys.TOKEN) const details = { diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 5932f381c..0713ddb15 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -17,7 +17,7 @@ import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; import { Roles } from '../../utils/enums/roles'; import { Button, Tooltip } from 'flowbite-react'; -import { getAllSchemasByOrgId } from '../../api/Schema'; +import { getAllCredDef, getAllSchemasByOrgId } from '../../api/Schema'; import type { GetAllSchemaListParameter } from '../Resources/Schema/interfaces'; import { getEcosystems } from '../../api/ecosystem'; import { getSchemaCredDef } from '../../api/BulkIssuance'; @@ -38,6 +38,7 @@ interface ISchema { } interface ICredDef { + tag: string; credentialDefinition: string; schemaVersion: string; schemaName: string; @@ -256,14 +257,15 @@ const UserDashBoard = () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); if (orgId) { setCredDefLoading(true); - const response = await getSchemaCredDef(); + const response = await getAllCredDef(); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setCredDefCount(data.data.length); - const credentialDefs = data?.data?.filter( + setCredDefCount(data.data.totalItems); + const credentialDefs = data?.data?.data?.filter( (ecosystem: Organisation, index: number) => index < 3, ); + setCredDefList(credentialDefs); } setCredDefLoading(false); @@ -330,30 +332,12 @@ const UserDashBoard = () => { window.location.href = url; }; - const goToCredDef = async ( - credentialDefinitionId: string, - schemaName: string, - schemaVersion: string, - ) => { - const schemaId = - credentialDefinitionId.split(':')[0] + - ':2:' + - schemaName + - ':' + - schemaVersion; - console.log( - credentialDefinitionId.split(':')[0] + - ':2:' + - schemaName + - ':' + - schemaVersion, - ); - + const goToCredDef = async (credentialDefinitionId: string) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); await setToLocalStorage(storageKeys.ORG_ID, orgId); const url = `${ pathRoutes.organizations.viewSchema - }?schemaId=${encodeURIComponent(schemaId)}`; + }?schemaId=${encodeURIComponent(credentialDefinitionId)}`; window.location.href = url; }; @@ -1013,20 +997,14 @@ const UserDashBoard = () => { >
- goToCredDef( - cred?.credentialDefinitionId, - cred?.schemaName, - cred?.schemaVersion, - ) - } + onClick={() => goToCredDef(cred?.schemaLedgerId)} > - {cred?.credentialDefinition} + {cred?.tag}
From 300ba1673ad2afe9a8a4526a6e6edd705e0166c7 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Wed, 10 Jan 2024 17:39:24 +0530 Subject: [PATCH 020/303] refactor: out of band issuance via email Signed-off-by: sanjay-k1910 --- src/common/global.css | 4 + src/components/Issuance/EmailIssuance.tsx | 139 ++++++++++------------ src/config/apiRoutes.ts | 2 +- 3 files changed, 65 insertions(+), 80 deletions(-) diff --git a/src/common/global.css b/src/common/global.css index 31158d179..4381a957c 100644 --- a/src/common/global.css +++ b/src/common/global.css @@ -135,6 +135,10 @@ ul.timelinestatic { @apply dark:!text-white !text-primary-700 w-fit; } +.email-bulk-issuance .select__single-value{ + width: calc(100% - 15px) !important; +} + .select__value-container .select__value-container--has-value .select__single-value { diff --git a/src/components/Issuance/EmailIssuance.tsx b/src/components/Issuance/EmailIssuance.tsx index daca68805..f727829ba 100644 --- a/src/components/Issuance/EmailIssuance.tsx +++ b/src/components/Issuance/EmailIssuance.tsx @@ -192,7 +192,7 @@ const EmailIssuance = () => { const handleResetOpenConfirmation = () => { setOpenResetModal(true); }; - + const MailError = ({ handler, formindex, @@ -256,10 +256,10 @@ const EmailIssuance = () => {

Email

-
+
-
-

+

+

Select Schema and credential definition

@@ -362,18 +362,12 @@ const EmailIssuance = () => {
-
+
-
+
-

+

Issue Credential(s) to the email

@@ -513,51 +507,51 @@ const EmailIssuance = () => { {arrayHelpers.form .values.formData .length > 1 && ( -
- -
- )} + + + + +
+ )}
{formData1.attributes && @@ -570,18 +564,18 @@ const EmailIssuance = () => { displayName: ReactNode | string; attributeName: ReactNode | string; name: + | string + | number + | boolean + | React.ReactElement< + any, | string - | number - | boolean - | React.ReactElement< - any, - | string - | React.JSXElementConstructor - > - | Iterable - | React.ReactPortal - | null - | undefined; + | React.JSXElementConstructor + > + | Iterable + | React.ReactPortal + | null + | undefined; schemaDataType: any; }, attIndex: any, @@ -590,20 +584,7 @@ const EmailIssuance = () => {
{ item?.name?.toString().length, ), ) * - 10 + + 10 + 28, }} > @@ -681,7 +662,7 @@ const EmailIssuance = () => { arrayHelpers.push({ email: '', attributes: attributes?.map( - + (item) => { return { attributeName: diff --git a/src/config/apiRoutes.ts b/src/config/apiRoutes.ts index 0e6f3b72a..dbdadbad7 100644 --- a/src/config/apiRoutes.ts +++ b/src/config/apiRoutes.ts @@ -50,7 +50,7 @@ export const apiRoutes = { getIssuedCredentials: '/credentials', getAllConnections: '/connections', issueCredential: '/credentials/offer', - issueOobEmailCredential: '/credentials/oob', + issueOobEmailCredential: '/credentials/oob/email', bulk:{ credefList:'/bulk/cred-defs', uploadCsv: '/bulk/upload', From 153b2bb56f4c028d491899090a1128deff53dcab Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 10 Jan 2024 18:32:38 +0530 Subject: [PATCH 021/303] changed count logic Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 0713ddb15..2af77a8b3 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -148,7 +148,7 @@ const UserDashBoard = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const totalPages = data?.data?.totalPages; - setOrgCount(data?.data?.organizations?.length); + setOrgCount(data?.data?.totalCount); const orgList = data?.data?.organizations.filter( (userOrg: Organisation, index: number) => index < 3, ); @@ -236,7 +236,7 @@ const UserDashBoard = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setEcoCount(data?.data?.length); + setEcoCount(data?.data?.totalCount); const ecosystemData = data?.data?.filter( (ecosystem: Organisation, index: number) => index < 3, ); From 433b9004c5a2d223988a40d62c217cfcbd478c5e Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 11 Jan 2024 12:34:45 +0530 Subject: [PATCH 022/303] removed: redundent code Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 2af77a8b3..a95f1b2b5 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -147,17 +147,11 @@ const UserDashBoard = () => { ); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const totalPages = data?.data?.totalPages; setOrgCount(data?.data?.totalCount); const orgList = data?.data?.organizations.filter( (userOrg: Organisation, index: number) => index < 3, ); - setOrganizationList(orgList); - setCurrentPage({ - ...currentPage, - total: totalPages, - }); } else { setError(response as string); } @@ -181,12 +175,14 @@ const UserDashBoard = () => { } setLoading(false); }; + const checkOrgId = async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); if (orgId) { await getAllEcosystemInvitations(); } }; + const getSchemaList = async ( schemaListAPIParameter: GetAllSchemaListParameter, flag: boolean, From 678220c9603921b36a232b0961910bc2c5c53f6e Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 11 Jan 2024 15:41:48 +0530 Subject: [PATCH 023/303] fix: all changes for ecosystem Signed-off-by: karan --- src/commonComponents/EcosystemProfileCard.tsx | 2 +- src/components/Ecosystem/Dashboard.tsx | 3 +-- src/components/Ecosystem/EcosystemList.tsx | 2 +- src/components/User/UserDashBoard.tsx | 10 +++++----- src/config/ecosystem.ts | 6 +++--- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/commonComponents/EcosystemProfileCard.tsx b/src/commonComponents/EcosystemProfileCard.tsx index b5a472963..f912cf541 100644 --- a/src/commonComponents/EcosystemProfileCard.tsx +++ b/src/commonComponents/EcosystemProfileCard.tsx @@ -28,7 +28,7 @@ const EcosystemProfileCard = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setEcosystemList(data?.data) - const ecosystemData = data?.data?.find((item: { id: string }) => item.id === ecosystemId); + const ecosystemData = data?.data?.ecosystemDetails?.find((item: { id: string }) => item.id === ecosystemId); if (ecosystemData) { setEcosystemId(ecosystemData?.id) const ecosystemOrg = diff --git a/src/components/Ecosystem/Dashboard.tsx b/src/components/Ecosystem/Dashboard.tsx index 0a36cb03d..1b64de14e 100644 --- a/src/components/Ecosystem/Dashboard.tsx +++ b/src/components/Ecosystem/Dashboard.tsx @@ -123,9 +123,8 @@ const Dashboard = () => { if (id) { const response = await getEcosystems(id); const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const ecosystemData = data?.data.find( + const ecosystemData = data?.data?.ecosystemDetails?.find( (item: { id: string }) => item.id === ecosystemId, ); if (ecosystemData) { diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index e20dd6105..3b016c61e 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -69,7 +69,7 @@ const EcosystemList = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const ecosystemData = data?.data; + const ecosystemData = data?.data.ecosystemDetails; if (ecosystemData) { setEcosystemList(ecosystemData); diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index a95f1b2b5..59d4bf88b 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -20,7 +20,6 @@ import { Button, Tooltip } from 'flowbite-react'; import { getAllCredDef, getAllSchemasByOrgId } from '../../api/Schema'; import type { GetAllSchemaListParameter } from '../Resources/Schema/interfaces'; import { getEcosystems } from '../../api/ecosystem'; -import { getSchemaCredDef } from '../../api/BulkIssuance'; import React from 'react'; import CustomSpinner from '../CustomSpinner'; @@ -79,7 +78,6 @@ const UserDashBoard = () => { const [orgLoading, setOrgLoading] = useState(true); const [schemaLoading, setSchemaLoading] = useState(true); const [walletLoading, setWalletLoading] = useState(true); - const getAllInvitations = async () => { setLoading(true); const response = await getUserInvitations( @@ -232,10 +230,10 @@ const UserDashBoard = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setEcoCount(data?.data?.totalCount); - const ecosystemData = data?.data?.filter( + setEcoCount(data?.data?.totalCount); + const ecosystemData = data?.data?.ecosystemDetails.filter( (ecosystem: Organisation, index: number) => index < 3, - ); + ); if (ecosystemData) { setEcosystemList(ecosystemData); } else { @@ -878,6 +876,8 @@ const UserDashBoard = () => { className="flex justify-between w-full mt-2 items-center" key={ecosystem?.id} > + <>{console.log("ecosystem1111",ecosystem) + }
goToEcoDashboard(ecosystem?.id)} diff --git a/src/config/ecosystem.ts b/src/config/ecosystem.ts index 7cd383955..2ddbd37b4 100644 --- a/src/config/ecosystem.ts +++ b/src/config/ecosystem.ts @@ -75,10 +75,10 @@ const getEcosystemId = async (): Promise => { if ( data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS && - data?.data && - data?.data.length > 0 + data?.data && data?.data.ecosystemDetails && + data?.data.ecosystemDetails.length > 0 ) { - const response = data?.data[0]; + const response = data?.data.ecosystemDetails[0]; const id = response?.id; const role = response?.ecosystemOrgs && From db86b6ce679c0402bc101a0f82c4e4772df847d3 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 11 Jan 2024 17:58:31 +0530 Subject: [PATCH 024/303] fix: alignment issue on org discription Signed-off-by: karan --- src/components/organization/Dashboard.tsx | 466 +++++++++++----------- tailwind.config.cjs | 1 + 2 files changed, 236 insertions(+), 231 deletions(-) diff --git a/src/components/organization/Dashboard.tsx b/src/components/organization/Dashboard.tsx index 2da9e62bf..fad946d4d 100644 --- a/src/components/organization/Dashboard.tsx +++ b/src/components/organization/Dashboard.tsx @@ -1,4 +1,4 @@ -import type { OrgDashboard, Organisation } from './interfaces' +import type { OrgDashboard, Organisation } from './interfaces'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { getOrgDashboard, getOrganizationById } from '../../api/organization'; import { useEffect, useState } from 'react'; @@ -20,233 +20,237 @@ import { pathRoutes } from '../../config/pathRoutes'; import DashboardCard from '../../commonComponents/DashboardCard'; const Dashboard = () => { - const [orgData, setOrgData] = useState(null); - - const [walletStatus, setWalletStatus] = useState(false); - - const [orgDashboard, setOrgDashboard] = useState(null) - const [success, setSuccess] = useState(null); - const [failure, setFailure] = useState(null) - - const [loading, setLoading] = useState(true) - const [userRoles, setUserRoles] = useState([]) - - const [openModal, setOpenModal] = useState(false); - const props = { openModal, setOpenModal }; - - - const EditOrgDetails = () => { - props.setOpenModal(true) - } - - - const updateOrganizationData = (updatedData: Organisation) => { - setOrgData(updatedData); - }; - - const getUserRoles = async () => { - const orgRoles = await getFromLocalStorage(storageKeys.ORG_ROLES) - const roles = orgRoles.split(',') - setUserRoles(roles) - } - - useEffect(() => { - getUserRoles() - }, []) - - - - const fetchOrganizationDetails = async () => { - - setLoading(true) - - const orgId = await getFromLocalStorage(storageKeys.ORG_ID) - - const response = await getOrganizationById(orgId as string); - - const { data } = response as AxiosResponse - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - - if (data?.data?.org_agents && data?.data?.org_agents?.length > 0) { - setWalletStatus(true) - } - setOrgData(data?.data) - } else { - setFailure(response as string) - } - setLoading(false) - - } - - const fetchOrganizationDashboard = async () => { - - setLoading(true) - - const orgId = await getFromLocalStorage(storageKeys.ORG_ID) - - const response = await getOrgDashboard(orgId as string); - - const { data } = response as AxiosResponse - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setOrgDashboard(data?.data) - - } else { - setFailure(response as string) - } - setLoading(false) - - } - - useEffect(() => { - fetchOrganizationDetails(); - fetchOrganizationDashboard() - }, []) - - useEffect(() => { - setTimeout(() => { - setSuccess(null) - setFailure(null) - }, 3000); - }, [success !== null, failure !== null]) - - - - const redirectDashboardInvitations = () => { - window.location.href = '/organizations/invitations' - } - - const setWalletSpinupStatus = (status: boolean) => { - setSuccess('Wallet created successfully') - fetchOrganizationDetails() - } - - const redirectOrgUsers = () => { - window.location.href = pathRoutes.organizations.users - } - - - return ( -
-
- -
-
-
- -
- -
- {(orgData?.logoUrl) ? : } -
- {orgData ? -
-

- {orgData?.name} -

- -

- {orgData?.description} -

- -

- Profile view : - - {orgData?.publicProfile ? " Public" : " Private"} - -

- -
- : - - } -
- - { - (userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) - &&
- -
- } - - { - throw new Error('Function not implemented.'); - }} - - /> - - - -
- -
-
- - - { - if (walletStatus) { - window.location.href = pathRoutes.organizations.schemas; - } - }} /> - -
-
- - { - (success || failure) && - setFailure(null)} - > - -

- {success || failure} -

-
-
- } - { - loading - ? (
- -
) - : walletStatus === true - ? () - : ((userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) - && setWalletSpinupStatus(flag)} />) - - - } - -
-
- ) - -} - -export default Dashboard + const [orgData, setOrgData] = useState(null); + + const [walletStatus, setWalletStatus] = useState(false); + + const [orgDashboard, setOrgDashboard] = useState(null); + const [success, setSuccess] = useState(null); + const [failure, setFailure] = useState(null); + + const [loading, setLoading] = useState(true); + const [userRoles, setUserRoles] = useState([]); + + const [openModal, setOpenModal] = useState(false); + const props = { openModal, setOpenModal }; + + const EditOrgDetails = () => { + props.setOpenModal(true); + }; + + const updateOrganizationData = (updatedData: Organisation) => { + setOrgData(updatedData); + }; + + const getUserRoles = async () => { + const orgRoles = await getFromLocalStorage(storageKeys.ORG_ROLES); + const roles = orgRoles.split(','); + setUserRoles(roles); + }; + + useEffect(() => { + getUserRoles(); + }, []); + + const fetchOrganizationDetails = async () => { + setLoading(true); + + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + + const response = await getOrganizationById(orgId as string); + + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (data?.data?.org_agents && data?.data?.org_agents?.length > 0) { + setWalletStatus(true); + } + setOrgData(data?.data); + } else { + setFailure(response as string); + } + setLoading(false); + }; + + const fetchOrganizationDashboard = async () => { + setLoading(true); + + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + + const response = await getOrgDashboard(orgId as string); + + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setOrgDashboard(data?.data); + } else { + setFailure(response as string); + } + setLoading(false); + }; + + useEffect(() => { + fetchOrganizationDetails(); + fetchOrganizationDashboard(); + }, []); + + useEffect(() => { + setTimeout(() => { + setSuccess(null); + setFailure(null); + }, 3000); + }, [success !== null, failure !== null]); + + const redirectDashboardInvitations = () => { + window.location.href = '/organizations/invitations'; + }; + + const setWalletSpinupStatus = (status: boolean) => { + setSuccess('Wallet created successfully'); + fetchOrganizationDetails(); + }; + + const redirectOrgUsers = () => { + window.location.href = pathRoutes.organizations.users; + }; + + return ( +
+
+ +
+
+
+
+
+
+ {orgData?.logoUrl ? ( + + ) : ( + + )} +
+
+ {orgData ? ( +
+

+ {orgData?.name} +

+ +

+ {orgData?.description} +

+ +

+ Profile view : + + {orgData?.publicProfile ? ' Public' : ' Private'} + +

+
+ ) : ( + + )} +
+
+ + {(userRoles.includes(Roles.OWNER) || + userRoles.includes(Roles.ADMIN)) && ( +
+ +
+ )} +
+ + { + throw new Error('Function not implemented.'); + }} + /> +
+ +
+
+ + + { + if (walletStatus) { + window.location.href = pathRoutes.organizations.schemas; + } + }} + /> + +
+
+ + {(success || failure) && ( + setFailure(null)} + > + +

{success || failure}

+
+
+ )} + {loading ? ( +
+ +
+ ) : walletStatus === true ? ( + + ) : ( + (userRoles.includes(Roles.OWNER) || + userRoles.includes(Roles.ADMIN)) && ( + + setWalletSpinupStatus(flag) + } + /> + ) + )} +
+
+ ); +}; + +export default Dashboard; diff --git a/tailwind.config.cjs b/tailwind.config.cjs index ae14bffcf..4e98f1352 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -105,6 +105,7 @@ module.exports = { width: { '100/22rem': 'calc(100% - 26rem)', '100/6rem': 'calc(100% - 6rem)', + '100/12rem': 'calc(100% - 12rem)', }, height: { '100/15rem': 'calc(100vh - 15rem)' From 81695737e97ee5a7b06fd9656954f95088957a0a Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 11 Jan 2024 18:11:58 +0530 Subject: [PATCH 025/303] fix: connection list on focus Signed-off-by: karan --- src/components/Issuance/ConnectionList.tsx | 2 +- src/components/Verification/ConnectionList.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index 7791cba83..60a0493f2 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -81,7 +81,7 @@ const ConnectionList = (props: { ); }} value="" - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" + className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" />
), diff --git a/src/components/Verification/ConnectionList.tsx b/src/components/Verification/ConnectionList.tsx index 7fb0577fe..66a32da9d 100644 --- a/src/components/Verification/ConnectionList.tsx +++ b/src/components/Verification/ConnectionList.tsx @@ -95,7 +95,7 @@ const ConnectionList = (props: { ); }} value="" - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" + className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" />
), From 6bf8763ea4eba05a73bb81acfa835f67a325852c Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 11 Jan 2024 19:44:12 +0530 Subject: [PATCH 026/303] fix: sonar lint issue Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 103 ++++++++++---------------- 1 file changed, 40 insertions(+), 63 deletions(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 59d4bf88b..5991df272 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -37,6 +37,7 @@ interface ISchema { } interface ICredDef { + schemaLedgerId: string; tag: string; credentialDefinition: string; schemaVersion: string; @@ -173,7 +174,7 @@ const UserDashBoard = () => { } setLoading(false); }; - + const checkOrgId = async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); if (orgId) { @@ -230,10 +231,10 @@ const UserDashBoard = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setEcoCount(data?.data?.totalCount); + setEcoCount(data?.data?.totalCount); const ecosystemData = data?.data?.ecosystemDetails.filter( (ecosystem: Organisation, index: number) => index < 3, - ); + ); if (ecosystemData) { setEcosystemList(ecosystemData); } else { @@ -340,6 +341,36 @@ const UserDashBoard = () => { window.location.href = pathRoutes.ecosystem.dashboard; }; + const ToolTipData = () => { + return ( +
+

What is ecosystem?

Contacts are people or + organizations you've
+ interacted with. +
+ You're connected over a secure and private +
line that no one but you or them can see. +
Nothing is shared without your permission. +
You can: +
+
    +
  • Direct message your Contacts
  • +
  • Get offered new credentials
  • +
  • + Get notified of updates to your credentials
    + issued by them +
  • +
  • + Request for information from your Contact
    + or they request information from you +
  • +
+ You can always remove Contacts at any
+ time from your Contacts list. +
+ ); + }; + return (
@@ -436,33 +467,7 @@ const UserDashBoard = () => { Organizations{' '}

-

What is organisation?

{' '} - Contacts are people or organizations you've
- interacted with. -
- You're connected over a secure and private -
line that no one but you or them can see. -
Nothing is shared without your permission. -
You can: -
-
    -
  • Direct message your Contacts
  • -
  • Get offered new credentials
  • -
  • - Get notified of updates to your credentials
    - issued by them -
  • -
  • - Request for information from your Contact
    - or they request information from you -
  • -
- You can always remove Contacts at any
- time from your Contacts list. -
- } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -483,7 +488,7 @@ const UserDashBoard = () => {
- {orgCount ? orgCount : 0} + {orgCount ?? 0}
@@ -737,7 +742,7 @@ const UserDashBoard = () => {
- {schemaCount ? schemaCount : 0} + {schemaCount ?? 0}
@@ -813,33 +818,7 @@ const UserDashBoard = () => { Ecosystems{' '}

-

What is ecosystem?

Contacts - are people or organizations you've
- interacted with. -
- You're connected over a secure and private -
line that no one but you or them can see. -
Nothing is shared without your permission. -
You can: -
-
    -
  • Direct message your Contacts
  • -
  • Get offered new credentials
  • -
  • - Get notified of updates to your credentials
    - issued by them -
  • -
  • - Request for information from your Contact
    - or they request information from you -
  • -
- You can always remove Contacts at any
- time from your Contacts list. -
- } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -860,7 +839,7 @@ const UserDashBoard = () => {
- {ecoCount ? ecoCount : 0} + {ecoCount ?? 0}
@@ -876,8 +855,6 @@ const UserDashBoard = () => { className="flex justify-between w-full mt-2 items-center" key={ecosystem?.id} > - <>{console.log("ecosystem1111",ecosystem) - }
goToEcoDashboard(ecosystem?.id)} @@ -974,7 +951,7 @@ const UserDashBoard = () => {
- {credDefCount ? credDefCount : 0} + {credDefCount ?? 0}
From 2aae5d902ca40091a87021b010a20a13a44cd2fb Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 12 Jan 2024 11:53:34 +0530 Subject: [PATCH 027/303] fix: sonar lint issue Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 5991df272..578cce061 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -508,7 +508,7 @@ const UserDashBoard = () => { className="flex justify-between w-full mt-2 items-center" key={org?.id} > -
goToOrgDashboard(org?.id, org?.roles) @@ -538,7 +538,7 @@ const UserDashBoard = () => { {org?.name} -
+
{ className="flex justify-between w-full mt-4 items-center" key={schema?.id} > -
goToSchemaCredDef(schema?.schemaLedgerId) @@ -773,7 +773,7 @@ const UserDashBoard = () => { {schema?.name} -
+
v.{schema?.version}
@@ -855,7 +855,7 @@ const UserDashBoard = () => { className="flex justify-between w-full mt-2 items-center" key={ecosystem?.id} > -
goToEcoDashboard(ecosystem?.id)} > @@ -883,7 +883,7 @@ const UserDashBoard = () => { {ecosystem?.name} -
+ ); })} @@ -968,7 +968,7 @@ const UserDashBoard = () => { className="flex justify-between w-full mt-4 items-center" key={cred?.id} > -
goToCredDef(cred?.schemaLedgerId)} > @@ -980,7 +980,7 @@ const UserDashBoard = () => { {cred?.tag} -
+
{cred?.credentialDefinitionId.slice(0, 8)}... From f5097b84133465392b02c8500bfac2bf2e8c780e Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 12 Jan 2024 12:31:03 +0530 Subject: [PATCH 028/303] refactor: user profile Signed-off-by: karan --- src/app/NavBarSidebar.astro | 114 ++++++++++++++++--------- src/components/Profile/DisplayUser.tsx | 8 +- src/components/SignOutButton/index.tsx | 81 +++++++++++------- 3 files changed, 128 insertions(+), 75 deletions(-) diff --git a/src/app/NavBarSidebar.astro b/src/app/NavBarSidebar.astro index 1f55009d7..833f48332 100644 --- a/src/app/NavBarSidebar.astro +++ b/src/app/NavBarSidebar.astro @@ -13,14 +13,12 @@ import { getFromCookies } from '../api/Auth'; import { RolePermissions } from '../config/permissions'; const { hideOrgAgent } = Astro.props; -console.log(3242, hideOrgAgent) const role = getFromCookies(Astro.cookies, 'role'); const permittedPages = RolePermissions.find( (item) => item.role === role, )?.pages; - ---
); }; diff --git a/src/components/Verification/ConnectionList.tsx b/src/components/Verification/ConnectionList.tsx index 66a32da9d..654410c6c 100644 --- a/src/components/Verification/ConnectionList.tsx +++ b/src/components/Verification/ConnectionList.tsx @@ -6,15 +6,13 @@ import { IConnectionListAPIParameter, getConnectionsByOrg, } from '../../api/connection'; -import DataTable from '../../commonComponents/datatable'; import type { TableData } from '../../commonComponents/datatable/interface'; import { apiStatusCodes } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; -import SearchInput from '../SearchInput'; -import { Pagination } from 'flowbite-react'; import type { IConnectionList } from './interface'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { itemPerPage: 10, @@ -32,12 +30,16 @@ const ConnectionList = (props: { const [selectedConnectionList, setSelectedConnectionList] = useState< TableData[] >([]); - const [loading, setLoading] = useState(false); const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [totalItem, setTotalItem] = useState(0); const [error, setError] = useState(null); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); useEffect(() => { getConnectionsVerification(listAPIParameter); @@ -61,6 +63,13 @@ const ConnectionList = (props: { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setTotalItem(data?.data.totalItems); + const { totalItems, nextPage, lastPage } = data.data; + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, + }); const connections = data?.data?.data?.map( (ele: IConnectionList) => { const userName = ele?.theirLabel @@ -162,6 +171,21 @@ const ConnectionList = (props: { } }; + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + + + const refreshPage = () => { + setSelectedConnectionList([]); + getConnectionsVerification(listAPIParameter); + }; + + useEffect(() => { props.selectConnection(selectedConnectionList); }, [selectedConnectionList]); @@ -178,9 +202,6 @@ const ConnectionList = (props: {

Connection List

-
- -
-
- -
- {Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && ( -
- { - setListAPIParameter((prevState) => ({ - ...prevState, - page, - })); - }} - totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} - /> -
- )} + { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + pageInfo={pageInfo} + searchSortByValue={searchSortByValue} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={true} + isPagination={true} + message={'No Connections'} + discription={"You don't have any connections yet"} + >
); }; From 4c72491f0084a0f256fd9fa45195d3449e7da088 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 15 Jan 2024 13:39:28 +0530 Subject: [PATCH 035/303] implemented debouncing Signed-off-by: karan --- src/components/Issuance/ConnectionList.tsx | 18 ++++++++++++++---- src/components/Verification/ConnectionList.tsx | 15 ++++++++++++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index df754d8ae..d4c06074c 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -12,7 +12,7 @@ import { AlertComponent } from '../AlertComponent'; import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; import type { IConnectionList } from './interface' -import SortDataTable from '../../commonComponents/datatable/SortDataTable'; +import NewDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { @@ -42,7 +42,17 @@ const ConnectionList = (props: { }); useEffect(() => { - getConnections(listAPIParameter); + let getData: NodeJS.Timeout; + + if (listAPIParameter?.search?.length >= 1) { + getData = setTimeout(() => { + getConnections(listAPIParameter); + }, 1000); + return () => clearTimeout(getData); + } else { + getConnections(listAPIParameter); + } + return () => clearTimeout(getData); }, [listAPIParameter]); const getConnections = async (apiParameter: IConnectionListAPIParameter) => { @@ -212,7 +222,7 @@ const ConnectionList = (props: { setError(null); }} /> - + >
); }; diff --git a/src/components/Verification/ConnectionList.tsx b/src/components/Verification/ConnectionList.tsx index 654410c6c..3d2e68d7f 100644 --- a/src/components/Verification/ConnectionList.tsx +++ b/src/components/Verification/ConnectionList.tsx @@ -42,10 +42,19 @@ const ConnectionList = (props: { }); useEffect(() => { - getConnectionsVerification(listAPIParameter); - }, [listAPIParameter]); + let getData: NodeJS.Timeout; - //onChange of Search input text + if (listAPIParameter?.search?.length >= 1) { + getData = setTimeout(() => { + getConnectionsVerification(listAPIParameter); + }, 1000); + return () => clearTimeout(getData); + } else { + getConnectionsVerification(listAPIParameter); + } + return () => clearTimeout(getData); + }, [listAPIParameter]); + const searchInputChange = (e: ChangeEvent) => { setListAPIParameter({ ...listAPIParameter, From 96bf6950faaacdb7e5a164ed4ecdad2f5e4f0e96 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 15 Jan 2024 14:50:09 +0530 Subject: [PATCH 036/303] fix: sonar lint issues Signed-off-by: karan --- src/components/Issuance/ConnectionList.tsx | 106 ++++++++++----------- 1 file changed, 50 insertions(+), 56 deletions(-) diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index d4c06074c..3db359d0a 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -11,10 +11,9 @@ import { apiStatusCodes } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; -import type { IConnectionList } from './interface' +import type { IConnectionList } from './interface'; import NewDataTable from '../../commonComponents/datatable/SortDataTable'; - const initialPageState = { itemPerPage: 10, page: 1, @@ -70,54 +69,50 @@ const ConnectionList = (props: { nextPage: nextPage, lastPage: lastPage, }); - const connections = data?.data?.data?.map( - (ele: IConnectionList) => { - const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; - const connectionId = ele.connectionId - ? ele.connectionId - : 'Not available'; - const createdOn = ele?.createDateTime - ? ele?.createDateTime - : 'Not available'; - return { - data: [ - { - data: ( -
- , - ) => { - const inputElement = event.target as HTMLInputElement; - selectConnection( - userName, - connectionId, - inputElement.checked, - ); - }} - value="" - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" - /> -
- ), - }, - { data: userName }, - { data: connectionId }, - { - data: ( - - {' '} - {dateConversion(createdOn)}{' '} - - ), - }, - ], - }; - }, - ); + const connections = data?.data?.data?.map((ele: IConnectionList) => { + const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; + const connectionId = ele.connectionId + ? ele.connectionId + : 'Not available'; + const createdOn = ele?.createDateTime + ? ele?.createDateTime + : 'Not available'; + return { + data: [ + { + data: ( +
+ ) => { + const inputElement = event.target as HTMLInputElement; + selectConnection( + userName, + connectionId, + inputElement.checked, + ); + }} + value="" + className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" + /> +
+ ), + }, + { data: userName }, + { data: connectionId }, + { + data: ( + + {' '} + {dateConversion(createdOn)}{' '} + + ), + }, + ], + }; + }); setConnectionList(connections); setError(null); @@ -195,9 +190,8 @@ const ConnectionList = (props: { }); }; - const refreshPage = () => { - setSelectedConnectionList([]) + setSelectedConnectionList([]); getConnections(listAPIParameter); }; @@ -223,6 +217,10 @@ const ConnectionList = (props: { }} /> From 8084f9753b832d0409db61f04da550ac52c9d7b4 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 15 Jan 2024 14:53:18 +0530 Subject: [PATCH 037/303] fix: sonar lint issues Signed-off-by: karan --- src/components/Issuance/ConnectionList.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index 3db359d0a..126cb70a0 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -61,8 +61,8 @@ const ConnectionList = (props: { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setTotalItem(data?.data.totalItems); const { totalItems, nextPage, lastPage } = data.data; + setTotalItem(data?.data.totalItems); setPageInfo({ totalItem: totalItems, @@ -70,13 +70,13 @@ const ConnectionList = (props: { lastPage: lastPage, }); const connections = data?.data?.data?.map((ele: IConnectionList) => { - const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; - const connectionId = ele.connectionId - ? ele.connectionId - : 'Not available'; const createdOn = ele?.createDateTime - ? ele?.createDateTime - : 'Not available'; + ? ele?.createDateTime + : 'Not available'; + const connectionId = ele.connectionId + ? ele.connectionId + : 'Not available'; + const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; return { data: [ { From f11e3650d9daa1e12d0fee9b9590de818a5255e1 Mon Sep 17 00:00:00 2001 From: Sheetal-ayanworks Date: Mon, 15 Jan 2024 16:48:41 +0530 Subject: [PATCH 038/303] Implement a QA Git Action workflow file to deploy the QA environment. Signed-off-by: Sheetal-ayanworks --- .github/workflows/deploy-qa.yml | 33 + pnpm-lock.yaml | 6805 +++++++++++++++++++++++++++++++ shell.sh | 48 + 3 files changed, 6886 insertions(+) create mode 100644 .github/workflows/deploy-qa.yml create mode 100644 pnpm-lock.yaml create mode 100644 shell.sh diff --git a/.github/workflows/deploy-qa.yml b/.github/workflows/deploy-qa.yml new file mode 100644 index 000000000..682462c48 --- /dev/null +++ b/.github/workflows/deploy-qa.yml @@ -0,0 +1,33 @@ +name: Deploy develop branch to Deno +on: + push: + branches: qa + pull_request: + branches: qa + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest + permissions: + id-token: write # Needed for auth with Deno Deploy + contents: read # Needed to clone the repository + + steps: + - name: Clone repository + uses: actions/checkout@v3 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: Build step + run: npm install && npm run build # 📝 Update the build command(s) + + - name: Upload to Deno Deploy + uses: denoland/deployctl@v1 + with: + project: "credebl-studio-qa" # Project name in Deno Deploy + entrypoint: "server/entry.mjs" # 📝 Update the entrypoint + root: "dist" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 000000000..57c0470e6 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,6805 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@astrojs/deno': + specifier: ^4.2.0 + version: 4.2.0(astro@2.9.0) + '@astrojs/react': + specifier: ^2.2.1 + version: 2.2.1(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) + '@astrojs/sitemap': + specifier: ^1.4.0 + version: 1.4.0 + '@astrojs/tailwind': + specifier: ^4.0.0 + version: 4.0.0(astro@2.9.0)(tailwindcss@3.3.3) + '@babel/runtime': + specifier: ^7.22.6 + version: 7.22.6 + '@babel/runtime-corejs3': + specifier: ^7.22.6 + version: 7.22.6 + '@faker-js/faker': + specifier: ^7.6.0 + version: 7.6.0 + '@simplewebauthn/browser': + specifier: ^7.2.0 + version: 7.2.0 + '@supabase/supabase-js': + specifier: ^2.31.0 + version: 2.31.0 + '@tanstack/react-form': + specifier: ^0.0.11 + version: 0.0.11(react-dom@18.2.0)(react@18.2.0) + '@types/react': + specifier: ^18.2.14 + version: 18.2.14 + '@types/react-dom': + specifier: ^18.2.6 + version: 18.2.6 + apexcharts: + specifier: ^3.37.2 + version: 3.37.2 + astro: + specifier: ^2.9.0 + version: 2.9.0 + axios: + specifier: ^1.4.0 + version: 1.4.0 + cookie: + specifier: ^0.5.0 + version: 0.5.0 + crypto-js: + specifier: ^4.1.1 + version: 4.1.1 + dom-to-image: + specifier: ^2.6.0 + version: 2.6.0 + downloadjs: + specifier: ^1.4.7 + version: 1.4.7 + flowbite: + specifier: ^1.7.0 + version: 1.7.0 + flowbite-react: + specifier: ^0.4.10 + version: 0.4.10(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.3) + flowbite-typography: + specifier: ^1.0.3 + version: 1.0.3(tailwindcss@3.3.3) + formik: + specifier: ^2.4.5 + version: 2.4.5(react@18.2.0) + html2canvas: + specifier: ^1.4.1 + version: 1.4.1 + i: + specifier: ^0.3.7 + version: 0.3.7 + moment: + specifier: ^2.29.4 + version: 2.29.4 + nanoid: + specifier: ^4.0.2 + version: 4.0.2 + npm: + specifier: ^9.8.0 + version: 9.8.0 + qrcode.react: + specifier: ^3.1.0 + version: 3.1.0(react@18.2.0) + react: + specifier: ^18.2.0 + version: 18.2.0 + react-avatar: + specifier: ^5.0.3 + version: 5.0.3(@babel/runtime@7.22.6)(core-js-pure@3.33.1)(prop-types@15.8.1)(react@18.2.0) + react-dom: + specifier: ^18.2.0 + version: 18.2.0(react@18.2.0) + react-helmet: + specifier: ^6.1.0 + version: 6.1.0(react@18.2.0) + react-icons: + specifier: ^4.10.1 + version: 4.10.1(react@18.2.0) + react-qr-code: + specifier: ^2.0.11 + version: 2.0.11(react@18.2.0) + react-select: + specifier: ^5.8.0 + version: 5.8.0(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0) + react-toastify: + specifier: ^9.1.3 + version: 9.1.3(react-dom@18.2.0)(react@18.2.0) + secure-random-password: + specifier: ^0.2.3 + version: 0.2.3 + shiki: + specifier: ^0.14.1 + version: 0.14.1 + socket.io-client: + specifier: ^4.6.2 + version: 4.6.2 + tailwind-scrollbar: + specifier: ^3.0.4 + version: 3.0.4(tailwindcss@3.3.3) + tailwindcss: + specifier: ^3.3.3 + version: 3.3.3 + uuid: + specifier: ^9.0.1 + version: 9.0.1 + yup: + specifier: ^1.2.0 + version: 1.2.0 + +devDependencies: + '@types/cookie': + specifier: ^0.5.1 + version: 0.5.1 + '@types/crypto-js': + specifier: ^4.1.1 + version: 4.1.1 + '@types/dom-to-image': + specifier: ^2.6.4 + version: 2.6.4 + '@types/downloadjs': + specifier: ^1.4.3 + version: 1.4.3 + '@types/eslint': + specifier: ^8.21.1 + version: 8.21.1 + '@types/secure-random-password': + specifier: ^0.2.1 + version: 0.2.1 + '@types/uuid': + specifier: ^9.0.3 + version: 9.0.3 + '@typescript-eslint/eslint-plugin': + specifier: ^5.54.1 + version: 5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/parser': + specifier: ^5.54.1 + version: 5.54.1(eslint@8.35.0)(typescript@5.2.2) + astro-eslint-parser: + specifier: ^0.11.0 + version: 0.11.0 + autoprefixer: + specifier: ^10.4.14 + version: 10.4.14(postcss@8.4.25) + babel-eslint: + specifier: ^10.1.0 + version: 10.1.0(eslint@8.35.0) + eslint: + specifier: ^8.35.0 + version: 8.35.0 + eslint-config-airbnb-base: + specifier: ^15.0.0 + version: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.35.0) + eslint-config-airbnb-typescript: + specifier: ^17.0.0 + version: 17.0.0(@typescript-eslint/eslint-plugin@5.54.1)(@typescript-eslint/parser@5.54.1)(eslint-plugin-import@2.27.5)(eslint@8.35.0) + eslint-config-prettier: + specifier: ^8.7.0 + version: 8.7.0(eslint@8.35.0) + eslint-import-resolver-typescript: + specifier: ^3.5.3 + version: 3.5.3(eslint-plugin-import@2.27.5)(eslint@8.35.0) + eslint-plugin-astro: + specifier: ^0.23.0 + version: 0.23.0(eslint@8.35.0) + eslint-plugin-import: + specifier: ^2.27.5 + version: 2.27.5(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0) + eslint-plugin-prettier: + specifier: ^4.2.1 + version: 4.2.1(eslint-config-prettier@8.7.0)(eslint@8.35.0)(prettier@3.0.3) + eslint-plugin-tsdoc: + specifier: ^0.2.17 + version: 0.2.17 + postcss: + specifier: ^8.4.25 + version: 8.4.25 + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@alloc/quick-lru@5.2.0: + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + dev: false + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: false + + /@astrojs/compiler@1.8.2: + resolution: {integrity: sha512-o/ObKgtMzl8SlpIdzaxFnt7SATKPxu4oIP/1NL+HDJRzxfJcAkOTAb/ZKMRyULbz4q+1t2/DAebs2Z1QairkZw==} + + /@astrojs/deno@4.2.0(astro@2.9.0): + resolution: {integrity: sha512-g32QsBUQGJXeZ7fcJui77mI1XDEWgscbOKiNpCpOjiyjMxZIG3n3NNiWlsHuTvk0to8tUD3+V+inhnQ3hoXr7w==} + peerDependencies: + astro: ^2.6.5 + dependencies: + astro: 2.9.0 + esbuild: 0.15.18 + dev: false + + /@astrojs/internal-helpers@0.1.2: + resolution: {integrity: sha512-YXLk1CUDdC9P5bjFZcGjz+cE/ZDceXObDTXn/GCID4r8LjThuexxi+dlJqukmUpkSItzQqgzfWnrPLxSFPejdA==} + dev: false + + /@astrojs/language-server@1.0.8: + resolution: {integrity: sha512-gssRxLGb8XnvKpqSzrDW5jdzdFnXD7eBXVkPCkkt2hv7Qzb+SAzv6hVgMok3jDCxpR1aeB+XNd9Qszj2h29iog==} + hasBin: true + dependencies: + '@astrojs/compiler': 1.8.2 + '@jridgewell/trace-mapping': 0.3.20 + '@vscode/emmet-helper': 2.9.2 + events: 3.3.0 + prettier: 2.8.8 + prettier-plugin-astro: 0.9.1 + vscode-css-languageservice: 6.2.10 + vscode-html-languageservice: 5.1.0 + vscode-languageserver: 8.1.0 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.11 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + dev: false + + /@astrojs/markdown-remark@2.2.1(astro@2.9.0): + resolution: {integrity: sha512-VF0HRv4GpC1XEMLnsKf6jth7JSmlt9qpqP0josQgA2eSpCIAC/Et+y94mgdBIZVBYH/yFnMoIxgKVe93xfO2GA==} + peerDependencies: + astro: ^2.5.0 + dependencies: + '@astrojs/prism': 2.1.2 + astro: 2.9.0 + github-slugger: 1.5.0 + import-meta-resolve: 2.2.2 + rehype-raw: 6.1.1 + rehype-stringify: 9.0.4 + remark-gfm: 3.0.1 + remark-parse: 10.0.2 + remark-rehype: 10.1.0 + remark-smartypants: 2.0.0 + shiki: 0.14.1 + unified: 10.1.2 + unist-util-visit: 4.1.2 + vfile: 5.3.7 + transitivePeerDependencies: + - supports-color + dev: false + + /@astrojs/prism@2.1.2: + resolution: {integrity: sha512-3antim1gb34689GHRQFJ88JEo93HuZKQBnmxDT5W/nxiNz1p/iRxnCTEhIbJhqMOTRbbo5h2ldm5qSxx+TMFQA==} + engines: {node: '>=16.12.0'} + dependencies: + prismjs: 1.29.0 + dev: false + + /@astrojs/react@2.2.1(@types/react-dom@18.2.6)(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-nq5Zr8iWdwjSp5fh1NReaCplwsnL4w5PXAY5XWu1jE/frxEfF/ycGHrrhwWW0uJHX9G+kUtmQLR0GBhlR4FmAw==} + engines: {node: '>=16.12.0'} + peerDependencies: + '@types/react': ^17.0.50 || ^18.0.21 + '@types/react-dom': ^17.0.17 || ^18.0.6 + react: ^17.0.2 || ^18.0.0 + react-dom: ^17.0.2 || ^18.0.0 + dependencies: + '@babel/core': 7.23.2 + '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.2) + '@types/react': 18.2.14 + '@types/react-dom': 18.2.6 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + transitivePeerDependencies: + - supports-color + dev: false + + /@astrojs/sitemap@1.4.0: + resolution: {integrity: sha512-uTK77kcg7iTiik+u7rTGG6vK4ZWTfYMaVnFndOVQrLzaE5xivmQgIbVLtlN+xRcME5n/m6vYQFJmogFR+elGCw==} + dependencies: + sitemap: 7.1.1 + zod: 3.22.4 + dev: false + + /@astrojs/tailwind@4.0.0(astro@2.9.0)(tailwindcss@3.3.3): + resolution: {integrity: sha512-HmCAXFFes7MUBt5ihdfH1goa8QyGkHejIpz6Z4XBKK9VNYY9G2E3brCn8+pNn5zAOzcwl3FYcuH2AiOa/NGoMQ==} + peerDependencies: + astro: ^2.6.5 + tailwindcss: ^3.0.24 + dependencies: + astro: 2.9.0 + autoprefixer: 10.4.14(postcss@8.4.25) + postcss: 8.4.25 + postcss-load-config: 4.0.1(postcss@8.4.25) + tailwindcss: 3.3.3 + transitivePeerDependencies: + - ts-node + dev: false + + /@astrojs/telemetry@2.1.1: + resolution: {integrity: sha512-4pRhyeQr0MLB5PKYgkdu+YE8sSpMbHL8dUuslBWBIdgcYjtD1SufPMBI8pgXJ+xlwrQJHKKfK2X1KonHYuOS9A==} + engines: {node: '>=16.12.0'} + dependencies: + ci-info: 3.9.0 + debug: 4.3.4 + dlv: 1.1.3 + dset: 3.1.2 + is-docker: 3.0.0 + is-wsl: 2.2.0 + undici: 5.26.5 + which-pm-runs: 1.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@astrojs/webapi@2.2.0: + resolution: {integrity: sha512-mHAOApWyjqSe5AQMOUD9rsZJqbMQqe3Wosb1a40JV6Okvyxj1G6GTlthwYadWCymq/lbgwh0PLiY8Fr4eFxtuQ==} + dependencies: + undici: 5.26.5 + dev: false + + /@babel/code-frame@7.22.13: + resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.20 + chalk: 2.4.2 + + /@babel/compat-data@7.23.2: + resolution: {integrity: sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/core@7.23.2: + resolution: {integrity: sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.0 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.2) + '@babel/helpers': 7.23.2 + '@babel/parser': 7.23.0 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.2 + '@babel/types': 7.23.0 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/generator@7.23.0: + resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + jsesc: 2.5.2 + + /@babel/helper-annotate-as-pure@7.22.5: + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-compilation-targets@7.22.15: + resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.2 + '@babel/helper-validator-option': 7.22.15 + browserslist: 4.22.1 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: false + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.0 + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-module-transforms@7.23.0(@babel/core@7.23.2): + resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: false + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + + /@babel/helper-string-parser@7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-option@7.22.15: + resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helpers@7.23.2: + resolution: {integrity: sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.2 + '@babel/types': 7.23.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/highlight@7.22.20: + resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + + /@babel/parser@7.23.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.0 + + /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.2): + resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.23.2): + resolution: {integrity: sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.2 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.2) + '@babel/types': 7.23.0 + dev: false + + /@babel/runtime-corejs3@7.22.6: + resolution: {integrity: sha512-M+37LLIRBTEVjktoJjbw4KVhupF0U/3PYUCbBwgAd9k17hoKhRu1n935QiG7Tuxv0LJOMrb2vuKEeYUlv0iyiw==} + engines: {node: '>=6.9.0'} + dependencies: + core-js-pure: 3.33.1 + regenerator-runtime: 0.13.11 + dev: false + + /@babel/runtime@7.22.6: + resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: false + + /@babel/template@7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + + /@babel/traverse@7.23.2: + resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.0 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + /@babel/types@7.23.0: + resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + + /@emmetio/abbreviation@2.3.3: + resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} + dependencies: + '@emmetio/scanner': 1.0.4 + dev: false + + /@emmetio/css-abbreviation@2.1.8: + resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==} + dependencies: + '@emmetio/scanner': 1.0.4 + dev: false + + /@emmetio/scanner@1.0.4: + resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} + dev: false + + /@emotion/babel-plugin@11.11.0: + resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} + dependencies: + '@babel/helper-module-imports': 7.22.15 + '@babel/runtime': 7.22.6 + '@emotion/hash': 0.9.1 + '@emotion/memoize': 0.8.1 + '@emotion/serialize': 1.1.3 + babel-plugin-macros: 3.1.0 + convert-source-map: 1.9.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.2.0 + dev: false + + /@emotion/cache@11.11.0: + resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==} + dependencies: + '@emotion/memoize': 0.8.1 + '@emotion/sheet': 1.2.2 + '@emotion/utils': 1.2.1 + '@emotion/weak-memoize': 0.3.1 + stylis: 4.2.0 + dev: false + + /@emotion/hash@0.9.1: + resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + dev: false + + /@emotion/memoize@0.8.1: + resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} + dev: false + + /@emotion/react@11.11.3(@types/react@18.2.14)(react@18.2.0): + resolution: {integrity: sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==} + peerDependencies: + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.6 + '@emotion/babel-plugin': 11.11.0 + '@emotion/cache': 11.11.0 + '@emotion/serialize': 1.1.3 + '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) + '@emotion/utils': 1.2.1 + '@emotion/weak-memoize': 0.3.1 + '@types/react': 18.2.14 + hoist-non-react-statics: 3.3.2 + react: 18.2.0 + dev: false + + /@emotion/serialize@1.1.3: + resolution: {integrity: sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==} + dependencies: + '@emotion/hash': 0.9.1 + '@emotion/memoize': 0.8.1 + '@emotion/unitless': 0.8.1 + '@emotion/utils': 1.2.1 + csstype: 3.1.2 + dev: false + + /@emotion/sheet@1.2.2: + resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} + dev: false + + /@emotion/unitless@0.8.1: + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + dev: false + + /@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.2.0): + resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} + peerDependencies: + react: '>=16.8.0' + dependencies: + react: 18.2.0 + dev: false + + /@emotion/utils@1.2.1: + resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} + dev: false + + /@emotion/weak-memoize@0.3.1: + resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} + dev: false + + /@esbuild/android-arm64@0.17.19: + resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm@0.15.18: + resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm@0.17.19: + resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-x64@0.17.19: + resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-arm64@0.17.19: + resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-x64@0.17.19: + resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-arm64@0.17.19: + resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-x64@0.17.19: + resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm64@0.17.19: + resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm@0.17.19: + resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ia32@0.17.19: + resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-loong64@0.15.18: + resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-loong64@0.17.19: + resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-mips64el@0.17.19: + resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ppc64@0.17.19: + resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-riscv64@0.17.19: + resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-s390x@0.17.19: + resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-x64@0.17.19: + resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/netbsd-x64@0.17.19: + resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/openbsd-x64@0.17.19: + resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/sunos-x64@0.17.19: + resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-arm64@0.17.19: + resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-ia32@0.17.19: + resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-x64@0.17.19: + resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@eslint/eslintrc@2.1.2: + resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.23.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.35.0: + resolution: {integrity: sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@faker-js/faker@7.6.0: + resolution: {integrity: sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==} + engines: {node: '>=14.0.0', npm: '>=6.0.0'} + dev: false + + /@fastify/busboy@2.0.0: + resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==} + engines: {node: '>=14'} + dev: false + + /@floating-ui/core@1.5.0: + resolution: {integrity: sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==} + dependencies: + '@floating-ui/utils': 0.1.6 + dev: false + + /@floating-ui/dom@1.5.3: + resolution: {integrity: sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==} + dependencies: + '@floating-ui/core': 1.5.0 + '@floating-ui/utils': 0.1.6 + dev: false + + /@floating-ui/react-dom@2.0.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.5.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@floating-ui/react@0.24.8(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-AuYeDoaR8jtUlUXtZ1IJ/6jtBkGnSpJXbGNzokBL87VDJ8opMq1Bgrc0szhK482ReQY6KZsMoZCVSb4xwalkBA==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tabbable: 6.2.0 + dev: false + + /@floating-ui/utils@0.1.6: + resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} + dev: false + + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.20 + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + + /@microsoft/tsdoc-config@0.16.2: + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + dev: true + + /@microsoft/tsdoc@0.14.2: + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + + /@pkgr/utils@2.4.2: + resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dependencies: + cross-spawn: 7.0.3 + fast-glob: 3.3.1 + is-glob: 4.0.3 + open: 9.1.0 + picocolors: 1.0.0 + tslib: 2.6.2 + + /@popperjs/core@2.11.8: + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + dev: false + + /@simplewebauthn/browser@7.2.0: + resolution: {integrity: sha512-HHIvRPpqKy0UV/BsGAmx4rQRZuZTUFYLLH65FwpSOslqHruiHx3Ql/bq7A75bjWuJ296a+4BIAq3+SPaII01TQ==} + dependencies: + '@simplewebauthn/typescript-types': 8.0.0 + dev: false + + /@simplewebauthn/typescript-types@8.0.0: + resolution: {integrity: sha512-d7Izb2H+LZJteXMkS8DmpAarD6mZdpIOu/av/yH4/u/3Pd6DKFLyBM3j8BMmUvUqpzvJvHARNrRfQYto58mtTQ==} + dev: false + + /@socket.io/component-emitter@3.1.0: + resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==} + dev: false + + /@supabase/functions-js@2.1.5: + resolution: {integrity: sha512-BNzC5XhCzzCaggJ8s53DP+WeHHGT/NfTsx2wUSSGKR2/ikLFQTBCDzMvGz/PxYMqRko/LwncQtKXGOYp1PkPaw==} + dependencies: + '@supabase/node-fetch': 2.6.14 + dev: false + + /@supabase/gotrue-js@2.57.0: + resolution: {integrity: sha512-/CcAW40aPKgp9/w9WgXVUQFg1AOdvFR687ONOMjASPBuC6FsNbKlcXp4pc+rwKNtxyxDkBbR+x7zj/8g00r/Og==} + dependencies: + '@supabase/node-fetch': 2.6.14 + dev: false + + /@supabase/node-fetch@2.6.14: + resolution: {integrity: sha512-w/Tsd22e/5fAeoxqQ4P2MX6EyF+iM6rc9kmlMVFkHuG0rAltt2TLhFbDJfemnHbtvnazWaRfy5KnFU/SYT37dQ==} + engines: {node: 4.x || >=6.0.0} + dependencies: + whatwg-url: 5.0.0 + dev: false + + /@supabase/postgrest-js@1.8.5: + resolution: {integrity: sha512-XvoqN5e5Z4TsQOYWLQYLW0HIlZtFSzwAcwiuToaSBSTpLOGCg4NaZ7au5GfBzCQJZdZPY5vk5FvwthfDsQK/Jw==} + dependencies: + '@supabase/node-fetch': 2.6.14 + dev: false + + /@supabase/realtime-js@2.8.1: + resolution: {integrity: sha512-bka5U4OeoKMdorGMPjdF30cl8n8nbhn+I9H4iySKzbN45W6AGxi7xoODnxdq/QwaDGtVyTMVbU+GVWre0QCdtw==} + dependencies: + '@supabase/node-fetch': 2.6.14 + '@types/phoenix': 1.6.3 + '@types/websocket': 1.0.8 + websocket: 1.0.34 + transitivePeerDependencies: + - supports-color + dev: false + + /@supabase/storage-js@2.5.4: + resolution: {integrity: sha512-yspHD19I9uQUgfTh0J94+/r/g6hnhdQmw6Y7OWqr/EbnL6uvicGV1i1UDkkmeUHqfF9Mbt2sLtuxRycYyKv2ew==} + dependencies: + '@supabase/node-fetch': 2.6.14 + dev: false + + /@supabase/supabase-js@2.31.0: + resolution: {integrity: sha512-W9/4s+KnSUX67wJKBn/3yLq+ieycnMzVjK3nNTLX5Wko3ypNT/081l2iFYrf+nsLQ1CiT4mA92I3dxCy6CmxTg==} + dependencies: + '@supabase/functions-js': 2.1.5 + '@supabase/gotrue-js': 2.57.0 + '@supabase/postgrest-js': 1.8.5 + '@supabase/realtime-js': 2.8.1 + '@supabase/storage-js': 2.5.4 + cross-fetch: 3.1.8 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@tanstack/form-core@0.0.11: + resolution: {integrity: sha512-Sv7b9IG0XmBoDbDe0nXrTTl9xl05TA4ir0pwr/xJwNP683CNRIzBpug3/WVzWoQVLCvRvvmo3t12N75Ip8HQNg==} + dependencies: + '@tanstack/store': 0.0.1-beta.89 + dev: false + + /@tanstack/react-form@0.0.11(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-76tyMuDVtHzWHSUSdYPIfpo06RexmSAg4dKMaBToH0yww8l1Y/PNKdoUGcmUHUUFstObm2ufw1VG2YAnsVWx8Q==} + peerDependencies: + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + '@tanstack/form-core': 0.0.11 + '@tanstack/react-store': 0.0.1-beta.85(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@tanstack/react-store@0.0.1-beta.85(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-5APLxQOHgws735Va5ndbS6aa9pIILcximTr5dQeEFRzCNqjLyJ6YHGDuqng9zLMLzCyNILmdEtpNW0tp5l/tNw==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + dependencies: + '@tanstack/store': 0.0.1-beta.85 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + + /@tanstack/store@0.0.1-beta.85: + resolution: {integrity: sha512-gUn8i4mhS7V5yRTu6NosoKuUBfw4w36JHx0rg2MJ5kAiKukISoTqlzUKKKzmVvVPL6H1xwaDGEf6bmLzLlgZEQ==} + engines: {node: '>=12'} + dev: false + + /@tanstack/store@0.0.1-beta.89: + resolution: {integrity: sha512-YW2aAhsXI4QYLXRnxZzB7MgEah91itQcWAjN3GYg1HKHxPv/11T5bL1CUCSxFLTI0f+45uNRjsmof6eqsN3ECA==} + engines: {node: '>=12'} + dev: false + + /@types/babel__core@7.20.3: + resolution: {integrity: sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==} + dependencies: + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + '@types/babel__generator': 7.6.6 + '@types/babel__template': 7.4.3 + '@types/babel__traverse': 7.20.3 + dev: false + + /@types/babel__generator@7.6.6: + resolution: {integrity: sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@types/babel__template@7.4.3: + resolution: {integrity: sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==} + dependencies: + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + dev: false + + /@types/babel__traverse@7.20.3: + resolution: {integrity: sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==} + dependencies: + '@babel/types': 7.23.0 + dev: false + + /@types/cookie@0.5.1: + resolution: {integrity: sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==} + dev: true + + /@types/crypto-js@4.1.1: + resolution: {integrity: sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==} + dev: true + + /@types/debug@4.1.10: + resolution: {integrity: sha512-tOSCru6s732pofZ+sMv9o4o3Zc+Sa8l3bxd/tweTQudFn06vAzb13ZX46Zi6m6EJ+RUbRTHvgQJ1gBtSgkaUYA==} + dependencies: + '@types/ms': 0.7.33 + dev: false + + /@types/dom-to-image@2.6.4: + resolution: {integrity: sha512-UddUdGF1qulrSDulkz3K2Ypq527MR6ixlgAzqLbxSiQ0icx0XDlIV+h4+edmjq/1dqn0KgN0xGSe1kI9t+vGuw==} + dev: true + + /@types/dom-view-transitions@1.0.3: + resolution: {integrity: sha512-1X/BUVdo9pKho8SFWVNcIz0fasBAqwcAvWGMt0Z57LUN68I4AtdrgTUXFryZW/OHUSO+9OH9KtSgCTMrzOZdRg==} + dev: false + + /@types/downloadjs@1.4.3: + resolution: {integrity: sha512-MjJepFle/tLtT2/jmDNth6ZnwWzEhm40L+olE5HKR70ISUCfgT55eqreeHldAzFLY2HDUGsn8zgyto8KygN0CA==} + dev: true + + /@types/eslint@8.21.1: + resolution: {integrity: sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==} + dependencies: + '@types/estree': 1.0.3 + '@types/json-schema': 7.0.14 + dev: true + + /@types/estree@1.0.3: + resolution: {integrity: sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==} + dev: true + + /@types/hast@2.3.7: + resolution: {integrity: sha512-EVLigw5zInURhzfXUM65eixfadfsHKomGKUakToXo84t8gGIJuTcD2xooM2See7GyQ7DRtYjhCHnSUQez8JaLw==} + dependencies: + '@types/unist': 2.0.9 + dev: false + + /@types/hoist-non-react-statics@3.3.5: + resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==} + dependencies: + '@types/react': 18.2.14 + hoist-non-react-statics: 3.3.2 + dev: false + + /@types/json-schema@7.0.14: + resolution: {integrity: sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/json5@0.0.30: + resolution: {integrity: sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==} + dev: false + + /@types/mdast@3.0.14: + resolution: {integrity: sha512-gVZ04PGgw1qLZKsnWnyFv4ORnaJ+DXLdHTVSFbU8yX6xZ34Bjg4Q32yPkmveUP1yItXReKfB0Aknlh/3zxTKAw==} + dependencies: + '@types/unist': 2.0.9 + dev: false + + /@types/ms@0.7.33: + resolution: {integrity: sha512-AuHIyzR5Hea7ij0P9q7vx7xu4z0C28ucwjAZC0ja7JhINyCnOw8/DnvAPQQ9TfOlCtZAmCERKQX9+o1mgQhuOQ==} + dev: false + + /@types/nlcst@1.0.3: + resolution: {integrity: sha512-cpO6PPMz4E++zxP2Vhp/3KVl2Nbtj+Iksb25rlRinG7mphu2zmCIKWWlqdsx1NwJEISogR2eeZTD7JqLOCzaiw==} + dependencies: + '@types/unist': 2.0.9 + dev: false + + /@types/node@17.0.45: + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + dev: false + + /@types/node@20.8.7: + resolution: {integrity: sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==} + dependencies: + undici-types: 5.25.3 + dev: false + + /@types/parse-json@4.0.2: + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + dev: false + + /@types/parse5@6.0.3: + resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} + dev: false + + /@types/phoenix@1.6.3: + resolution: {integrity: sha512-D8TtchWVnU2ZdPVDY6tBJuz8MUDmCNVduilZTrf0Gn/u5I/uZEXOsaL4Gs4F0j43cysHsU/4h7eqAKc+SF2boQ==} + dev: false + + /@types/prop-types@15.7.9: + resolution: {integrity: sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==} + dev: false + + /@types/react-dom@18.2.6: + resolution: {integrity: sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==} + dependencies: + '@types/react': 18.2.14 + dev: false + + /@types/react-transition-group@4.4.10: + resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} + dependencies: + '@types/react': 18.2.14 + dev: false + + /@types/react@18.2.14: + resolution: {integrity: sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==} + dependencies: + '@types/prop-types': 15.7.9 + '@types/scheduler': 0.16.5 + csstype: 3.1.2 + dev: false + + /@types/resolve@1.20.4: + resolution: {integrity: sha512-BKGK0T1VgB1zD+PwQR4RRf0ais3NyvH1qjLUrHI5SEiccYaJrhLstLuoXFWJ+2Op9whGizSPUMGPJY/Qtb/A2w==} + dev: false + + /@types/sax@1.2.6: + resolution: {integrity: sha512-A1mpYCYu1aHFayy8XKN57ebXeAbh9oQIZ1wXcno6b1ESUAfMBDMx7mf/QGlYwcMRaFryh9YBuH03i/3FlPGDkQ==} + dependencies: + '@types/node': 17.0.45 + dev: false + + /@types/scheduler@0.16.5: + resolution: {integrity: sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==} + dev: false + + /@types/secure-random-password@0.2.1: + resolution: {integrity: sha512-tpG5oVF+NpIS9UJ9ttXAokafyhE/MCZBg65D345qu3gOM4YoJ/mFNVzUDUNBfb1hIi598bNOzvY04BbfS7VKwA==} + dev: true + + /@types/semver@7.5.4: + resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==} + dev: true + + /@types/unist@2.0.9: + resolution: {integrity: sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ==} + dev: false + + /@types/uuid@9.0.3: + resolution: {integrity: sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug==} + dev: true + + /@types/websocket@1.0.8: + resolution: {integrity: sha512-wvkOpWApbuxVfHhSQ1XrjVN4363vsfLJwEo4AboIZk0g1vJA5nmLp8GXUHuIdf4/Fe7+/V0Efe2HvWiLqHtlqw==} + dependencies: + '@types/node': 20.8.7 + dev: false + + /@types/yargs-parser@21.0.2: + resolution: {integrity: sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==} + dev: false + + /@typescript-eslint/eslint-plugin@5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.2.2): + resolution: {integrity: sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 5.54.1 + '@typescript-eslint/type-utils': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/utils': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + debug: 4.3.4 + eslint: 8.35.0 + grapheme-splitter: 1.0.4 + ignore: 5.2.4 + natural-compare-lite: 1.4.0 + regexpp: 3.2.0 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@5.54.1(eslint@8.35.0)(typescript@5.2.2): + resolution: {integrity: sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.54.1 + '@typescript-eslint/types': 5.54.1 + '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.2.2) + debug: 4.3.4 + eslint: 8.35.0 + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.54.1: + resolution: {integrity: sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.54.1 + '@typescript-eslint/visitor-keys': 5.54.1 + dev: true + + /@typescript-eslint/scope-manager@5.62.0: + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + dev: true + + /@typescript-eslint/type-utils@5.54.1(eslint@8.35.0)(typescript@5.2.2): + resolution: {integrity: sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.2.2) + '@typescript-eslint/utils': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + debug: 4.3.4 + eslint: 8.35.0 + tsutils: 3.21.0(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@5.54.1: + resolution: {integrity: sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.54.1(typescript@5.2.2): + resolution: {integrity: sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.54.1 + '@typescript-eslint/visitor-keys': 5.54.1 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.2.2) + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@5.54.1(eslint@8.35.0)(typescript@5.2.2): + resolution: {integrity: sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@types/json-schema': 7.0.14 + '@types/semver': 7.5.4 + '@typescript-eslint/scope-manager': 5.54.1 + '@typescript-eslint/types': 5.54.1 + '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.2.2) + eslint: 8.35.0 + eslint-scope: 5.1.1 + eslint-utils: 3.0.0(eslint@8.35.0) + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.54.1: + resolution: {integrity: sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.54.1 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@5.62.0: + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@vscode/emmet-helper@2.9.2: + resolution: {integrity: sha512-MaGuyW+fa13q3aYsluKqclmh62Hgp0BpKIqS66fCxfOaBcVQ1OnMQxRRgQUYnCkxFISAQlkJ0qWWPyXjro1Qrg==} + dependencies: + emmet: 2.4.6 + jsonc-parser: 2.3.1 + vscode-languageserver-textdocument: 1.0.11 + vscode-languageserver-types: 3.17.5 + vscode-uri: 2.1.2 + dev: false + + /@vscode/l10n@0.0.16: + resolution: {integrity: sha512-JT5CvrIYYCrmB+dCana8sUqJEcGB1ZDXNLMQ2+42bW995WmNoenijWMUdZfwmuQUTQcEVVIa2OecZzTYWUW9Cg==} + dev: false + + /acorn-jsx@5.3.2(acorn@8.10.0): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.10.0 + dev: true + + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + dependencies: + string-width: 4.2.3 + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: false + + /ansi-sequence-parser@1.1.1: + resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} + dev: false + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: false + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: false + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: false + + /apexcharts@3.37.2: + resolution: {integrity: sha512-BE5+WgIjnJgLlNPiIVqH47mzhSeSHfzg5jMUN1PVZ3fxM6ZL8WEB6aaNAh0l3c9K6PitimWo7xho48Zp7mBG2w==} + dependencies: + svg.draggable.js: 2.2.2 + svg.easing.js: 2.0.0 + svg.filter.js: 2.0.2 + svg.pathmorphing.js: 0.1.3 + svg.resize.js: 1.4.3 + svg.select.js: 3.0.1 + dev: false + + /arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + dev: false + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + /aria-hidden@1.2.3: + resolution: {integrity: sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==} + engines: {node: '>=10'} + dependencies: + tslib: 2.6.2 + dev: false + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.5 + is-array-buffer: 3.0.2 + dev: true + + /array-includes@3.1.7: + resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-string: 1.0.7 + dev: true + + /array-iterate@2.0.1: + resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + dev: false + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /astro-eslint-parser@0.11.0: + resolution: {integrity: sha512-vcz8KBQ20WNOot6qK6w7DQtz2hwg+aLLqlUa6nAnitJLqbR12GxJN/+96U3O+VI4da5Up+FMWqNoL9mywSENtA==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@astrojs/compiler': 1.8.2 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + astrojs-compiler-sync: 0.3.3(@astrojs/compiler@1.8.2) + debug: 4.3.4 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /astro@2.9.0: + resolution: {integrity: sha512-qD8hFvFrpLDA1/wGivP9YbKq7vfMfS1XPE9SyrrDaYFB/NXnZPqnwSXOxRD0AA4WSv9OAtUO3DV8dHFj9xWi/Q==} + engines: {node: '>=16.12.0', npm: '>=6.14.0'} + hasBin: true + peerDependencies: + sharp: '>=0.31.0' + peerDependenciesMeta: + sharp: + optional: true + dependencies: + '@astrojs/compiler': 1.8.2 + '@astrojs/internal-helpers': 0.1.2 + '@astrojs/language-server': 1.0.8 + '@astrojs/markdown-remark': 2.2.1(astro@2.9.0) + '@astrojs/telemetry': 2.1.1 + '@astrojs/webapi': 2.2.0 + '@babel/core': 7.23.2 + '@babel/generator': 7.23.0 + '@babel/parser': 7.23.0 + '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.2) + '@babel/traverse': 7.23.2 + '@babel/types': 7.23.0 + '@types/babel__core': 7.20.3 + '@types/dom-view-transitions': 1.0.3 + '@types/yargs-parser': 21.0.2 + acorn: 8.10.0 + boxen: 6.2.1 + chokidar: 3.5.3 + ci-info: 3.9.0 + common-ancestor-path: 1.0.1 + cookie: 0.5.0 + debug: 4.3.4 + deepmerge-ts: 4.3.0 + devalue: 4.3.2 + diff: 5.1.0 + es-module-lexer: 1.3.1 + esbuild: 0.17.19 + estree-walker: 3.0.0 + execa: 6.1.0 + fast-glob: 3.3.1 + github-slugger: 2.0.0 + gray-matter: 4.0.3 + html-escaper: 3.0.3 + js-yaml: 4.1.0 + kleur: 4.1.5 + magic-string: 0.27.0 + mime: 3.0.0 + network-information-types: 0.1.1(typescript@5.2.2) + ora: 6.3.1 + p-limit: 4.0.0 + path-to-regexp: 6.2.1 + preferred-pm: 3.1.2 + prompts: 2.4.2 + rehype: 12.0.1 + semver: 7.5.4 + server-destroy: 1.0.1 + shiki: 0.14.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + tsconfig-resolver: 3.0.1 + typescript: 5.2.2 + unist-util-visit: 4.1.2 + vfile: 5.3.7 + vite: 4.5.0 + vitefu: 0.2.5(vite@4.5.0) + which-pm: 2.1.1 + yargs-parser: 21.1.1 + zod: 3.22.4 + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: false + + /astrojs-compiler-sync@0.3.3(@astrojs/compiler@1.8.2): + resolution: {integrity: sha512-LbhchWgsvjvRBb5n5ez8/Q/f9ZKViuox27VxMDOdTUm8MRv9U7phzOiLue5KluqTmC0z1LId4gY2SekvoDrkuw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@astrojs/compiler': '>=0.27.0' + dependencies: + '@astrojs/compiler': 1.8.2 + synckit: 0.8.5 + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /autoprefixer@10.4.14(postcss@8.4.25): + resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.22.1 + caniuse-lite: 1.0.30001553 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.25 + postcss-value-parser: 4.2.0 + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /axios@1.4.0: + resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==} + dependencies: + follow-redirects: 1.15.3 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /babel-eslint@10.1.0(eslint@8.35.0): + resolution: {integrity: sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==} + engines: {node: '>=6'} + deprecated: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates. + peerDependencies: + eslint: '>= 4.12.1' + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/parser': 7.23.0 + '@babel/traverse': 7.23.2 + '@babel/types': 7.23.0 + eslint: 8.35.0 + eslint-visitor-keys: 1.3.0 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + dependencies: + '@babel/runtime': 7.22.6 + cosmiconfig: 7.1.0 + resolve: 1.22.8 + dev: false + + /bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /base64-arraybuffer@1.0.2: + resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} + engines: {node: '>= 0.6.0'} + dev: false + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /big-integer@1.6.51: + resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} + engines: {node: '>=0.6'} + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: false + + /bl@5.1.0: + resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + dependencies: + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + + /boxen@6.2.1: + resolution: {integrity: sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + ansi-align: 3.0.1 + camelcase: 6.3.0 + chalk: 4.1.2 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.1.0 + dev: false + + /bplist-parser@0.2.0: + resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} + engines: {node: '>= 5.10.0'} + dependencies: + big-integer: 1.6.51 + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + + /browserslist@4.22.1: + resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001553 + electron-to-chromium: 1.4.563 + node-releases: 2.0.13 + update-browserslist-db: 1.0.13(browserslist@4.22.1) + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /bufferutil@4.0.8: + resolution: {integrity: sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==} + engines: {node: '>=6.14.2'} + requiresBuild: true + dependencies: + node-gyp-build: 4.6.1 + dev: false + + /bundle-name@3.0.0: + resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} + engines: {node: '>=12'} + dependencies: + run-applescript: 5.0.0 + + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: false + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: false + + /caniuse-lite@1.0.30001553: + resolution: {integrity: sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==} + + /ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + dev: false + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: false + + /character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + dev: false + + /character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + dev: false + + /character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + dev: false + + /charenc@0.0.2: + resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} + dev: false + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: false + + /classnames@2.3.2: + resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} + dev: false + + /cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + dev: false + + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + restore-cursor: 4.0.0 + dev: false + + /cli-spinners@2.9.1: + resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==} + engines: {node: '>=6'} + dev: false + + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: false + + /clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + dev: false + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + dev: false + + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: false + + /common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + /confusing-browser-globals@1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + dev: true + + /convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: false + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: false + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /core-js-pure@3.33.1: + resolution: {integrity: sha512-wCXGbLjnsP10PlK/thHSQlOLlLKNEkaWbTzVvHHZ79fZNeN1gUmw2gBlpItxPv/pvqldevEXFh/d5stdNvl6EQ==} + requiresBuild: true + dev: false + + /cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: false + + /cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + /crypt@0.0.2: + resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} + dev: false + + /crypto-js@4.1.1: + resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==} + dev: false + + /css-line-break@2.1.0: + resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + dependencies: + utrie: 1.0.2 + dev: false + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + /csstype@3.1.2: + resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + dev: false + + /d@1.0.1: + resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} + dependencies: + es5-ext: 0.10.62 + type: 1.2.0 + dev: false + + /debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} + dev: false + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + dependencies: + character-entities: 2.0.2 + dev: false + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge-ts@4.3.0: + resolution: {integrity: sha512-if3ZYdkD2dClhnXR5reKtG98cwyaRT1NeugQoAPTTfsOpV9kqyeiBF9Qa5RHjemb3KzD5ulqygv6ED3t5j9eJw==} + engines: {node: '>=12.4.0'} + dev: false + + /deepmerge@2.2.1: + resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==} + engines: {node: '>=0.10.0'} + dev: false + + /default-browser-id@3.0.0: + resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} + engines: {node: '>=12'} + dependencies: + bplist-parser: 0.2.0 + untildify: 4.0.0 + + /default-browser@4.0.0: + resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} + engines: {node: '>=14.16'} + dependencies: + bundle-name: 3.0.0 + default-browser-id: 3.0.0 + execa: 7.2.0 + titleize: 3.0.0 + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: false + + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: false + + /devalue@4.3.2: + resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} + dev: false + + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: false + + /diff@5.1.0: + resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} + engines: {node: '>=0.3.1'} + dev: false + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: false + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dom-helpers@5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dependencies: + '@babel/runtime': 7.22.6 + csstype: 3.1.2 + dev: false + + /dom-to-image@2.6.0: + resolution: {integrity: sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA==} + dev: false + + /downloadjs@1.4.7: + resolution: {integrity: sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==} + dev: false + + /dset@3.1.2: + resolution: {integrity: sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==} + engines: {node: '>=4'} + dev: false + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: false + + /easy-bem@1.1.1: + resolution: {integrity: sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==} + dev: false + + /electron-to-chromium@1.4.563: + resolution: {integrity: sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==} + + /emmet@2.4.6: + resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==} + dependencies: + '@emmetio/abbreviation': 2.3.3 + '@emmetio/css-abbreviation': 2.1.8 + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: false + + /engine.io-client@6.4.0: + resolution: {integrity: sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + engine.io-parser: 5.0.7 + ws: 8.11.0 + xmlhttprequest-ssl: 2.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + + /engine.io-parser@5.0.7: + resolution: {integrity: sha512-P+jDFbvK6lE3n1OL+q9KuzdOFWkkZ/cMV9gol/SbVfpyqfvrfrFTOFJ6fQm2VC3PZHlU3QPhVwmbsCnauHF2MQ==} + engines: {node: '>=10.0.0'} + dev: false + + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: false + + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.2 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + internal-slot: 1.0.6 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.0.1 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.13 + dev: true + + /es-module-lexer@1.3.1: + resolution: {integrity: sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==} + dev: false + + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + has-tostringtag: 1.0.0 + hasown: 2.0.0 + dev: true + + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.0 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /es5-ext@0.10.62: + resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + next-tick: 1.1.0 + dev: false + + /es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-symbol: 3.1.3 + dev: false + + /es6-symbol@3.1.3: + resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} + dependencies: + d: 1.0.1 + ext: 1.7.0 + dev: false + + /esbuild-android-64@0.15.18: + resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /esbuild-android-arm64@0.15.18: + resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /esbuild-darwin-64@0.15.18: + resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /esbuild-darwin-arm64@0.15.18: + resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /esbuild-freebsd-64@0.15.18: + resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /esbuild-freebsd-arm64@0.15.18: + resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-32@0.15.18: + resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-64@0.15.18: + resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-arm64@0.15.18: + resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-arm@0.15.18: + resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-mips64le@0.15.18: + resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-ppc64le@0.15.18: + resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-riscv64@0.15.18: + resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-linux-s390x@0.15.18: + resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /esbuild-netbsd-64@0.15.18: + resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /esbuild-openbsd-64@0.15.18: + resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /esbuild-sunos-64@0.15.18: + resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /esbuild-windows-32@0.15.18: + resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /esbuild-windows-64@0.15.18: + resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /esbuild-windows-arm64@0.15.18: + resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /esbuild@0.15.18: + resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.15.18 + '@esbuild/linux-loong64': 0.15.18 + esbuild-android-64: 0.15.18 + esbuild-android-arm64: 0.15.18 + esbuild-darwin-64: 0.15.18 + esbuild-darwin-arm64: 0.15.18 + esbuild-freebsd-64: 0.15.18 + esbuild-freebsd-arm64: 0.15.18 + esbuild-linux-32: 0.15.18 + esbuild-linux-64: 0.15.18 + esbuild-linux-arm: 0.15.18 + esbuild-linux-arm64: 0.15.18 + esbuild-linux-mips64le: 0.15.18 + esbuild-linux-ppc64le: 0.15.18 + esbuild-linux-riscv64: 0.15.18 + esbuild-linux-s390x: 0.15.18 + esbuild-netbsd-64: 0.15.18 + esbuild-openbsd-64: 0.15.18 + esbuild-sunos-64: 0.15.18 + esbuild-windows-32: 0.15.18 + esbuild-windows-64: 0.15.18 + esbuild-windows-arm64: 0.15.18 + dev: false + + /esbuild@0.17.19: + resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.19 + '@esbuild/android-arm64': 0.17.19 + '@esbuild/android-x64': 0.17.19 + '@esbuild/darwin-arm64': 0.17.19 + '@esbuild/darwin-x64': 0.17.19 + '@esbuild/freebsd-arm64': 0.17.19 + '@esbuild/freebsd-x64': 0.17.19 + '@esbuild/linux-arm': 0.17.19 + '@esbuild/linux-arm64': 0.17.19 + '@esbuild/linux-ia32': 0.17.19 + '@esbuild/linux-loong64': 0.17.19 + '@esbuild/linux-mips64el': 0.17.19 + '@esbuild/linux-ppc64': 0.17.19 + '@esbuild/linux-riscv64': 0.17.19 + '@esbuild/linux-s390x': 0.17.19 + '@esbuild/linux-x64': 0.17.19 + '@esbuild/netbsd-x64': 0.17.19 + '@esbuild/openbsd-x64': 0.17.19 + '@esbuild/sunos-x64': 0.17.19 + '@esbuild/win32-arm64': 0.17.19 + '@esbuild/win32-ia32': 0.17.19 + '@esbuild/win32-x64': 0.17.19 + dev: false + + /esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: false + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: false + + /eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.27.5)(eslint@8.35.0): + resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.2 + dependencies: + confusing-browser-globals: 1.0.11 + eslint: 8.35.0 + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0) + object.assign: 4.1.4 + object.entries: 1.1.7 + semver: 6.3.1 + dev: true + + /eslint-config-airbnb-typescript@17.0.0(@typescript-eslint/eslint-plugin@5.54.1)(@typescript-eslint/parser@5.54.1)(eslint-plugin-import@2.27.5)(eslint@8.35.0): + resolution: {integrity: sha512-elNiuzD0kPAPTXjFWg+lE24nMdHMtuxgYoD30OyMD6yrW1AhFZPAg27VX7d3tzOErw+dgJTNWfRSDqEcXb4V0g==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.13.0 + '@typescript-eslint/parser': ^5.0.0 + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.3 + dependencies: + '@typescript-eslint/eslint-plugin': 5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + eslint: 8.35.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.35.0) + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0) + dev: true + + /eslint-config-prettier@8.7.0(eslint@8.35.0): + resolution: {integrity: sha512-HHVXLSlVUhMSmyW4ZzEuvjpwqamgmlfkutD53cYXLikh4pt/modINRcCIApJ84czDxM4GZInwUrromsDdTImTA==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.35.0 + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-import-resolver-typescript@3.5.3(eslint-plugin-import@2.27.5)(eslint@8.35.0): + resolution: {integrity: sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4 + enhanced-resolve: 5.15.0 + eslint: 8.35.0 + eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0) + get-tsconfig: 4.7.2 + globby: 13.2.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + synckit: 0.8.5 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + debug: 3.2.7 + eslint: 8.35.0 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.5.3(eslint-plugin-import@2.27.5)(eslint@8.35.0) + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-astro@0.23.0(eslint@8.35.0): + resolution: {integrity: sha512-KsIL1sOrz40qf/d9RP4E3sH6+p6nrIBBXB6rPuE9EWb5de+m9BWfvURuoECXfiXCmQh8UlHJUxgSWxn1bLsD8g==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + '@typescript-eslint/types': 5.62.0 + astro-eslint-parser: 0.11.0 + eslint: 8.35.0 + eslint-utils: 3.0.0(eslint@8.35.0) + postcss: 8.4.25 + postcss-selector-parser: 6.0.13 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0): + resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + array-includes: 3.1.7 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.35.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0) + has: 1.0.4 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.values: 1.1.7 + resolve: 1.22.8 + semver: 6.3.1 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.7.0)(eslint@8.35.0)(prettier@3.0.3): + resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: '>=7.28.0' + eslint-config-prettier: '*' + prettier: '>=2.0.0' + peerDependenciesMeta: + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.35.0 + eslint-config-prettier: 8.7.0(eslint@8.35.0) + prettier: 3.0.3 + prettier-linter-helpers: 1.0.0 + dev: true + + /eslint-plugin-tsdoc@0.2.17: + resolution: {integrity: sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-utils@3.0.0(eslint@8.35.0): + resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} + engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} + peerDependencies: + eslint: '>=5' + dependencies: + eslint: 8.35.0 + eslint-visitor-keys: 2.1.0 + dev: true + + /eslint-visitor-keys@1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: true + + /eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.35.0: + resolution: {integrity: sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint/eslintrc': 2.1.2 + '@eslint/js': 8.35.0 + '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-utils: 3.0.0(eslint@8.35.0) + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.23.0 + grapheme-splitter: 1.0.4 + ignore: 5.2.4 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-sdsl: 4.4.2 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + regexpp: 3.2.0 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) + eslint-visitor-keys: 3.4.3 + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker@3.0.0: + resolution: {integrity: sha512-s6ceX0NFiU/vKPiKvFdR83U1Zffu7upwZsGwpoqfg5rbbq1l50WQ5hCeIvM6E6oD4shUHCYMsiFPns4Jk0YfMQ==} + dev: false + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + /execa@6.1.0: + resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 3.0.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + dev: false + + /execa@7.2.0: + resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} + engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 4.3.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.2 + dev: false + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: false + + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: false + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.1.1 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + + /find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + dev: false + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: false + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + /find-yarn-workspace-root2@1.2.16: + resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + dependencies: + micromatch: 4.0.5 + pkg-dir: 4.2.0 + dev: false + + /flat-cache@3.1.1: + resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} + engines: {node: '>=12.0.0'} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /flowbite-react@0.4.10(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.3): + resolution: {integrity: sha512-VGtOJDOSk3VF6MODerKQ9AbP9Um0MdkI8YMJOUkL/Gou4/mnAOYMNuheUqF/tqg6WkxWsqcDybPgl87bYRI4LQ==} + peerDependencies: + react: ^18 + react-dom: ^18 + tailwindcss: ^3 + dependencies: + '@floating-ui/react': 0.24.8(react-dom@18.2.0)(react@18.2.0) + flowbite: 1.7.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-icons: 4.10.1(react@18.2.0) + react-indiana-drag-scroll: 2.2.0(react-dom@18.2.0)(react@18.2.0) + tailwind-merge: 1.14.0 + tailwindcss: 3.3.3 + dev: false + + /flowbite-typography@1.0.3(tailwindcss@3.3.3): + resolution: {integrity: sha512-UbdQFIIOb7xx2TS+QQrqr79B6ZSkSZurxYWzV0npth6Wns3/j7KfeDJoH9QFU+Zs7zjrvejNtyzgzWLWyCrdiA==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders' + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + tailwindcss: 3.3.3 + dev: false + + /flowbite@1.7.0: + resolution: {integrity: sha512-OTTmnhRgv85Rs+mcMaVU7zB6EvRQs7BaQziyMUsZLRjW9aUpeQyqKjLmxsVMMCdr8isYPCLd6UL7X1IaSVI0WQ==} + dependencies: + '@popperjs/core': 2.11.8 + mini-svg-data-uri: 1.4.4 + dev: false + + /follow-redirects@1.15.3: + resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /formik@2.4.5(react@18.2.0): + resolution: {integrity: sha512-Gxlht0TD3vVdzMDHwkiNZqJ7Mvg77xQNfmBRrNtvzcHZs72TJppSTDKHpImCMJZwcWPBJ8jSQQ95GJzXFf1nAQ==} + peerDependencies: + react: '>=16.8.0' + dependencies: + '@types/hoist-non-react-statics': 3.3.5 + deepmerge: 2.2.1 + hoist-non-react-statics: 3.3.2 + lodash: 4.17.21 + lodash-es: 4.17.21 + react: 18.2.0 + react-fast-compare: 2.0.4 + tiny-warning: 1.0.3 + tslib: 2.6.2 + dev: false + + /fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: false + + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: true + + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + + /github-slugger@1.5.0: + resolution: {integrity: sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==} + dev: false + + /github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + dev: false + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + + /glob@7.1.6: + resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + /globals@13.23.0: + resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + /grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + + /gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + dev: false + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has@1.0.4: + resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==} + engines: {node: '>= 0.4.0'} + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /hast-util-from-parse5@7.1.2: + resolution: {integrity: sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==} + dependencies: + '@types/hast': 2.3.7 + '@types/unist': 2.0.9 + hastscript: 7.2.0 + property-information: 6.3.0 + vfile: 5.3.7 + vfile-location: 4.1.0 + web-namespaces: 2.0.1 + dev: false + + /hast-util-parse-selector@3.1.1: + resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} + dependencies: + '@types/hast': 2.3.7 + dev: false + + /hast-util-raw@7.2.3: + resolution: {integrity: sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==} + dependencies: + '@types/hast': 2.3.7 + '@types/parse5': 6.0.3 + hast-util-from-parse5: 7.1.2 + hast-util-to-parse5: 7.1.0 + html-void-elements: 2.0.1 + parse5: 6.0.1 + unist-util-position: 4.0.4 + unist-util-visit: 4.1.2 + vfile: 5.3.7 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + dev: false + + /hast-util-to-html@8.0.4: + resolution: {integrity: sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==} + dependencies: + '@types/hast': 2.3.7 + '@types/unist': 2.0.9 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-raw: 7.2.3 + hast-util-whitespace: 2.0.1 + html-void-elements: 2.0.1 + property-information: 6.3.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.3 + zwitch: 2.0.4 + dev: false + + /hast-util-to-parse5@7.1.0: + resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==} + dependencies: + '@types/hast': 2.3.7 + comma-separated-tokens: 2.0.3 + property-information: 6.3.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + dev: false + + /hast-util-whitespace@2.0.1: + resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} + dev: false + + /hastscript@7.2.0: + resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} + dependencies: + '@types/hast': 2.3.7 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 3.1.1 + property-information: 6.3.0 + space-separated-tokens: 2.0.2 + dev: false + + /hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + + /html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + dev: false + + /html-void-elements@2.0.1: + resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==} + dev: false + + /html2canvas@1.4.1: + resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} + engines: {node: '>=8.0.0'} + dependencies: + css-line-break: 2.1.0 + text-segmentation: 1.0.3 + dev: false + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + /human-signals@3.0.1: + resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==} + engines: {node: '>=12.20.0'} + dev: false + + /human-signals@4.3.1: + resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} + engines: {node: '>=14.18.0'} + + /i@0.3.7: + resolution: {integrity: sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==} + engines: {node: '>=0.4'} + dev: false + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + /import-meta-resolve@2.2.2: + resolution: {integrity: sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==} + dev: false + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + hasown: 2.0.0 + side-channel: 1.0.4 + dev: true + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: false + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: false + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: false + + /is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: false + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: false + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + + /is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + dev: false + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + dev: false + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-retina@1.0.3: + resolution: {integrity: sha512-/tCmbIETZwCd8uHWO+GvbRa7jxwHFHdfetHfiwoP0aN9UDf3prUJMtKn7iBFYipYhqY1bSTjur8hC/Dakt8eyw==} + dev: false + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.13 + dev: true + + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: false + + /is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: false + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + /jiti@1.20.0: + resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==} + hasBin: true + dev: false + + /jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + dev: true + + /js-sdsl@4.4.2: + resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: false + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: false + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: false + + /jsonc-parser@2.3.1: + resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} + dev: false + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: false + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: false + + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: false + + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: false + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + dev: false + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: false + + /load-yaml-file@0.2.0: + resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} + engines: {node: '>=6'} + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + dev: false + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: false + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + + /lodash.castarray@4.4.0: + resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==} + dev: false + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: false + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /log-symbols@5.1.0: + resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} + engines: {node: '>=12'} + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + dev: false + + /longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + dev: false + + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: false + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + + /magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + + /markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + dev: false + + /md5@2.3.0: + resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} + dependencies: + charenc: 0.0.2 + crypt: 0.0.2 + is-buffer: 1.1.6 + dev: false + + /mdast-util-definitions@5.1.2: + resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} + dependencies: + '@types/mdast': 3.0.14 + '@types/unist': 2.0.9 + unist-util-visit: 4.1.2 + dev: false + + /mdast-util-find-and-replace@2.2.2: + resolution: {integrity: sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==} + dependencies: + '@types/mdast': 3.0.14 + escape-string-regexp: 5.0.0 + unist-util-is: 5.2.1 + unist-util-visit-parents: 5.1.3 + dev: false + + /mdast-util-from-markdown@1.3.1: + resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==} + dependencies: + '@types/mdast': 3.0.14 + '@types/unist': 2.0.9 + decode-named-character-reference: 1.0.2 + mdast-util-to-string: 3.2.0 + micromark: 3.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-decode-string: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + unist-util-stringify-position: 3.0.3 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-autolink-literal@1.0.3: + resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==} + dependencies: + '@types/mdast': 3.0.14 + ccount: 2.0.1 + mdast-util-find-and-replace: 2.2.2 + micromark-util-character: 1.2.0 + dev: false + + /mdast-util-gfm-footnote@1.0.2: + resolution: {integrity: sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==} + dependencies: + '@types/mdast': 3.0.14 + mdast-util-to-markdown: 1.5.0 + micromark-util-normalize-identifier: 1.1.0 + dev: false + + /mdast-util-gfm-strikethrough@1.0.3: + resolution: {integrity: sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==} + dependencies: + '@types/mdast': 3.0.14 + mdast-util-to-markdown: 1.5.0 + dev: false + + /mdast-util-gfm-table@1.0.7: + resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==} + dependencies: + '@types/mdast': 3.0.14 + markdown-table: 3.0.3 + mdast-util-from-markdown: 1.3.1 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-task-list-item@1.0.2: + resolution: {integrity: sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==} + dependencies: + '@types/mdast': 3.0.14 + mdast-util-to-markdown: 1.5.0 + dev: false + + /mdast-util-gfm@2.0.2: + resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==} + dependencies: + mdast-util-from-markdown: 1.3.1 + mdast-util-gfm-autolink-literal: 1.0.3 + mdast-util-gfm-footnote: 1.0.2 + mdast-util-gfm-strikethrough: 1.0.3 + mdast-util-gfm-table: 1.0.7 + mdast-util-gfm-task-list-item: 1.0.2 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-phrasing@3.0.1: + resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==} + dependencies: + '@types/mdast': 3.0.14 + unist-util-is: 5.2.1 + dev: false + + /mdast-util-to-hast@12.3.0: + resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==} + dependencies: + '@types/hast': 2.3.7 + '@types/mdast': 3.0.14 + mdast-util-definitions: 5.1.2 + micromark-util-sanitize-uri: 1.2.0 + trim-lines: 3.0.1 + unist-util-generated: 2.0.1 + unist-util-position: 4.0.4 + unist-util-visit: 4.1.2 + dev: false + + /mdast-util-to-markdown@1.5.0: + resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==} + dependencies: + '@types/mdast': 3.0.14 + '@types/unist': 2.0.9 + longest-streak: 3.1.0 + mdast-util-phrasing: 3.0.1 + mdast-util-to-string: 3.2.0 + micromark-util-decode-string: 1.1.0 + unist-util-visit: 4.1.2 + zwitch: 2.0.4 + dev: false + + /mdast-util-to-string@3.2.0: + resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} + dependencies: + '@types/mdast': 3.0.14 + dev: false + + /memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + dev: false + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + /micromark-core-commonmark@1.1.0: + resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==} + dependencies: + decode-named-character-reference: 1.0.2 + micromark-factory-destination: 1.1.0 + micromark-factory-label: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-factory-title: 1.1.0 + micromark-factory-whitespace: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-classify-character: 1.1.0 + micromark-util-html-tag-name: 1.2.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-autolink-literal@1.0.5: + resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==} + dependencies: + micromark-util-character: 1.2.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-extension-gfm-footnote@1.1.2: + resolution: {integrity: sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==} + dependencies: + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-strikethrough@1.0.7: + resolution: {integrity: sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==} + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-classify-character: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-table@1.0.7: + resolution: {integrity: sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==} + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-tagfilter@1.0.2: + resolution: {integrity: sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==} + dependencies: + micromark-util-types: 1.1.0 + dev: false + + /micromark-extension-gfm-task-list-item@1.0.5: + resolution: {integrity: sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==} + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm@2.0.3: + resolution: {integrity: sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==} + dependencies: + micromark-extension-gfm-autolink-literal: 1.0.5 + micromark-extension-gfm-footnote: 1.1.2 + micromark-extension-gfm-strikethrough: 1.0.7 + micromark-extension-gfm-table: 1.0.7 + micromark-extension-gfm-tagfilter: 1.0.2 + micromark-extension-gfm-task-list-item: 1.0.5 + micromark-util-combine-extensions: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-factory-destination@1.1.0: + resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==} + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-factory-label@1.1.0: + resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==} + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-factory-space@1.1.0: + resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==} + dependencies: + micromark-util-character: 1.2.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-factory-title@1.1.0: + resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==} + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-factory-whitespace@1.1.0: + resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==} + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-character@1.2.0: + resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==} + dependencies: + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-chunked@1.1.0: + resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==} + dependencies: + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-classify-character@1.1.0: + resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==} + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-combine-extensions@1.1.0: + resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==} + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-decode-numeric-character-reference@1.1.0: + resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==} + dependencies: + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-decode-string@1.1.0: + resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==} + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 1.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-encode@1.1.0: + resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==} + dev: false + + /micromark-util-html-tag-name@1.2.0: + resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==} + dev: false + + /micromark-util-normalize-identifier@1.1.0: + resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==} + dependencies: + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-resolve-all@1.1.0: + resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==} + dependencies: + micromark-util-types: 1.1.0 + dev: false + + /micromark-util-sanitize-uri@1.2.0: + resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==} + dependencies: + micromark-util-character: 1.2.0 + micromark-util-encode: 1.1.0 + micromark-util-symbol: 1.1.0 + dev: false + + /micromark-util-subtokenize@1.1.0: + resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==} + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-util-symbol@1.1.0: + resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==} + dev: false + + /micromark-util-types@1.1.0: + resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==} + dev: false + + /micromark@3.2.0: + resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} + dependencies: + '@types/debug': 4.1.10 + debug: 4.3.4 + decode-named-character-reference: 1.0.2 + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-combine-extensions: 1.1.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-encode: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + dev: false + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + dev: false + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + /mini-svg-data-uri@1.4.4: + resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} + hasBin: true + dev: false + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /moment@2.29.4: + resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} + dev: false + + /mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + dev: false + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: false + + /nanoid@3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /nanoid@4.0.2: + resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} + engines: {node: ^14 || ^16 || >=18} + hasBin: true + dev: false + + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /network-information-types@0.1.1(typescript@5.2.2): + resolution: {integrity: sha512-mLXNafJYOkiJB6IlF727YWssTRpXitR+tKSLyA5VAdBi3SOvLf5gtizHgxf241YHPWocnAO/fAhVrB/68tPHDw==} + peerDependencies: + typescript: '>= 3.0.0' + dependencies: + typescript: 5.2.2 + dev: false + + /next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + dev: false + + /nlcst-to-string@3.1.1: + resolution: {integrity: sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw==} + dependencies: + '@types/nlcst': 1.0.3 + dev: false + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /node-gyp-build@4.6.1: + resolution: {integrity: sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==} + hasBin: true + dev: false + + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: false + + /normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + + /npm-run-path@5.1.0: + resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + + /npm@9.8.0: + resolution: {integrity: sha512-AXeiBAdfM5K2jvBwA7EGLKeYyt0VnhmJRnlq4k2+M0Ao9v7yKJBqF8xFPzQL8kAybzwlfpTPCZwM4uTIszb3xA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dev: false + bundledDependencies: + - '@isaacs/string-locale-compare' + - '@npmcli/arborist' + - '@npmcli/config' + - '@npmcli/map-workspaces' + - '@npmcli/package-json' + - '@npmcli/run-script' + - abbrev + - archy + - cacache + - chalk + - ci-info + - cli-columns + - cli-table3 + - columnify + - fastest-levenshtein + - fs-minipass + - glob + - graceful-fs + - hosted-git-info + - ini + - init-package-json + - is-cidr + - json-parse-even-better-errors + - libnpmaccess + - libnpmdiff + - libnpmexec + - libnpmfund + - libnpmhook + - libnpmorg + - libnpmpack + - libnpmpublish + - libnpmsearch + - libnpmteam + - libnpmversion + - make-fetch-happen + - minimatch + - minipass + - minipass-pipeline + - ms + - node-gyp + - nopt + - npm-audit-report + - npm-install-checks + - npm-package-arg + - npm-pick-manifest + - npm-profile + - npm-registry-fetch + - npm-user-validate + - npmlog + - p-map + - pacote + - parse-conflict-json + - proc-log + - qrcode-terminal + - read + - semver + - sigstore + - ssri + - supports-color + - tar + - text-table + - tiny-relative-date + - treeverse + - validate-npm-package-name + - which + - write-file-atomic + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: false + + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: false + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.entries@1.1.7: + resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /object.values@1.1.7: + resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + + /open@9.1.0: + resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} + engines: {node: '>=14.16'} + dependencies: + default-browser: 4.0.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 2.2.0 + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /ora@6.3.1: + resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + chalk: 5.3.0 + cli-cursor: 4.0.0 + cli-spinners: 2.9.1 + is-interactive: 2.0.0 + is-unicode-supported: 1.3.0 + log-symbols: 5.1.0 + stdin-discarder: 0.1.0 + strip-ansi: 7.1.0 + wcwidth: 1.0.1 + dev: false + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: false + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: false + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: false + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: false + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.22.13 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: false + + /parse-latin@5.0.1: + resolution: {integrity: sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg==} + dependencies: + nlcst-to-string: 3.1.1 + unist-util-modify-children: 3.1.1 + unist-util-visit-children: 2.0.2 + dev: false + + /parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: false + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + /path-to-regexp@6.2.1: + resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + dev: false + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: false + + /pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: false + + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: false + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: false + + /postcss-import@15.1.0(postcss@8.4.25): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.25 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + dev: false + + /postcss-js@4.0.1(postcss@8.4.25): + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.25 + dev: false + + /postcss-load-config@4.0.1(postcss@8.4.25): + resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.1.0 + postcss: 8.4.25 + yaml: 2.3.3 + dev: false + + /postcss-nested@6.0.1(postcss@8.4.25): + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.25 + postcss-selector-parser: 6.0.13 + dev: false + + /postcss-selector-parser@6.0.13: + resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + /postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + /postcss@8.4.25: + resolution: {integrity: sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: false + + /preferred-pm@3.1.2: + resolution: {integrity: sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==} + engines: {node: '>=10'} + dependencies: + find-up: 5.0.0 + find-yarn-workspace-root2: 1.2.16 + path-exists: 4.0.0 + which-pm: 2.0.0 + dev: false + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier-plugin-astro@0.9.1: + resolution: {integrity: sha512-pYZXSbdq0eElvzoIMArzv1SBn1NUXzopjlcnt6Ql8VW32PjC12NovwBjXJ6rh8qQLi7vF8jNqAbraKW03UPfag==} + engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} + dependencies: + '@astrojs/compiler': 1.8.2 + prettier: 2.8.8 + sass-formatter: 0.7.8 + synckit: 0.8.5 + dev: false + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: false + + /prettier@3.0.3: + resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + dev: false + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: false + + /prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: false + + /property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + dev: false + + /property-information@6.3.0: + resolution: {integrity: sha512-gVNZ74nqhRMiIUYWGQdosYetaKc83x8oT41a0LlV3AAFCAZwCpg4vmGkq8t34+cUhp3cnM4XDiU/7xlgK7HGrg==} + dev: false + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /qr.js@0.0.0: + resolution: {integrity: sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==} + dev: false + + /qrcode.react@3.1.0(react@18.2.0): + resolution: {integrity: sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + /react-avatar@5.0.3(@babel/runtime@7.22.6)(core-js-pure@3.33.1)(prop-types@15.8.1)(react@18.2.0): + resolution: {integrity: sha512-DNc+qkWH9QehSEZqHBhqpXWsPY+rU9W7kD68QFHfu8Atfsvx/3ML0DzAePgTUd96nCXQQ3KZMcC3LKYT8FiBIg==} + peerDependencies: + '@babel/runtime': '>=7' + core-js-pure: '>=3' + prop-types: ^15.0.0 || ^16.0.0 + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@babel/runtime': 7.22.6 + core-js-pure: 3.33.1 + is-retina: 1.0.3 + md5: 2.3.0 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + + /react-dom@18.2.0(react@18.2.0): + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + + /react-fast-compare@2.0.4: + resolution: {integrity: sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==} + dev: false + + /react-fast-compare@3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + dev: false + + /react-helmet@6.1.0(react@18.2.0): + resolution: {integrity: sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==} + peerDependencies: + react: '>=16.3.0' + dependencies: + object-assign: 4.1.1 + prop-types: 15.8.1 + react: 18.2.0 + react-fast-compare: 3.2.2 + react-side-effect: 2.1.2(react@18.2.0) + dev: false + + /react-icons@4.10.1(react@18.2.0): + resolution: {integrity: sha512-/ngzDP/77tlCfqthiiGNZeYFACw85fUjZtLbedmJ5DTlNDIwETxhwBzdOJ21zj4iJdvc0J3y7yOsX3PpxAJzrw==} + peerDependencies: + react: '*' + dependencies: + react: 18.2.0 + dev: false + + /react-indiana-drag-scroll@2.2.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-+W/3B2OQV0FrbdnsoIo4dww/xpH0MUQJz6ziQb7H+oBko3OCbXuzDFYnho6v6yhGrYDNWYPuFUewb89IONEl/A==} + engines: {node: '>=8', npm: '>=5'} + peerDependencies: + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + dependencies: + classnames: 2.3.2 + debounce: 1.2.1 + easy-bem: 1.1.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: false + + /react-qr-code@2.0.11(react@18.2.0): + resolution: {integrity: sha512-P7mvVM5vk9NjGdHMt4Z0KWeeJYwRAtonHTghZT2r+AASinLUUKQ9wfsGH2lPKsT++gps7hXmaiMGRvwTDEL9OA==} + peerDependencies: + react: ^16.x || ^17.x || ^18.x + react-native-svg: '*' + peerDependenciesMeta: + react-native-svg: + optional: true + dependencies: + prop-types: 15.8.1 + qr.js: 0.0.0 + react: 18.2.0 + dev: false + + /react-select@5.8.0(@types/react@18.2.14)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-TfjLDo58XrhP6VG5M/Mi56Us0Yt8X7xD6cDybC7yoRMUNm7BGO7qk8J0TLQOua/prb8vUOtsfnXZwfm30HGsAA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@babel/runtime': 7.22.6 + '@emotion/cache': 11.11.0 + '@emotion/react': 11.11.3(@types/react@18.2.14)(react@18.2.0) + '@floating-ui/dom': 1.5.3 + '@types/react-transition-group': 4.4.10 + memoize-one: 6.0.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) + use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.14)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + dev: false + + /react-side-effect@2.1.2(react@18.2.0): + resolution: {integrity: sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==} + peerDependencies: + react: ^16.3.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + + /react-toastify@9.1.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-fPfb8ghtn/XMxw3LkxQBk3IyagNpF/LIKjOBflbexr2AWxAH1MJgvnESwEwBn9liLFXgTKWgBSdZpw9m4OTHTg==} + peerDependencies: + react: '>=16' + react-dom: '>=16' + dependencies: + clsx: 1.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /react-transition-group@4.4.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + dependencies: + '@babel/runtime': 7.22.6 + dom-helpers: 5.2.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /react@18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + + /read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + dependencies: + pify: 2.3.0 + dev: false + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: false + + /regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: false + + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: true + + /regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /rehype-parse@8.0.5: + resolution: {integrity: sha512-Ds3RglaY/+clEX2U2mHflt7NlMA72KspZ0JLUJgBBLpRddBcEw3H8uYZQliQriku22NZpYMfjDdSgHcjxue24A==} + dependencies: + '@types/hast': 2.3.7 + hast-util-from-parse5: 7.1.2 + parse5: 6.0.1 + unified: 10.1.2 + dev: false + + /rehype-raw@6.1.1: + resolution: {integrity: sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==} + dependencies: + '@types/hast': 2.3.7 + hast-util-raw: 7.2.3 + unified: 10.1.2 + dev: false + + /rehype-stringify@9.0.4: + resolution: {integrity: sha512-Uk5xu1YKdqobe5XpSskwPvo1XeHUUucWEQSl8hTrXt5selvca1e8K1EZ37E6YoZ4BT8BCqCdVfQW7OfHfthtVQ==} + dependencies: + '@types/hast': 2.3.7 + hast-util-to-html: 8.0.4 + unified: 10.1.2 + dev: false + + /rehype@12.0.1: + resolution: {integrity: sha512-ey6kAqwLM3X6QnMDILJthGvG1m1ULROS9NT4uG9IDCuv08SFyLlreSuvOa//DgEvbXx62DS6elGVqusWhRUbgw==} + dependencies: + '@types/hast': 2.3.7 + rehype-parse: 8.0.5 + rehype-stringify: 9.0.4 + unified: 10.1.2 + dev: false + + /remark-gfm@3.0.1: + resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} + dependencies: + '@types/mdast': 3.0.14 + mdast-util-gfm: 2.0.2 + micromark-extension-gfm: 2.0.3 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-parse@10.0.2: + resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==} + dependencies: + '@types/mdast': 3.0.14 + mdast-util-from-markdown: 1.3.1 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-rehype@10.1.0: + resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} + dependencies: + '@types/hast': 2.3.7 + '@types/mdast': 3.0.14 + mdast-util-to-hast: 12.3.0 + unified: 10.1.2 + dev: false + + /remark-smartypants@2.0.0: + resolution: {integrity: sha512-Rc0VDmr/yhnMQIz8n2ACYXlfw/P/XZev884QU1I5u+5DgJls32o97Vc1RbK3pfumLsJomS2yy8eT4Fxj/2MDVA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + retext: 8.1.0 + retext-smartypants: 5.2.0 + unist-util-visit: 4.1.2 + dev: false + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + + /resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + /restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: false + + /retext-latin@3.1.0: + resolution: {integrity: sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==} + dependencies: + '@types/nlcst': 1.0.3 + parse-latin: 5.0.1 + unherit: 3.0.1 + unified: 10.1.2 + dev: false + + /retext-smartypants@5.2.0: + resolution: {integrity: sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==} + dependencies: + '@types/nlcst': 1.0.3 + nlcst-to-string: 3.1.1 + unified: 10.1.2 + unist-util-visit: 4.1.2 + dev: false + + /retext-stringify@3.1.0: + resolution: {integrity: sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==} + dependencies: + '@types/nlcst': 1.0.3 + nlcst-to-string: 3.1.1 + unified: 10.1.2 + dev: false + + /retext@8.1.0: + resolution: {integrity: sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==} + dependencies: + '@types/nlcst': 1.0.3 + retext-latin: 3.1.0 + retext-stringify: 3.1.0 + unified: 10.1.2 + dev: false + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup@3.29.4: + resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /run-applescript@5.0.0: + resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} + engines: {node: '>=12'} + dependencies: + execa: 5.1.1 + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + + /s.color@0.0.15: + resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} + dev: false + + /sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + dependencies: + mri: 1.2.0 + dev: false + + /safe-array-concat@1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: true + + /sass-formatter@0.7.8: + resolution: {integrity: sha512-7fI2a8THglflhhYis7k06eUf92VQuJoXzEs2KRP0r1bluFxKFvLx0Ns7c478oYGM0fPfrr846ZRWVi2MAgHt9Q==} + dependencies: + suf-log: 2.5.3 + dev: false + + /sax@1.3.0: + resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + dev: false + + /scheduler@0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + dev: false + + /secure-random-password@0.2.3: + resolution: {integrity: sha512-2zpmr6pK3CZGIS9fgApFw00/tKEBVbJTqe4AZLrLNgahCK6ueIR5uMzvbERNibr8hkWneMcOqDcm4wpHWUxrYw==} + dependencies: + secure-random: 1.1.2 + dev: false + + /secure-random@1.1.2: + resolution: {integrity: sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==} + dev: false + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + + /server-destroy@1.0.1: + resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==} + dev: false + + /set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + /shiki@0.14.1: + resolution: {integrity: sha512-+Jz4nBkCBe0mEDqo1eKRcCdjRtrCjozmcbTUjbPTX7OOJfEbTZzlUWlZtGe3Gb5oV1/jnojhG//YZc3rs9zSEw==} + dependencies: + ansi-sequence-parser: 1.1.1 + jsonc-parser: 3.2.0 + vscode-oniguruma: 1.7.0 + vscode-textmate: 8.0.0 + dev: false + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: false + + /sitemap@7.1.1: + resolution: {integrity: sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==} + engines: {node: '>=12.0.0', npm: '>=5.6.0'} + hasBin: true + dependencies: + '@types/node': 17.0.45 + '@types/sax': 1.2.6 + arg: 5.0.2 + sax: 1.3.0 + dev: false + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + + /socket.io-client@4.6.2: + resolution: {integrity: sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + engine.io-client: 6.4.0 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: false + + /socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + dependencies: + '@socket.io/component-emitter': 3.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + /source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: false + + /space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + dev: false + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + + /stdin-discarder@0.1.0: + resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + bl: 5.1.0 + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: false + + /string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /stringify-entities@4.0.3: + resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: false + + /strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + dev: false + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + /strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: false + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /stylis@4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + dev: false + + /sucrase@3.34.0: + resolution: {integrity: sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==} + engines: {node: '>=8'} + hasBin: true + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + commander: 4.1.1 + glob: 7.1.6 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + dev: false + + /suf-log@2.5.3: + resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} + dependencies: + s.color: 0.0.15 + dev: false + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + /svg.draggable.js@2.2.2: + resolution: {integrity: sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==} + engines: {node: '>= 0.8.0'} + dependencies: + svg.js: 2.7.1 + dev: false + + /svg.easing.js@2.0.0: + resolution: {integrity: sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==} + engines: {node: '>= 0.8.0'} + dependencies: + svg.js: 2.7.1 + dev: false + + /svg.filter.js@2.0.2: + resolution: {integrity: sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==} + engines: {node: '>= 0.8.0'} + dependencies: + svg.js: 2.7.1 + dev: false + + /svg.js@2.7.1: + resolution: {integrity: sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==} + dev: false + + /svg.pathmorphing.js@0.1.3: + resolution: {integrity: sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==} + engines: {node: '>= 0.8.0'} + dependencies: + svg.js: 2.7.1 + dev: false + + /svg.resize.js@1.4.3: + resolution: {integrity: sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==} + engines: {node: '>= 0.8.0'} + dependencies: + svg.js: 2.7.1 + svg.select.js: 2.1.2 + dev: false + + /svg.select.js@2.1.2: + resolution: {integrity: sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==} + engines: {node: '>= 0.8.0'} + dependencies: + svg.js: 2.7.1 + dev: false + + /svg.select.js@3.0.1: + resolution: {integrity: sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==} + engines: {node: '>= 0.8.0'} + dependencies: + svg.js: 2.7.1 + dev: false + + /synckit@0.8.5: + resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/utils': 2.4.2 + tslib: 2.6.2 + + /tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: false + + /tailwind-merge@1.14.0: + resolution: {integrity: sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==} + dev: false + + /tailwind-scrollbar@3.0.4(tailwindcss@3.3.3): + resolution: {integrity: sha512-X/QBsn/C5u9x6/YvTc1Zo7b09Gqs5BfDe0UK/8LDQUv8IEBKF+p2ISTRwvAr50MH0hn/wTyCEOann7uXoa1/2Q==} + engines: {node: '>=12.13.0'} + peerDependencies: + tailwindcss: 3.x + dependencies: + tailwindcss: 3.3.3 + dev: false + + /tailwindcss@3.3.3: + resolution: {integrity: sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.1 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.20.0 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.25 + postcss-import: 15.1.0(postcss@8.4.25) + postcss-js: 4.0.1(postcss@8.4.25) + postcss-load-config: 4.0.1(postcss@8.4.25) + postcss-nested: 6.0.1(postcss@8.4.25) + postcss-selector-parser: 6.0.13 + resolve: 1.22.8 + sucrase: 3.34.0 + transitivePeerDependencies: + - ts-node + dev: false + + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /text-segmentation@1.0.3: + resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} + dependencies: + utrie: 1.0.2 + dev: false + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: false + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: false + + /tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + dev: false + + /tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + dev: false + + /titleize@3.0.0: + resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} + engines: {node: '>=12'} + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + + /toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + dev: false + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + dev: false + + /trough@2.1.0: + resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + dev: false + + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: false + + /tsconfig-paths@3.14.2: + resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tsconfig-resolver@3.0.1: + resolution: {integrity: sha512-ZHqlstlQF449v8glscGRXzL6l2dZvASPCdXJRWG4gHEZlUVx2Jtmr+a2zeVG4LCsKhDXKRj5R3h0C/98UcVAQg==} + dependencies: + '@types/json5': 0.0.30 + '@types/resolve': 1.20.4 + json5: 2.2.3 + resolve: 1.22.8 + strip-bom: 4.0.0 + type-fest: 0.13.1 + dev: false + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + /tsutils@3.21.0(typescript@5.2.2): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 5.2.2 + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + dev: false + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: false + + /type@1.2.0: + resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} + dev: false + + /type@2.7.2: + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + dev: false + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + dependencies: + is-typedarray: 1.0.0 + dev: false + + /typescript@5.2.2: + resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + engines: {node: '>=14.17'} + hasBin: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.5 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /undici-types@5.25.3: + resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==} + dev: false + + /undici@5.26.5: + resolution: {integrity: sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==} + engines: {node: '>=14.0'} + dependencies: + '@fastify/busboy': 2.0.0 + dev: false + + /unherit@3.0.1: + resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==} + dev: false + + /unified@10.1.2: + resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} + dependencies: + '@types/unist': 2.0.9 + bail: 2.0.2 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 4.1.0 + trough: 2.1.0 + vfile: 5.3.7 + dev: false + + /unist-util-generated@2.0.1: + resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==} + dev: false + + /unist-util-is@5.2.1: + resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} + dependencies: + '@types/unist': 2.0.9 + dev: false + + /unist-util-modify-children@3.1.1: + resolution: {integrity: sha512-yXi4Lm+TG5VG+qvokP6tpnk+r1EPwyYL04JWDxLvgvPV40jANh7nm3udk65OOWquvbMDe+PL9+LmkxDpTv/7BA==} + dependencies: + '@types/unist': 2.0.9 + array-iterate: 2.0.1 + dev: false + + /unist-util-position@4.0.4: + resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} + dependencies: + '@types/unist': 2.0.9 + dev: false + + /unist-util-stringify-position@3.0.3: + resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} + dependencies: + '@types/unist': 2.0.9 + dev: false + + /unist-util-visit-children@2.0.2: + resolution: {integrity: sha512-+LWpMFqyUwLGpsQxpumsQ9o9DG2VGLFrpz+rpVXYIEdPy57GSy5HioC0g3bg/8WP9oCLlapQtklOzQ8uLS496Q==} + dependencies: + '@types/unist': 2.0.9 + dev: false + + /unist-util-visit-parents@5.1.3: + resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} + dependencies: + '@types/unist': 2.0.9 + unist-util-is: 5.2.1 + dev: false + + /unist-util-visit@4.1.2: + resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} + dependencies: + '@types/unist': 2.0.9 + unist-util-is: 5.2.1 + unist-util-visit-parents: 5.1.3 + dev: false + + /untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + + /update-browserslist-db@1.0.13(browserslist@4.22.1): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.1 + escalade: 3.1.1 + picocolors: 1.0.0 + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + + /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.14)(react@18.2.0): + resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.14 + react: 18.2.0 + dev: false + + /use-sync-external-store@1.2.0(react@18.2.0): + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + + /utf-8-validate@5.0.10: + resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} + engines: {node: '>=6.14.2'} + requiresBuild: true + dependencies: + node-gyp-build: 4.6.1 + dev: false + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + /utrie@1.0.2: + resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==} + dependencies: + base64-arraybuffer: 1.0.2 + dev: false + + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + + /uvu@0.5.6: + resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + dequal: 2.0.3 + diff: 5.1.0 + kleur: 4.1.5 + sade: 1.8.1 + dev: false + + /vfile-location@4.1.0: + resolution: {integrity: sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==} + dependencies: + '@types/unist': 2.0.9 + vfile: 5.3.7 + dev: false + + /vfile-message@3.1.4: + resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} + dependencies: + '@types/unist': 2.0.9 + unist-util-stringify-position: 3.0.3 + dev: false + + /vfile@5.3.7: + resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} + dependencies: + '@types/unist': 2.0.9 + is-buffer: 2.0.5 + unist-util-stringify-position: 3.0.3 + vfile-message: 3.1.4 + dev: false + + /vite@4.5.0: + resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.18.20 + postcss: 8.4.31 + rollup: 3.29.4 + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /vitefu@0.2.5(vite@4.5.0): + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 4.5.0 + dev: false + + /vscode-css-languageservice@6.2.10: + resolution: {integrity: sha512-sYUZPku4mQ06AWGCbMyjv2tdR6juBW6hTbVPFwbJvNVzdtEfBioQOgkdXg7yMJNWnXkvWSU1FL2kb4Vxu5Cdyw==} + dependencies: + '@vscode/l10n': 0.0.16 + vscode-languageserver-textdocument: 1.0.11 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + dev: false + + /vscode-html-languageservice@5.1.0: + resolution: {integrity: sha512-cGOu5+lrz+2dDXSGS15y24lDtPaML1T8K/SfqgFbLmCZ1btYOxceFieR+ybTS2es/A67kRc62m2cKFLUQPWG5g==} + dependencies: + '@vscode/l10n': 0.0.16 + vscode-languageserver-textdocument: 1.0.11 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + dev: false + + /vscode-jsonrpc@8.1.0: + resolution: {integrity: sha512-6TDy/abTQk+zDGYazgbIPc+4JoXdwC8NHU9Pbn4UJP1fehUyZmM4RHp5IthX7A6L5KS30PRui+j+tbbMMMafdw==} + engines: {node: '>=14.0.0'} + dev: false + + /vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + dev: false + + /vscode-languageserver-protocol@3.17.3: + resolution: {integrity: sha512-924/h0AqsMtA5yK22GgMtCYiMdCOtWTSGgUOkgEDX+wk2b0x4sAfLiO4NxBxqbiVtz7K7/1/RgVrVI0NClZwqA==} + dependencies: + vscode-jsonrpc: 8.1.0 + vscode-languageserver-types: 3.17.3 + dev: false + + /vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + dev: false + + /vscode-languageserver-textdocument@1.0.11: + resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} + dev: false + + /vscode-languageserver-types@3.17.3: + resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==} + dev: false + + /vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + dev: false + + /vscode-languageserver@8.1.0: + resolution: {integrity: sha512-eUt8f1z2N2IEUDBsKaNapkz7jl5QpskN2Y0G01T/ItMxBxw1fJwvtySGB9QMecatne8jFIWJGWI61dWjyTLQsw==} + hasBin: true + dependencies: + vscode-languageserver-protocol: 3.17.3 + dev: false + + /vscode-oniguruma@1.7.0: + resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + dev: false + + /vscode-textmate@8.0.0: + resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + dev: false + + /vscode-uri@2.1.2: + resolution: {integrity: sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==} + dev: false + + /vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + dev: false + + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: false + + /web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + dev: false + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /websocket@1.0.34: + resolution: {integrity: sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==} + engines: {node: '>=4.0.0'} + dependencies: + bufferutil: 4.0.8 + debug: 2.6.9 + es5-ext: 0.10.62 + typedarray-to-buffer: 3.1.5 + utf-8-validate: 5.0.10 + yaeti: 0.0.6 + transitivePeerDependencies: + - supports-color + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + dev: false + + /which-pm@2.0.0: + resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} + engines: {node: '>=8.15'} + dependencies: + load-yaml-file: 0.2.0 + path-exists: 4.0.0 + dev: false + + /which-pm@2.1.1: + resolution: {integrity: sha512-xzzxNw2wMaoCWXiGE8IJ9wuPMU+EYhFksjHxrRT8kMT5SnocBPRg69YAMtyV4D12fP582RA+k3P8H9J5EMdIxQ==} + engines: {node: '>=8.15'} + dependencies: + load-yaml-file: 0.2.0 + path-exists: 4.0.0 + dev: false + + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + + /widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + dev: false + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + /ws@8.11.0: + resolution: {integrity: sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /xmlhttprequest-ssl@2.0.0: + resolution: {integrity: sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==} + engines: {node: '>=0.4.0'} + dev: false + + /yaeti@0.0.6: + resolution: {integrity: sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==} + engines: {node: '>=0.10.32'} + dev: false + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: false + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + /yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: false + + /yaml@2.3.3: + resolution: {integrity: sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==} + engines: {node: '>= 14'} + dev: false + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: false + + /yup@1.2.0: + resolution: {integrity: sha512-PPqYKSAXjpRCgLgLKVGPA33v5c/WgEx3wi6NFjIiegz90zSwyMpvTFp/uGcVnnbx6to28pgnzp/q8ih3QRjLMQ==} + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 + dev: false + + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false + + /zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + dev: false diff --git a/shell.sh b/shell.sh new file mode 100644 index 000000000..3a119815a --- /dev/null +++ b/shell.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +LOG_FILE="/home/ec2-user/config/token/container_tokens" +LOGGED_TOKENS="/home/ec2-user/config/token/logged_tokens.txt" + +# Function to check if the token is already logged +is_token_logged() { + token="$1" + if grep -q "$token" "$LOGGED_TOKENS"; then + return 0 # Token is logged + else + return 1 # Token is not logged + fi +} + +# Function to extract token and store it in the log file +extract_token() { + container_id="$1" + container_name=$(docker inspect --format '{{.Name}}' "$container_id" | sed 's/\///g') + service_port=$(echo "$container_name" | awk -F'-' '{print $(NF-1)}') + service_name=$(echo "$container_name" | awk -F'-' -v OFS="-" '{$(NF-1)=""; print}' | sed 's/-$//') + + token=$(docker logs "$container_id" 2>&1 | grep -o -P '(?<=token )[^ ]+' | head -n 1) + + if [ -n "$token" ]; then + if ! is_token_logged "$token"; then + echo "$(date) - ${service_name}-${service_port}=${token}" >> "$LOG_FILE" + echo "$token" >> "$LOGGED_TOKENS" + fi + fi +} + +# Initial extraction for existing containers +container_ids=$(docker ps --format '{{.ID}}') +for id in $container_ids; do + extract_token "$id" +done + +# Continuously monitor for new containers and extract tokens +while true; do + new_container_ids=$(docker ps --format '{{.ID}}') + for id in $new_container_ids; do + if ! grep -q "$id" "$LOG_FILE"; then + extract_token "$id" + fi + done + sleep 10 # Adjust the interval as needed +done From 96fd469113f904f012bfa1e36b8c9afba688dcf2 Mon Sep 17 00:00:00 2001 From: Sheetal-ayanworks Date: Mon, 15 Jan 2024 16:53:16 +0530 Subject: [PATCH 039/303] Implement a QA Git Action workflow file to deploy the QA environment. Signed-off-by: Sheetal-ayanworks --- shell.sh | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) delete mode 100644 shell.sh diff --git a/shell.sh b/shell.sh deleted file mode 100644 index 3a119815a..000000000 --- a/shell.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -LOG_FILE="/home/ec2-user/config/token/container_tokens" -LOGGED_TOKENS="/home/ec2-user/config/token/logged_tokens.txt" - -# Function to check if the token is already logged -is_token_logged() { - token="$1" - if grep -q "$token" "$LOGGED_TOKENS"; then - return 0 # Token is logged - else - return 1 # Token is not logged - fi -} - -# Function to extract token and store it in the log file -extract_token() { - container_id="$1" - container_name=$(docker inspect --format '{{.Name}}' "$container_id" | sed 's/\///g') - service_port=$(echo "$container_name" | awk -F'-' '{print $(NF-1)}') - service_name=$(echo "$container_name" | awk -F'-' -v OFS="-" '{$(NF-1)=""; print}' | sed 's/-$//') - - token=$(docker logs "$container_id" 2>&1 | grep -o -P '(?<=token )[^ ]+' | head -n 1) - - if [ -n "$token" ]; then - if ! is_token_logged "$token"; then - echo "$(date) - ${service_name}-${service_port}=${token}" >> "$LOG_FILE" - echo "$token" >> "$LOGGED_TOKENS" - fi - fi -} - -# Initial extraction for existing containers -container_ids=$(docker ps --format '{{.ID}}') -for id in $container_ids; do - extract_token "$id" -done - -# Continuously monitor for new containers and extract tokens -while true; do - new_container_ids=$(docker ps --format '{{.ID}}') - for id in $new_container_ids; do - if ! grep -q "$id" "$LOG_FILE"; then - extract_token "$id" - fi - done - sleep 10 # Adjust the interval as needed -done From 4ac936dffa386c282102a2c926ba6f213c958adf Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 16 Jan 2024 12:08:05 +0530 Subject: [PATCH 040/303] handled dark mode Signed-off-by: karan --- src/app/NavBarSidebar.astro | 5 +++-- src/components/SignOutButton/index.tsx | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app/NavBarSidebar.astro b/src/app/NavBarSidebar.astro index 833f48332..a776d5259 100644 --- a/src/app/NavBarSidebar.astro +++ b/src/app/NavBarSidebar.astro @@ -446,7 +446,7 @@ const permittedPages = RolePermissions.find(
  • + fill="currentColor"> Profile diff --git a/src/components/SignOutButton/index.tsx b/src/components/SignOutButton/index.tsx index e5a22830f..13e1ba46f 100644 --- a/src/components/SignOutButton/index.tsx +++ b/src/components/SignOutButton/index.tsx @@ -25,7 +25,7 @@ const SignOutButton = () => { return ( -
    - v.{schema?.version} -
    ); })} @@ -937,7 +948,7 @@ const UserDashBoard = () => { key={ecosystem?.id} > +
    + + {' '} + {isEcosystemLead && ( + + )} + +
    ); })} @@ -1058,18 +1101,16 @@ const UserDashBoard = () => { > - + {cred?.tag} + + {cred?.credentialDefinitionId} + -
    - - {cred?.credentialDefinitionId.slice(0, 8)}... - -
    ); })} From 9705d395238505d6d58aee8fc7ff6aa61b2b7d25 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 17 Jan 2024 19:08:32 +0530 Subject: [PATCH 043/303] feat: implemented pagination on ecosystem Signed-off-by: karan --- .../datatable/SortDataTable.tsx | 25 +- src/commonComponents/datatable/interface.ts | 2 +- src/components/Ecosystem/MemberList.tsx | 280 +++++++++--------- 3 files changed, 153 insertions(+), 154 deletions(-) diff --git a/src/commonComponents/datatable/SortDataTable.tsx b/src/commonComponents/datatable/SortDataTable.tsx index 33e56f36d..2dfe6825e 100644 --- a/src/commonComponents/datatable/SortDataTable.tsx +++ b/src/commonComponents/datatable/SortDataTable.tsx @@ -1,31 +1,19 @@ import type { TableData, TableHeader } from './interface'; - import CustomSpinner from '../../components/CustomSpinner'; import SearchInput from '../../components/SearchInput'; import { Pagination } from 'flowbite-react'; import { useState } from 'react'; import { EmptyListMessage } from '../../components/EmptyListComponent'; -import React from 'react'; interface DataTableProps { header: TableHeader[]; data: TableData[]; loading: boolean; - callback?: (clickId: string | null | undefined) => void; - displaySelect?: boolean; - showBtn?: boolean; onInputChange: () => void; refresh: () => void; currentPage: any; onPageChange: () => void; totalPages: number; - pageInfo?: - | { - totalItem: number | undefined; - nextPage: number | undefined; - lastPage: number | undefined; - } - | {}; searchSortByValue: (value: any) => void; isPagination: boolean; isSearch: boolean; @@ -34,6 +22,17 @@ interface DataTableProps { isHeader: boolean; message: string; discription: string; + noExtraHeight?: boolean; + callback?: (clickId: string | null | undefined) => void; + displaySelect?: boolean; + showBtn?: boolean; + pageInfo?: + | { + totalItem: number | undefined; + nextPage: number | undefined; + lastPage: number | undefined; + } + | {}; } const SortDataTable: React.FC = ({ @@ -57,6 +56,7 @@ const SortDataTable: React.FC = ({ isHeader, message, discription, + noExtraHeight }) => { const [selectedValue, setSelectedValue] = useState(''); @@ -244,6 +244,7 @@ const SortDataTable: React.FC = ({
  • diff --git a/src/commonComponents/datatable/interface.ts b/src/commonComponents/datatable/interface.ts index ab0a23849..ddcd97ac5 100644 --- a/src/commonComponents/datatable/interface.ts +++ b/src/commonComponents/datatable/interface.ts @@ -9,7 +9,7 @@ export interface TableData { data: Data[]; } -interface Data { +export interface Data { data: string | JSX.Element; subData?: string; } diff --git a/src/components/Ecosystem/MemberList.tsx b/src/components/Ecosystem/MemberList.tsx index 32178f52b..5aff24d33 100644 --- a/src/components/Ecosystem/MemberList.tsx +++ b/src/components/Ecosystem/MemberList.tsx @@ -2,15 +2,13 @@ import { ChangeEvent, useEffect, useState } from 'react'; import { getEcosystemMemberList } from '../../api/ecosystem'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import type { AxiosResponse } from 'axios'; -import DataTable from '../../commonComponents/datatable'; -import type { TableData } from '../../commonComponents/datatable/interface'; +import type { Data } from '../../commonComponents/datatable/interface'; import DateTooltip from '../Tooltip'; import { dateConversion } from '../../utils/DateConversion'; import { AlertComponent } from '../AlertComponent'; -import { Pagination } from 'flowbite-react'; import { getFromLocalStorage } from '../../api/Auth'; -import SearchInput from '../SearchInput'; import CopyDid from '../../commonComponents/CopyDid'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { pageNumber: 1, @@ -22,156 +20,153 @@ interface IMemberList { orgId: string; ecosystem: { createDateTime: string }; ecosystemRole: { name: string }; - organisation: { name: string; orgSlug: string; org_agents: {orgDid: string}[] }; - // orgName: string; - // orgDid: string; + organisation: { + name: string; + orgSlug: string; + org_agents: { orgDid: string }[]; + }; role: string; createDateTime: any; status: string; copied?: boolean; + data: Data[]; } - const MemberList = () => { const [loading, setLoading] = useState(false); const [memberList, setMemberList] = useState([]); const [error, setError] = useState(null); const [currentPage, setCurrentPage] = useState(initialPageState); const [searchText, setSearchText] = useState(''); - const [memberTableData, setMemberTableData] = useState([]) + const [totalItem, setTotalItem] = useState(0); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); useEffect(() => { - generateTable(memberList) - }, [memberList]) + let getData: NodeJS.Timeout; - const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); - }; + if (searchText.length >= 1) { + getData = setTimeout(() => { + getEcosystemMembers(); + }, 1000); + return () => clearTimeout(getData); + } else { + getEcosystemMembers(); + } - const generateTable = async (memberList: IMemberList[]): Promise => { + return () => clearTimeout(getData); + }, [searchText, currentPage.pageNumber]); - const userOrgId = await getFromLocalStorage(storageKeys.ORG_ID); - const compareMembers = ( - firstMember: { ecosystemRole: { name: string } }, - secondMember: { ecosystemRole: { name: string } }, - ) => { - // remove this sorting logic when implemented from backend - const firstName = firstMember?.ecosystemRole?.name; - const secondName = secondMember?.ecosystemRole?.name; - - switch (true) { - case firstName > secondName: - return 1; - case secondName > firstName: - return -1; - default: - return 0; - } - }; - - const sortedMemberList = memberList && memberList.length > 0 && memberList?.sort(compareMembers); - const membersData = sortedMemberList && sortedMemberList.length > 0 && sortedMemberList?.map( - (member: IMemberList) => { - let orgDid ='Not available' - if(member.organisation.org_agents.length > 0){ - const orgAgent = member.organisation.org_agents[0]; - orgDid = orgAgent.orgDid - } - return { - data: [ - { - data: member?.organisation.name || 'Not available', - }, - { - data: - ( - - {dateConversion(member?.createDateTime)}{' '} - - ) || 'Not available', - }, - { - data: orgDid? ( -
    - -
    - ) : ( - - Not available - - ), - }, - { - data: member?.ecosystemRole?.name ? ( - - - {member?.ecosystemRole?.name} - - {member?.orgId === userOrgId ? '(You)' : ''} - - ) : ( - 'Not available' - ), - }, - { - data: member.status ? ( - - {member.status.charAt(0) + - member.status.slice(1).toLowerCase()} - - ) : ( - 'Not available' - ), - }, - ], - }; - }, - ); + const refreshPage = () => { + getEcosystemMembers(); + }; - if(membersData){ - setMemberTableData(membersData); - } - } + const searchInputChange = (e: ChangeEvent) => { + setSearchText(e.target.value); + }; const getEcosystemMembers = async () => { + const userOrgId = await getFromLocalStorage(storageKeys.ORG_ID); setLoading(true); const response = await getEcosystemMemberList( currentPage.pageNumber, currentPage.pageSize, - searchText + searchText, ); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const totalPages = data?.data?.totalPages; - setMemberList(data?.data?.members) - setCurrentPage({ - ...currentPage, - total: totalPages, + setTotalItem(data?.data.totalItems); + const { totalItems, nextPage, lastPage } = data.data; + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, }); + const memberList = + data?.data?.data?.length > 0 && + data?.data?.data?.map((member: IMemberList) => { + let orgDid = 'Not available'; + if (member.organisation.org_agents.length > 0) { + const orgAgent = member.organisation.org_agents[0]; + orgDid = orgAgent.orgDid; + } + return { + data: [ + { + data: member?.organisation.name || 'Not available', + }, + { + data: + ( + + {dateConversion(member?.createDateTime)}{' '} + + ) || 'Not available', + }, + { + data: orgDid ? ( +
    + +
    + ) : ( + + Not available + + ), + }, + { + data: member?.ecosystemRole?.name ? ( + + + {member?.ecosystemRole?.name} + + {member?.orgId === userOrgId ? '(You)' : ''} + + ) : ( + 'Not available' + ), + }, + { + data: member.status ? ( + + {member.status.charAt(0) + + member.status.slice(1).toLowerCase()} + + ) : ( + 'Not available' + ), + }, + ], + }; + }); + + setMemberList(memberList); } else { setError(response as string); } setLoading(false); }; - const onPageChange = (page: number) => { - setCurrentPage({ - ...currentPage, - pageNumber: page, - }); - }; - useEffect(() => { getEcosystemMembers(); }, []); @@ -187,16 +182,11 @@ const MemberList = () => { return (
    -
    -

    - Ecosystem Members -

    -
    - -
    -
    +

    + Ecosystem Members +

    { setError(null); }} /> - - - {currentPage.total > 1 && ( -
    - -
    - )} + currentPage={currentPage?.pageNumber} + onPageChange={(page: number) => { + setCurrentPage({ + ...currentPage, + pageNumber: page, + }); + }} + totalPages={totalItem} + pageInfo={pageInfo} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={false} + message={'No Members'} + discription={"The ecosystem doesn't have any matching member"} + noExtraHeight={true} + >
    ); }; From 88fb8782ab12ffb3d7ad3734997eb1daa67fd1aa Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 17 Jan 2024 19:35:06 +0530 Subject: [PATCH 044/303] handled ecosystem error message Signed-off-by: karan --- src/components/Ecosystem/MemberList.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/Ecosystem/MemberList.tsx b/src/components/Ecosystem/MemberList.tsx index 5aff24d33..09adbc81f 100644 --- a/src/components/Ecosystem/MemberList.tsx +++ b/src/components/Ecosystem/MemberList.tsx @@ -184,16 +184,18 @@ const MemberList = () => { id="ecosystem-datable" className="mt-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 dark:bg-gray-800" > -

    +

    Ecosystem Members

    - { - setError(null); - }} - /> +
    + { + setError(null); + }} + /> +
    Date: Thu, 18 Jan 2024 15:32:12 +0530 Subject: [PATCH 045/303] added sorting Signed-off-by: karan --- src/api/ecosystem.ts | 22 ++++++--- src/components/Ecosystem/MemberList.tsx | 66 ++++++++++++++++--------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/api/ecosystem.ts b/src/api/ecosystem.ts index e72275f56..97d2de28f 100644 --- a/src/api/ecosystem.ts +++ b/src/api/ecosystem.ts @@ -4,6 +4,7 @@ import { apiRoutes } from '../config/apiRoutes'; import { getFromLocalStorage } from './Auth'; import { storageKeys } from '../config/CommonConstant'; import { getHeaderConfigs } from '../config/GetHeaderConfigs'; +import type { IMemberListAPIParameter } from '../components/Ecosystem/MemberList'; interface CreateEcosystemPayload { name: string; @@ -63,7 +64,12 @@ export const updateEcosystem = async (dataPayload: CreateEcosystemPayload) => { } }; -export const getEcosystems = async (orgId: string, pageNumber?: number, pageSize?: number, search = '') => { +export const getEcosystems = async ( + orgId: string, + pageNumber?: number, + pageSize?: number, + search = '', +) => { const url = `${apiRoutes.Ecosystem.root}/${orgId}`; const axiosPayload = { url, @@ -228,14 +234,16 @@ export const getEcosystemDashboard = async ( } }; -export const getEcosystemMemberList = async ( - pageNumber: number, - pageSize: number, - search: string, -) => { +export const getEcosystemMemberList = async ({ + page, + itemPerPage, + search, + sortBy, + sortingOrder, +}: IMemberListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const ecosystemId = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID); - const url = `${apiRoutes.Ecosystem.root}/${ecosystemId}/${orgId}${apiRoutes.Ecosystem.members}?pageNumber=${pageNumber}&pageSize=${pageSize}&search=${search}`; + const url = `${apiRoutes.Ecosystem.root}/${ecosystemId}/${orgId}${apiRoutes.Ecosystem.members}?pageNumber=${page}&pageSize=${itemPerPage}&search=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; const axiosPayload = { url, diff --git a/src/components/Ecosystem/MemberList.tsx b/src/components/Ecosystem/MemberList.tsx index 09adbc81f..cada979c5 100644 --- a/src/components/Ecosystem/MemberList.tsx +++ b/src/components/Ecosystem/MemberList.tsx @@ -11,9 +11,12 @@ import CopyDid from '../../commonComponents/CopyDid'; import SortDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { - pageNumber: 1, - pageSize: 10, - total: 0, + itemPerPage: 10, + page: 1, + search: '', + sortBy: 'createDateTime', + sortingOrder: 'DESC', + allSearch: '', }; interface IMemberList { @@ -31,9 +34,17 @@ interface IMemberList { copied?: boolean; data: Data[]; } - +export interface IMemberListAPIParameter { + itemPerPage: number; + page: number; + search: string; + sortBy: string; + sortingOrder: string; + filter?: string; +} const MemberList = () => { const [loading, setLoading] = useState(false); + const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [memberList, setMemberList] = useState([]); const [error, setError] = useState(null); const [currentPage, setCurrentPage] = useState(initialPageState); @@ -48,34 +59,42 @@ const MemberList = () => { useEffect(() => { let getData: NodeJS.Timeout; - if (searchText.length >= 1) { + if (listAPIParameter?.search?.length >= 1) { getData = setTimeout(() => { - getEcosystemMembers(); + getEcosystemMembers(listAPIParameter); }, 1000); return () => clearTimeout(getData); } else { - getEcosystemMembers(); + getEcosystemMembers(listAPIParameter); } return () => clearTimeout(getData); - }, [searchText, currentPage.pageNumber]); + }, [listAPIParameter]); const refreshPage = () => { - getEcosystemMembers(); + getEcosystemMembers(listAPIParameter); }; const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1, + }); + }; + + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); }; - const getEcosystemMembers = async () => { + const getEcosystemMembers = async (apiParameter: IMemberListAPIParameter) => { const userOrgId = await getFromLocalStorage(storageKeys.ORG_ID); setLoading(true); - const response = await getEcosystemMemberList( - currentPage.pageNumber, - currentPage.pageSize, - searchText, - ); + const response = await getEcosystemMemberList(apiParameter); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { @@ -168,7 +187,7 @@ const MemberList = () => { }; useEffect(() => { - getEcosystemMembers(); + getEcosystemMembers(listAPIParameter); }, []); const header = [ @@ -202,19 +221,20 @@ const MemberList = () => { header={header} data={memberList} loading={loading} - currentPage={currentPage?.pageNumber} + currentPage={listAPIParameter.page} onPageChange={(page: number) => { - setCurrentPage({ - ...currentPage, - pageNumber: page, - }); + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); }} + searchSortByValue={searchSortByValue} totalPages={totalItem} pageInfo={pageInfo} isHeader={true} isSearch={true} isRefresh={true} - isSort={false} + isSort={true} message={'No Members'} discription={"The ecosystem doesn't have any matching member"} noExtraHeight={true} From 0d64a85b73806bc8ab51718fba4e06c6a3f8af8e Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 18 Jan 2024 17:13:16 +0530 Subject: [PATCH 046/303] handled all conditions Signed-off-by: karan --- src/api/ecosystem.ts | 2 +- .../datatable/SortDataTable.tsx | 39 +++---------------- src/commonComponents/datatable/interface.ts | 33 ++++++++++++++++ src/components/Ecosystem/MemberList.tsx | 6 +-- 4 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/api/ecosystem.ts b/src/api/ecosystem.ts index 97d2de28f..e72823489 100644 --- a/src/api/ecosystem.ts +++ b/src/api/ecosystem.ts @@ -243,7 +243,7 @@ export const getEcosystemMemberList = async ({ }: IMemberListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const ecosystemId = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID); - const url = `${apiRoutes.Ecosystem.root}/${ecosystemId}/${orgId}${apiRoutes.Ecosystem.members}?pageNumber=${page}&pageSize=${itemPerPage}&search=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; + const url = `${apiRoutes.Ecosystem.root}/${ecosystemId}/${orgId}${apiRoutes.Ecosystem.members}?pageNumber=${page}&pageSize=${itemPerPage}&search=${search}&sortBy=${sortingOrder.toLocaleLowerCase()}&sortField=${sortBy}`; const axiosPayload = { url, diff --git a/src/commonComponents/datatable/SortDataTable.tsx b/src/commonComponents/datatable/SortDataTable.tsx index 2dfe6825e..33ebfe2d0 100644 --- a/src/commonComponents/datatable/SortDataTable.tsx +++ b/src/commonComponents/datatable/SortDataTable.tsx @@ -1,41 +1,11 @@ -import type { TableData, TableHeader } from './interface'; +import type { IDataTable } from './interface'; import CustomSpinner from '../../components/CustomSpinner'; import SearchInput from '../../components/SearchInput'; import { Pagination } from 'flowbite-react'; import { useState } from 'react'; import { EmptyListMessage } from '../../components/EmptyListComponent'; -interface DataTableProps { - header: TableHeader[]; - data: TableData[]; - loading: boolean; - onInputChange: () => void; - refresh: () => void; - currentPage: any; - onPageChange: () => void; - totalPages: number; - searchSortByValue: (value: any) => void; - isPagination: boolean; - isSearch: boolean; - isRefresh: boolean; - isSort: boolean; - isHeader: boolean; - message: string; - discription: string; - noExtraHeight?: boolean; - callback?: (clickId: string | null | undefined) => void; - displaySelect?: boolean; - showBtn?: boolean; - pageInfo?: - | { - totalItem: number | undefined; - nextPage: number | undefined; - lastPage: number | undefined; - } - | {}; -} - -const SortDataTable: React.FC = ({ +const SortDataTable: React.FC = ({ header, displaySelect, data, @@ -56,9 +26,10 @@ const SortDataTable: React.FC = ({ isHeader, message, discription, - noExtraHeight + noExtraHeight, + sortOrder, }) => { - const [selectedValue, setSelectedValue] = useState(''); + const [selectedValue, setSelectedValue] = useState(sortOrder ?? ''); const handleSortByValues = (event: { target: { value: any } }) => { const newSelectedValue = event.target.value; diff --git a/src/commonComponents/datatable/interface.ts b/src/commonComponents/datatable/interface.ts index ddcd97ac5..2fac2355a 100644 --- a/src/commonComponents/datatable/interface.ts +++ b/src/commonComponents/datatable/interface.ts @@ -1,3 +1,5 @@ +import type { ChangeEvent } from "react"; + export interface TableHeader { columnName: string; subColumnName?: string; @@ -13,3 +15,34 @@ export interface Data { data: string | JSX.Element; subData?: string; } + +export interface IDataTable { + header: TableHeader[]; + data: TableData[]; + loading: boolean; + onInputChange: (e: ChangeEvent) => void; + refresh: () => void; + currentPage: any; + onPageChange: (page: number) => void; + totalPages: number; + searchSortByValue: (value: any) => void; + isPagination?: boolean; + isSearch: boolean; + isRefresh: boolean; + isSort: boolean; + isHeader: boolean; + message: string; + discription: string; + noExtraHeight?: boolean; + callback?: (clickId: string | null | undefined) => void; + displaySelect?: boolean; + showBtn?: boolean; + pageInfo?: + | { + totalItem: number | undefined; + nextPage: number | undefined; + lastPage: number | undefined; + } + | {}; + sortOrder?:string; +} diff --git a/src/components/Ecosystem/MemberList.tsx b/src/components/Ecosystem/MemberList.tsx index cada979c5..3040b5fb5 100644 --- a/src/components/Ecosystem/MemberList.tsx +++ b/src/components/Ecosystem/MemberList.tsx @@ -15,7 +15,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'ASC', allSearch: '', }; @@ -47,8 +47,6 @@ const MemberList = () => { const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [memberList, setMemberList] = useState([]); const [error, setError] = useState(null); - const [currentPage, setCurrentPage] = useState(initialPageState); - const [searchText, setSearchText] = useState(''); const [totalItem, setTotalItem] = useState(0); const [pageInfo, setPageInfo] = useState({ totalItem: '', @@ -235,9 +233,11 @@ const MemberList = () => { isSearch={true} isRefresh={true} isSort={true} + isPagination={true} message={'No Members'} discription={"The ecosystem doesn't have any matching member"} noExtraHeight={true} + sortOrder={listAPIParameter.sortingOrder} >
    ); From 7c4e4291b658cbed12bd9e314c071850e700f5f5 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 18 Jan 2024 17:21:39 +0530 Subject: [PATCH 047/303] fix: margin and padding Signed-off-by: karan --- src/components/Ecosystem/MemberList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Ecosystem/MemberList.tsx b/src/components/Ecosystem/MemberList.tsx index 3040b5fb5..cea92655c 100644 --- a/src/components/Ecosystem/MemberList.tsx +++ b/src/components/Ecosystem/MemberList.tsx @@ -201,7 +201,7 @@ const MemberList = () => { id="ecosystem-datable" className="mt-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 dark:bg-gray-800" > -

    +

    Ecosystem Members

    From 2be0439a346f96391026e3cd92e0f9e9335c9b5d Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 18 Jan 2024 19:29:50 +0530 Subject: [PATCH 048/303] improved tooltip data Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 118 ++++++++++++++++---------- 1 file changed, 75 insertions(+), 43 deletions(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index bf8b62abb..2e3929905 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -422,34 +422,81 @@ const UserDashBoard = () => { const navigateToInvitation = () => { window.location.href = pathRoutes.ecosystem.sentinvitation; }; - const ToolTipData = ({ isEcosystem }: { isEcosystem: boolean }) => { + + const ToolTipDataForOrganization = () => { + return ( +
    +

    What is Organization?

    + An organization is a participating entity, such as +
    a business, institution, or group. Organizations +
    + typically issue and verify some kind of digital +
    + credentials, fostering trust within the digital +
    + ecosystem. +
    + Each organization is uniquely identified by a DID +
    + (Decentralized Identifier), which is verifiable +
    + publicly, thus enhancing the level of trust. +
    + ); + }; + const ToolTipDataForEcosystem = () => { + return ( +
    +

    What is Ecosystem?

    + Ecosystem is a trusted network of organizations +
    + that empowers people and businesses with safe +
    + and secure ways of identifying themselves online +
    + and communicating confidentially with others. +
    + Examples are supply chain, marketplace, healthcare, +
    + banking, etc. where participants exchange +
    + information in an interoperable & trusted manner. +
    + ); + }; + + const ToolTipDataForSchema = () => { + return ( +
    +

    What is Schema?

    + Schema is a machine-readable semantic structure, +
    a predefined data template that provides a +
    + standard format for the digital credential +
    + contents. Schemas define attributes that are +
    + used in one or more Credential Definitions. +
    + Schemas are stored on the ledger. +
    + ); + }; + + const ToolTipDataForCredDef = () => { return (
    -

    - What is {isEcosystem ? 'Ecosystem' : 'Organization'}? -

    {' '} - Contacts are people or organizations you've
    - interacted with. +

    What is Credential Definition?

    + A Credential Definition is a machine-readable +
    + definition of any Schema or in simple terms, +
    a tag created specific to an issuer and Schema. +
    + Credentials are always issued by an issuer
    - You're connected over a secure and private -
    line that no one but you or them can see. -
    Nothing is shared without your permission. -
    You can: + using Cred-Def created by them.
    -
      -
    • Direct message your Contacts
    • -
    • Get offered new credentials
    • -
    • - Get notified of updates to your credentials
      - issued by them -
    • -
    • - Request for information from your Contact
      - or they request information from you -
    • -
    - You can always remove Contacts at any
    - time from your Contacts list. + Credential Definitions are stored on the ledger.
    ); }; @@ -550,7 +597,7 @@ const UserDashBoard = () => { Organizations{' '} } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -801,13 +848,7 @@ const UserDashBoard = () => { Schemas -

    What is schema?

    Schemas - define the attributes that -
    can be included in a credential. -
    - } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -907,7 +948,7 @@ const UserDashBoard = () => { Ecosystems{' '} } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -1045,16 +1086,7 @@ const UserDashBoard = () => { Cred - def -

    What is Cred-def?

    A - credential is a set of one or more
    - claims made by an issuer. A verifiable
    - credential is a tamper-evident
    credential that has - authorship -
    that can be cryptographically verified. -
    - } + content={} placement="bottom" className="items-center text-center dark:text-white" > From b987e7d1284f9c8c14fbd7af6d97c18f78ece2ca Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 18 Jan 2024 19:41:47 +0530 Subject: [PATCH 049/303] fix: width issue Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 2 +- tailwind.config.cjs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 2e3929905..e99467321 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -642,7 +642,7 @@ const UserDashBoard = () => { key={org?.id} > @@ -681,7 +730,11 @@ const UserDashBoard = () => { {' '} @@ -989,7 +1045,12 @@ const UserDashBoard = () => { key={ecosystem?.id} > @@ -1023,26 +1120,24 @@ const UserDashBoard = () => { placement="bottom" className="items-center text-center dark:text-white" > - {' '} - {isEcosystemLead && ( + {ecosystem?.ecosystemOrgs[0]?.ecosystemRole + ?.name === EcosystemRoles.ecosystemLead && ( diff --git a/tailwind.config.cjs b/tailwind.config.cjs index a69c8e4e6..c046b2fd5 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -107,6 +107,7 @@ module.exports = { '100/6rem': 'calc(100% - 6rem)', '100/12rem': 'calc(100% - 12rem)', '100/11rem': 'calc(100% - 11rem)', + '100/3rem': 'calc(100% - 3rem)', }, height: { '100/15rem': 'calc(100vh - 15rem)' From bf7d11b9ab420361317dfbd93d9adb062630d2ed Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 22 Jan 2024 12:11:01 +0530 Subject: [PATCH 051/303] changed verification svg Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 35 +++++++++------------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 9f2d3f401..cd4894be8 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -660,7 +660,7 @@ const UserDashBoard = () => { )} - {org?.name} + {org?.name} {organizationsList[index].userOrgRoles[0] .orgRole.name === @@ -730,11 +730,7 @@ const UserDashBoard = () => { {' '} @@ -1074,7 +1060,10 @@ const UserDashBoard = () => { )} - {ecosystem?.name}{' '} + + {' '} + {ecosystem?.name} + {' '} {ecosystem?.ecosystemOrgs[0]?.ecosystemRole ?.name === EcosystemRoles.ecosystemLead ? ( From 43bab4aa0e88686f4866a8bf9b325a7f4fedad91 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 22 Jan 2024 16:52:31 +0530 Subject: [PATCH 052/303] added sorting in oob Signed-off-by: karan --- src/api/BulkIssuance.ts | 24 ++++--- .../datatable/SortDataTable.tsx | 4 +- src/components/Issuance/History.tsx | 63 ++++++++-------- src/components/Issuance/HistoryDetails.tsx | 71 ++++++++++--------- 4 files changed, 89 insertions(+), 73 deletions(-) diff --git a/src/api/BulkIssuance.ts b/src/api/BulkIssuance.ts index 1a3842bb6..1d5d0ebdf 100644 --- a/src/api/BulkIssuance.ts +++ b/src/api/BulkIssuance.ts @@ -6,6 +6,7 @@ import { } from '../config/GetHeaderConfigs'; import { axiosGet, axiosPost } from '../services/apiRequests'; import { getFromLocalStorage } from './Auth'; +import type { IConnectionListAPIParameter } from './connection'; export const getSchemaCredDef = async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); @@ -124,13 +125,15 @@ export const retryBulkIssuance = async (fileId: string, clientId: string) => { } }; -export const getFilesHistory = async ( - pageNumber: number, - pageSize: number, - search: string, -) => { +export const getFilesHistory = async ({ + page, + itemPerPage, + search, + sortBy, + sortingOrder, +}: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.bulk.files}?pageNumber=${pageNumber}&pageSize=${pageSize}&search=${search}`; + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.bulk.files}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; const axiosPayload = { url, @@ -147,13 +150,14 @@ export const getFilesHistory = async ( export const getFilesDataHistory = async ( requestId: string, - pageNumber: number, - pageSize: number, + itemPerPage: number, + page: number, search: string, - sortBy: string = '', + sortingOrder: string, + sortBy: string, ) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}/${requestId}${apiRoutes.Issuance.bulk.filesData}?pageNumber=${pageNumber}&pageSize=${pageSize}&search=${search}&sortBy=${sortBy}`; + const url = `${apiRoutes.organizations.root}/${orgId}/${requestId}${apiRoutes.Issuance.bulk.filesData}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortBy=${sortBy}&sortField=${sortingOrder}`; const axiosPayload = { url, diff --git a/src/commonComponents/datatable/SortDataTable.tsx b/src/commonComponents/datatable/SortDataTable.tsx index 564753dca..fefc37d94 100644 --- a/src/commonComponents/datatable/SortDataTable.tsx +++ b/src/commonComponents/datatable/SortDataTable.tsx @@ -55,9 +55,9 @@ const SortDataTable: React.FC = ({ const sortValues = [ { label: 'Descending', - value: 'DESC', + value: 'desc', }, - { label: 'Ascending', value: 'ASC' }, + { label: 'Ascending', value: 'asc' }, ]; return ( diff --git a/src/components/Issuance/History.tsx b/src/components/Issuance/History.tsx index ca8568524..9afa4b29c 100644 --- a/src/components/Issuance/History.tsx +++ b/src/components/Issuance/History.tsx @@ -20,14 +20,17 @@ import { import { ToastContainer, toast } from 'react-toastify'; import React from 'react'; import SortDataTable from '../../commonComponents/datatable/SortDataTable'; +import type { IConnectionListAPIParameter } from '../../api/connection'; const HistoryBulkIssuance = () => { const initialPageState = { - pageNumber: 1, - pageSize: 9, - total: 0, + itemPerPage: 10, + page: 1, + search: '', + sortBy: 'createDateTime', + sortingOrder: 'desc', }; - + const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [connectionList, setConnectionList] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -40,12 +43,14 @@ const HistoryBulkIssuance = () => { nextPage: '', lastPage: '', }); - const [searchText, setSearchText] = useState(''); const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1, + }); }; - const handleRetry = async (fileId: string) => { setSuccess('Issuance process reinitiated. Please wait a moment.'); setLoading(true); @@ -55,7 +60,7 @@ const HistoryBulkIssuance = () => { if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { if (data?.data) { setLoading(false); - getHistory(); + getHistory(listAPIParameter); } else { setLoading(false); } @@ -68,6 +73,14 @@ const HistoryBulkIssuance = () => { } }; + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + useEffect(() => { SOCKET.emit('bulk-connection'); SOCKET.on('bulk-issuance-process-retry-completed', () => { @@ -83,7 +96,7 @@ const HistoryBulkIssuance = () => { progress: undefined, theme: 'colored', }); - getHistory(); + getHistory(listAPIParameter); }); SOCKET.on('error-in-bulk-issuance-retry-process', () => { @@ -99,30 +112,26 @@ const HistoryBulkIssuance = () => { progress: undefined, theme: 'colored', }); - getHistory(); + getHistory(listAPIParameter); }); let getData: NodeJS.Timeout; - if (searchText.length >= 1) { + if (listAPIParameter.search.length >= 1) { getData = setTimeout(() => { - getHistory(); + getHistory(listAPIParameter); }, 1000); return () => clearTimeout(getData); } else { - getHistory(); + getHistory(listAPIParameter); } return () => clearTimeout(getData); - }, [searchText, currentPage.pageNumber]); + }, [listAPIParameter]); - const getHistory = async () => { + const getHistory = async (apiParameter: IConnectionListAPIParameter) => { setLoading(true); - const response = await getFilesHistory( - currentPage.pageNumber, - currentPage.pageSize, - searchText, - ); + const response = await getFilesHistory(apiParameter ); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { @@ -134,7 +143,6 @@ const HistoryBulkIssuance = () => { nextPage: nextPage, lastPage: lastPage, }); - const totalPages = data?.data?.lastPage; const connections = data?.data?.data?.map( (ele: { totalRecords: any; @@ -259,10 +267,6 @@ const HistoryBulkIssuance = () => { }, ); setConnectionList(connections); - setCurrentPage({ - ...currentPage, - total: totalPages, - }); } else { if (response?.toString()?.toLowerCase() !== 'history not found') { setFailure(response as string); @@ -282,7 +286,7 @@ const HistoryBulkIssuance = () => { ]; const refreshPage = () => { - getHistory(); + getHistory(listAPIParameter); }; return ( @@ -326,19 +330,20 @@ const HistoryBulkIssuance = () => { header={header} data={connectionList} loading={loading} - currentPage={currentPage?.pageNumber} + currentPage={currentPage?.page} onPageChange={(page: number) => { setCurrentPage((prevState) => ({ ...prevState, page, })); }} - totalPages={Math.ceil(totalItem / currentPage?.pageSize)} + searchSortByValue={searchSortByValue} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} pageInfo={pageInfo} isHeader={true} isSearch={true} isRefresh={true} - isSort={false} + isSort={true} message={'No History'} discription={"You don't have any activities yet"} > diff --git a/src/components/Issuance/HistoryDetails.tsx b/src/components/Issuance/HistoryDetails.tsx index bdc4103fc..52eb85f67 100644 --- a/src/components/Issuance/HistoryDetails.tsx +++ b/src/components/Issuance/HistoryDetails.tsx @@ -11,6 +11,7 @@ import { getFilesDataHistory } from '../../api/BulkIssuance'; import type { AxiosResponse } from 'axios'; import { BulkIssuanceStatus } from '../../common/enums'; import SortDataTable from '../../commonComponents/datatable/SortDataTable'; +import type { IConnectionListAPIParameter } from '../../api/connection'; interface IProps { requestId: string; @@ -18,15 +19,17 @@ interface IProps { const HistoryDetails = ({ requestId }: IProps) => { const initialPageState = { - pageNumber: 1, - pageSize: 10, - total: 0, + itemPerPage: 10, + page: 1, + search: '', + sortBy: 'createDateTime', + sortingOrder: 'desc', }; + + const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [historyList, setHistoryList] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [currentPage, setCurrentPage] = useState(initialPageState); - const [searchText, setSearchText] = useState(''); const [totalItem, setTotalItem] = useState(0); const [pageInfo, setPageInfo] = useState({ totalItem: '', @@ -37,30 +40,21 @@ const HistoryDetails = ({ requestId }: IProps) => { useEffect(() => { let getData: NodeJS.Timeout; - if (searchText.length >= 1) { + if (listAPIParameter.search.length >= 1) { getData = setTimeout(() => { - getHistoryDetails(); + getHistoryDetails(listAPIParameter); }, 1000); return () => clearTimeout(getData); } else { - getHistoryDetails(); + getHistoryDetails(listAPIParameter); } return () => clearTimeout(getData); - }, [searchText, currentPage.pageNumber]); + }, [listAPIParameter]); - const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); - }; - - const getHistoryDetails = async () => { + const getHistoryDetails = async (apiParameter: IConnectionListAPIParameter) => { setLoading(true); - const response = await getFilesDataHistory( - requestId, - currentPage.pageNumber, - currentPage.pageSize, - searchText, - ); + const response = await getFilesDataHistory(requestId, apiParameter.itemPerPage, apiParameter.page, apiParameter.search, apiParameter.sortBy, apiParameter.sortingOrder); const { data } = response as AxiosResponse; @@ -116,18 +110,30 @@ const HistoryDetails = ({ requestId }: IProps) => { }, ); setHistoryList(historyData); - setCurrentPage({ - ...currentPage, - total: totalPages, - }); } else { setError(response as string); } setLoading(false); }; + const searchInputChange = (e: ChangeEvent) => { + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1, + }); + }; + + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + const refreshPage = () => { - getHistoryDetails(); + getHistoryDetails(listAPIParameter); }; const header = [ { columnName: 'User' }, @@ -166,19 +172,20 @@ const HistoryDetails = ({ requestId }: IProps) => { header={header} data={historyList} loading={loading} - currentPage={currentPage?.pageNumber} + currentPage={listAPIParameter?.page} onPageChange={(page: number) => { - setCurrentPage({ - ...currentPage, - pageNumber: page, - }); + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); }} - totalPages={Math.ceil(totalItem / currentPage?.pageSize)} + searchSortByValue={searchSortByValue} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} pageInfo={pageInfo} isHeader={true} isSearch={true} isRefresh={true} - isSort={false} + isSort={true} message={'No History'} discription={"You don't have any activities yet"} > From 6e3d75f71b0eb3e7fdb8452aee97bd8c7144622b Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 22 Jan 2024 16:59:06 +0530 Subject: [PATCH 053/303] improved sorting Signed-off-by: karan --- src/components/ConnectionsList/index.tsx | 2 +- src/components/Issuance/IssuedCrdentials.tsx | 2 +- src/components/Verification/VerificationCredentialList.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ConnectionsList/index.tsx b/src/components/ConnectionsList/index.tsx index b891faf89..099e2d4c9 100644 --- a/src/components/ConnectionsList/index.tsx +++ b/src/components/ConnectionsList/index.tsx @@ -22,7 +22,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; const ConnectionList = () => { diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 6b3517383..7f584da16 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -27,7 +27,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 2c0274ac8..14f30bd0a 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -34,7 +34,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; From 482e6cb00b493b6337c1f338e6cf304d6e553f6a Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 22 Jan 2024 17:43:10 +0530 Subject: [PATCH 054/303] handled spell check Signed-off-by: karan --- src/components/User/UserDashBoard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index cd4894be8..e5319dfd4 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -868,7 +868,7 @@ const UserDashBoard = () => { ) : (
    -

    You have no organisations created or joined

    +

    You have no organizations created or joined

    )} From 371b75ac97d54bc152bdf93a3c0fae95fbabd4b6 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 23 Jan 2024 16:13:13 +0530 Subject: [PATCH 055/303] feat: client credentials Signed-off-by: karan --- src/app/NavBarSidebar.astro | 7 + src/components/Setting/index.tsx | 256 +++++++++++++++++++++++++++++++ src/config/apiRoutes.ts | 3 + src/config/pathRoutes.ts | 1 + src/pages/setting/index.astro | 15 ++ 5 files changed, 282 insertions(+) create mode 100644 src/components/Setting/index.tsx create mode 100644 src/pages/setting/index.astro diff --git a/src/app/NavBarSidebar.astro b/src/app/NavBarSidebar.astro index 1f55009d7..31f39240a 100644 --- a/src/app/NavBarSidebar.astro +++ b/src/app/NavBarSidebar.astro @@ -434,6 +434,13 @@ const permittedPages = RolePermissions.find( role="menuitem">Profile +
  • + Setting +
  • diff --git a/src/components/Setting/index.tsx b/src/components/Setting/index.tsx new file mode 100644 index 000000000..d34085a84 --- /dev/null +++ b/src/components/Setting/index.tsx @@ -0,0 +1,256 @@ +import { Alert, Button } from 'flowbite-react'; +import React, { useEffect, useState } from 'react'; +import CustomSpinner from '../CustomSpinner'; +import { getFromLocalStorage } from '../../api/Auth'; +import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; +import { apiRoutes } from '../../config/apiRoutes'; +import { getHeaderConfigs } from '../../config/GetHeaderConfigs'; +import { axiosGet, axiosPost } from '../../services/apiRequests'; +import type { AxiosResponse } from 'axios'; +import CopyDid from '../../commonComponents/CopyDid'; +import { AlertComponent } from '../AlertComponent'; + +const index = () => { + const [loading, setLoading] = useState(true); + const [clentId, setClientId] = useState(''); + const [clientSecret, setClientSecret] = useState(''); + const [success, setSuccess] = useState(null); + const [failure, setFailure] = useState(null); + const [warning, setWarning] = useState(null); + const [hideCopy, setHideCopy] = useState(true); + + const getCredentials = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.setting.setting}`; + + const axiosPayload = { + url, + config: await getHeaderConfigs(), + }; + + try { + return await axiosGet(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } + }; + + const createCredentials = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.setting.setting}`; + + const axiosPayload = { + url, + config: await getHeaderConfigs(), + }; + try { + return await axiosPost(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } + }; + + const createClientCredentials = async () => { + console.log('--------', 'create'); + + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + + if (orgId) { + setLoading(true); + try { + // const response = await createCredentials(); + // const { data } = response as AxiosResponse; + + const data = { + statusCode: 201, + message: 'Organization credentials created successfully', + data: { + clientId: '5d1533ac-0432-4da4-bd15-e86dc5465c0a', + clientSecret: 'T7QSRemu1MtcN1rjyVZ3uNA9FzVkp2U9', + }, + }; + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + setHideCopy(false); + + setClientId(data.data.clientId); + setClientSecret(data.data.clientSecret); + setSuccess(data.message); + setWarning( + 'Make sure to copy your new client secret now. You won’t be able to see it again.', + ); + } + } catch (error) { + setFailure(error as string); + } finally { + setLoading(false); + } + } else { + setLoading(false); + } + }; + + const getClientCredentials = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + + if (orgId) { + setLoading(true); + try { + // const response = await getCredentials(); + // const { data } = response as AxiosResponse; + const data = { + statusCode: 200, + message: 'Organization credentials fetched successfully', + data: { + clientId: '5d1533ac-0432-4da4-bd15-e86dc5465c0a', + clientSecret: '************************FzVkp2U9', + }, + }; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setHideCopy(true); + setClientId(data.data.clientId); + setClientSecret(data.data.clientSecret); + } + } catch (error) { + setFailure(error as string); + setLoading(false); + } finally { + setLoading(false); + } + } else { + setLoading(false); + } + }; + + const deleteKey = () => { + setClientSecret(null); + }; + + useEffect(() => { + getClientCredentials(); + }, []); + + return ( +
    +
    +
    +
    + {loading ? ( +
    + +
    + ) : ( +
    + {(success || failure) && ( + { + setSuccess(null); + setFailure(null); + }} + /> + )} +
    +
    +

    + Client Id : +

    +

    + {clentId && ( + + )} +

    +
    + +
    +
    +

    + Client Secrate +

    +
    + +
    +
    + {warning && ( + { + setWarning(null); + setFailure(null); + }} + /> + )} + + {clentId && ( +
    +
    kkk
    +
    +

    + {!hideCopy ? ( + clientSecret && ( + + ) + ) : ( +

    + {' '} + {clientSecret} +

    + )} +

    +
    +
    + +
    +
    + )} +
    +
    + + )} +
    +
    +
    +
    + ); +}; + +export default index; diff --git a/src/config/apiRoutes.ts b/src/config/apiRoutes.ts index 361dea32a..9acbf4157 100644 --- a/src/config/apiRoutes.ts +++ b/src/config/apiRoutes.ts @@ -98,4 +98,7 @@ export const apiRoutes = { usersInvitation: '/users/invitations', members: '/members', }, + setting:{ + setting: '/client_credentials' + } }; diff --git a/src/config/pathRoutes.ts b/src/config/pathRoutes.ts index 8bac068e3..94d370fdf 100644 --- a/src/config/pathRoutes.ts +++ b/src/config/pathRoutes.ts @@ -11,6 +11,7 @@ export const pathRoutes = { fetchUsers: '/users', connectionList: '/connections', platformSetting: '/platform-settings', + setting: '/setting' }, organizations: { root: '/organizations', diff --git a/src/pages/setting/index.astro b/src/pages/setting/index.astro new file mode 100644 index 000000000..254629dc4 --- /dev/null +++ b/src/pages/setting/index.astro @@ -0,0 +1,15 @@ +--- +import LayoutSidebar from "../../app/LayoutSidebar.astro"; +import Setting from '../../components/Setting' +import { pathRoutes } from "../../config/pathRoutes"; +import { checkUserSession } from "../../utils/check-session"; +const response = await checkUserSession({cookies: Astro.cookies, currentPath: Astro.url.pathname}); +const route: string = pathRoutes.auth.sinIn +if (!response.authorized) { + return Astro.redirect(response.redirect); +} +--- + + + + From 6fd84c04d7c14765c0eb190752176439dca642a7 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 23 Jan 2024 16:45:24 +0530 Subject: [PATCH 056/303] fix: PR Commits Signed-off-by: karan --- src/app/SideBar.astro | 253 ++++++++++++++++++-------- src/components/User/UserDashBoard.tsx | 29 ++- 2 files changed, 195 insertions(+), 87 deletions(-) diff --git a/src/app/SideBar.astro b/src/app/SideBar.astro index 051c0cc05..760d54832 100644 --- a/src/app/SideBar.astro +++ b/src/app/SideBar.astro @@ -57,9 +57,19 @@ import { pathRoutes } from '../config/pathRoutes'; href={pathRoutes.users.dashboard} class="flex items-center p-2 text-base text-gray-900 transition duration-75 rounded-lg hover:bg-gray-100 group dark:text-gray-200 dark:hover:bg-gray-700" > - - - + + + Dashboard @@ -69,9 +79,22 @@ import { pathRoutes } from '../config/pathRoutes'; href={pathRoutes.organizations.root} class="flex items-center p-2 text-base text-gray-900 rounded-lg hover:bg-gray-100 group dark:text-gray-200 dark:hover:bg-gray-700" > - - - + + + Organizations @@ -81,9 +104,19 @@ import { pathRoutes } from '../config/pathRoutes'; href={pathRoutes.organizations.users} class="flex items-center p-2 text-base text-gray-900 rounded-lg hover:bg-gray-100 group dark:text-gray-200 dark:hover:bg-gray-700" > - - - + + + Users @@ -94,9 +127,22 @@ import { pathRoutes } from '../config/pathRoutes'; href={pathRoutes.users.connectionList} class="flex items-center p-2 text-base text-gray-900 rounded-lg hover:bg-gray-100 group dark:text-gray-200 dark:hover:bg-gray-700" > - - - + + + Connections @@ -108,9 +154,22 @@ import { pathRoutes } from '../config/pathRoutes'; aria-controls="dropdown-credentials" data-collapse-toggle="dropdown-credentials" > - - - + + + - - - - - + + + + + Issue @@ -149,16 +230,20 @@ import { pathRoutes } from '../config/pathRoutes'; href={pathRoutes.organizations.credentials} class="flex items-center p-2 text-base text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" > - - - - - - - - - - + + + + Verify @@ -171,46 +256,75 @@ import { pathRoutes } from '../config/pathRoutes';
  • - - - - GitHub Repository - -
  • -
  • - - - - - - Documentation - -
  • - -
  • - - - - - - Support - -
  • + href={'https://github.com/credebl'} + target="_blank" + class="flex items-center p-2 text-base text-gray-900 transition duration-75 rounded-lg hover:bg-gray-100 group dark:text-gray-200 dark:hover:bg-gray-700" + > + + + + GitHub Repository + + +
  • + + + + -
  • + Documentation + + + +
  • + + + + + Support + +
  • +
    -
    diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index e5319dfd4..d250c5be6 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -461,16 +461,13 @@ const UserDashBoard = () => { return (

    What is Schema?

    - Schema is a machine-readable semantic structure, -
    a predefined data template that provides a -
    - standard format for the digital credential -
    - contents. Schemas define attributes that are -
    - used in one or more Credential Definitions. -
    - Schemas are stored on the ledger. + Schema is a machine-readable semantic +
    structure, a predefined data template +
    that provides a standard format for the +
    digital credential contents. Schemas +
    define attributes that are used in one +
    or more Credential Definitions. +
    Schemas are stored on the ledger.
    ); }; @@ -523,7 +520,7 @@ const UserDashBoard = () => { <> ) : (
    {walletLoading ? ( @@ -867,8 +864,8 @@ const UserDashBoard = () => { )}{' '} ) : ( -
    -

    You have no organizations created or joined

    +
    +

    You have no organizations created or joined

    )} @@ -963,7 +960,7 @@ const UserDashBoard = () => {
    ) : (
    -

    You have no schemas created

    +

    You have no schemas created

    )} @@ -1148,7 +1145,7 @@ const UserDashBoard = () => { ) : (
    -

    You have no ecosystems created or joined

    +

    You have no ecosystems created or joined

    )} @@ -1233,7 +1230,7 @@ const UserDashBoard = () => { ) : (
    -

    You have no cred-defs created

    +

    You have no cred-defs created

    )}{' '} From 4c5822066b351f9fd20b17036d2b20006868dc89 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 23 Jan 2024 19:37:11 +0530 Subject: [PATCH 057/303] added org roles Signed-off-by: karan --- src/components/Setting/index.tsx | 151 +++++++++++++++++++++---------- 1 file changed, 101 insertions(+), 50 deletions(-) diff --git a/src/components/Setting/index.tsx b/src/components/Setting/index.tsx index d34085a84..fa5e6b881 100644 --- a/src/components/Setting/index.tsx +++ b/src/components/Setting/index.tsx @@ -9,6 +9,7 @@ import { axiosGet, axiosPost } from '../../services/apiRequests'; import type { AxiosResponse } from 'axios'; import CopyDid from '../../commonComponents/CopyDid'; import { AlertComponent } from '../AlertComponent'; +import { Roles } from '../../utils/enums/roles'; const index = () => { const [loading, setLoading] = useState(true); @@ -18,6 +19,8 @@ const index = () => { const [failure, setFailure] = useState(null); const [warning, setWarning] = useState(null); const [hideCopy, setHideCopy] = useState(true); + const [userRoles, setUserRoles] = useState([]); + console.log('userRoles', userRoles); const getCredentials = async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); @@ -127,8 +130,15 @@ const index = () => { setClientSecret(null); }; + const getUserRoles = async () => { + const orgRoles = await getFromLocalStorage(storageKeys.ORG_ROLES); + const roles = orgRoles.split(','); + setUserRoles(roles); + }; + useEffect(() => { getClientCredentials(); + getUserRoles(); }, []); return ( @@ -172,31 +182,34 @@ const index = () => {

    Client Secrate

    -
    - -
    + + + + Generate Client Secrate{' '} + +
    + )} {warning && ( { }} /> )} - + {/* {clentId && (
    -
    kkk
    -
    -

    - {!hideCopy ? ( - clientSecret && ( - - ) - ) : ( -

    - {' '} - {clientSecret} -

    - )} -

    +
    +
    SVG
    +
    +

    + {!hideCopy ? ( + clientSecret && ( + + ) + ) : ( +
    + {clientSecret} +
    + )} +

    +
    -
    - + {(userRoles.includes(Roles.OWNER) || + userRoles.includes(Roles.ADMIN)) && ( +
    + +
    + )} +
    + )} */} + + {clentId && ( +
    +
    +
    SVG
    +
    +

    + {!hideCopy + ? clientSecret && ( + + ) + : {clientSecret}} +

    +
    + {(userRoles.includes(Roles.OWNER) || + userRoles.includes(Roles.ADMIN)) && ( +
    + +
    + )}
    )}
    From ca5fb74970b8f7456c0193370572690adc392cb4 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 24 Jan 2024 15:20:52 +0530 Subject: [PATCH 058/303] fix: org and ecosystem edit popup Signed-off-by: karan --- src/components/Ecosystem/interfaces/index.ts | 22 +- .../EditEcosystemOrgModal/index.tsx | 775 +++++++++--------- src/components/User/UserDashBoard.tsx | 4 +- src/components/organization/Dashboard.tsx | 46 +- .../organization/EditOrgdetailsModal.tsx | 46 +- 5 files changed, 483 insertions(+), 410 deletions(-) diff --git a/src/components/Ecosystem/interfaces/index.ts b/src/components/Ecosystem/interfaces/index.ts index 479f2f950..bc85f9042 100644 --- a/src/components/Ecosystem/interfaces/index.ts +++ b/src/components/Ecosystem/interfaces/index.ts @@ -26,4 +26,24 @@ export interface Ecosystem { website: string roles: string[] logoFile:string -} \ No newline at end of file +} + +export interface EditEntityModalProps { + openModal: boolean; + setMessage: (message: string) => void; + setOpenModal: (flag: boolean) => void; + onEditSuccess?: () => void; + entityData: Ecosystem | null; + isOrganization: boolean; +} + +export interface EditEntityValues { + name: string; + description: string; +} + +export interface ILogoImage { + logoFile: string | File; + imagePreviewUrl: string | ArrayBuffer | null | File; + fileName: string; +} diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index 549fc273d..c0301bf85 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -1,396 +1,437 @@ -import * as yup from "yup"; +import * as yup from 'yup'; import { Avatar, Button, Label, Modal } from 'flowbite-react'; import { Field, Form, Formik, FormikHelpers } from 'formik'; -import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, apiStatusCodes, imageSizeAccepted } from '../../config/CommonConstant'; -import { calculateSize, dataURItoBlob } from "../../utils/CompressImage"; -import { AlertComponent } from "../AlertComponent"; +import { + IMG_MAX_HEIGHT, + IMG_MAX_WIDTH, + apiStatusCodes, + imageSizeAccepted, +} from '../../config/CommonConstant'; +import { calculateSize, dataURItoBlob } from '../../utils/CompressImage'; +import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; -import { updateOrganization } from "../../api/organization"; -import { updateEcosystem } from "../../api/ecosystem"; -import type { Ecosystem } from "../Ecosystem/interfaces"; -import React, { useEffect, useState } from "react"; -import EndorsementTooltip from "../../commonComponents/EndorsementTooltip"; - -interface EditEntityModalProps { - openModal: boolean; - setMessage: (message: string) => void; - setOpenModal: (flag: boolean) => void; - onEditSuccess?: () => void; - entityData: Ecosystem | null; - isOrganization: boolean; - -} - -interface EditEntityValues { - name: string; - description: string; -} - -interface ILogoImage { - logoFile: string | File; - imagePreviewUrl: string | ArrayBuffer | null | File; - fileName: string; -} +import { updateOrganization } from '../../api/organization'; +import { updateEcosystem } from '../../api/ecosystem'; +import type { Ecosystem, EditEntityModalProps, EditEntityValues, ILogoImage } from '../Ecosystem/interfaces'; +import React, { useEffect, useState } from 'react'; +import EndorsementTooltip from '../../commonComponents/EndorsementTooltip'; const EditPopupModal = (props: EditEntityModalProps) => { - const [logoImage, setLogoImage] = useState({ - logoFile: "", - imagePreviewUrl: props?.entityData?.logoUrl ?? "", - fileName: '', - }); + + const [logoImage, setLogoImage] = useState({ + logoFile: '', + imagePreviewUrl: props?.entityData?.logoUrl ?? '', + fileName: '', + }); - const [loading, setLoading] = useState(false); - const [isImageEmpty, setIsImageEmpty] = useState(true); - const [initialEntityData, setInitialEntityData] = useState({ - name: "", - description: "" - }); + const [loading, setLoading] = useState(false); + const [isImageEmpty, setIsImageEmpty] = useState(true); + const [initialEntityData, setInitialEntityData] = useState({ + name: '', + description: '', + }); - useEffect(() => { - if (props.openModal && props.entityData) { - setInitialEntityData({ - name: props.entityData.name ?? "", - description: props.entityData.description ?? "", - }); - SetisAutoEndorse(props.entityData.autoEndorsement) - setLogoImage({ - logoFile: "", - imagePreviewUrl: props.entityData.logoUrl ?? "", - fileName: props.entityData.logoFile ?? "", - }); - } - }, [props.entityData, props.openModal]); + useEffect(() => { + if (props.openModal && props.entityData) { + setInitialEntityData({ + name: props.entityData.name ?? '', + description: props.entityData.description ?? '', + }); + SetisAutoEndorse(props.entityData.autoEndorsement); + setLogoImage({ + logoFile: '', + imagePreviewUrl: props.entityData.logoUrl ?? '', + fileName: props.entityData.logoFile ?? '', + }); + } + }, [props.entityData, props.openModal]); - const [errMsg, setErrMsg] = useState(null); - const [imgError, setImgError] = useState(''); - const [isAutoEndorse, SetisAutoEndorse] = useState(false) + const [errMsg, setErrMsg] = useState(null); + const [imgError, setImgError] = useState(''); + const [isAutoEndorse, SetisAutoEndorse] = useState(false); + useEffect(() => { + if (!props.openModal) { + setInitialEntityData({ + name: '', + description: '', + }); - useEffect(() => { - if (!props.openModal) { - setInitialEntityData({ - name: "", - description: "", - }); + setLogoImage({ + logoFile: '', + imagePreviewUrl: '', + fileName: '', + }); + setImgError(''); + setErrMsg(null); + setLoading(false); + } + }, [props.openModal]); - setLogoImage({ - logoFile: "", - imagePreviewUrl: "", - fileName: "", - }); - setImgError(''); - setErrMsg(null); - setLoading(false); - } - }, [props.openModal]); - - const processImage = (e: any): string | undefined => { - const file = e?.target?.files[0]; - if (!file) return; + const processImage = (e: any): string | undefined => { + const file = e?.target?.files[0]; + if (!file) return; - const reader = new FileReader(); - reader.readAsDataURL(file); + const reader = new FileReader(); + reader.readAsDataURL(file); - reader.onload = (event): void => { - const imgElement = document.createElement("img"); - if (imgElement) { - imgElement.src = typeof event?.target?.result === 'string' ? event.target.result : ""; - imgElement.onload = (e): void => { - let fileUpdated: File | string = file; - let srcEncoded = ''; - const canvas = document.createElement("canvas"); + reader.onload = (event): void => { + const imgElement = document.createElement('img'); + if (imgElement) { + imgElement.src = + typeof event?.target?.result === 'string' ? event.target.result : ''; + imgElement.onload = (e): void => { + let fileUpdated: File | string = file; + let srcEncoded = ''; + const canvas = document.createElement('canvas'); - const { width, height, ev } = calculateSize(imgElement, IMG_MAX_WIDTH, IMG_MAX_HEIGHT); - canvas.width = width; - canvas.height = height; + const { width, height, ev } = calculateSize( + imgElement, + IMG_MAX_WIDTH, + IMG_MAX_HEIGHT, + ); + canvas.width = width; + canvas.height = height; - const ctx = canvas.getContext("2d"); - if (ctx && e?.target) { - ctx.imageSmoothingEnabled = true; - ctx.imageSmoothingQuality = "high"; - ctx.drawImage(ev, 0, 0, canvas.width, canvas.height); - srcEncoded = ctx.canvas.toDataURL(ev, file.type); - const blob = dataURItoBlob(srcEncoded, file.type); - fileUpdated = new File([blob], file.name, { type: file.type, lastModified: new Date().getTime() }); - setLogoImage({ - logoFile: fileUpdated, - imagePreviewUrl: srcEncoded, - fileName: file.name - }); - } - }; - } - }; - }; - - const handleImageChange = (event: any): void => { - setImgError(''); - const reader = new FileReader(); - const file = event?.target?.files; - - const fileSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); - const extension = file[0]?.name?.substring(file[0]?.name?.lastIndexOf(".") + 1)?.toLowerCase(); + const ctx = canvas.getContext('2d'); + if (ctx && e?.target) { + ctx.imageSmoothingEnabled = true; + ctx.imageSmoothingQuality = 'high'; + ctx.drawImage(ev, 0, 0, canvas.width, canvas.height); + srcEncoded = ctx.canvas.toDataURL(ev, file.type); + const blob = dataURItoBlob(srcEncoded, file.type); + fileUpdated = new File([blob], file.name, { + type: file.type, + lastModified: new Date().getTime(), + }); + setLogoImage({ + logoFile: fileUpdated, + imagePreviewUrl: srcEncoded, + fileName: file.name, + }); + } + }; + } + }; + }; - if (extension === "png" || extension === "jpeg" || extension === "jpg") { - if (fileSize <= imageSizeAccepted) { - reader.onloadend = (): void => { - processImage(event); - setIsImageEmpty(false); - }; - reader.readAsDataURL(file[0]); - event.preventDefault(); - } else { - setImgError("Please check image size"); - } - } else { - setImgError("Invalid image type"); - } - }; + const isEmpty = (object: any): boolean => { + for (const property in object) { + return false; + } + return true; + }; + + const handleImageChange = (event: any): void => { + setImgError(''); + const reader = new FileReader(); + const file = event?.target?.files; - const isEmpty = (object: any): boolean => { + const fileSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); + const extension = file[0]?.name + ?.substring(file[0]?.name?.lastIndexOf('.') + 1) + ?.toLowerCase(); - return true; - }; + if (extension === 'png' || extension === 'jpeg' || extension === 'jpg') { + if (fileSize <= imageSizeAccepted) { + reader.onloadend = (): void => { + processImage(event); + setIsImageEmpty(false); + }; + reader.readAsDataURL(file[0]); + event.preventDefault(); + } else { + setImgError('Please check image size'); + } + } else { + setImgError('Invalid image type'); + } + }; - const submitUpdateEntity = async (values: EditEntityValues) => { - setLoading(true); - const entityData = { - id: props?.entityData?.id, - name: values.name, - description: values.description, - logo: logoImage?.imagePreviewUrl as string || props?.entityData?.logoUrl, - autoEndorsement:isAutoEndorse - }; + const submitUpdateEntity = async (values: EditEntityValues) => { + setLoading(true); - try { - if (props.isOrganization) { - const response = await updateOrganization(entityData, entityData.id?.toString() as string); - const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - if (props?.onEditSuccess) { - props?.onEditSuccess(); - } - props.setOpenModal(false); - } else { - setErrMsg(data?.message as string); - } - } else { - const response = await updateEcosystem(entityData); - const { data } = response as AxiosResponse; + const entityData = { + id: props?.entityData?.id, + name: values.name, + description: values.description, + logo: + (logoImage?.imagePreviewUrl as string) || props?.entityData?.logoUrl, + autoEndorsement: isAutoEndorse, + }; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - if (props?.onEditSuccess) { - props?.onEditSuccess(); - } - props.setOpenModal(false); - } else { - setErrMsg(data?.message as string); - } - } - } catch (error) { - console.error("An error occurred:", error); - setLoading(false); - } - }; - return ( - { - setLogoImage({ - logoFile: "", - imagePreviewUrl: "", - fileName: '' - }); - setInitialEntityData({ - name: "", - description: "" - }); - props.setOpenModal(false); - }}> - Edit {props.isOrganization ? "Organization" : "Ecosystem"} - - { - setErrMsg(null); - }} - /> - - ) => { - await submitUpdateEntity(values); - }} - > - {(formikHandlers): JSX.Element => ( -
    -
    -
    - {logoImage.imagePreviewUrl ? ( - {`${props.isOrganization - ) : ( - - )} - -
    -

    - {props.isOrganization ? "Organization Logo" : "Ecosystem Logo"} -

    -
    - JPG, JPEG and PNG. Max size of 1MB -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - { - const value = e.target.value; - formikHandlers.setFieldValue('name', value); - formikHandlers.setFieldTouched('name', true, false); - - if (value.length > 50) { - formikHandlers.setFieldError('name', props.isOrganization ? 'Organization name must be at most 50 characters' : 'Ecosystem name must be at most 50 characters'); - } - }} + try { + if (props.isOrganization) { + const response = await updateOrganization( + entityData, + entityData.id?.toString() as string, + ); + const { data } = response as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (props?.onEditSuccess) { + props?.onEditSuccess(); + } + props.setOpenModal(false); + props.setMessage(data?.message) + } else { + setErrMsg(response as string); + setLoading(false); + } + } else { + const response = await updateEcosystem(entityData); + const { data } = response as AxiosResponse; - /> - {formikHandlers?.errors?.name && formikHandlers?.touched?.name && ( - {formikHandlers?.errors?.name} - )} -
    -
    -
    -
    - { - const value = e.target.value; - formikHandlers.setFieldValue('description', value); - formikHandlers.setFieldTouched('description', true, false); - - if (value.length > 50) { - formikHandlers.setFieldError('description', 'Description must be at most 255 characters'); - } - }} + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (props?.onEditSuccess) { + props?.onEditSuccess(); + } + props.setOpenModal(false); + props.setMessage(data?.message) + } else { + setErrMsg(response as string); + setLoading(false); + } + } + } catch (error) { + console.error('An error occurred:', error); + setLoading(false); + } + }; + return ( + { + setLogoImage({ + logoFile: '', + imagePreviewUrl: '', + fileName: '', + }); + setInitialEntityData({ + name: '', + description: '', + }); + props.setOpenModal(false); + }} + > + + Edit {props.isOrganization ? 'Organization' : 'Ecosystem'} + + + { + setErrMsg(null); + }} + /> + , + ) => { + await submitUpdateEntity(values); + }} + > + {(formikHandlers): JSX.Element => ( + +
    +
    + {logoImage.imagePreviewUrl ? ( + {`${ + ) : ( + + )} - /> - {formikHandlers?.errors?.description && formikHandlers?.touched?.description && ( - {formikHandlers?.errors?.description} - )} -
    -
    -
    -
    +
    +
    +
    +
    + { + const value = e.target.value; + formikHandlers.setFieldValue('name', value); + formikHandlers.setFieldTouched('name', true, false); + + if (value.length > 50) { + formikHandlers.setFieldError( + 'name', + props.isOrganization + ? 'Organization name must be at most 50 characters' + : 'Ecosystem name must be at most 50 characters', + ); + } + }} + /> + {formikHandlers?.errors?.name && + formikHandlers?.touched?.name && ( + + {formikHandlers?.errors?.name} + + )} +
    +
    +
    +
    + { + const value = e.target.value; + formikHandlers.setFieldValue('description', value); + formikHandlers.setFieldTouched('description', true, false); - Update - - - )} - - - - ); + if (value.length > 50) { + formikHandlers.setFieldError( + 'description', + 'Description must be at most 255 characters', + ); + } + }} + /> + {formikHandlers?.errors?.description && + formikHandlers?.touched?.description && ( + + {formikHandlers?.errors?.description} + + )} +
    +
    +
    +
    +
    + SetisAutoEndorse(false)} + /> + + Sign + +
    +
    + SetisAutoEndorse(true)} + /> + + Sign and Submit + +
    +
    + + + )} + + + + ); }; -export default EditPopupModal; \ No newline at end of file +export default EditPopupModal; diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index d250c5be6..ea2b77967 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -531,10 +531,10 @@ const UserDashBoard = () => {

    - Wallet lets you create schemas and credential-definitions + Wallet lets you create schemas and credential definitions

    - Please create wallet for your organisation which would + Please create wallet for your organization which would help you to issue and verify credentials for your users.
    diff --git a/src/components/organization/Dashboard.tsx b/src/components/organization/Dashboard.tsx index fad946d4d..76358e020 100644 --- a/src/components/organization/Dashboard.tsx +++ b/src/components/organization/Dashboard.tsx @@ -18,6 +18,7 @@ import WalletSpinup from './WalletSpinup'; import { getFromLocalStorage } from '../../api/Auth'; import { pathRoutes } from '../../config/pathRoutes'; import DashboardCard from '../../commonComponents/DashboardCard'; +import { AlertComponent } from '../AlertComponent'; const Dashboard = () => { const [orgData, setOrgData] = useState(null); @@ -30,16 +31,11 @@ const Dashboard = () => { const [loading, setLoading] = useState(true); const [userRoles, setUserRoles] = useState([]); - + const [orgSuccess, setOrgSuccess] = useState(null); const [openModal, setOpenModal] = useState(false); - const props = { openModal, setOpenModal }; const EditOrgDetails = () => { - props.setOpenModal(true); - }; - - const updateOrganizationData = (updatedData: Organisation) => { - setOrgData(updatedData); + setOpenModal(true); }; const getUserRoles = async () => { @@ -54,11 +50,8 @@ const Dashboard = () => { const fetchOrganizationDetails = async () => { setLoading(true); - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const response = await getOrganizationById(orgId as string); - const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { @@ -74,11 +67,8 @@ const Dashboard = () => { const fetchOrganizationDashboard = async () => { setLoading(true); - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const response = await getOrgDashboard(orgId as string); - const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { @@ -94,6 +84,11 @@ const Dashboard = () => { fetchOrganizationDashboard(); }, []); + const handleEditModalClose = () => { + setOpenModal(false); + fetchOrganizationDetails(); + }; + useEffect(() => { setTimeout(() => { setSuccess(null); @@ -101,10 +96,6 @@ const Dashboard = () => { }, 3000); }, [success !== null, failure !== null]); - const redirectDashboardInvitations = () => { - window.location.href = '/organizations/invitations'; - }; - const setWalletSpinupStatus = (status: boolean) => { setSuccess('Wallet created successfully'); fetchOrganizationDetails(); @@ -119,6 +110,19 @@ const Dashboard = () => {
    +
    + {orgSuccess && ( +
    + { + setOrgSuccess(null); + }} + /> +
    + )} +
    @@ -180,13 +184,13 @@ const Dashboard = () => {
    { - throw new Error('Function not implemented.'); + setOrgSuccess(message); }} + orgData={orgData} />
    diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index b7d528f99..9c5313ecb 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -48,7 +48,7 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { }); useEffect(() => { - if (props.orgData) { + if (props.openModal && props.orgData) { setInitialOrgData({ name: props.orgData.name ?? '', description: props.orgData.description ?? '', @@ -63,14 +63,14 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { setIsPublic(props?.orgData?.publicProfile); } - }, [props]); + }, [props.orgData, props.openModal]); const [erroMsg, setErrMsg] = useState(null); const [imgError, setImgError] = useState(''); useEffect(() => { - if (props.openModal === false) { + if (!props.openModal) { setInitialOrgData({ name: '', description: '', @@ -176,22 +176,26 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { website: values.website, isPublic: isPublic, }; - - const resUpdateOrg = await updateOrganization( - orgData, - orgData.orgId?.toString() as string, - ); - - const { data } = resUpdateOrg as AxiosResponse; - setLoading(false); - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - if (props?.onEditSucess) { - props?.onEditSucess(); + try { + const response = await updateOrganization( + orgData, + orgData.orgId?.toString() as string, + ); + const { data } = response as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (props?.onEditSucess) { + props?.onEditSucess(); + } + props.setOpenModal(false); + props.setMessage(data?.message); + setLoading(false); + } else { + setErrMsg(response as string); + setLoading(false); } - props.setOpenModal(false); - } else { - setErrMsg(resUpdateOrg as string); + } catch (error) { + console.error('An error occurred:', error); + setLoading(false); } }; @@ -204,6 +208,11 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { imagePreviewUrl: '', fileName: '', }); + setInitialOrgData({ + name: props?.orgData?.name ?? '', + description: props?.orgData?.description ?? '', + website: props?.orgData?.website ?? '', + }); props.setOpenModal(false); }} > @@ -239,7 +248,6 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { { resetForm }: FormikHelpers, ) => { submitUpdateOrganization(values); - window.location.reload(); }} > {(formikHandlers): JSX.Element => ( From 46673f5d5f2e9d29d75998506535bf6b81977c2f Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 24 Jan 2024 15:26:11 +0530 Subject: [PATCH 059/303] fix: org and ecosystem edit popup Signed-off-by: karan --- src/components/EditEcosystemOrgModal/index.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index c0301bf85..047b59112 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -12,7 +12,7 @@ import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import { updateOrganization } from '../../api/organization'; import { updateEcosystem } from '../../api/ecosystem'; -import type { Ecosystem, EditEntityModalProps, EditEntityValues, ILogoImage } from '../Ecosystem/interfaces'; +import type { EditEntityModalProps, EditEntityValues, ILogoImage } from '../Ecosystem/interfaces'; import React, { useEffect, useState } from 'react'; import EndorsementTooltip from '../../commonComponents/EndorsementTooltip'; @@ -114,13 +114,6 @@ const EditPopupModal = (props: EditEntityModalProps) => { } }; }; - - const isEmpty = (object: any): boolean => { - for (const property in object) { - return false; - } - return true; - }; const handleImageChange = (event: any): void => { setImgError(''); From 0e9efdd5c1ff5e2192856e2df76b629a06fe9db9 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 24 Jan 2024 16:10:23 +0530 Subject: [PATCH 060/303] placed process image function in enum Signed-off-by: karan --- .../EditEcosystemOrgModal/index.tsx | 97 +++----------- src/components/organization/Dashboard.tsx | 5 +- .../organization/EditOrgdetailsModal.tsx | 122 +++--------------- .../organization/interfaces/index.ts | 18 ++- src/utils/enums/processImage.ts | 26 ++++ 5 files changed, 79 insertions(+), 189 deletions(-) create mode 100644 src/utils/enums/processImage.ts diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index 047b59112..dd4f68f02 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -1,23 +1,21 @@ import * as yup from 'yup'; import { Avatar, Button, Label, Modal } from 'flowbite-react'; import { Field, Form, Formik, FormikHelpers } from 'formik'; -import { - IMG_MAX_HEIGHT, - IMG_MAX_WIDTH, - apiStatusCodes, - imageSizeAccepted, -} from '../../config/CommonConstant'; -import { calculateSize, dataURItoBlob } from '../../utils/CompressImage'; +import { apiStatusCodes } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import { updateOrganization } from '../../api/organization'; import { updateEcosystem } from '../../api/ecosystem'; -import type { EditEntityModalProps, EditEntityValues, ILogoImage } from '../Ecosystem/interfaces'; +import type { + EditEntityModalProps, + EditEntityValues, + ILogoImage, +} from '../Ecosystem/interfaces'; import React, { useEffect, useState } from 'react'; import EndorsementTooltip from '../../commonComponents/EndorsementTooltip'; +import { processImage } from '../../utils/enums/processImage'; const EditPopupModal = (props: EditEntityModalProps) => { - const [logoImage, setLogoImage] = useState({ logoFile: '', imagePreviewUrl: props?.entityData?.logoUrl ?? '', @@ -68,80 +66,21 @@ const EditPopupModal = (props: EditEntityModalProps) => { } }, [props.openModal]); - const processImage = (e: any): string | undefined => { - const file = e?.target?.files[0]; - if (!file) return; - - const reader = new FileReader(); - reader.readAsDataURL(file); - - reader.onload = (event): void => { - const imgElement = document.createElement('img'); - if (imgElement) { - imgElement.src = - typeof event?.target?.result === 'string' ? event.target.result : ''; - imgElement.onload = (e): void => { - let fileUpdated: File | string = file; - let srcEncoded = ''; - const canvas = document.createElement('canvas'); - - const { width, height, ev } = calculateSize( - imgElement, - IMG_MAX_WIDTH, - IMG_MAX_HEIGHT, - ); - canvas.width = width; - canvas.height = height; - - const ctx = canvas.getContext('2d'); - if (ctx && e?.target) { - ctx.imageSmoothingEnabled = true; - ctx.imageSmoothingQuality = 'high'; - ctx.drawImage(ev, 0, 0, canvas.width, canvas.height); - srcEncoded = ctx.canvas.toDataURL(ev, file.type); - const blob = dataURItoBlob(srcEncoded, file.type); - fileUpdated = new File([blob], file.name, { - type: file.type, - lastModified: new Date().getTime(), - }); - setLogoImage({ - logoFile: fileUpdated, - imagePreviewUrl: srcEncoded, - fileName: file.name, - }); - } - }; - } - }; - }; - const handleImageChange = (event: any): void => { setImgError(''); - const reader = new FileReader(); - const file = event?.target?.files; - - const fileSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); - const extension = file[0]?.name - ?.substring(file[0]?.name?.lastIndexOf('.') + 1) - ?.toLowerCase(); - - if (extension === 'png' || extension === 'jpeg' || extension === 'jpg') { - if (fileSize <= imageSizeAccepted) { - reader.onloadend = (): void => { - processImage(event); - setIsImageEmpty(false); - }; - reader.readAsDataURL(file[0]); - event.preventDefault(); + processImage(event, (result, error) => { + if (result) { + setLogoImage({ + logoFile: '', + imagePreviewUrl: result, + fileName: event.target.files[0].name, + }); } else { - setImgError('Please check image size'); + setImgError(error || 'An error occurred while processing the image.'); } - } else { - setImgError('Invalid image type'); - } + }); }; - const submitUpdateEntity = async (values: EditEntityValues) => { setLoading(true); @@ -166,7 +105,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { props?.onEditSuccess(); } props.setOpenModal(false); - props.setMessage(data?.message) + props.setMessage(data?.message); } else { setErrMsg(response as string); setLoading(false); @@ -180,7 +119,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { props?.onEditSuccess(); } props.setOpenModal(false); - props.setMessage(data?.message) + props.setMessage(data?.message); } else { setErrMsg(response as string); setLoading(false); diff --git a/src/components/organization/Dashboard.tsx b/src/components/organization/Dashboard.tsx index 76358e020..37e3c3a81 100644 --- a/src/components/organization/Dashboard.tsx +++ b/src/components/organization/Dashboard.tsx @@ -2,7 +2,6 @@ import type { OrgDashboard, Organisation } from './interfaces'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { getOrgDashboard, getOrganizationById } from '../../api/organization'; import { useEffect, useState } from 'react'; - import { Alert } from 'flowbite-react'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; @@ -19,16 +18,14 @@ import { getFromLocalStorage } from '../../api/Auth'; import { pathRoutes } from '../../config/pathRoutes'; import DashboardCard from '../../commonComponents/DashboardCard'; import { AlertComponent } from '../AlertComponent'; +import React from 'react'; const Dashboard = () => { const [orgData, setOrgData] = useState(null); - const [walletStatus, setWalletStatus] = useState(false); - const [orgDashboard, setOrgDashboard] = useState(null); const [success, setSuccess] = useState(null); const [failure, setFailure] = useState(null); - const [loading, setLoading] = useState(true); const [userRoles, setUserRoles] = useState([]); const [orgSuccess, setOrgSuccess] = useState(null); diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index 9c5313ecb..cb9d73a5a 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -2,36 +2,15 @@ import * as yup from 'yup'; import { Avatar, Button, Label, Modal } from 'flowbite-react'; import { Field, Form, Formik, FormikHelpers } from 'formik'; import { - IMG_MAX_HEIGHT, - IMG_MAX_WIDTH, apiStatusCodes, - imageSizeAccepted, } from '../../config/CommonConstant'; -import { calculateSize, dataURItoBlob } from '../../utils/CompressImage'; import React, { useEffect, useState } from 'react'; import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import { updateOrganization } from '../../api/organization'; -import type { Organisation } from './interfaces'; +import type { EditOrgdetailsModalProps, ILogoImage, Organisation, Values } from './interfaces'; import defaultUserIcon from '../../../public/images/person_FILL1_wght400_GRAD0_opsz24.svg'; - -interface Values { - website: any; - name: string; - description: string; -} -interface ILogoImage { - logoFile: string | File; - imagePreviewUrl: string | ArrayBuffer | null | File; - fileName: string; -} -interface EditOrgdetailsModalProps { - openModal: boolean; - setMessage: (message: string) => void; - setOpenModal: (flag: boolean) => void; - onEditSucess?: () => void; - orgData: Organisation | null; -} +import { processImage } from '../../utils/enums/processImage'; const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { const [logoImage, setLogoImage] = useState({ @@ -85,86 +64,20 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { } }, [props.openModal]); - const ProcessImg = (e: any): string | undefined => { - const file = e?.target.files[0]; - if (!file) { - return; - } - - const reader = new FileReader(); - reader.readAsDataURL(file); - - reader.onload = (event): void => { - const imgElement = document.createElement('img'); - if (imgElement) { - imgElement.src = - typeof event?.target?.result === 'string' ? event.target.result : ''; - imgElement.onload = (e): void => { - let fileUpdated: File | string = file; - let srcEncoded = ''; - const canvas = document.createElement('canvas'); - - const { width, height, ev } = calculateSize( - imgElement, - IMG_MAX_WIDTH, - IMG_MAX_HEIGHT, - ); - canvas.width = width; - canvas.height = height; - - const ctx = canvas.getContext('2d'); - if (ctx && e?.target) { - ctx.imageSmoothingEnabled = true; - ctx.imageSmoothingQuality = 'high'; - ctx.drawImage(ev, 0, 0, canvas.width, canvas.height); - srcEncoded = ctx.canvas.toDataURL(ev, file.type); - const blob = dataURItoBlob(srcEncoded, file.type); - fileUpdated = new File([blob], file.name, { - type: file.type, - lastModified: new Date().getTime(), - }); - setLogoImage({ - logoFile: fileUpdated, - imagePreviewUrl: srcEncoded, - fileName: file.name, - }); - } - }; - } - }; - }; - - const isEmpty = (object: any): boolean => { - for (const property in object) { - return false; - } - return true; - }; const handleImageChange = (event: any): void => { - setImgError(''); - const reader = new FileReader(); - const file = event?.target?.files; - - const fieSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); - const extension = file[0]?.name - ?.substring(file[0]?.name?.lastIndexOf('.') + 1) - ?.toLowerCase(); - if (extension === 'png' || extension === 'jpeg' || extension === 'jpg') { - if (fieSize <= imageSizeAccepted) { - reader.onloadend = (): void => { - ProcessImg(event); - isEmpty(reader.result); - }; - reader.readAsDataURL(file[0]); - event.preventDefault(); - } else { - setImgError('Please check image size'); - } - } else { - setImgError('Invalid image type'); - } - }; - + setImgError(''); + processImage(event, (result, error) => { + if (result) { + setLogoImage({ + logoFile: '', + imagePreviewUrl: result, + fileName: event.target.files[0].name, + }); + } else { + setImgError(error || 'An error occurred while processing the image.'); + } + }); + }; const submitUpdateOrganization = async (values: Values) => { setLoading(true); @@ -254,11 +167,10 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => {
    - {typeof logoImage.logoFile === 'string' && - props?.orgData?.logoUrl ? ( + {logoImage?.imagePreviewUrl ? ( Jese picture ) : typeof logoImage.logoFile === 'string' ? ( diff --git a/src/components/organization/interfaces/index.ts b/src/components/organization/interfaces/index.ts index c84cfb931..ffb359f83 100644 --- a/src/components/organization/interfaces/index.ts +++ b/src/components/organization/interfaces/index.ts @@ -167,4 +167,20 @@ export interface IOrgData { export interface IExploreOrg { orgData: IOrgData } - +export interface Values { + website: any; + name: string; + description: string; +} +export interface ILogoImage { + logoFile: string | File; + imagePreviewUrl: string | ArrayBuffer | null | File; + fileName: string; +} +export interface EditOrgdetailsModalProps { + openModal: boolean; + setMessage: (message: string) => void; + setOpenModal: (flag: boolean) => void; + onEditSucess?: () => void; + orgData: Organisation | null; +} diff --git a/src/utils/enums/processImage.ts b/src/utils/enums/processImage.ts new file mode 100644 index 000000000..b1dcf6867 --- /dev/null +++ b/src/utils/enums/processImage.ts @@ -0,0 +1,26 @@ +import { + imageSizeAccepted, +} from '../../config/CommonConstant'; + +export const processImage = (event, callback) => { + const reader = new FileReader(); + const file = event?.target?.files; + + const fileSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); + const extension = file[0]?.name + ?.substring(file[0]?.name?.lastIndexOf('.') + 1) + ?.toLowerCase(); + + if ( + (extension === 'png' || extension === 'jpeg' || extension === 'jpg') && + fileSize <= imageSizeAccepted + ) { + reader.onloadend = () => { + callback(reader.result); + }; + reader.readAsDataURL(file[0]); + event.preventDefault(); + } else { + callback(null, extension === 'png' || extension === 'jpeg' || extension === 'jpg' ? 'Please check image size' : 'Invalid image type'); + } +}; From 6980c5f8f23bf404bd6f4e028bcb61935bc7478e Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 24 Jan 2024 16:28:13 +0530 Subject: [PATCH 061/303] created common component to error message Signed-off-by: karan --- src/commonComponents/formikerror/index.tsx | 6 +++++ .../EditEcosystemOrgModal/index.tsx | 22 ++++++++--------- .../organization/EditOrgdetailsModal.tsx | 24 +++++++------------ 3 files changed, 25 insertions(+), 27 deletions(-) create mode 100644 src/commonComponents/formikerror/index.tsx diff --git a/src/commonComponents/formikerror/index.tsx b/src/commonComponents/formikerror/index.tsx new file mode 100644 index 000000000..2a8ad083d --- /dev/null +++ b/src/commonComponents/formikerror/index.tsx @@ -0,0 +1,6 @@ +import React from 'react'; + +const ErrorMessage = ({ error, touched }) => { + return touched && {error}; +}; +export default ErrorMessage; diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index dd4f68f02..83ac49783 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -14,6 +14,7 @@ import type { import React, { useEffect, useState } from 'react'; import EndorsementTooltip from '../../commonComponents/EndorsementTooltip'; import { processImage } from '../../utils/enums/processImage'; +import FormikErrorMessage from '../../commonComponents/formikerror/index' const EditPopupModal = (props: EditEntityModalProps) => { const [logoImage, setLogoImage] = useState({ @@ -130,6 +131,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { setLoading(false); } }; + return ( { } }} /> - {formikHandlers?.errors?.name && - formikHandlers?.touched?.name && ( - - {formikHandlers?.errors?.name} - - )} +
    @@ -312,12 +312,10 @@ const EditPopupModal = (props: EditEntityModalProps) => { } }} /> - {formikHandlers?.errors?.description && - formikHandlers?.touched?.description && ( - - {formikHandlers?.errors?.description} - - )} +
    diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index cb9d73a5a..dcb4edcdc 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -11,6 +11,7 @@ import { updateOrganization } from '../../api/organization'; import type { EditOrgdetailsModalProps, ILogoImage, Organisation, Values } from './interfaces'; import defaultUserIcon from '../../../public/images/person_FILL1_wght400_GRAD0_opsz24.svg'; import { processImage } from '../../utils/enums/processImage'; +import FormikErrorMessage from '../../commonComponents/formikerror/index' const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { const [logoImage, setLogoImage] = useState({ @@ -241,13 +242,10 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { } }} /> - {formikHandlers?.errors && - formikHandlers?.errors?.name && - formikHandlers?.touched?.name && ( - - {formikHandlers?.errors?.name} - - )} +
    @@ -278,14 +276,10 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { } }} /> - {formikHandlers?.errors && - formikHandlers?.errors?.description && - formikHandlers?.touched && - formikHandlers?.touched?.description && ( - - {formikHandlers?.errors?.description} - - )} +
    From df6f7c0d97270f87fd67783eb056f7f5a0bb4ccc Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Wed, 24 Jan 2024 17:16:26 +0530 Subject: [PATCH 062/303] refactor: security Signed-off-by: sanjay-k1910 --- package-lock.json | 85 ++++++++++++++++ package.json | 2 + pnpm-lock.yaml | 173 ++++++++++++++++++++++----------- src/app/LayoutCommon.astro | 12 ++- src/components/HelmetHead.tsx | 13 ++- src/config/GetHeaderConfigs.ts | 18 ++-- 6 files changed, 238 insertions(+), 65 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5811ff266..6c2b34765 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,7 @@ "flowbite-react": "^0.4.11", "flowbite-typography": "^1.0.3", "formik": "^2.4.5", + "helmet": "^7.1.0", "html2canvas": "^1.4.1", "i": "^0.3.7", "moment": "^2.29.4", @@ -42,6 +43,7 @@ "react-avatar": "^5.0.3", "react-dom": "^18.2.0", "react-helmet": "^6.1.0", + "react-helmet-async": "^2.0.4", "react-icons": "^4.10.1", "react-qr-code": "^2.0.11", "react-select": "^5.8.0", @@ -4931,6 +4933,14 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/helmet": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", + "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -5083,6 +5093,14 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -9297,6 +9315,8 @@ }, "node_modules/npm/node_modules/string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "inBundle": true, "license": "MIT", "dependencies": { @@ -9324,6 +9344,8 @@ }, "node_modules/npm/node_modules/strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "inBundle": true, "license": "MIT", "dependencies": { @@ -10392,6 +10414,25 @@ "react": ">=16.3.0" } }, + "node_modules/react-helmet-async": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.4.tgz", + "integrity": "sha512-yxjQMWposw+akRfvpl5+8xejl4JtUlHnEBcji6u8/e6oc7ozT+P9PNTWMhCbz2y9tc5zPegw2BvKjQA+NwdEjQ==", + "dependencies": { + "invariant": "^2.2.4", + "react-fast-compare": "^3.2.2", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-helmet-async/node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, "node_modules/react-helmet/node_modules/react-fast-compare": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", @@ -11011,6 +11052,11 @@ "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -16110,6 +16156,11 @@ "space-separated-tokens": "^2.0.0" } }, + "helmet": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", + "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==" + }, "hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -16213,6 +16264,14 @@ "side-channel": "^1.0.4" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -18897,6 +18956,8 @@ }, "string-width": { "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "bundled": true, "requires": { "emoji-regex": "^8.0.0", @@ -18915,6 +18976,8 @@ }, "strip-ansi": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "bundled": true, "requires": { "ansi-regex": "^5.0.1" @@ -19622,6 +19685,23 @@ } } }, + "react-helmet-async": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.4.tgz", + "integrity": "sha512-yxjQMWposw+akRfvpl5+8xejl4JtUlHnEBcji6u8/e6oc7ozT+P9PNTWMhCbz2y9tc5zPegw2BvKjQA+NwdEjQ==", + "requires": { + "invariant": "^2.2.4", + "react-fast-compare": "^3.2.2", + "shallowequal": "^1.1.0" + }, + "dependencies": { + "react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + } + } + }, "react-icons": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.10.1.tgz", @@ -20055,6 +20135,11 @@ "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==" }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", diff --git a/package.json b/package.json index 1405581ee..c5b70644a 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "flowbite-react": "^0.4.11", "flowbite-typography": "^1.0.3", "formik": "^2.4.5", + "helmet": "^7.1.0", "html2canvas": "^1.4.1", "i": "^0.3.7", "moment": "^2.29.4", @@ -58,6 +59,7 @@ "react-avatar": "^5.0.3", "react-dom": "^18.2.0", "react-helmet": "^6.1.0", + "react-helmet-async": "^2.0.4", "react-icons": "^4.10.1", "react-qr-code": "^2.0.11", "react-select": "^5.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57c0470e6..c7a1c557a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,17 +63,20 @@ dependencies: specifier: ^1.4.7 version: 1.4.7 flowbite: - specifier: ^1.7.0 - version: 1.7.0 + specifier: ^1.8.1 + version: 1.8.1 flowbite-react: - specifier: ^0.4.10 - version: 0.4.10(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.3) + specifier: ^0.4.11 + version: 0.4.11(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.3) flowbite-typography: specifier: ^1.0.3 version: 1.0.3(tailwindcss@3.3.3) formik: specifier: ^2.4.5 version: 2.4.5(react@18.2.0) + helmet: + specifier: ^7.1.0 + version: 7.1.0 html2canvas: specifier: ^1.4.1 version: 1.4.1 @@ -97,13 +100,16 @@ dependencies: version: 18.2.0 react-avatar: specifier: ^5.0.3 - version: 5.0.3(@babel/runtime@7.22.6)(core-js-pure@3.33.1)(prop-types@15.8.1)(react@18.2.0) + version: 5.0.3(@babel/runtime@7.22.6)(core-js-pure@3.35.1)(prop-types@15.8.1)(react@18.2.0) react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) react-helmet: specifier: ^6.1.0 version: 6.1.0(react@18.2.0) + react-helmet-async: + specifier: ^2.0.4 + version: 2.0.4(react-dom@18.2.0)(react@18.2.0) react-icons: specifier: ^4.10.1 version: 4.10.1(react@18.2.0) @@ -162,10 +168,10 @@ devDependencies: version: 9.0.3 '@typescript-eslint/eslint-plugin': specifier: ^5.54.1 - version: 5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.2.2) + version: 5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.3.3) '@typescript-eslint/parser': specifier: ^5.54.1 - version: 5.54.1(eslint@8.35.0)(typescript@5.2.2) + version: 5.54.1(eslint@8.35.0)(typescript@5.3.3) astro-eslint-parser: specifier: ^0.11.0 version: 0.11.0 @@ -198,7 +204,7 @@ devDependencies: version: 2.27.5(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0) eslint-plugin-prettier: specifier: ^4.2.1 - version: 4.2.1(eslint-config-prettier@8.7.0)(eslint@8.35.0)(prettier@3.0.3) + version: 4.2.1(eslint-config-prettier@8.7.0)(eslint@8.35.0)(prettier@3.2.4) eslint-plugin-tsdoc: specifier: ^0.2.17 version: 0.2.17 @@ -1140,6 +1146,12 @@ packages: '@floating-ui/utils': 0.1.6 dev: false + /@floating-ui/core@1.5.3: + resolution: {integrity: sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==} + dependencies: + '@floating-ui/utils': 0.2.1 + dev: false + /@floating-ui/dom@1.5.3: resolution: {integrity: sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==} dependencies: @@ -1147,13 +1159,20 @@ packages: '@floating-ui/utils': 0.1.6 dev: false - /@floating-ui/react-dom@2.0.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==} + /@floating-ui/dom@1.5.4: + resolution: {integrity: sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==} + dependencies: + '@floating-ui/core': 1.5.3 + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/react-dom@2.0.6(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-IB8aCRFxr8nFkdYZgH+Otd9EVQPJoynxeFRGTB8voPoZMRWo8XjYuCRgpI1btvuKY69XMiLnW+ym7zoBHM90Rw==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@floating-ui/dom': 1.5.3 + '@floating-ui/dom': 1.5.4 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -1164,7 +1183,7 @@ packages: react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) + '@floating-ui/react-dom': 2.0.6(react-dom@18.2.0)(react@18.2.0) aria-hidden: 1.2.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -1175,6 +1194,10 @@ packages: resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} dev: false + /@floating-ui/utils@0.2.1: + resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + dev: false + /@humanwhocodes/config-array@0.11.13: resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} @@ -1576,7 +1599,7 @@ packages: resolution: {integrity: sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==} dev: false - /@typescript-eslint/eslint-plugin@5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.2.2): + /@typescript-eslint/eslint-plugin@5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.3.3): resolution: {integrity: sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1587,10 +1610,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.3.3) '@typescript-eslint/scope-manager': 5.54.1 - '@typescript-eslint/type-utils': 5.54.1(eslint@8.35.0)(typescript@5.2.2) - '@typescript-eslint/utils': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/type-utils': 5.54.1(eslint@8.35.0)(typescript@5.3.3) + '@typescript-eslint/utils': 5.54.1(eslint@8.35.0)(typescript@5.3.3) debug: 4.3.4 eslint: 8.35.0 grapheme-splitter: 1.0.4 @@ -1598,13 +1621,13 @@ packages: natural-compare-lite: 1.4.0 regexpp: 3.2.0 semver: 7.5.4 - tsutils: 3.21.0(typescript@5.2.2) - typescript: 5.2.2 + tsutils: 3.21.0(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.54.1(eslint@8.35.0)(typescript@5.2.2): + /@typescript-eslint/parser@5.54.1(eslint@8.35.0)(typescript@5.3.3): resolution: {integrity: sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1616,10 +1639,10 @@ packages: dependencies: '@typescript-eslint/scope-manager': 5.54.1 '@typescript-eslint/types': 5.54.1 - '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.3.3) debug: 4.3.4 eslint: 8.35.0 - typescript: 5.2.2 + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -1640,7 +1663,7 @@ packages: '@typescript-eslint/visitor-keys': 5.62.0 dev: true - /@typescript-eslint/type-utils@5.54.1(eslint@8.35.0)(typescript@5.2.2): + /@typescript-eslint/type-utils@5.54.1(eslint@8.35.0)(typescript@5.3.3): resolution: {integrity: sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1650,12 +1673,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.2.2) - '@typescript-eslint/utils': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.3.3) + '@typescript-eslint/utils': 5.54.1(eslint@8.35.0)(typescript@5.3.3) debug: 4.3.4 eslint: 8.35.0 - tsutils: 3.21.0(typescript@5.2.2) - typescript: 5.2.2 + tsutils: 3.21.0(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -1670,7 +1693,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/typescript-estree@5.54.1(typescript@5.2.2): + /@typescript-eslint/typescript-estree@5.54.1(typescript@5.3.3): resolution: {integrity: sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1685,13 +1708,13 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - tsutils: 3.21.0(typescript@5.2.2) - typescript: 5.2.2 + tsutils: 3.21.0(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@5.54.1(eslint@8.35.0)(typescript@5.2.2): + /@typescript-eslint/utils@5.54.1(eslint@8.35.0)(typescript@5.3.3): resolution: {integrity: sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: @@ -1701,7 +1724,7 @@ packages: '@types/semver': 7.5.4 '@typescript-eslint/scope-manager': 5.54.1 '@typescript-eslint/types': 5.54.1 - '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 5.54.1(typescript@5.3.3) eslint: 8.35.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0(eslint@8.35.0) @@ -2018,7 +2041,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.22.1 - caniuse-lite: 1.0.30001553 + caniuse-lite: 1.0.30001579 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -2137,7 +2160,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001553 + caniuse-lite: 1.0.30001579 electron-to-chromium: 1.4.563 node-releases: 2.0.13 update-browserslist-db: 1.0.13(browserslist@4.22.1) @@ -2185,8 +2208,8 @@ packages: engines: {node: '>=10'} dev: false - /caniuse-lite@1.0.30001553: - resolution: {integrity: sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==} + /caniuse-lite@1.0.30001579: + resolution: {integrity: sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==} /ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -2248,8 +2271,8 @@ packages: engines: {node: '>=8'} dev: false - /classnames@2.3.2: - resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} + /classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} dev: false /cli-boxes@3.0.0: @@ -2341,6 +2364,11 @@ packages: requiresBuild: true dev: false + /core-js-pure@3.35.1: + resolution: {integrity: sha512-zcIdi/CL3MWbBJYo5YCeVAAx+Sy9yJE9I3/u9LkFABwbeaPhTMRWraM8mYFp9jW5Z50hOy7FVzCc8dCrpZqtIQ==} + requiresBuild: true + dev: false + /cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} @@ -3034,8 +3062,8 @@ packages: eslint: ^7.32.0 || ^8.2.0 eslint-plugin-import: ^2.25.3 dependencies: - '@typescript-eslint/eslint-plugin': 5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.2.2) - '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/eslint-plugin': 5.54.1(@typescript-eslint/parser@5.54.1)(eslint@8.35.0)(typescript@5.3.3) + '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.3.3) eslint: 8.35.0 eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.27.5)(eslint@8.35.0) eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-typescript@3.5.3)(eslint@8.35.0) @@ -3101,7 +3129,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.3.3) debug: 3.2.7 eslint: 8.35.0 eslint-import-resolver-node: 0.3.9 @@ -3137,7 +3165,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.2.2) + '@typescript-eslint/parser': 5.54.1(eslint@8.35.0)(typescript@5.3.3) array-includes: 3.1.7 array.prototype.flat: 1.3.2 array.prototype.flatmap: 1.3.2 @@ -3160,7 +3188,7 @@ packages: - supports-color dev: true - /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.7.0)(eslint@8.35.0)(prettier@3.0.3): + /eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.7.0)(eslint@8.35.0)(prettier@3.2.4): resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -3173,7 +3201,7 @@ packages: dependencies: eslint: 8.35.0 eslint-config-prettier: 8.7.0(eslint@8.35.0) - prettier: 3.0.3 + prettier: 3.2.4 prettier-linter-helpers: 1.0.0 dev: true @@ -3470,15 +3498,15 @@ packages: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true - /flowbite-react@0.4.10(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.3): - resolution: {integrity: sha512-VGtOJDOSk3VF6MODerKQ9AbP9Um0MdkI8YMJOUkL/Gou4/mnAOYMNuheUqF/tqg6WkxWsqcDybPgl87bYRI4LQ==} + /flowbite-react@0.4.11(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.3.3): + resolution: {integrity: sha512-QB0PWB/kiogL0YQlT+X1x4Ue0D3cpd+WaiCbGsMqo2LCYySRsctHxEciRQji3JELGuc6O1OaBtK9ZUSErQkJEg==} peerDependencies: react: ^18 react-dom: ^18 tailwindcss: ^3 dependencies: '@floating-ui/react': 0.24.8(react-dom@18.2.0)(react@18.2.0) - flowbite: 1.7.0 + flowbite: 1.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-icons: 4.10.1(react@18.2.0) @@ -3498,8 +3526,8 @@ packages: tailwindcss: 3.3.3 dev: false - /flowbite@1.7.0: - resolution: {integrity: sha512-OTTmnhRgv85Rs+mcMaVU7zB6EvRQs7BaQziyMUsZLRjW9aUpeQyqKjLmxsVMMCdr8isYPCLd6UL7X1IaSVI0WQ==} + /flowbite@1.8.1: + resolution: {integrity: sha512-lXTcO8a6dRTPFpINyOLcATCN/pK1Of/jY4PryklPllAiqH64tSDUsOdQpar3TO59ZXWwugm2e92oaqwH6X90Xg==} dependencies: '@popperjs/core': 2.11.8 mini-svg-data-uri: 1.4.4 @@ -3836,6 +3864,11 @@ packages: space-separated-tokens: 2.0.2 dev: false + /helmet@7.1.0: + resolution: {integrity: sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==} + engines: {node: '>=16.0.0'} + dev: false + /hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} dependencies: @@ -3919,6 +3952,12 @@ packages: side-channel: 1.0.4 dev: true + /invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + dependencies: + loose-envify: 1.4.0 + dev: false + /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: @@ -5274,8 +5313,8 @@ packages: hasBin: true dev: false - /prettier@3.0.3: - resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} + /prettier@3.2.4: + resolution: {integrity: sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==} engines: {node: '>=14'} hasBin: true dev: true @@ -5333,7 +5372,7 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - /react-avatar@5.0.3(@babel/runtime@7.22.6)(core-js-pure@3.33.1)(prop-types@15.8.1)(react@18.2.0): + /react-avatar@5.0.3(@babel/runtime@7.22.6)(core-js-pure@3.35.1)(prop-types@15.8.1)(react@18.2.0): resolution: {integrity: sha512-DNc+qkWH9QehSEZqHBhqpXWsPY+rU9W7kD68QFHfu8Atfsvx/3ML0DzAePgTUd96nCXQQ3KZMcC3LKYT8FiBIg==} peerDependencies: '@babel/runtime': '>=7' @@ -5342,7 +5381,7 @@ packages: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 dependencies: '@babel/runtime': 7.22.6 - core-js-pure: 3.33.1 + core-js-pure: 3.35.1 is-retina: 1.0.3 md5: 2.3.0 prop-types: 15.8.1 @@ -5367,6 +5406,19 @@ packages: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} dev: false + /react-helmet-async@2.0.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-yxjQMWposw+akRfvpl5+8xejl4JtUlHnEBcji6u8/e6oc7ozT+P9PNTWMhCbz2y9tc5zPegw2BvKjQA+NwdEjQ==} + peerDependencies: + react: ^16.6.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 + dependencies: + invariant: 2.2.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-fast-compare: 3.2.2 + shallowequal: 1.1.0 + dev: false + /react-helmet@6.1.0(react@18.2.0): resolution: {integrity: sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==} peerDependencies: @@ -5394,7 +5446,7 @@ packages: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 dependencies: - classnames: 2.3.2 + classnames: 2.5.1 debounce: 1.2.1 easy-bem: 1.1.1 react: 18.2.0 @@ -5790,6 +5842,10 @@ packages: has-property-descriptors: 1.0.1 dev: true + /shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + dev: false + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -6235,14 +6291,14 @@ packages: /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - /tsutils@3.21.0(typescript@5.2.2): + /tsutils@3.21.0(typescript@5.3.3): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 - typescript: 5.2.2 + typescript: 5.3.3 dev: true /type-check@0.4.0: @@ -6323,6 +6379,13 @@ packages: resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} engines: {node: '>=14.17'} hasBin: true + dev: false + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + dev: true /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} diff --git a/src/app/LayoutCommon.astro b/src/app/LayoutCommon.astro index 1a1a677ba..7155bea99 100644 --- a/src/app/LayoutCommon.astro +++ b/src/app/LayoutCommon.astro @@ -1,5 +1,6 @@ --- import pkg from '../../package.json' assert { type: 'json' }; +// import { HelmetProvider } from 'react-helmet-async'; import HelmetHead from '../components/HelmetHead'; import { url } from '../lib/data.js'; @@ -15,6 +16,7 @@ const supabaseUrl = process.env.PUBLIC_SUPABASE_URL || import.meta.env.PUBLIC_SUPABASE_URL; const supabaseKey = process.env.PUBLIC_SUPABASE_KEY || import.meta.env.PUBLIC_SUPABASE_KEY; + --- @@ -29,7 +31,14 @@ const supabaseKey = sitemap={url('sitemap-index.xml')} client:load /> - + - ( {siteTitle} — v{version} @@ -23,6 +26,14 @@ const HelmetHead = ({ generator, desc, icon, sitemap, siteTitle, version }: IPro + + ) diff --git a/src/config/GetHeaderConfigs.ts b/src/config/GetHeaderConfigs.ts index 1eb737ab2..677252e8e 100644 --- a/src/config/GetHeaderConfigs.ts +++ b/src/config/GetHeaderConfigs.ts @@ -7,19 +7,23 @@ export const getHeaderConfigs = async (tokenVal?: string) => { return { headers: { 'Content-Type': 'application/json', + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "X-Content-Type-Options": "nosniff", Authorization: `Bearer ${token}` } } } export const getHeaderConfigsForFormData = async () => { - const token = await getFromLocalStorage(storageKeys.TOKEN) + const token = await getFromLocalStorage(storageKeys.TOKEN) - return { - headers: { - "Content-Type": "multipart/form-data", - Authorization: `Bearer ${token}` - } - } + return { + headers: { + "Content-Type": "multipart/form-data", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "X-Content-Type-Options": "nosniff", + Authorization: `Bearer ${token}` + } + } } From cdea83f60dfe4d0e0397f7df710f1561fdb6d9ee Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Wed, 24 Jan 2024 17:59:40 +0530 Subject: [PATCH 063/303] refactor: content policy in meta tags Signed-off-by: sanjay-k1910 --- src/app/LayoutCommon.astro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/LayoutCommon.astro b/src/app/LayoutCommon.astro index 7155bea99..8282f75f3 100644 --- a/src/app/LayoutCommon.astro +++ b/src/app/LayoutCommon.astro @@ -31,6 +31,8 @@ const supabaseKey = sitemap={url('sitemap-index.xml')} client:load /> + + + + + + + + + Developer Settings +
  • diff --git a/src/commonComponents/CopyDid.tsx b/src/commonComponents/CopyDid.tsx index 0772b1e68..25901b912 100644 --- a/src/commonComponents/CopyDid.tsx +++ b/src/commonComponents/CopyDid.tsx @@ -24,9 +24,9 @@ const CopyDid = ({ value, className }: IProps) => { } return ( <> - +
    {value} - +
  • )}
    - {warning && ( - { - setWarning(null); - setFailure(null); - }} - /> - )} +
    +
    + {warning && ( + { + setWarning(null); + setFailure(null); + }} + /> + )} +
    {/* {clentId && (
    { {clentId && (
    -
    SVG
    -
    -

    - {!hideCopy - ? clientSecret && ( - - ) - : {clientSecret}} +
    + + + +
    +
    +

    + {!hideCopy ? ( + clientSecret && ( + // font-courier font-semibold + + ) + ) : ( + + {clientSecret} + + )}

    {(userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) && ( -
    +
    diff --git a/src/components/SignOutButton/index.tsx b/src/components/SignOutButton/index.tsx index 13e1ba46f..c6de6199a 100644 --- a/src/components/SignOutButton/index.tsx +++ b/src/components/SignOutButton/index.tsx @@ -34,19 +34,19 @@ const SignOutButton = () => { width="16" height="20" viewBox="0 0 16 20" - fill="text-gray-700 dark:text-white" + fill="none" > Sign out From 49c0e93e15f67f306d4a2e1d2435762d2a43dc9b Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 25 Jan 2024 13:30:05 +0530 Subject: [PATCH 069/303] fix: connection issue Signed-off-by: karan --- src/components/Issuance/ConnectionList.tsx | 2 +- src/components/Verification/ConnectionList.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index 126cb70a0..253faba28 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -19,7 +19,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; const ConnectionList = (props: { diff --git a/src/components/Verification/ConnectionList.tsx b/src/components/Verification/ConnectionList.tsx index 3d2e68d7f..5a1b07913 100644 --- a/src/components/Verification/ConnectionList.tsx +++ b/src/components/Verification/ConnectionList.tsx @@ -19,7 +19,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; From c88bba86436b413ebcc5f56d4d1d7af539f9f63b Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 25 Jan 2024 13:50:04 +0530 Subject: [PATCH 070/303] fix: connection issue Signed-off-by: karan --- src/components/Ecosystem/Endorsement/index.tsx | 2 +- src/components/Resources/Schema/SchemasList.tsx | 2 +- src/components/User/UserDashBoard.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Ecosystem/Endorsement/index.tsx b/src/components/Ecosystem/Endorsement/index.tsx index 05fc2cead..231e5e417 100644 --- a/src/components/Ecosystem/Endorsement/index.tsx +++ b/src/components/Ecosystem/Endorsement/index.tsx @@ -61,7 +61,7 @@ const EndorsementList = () => { page: 1, search: '', sortBy: 'id', - sortingOrder: 'DESC', + sortingOrder: 'desc', type: '', status: '', }); diff --git a/src/components/Resources/Schema/SchemasList.tsx b/src/components/Resources/Schema/SchemasList.tsx index f03b7073f..48e89bd15 100644 --- a/src/components/Resources/Schema/SchemasList.tsx +++ b/src/components/Resources/Schema/SchemasList.tsx @@ -36,7 +36,7 @@ const SchemaList = (props: { page: 1, search: '', sortBy: 'id', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }); const [walletStatus, setWalletStatus] = useState(false); diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index d250c5be6..8eb9bc988 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -66,7 +66,7 @@ const UserDashBoard = () => { page: 1, search: '', sortBy: 'id', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }); const [ecoCount, setEcoCount] = useState(0); From cb1cbfdb11409e660c46cbc55c143d5615d5ac37 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 25 Jan 2024 17:51:25 +0530 Subject: [PATCH 071/303] handled data types Signed-off-by: karan --- src/components/EditEcosystemOrgModal/index.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index 83ac49783..7318c5ed0 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -24,7 +24,6 @@ const EditPopupModal = (props: EditEntityModalProps) => { }); const [loading, setLoading] = useState(false); - const [isImageEmpty, setIsImageEmpty] = useState(true); const [initialEntityData, setInitialEntityData] = useState({ name: '', description: '', @@ -36,7 +35,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { name: props.entityData.name ?? '', description: props.entityData.description ?? '', }); - SetisAutoEndorse(props.entityData.autoEndorsement); + setIsAutoEndorse(props.entityData.autoEndorsement); setLogoImage({ logoFile: '', imagePreviewUrl: props.entityData.logoUrl ?? '', @@ -47,7 +46,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { const [errMsg, setErrMsg] = useState(null); const [imgError, setImgError] = useState(''); - const [isAutoEndorse, SetisAutoEndorse] = useState(false); + const [isAutoEndorse, setIsAutoEndorse] = useState(false); useEffect(() => { if (!props.openModal) { @@ -329,7 +328,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { id="sign" name="autoEndorsement" checked={isAutoEndorse === false} - onChange={() => SetisAutoEndorse(false)} + onChange={() => setIsAutoEndorse(false)} /> Sign @@ -342,7 +341,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { id="sign-submit" name="autoEndorsement" checked={isAutoEndorse === true} - onChange={() => SetisAutoEndorse(true)} + onChange={() => setIsAutoEndorse(true)} /> Sign and Submit From 37191e35ce3c8f9d443b3d69354f4588c05b532f Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 25 Jan 2024 17:51:37 +0530 Subject: [PATCH 072/303] handled data types Signed-off-by: karan --- src/components/EditEcosystemOrgModal/index.tsx | 4 ++-- src/components/organization/EditOrgdetailsModal.tsx | 2 +- src/utils/{enums => }/processImage.ts | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) rename src/utils/{enums => }/processImage.ts (79%) diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index 7318c5ed0..e649fd707 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -13,7 +13,7 @@ import type { } from '../Ecosystem/interfaces'; import React, { useEffect, useState } from 'react'; import EndorsementTooltip from '../../commonComponents/EndorsementTooltip'; -import { processImage } from '../../utils/enums/processImage'; +import { processImage } from '../../utils/processImage'; import FormikErrorMessage from '../../commonComponents/formikerror/index' const EditPopupModal = (props: EditEntityModalProps) => { @@ -68,7 +68,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { const handleImageChange = (event: any): void => { setImgError(''); - processImage(event, (result, error) => { + processImage(event, (result: any, error: any) => { if (result) { setLogoImage({ logoFile: '', diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index dcb4edcdc..24aba5a4b 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -10,7 +10,7 @@ import type { AxiosResponse } from 'axios'; import { updateOrganization } from '../../api/organization'; import type { EditOrgdetailsModalProps, ILogoImage, Organisation, Values } from './interfaces'; import defaultUserIcon from '../../../public/images/person_FILL1_wght400_GRAD0_opsz24.svg'; -import { processImage } from '../../utils/enums/processImage'; +import { processImage } from '../../utils/processImage'; import FormikErrorMessage from '../../commonComponents/formikerror/index' const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { diff --git a/src/utils/enums/processImage.ts b/src/utils/processImage.ts similarity index 79% rename from src/utils/enums/processImage.ts rename to src/utils/processImage.ts index b1dcf6867..3939e193a 100644 --- a/src/utils/enums/processImage.ts +++ b/src/utils/processImage.ts @@ -1,11 +1,12 @@ +import type { ChangeEvent } from 'react'; import { imageSizeAccepted, -} from '../../config/CommonConstant'; +} from '../config/CommonConstant'; -export const processImage = (event, callback) => { +export const processImage = (event: ChangeEvent, callback:any) => { const reader = new FileReader(); const file = event?.target?.files; - +if(file){ const fileSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); const extension = file[0]?.name ?.substring(file[0]?.name?.lastIndexOf('.') + 1) @@ -23,4 +24,6 @@ export const processImage = (event, callback) => { } else { callback(null, extension === 'png' || extension === 'jpeg' || extension === 'jpg' ? 'Please check image size' : 'Invalid image type'); } +} + }; From efd36e65471b106056a81f73a964deedbf20918a Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 25 Jan 2024 20:17:13 +0530 Subject: [PATCH 073/303] fix: verified details data sync issue Signed-off-by: karan --- src/components/Verification/ProofRequestPopup.tsx | 7 ++++--- .../Verification/VerificationCredentialList.tsx | 9 ++++++--- src/components/Verification/interface.ts | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/components/Verification/ProofRequestPopup.tsx b/src/components/Verification/ProofRequestPopup.tsx index 170225a95..b7b2d03dd 100644 --- a/src/components/Verification/ProofRequestPopup.tsx +++ b/src/components/Verification/ProofRequestPopup.tsx @@ -189,7 +189,7 @@ const ProofRequest = (props: IProofRrquestDetails) => {

    Verified Details

    - {!props.userData ? ( + {props.verifyLoading ? (
    @@ -206,16 +206,17 @@ const ProofRequest = (props: IProofRrquestDetails) => { )}
    - +
    diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 14f30bd0a..29cca4dca 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -52,6 +52,7 @@ const VerificationCredentialList = () => { const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [totalItem, setTotalItem] = useState(0); + const [verifyLoading, setVerifyLoading]= useState(true) const [pageInfo, setPageInfo] = useState({ totalItem: '', nextPage: '', @@ -60,14 +61,17 @@ const VerificationCredentialList = () => { const getProofPresentationData = async (proofId: string) => { try { + setVerifyLoading(true) const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const response = await getVerifiedProofDetails(proofId, orgId); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes?.API_STATUS_SUCCESS) { setUserData(data?.data); + setVerifyLoading(false) } else { setErrMsg(response as string); + setVerifyLoading(false) } } catch (error) { throw error; @@ -102,8 +106,6 @@ const VerificationCredentialList = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const { totalItems, nextPage, lastPage } = data.data; - console.log('data.data', data.data); - setPageInfo({ totalItem: totalItems, nextPage: nextPage, @@ -435,11 +437,12 @@ const VerificationCredentialList = () => { {userData && ( openProofRequestModel(false, '', '')} + closeModal={() => {openProofRequestModel(false, '', '')}} onSucess={requestProof} requestId={requestId} userData={userData} view={view} + verifyLoading={verifyLoading} /> )}
    diff --git a/src/components/Verification/interface.ts b/src/components/Verification/interface.ts index a49940da6..7bb0d1ea1 100644 --- a/src/components/Verification/interface.ts +++ b/src/components/Verification/interface.ts @@ -38,6 +38,7 @@ export interface SchemaDetails { } export interface IProofRrquestDetails { + verifyLoading: boolean; openModal: boolean; closeModal: (flag: boolean, id: string, state: boolean) => void; onSucess: (verifyPresentationId: string) => void; From fe5bba4abb9624d562a7b5426ac225aff5cd18d4 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 29 Jan 2024 15:50:26 +0530 Subject: [PATCH 074/303] fix: verification popup Signed-off-by: karan --- src/components/Verification/ProofRequestPopup.tsx | 3 ++- src/components/Verification/VerificationCredentialList.tsx | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Verification/ProofRequestPopup.tsx b/src/components/Verification/ProofRequestPopup.tsx index b7b2d03dd..83d0af8c9 100644 --- a/src/components/Verification/ProofRequestPopup.tsx +++ b/src/components/Verification/ProofRequestPopup.tsx @@ -14,6 +14,7 @@ const ProofRequest = (props: IProofRrquestDetails) => { const [navigation, setNavigation] = useState(false); const [succesMsg, setSuccesMsg] = useState(''); const [error, setError] = useState(''); + const handleConfirmClick = async (id: string) => { try { setButtonLoader(true); @@ -85,7 +86,7 @@ const ProofRequest = (props: IProofRrquestDetails) => { {' '} Verification Details

    - {!props.userData ? ( + {props.verifyLoading ? (
    diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 29cca4dca..f381715f8 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -45,7 +45,6 @@ const VerificationCredentialList = () => { const [requestId, setRequestId] = useState(''); const [errMsg, setErrMsg] = useState(null); const [proofReqSuccess, setProofReqSuccess] = useState(''); - const [verifyLoader, setVerifyloader] = useState(false); const [userData, setUserData] = useState(null); const [view, setView] = useState(false); const [walletCreated, setWalletCreated] = useState(false); @@ -263,14 +262,14 @@ const VerificationCredentialList = () => { if (data?.statusCode === apiStatusCodes?.API_STATUS_CREATED) { setOpenModal(false); setProofReqSuccess(data.message); - setVerifyloader(false); + setVerifyLoading(false); setTimeout(() => { getproofRequestList(listAPIParameter); }, 2000); } else { setOpenModal(false); setErrMsg(response as string); - setVerifyloader(false); + setVerifyLoading(false); } setTimeout(() => { setProofReqSuccess(''); @@ -278,7 +277,7 @@ const VerificationCredentialList = () => { }, 4000); } catch (error) { setOpenModal(false); - setVerifyloader(false); + setVerifyLoading(false); console.error('An error occurred:', error); setErrMsg('An error occurred while processing the presentation.'); } From 5efaee48cc02ab00d1a75576e5dd31bff1e59200 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Mon, 29 Jan 2024 17:05:29 +0530 Subject: [PATCH 075/303] fix: email validation Signed-off-by: sanjay-k1910 --- .../organization/invitations/SendInvitationModal.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/organization/invitations/SendInvitationModal.tsx b/src/components/organization/invitations/SendInvitationModal.tsx index cbbb5aa85..d2fde63e0 100644 --- a/src/components/organization/invitations/SendInvitationModal.tsx +++ b/src/components/organization/invitations/SendInvitationModal.tsx @@ -185,8 +185,9 @@ const SendInvitationModal = (props: { validationSchema={yup.object().shape({ email: yup .string() - .required('Email is required') + .matches(/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/g, "Email is invalid") .email('Email is invalid') + .required('Email is required') .test('is-self-email', "You can't send invitation to self", (value) => value.trim() !== selfEmail.email.trim()) .trim(), })} From 880e401560c8de12e446218c6af03834c33e7e3f Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Mon, 29 Jan 2024 17:32:34 +0530 Subject: [PATCH 076/303] fix: popup height issue on multiple screens, user dashboard ui Signed-off-by: sanjay-k1910 --- src/components/User/UserDashBoard.tsx | 2 +- .../organization/EditOrgdetailsModal.tsx | 52 ++++++++++--------- tailwind.config.cjs | 2 +- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 8eb9bc988..3aff36af5 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -520,7 +520,7 @@ const UserDashBoard = () => { <> ) : (
    {walletLoading ? ( diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index b7d528f99..3fe829d6b 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -247,11 +247,11 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => {
    {typeof logoImage.logoFile === 'string' && - props?.orgData?.logoUrl ? ( + props?.orgData?.logoUrl ? ( Jese picture ) : typeof logoImage.logoFile === 'string' ? ( @@ -259,7 +259,7 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { Jese picture )}
    @@ -420,29 +420,31 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => {
    - + + + + Save + +
    )} diff --git a/tailwind.config.cjs b/tailwind.config.cjs index c046b2fd5..419edbb5f 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -130,7 +130,7 @@ module.exports = { '100/15rem' : 'calc(100vh - 15rem)', }, maxHeight: { - '[90vh]': 'fit-content !important', + '[90vh]': 'calc(100vh - 4rem) !important', '100/10rem': 'calc(100vh - 10rem)', }, scale: { From a48170c29c3a21aab1aedf0e36952dc1eb572a2f Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 29 Jan 2024 19:48:48 +0530 Subject: [PATCH 077/303] implementation of create schema functionality in oob bulk and email issunace Signed-off-by: karan --- src/app/SideBar.astro | 5 +- src/common/global.css | 4 + src/components/Issuance/BulkIssuance.tsx | 44 +++++- src/components/Issuance/Constant.tsx | 34 ++++ src/components/Issuance/EmailIssuance.tsx | 148 ++++++------------ .../Resources/Schema/SchemasList.tsx | 56 ++----- src/components/RoleViewButton/index.tsx | 13 +- 7 files changed, 142 insertions(+), 162 deletions(-) create mode 100644 src/components/Issuance/Constant.tsx diff --git a/src/app/SideBar.astro b/src/app/SideBar.astro index 760d54832..055711d09 100644 --- a/src/app/SideBar.astro +++ b/src/app/SideBar.astro @@ -236,13 +236,14 @@ import { pathRoutes } from '../config/pathRoutes'; height="24" viewBox="0 0 24 24" fill="none" + class="text-[#6B7280] group-hover:text-gray-700 dark:group-hover:text-white" > + fill="currentColor"> + fill="currentColor"> Verify diff --git a/src/common/global.css b/src/common/global.css index 31158d179..4913f04bc 100644 --- a/src/common/global.css +++ b/src/common/global.css @@ -183,3 +183,7 @@ ul.timelinestatic { .select__input-container { width: 1px; } + +.email-bulk-issuance .select__single-value{ + width: calc(100% - 15px) !important; +} diff --git a/src/components/Issuance/BulkIssuance.tsx b/src/components/Issuance/BulkIssuance.tsx index 5ece10f30..071091032 100644 --- a/src/components/Issuance/BulkIssuance.tsx +++ b/src/components/Issuance/BulkIssuance.tsx @@ -16,7 +16,11 @@ import SOCKET from '../../config/SocketConfig'; import { ToastContainer, toast } from 'react-toastify'; import BreadCrumbs from '../BreadCrumbs'; import BackButton from '../../commonComponents/backbutton' +import { checkEcosystem, type ICheckEcosystem } from '../../config/ecosystem'; import type { ICredentials, IValues, IAttributes, IUploadMessage } from './interface'; +import RoleViewButton from '../RoleViewButton'; +import { Features } from '../../utils/enums/features'; +import { Create, SchemaEndorsement } from './Constant'; const BulkIssuance = () => { const [csvData, setCsvData] = useState([]); @@ -33,6 +37,7 @@ const BulkIssuance = () => { const [uploadMessage, setUploadMessage] = useState(null) const [success, setSuccess] = useState(null); const [failure, setFailure] = useState(null); + const [isEcosystemData, setIsEcosystemData] = useState(); const onPageChange = (page: number) => { setCurrentPage({ @@ -85,6 +90,14 @@ const BulkIssuance = () => { useEffect(() => { getSchemaCredentials(); + (async () => { + try { + const data: ICheckEcosystem = await checkEcosystem(); + setIsEcosystemData(data); + } catch (error) { + console.log(error); + } + })(); }, []); @@ -387,7 +400,11 @@ const BulkIssuance = () => { item.value && item.value === credentialSelected, ); - + + const createSchemaTitle = isEcosystemData?.isEcosystemMember + ? { title: 'Schema Endorsement', svg: } + : { title: 'Create', svg: }; + return (
    @@ -405,23 +422,24 @@ const BulkIssuance = () => {

    Upload a .CSV file for bulk issuance
    +
    + { + window.location.href = `${pathRoutes.organizations.createSchema}`; + }} + isPadding={createSchemaTitle.title === 'Create' ? false : true} + /> +
    {(success || failure) && ( ( + + + +); + +export const Create = () => ( +
    + + + +
    +); + diff --git a/src/components/Issuance/EmailIssuance.tsx b/src/components/Issuance/EmailIssuance.tsx index daca68805..fcd27b8e9 100644 --- a/src/components/Issuance/EmailIssuance.tsx +++ b/src/components/Issuance/EmailIssuance.tsx @@ -17,6 +17,10 @@ import CustomSpinner from '../CustomSpinner'; import { issueOobEmailCredential } from '../../api/issuance'; import { EmptyListMessage } from '../EmptyListComponent'; import ResetPopup from './ResetPopup'; +import RoleViewButton from '../RoleViewButton'; +import { checkEcosystem, type ICheckEcosystem } from '../../config/ecosystem'; +import { Features } from '../../utils/enums/features'; +import {SchemaEndorsement, Create} from './Constant' const EmailIssuance = () => { const [formData, setFormData] = useState(); @@ -32,6 +36,7 @@ const EmailIssuance = () => { const [failure, setFailure] = useState(null); const [isEditing, setIsEditing] = useState(false); const [issueLoader, setIssueLoader] = useState(false); + const [isEcosystemData, setIsEcosystemData] = useState(); const inputRef = useRef(null); const getSchemaCredentials = async () => { @@ -71,6 +76,16 @@ const EmailIssuance = () => { useEffect(() => { getSchemaCredentials(); + (async () => { + try { + const data: ICheckEcosystem = await checkEcosystem(); + console.log("data",data); + + setIsEcosystemData(data); + } catch (error) { + console.log(error); + } + })(); }, []); useEffect(() => { @@ -192,7 +207,11 @@ const EmailIssuance = () => { const handleResetOpenConfirmation = () => { setOpenResetModal(true); }; - + + const createSchemaTitle = isEcosystemData?.isEcosystemMember + ? { title: 'Schema Endorsement', svg: } + : { title: 'Create', svg: }; + const MailError = ({ handler, formindex, @@ -255,11 +274,19 @@ const EmailIssuance = () => {

    Email

    + { + window.location.href = `${pathRoutes.organizations.createSchema}`; + }} + />
    -
    -

    +

    +

    Select Schema and credential definition

    @@ -320,45 +347,6 @@ const EmailIssuance = () => { )}
    - {/* required for batch application */} - {/*
    - - -
    */}
    @@ -373,43 +361,13 @@ const EmailIssuance = () => { >
    -

    +

    Issue Credential(s) to the email

    Please enter an email address to issue the credential to
    - {/* rquired for history details */} - {/* */}
    {isCredSelected ? (
    @@ -557,7 +515,7 @@ const EmailIssuance = () => {
    {formData1.attributes && @@ -567,8 +525,12 @@ const EmailIssuance = () => { formData1?.attributes.map( ( item: { - displayName: ReactNode | string; - attributeName: ReactNode | string; + displayName: + | ReactNode + | string; + attributeName: + | ReactNode + | string; name: | string | number @@ -589,22 +551,10 @@ const EmailIssuance = () => { <>
    -
    - {/* // required for validation of only one attribute is required */} - {/* {!formData1.attributes.some( - (item) => item?.value, - ) && ( -
    - Atleast one - attribute should - have a value -
    - )} */}
    ); }, @@ -681,7 +622,6 @@ const EmailIssuance = () => { arrayHelpers.push({ email: '', attributes: attributes?.map( - (item) => { return { attributeName: diff --git a/src/components/Resources/Schema/SchemasList.tsx b/src/components/Resources/Schema/SchemasList.tsx index 48e89bd15..8b6a06e50 100644 --- a/src/components/Resources/Schema/SchemasList.tsx +++ b/src/components/Resources/Schema/SchemasList.tsx @@ -19,6 +19,7 @@ import { getFromLocalStorage } from '../../../api/Auth'; import { pathRoutes } from '../../../config/pathRoutes'; import { getOrganizationById } from '../../../api/organization'; import { ICheckEcosystem, checkEcosystem } from '../../../config/ecosystem'; +import { Create, SchemaEndorsement } from '../../Issuance/Constant'; const SchemaList = (props: { schemaSelectionCallback: ( @@ -160,55 +161,24 @@ const SchemaList = (props: { useEffect(() => { fetchOrganizationDetails(); - const checkEcosystemData = async () => { - const data: ICheckEcosystem = await checkEcosystem(); - setIsEcosystemData(data); - }; - - checkEcosystemData(); + (async () => { + try { + const data: ICheckEcosystem = await checkEcosystem(); + setIsEcosystemData(data); + } catch (error) { + console.log(error); + } + })(); }, []); - const schemaEndorsement = ( - - - - ); - - const create = ( -
    - - - -
    - ); - const createSchemaTitle = isEcosystemData?.isEcosystemMember - ? { title: 'Schema Endorsement', svg: schemaEndorsement } - : { title: 'Create', svg: create }; + ? { title: 'Schema Endorsement', svg: } + : { title: 'Create', svg: }; const emptyListTitle = 'No Schemas'; const emptyListDesc = 'Get started by creating a new Schema'; const emptyListBtn = isEcosystemData?.isEcosystemMember - ? { title: 'Schema Endorsement', svg: schemaEndorsement } - : { title: 'Create Schema', svg: create }; + ? { title: 'Schema Endorsement', svg: } + : { title: 'Create Schema', svg: }; return (
    diff --git a/src/components/RoleViewButton/index.tsx b/src/components/RoleViewButton/index.tsx index 803b76f26..7f1e620be 100644 --- a/src/components/RoleViewButton/index.tsx +++ b/src/components/RoleViewButton/index.tsx @@ -10,12 +10,13 @@ interface RoleViewButtonProps { buttonTitle?: string, svgComponent?: ReactElement, onClickEvent?: () => void, - feature: string - isOutline?: boolean + feature: string, + isOutline?: boolean, + isPadding?: boolean } -const RoleViewButton = ({ buttonTitle, svgComponent, onClickEvent, feature, isOutline }: RoleViewButtonProps) => { +const RoleViewButton = ({ buttonTitle, svgComponent, onClickEvent, feature, isOutline, isPadding }: RoleViewButtonProps) => { const [userRoles, setUserRoles] = useState([]) @@ -65,8 +66,10 @@ const RoleViewButton = ({ buttonTitle, svgComponent, onClickEvent, feature, isOu outline={Boolean(isOutline)} onClick={onClickEvent} color={isOutline ? "bg-primary-800" : "bg-primary-700"} - className={`${isOutline ? "!p-0 role-btn group flex h-min items-center justify-center text-center focus:z-10 focus:ring-2 ring-primary-700 bg-white-700 hover:bg-secondary-700 ring-2 text-black font-medium rounded-md text-sm dark:text-white dark:hover:text-primary-700" : "text-base font-medium text-center text-white bg-primary-700 hover:!bg-primary-800 rounded-md hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"}`} - > + className={`${isOutline + ? "!p-0 role-btn group flex h-min items-center justify-center text-center focus:z-10 focus:ring-2 ring-primary-700 bg-white-700 hover:bg-secondary-700 ring-2 text-black font-medium rounded-md text-sm dark:text-white dark:hover:text-primary-700" + : `${isPadding ? "!p-0" : ""} text-base font-medium text-center text-white bg-primary-700 hover:!bg-primary-800 rounded-md hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800` + }`} > {svgComponent} {buttonTitle} From a300734d03dab384bbbf1823c9671350ab905cb5 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 29 Jan 2024 19:57:30 +0530 Subject: [PATCH 078/303] reduced complexcity Signed-off-by: karan --- src/components/Issuance/BulkIssuance.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Issuance/BulkIssuance.tsx b/src/components/Issuance/BulkIssuance.tsx index 071091032..f55e863a5 100644 --- a/src/components/Issuance/BulkIssuance.tsx +++ b/src/components/Issuance/BulkIssuance.tsx @@ -458,7 +458,7 @@ const BulkIssuance = () => { onClickEvent={() => { window.location.href = `${pathRoutes.organizations.createSchema}`; }} - isPadding={createSchemaTitle.title === 'Create' ? false : true} + isPadding={createSchemaTitle.title !== 'Create'} />
    From 96575ca458cb8f7e90973052a189d2b43443dfc2 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Mon, 29 Jan 2024 20:19:30 +0530 Subject: [PATCH 079/303] fix: empty message for ecosystem list when no wallet is created Signed-off-by: sanjay-k1910 --- src/components/Ecosystem/EcosystemList.tsx | 143 +++++++++++------- .../organization/OrganizationsList.tsx | 4 +- 2 files changed, 91 insertions(+), 56 deletions(-) diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index 3b016c61e..82970fe97 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -22,7 +22,7 @@ import CustomSpinner from '../CustomSpinner'; import CreateEcosystemOrgModal from '../CreateEcosystemOrgModal'; import { getEcosystems } from '../../api/ecosystem'; import type { IEcosystem } from './interfaces'; -import { checkEcosystem, type ICheckEcosystem } from '../../config/ecosystem'; +import { checkEcosystem, getOrgDetails, type ICheckEcosystem } from '../../config/ecosystem'; import React from 'react'; const initialPageState = { @@ -34,6 +34,7 @@ const initialPageState = { const EcosystemList = () => { const [openModal, setOpenModal] = useState(false); const [loading, setLoading] = useState(true); + const [isWalletSpinUp, setIsWalletSpinUp] = useState(false); const [selectedOrgId, setSelectedOrgId] = useState(""); const [message, setMessage] = useState(null); const [error, setError] = useState(null); @@ -58,6 +59,8 @@ const EcosystemList = () => { const fetchEcosystems = async () => { const id = await getFromLocalStorage(storageKeys.ORG_ID); setSelectedOrgId(id) + const orgData = await getOrgDetails(); + setIsWalletSpinUp(Boolean(orgData?.orgDid)) setLoading(true); if (id) { const response = await getEcosystems( @@ -103,17 +106,16 @@ const EcosystemList = () => { useEffect(() => { const queryParameters = new URLSearchParams(window?.location?.search); - const isModel = queryParameters.get('orgModal') || ''; + const isModel = queryParameters.get('orgModal') === 'true' || false; - if (isModel !== '') { + if (isModel) { setOpenModal(true); } - const checkEcosystemData = async () => { + (async () => { const data: ICheckEcosystem = await checkEcosystem(); setIsEcosystemData(data); - }; - checkEcosystemData(); + })(); }, []); //onCHnage of Search input text @@ -130,6 +132,84 @@ const EcosystemList = () => { window.location.href = pathRoutes.ecosystem.dashboard; }; + console.log(35345, selectedOrgId); + const emptyListMessage = (isWalletSpinUp: boolean, selectedOrgId: boolean, ecosystemList: boolean) => { + try { + switch (true) { + case !isWalletSpinUp: + return window.location.assign(pathRoutes.organizations.dashboard)} + svgComponent={ + + + + } + /> + case !selectedOrgId: + return + + + } + /> + case ecosystemList: + return + + + } + /> + default: + break; + } + } catch (error) { + console.error(error) + } + } + const isEcosystemList = Boolean(ecosystemList && ecosystemList?.length > 0); const showCreateButton = Boolean( isEcosystemList && @@ -262,55 +342,10 @@ const EcosystemList = () => { ) : ( <> - {ecosystemList && ( - - - - } - /> - )} - { - !selectedOrgId && - - - - } - /> - } + {console.log(345345345, isWalletSpinUp, Boolean(selectedOrgId), Boolean(ecosystemList && ecosystemList?.length === 0)) + } + {emptyListMessage(isWalletSpinUp, Boolean(selectedOrgId), Boolean(ecosystemList && ecosystemList?.length === 0))} - )}
    { useEffect(() => { const queryParameters = new URLSearchParams(window?.location?.search); - const isModel = queryParameters.get('orgModal') ?? ''; + const isModel = queryParameters.get('orgModal') === 'true' || false; - if (isModel !== '') { + if (isModel) { props.setOpenModal(true); } }, []); From 285324dd4b3193eee75e2ebb0b94a0fa2492e5a5 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 30 Jan 2024 12:29:54 +0530 Subject: [PATCH 080/303] changed text Signed-off-by: karan --- src/components/Issuance/BulkIssuance.tsx | 4 ++-- src/components/Issuance/EmailIssuance.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Issuance/BulkIssuance.tsx b/src/components/Issuance/BulkIssuance.tsx index f55e863a5..6c3a7c31c 100644 --- a/src/components/Issuance/BulkIssuance.tsx +++ b/src/components/Issuance/BulkIssuance.tsx @@ -403,7 +403,7 @@ const BulkIssuance = () => { const createSchemaTitle = isEcosystemData?.isEcosystemMember ? { title: 'Schema Endorsement', svg: } - : { title: 'Create', svg: }; + : { title: 'Create Schema', svg: }; return (
    @@ -458,7 +458,7 @@ const BulkIssuance = () => { onClickEvent={() => { window.location.href = `${pathRoutes.organizations.createSchema}`; }} - isPadding={createSchemaTitle.title !== 'Create'} + isPadding={createSchemaTitle.title !== 'Create Schema'} />
    diff --git a/src/components/Issuance/EmailIssuance.tsx b/src/components/Issuance/EmailIssuance.tsx index fcd27b8e9..a6d698635 100644 --- a/src/components/Issuance/EmailIssuance.tsx +++ b/src/components/Issuance/EmailIssuance.tsx @@ -210,7 +210,7 @@ const EmailIssuance = () => { const createSchemaTitle = isEcosystemData?.isEcosystemMember ? { title: 'Schema Endorsement', svg: } - : { title: 'Create', svg: }; + : { title: 'Create Schema', svg: }; const MailError = ({ handler, From 7359f90311808f90b341a3308ede291790dfc620 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Tue, 30 Jan 2024 14:02:17 +0530 Subject: [PATCH 081/303] fix: card overlapping on content in IPad Signed-off-by: sanjay-k1910 --- src/components/Ecosystem/EcosystemList.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index 82970fe97..97eb503ee 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -283,12 +283,7 @@ const EcosystemList = () => { redirectOrgDashboard(item.id, role)} - className="transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden" - style={{ - maxHeight: '100%', - maxWidth: '100%', - overflow: 'auto', - }} + className="transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden max-w-full max-h-fit overflow-auto" >
    {item.logoUrl ? ( @@ -342,8 +337,6 @@ const EcosystemList = () => { ) : ( <> - {console.log(345345345, isWalletSpinUp, Boolean(selectedOrgId), Boolean(ecosystemList && ecosystemList?.length === 0)) - } {emptyListMessage(isWalletSpinUp, Boolean(selectedOrgId), Boolean(ecosystemList && ecosystemList?.length === 0))} )} From 7fbb4067a5465dbd451d4122a2b3dc49035caa3b Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Tue, 30 Jan 2024 14:03:49 +0530 Subject: [PATCH 082/303] fix: ui alignment issue Signed-off-by: sanjay-k1910 --- src/commonComponents/EcosystemProfileCard.tsx | 2 +- src/commonComponents/PublicNavbar.astro | 49 ++++++++++--------- .../Authentication/SignInUserPasskey.tsx | 2 +- src/components/Ecosystem/Dashboard.tsx | 2 +- .../publicProfile/ProfilesDesign.tsx | 3 +- src/pages/index.astro | 4 +- tailwind.config.cjs | 2 +- 7 files changed, 35 insertions(+), 29 deletions(-) diff --git a/src/commonComponents/EcosystemProfileCard.tsx b/src/commonComponents/EcosystemProfileCard.tsx index f912cf541..bda992736 100644 --- a/src/commonComponents/EcosystemProfileCard.tsx +++ b/src/commonComponents/EcosystemProfileCard.tsx @@ -90,7 +90,7 @@ const EcosystemProfileCard = () => { )}
    -
    +

    {ecosystemDetails?.name}

    diff --git a/src/commonComponents/PublicNavbar.astro b/src/commonComponents/PublicNavbar.astro index d5344d791..b8d99f5f5 100644 --- a/src/commonComponents/PublicNavbar.astro +++ b/src/commonComponents/PublicNavbar.astro @@ -65,7 +65,6 @@ const navbarClass = `bg-white dark:bg-gray-900 w-full z-20 top-0 left-0 border-g diff --git a/src/components/Authentication/SignInUserPasskey.tsx b/src/components/Authentication/SignInUserPasskey.tsx index bc1078900..0242f2f01 100644 --- a/src/components/Authentication/SignInUserPasskey.tsx +++ b/src/components/Authentication/SignInUserPasskey.tsx @@ -227,7 +227,7 @@ const SignInUserPasskey = (signInUserProps: signInUserProps) => {

    -
    +
    { )}
    {ecosystemDetails ? ( -
    +

    {ecosystemDetails?.name}

    diff --git a/src/components/publicProfile/ProfilesDesign.tsx b/src/components/publicProfile/ProfilesDesign.tsx index d835ded9d..01e9ac2a1 100644 --- a/src/components/publicProfile/ProfilesDesign.tsx +++ b/src/components/publicProfile/ProfilesDesign.tsx @@ -1,4 +1,5 @@ import CustomAvatar from "../../components/Avatar" +import '../../common/global.css' import type { IExploreOrg } from "../organization/interfaces" const ProfilesDesign = ({ orgData }: IExploreOrg) => { @@ -12,7 +13,7 @@ const ProfilesDesign = ({ orgData }: IExploreOrg) => { )} -

    {orgData?.name}

    +

    {orgData?.name}

    {orgData?.website && <>
    Date: Tue, 30 Jan 2024 15:33:43 +0530 Subject: [PATCH 083/303] Merge develop to QA (#544) * refactor: user profile Signed-off-by: karan * implemented new table Signed-off-by: karan * replaced old table with new table Signed-off-by: karan * implemented debouncing Signed-off-by: karan * fix: sonar lint issues Signed-off-by: karan * fix: sonar lint issues Signed-off-by: karan * handled dark mode Signed-off-by: karan * made minor changes Signed-off-by: karan * updated user dashboard Signed-off-by: karan * feat: implemented pagination on ecosystem Signed-off-by: karan * handled ecosystem error message Signed-off-by: karan * added sorting Signed-off-by: karan * handled all conditions Signed-off-by: karan * fix: margin and padding Signed-off-by: karan * improved tooltip data Signed-off-by: karan * fix: width issue Signed-off-by: karan * improved roles wise svg Signed-off-by: karan * changed verification svg Signed-off-by: karan * added sorting in oob Signed-off-by: karan * improved sorting Signed-off-by: karan * handled spell check Signed-off-by: karan * fix: PR Commits Signed-off-by: karan * fix: org and ecosystem edit popup Signed-off-by: karan * fix: org and ecosystem edit popup Signed-off-by: karan * placed process image function in enum Signed-off-by: karan * created common component to error message Signed-off-by: karan * fix: passkey auth Signed-off-by: karan * fix: validation for passkey Signed-off-by: karan * fix: connection issue Signed-off-by: karan * fix: connection issue Signed-off-by: karan * handled data types Signed-off-by: karan * handled data types Signed-off-by: karan * fix: verified details data sync issue Signed-off-by: karan * fix: verification popup Signed-off-by: karan --------- Signed-off-by: karan Co-authored-by: karan Co-authored-by: Sanjay Khatal <114503410+sanjay-k1910@users.noreply.github.com> Co-authored-by: Nishad Shirsat <103021375+nishad-ayanworks@users.noreply.github.com> Co-authored-by: 16-karan <141734327+16-karan@users.noreply.github.com> --- src/api/BulkIssuance.ts | 70 +- src/api/ecosystem.ts | 22 +- src/app/NavBarSidebar.astro | 115 ++- src/app/SideBar.astro | 253 ++++-- src/common/enums.ts | 7 + src/commonComponents/PasseyAddDevicePopup.tsx | 3 +- .../datatable/SortDataTable.tsx | 50 +- src/commonComponents/datatable/interface.ts | 35 +- src/commonComponents/formikerror/index.tsx | 6 + src/components/ConnectionsList/index.tsx | 2 +- .../Ecosystem/Endorsement/index.tsx | 2 +- src/components/Ecosystem/MemberList.tsx | 336 ++++---- src/components/Ecosystem/interfaces/index.ts | 22 +- .../EditEcosystemOrgModal/index.tsx | 718 +++++++++--------- src/components/Issuance/ConnectionList.tsx | 190 +++-- src/components/Issuance/History.tsx | 160 ++-- src/components/Issuance/HistoryDetails.tsx | 186 ++--- src/components/Issuance/IssuedCrdentials.tsx | 2 +- src/components/Profile/AddPasskey.tsx | 8 +- src/components/Profile/DisplayUser.tsx | 8 +- .../Resources/Schema/SchemasList.tsx | 2 +- src/components/SignOutButton/index.tsx | 81 +- src/components/User/UserDashBoard.tsx | 401 +++++++--- .../Verification/ConnectionList.tsx | 100 ++- .../Verification/ProofRequestPopup.tsx | 10 +- .../VerificationCredentialList.tsx | 18 +- src/components/Verification/interface.ts | 1 + src/components/organization/Dashboard.tsx | 51 +- .../organization/EditOrgdetailsModal.tsx | 192 ++--- .../organization/interfaces/index.ts | 18 +- src/utils/processImage.ts | 29 + tailwind.config.cjs | 2 + 32 files changed, 1734 insertions(+), 1366 deletions(-) create mode 100644 src/commonComponents/formikerror/index.tsx create mode 100644 src/utils/processImage.ts diff --git a/src/api/BulkIssuance.ts b/src/api/BulkIssuance.ts index 64f18a7dd..1d5d0ebdf 100644 --- a/src/api/BulkIssuance.ts +++ b/src/api/BulkIssuance.ts @@ -6,6 +6,7 @@ import { } from '../config/GetHeaderConfigs'; import { axiosGet, axiosPost } from '../services/apiRequests'; import { getFromLocalStorage } from './Auth'; +import type { IConnectionListAPIParameter } from './connection'; export const getSchemaCredDef = async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); @@ -40,7 +41,10 @@ export const DownloadCsvTemplate = async (credDefId: string) => { } }; -export const uploadCsvFile = async (payload: {file: Uint8Array | Blob, fileName:string}, credefId: string) => { +export const uploadCsvFile = async ( + payload: { file: Uint8Array | Blob; fileName: string }, + credefId: string, +) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.bulk.uploadCsv}?credDefId=${credefId}`; @@ -80,7 +84,10 @@ export const getCsvFileData = async ( } }; -export const issueBulkCredential = async (requestId: string, clientId: string) => { +export const issueBulkCredential = async ( + requestId: string, + clientId: string, +) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const url = `${apiRoutes.organizations.root}/${orgId}/${requestId}${apiRoutes.Issuance.bulk.bulk}`; @@ -88,8 +95,8 @@ export const issueBulkCredential = async (requestId: string, clientId: string) = url, config: await getHeaderConfigs(), payload: { - clientId - } + clientId, + }, }; try { @@ -100,31 +107,33 @@ export const issueBulkCredential = async (requestId: string, clientId: string) = } }; -export const retryBulkIssuance = async (fileId:string, clientId:string) => { - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}/${fileId}${apiRoutes.Issuance.bulk.retry}`; - - const axiosPayload = { - url, - payload:{clientId:clientId}, - config: await getHeaderConfigs(), - }; - - try { - return await axiosPost(axiosPayload); - } catch (error) { - const err = error as Error; - return err?.message; - } +export const retryBulkIssuance = async (fileId: string, clientId: string) => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const url = `${apiRoutes.organizations.root}/${orgId}/${fileId}${apiRoutes.Issuance.bulk.retry}`; + + const axiosPayload = { + url, + payload: { clientId: clientId }, + config: await getHeaderConfigs(), + }; + + try { + return await axiosPost(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } }; -export const getFilesHistory = async ( - pageNumber: number, - pageSize: number, - search: string, -) => { +export const getFilesHistory = async ({ + page, + itemPerPage, + search, + sortBy, + sortingOrder, +}: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.bulk.files}?pageNumber=${pageNumber}&pageSize=${pageSize}&search=${search}`; + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.bulk.files}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; const axiosPayload = { url, @@ -141,13 +150,14 @@ export const getFilesHistory = async ( export const getFilesDataHistory = async ( requestId: string, - pageNumber: number, - pageSize: number, + itemPerPage: number, + page: number, search: string, - sortBy:string + sortingOrder: string, + sortBy: string, ) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}/${requestId}${apiRoutes.Issuance.bulk.filesData}?pageNumber=${pageNumber}&pageSize=${pageSize}&search=${search}&sortBy=${sortBy}`; + const url = `${apiRoutes.organizations.root}/${orgId}/${requestId}${apiRoutes.Issuance.bulk.filesData}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortBy=${sortBy}&sortField=${sortingOrder}`; const axiosPayload = { url, diff --git a/src/api/ecosystem.ts b/src/api/ecosystem.ts index e72275f56..e72823489 100644 --- a/src/api/ecosystem.ts +++ b/src/api/ecosystem.ts @@ -4,6 +4,7 @@ import { apiRoutes } from '../config/apiRoutes'; import { getFromLocalStorage } from './Auth'; import { storageKeys } from '../config/CommonConstant'; import { getHeaderConfigs } from '../config/GetHeaderConfigs'; +import type { IMemberListAPIParameter } from '../components/Ecosystem/MemberList'; interface CreateEcosystemPayload { name: string; @@ -63,7 +64,12 @@ export const updateEcosystem = async (dataPayload: CreateEcosystemPayload) => { } }; -export const getEcosystems = async (orgId: string, pageNumber?: number, pageSize?: number, search = '') => { +export const getEcosystems = async ( + orgId: string, + pageNumber?: number, + pageSize?: number, + search = '', +) => { const url = `${apiRoutes.Ecosystem.root}/${orgId}`; const axiosPayload = { url, @@ -228,14 +234,16 @@ export const getEcosystemDashboard = async ( } }; -export const getEcosystemMemberList = async ( - pageNumber: number, - pageSize: number, - search: string, -) => { +export const getEcosystemMemberList = async ({ + page, + itemPerPage, + search, + sortBy, + sortingOrder, +}: IMemberListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const ecosystemId = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID); - const url = `${apiRoutes.Ecosystem.root}/${ecosystemId}/${orgId}${apiRoutes.Ecosystem.members}?pageNumber=${pageNumber}&pageSize=${pageSize}&search=${search}`; + const url = `${apiRoutes.Ecosystem.root}/${ecosystemId}/${orgId}${apiRoutes.Ecosystem.members}?pageNumber=${page}&pageSize=${itemPerPage}&search=${search}&sortBy=${sortingOrder.toLocaleLowerCase()}&sortField=${sortBy}`; const axiosPayload = { url, diff --git a/src/app/NavBarSidebar.astro b/src/app/NavBarSidebar.astro index 1f55009d7..a776d5259 100644 --- a/src/app/NavBarSidebar.astro +++ b/src/app/NavBarSidebar.astro @@ -13,14 +13,12 @@ import { getFromCookies } from '../api/Auth'; import { RolePermissions } from '../config/permissions'; const { hideOrgAgent } = Astro.props; -console.log(3242, hideOrgAgent) const role = getFromCookies(Astro.cookies, 'role'); const permittedPages = RolePermissions.find( (item) => item.role === role, )?.pages; - --- - ) } @@ -392,9 +396,21 @@ const permittedPages = RolePermissions.find( > View - - - + + + + Documentation + + + +
  • + + + + + Support + +
  • +
    -
    diff --git a/src/common/enums.ts b/src/common/enums.ts index 149a3ae3a..ea3ab190a 100644 --- a/src/common/enums.ts +++ b/src/common/enums.ts @@ -57,6 +57,13 @@ export enum EcosystemRoles { ecosystemLead = "Ecosystem Lead" } +export enum OrganizationRoles { + organizationMember = "member", + organizationOwner = "owner", + organizationIssuer = "issuer", + organizationVerifier = "verifier" +} + export enum PlatformRoles { platformAdmin = "platform_admin" } diff --git a/src/commonComponents/PasseyAddDevicePopup.tsx b/src/commonComponents/PasseyAddDevicePopup.tsx index a6a7707e9..a80c7f30c 100644 --- a/src/commonComponents/PasseyAddDevicePopup.tsx +++ b/src/commonComponents/PasseyAddDevicePopup.tsx @@ -18,7 +18,8 @@ interface PasswordValue { } const PasskeyAddDevice = (props: { - setOpenModel(arg0: boolean): unknown; openModal: boolean; closeModal: (flag: boolean) => void; registerWithPasskey: (flag: boolean) => Promise + setOpenModel(arg0: boolean): unknown; openModal: boolean; closeModal: (flag: boolean) => void; + registerWithPasskey: (flag: boolean) => Promise } ) => { const [fidoUserError, setFidoUserError] = useState(null) diff --git a/src/commonComponents/datatable/SortDataTable.tsx b/src/commonComponents/datatable/SortDataTable.tsx index 33e56f36d..fefc37d94 100644 --- a/src/commonComponents/datatable/SortDataTable.tsx +++ b/src/commonComponents/datatable/SortDataTable.tsx @@ -1,42 +1,11 @@ -import type { TableData, TableHeader } from './interface'; - +import type { IDataTable } from './interface'; import CustomSpinner from '../../components/CustomSpinner'; import SearchInput from '../../components/SearchInput'; import { Pagination } from 'flowbite-react'; -import { useState } from 'react'; +import { ChangeEvent, useState } from 'react'; import { EmptyListMessage } from '../../components/EmptyListComponent'; -import React from 'react'; - -interface DataTableProps { - header: TableHeader[]; - data: TableData[]; - loading: boolean; - callback?: (clickId: string | null | undefined) => void; - displaySelect?: boolean; - showBtn?: boolean; - onInputChange: () => void; - refresh: () => void; - currentPage: any; - onPageChange: () => void; - totalPages: number; - pageInfo?: - | { - totalItem: number | undefined; - nextPage: number | undefined; - lastPage: number | undefined; - } - | {}; - searchSortByValue: (value: any) => void; - isPagination: boolean; - isSearch: boolean; - isRefresh: boolean; - isSort: boolean; - isHeader: boolean; - message: string; - discription: string; -} -const SortDataTable: React.FC = ({ +const SortDataTable: React.FC = ({ header, displaySelect, data, @@ -57,13 +26,17 @@ const SortDataTable: React.FC = ({ isHeader, message, discription, + noExtraHeight, + sortOrder, }) => { - const [selectedValue, setSelectedValue] = useState(''); + const [selectedValue, setSelectedValue] = useState(sortOrder ?? ''); const handleSortByValues = (event: { target: { value: any } }) => { const newSelectedValue = event.target.value; setSelectedValue(newSelectedValue); - searchSortByValue(newSelectedValue); + if(searchSortByValue){ + searchSortByValue(newSelectedValue); + } }; const { @@ -82,9 +55,9 @@ const SortDataTable: React.FC = ({ const sortValues = [ { label: 'Descending', - value: 'DESC', + value: 'desc', }, - { label: 'Ascending', value: 'ASC' }, + { label: 'Ascending', value: 'asc' }, ]; return ( @@ -244,6 +217,7 @@ const SortDataTable: React.FC = ({
    diff --git a/src/commonComponents/datatable/interface.ts b/src/commonComponents/datatable/interface.ts index ab0a23849..2fac2355a 100644 --- a/src/commonComponents/datatable/interface.ts +++ b/src/commonComponents/datatable/interface.ts @@ -1,3 +1,5 @@ +import type { ChangeEvent } from "react"; + export interface TableHeader { columnName: string; subColumnName?: string; @@ -9,7 +11,38 @@ export interface TableData { data: Data[]; } -interface Data { +export interface Data { data: string | JSX.Element; subData?: string; } + +export interface IDataTable { + header: TableHeader[]; + data: TableData[]; + loading: boolean; + onInputChange: (e: ChangeEvent) => void; + refresh: () => void; + currentPage: any; + onPageChange: (page: number) => void; + totalPages: number; + searchSortByValue: (value: any) => void; + isPagination?: boolean; + isSearch: boolean; + isRefresh: boolean; + isSort: boolean; + isHeader: boolean; + message: string; + discription: string; + noExtraHeight?: boolean; + callback?: (clickId: string | null | undefined) => void; + displaySelect?: boolean; + showBtn?: boolean; + pageInfo?: + | { + totalItem: number | undefined; + nextPage: number | undefined; + lastPage: number | undefined; + } + | {}; + sortOrder?:string; +} diff --git a/src/commonComponents/formikerror/index.tsx b/src/commonComponents/formikerror/index.tsx new file mode 100644 index 000000000..2a8ad083d --- /dev/null +++ b/src/commonComponents/formikerror/index.tsx @@ -0,0 +1,6 @@ +import React from 'react'; + +const ErrorMessage = ({ error, touched }) => { + return touched && {error}; +}; +export default ErrorMessage; diff --git a/src/components/ConnectionsList/index.tsx b/src/components/ConnectionsList/index.tsx index b891faf89..099e2d4c9 100644 --- a/src/components/ConnectionsList/index.tsx +++ b/src/components/ConnectionsList/index.tsx @@ -22,7 +22,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; const ConnectionList = () => { diff --git a/src/components/Ecosystem/Endorsement/index.tsx b/src/components/Ecosystem/Endorsement/index.tsx index 05fc2cead..231e5e417 100644 --- a/src/components/Ecosystem/Endorsement/index.tsx +++ b/src/components/Ecosystem/Endorsement/index.tsx @@ -61,7 +61,7 @@ const EndorsementList = () => { page: 1, search: '', sortBy: 'id', - sortingOrder: 'DESC', + sortingOrder: 'desc', type: '', status: '', }); diff --git a/src/components/Ecosystem/MemberList.tsx b/src/components/Ecosystem/MemberList.tsx index 32178f52b..cea92655c 100644 --- a/src/components/Ecosystem/MemberList.tsx +++ b/src/components/Ecosystem/MemberList.tsx @@ -2,178 +2,190 @@ import { ChangeEvent, useEffect, useState } from 'react'; import { getEcosystemMemberList } from '../../api/ecosystem'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import type { AxiosResponse } from 'axios'; -import DataTable from '../../commonComponents/datatable'; -import type { TableData } from '../../commonComponents/datatable/interface'; +import type { Data } from '../../commonComponents/datatable/interface'; import DateTooltip from '../Tooltip'; import { dateConversion } from '../../utils/DateConversion'; import { AlertComponent } from '../AlertComponent'; -import { Pagination } from 'flowbite-react'; import { getFromLocalStorage } from '../../api/Auth'; -import SearchInput from '../SearchInput'; import CopyDid from '../../commonComponents/CopyDid'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { - pageNumber: 1, - pageSize: 10, - total: 0, + itemPerPage: 10, + page: 1, + search: '', + sortBy: 'createDateTime', + sortingOrder: 'ASC', + allSearch: '', }; interface IMemberList { orgId: string; ecosystem: { createDateTime: string }; ecosystemRole: { name: string }; - organisation: { name: string; orgSlug: string; org_agents: {orgDid: string}[] }; - // orgName: string; - // orgDid: string; + organisation: { + name: string; + orgSlug: string; + org_agents: { orgDid: string }[]; + }; role: string; createDateTime: any; status: string; copied?: boolean; + data: Data[]; +} +export interface IMemberListAPIParameter { + itemPerPage: number; + page: number; + search: string; + sortBy: string; + sortingOrder: string; + filter?: string; } - - const MemberList = () => { const [loading, setLoading] = useState(false); + const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [memberList, setMemberList] = useState([]); const [error, setError] = useState(null); - const [currentPage, setCurrentPage] = useState(initialPageState); - const [searchText, setSearchText] = useState(''); - const [memberTableData, setMemberTableData] = useState([]) + const [totalItem, setTotalItem] = useState(0); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); useEffect(() => { - generateTable(memberList) - }, [memberList]) + let getData: NodeJS.Timeout; + + if (listAPIParameter?.search?.length >= 1) { + getData = setTimeout(() => { + getEcosystemMembers(listAPIParameter); + }, 1000); + return () => clearTimeout(getData); + } else { + getEcosystemMembers(listAPIParameter); + } + + return () => clearTimeout(getData); + }, [listAPIParameter]); + + const refreshPage = () => { + getEcosystemMembers(listAPIParameter); + }; const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1, + }); }; - const generateTable = async (memberList: IMemberList[]): Promise => { + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + const getEcosystemMembers = async (apiParameter: IMemberListAPIParameter) => { const userOrgId = await getFromLocalStorage(storageKeys.ORG_ID); - const compareMembers = ( - firstMember: { ecosystemRole: { name: string } }, - secondMember: { ecosystemRole: { name: string } }, - ) => { - // remove this sorting logic when implemented from backend - const firstName = firstMember?.ecosystemRole?.name; - const secondName = secondMember?.ecosystemRole?.name; - - switch (true) { - case firstName > secondName: - return 1; - case secondName > firstName: - return -1; - default: - return 0; - } - }; - - const sortedMemberList = memberList && memberList.length > 0 && memberList?.sort(compareMembers); - const membersData = sortedMemberList && sortedMemberList.length > 0 && sortedMemberList?.map( - (member: IMemberList) => { - let orgDid ='Not available' - if(member.organisation.org_agents.length > 0){ - const orgAgent = member.organisation.org_agents[0]; - orgDid = orgAgent.orgDid - } - return { - data: [ - { - data: member?.organisation.name || 'Not available', - }, - { - data: - ( - - {dateConversion(member?.createDateTime)}{' '} - - ) || 'Not available', - }, - { - data: orgDid? ( -
    - -
    - ) : ( - - Not available - - ), - }, - { - data: member?.ecosystemRole?.name ? ( - - - {member?.ecosystemRole?.name} - - {member?.orgId === userOrgId ? '(You)' : ''} - - ) : ( - 'Not available' - ), - }, - { - data: member.status ? ( - - {member.status.charAt(0) + - member.status.slice(1).toLowerCase()} - - ) : ( - 'Not available' - ), - }, - ], - }; - }, - ); - - if(membersData){ - setMemberTableData(membersData); - } - } - - const getEcosystemMembers = async () => { setLoading(true); - const response = await getEcosystemMemberList( - currentPage.pageNumber, - currentPage.pageSize, - searchText - ); + const response = await getEcosystemMemberList(apiParameter); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const totalPages = data?.data?.totalPages; - setMemberList(data?.data?.members) - setCurrentPage({ - ...currentPage, - total: totalPages, + setTotalItem(data?.data.totalItems); + const { totalItems, nextPage, lastPage } = data.data; + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, }); + const memberList = + data?.data?.data?.length > 0 && + data?.data?.data?.map((member: IMemberList) => { + let orgDid = 'Not available'; + if (member.organisation.org_agents.length > 0) { + const orgAgent = member.organisation.org_agents[0]; + orgDid = orgAgent.orgDid; + } + return { + data: [ + { + data: member?.organisation.name || 'Not available', + }, + { + data: + ( + + {dateConversion(member?.createDateTime)}{' '} + + ) || 'Not available', + }, + { + data: orgDid ? ( +
    + +
    + ) : ( + + Not available + + ), + }, + { + data: member?.ecosystemRole?.name ? ( + + + {member?.ecosystemRole?.name} + + {member?.orgId === userOrgId ? '(You)' : ''} + + ) : ( + 'Not available' + ), + }, + { + data: member.status ? ( + + {member.status.charAt(0) + + member.status.slice(1).toLowerCase()} + + ) : ( + 'Not available' + ), + }, + ], + }; + }); + + setMemberList(memberList); } else { setError(response as string); } setLoading(false); }; - const onPageChange = (page: number) => { - setCurrentPage({ - ...currentPage, - pageNumber: page, - }); - }; - useEffect(() => { - getEcosystemMembers(); + getEcosystemMembers(listAPIParameter); }, []); const header = [ @@ -187,38 +199,46 @@ const MemberList = () => { return (
    -
    -

    - Ecosystem Members -

    -
    - -
    +

    + Ecosystem Members +

    +
    + { + setError(null); + }} + />
    - { - setError(null); - }} - /> - - - {currentPage.total > 1 && ( -
    - -
    - )} + currentPage={listAPIParameter.page} + onPageChange={(page: number) => { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + searchSortByValue={searchSortByValue} + totalPages={totalItem} + pageInfo={pageInfo} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={true} + isPagination={true} + message={'No Members'} + discription={"The ecosystem doesn't have any matching member"} + noExtraHeight={true} + sortOrder={listAPIParameter.sortingOrder} + >
    ); }; diff --git a/src/components/Ecosystem/interfaces/index.ts b/src/components/Ecosystem/interfaces/index.ts index 479f2f950..bc85f9042 100644 --- a/src/components/Ecosystem/interfaces/index.ts +++ b/src/components/Ecosystem/interfaces/index.ts @@ -26,4 +26,24 @@ export interface Ecosystem { website: string roles: string[] logoFile:string -} \ No newline at end of file +} + +export interface EditEntityModalProps { + openModal: boolean; + setMessage: (message: string) => void; + setOpenModal: (flag: boolean) => void; + onEditSuccess?: () => void; + entityData: Ecosystem | null; + isOrganization: boolean; +} + +export interface EditEntityValues { + name: string; + description: string; +} + +export interface ILogoImage { + logoFile: string | File; + imagePreviewUrl: string | ArrayBuffer | null | File; + fileName: string; +} diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index 549fc273d..e649fd707 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -1,396 +1,366 @@ -import * as yup from "yup"; +import * as yup from 'yup'; import { Avatar, Button, Label, Modal } from 'flowbite-react'; import { Field, Form, Formik, FormikHelpers } from 'formik'; -import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, apiStatusCodes, imageSizeAccepted } from '../../config/CommonConstant'; -import { calculateSize, dataURItoBlob } from "../../utils/CompressImage"; -import { AlertComponent } from "../AlertComponent"; +import { apiStatusCodes } from '../../config/CommonConstant'; +import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; -import { updateOrganization } from "../../api/organization"; -import { updateEcosystem } from "../../api/ecosystem"; -import type { Ecosystem } from "../Ecosystem/interfaces"; -import React, { useEffect, useState } from "react"; -import EndorsementTooltip from "../../commonComponents/EndorsementTooltip"; - -interface EditEntityModalProps { - openModal: boolean; - setMessage: (message: string) => void; - setOpenModal: (flag: boolean) => void; - onEditSuccess?: () => void; - entityData: Ecosystem | null; - isOrganization: boolean; - -} - -interface EditEntityValues { - name: string; - description: string; -} - -interface ILogoImage { - logoFile: string | File; - imagePreviewUrl: string | ArrayBuffer | null | File; - fileName: string; -} +import { updateOrganization } from '../../api/organization'; +import { updateEcosystem } from '../../api/ecosystem'; +import type { + EditEntityModalProps, + EditEntityValues, + ILogoImage, +} from '../Ecosystem/interfaces'; +import React, { useEffect, useState } from 'react'; +import EndorsementTooltip from '../../commonComponents/EndorsementTooltip'; +import { processImage } from '../../utils/processImage'; +import FormikErrorMessage from '../../commonComponents/formikerror/index' const EditPopupModal = (props: EditEntityModalProps) => { - const [logoImage, setLogoImage] = useState({ - logoFile: "", - imagePreviewUrl: props?.entityData?.logoUrl ?? "", - fileName: '', - }); - - const [loading, setLoading] = useState(false); - const [isImageEmpty, setIsImageEmpty] = useState(true); - const [initialEntityData, setInitialEntityData] = useState({ - name: "", - description: "" - }); - - useEffect(() => { - if (props.openModal && props.entityData) { - setInitialEntityData({ - name: props.entityData.name ?? "", - description: props.entityData.description ?? "", - }); - SetisAutoEndorse(props.entityData.autoEndorsement) - setLogoImage({ - logoFile: "", - imagePreviewUrl: props.entityData.logoUrl ?? "", - fileName: props.entityData.logoFile ?? "", - }); - } - }, [props.entityData, props.openModal]); - - const [errMsg, setErrMsg] = useState(null); - const [imgError, setImgError] = useState(''); - const [isAutoEndorse, SetisAutoEndorse] = useState(false) + const [logoImage, setLogoImage] = useState({ + logoFile: '', + imagePreviewUrl: props?.entityData?.logoUrl ?? '', + fileName: '', + }); + const [loading, setLoading] = useState(false); + const [initialEntityData, setInitialEntityData] = useState({ + name: '', + description: '', + }); - useEffect(() => { - if (!props.openModal) { - setInitialEntityData({ - name: "", - description: "", - }); + useEffect(() => { + if (props.openModal && props.entityData) { + setInitialEntityData({ + name: props.entityData.name ?? '', + description: props.entityData.description ?? '', + }); + setIsAutoEndorse(props.entityData.autoEndorsement); + setLogoImage({ + logoFile: '', + imagePreviewUrl: props.entityData.logoUrl ?? '', + fileName: props.entityData.logoFile ?? '', + }); + } + }, [props.entityData, props.openModal]); - setLogoImage({ - logoFile: "", - imagePreviewUrl: "", - fileName: "", - }); - setImgError(''); - setErrMsg(null); - setLoading(false); - } - }, [props.openModal]); - - const processImage = (e: any): string | undefined => { - const file = e?.target?.files[0]; - if (!file) return; + const [errMsg, setErrMsg] = useState(null); + const [imgError, setImgError] = useState(''); + const [isAutoEndorse, setIsAutoEndorse] = useState(false); - const reader = new FileReader(); - reader.readAsDataURL(file); + useEffect(() => { + if (!props.openModal) { + setInitialEntityData({ + name: '', + description: '', + }); - reader.onload = (event): void => { - const imgElement = document.createElement("img"); - if (imgElement) { - imgElement.src = typeof event?.target?.result === 'string' ? event.target.result : ""; - imgElement.onload = (e): void => { - let fileUpdated: File | string = file; - let srcEncoded = ''; - const canvas = document.createElement("canvas"); + setLogoImage({ + logoFile: '', + imagePreviewUrl: '', + fileName: '', + }); + setImgError(''); + setErrMsg(null); + setLoading(false); + } + }, [props.openModal]); - const { width, height, ev } = calculateSize(imgElement, IMG_MAX_WIDTH, IMG_MAX_HEIGHT); - canvas.width = width; - canvas.height = height; + const handleImageChange = (event: any): void => { + setImgError(''); + processImage(event, (result: any, error: any) => { + if (result) { + setLogoImage({ + logoFile: '', + imagePreviewUrl: result, + fileName: event.target.files[0].name, + }); + } else { + setImgError(error || 'An error occurred while processing the image.'); + } + }); + }; - const ctx = canvas.getContext("2d"); - if (ctx && e?.target) { - ctx.imageSmoothingEnabled = true; - ctx.imageSmoothingQuality = "high"; - ctx.drawImage(ev, 0, 0, canvas.width, canvas.height); - srcEncoded = ctx.canvas.toDataURL(ev, file.type); - const blob = dataURItoBlob(srcEncoded, file.type); - fileUpdated = new File([blob], file.name, { type: file.type, lastModified: new Date().getTime() }); - setLogoImage({ - logoFile: fileUpdated, - imagePreviewUrl: srcEncoded, - fileName: file.name - }); - } - }; - } - }; - }; - - const handleImageChange = (event: any): void => { - setImgError(''); - const reader = new FileReader(); - const file = event?.target?.files; - - const fileSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); - const extension = file[0]?.name?.substring(file[0]?.name?.lastIndexOf(".") + 1)?.toLowerCase(); + const submitUpdateEntity = async (values: EditEntityValues) => { + setLoading(true); - if (extension === "png" || extension === "jpeg" || extension === "jpg") { - if (fileSize <= imageSizeAccepted) { - reader.onloadend = (): void => { - processImage(event); - setIsImageEmpty(false); - }; - reader.readAsDataURL(file[0]); - event.preventDefault(); - } else { - setImgError("Please check image size"); - } - } else { - setImgError("Invalid image type"); - } - }; + const entityData = { + id: props?.entityData?.id, + name: values.name, + description: values.description, + logo: + (logoImage?.imagePreviewUrl as string) || props?.entityData?.logoUrl, + autoEndorsement: isAutoEndorse, + }; - const isEmpty = (object: any): boolean => { + try { + if (props.isOrganization) { + const response = await updateOrganization( + entityData, + entityData.id?.toString() as string, + ); + const { data } = response as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (props?.onEditSuccess) { + props?.onEditSuccess(); + } + props.setOpenModal(false); + props.setMessage(data?.message); + } else { + setErrMsg(response as string); + setLoading(false); + } + } else { + const response = await updateEcosystem(entityData); + const { data } = response as AxiosResponse; - return true; - }; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (props?.onEditSuccess) { + props?.onEditSuccess(); + } + props.setOpenModal(false); + props.setMessage(data?.message); + } else { + setErrMsg(response as string); + setLoading(false); + } + } + } catch (error) { + console.error('An error occurred:', error); + setLoading(false); + } + }; - const submitUpdateEntity = async (values: EditEntityValues) => { - setLoading(true); + return ( + { + setLogoImage({ + logoFile: '', + imagePreviewUrl: '', + fileName: '', + }); + setInitialEntityData({ + name: '', + description: '', + }); + props.setOpenModal(false); + }} + > + + Edit {props.isOrganization ? 'Organization' : 'Ecosystem'} + + + { + setErrMsg(null); + }} + /> + , + ) => { + await submitUpdateEntity(values); + }} + > + {(formikHandlers): JSX.Element => ( +
    +
    +
    + {logoImage.imagePreviewUrl ? ( + {`${ + ) : ( + + )} - const entityData = { - id: props?.entityData?.id, - name: values.name, - description: values.description, - logo: logoImage?.imagePreviewUrl as string || props?.entityData?.logoUrl, - autoEndorsement:isAutoEndorse - }; - - try { - if (props.isOrganization) { - const response = await updateOrganization(entityData, entityData.id?.toString() as string); - const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - if (props?.onEditSuccess) { - props?.onEditSuccess(); - } - props.setOpenModal(false); - } else { - setErrMsg(data?.message as string); - } - } else { - const response = await updateEcosystem(entityData); - const { data } = response as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - if (props?.onEditSuccess) { - props?.onEditSuccess(); - } - props.setOpenModal(false); - } else { - setErrMsg(data?.message as string); - } - } - } catch (error) { - console.error("An error occurred:", error); - setLoading(false); - } - }; - return ( - { - setLogoImage({ - logoFile: "", - imagePreviewUrl: "", - fileName: '' - }); - setInitialEntityData({ - name: "", - description: "" - }); - props.setOpenModal(false); - }}> - Edit {props.isOrganization ? "Organization" : "Ecosystem"} - - { - setErrMsg(null); - }} - /> - - ) => { - await submitUpdateEntity(values); - }} - > - {(formikHandlers): JSX.Element => ( - -
    -
    - {logoImage.imagePreviewUrl ? ( - {`${props.isOrganization - ) : ( - - )} - -
    -

    - {props.isOrganization ? "Organization Logo" : "Ecosystem Logo"} -

    -
    - JPG, JPEG and PNG. Max size of 1MB -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - { - const value = e.target.value; - formikHandlers.setFieldValue('name', value); - formikHandlers.setFieldTouched('name', true, false); - - if (value.length > 50) { - formikHandlers.setFieldError('name', props.isOrganization ? 'Organization name must be at most 50 characters' : 'Ecosystem name must be at most 50 characters'); - } - }} - - /> - {formikHandlers?.errors?.name && formikHandlers?.touched?.name && ( - {formikHandlers?.errors?.name} - )} -
    -
    -
    -
    - { - const value = e.target.value; - formikHandlers.setFieldValue('description', value); - formikHandlers.setFieldTouched('description', true, false); - - if (value.length > 50) { - formikHandlers.setFieldError('description', 'Description must be at most 255 characters'); - } - }} - - /> - {formikHandlers?.errors?.description && formikHandlers?.touched?.description && ( - {formikHandlers?.errors?.description} - )} -
    -
    -
    -
    +
    +
    +
    +
    + { + const value = e.target.value; + formikHandlers.setFieldValue('name', value); + formikHandlers.setFieldTouched('name', true, false); + + if (value.length > 50) { + formikHandlers.setFieldError( + 'name', + props.isOrganization + ? 'Organization name must be at most 50 characters' + : 'Ecosystem name must be at most 50 characters', + ); + } + }} + /> + +
    +
    +
    +
    + { + const value = e.target.value; + formikHandlers.setFieldValue('description', value); + formikHandlers.setFieldTouched('description', true, false); - Update - - - )} - - - - ); + if (value.length > 50) { + formikHandlers.setFieldError( + 'description', + 'Description must be at most 255 characters', + ); + } + }} + /> + +
    +
    +
    +
    +
    + setIsAutoEndorse(false)} + /> + + Sign + +
    +
    + setIsAutoEndorse(true)} + /> + + Sign and Submit + +
    +
    + + + )} +
    +
    +
    + ); }; -export default EditPopupModal; \ No newline at end of file +export default EditPopupModal; diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index 60a0493f2..253faba28 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -6,23 +6,20 @@ import { IConnectionListAPIParameter, getConnectionsByOrg, } from '../../api/connection'; -import DataTable from '../../commonComponents/datatable'; import type { TableData } from '../../commonComponents/datatable/interface'; import { apiStatusCodes } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; -import SearchInput from '../SearchInput'; -import { Pagination } from 'flowbite-react'; -import type { IConnectionList } from './interface' - +import type { IConnectionList } from './interface'; +import NewDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { itemPerPage: 10, page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; const ConnectionList = (props: { @@ -37,13 +34,26 @@ const ConnectionList = (props: { const [loading, setLoading] = useState(false); const [totalItem, setTotalItem] = useState(0); const [error, setError] = useState(null); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); - //This useEffect is called when the searchText changes useEffect(() => { - getConnections(listAPIParameter); + let getData: NodeJS.Timeout; + + if (listAPIParameter?.search?.length >= 1) { + getData = setTimeout(() => { + getConnections(listAPIParameter); + }, 1000); + return () => clearTimeout(getData); + } else { + getConnections(listAPIParameter); + } + return () => clearTimeout(getData); }, [listAPIParameter]); - //Fetch the connection list against organization id const getConnections = async (apiParameter: IConnectionListAPIParameter) => { setLoading(true); try { @@ -51,55 +61,58 @@ const ConnectionList = (props: { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const { totalItems, nextPage, lastPage } = data.data; setTotalItem(data?.data.totalItems); - const connections = data?.data?.data?.map( - (ele: IConnectionList) => { - const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; - const connectionId = ele.connectionId - ? ele.connectionId - : 'Not available'; - const createdOn = ele?.createDateTime - ? ele?.createDateTime - : 'Not available'; - return { - data: [ - { - data: ( -
    - , - ) => { - const inputElement = event.target as HTMLInputElement; - selectConnection( - userName, - connectionId, - inputElement.checked, - ); - }} - value="" - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" - /> -
    - ), - }, - { data: userName }, - { data: connectionId }, - { - data: ( - - {' '} - {dateConversion(createdOn)}{' '} - - ), - }, - ], - }; - }, - ); + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, + }); + const connections = data?.data?.data?.map((ele: IConnectionList) => { + const createdOn = ele?.createDateTime + ? ele?.createDateTime + : 'Not available'; + const connectionId = ele.connectionId + ? ele.connectionId + : 'Not available'; + const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; + return { + data: [ + { + data: ( +
    + ) => { + const inputElement = event.target as HTMLInputElement; + selectConnection( + userName, + connectionId, + inputElement.checked, + ); + }} + value="" + className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded-lg dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" + /> +
    + ), + }, + { data: userName }, + { data: connectionId }, + { + data: ( + + {' '} + {dateConversion(createdOn)}{' '} + + ), + }, + ], + }; + }); setConnectionList(connections); setError(null); @@ -169,6 +182,19 @@ const ConnectionList = (props: { } }; + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + + const refreshPage = () => { + setSelectedConnectionList([]); + getConnections(listAPIParameter); + }; + useEffect(() => { props.selectConnection(selectedConnectionList); }, [selectedConnectionList]); @@ -182,9 +208,6 @@ const ConnectionList = (props: {

    Connection List

    -
    - -
    -
    - -
    - {Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && ( -
    - { - setListAPIParameter((prevState) => ({ - ...prevState, - page: page, - })); - }} - totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} - /> -
    - )} + { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + pageInfo={pageInfo} + searchSortByValue={searchSortByValue} + message={'No Connections'} + discription={"You don't have any connections yet"} + >
    ); }; diff --git a/src/components/Issuance/History.tsx b/src/components/Issuance/History.tsx index 0b186ec30..9afa4b29c 100644 --- a/src/components/Issuance/History.tsx +++ b/src/components/Issuance/History.tsx @@ -2,19 +2,15 @@ import 'react-toastify/dist/ReactToastify.css'; import type { AxiosResponse } from 'axios'; import { ChangeEvent, useEffect, useState } from 'react'; -import DataTable from '../../commonComponents/datatable'; import type { TableData } from '../../commonComponents/datatable/interface'; import { apiStatusCodes } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; import BreadCrumbs from '../BreadCrumbs'; -import CustomSpinner from '../CustomSpinner'; -import { EmptyListMessage } from '../EmptyListComponent'; import BackButton from '../../commonComponents/backbutton'; import { pathRoutes } from '../../config/pathRoutes'; -import SearchInput from '../SearchInput'; -import { Button, Pagination } from 'flowbite-react'; +import { Button } from 'flowbite-react'; import { getFilesHistory, retryBulkIssuance } from '../../api/BulkIssuance'; import SOCKET from '../../config/SocketConfig'; import { @@ -23,33 +19,38 @@ import { } from '../../common/enums'; import { ToastContainer, toast } from 'react-toastify'; import React from 'react'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; +import type { IConnectionListAPIParameter } from '../../api/connection'; const HistoryBulkIssuance = () => { const initialPageState = { - pageNumber: 1, - pageSize: 9, - total: 0, + itemPerPage: 10, + page: 1, + search: '', + sortBy: 'createDateTime', + sortingOrder: 'desc', }; - + const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [connectionList, setConnectionList] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [currentPage, setCurrentPage] = useState(initialPageState); const [failure, setFailure] = useState(null); const [success, setSuccess] = useState(null); - - const onPageChange = (page: number) => { - setCurrentPage({ - ...currentPage, - pageNumber: page, - }); - }; - const [searchText, setSearchText] = useState(''); + const [totalItem, setTotalItem] = useState(0); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1, + }); }; - const handleRetry = async (fileId: string) => { setSuccess('Issuance process reinitiated. Please wait a moment.'); setLoading(true); @@ -59,7 +60,7 @@ const HistoryBulkIssuance = () => { if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { if (data?.data) { setLoading(false); - getConnections(); + getHistory(listAPIParameter); } else { setLoading(false); } @@ -72,6 +73,14 @@ const HistoryBulkIssuance = () => { } }; + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + useEffect(() => { SOCKET.emit('bulk-connection'); SOCKET.on('bulk-issuance-process-retry-completed', () => { @@ -87,7 +96,7 @@ const HistoryBulkIssuance = () => { progress: undefined, theme: 'colored', }); - getConnections(); + getHistory(listAPIParameter); }); SOCKET.on('error-in-bulk-issuance-retry-process', () => { @@ -103,34 +112,37 @@ const HistoryBulkIssuance = () => { progress: undefined, theme: 'colored', }); - getConnections(); + getHistory(listAPIParameter); }); let getData: NodeJS.Timeout; - if (searchText.length >= 1) { + if (listAPIParameter.search.length >= 1) { getData = setTimeout(() => { - getConnections(); + getHistory(listAPIParameter); }, 1000); return () => clearTimeout(getData); } else { - getConnections(); + getHistory(listAPIParameter); } return () => clearTimeout(getData); - }, [searchText, currentPage.pageNumber]); + }, [listAPIParameter]); - const getConnections = async () => { + const getHistory = async (apiParameter: IConnectionListAPIParameter) => { setLoading(true); - const response = await getFilesHistory( - currentPage.pageNumber, - currentPage.pageSize, - searchText, - ); + const response = await getFilesHistory(apiParameter ); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const totalPages = data?.data?.lastPage; + setTotalItem(data?.data.totalItems); + const { totalItems, nextPage, lastPage } = data.data; + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, + }); const connections = data?.data?.data?.map( (ele: { totalRecords: any; @@ -255,10 +267,6 @@ const HistoryBulkIssuance = () => { }, ); setConnectionList(connections); - setCurrentPage({ - ...currentPage, - total: totalPages, - }); } else { if (response?.toString()?.toLowerCase() !== 'history not found') { setFailure(response as string); @@ -277,6 +285,10 @@ const HistoryBulkIssuance = () => { { columnName: 'Action' }, ]; + const refreshPage = () => { + getHistory(listAPIParameter); + }; + return (
    @@ -284,21 +296,6 @@ const HistoryBulkIssuance = () => {
    -
    @@ -313,9 +310,6 @@ const HistoryBulkIssuance = () => {

    Bulk Issuance History

    -
    - -
    {(success || failure) && ( @@ -330,39 +324,29 @@ const HistoryBulkIssuance = () => { /> )} - {loading ? ( -
    - -
    - ) : connectionList && connectionList?.length > 0 ? ( -
    - - - {currentPage.total > 1 && ( -
    - -
    - )} -
    - ) : ( -
    - -
    - )} + { + setCurrentPage((prevState) => ({ + ...prevState, + page, + })); + }} + searchSortByValue={searchSortByValue} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + pageInfo={pageInfo} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={true} + message={'No History'} + discription={"You don't have any activities yet"} + >
    ); }; diff --git a/src/components/Issuance/HistoryDetails.tsx b/src/components/Issuance/HistoryDetails.tsx index 80df39283..52eb85f67 100644 --- a/src/components/Issuance/HistoryDetails.tsx +++ b/src/components/Issuance/HistoryDetails.tsx @@ -1,20 +1,17 @@ 'use client'; import { ChangeEvent, useEffect, useState } from 'react'; -import DataTable from '../../commonComponents/datatable'; import type { TableData } from '../../commonComponents/datatable/interface'; import { apiStatusCodes } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import BreadCrumbs from '../BreadCrumbs'; -import CustomSpinner from '../CustomSpinner'; -import { EmptyListMessage } from '../EmptyListComponent'; import { pathRoutes } from '../../config/pathRoutes'; import BackButton from '../../commonComponents/backbutton'; -import SearchInput from '../SearchInput'; import { getFilesDataHistory } from '../../api/BulkIssuance'; import type { AxiosResponse } from 'axios'; -import { Pagination } from 'flowbite-react'; import { BulkIssuanceStatus } from '../../common/enums'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; +import type { IConnectionListAPIParameter } from '../../api/connection'; interface IProps { requestId: string; @@ -22,76 +19,55 @@ interface IProps { const HistoryDetails = ({ requestId }: IProps) => { const initialPageState = { - pageNumber: 1, - pageSize: 10, - total: 0, + itemPerPage: 10, + page: 1, + search: '', + sortBy: 'createDateTime', + sortingOrder: 'desc', }; + + const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [historyList, setHistoryList] = useState([]); - const [options, setOptions] = useState(['All', 'Successful', 'Failed']); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [currentPage, setCurrentPage] = useState(initialPageState); - const [searchText, setSearchText] = useState(''); - const [sortBy, setSortBy] = useState('All'); - - const onPageChange = (page: number) => { - setCurrentPage({ - ...currentPage, - pageNumber: page, - }); - }; - useEffect(() => { - let getData: NodeJS.Timeout; - - if (searchText.length >= 1) { - getData = setTimeout(() => { - getHistoryDetails(); - }, 1000); - return () => clearTimeout(getData); - } else { - getHistoryDetails(); - } - - return () => clearTimeout(getData); - }, [searchText, currentPage.pageNumber]); + const [totalItem, setTotalItem] = useState(0); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); useEffect(() => { let getData: NodeJS.Timeout; - if (sortBy !== 'All') { + if (listAPIParameter.search.length >= 1) { getData = setTimeout(() => { - getHistoryDetails(); + getHistoryDetails(listAPIParameter); }, 1000); + return () => clearTimeout(getData); } else { - getHistoryDetails(); + getHistoryDetails(listAPIParameter); } return () => clearTimeout(getData); - }, [sortBy]); - - const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); - }; + }, [listAPIParameter]); - const handleFilter = async (e: React.ChangeEvent) => { - setSortBy(e.target.value); - }; - - const getHistoryDetails = async () => { + const getHistoryDetails = async (apiParameter: IConnectionListAPIParameter) => { setLoading(true); - const response = await getFilesDataHistory( - requestId, - currentPage.pageNumber, - currentPage.pageSize, - searchText, - sortBy, - ); + const response = await getFilesDataHistory(requestId, apiParameter.itemPerPage, apiParameter.page, apiParameter.search, apiParameter.sortBy, apiParameter.sortingOrder); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const totalPages = data?.data?.lastPage; + setTotalItem(data?.data.totalItems); + const { totalItems, nextPage, lastPage } = data.data; + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, + }); const historyData = data?.data?.data?.map( (history: { isError: any; @@ -116,13 +92,17 @@ const HistoryDetails = ({ requestId }: IProps) => { : 'bg-red-100 text-red-800 border border-red-100 dark:border-red-400 dark:bg-gray-700 dark:text-red-400' } text-md font-medium sm:mr-0 md:mr-2 px-2 min-[320]:px-3 sm:px-3 lg:px-3 py-0.5 rounded-md flex justify-center w-fit`} > - {history?.isError === false ? BulkIssuanceStatus.successful : BulkIssuanceStatus.failed} + {history?.isError === false + ? BulkIssuanceStatus.successful + : BulkIssuanceStatus.failed}

    ), }, { data: history?.error - ? history?.error === 'Http Exception' ? 'Credential Issuance failed due to error in Wallet Agent' : history?.error?.replace(/[[\]"{},]/g, ' ') + ? history?.error === 'Http Exception' + ? 'Credential Issuance failed due to error in Wallet Agent' + : history?.error?.replace(/[[\]"{},]/g, ' ') : '-', }, ], @@ -130,16 +110,31 @@ const HistoryDetails = ({ requestId }: IProps) => { }, ); setHistoryList(historyData); - setCurrentPage({ - ...currentPage, - total: totalPages, - }); } else { setError(response as string); } setLoading(false); }; + const searchInputChange = (e: ChangeEvent) => { + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1, + }); + }; + + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + + const refreshPage = () => { + getHistoryDetails(listAPIParameter); + }; const header = [ { columnName: 'User' }, { columnName: 'Status' }, @@ -163,24 +158,6 @@ const HistoryDetails = ({ requestId }: IProps) => {

    Bulk Issuance History Details

    -
    - - - -
    { }} /> - {loading ? ( -
    - -
    - ) : historyList && historyList?.length > 0 ? ( -
    - - {currentPage.total > 1 && ( -
    - -
    - )} -
    - ) : ( -
    - -
    - )} + { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + searchSortByValue={searchSortByValue} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + pageInfo={pageInfo} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={true} + message={'No History'} + discription={"You don't have any activities yet"} + >
    ); }; diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 6b3517383..7f584da16 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -27,7 +27,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; diff --git a/src/components/Profile/AddPasskey.tsx b/src/components/Profile/AddPasskey.tsx index 184ee14e5..8485daaf8 100644 --- a/src/components/Profile/AddPasskey.tsx +++ b/src/components/Profile/AddPasskey.tsx @@ -58,7 +58,13 @@ const AddPasskey = ({ responseMessages }: { responseMessages: (value: IResponseM const addDevice = async (): Promise => { try { - setOpenModel(true); + if(deviceList?.length > 0){ + registerWithPasskey(true) + setOpenModel(false); + }else{ + setOpenModel(true); + + } } catch (error) { setFidoLoader(false); } diff --git a/src/components/Profile/DisplayUser.tsx b/src/components/Profile/DisplayUser.tsx index b8af4dc59..120d9848d 100644 --- a/src/components/Profile/DisplayUser.tsx +++ b/src/components/Profile/DisplayUser.tsx @@ -27,16 +27,16 @@ const DisplayUser = () => { userObj && <>

    {userObj['firstName']}

    -

    +

    {userObj['email']}

    {TextTittlecase(userObj['roles'])} @@ -49,4 +49,4 @@ const DisplayUser = () => { ) } -export default DisplayUser \ No newline at end of file +export default DisplayUser diff --git a/src/components/Resources/Schema/SchemasList.tsx b/src/components/Resources/Schema/SchemasList.tsx index f03b7073f..48e89bd15 100644 --- a/src/components/Resources/Schema/SchemasList.tsx +++ b/src/components/Resources/Schema/SchemasList.tsx @@ -36,7 +36,7 @@ const SchemaList = (props: { page: 1, search: '', sortBy: 'id', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }); const [walletStatus, setWalletStatus] = useState(false); diff --git a/src/components/SignOutButton/index.tsx b/src/components/SignOutButton/index.tsx index 91172287c..13e1ba46f 100644 --- a/src/components/SignOutButton/index.tsx +++ b/src/components/SignOutButton/index.tsx @@ -1,34 +1,57 @@ -import { removeFromLocalStorage } from "../../api/Auth" -import { storageKeys } from "../../config/CommonConstant" +import { removeFromLocalStorage } from '../../api/Auth'; +import { storageKeys } from '../../config/CommonConstant'; const SignOutButton = () => { + const signOut = async () => { + await removeFromLocalStorage(storageKeys.TOKEN); + await removeFromLocalStorage(storageKeys.USER_EMAIL); + await removeFromLocalStorage(storageKeys.ORG_ID); + await removeFromLocalStorage(storageKeys.ORG_ROLES); + await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); + await removeFromLocalStorage(storageKeys.ECOSYSTEM_ROLE); + await removeFromLocalStorage(storageKeys.USER_PROFILE); - const signOut = async () => { + const response = await fetch('/api/auth/signout', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); - await removeFromLocalStorage(storageKeys.TOKEN) - await removeFromLocalStorage(storageKeys.USER_EMAIL) - await removeFromLocalStorage(storageKeys.ORG_ID) - await removeFromLocalStorage(storageKeys.ORG_ROLES) - await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID) - await removeFromLocalStorage(storageKeys.ECOSYSTEM_ROLE) - await removeFromLocalStorage(storageKeys.USER_PROFILE) + if (response.redirected) { + window.location.assign(response.url); + } + }; + return ( + + ); +}; - const response = await fetch('/api/auth/signout', { - method: "GET", - headers: { - "Content-Type": "application/json", - } - }); - - if (response.redirected) { - window.location.assign(response.url); - } - } - return ( - - ) -} - -export default SignOutButton \ No newline at end of file +export default SignOutButton; diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 04a8edb0e..d808ce07c 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -21,8 +21,9 @@ import { getAllCredDef, getAllSchemasByOrgId } from '../../api/Schema'; import type { GetAllSchemaListParameter } from '../Resources/Schema/interfaces'; import { getEcosystems } from '../../api/ecosystem'; import React from 'react'; - +import { EcosystemRoles, OrganizationRoles } from '../../common/enums'; import CustomSpinner from '../CustomSpinner'; + const initialPageState = { pageNumber: 1, pageSize: 10, @@ -65,7 +66,7 @@ const UserDashBoard = () => { page: 1, search: '', sortBy: 'id', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }); const [ecoCount, setEcoCount] = useState(0); @@ -79,6 +80,7 @@ const UserDashBoard = () => { const [orgLoading, setOrgLoading] = useState(true); const [schemaLoading, setSchemaLoading] = useState(true); const [walletLoading, setWalletLoading] = useState(true); + const getAllInvitations = async () => { setLoading(true); const response = await getUserInvitations( @@ -218,6 +220,8 @@ const UserDashBoard = () => { } } catch (error) { setSchemaLoading(false); + } finally { + setSchemaLoading(false); } }; @@ -235,7 +239,6 @@ const UserDashBoard = () => { '', ); const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setEcoCount(data?.data?.totalCount); const ecosystemData = data?.data?.ecosystemDetails.filter( @@ -316,6 +319,14 @@ const UserDashBoard = () => { getAllResponses(); }, []); + useEffect(() => { + if (!orgLoading) { + setSchemaLoading(false); + setCredDefLoading(false); + setEcoLoading(false); + } + }, [orgLoading]); + useEffect(() => { if (organizationsList && organizationsList?.length > 0) { fetchOrganizationDetails(); @@ -400,34 +411,81 @@ const UserDashBoard = () => { window.location.href = pathRoutes.organizations.credentials; }; - const ToolTipData = ({ isEcosystem }) => { + const navigateToInvitation = () => { + window.location.href = pathRoutes.ecosystem.sentinvitation; + }; + + const ToolTipDataForOrganization = () => { return (

    -

    - What is {isEcosystem ? 'Ecosystem' : 'Organization'}? -

    {' '} - Contacts are people or organizations you've
    - interacted with. +

    What is Organization?

    + An organization is a participating entity, such as +
    a business, institution, or group. Organizations
    - You're connected over a secure and private -
    line that no one but you or them can see. -
    Nothing is shared without your permission. -
    You can: + typically issue and verify some kind of digital
    -
      -
    • Direct message your Contacts
    • -
    • Get offered new credentials
    • -
    • - Get notified of updates to your credentials
      - issued by them -
    • -
    • - Request for information from your Contact
      - or they request information from you -
    • -
    - You can always remove Contacts at any
    - time from your Contacts list. + credentials, fostering trust within the digital +
    + ecosystem. +
    + Each organization is uniquely identified by a DID +
    + (Decentralized Identifier), which is verifiable +
    + publicly, thus enhancing the level of trust. +
    + ); + }; + const ToolTipDataForEcosystem = () => { + return ( +
    +

    What is Ecosystem?

    + Ecosystem is a trusted network of organizations +
    + that empowers people and businesses with safe +
    + and secure ways of identifying themselves online +
    + and communicating confidentially with others. +
    + Examples are supply chain, marketplace, healthcare, +
    + banking, etc. where participants exchange +
    + information in an interoperable & trusted manner. +
    + ); + }; + + const ToolTipDataForSchema = () => { + return ( +
    +

    What is Schema?

    + Schema is a machine-readable semantic +
    structure, a predefined data template +
    that provides a standard format for the +
    digital credential contents. Schemas +
    define attributes that are used in one +
    or more Credential Definitions. +
    Schemas are stored on the ledger. +
    + ); + }; + + const ToolTipDataForCredDef = () => { + return ( +
    +

    What is Credential Definition?

    + A Credential Definition is a machine-readable +
    + definition of any Schema or in simple terms, +
    a tag created specific to an issuer and Schema. +
    + Credentials are always issued by an issuer +
    + using Cred-Def created by them. +
    + Credential Definitions are stored on the ledger.
    ); }; @@ -462,8 +520,8 @@ const UserDashBoard = () => { <> ) : (
    {walletLoading ? ( <> @@ -473,10 +531,10 @@ const UserDashBoard = () => {

    - Wallet lets you create schemas and credential-definitions + Wallet lets you create schemas and credential definitions

    - Please create wallet for your organisation which would + Please create wallet for your organization which would help you to issue and verify credentials for your users.
    @@ -523,12 +581,12 @@ const UserDashBoard = () => { >
    -
    -

    +
    +

    Organizations{' '}

    } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -538,7 +596,7 @@ const UserDashBoard = () => { height="20" fill="none" viewBox="0 0 20 20" - className="mt-[6px] ml-3 dark:text-white text-primary-700" + className="ml-3 dark:text-white text-primary-700" > {
    -
    - +
    + {orgCount ?? 0}
    @@ -559,7 +620,7 @@ const UserDashBoard = () => { {organizationsList && organizationsList?.length > 0 ? ( <> {' '} - {organizationsList?.map((org) => { + {organizationsList?.map((org, index) => { const roles: string[] = org.userOrgRoles.map( (role) => role.orgRole.name, ); @@ -570,7 +631,7 @@ const UserDashBoard = () => { key={org?.id} > @@ -617,12 +735,15 @@ const UserDashBoard = () => { xmlns="http://www.w3.org/2000/svg" width="24" height="24" - fill="none" viewBox="0 0 24 24" + fill="none" > @@ -715,27 +836,17 @@ const UserDashBoard = () => { xmlns="http://www.w3.org/2000/svg" width="24" height="24" - fill="none" viewBox="0 0 24 24" + fill="none" > + - - - - - - - - @@ -753,8 +864,8 @@ const UserDashBoard = () => { )}{' '} ) : ( -
    -

    You have no organisations created or joined

    +
    +

    You have no organizations created or joined

    )} @@ -771,18 +882,12 @@ const UserDashBoard = () => { >
    -
    -

    +
    +

    Schemas

    -

    What is schema?

    Schemas - define the attributes that -
    can be included in a credential. -
    - } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -792,7 +897,7 @@ const UserDashBoard = () => { height="20" fill="none" viewBox="0 0 20 20" - className="mt-[6px] ml-3 dark:text-white text-primary-700" + className="ml-3 dark:text-white text-primary-700" > {

    -
    - +
    + {schemaCount ?? 0}
    @@ -828,16 +936,16 @@ const UserDashBoard = () => { > {schema?.name} + + {schema?.version} + -
    - v.{schema?.version} -
    ); })} @@ -852,7 +960,7 @@ const UserDashBoard = () => {
    ) : (
    -

    You have no schemas created

    +

    You have no schemas created

    )} @@ -874,12 +982,12 @@ const UserDashBoard = () => { >
    -
    -

    +
    +

    Ecosystems{' '}

    } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -889,7 +997,7 @@ const UserDashBoard = () => { height="20" fill="none" viewBox="0 0 20 20" - className="mt-[6px] ml-3 dark:text-white text-primary-700" + className="ml-3 dark:text-white text-primary-700" > {
    -
    - +
    + {ecoCount ?? 0}
    @@ -917,7 +1028,12 @@ const UserDashBoard = () => { key={ecosystem?.id} > +
    + + {ecosystem?.ecosystemOrgs[0]?.ecosystemRole + ?.name === EcosystemRoles.ecosystemLead && ( + + )} + +
    ); })} @@ -960,7 +1145,7 @@ const UserDashBoard = () => { ) : (
    -

    You have no ecosystems created or joined

    +

    You have no ecosystems created or joined

    )} @@ -977,21 +1162,12 @@ const UserDashBoard = () => { >
    -
    -

    +
    +

    Cred - def

    -

    What is Cred-def?

    A - credential is a set of one or more
    - claims made by an issuer. A verifiable
    - credential is a tamper-evident
    credential that has - authorship -
    that can be cryptographically verified. -
    - } + content={} placement="bottom" className="items-center text-center dark:text-white" > @@ -1001,7 +1177,7 @@ const UserDashBoard = () => { height="20" fill="none" viewBox="0 0 20 20" - className="mt-[6px] ml-3 dark:text-white text-primary-700" + className="ml-3 dark:text-white text-primary-700" > {

    -
    - +
    + {credDefCount ?? 0}
    @@ -1035,25 +1214,23 @@ const UserDashBoard = () => { > - + {cred?.tag} + + {cred?.credentialDefinitionId} + -
    - - {cred?.credentialDefinitionId.slice(0, 8)}... - -
    ); })} ) : (
    -

    You have no cred-defs created

    +

    You have no cred-defs created

    )}{' '} diff --git a/src/components/Verification/ConnectionList.tsx b/src/components/Verification/ConnectionList.tsx index 66a32da9d..5a1b07913 100644 --- a/src/components/Verification/ConnectionList.tsx +++ b/src/components/Verification/ConnectionList.tsx @@ -6,22 +6,20 @@ import { IConnectionListAPIParameter, getConnectionsByOrg, } from '../../api/connection'; -import DataTable from '../../commonComponents/datatable'; import type { TableData } from '../../commonComponents/datatable/interface'; import { apiStatusCodes } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; -import SearchInput from '../SearchInput'; -import { Pagination } from 'flowbite-react'; import type { IConnectionList } from './interface'; +import SortDataTable from '../../commonComponents/datatable/SortDataTable'; const initialPageState = { itemPerPage: 10, page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; @@ -32,18 +30,31 @@ const ConnectionList = (props: { const [selectedConnectionList, setSelectedConnectionList] = useState< TableData[] >([]); - const [loading, setLoading] = useState(false); const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [totalItem, setTotalItem] = useState(0); const [error, setError] = useState(null); + const [pageInfo, setPageInfo] = useState({ + totalItem: '', + nextPage: '', + lastPage: '', + }); useEffect(() => { - getConnectionsVerification(listAPIParameter); - }, [listAPIParameter]); + let getData: NodeJS.Timeout; - //onChange of Search input text + if (listAPIParameter?.search?.length >= 1) { + getData = setTimeout(() => { + getConnectionsVerification(listAPIParameter); + }, 1000); + return () => clearTimeout(getData); + } else { + getConnectionsVerification(listAPIParameter); + } + return () => clearTimeout(getData); + }, [listAPIParameter]); + const searchInputChange = (e: ChangeEvent) => { setListAPIParameter({ ...listAPIParameter, @@ -61,6 +72,13 @@ const ConnectionList = (props: { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setTotalItem(data?.data.totalItems); + const { totalItems, nextPage, lastPage } = data.data; + + setPageInfo({ + totalItem: totalItems, + nextPage: nextPage, + lastPage: lastPage, + }); const connections = data?.data?.data?.map( (ele: IConnectionList) => { const userName = ele?.theirLabel @@ -162,6 +180,21 @@ const ConnectionList = (props: { } }; + const searchSortByValue = (value: any) => { + setListAPIParameter({ + ...listAPIParameter, + page: 1, + sortingOrder: value, + }); + }; + + + const refreshPage = () => { + setSelectedConnectionList([]); + getConnectionsVerification(listAPIParameter); + }; + + useEffect(() => { props.selectConnection(selectedConnectionList); }, [selectedConnectionList]); @@ -178,9 +211,6 @@ const ConnectionList = (props: {

    Connection List

    -
    - -
    -
    - -
    - {Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && ( -
    - { - setListAPIParameter((prevState) => ({ - ...prevState, - page, - })); - }} - totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} - /> -
    - )} + { + setListAPIParameter((prevState) => ({ + ...prevState, + page, + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + pageInfo={pageInfo} + searchSortByValue={searchSortByValue} + isHeader={true} + isSearch={true} + isRefresh={true} + isSort={true} + isPagination={true} + message={'No Connections'} + discription={"You don't have any connections yet"} + >
    ); }; diff --git a/src/components/Verification/ProofRequestPopup.tsx b/src/components/Verification/ProofRequestPopup.tsx index 170225a95..83d0af8c9 100644 --- a/src/components/Verification/ProofRequestPopup.tsx +++ b/src/components/Verification/ProofRequestPopup.tsx @@ -14,6 +14,7 @@ const ProofRequest = (props: IProofRrquestDetails) => { const [navigation, setNavigation] = useState(false); const [succesMsg, setSuccesMsg] = useState(''); const [error, setError] = useState(''); + const handleConfirmClick = async (id: string) => { try { setButtonLoader(true); @@ -85,7 +86,7 @@ const ProofRequest = (props: IProofRrquestDetails) => { {' '} Verification Details

    - {!props.userData ? ( + {props.verifyLoading ? (
    @@ -189,7 +190,7 @@ const ProofRequest = (props: IProofRrquestDetails) => {

    Verified Details

    - {!props.userData ? ( + {props.verifyLoading ? (
    @@ -206,16 +207,17 @@ const ProofRequest = (props: IProofRrquestDetails) => { )}
    - +
    diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 2c0274ac8..f381715f8 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -34,7 +34,7 @@ const initialPageState = { page: 1, search: '', sortBy: 'createDateTime', - sortingOrder: 'DESC', + sortingOrder: 'desc', allSearch: '', }; @@ -45,13 +45,13 @@ const VerificationCredentialList = () => { const [requestId, setRequestId] = useState(''); const [errMsg, setErrMsg] = useState(null); const [proofReqSuccess, setProofReqSuccess] = useState(''); - const [verifyLoader, setVerifyloader] = useState(false); const [userData, setUserData] = useState(null); const [view, setView] = useState(false); const [walletCreated, setWalletCreated] = useState(false); const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [totalItem, setTotalItem] = useState(0); + const [verifyLoading, setVerifyLoading]= useState(true) const [pageInfo, setPageInfo] = useState({ totalItem: '', nextPage: '', @@ -60,14 +60,17 @@ const VerificationCredentialList = () => { const getProofPresentationData = async (proofId: string) => { try { + setVerifyLoading(true) const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const response = await getVerifiedProofDetails(proofId, orgId); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes?.API_STATUS_SUCCESS) { setUserData(data?.data); + setVerifyLoading(false) } else { setErrMsg(response as string); + setVerifyLoading(false) } } catch (error) { throw error; @@ -102,8 +105,6 @@ const VerificationCredentialList = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const { totalItems, nextPage, lastPage } = data.data; - console.log('data.data', data.data); - setPageInfo({ totalItem: totalItems, nextPage: nextPage, @@ -261,14 +262,14 @@ const VerificationCredentialList = () => { if (data?.statusCode === apiStatusCodes?.API_STATUS_CREATED) { setOpenModal(false); setProofReqSuccess(data.message); - setVerifyloader(false); + setVerifyLoading(false); setTimeout(() => { getproofRequestList(listAPIParameter); }, 2000); } else { setOpenModal(false); setErrMsg(response as string); - setVerifyloader(false); + setVerifyLoading(false); } setTimeout(() => { setProofReqSuccess(''); @@ -276,7 +277,7 @@ const VerificationCredentialList = () => { }, 4000); } catch (error) { setOpenModal(false); - setVerifyloader(false); + setVerifyLoading(false); console.error('An error occurred:', error); setErrMsg('An error occurred while processing the presentation.'); } @@ -435,11 +436,12 @@ const VerificationCredentialList = () => { {userData && ( openProofRequestModel(false, '', '')} + closeModal={() => {openProofRequestModel(false, '', '')}} onSucess={requestProof} requestId={requestId} userData={userData} view={view} + verifyLoading={verifyLoading} /> )}

    diff --git a/src/components/Verification/interface.ts b/src/components/Verification/interface.ts index a49940da6..7bb0d1ea1 100644 --- a/src/components/Verification/interface.ts +++ b/src/components/Verification/interface.ts @@ -38,6 +38,7 @@ export interface SchemaDetails { } export interface IProofRrquestDetails { + verifyLoading: boolean; openModal: boolean; closeModal: (flag: boolean, id: string, state: boolean) => void; onSucess: (verifyPresentationId: string) => void; diff --git a/src/components/organization/Dashboard.tsx b/src/components/organization/Dashboard.tsx index fad946d4d..37e3c3a81 100644 --- a/src/components/organization/Dashboard.tsx +++ b/src/components/organization/Dashboard.tsx @@ -2,7 +2,6 @@ import type { OrgDashboard, Organisation } from './interfaces'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { getOrgDashboard, getOrganizationById } from '../../api/organization'; import { useEffect, useState } from 'react'; - import { Alert } from 'flowbite-react'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; @@ -18,28 +17,22 @@ import WalletSpinup from './WalletSpinup'; import { getFromLocalStorage } from '../../api/Auth'; import { pathRoutes } from '../../config/pathRoutes'; import DashboardCard from '../../commonComponents/DashboardCard'; +import { AlertComponent } from '../AlertComponent'; +import React from 'react'; const Dashboard = () => { const [orgData, setOrgData] = useState(null); - const [walletStatus, setWalletStatus] = useState(false); - const [orgDashboard, setOrgDashboard] = useState(null); const [success, setSuccess] = useState(null); const [failure, setFailure] = useState(null); - const [loading, setLoading] = useState(true); const [userRoles, setUserRoles] = useState([]); - + const [orgSuccess, setOrgSuccess] = useState(null); const [openModal, setOpenModal] = useState(false); - const props = { openModal, setOpenModal }; const EditOrgDetails = () => { - props.setOpenModal(true); - }; - - const updateOrganizationData = (updatedData: Organisation) => { - setOrgData(updatedData); + setOpenModal(true); }; const getUserRoles = async () => { @@ -54,11 +47,8 @@ const Dashboard = () => { const fetchOrganizationDetails = async () => { setLoading(true); - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const response = await getOrganizationById(orgId as string); - const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { @@ -74,11 +64,8 @@ const Dashboard = () => { const fetchOrganizationDashboard = async () => { setLoading(true); - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const response = await getOrgDashboard(orgId as string); - const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { @@ -94,6 +81,11 @@ const Dashboard = () => { fetchOrganizationDashboard(); }, []); + const handleEditModalClose = () => { + setOpenModal(false); + fetchOrganizationDetails(); + }; + useEffect(() => { setTimeout(() => { setSuccess(null); @@ -101,10 +93,6 @@ const Dashboard = () => { }, 3000); }, [success !== null, failure !== null]); - const redirectDashboardInvitations = () => { - window.location.href = '/organizations/invitations'; - }; - const setWalletSpinupStatus = (status: boolean) => { setSuccess('Wallet created successfully'); fetchOrganizationDetails(); @@ -119,6 +107,19 @@ const Dashboard = () => {
    +
    + {orgSuccess && ( +
    + { + setOrgSuccess(null); + }} + /> +
    + )} +
    @@ -180,13 +181,13 @@ const Dashboard = () => {
    { - throw new Error('Function not implemented.'); + setOrgSuccess(message); }} + orgData={orgData} />
    diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index b7d528f99..24aba5a4b 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -2,36 +2,16 @@ import * as yup from 'yup'; import { Avatar, Button, Label, Modal } from 'flowbite-react'; import { Field, Form, Formik, FormikHelpers } from 'formik'; import { - IMG_MAX_HEIGHT, - IMG_MAX_WIDTH, apiStatusCodes, - imageSizeAccepted, } from '../../config/CommonConstant'; -import { calculateSize, dataURItoBlob } from '../../utils/CompressImage'; import React, { useEffect, useState } from 'react'; import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import { updateOrganization } from '../../api/organization'; -import type { Organisation } from './interfaces'; +import type { EditOrgdetailsModalProps, ILogoImage, Organisation, Values } from './interfaces'; import defaultUserIcon from '../../../public/images/person_FILL1_wght400_GRAD0_opsz24.svg'; - -interface Values { - website: any; - name: string; - description: string; -} -interface ILogoImage { - logoFile: string | File; - imagePreviewUrl: string | ArrayBuffer | null | File; - fileName: string; -} -interface EditOrgdetailsModalProps { - openModal: boolean; - setMessage: (message: string) => void; - setOpenModal: (flag: boolean) => void; - onEditSucess?: () => void; - orgData: Organisation | null; -} +import { processImage } from '../../utils/processImage'; +import FormikErrorMessage from '../../commonComponents/formikerror/index' const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { const [logoImage, setLogoImage] = useState({ @@ -48,7 +28,7 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { }); useEffect(() => { - if (props.orgData) { + if (props.openModal && props.orgData) { setInitialOrgData({ name: props.orgData.name ?? '', description: props.orgData.description ?? '', @@ -63,14 +43,14 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { setIsPublic(props?.orgData?.publicProfile); } - }, [props]); + }, [props.orgData, props.openModal]); const [erroMsg, setErrMsg] = useState(null); const [imgError, setImgError] = useState(''); useEffect(() => { - if (props.openModal === false) { + if (!props.openModal) { setInitialOrgData({ name: '', description: '', @@ -85,86 +65,20 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { } }, [props.openModal]); - const ProcessImg = (e: any): string | undefined => { - const file = e?.target.files[0]; - if (!file) { - return; - } - - const reader = new FileReader(); - reader.readAsDataURL(file); - - reader.onload = (event): void => { - const imgElement = document.createElement('img'); - if (imgElement) { - imgElement.src = - typeof event?.target?.result === 'string' ? event.target.result : ''; - imgElement.onload = (e): void => { - let fileUpdated: File | string = file; - let srcEncoded = ''; - const canvas = document.createElement('canvas'); - - const { width, height, ev } = calculateSize( - imgElement, - IMG_MAX_WIDTH, - IMG_MAX_HEIGHT, - ); - canvas.width = width; - canvas.height = height; - - const ctx = canvas.getContext('2d'); - if (ctx && e?.target) { - ctx.imageSmoothingEnabled = true; - ctx.imageSmoothingQuality = 'high'; - ctx.drawImage(ev, 0, 0, canvas.width, canvas.height); - srcEncoded = ctx.canvas.toDataURL(ev, file.type); - const blob = dataURItoBlob(srcEncoded, file.type); - fileUpdated = new File([blob], file.name, { - type: file.type, - lastModified: new Date().getTime(), - }); - setLogoImage({ - logoFile: fileUpdated, - imagePreviewUrl: srcEncoded, - fileName: file.name, - }); - } - }; - } - }; - }; - - const isEmpty = (object: any): boolean => { - for (const property in object) { - return false; - } - return true; - }; const handleImageChange = (event: any): void => { - setImgError(''); - const reader = new FileReader(); - const file = event?.target?.files; - - const fieSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); - const extension = file[0]?.name - ?.substring(file[0]?.name?.lastIndexOf('.') + 1) - ?.toLowerCase(); - if (extension === 'png' || extension === 'jpeg' || extension === 'jpg') { - if (fieSize <= imageSizeAccepted) { - reader.onloadend = (): void => { - ProcessImg(event); - isEmpty(reader.result); - }; - reader.readAsDataURL(file[0]); - event.preventDefault(); - } else { - setImgError('Please check image size'); - } - } else { - setImgError('Invalid image type'); - } - }; - + setImgError(''); + processImage(event, (result, error) => { + if (result) { + setLogoImage({ + logoFile: '', + imagePreviewUrl: result, + fileName: event.target.files[0].name, + }); + } else { + setImgError(error || 'An error occurred while processing the image.'); + } + }); + }; const submitUpdateOrganization = async (values: Values) => { setLoading(true); @@ -176,22 +90,26 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { website: values.website, isPublic: isPublic, }; - - const resUpdateOrg = await updateOrganization( - orgData, - orgData.orgId?.toString() as string, - ); - - const { data } = resUpdateOrg as AxiosResponse; - setLoading(false); - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - if (props?.onEditSucess) { - props?.onEditSucess(); + try { + const response = await updateOrganization( + orgData, + orgData.orgId?.toString() as string, + ); + const { data } = response as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + if (props?.onEditSucess) { + props?.onEditSucess(); + } + props.setOpenModal(false); + props.setMessage(data?.message); + setLoading(false); + } else { + setErrMsg(response as string); + setLoading(false); } - props.setOpenModal(false); - } else { - setErrMsg(resUpdateOrg as string); + } catch (error) { + console.error('An error occurred:', error); + setLoading(false); } }; @@ -204,6 +122,11 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { imagePreviewUrl: '', fileName: '', }); + setInitialOrgData({ + name: props?.orgData?.name ?? '', + description: props?.orgData?.description ?? '', + website: props?.orgData?.website ?? '', + }); props.setOpenModal(false); }} > @@ -239,18 +162,16 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { { resetForm }: FormikHelpers, ) => { submitUpdateOrganization(values); - window.location.reload(); }} > {(formikHandlers): JSX.Element => (
    - {typeof logoImage.logoFile === 'string' && - props?.orgData?.logoUrl ? ( + {logoImage?.imagePreviewUrl ? ( Jese picture ) : typeof logoImage.logoFile === 'string' ? ( @@ -321,13 +242,10 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { } }} /> - {formikHandlers?.errors && - formikHandlers?.errors?.name && - formikHandlers?.touched?.name && ( - - {formikHandlers?.errors?.name} - - )} +
    @@ -358,14 +276,10 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { } }} /> - {formikHandlers?.errors && - formikHandlers?.errors?.description && - formikHandlers?.touched && - formikHandlers?.touched?.description && ( - - {formikHandlers?.errors?.description} - - )} +
    diff --git a/src/components/organization/interfaces/index.ts b/src/components/organization/interfaces/index.ts index c84cfb931..ffb359f83 100644 --- a/src/components/organization/interfaces/index.ts +++ b/src/components/organization/interfaces/index.ts @@ -167,4 +167,20 @@ export interface IOrgData { export interface IExploreOrg { orgData: IOrgData } - +export interface Values { + website: any; + name: string; + description: string; +} +export interface ILogoImage { + logoFile: string | File; + imagePreviewUrl: string | ArrayBuffer | null | File; + fileName: string; +} +export interface EditOrgdetailsModalProps { + openModal: boolean; + setMessage: (message: string) => void; + setOpenModal: (flag: boolean) => void; + onEditSucess?: () => void; + orgData: Organisation | null; +} diff --git a/src/utils/processImage.ts b/src/utils/processImage.ts new file mode 100644 index 000000000..3939e193a --- /dev/null +++ b/src/utils/processImage.ts @@ -0,0 +1,29 @@ +import type { ChangeEvent } from 'react'; +import { + imageSizeAccepted, +} from '../config/CommonConstant'; + +export const processImage = (event: ChangeEvent, callback:any) => { + const reader = new FileReader(); + const file = event?.target?.files; +if(file){ + const fileSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); + const extension = file[0]?.name + ?.substring(file[0]?.name?.lastIndexOf('.') + 1) + ?.toLowerCase(); + + if ( + (extension === 'png' || extension === 'jpeg' || extension === 'jpg') && + fileSize <= imageSizeAccepted + ) { + reader.onloadend = () => { + callback(reader.result); + }; + reader.readAsDataURL(file[0]); + event.preventDefault(); + } else { + callback(null, extension === 'png' || extension === 'jpeg' || extension === 'jpg' ? 'Please check image size' : 'Invalid image type'); + } +} + +}; diff --git a/tailwind.config.cjs b/tailwind.config.cjs index 4e98f1352..c046b2fd5 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -106,6 +106,8 @@ module.exports = { '100/22rem': 'calc(100% - 26rem)', '100/6rem': 'calc(100% - 6rem)', '100/12rem': 'calc(100% - 12rem)', + '100/11rem': 'calc(100% - 11rem)', + '100/3rem': 'calc(100% - 3rem)', }, height: { '100/15rem': 'calc(100vh - 15rem)' From a74e3745ca2ca6af1806fd9f36c0e153dd9c1cbe Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Tue, 30 Jan 2024 15:47:51 +0530 Subject: [PATCH 084/303] refactor: unused consoles Signed-off-by: sanjay-k1910 --- src/components/Authentication/SignInUser.tsx | 4 ---- src/components/Ecosystem/EcosystemList.tsx | 1 - src/components/organization/WalletSpinup.tsx | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/Authentication/SignInUser.tsx b/src/components/Authentication/SignInUser.tsx index 3a11b24c8..bc47bd924 100644 --- a/src/components/Authentication/SignInUser.tsx +++ b/src/components/Authentication/SignInUser.tsx @@ -94,11 +94,7 @@ const SignInUser = () => { await removeFromLocalStorage(storageKeys.ECOSYSTEM_ROLE) await removeFromLocalStorage(storageKeys.USER_PROFILE) setCurrentComponent('password'); - const fg = await getFromLocalStorage(storageKeys.LOGIN_USER_EMAIL) - console.log(3455, values, fg) await setToLocalStorage(storageKeys.LOGIN_USER_EMAIL, values.email); - const fg1 = await getFromLocalStorage(storageKeys.LOGIN_USER_EMAIL) - console.log(34551, values, fg1) setIsPasskeySuccess(true); }; diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index 97eb503ee..2a06b65a4 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -132,7 +132,6 @@ const EcosystemList = () => { window.location.href = pathRoutes.ecosystem.dashboard; }; - console.log(35345, selectedOrgId); const emptyListMessage = (isWalletSpinUp: boolean, selectedOrgId: boolean, ecosystemList: boolean) => { try { switch (true) { diff --git a/src/components/organization/WalletSpinup.tsx b/src/components/organization/WalletSpinup.tsx index ac1e275ac..ed21517e6 100644 --- a/src/components/organization/WalletSpinup.tsx +++ b/src/components/organization/WalletSpinup.tsx @@ -71,7 +71,7 @@ const fetchNetworks = async () => { } return [] } catch (err) { - console.log(7578, err) + console.log("Fetch Network ERROR::::", err) } } From c636928cc56ebb775c6a11799fc90a0abe48dc75 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 30 Jan 2024 16:03:03 +0530 Subject: [PATCH 085/303] implemented delete api Signed-off-by: karan --- src/components/Setting/index.tsx | 274 +++++++++++------------------- src/components/Setting/setting.ts | 54 ++++++ src/config/CommonConstant.ts | 1 + src/utils/check-session.ts | 60 +++---- 4 files changed, 187 insertions(+), 202 deletions(-) create mode 100644 src/components/Setting/setting.ts diff --git a/src/components/Setting/index.tsx b/src/components/Setting/index.tsx index fa8be154b..a1d58949f 100644 --- a/src/components/Setting/index.tsx +++ b/src/components/Setting/index.tsx @@ -1,79 +1,37 @@ -import { Alert, Button } from 'flowbite-react'; +import { Button } from 'flowbite-react'; import React, { useEffect, useState } from 'react'; import CustomSpinner from '../CustomSpinner'; import { getFromLocalStorage } from '../../api/Auth'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; -import { apiRoutes } from '../../config/apiRoutes'; -import { getHeaderConfigs } from '../../config/GetHeaderConfigs'; -import { axiosGet, axiosPost } from '../../services/apiRequests'; import type { AxiosResponse } from 'axios'; import CopyDid from '../../commonComponents/CopyDid'; import { AlertComponent } from '../AlertComponent'; import { Roles } from '../../utils/enums/roles'; import BreadCrumbs from '../BreadCrumbs'; +import { + createCredentials, + deleteCredentials, + getCredentials, +} from './setting'; const index = () => { const [loading, setLoading] = useState(false); - const [clentId, setClientId] = useState(''); - const [clientSecret, setClientSecret] = useState(''); + const [clentId, setClientId] = useState(null); + const [clientSecret, setClientSecret] = useState(null); const [success, setSuccess] = useState(null); const [failure, setFailure] = useState(null); const [warning, setWarning] = useState(null); const [hideCopy, setHideCopy] = useState(true); const [userRoles, setUserRoles] = useState([]); - const getCredentials = async () => { - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.setting.setting}`; - - const axiosPayload = { - url, - config: await getHeaderConfigs(), - }; - - try { - return await axiosGet(axiosPayload); - } catch (error) { - const err = error as Error; - return err?.message; - } - }; - - const createCredentials = async () => { - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.setting.setting}`; - - const axiosPayload = { - url, - config: await getHeaderConfigs(), - }; - try { - return await axiosPost(axiosPayload); - } catch (error) { - const err = error as Error; - return err?.message; - } - }; - const createClientCredentials = async () => { - console.log('--------', 'create'); - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - if (orgId) { setLoading(true); try { - // const response = await createCredentials(); - // const { data } = response as AxiosResponse; + const response = await createCredentials(); + const { data } = response as AxiosResponse; - const data = { - statusCode: 201, - message: 'Organization credentials created successfully', - data: { - clientId: '5d1533ac-0432-4da4-bd15-e86dc5465c0a', - clientSecret: 'T7QSRemu1MtcN1rjyVZ3uNA9FzVkp2U9', - }, - }; if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { setHideCopy(false); @@ -96,24 +54,19 @@ const index = () => { const getClientCredentials = async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - if (orgId) { setLoading(true); try { - // const response = await getCredentials(); - // const { data } = response as AxiosResponse; - const data = { - statusCode: 200, - message: 'Organization credentials fetched successfully', - data: { - clientId: '5d1533ac-0432-4da4-bd15-e86dc5465c0a', - clientSecret: '************************FzVkp2U9', - }, - }; + const response = await getCredentials(); + const { data } = response as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setHideCopy(true); setClientId(data.data.clientId); setClientSecret(data.data.clientSecret); + }else{ + setClientId(null); + setClientSecret(null); } } catch (error) { setFailure(error as string); @@ -126,8 +79,30 @@ const index = () => { } }; - const deleteKey = () => { - setClientSecret(null); + const deleteClientCredentials = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + + if (orgId) { + setLoading(true); + try { + const response = await deleteCredentials(); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_DELETED) { + setSuccess(data?.message); + await getClientCredentials(); + } + } catch (error) { + setFailure(error as string); + setLoading(false); + setClientId(null); + setClientSecret(null); + } finally { + setLoading(false); + } + } else { + setLoading(false); + } }; const getUserRoles = async () => { @@ -194,14 +169,6 @@ const index = () => { {(userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) && (
    - {/*
    )}
    -
    -
    - {warning && ( - { - setWarning(null); - setFailure(null); - }} - /> - )} -
    - {/* - {clentId && ( -
    -
    -
    SVG
    -
    -

    - {!hideCopy ? ( - clientSecret && ( - - ) - ) : ( -
    - {clientSecret} -
    - )} -

    -
    -
    - {(userRoles.includes(Roles.OWNER) || - userRoles.includes(Roles.ADMIN)) && ( -
    - -
    - )} -
    - )} */} {clentId && ( -
    -
    -
    - - - -
    -
    -

    - {!hideCopy ? ( - clientSecret && ( - // font-courier font-semibold - - ) - ) : ( - - {clientSecret} - - )} -

    -
    + <> +
    +
    + {warning && ( + { + setWarning(null); + setFailure(null); + }} + /> + )}
    - {(userRoles.includes(Roles.OWNER) || - userRoles.includes(Roles.ADMIN)) && ( -
    - +
    +
    +
    + + + +
    +
    +

    + {!hideCopy ? ( + clientSecret && ( + // font-courier font-semibold + + ) + ) : ( + + {clientSecret} + + )} +

    +
    - )} -
    + {(userRoles.includes(Roles.OWNER) || + userRoles.includes(Roles.ADMIN)) && ( +
    + +
    + )} +
    + )}
    diff --git a/src/components/Setting/setting.ts b/src/components/Setting/setting.ts new file mode 100644 index 000000000..001f617ba --- /dev/null +++ b/src/components/Setting/setting.ts @@ -0,0 +1,54 @@ +import { getFromLocalStorage } from "../../api/Auth"; +import { storageKeys } from "../../config/CommonConstant"; +import { getHeaderConfigs } from "../../config/GetHeaderConfigs"; +import { apiRoutes } from "../../config/apiRoutes"; +import { axiosDelete, axiosGet, axiosPost } from "../../services/apiRequests"; + +export const getCredentials = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.setting.setting}`; + + const axiosPayload = { + url, + config: await getHeaderConfigs(), + }; + + try { + return await axiosGet(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } +}; + +export const createCredentials = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.setting.setting}`; + + const axiosPayload = { + url, + config: await getHeaderConfigs(), + }; + try { + return await axiosPost(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } +}; + +export const deleteCredentials = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.setting.setting}`; + + const axiosPayload = { + url, + config: await getHeaderConfigs(), + }; + try { + return await axiosDelete(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } +}; diff --git a/src/config/CommonConstant.ts b/src/config/CommonConstant.ts index e56e3b300..c39515952 100644 --- a/src/config/CommonConstant.ts +++ b/src/config/CommonConstant.ts @@ -10,6 +10,7 @@ export const schemaVersionRegex = /^\d{1,5}(?=.*[0-9])(?:\.\d{1,5})?(?:\.\d{1,5} export const apiStatusCodes = { API_STATUS_SUCCESS : 200, API_STATUS_CREATED : 201, + API_STATUS_DELETED : 202, API_STATUS_BAD_REQUEST : 400, API_STATUS_UNAUTHORIZED : 401, API_STATUS_NOT_FOUND : 404 diff --git a/src/utils/check-session.ts b/src/utils/check-session.ts index 84af87912..c35284ad2 100755 --- a/src/utils/check-session.ts +++ b/src/utils/check-session.ts @@ -29,39 +29,39 @@ export const checkUserSession = async ({ }; } - const { - data: { user }, - error, - } = await getSupabaseClient().auth.getUser(sessionCookie); + // const { + // data: { user }, + // error, + // } = await getSupabaseClient().auth.getUser(sessionCookie); - if (!user || user.role !== 'authenticated') { - return { - permitted: false, - redirect: pathRoutes.auth.sinIn, - authorized: false, - }; - } + // if (!user || user.role !== 'authenticated') { + // return { + // permitted: false, + // redirect: pathRoutes.auth.sinIn, + // authorized: false, + // }; + // } - const role = getFromCookies(cookies, 'role'); - const permittedPages = RolePermissions.find( - (item) => item.role === role, - )?.pages; + // const role = getFromCookies(cookies, 'role'); + // const permittedPages = RolePermissions.find( + // (item) => item.role === role, + // )?.pages; - if (!permittedPages?.includes(currentPath)) { - if (permittedPages) { - return { - permitted: false, - redirect: permittedPages[0], - authorized: true, - }; - } else { - return { - permitted: true, - redirect: pathRoutes.users.dashboard, - authorized: true, - }; - } - } + // if (!permittedPages?.includes(currentPath)) { + // if (permittedPages) { + // return { + // permitted: false, + // redirect: permittedPages[0], + // authorized: true, + // }; + // } else { + // return { + // permitted: true, + // redirect: pathRoutes.users.dashboard, + // authorized: true, + // }; + // } + // } return { permitted: true, From 51f0e266dfd8ca94f713efae401d09d1df9cbcfc Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 30 Jan 2024 18:03:03 +0530 Subject: [PATCH 086/303] fix: responsiveness issue on ecosystem received invitation page Signed-off-by: karan --- .../EcosystemInvite/EcoInvitationList.tsx | 2 +- .../EcoSystemReceivedInvitations.tsx | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/components/EcosystemInvite/EcoInvitationList.tsx b/src/components/EcosystemInvite/EcoInvitationList.tsx index 384f7773a..c184ea70f 100644 --- a/src/components/EcosystemInvite/EcoInvitationList.tsx +++ b/src/components/EcosystemInvite/EcoInvitationList.tsx @@ -23,7 +23,7 @@ const EcoInvitationList = (props: InvitationProps) => {
      -
    • +
    • Role:{' '} diff --git a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx index 6c63f8721..a979bd99c 100644 --- a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx +++ b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx @@ -15,8 +15,8 @@ import CustomSpinner from '../CustomSpinner'; import { getFromLocalStorage } from '../../api/Auth'; import { getOrganizationById, getOrganizations } from '../../api/organization'; import EcoInvitationList from './EcoInvitationList'; -import { getOrgDetails } from '../../config/ecosystem'; import BackButton from '../../commonComponents/backbutton'; +import React from 'react'; const initialPageState = { pageNumber: 1, @@ -322,18 +322,17 @@ const ReceivedInvitations = () => {
      -
      +
      -
      +
      handleDropdownChange(e, invitation.id) @@ -407,7 +393,7 @@ const ReceivedInvitations = () => { /> )} - ) + ); })}
    diff --git a/src/components/Issuance/BulkIssuance.tsx b/src/components/Issuance/BulkIssuance.tsx index 5ece10f30..440fbe9d7 100644 --- a/src/components/Issuance/BulkIssuance.tsx +++ b/src/components/Issuance/BulkIssuance.tsx @@ -18,6 +18,9 @@ import BreadCrumbs from '../BreadCrumbs'; import BackButton from '../../commonComponents/backbutton' import type { ICredentials, IValues, IAttributes, IUploadMessage } from './interface'; +export interface SelectRef { + clearValue(): void; +} const BulkIssuance = () => { const [csvData, setCsvData] = useState([]); const [requestId, setRequestId] = useState(""); @@ -341,11 +344,18 @@ const BulkIssuance = () => { const handleCloseConfirmation = () => { setOpenModal(false); }; + const selectInputRef = React.useRef(null); + const onClear = () => { + if (selectInputRef.current) { + selectInputRef.current.clearValue(); + } }; + const handleReset = () => { handleDiscardFile(); setCredentialSelected(""); setSuccess(null); + onClear() }; const handleResetForConfirm = () => { handleDiscardFile(); @@ -465,6 +475,7 @@ const BulkIssuance = () => { onChange={(value: IValues | null) => { setCredentialSelected(value?.value ?? ""); }} + ref={selectInputRef} />
    diff --git a/src/components/Issuance/EmailIssuance.tsx b/src/components/Issuance/EmailIssuance.tsx index daca68805..29be8ce7f 100644 --- a/src/components/Issuance/EmailIssuance.tsx +++ b/src/components/Issuance/EmailIssuance.tsx @@ -17,6 +17,7 @@ import CustomSpinner from '../CustomSpinner'; import { issueOobEmailCredential } from '../../api/issuance'; import { EmptyListMessage } from '../EmptyListComponent'; import ResetPopup from './ResetPopup'; +import type { SelectRef } from './BulkIssuance'; const EmailIssuance = () => { const [formData, setFormData] = useState(); @@ -171,11 +172,16 @@ const EmailIssuance = () => { const handleBlur = () => { setIsEditing(false); }; + const selectInputRef = React.useRef(null); const handleReset = () => { setCredentialSelected(null); setBatchName(''); setOpenResetModal(false); + if(selectInputRef.current){ + + selectInputRef.current.clearValue(); + } }; const handleCloseConfirmation = () => { @@ -192,6 +198,17 @@ const EmailIssuance = () => { const handleResetOpenConfirmation = () => { setOpenResetModal(true); }; + + // const selectInputRef = React.useRef(null); + + // const onClear = () => { + + // // if (selectInputRef.current) { + // console.log("kkkkkkkkkkkkkk"); + // selectInputRef.current.clearValue(); + // // } + // }; + const MailError = ({ handler, @@ -258,7 +275,7 @@ const EmailIssuance = () => {
    -
    +

    Select Schema and credential definition

    @@ -280,6 +297,7 @@ const EmailIssuance = () => { setCredentialSelected(value?.value ?? ''); setAttributes(value?.schemaAttributes); }} + ref={selectInputRef} />
    From 79af76660979fa45d3568c83b26e4c91bcb734b9 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 31 Jan 2024 12:32:28 +0530 Subject: [PATCH 088/303] fix: clear lable Signed-off-by: karan --- src/components/Issuance/BulkIssuance.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Issuance/BulkIssuance.tsx b/src/components/Issuance/BulkIssuance.tsx index 0e3bfaf1b..5ab024c4b 100644 --- a/src/components/Issuance/BulkIssuance.tsx +++ b/src/components/Issuance/BulkIssuance.tsx @@ -387,6 +387,7 @@ const BulkIssuance = () => { setSuccess(data.message); setUploadMessage(null) handleResetForConfirm() + onClear() } else { setFailure(response as string); setTimeout(()=>{ From 074d66148e6d068d3cecb34f19d0a9628192d136 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 31 Jan 2024 12:38:44 +0530 Subject: [PATCH 089/303] fix: unwanted code removed Signed-off-by: karan --- src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx index c183d7a09..febf1665b 100644 --- a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx +++ b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx @@ -329,7 +329,7 @@ const ReceivedInvitations = () => { disabled={!invitation?.orgData} id={invitation.id} color="bg-white" - className='shrink-0 text-base font-medium text-center text-gray-00 bg-secondary-700 hover:!bg-secondary-800 rounded-lg focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:focus:ring-primary-800 dark:bg-gray-800"' + className='shrink-0 text-base font-medium text-center text-gray-00 bg-secondary-700 hover:!bg-secondary-800 rounded-lg focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:focus:ring-primary-800 dark:bg-gray-800"' style={{ height: '2.5rem', minWidth: '2rem', From e6729427778781c74674f9308cf7a2597073c351 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 31 Jan 2024 16:54:35 +0530 Subject: [PATCH 090/303] fix: multiple issues from automation board Signed-off-by: karan --- src/components/Profile/DisplayUserProfile.tsx | 181 +++++++++--------- src/components/Profile/interfaces/index.ts | 5 + .../organization/invitations/Invitations.tsx | 14 +- src/components/organization/users/Members.tsx | 4 - src/components/organization/users/index.tsx | 4 +- 5 files changed, 101 insertions(+), 107 deletions(-) diff --git a/src/components/Profile/DisplayUserProfile.tsx b/src/components/Profile/DisplayUserProfile.tsx index 195a56c0d..fbe7912ee 100644 --- a/src/components/Profile/DisplayUserProfile.tsx +++ b/src/components/Profile/DisplayUserProfile.tsx @@ -1,96 +1,97 @@ -import type { UserProfile } from "./interfaces"; -import CustomAvatar from '../Avatar' -import { Button } from "flowbite-react"; +import type { DisplayUserProfileProps } from './interfaces'; +import CustomAvatar from '../Avatar'; +import { Button } from 'flowbite-react'; -interface DisplayUserProfileProps { - toggleEditProfile: () => void; - userProfileInfo: UserProfile | null; -} -const DisplayUserProfile = ({ toggleEditProfile, userProfileInfo }: DisplayUserProfileProps) => { - return ( -
    -
    -
    -
    -
    +const DisplayUserProfile = ({ + toggleEditProfile, + userProfileInfo, +}: DisplayUserProfileProps) => { + return ( +
    +
    +
    +
    +
    +

    + General +

    + + Basic info, like your first name, last name and profile image + that will be displayed + +
    - -
    -
    + +
    -
    -

    General

    -

    Basic info, like your first name, last name and profile image that will be displayed

    -
    - - - -
    - -
    -
    First Name
    -
    - {userProfileInfo?.firstName ? ( - userProfileInfo.firstName - ) : ( - "N/A" - )} - -
    -
    -
    -
    Last Name
    -
    - {userProfileInfo?.lastName ? ( - userProfileInfo.lastName - ) : ( - "N/A" - )} - -
    -
    -
    -
    Profile Image
    -
    -
    - - {(userProfileInfo?.profileImg) ? - : - } -
    -
    -
    -
    - -
    -
    -
    -
    -
    - ); +
    +
    + First Name +
    +
    + {userProfileInfo?.firstName ? userProfileInfo.firstName : 'N/A'} +
    +
    +
    +
    + Last Name +
    +
    + {userProfileInfo?.lastName ? userProfileInfo.lastName : 'N/A'} +
    +
    +
    +
    + Profile Image +
    +
    +
    + {userProfileInfo?.profileImg ? ( + + ) : ( + + )} +
    +
    +
    +
    +
    +
    + ); }; export default DisplayUserProfile; - diff --git a/src/components/Profile/interfaces/index.ts b/src/components/Profile/interfaces/index.ts index 249fda505..a1ecd8586 100644 --- a/src/components/Profile/interfaces/index.ts +++ b/src/components/Profile/interfaces/index.ts @@ -50,3 +50,8 @@ export interface UserProfile { publicProfile?: boolean isPublic?:boolean } + +export interface DisplayUserProfileProps { + toggleEditProfile: () => void; + userProfileInfo: UserProfile | null; +} diff --git a/src/components/organization/invitations/Invitations.tsx b/src/components/organization/invitations/Invitations.tsx index 3bacde316..d532613a0 100644 --- a/src/components/organization/invitations/Invitations.tsx +++ b/src/components/organization/invitations/Invitations.tsx @@ -50,7 +50,6 @@ const Invitations = () => { const [invitationsList, setInvitationsList] = useState | null>(null) const props = { openModal, setOpenModal }; - //Fetch the user organization list const getAllInvitations = async () => { setLoading(true) @@ -68,14 +67,9 @@ const Invitations = () => { total: totalPages }) } - else { - setError(response as string) - - } } - //This useEffect is called when the searchText changes - useEffect(() => { + useEffect(() => { let getData: NodeJS.Timeout if (searchText.length >= 1) { @@ -90,8 +84,6 @@ const Invitations = () => { return () => clearTimeout(getData) }, [searchText, openModal, currentPage.pageNumber]) - - //onChange of Search input text const searchInputChange = (e: ChangeEvent) => { setSearchText(e.target.value); } @@ -276,9 +268,9 @@ const Invitations = () => {
    ) - : invitationsList && ( { ...currentPage, total: totalPages, }); - } else { - setError(response as string); } setLoading(false); }; - //This useEffect is called when the searchText changes useEffect(() => { let getData: NodeJS.Timeout; @@ -100,7 +97,6 @@ const Members = () => { getUserRoles(); }, []); - //onCHnage of Search input text const searchInputChange = (e: ChangeEvent) => { setSearchText(e.target.value); }; diff --git a/src/components/organization/users/index.tsx b/src/components/organization/users/index.tsx index 7e77dbe8c..b9d5b1f5d 100644 --- a/src/components/organization/users/index.tsx +++ b/src/components/organization/users/index.tsx @@ -35,10 +35,10 @@ const Users = () => {
    -
    +
    -
    +
    From d8cf00ffb8ad8b4035af4847e8c97ab38bd4cf86 Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 31 Jan 2024 17:34:24 +0530 Subject: [PATCH 091/303] fix: implemented loading Signed-off-by: karan --- .../organization/invitations/Invitations.tsx | 31 +++++++++++-------- src/components/organization/users/Members.tsx | 3 -- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/components/organization/invitations/Invitations.tsx b/src/components/organization/invitations/Invitations.tsx index d532613a0..363c2dd19 100644 --- a/src/components/organization/invitations/Invitations.tsx +++ b/src/components/organization/invitations/Invitations.tsx @@ -2,7 +2,6 @@ import React, { ChangeEvent, useEffect, useState } from 'react'; import { apiStatusCodes, storageKeys } from '../../../config/CommonConstant'; - import { AlertComponent } from '../../AlertComponent'; import type { AxiosResponse } from 'axios'; import { EmptyListMessage } from '../../EmptyListComponent'; @@ -52,21 +51,20 @@ const Invitations = () => { const getAllInvitations = async () => { setLoading(true) - const response = await getOrganizationInvitations(currentPage.pageNumber, currentPage.pageSize, searchText); const { data } = response as AxiosResponse - setLoading(false) - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const totalPages = data?.data?.totalPages; - const invitationList = data?.data?.invitations - setInvitationsList(invitationList) - setCurrentPage({ - ...currentPage, - total: totalPages - }) + const totalPages = data?.data?.totalPages; + const invitationList = data?.data?.invitations + setInvitationsList(invitationList) + setCurrentPage({ + ...currentPage, + total: totalPages + }) + setLoading(false) } + setLoading(false) } useEffect(() => { @@ -93,6 +91,7 @@ const Invitations = () => { } const deleteInvitations = async () => { + setDeleteLoading(true); const orgId = await getFromLocalStorage(storageKeys.ORG_ID) const invitationId = selectedInvitation const response = await deleteOrganizationInvitation(orgId, invitationId); @@ -105,6 +104,7 @@ const Invitations = () => { setShowPopup(false) } else { setError(response as string); + setDeleteLoading(false); } setDeleteLoading(false); }; @@ -144,7 +144,11 @@ const Invitations = () => { setError(null) }} /> - { + {loading ? ( +
    + +
    + ) : invitationsList && invitationsList?.length > 0 ? (
    @@ -268,7 +272,7 @@ const Invitations = () => {
    ) - : ( {
    } { const [error, setError] = useState(null); const [userRoles, setUserRoles] = useState([]); const [currentPage, setCurrentPage] = useState(initialPageState); - const timestamp = Date.now(); const onPageChange = (page: number) => { setCurrentPage({ @@ -42,7 +40,6 @@ const Members = () => { const [selectedUser, setSelectedUser] = useState(null); const props = { openModal, setOpenModal }; - //Fetch the user organization list const getAllUsers = async () => { setLoading(true); From 5520768cde0983446c93f8cae6601a808d2904ed Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Wed, 31 Jan 2024 21:42:16 +0530 Subject: [PATCH 092/303] refactor: submit endorsement endpoint Signed-off-by: sanjay-k1910 --- src/config/apiRoutes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/apiRoutes.ts b/src/config/apiRoutes.ts index 361dea32a..14b582410 100644 --- a/src/config/apiRoutes.ts +++ b/src/config/apiRoutes.ts @@ -90,7 +90,7 @@ export const apiRoutes = { createSchemaRequest: '/transaction/schema', createCredDefRequest: '/transaction/cred-def', signRequest: '/transaction/sign/', - submitRequest: '/transaction/sumbit/', + submitRequest: '/transaction/submit/', rejectRequest: '/transactions/', transactionApproval: '/transaction-approval/', }, From 6d1fd71c61ead26581be543697c9b0de2706b880 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 1 Feb 2024 11:56:26 +0530 Subject: [PATCH 093/303] fix: issues from automation board Signed-off-by: karan --- src/components/Issuance/Connections.tsx | 2 +- src/components/Verification/Connections.tsx | 2 +- .../Verification/ProofRequestPopup.tsx | 9 ++++++- .../VerificationCredentialList.tsx | 25 ++++++++++++++----- src/components/Verification/interface.ts | 1 + 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/components/Issuance/Connections.tsx b/src/components/Issuance/Connections.tsx index fffdc7e5f..319f549e4 100644 --- a/src/components/Issuance/Connections.tsx +++ b/src/components/Issuance/Connections.tsx @@ -80,7 +80,7 @@ const Connections = () => {
    {
    -
    +
    diff --git a/src/components/Verification/ProofRequestPopup.tsx b/src/components/Verification/ProofRequestPopup.tsx index 83d0af8c9..a7ca02018 100644 --- a/src/components/Verification/ProofRequestPopup.tsx +++ b/src/components/Verification/ProofRequestPopup.tsx @@ -8,6 +8,7 @@ import { pathRoutes } from '../../config/pathRoutes'; import AttributesListData from './AttributesListData'; import SchemaCredDefDetails from './SchemaCredDefDetails'; import type { IProofRrquestDetails } from './interface'; +import { Roles } from '../../utils/enums/roles'; const ProofRequest = (props: IProofRrquestDetails) => { const [buttonLoader, setButtonLoader] = useState(false); @@ -135,7 +136,13 @@ const ProofRequest = (props: IProofRrquestDetails) => {
    diff --git a/src/components/Verification/interface.ts b/src/components/Verification/interface.ts index 7bb0d1ea1..6f9305149 100644 --- a/src/components/Verification/interface.ts +++ b/src/components/Verification/interface.ts @@ -45,6 +45,7 @@ export interface IProofRrquestDetails { requestId: string; userData: object[]; view: boolean; + userRoles?: string[], } export interface IConnectionList { From 561e8a1e64afe96119dc27ee0e7a841481609e85 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 1 Feb 2024 12:04:08 +0530 Subject: [PATCH 094/303] fix: issues from automation board Signed-off-by: karan --- src/components/Profile/DisplayUserProfile.tsx | 8 ++++---- src/components/Verification/ProofRequestPopup.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Profile/DisplayUserProfile.tsx b/src/components/Profile/DisplayUserProfile.tsx index fbe7912ee..82b18d628 100644 --- a/src/components/Profile/DisplayUserProfile.tsx +++ b/src/components/Profile/DisplayUserProfile.tsx @@ -31,11 +31,11 @@ const DisplayUserProfile = ({ @@ -79,7 +79,7 @@ const DisplayUserProfile = ({ className="mb-4 border border-b rounded-full w-28 h-28 sm:mb-0 xl:mb-4 2xl:mb-0" size="90" src={ - userProfileInfo?.firstName || + userProfileInfo?.firstName ?? '../../public/images/profile.png' } name={userProfileInfo?.firstName} diff --git a/src/components/Verification/ProofRequestPopup.tsx b/src/components/Verification/ProofRequestPopup.tsx index a7ca02018..8fbdb3aef 100644 --- a/src/components/Verification/ProofRequestPopup.tsx +++ b/src/components/Verification/ProofRequestPopup.tsx @@ -139,7 +139,7 @@ const ProofRequest = (props: IProofRrquestDetails) => { disabled={ navigation || buttonLoader || - (props?.userRoles || []).every(role => + (props?.userRoles ?? []).every(role => [Roles.MEMBER, Roles.ISSUER].includes(role as Roles) ) } From a1f12d452ae8ce0cd268b196fb5e724eebe262a7 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 1 Feb 2024 16:13:07 +0530 Subject: [PATCH 095/303] fix: ecosystem drop down issue Signed-off-by: karan --- src/commonComponents/EcosystemProfileCard.tsx | 21 ++++++++++++------- .../Ecosystem/Endorsement/index.tsx | 3 +-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/commonComponents/EcosystemProfileCard.tsx b/src/commonComponents/EcosystemProfileCard.tsx index bda992736..5d5853a65 100644 --- a/src/commonComponents/EcosystemProfileCard.tsx +++ b/src/commonComponents/EcosystemProfileCard.tsx @@ -11,7 +11,11 @@ import CustomSpinner from '../components/CustomSpinner'; import { pathRoutes } from '../config/pathRoutes'; import { EmptyListMessage } from '../components/EmptyListComponent'; -const EcosystemProfileCard = () => { +interface endordememntInterface { + getEndorsementListData: () => void; +} + +const EcosystemProfileCard = ({getEndorsementListData}:endordememntInterface) => { const [ecosystemDetails, setEcosystemDetails] = useState(); const [ecosystemList, setEcosystemList] = useState(); const [loading, setLoading] = useState(); @@ -26,8 +30,9 @@ const EcosystemProfileCard = () => { const response = await getEcosystems(id); setLoading(false) const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setEcosystemList(data?.data) + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setEcosystemList(data?.data.ecosystemDetails + ) const ecosystemData = data?.data?.ecosystemDetails?.find((item: { id: string }) => item.id === ecosystemId); if (ecosystemData) { setEcosystemId(ecosystemData?.id) @@ -66,7 +71,10 @@ const EcosystemProfileCard = () => { const handleSelectEcosystem = async (e: { target: { value: string; }; }) => { await fetchEcosystemDetails(e.target.value) await setToLocalStorage(storageKeys.ECOSYSTEM_ID, e.target.value); - window.location.reload() + let kkkk= await getFromLocalStorage(storageKeys.ECOSYSTEM_ID) + console.log("kkkk",kkkk); + + await getEndorsementListData() } @@ -96,11 +104,10 @@ const EcosystemProfileCard = () => {

    Role: {' '} - +
    -
    { Boolean(ecosystemOptions && ecosystemOptions.length > 0) && @@ -110,7 +117,7 @@ const EcosystemProfileCard = () => { > { - ecosystemOptions && ecosystemOptions.length > 0 && ecosystemOptions.map(item => ( + ecosystemOptions && ecosystemOptions.map(item => ( )) } diff --git a/src/components/Ecosystem/Endorsement/index.tsx b/src/components/Ecosystem/Endorsement/index.tsx index 231e5e417..277443a23 100644 --- a/src/components/Ecosystem/Endorsement/index.tsx +++ b/src/components/Ecosystem/Endorsement/index.tsx @@ -10,7 +10,6 @@ import CustomSpinner from '../../CustomSpinner'; import { EmptyListMessage } from '../../EmptyListComponent'; import SearchInput from '../../SearchInput'; import { getFromLocalStorage } from '../../../api/Auth'; -import { pathRoutes } from '../../../config/pathRoutes'; import { getOrganizationById } from '../../../api/organization'; import { ICheckEcosystem, @@ -219,7 +218,7 @@ const EndorsementList = () => { { isEcosystemData?.isEnabledEcosystem &&
    - + getEndorsementListData(endorsementListAPIParameter)} />
    }

    From 6144c83dc81f6ed3bfb2ff83dd4069b233aa69e9 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 1 Feb 2024 16:19:04 +0530 Subject: [PATCH 096/303] fix: interfaces handled Signed-off-by: karan --- src/commonComponents/EcosystemProfileCard.tsx | 7 ++--- .../Ecosystem/Endorsement/index.tsx | 22 +-------------- src/components/Ecosystem/interfaces/index.ts | 27 +++++++++++++++++++ 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/commonComponents/EcosystemProfileCard.tsx b/src/commonComponents/EcosystemProfileCard.tsx index 5d5853a65..2346e471d 100644 --- a/src/commonComponents/EcosystemProfileCard.tsx +++ b/src/commonComponents/EcosystemProfileCard.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' import { Card } from 'flowbite-react'; -import type { IEcosystem } from '../components/Ecosystem/interfaces'; +import type { EndorsementInterface, IEcosystem } from '../components/Ecosystem/interfaces'; import { getFromLocalStorage, removeFromLocalStorage, setToLocalStorage } from '../api/Auth'; import { apiStatusCodes, storageKeys } from '../config/CommonConstant'; import type { AxiosResponse } from 'axios'; @@ -11,11 +11,8 @@ import CustomSpinner from '../components/CustomSpinner'; import { pathRoutes } from '../config/pathRoutes'; import { EmptyListMessage } from '../components/EmptyListComponent'; -interface endordememntInterface { - getEndorsementListData: () => void; -} -const EcosystemProfileCard = ({getEndorsementListData}:endordememntInterface) => { +const EcosystemProfileCard = ({getEndorsementListData}:EndorsementInterface) => { const [ecosystemDetails, setEcosystemDetails] = useState(); const [ecosystemList, setEcosystemList] = useState(); const [loading, setLoading] = useState(); diff --git a/src/components/Ecosystem/Endorsement/index.tsx b/src/components/Ecosystem/Endorsement/index.tsx index 277443a23..f48fc101a 100644 --- a/src/components/Ecosystem/Endorsement/index.tsx +++ b/src/components/Ecosystem/Endorsement/index.tsx @@ -16,7 +16,6 @@ import { checkEcosystem, getEcosystemId, } from '../../../config/ecosystem'; -import type { IAttributes } from '../../Resources/Schema/interfaces'; import EndorsementCard from './EndorsementCard'; import { GetEndorsementListParameter, @@ -26,27 +25,8 @@ import { EndorsementStatus, EndorsementType } from '../../../common/enums'; import { AlertComponent } from '../../AlertComponent'; import { Features } from '../../../utils/enums/features'; import EcosystemProfileCard from '../../../commonComponents/EcosystemProfileCard'; +import type { IEndorsementList, ISelectedRequest } from '../interfaces'; -interface ISelectedRequest { - attribute: IAttributes[]; - issuerDid: string; - createdDate: string; - schemaId: string; -} - -interface IEndorsementList { - id: string; - endorserDid: string; - authorDid: string; - status: string; - type: string; - ecosystemOrgs: { - orgId: string; - }; - requestPayload: string; - responsePayload: string; - createDateTime: string; -} const EndorsementList = () => { const [schemaList, setSchemaList] = useState([]); diff --git a/src/components/Ecosystem/interfaces/index.ts b/src/components/Ecosystem/interfaces/index.ts index bc85f9042..34c3f9c0f 100644 --- a/src/components/Ecosystem/interfaces/index.ts +++ b/src/components/Ecosystem/interfaces/index.ts @@ -1,3 +1,5 @@ +import type { IAttributes } from '../../Resources/Schema/interfaces'; + export interface IEcosystem { id: string name: string @@ -47,3 +49,28 @@ export interface ILogoImage { imagePreviewUrl: string | ArrayBuffer | null | File; fileName: string; } + +export interface ISelectedRequest { + attribute: IAttributes[]; + issuerDid: string; + createdDate: string; + schemaId: string; +} + +export interface IEndorsementList { + id: string; + endorserDid: string; + authorDid: string; + status: string; + type: string; + ecosystemOrgs: { + orgId: string; + }; + requestPayload: string; + responsePayload: string; + createDateTime: string; +} + +export interface EndorsementInterface { + getEndorsementListData: () => void; +} From 6abf1a9acdaa10007b55cf0fc8bc0fbf54035fe0 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 1 Feb 2024 20:27:58 +0530 Subject: [PATCH 097/303] implemented reset password functionality Signed-off-by: karan --- src/api/Auth.ts | 23 ++ .../Authentication/KeyCloakResetPassword.tsx | 297 ++++++++++++++++ .../Authentication/SignInUserPassword.tsx | 322 ++++++++++-------- src/config/apiRoutes.ts | 1 + src/utils/check-session.ts | 22 +- 5 files changed, 517 insertions(+), 148 deletions(-) create mode 100644 src/components/Authentication/KeyCloakResetPassword.tsx diff --git a/src/api/Auth.ts b/src/api/Auth.ts index 555357893..7a18cd159 100644 --- a/src/api/Auth.ts +++ b/src/api/Auth.ts @@ -26,6 +26,12 @@ export interface EmailVerifyData { email: string } +export interface KeyCloakData { + email: string, + oldPassword: string, + newPassword: string +} + export const sendVerificationMail = async(payload:UserSignUpData) => { const details ={ url: apiRoutes.auth.sendMail, @@ -58,6 +64,23 @@ export const loginUser = async(payload: UserSignInData) => { } } +export const resetPasswordKeyCloak = async(payload: KeyCloakData) => { + + const details = { + url: apiRoutes.auth.keyClockResetPassword, + payload, + config: { headers: { "Content-type": "application/json" } } + } + try{ + const response = await axiosPost(details) + return response + } + catch(error){ + const err = error as Error + return err?.message + } +} + export const getUserProfile = async(accessToken: string) => { const details = { url: apiRoutes.users.userProfile, diff --git a/src/components/Authentication/KeyCloakResetPassword.tsx b/src/components/Authentication/KeyCloakResetPassword.tsx new file mode 100644 index 000000000..43857d2a8 --- /dev/null +++ b/src/components/Authentication/KeyCloakResetPassword.tsx @@ -0,0 +1,297 @@ +import * as yup from 'yup'; +import { Avatar, Button, Label, Modal } from 'flowbite-react'; +import { Field, Form, Formik, FormikHelpers } from 'formik'; +import { apiStatusCodes, passwordRegex } from '../../config/CommonConstant'; +import { AlertComponent } from '../AlertComponent'; +import type { AxiosResponse } from 'axios'; +import { updateOrganization } from '../../api/organization'; +import { updateEcosystem } from '../../api/ecosystem'; +import type { + EditEntityModalProps, + EditEntityValues, + ILogoImage, +} from '../Ecosystem/interfaces'; +import React, { useEffect, useState } from 'react'; +import EndorsementTooltip from '../../commonComponents/EndorsementTooltip'; +import { processImage } from '../../utils/processImage'; +import FormikErrorMessage from '../../commonComponents/formikerror/index'; +import { passwordEncryption, resetPasswordKeyCloak } from '../../api/Auth'; +import { PassInvisible, PassVisible } from './Svg.js'; + +// EditEntityModalProps +const KeyClockResetPassword = (props) => { + const [loading, setLoading] = useState(false); + // const [passwordVisible, setPasswordVisible] = useState(false); + const [passwordVisibility, setPasswordVisibility] = useState({ + currentPassword: false, + newPassword: false, + confirmPassword: false, + }); + const submitUpdatePassword = async (values) => { + setLoading(true); + const entityData = { + email: props.email, + oldPassword: passwordEncryption(values.currentPassword), + newPassword: passwordEncryption(values.newPassword), + }; + try { + const response = await resetPasswordKeyCloak(entityData); + const { data } = response as AxiosResponse; + + // if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + // if (props?.onEditSuccess) { + // props?.onEditSuccess(); + // } + // props.setOpenModal(false); + // props.setMessage(data?.message); + // } else { + // setErrMsg(response as string); + // setLoading(false); + // } + } catch (error) { + console.error('An error occurred:', error); + setLoading(false); + } + }; + + const handleToggleVisibility = (passwordType: string) => { + setPasswordVisibility((prevVisibility) => ({ + ...prevVisibility, + [passwordType]: !prevVisibility[passwordType], + })); + }; + + return ( + { + props.setOpenModal(false); + }} + > + +

    Reset Password

    +

    + Choose a new password for your account +

    +

    + Note: CREDEBL has an update for your seamless experience, we request + you to please reset your password for it. +

    +
    + + {/* { + setErrMsg(null); + }} + /> */} + submitUpdatePassword(values)} + > + {(formikHandlers): JSX.Element => ( +
    +
    +
    +
    +
    + { + // setShowSuggestion(true); + // }} + // onBlurCapture={(e: any): void => { + // setShowSuggestion(false); + // formikHandlers.handleBlur(e); + // }} + /> + +
    + + {/* {showSuggestion && + formikHandlers?.errors?.password && + formikHandlers.values.password && ( + + )} */} + {formikHandlers?.errors?.currentPassword && + formikHandlers?.touched?.currentPassword && ( + + {formikHandlers?.errors?.currentPassword} + + )} +
    +
    +
    +
    +
    + { + // setShowSuggestion(true); + // }} + // onBlurCapture={(e: any): void => { + // setShowSuggestion(false); + // formikHandlers.handleBlur(e); + // }} + /> + +
    + + {/* {showSuggestion && + formikHandlers?.errors?.password && + formikHandlers.values.password && ( + + )} */} + {formikHandlers?.errors?.newPassword && + formikHandlers?.touched?.newPassword && ( + + {formikHandlers?.errors?.newPassword} + + )} +
    +
    +
    +
    +
    + { + // setShowSuggestion(true); + // }} + // onBlurCapture={(e: any): void => { + // setShowSuggestion(false); + // formikHandlers.handleBlur(e); + // }} + /> + +
    + + {/* {showSuggestion && + formikHandlers?.errors?.password && + formikHandlers.values.password && ( + + )} */} + {formikHandlers?.errors?.confirmPassword && + formikHandlers?.touched?.confirmPassword && ( + + {formikHandlers?.errors?.confirmPassword} + + )} +
    +
    + +
    +
    + )} +
    +
    +
    + ); +}; + +export default KeyClockResetPassword; diff --git a/src/components/Authentication/SignInUserPassword.tsx b/src/components/Authentication/SignInUserPassword.tsx index 04c7cfb3d..164510dd5 100644 --- a/src/components/Authentication/SignInUserPassword.tsx +++ b/src/components/Authentication/SignInUserPassword.tsx @@ -1,15 +1,16 @@ -import '../../common/global.css' +import '../../common/global.css'; import * as yup from 'yup'; import { Button, Label } from 'flowbite-react'; -import { - Field, - Form, - Formik, -} from 'formik'; +import { Field, Form, Formik } from 'formik'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; -import { getUserProfile, loginUser, passwordEncryption, setToLocalStorage } from '../../api/Auth'; +import { + getUserProfile, + loginUser, + passwordEncryption, + setToLocalStorage, +} from '../../api/Auth'; import { Alert } from 'flowbite-react'; import type { AxiosResponse } from 'axios'; @@ -21,6 +22,7 @@ import FooterBar from './FooterBar'; import React, { useState } from 'react'; import { PlatformRoles } from '../../common/enums'; import { pathRoutes } from '../../config/pathRoutes'; +import KeyClockResetPassword from './KeyCloakResetPassword'; interface emailValue { email: string; @@ -31,91 +33,102 @@ interface passwordValue { } interface SignInUser3Props { - email: string, - isPasskey: boolean, - password?: string + email: string; + isPasskey: boolean; + password?: string; } const SignInUserPassword = (signInUserProps: SignInUser3Props) => { - const [email, setEmail] = useState(signInUserProps?.email) - const [fidoUserError, setFidoUserError] = useState("") - const [success, setSuccess] = useState(null) - const [failure, setFailure] = useState(null) - const [isForgotPassLoading, setForgotPassLoading] = useState(false) - const [loading, setLoading] = useState(false) + const [email, setEmail] = useState(signInUserProps?.email); + const [fidoUserError, setFidoUserError] = useState(''); + const [success, setSuccess] = useState(null); + const [failure, setFailure] = useState(null); + const [isForgotPassLoading, setForgotPassLoading] = useState(false); + const [loading, setLoading] = useState(false); const [currentComponent, setCurrentComponent] = useState('email'); const [showSignInUser2, setShowSignInUser2] = useState(false); const [passwordVisible, setPasswordVisible] = useState(false); - + const [openModel, setOpenModel] = useState(false); const getUserDetails = async (access_token: string) => { - const userDetails = await getUserProfile(access_token); - const { data } = userDetails as AxiosResponse + const { data } = userDetails as AxiosResponse; if (data?.data?.userOrgRoles?.length > 0) { - const role = data?.data?.userOrgRoles.find((item: { orgRole: { name: PlatformRoles; }; }) => item.orgRole.name === PlatformRoles.platformAdmin) - const permissionArray: number | string[] = [] - data?.data?.userOrgRoles?.forEach((element: { orgRole: { name: string } }) => permissionArray.push(element?.orgRole?.name)); - await setToLocalStorage(storageKeys.USER_PROFILE, data?.data) - await setToLocalStorage(storageKeys.USER_EMAIL, data?.data?.email) + const role = data?.data?.userOrgRoles.find( + (item: { orgRole: { name: PlatformRoles } }) => + item.orgRole.name === PlatformRoles.platformAdmin, + ); + const permissionArray: number | string[] = []; + data?.data?.userOrgRoles?.forEach( + (element: { orgRole: { name: string } }) => + permissionArray.push(element?.orgRole?.name), + ); + await setToLocalStorage(storageKeys.USER_PROFILE, data?.data); + await setToLocalStorage(storageKeys.USER_EMAIL, data?.data?.email); return { - role: role?.orgRole || "" - } + role: role?.orgRole || '', + }; } else { - setFailure(userDetails as string) + setFailure(userDetails as string); } - setLoading(false) - } + setLoading(false); + }; const signInUser = async (values: passwordValue) => { const payload: SignInUser3Props = { email: email?.trim()?.toLocaleLowerCase(), isPasskey: false, - password: passwordEncryption(values.password) - } - setLoading(true) - const loginRsp = await loginUser(payload) - const { data } = loginRsp as AxiosResponse + password: passwordEncryption(values.password), + }; + setLoading(true); + const loginRsp = await loginUser(payload); + const { data } = loginRsp as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - await setToLocalStorage(storageKeys.TOKEN, data?.data?.access_token) - const userRole = await getUserDetails(data?.data?.access_token) - - const userPayload = { - ...data, - data: { - ...data.data, - role: userRole?.role?.name || "" - } + if (data.data.isRegisteredToSupabase) { + setOpenModel(true); + setLoading(false); + } else { + await setToLocalStorage(storageKeys.TOKEN, data?.data?.access_token); + const userRole = await getUserDetails(data?.data?.access_token); + + const userPayload = { + ...data, + data: { + ...data.data, + role: userRole?.role?.name || '', + }, + }; + + await fetch('/api/auth/signin', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(userPayload), + }); + + window.location.href = + userRole?.role?.name === PlatformRoles.platformAdmin + ? pathRoutes.users.platformSetting + : pathRoutes.users.dashboard; } - - await fetch('/api/auth/signin', { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(userPayload), - }); - - window.location.href = userRole?.role?.name === PlatformRoles.platformAdmin ? pathRoutes.users.platformSetting : pathRoutes.users.dashboard } else { - setLoading(false) - setFailure(loginRsp as string) + setLoading(false); + setFailure(loginRsp as string); } - } + }; const handleBackButtonClick = () => { setShowSignInUser2(!showSignInUser2); - }; const forgotPassword = async () => { - setForgotPassLoading(true); var base_url = window.location.origin; - const { data, error } = await getSupabaseClient().auth.resetPasswordForEmail(email - , { + const { data, error } = + await getSupabaseClient().auth.resetPasswordForEmail(email, { redirectTo: `${base_url}/reset-password`, }); setForgotPassLoading(false); @@ -123,11 +136,9 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => { if (!error) { setSuccess('Reset password link has been sent to you on mail'); } else { - setFailure('Unable to send reset link for the password') + setFailure('Unable to send reset link for the password'); } - - } - + }; return (
    @@ -135,48 +146,53 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => { ) : ( currentComponent === 'email' && ( - -
    -
    - +
    img - + alt="img" + />
    -
    - - { - (success || failure || fidoUserError) && + {(success || failure || fidoUserError) && ( { - setSuccess(null) - setFailure(null) + setSuccess(null); + setFailure(null); }} > -

    - {success || failure || fidoUserError} -

    +

    {success || failure || fidoUserError}

    - } + )} -
    - @@ -189,7 +205,7 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => {

    -
    +
    { fill="#1F4EAD" /> - + {signInUserProps?.email}
    - img + img
    - - - + signInUser(values)} > + onSubmit={(values: passwordValue) => signInUser(values)} + > {(formikHandlers): JSX.Element => (
    -
    -
    - + type={passwordVisible ? 'text' : 'password'} + />
    - { - (formikHandlers?.errors?.password && formikHandlers?.touched?.password) && - - {formikHandlers?.errors?.password} - } - + {formikHandlers?.errors?.password && + formikHandlers?.touched?.password && ( + + {formikHandlers?.errors?.password} + + )}
    - - {isForgotPassLoading - ? - : - } + )}
    - -
    +
    { {` Create an account`}
    @@ -321,11 +370,10 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => {
    - - - ))} + ) + )}
    ); }; -export default SignInUserPassword; \ No newline at end of file +export default SignInUserPassword; diff --git a/src/config/apiRoutes.ts b/src/config/apiRoutes.ts index 14b582410..1323038c7 100644 --- a/src/config/apiRoutes.ts +++ b/src/config/apiRoutes.ts @@ -14,6 +14,7 @@ export const apiRoutes = { fidoDevice: 'auth/passkey', fidoAuthentication: 'auth/passkey/authentication-options', fidoVerifyAuthentication: 'auth/passkey/verify-authentication/', + keyClockResetPassword: 'auth/reset-password' }, users: { userProfile: '/users/profile', diff --git a/src/utils/check-session.ts b/src/utils/check-session.ts index 84af87912..e90735013 100755 --- a/src/utils/check-session.ts +++ b/src/utils/check-session.ts @@ -29,18 +29,18 @@ export const checkUserSession = async ({ }; } - const { - data: { user }, - error, - } = await getSupabaseClient().auth.getUser(sessionCookie); + // const { + // data: { user }, + // error, + // } = await getSupabaseClient().auth.getUser(sessionCookie); - if (!user || user.role !== 'authenticated') { - return { - permitted: false, - redirect: pathRoutes.auth.sinIn, - authorized: false, - }; - } + // if (!user || user.role !== 'authenticated') { + // return { + // permitted: false, + // redirect: pathRoutes.auth.sinIn, + // authorized: false, + // }; + // } const role = getFromCookies(cookies, 'role'); const permittedPages = RolePermissions.find( From bc8da2b06d4ca397f166dfd8fc397f54bf82623a Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 2 Feb 2024 12:13:23 +0530 Subject: [PATCH 098/303] removed logs Signed-off-by: karan --- src/commonComponents/EcosystemProfileCard.tsx | 7 ++----- src/components/Ecosystem/interfaces/index.ts | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/commonComponents/EcosystemProfileCard.tsx b/src/commonComponents/EcosystemProfileCard.tsx index 2346e471d..323ec5494 100644 --- a/src/commonComponents/EcosystemProfileCard.tsx +++ b/src/commonComponents/EcosystemProfileCard.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' import { Card } from 'flowbite-react'; -import type { EndorsementInterface, IEcosystem } from '../components/Ecosystem/interfaces'; +import type { IEndorsement, IEcosystem } from '../components/Ecosystem/interfaces'; import { getFromLocalStorage, removeFromLocalStorage, setToLocalStorage } from '../api/Auth'; import { apiStatusCodes, storageKeys } from '../config/CommonConstant'; import type { AxiosResponse } from 'axios'; @@ -12,7 +12,7 @@ import { pathRoutes } from '../config/pathRoutes'; import { EmptyListMessage } from '../components/EmptyListComponent'; -const EcosystemProfileCard = ({getEndorsementListData}:EndorsementInterface) => { +const EcosystemProfileCard = ({getEndorsementListData}:IEndorsement) => { const [ecosystemDetails, setEcosystemDetails] = useState(); const [ecosystemList, setEcosystemList] = useState(); const [loading, setLoading] = useState(); @@ -68,9 +68,6 @@ const EcosystemProfileCard = ({getEndorsementListData}:EndorsementInterface) => const handleSelectEcosystem = async (e: { target: { value: string; }; }) => { await fetchEcosystemDetails(e.target.value) await setToLocalStorage(storageKeys.ECOSYSTEM_ID, e.target.value); - let kkkk= await getFromLocalStorage(storageKeys.ECOSYSTEM_ID) - console.log("kkkk",kkkk); - await getEndorsementListData() } diff --git a/src/components/Ecosystem/interfaces/index.ts b/src/components/Ecosystem/interfaces/index.ts index 34c3f9c0f..33757eeff 100644 --- a/src/components/Ecosystem/interfaces/index.ts +++ b/src/components/Ecosystem/interfaces/index.ts @@ -71,6 +71,6 @@ export interface IEndorsementList { createDateTime: string; } -export interface EndorsementInterface { +export interface IEndorsement { getEndorsementListData: () => void; } From 0157a82cbcb47f570a5f9e7ec4edc4304ed2e304 Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 2 Feb 2024 17:08:19 +0530 Subject: [PATCH 099/303] implemented reset password Signed-off-by: karan --- src/components/Authentication/KeyCloakResetPassword.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Authentication/KeyCloakResetPassword.tsx b/src/components/Authentication/KeyCloakResetPassword.tsx index 43857d2a8..694d08f3c 100644 --- a/src/components/Authentication/KeyCloakResetPassword.tsx +++ b/src/components/Authentication/KeyCloakResetPassword.tsx @@ -64,7 +64,7 @@ const KeyClockResetPassword = (props) => { return ( { props.setOpenModal(false); }} From 8f83fed559fea6d0a28abbc11665d09767f4bd9c Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 2 Feb 2024 17:18:12 +0530 Subject: [PATCH 100/303] feat: reset password to register on keycloak Signed-off-by: karan --- .../Authentication/KeyCloakResetPassword.tsx | 133 ++++++------------ .../Authentication/SignInUserPassword.tsx | 20 +-- .../Authentication/interfaces/index.ts | 20 ++- src/config/pathRoutes.ts | 3 + src/utils/check-session.ts | 13 -- 5 files changed, 73 insertions(+), 116 deletions(-) diff --git a/src/components/Authentication/KeyCloakResetPassword.tsx b/src/components/Authentication/KeyCloakResetPassword.tsx index 694d08f3c..fba55d0db 100644 --- a/src/components/Authentication/KeyCloakResetPassword.tsx +++ b/src/components/Authentication/KeyCloakResetPassword.tsx @@ -1,33 +1,26 @@ import * as yup from 'yup'; -import { Avatar, Button, Label, Modal } from 'flowbite-react'; -import { Field, Form, Formik, FormikHelpers } from 'formik'; +import { Button, Label, Modal } from 'flowbite-react'; +import { Field, Form, Formik } from 'formik'; import { apiStatusCodes, passwordRegex } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; -import { updateOrganization } from '../../api/organization'; -import { updateEcosystem } from '../../api/ecosystem'; -import type { - EditEntityModalProps, - EditEntityValues, - ILogoImage, -} from '../Ecosystem/interfaces'; -import React, { useEffect, useState } from 'react'; -import EndorsementTooltip from '../../commonComponents/EndorsementTooltip'; -import { processImage } from '../../utils/processImage'; -import FormikErrorMessage from '../../commonComponents/formikerror/index'; +import { useState } from 'react'; import { passwordEncryption, resetPasswordKeyCloak } from '../../api/Auth'; import { PassInvisible, PassVisible } from './Svg.js'; +import { pathRoutes } from '../../config/pathRoutes'; +import type { IPassword, IProps, IValues } from './interfaces'; -// EditEntityModalProps -const KeyClockResetPassword = (props) => { +const KeyClockResetPassword = (props: IProps) => { const [loading, setLoading] = useState(false); - // const [passwordVisible, setPasswordVisible] = useState(false); - const [passwordVisibility, setPasswordVisibility] = useState({ + const [success, setSuccess] = useState(null); + const [error, setError] = useState(null); + const [passwordVisibility, setPasswordVisibility] = useState({ currentPassword: false, newPassword: false, confirmPassword: false, }); - const submitUpdatePassword = async (values) => { + + const submitUpdatePassword = async (values: IValues) => { setLoading(true); const entityData = { email: props.email, @@ -38,23 +31,21 @@ const KeyClockResetPassword = (props) => { const response = await resetPasswordKeyCloak(entityData); const { data } = response as AxiosResponse; - // if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - // if (props?.onEditSuccess) { - // props?.onEditSuccess(); - // } - // props.setOpenModal(false); - // props.setMessage(data?.message); - // } else { - // setErrMsg(response as string); - // setLoading(false); - // } + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setSuccess(data.message); + setLoading(false); + window.location.href = pathRoutes.landingPage.landingPage; + } else { + setError(response as string); + setLoading(false); + } } catch (error) { console.error('An error occurred:', error); setLoading(false); } }; - const handleToggleVisibility = (passwordType: string) => { + const handleToggleVisibility = (passwordType: keyof IPassword) => { setPasswordVisibility((prevVisibility) => ({ ...prevVisibility, [passwordType]: !prevVisibility[passwordType], @@ -64,7 +55,7 @@ const KeyClockResetPassword = (props) => { return ( { props.setOpenModal(false); }} @@ -75,18 +66,19 @@ const KeyClockResetPassword = (props) => { Choose a new password for your account

    - Note: CREDEBL has an update for your seamless experience, we request - you to please reset your password for it. + CREDEBL has an update for your seamless experience. We request you to + please reset your password for it.

    - {/* { - setErrMsg(null); - }} - /> */} + { + setError(null); + setSuccess(null); + }} + /> { .string() .required('Current Password is required') .min(8, 'Password must be at least 8 characters') - .matches(passwordRegex, 'Invalid password'), + .matches(passwordRegex, 'Password must contain at least one lowercase letter, one uppercase letter, one number, and one special character'), newPassword: yup .string() .required('New Password is required') .min(8, 'Password must be at least 8 characters') - .matches(passwordRegex, 'Invalid password'), + .matches(passwordRegex, 'Password must contain at least one lowercase letter, one uppercase letter, one number, and one special character'), confirmPassword: yup .string() .required('Confirm Password is required') @@ -113,7 +105,7 @@ const KeyClockResetPassword = (props) => { validateOnBlur validateOnChange enableReinitialize - onSubmit={(values: any) => submitUpdatePassword(values)} + onSubmit={(values: IValues) => submitUpdatePassword(values)} > {(formikHandlers): JSX.Element => (
    @@ -135,13 +127,6 @@ const KeyClockResetPassword = (props) => { type={ passwordVisibility.currentPassword ? 'text' : 'password' } - // onFocus={(): void => { - // setShowSuggestion(true); - // }} - // onBlurCapture={(e: any): void => { - // setShowSuggestion(false); - // formikHandlers.handleBlur(e); - // }} />
    - - {/* {showSuggestion && - formikHandlers?.errors?.password && - formikHandlers.values.password && ( - - )} */} {formikHandlers?.errors?.currentPassword && + typeof formikHandlers?.errors?.currentPassword === 'string' && formikHandlers?.touched?.currentPassword && ( - +
    {formikHandlers?.errors?.currentPassword} - +
    )}
    @@ -187,13 +164,6 @@ const KeyClockResetPassword = (props) => { placeholder="Please enter password" className="truncate w-full bg-gray-200 pl-4 !pr-10 py-2 text-gray-700 dark:text-white dark:bg-gray-800 text-sm rounded-md focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-600" type={passwordVisibility.newPassword ? 'text' : 'password'} - // onFocus={(): void => { - // setShowSuggestion(true); - // }} - // onBlurCapture={(e: any): void => { - // setShowSuggestion(false); - // formikHandlers.handleBlur(e); - // }} />
    - - {/* {showSuggestion && - formikHandlers?.errors?.password && - formikHandlers.values.password && ( - - )} */} {formikHandlers?.errors?.newPassword && + typeof formikHandlers?.errors?.newPassword === 'string' && + formikHandlers?.errors?.newPassword && formikHandlers?.touched?.newPassword && ( {formikHandlers?.errors?.newPassword} @@ -241,13 +204,6 @@ const KeyClockResetPassword = (props) => { type={ passwordVisibility.confirmPassword ? 'text' : 'password' } - // onFocus={(): void => { - // setShowSuggestion(true); - // }} - // onBlurCapture={(e: any): void => { - // setShowSuggestion(false); - // formikHandlers.handleBlur(e); - // }} />
    - - {/* {showSuggestion && - formikHandlers?.errors?.password && - formikHandlers.values.password && ( - - )} */} {formikHandlers?.errors?.confirmPassword && + typeof formikHandlers?.errors?.confirmPassword === 'string' && formikHandlers?.touched?.confirmPassword && ( {formikHandlers?.errors?.confirmPassword} @@ -281,6 +229,7 @@ const KeyClockResetPassword = (props) => { + {dropdownOpen ? ( + ( + + )} + dismissOnClick={true} + > + { + EditEcosystemOrgModal(); + }} + > +
    Edit Ecosystem
    +
    + {/* +
    Enable/Disable Ecosystem
    +
    */} + {/* +
    Manual Registration
    +
    */} +
    + ) : ( + + )} +
    +

    +
    +
    + + ) : ( + <> +
    +
    +
    + {ecosystemDetails?.logoUrl ? ( + + ) : ( + + )} +
    +
    +
    +

    + {ecosystemDetails?.name} +

    +

    + {ecosystemDetails?.description} +

    +
    +
    + + Ecosystem Owner + + :{' '} + + {leadOrg} + +
    +
    + + Ecosystem Lead + {' '} + : + + {leadOrg} + +
    +
    + + Joined since + {' '} + : + + + {dateConversion(ecosystemDetails.joinedDate || '')} + + +
    +
    +
    + + Endorsement Flow + {' '} + : + + {ecosystemDetails.autoEndorsement + ? ' Sign and Submit' + : ' Sign'} + +
    +
    +
    + Role: {' '} + +
    +
    + + )} + + {/*
    @@ -321,7 +498,7 @@ const Dashboard = () => { :{' '} {leadOrg} - +
    @@ -350,7 +527,7 @@ const Dashboard = () => {
    )} -
    +
    Endorsement Flow {' '} @@ -372,7 +549,7 @@ const Dashboard = () => { )} {isEcosystemLead && ( -
    +
    )}
    -
    +
    */} +
    {
    + { Date: Mon, 5 Feb 2024 12:34:24 +0530 Subject: [PATCH 102/303] Merge branch ' merge-dev-to-qa Signed-off-by: karan --- src/commonComponents/EcosystemProfileCard.tsx | 6 +++--- .../EcosystemInvite/EcoSystemReceivedInvitations.tsx | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/commonComponents/EcosystemProfileCard.tsx b/src/commonComponents/EcosystemProfileCard.tsx index 323ec5494..3915037e1 100644 --- a/src/commonComponents/EcosystemProfileCard.tsx +++ b/src/commonComponents/EcosystemProfileCard.tsx @@ -104,15 +104,15 @@ const EcosystemProfileCard = ({getEndorsementListData}:IEndorsement) => {
    { - Boolean(ecosystemOptions && ecosystemOptions.length > 0) && + Boolean(ecosystemOptions && ecosystemOptions?.length > 0) && diff --git a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx index febf1665b..db9416c21 100644 --- a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx +++ b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx @@ -1,5 +1,5 @@ import { Button, Card, Pagination } from 'flowbite-react'; -import { useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { acceptRejectEcosystemInvitations, getUserEcosystemInvitations, @@ -16,7 +16,6 @@ import { getFromLocalStorage } from '../../api/Auth'; import { getOrganizationById, getOrganizations } from '../../api/organization'; import EcoInvitationList from './EcoInvitationList'; import BackButton from '../../commonComponents/backbutton'; -import React from 'react'; const initialPageState = { pageNumber: 1, From 18e66cae6beaf9c62d561dac01092c7744327e36 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 5 Feb 2024 13:49:14 +0530 Subject: [PATCH 103/303] fix: white space issue between words Signed-off-by: karan --- src/components/Profile/AddPasskey.tsx | 2 +- src/components/Profile/DisplayUserProfile.tsx | 2 +- src/components/Profile/EditUserProfile.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Profile/AddPasskey.tsx b/src/components/Profile/AddPasskey.tsx index 8485daaf8..04a3add32 100644 --- a/src/components/Profile/AddPasskey.tsx +++ b/src/components/Profile/AddPasskey.tsx @@ -223,7 +223,7 @@ const AddPasskey = ({ responseMessages }: { responseMessages: (value: IResponseM

    Add Passkey

    -

    +

    With Passkey, no complex passwords to remember.

    diff --git a/src/components/Profile/DisplayUserProfile.tsx b/src/components/Profile/DisplayUserProfile.tsx index 82b18d628..eb806442d 100644 --- a/src/components/Profile/DisplayUserProfile.tsx +++ b/src/components/Profile/DisplayUserProfile.tsx @@ -15,7 +15,7 @@ const DisplayUserProfile = ({

    General

    - + Basic info, like your first name, last name and profile image that will be displayed diff --git a/src/components/Profile/EditUserProfile.tsx b/src/components/Profile/EditUserProfile.tsx index 41fbfa2f5..78e16f467 100644 --- a/src/components/Profile/EditUserProfile.tsx +++ b/src/components/Profile/EditUserProfile.tsx @@ -241,7 +241,7 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile }:

    General

    -

    Basic info, like your first name, last name and profile image that will be displayed

    +

    Basic info, like your first name, last name and profile image that will be displayed

    From d22c822855a54f06636ace4a4ac41061d23f1d33 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 5 Feb 2024 15:47:28 +0530 Subject: [PATCH 104/303] fix: sapce issue between svg and text Signed-off-by: karan --- src/components/Authentication/SignUpUser.tsx | 4 ++-- src/components/Authentication/SignUpUserName.tsx | 2 +- src/components/Authentication/SignUpUserPasskey.tsx | 6 +++--- src/components/Authentication/SignUpUserPassword.tsx | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/Authentication/SignUpUser.tsx b/src/components/Authentication/SignUpUser.tsx index efe80853b..6e8b774f8 100644 --- a/src/components/Authentication/SignUpUser.tsx +++ b/src/components/Authentication/SignUpUser.tsx @@ -125,7 +125,7 @@ const SignUpUser = () => { } -
    +
    -
    +

    Create account @@ -318,4 +318,4 @@ const SignUpUserPasskey = ({ email, firstName, lastName }: { email: string, firs ); }; -export default SignUpUserPasskey; \ No newline at end of file +export default SignUpUserPasskey; diff --git a/src/components/Authentication/SignUpUserPassword.tsx b/src/components/Authentication/SignUpUserPassword.tsx index 2185ab6c4..db452ebbf 100644 --- a/src/components/Authentication/SignUpUserPassword.tsx +++ b/src/components/Authentication/SignUpUserPassword.tsx @@ -124,7 +124,7 @@ const SignUpUserPassword = ({ )} -
    +
    - {dropdownOpen ? ( - ( - + Invitations + + {dropdownOpen ? ( + ( + + )} + dismissOnClick={true} + > + { + EditEcosystemOrgModal(); + }} > - - - )} - dismissOnClick={true} - > - { - EditEcosystemOrgModal(); - }} +
    Edit Ecosystem
    +
    +
    + ) : ( +
    Edit Ecosystem
    - - {/* -
    Enable/Disable Ecosystem
    -
    */} - {/* -
    Manual Registration
    -
    */} -
    - ) : ( - - )} -
    + + + )} +

    @@ -396,7 +390,7 @@ const Dashboard = () => { ) : ( <>
    @@ -407,7 +401,10 @@ const Dashboard = () => { )}
    -
    +

    {ecosystemDetails?.name}

    @@ -420,7 +417,7 @@ const Dashboard = () => { Ecosystem Owner :{' '} - + {leadOrg}
    @@ -429,7 +426,7 @@ const Dashboard = () => { Ecosystem Lead {' '} : - + {leadOrg}
    @@ -438,7 +435,7 @@ const Dashboard = () => { Joined since {' '} : - + {dateConversion(ecosystemDetails.joinedDate || '')} @@ -450,7 +447,7 @@ const Dashboard = () => { Endorsement Flow {' '} : - + {ecosystemDetails.autoEndorsement ? ' Sign and Submit' : ' Sign'} @@ -465,151 +462,6 @@ const Dashboard = () => { )} - {/*
    -
    -
    - {ecosystemDetails?.logoUrl ? ( - - ) : ( - - )} -
    - {ecosystemDetails ? ( -
    -

    - {ecosystemDetails?.name} -

    - -

    - {ecosystemDetails?.description} -

    - {!isEcosystemLead ? ( -
    -
    - - Ecosystem Owner - - :{' '} - - {leadOrg} - -
    -
    - - Ecosystem Lead - {' '} - : - - {leadOrg} - -
    -
    - - Joined since - {' '} - : - - - {dateConversion(ecosystemDetails.joinedDate || '')} - - -
    -
    - ) : ( -
    - Role: {' '} - -
    - )} -
    - - Endorsement Flow - {' '} - : - - {ecosystemDetails.autoEndorsement ? ' Sign and Submit' : ' Sign'} - -
    -
    - ) : ( - - )} - - {!isEcosystemLead && ( -
    - Role: {' '} - -
    - )} - - {isEcosystemLead && ( -
    - - {dropdownOpen ? ( - ( - - )} - dismissOnClick={true} - > - { - EditEcosystemOrgModal(); - }} - > -
    Edit Ecosystem
    -
    - -
    - ) : ( - - )} -
    - )} -
    -
    */} -
    { website: props?.orgData?.website ?? '', }); props.setOpenModal(false); + setErrMsg(null); }} > Edit Organization From 4350e08b14cab4a6f6a905fd504ef9576ba38d0b Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 5 Feb 2024 20:03:01 +0530 Subject: [PATCH 107/303] handled empty response for organization Signed-off-by: karan --- src/components/Setting/index.tsx | 259 +++++++++++++++++-------------- 1 file changed, 144 insertions(+), 115 deletions(-) diff --git a/src/components/Setting/index.tsx b/src/components/Setting/index.tsx index a1d58949f..4df44b329 100644 --- a/src/components/Setting/index.tsx +++ b/src/components/Setting/index.tsx @@ -1,7 +1,7 @@ import { Button } from 'flowbite-react'; import React, { useEffect, useState } from 'react'; import CustomSpinner from '../CustomSpinner'; -import { getFromLocalStorage } from '../../api/Auth'; +import { getFromLocalStorage, setToLocalStorage } from '../../api/Auth'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import type { AxiosResponse } from 'axios'; import CopyDid from '../../commonComponents/CopyDid'; @@ -13,6 +13,7 @@ import { deleteCredentials, getCredentials, } from './setting'; +import { EmptyListMessage } from '../EmptyListComponent'; const index = () => { const [loading, setLoading] = useState(false); @@ -23,6 +24,7 @@ const index = () => { const [warning, setWarning] = useState(null); const [hideCopy, setHideCopy] = useState(true); const [userRoles, setUserRoles] = useState([]); + const [orgnizationId, setOrgnizationId] = useState(null); const createClientCredentials = async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); @@ -64,7 +66,7 @@ const index = () => { setHideCopy(true); setClientId(data.data.clientId); setClientSecret(data.data.clientSecret); - }else{ + } else { setClientId(null); setClientSecret(null); } @@ -112,8 +114,12 @@ const index = () => { }; useEffect(() => { - getClientCredentials(); - getUserRoles(); + (async () => { + await getClientCredentials(); + await getUserRoles(); + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + setOrgnizationId(orgId); + })(); }, []); return ( @@ -138,123 +144,146 @@ const index = () => {
    - ) : ( - -
    -
    -

    - Client Id -

    -

    - {clentId && ( - - )} -

    -
    - -
    -
    -
    -

    - Client Secrate -

    - - You need a client secret to authenticate as the - organization to the API. - -
    - {(userRoles.includes(Roles.OWNER) || - userRoles.includes(Roles.ADMIN)) && ( -
    - -
    - )} + ) : orgnizationId ? ( + <> + {' '} + +
    +
    +

    + Client Id +

    +

    + {clentId && ( + + )} +

    - {clentId && ( - <> -
    -
    - {warning && ( - { - setWarning(null); - setFailure(null); - }} - /> - )} +
    +
    +
    +

    + Client Secrate +

    + + You need a client secret to authenticate as the + organization to the API. +
    -
    -
    -
    - - - -
    -
    -

    - {!hideCopy ? ( - clientSecret && ( - // font-courier font-semibold - - ) - ) : ( - - {clientSecret} - - )} -

    -
    + {(userRoles.includes(Roles.OWNER) || + userRoles.includes(Roles.ADMIN)) && ( +
    +
    - {(userRoles.includes(Roles.OWNER) || - userRoles.includes(Roles.ADMIN)) && ( -
    - + )} +
    + + {clentId && ( + <> +
    +
    + {warning && ( + { + setWarning(null); + setFailure(null); + }} + /> + )} +
    +
    +
    +
    + + + +
    +
    +

    + {!hideCopy ? ( + clientSecret && ( + // font-courier font-semibold + + ) + ) : ( + + {clientSecret} + + )} +

    +
    - )} -
    - - )} + {(userRoles.includes(Roles.OWNER) || + userRoles.includes(Roles.ADMIN)) && ( +
    + +
    + )} +
    + + )} +
    -
    - + {' '} + + ) : ( + + + + } + /> )}
    From ebf9d25a541565ee231d94feec6cdbbd28421469 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Tue, 6 Feb 2024 10:56:56 +0530 Subject: [PATCH 108/303] refactor:endorsement button text and statuses Signed-off-by: pranalidhanavade --- src/commonComponents/StatusTabletTag.tsx | 4 ++-- src/components/Ecosystem/Endorsement/EndorsementPopup.tsx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/commonComponents/StatusTabletTag.tsx b/src/commonComponents/StatusTabletTag.tsx index a29f9196a..a8335fe76 100644 --- a/src/commonComponents/StatusTabletTag.tsx +++ b/src/commonComponents/StatusTabletTag.tsx @@ -10,12 +10,12 @@ const StatusTabletTag = ({ status }: IStatusTabletTag) => { case status === EndorsementStatus.signed: return { style: `bg-[#fca20033] text-[#FCA200]`, - title: "Accepted" + title: "Endorsed" } case status === EndorsementStatus.rejected: return { style: `bg-[#FFE4E4] text-[#EA5455]`, - title: "Rejected" + title: "Declined" } case status === EndorsementStatus.requested: return { diff --git a/src/components/Ecosystem/Endorsement/EndorsementPopup.tsx b/src/components/Ecosystem/Endorsement/EndorsementPopup.tsx index 83c4137d4..3cb427bc2 100644 --- a/src/components/Ecosystem/Endorsement/EndorsementPopup.tsx +++ b/src/components/Ecosystem/Endorsement/EndorsementPopup.tsx @@ -178,7 +178,7 @@ const EndorsementPopup = (props: { fill="#1F4EAD" /> - Reject + Decline @@ -205,7 +205,7 @@ const EndorsementPopup = (props: { /> - Accept + Endorse
    @@ -238,7 +238,7 @@ const EndorsementPopup = (props: { /> - Submit + Submit
    From 4120b712884fba3a9ba50ca44659dc11a44e7162 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 6 Feb 2024 12:04:18 +0530 Subject: [PATCH 109/303] handled loading Signed-off-by: karan --- src/components/Setting/index.tsx | 7 ++++--- src/components/SignOutButton/index.tsx | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Setting/index.tsx b/src/components/Setting/index.tsx index 4df44b329..70381f760 100644 --- a/src/components/Setting/index.tsx +++ b/src/components/Setting/index.tsx @@ -1,7 +1,7 @@ import { Button } from 'flowbite-react'; import React, { useEffect, useState } from 'react'; import CustomSpinner from '../CustomSpinner'; -import { getFromLocalStorage, setToLocalStorage } from '../../api/Auth'; +import { getFromLocalStorage } from '../../api/Auth'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import type { AxiosResponse } from 'axios'; import CopyDid from '../../commonComponents/CopyDid'; @@ -16,7 +16,7 @@ import { import { EmptyListMessage } from '../EmptyListComponent'; const index = () => { - const [loading, setLoading] = useState(false); + const [loading, setLoading] = useState(true); const [clentId, setClientId] = useState(null); const [clientSecret, setClientSecret] = useState(null); const [success, setSuccess] = useState(null); @@ -46,6 +46,7 @@ const index = () => { } } catch (error) { setFailure(error as string); + setLoading(false); } finally { setLoading(false); } @@ -144,7 +145,7 @@ const index = () => {
    - ) : orgnizationId ? ( + ) : !loading && orgnizationId ? ( <> {' '}
    diff --git a/src/components/SignOutButton/index.tsx b/src/components/SignOutButton/index.tsx index c6de6199a..862372974 100644 --- a/src/components/SignOutButton/index.tsx +++ b/src/components/SignOutButton/index.tsx @@ -35,6 +35,7 @@ const SignOutButton = () => { height="20" viewBox="0 0 16 20" fill="none" + className='ml-[2px]' > Date: Tue, 6 Feb 2024 12:12:53 +0530 Subject: [PATCH 110/303] removed authentication of supabase Signed-off-by: karan --- src/utils/check-session.ts | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/utils/check-session.ts b/src/utils/check-session.ts index c35284ad2..27434496d 100755 --- a/src/utils/check-session.ts +++ b/src/utils/check-session.ts @@ -6,7 +6,6 @@ import { RolePermissions } from '../config/permissions'; interface IProps { cookies: AstroCookies; - currentPath: string; } interface IOutput { @@ -17,7 +16,6 @@ interface IOutput { export const checkUserSession = async ({ cookies, - currentPath, }: IProps): Promise => { const sessionCookie = getFromCookies(cookies, 'session'); @@ -29,40 +27,6 @@ export const checkUserSession = async ({ }; } - // const { - // data: { user }, - // error, - // } = await getSupabaseClient().auth.getUser(sessionCookie); - - // if (!user || user.role !== 'authenticated') { - // return { - // permitted: false, - // redirect: pathRoutes.auth.sinIn, - // authorized: false, - // }; - // } - - // const role = getFromCookies(cookies, 'role'); - // const permittedPages = RolePermissions.find( - // (item) => item.role === role, - // )?.pages; - - // if (!permittedPages?.includes(currentPath)) { - // if (permittedPages) { - // return { - // permitted: false, - // redirect: permittedPages[0], - // authorized: true, - // }; - // } else { - // return { - // permitted: true, - // redirect: pathRoutes.users.dashboard, - // authorized: true, - // }; - // } - // } - return { permitted: true, authorized: true, From 85a8f1d85caf61c0efbd304dbb0dd8f81dd907da Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 6 Feb 2024 12:23:57 +0530 Subject: [PATCH 111/303] removed commented code and type error Signed-off-by: karan --- src/components/Setting/index.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/Setting/index.tsx b/src/components/Setting/index.tsx index 70381f760..af84f2968 100644 --- a/src/components/Setting/index.tsx +++ b/src/components/Setting/index.tsx @@ -15,7 +15,7 @@ import { } from './setting'; import { EmptyListMessage } from '../EmptyListComponent'; -const index = () => { +const Index = () => { const [loading, setLoading] = useState(true); const [clentId, setClientId] = useState(null); const [clientSecret, setClientSecret] = useState(null); @@ -24,7 +24,7 @@ const index = () => { const [warning, setWarning] = useState(null); const [hideCopy, setHideCopy] = useState(true); const [userRoles, setUserRoles] = useState([]); - const [orgnizationId, setOrgnizationId] = useState(null); + const [orgnizationId, setOrgnizationId] = useState(null); const createClientCredentials = async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); @@ -233,7 +233,6 @@ const index = () => {

    {!hideCopy ? ( clientSecret && ( - // font-courier font-semibold { ); }; -export default index; +export default Index; From 10ea7005cfb70b608a6aeac422444384f3513844 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 6 Feb 2024 12:27:09 +0530 Subject: [PATCH 112/303] handled sonar suggestions Signed-off-by: karan --- src/components/Setting/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Setting/index.tsx b/src/components/Setting/index.tsx index af84f2968..75acdcafb 100644 --- a/src/components/Setting/index.tsx +++ b/src/components/Setting/index.tsx @@ -17,7 +17,7 @@ import { EmptyListMessage } from '../EmptyListComponent'; const Index = () => { const [loading, setLoading] = useState(true); - const [clentId, setClientId] = useState(null); + const [clientId, setClientId] = useState(null); const [clientSecret, setClientSecret] = useState(null); const [success, setSuccess] = useState(null); const [failure, setFailure] = useState(null); @@ -155,10 +155,10 @@ const Index = () => { Client Id

    - {clentId && ( + {clientId && ( )}

    @@ -195,7 +195,7 @@ const Index = () => { )}
    - {clentId && ( + {clientId && ( <>
    From df16fd1bc06e9636f83f53f55f42522fe9524fce Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 6 Feb 2024 13:13:14 +0530 Subject: [PATCH 113/303] role check added Signed-off-by: karan --- src/utils/check-session.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/utils/check-session.ts b/src/utils/check-session.ts index 27434496d..1c7f92bf6 100755 --- a/src/utils/check-session.ts +++ b/src/utils/check-session.ts @@ -6,6 +6,7 @@ import { RolePermissions } from '../config/permissions'; interface IProps { cookies: AstroCookies; + currentPath: string; } interface IOutput { @@ -16,6 +17,7 @@ interface IOutput { export const checkUserSession = async ({ cookies, + currentPath }: IProps): Promise => { const sessionCookie = getFromCookies(cookies, 'session'); @@ -26,7 +28,26 @@ export const checkUserSession = async ({ authorized: false, }; } + const role = getFromCookies(cookies, 'role'); + const permittedPages = RolePermissions.find( + (item) => item.role === role, + )?.pages; + if (!permittedPages?.includes(currentPath)) { + if (permittedPages) { + return { + permitted: false, + redirect: permittedPages[0], + authorized: true, + }; + } else { + return { + permitted: true, + redirect: pathRoutes.users.dashboard, + authorized: true, + }; + } + } return { permitted: true, authorized: true, From 5f5beacaab5c22f4a980f81f7c67f71e8731c105 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 6 Feb 2024 16:08:16 +0530 Subject: [PATCH 114/303] handled success navigation Signed-off-by: karan --- src/components/Authentication/KeyCloakResetPassword.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Authentication/KeyCloakResetPassword.tsx b/src/components/Authentication/KeyCloakResetPassword.tsx index fba55d0db..31d8dc257 100644 --- a/src/components/Authentication/KeyCloakResetPassword.tsx +++ b/src/components/Authentication/KeyCloakResetPassword.tsx @@ -9,6 +9,7 @@ import { passwordEncryption, resetPasswordKeyCloak } from '../../api/Auth'; import { PassInvisible, PassVisible } from './Svg.js'; import { pathRoutes } from '../../config/pathRoutes'; import type { IPassword, IProps, IValues } from './interfaces'; +import React from 'react'; const KeyClockResetPassword = (props: IProps) => { const [loading, setLoading] = useState(false); @@ -34,7 +35,7 @@ const KeyClockResetPassword = (props: IProps) => { if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setSuccess(data.message); setLoading(false); - window.location.href = pathRoutes.landingPage.landingPage; + window.location.href= pathRoutes.auth.sinIn } else { setError(response as string); setLoading(false); From 82cb8e88f080ff0e7e1e8ccd84f7dac88835dca8 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 6 Feb 2024 16:45:55 +0530 Subject: [PATCH 115/303] handled ecosystem content change on dropdown Signed-off-by: karan --- src/commonComponents/EcosystemProfileCard.tsx | 1 - src/components/Resources/Schema/Create.tsx | 19 +++++++++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/commonComponents/EcosystemProfileCard.tsx b/src/commonComponents/EcosystemProfileCard.tsx index 323ec5494..9a9b7518a 100644 --- a/src/commonComponents/EcosystemProfileCard.tsx +++ b/src/commonComponents/EcosystemProfileCard.tsx @@ -71,7 +71,6 @@ const EcosystemProfileCard = ({getEndorsementListData}:IEndorsement) => { await getEndorsementListData() } - useEffect(() => { fetchEcosystemDetails(); }, []); diff --git a/src/components/Resources/Schema/Create.tsx b/src/components/Resources/Schema/Create.tsx index b90ec4c53..56b34a2ed 100644 --- a/src/components/Resources/Schema/Create.tsx +++ b/src/components/Resources/Schema/Create.tsx @@ -70,19 +70,18 @@ const CreateSchema = () => { }, ], }; + const checkEcosystemData = async () => { + const data: ICheckEcosystem = await checkEcosystem(); + setIsEcosystemData(data); + }; + const [formData, setFormData] = useState(initFormData); + useEffect(() => { - const fetchData = async () => { + (async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); setOrgId(orgId); - }; - - fetchData(); - - const checkEcosystemData = async () => { - const data: ICheckEcosystem = await checkEcosystem(); - setIsEcosystemData(data); - }; + })(); checkEcosystemData(); }, []); @@ -283,7 +282,7 @@ const CreateSchema = () => {
    {isEcosystemData?.isEnabledEcosystem && (
    - +
    )} From d1332d0c0dd5203023798482f545f5f9bb9a7f5e Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 6 Feb 2024 18:39:53 +0530 Subject: [PATCH 116/303] handled delete invitation access Signed-off-by: karan --- .../organization/invitations/Invitations.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/organization/invitations/Invitations.tsx b/src/components/organization/invitations/Invitations.tsx index 363c2dd19..90e35ebc8 100644 --- a/src/components/organization/invitations/Invitations.tsx +++ b/src/components/organization/invitations/Invitations.tsx @@ -20,6 +20,7 @@ import DateTooltip from '../../Tooltip'; import { deleteOrganizationInvitation } from '../../../api/organization'; import { getFromLocalStorage } from '../../../api/Auth'; import ConfirmationModal from '../../../commonComponents/ConfirmationModal'; +import { Roles } from '../../../utils/enums/roles'; const initialPageState = { pageNumber: 1, @@ -36,8 +37,9 @@ const Invitations = () => { const [message, setMessage] = useState(null) const [showPopup, setShowPopup] = useState(false) const [error, setError] = useState(null) - const [currentPage, setCurrentPage] = useState(initialPageState); - + const [roles, setRoles] = useState([]); + const [currentPage, setCurrentPage] = useState(initialPageState); + const onPageChange = (page: number) => { setCurrentPage({ ...currentPage, @@ -45,11 +47,12 @@ const Invitations = () => { }) }; const [searchText, setSearchText] = useState(""); - const [invitationsList, setInvitationsList] = useState | null>(null) const props = { openModal, setOpenModal }; - + const getAllInvitations = async () => { + const roles = await getFromLocalStorage(storageKeys.ORG_ROLES) + setRoles(roles?.split(',')) setLoading(true) const response = await getOrganizationInvitations(currentPage.pageNumber, currentPage.pageSize, searchText); const { data } = response as AxiosResponse @@ -242,7 +245,8 @@ const Invitations = () => { }} color="bg-white" className="ml-5 p-0 font-normal items-center mt-5 text-sm text-primary-700 border border-blue-700 text-center hover:!bg-primary-800 hover:text-white rounded-lg focus:ring-4 focus:ring-primary-300 sm:w-auto dark:hover:bg-primary-700 dark:text-white dark:bg-primary-700 dark:focus:ring-blue-800" - > + disabled={!roles?.includes(Roles.ADMIN) && !roles?.includes(Roles.OWNER)} + >
    {formikHandlers?.errors?.newPassword && typeof formikHandlers?.errors?.newPassword === 'string' && - formikHandlers?.errors?.newPassword && formikHandlers?.touched?.newPassword && ( - + {formikHandlers?.errors?.newPassword} )} From 6b51f50001d2f942f2413e4edfa0a2a740a9ac7c Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 7 Feb 2024 15:00:13 +0530 Subject: [PATCH 122/303] fix: loading handled Signed-off-by: karan --- .../Resources/Schema/ViewSchema.tsx | 1114 +++++++++-------- 1 file changed, 623 insertions(+), 491 deletions(-) diff --git a/src/components/Resources/Schema/ViewSchema.tsx b/src/components/Resources/Schema/ViewSchema.tsx index f5da0a2bf..dcd543098 100644 --- a/src/components/Resources/Schema/ViewSchema.tsx +++ b/src/components/Resources/Schema/ViewSchema.tsx @@ -1,12 +1,23 @@ import * as yup from 'yup'; -import { Alert, Button, Card, Label, Pagination, Spinner } from 'flowbite-react'; +import { + Alert, + Button, + Card, + Label, + Pagination, + Spinner, +} from 'flowbite-react'; import { Field, Form, Formik } from 'formik'; import { apiStatusCodes, storageKeys } from '../../../config/CommonConstant'; -import { createCredentialDefinition, getCredDeffById, getSchemaById } from '../../../api/Schema'; +import { + createCredentialDefinition, + getCredDeffById, + getSchemaById, +} from '../../../api/Schema'; import { getFromLocalStorage, setToLocalStorage } from '../../../api/Auth'; import { useEffect, useState } from 'react'; -import BackButton from '../../../commonComponents/backbutton' +import BackButton from '../../../commonComponents/backbutton'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../../BreadCrumbs'; import CredDeffCard from '../../../commonComponents/CredentialDefinitionCard'; @@ -16,508 +27,629 @@ import { EmptyListMessage } from '../../EmptyListComponent'; import { Roles } from '../../../utils/enums/roles'; import { nanoid } from 'nanoid'; import { pathRoutes } from '../../../config/pathRoutes'; -import { ICheckEcosystem, checkEcosystem, getEcosystemId } from '../../../config/ecosystem'; +import { + ICheckEcosystem, + checkEcosystem, + getEcosystemId, +} from '../../../config/ecosystem'; import { createCredDefRequest } from '../../../api/ecosystem'; import EcosystemProfileCard from '../../../commonComponents/EcosystemProfileCard'; import { getLedgersPlatformUrl } from '../../../api/Agent'; +import React from 'react'; interface Values { - tagName: string; - revocable: boolean; + tagName: string; + revocable: boolean; } type SchemaData = { - schema: { - attrNames: string[]; - name: string; - version: string; - issuerId: string; - }; - schemaId: string; - resolutionMetadata: Record; - schemaMetadata: { - didIndyNamespace: string; - indyLedgerSeqNo: number; - }; + schema: { + attrNames: string[]; + name: string; + version: string; + issuerId: string; + }; + schemaId: string; + resolutionMetadata: Record; + schemaMetadata: { + didIndyNamespace: string; + indyLedgerSeqNo: number; + }; }; interface ICredDefCard { - tag: string, - credentialDefinitionId: string - schemaLedgerId: string - revocable: boolean + tag: string; + credentialDefinitionId: string; + schemaLedgerId: string; + revocable: boolean; } - - +const initialPageState = { + pageNumber: 1, + pageSize: 9, + total: 0, +}; const ViewSchemas = () => { - const [schemaDetails, setSchemaDetails] = useState(null); - const [credDeffList, setCredDeffList] = useState([]); - const [loading, setLoading] = useState(true) - const [createloader, setCreateLoader] = useState(false) - const [credDeffloader, setCredDeffloader] = useState(false) - const [success, setSuccess] = useState(null) - const [credDefListErr, setCredDefListErr] = useState(null) - const [schemaDetailErr, setSchemaDetailErr] = useState(null) - const [failure, setFailure] = useState(null) - const [orgId, setOrgId] = useState('') - const [credDefAuto, setCredDefAuto] = useState('') - const [isEcosystemData, setIsEcosystemData] = useState(); - const [ledgerPlatformLoading, setLedgerPlatformLoading] = useState(false) - - - const [userRoles, setUserRoles] = useState([]) - - - const getSchemaDetails = async (SchemaId: string, organizationId: string) => { - try { - setLoading(true); - const SchemaDetails = await getSchemaById(SchemaId, organizationId); - const { data } = SchemaDetails as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setSchemaDetails(data?.data); - setCredDefAuto(`${data?.data?.response?.schema?.name} ${nanoid(8)}`); - setLoading(false); - } else { - setLoading(false); - setSchemaDetailErr(SchemaDetails as unknown as string) - } - } catch (error) { - setSchemaDetailErr('Error while fetching schema details') - console.error('Error while fetching schema details:', error); - setLoading(false); - } - }; - - const getCredentialDefinitionList = async (id: string, orgId: string) => { - try { - setCredDeffloader(true); - const credentialDefinitions = await getCredDeffById(id, orgId); - const { data } = credentialDefinitions as AxiosResponse - if (data?.data?.data.length === 0) { - setCredDefListErr('No Data Found'); - } - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setCredDeffList(data?.data?.data); - setCredDeffloader(false); - } else { - setCredDefListErr(credentialDefinitions as string) - setCredDeffloader(false) - } - } catch (error) { - console.error('Error while fetching credential definition list:', error); - setCredDeffloader(false); - } - }; - - - useEffect(() => { - const fetchData = async () => { - const organizationId = await getFromLocalStorage(storageKeys.ORG_ID); - setOrgId(String(organizationId)); - if (window?.location?.search) { - const str = window?.location?.search; - const schemaId = str.substring(str.indexOf('=') + 1); - await getSchemaDetails(schemaId, String(organizationId)); - await getCredentialDefinitionList(schemaId, String(organizationId)); - } - }; - - fetchData(); - }, []); - - const getUserRoles = async () => { - const orgRoles = await getFromLocalStorage(storageKeys.ORG_ROLES) - const roles = orgRoles.split(',') - setUserRoles(roles) - } - - useEffect(() => { - getUserRoles() - const checkEcosystemData = async () => { - const data: ICheckEcosystem = await checkEcosystem(); - setIsEcosystemData(data) - } - - checkEcosystemData(); - }, []) - - - const submit = async (values: Values) => { - if (isEcosystemData?.isEnabledEcosystem && isEcosystemData?.isEcosystemMember) { - console.log("Submitted for endorsement by ecosystem member") - setCreateLoader(true) - const schemaId = schemaDetails?.schemaId || "" - const requestPayload = { - endorse: true, - tag: values?.tagName, - schemaId, - schemaDetails: { - name: schemaDetails?.schema?.name, - version: schemaDetails?.schema?.version, - attributes: schemaDetails?.schema?.attrNames - } - } - - const ecoId = await getEcosystemId() - - const createCredDeff = await createCredDefRequest(requestPayload, ecoId, orgId); - const { data } = createCredDeff as AxiosResponse - if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { - setCreateLoader(false) - setSuccess(data?.message) - } - else { - setFailure(createCredDeff as string) - setCreateLoader(false) - } - getCredentialDefinitionList(schemaId, orgId) - } else { - setCreateLoader(true) - const schemaId = schemaDetails?.schemaId || "" - const CredDeffFieldName: CredDeffFieldNameType = { - tag: values?.tagName, - revocable: values?.revocable, - orgId: orgId, - schemaLedgerId: schemaId - } - - const createCredDeff = await createCredentialDefinition(CredDeffFieldName, orgId); - const { data } = createCredDeff as AxiosResponse - if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { - setCreateLoader(false) - setSuccess(data?.message) - } - else { - setFailure(createCredDeff as string) - setCreateLoader(false) - } - getCredentialDefinitionList(schemaId, orgId) - } - } - - const credDefSelectionCallback = async () => { - window.location.href = `${pathRoutes.organizations.Issuance.issue}` - } - - const fetchLedgerPlatformUrl = async (indyNamespace: string) => { - setLedgerPlatformLoading(true) - try { - const response = await getLedgersPlatformUrl(indyNamespace) - const { data } = response as AxiosResponse - setLedgerPlatformLoading(false) - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - if (data.data.networkUrl) { - window.open(data.data.networkUrl) - } - } - } catch (err) { - setLedgerPlatformLoading(false) - } - } - - const formTitle = isEcosystemData?.isEcosystemMember ? "Credential Definition Endorsement" : "Create Credential Definition" - const submitButtonTitle = isEcosystemData?.isEcosystemMember ? { - title: "Request Endorsement", svg: - - - } : { - title: "Create", svg:
    - - - -
    - } - - return ( -
    -
    - - - { - isEcosystemData?.isEnabledEcosystem && -
    - -
    - } - -
    -

    - Schemas -

    - -
    -
    - -
    -
    - - {loading ? ( -
    - -
    - ) : ( -
    -
    -
    - Schema Details -
    -
    - - {/* */} -
    -
    -
    -
    -

    - Name: {schemaDetails?.schema?.name} -

    -
    -
    -

    - Version: {schemaDetails?.schema?.version} -

    -
    -

    - Schema ID: {schemaDetails?.schemaId} -

    -

    - Issuer DID: {schemaDetails?.schema?.issuerId} -

    -
    -
    -
      -
    • -
      -
      - Attributes: - {schemaDetails?.schema?.attrNames && schemaDetails?.schema?.attrNames?.length > 0 && - schemaDetails?.schema?.attrNames.map((element: string) => ( - {element} - ))} -
      -
      -
    • -
    -
    -
    - )} -
    - { - (userRoles.includes(Roles.OWNER) - || userRoles.includes(Roles.ADMIN)) - - && -
    -
    - {formTitle} -
    -
    -
    - => { - await submit(values) - formikHandlers.resetForm(); - - }} - > - {(formikHandlers): JSX.Element => ( - -
    -
    -
    -
    - - { - (formikHandlers?.errors?.tagName && formikHandlers?.touched?.tagName) && - {formikHandlers?.errors?.tagName} - } -
    -
    - -
    - {/*
    */} - {/* */} - {/*
    +
    +
    +
    +

    + Name: {' '} + {schemaDetails?.schema?.name} +

    +
    +
    +

    + Version: + {schemaDetails?.schema?.version} +

    +
    +

    + Schema ID: + {schemaDetails?.schemaId} +

    +

    + Issuer DID: + {schemaDetails?.schema?.issuerId} +

    +
    +
    +
      +
    • +
      +
      + Attributes: + {schemaDetails?.schema?.attrNames && + schemaDetails?.schema?.attrNames?.length > 0 && + schemaDetails?.schema?.attrNames.map( + (element: string) => ( + + {' '} + {element} + + ), + )} +
      +
      +
    • +
    +
    +
    + )} +
    + {(userRoles.includes(Roles.OWNER) || + userRoles.includes(Roles.ADMIN)) && ( + +
    +
    + {formTitle} +
    +
    +
    + => { + await submit(values); + formikHandlers.resetForm(); + }} + > + {(formikHandlers): JSX.Element => ( + +
    +
    +
    +
    + + {formikHandlers?.errors?.tagName && + formikHandlers?.touched?.tagName && ( + + {formikHandlers?.errors?.tagName} + + )} +
    +
    + +
    + {/*
    */} + {/* */} + {/* */} - {/*
    */} - {createloader &&
    -

    - - - - - Hold your coffee, this might take a moment... -

    -
    } -
    - { - (success || failure) && -
    - { - setSuccess(null) - setFailure(null) - }} - > - -

    - {success || failure} -

    -
    -
    -
    - } -
    -
    - -
    -
    - -
    -
    - - )} -
    -
    -
    - } -
    -
    -
    - {schemaDetailErr && ( - setSchemaDetailErr(null)}> - -

    - {schemaDetailErr} -

    -
    -
    - )} -
    -
    - Credential Definitions -
    - - {loading ? (
    - -
    ) - : credDeffList && credDeffList.length > 0 ? ( -
    -
    - {credDeffList && credDeffList.length > 0 && - credDeffList.map((element: ICredDefCard, index: number) => ( -
    - -
    - )) - } -
    -
    - { - }} - totalPages={0} - /> -
    -
    ) : ( - - } - onClick={() => { }} - />) - } -
    - ) -} -export default ViewSchemas + {/*
    */} + {createloader && ( +
    +

    + + + + + Hold your coffee, this might take a moment... +

    +
    + )} +
    + {(success || failure) && ( +
    + { + setSuccess(null); + setFailure(null); + }} + > + +

    {success || failure}

    +
    +
    +
    + )} +
    +
    + +
    +
    + +
    +
    + + )} + +
    + + )} +
    +
    +
    + {schemaDetailErr && ( + setSchemaDetailErr(null)}> + +

    {schemaDetailErr}

    +
    +
    + )} +
    +
    + Credential Definitions +
    + + {loading ? ( +
    + +
    + ) : credDeffList && credDeffList.length > 0 ? ( +
    +
    + {credDeffList && + credDeffList.length > 0 && + credDeffList.map((element: ICredDefCard, index: number) => ( +
    + +
    + ))} +
    + {currentPage.total > 1 && ( +
    + +
    + )} +
    + ) : ( + + + + } + onClick={() => {}} + /> + )} +
    + ); +}; +export default ViewSchemas; From fd3df5b17b708a8016c42cef4648c44f868e0c8e Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 7 Feb 2024 15:57:08 +0530 Subject: [PATCH 123/303] spell changes Signed-off-by: karan --- src/components/Setting/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Setting/index.tsx b/src/components/Setting/index.tsx index 75acdcafb..80057a292 100644 --- a/src/components/Setting/index.tsx +++ b/src/components/Setting/index.tsx @@ -168,7 +168,7 @@ const Index = () => {

    - Client Secrate + Client Secret

    You need a client secret to authenticate as the @@ -189,7 +189,7 @@ const Index = () => { : 'bg-primary-700 hover:!bg-primary-800 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800' }`} > - Generate Client Secrate{' '} + Generate Client Secret{' '}
    )} From 5fee5a9d841658eaef43c7367b9d2d38b0b673fc Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 7 Feb 2024 18:59:33 +0530 Subject: [PATCH 124/303] feat: forgot password Signed-off-by: karan --- src/api/Auth.ts | 30 + .../Authentication/ResetPassword.tsx | 598 +++++++++--------- .../Authentication/SignInUserPassword.tsx | 37 +- src/config/apiRoutes.ts | 4 +- 4 files changed, 349 insertions(+), 320 deletions(-) diff --git a/src/api/Auth.ts b/src/api/Auth.ts index 7a18cd159..bbb9087ca 100644 --- a/src/api/Auth.ts +++ b/src/api/Auth.ts @@ -48,6 +48,36 @@ export const sendVerificationMail = async(payload:UserSignUpData) => { } } +export const resetPassword = async(payload: { password: string; token: string | null }, email: string | null) => { + const details = { + url: `${apiRoutes.auth.resetPassword}/${email}`, + payload + } + try{ + const response = await axiosPost(details) + return response + } + catch(error){ + const err = error as Error + return err?.message + } +} + +export const forgotPassword = async(payload: {email: string}) => { + const details = { + url: apiRoutes.auth.forgotPassword, + payload + } + try{ + const response = await axiosPost(details) + return response + } + catch(error){ + const err = error as Error + return err?.message + } +} + export const loginUser = async(payload: UserSignInData) => { const details = { url: apiRoutes.auth.sinIn, diff --git a/src/components/Authentication/ResetPassword.tsx b/src/components/Authentication/ResetPassword.tsx index d3e4fc7c6..fea40959a 100644 --- a/src/components/Authentication/ResetPassword.tsx +++ b/src/components/Authentication/ResetPassword.tsx @@ -1,9 +1,11 @@ import 'react-toastify/dist/ReactToastify.css'; - import * as yup from 'yup'; - -import { Alert, Button, Label } from 'flowbite-react';; -import { apiStatusCodes, passwordRegex, storageKeys } from '../../config/CommonConstant.js'; +import { Alert, Button, Label } from 'flowbite-react'; +import { + apiStatusCodes, + passwordRegex, + storageKeys, +} from '../../config/CommonConstant.js'; import { useEffect, useState } from 'react'; import { Field, Form, Formik } from 'formik'; import { getSupabaseClient } from '../../supabase'; @@ -11,306 +13,304 @@ import { pathRoutes } from '../../config/pathRoutes.js'; import PasswordSuggestionBox from './PasswordSuggestionBox.js'; import FooterBar from './FooterBar.js'; import NavBar from './NavBar.js'; -import { addPasskeyUserDetails, passwordEncryption, setToLocalStorage } from '../../api/Auth.js'; +import { + passwordEncryption, + resetPassword, + setToLocalStorage, +} from '../../api/Auth.js'; import type { AxiosResponse } from 'axios'; -import { PassInvisible, PassVisible, SignUpArrow } from './Svg.js'; -import React from 'react'; - +import { PassInvisible, PassVisible } from './Svg.js'; interface passwordValues { - password: string; - confirmPassword: string; + password: string; + confirmPassword: string; } const ResetPassword = () => { - - const [loading, setLoading] = useState(false) - const [erroMsg, setErrMsg] = useState(null) - const [message, setMessage] = useState('') - const [passwordVisible, setPasswordVisible] = useState(false); - const [confirmPasswordVisible, setConfirmPasswordVisible] = useState(false); - const [userToken, setUserToken] = useState(''); - const [showSuggestion, setShowSuggestion] = useState(false); - - useEffect(() => { - const setAccessToken = async () => { - const hashPart = window.location.href.split("#")[1]; - const paramsArray = hashPart.split("&"); - let accessToken; - for (const param of paramsArray) { - const [key, value] = param.split("="); - if (key === "access_token") { - accessToken = value; - break; - } - } - if (accessToken) { - setUserToken(accessToken); - } else { - setErrMsg('An error occurred while updating password in supabase.'); - } - - }; - setAccessToken(); - }, []); - - const submit = async (passwordDetails: passwordValues) => { - try { - await setToLocalStorage(storageKeys.TOKEN, userToken); - setLoading(true); - - const { data, error } = await getSupabaseClient().auth.updateUser({ password: passwordDetails?.password }); - - if (data?.user?.email) { - await updatePasswordDetails(passwordEncryption(passwordDetails?.password), data.user.email); - } - - if (!error) { - setLoading(false); - window.location.href = `${pathRoutes.auth.sinIn}?isPasswordSet=true` - } else { - setLoading(false); - setErrMsg(error.message); - } - } catch (error) { - console.error('An error occurred:', error); - setErrMsg('An error occurred while updating password in supabase.'); - } - }; - - - const updatePasswordDetails = async (password: string, email: string) => { - try { - const payload = { - password: password - } - const passkeyUserDetailsResp = await addPasskeyUserDetails(payload, email); - const { data } = passkeyUserDetailsResp as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setLoading(false); - } else { - setErrMsg(passkeyUserDetailsResp as string); - } - } catch (error) { - console.error('An error occurred:', error); - setErrMsg('An error occurred while updating password details.'); - } - }; - - - return ( -
    -
    - - -
    -
    -
    - img -
    -
    -
    -
    - { - (message || erroMsg) && - setErrMsg(null)} - > - -

    - {message || erroMsg} -

    -
    -
    - } - -
    -
    - Reset Password -
    -
    - Please set new password -
    - -
    - -
    - - img -
    - - - { - submit(values) - }} - - > - {(formikHandlers): JSX.Element => ( - -
    - -
    -
    -
    -
    -
    - { - setShowSuggestion(true); - }} - onBlurCapture={(e: any): void => { - setShowSuggestion(false); - formikHandlers.handleBlur(e); - }} - /> - -
    - {showSuggestion && - formikHandlers?.errors?.password && - formikHandlers.values.password && ( - - )} - - { - (formikHandlers?.errors?.password && formikHandlers?.touched?.password) && - {formikHandlers?.errors?.password} - } -
    -
    -
    -
    -
    - { - formikHandlers.handleBlur(e); - }} - /> - - - -
    - { - (formikHandlers?.errors?.confirmPassword && formikHandlers?.touched?.confirmPassword) && - {formikHandlers?.errors?.confirmPassword} - } -
    - -
    - - - -
    -
    - -
    - - )} -
    - -
    - -
    -
    -
    - -
    - ); + const [loading, setLoading] = useState(false); + const [erroMsg, setErrMsg] = useState(null); + const [message, setMessage] = useState(''); + const [passwordVisible, setPasswordVisible] = useState(false); + const [confirmPasswordVisible, setConfirmPasswordVisible] = useState(false); + const [userToken, setUserToken] = useState(''); + const [showSuggestion, setShowSuggestion] = useState(false); + + useEffect(() => { + const setAccessToken = async () => { + const hashPart = window.location.href.split('#')[1]; + const paramsArray = hashPart.split('&'); + let accessToken; + for (const param of paramsArray) { + const [key, value] = param.split('='); + if (key === 'access_token') { + accessToken = value; + break; + } + } + if (accessToken) { + setUserToken(accessToken); + } else { + setErrMsg('An error occurred while updating password in supabase.'); + } + }; + setAccessToken(); + }, []); + + const submit = async (passwordDetails: passwordValues) => { + try { + setLoading(true); + await setToLocalStorage(storageKeys.TOKEN, userToken); + const url = window.location.href; + const params = new URLSearchParams(new URL(url).search); + const verificationCode = params.get('verificationCode'); + const email = params.get('email'); + const payload = { + password: passwordEncryption(passwordDetails?.password), + token: verificationCode, + }; + + const response = await resetPassword(payload, email); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setMessage(data.message); + setLoading(false); + window.location.href=pathRoutes.auth.sinIn + } else { + setErrMsg(response as string); + setLoading(false); + } + } catch (error) { + console.error('An error occurred:', error); + setErrMsg('An error occurred while updating password.'); + } finally { + setLoading(false); + } + }; + + return ( +
    +
    + +
    +
    +
    + img +
    +
    +
    +
    + {(message || erroMsg) && ( + setErrMsg(null)} + > + +

    {message || erroMsg}

    +
    +
    + )} + +
    +
    + Reset Password +
    +
    + Please set new password +
    +
    + +
    + img +
    + + { + console.log('values', values); + + submit(values); + }} + > + {(formikHandlers): JSX.Element => ( +
    +
    +
    +
    +
    +
    + { + setShowSuggestion(true); + }} + onBlurCapture={(e: any): void => { + setShowSuggestion(false); + formikHandlers.handleBlur(e); + }} + /> + +
    + {showSuggestion && + formikHandlers?.errors?.password && + formikHandlers.values.password && ( + + )} + + {formikHandlers?.errors?.password && + formikHandlers?.touched?.password && ( + + {formikHandlers?.errors?.password} + + )} +
    +
    +
    +
    +
    + { + formikHandlers.handleBlur(e); + }} + /> + + +
    + {formikHandlers?.errors?.confirmPassword && + formikHandlers?.touched?.confirmPassword && ( + + {formikHandlers?.errors?.confirmPassword} + + )} +
    + +
    + +
    +
    +
    + )} +
    +
    +
    +
    +
    + +
    + ); }; export default ResetPassword; diff --git a/src/components/Authentication/SignInUserPassword.tsx b/src/components/Authentication/SignInUserPassword.tsx index 865292258..fe5e0d563 100644 --- a/src/components/Authentication/SignInUserPassword.tsx +++ b/src/components/Authentication/SignInUserPassword.tsx @@ -1,22 +1,19 @@ import '../../common/global.css'; - import * as yup from 'yup'; - import { Button, Label } from 'flowbite-react'; import { Field, Form, Formik } from 'formik'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { + forgotPassword, getUserProfile, loginUser, passwordEncryption, setToLocalStorage, } from '../../api/Auth'; - import { Alert } from 'flowbite-react'; import type { AxiosResponse } from 'axios'; import CustomSpinner from '../CustomSpinner'; import SignInUserPasskey from './SignInUserPasskey'; -import { getSupabaseClient } from '../../supabase'; import NavBar from './NavBar'; import FooterBar from './FooterBar'; import React, { useState } from 'react'; @@ -62,12 +59,11 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => { await setToLocalStorage(storageKeys.USER_PROFILE, data?.data); await setToLocalStorage(storageKeys.USER_EMAIL, data?.data?.email); return { - role: role?.orgRole || '', + role: role?.orgRole ?? '', }; } else { setFailure(userDetails as string); } - setLoading(false); }; @@ -125,21 +121,22 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => { setShowSignInUser2(!showSignInUser2); }; - const forgotPassword = async () => { + const forgotUserPassword = async () => { setForgotPassLoading(true); + try { + const response = await forgotPassword({email}); + const { data } = response as AxiosResponse; - var base_url = window.location.origin; - - const { data, error } = - await getSupabaseClient().auth.resetPasswordForEmail(email, { - redirectTo: `${base_url}/reset-password`, - }); - setForgotPassLoading(false); - - if (!error) { - setSuccess('Reset password link has been sent to you on mail'); - } else { - setFailure('Unable to send reset link for the password'); + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setSuccess(data.message); + setForgotPassLoading(false); + } else { + setFailure(response as string); + setForgotPassLoading(false); + } + } catch (error) { + console.error('An error occurred:', error); + setForgotPassLoading(false); } }; @@ -320,7 +317,7 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => { ) : (
    )} From c0f0eaa6a3d16b81834084378e2ecfeefee643ee Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 8 Feb 2024 19:22:37 +0530 Subject: [PATCH 126/303] fix: issues from live tracker Signed-off-by: karan --- src/components/Ecosystem/Dashboard.tsx | 2 +- .../EcoSystemReceivedInvitations.tsx | 6 +- src/components/Issuance/Issuance.tsx | 69 +++++-------------- src/components/Issuance/interface.ts | 36 ++++++++++ src/components/Profile/DisplayUserProfile.tsx | 1 - .../Resources/Schema/SchemasList.tsx | 7 +- .../Resources/Schema/ViewSchema.tsx | 10 +-- src/components/RoleViewButton/index.tsx | 10 +-- src/components/Verification/Verification.tsx | 66 +++--------------- .../VerificationCredentialList.tsx | 5 -- src/components/Verification/interface.ts | 22 ++++++ 11 files changed, 102 insertions(+), 132 deletions(-) diff --git a/src/components/Ecosystem/Dashboard.tsx b/src/components/Ecosystem/Dashboard.tsx index 58a1346b9..dbee02e5b 100644 --- a/src/components/Ecosystem/Dashboard.tsx +++ b/src/components/Ecosystem/Dashboard.tsx @@ -302,7 +302,7 @@ const Dashboard = () => { )}
    -
    +

    {ecosystemDetails?.name}

    diff --git a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx index febf1665b..2bbf0732b 100644 --- a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx +++ b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx @@ -111,7 +111,6 @@ const ReceivedInvitations = () => { '', ); const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const totalPages = data?.data?.totalPages; @@ -147,8 +146,8 @@ const ReceivedInvitations = () => { status, ); setLoading(false); - const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + const { data } = response as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setMessage(data?.message); getAllInvitations(); } else { @@ -158,6 +157,7 @@ const ReceivedInvitations = () => { setLoading(false); } catch (err) { console.log('ERROR - Accept/Reject Ecosystem::', err); + setLoading(false); } }; diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index 256ae3e68..7ab630ccb 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -5,7 +5,7 @@ import * as Yup from 'yup'; import { Alert, Button, Card } from 'flowbite-react'; import { ErrorMessage, Field, Form, Formik } from 'formik'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; -import { getFromLocalStorage, removeFromLocalStorage } from '../../api/Auth'; +import { getFromLocalStorage } from '../../api/Auth'; import { useEffect, useState } from 'react'; import BackButton from '../../commonComponents/backbutton' import type { AxiosResponse } from 'axios'; @@ -13,42 +13,8 @@ import BreadCrumbs from '../BreadCrumbs'; import CustomSpinner from '../CustomSpinner'; import { issueCredential } from '../../api/issuance'; import { pathRoutes } from '../../config/pathRoutes'; - -interface SchemaDetails { - schemaName: string; - version: string; - schemaId: string; - credDefId: string; -} - -interface SelectedUsers { - userName: string; - connectionId: string; -} - -interface Attributes { - name: string; - value: string; - dataType: string; -} -interface IssuanceFormPayload { - userName?: string; - connectionId: string; - attributes: Attributes[]; - credentialDefinitionId: string; - orgId: string; -} - -interface DataTypeAttributes { - schemaDataType: string; - attributeName:string -} - -interface Attribute { - attributeName: string; - schemaDataType: string; - displayName: string; -} +import { AlertComponent } from '../AlertComponent'; +import type {Attribute, DataTypeAttributes, IssuanceFormPayload, SchemaDetails, SelectedUsers} from './interface' const IssueCred = () => { const [schemaLoader, setSchemaLoader] = useState(true); @@ -65,10 +31,13 @@ const IssueCred = () => { const [issuanceLoader, setIssuanceLoader] = useState(false); const [failure, setFailure] = useState(null); const [schemaAttributesDetails, setSchemaAttributesDetails] = useState([]); + const [success, setSuccess]= useState(null) + const [error, setError]= useState(null) useEffect(() => { getSchemaAndUsers(); getSchemaDetails(); + return(() => setUserLoader(false)) }, []); const getSchemaAndUsers = async () => { @@ -170,22 +139,16 @@ const IssueCred = () => { setIssuanceLoader(true); const issueCredRes = await issueCredential(convertedAttributesValues); const { data } = issueCredRes as AxiosResponse; - setIssuanceLoader(false); - + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { - goToIssueCredList(); + setSuccess(data?.message) + window.location.href = `${pathRoutes.organizations.issuedCredentials}`; } else { setFailure(issueCredRes as string); + setIssuanceLoader(false); } }; - const goToIssueCredList = () => { - removeFromLocalStorage(storageKeys.SELECTED_USER); - removeFromLocalStorage(storageKeys.SCHEMA_ID); - removeFromLocalStorage(storageKeys.CRED_DEF_ID); - window.location.href = `${pathRoutes.organizations.issuedCredentials}`; - }; - return (
    @@ -193,6 +156,14 @@ const IssueCred = () => {
    + { + setError(null); + setSuccess(null); + }} + />

    Issuance

    @@ -260,10 +231,6 @@ const IssueCred = () => {
    {user.userName}
    - {/* Needed for multiple users issuance */} - {/*
    - -
    */}
    diff --git a/src/components/Issuance/interface.ts b/src/components/Issuance/interface.ts index 10281ea98..314bbbdce 100644 --- a/src/components/Issuance/interface.ts +++ b/src/components/Issuance/interface.ts @@ -58,3 +58,39 @@ export interface IConnectionList { connectionId: string; createDateTime: string; } + +export interface SchemaDetails { + schemaName: string; + version: string; + schemaId: string; + credDefId: string; +} + +export interface SelectedUsers { + userName: string; + connectionId: string; +} + +export interface Attributes { + name: string; + value: string; + dataType: string; +} +export interface IssuanceFormPayload { + userName?: string; + connectionId: string; + attributes: Attributes[]; + credentialDefinitionId: string; + orgId: string; +} + +export interface DataTypeAttributes { + schemaDataType: string; + attributeName:string +} + +export interface Attribute { + attributeName: string; + schemaDataType: string; + displayName: string; +} diff --git a/src/components/Profile/DisplayUserProfile.tsx b/src/components/Profile/DisplayUserProfile.tsx index eb806442d..2ea1c7957 100644 --- a/src/components/Profile/DisplayUserProfile.tsx +++ b/src/components/Profile/DisplayUserProfile.tsx @@ -23,7 +23,6 @@ const DisplayUserProfile = ({
    ), + tooltip: 'Create new credential-definition' }; return ( @@ -472,12 +474,6 @@ const ViewSchemas = () => {
    - {/*
    */} - {/* */} - {/* */} - {/*
    */} {createloader && (

    @@ -525,7 +521,7 @@ const ViewSchemas = () => {

    diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index c397f8a1e..0d4f36c13 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -3,7 +3,7 @@ import type { AxiosResponse } from "axios"; import { Alert, Button, Card } from "flowbite-react"; import { useEffect, useState } from "react"; -import { getFromLocalStorage, removeFromLocalStorage } from "../../api/Auth"; +import { getFromLocalStorage } from "../../api/Auth"; import { apiStatusCodes, storageKeys } from "../../config/CommonConstant"; import BreadCrumbs from "../BreadCrumbs"; import DataTable from "../../commonComponents/datatable"; @@ -12,49 +12,26 @@ import { verifyCredential } from "../../api/verification"; import { pathRoutes } from "../../config/pathRoutes"; import CustomSpinner from "../CustomSpinner"; import BackButton from '../../commonComponents/backbutton' - -interface SchemaDetails { - schemaName: string, - version: string, - schemaId: string, - credDefId: string -} - -interface SelectedUsers { - userName: string, - connectionId: string -} - -interface VerifyCredentialPayload { - connectionId: string; - attributes: Array<{ - attributeName: string; - credDefId?: string ; - }>; - comment: string; - orgId: string; -} +import type { SchemaDetail, SelectedUsers, VerifyCredentialPayload } from "./interface"; const VerificationCred = () => { const [attributeList, setAttributeList] = useState([]) const [proofReqSuccess, setProofReqSuccess] = useState('') const [errMsg, setErrMsg] = useState(null) - const [schemaLoader, setSchemaLoader] = useState(false) - const [schemaDetails, setSchemaDetails] = useState({ + const [schemaDetails, setSchemaDetails] = useState({ schemaName: '', version: '', schemaId: '', credDefId: '' }) const [loading, setLoading] = useState(true) - const [schemaAttributes, setSchemaAttributes] = useState([]); const [selectedUsersData, setSelectedUsersData] = useState>([]); const [requestLoader, setRequestLoader] = useState(false) useEffect(() => { - const fetchData = async () => { + const fetchData = async () => { try { setLoading(true) await getSchemaAndUsers(); - const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR) + const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR) const parsedSchemaDetails = JSON.parse(schemaAttributes) || []; const attributes = parsedSchemaDetails.attribute.map((ele: any) => { const attributesName = ele.attributeName ? ele.attributeName : 'Not available'; @@ -91,6 +68,8 @@ const VerificationCred = () => { }; fetchData(); + return (()=>{ setRequestLoader(false); + }) }, []); @@ -109,10 +88,6 @@ const VerificationCred = () => { const getSchemaAndUsers = async () => { - const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR) - const parsedSchemaAttributes = JSON.parse(schemaAttributes) || []; - - setSchemaAttributes(parsedSchemaAttributes); const credDefId = await getFromLocalStorage(storageKeys.CRED_DEF_ID) const schemaId = await getFromLocalStorage(storageKeys.SCHEMA_ID) createSchemaPayload(schemaId, credDefId) @@ -122,12 +97,10 @@ const VerificationCred = () => { const createSchemaPayload = async (schemaId: string, credDefId: string) => { if (schemaId) { - setSchemaLoader(true) const parts = schemaId.split(":"); const schemaName = parts[2]; const version = parts[3]; setSchemaDetails({ schemaName, version, schemaId, credDefId }) - setSchemaLoader(false) } } @@ -136,14 +109,6 @@ const VerificationCred = () => { return JSON.parse(selectedUsers) } - const clearLocalStorage = () => { - removeFromLocalStorage(storageKeys.SELECTED_USER) - removeFromLocalStorage(storageKeys.SCHEMA_ID) - removeFromLocalStorage(storageKeys.CRED_DEF_ID) - - } - - const verifyCredentialSubmit = async () => { try { setRequestLoader(true); @@ -168,34 +133,23 @@ const VerificationCred = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { setProofReqSuccess(data?.message); - setRequestLoader(false); - clearLocalStorage() - setTimeout(()=>{ - window.location.href = '/organizations/verification' - }, 2000) + window.location.href = pathRoutes.organizations.credentials } else { setErrMsg(response as string); + setRequestLoader(false); } } - setTimeout(()=>{ - setErrMsg(''); - setProofReqSuccess('') - - }, 4000) } catch (error) { - console.error("Error:", error); setErrMsg("An error occurred. Please try again."); setRequestLoader(false); } }; - const header = [ { columnName: '', width: 'w-0.5' }, { columnName: 'Attributes' } ] - return ( <>
    @@ -263,7 +217,7 @@ const VerificationCred = () => {
    - ) : ( - <>
    @@ -459,7 +456,6 @@ const Dashboard = () => {
    - )}
    diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index 0d4f36c13..d1f2b033a 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -2,7 +2,7 @@ import type { AxiosResponse } from "axios"; import { Alert, Button, Card } from "flowbite-react"; -import { useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import { getFromLocalStorage } from "../../api/Auth"; import { apiStatusCodes, storageKeys } from "../../config/CommonConstant"; import BreadCrumbs from "../BreadCrumbs"; @@ -217,7 +217,7 @@ const VerificationCred = () => { From f65328eccc59b5f042e8cb5f1c38bd4869761f5c Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 9 Feb 2024 22:20:53 +0530 Subject: [PATCH 134/303] fix: check user session Signed-off-by: karan --- src/commonComponents/PasseyAddDevicePopup.tsx | 6 +++- src/services/axiosIntercepter.ts | 12 +------ src/utils/check-session.ts | 36 ++++++++++++++++++- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/commonComponents/PasseyAddDevicePopup.tsx b/src/commonComponents/PasseyAddDevicePopup.tsx index b5312a9fb..01c1ae0e3 100644 --- a/src/commonComponents/PasseyAddDevicePopup.tsx +++ b/src/commonComponents/PasseyAddDevicePopup.tsx @@ -38,7 +38,11 @@ const PasskeyAddDevice = (props: { if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setNextFlag(true) } else { - setFidoUserError(passkeyUserDetailsResp as string) + if (passkeyUserDetailsResp.toString().includes('401')) { + setFidoUserError('Invalid Credntials'); + } else { + setFidoUserError(passkeyUserDetailsResp as string); + } } } catch (error) { console.error('An unexpected error occurred:', error.message); diff --git a/src/services/axiosIntercepter.ts b/src/services/axiosIntercepter.ts index 084b23c6d..ec22f16c2 100644 --- a/src/services/axiosIntercepter.ts +++ b/src/services/axiosIntercepter.ts @@ -1,8 +1,5 @@ import axios from 'axios' import { envConfig } from '../config/envConfig'; -import { pathRoutes } from '../config/pathRoutes'; -import { getFromLocalStorage } from '../api/Auth'; -import { storageKeys } from '../config/CommonConstant'; const instance = axios.create({ baseURL: envConfig.PUBLIC_BASE_URL @@ -21,14 +18,7 @@ instance.interceptors.response.use(function (response) { return response; }, async function (error) { // Any status codes that falls outside the range of 2xx cause this function to trigger - // Do something with response error - const errorRes = error?.response; - const token = await getFromLocalStorage(storageKeys.TOKEN) - if(errorRes?.status === 401 && token){ - await localStorage.clear() - window.location.href = pathRoutes.auth.sinIn - } - + // Do something with response error return Promise.reject(error); }); diff --git a/src/utils/check-session.ts b/src/utils/check-session.ts index 6f0f89fc4..b5224f5b7 100755 --- a/src/utils/check-session.ts +++ b/src/utils/check-session.ts @@ -1,8 +1,10 @@ import type { AstroCookies } from 'astro'; -import { getSupabaseClient } from '../supabase'; import { getFromCookies } from '../api/Auth'; import { pathRoutes } from '../config/pathRoutes'; import { RolePermissions } from '../config/permissions'; +import { apiStatusCodes } from '../config/CommonConstant'; +import { apiRoutes } from '../config/apiRoutes'; +import { envConfig } from '../config/envConfig'; interface IProps { cookies: AstroCookies; @@ -29,6 +31,38 @@ export const checkUserSession = async ({ }; } + try { + const baseURL = + globalThis.baseUrl || + envConfig.PUBLIC_BASE_URL || + process.env.PUBLIC_BASE_URL; + const config = { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${sessionCookie + ''}`, + }, + method: 'GET', + }; + const res = await fetch(`${baseURL + apiRoutes.users.userProfile}`, { + ...config, + }); + const userData = await res.json(); + console.log('Check Authorized User:::', { + status: userData.statusCode, + message: userData.message, + }); + + if (userData?.statusCode === apiStatusCodes.API_STATUS_UNAUTHORIZED) { + return { + permitted: false, + redirect: pathRoutes.auth.sinIn, + authorized: false, + }; + } + } catch (error) { + console.log('GET USER DETAILS ERROR::::', error); + } + const role = getFromCookies(cookies, 'role'); const permittedPages = RolePermissions.find( (item) => item.role === role, From 7fefcd41b121a356220439b434cd704722ed765f Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 9 Feb 2024 22:38:59 +0530 Subject: [PATCH 135/303] fix: padding Signed-off-by: karan --- src/commonComponents/PasseyAddDevicePopup.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/commonComponents/PasseyAddDevicePopup.tsx b/src/commonComponents/PasseyAddDevicePopup.tsx index b5312a9fb..45321f917 100644 --- a/src/commonComponents/PasseyAddDevicePopup.tsx +++ b/src/commonComponents/PasseyAddDevicePopup.tsx @@ -65,11 +65,7 @@ const PasskeyAddDevice = (props: { } } > - -

    {success || fidoUserError} -

    -
    } From a8f07c07b0417ff86ef9d3a93605e5f0661628b8 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 12 Feb 2024 13:12:26 +0530 Subject: [PATCH 136/303] fix: pagination issue on history page Signed-off-by: karan --- src/components/Issuance/History.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/Issuance/History.tsx b/src/components/Issuance/History.tsx index 9afa4b29c..9111ad473 100644 --- a/src/components/Issuance/History.tsx +++ b/src/components/Issuance/History.tsx @@ -33,8 +33,6 @@ const HistoryBulkIssuance = () => { const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [connectionList, setConnectionList] = useState([]); const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - const [currentPage, setCurrentPage] = useState(initialPageState); const [failure, setFailure] = useState(null); const [success, setSuccess] = useState(null); const [totalItem, setTotalItem] = useState(0); @@ -319,7 +317,6 @@ const HistoryBulkIssuance = () => { onAlertClose={() => { setSuccess(null); setFailure(null); - setError(null); }} /> )} @@ -330,9 +327,9 @@ const HistoryBulkIssuance = () => { header={header} data={connectionList} loading={loading} - currentPage={currentPage?.page} + currentPage={listAPIParameter?.page} onPageChange={(page: number) => { - setCurrentPage((prevState) => ({ + setListAPIParameter((prevState) => ({ ...prevState, page, })); From d8280cd02717057c9bcef3aabbaaf0fe56565511 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 12 Feb 2024 13:43:31 +0530 Subject: [PATCH 137/303] fix: comment and sonar issues Signed-off-by: karan --- src/commonComponents/PasseyAddDevicePopup.tsx | 14 ++++----- src/components/Issuance/History.tsx | 29 +++++++++---------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/commonComponents/PasseyAddDevicePopup.tsx b/src/commonComponents/PasseyAddDevicePopup.tsx index be2519747..e5d03ec91 100644 --- a/src/commonComponents/PasseyAddDevicePopup.tsx +++ b/src/commonComponents/PasseyAddDevicePopup.tsx @@ -37,13 +37,13 @@ const PasskeyAddDevice = (props: { const { data } = passkeyUserDetailsResp as AxiosResponse if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setNextFlag(true) - } else { - if (passkeyUserDetailsResp.toString().includes('401')) { - setFidoUserError('Invalid Credntials'); - } else { - setFidoUserError(passkeyUserDetailsResp as string); - } - } + } else if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setNextFlag(true); + } else if (passkeyUserDetailsResp.toString().includes('401')) { + setFidoUserError('Invalid Credentials'); + } else { + setFidoUserError(passkeyUserDetailsResp as string); + } } catch (error) { console.error('An unexpected error occurred:', error.message); setFidoUserError('An unexpected error occurred') diff --git a/src/components/Issuance/History.tsx b/src/components/Issuance/History.tsx index 9111ad473..5b06ea5a8 100644 --- a/src/components/Issuance/History.tsx +++ b/src/components/Issuance/History.tsx @@ -129,7 +129,7 @@ const HistoryBulkIssuance = () => { const getHistory = async (apiParameter: IConnectionListAPIParameter) => { setLoading(true); - const response = await getFilesHistory(apiParameter ); + const response = await getFilesHistory(apiParameter); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { @@ -143,23 +143,23 @@ const HistoryBulkIssuance = () => { }); const connections = data?.data?.data?.map( (ele: { - totalRecords: any; - successfulRecords: any; - failedRecords: any; - status: any; - createDateTime: any; - name: any; + totalRecords: number; + successfulRecords: number; + failedRecords: number; + status: string; + createDateTime: string; + name: string; theirLabel: string; id: string; createdAt: string; }) => { const fileId = ele?.id; const userName = ele?.name ? ele.name : 'Not available'; - const totalRecords = ele.totalRecords ? ele.totalRecords : '0'; + const totalRecords = ele.totalRecords ? ele.totalRecords : 0; const successfulRecords = ele.successfulRecords ? ele.successfulRecords - : '0'; - const failedRecords = ele.failedRecords ? ele.failedRecords : '0'; + : 0; + const failedRecords = ele.failedRecords ? ele.failedRecords : 0; const createdOn = ele?.createDateTime ? ele?.createDateTime : 'Not available'; @@ -294,7 +294,6 @@ const HistoryBulkIssuance = () => {
    -
    @@ -322,6 +321,10 @@ const HistoryBulkIssuance = () => { )} { searchSortByValue={searchSortByValue} totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} pageInfo={pageInfo} - isHeader={true} - isSearch={true} - isRefresh={true} - isSort={true} message={'No History'} discription={"You don't have any activities yet"} > From 9e25c36da07b8e4f12f56ac07069365900a77c40 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 12 Feb 2024 15:00:03 +0530 Subject: [PATCH 138/303] fix: comment and sonar issues Signed-off-by: karan --- src/commonComponents/PasseyAddDevicePopup.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/commonComponents/PasseyAddDevicePopup.tsx b/src/commonComponents/PasseyAddDevicePopup.tsx index e5d03ec91..7af706c7d 100644 --- a/src/commonComponents/PasseyAddDevicePopup.tsx +++ b/src/commonComponents/PasseyAddDevicePopup.tsx @@ -37,15 +37,13 @@ const PasskeyAddDevice = (props: { const { data } = passkeyUserDetailsResp as AxiosResponse if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setNextFlag(true) - } else if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setNextFlag(true); - } else if (passkeyUserDetailsResp.toString().includes('401')) { + } else if (passkeyUserDetailsResp.toString().includes('401')) { setFidoUserError('Invalid Credentials'); } else { setFidoUserError(passkeyUserDetailsResp as string); } } catch (error) { - console.error('An unexpected error occurred:', error.message); + console.error('An unexpected error occurred:', error); setFidoUserError('An unexpected error occurred') } }; From 3becd8904e5df0d436b5a169f7f46a05e7161431 Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 12 Feb 2024 19:44:42 +0530 Subject: [PATCH 139/303] feat: implementation of predicates for verification Signed-off-by: karan --- src/commonComponents/datatable/interface.ts | 2 + src/components/Verification/Verification.tsx | 391 ++++++++++++------- 2 files changed, 261 insertions(+), 132 deletions(-) diff --git a/src/commonComponents/datatable/interface.ts b/src/commonComponents/datatable/interface.ts index 2fac2355a..cf2383e8b 100644 --- a/src/commonComponents/datatable/interface.ts +++ b/src/commonComponents/datatable/interface.ts @@ -12,6 +12,8 @@ export interface TableData { } export interface Data { + handleChange(value: string): void; + inputType: string; data: string | JSX.Element; subData?: string; } diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index 27e58cb7a..da9c6b585 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -1,41 +1,65 @@ 'use client'; -import type { AxiosResponse } from "axios"; -import { Alert, Button, Card } from "flowbite-react"; -import React, { useEffect, useState } from "react"; -import { getFromLocalStorage } from "../../api/Auth"; -import { apiStatusCodes, storageKeys } from "../../config/CommonConstant"; -import BreadCrumbs from "../BreadCrumbs"; -import DataTable from "../../commonComponents/datatable"; -import type { TableData } from "../../commonComponents/datatable/interface"; -import { verifyCredential } from "../../api/verification"; -import { pathRoutes } from "../../config/pathRoutes"; -import CustomSpinner from "../CustomSpinner"; -import BackButton from '../../commonComponents/backbutton' -import type { SchemaDetail, SelectedUsers, VerifyCredentialPayload } from "./interface"; +import type { AxiosResponse } from 'axios'; +import { Alert, Button, Card } from 'flowbite-react'; +import React, { useEffect, useState } from 'react'; +import { getFromLocalStorage } from '../../api/Auth'; +import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; +import BreadCrumbs from '../BreadCrumbs'; +import DataTable from '../../commonComponents/datatable'; +import type { TableData } from '../../commonComponents/datatable/interface'; +import { verifyCredential } from '../../api/verification'; +import { pathRoutes } from '../../config/pathRoutes'; +import CustomSpinner from '../CustomSpinner'; +import BackButton from '../../commonComponents/backbutton'; +import type { + SchemaDetail, + SelectedUsers, + VerifyCredentialPayload, +} from './interface'; +interface SelectedUser { + name: string; + selected: boolean; + condition: string; + value: number; +} const VerificationCred = () => { - const [attributeList, setAttributeList] = useState([]) - const [proofReqSuccess, setProofReqSuccess] = useState('') - const [errMsg, setErrMsg] = useState(null) + const [attributeList, setAttributeList] = useState([]); + const [proofReqSuccess, setProofReqSuccess] = useState(null); + const [errMsg, setErrMsg] = useState(null); + const [display, setDisplay] = useState(false); const [schemaDetails, setSchemaDetails] = useState({ - schemaName: '', version: '', schemaId: '', credDefId: '' - }) - const [loading, setLoading] = useState(true) - const [selectedUsersData, setSelectedUsersData] = useState>([]); - const [requestLoader, setRequestLoader] = useState(false) - + schemaName: '', + version: '', + schemaId: '', + credDefId: '', + }); + const [predicates, setPredicates] = useState(false); + const [loading, setLoading] = useState(true); + const [selectedUsersData, setSelectedUsersData] = useState( + [], + ); + const [requestLoader, setRequestLoader] = useState(false); useEffect(() => { - const fetchData = async () => { + const fetchData = async () => { try { - setLoading(true) + setLoading(true); await getSchemaAndUsers(); - const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR) + const schemaAttributes = await getFromLocalStorage( + storageKeys.SCHEMA_ATTR, + ); const parsedSchemaDetails = JSON.parse(schemaAttributes) || []; const attributes = parsedSchemaDetails.attribute.map((ele: any) => { - const attributesName = ele.attributeName ? ele.attributeName : 'Not available'; - const displayName = ele.displayName ? ele.displayName : 'Not available'; + const attributesName = ele.attributeName + ? ele.attributeName + : 'Not available'; + const displayName = ele.displayName + ? ele.displayName + : 'Not available'; + const attributeType = ele.schemaDataType === 'number'; + setDisplay(attributeType); return { data: [ @@ -47,67 +71,137 @@ const VerificationCred = () => { type="checkbox" onClick={(event: React.MouseEvent) => { const inputElement = event?.target as HTMLInputElement; - selectConnection(attributesName, inputElement?.checked); + selectConnection( + attributesName, + inputElement?.checked, + '', + null, + ); }} value="" - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" + className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" />
    - ) + ), }, { data: displayName }, - ] + + { + data: predicates && attributeType && ( +
    + +
    + ), + }, + { + data: predicates && attributeType && ( +
    + + setSelectedUsersData((prev) => { + const updatedData = [...prev]; + if (updatedData.length > 0) { + updatedData[updatedData.length - 1].value = + parseInt(e.target.value); + } + return updatedData; + }) + } + /> +
    + ), + }, + ], }; }); setAttributeList(attributes); - setLoading(false) + setLoading(false); } catch (error) { - setLoading(false) + setLoading(false); console.error('Error fetching data:', error); } }; fetchData(); - return (()=>{ setRequestLoader(false); - }) - }, []); - + return () => { + setRequestLoader(false); + }; + }, [predicates]); - const selectConnection = (attributes: string, checked: boolean) => { + const selectConnection = ( + attributes: string, + checked: boolean, + condition: string, + value: number | null, + ) => { if (checked) { - setSelectedUsersData(prevSelectedUsersData => [ + setSelectedUsersData((prevSelectedUsersData) => [ ...prevSelectedUsersData, - { name: attributes, selected: true } + { + name: attributes, + selected: true, + condition: condition, + value: value, + }, ]); } else { - setSelectedUsersData(prevSelectedUsersData => - prevSelectedUsersData.filter(item => item.name !== attributes) + setSelectedUsersData((prevSelectedUsersData) => + prevSelectedUsersData.filter((item) => item.name !== attributes), ); } - } - + }; const getSchemaAndUsers = async () => { - const credDefId = await getFromLocalStorage(storageKeys.CRED_DEF_ID) - const schemaId = await getFromLocalStorage(storageKeys.SCHEMA_ID) - createSchemaPayload(schemaId, credDefId) - } - - + const credDefId = await getFromLocalStorage(storageKeys.CRED_DEF_ID); + const schemaId = await getFromLocalStorage(storageKeys.SCHEMA_ID); + createSchemaPayload(schemaId, credDefId); + }; const createSchemaPayload = async (schemaId: string, credDefId: string) => { if (schemaId) { - const parts = schemaId.split(":"); + const parts = schemaId.split(':'); const schemaName = parts[2]; const version = parts[3]; - setSchemaDetails({ schemaName, version, schemaId, credDefId }) + setSchemaDetails({ schemaName, version, schemaId, credDefId }); } - } + }; const getSelectedUsers = async (): Promise => { - const selectedUsers = await getFromLocalStorage(storageKeys.SELECTED_USER) - return JSON.parse(selectedUsers) - } + const selectedUsers = await getFromLocalStorage(storageKeys.SELECTED_USER); + return JSON.parse(selectedUsers); + }; const verifyCredentialSubmit = async () => { try { @@ -116,120 +210,153 @@ const VerificationCred = () => { const credDefId = await getFromLocalStorage(storageKeys.CRED_DEF_ID); const schemaId = await getFromLocalStorage(storageKeys.SCHEMA_ID); const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - - const attributes = await selectedUsersData.map(user => ({ + + const attributes = selectedUsersData.map((user) => ({ attributeName: user.name, - ...(credDefId ? { credDefId } : {}), - schemaId: schemaId + condition: user.condition, + value: user.value.toString(), + ...(credDefId ? { credDefId } : {}), + schemaId: schemaId, })); + console.log('attributes', attributes); + const verifyCredentialPayload: VerifyCredentialPayload = { connectionId: `${selectedUsers[0].connectionId}`, attributes: attributes, - comment: "string", - orgId: orgId + comment: 'string', + orgId: orgId, }; if (attributes) { const response = await verifyCredential(verifyCredentialPayload); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { setProofReqSuccess(data?.message); - window.location.href = pathRoutes.organizations.credentials + // window.location.href = pathRoutes.organizations.credentials } else { setErrMsg(response as string); setRequestLoader(false); } } } catch (error) { - setErrMsg("An error occurred. Please try again."); + setErrMsg('An error occurred. Please try again.'); setRequestLoader(false); } }; - + + const handelPredicates = () => { + setPredicates(!predicates); + }; const header = [ { columnName: '', width: 'w-0.5' }, - { columnName: 'Attributes' } - ] + { columnName: 'Attributes' }, + + predicates && display && { columnName: 'Condition' }, + predicates && display && { columnName: 'Predicates', width: 'w-0.5' }, + ]; return ( - <>
    -
    -
    - - + <> +
    +
    +
    + + +
    +

    + Verification +

    -

    - Verification -

    -
    - {loading ? -
    - + {loading ? ( +
    +
    - : - -
    -
    -
    - {schemaDetails.schemaName} -
    -

    - Version: {schemaDetails.version} -

    + ) : ( + +
    +
    +
    + {schemaDetails.schemaName} +
    +

    + Version: {schemaDetails.version} +

    +
    +
    +
    +

    + Schema ID:{' '} + {schemaDetails.schemaId} +

    +

    + + Credential definition restriction: + + {schemaDetails.credDefId ? ' Yes' : ' No'} +

    +
    +
    + )} + {(proofReqSuccess || errMsg) && ( +
    + { + setProofReqSuccess(null), setErrMsg(null); + }} + > + +

    {proofReqSuccess || errMsg}

    +
    +
    + )} +
    + handelPredicates()} /> +
    -
    -

    - Schema ID: {schemaDetails.schemaId} -

    -

    - Credential definition restriction: - {schemaDetails.credDefId ? ' Yes' : ' No'} - -

    +
    +
    - - } - { - (proofReqSuccess || errMsg) && -
    - setErrMsg(null)} - > - -

    - {proofReqSuccess || errMsg} -

    -
    -
    -
    - } -
    - Attribute List
    -
    - -
    -
    - -
    +
    + ); +}; - ) -} - -export default VerificationCred +export default VerificationCred; From 1f9c66e111079737fa46c1bd7176b832cb51685f Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 13 Feb 2024 15:21:33 +0530 Subject: [PATCH 140/303] fix: minor spell change Signed-off-by: karan --- src/components/Authentication/SignInUserPassword.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Authentication/SignInUserPassword.tsx b/src/components/Authentication/SignInUserPassword.tsx index fe5e0d563..89edd4990 100644 --- a/src/components/Authentication/SignInUserPassword.tsx +++ b/src/components/Authentication/SignInUserPassword.tsx @@ -109,7 +109,7 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => { } else { setLoading(false); if (loginRsp.toString().includes('401')) { - setFailure('Invalid Credntials'); + setFailure('Invalid Credentials'); } else { setFailure(loginRsp as string); } From 02967d1fef99bbb81169dbcb00863de52fa0e7fd Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 13 Feb 2024 15:29:31 +0530 Subject: [PATCH 141/303] fix: minor spell change Signed-off-by: karan --- src/components/Authentication/SignInUserPassword.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Authentication/SignInUserPassword.tsx b/src/components/Authentication/SignInUserPassword.tsx index 89edd4990..e7cb0f2d5 100644 --- a/src/components/Authentication/SignInUserPassword.tsx +++ b/src/components/Authentication/SignInUserPassword.tsx @@ -109,7 +109,7 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => { } else { setLoading(false); if (loginRsp.toString().includes('401')) { - setFailure('Invalid Credentials'); + setFailure('Invalid Credentials'); } else { setFailure(loginRsp as string); } From 6284267093bacd9928463d8fe3a246aac8c249d0 Mon Sep 17 00:00:00 2001 From: karan Date: Tue, 13 Feb 2024 18:13:52 +0530 Subject: [PATCH 142/303] added predicates input and select and handled empty condition Signed-off-by: karan --- src/components/Verification/Verification.tsx | 97 +++++++++++++++----- 1 file changed, 72 insertions(+), 25 deletions(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index da9c6b585..d0b1d867e 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -20,8 +20,8 @@ import type { interface SelectedUser { name: string; selected: boolean; - condition: string; - value: number; + condition?: string; + value?: number; } const VerificationCred = () => { @@ -40,6 +40,8 @@ const VerificationCred = () => { const [selectedUsersData, setSelectedUsersData] = useState( [], ); + const [inputError, setInputError] = useState(null); + const [inputTouched, setInputTouched] = useState(false); const [requestLoader, setRequestLoader] = useState(false); useEffect(() => { @@ -51,7 +53,8 @@ const VerificationCred = () => { storageKeys.SCHEMA_ATTR, ); const parsedSchemaDetails = JSON.parse(schemaAttributes) || []; - const attributes = parsedSchemaDetails.attribute.map((ele: any) => { + + const attributes = parsedSchemaDetails.attribute.map((ele: any, index:number) => { const attributesName = ele.attributeName ? ele.attributeName : 'Not available'; @@ -59,7 +62,7 @@ const VerificationCred = () => { ? ele.displayName : 'Not available'; const attributeType = ele.schemaDataType === 'number'; - setDisplay(attributeType); + // setDisplay(attributeType); return { data: [ @@ -67,7 +70,8 @@ const VerificationCred = () => { data: (
    ) => { const inputElement = event?.target as HTMLInputElement; @@ -90,6 +94,7 @@ const VerificationCred = () => { data: predicates && attributeType && (
    + // onChange={(e) => + // setSelectedUsersData((prev) => { + // const updatedData = [...prev]; + // if (updatedData.length > 0) { + // updatedData[updatedData.length - 1].value = + // parseInt(e.target.value); + // } + // return updatedData; + // }) + // } + onChange={(e) => { + const value = e.target.value; setSelectedUsersData((prev) => { const updatedData = [...prev]; if (updatedData.length > 0) { updatedData[updatedData.length - 1].value = - parseInt(e.target.value); + parseInt(value); } return updatedData; - }) + }); + setInputTouched(true); + setInputError(null); + }} + onBlur={() => { + const inputValue = + selectedUsersData[selectedUsersData.length - 1] + ?.value; + if ( + (!inputValue || inputValue.toString().length < 1) && + selectedUsersData[selectedUsersData.length - 1] + ?.selected + ) { + setInputError('Value cannot be empty'); + } else { + setInputError(null); + } + }} + disabled={ + !selectedUsersData[selectedUsersData.length - 1] + ?.selected } /> + {inputError && inputTouched && ( +

    {inputError}

    + )}
    ), }, @@ -147,6 +191,8 @@ const VerificationCred = () => { }; }); setAttributeList(attributes); + const attributeTypeArray = parsedSchemaDetails.attribute.map((ele: any) => ele.schemaDataType === 'number'); + setDisplay(attributeTypeArray.includes(true)); setLoading(false); } catch (error) { setLoading(false); @@ -158,13 +204,13 @@ const VerificationCred = () => { return () => { setRequestLoader(false); }; - }, [predicates]); + }, [predicates, selectedUsersData, inputError]); const selectConnection = ( attributes: string, checked: boolean, - condition: string, - value: number | null, + condition?: string, + value?: number | null, ) => { if (checked) { setSelectedUsersData((prevSelectedUsersData) => [ @@ -172,7 +218,7 @@ const VerificationCred = () => { { name: attributes, selected: true, - condition: condition, + condition: condition !== '' ? condition : undefined, value: value, }, ]); @@ -200,9 +246,10 @@ const VerificationCred = () => { const getSelectedUsers = async (): Promise => { const selectedUsers = await getFromLocalStorage(storageKeys.SELECTED_USER); + return JSON.parse(selectedUsers); }; - + const verifyCredentialSubmit = async () => { try { setRequestLoader(true); @@ -213,12 +260,11 @@ const VerificationCred = () => { const attributes = selectedUsersData.map((user) => ({ attributeName: user.name, - condition: user.condition, - value: user.value.toString(), + condition: user.condition ?? undefined, + value: user?.value?.toString(), ...(credDefId ? { credDefId } : {}), schemaId: schemaId, })); - console.log('attributes', attributes); const verifyCredentialPayload: VerifyCredentialPayload = { connectionId: `${selectedUsers[0].connectionId}`, @@ -272,7 +318,7 @@ const VerificationCred = () => {
    ) : ( { setProofReqSuccess(null), setErrMsg(null); }} > - -

    {proofReqSuccess || errMsg}

    -
    + {proofReqSuccess || errMsg}
    )} -
    - handelPredicates()} /> +
    +

    Attribute List

    +
    + handelPredicates()} /> -
    -
    +
    +
    +
    Date: Wed, 14 Feb 2024 12:08:35 +0530 Subject: [PATCH 143/303] added predicates input and select and handled empty condition Signed-off-by: karan --- src/components/Verification/Verification.tsx | 296 ++++++++++--------- 1 file changed, 154 insertions(+), 142 deletions(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index d0b1d867e..bd8da35a0 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -53,146 +53,154 @@ const VerificationCred = () => { storageKeys.SCHEMA_ATTR, ); const parsedSchemaDetails = JSON.parse(schemaAttributes) || []; - - const attributes = parsedSchemaDetails.attribute.map((ele: any, index:number) => { - const attributesName = ele.attributeName - ? ele.attributeName - : 'Not available'; - const displayName = ele.displayName - ? ele.displayName - : 'Not available'; - const attributeType = ele.schemaDataType === 'number'; - // setDisplay(attributeType); - return { - data: [ - { - data: ( -
    - ) => { - const inputElement = event?.target as HTMLInputElement; - selectConnection( - attributesName, - inputElement?.checked, - '', - null, - ); - }} - value="" - className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" - /> -
    - ), - }, - { data: displayName }, + const attributes = parsedSchemaDetails.attribute.map( + (ele: any, index: number) => { + const attributesName = ele.attributeName + ? ele.attributeName + : 'Not available'; + const displayName = ele.displayName + ? ele.displayName + : 'Not available'; + const attributeType = ele.schemaDataType === 'number'; + return { + data: [ + { + data: ( +
    + , + ) => { + const inputElement = + event?.target as HTMLInputElement; + selectConnection( + attributesName, + inputElement?.checked, + '', + null, + ); + }} + value="" + className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" + /> +
    + ), + }, + { data: displayName }, - { - data: predicates && attributeType && ( -
    - -
    - ), - }, - { - data: predicates && attributeType && ( -
    - - // setSelectedUsersData((prev) => { - // const updatedData = [...prev]; - // if (updatedData.length > 0) { - // updatedData[updatedData.length - 1].value = - // parseInt(e.target.value); - // } - // return updatedData; - // }) - // } - onChange={(e) => { - const value = e.target.value; - setSelectedUsersData((prev) => { - const updatedData = [...prev]; - if (updatedData.length > 0) { - updatedData[updatedData.length - 1].value = - parseInt(value); - } - return updatedData; - }); - setInputTouched(true); - setInputError(null); - }} - onBlur={() => { - const inputValue = - selectedUsersData[selectedUsersData.length - 1] - ?.value; - if ( - (!inputValue || inputValue.toString().length < 1) && - selectedUsersData[selectedUsersData.length - 1] + { + data: predicates && attributeType && ( +
    + +
    + ), + }, + { + data: predicates && attributeType && ( +
    + + // setSelectedUsersData((prev) => { + // const updatedData = [...prev]; + // if (updatedData.length > 0) { + // updatedData[updatedData.length - 1].value = + // parseInt(e.target.value); + // } + // return updatedData; + // }) + // } + onChange={(e) => { + const value = e.target.value; + setSelectedUsersData((prev) => { + const updatedData = [...prev]; + if (updatedData.length > 0) { + updatedData[updatedData.length - 1].value = + parseInt(value); + } + return updatedData; + }); + setInputTouched(true); setInputError(null); + }} + onBlur={() => { + const inputValue = + selectedUsersData[selectedUsersData.length - 1] + ?.value; + if ( + (!inputValue || inputValue.toString().length < 1) && + selectedUsersData[selectedUsersData.length - 1] + ?.selected + ) { + setInputError('Value cannot be empty'); + } else { + setInputError(null); + } + }} + disabled={ + !selectedUsersData[selectedUsersData.length - 1] + ?.selected } - }} - disabled={ - !selectedUsersData[selectedUsersData.length - 1] - ?.selected - } - /> - {inputError && inputTouched && ( -

    {inputError}

    - )} -
    - ), - }, - ], - }; - }); + /> + {inputError && inputTouched && ( +

    + {inputError} +

    + )} +
    + ), + }, + ], + }; + }, + ); setAttributeList(attributes); - const attributeTypeArray = parsedSchemaDetails.attribute.map((ele: any) => ele.schemaDataType === 'number'); - setDisplay(attributeTypeArray.includes(true)); + const attributeTypeArray = parsedSchemaDetails.attribute.map( + (ele: any) => ele.schemaDataType === 'number', + ); + setDisplay(attributeTypeArray.includes(true)); setLoading(false); } catch (error) { setLoading(false); @@ -246,10 +254,10 @@ const VerificationCred = () => { const getSelectedUsers = async (): Promise => { const selectedUsers = await getFromLocalStorage(storageKeys.SELECTED_USER); - + return JSON.parse(selectedUsers); }; - + const verifyCredentialSubmit = async () => { try { setRequestLoader(true); @@ -297,7 +305,7 @@ const VerificationCred = () => { { columnName: 'Attributes' }, predicates && display && { columnName: 'Condition' }, - predicates && display && { columnName: 'Predicates', width: 'w-0.5' }, + predicates && display && { columnName: 'Predicates', width: 'w-0.75' }, ]; return ( @@ -363,13 +371,17 @@ const VerificationCred = () => {
    )} -
    +

    Attribute List

    -
    - handelPredicates()} /> - +
    + handelPredicates()} + /> +
    -
    +
    Date: Wed, 14 Feb 2024 23:58:44 +0530 Subject: [PATCH 144/303] feat: predicate based verification Signed-off-by: karan --- src/components/Verification/Verification.tsx | 273 +++++++++++-------- 1 file changed, 160 insertions(+), 113 deletions(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index bd8da35a0..6f0baaad1 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -40,10 +40,47 @@ const VerificationCred = () => { const [selectedUsersData, setSelectedUsersData] = useState( [], ); - const [inputError, setInputError] = useState(null); + const [inputErrors, setInputErrors] = useState< + Record + >({}); const [inputTouched, setInputTouched] = useState(false); const [requestLoader, setRequestLoader] = useState(false); + const conditionOptions = [ + { value: undefined, label: 'Select' }, + { + value: '>', + label: ( + <> +

    {'>'}

    : Greater Than + + ), + }, + { + value: '<', + label: ( + <> +

    {'<'}

    : Less Than + + ), + }, + { + value: '>=', + label: ( + <> +

    {'>='}

    : Greater Than Equal To + + ), + }, + { + value: '<=', + label: ( + <> +

    {'<='}

    : Less Than Equal To + + ), + }, + ]; useEffect(() => { const fetchData = async () => { try { @@ -63,6 +100,7 @@ const VerificationCred = () => { ? ele.displayName : 'Not available'; const attributeType = ele.schemaDataType === 'number'; + return { data: [ { @@ -82,6 +120,7 @@ const VerificationCred = () => { inputElement?.checked, '', null, + index, ); }} value="" @@ -91,102 +130,103 @@ const VerificationCred = () => { ), }, { data: displayName }, - { - data: predicates && attributeType && ( + data: predicates && (
    - + {attributeType && ( + + )}
    ), }, { data: predicates && attributeType && (
    - - // setSelectedUsersData((prev) => { - // const updatedData = [...prev]; - // if (updatedData.length > 0) { - // updatedData[updatedData.length - 1].value = - // parseInt(e.target.value); - // } - // return updatedData; - // }) - // } - onChange={(e) => { - const value = e.target.value; - setSelectedUsersData((prev) => { - const updatedData = [...prev]; - if (updatedData.length > 0) { - updatedData[updatedData.length - 1].value = - parseInt(value); + {attributeType && ( + item.name === attributesName)?.selected ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer '}`} + type="number" + min="0" + onChange={(e) => { + const value = e.target.value; + setSelectedUsersData((prev) => { + const updatedData = [...prev]; + if (updatedData.length > 0) { + updatedData[updatedData.length - 1].value = + parseInt(value); + } + return updatedData; + }); + setInputTouched(true); + setInputErrors({}); + }} + onBlur={() => { + setInputTouched(true); + const inputValue = + selectedUsersData[selectedUsersData.length - 1] + ?.value; + const attributeName = attributesName; + if ( + (inputValue === undefined || + inputValue === null || + Number.isNaN(inputValue)) && + selectedUsersData[selectedUsersData.length - 1] + ?.selected + ) { + setInputErrors((prevErrors) => ({ + ...prevErrors, + [attributeName]: 'Value cannot be empty', + })); + } else if (inputValue && inputValue < 0) { + setInputErrors((prevErrors) => ({ + ...prevErrors, + [attributeName]: + 'Please enter a positive number', + })); + } else { + setInputErrors((prevErrors) => ({ + ...prevErrors, + [attributeName]: null, + })); } - return updatedData; - }); - setInputTouched(true); - setInputError(null); - }} - onBlur={() => { - const inputValue = - selectedUsersData[selectedUsersData.length - 1] - ?.value; - if ( - (!inputValue || inputValue.toString().length < 1) && - selectedUsersData[selectedUsersData.length - 1] - ?.selected - ) { - setInputError('Value cannot be empty'); - } else { - setInputError(null); + }} + disabled={ + !selectedUsersData.find( + (item) => item.name === attributesName, + )?.selected } - }} - disabled={ - !selectedUsersData[selectedUsersData.length - 1] - ?.selected - } - /> - {inputError && inputTouched && ( + /> + )} + {inputErrors[attributesName] && inputTouched && (

    - {inputError} + {inputErrors[attributesName]}

    )}
    @@ -196,6 +236,7 @@ const VerificationCred = () => { }; }, ); + setAttributeList(attributes); const attributeTypeArray = parsedSchemaDetails.attribute.map( (ele: any) => ele.schemaDataType === 'number', @@ -212,7 +253,7 @@ const VerificationCred = () => { return () => { setRequestLoader(false); }; - }, [predicates, selectedUsersData, inputError]); + }, [predicates, selectedUsersData, inputErrors]); const selectConnection = ( attributes: string, @@ -226,7 +267,7 @@ const VerificationCred = () => { { name: attributes, selected: true, - condition: condition !== '' ? condition : undefined, + condition: condition, value: value, }, ]); @@ -268,11 +309,11 @@ const VerificationCred = () => { const attributes = selectedUsersData.map((user) => ({ attributeName: user.name, - condition: user.condition ?? undefined, + condition: user.condition === '' ? undefined : user.condition, value: user?.value?.toString(), ...(credDefId ? { credDefId } : {}), schemaId: schemaId, - })); + })); const verifyCredentialPayload: VerifyCredentialPayload = { connectionId: `${selectedUsers[0].connectionId}`, @@ -389,30 +430,36 @@ const VerificationCred = () => { loading={loading} >
    -
    - -
    - + + + + Request Proof + +
    ); From bf4b90e85576edc951be09eec8cf4db0fbf33c36 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 15 Feb 2024 16:05:49 +0530 Subject: [PATCH 145/303] feat: predicates based proof request Signed-off-by: karan --- src/components/Verification/Verification.tsx | 466 +++++++++++-------- 1 file changed, 270 insertions(+), 196 deletions(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index 6f0baaad1..df4dd129e 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -2,7 +2,7 @@ import type { AxiosResponse } from 'axios'; import { Alert, Button, Card } from 'flowbite-react'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { getFromLocalStorage } from '../../api/Auth'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import BreadCrumbs from '../BreadCrumbs'; @@ -18,6 +18,7 @@ import type { VerifyCredentialPayload, } from './interface'; interface SelectedUser { + dataType: string; name: string; selected: boolean; condition?: string; @@ -28,7 +29,7 @@ const VerificationCred = () => { const [attributeList, setAttributeList] = useState([]); const [proofReqSuccess, setProofReqSuccess] = useState(null); const [errMsg, setErrMsg] = useState(null); - const [display, setDisplay] = useState(false); + const [display, setDisplay] = useState(false); const [schemaDetails, setSchemaDetails] = useState({ schemaName: '', version: '', @@ -43,11 +44,22 @@ const VerificationCred = () => { const [inputErrors, setInputErrors] = useState< Record >({}); - const [inputTouched, setInputTouched] = useState(false); + const [inputTouched, setInputTouched] = useState(false); const [requestLoader, setRequestLoader] = useState(false); + const inputRefs = useRef({}); + const selectRefs = useRef({}); + const conditionOptions = [ - { value: undefined, label: 'Select' }, + { + value: '', + label: ( + <> + {' '} + Select + + ), + }, { value: '>', label: ( @@ -81,174 +93,189 @@ const VerificationCred = () => { ), }, ]; - useEffect(() => { - const fetchData = async () => { - try { - setLoading(true); - await getSchemaAndUsers(); - const schemaAttributes = await getFromLocalStorage( - storageKeys.SCHEMA_ATTR, - ); - const parsedSchemaDetails = JSON.parse(schemaAttributes) || []; - const attributes = parsedSchemaDetails.attribute.map( - (ele: any, index: number) => { - const attributesName = ele.attributeName - ? ele.attributeName - : 'Not available'; - const displayName = ele.displayName - ? ele.displayName - : 'Not available'; - const attributeType = ele.schemaDataType === 'number'; + const fetchData = async () => { + try { + setLoading(true); + await getSchemaAndUsers(); + const schemaAttributes = await getFromLocalStorage( + storageKeys.SCHEMA_ATTR, + ); + const parsedSchemaDetails = JSON.parse(schemaAttributes) || []; - return { - data: [ - { - data: ( -
    - { + const attributesName = ele.attributeName + ? ele.attributeName + : 'Not available'; + const displayName = ele.displayName + ? ele.displayName + : 'Not available'; + const attributeType = ele.schemaDataType === 'number'; + + return { + data: [ + { + data: ( +
    + ) => { + const inputElement = event?.target as HTMLInputElement; + selectConnection( + attributesName, + inputElement?.checked, + '', + null, + ); + }} + value="" + className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 dark:bg-gray-700 dark:border-gray-600 cursor-pointer" + /> +
    + ), + }, + { data: displayName }, + { + data: predicates && ( +
    + {attributeType && ( + item.name === attributesName)?.selected ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer '}`} - id="dropdown" - onChange={(e) => { - const selectedValue = e.target.value; - setSelectedUsersData((prev) => { - const updatedData = [...prev]; - updatedData[updatedData.length - 1] = { - ...updatedData[updatedData.length - 1], - condition: selectedValue, - }; - return updatedData; - }); - }} - disabled={ - !selectedUsersData.find( - (item) => item.name === attributesName, - )?.selected - } - > - {conditionOptions?.map((option, optionIndex) => ( - - ))} - - )} -
    - ), - }, - { - data: predicates && attributeType && ( -
    - {attributeType && ( - item.name === attributesName)?.selected ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer '}`} - type="number" - min="0" - onChange={(e) => { - const value = e.target.value; - setSelectedUsersData((prev) => { - const updatedData = [...prev]; - if (updatedData.length > 0) { - updatedData[updatedData.length - 1].value = - parseInt(value); - } - return updatedData; - }); - setInputTouched(true); - setInputErrors({}); - }} - onBlur={() => { - setInputTouched(true); - const inputValue = - selectedUsersData[selectedUsersData.length - 1] - ?.value; - const attributeName = attributesName; - if ( - (inputValue === undefined || - inputValue === null || - Number.isNaN(inputValue)) && - selectedUsersData[selectedUsersData.length - 1] - ?.selected - ) { - setInputErrors((prevErrors) => ({ - ...prevErrors, - [attributeName]: 'Value cannot be empty', - })); - } else if (inputValue && inputValue < 0) { - setInputErrors((prevErrors) => ({ - ...prevErrors, - [attributeName]: - 'Please enter a positive number', - })); - } else { - setInputErrors((prevErrors) => ({ - ...prevErrors, - [attributeName]: null, - })); + disabled={ + !selectedUsersData.find( + (item) => item.name === attributesName, + )?.selected + } + > + {conditionOptions?.map((option, optionIndex) => ( + + ))} + + )} +
    + ), + }, + { + data: predicates && attributeType && ( +
    + {attributeType && ( + (inputRefs.current[index] = ref)} + className={`flex shrink-0 bg-gray-50 border border-gray-400 text-gray-900 sm:text-sm rounded-md focus:ring-primary-700 focus:border-primary-700 block px-2 py-1.5 dark:bg-gray-700 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-700 dark:focus:border-primary-700 ${ + !selectedUsersData.find( + (item) => item.name === attributesName, + )?.selected || + selectedUsersData.find( + (item) => item.name === attributesName, + )?.condition === '' + ? 'opacity-50 cursor-not-allowed' + : 'cursor-pointer ' + }`} + type="number" + min="0" + onChange={(e) => { + const value = e.target.value; + setSelectedUsersData((prev) => { + const updatedData = [...prev]; + if (updatedData.length > 0) { + updatedData[updatedData.length - 1].value = + parseInt(value); } - }} - disabled={ - !selectedUsersData.find( - (item) => item.name === attributesName, - )?.selected + return updatedData; + }); + setInputTouched(true); + setInputErrors({}); + }} + onBlur={() => { + setInputTouched(true); + const inputValue = + selectedUsersData[selectedUsersData.length - 1] + ?.value; + const attributeName = attributesName; + if ( + (inputValue === undefined || + inputValue === null || + Number.isNaN(inputValue)) && + selectedUsersData[selectedUsersData.length - 1] + ?.selected + ) { + setInputErrors((prevErrors) => ({ + ...prevErrors, + [attributeName]: 'Value cannot be empty', + })); + } else if (inputValue && inputValue < 0) { + setInputErrors((prevErrors) => ({ + ...prevErrors, + [attributeName]: 'Please enter a positive number', + })); + } else { + setInputErrors((prevErrors) => ({ + ...prevErrors, + [attributeName]: null, + })); } - /> - )} - {inputErrors[attributesName] && inputTouched && ( -

    - {inputErrors[attributesName]} -

    - )} -
    - ), - }, - ], - }; - }, - ); - - setAttributeList(attributes); - const attributeTypeArray = parsedSchemaDetails.attribute.map( - (ele: any) => ele.schemaDataType === 'number', - ); - setDisplay(attributeTypeArray.includes(true)); - setLoading(false); - } catch (error) { - setLoading(false); - console.error('Error fetching data:', error); - } - }; + }} + disabled={ + !selectedUsersData.find( + (item) => item.name === attributesName, + )?.selected || + selectedUsersData.find( + (item) => item.name === attributesName, + )?.condition === '' + } + /> + )} + {inputErrors[attributesName] && inputTouched && ( +

    + {inputErrors[attributesName]} +

    + )} +
    + ), + }, + ], + }; + }, + ); + setAttributeList(attributes); + const attributeTypeArray = parsedSchemaDetails.attribute.map( + (ele: any) => ele.schemaDataType === 'number', + ); + setDisplay(attributeTypeArray.includes(true)); + setLoading(false); + } catch (error) { + setLoading(false); + console.error('Error fetching data:', error); + } + }; + useEffect(() => { fetchData(); return () => { setRequestLoader(false); @@ -275,6 +302,14 @@ const VerificationCred = () => { setSelectedUsersData((prevSelectedUsersData) => prevSelectedUsersData.filter((item) => item.name !== attributes), ); + if (inputRefs.current[attributes]) { + inputRefs.current[attributes].value = ''; + } + + // Clear select value + if (selectRefs.current[attributes]) { + selectRefs.current[attributes].value = ''; + } } }; @@ -295,7 +330,6 @@ const VerificationCred = () => { const getSelectedUsers = async (): Promise => { const selectedUsers = await getFromLocalStorage(storageKeys.SELECTED_USER); - return JSON.parse(selectedUsers); }; @@ -313,7 +347,7 @@ const VerificationCred = () => { value: user?.value?.toString(), ...(credDefId ? { credDefId } : {}), schemaId: schemaId, - })); + })); const verifyCredentialPayload: VerifyCredentialPayload = { connectionId: `${selectedUsers[0].connectionId}`, @@ -326,7 +360,7 @@ const VerificationCred = () => { const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { setProofReqSuccess(data?.message); - // window.location.href = pathRoutes.organizations.credentials + window.location.href = pathRoutes.organizations.credentials; } else { setErrMsg(response as string); setRequestLoader(false); @@ -340,11 +374,19 @@ const VerificationCred = () => { const handelPredicates = () => { setPredicates(!predicates); + setSelectedUsersData((prevSelectedUsersData) => { + return prevSelectedUsersData.map((user) => { + return { + ...user, + condition: '', + value: undefined, + }; + }); + }); }; const header = [ { columnName: '', width: 'w-0.5' }, { columnName: 'Attributes' }, - predicates && display && { columnName: 'Condition' }, predicates && display && { columnName: 'Predicates', width: 'w-0.75' }, ]; @@ -430,35 +472,67 @@ const VerificationCred = () => { loading={loading} >
    +
    - + ) : ( + + + + + Request Proof + + )}
    From 9b0a76619f44d78b2035828b566dacd810a124b5 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 15 Feb 2024 17:05:16 +0530 Subject: [PATCH 146/303] feat: predicates based proof request Signed-off-by: karan --- src/components/Verification/Verification.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index df4dd129e..48bef08a4 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -447,7 +447,8 @@ const VerificationCred = () => { { - setProofReqSuccess(null), setErrMsg(null); + setProofReqSuccess(null); + setErrMsg(null); }} > {proofReqSuccess || errMsg} From ca5d5e9f9f56b705805f8990b8546970675e95b3 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 15 Feb 2024 17:19:55 +0530 Subject: [PATCH 147/303] fix: header cahnge Signed-off-by: karan --- src/components/Verification/Verification.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index 48bef08a4..db433360d 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -388,7 +388,7 @@ const VerificationCred = () => { { columnName: '', width: 'w-0.5' }, { columnName: 'Attributes' }, predicates && display && { columnName: 'Condition' }, - predicates && display && { columnName: 'Predicates', width: 'w-0.75' }, + predicates && display && { columnName: 'Value', width: 'w-0.75' }, ]; return ( From 8d63dc49ed9d5da8c74791cbf0da1b3369b98d07 Mon Sep 17 00:00:00 2001 From: karan Date: Thu, 15 Feb 2024 17:34:59 +0530 Subject: [PATCH 148/303] fix: alignment of button Signed-off-by: karan --- src/components/Verification/Verification.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index db433360d..6794d7297 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -494,7 +494,7 @@ const VerificationCred = () => { ) || Object.values(inputErrors).some((error) => error !== null) } - className="text-base font-medium text-center text-white bg-primary-700 hover:!bg-primary-800 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 mt-2 ml-auto mr-8" + className="text-base font-medium text-center text-white bg-primary-700 hover:!bg-primary-800 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 mt-2 ml-auto" > { onClick={verifyCredentialSubmit} isProcessing={requestLoader} disabled={requestLoader || !selectedUsersData.length} - className="text-base font-medium text-center text-white bg-primary-700 hover:!bg-primary-800 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 mt-2 ml-auto mr-8" + className="text-base font-medium text-center text-white bg-primary-700 hover:!bg-primary-800 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 mt-2 ml-auto" > Date: Fri, 16 Feb 2024 15:56:42 +0530 Subject: [PATCH 149/303] feat: implementation of required field in schema creatation Signed-off-by: karan --- src/components/Resources/Schema/Create.tsx | 625 ++++++++++++------ .../Resources/Schema/interfaces/index.ts | 1 + 2 files changed, 416 insertions(+), 210 deletions(-) diff --git a/src/components/Resources/Schema/Create.tsx b/src/components/Resources/Schema/Create.tsx index 56b34a2ed..01dd12db4 100644 --- a/src/components/Resources/Schema/Create.tsx +++ b/src/components/Resources/Schema/Create.tsx @@ -3,7 +3,17 @@ import * as yup from 'yup'; import { Button, Card, Label } from 'flowbite-react'; -import { Field, FieldArray, Form, Formik, FormikConfig, FormikErrors, FormikHandlers, FormikHelpers, FormikProps } from 'formik'; +import { + Field, + FieldArray, + Form, + Formik, + FormikConfig, + FormikErrors, + FormikHandlers, + FormikHelpers, + FormikProps, +} from 'formik'; import { apiStatusCodes, schemaVersionRegex, @@ -23,7 +33,7 @@ import { } from '../../../config/ecosystem'; import { createSchemaRequest } from '../../../api/ecosystem'; import EcosystemProfileCard from '../../../commonComponents/EcosystemProfileCard'; -import ConfirmationModal from '../../../commonComponents/ConfirmationModal' +import ConfirmationModal from '../../../commonComponents/ConfirmationModal'; const options = [ { @@ -45,8 +55,8 @@ const options = [ ]; interface IPopup { - show: boolean, - type: "reset" | "create" + show: boolean; + type: 'reset' | 'create'; } const CreateSchema = () => { @@ -54,11 +64,14 @@ const CreateSchema = () => { const [success, setSuccess] = useState(null); const [orgId, setOrgId] = useState(''); const [createLoader, setCreateLoader] = useState(false); - const [showPopup, setShowPopup] = useState({ show: false, type: "reset" }); + const [showPopup, setShowPopup] = useState({ + show: false, + type: 'reset', + }); const [isEcosystemData, setIsEcosystemData] = useState(); - const [btnState, setBtnState] = useState(false); + const [btnState, setBtnState] = useState(true); const [loading, setLoading] = useState(false); - + const initFormData: IFormData = { schemaName: '', schemaVersion: '', @@ -67,6 +80,7 @@ const CreateSchema = () => { attributeName: '', schemaDataType: 'string', displayName: '', + isRequired: false, }, ], }; @@ -81,12 +95,43 @@ const CreateSchema = () => { (async () => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); setOrgId(orgId); - })(); + })(); checkEcosystemData(); }, []); + + const areAllInputsFilled = (formData) => { + // Destructure formData to extract schemaName, schemaVersion, and attribute + const { schemaName, schemaVersion, attribute } = formData; + + // Check if schemaName and schemaVersion are filled + if (!schemaName || !schemaVersion) { + return false; + } + + // Check if at least one attribute is required + const isAtLeastOneRequired = attribute.some(attr => attr.isRequired); + + if (!isAtLeastOneRequired) { + return false; + } + + // Check if all attributes are filled + for (const attr of attribute) { + if (!attr.attributeName || !attr.schemaDataType || !attr.displayName) { + return false; + } + } + + return true; + }; + + + const submit = async (values: IFormData) => { + console.log('values::::', values); + setCreateLoader(true); const schemaFieldName: FieldName = { schemaName: values.schemaName, @@ -95,44 +140,46 @@ const CreateSchema = () => { orgId: orgId, }; - const createSchema = await createSchemas(schemaFieldName, orgId); - const { data } = createSchema as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { - if (data) { - setSuccess(data?.message); - setCreateLoader(false); - setLoading(true) - setTimeout(() => { - setSuccess(null); - window.location.href = pathRoutes?.organizations?.schemas; - }, 1500); - setTimeout(() => { - setShowPopup({ - type: "create", - show: false - }); - }, 2000); - } else { - setFailure(createSchema as string); - setCreateLoader(false); - } - } else { - setCreateLoader(false); - setFailure(createSchema as string); - setTimeout(() => { - setFailure(null); - }, 2000); - } - setTimeout(() => { - setShowPopup({ - type: "create", - show: false - }); - }, 2000); + // const createSchema = await createSchemas(schemaFieldName, orgId); + // const { data } = createSchema as AxiosResponse; + // if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + // if (data) { + // setSuccess(data?.message); + // setCreateLoader(false); + // setLoading(true); + // setTimeout(() => { + // setSuccess(null); + // window.location.href = pathRoutes?.organizations?.schemas; + // }, 1500); + // setTimeout(() => { + // setShowPopup({ + // type: 'create', + // show: false, + // }); + // }, 2000); + // } else { + // setFailure(createSchema as string); + // setCreateLoader(false); + // } + // } else { + // setCreateLoader(false); + // setFailure(createSchema as string); + // setTimeout(() => { + // setFailure(null); + // }, 2000); + // } + // setTimeout(() => { + // setShowPopup({ + // type: 'create', + // show: false, + // }); + // }, 2000); }; const submitSchemaCreationRequest = async (values: IFormData) => { setCreateLoader(true); + console.log('values::::', values); + const schemaFieldName = { endorse: true, attributes: values.attribute, @@ -144,25 +191,26 @@ const CreateSchema = () => { const createSchema = await createSchemaRequest(schemaFieldName, id, orgId); const { data } = createSchema as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { - setSuccess(data?.message); - setCreateLoader(false); - window.location.href = pathRoutes.ecosystem.endorsements; - setTimeout(() => { - setSuccess(null); - }, 2000); - } else { - setCreateLoader(false); - setFailure(createSchema as string); - setTimeout(() => { - setFailure(null); - }, 2000); - } + // if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + // setSuccess(data?.message); + // setCreateLoader(false); + // window.location.href = pathRoutes.ecosystem.endorsements; + // setTimeout(() => { + // setSuccess(null); + // }, 2000); + // } else { + // setCreateLoader(false); + // setFailure(createSchema as string); + // setTimeout(() => { + // setFailure(null); + // }, 2000); + // } setTimeout(() => { setShowPopup({ - type: "create", - show: false + type: 'create', + show: false, }); + setCreateLoader(false); }, 2000); }; @@ -171,42 +219,42 @@ const CreateSchema = () => { : 'Create Schema'; const submitButtonTitle = isEcosystemData?.isEcosystemMember ? { - title: 'Request Endorsement', - svg: ( - - - - ), - } - : { - title: 'Create', - svg: ( -
    + title: 'Request Endorsement', + svg: ( -
    - ), - }; + ), + } + : { + title: 'Create', + svg: ( +
    + + + +
    + ), + }; const confirmCreateSchema = () => { if ( @@ -224,56 +272,85 @@ const CreateSchema = () => { formData.attribute.forEach((element) => { updatedAttribute.push(Number(element)); }); + submit(formData); } }; - const validSameAttribute = (formikHandlers: FormikProps, index: number, field: "attributeName" | "displayName") => { - const attributeError: string | string[] | FormikErrors[] | undefined = formikHandlers?.errors?.attribute - const attributeTouched = formikHandlers?.touched?.attribute - const attributeValue = formikHandlers?.values?.attribute - const isErrorAttribute = attributeError && attributeError.length > 0 && attributeError[index] && attributeError[index][field] - const isTouchedAttribute = attributeTouched && attributeTouched.length > 0 && attributeTouched[index] && attributeTouched[index][field] - const isValueAttribute = attributeValue && attributeValue.length > 0 && attributeValue[index] && attributeValue[index][field] + const validSameAttribute = ( + formikHandlers: FormikProps, + index: number, + field: 'attributeName' | 'displayName', + ) => { + const attributeError: + | string + | string[] + | FormikErrors[] + | undefined = formikHandlers?.errors?.attribute; + const attributeTouched = formikHandlers?.touched?.attribute; + const attributeValue = formikHandlers?.values?.attribute; + const isErrorAttribute = + attributeError && + attributeError.length > 0 && + attributeError[index] && + attributeError[index][field]; + const isTouchedAttribute = + attributeTouched && + attributeTouched.length > 0 && + attributeTouched[index] && + attributeTouched[index][field]; + const isValueAttribute = + attributeValue && + attributeValue.length > 0 && + attributeValue[index] && + attributeValue[index][field]; if (!(isTouchedAttribute && isErrorAttribute) && isValueAttribute) { - const isValid = attributeValue.filter((item: IAttributes, i: number) => { - const itemAttribute = item[field]?.trim()?.toLocaleLowerCase() - const enteredAttribute = attributeValue[index][field]?.trim()?.toLocaleLowerCase() - if ((itemAttribute && enteredAttribute) && itemAttribute === enteredAttribute) { - return { - ...item, - index: i + const isValid = + attributeValue.filter((item: IAttributes, i: number) => { + const itemAttribute = item[field]?.trim()?.toLocaleLowerCase(); + const enteredAttribute = attributeValue[index][field] + ?.trim() + ?.toLocaleLowerCase(); + if ( + itemAttribute && + enteredAttribute && + itemAttribute === enteredAttribute + ) { + return { + ...item, + index: i, + }; } - } - }).length > 1 - return isValid + }).length > 1; + return isValid; } else { - return false + return false; } - } + }; - const inValidAttributes = (formikHandlers: FormikProps, propertyName: "attributeName" | "displayName") => { - const attributeValue: IAttributes[] = formikHandlers?.values?.attribute - const isValueAttribute = attributeValue && attributeValue.length > 0 + const inValidAttributes = ( + formikHandlers: FormikProps, + propertyName: 'attributeName' | 'displayName', + ) => { + const attributeValue: IAttributes[] = formikHandlers?.values?.attribute; + const isValueAttribute = attributeValue && attributeValue.length > 0; if (isValueAttribute) { - const seen: {[key: string]: boolean} = {}; + const seen: { [key: string]: boolean } = {}; for (const obj of attributeValue) { const propertyValue = obj[propertyName]; if (seen[propertyValue]) { - return true + return true; } seen[propertyValue] = true; } - - // No duplicates found return false; } else { - return true + return true; } - } + }; return (
    @@ -297,33 +374,43 @@ const CreateSchema = () => { validationSchema={yup.object().shape({ schemaName: yup.string().trim().required('Schema is required'), schemaVersion: yup - .string() - .matches( - schemaVersionRegex, - 'Enter valid schema version (eg. 0.1 or 0.0.1)', - ) - .required('Schema version is required'), + .string() + .matches( + schemaVersionRegex, + 'Enter valid schema version (eg. 0.1 or 0.0.1)', + ) + .required('Schema version is required'), attribute: yup.array().of( - yup.object().shape({ - attributeName: yup - .string() - .trim() - .required('Attribute name is required'), - displayName: yup - .string() - .trim() - .required('Display name is required'), - }), - ), - })} + yup.object().shape({ + attributeName: yup + .string() + .trim() + .required('Attribute name is required'), + displayName: yup + .string() + .trim() + .required('Display name is required'), + isRequired: yup.boolean(), // Define isRequired as boolean without validation + }).default(() => ({ isRequired: false })) // Default isRequired to false + ).required('At least one attribute is required') + .test({ + name: 'at-least-one-is-required', + message: 'At least one attribute must be required', + test: (value) => { + return value.some((attr) => attr.isRequired === true); + }, + }), + })} + + validateOnBlur validateOnChange enableReinitialize onSubmit={async (values): Promise => { setFormData(values); setShowPopup({ - type: "create", - show: true + type: 'create', + show: true, }); }} > @@ -344,13 +431,13 @@ const CreateSchema = () => { className="w-full bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" /> {formikHandlers.errors && - formikHandlers.touched.schemaName && - formikHandlers.errors.schemaName ? ( -
    @@ -371,19 +458,21 @@ const CreateSchema = () => { className="w-full bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" /> {formikHandlers.errors && - formikHandlers.touched.schemaVersion && - formikHandlers.errors.schemaVersion ? ( -
    - -
    +

    + You must select at least one attribute to create schema +

    +
    {(fieldArrayProps: any): JSX.Element => { const { form, remove, push } = fieldArrayProps; @@ -392,7 +481,10 @@ const CreateSchema = () => { const areFirstInputsSelected = values.schemaName && values.schemaVersion; - setBtnState(Boolean(areFirstInputsSelected)); + // setBtnState(Boolean(areFirstInputsSelected)); + const isAtLeastOneRequired = attribute.some(attr => attr.isRequired); + const btnState = Boolean(areFirstInputsSelected && isAtLeastOneRequired); + setBtnState(btnState); return (
    {attribute?.map( @@ -420,26 +512,36 @@ const CreateSchema = () => { placeholder="Attribute eg. NAME, ID" disabled={!areFirstInputsSelected} onChange={(e: any) => { - formikHandlers.handleChange(e) - formikHandlers.setFieldValue(`attribute[${index}].displayName`, e.target.value, true) + formikHandlers.handleChange(e); + formikHandlers.setFieldValue( + `attribute[${index}].displayName`, + e.target.value, + true, + ); }} className="w-full bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" /> - { - validSameAttribute(formikHandlers, index, 'attributeName') && - } + {validSameAttribute( + formikHandlers, + index, + 'attributeName', + ) && ( + + )} {formikHandlers.touched.attribute && - attribute[index] && - formikHandlers?.errors?.attribute && - formikHandlers?.errors?.attribute[ + attribute[index] && + formikHandlers?.errors?.attribute && + formikHandlers?.errors?.attribute[ index - ] && - formikHandlers?.touched?.attribute[ - index - ]?.attributeName && - formikHandlers?.errors?.attribute[index] - ?.attributeName ? ( -
    @@ -473,17 +575,17 @@ const CreateSchema = () => { })} {formikHandlers?.touched?.attribute && - attribute[index] && - formikHandlers?.errors?.attribute && - formikHandlers?.errors?.attribute[ + attribute[index] && + formikHandlers?.errors?.attribute && + formikHandlers?.errors?.attribute[ + index + ] && + formikHandlers?.touched?.attribute[ index - ] && - formikHandlers?.touched?.attribute[ - index - ]?.schemaDataType && - formikHandlers?.errors?.attribute[index] - ?.schemaDataType ? ( -
    @@ -502,21 +604,28 @@ const CreateSchema = () => { disabled={!areFirstInputsSelected} className="w-full bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" /> - { - validSameAttribute(formikHandlers, index, 'displayName') && - } + {validSameAttribute( + formikHandlers, + index, + 'displayName', + ) && ( + + )} {formikHandlers?.touched?.attribute && - attribute[index] && - formikHandlers?.errors?.attribute && - formikHandlers?.errors?.attribute[ + attribute[index] && + formikHandlers?.errors?.attribute && + formikHandlers?.errors?.attribute[ index - ] && - formikHandlers?.touched?.attribute[ - index - ]?.displayName && - formikHandlers?.errors?.attribute[index] - ?.displayName ? ( -
    +
    + +
    +
    +
    +
    {index === 0 && - values.attribute.length === 1 ? ( + values.attribute.length === 1 ? (
    { type="button" color="danger" onClick={() => remove(index)} - className={`${index === 0 && + className={`${ + index === 0 && values.attribute.length === 1 - ? 'hidden' - : 'block' - } flex justify-end focus:ring-0`} + ? 'hidden' + : 'block' + } flex justify-end focus:ring-0`} > {
    )}
    +
    + + {formikHandlers?.touched?.attribute && + attribute[index] && + formikHandlers?.errors?.attribute && + formikHandlers?.errors?.attribute[ + index + ] && + formikHandlers?.touched?.attribute[ + index + ]?.isRequired && + formikHandlers?.errors?.attribute[index] + ?.isRequired && + !attribute.some( + (item) => item.isRequired === true, + ) ? ( + + ) : null} + +
    {index === values.attribute.length - 1 && ( @@ -587,14 +759,26 @@ const CreateSchema = () => { attributeName: '', schemaDataType: 'string', displayName: '', + isRequired:false }) } disabled={ - !formikHandlers.isValid || !btnState + !areAllInputsFilled(formikHandlers.values) } > - - + + @@ -615,14 +799,22 @@ const CreateSchema = () => { + <>{console.log("formikHandlers.isValid",formikHandlers.isValid) + } - <>{console.log("formikHandlers.isValid",formikHandlers.isValid) - } diff --git a/src/commonComponents/CredentialDefinitionCard.tsx b/src/commonComponents/CredentialDefinitionCard.tsx index abcab12b8..5fb362fb5 100644 --- a/src/commonComponents/CredentialDefinitionCard.tsx +++ b/src/commonComponents/CredentialDefinitionCard.tsx @@ -1,6 +1,7 @@ import { Button, Card } from 'flowbite-react'; import { Roles } from '../utils/enums/roles'; +import CopyDid from './CopyDid'; interface IProps { credDeffName: string, @@ -23,64 +24,66 @@ const CredDeffCard = (props: IProps) => { } return ( - +
    {/* This will take up 2/3 of the available width on larger screens */}
    {props.credDeffName}
    - { - props.userRoles - && (props.userRoles.includes(Roles.OWNER) - || props.userRoles.includes(Roles.ADMIN) - || props.userRoles.includes(Roles.ISSUER) - ) - &&
    - +
    - Issue - -
    - }
    -

    - ID : {props.credentialDefinitionId} +

    + + ID: + + + +

    -

    - Schema ID:{props.schemaId} +

    + + Schema ID: + +

    + +

    Revocable: - <> - - {props.revocable ? 'Yes' : 'No'} - - - - + + {props?.revocable ? 'Yes' : 'No'} +
    -
    - - ) } diff --git a/src/commonComponents/SchemaCard.tsx b/src/commonComponents/SchemaCard.tsx index 9a7c15da4..81b025c3b 100644 --- a/src/commonComponents/SchemaCard.tsx +++ b/src/commonComponents/SchemaCard.tsx @@ -1,6 +1,7 @@ import { Card } from 'flowbite-react'; import { dateConversion } from '../utils/DateConversion'; import DateTooltip from '../components/Tooltip'; +import CopyDid from './CopyDid'; interface IProps { className?: string, @@ -22,8 +23,8 @@ const SchemaCard = (props: IProps) => { { props.onClickCallback(props.schemaId, props.attributes, props.issuerDid, props.created) }} - id="schema-cards" - className={`transform transition duration-500 ${props.isClickable !== false ? "hover:scale-105" : "hover:!cursor-default"} hover:bg-gray-50 cursor-pointer h-full w-full overflow-hidden`}> + id="schema-cards" + className={`transform transition duration-500 ${props.isClickable !== false ? "hover:scale-105 hover:bg-gray-50 cursor-pointer" : "hover:!cursor-default"} h-full w-full overflow-hidden`}>
    @@ -41,14 +42,28 @@ const SchemaCard = (props: IProps) => {
    -

    - Schema ID: {props.schemaId} +

    + Schema ID: + + { + props.isClickable !== false ? +

    {props?.schemaId}
    + : + } +

    -

    - Issuer DID: {props.issuerDid} +

    + Issuer DID: + + { + props.isClickable !== false ? +

    {props?.issuerDid}
    + : + } +

    -

    - Ledger: {props.issuerDid.split(":")[2]} +

    + Ledger: {props?.issuerDid?.split(":")[2]}

    diff --git a/src/components/Issuance/CredDefSelection.tsx b/src/components/Issuance/CredDefSelection.tsx index e4d9f1e94..21a546c55 100644 --- a/src/components/Issuance/CredDefSelection.tsx +++ b/src/components/Issuance/CredDefSelection.tsx @@ -153,9 +153,9 @@ const CredDefSelection = () => {
    ) : ( -
    +
    { const [schemaLoader, setSchemaLoader] = useState(true); @@ -31,13 +32,13 @@ const IssueCred = () => { const [issuanceLoader, setIssuanceLoader] = useState(false); const [failure, setFailure] = useState(null); const [schemaAttributesDetails, setSchemaAttributesDetails] = useState([]); - const [success, setSuccess]= useState(null) - const [error, setError]= useState(null) + const [success, setSuccess] = useState(null) + const [error, setError] = useState(null) useEffect(() => { getSchemaAndUsers(); getSchemaDetails(); - return(() => setUserLoader(false)) + return (() => setUserLoader(false)) }, []); const getSchemaAndUsers = async () => { @@ -49,7 +50,7 @@ const IssueCred = () => { setUserLoader(true); const selectedUsers = await getSelectedUsers(); const attributes = await getSchemaDetails(); - if (attributes && attributes.length) { + if (attributes && attributes.length && selectedUsers) { createIssuanceForm(selectedUsers, attributes, credDefId, orgId); } else { setFailure('Attributes are not available'); @@ -67,7 +68,7 @@ const IssueCred = () => { value: '', dataType: attr?.schemaDataType, })); - const issuancePayload = selectedUsers.map((user) => { + const issuancePayload = selectedUsers?.map((user) => { return { connectionId: user?.connectionId, attributes: attrObj, @@ -82,7 +83,7 @@ const IssueCred = () => { const getSchemaDetails = async (): Promise => { const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR); const parsedSchemaAttributes = JSON.parse(schemaAttributes) || []; - setSchemaAttributesDetails(parsedSchemaAttributes?.attribute) + setSchemaAttributesDetails(parsedSchemaAttributes?.attribute) return parsedSchemaAttributes.attribute; }; @@ -98,13 +99,19 @@ const IssueCred = () => { }; const getSelectedUsers = async (): Promise => { - const selectedUsers = await getFromLocalStorage(storageKeys.SELECTED_USER); - return JSON.parse(selectedUsers); + try { + const selectedUsers = await getFromLocalStorage(storageKeys.SELECTED_USER); + return JSON.parse(selectedUsers); + } catch (error) { + setUserLoader(false) + setError("Selected user details not found") + return [] + } }; const createAttributeValidationSchema = (dataType: string) => { let attributeSchema; - + if (dataType === 'string') { attributeSchema = Yup.string().typeError('Value must be a string'); } else if (dataType === 'number') { @@ -118,7 +125,7 @@ const IssueCred = () => { value: attributeSchema, }); }; - + const validationSchema = Yup.object().shape({ attributes: Yup.array().of( Yup.lazy(({ dataType }) => createAttributeValidationSchema(dataType)) @@ -139,7 +146,7 @@ const IssueCred = () => { setIssuanceLoader(true); const issueCredRes = await issueCredential(convertedAttributesValues); const { data } = issueCredRes as AxiosResponse; - + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { setSuccess(data?.message) window.location.href = `${pathRoutes.organizations.issuedCredentials}`; @@ -152,174 +159,173 @@ const IssueCred = () => { return (
    -
    +
    -
    - { - setError(null); - setSuccess(null); - }} - /> -

    +

    Issuance +

    - {!schemaLoader ? ( - + { + setError(null); + setSuccess(null); }} - > -
    -
    -
    - {schemaDetails.schemaName} -
    -

    - Version: {schemaDetails.version} + /> +

    + {!schemaLoader ? ( +
    + +
    +
    +
    + {schemaDetails.schemaName} +
    +

    + Version: {schemaDetails.version} +

    +
    +
    +
    +

    + Schema ID: + + + +

    +

    + Credential Definition: + + +

    -
    -
    -

    - Schema ID:{' '} - {schemaDetails.schemaId} -

    -

    - - Credential Definition: - {' '} - {schemaDetails.credDefId} -

    -
    - + +
    ) : ( '' )} {userLoader ? (
    - +
    ) : ( <> {issuanceFormPayload.length ? issuanceFormPayload.map((user) => ( - - {({ values }) => ( -
    - -
    -
    - {user.userName} -
    -
    -
    -
    - Connection Id -
    - : -

    {user.connectionId}

    -
    -

    Attributes

    -
    -
    - {schemaAttributesDetails.map((attr, index) => ( -
    -
    - - -
    -
    -
    - -
    + + {({ values }) => ( + + +
    +
    + {user.userName} +
    +
    +
    +
    + Connection Id +
    + : +

    {user.connectionId}

    +
    +

    Attributes

    +
    +
    + {schemaAttributesDetails.map((attr, index) => ( +
    +
    + +
    - ))} -
    -
    - - {failure && ( -
    - setFailure(null)} - > - -

    {failure}

    -
    -
    +
    +
    + +
    +
    + ))}
    - )} -
    - + +

    {failure}

    +
    +
    - - )} -
    - )) + )} +
    + +
    + + )} + + )) : ''} )} diff --git a/src/components/Resources/Schema/ViewSchema.tsx b/src/components/Resources/Schema/ViewSchema.tsx index bcbc8b910..7afc1f8d3 100644 --- a/src/components/Resources/Schema/ViewSchema.tsx +++ b/src/components/Resources/Schema/ViewSchema.tsx @@ -15,8 +15,8 @@ import { getCredDeffById, getSchemaById, } from '../../../api/Schema'; -import { getFromLocalStorage, setToLocalStorage } from '../../../api/Auth'; -import { useEffect, useState } from 'react'; +import { getFromLocalStorage } from '../../../api/Auth'; +import React, { useEffect, useState } from 'react'; import BackButton from '../../../commonComponents/backbutton'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../../BreadCrumbs'; @@ -31,7 +31,7 @@ import { ICheckEcosystem, checkEcosystem, getEcosystemId, getUserRoles } from '. import { createCredDefRequest } from '../../../api/ecosystem'; import EcosystemProfileCard from '../../../commonComponents/EcosystemProfileCard'; import { getLedgersPlatformUrl } from '../../../api/Agent'; -import React from 'react'; +import CopyDid from '../../../commonComponents/CopyDid'; interface Values { tagName: string; @@ -250,44 +250,44 @@ const ViewSchemas = () => { : 'Create Credential Definition'; const submitButtonTitle = isEcosystemData?.isEcosystemMember ? { - title: 'Request Endorsement', - svg: ( + title: 'Request Endorsement', + svg: ( + + + + ), + tooltip: 'Add new credential-definition request' + } + : { + title: 'Create', + svg: ( +
    - ), - tooltip: 'Add new credential-definition request' - } - : { - title: 'Create', - svg: ( -
    - - - -
    - ), - tooltip: 'Create new credential-definition' - }; +
    + ), + tooltip: 'Create new credential-definition' + }; return (
    @@ -321,7 +321,7 @@ const ViewSchemas = () => { style={{ overflow: 'auto' }} >
    -
    +
    Schema Details
    @@ -366,24 +366,28 @@ const ViewSchemas = () => {
    -

    +

    Name: {' '} {schemaDetails?.schema?.name}

    -

    +

    Version: {schemaDetails?.schema?.version}

    -

    - Schema ID: - {schemaDetails?.schemaId} +

    + Schema ID: + + +

    -

    - Issuer DID: - {schemaDetails?.schema?.issuerId} +

    + Issuer DID: + + +

    @@ -415,157 +419,157 @@ const ViewSchemas = () => { {(userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN)) && ( - -
    -
    - {formTitle} -
    -
    -
    - => { - await submit(values); - formikHandlers.resetForm(); - }} - > - {(formikHandlers): JSX.Element => ( -
    -
    -
    -
    -
    @@ -638,7 +642,6 @@ const ViewSchemas = () => { /> } - onClick={() => {}} /> )}
    diff --git a/src/components/RoleViewButton/index.tsx b/src/components/RoleViewButton/index.tsx index 3a469c636..1cddd7a21 100644 --- a/src/components/RoleViewButton/index.tsx +++ b/src/components/RoleViewButton/index.tsx @@ -5,13 +5,13 @@ import { Roles } from '../../utils/enums/roles'; import { getUserRoles } from '../../config/ecosystem' interface RoleViewButtonProps { - title?:string + title?: string buttonTitle?: string, svgComponent?: ReactElement, onClickEvent?: () => void, feature: string, isOutline?: boolean, - isPadding?: boolean, + isPadding?: boolean, } @@ -20,12 +20,12 @@ const RoleViewButton = ({ title, buttonTitle, svgComponent, onClickEvent, featur const [userRoles, setUserRoles] = useState([]) const getUserOrgRoles = async () => { - const roles = await getUserRoles() + const roles = await getUserRoles() setUserRoles(roles) } useEffect(() => { - getUserOrgRoles() + getUserOrgRoles() }, []) const isRoleAccess = (): boolean => { @@ -48,7 +48,7 @@ const RoleViewButton = ({ title, buttonTitle, svgComponent, onClickEvent, featur return true } return false - } else if (feature === Features.CREATE_ECOSYSTEMS) { + } else if (feature === Features.CREATE_ECOSYSTEMS) { if (userRoles.includes(Roles.OWNER) || userRoles.includes(Roles.ADMIN) ) { @@ -64,23 +64,20 @@ const RoleViewButton = ({ title, buttonTitle, svgComponent, onClickEvent, featur } return ( - <> - { - isRoleAccess() - && - } - + ) } diff --git a/src/components/Verification/CredDefSelection.tsx b/src/components/Verification/CredDefSelection.tsx index d19ccf54a..0ea97447d 100644 --- a/src/components/Verification/CredDefSelection.tsx +++ b/src/components/Verification/CredDefSelection.tsx @@ -139,7 +139,7 @@ const CredDefSelection = () => {
    :
    + onClickCallback={schemaSelectionCallback} isClickable={false} />
    }
    diff --git a/src/components/Verification/SchemaCredDefDetails.tsx b/src/components/Verification/SchemaCredDefDetails.tsx index a99309352..af8ca24b3 100644 --- a/src/components/Verification/SchemaCredDefDetails.tsx +++ b/src/components/Verification/SchemaCredDefDetails.tsx @@ -1,3 +1,4 @@ +import CopyDid from "../../commonComponents/CopyDid" interface SchemaCredDefProps { schemaCredDefList: object[] @@ -10,7 +11,7 @@ const SchemaCredDefDetails = ({ schemaCredDefList }: SchemaCredDefProps) => { {schemaCredDefList.map((item) => (
    - + {Object.values(item)[2] ? (
    @@ -21,9 +22,9 @@ const SchemaCredDefDetails = ({ schemaCredDefList }: SchemaCredDefProps) => { :
    {' '}
    - {Object.values(item)[2] - ? Object.values(item)[2] - : ''} +
    + +
    ) : ( @@ -40,9 +41,9 @@ const SchemaCredDefDetails = ({ schemaCredDefList }: SchemaCredDefProps) => { :
    {' '}
    - {Object.values(item)[1] - ? Object.values(item)[1] - : ''} +
    + +
    ) : ( diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index 27e58cb7a..d11585db9 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -13,11 +13,12 @@ import { pathRoutes } from "../../config/pathRoutes"; import CustomSpinner from "../CustomSpinner"; import BackButton from '../../commonComponents/backbutton' import type { SchemaDetail, SelectedUsers, VerifyCredentialPayload } from "./interface"; +import CopyDid from "../../commonComponents/CopyDid"; const VerificationCred = () => { const [attributeList, setAttributeList] = useState([]) const [proofReqSuccess, setProofReqSuccess] = useState('') - const [errMsg, setErrMsg] = useState(null) + const [errMsg, setErrMsg] = useState(null) const [schemaDetails, setSchemaDetails] = useState({ schemaName: '', version: '', schemaId: '', credDefId: '' }) @@ -27,11 +28,11 @@ const VerificationCred = () => { useEffect(() => { - const fetchData = async () => { + const fetchData = async () => { try { setLoading(true) await getSchemaAndUsers(); - const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR) + const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR) const parsedSchemaDetails = JSON.parse(schemaAttributes) || []; const attributes = parsedSchemaDetails.attribute.map((ele: any) => { const attributesName = ele.attributeName ? ele.attributeName : 'Not available'; @@ -68,7 +69,8 @@ const VerificationCred = () => { }; fetchData(); - return (()=>{ setRequestLoader(false); + return (() => { + setRequestLoader(false); }) }, []); @@ -116,10 +118,10 @@ const VerificationCred = () => { const credDefId = await getFromLocalStorage(storageKeys.CRED_DEF_ID); const schemaId = await getFromLocalStorage(storageKeys.SCHEMA_ID); const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - + const attributes = await selectedUsersData.map(user => ({ attributeName: user.name, - ...(credDefId ? { credDefId } : {}), + ...(credDefId ? { credDefId } : {}), schemaId: schemaId })); const verifyCredentialPayload: VerifyCredentialPayload = { @@ -144,7 +146,7 @@ const VerificationCred = () => { setRequestLoader(false); } }; - + const header = [ { columnName: '', width: 'w-0.5' }, { columnName: 'Attributes' } @@ -153,7 +155,7 @@ const VerificationCred = () => { return ( <>
    -
    +
    @@ -161,47 +163,53 @@ const VerificationCred = () => { Verification
    - {loading ? + {loading ?
    - -
    - : - -
    -
    -
    - {schemaDetails.schemaName} -
    -

    - Version: {schemaDetails.version} -

    -
    +
    -
    -

    - Schema ID: {schemaDetails.schemaId} -

    -

    - Credential definition restriction: - {schemaDetails.credDefId ? ' Yes' : ' No'} - -

    + : +
    + +
    +
    +
    + {schemaDetails.schemaName} +
    +

    + Version: {schemaDetails.version} +

    +
    +
    +
    +

    + Schema ID: + + + +

    +

    + Credential definition restriction: + + {schemaDetails.credDefId ? ' Yes' : ' No'} + +

    +
    +
    - } { (proofReqSuccess || errMsg) &&
    - setErrMsg(null)} - > - -

    - {proofReqSuccess || errMsg} -

    -
    -
    + setErrMsg(null)} + > + +

    + {proofReqSuccess || errMsg} +

    +
    +
    }
    @@ -220,13 +228,13 @@ const VerificationCred = () => { disabled={(requestLoader || !selectedUsersData.length)} className='text-base font-medium text-center text-white bg-primary-700 hover:!bg-primary-800 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 mt-2 ml-auto mr-8' > - - + + Request Proof -
    +
    ) From d8c9c758a8d85a7ec57f90c85e9c241a3ebcbcd2 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Mon, 19 Feb 2024 17:33:19 +0530 Subject: [PATCH 152/303] refactor: custom card for issuance and verification summary Signed-off-by: sanjay-k1910 --- src/commonComponents/SummaryCard.tsx | 57 ++++++++++++++++++++ src/components/Issuance/Issuance.tsx | 31 +---------- src/components/Verification/Verification.tsx | 31 +---------- 3 files changed, 61 insertions(+), 58 deletions(-) create mode 100644 src/commonComponents/SummaryCard.tsx diff --git a/src/commonComponents/SummaryCard.tsx b/src/commonComponents/SummaryCard.tsx new file mode 100644 index 000000000..cbb0165e5 --- /dev/null +++ b/src/commonComponents/SummaryCard.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import { Card } from 'flowbite-react'; +import CopyDid from '../commonComponents/CopyDid'; + +interface IProps { + schemaName: string; + version: string; + credDefId: string; + schemaId: string; + hideCredDefId: boolean; +} + +const SummaryCard = ({ schemaName, version, credDefId, schemaId, hideCredDefId }: Readonly) => { + return ( +
    + +
    +
    +
    + {schemaName} +
    +

    + Version: {version} +

    +
    +
    +
    +

    + Schema ID: + + + +

    + { + hideCredDefId ? +

    + Credential definition restriction: + + {credDefId ? ' Yes' : ' No'} + +

    + : +

    + Credential Definition: + + + +

    + + } +
    +
    +
    + ) +} + +export default SummaryCard \ No newline at end of file diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index 87390b108..b0a50ed0c 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -15,7 +15,7 @@ import { issueCredential } from '../../api/issuance'; import { pathRoutes } from '../../config/pathRoutes'; import { AlertComponent } from '../AlertComponent'; import type { Attribute, DataTypeAttributes, IssuanceFormPayload, SchemaDetails, SelectedUsers } from './interface' -import CopyDid from '../../commonComponents/CopyDid'; +import SummaryCard from '../../commonComponents/SummaryCard' const IssueCred = () => { const [schemaLoader, setSchemaLoader] = useState(true); @@ -178,34 +178,7 @@ const IssueCred = () => { />
    {!schemaLoader ? ( -
    - -
    -
    -
    - {schemaDetails.schemaName} -
    -

    - Version: {schemaDetails.version} -

    -
    -
    -
    -

    - Schema ID: - - - -

    -

    - Credential Definition: - - - -

    -
    -
    -
    + ) : ( '' )} diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index d11585db9..a7800a10e 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -13,7 +13,7 @@ import { pathRoutes } from "../../config/pathRoutes"; import CustomSpinner from "../CustomSpinner"; import BackButton from '../../commonComponents/backbutton' import type { SchemaDetail, SelectedUsers, VerifyCredentialPayload } from "./interface"; -import CopyDid from "../../commonComponents/CopyDid"; +import SummaryCard from "../../commonComponents/SummaryCard"; const VerificationCred = () => { const [attributeList, setAttributeList] = useState([]) @@ -168,34 +168,7 @@ const VerificationCred = () => {
    : -
    - -
    -
    -
    - {schemaDetails.schemaName} -
    -

    - Version: {schemaDetails.version} -

    -
    -
    -
    -

    - Schema ID: - - - -

    -

    - Credential definition restriction: - - {schemaDetails.credDefId ? ' Yes' : ' No'} - -

    -
    -
    -
    + } { (proofReqSuccess || errMsg) && From 51d3b0fc69cc712656b440de96bf81f62c92019e Mon Sep 17 00:00:00 2001 From: karan Date: Mon, 19 Feb 2024 20:06:50 +0530 Subject: [PATCH 153/303] feat: implemented required field validation in issuance via connection and email Signed-off-by: karan --- -new-table | 118 +++++++++ src/components/Issuance/EmailIssuance.tsx | 282 +++++++++++++--------- src/components/Issuance/Issuance.tsx | 106 +++++--- src/components/Issuance/interface.ts | 3 + 4 files changed, 364 insertions(+), 145 deletions(-) create mode 100644 -new-table diff --git a/-new-table b/-new-table new file mode 100644 index 000000000..dbd4bff66 --- /dev/null +++ b/-new-table @@ -0,0 +1,118 @@ + 289-refactor-landgin-page-ui + 533-ui-for-the-client-credentials + 541-implementation-create-schema-functionality-in-oob-bulk-and-email-issuance + 549-implementation-of-reset-password-functionality-for-keycloak-registration +* 580-predicate-based-proof-request-frontend + alignment-issue + api-standardization + api-standardization-changes + api-standardization-for-schema-module + apis-standardization + automation-issues + automation-test-issues + conversion-id-into-uuid + cred-def-select + dahboard-issues + dashboard-improvement + dashboard-schema + debouncing-issuance-verification + delete-invitation-access + develop + ecosystem-dashboard-issues + ecosystem-invitation-alignment + ecosystem-invitation-flow-issues + ecosystem-member-pagination + edit-org-alignment + error-handling + explore + feat-accept-reject-delete-functionality + feat-ecosystem-invitation + feat-ecosystem-memberlist + feat-oob-email-issuance + feat-subscription-ui + fix-automation-issues + fix-bulk-issuance-changes + fix-button-position + fix-connection-issue + fix-create-schema + fix-credentials-status + fix-dark-mode-responsiveness + fix-ecosystem-flow-issues + fix-ecosystem-invitation-issues + fix-error-message + fix-invitation-error + fix-issuance-minor-changes + fix-minor-issues + fix-minor-ui-changes + fix-oob-email-issuance + fix-org-roles + fix-prod-dev-merge + fix-schma-errors + fix-send-invitation-model + fix-ui-issues + fix-user-org-role + forgot-password + invitation-flow-issues + invitation-issues + live-issues-tracker + main + memberlist-error + merge-dev-main + merge-dev-to-main + merge-dev-to-qa + merge-develop-to-main + merge-qa-to-main + minor-fixes + minor-issues + org-drop-down + org-popup-error + out-of-band-issuance-and-verification + pagination-history-page + pagination-table + passkey-alignment + passkey-validation + predicates-for-verification + predicates-new-table + public-profile-edit-profile + qa + refactor-alert-component + refactor-api-issuance-verification-connection + refactor-bulk-issuance + refactor-connection-list + refactor-create-schema-ui + refactor-dasboard-memberlist + refactor-dashboard + refactor-ecosystem-invitation-flow + refactor-explore-button-position + refactor-invitations-page + refactor-memberlist + refactor-messages-issuance + refactor-public-profile + refactor-response + refactor-search + refactor-sent-invitation-button + refactor-table-error-message-consistancy + refactor-user-dashboard + refactor-user-profile + refactored-memberlist + refactored-memberlist-sonar + reset-error-message + reset-password + role-management + role-wise-access + schema-popup + schems-refactoring + session-management + sign-in-button + sign-up-page-alignment + space-between-word + space-between-words + table-enhancement + table-issues + table-refactor + upgrade-astro-v4 + user-session-management + verification-errors + verification-issue + verification-popup-alignment + verification-status diff --git a/src/components/Issuance/EmailIssuance.tsx b/src/components/Issuance/EmailIssuance.tsx index ffd6cddcd..35ac6fd54 100644 --- a/src/components/Issuance/EmailIssuance.tsx +++ b/src/components/Issuance/EmailIssuance.tsx @@ -80,8 +80,6 @@ const EmailIssuance = () => { (async () => { try { const data: ICheckEcosystem = await checkEcosystem(); - console.log("data",data); - setIsEcosystemData(data); } catch (error) { console.log(error); @@ -107,6 +105,7 @@ const EmailIssuance = () => { const transformedAttribute = { value: String(attribute.value || ''), name: attribute.name || '', + isRequired: attribute.isRequired, }; transformedEntry.attributes.push(transformedAttribute); }); @@ -129,7 +128,7 @@ const EmailIssuance = () => { }, 3000); handleReset(); setTimeout(() => { - window.location.href = pathRoutes?.organizations?.issuedCredentials; + // window.location.href = pathRoutes?.organizations?.issuedCredentials; }, 500); } else { setFailure(response as string); @@ -156,6 +155,7 @@ const EmailIssuance = () => { ...item, value: '', name: item?.attributeName, + isRequired: item?.isRequired, }; }), }; @@ -193,8 +193,7 @@ const EmailIssuance = () => { setCredentialSelected(null); setBatchName(''); setOpenResetModal(false); - if(selectInputRef.current){ - + if (selectInputRef.current) { selectInputRef.current.clearValue(); } }; @@ -213,11 +212,11 @@ const EmailIssuance = () => { const handleResetOpenConfirmation = () => { setOpenResetModal(true); }; - + const createSchemaTitle = isEcosystemData?.isEcosystemMember - ? { title: 'Schema Endorsement', svg: } - : { title: 'Create Schema', svg: }; - + ? { title: 'Schema Endorsement', svg: } + : { title: 'Create Schema', svg: }; + const MailError = ({ handler, formindex, @@ -390,11 +389,15 @@ const EmailIssuance = () => { .email('Invalid email address') .required('Email is required'), attributes: Yup.array().of( - Yup.object().shape({ - value: Yup.string().required( - 'All attribute are required', - ), - }), + Yup.lazy((value) => + Yup.object().shape({ + value: value.isRequired + ? Yup.string().required( + 'This field is required', + ) + : Yup.string(), + }), + ), ), }), ), @@ -432,6 +435,11 @@ const EmailIssuance = () => { .formData.length > 0 && arrayHelpers.form.values.formData.map( (formData1, index) => { + console.log( + 'formData1', + formData1, + ); + return (
    { '80px', }} > - Email ID + Email ID{' '} + + * + { className="w-full md:w-5/12 bg-gray-50 border border-gray-300 text-gray-900 sm:text-md rounded-lg focus:ring-primary-500 focus:border-primary-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" />
    - + ]?.email && + formikHandlers + ?.errors + ?.formData && + formikHandlers + ?.errors + ?.formData[ + index + ]?.email && ( + + )}
    {arrayHelpers.form .values.formData .length > 1 && ( -
    + -
    - )} + + + +
    + )}