From 672c4cebec08730476771e2eaf3731b33ebbc5d7 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Thu, 14 Dec 2023 17:50:02 +0530 Subject: [PATCH 1/4] feat: pagination and search in connection list Signed-off-by: sanjay-k1910 --- src/api/connection.ts | 18 ++++- src/components/ConnectionsList/index.tsx | 90 ++++++++++++++++++------ 2 files changed, 83 insertions(+), 25 deletions(-) diff --git a/src/api/connection.ts b/src/api/connection.ts index 5b670771b..464c1040d 100644 --- a/src/api/connection.ts +++ b/src/api/connection.ts @@ -3,10 +3,24 @@ import { storageKeys } from '../config/CommonConstant'; 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, + } -export const getConnectionsByOrg = async () => { +export const getConnectionsByOrg = async ({ + page, + itemPerPage, + search, + sortBy, + sortingOrder +}: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getAllConnections}`; + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getAllConnections}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortByValue=${sortingOrder}&sorting=${sortBy}`; + const axiosPayload = { url, config: await getHeaderConfigs(), diff --git a/src/components/ConnectionsList/index.tsx b/src/components/ConnectionsList/index.tsx index 345af8e52..4691aee42 100644 --- a/src/components/ConnectionsList/index.tsx +++ b/src/components/ConnectionsList/index.tsx @@ -1,8 +1,8 @@ 'use client'; import type { AxiosResponse } from 'axios'; -import { useEffect, useState } from 'react'; -import { getConnectionsByOrg } from '../../api/connection'; +import { ChangeEvent, useEffect, useState } from 'react'; +import { IConnectionListAPIParameter, getConnectionsByOrg } from '../../api/connection'; import DataTable from '../../commonComponents/datatable'; import type { TableData } from '../../commonComponents/datatable/interface'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; @@ -14,17 +14,25 @@ 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'; +const initialPageState = { + itemPerPage: 4, + page: 1, + search: "", + sortBy: "createDateTime", + sortingOrder: "ASC", + allSearch: "" +}; const ConnectionList = () => { + const [listAPIParameter, setListAPIParameter] = useState(initialPageState) const [connectionList, setConnectionList] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + const [totalItem, setTotalItem] = useState(0) - useEffect(() => { - getConnections(); - }, []); - - const getConnections = async () => { + const getConnections = async (apiParameter: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); const orgData = await getOrgDetails(); const checkWalletCreated = Boolean(orgData.orgDid); @@ -32,17 +40,18 @@ const ConnectionList = () => { if (orgId && checkWalletCreated) { setLoading(true); try { - const response = await getConnectionsByOrg(); + const response = await getConnectionsByOrg(apiParameter); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const connections = data?.data?.map( - (ele: { theirLabel: string; id: string; createdAt: string }) => { + setTotalItem(data?.data.totalItems) + const connections = data?.data?.data?.map( + (ele: { theirLabel: string; connectionId: string; createDateTime: string }) => { const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; - const connectionId = ele.id ? ele.id : 'Not available'; - const createdOn = ele?.createdAt - ? ele?.createdAt + const connectionId = ele.connectionId ? ele.connectionId : 'Not available'; + const createdOn = ele?.createDateTime + ? ele?.createDateTime : 'Not available'; return { data: [ @@ -77,12 +86,26 @@ const ConnectionList = () => { } }; + const header = [ { columnName: 'User' }, { columnName: 'Connection ID' }, { columnName: 'Created on' }, ]; + //onChange of Search input text + const searchInputChange = (e: ChangeEvent) => { + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1 + }) + }; + + useEffect(() => { + getConnections(listAPIParameter) + }, [listAPIParameter]) + return (
@@ -93,6 +116,9 @@ const ConnectionList = () => {

Connections

+
+ +
{error && ( { ) : connectionList && connectionList?.length > 0 ? ( -
- -
+ <> +
+ +
+ + { + Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && +
+ { + setListAPIParameter(prevState => ({ + ...prevState, + page: page + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + /> +
+ } + ) : (
Date: Thu, 14 Dec 2023 19:37:46 +0530 Subject: [PATCH 2/4] feat: pagination and search for issuance and verification Signed-off-by: sanjay-k1910 --- src/api/issuance.ts | 12 +- src/api/verification.ts | 19 +- src/components/ConnectionsList/index.tsx | 8 +- src/components/Issuance/ConnectionList.tsx | 103 ++-- src/components/Issuance/IssuedCrdentials.tsx | 266 +++++---- .../Verification/ConnectionList.tsx | 79 ++- .../VerificationCredentialList.tsx | 508 ++++++++++-------- src/components/Verification/interface.ts | 2 +- 8 files changed, 587 insertions(+), 410 deletions(-) diff --git a/src/api/issuance.ts b/src/api/issuance.ts index ee09590db..3ec910d3b 100644 --- a/src/api/issuance.ts +++ b/src/api/issuance.ts @@ -2,15 +2,19 @@ import axios from 'axios'; import { apiRoutes } from '../config/apiRoutes'; import { storageKeys } from '../config/CommonConstant'; import { - getHeaderConfigs, - getHeaderConfigsForFormData, + getHeaderConfigs } from '../config/GetHeaderConfigs'; import { axiosGet, axiosPost } from '../services/apiRequests'; import { getFromLocalStorage } from './Auth'; +import type { IConnectionListAPIParameter } from './connection'; -export const getIssuedCredentials = async () => { +export const getIssuedCredentials = async ({page, + itemPerPage, + search, + sortBy, + sortingOrder}: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getIssuedCredentials}`; + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getIssuedCredentials}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortByValue=${sortingOrder}&sorting=${sortBy}`; const axiosPayload = { url, diff --git a/src/api/verification.ts b/src/api/verification.ts index 177185d36..4bbc98eb4 100644 --- a/src/api/verification.ts +++ b/src/api/verification.ts @@ -4,10 +4,12 @@ import { storageKeys } from '../config/CommonConstant'; import { getHeaderConfigs } from '../config/GetHeaderConfigs'; import { axiosGet, axiosPost } from '../services/apiRequests'; import { getFromLocalStorage } from './Auth'; +import type { IConnectionListAPIParameter } from './connection'; export const verifyCredential = async (payload: any) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.verifyCredential}`; const axiosPayload = { + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.verifyCredential}`; + const axiosPayload = { url, payload, config: await getHeaderConfigs(), @@ -37,10 +39,16 @@ export const getVerificationCredential = async (state: IssueCredential) => { } }; -export const getVerificationList = async () => { +export const getVerificationList = async ({ + page, + itemPerPage, + search, + sortBy, + sortingOrder, +}: IConnectionListAPIParameter) => { const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.verifyCredential}` - + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.verifyCredential}?pageSize=${itemPerPage}&pageNumber=${page}&searchByText=${search}&sortByValue=${sortingOrder}&sorting=${sortBy}`; + const axiosPayload = { url, config: await getHeaderConfigs(), @@ -71,8 +79,7 @@ export const verifyPresentation = async (proofId:string) => { }; -export const getProofAttributes=async (proofId:string)=>{ - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); +export const getProofAttributes=async (proofId:string, orgId: string)=>{ const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.proofRequestAttributesVerification}/${proofId}/form`; const axiosPayload = { url, diff --git a/src/components/ConnectionsList/index.tsx b/src/components/ConnectionsList/index.tsx index 4691aee42..c72042c0a 100644 --- a/src/components/ConnectionsList/index.tsx +++ b/src/components/ConnectionsList/index.tsx @@ -18,11 +18,11 @@ import { Pagination } from 'flowbite-react'; import SearchInput from '../SearchInput'; const initialPageState = { - itemPerPage: 4, + itemPerPage: 9, page: 1, search: "", sortBy: "createDateTime", - sortingOrder: "ASC", + sortingOrder: "DESC", allSearch: "" }; const ConnectionList = () => { @@ -73,15 +73,19 @@ const ConnectionList = () => { }, ); setConnectionList(connections); + setError(null) } else { + setConnectionList([]) setError(response as unknown as string); } } catch (error) { + setConnectionList([]) setError(error as string); } finally { setLoading(false); } } else { + setConnectionList([]) setLoading(false); } }; diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index d054c1a63..442dac3b0 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -1,62 +1,73 @@ 'use client'; import type { AxiosResponse } from "axios"; -import { useEffect, useState } from "react"; -import { getConnectionsByOrg } from "../../api/connection"; +import React, { ChangeEvent, useEffect, useState } from "react"; +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 React from "react"; - +import SearchInput from "../SearchInput"; +import { Pagination } from "flowbite-react"; + +const initialPageState = { + itemPerPage: 9, + page: 1, + search: "", + sortBy: "createDateTime", + sortingOrder: "DESC", + allSearch: "" +}; const ConnectionList = (props: { selectConnection: (connections: TableData[]) => void; }) => { - - + const [listAPIParameter, setListAPIParameter] = useState(initialPageState) const [connectionList, setConnectionList] = useState([]) const [selectedConnectionList, setSelectedConnectionList] = useState([]) const [loading, setLoading] = useState(false) - const [searchText, setSearchText] = useState(""); + const [totalItem, setTotalItem] = useState(0) const [error, setError] = useState(null) //This useEffect is called when the searchText changes useEffect(() => { - getConnections() - }, []) + getConnections(listAPIParameter) + }, [listAPIParameter]) //Fetch the connection list against organization id - const getConnections = async () => { + const getConnections = async (apiParameter: IConnectionListAPIParameter) => { setLoading(true) - const response = await getConnectionsByOrg(); - const { data } = response as AxiosResponse - + const response = await getConnectionsByOrg(apiParameter); + const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const connections = data?.data?.map((ele) => { - const userName = ele?.theirLabel ? ele.theirLabel : 'Not available'; - const connectionId = ele.id ? ele.id : 'Not available' - const createdOn = ele?.createdAt ? ele?.createdAt : '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 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" /> -
- }, - { data: userName }, - { data: connectionId }, - {data: {dateConversion(createdOn)} }, - ] - } - }) + setTotalItem(data?.data.totalItems) + const connections = data?.data?.data?.map( + (ele: { theirLabel: string; connectionId: string; createDateTime: string }) => { + 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 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" /> +
+ }, + { data: userName }, + { data: connectionId }, + { data: {dateConversion(createdOn)} }, + ] + } + }) setConnectionList(connections) + setError(null) } else { + setConnectionList([]) setError(response as string) } @@ -71,6 +82,14 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => { columnName: 'Created on' } ] + //onChange of Search input text + const searchInputChange = (e: ChangeEvent) => { + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1 + }) + }; const selectConnection = (user: string, connectionId: string, checked: boolean) => { if (checked) { @@ -113,6 +132,9 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) =>

Connection List

+
+ +
className="p-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800"> + { + Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && +
+ { + setListAPIParameter(prevState => ({ + ...prevState, + page: page + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + /> +
+ } ) } diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 93447948d..348b33ad4 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -1,18 +1,17 @@ 'use client'; -import { ChangeEvent, useEffect, useState } from 'react'; +import React, { ChangeEvent, useEffect, useState } from 'react'; import { IssueCredential, IssueCredentialUserText } from '../../common/enums'; import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; -import { Button } from 'flowbite-react'; +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 React from 'react'; import RoleViewButton from '../RoleViewButton'; import SearchInput from '../SearchInput'; import type { TableData } from '../../commonComponents/datatable/interface'; @@ -22,144 +21,167 @@ import { getIssuedCredentials } from '../../api/issuance'; import { pathRoutes } from '../../config/pathRoutes'; import { getFromLocalStorage } from '../../api/Auth'; import { getOrgDetails } from '../../config/ecosystem'; +import type { IConnectionListAPIParameter } from '../../api/connection'; interface IssuedCredential { metadata: { [x: string]: { schemaId: string } }; connectionId: string; - updatedAt: string; + createDateTime: string; state: string; isRevocable: boolean; + schemaId: string; } + +const initialPageState = { + itemPerPage: 9, + page: 1, + search: "", + sortBy: "createDateTime", + sortingOrder: "DESC", + allSearch: "" +}; + const CredentialList = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [searchText, setSearchText] = useState(''); const [issuedCredList, setIssuedCredList] = useState([]); const [walletCreated, setWalletCreated] = useState(false); + const [listAPIParameter, setListAPIParameter] = useState(initialPageState) + const [totalItem, setTotalItem] = useState(0) - const getIssuedCredDefs = async () => { + const getIssuedCredDefs = async (listAPIParameter: IConnectionListAPIParameter) => { setLoading(true); - const orgData = await getOrgDetails(); - const isWalletCreated = Boolean(orgData.orgDid); - setWalletCreated(isWalletCreated); - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - if (orgId && isWalletCreated) { - const response = await getIssuedCredentials(); + try { + const orgData = await getOrgDetails(); + const isWalletCreated = Boolean(orgData.orgDid); + setWalletCreated(isWalletCreated); + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const { data } = response as AxiosResponse; + if (orgId && isWalletCreated) { + const response = await getIssuedCredentials(listAPIParameter); + setLoading(false) + const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const credentialList = data?.data?.map( - (issuedCredential: IssuedCredential) => { - const schemaName = issuedCredential.metadata[ - '_anoncreds/credential' - ].schemaId - ? issuedCredential.metadata['_anoncreds/credential'].schemaId + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setTotalItem(data?.data.totalItems) + const credentialList = data?.data?.data?.map( + (issuedCredential: IssuedCredential) => { + const schemaName = issuedCredential.schemaId + ? issuedCredential.schemaId .split(':') .slice(2) .join(':') - : 'Not available'; + : 'Not available'; - return { - data: [ - { - data: issuedCredential.connectionId - ? issuedCredential.connectionId - : 'Not available', - }, - { data: schemaName }, - { - data: ( - - {' '} - {dateConversion(issuedCredential.updatedAt)}{' '} - - ), - }, - { - data: ( - + {' '} + {dateConversion(issuedCredential.createDateTime)}{' '} + + ), + }, + { + data: ( + - {issuedCredential.state === IssueCredential.offerSent - ? IssueCredentialUserText.offerSent - : issuedCredential.state === IssueCredential.done - ? IssueCredentialUserText.done - : issuedCredential.state === IssueCredential.abandoned - ? IssueCredentialUserText.abandoned - : issuedCredential.state === - IssueCredential.requestReceived - ? IssueCredentialUserText.received - : issuedCredential.state === - IssueCredential.proposalReceived - ? IssueCredentialUserText.proposalReceived - : IssueCredentialUserText.credIssued} - - ), - }, - { - data: issuedCredential?.isRevocable ? ( - - ) : ( - Non revocable - ), - }, - ], - }; - }, - ); + 'bg-sky-300 text-primary-700 border border-sky-100 dark:border-sky-700 dark:bg-gray-700 dark:text-sky-500' + } text-xs font-medium mr-0.5 px-0.5 py-0.5 rounded-md border flex justify-center rounded-md items-center w-fit px-2`} + > + {issuedCredential.state === IssueCredential.offerSent + ? IssueCredentialUserText.offerSent + : issuedCredential.state === IssueCredential.done + ? IssueCredentialUserText.done + : issuedCredential.state === IssueCredential.abandoned + ? IssueCredentialUserText.abandoned + : issuedCredential.state === + IssueCredential.requestReceived + ? IssueCredentialUserText.received + : issuedCredential.state === + IssueCredential.proposalReceived + ? IssueCredentialUserText.proposalReceived + : IssueCredentialUserText.credIssued} + + ), + }, + { + data: issuedCredential?.isRevocable ? ( + + ) : ( + Non revocable + ), + }, + ], + }; + }, + ); - setIssuedCredList(credentialList); - } else { - setError(response as string); + setIssuedCredList(credentialList); + setError(null) + } else { + setError(response as string); + setIssuedCredList([]) + } } + } catch (error) { + console.error("ISSUED CREDENTIALS:::", error) + setIssuedCredList([]) } setLoading(false); }; - useEffect(() => { - let getData: NodeJS.Timeout; + // useEffect(() => { + // let getData: NodeJS.Timeout; - if (searchText.length >= 1) { - getData = setTimeout(() => { - getIssuedCredDefs(); - }, 1000); - return () => clearTimeout(getData); - } else { - getIssuedCredDefs(); - } + // if (searchText.length >= 1) { + // getData = setTimeout(() => { + // getIssuedCredDefs(); + // }, 1000); + // return () => clearTimeout(getData); + // } else { + // getIssuedCredDefs(); + // } + + // return () => clearTimeout(getData); + // }, [searchText]); - return () => clearTimeout(getData); - }, [searchText]); + useEffect(() => { + getIssuedCredDefs(listAPIParameter) + }, [listAPIParameter]) + //onChange of Search input text const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1 + }) }; const schemeSelection = () => { @@ -167,7 +189,7 @@ const CredentialList = () => { }; const refreshPage = () => { - getIssuedCredDefs(); + getIssuedCredDefs(listAPIParameter); }; const header = [ @@ -183,10 +205,13 @@ const CredentialList = () => {
-
-

+
+

Credentials

+
+ +
+ { + Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && +
+ { + setListAPIParameter(prevState => ({ + ...prevState, + page + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + /> +
+ }
) : (
diff --git a/src/components/Verification/ConnectionList.tsx b/src/components/Verification/ConnectionList.tsx index c9995b8f1..86c3f2132 100644 --- a/src/components/Verification/ConnectionList.tsx +++ b/src/components/Verification/ConnectionList.tsx @@ -1,38 +1,58 @@ 'use client'; import type { AxiosResponse } from "axios"; -import { useEffect, useState } from "react"; -import { getConnectionsByOrg } from "../../api/connection"; +import React, { ChangeEvent, useEffect, useState } from "react"; +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 React from "react"; +import SearchInput from "../SearchInput"; +import { Pagination } from "flowbite-react"; + +const initialPageState = { + itemPerPage: 9, + page: 1, + search: "", + sortBy: "createDateTime", + sortingOrder: "DESC", + allSearch: "" +}; const ConnectionList = (props: { selectConnection: (connections: TableData[]) => void; }) => { const [connectionList, setConnectionList] = useState([]) const [selectedConnectionList, setSelectedConnectionList] = useState([]) const [loading, setLoading] = useState(false) - const [searchText, setSearchText] = useState(""); + const [listAPIParameter, setListAPIParameter] = useState(initialPageState) + const [totalItem, setTotalItem] = useState(0) const [error, setError] = useState(null) useEffect(() => { - getConnectionsVerification() - }, []) + getConnectionsVerification(listAPIParameter) + }, [listAPIParameter]) - const getConnectionsVerification = async () => { - setLoading(true) - const response = await getConnectionsByOrg(); - const { data } = response as AxiosResponse + //onChange of Search input text + const searchInputChange = (e: ChangeEvent) => { + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1 + }) + }; + const getConnectionsVerification = async (apiParameter: IConnectionListAPIParameter) => { + setLoading(true) + const response = await getConnectionsByOrg(apiParameter); + const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const connections = data?.data?.map((ele) => { + setTotalItem(data?.data.totalItems) + const connections = data?.data?.data?.map((ele: { theirLabel: string, connectionId: string, createDateTime: string }) => { const userName = ele?.theirLabel ? ele?.theirLabel : 'Not available'; - const connectionId = ele?.id ? ele?.id : 'Not available' - const createdOn = ele?.createdAt ? ele?.createdAt : 'Not available' + const connectionId = ele?.connectionId ? ele?.connectionId : 'Not available' + const createdOn = ele?.createDateTime ? ele?.createDateTime : 'Not available' return { data: [{ data:
@@ -40,25 +60,27 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => const inputElement = event.target as HTMLInputElement; selectConnection(userName, connectionId, inputElement.checked) }} - value="" + 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" />
}, - { data: userName }, - { data: connectionId }, - {data: {dateConversion(createdOn)} }, + { data: userName }, + { data: connectionId }, + { data: {dateConversion(createdOn)} }, ] } }) setConnectionList(connections) + setError(null) } else { + setConnectionList([]) setError(response as string) } setLoading(false) } - + const verification_header = [ { columnName: '', width: 'w-0.5' }, { columnName: 'User' }, @@ -85,7 +107,6 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => useEffect(() => { props.selectConnection(selectedConnectionList); - }, [selectedConnectionList]) return ( @@ -95,8 +116,11 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) =>

Connection List

+
+ +
- { @@ -107,6 +131,21 @@ const ConnectionList = (props: { selectConnection: (connections: TableData[]) => className="p-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">

+ { + Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && +
+ { + setListAPIParameter(prevState => ({ + ...prevState, + page + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + /> +
+ } ) } diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 7d9b944c0..23200b7df 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -1,7 +1,7 @@ 'use client'; -import { Alert, Button } from 'flowbite-react'; -import { ChangeEvent, useEffect, useState } from 'react'; +import { Alert, Button, Pagination } from 'flowbite-react'; +import React, { ChangeEvent, useEffect, useState } from 'react'; import { ProofRequestState, ProofRequestStateUserText, @@ -13,7 +13,6 @@ import { verifyPresentation, } from '../../api/verification'; -import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; import CustomSpinner from '../CustomSpinner'; @@ -22,7 +21,6 @@ import DateTooltip from '../Tooltip'; import { EmptyListMessage } from '../EmptyListComponent'; import { Features } from '../../utils/enums/features'; import ProofRequest from './ProofRequestPopup'; -import React from 'react'; import type { RequestProof } from './interface'; import RoleViewButton from '../RoleViewButton'; import SearchInput from '../SearchInput'; @@ -31,10 +29,19 @@ 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'; + +const initialPageState = { + itemPerPage: 9, + page: 1, + search: "", + sortBy: "createDateTime", + sortingOrder: "DESC", + allSearch: "" +}; const VerificationCredentialList = () => { const [loading, setLoading] = useState(true); - const [searchText, setSearchText] = useState(''); const [verificationList, setVerificationList] = useState([]); const [openModal, setOpenModal] = useState(false); const [requestId, setRequestId] = useState(''); @@ -44,10 +51,13 @@ const VerificationCredentialList = () => { 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 getProofPresentationData = async (id: string) => { + const getProofPresentationData = async (id: string) => { try { - const response = await getProofAttributes(id); + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const response = await getProofAttributes(id, orgId); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes?.API_STATUS_SUCCESS) { @@ -60,7 +70,16 @@ const VerificationCredentialList = () => { } }; - const getproofRequestList = async () => { + //onChange of Search input text + const searchInputChange = (e: ChangeEvent) => { + setListAPIParameter({ + ...listAPIParameter, + search: e.target.value, + page: 1 + }) + }; + + const getproofRequestList = async (apiParameter: IConnectionListAPIParameter) => { await removeFromLocalStorage(storageKeys.SELECTED_USER); await removeFromLocalStorage(storageKeys.SCHEMA_ID); await removeFromLocalStorage(storageKeys.CRED_DEF_ID); @@ -73,216 +92,226 @@ const VerificationCredentialList = () => { setWalletCreated(isWalletCreated) const orgId = await getFromLocalStorage(storageKeys.ORG_ID); if (orgId && isWalletCreated) { - const response = await getVerificationList(); - const { data } = response as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - - const credentialList = data?.data?.map((requestProof: RequestProof) => { - return { - data: [ - { data: requestProof?.id ? requestProof?.id : 'Not available' }, - { - data: requestProof?.connectionId - ? requestProof?.connectionId - : 'Not available', - }, - { data: {dateConversion(requestProof.updatedAt)} }, - { - data: ( - - {requestProof?.state === ProofRequestState.requestSent - ? ProofRequestStateUserText.requestSent - : requestProof?.state === - ProofRequestState.presentationReceived - ? ProofRequestStateUserText.requestReceived - : requestProof?.state === ProofRequestState.done - ? ProofRequestStateUserText.done - : requestProof?.state === ProofRequestState.abandoned - ? ProofRequestStateUserText.abandoned - : ''} - - ), - }, - { - data: ( - - ), - }, - ], - }; - }); + + + View{' '} +

+ ) : ( +

+ {' '} + + + + + Verify +

+ )} + + ), + }, + ], + }; + }); - setVerificationList(credentialList); - } else { - setErrMsg(response as string); - } + setVerificationList(credentialList); + setErrMsg(null) + } else { + setVerificationList([]) + setErrMsg(response as string); } - } catch (error) { - setErrMsg('An error occurred while fetching the proof request list'); } + } catch (error) { + setVerificationList([]) + setErrMsg('An error occurred while fetching the proof request list'); + } - setLoading(false); - }; + setLoading(false); + }; - const presentProofById = async (id: string) => { - try { - const response = await verifyPresentation(id); - const { data } = response as AxiosResponse; + const presentProofById = async (id: string) => { + try { + const response = await verifyPresentation(id); + const { data } = response as AxiosResponse; - if (data?.statusCode === apiStatusCodes?.API_STATUS_CREATED) { - setOpenModal(false) - setProofReqSuccess(data.message) - setVerifyloader(false) - setTimeout(() => { - getproofRequestList() - }, 2000) - } else { - setOpenModal(false) - setErrMsg(response as string); - setVerifyloader(false) - } + if (data?.statusCode === apiStatusCodes?.API_STATUS_CREATED) { + setOpenModal(false) + setProofReqSuccess(data.message) + setVerifyloader(false) setTimeout(() => { - setProofReqSuccess('') - setErrMsg('') - }, 4000) - } catch (error) { + getproofRequestList(listAPIParameter) + }, 2000) + } else { setOpenModal(false) + setErrMsg(response as string); setVerifyloader(false) - console.error("An error occurred:", error); - setErrMsg("An error occurred while processing the presentation."); } - }; + setTimeout(() => { + setProofReqSuccess('') + setErrMsg('') + }, 4000) + } catch (error) { + setOpenModal(false) + setVerifyloader(false) + console.error("An error occurred:", error); + setErrMsg("An error occurred while processing the presentation."); + } + }; - const openProofRequestModel = (flag: boolean, requestId: string, state: boolean) => { - setRequestId(requestId) - setOpenModal(flag) - setView(state === "done" ? true : false) + const openProofRequestModel = (flag: boolean, requestId: string, state: string) => { + setRequestId(requestId) + setOpenModal(flag) + setView(state === "done") + } + const requestProof = async (proofVericationId: string) => { + if (proofVericationId) { + setOpenModal(false) + presentProofById(proofVericationId) } + } - const requestProof = async (proofVericationId: string) => { - if (proofVericationId) { - setOpenModal(false) - presentProofById(proofVericationId) - } - } + // useEffect(() => { + // let getData: NodeJS.Timeout - useEffect(() => { - let getData: NodeJS.Timeout + // if (searchText?.length >= 1) { + // getData = setTimeout(() => { + // getproofRequestList(listAPIParameter) + // }, 1000); + // return () => clearTimeout(getData); + // } else { + // getproofRequestList(listAPIParameter) + // } - if (searchText?.length >= 1) { - getData = setTimeout(() => { - getproofRequestList() - }, 1000); - return () => clearTimeout(getData); - } else { - getproofRequestList() - } + // return () => clearTimeout(getData) + // }, [searchText]) - return () => clearTimeout(getData) - }, [searchText]) + // const searchInputChange = (e: ChangeEvent) => { + // setSearchText(e.target.value); + // } - const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); - } + useEffect(() => { + getproofRequestList(listAPIParameter) + }, [listAPIParameter]) - const schemeSelection = () => { - window.location.href = pathRoutes.organizations.verification.schema - } - const header = [ - { columnName: 'Request Id' }, - { columnName: 'Connection Id' }, - { columnName: 'Requested On' }, - { columnName: 'Status' }, - { columnName: 'Action' }, - ]; + const schemeSelection = () => { + window.location.href = pathRoutes.organizations.verification.schema + } + + const header = [ + { columnName: 'Request Id' }, + { columnName: 'Connection Id' }, + { columnName: 'Requested On' }, + { columnName: 'Status' }, + { columnName: 'Action' }, + ]; - return ( -
+ return ( +
-
-

+
+

Verification List

+
+ +
{ walletCreated && @@ -318,49 +347,65 @@ const VerificationCredentialList = () => {
)} - { - !walletCreated && !loading ? -
- -
- : -
- { + { + !walletCreated && !loading ? +
+ +
+ : +
+ { - loading ? ( -
- + loading ? ( +
+ +
+ ) : verificationList && verificationList.length > 0 ? ( +
+
+ {verificationList && verificationList.length > 0 && + + }
- ) : verificationList && verificationList.length > 0 ? ( -
-
- {verificationList && verificationList.length > 0 && - - } + { + Math.ceil(totalItem / listAPIParameter?.itemPerPage) > 1 && +
+ { + setListAPIParameter(prevState => ({ + ...prevState, + page + })); + }} + totalPages={Math.ceil(totalItem / listAPIParameter?.itemPerPage)} + />
-
- ) : ( -
- - There isn't any data available. - -
- ) + } +
+ ) : ( +
+ + There isn't any data available. + +
+ ) - } -
- } + } +
+ } + { + userData && openProofRequestModel(false, "", "") } onSucess={ requestProof @@ -369,10 +414,11 @@ const VerificationCredentialList = () => { userData={userData} view={view} /> -
+ }
- ) - } +

