From d42a9cdc3a2c907f5893a431911399515e47ef36 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Thu, 4 Apr 2024 17:20:51 +0530 Subject: [PATCH 01/34] feat: multi select connections while issuance Signed-off-by: bhavanakarwade --- src/components/Issuance/ConnectionList.tsx | 34 +- src/components/Issuance/Issuance.tsx | 419 +++++++++++++-------- src/components/Issuance/interface.ts | 10 +- src/pages/api/auth/signin.ts | 2 +- 4 files changed, 273 insertions(+), 192 deletions(-) diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index 253faba28..124515574 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -84,7 +84,7 @@ const ConnectionList = (props: {
) => { const inputElement = event.target as HTMLInputElement; @@ -150,29 +150,15 @@ const ConnectionList = (props: { ) => { if (checked) { // Needed for multiple connection selection - // setSelectedConnectionList((prevList) => [...prevList, { - // data: [ - // { - // data: user, - // }, { - // data: connectionId, - // }] - // }] - // ) - - // It is for single connection selection - setSelectedConnectionList([ - { - data: [ - { - data: user, - }, - { - data: connectionId, - }, - ], - }, - ]); + setSelectedConnectionList((prevList) => [...prevList, { + data: [ + { + data: user, + }, { + data: connectionId, + }] + }] + ) } else { setSelectedConnectionList((prevList) => prevList.filter( diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index 95adae670..623ce9c36 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -3,9 +3,9 @@ import * as Yup from 'yup'; import { Alert, Button, Card } from 'flowbite-react'; -import { Field, Form, Formik } from 'formik'; +import { Field, FieldArray, Form, Formik } from 'formik'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; -import { getFromLocalStorage } from '../../api/Auth'; +import { getFromLocalStorage, setToLocalStorage } from '../../api/Auth'; import React, { useEffect, useState } from 'react'; import BackButton from '../../commonComponents/backbutton'; import type { AxiosResponse } from 'axios'; @@ -57,6 +57,7 @@ const IssueCred = () => { createSchemaPayload(schemaId, credDefId); setUserLoader(true); const selectedUsers = await getSelectedUsers(); + const attributes = await getSchemaDetails(); if (attributes && attributes?.length) { createIssuanceForm(selectedUsers, attributes, credDefId, orgId); @@ -71,57 +72,66 @@ const IssueCred = () => { credDefId: string, orgId: string, ) => { - const attrObj = attributes.map((attr) => ({ - name: attr?.attributeName, - value: '', - dataType: attr?.schemaDataType, - isRequired: attr?.isRequired, - })); - const issuancePayload = selectedUsers.map((user) => { + + const credentialData = selectedUsers.map((user) => { + const attributesArray = attributes.map((attr) => ({ + name: attr.attributeName, + value: '', + isRequired: attr.isRequired + })); + return { - connectionId: user?.connectionId, - attributes: attrObj, - credentialDefinitionId: credDefId, - orgId, + connectionId: user.connectionId, + attributes: attributesArray, }; }); + + const issuancePayload = { + credentialData, + credentialDefinitionId: credDefId, + orgId, + }; + setIssuanceFormPayload(issuancePayload); setUserLoader(false); }; - + const createAttributeValidationSchema = ( - dataType: string, - isRequired: boolean, + name: string, + value: string, + isRequired: boolean ) => { - let attributeSchema; + let attributeSchema = Yup.string();; if (isRequired) { - attributeSchema = Yup.string().required('This field is required'); - } else if (dataType === 'string') { - attributeSchema = Yup.string().typeError('Value must be a string'); - } else if (dataType === 'number') { - attributeSchema = Yup.number().typeError('Value must be a number'); - } else if (dataType === 'date') { - attributeSchema = Yup.date().typeError('Value must be a valid date'); - } else { - attributeSchema = Yup.mixed(); + if (!value) { + attributeSchema = Yup.string().required(`${name} is required`); + } } + return Yup.object().shape({ value: attributeSchema, }); }; const validationSchema = Yup.object().shape({ - attributes: Yup.array().of( - Yup.lazy(({ dataType, isRequired }) => - createAttributeValidationSchema(dataType, isRequired), - ), - ), - }); + credentialData: Yup.array().of( + Yup.object().shape({ + attributes: Yup.array().of( + Yup.lazy((attr: any) => { + return createAttributeValidationSchema(attr?.name, attr?.value, attr?.isRequired) + }), + ), + }), + ), + }); + const getSchemaDetails = async (): Promise => { const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR); + const parsedSchemaAttributes = JSON.parse(schemaAttributes) || []; + setSchemaAttributesDetails(parsedSchemaAttributes?.attribute); return parsedSchemaAttributes.attribute; }; @@ -143,20 +153,29 @@ const IssueCred = () => { }; const handleSubmit = async (values: IssuanceFormPayload) => { - const convertedAttributes = values?.attributes.map((attr) => ({ - ...attr, - value: String(attr.value), - })); + const payload = { + credentialData: values.credentialData.map(item => { + return { + ...item, + attributes: item.attributes.map(attr => ({ + name: attr.name, + value: attr.value.toString() + })) + } + }), + credentialDefinitionId: values.credentialDefinitionId, + orgId: values.orgId + }; const convertedAttributesValues = { - ...values, - attributes: convertedAttributes, + ...payload, }; - + 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}`; @@ -165,7 +184,7 @@ const IssueCred = () => { setIssuanceLoader(false); } }; - + return (
@@ -200,137 +219,209 @@ const IssueCred = () => {
) : ( <> - {issuanceFormPayload?.length - ? issuanceFormPayload?.map((user) => ( - - {({ values, errors, touched, isValid }) => ( -
- -
-
- {user.userName} -
-
-
-
- Connection Id -
- - : - -

- {user?.connectionId} -

-
-

Attributes

-
-
- {schemaAttributesDetails && - schemaAttributesDetails?.length > 0 && - schemaAttributesDetails?.map((attr, index) => ( -
+
+ + {({ values, errors, touched, isValid }) => ( + + {failure && ( +
+ setFailure(null)}> + +

{failure}

+
+
+
+ )} + + {(arrayHelpers) => ( + <> + {values?.credentialData.map((user, index) => ( +
+ +
+
+
+ Connection Id +
+ + : + +

+ {user?.connectionId} +

+
+ {values.credentialData.length > 1 && (
- -
- - {errors?.attributes && - errors?.attributes[index] && - touched?.attributes && - touched?.attributes[index] && - errors?.attributes[index]?.value && ( -
- {errors?.attributes[index]?.value} -
- )} -
+ + + +
+ )} +
+ +

Attributes

+
+
+ {schemaAttributesDetails && + schemaAttributesDetails?.length > 0 && + schemaAttributesDetails?.map( + (attr, attrIndex) => ( +
+
+ +
+ { + try { + Yup.reach( + validationSchema, + `credentialData.${index}.attributes.${attrIndex}.value`, + ).validateSync(value, { + abortEarly: false, + }); + } catch (error) { + return error.message; + } + }} + /> + {errors?.credentialData?.[index] + ?.attributes?.[attrIndex] + ?.value && + touched?.credentialData?.[index] + ?.attributes?.[attrIndex] + ?.value && ( +
+ { + errors?.credentialData?.[ + index + ]?.attributes?.[attrIndex] + ?.value + } +
+ )}{' '} +
+
+
+ ), + )}
- ))} +
+
-
- - {failure && ( -
- setFailure(null)} - > - -

{failure}

-
-
-
- )} -
- + + +
- - )} - - )) - : ''} + Issue + +
+ + )} + +
)}
diff --git a/src/components/Issuance/interface.ts b/src/components/Issuance/interface.ts index 72179bcd7..48233b1a1 100644 --- a/src/components/Issuance/interface.ts +++ b/src/components/Issuance/interface.ts @@ -80,10 +80,14 @@ export interface Attributes { value: string; dataType: string; } -export interface IssuanceFormPayload { - userName?: string; + +export interface ICredentialdata { connectionId: string; attributes: Attributes[]; +} +export interface IssuanceFormPayload { + userName?: string; + credentialData: ICredentialdata[]; credentialDefinitionId: string; orgId: string; } @@ -95,7 +99,7 @@ export interface DataTypeAttributes { } export interface Attribute { - isRequired: string; + isRequired: string; attributeName: string; schemaDataType: string; displayName: string; diff --git a/src/pages/api/auth/signin.ts b/src/pages/api/auth/signin.ts index 2de546ed5..3917861dc 100644 --- a/src/pages/api/auth/signin.ts +++ b/src/pages/api/auth/signin.ts @@ -7,7 +7,7 @@ export const post: APIRoute = async ({ request, cookies, redirect }) => { const body = await request.json(); const sessionCookie = body?.data - + setToCookies(cookies, "session", sessionCookie?.access_token as string, { path: "/" }) From 74f83b3ae8717f09cbbc94dc3a2f6e469b9b9936 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Thu, 4 Apr 2024 20:20:33 +0530 Subject: [PATCH 02/34] refactor: modify connection list screen Signed-off-by: bhavanakarwade --- src/components/Issuance/Issuance.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index 623ce9c36..22c0357ae 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -57,7 +57,6 @@ const IssueCred = () => { createSchemaPayload(schemaId, credDefId); setUserLoader(true); const selectedUsers = await getSelectedUsers(); - const attributes = await getSchemaDetails(); if (attributes && attributes?.length) { createIssuanceForm(selectedUsers, attributes, credDefId, orgId); From 992a57135806116d1d48d833468e1d1c279e39af Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Thu, 4 Apr 2024 21:02:43 +0530 Subject: [PATCH 03/34] fix: resolved comments Signed-off-by: bhavanakarwade --- src/components/Issuance/Issuance.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index 22c0357ae..fb965eae8 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -117,7 +117,7 @@ const IssueCred = () => { credentialData: Yup.array().of( Yup.object().shape({ attributes: Yup.array().of( - Yup.lazy((attr: any) => { + Yup.lazy((attr) => { return createAttributeValidationSchema(attr?.name, attr?.value, attr?.isRequired) }), ), @@ -152,7 +152,7 @@ const IssueCred = () => { }; const handleSubmit = async (values: IssuanceFormPayload) => { - const payload = { + const issuancePayload = { credentialData: values.credentialData.map(item => { return { ...item, @@ -167,7 +167,7 @@ const IssueCred = () => { }; const convertedAttributesValues = { - ...payload, + ...issuancePayload, }; setIssuanceLoader(true); From 5dd94bc96dcd1647e875c5ca0898cc44b02af49d Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Wed, 10 Apr 2024 17:21:44 +0530 Subject: [PATCH 04/34] refactor: modify issuance ui Signed-off-by: bhavanakarwade --- src/components/Issuance/Issuance.tsx | 8 ++++++++ src/components/organization/WalletSpinup.tsx | 11 ++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index fb965eae8..4919a5e0c 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -102,6 +102,13 @@ const IssueCred = () => { ) => { let attributeSchema = Yup.string();; + if (name) { + name = name + .split('_') + .map(item => item.charAt(0).toUpperCase() + item.slice(1)) + .join(' '); + } + if (isRequired) { if (!value) { attributeSchema = Yup.string().required(`${name} is required`); @@ -286,6 +293,7 @@ const IssueCred = () => { credentialData: data, }; setIssuanceFormPayload(issuancePayload); + window.location.reload(); await setToLocalStorage(storageKeys.SELECTED_USER, data); diff --git a/src/components/organization/WalletSpinup.tsx b/src/components/organization/WalletSpinup.tsx index 17f7a429f..7a782dd42 100644 --- a/src/components/organization/WalletSpinup.tsx +++ b/src/components/organization/WalletSpinup.tsx @@ -240,7 +240,12 @@ const SharedAgentForm = ({ }; const validations = { - label: yup.string().required('Wallet label is required'), + label: yup + .string() + .required('Wallet label is required') + .trim() + .min(2, 'Wallet label must be at least 2 characters') + .max(25, 'Wallet label must be at most 25 characters'), method: yup.string().required('Method is required'), ...(DidMethod.INDY === selectedLedger || DidMethod.POLYGON === selectedLedger) && { network: yup.string().required('Network is required') }, ...(DidMethod.INDY === selectedLedger) && { ledger: yup.string().required('Ledger is required') }, @@ -710,10 +715,6 @@ const DedicatedAgentForm = ({ .max(20, 'Wallet name must be at most 20 characters') .trim() .required('Wallet name is required') - .matches( - /^[A-Za-z0-9-][^ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]*$/, - 'Wallet name must be alphanumeric only', - ) .label('Wallet name'), password: yup .string() From 8f24483eefe85960f4afedbf144586e88ca0bd44 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Fri, 12 Apr 2024 15:50:14 +0530 Subject: [PATCH 05/34] fix: modify query param name Signed-off-by: bhavanakarwade --- src/api/issuance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/issuance.ts b/src/api/issuance.ts index 8544d06ba..981702bfd 100644 --- a/src/api/issuance.ts +++ b/src/api/issuance.ts @@ -14,7 +14,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}&sortBy=${sortingOrder}&sortField=${sortBy}`; + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Issuance.getIssuedCredentials}?pageSize=${itemPerPage}&pageNumber=${page}&search=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; const axiosPayload = { url, config: await getHeaderConfigs(), From 7c6c3bce030df5236327d9dbd535fa150ad7081c Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Fri, 12 Apr 2024 16:54:44 +0530 Subject: [PATCH 06/34] fix: dark mode issues Signed-off-by: bhavanakarwade --- src/components/Authentication/Svg.tsx | 2 +- src/components/Ecosystem/Dashboard.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Authentication/Svg.tsx b/src/components/Authentication/Svg.tsx index b7fab88e2..f0fab302e 100644 --- a/src/components/Authentication/Svg.tsx +++ b/src/components/Authentication/Svg.tsx @@ -1,5 +1,5 @@ export const PassVisible = () => ( - {
- {/* Keep this code as it is, this is required in future use. */} - {/*
  • - -
  • */}
    @@ -86,7 +104,7 @@ const Connections = () => { aria-labelledby="profile-tab" > -
    +

    Selected Users

    @@ -94,10 +112,10 @@ const Connections = () => {
    - {selectedConnectionList.length ? ( + {selectedConnections.length ? (
    - {/* Keep this code as it is, this is required in future use. */} - {/*
    - -
    */}
    ); diff --git a/src/components/Issuance/interface.ts b/src/components/Issuance/interface.ts index 48233b1a1..923810aff 100644 --- a/src/components/Issuance/interface.ts +++ b/src/components/Issuance/interface.ts @@ -60,6 +60,7 @@ export interface IConnectionList { theirLabel: string; connectionId: string; createDateTime: string; + checked?: boolean; } export interface SchemaDetails { diff --git a/src/config/CommonConstant.ts b/src/config/CommonConstant.ts index 4f8347804..826ba141a 100644 --- a/src/config/CommonConstant.ts +++ b/src/config/CommonConstant.ts @@ -26,6 +26,7 @@ export const storageKeys = { PERMISSIONS: 'user_permissions', USER_EMAIL: 'user_email', SELECTED_USER:'selected_user', + SELECTED_CONNECTIONS: 'selected_connections', SCHEMA_ID:'schema_id', SCHEMA_ATTR:'schema_attr', CRED_DEF_ID:'cred_def_id', From e8c68100e93c84966c70fcdffe02497bc388231d Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Tue, 23 Apr 2024 11:07:55 +0530 Subject: [PATCH 12/34] fix: checkoboxes state change functionality Signed-off-by: bhavanakarwade --- src/components/Issuance/Issuance.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index 4919a5e0c..45de37e84 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -139,6 +139,7 @@ const IssueCred = () => { const parsedSchemaAttributes = JSON.parse(schemaAttributes) || []; setSchemaAttributesDetails(parsedSchemaAttributes?.attribute); + return parsedSchemaAttributes.attribute; }; From 41b6ef7ea97719a0fd2a658e89187fd79e029d99 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Tue, 23 Apr 2024 13:03:53 +0530 Subject: [PATCH 13/34] fix: issue button click Signed-off-by: bhavanakarwade --- src/components/Issuance/Issuance.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index 45de37e84..f5fa5cea6 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -76,6 +76,7 @@ const IssueCred = () => { const attributesArray = attributes.map((attr) => ({ name: attr.attributeName, value: '', + dataType: attr?.schemaDataType, isRequired: attr.isRequired })); @@ -139,7 +140,7 @@ const IssueCred = () => { const parsedSchemaAttributes = JSON.parse(schemaAttributes) || []; setSchemaAttributesDetails(parsedSchemaAttributes?.attribute); - + return parsedSchemaAttributes.attribute; }; @@ -401,7 +402,7 @@ const IssueCred = () => {
    +
    +
    + ); +}; + +export default AddOrganizationInEcosystem; diff --git a/src/components/Ecosystem/Dashboard.tsx b/src/components/Ecosystem/Dashboard.tsx index edb48188f..4715bc834 100644 --- a/src/components/Ecosystem/Dashboard.tsx +++ b/src/components/Ecosystem/Dashboard.tsx @@ -292,177 +292,199 @@ const Dashboard = () => { {ecosystemDetails ? (
    {isEcosystemLead ? ( +
    -
    -
    - {ecosystemDetails?.logoUrl ? ( - - ) : ( - - )} -
    -
    -
    -

    - {ecosystemDetails?.name} -

    -

    - {ecosystemDetails?.description} -

    -
    - - Role:{' '} - {' '} - -
    -
    - - Endorsement Flow - {' '} - : - - {ecosystemDetails.autoEndorsement - ? ' Sign and Submit' - : ' Sign'} - -
    + > +
    + {ecosystemDetails?.logoUrl ? ( + + ) : ( + + )} +
    +
    +
    +

    + {ecosystemDetails?.name} +

    +

    + {ecosystemDetails?.description} +

    +
    + + Role:{' '} + {' '} +
    -
    -
    +
    +
    + - {dropdownOpen && isAccess ? ( - ( - - )} - dismissOnClick={true} - > - { - EditEcosystemOrgModal(); - }} + + + + My Organizations + + + + {dropdownOpen && isAccess ? ( + ( +
    Edit Ecosystem
    -
    -
    - ) : ( - + + )} + dismissOnClick={true} + > + { + EditEcosystemOrgModal(); + }} > - - - )} -
    +
    Edit Ecosystem
    + + + ) : ( + + )}
    +
    ) : ( +
    +
    +
    + {ecosystemDetails?.logoUrl ? ( + + ) : ( + + )} +
    +
    -
    -
    - {ecosystemDetails?.logoUrl ? ( - - ) : ( - - )} +

    + {ecosystemDetails?.name} +

    +

    + {ecosystemDetails?.description} +

    +
    +
    + + Ecosystem Owner + + :{' '} + + {leadOrg} +
    -
    -
    -

    - {ecosystemDetails?.name} -

    -

    - {ecosystemDetails?.description} -

    -
    -
    - - Ecosystem Owner - - :{' '} - - {leadOrg} - -
    -
    - - Ecosystem Lead - {' '} - : - - {leadOrg} - -
    -
    - - Joined since - {' '} - : - - - {dateConversion(ecosystemDetails.joinedDate || '')} - - -
    +
    + + Ecosystem Lead + {' '} + : + + {leadOrg} +
    - Endorsement Flow + Joined since {' '} : - {ecosystemDetails.autoEndorsement - ? ' Sign and Submit' - : ' Sign'} + + {dateConversion(ecosystemDetails.joinedDate || '')} +
    -
    - Role: {' '} - +
    + + Endorsement Flow + {' '} + : + + {ecosystemDetails.autoEndorsement + ? ' Sign and Submit' + : ' Sign'} +
    +
    + Role: {' '} + +
    +
    )}
    @@ -526,11 +548,10 @@ const Dashboard = () => { { }; const getEcosystemMembers = async (apiParameter: IMemberListAPIParameter) => { - const userOrgId = await getFromLocalStorage(storageKeys.ORG_ID); + const userProfile = await getFromLocalStorage(storageKeys.USER_PROFILE) + const parsedUserProfileData = JSON.parse(userProfile); + const userId = parsedUserProfileData.id; + setLoading(true); const response = await getEcosystemMemberList(apiParameter); const { data } = response as AxiosResponse; @@ -151,7 +155,8 @@ const MemberList = () => { > {member?.ecosystemRole?.name} - {member?.orgId === userOrgId ? '(You)' : ''} + {member.organisation.userOrgRoles.some((item) => item.userId === userId) ? '(You)' : ''} + ) : ( 'Not available' diff --git a/src/components/organization/WalletSpinup.tsx b/src/components/organization/WalletSpinup.tsx index 7a782dd42..562cf43a9 100644 --- a/src/components/organization/WalletSpinup.tsx +++ b/src/components/organization/WalletSpinup.tsx @@ -935,7 +935,7 @@ const WalletSpinup = (props: { : `${values?.ledger}:${values?.network}`, domain: values.method === DidMethod.WEB ? domain : '', role: values.method === DidMethod.INDY ? values?.role || 'endorser' : '', - endorserDid: values?.endorserDid, + endorserDid: values?.endorserDid || '', clientSocketId: SOCKET.id, }; const orgId = await getFromLocalStorage(storageKeys.ORG_ID); diff --git a/src/components/organization/interfaces/index.ts b/src/components/organization/interfaces/index.ts index 566b67047..eaf6bcdbd 100644 --- a/src/components/organization/interfaces/index.ts +++ b/src/components/organization/interfaces/index.ts @@ -6,6 +6,10 @@ export interface UserOrgRole { orgRole: OrgRole } +interface IEcosystemOrgs { + ecosystemId: string; +} + export interface Organisation { logoFile: string id: string @@ -21,7 +25,9 @@ export interface Organisation { userOrgRoles: UserOrgRole[] org_agents: OrgAgent[] publicProfile: boolean - + checked?: boolean | undefined + ecosystemOrgs?: IEcosystemOrgs[] + error?: string; } export interface OrgRole { diff --git a/src/config/CommonConstant.ts b/src/config/CommonConstant.ts index 826ba141a..b4b4e9320 100644 --- a/src/config/CommonConstant.ts +++ b/src/config/CommonConstant.ts @@ -11,7 +11,8 @@ 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_DELETED : 202, + API_STATUS_PARTIALLY_COMPLETED : 206, API_STATUS_BAD_REQUEST : 400, API_STATUS_UNAUTHORIZED : 401, API_STATUS_NOT_FOUND : 404 @@ -37,5 +38,7 @@ export const storageKeys = { ECOSYSTEM_ROLE: "ecosystem_role", SOCKET_ID: "socket_id", LEDGER_ID: "ledger_id", - ORG_INFO:'organization_Info' + ORG_INFO:'organization_Info', + SELECT_ORG_IN_ECOSYSTEM: 'select_orgs_in_ecosystem', + ERROR_ORG_IN_ECOSYSTEM: 'error_orgs_in_ecosystem' } diff --git a/src/config/pathRoutes.ts b/src/config/pathRoutes.ts index 163af1fa3..d4df16e15 100644 --- a/src/config/pathRoutes.ts +++ b/src/config/pathRoutes.ts @@ -56,6 +56,7 @@ export const pathRoutes = { endorsements: '/ecosystems/endorsement', invitation: '/ecosystems/invitation', sentinvitation: '/ecosystems/invitations', + addOrgs: '/ecosystems/dashboard/add-organizations' }, documentation: { root: envConfig.PLATFORM_DATA.docs diff --git a/src/pages/ecosystems/dashboard/add-organizations.astro b/src/pages/ecosystems/dashboard/add-organizations.astro new file mode 100644 index 000000000..8c53d6e36 --- /dev/null +++ b/src/pages/ecosystems/dashboard/add-organizations.astro @@ -0,0 +1,16 @@ +--- +import LayoutSidebar from '../../../app/LayoutSidebar.astro'; +import { checkUserSession } from '../../../utils/check-session'; +import { pathRoutes } from '../../../config/pathRoutes'; +import AddOrganizationInEcosystem from '../../../components/AddOrganizationInEcosystem'; + +const response = await checkUserSession({cookies: Astro.cookies, currentPath: Astro.url.pathname}); +const route = pathRoutes.auth.sinIn; +if (!response.authorized) { + return Astro.redirect(response.redirect); +} +--- + + + + diff --git a/src/pages/ecosystems/dashboard.astro b/src/pages/ecosystems/dashboard/index.astro similarity index 56% rename from src/pages/ecosystems/dashboard.astro rename to src/pages/ecosystems/dashboard/index.astro index 7d351ab56..f417ea61c 100644 --- a/src/pages/ecosystems/dashboard.astro +++ b/src/pages/ecosystems/dashboard/index.astro @@ -1,8 +1,8 @@ --- -import LayoutSidebar from '../../app/LayoutSidebar.astro'; -import Dashboard from '../../components/Ecosystem/Dashboard'; -import { checkUserSession } from '../../utils/check-session'; -import { pathRoutes } from '../../config/pathRoutes'; +import LayoutSidebar from '../../../app/LayoutSidebar.astro'; +import Dashboard from '../../../components/Ecosystem/Dashboard'; +import { checkUserSession } from '../../../utils/check-session'; +import { pathRoutes } from '../../../config/pathRoutes'; const response = await checkUserSession({cookies: Astro.cookies, currentPath: Astro.url.pathname}); const route: string = pathRoutes.auth.sinIn From 06599e8e475bc5e8737a85accc24c72d3d46a90f Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Fri, 26 Apr 2024 19:15:41 +0530 Subject: [PATCH 17/34] refactor: dockerfile changes Signed-off-by: bhavanakarwade --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 56f54472e..16aadce3a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,4 +27,4 @@ COPY --from=build /app/node_modules ./node_modules COPY --from=build /app/package.json ./ COPY --from=build /app/dist ./dist EXPOSE 3000 -CMD [ "npm", "run", "preview" ] \ No newline at end of file +CMD ["deno", "run", "--allow-net", "--allow-read", "--allow-env", "./dist/server/entry.mjs"] \ No newline at end of file From 34afbe074fbbaf97a8fae2383bb9ac1de7c686c5 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Mon, 29 Apr 2024 23:17:12 +0530 Subject: [PATCH 18/34] refactor: proof request payload for w3c format Signed-off-by: pranalidhanavade --- src/components/Verification/Verification.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index 7ed5c107a..d9abcb51e 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -161,13 +161,16 @@ const VerificationCred = () => { schemaId: schemaId, })); - const verifyCredentialPayload: VerifyCredentialPayload = { + const verifyCredentialPayload = { connectionId: JSON.parse(userData)[0]?.connectionId, - attributes: attributes, comment: 'string', orgId: orgId, + proofFormats: { + indy: { + attributes: attributes, + } + } }; - if (attributes) { const response = await verifyCredential(verifyCredentialPayload); const { data } = response as AxiosResponse; From 7bd10818b2425bac02e44343a311843ee608a408 Mon Sep 17 00:00:00 2001 From: Krishna Date: Thu, 2 May 2024 12:32:53 +0530 Subject: [PATCH 19/34] fix: pagination parameter name to sync with backend Signed-off-by: Krishna --- src/api/verification.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/verification.ts b/src/api/verification.ts index f47b654ec..cf32e8bd2 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}&sortBy=${sortingOrder}&sortField=${sortBy}`; + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.Verification.verifyCredential}?pageSize=${itemPerPage}&pageNumber=${page}&search=${search}&sortBy=${sortingOrder}&sortField=${sortBy}`; const axiosPayload = { url, From ef12134dae68926061c77a4a92a896940953ae21 Mon Sep 17 00:00:00 2001 From: Krishna Date: Wed, 15 May 2024 13:35:40 +0530 Subject: [PATCH 20/34] fix: image uri issue Signed-off-by: Krishna --- .../organization/EditOrgdetailsModal.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index ca25fdbc9..30366217c 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -13,6 +13,15 @@ import defaultUserIcon from '../../../public/images/person_FILL1_wght400_GRAD0_o import { processImage } from '../../utils/processImage'; import FormikErrorMessage from '../../commonComponents/formikerror/index' +interface IUpdateOrgPayload { + orgId: string | undefined; + name: string; + description: string; + website: string; + isPublic: boolean | undefined; + logo?: string; +} + const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { const [logoImage, setLogoImage] = useState({ logoFile: '', @@ -82,7 +91,7 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { const submitUpdateOrganization = async (values: Values) => { setLoading(true); - const orgData = { + const orgData: IUpdateOrgPayload = { orgId: props?.orgData?.id, name: values.name, description: values.description, @@ -90,6 +99,13 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { website: values.website, isPublic: isPublic, }; + + const logo = (logoImage?.imagePreviewUrl as string) || props?.orgData?.logoUrl + + if ((logo?.includes('data:image/') && logo?.includes(';base64'))) { + orgData['logo'] = logo; + } + try { const response = await updateOrganization( orgData, From 6f962d659c30750a31463336695685e3bf731628 Mon Sep 17 00:00:00 2001 From: Krishna Date: Thu, 16 May 2024 11:59:33 +0530 Subject: [PATCH 21/34] fix: optional logo url addition while updating org details Signed-off-by: Krishna --- src/components/organization/EditOrgdetailsModal.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index 30366217c..71ba96ce2 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -95,7 +95,6 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { orgId: props?.orgData?.id, name: values.name, description: values.description, - logo: (logoImage?.imagePreviewUrl as string) || props?.orgData?.logoUrl, website: values.website, isPublic: isPublic, }; From 29f96324c3bc6d2eb8eb6a9df2501efabcec1bed Mon Sep 17 00:00:00 2001 From: bhavanakarwade <137506897+bhavanakarwade@users.noreply.github.com> Date: Thu, 16 May 2024 13:45:53 +0530 Subject: [PATCH 22/34] feat: create new did and set primary did (#673) * feat: create and update did Signed-off-by: sanjay.khatal * feat: implement create new did and set primary did ui Signed-off-by: bhavanakarwade * reafctor: interface name Signed-off-by: bhavanakarwade * refactor: payload type Signed-off-by: bhavanakarwade * fix: resolved comments on PR Signed-off-by: bhavanakarwade --------- Signed-off-by: sanjay.khatal Signed-off-by: bhavanakarwade Co-authored-by: sanjay.khatal --- src/api/organization.ts | 60 ++ .../organization/OrganizationDetails.tsx | 15 +- .../configuration-settings/CreateDid.tsx | 570 ++++++++++++++++++ .../configuration-settings/DidList.tsx | 145 +++++ .../organization/interfaces/index.ts | 22 + .../SetPrivateKeyValue.tsx | 4 +- src/config/apiRoutes.ts | 3 + .../index.astro} | 8 +- 8 files changed, 817 insertions(+), 10 deletions(-) create mode 100644 src/components/organization/configuration-settings/CreateDid.tsx create mode 100644 src/components/organization/configuration-settings/DidList.tsx rename src/pages/organizations/{dashboard.astro => dashboard/index.astro} (56%) diff --git a/src/api/organization.ts b/src/api/organization.ts index 1ec6dd5e3..30f87a683 100644 --- a/src/api/organization.ts +++ b/src/api/organization.ts @@ -10,6 +10,7 @@ import { apiRoutes } from '../config/apiRoutes'; import { getFromLocalStorage } from './Auth'; import { getHeaderConfigs } from '../config/GetHeaderConfigs'; import { storageKeys } from '../config/CommonConstant'; +import type { IUpdatePrimaryDid } from '../components/organization/interfaces'; export const createOrganization = async (data: object) => { const url = apiRoutes.organizations.create; @@ -364,3 +365,62 @@ export const deleteOrganizationInvitation = async ( return err?.message; } }; + +export const getDids = async (orgId: string) => { + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.organizations.didList}`; + + const token = await getFromLocalStorage(storageKeys.TOKEN); + + const config = { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + }; + const axiosPayload = { + url, + config, + }; + + try { + return await axiosGet(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } +}; + +export const createDid = async (payload: any) => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.organizations.createDid}`; + + const axiosPayload = { + url, + payload, + config: await getHeaderConfigs(), + }; + + try { + return await axiosPost(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } +}; + +export const updatePrimaryDid = async (orgId: string, payload: IUpdatePrimaryDid) => { + const url = `${apiRoutes.organizations.root}/${orgId}${apiRoutes.organizations.primaryDid}`; + + const axiosPayload = { + url, + payload, + config: await getHeaderConfigs(), + }; + + try { + return await axiosPut(axiosPayload); + } catch (error) { + const err = error as Error; + return err?.message; + } +}; \ No newline at end of file diff --git a/src/components/organization/OrganizationDetails.tsx b/src/components/organization/OrganizationDetails.tsx index 5f42bbb7e..97447b569 100644 --- a/src/components/organization/OrganizationDetails.tsx +++ b/src/components/organization/OrganizationDetails.tsx @@ -11,6 +11,7 @@ import DateTooltip from '../Tooltip'; import CopyDid from '../../commonComponents/CopyDid'; import { setToLocalStorage } from '../../api/Auth'; import { Tooltip } from 'flowbite-react'; +import DIDList from './configuration-settings/DidList'; const OrganizationDetails = ({ orgData }: { orgData: Organisation | null }) => { const { org_agents } = orgData as Organisation; @@ -43,14 +44,16 @@ const OrganizationDetails = ({ orgData }: { orgData: Organisation | null }) => { return ( <> -
    +
    +
    +

    + Web Wallet Details +

    +
    -

    - Web Wallet Details -

    • @@ -173,8 +176,10 @@ const OrganizationDetails = ({ orgData }: { orgData: Organisation | null }) => { ) )}
    +
    + +
    - {agentData?.orgDid?.startsWith('did:web') && (
    diff --git a/src/components/organization/configuration-settings/CreateDid.tsx b/src/components/organization/configuration-settings/CreateDid.tsx new file mode 100644 index 000000000..ccce6bf20 --- /dev/null +++ b/src/components/organization/configuration-settings/CreateDid.tsx @@ -0,0 +1,570 @@ +import * as yup from 'yup'; +import { Button, Modal } from 'flowbite-react'; +import { Field, Form, Formik, FormikHelpers } from 'formik'; +import { apiStatusCodes, storageKeys } from '../../../config/CommonConstant'; +import { useEffect, useState } from 'react'; +import { AlertComponent } from '../../AlertComponent'; +import type { AxiosResponse } from 'axios'; +import { createDid, getOrganizationById } from '../../../api/organization'; +import type { EditOrgdetailsModalProps, IFormikValues, Organisation } from '../interfaces'; +import { createPolygonKeyValuePair, getLedgerConfig } from '../../../api/Agent'; +import { DidMethod } from '../../../common/enums'; +import { nanoid } from 'nanoid'; +import TokenWarningMessage from '../walletCommonComponents/TokenWarningMessage'; +import CopyDid from '../../../commonComponents/CopyDid'; +import GenerateBtnPolygon from '../walletCommonComponents/GenerateBtnPolygon'; +import { getFromLocalStorage } from '../../../api/Auth'; + +interface IPolygonKeys { + privateKey: string; + publicKeyBase58: string; + address: string; +} + +interface ILedgerConfig { + [method: string]: { + [network: string]: string; + }; +} + +interface ILedgerItem { + name: string; + details: { + [network: string]: string; + }; +} + +const CreateDIDModal = (props: EditOrgdetailsModalProps) => { + const [loading, setLoading] = useState(false); + const [mappedData, setMappedData] = useState({}); + const [erroMsg, setErrMsg] = useState(null); + const [successMsg, setSuccessMsg] = useState(null); + const [seed, setSeed] = useState(''); + const [selectedMethod, setSelectedMethod] = useState(''); + const [generatedKeys, setGeneratedKeys] = useState(null); + const [ledgerName, setLedgerName] = useState(null); + const fetchLedgerConfig = async () => { + try { + const { data } = (await getLedgerConfig()) as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const ledgerdata: ILedgerConfig = {}; + data.data.forEach((item: ILedgerItem) => { + ledgerdata[item.name.toLowerCase()] = { ...item.details }; + }); + setMappedData(ledgerdata); + } + } catch (err) { + console.error('Error in fetching ledger config:::', err); + } + }; + + const fetchOrganizationDetails = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const response = await getOrganizationById(orgId as string); + const { data } = response as AxiosResponse; + setLoading(false); + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const didMethod = data?.data?.org_agents[0]?.orgDid + ?.split(':') + .slice(0, 2) + .join(':'); + let getLedgerName; + switch (didMethod) { + case 'did:indy': + case 'did:polygon': + getLedgerName = data?.data?.org_agents[0]?.ledgers?.name; + setLedgerName(getLedgerName); + + break; + case 'did:web': + case 'did:key': + getLedgerName = data?.data?.org_agents[0]?.orgDid + ?.split(':') + .slice(1)[0]; + setLedgerName(getLedgerName); + + break; + default: + console.error('Unsupported DID format'); + } + } else { + console.error('Error in fetching organization:::'); + } + setLoading(false); + }; + + useEffect(() => { + fetchOrganizationDetails(); + }, []); + + const createNewDid = async (values: IFormikValues) => { + setLoading(true); + + const didData = { + seed: values.method === DidMethod.POLYGON ? '' : seed, + keyType: 'ed25519', + method: values.method, + network: + values.method === DidMethod.POLYGON + ? `${values.method}:${values.network}` + : values.method !== DidMethod.KEY + ? `${values.ledger}:${values.network}` + : '', + domain: values.method === DidMethod.WEB ? values.domain : '', + role: values.method === DidMethod.INDY ? 'endorser' : '', + privatekey: values.method === DidMethod.POLYGON ? values.privatekey : '', + did: '', + endorserDid: values?.endorserDid || '', + isPrimaryDid: false, + }; + try { + const response = await createDid(didData); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + if (props?.onEditSucess) { + props?.onEditSucess(); + } + props.setOpenModal(false); + props.setMessage(data?.message); + setSuccessMsg(data?.message); + setLoading(false); + } else { + setErrMsg(response as string); + setLoading(false); + } + } catch (error) { + console.error('An error occurred while creating did:', error); + setLoading(false); + } + }; + + const generatePolygonKeyValuePair = async () => { + try { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const resCreatePolygonKeys = await createPolygonKeyValuePair(orgId); + const { data } = resCreatePolygonKeys as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + setGeneratedKeys(data?.data); + } + } catch (err) { + console.error('Generate private key ERROR::::', err); + } + }; + + const showMethod = ( + method: string, + selectedLedger: string, + selectedMethod: string, + selectedNetwork: string, + ): string => { + switch (method) { + case DidMethod.POLYGON: { + return mappedData && selectedNetwork && method + ? mappedData[method][selectedNetwork] || '' + : ''; + } + case DidMethod.INDY: { + return mappedData && selectedLedger && selectedNetwork && method + ? mappedData[method][selectedLedger][selectedNetwork] || '' + : ''; + } + case DidMethod.KEY: + case DidMethod.WEB: { + return mappedData && method ? mappedData[method][method] || '' : ''; + } + default: + return ''; + } + }; + + useEffect(() => { + fetchLedgerConfig(); + setSeed(nanoid(32)); + }, []); + + const validations = { + method: yup.string().required('Method is required').trim(), + ledger: yup.string(), + network: yup.string(), + domain: yup.string(), + privatekey: yup.string(), + }; + + if (selectedMethod === DidMethod.WEB) { + validations['domain'] = yup.string().required('Domain is required').trim(); + } + + if (selectedMethod === DidMethod.POLYGON) { + (validations['network'] = yup + .string() + .required('Network is required') + .trim()), + (validations['privatekey'] = yup + .string() + .required('Private key is required') + .trim() + .length(64, 'Private key must be exactly 64 characters long')); + } + + if (selectedMethod === DidMethod.INDY) { + (validations['ledger'] = yup.string().required('Ledger is required')), + (validations['network'] = yup.string().required('Network is required')); + } + + return ( + { + props.setOpenModal(false); + setErrMsg(null); + }} + > + Create DID + + { + setErrMsg(null); + setSuccessMsg(null); + }} + /> + , + ) => { + const didMethodValue = showMethod( + values.method, + values.ledger, + values.method, + values.network, + ); + + const didMethodName = didMethodValue + .split(':') + .slice(0, 2) + .join(':'); + let selectedLedgerName; + + switch (didMethodName) { + case 'did:indy': + selectedLedgerName = didMethodValue + .split(':') + .slice(-2) + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + + break; + + case 'did:polygon': + selectedLedgerName = didMethodValue + .split(':') + .slice(1) + .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) + .join(' '); + + break; + + case 'did:web': + case 'did:key': + selectedLedgerName = didMethodValue.split(':')[1]; + + break; + + default: + console.error('Unsupported DID format'); + } + + if (ledgerName !== selectedLedgerName) { + setErrMsg('This ledger is not applicable to create a DID'); + } else { + await createNewDid(values); + setErrMsg(null); + window.location.reload(); + } + }} + > + {(formikHandlers): JSX.Element => { + return ( +
    +
    +
    + + + {formikHandlers?.errors?.method && + formikHandlers?.touched?.method && ( + + {formikHandlers?.errors?.method} + + )} +
    + + {formikHandlers.values.method !== DidMethod.POLYGON && + formikHandlers.values.method !== DidMethod.KEY && + formikHandlers.values.method !== DidMethod.WEB && ( +
    + + + {formikHandlers?.errors?.ledger && + formikHandlers?.touched?.ledger && ( + + {formikHandlers?.errors?.ledger} + + )} +
    + )} + + {formikHandlers.values.method !== DidMethod.WEB && + formikHandlers.values.method !== DidMethod.KEY && ( +
    + + + {formikHandlers?.errors?.network && + formikHandlers?.touched?.network && ( + + {formikHandlers?.errors?.network} + + )} +
    + )} + {formikHandlers.values.method === DidMethod.POLYGON && ( +
    + {formikHandlers.values.method === DidMethod.POLYGON && ( + + generatePolygonKeyValuePair() + } + /> + )} + {generatedKeys && ( +
    +

    + + Private Key: + +

    + +
    +

    + +

    + + Address: + +

    + +
    +

    +
    + )} + + {generatedKeys && + formikHandlers.values.method === DidMethod.POLYGON && ( + + )} + + {formikHandlers.values.method === DidMethod.POLYGON && ( +
    +
    + + +
    + {formikHandlers?.errors?.privatekey && + formikHandlers?.touched?.privatekey && ( + + {formikHandlers?.errors?.privatekey} + + )} +
    + )} +
    + )} + + {formikHandlers.values.method === DidMethod.WEB && ( +
    +
    + + +
    + {formikHandlers?.errors?.domain && + formikHandlers?.touched?.domain && ( + + {formikHandlers?.errors?.domain} + + )} +
    + )} +
    + + +
    +
    +
    + +
    +
    + ); + }} +
    +
    +
    + ); +}; + +export default CreateDIDModal; diff --git a/src/components/organization/configuration-settings/DidList.tsx b/src/components/organization/configuration-settings/DidList.tsx new file mode 100644 index 000000000..55abea91a --- /dev/null +++ b/src/components/organization/configuration-settings/DidList.tsx @@ -0,0 +1,145 @@ +import React, { useEffect, useState } from "react" +import BreadCrumbs from '../../BreadCrumbs' +import { Button } from "flowbite-react" +import CopyDid from '../../../commonComponents/CopyDid' +import CreateDidPopup from "./CreateDid" +import { getDids, updatePrimaryDid } from "../../../api/organization" +import { getFromLocalStorage } from "../../../api/Auth" +import { apiStatusCodes, storageKeys } from "../../../config/CommonConstant" +import type { AxiosResponse } from "axios" +import { AlertComponent } from "../../AlertComponent" +import type { IDidList, IUpdatePrimaryDid } from "../interfaces" + +const DIDList = () => { + const [didList, setDidList] = useState([]); + const [showPopup, setShowPopup] = useState(false); + const [erroMsg, setErrMsg] = useState(null); + const [successMsg, setSuccessMsg] = useState(null); + + const setPrimaryDid = async (id: string, did: string) => { + try { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const payload: IUpdatePrimaryDid = { + id, + did + } + const response = await updatePrimaryDid(orgId, payload); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + window.location.reload(); + } else { + setErrMsg(response as string); + } + } catch (error) { + } + } + + const getData = async () => { + try { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const response = await getDids(orgId); + const { data } = response as AxiosResponse; + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const sortedDids = data?.data.sort((a, b) => { + if (a.isPrimaryDid && !b.isPrimaryDid) return -1; + if (!a.isPrimaryDid && b.isPrimaryDid) return 1; + return 0; + }); + setDidList(sortedDids) + } + } catch (error) { + console.log("ERROR::::", error); + } + } + + useEffect(() => { + getData(); + }, []) + + return ( + <> +
    + { + setErrMsg(null); + setSuccessMsg(null); + }} + /> +
    +

    DID Details

    + + +
    +
    + { + didList.map((item: IDidList, index: number) => { + const primary = item.id; + return ( +
    +
    +

    DID {index + 1}

    +

    :

    + {item?.did ? ( + + ) : ( + + Not available + + )} + { + primary && item.isPrimaryDid ? +
    + Primary DID +
    + : +
    + +
    + } +
    +
    + ) + }) + } +
    +
    + setShowPopup(value)} + loading={false} + success={"message"} + failure={""} + openModal={showPopup} + closeModal={() => setShowPopup(false)} + onSuccess={() => console.log("On Success")} + message={'Would you like to proceed? Keep in mind that this action cannot be undone.'} + buttonTitles={["No, cancel", "Yes, I'm sure"]} + isProcessing={false} + setFailure={() => console.log("SET Error")} + setSuccess={() => console.log("SET Success")} + /> + + ) +} + + +export default DIDList; \ No newline at end of file diff --git a/src/components/organization/interfaces/index.ts b/src/components/organization/interfaces/index.ts index eaf6bcdbd..99bc7d5ca 100644 --- a/src/components/organization/interfaces/index.ts +++ b/src/components/organization/interfaces/index.ts @@ -198,3 +198,25 @@ export interface IOrgInfo { id: string; roles: string[] } + +export interface IUpdatePrimaryDid { + id: string; + did: string; +} + +export interface IDidList { + id: string; + did: string; + isPrimaryDid: boolean; + createDateTime: string; + lastChangedDateTime: string; +} + +export interface IFormikValues { + ledger: string; + method: string; + network: string; + domain: string; + privatekey: string; + endorserDid: string; +} diff --git a/src/components/organization/walletCommonComponents/SetPrivateKeyValue.tsx b/src/components/organization/walletCommonComponents/SetPrivateKeyValue.tsx index f5fe3bcff..6ca93138a 100644 --- a/src/components/organization/walletCommonComponents/SetPrivateKeyValue.tsx +++ b/src/components/organization/walletCommonComponents/SetPrivateKeyValue.tsx @@ -1,5 +1,6 @@ import {Label } from 'flowbite-react'; import { Field} from 'formik'; +import type { ChangeEvent } from 'react'; interface IProps { setPrivateKeyValue:(val:string)=>void privateKeyValue:string @@ -22,11 +23,12 @@ const SetPrivateKeyValueInput = ({
    { + onChange={(e: ChangeEvent) => { setPrivateKeyValue(e.target.value); formikHandlers.handleChange(e); }} diff --git a/src/config/apiRoutes.ts b/src/config/apiRoutes.ts index d20fe4216..b11c9febb 100644 --- a/src/config/apiRoutes.ts +++ b/src/config/apiRoutes.ts @@ -39,6 +39,9 @@ export const apiRoutes = { invitations: '/invitations', orgRoles: '/orgs/roles', editUserROle: '/user-roles', + didList: '/dids', + createDid: '/agents/did', + primaryDid: '/primary-did' }, connection: { create: '/connections', diff --git a/src/pages/organizations/dashboard.astro b/src/pages/organizations/dashboard/index.astro similarity index 56% rename from src/pages/organizations/dashboard.astro rename to src/pages/organizations/dashboard/index.astro index 138de6f12..3612ea7c9 100644 --- a/src/pages/organizations/dashboard.astro +++ b/src/pages/organizations/dashboard/index.astro @@ -1,8 +1,8 @@ --- -import LayoutSidebar from '../../app/LayoutSidebar.astro'; -import Dashboard from '../../components/organization/Dashboard'; -import { checkUserSession } from '../../utils/check-session'; -import { pathRoutes } from '../../config/pathRoutes'; +import LayoutSidebar from '../../../app/LayoutSidebar.astro'; +import Dashboard from '../../../components/organization/Dashboard'; +import { checkUserSession } from '../../../utils/check-session'; +import { pathRoutes } from '../../../config/pathRoutes'; const response = await checkUserSession({cookies: Astro.cookies, currentPath: Astro.url.pathname}); const route: string = pathRoutes.auth.sinIn From 99365ddfb9d474eac5d68b42fc93d339a30e0dd7 Mon Sep 17 00:00:00 2001 From: bhavanakarwade <137506897+bhavanakarwade@users.noreply.github.com> Date: Thu, 23 May 2024 17:04:13 +0530 Subject: [PATCH 23/34] refactor: api endpoint (#677) * refactor: parameter name Signed-off-by: bhavanakarwade * refactor: added query parameter Signed-off-by: bhavanakarwade * fix: remove unnecessary code Signed-off-by: bhavanakarwade * fix: query param issue Signed-off-by: bhavanakarwade --------- Signed-off-by: bhavanakarwade --- src/api/ecosystem.ts | 3 ++- src/common/enums.ts | 4 ++++ src/components/Resources/Schema/Create.tsx | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/api/ecosystem.ts b/src/api/ecosystem.ts index 112476acc..7d3445153 100644 --- a/src/api/ecosystem.ts +++ b/src/api/ecosystem.ts @@ -110,10 +110,11 @@ export const getEndorsementList = async ( export const createSchemaRequest = async ( data: object, + schemaType: string, endorsementId: string, orgId: string, ) => { - const url = `${apiRoutes.Ecosystem.root}/${endorsementId}/${orgId}${apiRoutes.Ecosystem.endorsements.createSchemaRequest}`; + const url = `${apiRoutes.Ecosystem.root}/${endorsementId}/${orgId}${apiRoutes.Ecosystem.endorsements.createSchemaRequest}?schemaType=${schemaType}`; const payload = data; const axiosPayload = { url, diff --git a/src/common/enums.ts b/src/common/enums.ts index 7abdc1dff..dd66bea4f 100644 --- a/src/common/enums.ts +++ b/src/common/enums.ts @@ -31,6 +31,10 @@ export enum ProofRequestStateUserText { abandoned = 'Declined', } +export enum SchemaType { + INDY = 'indy', + W3C = 'w3c' +} export enum IssueCredentialUserText { offerSent = 'Offered', done = 'Accepted', diff --git a/src/components/Resources/Schema/Create.tsx b/src/components/Resources/Schema/Create.tsx index 23b7803f3..8f85fa74b 100644 --- a/src/components/Resources/Schema/Create.tsx +++ b/src/components/Resources/Schema/Create.tsx @@ -20,6 +20,7 @@ import { ICheckEcosystem, checkEcosystem, getEcosystemId } from '../../../config import { createSchemaRequest } from '../../../api/ecosystem'; import EcosystemProfileCard from '../../../commonComponents/EcosystemProfileCard'; import ConfirmationModal from '../../../commonComponents/ConfirmationModal'; +import { SchemaType } from '../../../common/enums'; const options = [ { @@ -158,7 +159,7 @@ const CreateSchema = () => { const id = await getEcosystemId(); - const createSchema = await createSchemaRequest(schemaFieldName, id, orgId); + const createSchema = await createSchemaRequest(schemaFieldName, SchemaType.INDY, id, orgId); const { data } = createSchema as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { setSuccess(data?.message); From 9c59d1340b158ca9628502473eaf9cd4b53de9ba Mon Sep 17 00:00:00 2001 From: bhavanakarwade <137506897+bhavanakarwade@users.noreply.github.com> Date: Fri, 24 May 2024 12:37:24 +0530 Subject: [PATCH 24/34] fix: checkboxes state clear issue (#680) * feat: created page Signed-off-by: sanjay.khatal * feat: add own organizations in the ecosystem Signed-off-by: sanjay.khatal * feat: add orgs in ecosystem Signed-off-by: sanjay.khatal * fix: types, redirection and error handling Signed-off-by: sanjay.khatal * fix: sonarlint issues Signed-off-by: sanjay.khatal * fix: role wise list access Signed-off-by: bhavanakarwade * fix: resolved comments Signed-off-by: bhavanakarwade * fix: pagesize Signed-off-by: bhavanakarwade * fix: checkboxes state clear issue Signed-off-by: bhavanakarwade * fix: remove unnecessary attribute Signed-off-by: bhavanakarwade --------- Signed-off-by: sanjay.khatal Signed-off-by: bhavanakarwade Co-authored-by: sanjay.khatal --- src/components/AddOrganizationInEcosystem.tsx | 105 ++++++-- src/components/Issuance/ConnectionList.tsx | 193 ++++++++------ src/components/Issuance/Issuance.tsx | 236 +++++++++--------- 3 files changed, 310 insertions(+), 224 deletions(-) diff --git a/src/components/AddOrganizationInEcosystem.tsx b/src/components/AddOrganizationInEcosystem.tsx index e96d9e1fd..2e0354927 100644 --- a/src/components/AddOrganizationInEcosystem.tsx +++ b/src/components/AddOrganizationInEcosystem.tsx @@ -227,6 +227,7 @@ const AddOrganizationInEcosystem = () => { }; const refreshPage = () => { + setLocalOrgs([]); getOwnerOrganizations(listAPIParameter); }; @@ -241,43 +242,104 @@ const AddOrganizationInEcosystem = () => { } const handleAddOrganization = async () => { - const orgId = await getFromLocalStorage(storageKeys.ORG_ID) || ""; - const ecosystemId = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID) || ""; - setLoader(true) + const orgId = (await getFromLocalStorage(storageKeys.ORG_ID)) || ''; + const ecosystemId = + (await getFromLocalStorage(storageKeys.ECOSYSTEM_ID)) || ''; + setLoader(true); try { - const response = await addOrganizationInEcosystem(localOrgs, ecosystemId, orgId); + const response = await addOrganizationInEcosystem( + localOrgs, + ecosystemId, + orgId, + ); const { data } = response as AxiosResponse; - setLoader(false) + setLoader(false); + setLocalOrgs([]); + setErrorList([]); + setOrganizationsList( + (prevState) => + prevState?.map((org) => ({ ...org, checked: false, error: '' })) || + [], + ); + switch (data?.statusCode) { case apiStatusCodes.API_STATUS_CREATED: - await removeFromLocalStorage(storageKeys.SELECT_ORG_IN_ECOSYSTEM) - setSuccess(data.message) + await removeFromLocalStorage(storageKeys.SELECT_ORG_IN_ECOSYSTEM); + setSuccess(data.message); setTimeout(() => { window.location.href = pathRoutes.ecosystem.dashboard; }, 1000); break; + case apiStatusCodes.API_STATUS_PARTIALLY_COMPLETED: - await removeFromLocalStorage(storageKeys.SELECT_ORG_IN_ECOSYSTEM) - const errors = data?.data?.filter((item: IErrorResponse) => item.statusCode !== apiStatusCodes.API_STATUS_CREATED) - const errorData = errors.map((item: IErrorResponse) => ({ id: item?.data?.orgId || "", error: item.message })) - await setToLocalStorage(storageKeys.ERROR_ORG_IN_ECOSYSTEM, JSON.stringify(errorData)) - setErrorList(errorData) - const updateWithError = organizationsList && organizationsList?.length > 0 ? organizationsList?.map((item => ({ - ...item, - error: errors?.find((ele: IErrorResponse) => ele?.data?.orgId === item.id)?.message || "" - }))) : [] + await removeFromLocalStorage(storageKeys.SELECT_ORG_IN_ECOSYSTEM); + const errors = data?.data?.filter( + (item: IErrorResponse) => + item.statusCode !== apiStatusCodes.API_STATUS_CREATED, + ); + const errorData = errors.map((item: IErrorResponse) => ({ + id: item?.data?.orgId || '', + error: item.message, + })); + await setToLocalStorage( + storageKeys.ERROR_ORG_IN_ECOSYSTEM, + JSON.stringify(errorData), + ); + setErrorList(errorData); + setLocalOrgs([]); + + const updateWithError = + organizationsList && organizationsList?.length > 0 + ? organizationsList?.map((item) => ({ + ...item, + error: + errors?.find( + (ele: IErrorResponse) => ele?.data?.orgId === item.id, + )?.message || '', + checked: false + })) + : []; setSuccess(data?.message); - setOrganizationsList(updateWithError) + setOrganizationsList(updateWithError); + setErrorList([]); break; default: - setError(response as string || data?.message) + setError((response as string) || data?.message); + setErrorList([]); + setLocalOrgs([]); + setOrganizationsList( + (prevState) => + prevState?.map((org) => ({ + ...org, + checked: false, + error: '', + })) || [], + ); + break; } } catch (error) { - setError(error.message as string) - setLoader(false) + setError(error.message as string); + setLoader(false); + setLocalOrgs([]); + setErrorList([]); + setOrganizationsList( + (prevState) => + prevState?.map((org) => ({ ...org, checked: false, error: '' })) || + [], + ); } - } + }; + + useEffect(() => { + const clearLocalStorage = async () => { + await removeFromLocalStorage(storageKeys.SELECT_ORG_IN_ECOSYSTEM); + await removeFromLocalStorage(storageKeys.ERROR_ORG_IN_ECOSYSTEM); + }; + clearLocalStorage(); + refreshPage(); + + }, []); useEffect(() => { getOwnerOrganizations(listAPIParameter); @@ -292,6 +354,7 @@ const AddOrganizationInEcosystem = () => { })() }, []) + useEffect(() => { (async () => { await setToLocalStorage(storageKeys.SELECT_ORG_IN_ECOSYSTEM, JSON.stringify(localOrgs)) diff --git a/src/components/Issuance/ConnectionList.tsx b/src/components/Issuance/ConnectionList.tsx index d0bea4c98..17e5800fa 100644 --- a/src/components/Issuance/ConnectionList.tsx +++ b/src/components/Issuance/ConnectionList.tsx @@ -13,7 +13,11 @@ import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; import type { IConnectionList } from './interface'; import NewDataTable from '../../commonComponents/datatable/SortDataTable'; -import { getFromLocalStorage, setToLocalStorage } from '../../api/Auth'; +import { + getFromLocalStorage, + removeFromLocalStorage, + setToLocalStorage, +} from '../../api/Auth'; const initialPageState = { itemPerPage: 10, @@ -28,14 +32,14 @@ type LocalOrgs = { connectionId: string; theirLabel: string; createDateTime: string; -} +}; const ConnectionList = (props: { selectConnection: (connections: IConnectionList[]) => void; }) => { const [listAPIParameter, setListAPIParameter] = useState(initialPageState); const [tableData, setTableData] = useState([]); - const [connectionList, setConnectionList] = useState([]) + const [connectionList, setConnectionList] = useState([]); const [localOrgs, setLocalOrgs] = useState([]); const [loading, setLoading] = useState(false); @@ -47,91 +51,106 @@ const ConnectionList = (props: { lastPage: '', }); - const selectOrganization = async (item: IConnectionList, checked: boolean) => { + const selectOrganization = async ( + item: IConnectionList, + checked: boolean, + ) => { try { - const index = localOrgs?.length > 0 ? localOrgs.findIndex(ele => ele.connectionId === item.connectionId) : -1 + const index = + localOrgs?.length > 0 + ? localOrgs.findIndex((ele) => ele.connectionId === item.connectionId) + : -1; const { connectionId, theirLabel, createDateTime } = item || {}; if (index === -1) { - setLocalOrgs((prev: LocalOrgs[]) => [...prev, { - connectionId, - theirLabel, - createDateTime - }]) + setLocalOrgs((prev: LocalOrgs[]) => [ + ...prev, + { + connectionId, + theirLabel, + createDateTime, + }, + ]); } else { - const updateLocalOrgs = [...localOrgs] + const updateLocalOrgs = [...localOrgs]; if (!checked) { updateLocalOrgs.splice(index, 1); } - setLocalOrgs(updateLocalOrgs) + setLocalOrgs(updateLocalOrgs); } } catch (error) { - console.error("SELECTED ORGANIZATION:::", error) + console.error('SELECTED ORGANIZATION:::', error); } - } + }; const generateTable = async (connections: IConnectionList[]) => { try { - const connectionsData = connections?.length > 0 && connections?.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'; + const connectionsData = + connections?.length > 0 && + connections?.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'; - const isChecked = localOrgs.map(item => item.connectionId).includes(ele.connectionId) + const isChecked = localOrgs + .map((item) => item.connectionId) + .includes(ele.connectionId); - return { - data: [ - { - data: ( -
    - ) => { - const inputElement = event.target as HTMLInputElement; + return { + data: [ + { + data: ( +
    + , + ) => { + const inputElement = event.target as HTMLInputElement; - const updateConnectionList = connections?.map(item => { - if (item.connectionId === ele.connectionId) { - selectOrganization(item, inputElement.checked) - return { - ...item, - checked: inputElement.checked - } - } - return item - }) - setConnectionList(updateConnectionList) - }} - checked={ele.checked || isChecked} - 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)}{' '} - - ), - }, - ], - }; - }); - - setTableData(connectionsData) - } catch (err) { + const updateConnectionList = connections?.map( + (item) => { + if (item.connectionId === ele.connectionId) { + selectOrganization(item, inputElement.checked); + return { + ...item, + checked: inputElement.checked, + }; + } + return item; + }, + ); + setConnectionList(updateConnectionList); + }} + checked={ele.checked || isChecked} + 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)}{' '} + + ), + }, + ], + }; + }); - } - } + setTableData(connectionsData); + } catch (err) {} + }; const getConnections = async (apiParameter: IConnectionListAPIParameter) => { setLoading(true); @@ -185,14 +204,25 @@ const ConnectionList = (props: { }; const refreshPage = () => { + setLocalOrgs([]); getConnections(listAPIParameter); }; const updateLocalOrgs = async () => { - const res = await getFromLocalStorage(storageKeys.SELECTED_CONNECTIONS) - const selectedOrg = res ? JSON.parse(res) : [] + const res = await getFromLocalStorage(storageKeys.SELECTED_CONNECTIONS); + const selectedOrg = res ? JSON.parse(res) : []; setLocalOrgs(selectedOrg); - } + }; + + useEffect(() => { + const clearStorageAndRefresh = async () => { + refreshPage(); + await removeFromLocalStorage(storageKeys.SELECTED_CONNECTIONS); + await removeFromLocalStorage(storageKeys.SELECTED_USER); + }; + + clearStorageAndRefresh(); + }, []); useEffect(() => { props.selectConnection(localOrgs); @@ -200,17 +230,20 @@ const ConnectionList = (props: { useEffect(() => { generateTable(connectionList); - }, [connectionList, localOrgs]) + }, [connectionList, localOrgs]); useEffect(() => { (async () => { - await setToLocalStorage(storageKeys.SELECTED_CONNECTIONS, JSON.stringify(localOrgs)) - })() - }, [localOrgs]) + await setToLocalStorage( + storageKeys.SELECTED_CONNECTIONS, + JSON.stringify(localOrgs), + ); + })(); + }, [localOrgs]); useEffect(() => { let getData: NodeJS.Timeout; - updateLocalOrgs() + updateLocalOrgs(); if (listAPIParameter?.search?.length >= 1) { getData = setTimeout(() => { getConnections(listAPIParameter); @@ -223,8 +256,8 @@ const ConnectionList = (props: { }, [listAPIParameter]); useEffect(() => { - updateLocalOrgs() - }, []) + updateLocalOrgs(); + }, []); return (
    diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index 694c03737..336968c6f 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -5,8 +5,8 @@ import * as Yup from 'yup'; import { Alert, Button, Card } from 'flowbite-react'; import { Field, FieldArray, Form, Formik } from 'formik'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; -import { getFromLocalStorage, removeFromLocalStorage, setToLocalStorage } from '../../api/Auth'; -import React, { useEffect, useState } from 'react'; +import { getFromLocalStorage, removeFromLocalStorage } from '../../api/Auth'; +import { useEffect, useState } from 'react'; import BackButton from '../../commonComponents/backbutton'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; @@ -71,21 +71,20 @@ const IssueCred = () => { credDefId: string, orgId: string, ) => { - const credentialData = selectedUsers.map((user) => { const attributesArray = attributes.map((attr) => ({ name: attr.attributeName, value: '', - dataType: attr?.schemaDataType, - isRequired: attr.isRequired + dataType: attr?.schemaDataType, + isRequired: attr.isRequired, })); - + return { connectionId: user.connectionId, attributes: attributesArray, }; }); - + const issuancePayload = { credentialData, credentialDefinitionId: credDefId, @@ -95,50 +94,53 @@ const IssueCred = () => { setIssuanceFormPayload(issuancePayload); setUserLoader(false); }; - + const createAttributeValidationSchema = ( name: string, value: string, - isRequired: boolean + isRequired: boolean, ) => { - let attributeSchema = Yup.string();; + let attributeSchema = Yup.string(); if (name) { name = name .split('_') - .map(item => item.charAt(0).toUpperCase() + item.slice(1)) + .map((item) => item.charAt(0).toUpperCase() + item.slice(1)) .join(' '); } - + if (isRequired) { if (!value) { attributeSchema = Yup.string().required(`${name} is required`); } } - + return Yup.object().shape({ value: attributeSchema, }); }; const validationSchema = Yup.object().shape({ - credentialData: Yup.array().of( - Yup.object().shape({ + credentialData: Yup.array().of( + Yup.object().shape({ attributes: Yup.array().of( - Yup.lazy((attr) => { - return createAttributeValidationSchema(attr?.name, attr?.value, attr?.isRequired) + Yup.lazy((attr) => { + return createAttributeValidationSchema( + attr?.name, + attr?.value, + attr?.isRequired, + ); }), - ), - }), - ), - }); - + ), + }), + ), + }); const getSchemaDetails = async (): Promise => { const schemaAttributes = await getFromLocalStorage(storageKeys.SCHEMA_ATTR); const parsedSchemaAttributes = JSON.parse(schemaAttributes) || []; - + setSchemaAttributesDetails(parsedSchemaAttributes?.attribute); return parsedSchemaAttributes.attribute; @@ -162,28 +164,28 @@ const IssueCred = () => { const handleSubmit = async (values: IssuanceFormPayload) => { const issuancePayload = { - credentialData: values.credentialData.map(item => { + credentialData: values.credentialData.map((item) => { return { ...item, - attributes: item.attributes.map(attr => ({ + attributes: item.attributes.map((attr) => ({ name: attr.name, - value: attr.value.toString() - })) - } + value: attr.value.toString(), + })), + }; }), - credentialDefinitionId: values.credentialDefinitionId, - orgId: values.orgId - }; + credentialDefinitionId: values.credentialDefinitionId, + orgId: values.orgId, + }; const convertedAttributesValues = { ...issuancePayload, }; - + 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}`; @@ -194,7 +196,7 @@ const IssueCred = () => { setIssuanceLoader(false); } }; - + return (
    @@ -237,7 +239,7 @@ const IssueCred = () => { validationSchema={validationSchema} onSubmit={handleSubmit} > - {({ values, errors, touched, isValid }) => ( + {({ values, errors, touched }) => (
    {failure && (
    @@ -248,7 +250,7 @@ const IssueCred = () => {
    )} - + {(arrayHelpers) => ( <> {values?.credentialData.map((user, index) => ( @@ -280,27 +282,11 @@ const IssueCred = () => { > @@ -156,7 +156,7 @@ const PasskeyAddDevice = (props: {
    SVG Image { @@ -56,7 +55,7 @@ const CustomQRCode = ({ value, size }: { value: string, size: number }) => { > @@ -68,8 +67,8 @@ const CustomQRCode = ({ value, size }: { value: string, size: number }) => { className= {`${isCopied }`} onClick={copyTextVal}> {isCopied - ? - : + ? + : } diff --git a/src/commonComponents/SchemaCard.tsx b/src/commonComponents/SchemaCard.tsx index 80e1638e5..5d9c6dab1 100644 --- a/src/commonComponents/SchemaCard.tsx +++ b/src/commonComponents/SchemaCard.tsx @@ -35,10 +35,10 @@ const SchemaCard = (props: IProps) => {

    -

    +

    Created: {dateConversion(props.created)} -

    +
    diff --git a/src/commonComponents/backbutton/index.tsx b/src/commonComponents/backbutton/index.tsx index 8a401a20c..c431b5b27 100644 --- a/src/commonComponents/backbutton/index.tsx +++ b/src/commonComponents/backbutton/index.tsx @@ -9,7 +9,7 @@ const index = ({ path }: { path: string }) => { onClick={() => { window.location.href = path; }} - className="bg-secondary-700 ring-primary-700 bg-white-700 hover:bg-secondary-700 ring-2 text-black font-medium rounded-lg text-sm px-4 lg:px-5 py-2 lg:py-2.5 m-2 ml-2 dark:text-white dark:hover:text-black" + className="bg-secondary-700 ring-primary-700 bg-white-700 hover:bg-secondary-700 ring-2 text-black font-medium rounded-lg text-sm dark:text-white dark:hover:text-black" style={{ height: '2.5rem', width: '5rem', minWidth: '2rem' }} > = ({ header, displaySelect, @@ -162,7 +163,7 @@ const SortDataTable: React.FC = ({ ))} - + {loading ? (
    = ({
    - ) : ( - - {data?.length ? ( - data?.map((ele, index) => ( + ) : data?.length ? ( + data?.map((ele, index) => ( = ({ )} - )} - -
    - {loading && isPagination && data.length > 0 ? ( - '' + + +
    + {loading && isPagination && data.length > 0 ? ( + '' ) : (
    diff --git a/src/components/Authentication/KeyCloakResetPassword.tsx b/src/components/Authentication/KeyCloakResetPassword.tsx index 02a01ce95..b8c4384f2 100644 --- a/src/components/Authentication/KeyCloakResetPassword.tsx +++ b/src/components/Authentication/KeyCloakResetPassword.tsx @@ -11,6 +11,7 @@ import { pathRoutes } from '../../config/pathRoutes'; import type { IPassword, IProps, IValues } from './interfaces'; import React from 'react'; import { envConfig } from '../../config/envConfig'; +import CustomSpinner from '../CustomSpinner/index.js'; const KeyClockResetPassword = (props: IProps) => { const [loading, setLoading] = useState(false); @@ -233,6 +234,9 @@ const KeyClockResetPassword = (props: IProps) => { disabled={loading} className="w-full mt-12 text-base py-1 font-medium text-center text-white bg-primary-700 hover:!bg-primary-800 rounded-lg hover:bg-primary-700 focus:ring-4 focus:ring-primary-300 dark:bg-primary-700 dark:hover:bg-primary-700 dark:focus:ring-primary-800" > + { + loading ? : "" + } Reset Password
    diff --git a/src/components/Authentication/ResetPassword.tsx b/src/components/Authentication/ResetPassword.tsx index e63a14e56..6d6864d68 100644 --- a/src/components/Authentication/ResetPassword.tsx +++ b/src/components/Authentication/ResetPassword.tsx @@ -20,6 +20,7 @@ import { } from '../../api/Auth.js'; import type { AxiosResponse } from 'axios'; import { PassInvisible, PassVisible } from './Svg.js'; + interface passwordValues { password: string; confirmPassword: string; @@ -284,6 +285,7 @@ const ResetPassword = () => { isProcessing={loading} className="w-full 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 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" > + { { @@ -326,6 +326,7 @@ const SignInUserPasskey = (signInUserProps: signInUserProps) => { }} className="px-10 min-w-fit sm:min-w-[12rem] 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 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" > + { Passkey diff --git a/src/components/Authentication/SignInUserPassword.tsx b/src/components/Authentication/SignInUserPassword.tsx index 4690b0b97..e9440ec2a 100644 --- a/src/components/Authentication/SignInUserPassword.tsx +++ b/src/components/Authentication/SignInUserPassword.tsx @@ -343,14 +343,15 @@ const SignInUserPassword = (signInUserProps: SignInUser3Props) => { isProcessing={loading} type="submit" className="w-fit px-0 sm:px-4 xl:px-12 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 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800" - > + > + + > { strokeLinecap="round" /> + Login
    diff --git a/src/components/Authentication/SignUpUser.tsx b/src/components/Authentication/SignUpUser.tsx index 0270e618d..074972640 100644 --- a/src/components/Authentication/SignUpUser.tsx +++ b/src/components/Authentication/SignUpUser.tsx @@ -230,6 +230,7 @@ const SignUpUser = () => { type="submit" className='w-fit px-0 sm:px-4 xl:px-12 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 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800' > + diff --git a/src/components/Authentication/SignUpUserName.tsx b/src/components/Authentication/SignUpUserName.tsx index 28cd85831..bf02906bc 100644 --- a/src/components/Authentication/SignUpUserName.tsx +++ b/src/components/Authentication/SignUpUserName.tsx @@ -11,7 +11,6 @@ import SignUpUserPasskey from './SignUpUserPasskey.js'; import SignUpUser from './SignUpUser.js'; import NavBar from './NavBar.js'; import FooterBar from './FooterBar.js'; -import React from 'react'; interface nameValues { firstName: string; diff --git a/src/components/Authentication/SignUpUserPasskey.tsx b/src/components/Authentication/SignUpUserPasskey.tsx index 8e1424e53..1f4d35a13 100644 --- a/src/components/Authentication/SignUpUserPasskey.tsx +++ b/src/components/Authentication/SignUpUserPasskey.tsx @@ -4,7 +4,9 @@ import { Alert, Button } from 'flowbite-react'; import type { AxiosError, AxiosResponse } from 'axios'; import type { IdeviceBody, RegistrationOptionInterface, VerifyRegistrationObjInterface } from '../Profile/interfaces/index.js'; import { addDeviceDetails, generateRegistrationOption, verifyRegistration } from '../../api/Fido.js'; -import { AddPasswordDetails, addPasswordDetails, getFromLocalStorage, passwordEncryption } from '../../api/Auth.js'; +import { addPasswordDetails, getFromLocalStorage, passwordEncryption } from '../../api/Auth'; +import type { AddPasswordDetails } from '../../api/Auth'; + import { apiStatusCodes, storageKeys } from '../../config/CommonConstant.js'; import { useEffect, useState } from 'react'; import SignUpUserPassword from './SignUpUserPassword.jsx'; @@ -19,7 +21,6 @@ interface passwordValues { password: string, confirmPassword: string } - const SignUpUserPasskey = ({ email, firstName, lastName }: { email: string, firstName: string; lastName: string }) => { const [loading, setLoading] = useState(false) @@ -262,15 +263,15 @@ const SignUpUserPasskey = ({ email, firstName, lastName }: { email: string, firs onClick={() => setCurrentComponent('password')} > - - + + - - + + Password @@ -282,10 +283,11 @@ const SignUpUserPasskey = ({ email, firstName, lastName }: { email: string, firs registerWithPasskey(true) }} > + - - - + + + Passkey diff --git a/src/components/Authentication/SignUpUserPassword.tsx b/src/components/Authentication/SignUpUserPassword.tsx index b7ac744f1..b0257fb8a 100644 --- a/src/components/Authentication/SignUpUserPassword.tsx +++ b/src/components/Authentication/SignUpUserPassword.tsx @@ -172,7 +172,7 @@ const SignUpUserPassword = ({ >
    -
    +