+ ) +} - export default VerificationCredentialList; +export default VerificationCredentialList; diff --git a/src/components/Verification/interface.ts b/src/components/Verification/interface.ts index 2d7df7d26..17cc21107 100644 --- a/src/components/Verification/interface.ts +++ b/src/components/Verification/interface.ts @@ -26,7 +26,7 @@ export interface RequestProof { connectionId: string; threadId: string; autoAcceptProof: string; - updatedAt: string; + createDateTime: string; isVerified?: boolean; } From 7d449553e2bd74219050d89a2e40677c7236d091 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Fri, 15 Dec 2023 13:43:22 +0530 Subject: [PATCH 3/4] added missing attributes which are required for fetching verification list Signed-off-by: bhavanakarwade --- src/components/Verification/VerificationCredentialList.tsx | 7 +++---- src/components/Verification/interface.ts | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 23200b7df..c621024d3 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -97,10 +97,9 @@ const VerificationCredentialList = () => { if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setTotalItem(data?.data.totalItems) const credentialList = data?.data?.data?.map((requestProof: RequestProof) => { - console.log(8768768, requestProof) return { data: [ - { data: requestProof?.id ? requestProof?.id : 'Not available' }, + { data: requestProof?.presentationId ? requestProof?.presentationId : 'Not available' }, { data: requestProof?.connectionId ? requestProof?.connectionId @@ -147,10 +146,10 @@ const VerificationCredentialList = () => { onClick={() => { openProofRequestModel( true, - requestProof?.id, + requestProof?.presentationId, requestProof?.state, ); - getProofPresentationData(requestProof?.id); + getProofPresentationData(requestProof?.presentationId); }} > {requestProof?.state === 'done' ? ( diff --git a/src/components/Verification/interface.ts b/src/components/Verification/interface.ts index 17cc21107..062e5c295 100644 --- a/src/components/Verification/interface.ts +++ b/src/components/Verification/interface.ts @@ -20,6 +20,7 @@ export interface RequestProof { }; metadata: Record; id: string; + presentationId: string; createdAt: string; protocolVersion: string; state: string; From 69382f4cbb6bc3c878677d45eaf6513ec33e8801 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Fri, 15 Dec 2023 14:24:50 +0530 Subject: [PATCH 4/4] removed unnecessary code Signed-off-by: bhavanakarwade --- src/components/Issuance/IssuedCrdentials.tsx | 15 --------------- .../VerificationCredentialList.tsx | 19 ------------------- 2 files changed, 34 deletions(-) diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 348b33ad4..08e0e5be2 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -156,21 +156,6 @@ const CredentialList = () => { setLoading(false); }; - // useEffect(() => { - // let getData: NodeJS.Timeout; - - // if (searchText.length >= 1) { - // getData = setTimeout(() => { - // getIssuedCredDefs(); - // }, 1000); - // return () => clearTimeout(getData); - // } else { - // getIssuedCredDefs(); - // } - - // return () => clearTimeout(getData); - // }, [searchText]); - useEffect(() => { getIssuedCredDefs(listAPIParameter) }, [listAPIParameter]) diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index c621024d3..97b722274 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -263,25 +263,6 @@ const VerificationCredentialList = () => { } } - // useEffect(() => { - // let getData: NodeJS.Timeout - - // if (searchText?.length >= 1) { - // getData = setTimeout(() => { - // getproofRequestList(listAPIParameter) - // }, 1000); - // return () => clearTimeout(getData); - // } else { - // getproofRequestList(listAPIParameter) - // } - - // return () => clearTimeout(getData) - // }, [searchText]) - - // const searchInputChange = (e: ChangeEvent) => { - // setSearchText(e.target.value); - // } - useEffect(() => { getproofRequestList(listAPIParameter) }, [listAPIParameter])