From f835f35c8531eace5c858346113f4952231453ef Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Wed, 25 Oct 2023 19:00:32 +0530 Subject: [PATCH 01/54] fix: ecosystem option hide issue Signed-off-by: sanjay-k1910 --- src/components/Profile/EditUserProfile.tsx | 72 ++++++++++++---------- src/components/Profile/UserProfile.tsx | 16 +++-- 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/components/Profile/EditUserProfile.tsx b/src/components/Profile/EditUserProfile.tsx index 2c31e0660..7d025a57d 100644 --- a/src/components/Profile/EditUserProfile.tsx +++ b/src/components/Profile/EditUserProfile.tsx @@ -1,11 +1,11 @@ import { useEffect, useRef, useState } from "react"; import type { UserProfile } from "./interfaces"; -import { setToLocalStorage, updateUserProfile } from "../../api/Auth"; -import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, imageSizeAccepted, storageKeys} from "../../config/CommonConstant"; +import { getFromLocalStorage, setToLocalStorage, updateUserProfile } from "../../api/Auth"; +import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, imageSizeAccepted, storageKeys } from "../../config/CommonConstant"; import type { AxiosResponse } from "axios"; import CustomAvatar from '../Avatar' import { calculateSize, dataURItoBlob } from "../../utils/CompressImage"; -import { Alert,Button} from "flowbite-react"; +import { Alert, Button } from "flowbite-react"; import { Form, Formik, FormikHelpers } from "formik"; import * as yup from "yup" import React from "react"; @@ -28,7 +28,7 @@ interface EditUserProfileProps { updateProfile: (updatedProfile: UserProfile) => void; } -const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile}: EditUserProfileProps) => { +const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile }: EditUserProfileProps) => { const [loading, setLoading] = useState(false) const [isImageEmpty, setIsImageEmpty] = useState(true) @@ -54,7 +54,7 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile}: E if (firstNameInputRef.current) { firstNameInputRef.current.focus(); } - }, []); + }, []); useEffect(() => { @@ -166,11 +166,19 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile}: E } const resUpdateUserDetails = await updateUserProfile(userData) + const existingUser = await getFromLocalStorage(storageKeys.USER_PROFILE) + const { data } = resUpdateUserDetails as AxiosResponse - setToLocalStorage(storageKeys.USER_PROFILE, userData) + + const updatedUser = JSON.parse(existingUser) + + const updatedUserData = { + ...updatedUser, + ...userData + } updateProfile(userData); - await setToLocalStorage(storageKeys.USER_PROFILE, userData); + await setToLocalStorage(storageKeys.USER_PROFILE, updatedUserData); window.location.reload(); setLoading(false) } @@ -219,7 +227,7 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile}: E values: Values, { resetForm }: FormikHelpers ) => { - await updateUserDetails(values); + await updateUserDetails(values); toggleEditProfile(); }} @@ -321,28 +329,28 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile}: E
-
- -
-
-
+
+ -
+ + Cancel + +
)} diff --git a/src/components/Profile/UserProfile.tsx b/src/components/Profile/UserProfile.tsx index d5c8e3cfc..cd6eaf840 100644 --- a/src/components/Profile/UserProfile.tsx +++ b/src/components/Profile/UserProfile.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import type { AxiosResponse } from 'axios'; import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; -import { getFromLocalStorage, getUserProfile } from '../../api/Auth'; +import { getFromLocalStorage, getUserProfile, setToLocalStorage } from '../../api/Auth'; import BreadCrumbs from '../BreadCrumbs'; import type { UserProfile } from './interfaces'; import DisplayUserProfile from './DisplayUserProfile'; @@ -9,9 +9,16 @@ import React from 'react'; import AddPasskey from './AddPasskey'; import EditUserProfile from './EditUserProfile'; +interface IUserProfile { + firstName: string + lastName: string + email: string + profileImg: string +} + const UserProfile = () => { const [isEditProfileOpen, setIsEditProfileOpen] = useState(false); - const [prePopulatedUserProfile, setPrePopulatedUserProfile] = useState(null); + const [prePopulatedUserProfile, setPrePopulatedUserProfile] = useState(null); const fetchUserProfile = async () => { try { @@ -21,6 +28,8 @@ const UserProfile = () => { if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { setPrePopulatedUserProfile(data?.data); + await setToLocalStorage(storageKeys.USER_PROFILE, data?.data) + await setToLocalStorage(storageKeys.USER_EMAIL, data?.data?.email) } } catch (error) { } @@ -37,7 +46,7 @@ const UserProfile = () => { }, []); - const updatePrePopulatedUserProfile = (updatedProfile: UserProfile) => { + const updatePrePopulatedUserProfile = (updatedProfile: IUserProfile) => { setPrePopulatedUserProfile(updatedProfile); }; @@ -107,7 +116,6 @@ const UserProfile = () => { - ); }; From 039392b32febe3ca1b28d3e1db0fc638dbb74c71 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Wed, 25 Oct 2023 19:19:50 +0530 Subject: [PATCH 02/54] fix: dark mode issue on update profile form Signed-off-by: sanjay-k1910 --- src/components/Profile/EditUserProfile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Profile/EditUserProfile.tsx b/src/components/Profile/EditUserProfile.tsx index 7d025a57d..49c7016cd 100644 --- a/src/components/Profile/EditUserProfile.tsx +++ b/src/components/Profile/EditUserProfile.tsx @@ -346,7 +346,7 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile }: - ), - }, - ], - }; - }); + + + + + Verify +

+ )} + + ), + }, + ], + }; + }); - setVerificationList(credentialList); - } else { - setErrMsg(response as string); + setVerificationList(credentialList); + } else { + setErrMsg(response as string); + } } + } catch (error) { + setErrMsg('An error occurred while fetching the proof request list'); } - } catch (error) { - 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) + 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) + } setTimeout(() => { - getproofRequestList() - }, 2000) - } else { + setProofReqSuccess('') + setErrMsg('') + }, 4000) + } catch (error) { 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: boolean) => { + setRequestId(requestId) + setOpenModal(flag) + setView(state === "done" ? true : false) - } + } - 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(() => { }, 1000); - } else { - getproofRequestList() - } + if (searchText.length >= 1) { + getData = setTimeout(() => { }, 1000); + } 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); + } - const schemeSelection = () => { - window.location.href = pathRoutes.organizations.verification.schema - } + 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 header = [ + { columnName: 'Request Id' }, + { columnName: 'Connection Id' }, + { columnName: 'Requested On' }, + { columnName: 'Status' }, + { columnName: 'Action' }, + ]; - return ( -
-
- -

- Verification List -

-
-
-
-
- - - + return ( +
+
+ +

+ Verification List +

+
+
+
+
+ { + walletCreated && + + + + } + onClickEvent={schemeSelection} + /> } - onClickEvent={schemeSelection} - /> -
- { - (proofReqSuccess || errMsg) && ( -
- setErrMsg(null)} - > - -

- {proofReqSuccess || errMsg} -

-
-
-
- )} - {loading ? ( -
-
- ) : verificationList && verificationList.length > 0 ? ( -
-
- {verificationList && verificationList.length > 0 && - - } -
-
- ) : ( -
- - There isn't any data available. - -
- )} + { + (proofReqSuccess || errMsg) && ( +
+ setErrMsg(null)} + > + +

+ {proofReqSuccess || errMsg} +

+
+
+
+ )} - + +
+ : +
+ { + + loading ? ( +
+ +
+ ) : verificationList && verificationList.length > 0 ? ( +
+
+ {verificationList && verificationList.length > 0 && + + } +
+
+ ) : ( +
+ + There isn't any data available. + +
+ ) + + } +
} - requestId={requestId} - userData={userData} - view={view} - /> + + +
-
- ) -} + ) + } -export default VerificationCredentialList; + export default VerificationCredentialList; diff --git a/src/components/organization/OrgDropDown.tsx b/src/components/organization/OrgDropDown.tsx index 4169a7abb..48e423e77 100644 --- a/src/components/organization/OrgDropDown.tsx +++ b/src/components/organization/OrgDropDown.tsx @@ -29,6 +29,7 @@ const OrgDropDown = () => { const goToOrgDashboard = async (org: Organisation) => { await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID) await removeFromLocalStorage(storageKeys.ECOSYSTEM_ROLE) + await removeFromLocalStorage(storageKeys.ORG_DETAILS) await setOrgRoleDetails(org) window.location.href = pathRoutes.organizations.dashboard; diff --git a/src/components/organization/WalletSpinup.tsx b/src/components/organization/WalletSpinup.tsx index 8028e0f2e..113699d9f 100644 --- a/src/components/organization/WalletSpinup.tsx +++ b/src/components/organization/WalletSpinup.tsx @@ -28,7 +28,6 @@ interface Values { } interface ValuesShared { - seed: string; label: string; } @@ -37,36 +36,234 @@ enum AgentType { DEDICATED = 'dedicated', } +interface ISharedAgentForm { + seeds: string + isCopied: boolean + copyTextVal: (e: any) => void + orgName: string + loading: boolean + submitSharedWallet: (values: ValuesShared) => void +} + +interface IDedicatedAgentForm { + seeds: string + loading: boolean + submitDedicatedWallet: (values: Values) => void +} + +const SharedAgentForm = ({ orgName, seeds, isCopied, loading, copyTextVal, submitSharedWallet }: ISharedAgentForm) => ( +
+
+
+
+
+ {seeds} + + + +
+
+ !value || !value.includes(' ')) + .matches( + /^[A-Za-z0-9-][^ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]*$/, + 'Wallet label must be alphanumeric only', + ) + .min(2, 'Wallet label must be at least 2 characters') + .max(25, 'Wallet label must be at most 25 characters'), + })} + validateOnBlur + validateOnChange + enableReinitialize + onSubmit={(values: ValuesShared) => submitSharedWallet(values)} + > + {(formikHandlers): JSX.Element => ( +
+
+
+
+ + { + // formikHandlers.handleChange(e) + // setOrganization(e.target.value) + // }} + /> + {formikHandlers?.errors?.label && + formikHandlers?.touched?.label && ( + + {formikHandlers?.errors?.label} + + )} +
+ + +
+ )} +
+
+); + +const DedicatedAgentForm = ({ seeds, loading, submitDedicatedWallet }: IDedicatedAgentForm) => ( + ?@[\]^_`{|}~]*$/, + 'Wallet name must be alphanumeric only', + ) + .label('Wallet name'), + password: yup + .string() + .matches( + passwordRegex, + 'Password must contain one Capital, Special character', + ) + .required('Wallet password is required') + .label('Wallet password'), + })} + validateOnBlur + validateOnChange + enableReinitialize + onSubmit={(values: Values) => submitDedicatedWallet(values)} + > + {(formikHandlers): JSX.Element => ( +
+
+
+
+ + {formikHandlers?.errors?.seed && formikHandlers?.touched?.seed && ( + + {formikHandlers?.errors?.seed} + + )} +
+
+
+
+ + {formikHandlers?.errors?.name && formikHandlers?.touched?.name && ( + + {formikHandlers?.errors?.name} + + )} +
+
+
+
+ + {formikHandlers?.errors?.password && + formikHandlers?.touched?.password && ( + + {formikHandlers?.errors?.password} + + )} +
+ +
+ )} +
+); + const WalletSpinup = (props: { setWalletSpinupStatus: (flag: boolean) => void; orgName: string }) => { const [agentType, setAgentType] = useState(AgentType.SHARED); - const [loading, setLoading] = useState(false); - const [walletSpinStep, setWalletSpinStep] = useState(0); - const [success, setSuccess] = useState(null); - const [agentSpinupCall, setAgentSpinupCall] = useState(false); - const [failure, setFailure] = useState(null); - const [seeds, setSeeds] = useState(''); - const [isCopied, setIsCopied] = useState(false); + // const [organization, setOrganization] = useState(props.orgName) - - const generateWalletname = () => { - - } useEffect(() => { setSeeds(nanoid(32)); - generateWalletname() }, []); - function copyTextVal(event: React.MouseEvent) { + const copyTextVal = (event: React.MouseEvent) => { event.preventDefault() setIsCopied(true); @@ -183,202 +380,9 @@ const WalletSpinup = (props: { console.log(`error-in-wallet-creation-process`, JSON.stringify(data)); }); - const DedicatedAgentForm = () => ( - ?@[\]^_`{|}~]*$/, - 'Wallet name must be alphanumeric only', - ) - .label('Wallet name'), - password: yup - .string() - .matches( - passwordRegex, - 'Password must contain one Capital, Special character', - ) - .required('Wallet password is required') - .label('Wallet password'), - })} - validateOnBlur - validateOnChange - enableReinitialize - onSubmit={(values: Values) => submitDedicatedWallet(values)} - > - {(formikHandlers): JSX.Element => ( -
-
-
-
- - {formikHandlers?.errors?.seed && formikHandlers?.touched?.seed && ( - - {formikHandlers?.errors?.seed} - - )} -
-
-
-
- - - {formikHandlers?.errors?.name && formikHandlers?.touched?.name && ( - - {formikHandlers?.errors?.name} - - )} -
- -
-
-
- - - {formikHandlers?.errors?.password && - formikHandlers?.touched?.password && ( - - {formikHandlers?.errors?.password} - - )} -
- -
- )} -
- ); - const orgName = props?.orgName ? props?.orgName?.split(" ").reduce((s, c) => (s.charAt(0).toUpperCase() + s.slice(1)) + (c.charAt(0).toUpperCase() + c.slice(1)) ) : "" - const SharedAgentForm = () => ( - !value || !value.includes(' ')) - .matches( - /^[A-Za-z0-9-][^ !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]*$/, - 'Wallet label must be alphanumeric only', - ) - .min(2, 'Wallet label must be at least 2 characters') - .max(25, 'Wallet label must be at most 25 characters'), - })} - validateOnBlur - validateOnChange - enableReinitialize - onSubmit={(values: ValuesShared) => submitSharedWallet(values)} - > - {(formikHandlers): JSX.Element => ( -
-
-
-
-
- {seeds} - - - -
- -
-
-
-
- - - {formikHandlers?.errors?.label && - formikHandlers?.touched?.label && ( - - {formikHandlers?.errors?.label} - - )} -
- - -
- )} -
- ); return (
@@ -444,9 +448,9 @@ const WalletSpinup = (props: { {!agentSpinupCall ? ( agentType === AgentType.SHARED ? ( - + ) : ( - + ) ) : ( Date: Thu, 26 Oct 2023 13:50:20 +0530 Subject: [PATCH 04/54] refactor: commented code Signed-off-by: sanjay-k1910 --- src/components/organization/WalletSpinup.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/organization/WalletSpinup.tsx b/src/components/organization/WalletSpinup.tsx index 113699d9f..7b3e329a9 100644 --- a/src/components/organization/WalletSpinup.tsx +++ b/src/components/organization/WalletSpinup.tsx @@ -111,10 +111,6 @@ const SharedAgentForm = ({ orgName, seeds, isCopied, loading, copyTextVal, submi name="label" className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" type="text" - // onChange={(e) => { - // formikHandlers.handleChange(e) - // setOrganization(e.target.value) - // }} /> {formikHandlers?.errors?.label && formikHandlers?.touched?.label && ( From a291236a458a672412ae89617e2f8a9821f49e3c Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Thu, 26 Oct 2023 14:54:36 +0530 Subject: [PATCH 05/54] fix: length of the input field characters Signed-off-by: bhavanakarwade --- .../Authentication/SignUpUserName.tsx | 127 +++++++++++++----- .../CreateEcosystemOrgModal/index.tsx | 32 ++++- .../EditEcosystemOrgModal/index.tsx | 24 ++++ src/components/Profile/EditUserProfile.tsx | 33 ++++- .../organization/EditOrgdetailsModal.tsx | 63 +++++++-- 5 files changed, 224 insertions(+), 55 deletions(-) diff --git a/src/components/Authentication/SignUpUserName.tsx b/src/components/Authentication/SignUpUserName.tsx index c91195775..94f814727 100644 --- a/src/components/Authentication/SignUpUserName.tsx +++ b/src/components/Authentication/SignUpUserName.tsx @@ -1,7 +1,5 @@ import 'react-toastify/dist/ReactToastify.css'; - import * as yup from 'yup'; - import { Button, Label } from 'flowbite-react'; import { Field, @@ -9,12 +7,11 @@ import { Formik } from 'formik'; import { useState } from 'react'; - -import React from 'react'; 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; @@ -126,13 +123,13 @@ const SignUpUserName = () => { .string() .required('First name is required') .min(2, 'First name must be at least 2 characters') - .max(50, 'First name must be at most 255 characters') + .max(50, 'First name must be at most 50 characters') .trim(), lastName: yup .string() .required('Last name is required') .min(2, 'Last name must be at least 2 characters') - .max(50, 'Last name must be at most 255 characters') + .max(50, 'Last name must be at most 50 characters') .trim() })} validateOnBlur @@ -151,72 +148,134 @@ const SignUpUserName = () => { lastName: formikHandlers.values.lastName }) return ( -
+
-
-
{ + const value = e.target.value; + formikHandlers.setFieldValue( + 'firstName', + value, + ); + formikHandlers.setFieldTouched( + 'firstName', + true, + ); + + if (value.length > 50) { + formikHandlers.setFieldError( + 'firstName', + 'First name must be at most 50 characters', + ); + } else { + formikHandlers.setFieldError( + 'firstName', + undefined, + ); + } + }} /> - { - (formikHandlers?.errors?.firstName && formikHandlers?.touched?.firstName) && - {formikHandlers?.errors?.firstName} - } + + {formikHandlers?.errors?.firstName && + formikHandlers?.touched?.firstName && ( + + {formikHandlers?.errors?.firstName} + + )}
-
-
{ + const value = e.target.value; + formikHandlers.setFieldValue('lastName', value); + formikHandlers.setFieldTouched( + 'lastName', + true, + ); + + if (value.length > 50) { + formikHandlers.setFieldError( + 'lastName', + 'Last name must be at most 50 characters', + ); + } else { + formikHandlers.setFieldError( + 'lastName', + undefined, + ); + } + }} /> - { - (formikHandlers?.errors?.lastName && formikHandlers?.touched?.lastName) && - {formikHandlers?.errors?.lastName} - } + {formikHandlers?.errors?.lastName && + formikHandlers?.touched?.lastName && ( + + {formikHandlers?.errors?.lastName} + + )}
- -
- Already have an account? -   {` Login here`}
-
- ) + ); }} diff --git a/src/components/CreateEcosystemOrgModal/index.tsx b/src/components/CreateEcosystemOrgModal/index.tsx index 5ebda9078..967e5500e 100644 --- a/src/components/CreateEcosystemOrgModal/index.tsx +++ b/src/components/CreateEcosystemOrgModal/index.tsx @@ -14,6 +14,7 @@ import { createOrganization } from "../../api/organization"; import { getFromLocalStorage } from "../../api/Auth"; import { createEcosystems } from "../../api/ecosystem"; import { getOrgDetails } from "../../config/ecosystem"; +import React from "react"; interface Values { name: string; @@ -340,7 +341,19 @@ const CreateEcosystemOrgModal = (props: IProps) => { name="name" value={formikHandlers.values.name} className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" - placeholder={`Enter ${popupName} Name`} /> + placeholder={`Enter ${popupName} Name`} + onChange={(e) => { + const value = e.target.value; + formikHandlers.setFieldValue('name', value); + formikHandlers.setFieldTouched('name', true); + + if (value.length > 50) { + formikHandlers.setFieldError('name', props.isorgModal ? 'Organization name must be at most 50 characters' : 'Ecosystem name must be at most 50 characters'); + } else { + formikHandlers.setFieldError('name', undefined); + } + }} + /> { (formikHandlers?.errors?.name && formikHandlers?.touched?.name) && {formikHandlers?.errors?.name} @@ -365,7 +378,19 @@ const CreateEcosystemOrgModal = (props: IProps) => { value={formikHandlers.values.description} as='textarea' className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" - placeholder={`Enter ${popupName} Description`} /> + placeholder={`Enter ${popupName} Description`} + onChange={(e) => { + const value = e.target.value; + formikHandlers.setFieldValue('description', value); + formikHandlers.setFieldTouched('description', true); + + if (value.length > 50) { + formikHandlers.setFieldError('description', 'Description must be at most 255 characters'); + } else { + formikHandlers.setFieldError('description', undefined); + } + }} + /> { (formikHandlers?.errors?.description && formikHandlers?.touched?.description) && {formikHandlers?.errors?.description} @@ -385,14 +410,11 @@ const CreateEcosystemOrgModal = (props: IProps) => { )} - - ) } - return ( <> {renderEcosystemModal()} diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index b2ec9e95c..986e5bba8 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -295,6 +295,18 @@ const EditPopupModal = (props: EditEntityModalProps) => { value={formikHandlers.values.name} className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder={`Enter ${props.isOrganization ? "Organization" : "Ecosystem"} Name`} + onChange={(e) => { + const value = e.target.value; + formikHandlers.setFieldValue('name', value); + formikHandlers.setFieldTouched('name', true); + + if (value.length > 50) { + formikHandlers.setFieldError('name', props.isOrganization ? 'Organization name must be at most 50 characters' : 'Ecosystem name must be at most 50 characters'); + } else { + formikHandlers.setFieldError('name', undefined); + } + }} + /> {formikHandlers?.errors?.name && formikHandlers?.touched?.name && ( {formikHandlers?.errors?.name} @@ -312,6 +324,18 @@ const EditPopupModal = (props: EditEntityModalProps) => { as='textarea' className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" placeholder={`Enter ${props.isOrganization ? "Organization" : "Ecosystem"} Description`} + onChange={(e) => { + const value = e.target.value; + formikHandlers.setFieldValue('description', value); + formikHandlers.setFieldTouched('description', true); + + if (value.length > 50) { + formikHandlers.setFieldError('description', 'Description must be at most 255 characters'); + } else { + formikHandlers.setFieldError('description', undefined); + } + }} + /> {formikHandlers?.errors?.description && formikHandlers?.touched?.description && ( {formikHandlers?.errors?.description} diff --git a/src/components/Profile/EditUserProfile.tsx b/src/components/Profile/EditUserProfile.tsx index 2c31e0660..0a74fee1b 100644 --- a/src/components/Profile/EditUserProfile.tsx +++ b/src/components/Profile/EditUserProfile.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useRef, useState} from "react"; import type { UserProfile } from "./interfaces"; import { setToLocalStorage, updateUserProfile } from "../../api/Auth"; import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, imageSizeAccepted, storageKeys} from "../../config/CommonConstant"; @@ -8,7 +8,6 @@ import { calculateSize, dataURItoBlob } from "../../utils/CompressImage"; import { Alert,Button} from "flowbite-react"; import { Form, Formik, FormikHelpers } from "formik"; import * as yup from "yup" -import React from "react"; interface Values { profileImg: string; @@ -179,12 +178,12 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile}: E firstName: yup.string() .required("First Name is required") .min(2, 'First name must be at least 2 characters') - .max(255, 'First name must be at most 255 characters'), - + .max(50, 'First name must be at most 50 characters'), + lastName: yup.string() .required("Last Name is required") .min(2, 'Last name must be at least 2 characters') - .max(255, 'Last name must be at most 255 characters') + .max(50, 'Last name must be at most 50 characters') }); @@ -253,7 +252,17 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile}: E name="firstName" placeholder="Enter your first name" value={formikHandlers.values.firstName} - onChange={formikHandlers.handleChange} + onChange={(e) => { + const value = e.target.value; + formikHandlers.setFieldValue('firstName', value); + formikHandlers.setFieldTouched('firstName', true); + + if (value.length > 50) { + formikHandlers.setFieldError('firstName', 'First name must be at most 50 characters'); + } else { + formikHandlers.setFieldError('firstName', undefined); + } + }} onBlur={formikHandlers.handleBlur} ref={firstNameInputRef} className="bg-gray-50 py-3 px-4 font-medium text-gray-900 border border-gray-300 w-full rounded-md focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 max-w-100/6rem" /> @@ -278,7 +287,17 @@ const EditUserProfile = ({ toggleEditProfile, userProfileInfo, updateProfile}: E name="lastName" placeholder="Enter your last name" value={formikHandlers.values.lastName} - onChange={formikHandlers.handleChange} + onChange={(e) => { + const value = e.target.value; + formikHandlers.setFieldValue('lastName', value); + formikHandlers.setFieldTouched('lastName', true); + + if (value.length > 50) { + formikHandlers.setFieldError('lastName', 'Last name must be at most 50 characters'); + } else { + formikHandlers.setFieldError('lastName', undefined); + } + }} onBlur={formikHandlers.handleBlur} className="bg-gray-50 py-3 px-4 font-medium text-gray-900 border border-gray-300 w-full rounded-md focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 max-w-100/6rem" /> {(formikHandlers?.errors?.lastName && formikHandlers?.touched?.lastName) && ( diff --git a/src/components/organization/EditOrgdetailsModal.tsx b/src/components/organization/EditOrgdetailsModal.tsx index 997179817..3e055d5a6 100644 --- a/src/components/organization/EditOrgdetailsModal.tsx +++ b/src/components/organization/EditOrgdetailsModal.tsx @@ -2,7 +2,7 @@ import * as yup from "yup" import { Avatar, Button, Label, Modal } from 'flowbite-react'; import { Field, Form, Formik, FormikHelpers } from 'formik'; -import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, apiStatusCodes, imageSizeAccepted, storageKeys } from '../../config/CommonConstant' +import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, apiStatusCodes, imageSizeAccepted} from '../../config/CommonConstant' import { calculateSize, dataURItoBlob } from "../../utils/CompressImage"; import { useEffect, useState } from "react"; @@ -10,26 +10,24 @@ import { AlertComponent } from "../AlertComponent"; import type { AxiosResponse } from 'axios'; import { updateOrganization } from "../../api/organization"; import type { Organisation } from "./interfaces"; +import React from "react"; interface Values { website: any; name: string; description: string; } - interface ILogoImage { logoFile: string | File imagePreviewUrl: string | ArrayBuffer | null | File, fileName: string } - interface EditOrgdetailsModalProps { openModal: boolean; setMessage: (message: string) => void; setOpenModal: (flag: boolean) => void; onEditSucess?: () => void; orgData: Organisation | null; - } const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { @@ -55,7 +53,7 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { setOrgData({ name: props.orgData.name || '', description: props.orgData.description || '', - website: props?.orgData?.website || "", + website: props?.orgData?.website || "", }); setLogoImage({ @@ -76,7 +74,7 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { setOrgData({ name: '', description: '', - website:'' + website:'' }) setLogoImage({ @@ -282,7 +280,6 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { className="hidden" id="organizationlogo" title="" onChange={(event): void => handleImageChange(event)} /> - {/* {selectedImage || 'No File Chosen'} */} {imgError ?
{imgError}
: {logoImage.fileName || 'No File Chosen'}} @@ -308,7 +305,31 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { name="name" value={formikHandlers.values.name} className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" - placeholder="Your organization name" /> + placeholder="Your organization name" + onChange={(e) => { + const value = e.target.value; + formikHandlers.setFieldValue( + 'name', + value, + ); + formikHandlers.setFieldTouched( + 'name', + true, + ); + + if (value.length > 50) { + formikHandlers.setFieldError( + 'name', + 'Organization name must be at most 50 characters', + ); + } else { + formikHandlers.setFieldError( + 'name', + undefined, + ); + } + }} + /> { (formikHandlers?.errors?.name && formikHandlers?.touched?.name) && {formikHandlers?.errors?.name} @@ -334,7 +355,31 @@ const EditOrgdetailsModal = (props: EditOrgdetailsModalProps) => { value={formikHandlers.values.description} as='textarea' className="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500" - placeholder="Description of your organization" /> + placeholder="Description of your organization" + onChange={(e) => { + const value = e.target.value; + formikHandlers.setFieldValue( + 'description', + value, + ); + formikHandlers.setFieldTouched( + 'description', + true, + ); + + if (value.length > 50) { + formikHandlers.setFieldError( + 'description', + 'Description must be at most 50 characters', + ); + } else { + formikHandlers.setFieldError( + 'description', + undefined, + ); + } + }} + /> { (formikHandlers?.errors?.description && formikHandlers?.touched?.description) && {formikHandlers?.errors?.description} From 6c3535487d7aea64df7b7cd1d88b380eaec6fd97 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Fri, 27 Oct 2023 15:38:26 +0530 Subject: [PATCH 06/54] feat: multi-ecosystem Signed-off-by: sanjay-k1910 --- src/api/ecosystem.ts | 3 +- src/app/LayoutCommon.astro | 2 +- src/components/Ecosystem/Dashboard.tsx | 71 ++--- src/components/Ecosystem/EcosystemList.tsx | 249 ++++++++++++++++++ .../Ecosystem/EcosystemSidebarOption.tsx | 60 +---- src/components/Ecosystem/interfaces/index.ts | 6 + src/config/ecosystem.ts | 202 +++++++------- src/config/pathRoutes.ts | 10 +- src/pages/dashboard.astro | 1 + .../dashboard.astro} | 0 .../endorsement/index.astro | 0 src/pages/ecosystems/index.astro | 16 ++ .../invitation.astro | 10 +- .../invitations.astro | 10 +- 14 files changed, 437 insertions(+), 203 deletions(-) create mode 100644 src/components/Ecosystem/EcosystemList.tsx rename src/pages/{ecosystem/index.astro => ecosystems/dashboard.astro} (100%) rename src/pages/{ecosystem => ecosystems}/endorsement/index.astro (100%) create mode 100644 src/pages/ecosystems/index.astro rename src/pages/{ecosystem => ecosystems}/invitation.astro (75%) rename src/pages/{ecosystem => ecosystems}/invitations.astro (81%) diff --git a/src/api/ecosystem.ts b/src/api/ecosystem.ts index bab35e7ca..d42ee22d7 100644 --- a/src/api/ecosystem.ts +++ b/src/api/ecosystem.ts @@ -62,9 +62,8 @@ export const updateEcosystem = async (dataPayload: CreateEcosystemPayload) => { } }; -export const getEcosystem = async (orgId: string) => { +export const getEcosystems = async (orgId: string, pageNumber?: number, pageSize?: number, search = '') => { const url = `${apiRoutes.Ecosystem.root}/${orgId}`; - const axiosPayload = { url, config: await getHeaderConfigs(), diff --git a/src/app/LayoutCommon.astro b/src/app/LayoutCommon.astro index ed0817e24..c253a4d63 100644 --- a/src/app/LayoutCommon.astro +++ b/src/app/LayoutCommon.astro @@ -46,7 +46,7 @@ const supabaseKey = process.env.PUBLIC_SUPABASE_KEY || import.meta.env.PUBLIC_SU + , 'dark:scrollbar-track-gray-900 dark:scrollbar-thumb-gray-700' , 'dark:bg-[#111827]']}> diff --git a/src/components/Ecosystem/Dashboard.tsx b/src/components/Ecosystem/Dashboard.tsx index c4600b5c2..d6c195f5a 100644 --- a/src/components/Ecosystem/Dashboard.tsx +++ b/src/components/Ecosystem/Dashboard.tsx @@ -9,7 +9,7 @@ import CustomSpinner from '../CustomSpinner'; import endorseIcon from '../../assets/endorser-icon.svg'; import memberIcon from '../../assets/member-icon.svg'; import MemberList from './MemberList'; -import { getEcosystem, getEcosystemDashboard } from '../../api/ecosystem'; +import { getEcosystems, getEcosystemDashboard } from '../../api/ecosystem'; import { EmptyListMessage } from '../EmptyListComponent'; import CreateEcosystemOrgModal from '../CreateEcosystemOrgModal'; import { AlertComponent } from '../AlertComponent'; @@ -118,20 +118,21 @@ const Dashboard = () => { const fetchEcosystemDetails = async () => { setLoading(true); const id = await getFromLocalStorage(storageKeys.ORG_ID); + const ecosystemId = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID); setOrgId(id); if (id) { - const response = await getEcosystem(id); + const response = await getEcosystems(id); const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const ecosystemData = data?.data[0]; + const ecosystemData = data?.data.find((item: { id: string }) => item.id === ecosystemId); if (ecosystemData) { - await setToLocalStorage(storageKeys.ECOSYSTEM_ID, ecosystemData?.id); const ecosystemOrg = ecosystemData?.ecosystemOrgs && ecosystemData?.ecosystemOrgs.length > 0 && ecosystemData?.ecosystemOrgs[0]; setEcosystemDetails({ + id: ecosystemData?.id, logoUrl: ecosystemData?.logoUrl, name: ecosystemData?.name, description: ecosystemData?.description, @@ -422,36 +423,36 @@ const Dashboard = () => { )}
- -
-
- - -
-
-
- -
- { - setSuccess(value); - }} - isOrganization={false} - onEditSuccess={handleEditModalClose} - entityData={ecosystemDetails} +
+
+ + window.location.href = pathRoutes.ecosystem.endorsements} + /> +
+
+
+ +
+ { + setSuccess(value); + }} + isOrganization={false} + onEditSuccess={handleEditModalClose} + entityData={ecosystemDetails} + />
) : (
@@ -481,8 +482,8 @@ const Dashboard = () => { feature={!orgId ? Features.CRETAE_ORG : ''} message={'No Ecosystem found'} description={`Get started by creating ${!orgId - ? 'a new Organization to set up your Ecosystem' - : 'an Ecosystem' + ? 'a new Organization to set up your Ecosystem' + : 'an Ecosystem' }`} buttonContent={`${!orgId ? '' : 'Create Ecosystem'}`} svgComponent={ diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx new file mode 100644 index 000000000..2af1a087a --- /dev/null +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -0,0 +1,249 @@ +'use client'; + +import { Card, Pagination } from 'flowbite-react'; +import { ChangeEvent, useEffect, useState } from 'react'; +import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; + +import { AlertComponent } from '../AlertComponent'; +import type { AxiosResponse } from 'axios'; +import BreadCrumbs from '../BreadCrumbs'; +import CustomAvatar from '../Avatar' +import { Features } from '../../utils/enums/features'; +import RoleViewButton from '../RoleViewButton'; +import SearchInput from '../SearchInput'; +import { pathRoutes } from '../../config/pathRoutes'; +import { getFromLocalStorage, removeFromLocalStorage, setToLocalStorage } from '../../api/Auth'; +import { EmptyListMessage } from '../EmptyListComponent'; +import CustomSpinner from '../CustomSpinner'; +import CreateEcosystemOrgModal from '../CreateEcosystemOrgModal'; +import { getEcosystems } from '../../api/ecosystem'; +import type { IEcosystem } from './interfaces'; +import { checkEcosystem, type ICheckEcosystem } from '../../config/ecosystem'; + +const initialPageState = { + pageNumber: 1, + pageSize: 9, + total: 100, +}; + +const EcosystemList = () => { + const [openModal, setOpenModal] = useState(false); + const [loading, setLoading] = useState(true) + const [message, setMessage] = useState(null) + const [error, setError] = useState(null) + const [currentPage, setCurrentPage] = useState(initialPageState); + const onPageChange = (page: number) => { + setCurrentPage({ + ...currentPage, + pageNumber: page + }) + }; + const [searchText, setSearchText] = useState(""); + + const [ecosystemList, setEcosystemList] = useState | null>(null) + const [isEcosystemData, setIsEcosystemData] = useState() + + const createOrganizationModel = () => { + setOpenModal(true) + } + + const fetchEcosystems = async () => { + setLoading(true); + const id = await getFromLocalStorage(storageKeys.ORG_ID); + // setOrgId(id); + if (id) { + const response = await getEcosystems(id, currentPage.pageNumber, currentPage.pageSize, searchText); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const ecosystemData = data?.data; + if (ecosystemData) { + console.log(6565, data) + setEcosystemList(ecosystemData) + } else { + await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); + setError(response as string) + } + } else { + await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); + setError(response as string) + } + } + setLoading(false); + }; + + //This useEffect is called when the searchText changes + useEffect(() => { + let getData: NodeJS.Timeout + + if (searchText.length >= 1) { + getData = setTimeout(() => { + fetchEcosystems() + }, 1000) + } else { + fetchEcosystems() + } + + return () => clearTimeout(getData) + }, [searchText, openModal, currentPage.pageNumber]) + + useEffect(() => { + const queryParameters = new URLSearchParams(window?.location?.search) + const isModel = queryParameters.get("orgModal") || '' + + if (isModel !== '') { + setOpenModal(true) + } + + const checkEcosystemData = async () => { + const data: ICheckEcosystem = await checkEcosystem(); + setIsEcosystemData(data) + } + checkEcosystemData(); + }, []) + + //onCHnage of Search input text + const searchInputChange = (e: ChangeEvent) => { + setSearchText(e.target.value); + } + + const redirectOrgDashboard = async (ecosystemId: string, ecosystemRole: string) => { + await setToLocalStorage(storageKeys.ECOSYSTEM_ID, ecosystemId); + await setToLocalStorage(storageKeys.ECOSYSTEM_ROLE, ecosystemRole); + window.location.href = pathRoutes.ecosystem.dashboard + } + + const isEcosystemList = Boolean(ecosystemList && ecosystemList?.length > 0) + const showCreateButton = Boolean(isEcosystemList && (isEcosystemData?.isMultiEcosystem || isEcosystemData?.isEcosystemLead)) + console.log(6534, isEcosystemData, showCreateButton, isEcosystemList, isEcosystemData?.isMultiEcosystem, isEcosystemData?.isEcosystemLead, (isEcosystemList && isEcosystemData?.isMultiEcosystem) || isEcosystemData?.isEcosystemLead) + return ( +
+
+ + +

+ Ecosystems +

+
+
+
+
+ + { + showCreateButton && + + + + +
+ } + onClickEvent={createOrganizationModel} + /> + } +
+ + { + setMessage(null) + setError(null) + }} + /> + + {loading + ?
+ +
+ : isEcosystemList ? (
+ { + isEcosystemList && ecosystemList && ecosystemList.map((item) => { + const role = item?.ecosystemOrgs && item?.ecosystemOrgs.length > 0 && item?.ecosystemOrgs[0]?.ecosystemRole?.name || "" + return ( + redirectOrgDashboard(item.id, role)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden overflow-ellipsis' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto' }}> +
+ {(item.logoUrl) ? : } + +
+
+ {item.name} +
+

{item.description}

+
+
    +
  • +
    +
    + Roles: + {item?.ecosystemOrgs && item?.ecosystemOrgs?.length > 0 && item?.ecosystemOrgs[0].ecosystemRole && + item?.ecosystemOrgs[0]?.ecosystemRole?.name && + + {item?.ecosystemOrgs[0]?.ecosystemRole?.name} + + } +
    +
    +
  • +
+
+
+
+
+ ) + }) + } +
) + : ecosystemList && ( + + + } />) + } + +
+ { + isEcosystemList && ( + + ) + } +
+ { + setMessage(value) + if (value) { + setTimeout(() => { + window.location.reload(); + }, 2000); + } else { + fetchEcosystems(); + } + }} + isorgModal={false} + /> +
+
+
+ ) +} + +export default EcosystemList; diff --git a/src/components/Ecosystem/EcosystemSidebarOption.tsx b/src/components/Ecosystem/EcosystemSidebarOption.tsx index 0fc019aae..4904e4005 100644 --- a/src/components/Ecosystem/EcosystemSidebarOption.tsx +++ b/src/components/Ecosystem/EcosystemSidebarOption.tsx @@ -1,11 +1,9 @@ import { useEffect, useState } from 'react' import { ICheckEcosystem, checkEcosystem } from '../../config/ecosystem' import { pathRoutes } from '../../config/pathRoutes' -import React from 'react'; const EcosystemSidebarOption = () => { const [isEcosystemEnabled, setIsEcosystemEnabled] = useState(false); - const [showSubMenus, setShowSubMenus] = useState(true); useEffect(() => { const checkEcosystemData = async () => { @@ -18,12 +16,9 @@ const EcosystemSidebarOption = () => { if (isEcosystemEnabled) { return (
  • - - { - showSubMenus && - - } + Ecosystems +
  • ) } diff --git a/src/components/Ecosystem/interfaces/index.ts b/src/components/Ecosystem/interfaces/index.ts index bd8f6c334..24e41c258 100644 --- a/src/components/Ecosystem/interfaces/index.ts +++ b/src/components/Ecosystem/interfaces/index.ts @@ -1,9 +1,15 @@ export interface IEcosystem { + id: string name: string description: string logoUrl: string joinedDate?: string role?: string + ecosystemOrgs?: { + ecosystemRole: { + name: string + } + }[] } export interface Ecosystem { diff --git a/src/config/ecosystem.ts b/src/config/ecosystem.ts index deb0dbed9..7cd383955 100644 --- a/src/config/ecosystem.ts +++ b/src/config/ecosystem.ts @@ -1,114 +1,134 @@ -import type { AxiosResponse } from "axios" -import { getFromLocalStorage, setToLocalStorage } from "../api/Auth" -import { getEcosystem } from "../api/ecosystem" -import { EcosystemRoles } from "../common/enums" -import { apiStatusCodes, storageKeys } from "./CommonConstant" -import { getOrganizationById } from "../api/organization" +import type { AxiosResponse } from 'axios'; +import { getFromLocalStorage, setToLocalStorage } from '../api/Auth'; +import { getEcosystems } from '../api/ecosystem'; +import { EcosystemRoles } from '../common/enums'; +import { apiStatusCodes, storageKeys } from './CommonConstant'; +import { getOrganizationById } from '../api/organization'; export interface ICheckEcosystem { - isEnabledEcosystem: boolean; - isEcosystemMember: boolean; - isEcosystemLead: boolean; + isEnabledEcosystem: boolean; + isEcosystemMember: boolean; + isEcosystemLead: boolean; + isMultiEcosystem: boolean; } export interface IOrgDetails { - orgName: string - orgDid: string + orgName: string; + orgDid: string; } const ecosystemId = async () => { - const id = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID) - return id -} + const id = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID); + return id; +}; const getOrgData = async () => { - const data = await getFromLocalStorage(storageKeys.ORG_DETAILS) - return data -} + const data = await getFromLocalStorage(storageKeys.ORG_DETAILS); + return data; +}; const getEcosystemRole = async () => { - const data = await getFromLocalStorage(storageKeys.ECOSYSTEM_ROLE) - return data -} + const data = await getFromLocalStorage(storageKeys.ECOSYSTEM_ROLE); + return data; +}; const getOrgId = async () => { - const id = await getFromLocalStorage(storageKeys.ORG_ID) - return id -} + const id = await getFromLocalStorage(storageKeys.ORG_ID); + return id; +}; const getUserProfile = async () => { - const userProfile = await getFromLocalStorage(storageKeys.USER_PROFILE) - const userDetails = userProfile && await JSON.parse(userProfile) - return userDetails -} + const userProfile = await getFromLocalStorage(storageKeys.USER_PROFILE); + const userDetails = userProfile && (await JSON.parse(userProfile)); + return userDetails; +}; const checkEcosystem = async (): Promise => { - await getEcosystemId() - const userData = await getUserProfile() - const role = await getEcosystemRole() - - const isEnabledEcosystem = userData?.enableEcosystem - const ecosystemRole = role || EcosystemRoles.ecosystemLead - - return { - isEnabledEcosystem, - isEcosystemMember: ecosystemRole === EcosystemRoles.ecosystemMember && isEnabledEcosystem, - isEcosystemLead: ecosystemRole === EcosystemRoles.ecosystemLead && isEnabledEcosystem - } -} + await getEcosystemId(); + const userData = await getUserProfile(); + const role = await getEcosystemRole(); + + const isEnabledEcosystem = userData?.enableEcosystem; + const ecosystemRole = role || EcosystemRoles.ecosystemLead; + + const isMultiEcosystem = userData?.multiEcosystemSupport; + // const isMultiEcosystem = false + + return { + isEnabledEcosystem, + isMultiEcosystem, + isEcosystemMember: + ecosystemRole === EcosystemRoles.ecosystemMember && isEnabledEcosystem, + isEcosystemLead: + ecosystemRole === EcosystemRoles.ecosystemLead && isEnabledEcosystem, + }; +}; const getEcosystemId = async (): Promise => { - const ecoId = await ecosystemId() - const ecoRole = await getEcosystemRole() - const orgId = await getOrgId() - if (!ecoId || !ecoRole) { - try { - if(orgId){ - const { data } = await getEcosystem(orgId) as AxiosResponse - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS && data?.data && data?.data.length > 0) { - const response = data?.data[0] - const id = response?.id - const role = response?.ecosystemOrgs && response?.ecosystemOrgs.length > 0 && response?.ecosystemOrgs[0]?.ecosystemRole?.name - await setToLocalStorage(storageKeys.ECOSYSTEM_ID, id); - if(role){ - await setToLocalStorage(storageKeys.ECOSYSTEM_ROLE, role); - } - return id - } - } - } catch (err) { - console.log("ERROR-Get Ecosystem", err) - } - } - return ecoId -} + const ecoId = await ecosystemId(); + const ecoRole = await getEcosystemRole(); + const orgId = await getOrgId(); + if (!ecoId || !ecoRole) { + try { + if (orgId) { + const { data } = (await getEcosystems(orgId)) as AxiosResponse; + + if ( + data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS && + data?.data && + data?.data.length > 0 + ) { + const response = data?.data[0]; + const id = response?.id; + const role = + response?.ecosystemOrgs && + response?.ecosystemOrgs.length > 0 && + response?.ecosystemOrgs[0]?.ecosystemRole?.name; + await setToLocalStorage(storageKeys.ECOSYSTEM_ID, id); + if (role) { + await setToLocalStorage(storageKeys.ECOSYSTEM_ROLE, role); + } + return id; + } + } + } catch (err) { + console.log('ERROR-Get Ecosystem', err); + } + } + return ecoId; +}; const getOrgDetails = async (): Promise => { - const orgId = await getOrgId() - const org = await getOrgData() - const orgData: IOrgDetails = org && JSON.parse(org) - const isOrgData = Object.keys(orgData).length > 0 - const isOrgDid = orgData?.orgDid - if (!isOrgData || !isOrgDid) { - try { - if(orgId){ - const { data } = await getOrganizationById(orgId) as AxiosResponse - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const orgData: IOrgDetails = { - orgName: data?.data?.name, - orgDid: data?.data && data?.data?.org_agents?.length > 0 ? data?.data?.org_agents[0]?.orgDid : "" - } - await setToLocalStorage(storageKeys.ORG_DETAILS, JSON.stringify(orgData)); - return orgData - } - } - } catch (err) { - console.log("ERROR-Get ORG Details", err) - } - } - return orgData -} + const orgId = await getOrgId(); + const org = await getOrgData(); + const orgData: IOrgDetails = org && JSON.parse(org); + const isOrgData = Object.keys(orgData).length > 0; + const isOrgDid = orgData?.orgDid; + if (!isOrgData || !isOrgDid) { + try { + if (orgId) { + const { data } = (await getOrganizationById(orgId)) as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const orgData: IOrgDetails = { + orgName: data?.data?.name, + orgDid: + data?.data && data?.data?.org_agents?.length > 0 + ? data?.data?.org_agents[0]?.orgDid + : '', + }; + await setToLocalStorage( + storageKeys.ORG_DETAILS, + JSON.stringify(orgData), + ); + return orgData; + } + } + } catch (err) { + console.log('ERROR-Get ORG Details', err); + } + } + return orgData; +}; -export { checkEcosystem, getEcosystemId, getOrgDetails } \ No newline at end of file +export { checkEcosystem, getEcosystemId, getOrgDetails }; diff --git a/src/config/pathRoutes.ts b/src/config/pathRoutes.ts index 0472b3f1b..1cbdb9584 100644 --- a/src/config/pathRoutes.ts +++ b/src/config/pathRoutes.ts @@ -34,11 +34,11 @@ export const pathRoutes = { }, }, ecosystem: { - root: '/ecosystem', - profile: "/ecosystem/profile", - endorsements: "/ecosystem/endorsement", - invitation:"/ecosystem/invitation", - sentinvitation:'/ecosystem/invitations' + root: '/ecosystems', + dashboard: "/ecosystems/dashboard", + endorsements: "/ecosystems/endorsement", + invitation:"/ecosystems/invitation", + sentinvitation:'/ecosystems/invitations' }, documentation: { root: 'https://docs.credebl.id' diff --git a/src/pages/dashboard.astro b/src/pages/dashboard.astro index be1dfb0df..33f76a0e4 100644 --- a/src/pages/dashboard.astro +++ b/src/pages/dashboard.astro @@ -7,6 +7,7 @@ import { checkUserSession } from '../utils/check-session'; const response = await checkUserSession(Astro.cookies); const route: string = pathRoutes.auth.sinIn if (!response) { + await localStorage.clear() return Astro.redirect(route); } --- diff --git a/src/pages/ecosystem/index.astro b/src/pages/ecosystems/dashboard.astro similarity index 100% rename from src/pages/ecosystem/index.astro rename to src/pages/ecosystems/dashboard.astro diff --git a/src/pages/ecosystem/endorsement/index.astro b/src/pages/ecosystems/endorsement/index.astro similarity index 100% rename from src/pages/ecosystem/endorsement/index.astro rename to src/pages/ecosystems/endorsement/index.astro diff --git a/src/pages/ecosystems/index.astro b/src/pages/ecosystems/index.astro new file mode 100644 index 000000000..1849c2d9d --- /dev/null +++ b/src/pages/ecosystems/index.astro @@ -0,0 +1,16 @@ +--- +import LayoutSidebar from '../../app/LayoutSidebar.astro'; +import { checkUserSession } from '../../utils/check-session'; +import { pathRoutes } from '../../config/pathRoutes'; +import EcosystemList from '../../components/Ecosystem/EcosystemList'; + +const response = await checkUserSession(Astro.cookies); +const route: string = pathRoutes.auth.sinIn +if (!response) { + return Astro.redirect(route); +} +--- + + + + \ No newline at end of file diff --git a/src/pages/ecosystem/invitation.astro b/src/pages/ecosystems/invitation.astro similarity index 75% rename from src/pages/ecosystem/invitation.astro rename to src/pages/ecosystems/invitation.astro index ab1fc836f..c7578c5f1 100644 --- a/src/pages/ecosystem/invitation.astro +++ b/src/pages/ecosystems/invitation.astro @@ -2,19 +2,15 @@ import LayoutSidebar from '../../app/LayoutSidebar.astro'; import { checkUserSession } from '../../utils/check-session'; import { pathRoutes } from '../../config/pathRoutes'; -import EcoSystemReceivedInvitations from '../../components/EcosystemInvite/EcoSystemReceivedInvitations' +import EcoSystemReceivedInvitations from '../../components/EcosystemInvite/EcoSystemReceivedInvitations'; const response = await checkUserSession(Astro.cookies); -const route = pathRoutes.auth.sinIn +const route = pathRoutes.auth.sinIn; if (!response) { return Astro.redirect(route); } --- - + - - - - diff --git a/src/pages/ecosystem/invitations.astro b/src/pages/ecosystems/invitations.astro similarity index 81% rename from src/pages/ecosystem/invitations.astro rename to src/pages/ecosystems/invitations.astro index e1edcb51e..98c1e7c39 100644 --- a/src/pages/ecosystem/invitations.astro +++ b/src/pages/ecosystems/invitations.astro @@ -2,19 +2,15 @@ import LayoutSidebar from '../../app/LayoutSidebar.astro'; import { checkUserSession } from '../../utils/check-session'; import { pathRoutes } from '../../config/pathRoutes'; -import SentInvitations from '../../components/EcosystemInvite/SentInvitations' +import SentInvitations from '../../components/EcosystemInvite/SentInvitations'; const response = await checkUserSession(Astro.cookies); -const route = pathRoutes.auth.sinIn +const route = pathRoutes.auth.sinIn; if (!response) { return Astro.redirect(route); } --- - + - - - - From 5c7a4f5bbb623ad57eae31e932d358cb214765d9 Mon Sep 17 00:00:00 2001 From: karan Date: Fri, 27 Oct 2023 17:26:53 +0530 Subject: [PATCH 07/54] refactor: connection list read only on sidebar Signed-off-by: karan --- src/app/SideBar.astro | 24 ++++++++ src/components/ConnectionsList/index.tsx | 77 ++++++++++++++++++++++++ src/config/pathRoutes.ts | 1 + src/pages/connections.astro | 8 +++ 4 files changed, 110 insertions(+) create mode 100644 src/components/ConnectionsList/index.tsx create mode 100644 src/pages/connections.astro diff --git a/src/app/SideBar.astro b/src/app/SideBar.astro index 62e3d9e49..1ca03c146 100644 --- a/src/app/SideBar.astro +++ b/src/app/SideBar.astro @@ -163,6 +163,30 @@ import { pathRoutes } from '../config/pathRoutes'; +
  • + + + + + + Connections + +
  • + - + + + GitHub Repository + + + Documentation - - - - - - Support - + diff --git a/src/components/organization/invitations/Invitations.tsx b/src/components/organization/invitations/Invitations.tsx index 017f0e3fa..43db0c787 100644 --- a/src/components/organization/invitations/Invitations.tsx +++ b/src/components/organization/invitations/Invitations.tsx @@ -164,14 +164,14 @@ const Invitations = () => {

    {invitation.email}

      -
    • +
    • {invitation.orgRoles.length>1 ? 'Roles:' : 'Role:'} @@ -226,7 +226,6 @@ const Invitations = () => { > Invited On:  {dateConversion(invitation.createDateTime)}

      -
    • )) diff --git a/src/components/organization/users/Members.tsx b/src/components/organization/users/Members.tsx index 677419589..b1d0766cb 100644 --- a/src/components/organization/users/Members.tsx +++ b/src/components/organization/users/Members.tsx @@ -144,15 +144,16 @@ const Members = () => { ) : ( usersList && usersList?.length > 0 && ( -
      -
      +
      +
        +
        {usersList.map((user) => (
      • -
        +
        -

        +

        {user.firstName} {user.lastName}

        @@ -160,8 +161,8 @@ const Members = () => {
        • -
          - Roles: +
          + {user.roles.length >1 ? 'Roles:' : 'Role:'} {user.roles && user.roles.length > 0 && user.roles.map( @@ -197,7 +198,7 @@ const Members = () => { className="cursor-pointer mr-2 flex items-center text-sm font-medium text-gray-500 dark:text-gray-400" > {
        • ))} +
      -
      +
      ) )} From 2fd0585c321a95a2a0b2a4b5239afe2c38d5fc1b Mon Sep 17 00:00:00 2001 From: karan Date: Wed, 1 Nov 2023 17:39:44 +0530 Subject: [PATCH 22/54] fix: connection list issue and verification popup issue Signed-off-by: karan --- src/components/ConnectionsList/index.tsx | 64 ++++++++++--------- .../Verification/SchemaCredDefDetails.tsx | 2 +- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/components/ConnectionsList/index.tsx b/src/components/ConnectionsList/index.tsx index 2ec479ef2..261bf6045 100644 --- a/src/components/ConnectionsList/index.tsx +++ b/src/components/ConnectionsList/index.tsx @@ -5,13 +5,14 @@ import { useEffect, useState } from 'react'; import { getConnectionsByOrg } from '../../api/connection'; import DataTable from '../../commonComponents/datatable'; import type { TableData } from '../../commonComponents/datatable/interface'; -import { apiStatusCodes } from '../../config/CommonConstant'; +import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import { dateConversion } from '../../utils/DateConversion'; import DateTooltip from '../Tooltip'; import BreadCrumbs from '../BreadCrumbs'; import CustomSpinner from '../CustomSpinner'; import { EmptyListMessage } from '../EmptyListComponent'; +import { getFromLocalStorage } from '../../api/Auth'; const ConnectionList = () => { const [connectionList, setConnectionList] = useState([]); @@ -23,35 +24,38 @@ const ConnectionList = () => { }, []); const getConnections = async () => { - setLoading(true); - const response = await getConnectionsByOrg(); - const { data } = response as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const connections = data?.data?.map( - (ele: { theirLabel: string; id: string; createdAt: 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'; - return { - data: [ - { data: userName }, - { data: connectionId }, - { - data: ( - - {' '} - {dateConversion(createdOn)}{' '} - - ), - }, - ], - }; - }, - ); - setConnectionList(connections); - } else { - setError(response as string); + const orgId= await getFromLocalStorage(storageKeys.ORG_ID) + if(orgId){ + setLoading(true); + const response = await getConnectionsByOrg(); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const connections = data?.data?.map( + (ele: { theirLabel: string; id: string; createdAt: 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'; + return { + data: [ + { data: userName }, + { data: connectionId }, + { + data: ( + + {' '} + {dateConversion(createdOn)}{' '} + + ), + }, + ], + }; + }, + ); + setConnectionList(connections); + } else { + setError(response as string); + } } setLoading(false); }; diff --git a/src/components/Verification/SchemaCredDefDetails.tsx b/src/components/Verification/SchemaCredDefDetails.tsx index f0251d8a5..a99309352 100644 --- a/src/components/Verification/SchemaCredDefDetails.tsx +++ b/src/components/Verification/SchemaCredDefDetails.tsx @@ -32,7 +32,7 @@ const SchemaCredDefDetails = ({ schemaCredDefList }: SchemaCredDefProps) => { {Object.values(item)[1] ? (
      -
      +
      {Object.values(item)[1] ? 'CredDef Id' : ''}
      {' '}
      From f62d7a4b511fac97b48cd2b4941e50c66f009a2a Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Wed, 1 Nov 2023 19:43:17 +0530 Subject: [PATCH 23/54] fix:css fixes in ecosystem and organization list Signed-off-by: pranalidhanavade --- src/components/Ecosystem/EcosystemList.tsx | 14 +++++++------- src/components/organization/OrganizationsList.tsx | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index 2f69d0538..55e4ea39b 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -121,8 +121,8 @@ const EcosystemList = () => {
      -
      -

      +
      +

      Ecosystems

      { @@ -169,15 +169,15 @@ const EcosystemList = () => { ecosystemList?.map((item) => { const role = item?.ecosystemOrgs && item?.ecosystemOrgs.length > 0 && item?.ecosystemOrgs[0]?.ecosystemRole?.name || "" return ( - redirectOrgDashboard(item.id, role)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto' }}> + redirectOrgDashboard(item.id, role)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto'}}>
      - {(item.logoUrl) ? : } - -
      + + {(item.logoUrl) ? : } +
      {item.name}
      -

      {item.description}

      +

      {item.description}

      • diff --git a/src/components/organization/OrganizationsList.tsx b/src/components/organization/OrganizationsList.tsx index fdbbe3d63..899f1c6ae 100644 --- a/src/components/organization/OrganizationsList.tsx +++ b/src/components/organization/OrganizationsList.tsx @@ -178,10 +178,10 @@ const OrganizationsList = () => { { organizationsList.map((org) => ( redirectOrgDashboard(org)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden overflow-ellipsis' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto' }}> -
        +
        {(org.logoUrl) ? : } -
        +
        {org?.name}
        From 6ae46b0acc61875c33126179bfa7b1ef3239fce8 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Thu, 2 Nov 2023 11:56:08 +0530 Subject: [PATCH 24/54] feat: developed landing page Signed-off-by: bhavanakarwade --- public/images/half_banner.png | Bin 0 -> 47718 bytes src/pages/index copy.astro | 1112 +++++++++++++++++++++++++++++++++ src/pages/index.astro | 1085 +++----------------------------- 3 files changed, 1193 insertions(+), 1004 deletions(-) create mode 100644 public/images/half_banner.png create mode 100644 src/pages/index copy.astro diff --git a/public/images/half_banner.png b/public/images/half_banner.png new file mode 100644 index 0000000000000000000000000000000000000000..22b2e30863c4405bbdd142308cf9e0ba6ca484ba GIT binary patch literal 47718 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 Ol@^y5s}eB`_ +
        +
        + +
        +
        +
        +
        + + New + CREDEBL 2.0 is out! See what's new + + +

        + Build Self-Sovereign Identity (SSI) solutions faster - for global + scale. +

        +

        + CREDEBL aims to significantly reduce the tedious work required to + build SSI solutions from scratch. +

        + +
        +
        + + +
        +
        +
        +

        + Build trusted digital ecosystems using the SSI core. +

        +

        + CREDEBL helps you build trusted digital ecosystems, by leveraging + global standards of W3C Decentralized Identifiers (DID) & Verifiable Credentials (VC) standards. +

        +
        +
        +
        +
        + + + + +
        +

        + Open Standards & Open Source +

        +

        + Built upon open standards of W3C Decentralized Identifiers, + Verifiable Credentials, DIF Protocols & Hyperledger Aries. +

        +
        +
        +
        + + + + + +
        +

        + Ledger-agnostic & Ledger-less +

        +

        + Supports multiple ledgers such as Indy, Cheqd, Polygon. Also + issue ledger-less VCs using did methods like did:web, did:peer, + did:key +

        +
        +
        +
        + + + +
        +

        + Multiple credential exchange formats +

        +

        + Supports multiple verifiable credential exchange formats such as + AnonCreds, JSON-LD, JWT, etc. +

        +
        +
        +
        + + + + + + + + + + + + +
        +

        + Digital Public Good (DPG) +

        +

        + CREDEBL is an open-souce Digital Public Good (DPG), designed to + host Digital Public Infrastructure (DPI) for trusted digital + ecosystems. +

        +
        +
        +
        + + + + + +
        +

        + Self-host on your cloud infra +

        +

        + You can self-host the entire CREDEBL platform and it's + components on your organization's cloud infrastructure of + choice. +

        +
        +
        +
        + + + + +
        +

        + Enterprise Grade, Large Scale +

        +

        + Build for large scale using highly scalable micro-services + architecture, and asynchronous message-driven communication. +

        +
        +
        +
        +
        + +
        +
        +
        +
        +

        + In-CREDEBL Team +

        +

        + Join our team & a community of open-source contributors by + tuning in with the CREDEBL Discord channel and become one of the + highlighted members. +

        +
        +
        +
        +
        + + ajile-in avatar +
        + +
        + + kkkulkarni avatar +
        + + +
        + amitayanworks avatar +
        + +
        + + nishad-ayanworks avatar +
        + +
        + KulkarniShashank avatar +
        + +
        + tipusinghaw avatar +
        + + +
        + vivekayanworks avatar +
        + +
        + Sheetal-ayanworks avatar +
        + + +
        + amitpadmani-awts avatar +
        + + +
        + sairanjit avatar +
        + + +
        + makrandshinde avatar +
        + + +
        + poonam-ghewande avatar +
        + + +
        + yogeshayanworks avatar +
        + + +
        + 16-karan avatar +
        + + +
        + Girish9960 avatar +
        + + +
        + bhavanakarwade avatar +
        + + +
        + sunilbade avatar +
        + + +
        + sayali-chavan96 avatar +
        + + +
        + MoulikaKulkarni avatar +
        + + +
        + ashwini-aher avatar +
        + + +
        + pranalidhanavade avatar +
        + + +
        + RinkalBhojani avatar +
        + +
        +
        +
        +
        + +
        +

        + Join Discord Community +

        +

        + Become a member of a community of SSI developers by + supporting CREDEBL +

        +
        Join discord +
        +
        +
        +
        +
        + + +
        +
        + diff --git a/src/pages/index.astro b/src/pages/index.astro index b858243e4..3a20ef4b4 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -5,33 +5,38 @@ import { pathRoutes } from '../config/pathRoutes';
        -
        - - New - CREDEBL 2.0 is out! See what's new - - -

        - Build Self-Sovereign Identity (SSI) solutions faster - for global - scale. -

        -

        - CREDEBL aims to significantly reduce the tedious work required to - build SSI solutions from scratch. -

        - -
        -
        - - -
        -
        -
        -

        - Build trusted digital ecosystems using the SSI core. -

        -

        - CREDEBL helps you build trusted digital ecosystems, by leveraging - global standards of W3C Decentralized Identifiers (DID) & Verifiable Credentials (VC) standards. -

        -
        -
        -
        -
        - - - - -
        -

        - Open Standards & Open Source -

        -

        - Built upon open standards of W3C Decentralized Identifiers, - Verifiable Credentials, DIF Protocols & Hyperledger Aries. -

        -
        -
        -
        - - - - - -
        -

        - Ledger-agnostic & Ledger-less -

        -

        - Supports multiple ledgers such as Indy, Cheqd, Polygon. Also - issue ledger-less VCs using did methods like did:web, did:peer, - did:key -

        -
        -
        -
        - - - -
        -

        - Multiple credential exchange formats -

        -

        - Supports multiple verifiable credential exchange formats such as - AnonCreds, JSON-LD, JWT, etc. -

        -
        -
        -
        - - - - - - - - - - - - -
        -

        - Digital Public Good (DPG) -

        -

        - CREDEBL is an open-souce Digital Public Good (DPG), designed to - host Digital Public Infrastructure (DPI) for trusted digital - ecosystems. -

        -
        -
        -
        + -
        - -

        - Enterprise Grade, Large Scale -

        -

        - Build for large scale using highly scalable micro-services - architecture, and asynchronous message-driven communication. -

        -
        -
        -
        -
        - -
        -
        -
        -
        -

        faster - for + global scale. +

        +

        - In-CREDEBL Team -

      -

      - Join our team & a community of open-source contributors by - tuning in with the CREDEBL Discord channel and become one of the - highlighted members. + CREDEBL aims to significantly reduce the tedious work required + to
      build SSI solutions from scratch.

      -
      -
      -
      -
      - - ajile-in avatar -
      - -
      - - kkkulkarni avatar -
      - - -
      - amitayanworks avatar -
      - -
      - - nishad-ayanworks avatar -
      - -
      - KulkarniShashank avatar -
      - -
      - tipusinghaw avatar -
      - - -
      - vivekayanworks avatar -
      - -
      - Sheetal-ayanworks avatar -
      - - -
      - amitpadmani-awts avatar -
      - - -
      - sairanjit avatar -
      - - -
      - makrandshinde avatar -
      - - -
      - poonam-ghewande avatar -
      - - -
      - yogeshayanworks avatar -
      - - -
      - 16-karan avatar -
      - - -
      - Girish9960 avatar -
      - - -
      - bhavanakarwade avatar -
      - - -
      - sunilbade avatar -
      - - -
      - sayali-chavan96 avatar -
      - - -
      - MoulikaKulkarni avatar -
      - - -
      - ashwini-aher avatar -
      - - -
      - pranalidhanavade avatar -
      - - -
      - RinkalBhojani avatar -
      - -
      -
      -
      - -
      -

      - Join Discord Community -

      -

      - Become a member of a community of SSI developers by - supporting CREDEBL -

      -
      Join discord - - +
      +
      + banner +
      - +
      +
      + hiiiii +
      +
      From 646a6148d588faf55dd879062370f7cff19c04f1 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Thu, 2 Nov 2023 12:07:38 +0530 Subject: [PATCH 25/54] fix:css issues on ecosystem and organization list Signed-off-by: pranalidhanavade --- src/components/Ecosystem/EcosystemList.tsx | 6 +- .../organization/OrganizationsList.tsx | 6 +- tailwind.config.cjs | 62 ++++++++++--------- 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index be75245b8..7d7c6c7fb 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -169,10 +169,10 @@ const EcosystemList = () => { const role = item?.ecosystemOrgs && item?.ecosystemOrgs.length > 0 && item?.ecosystemOrgs[0]?.ecosystemRole?.name || "" return ( redirectOrgDashboard(item.id, role)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto'}}> -
      +
      - {(item.logoUrl) ? : } -
      + {(item.logoUrl) ? : } +
      {item.name}
      diff --git a/src/components/organization/OrganizationsList.tsx b/src/components/organization/OrganizationsList.tsx index 899f1c6ae..55ebfc727 100644 --- a/src/components/organization/OrganizationsList.tsx +++ b/src/components/organization/OrganizationsList.tsx @@ -178,10 +178,10 @@ const OrganizationsList = () => { { organizationsList.map((org) => ( redirectOrgDashboard(org)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden overflow-ellipsis' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto' }}> -
      - {(org.logoUrl) ? : } +
      + {(org.logoUrl) ? : } -
      +
      {org?.name}
      diff --git a/tailwind.config.cjs b/tailwind.config.cjs index 7dfc192ae..e2044edb1 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -100,6 +100,7 @@ module.exports = { textDecoration: ['active'], width: { '100/22rem': 'calc(100% - 22rem)', + '100/6rem': 'calc(100% - 6rem)', }, minWidth: { kanban: '28rem', @@ -108,7 +109,7 @@ module.exports = { '100/6rem': 'calc(100% - 6rem)', '100/13rem': 'calc(100% - 13rem)', '100/10rem': 'calc(100% - 10rem)', - '100/8rem': 'calc(100% - 8rem)' + '100/8rem': 'calc(100% - 8rem)', }, minHeight: { '100/18rem': 'calc(100vh - 18rem)', @@ -121,37 +122,38 @@ module.exports = { 103: '1.03', }, }, - }, + - safelist: [ - // In Markdown (README…) - 'justify-evenly', - 'overflow-hidden', - 'rounded-md', + safelist: [ + // In Markdown (README…) + 'justify-evenly', + 'overflow-hidden', + 'rounded-md', - // From the Hugo Dashboard - 'w-64', - 'w-1/2', - 'rounded-l-lg', - 'rounded-r-lg', - 'bg-gray-200', - 'grid-cols-4', - 'grid-cols-7', - 'h-6', - 'leading-6', - 'h-9', - 'leading-9', - 'shadow-lg', - 'bg-opacity-50', - 'dark:bg-opacity-80', + // From the Hugo Dashboard + 'w-64', + 'w-1/2', + 'rounded-l-lg', + 'rounded-r-lg', + 'bg-gray-200', + 'grid-cols-4', + 'grid-cols-7', + 'h-6', + 'leading-6', + 'h-9', + 'leading-9', + 'shadow-lg', + 'bg-opacity-50', + 'dark:bg-opacity-80', - // For Astro one - 'grid', - ], + // For Astro one + 'grid', + ], - plugins: [ - require('flowbite/plugin'), - require('flowbite-typography'), - require('tailwind-scrollbar')({ nocompatible: true }), - ], + plugins: [ + require('flowbite/plugin'), + require('flowbite-typography'), + require('tailwind-scrollbar')({ nocompatible: true }), + ], + }, }; From a1a58703c04c66fa49039167927914b262fee2a7 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Thu, 2 Nov 2023 15:13:20 +0530 Subject: [PATCH 26/54] added cta section Signed-off-by: bhavanakarwade --- src/pages/index.astro | 52 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/pages/index.astro b/src/pages/index.astro index 3a20ef4b4..a8508f08e 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -142,14 +142,14 @@ import { pathRoutes } from '../config/pathRoutes';

      - Build Self-Sovereign Identity (SSI) solutions
      faster - for + Build Self-Sovereign Identity (SSI) solutions
      faster - for global scale.

      CREDEBL aims to significantly reduce the tedious work required - to
      build SSI solutions from scratch. + to
      build SSI solutions from scratch.

      -
      - hiiiii -
      +
      +

      + Build trusted digital ecosystems using the SSI core. +

      +

      + CREDEBL helps you build trusted digital ecosystems, by leveraging + global standards of W3C Decentralized Identifiers (DID) &
      Verifiable Credentials (VC) standards. +

      +
      + +
      +
      +
      + + + +
      +

      + Open Standards & Open Source +

      +

      + Built upon open standards of W3C Decentralized Identifiers, + Verifiable Credentials, DIF Protocols & Hyperledger Aries. +

      +
      +
      From a35617b6909242c3131289bf679a27fd167fb077 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Thu, 2 Nov 2023 15:58:25 +0530 Subject: [PATCH 27/54] worked on landing page Signed-off-by: bhavanakarwade --- src/pages/index copy.astro | 36 +++++++------- src/pages/index.astro | 96 +++++++++++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 20 deletions(-) diff --git a/src/pages/index copy.astro b/src/pages/index copy.astro index b858243e4..77c469e45 100644 --- a/src/pages/index copy.astro +++ b/src/pages/index copy.astro @@ -232,25 +232,25 @@ import { pathRoutes } from '../config/pathRoutes'; Verifiable Credentials, DIF Protocols & Hyperledger Aries.

      -
      -
      - - - - - +
      +
      + + + + + +
      +

      + Ledger-agnostic & Ledger-less +

      +

      + Supports multiple ledgers such as Indy, Cheqd, Polygon. Also + issue ledger-less VCs using did methods like did:web, did:peer, + did:key +

      -

      - Ledger-agnostic & Ledger-less -

      -

      - Supports multiple ledgers such as Indy, Cheqd, Polygon. Also - issue ledger-less VCs using did methods like did:web, did:peer, - did:key -

      -
      standards.

      - -
      +
      +
      +
      +
      + + + + +
      +

      + Ledger-agnostic & Ledger-less +

      +

      + Supports multiple ledgers such as Indy, Cheqd, Polygon. Also issue + ledger-less VCs using did methods like did:web, did:peer, did:key +

      +
      +
      +
      + + + +
      +

      + Multiple credential exchange formats +

      +

      + Supports multiple verifiable credential exchange formats such as + AnonCreds, JSON-LD, JWT, etc. +

      +
      +
      +
      + + + + + + + + + + + +
      +

      + Digital Public Good (DPG) +

      +

      + CREDEBL is an open-souce Digital Public Good (DPG), designed to + host Digital Public Infrastructure (DPI) for trusted digital + ecosystems. +

      +
      +
      From e1cd7a7b163226903947edbc60d687abfe732ae9 Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Thu, 2 Nov 2023 16:11:06 +0530 Subject: [PATCH 28/54] refactor: attribute datatype by adding date and time option Signed-off-by: sanjay-k1910 --- src/components/Resources/Schema/Create.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Resources/Schema/Create.tsx b/src/components/Resources/Schema/Create.tsx index 814fa338d..3a5094d9e 100644 --- a/src/components/Resources/Schema/Create.tsx +++ b/src/components/Resources/Schema/Create.tsx @@ -20,7 +20,7 @@ import EcosystemProfileCard from '../../../commonComponents/EcosystemProfileCard const options = [ { value: 'string', label: 'String' }, { value: 'number', label: 'Number' }, - { value: 'date', label: 'Date' }, + { value: 'datetime-local', label: 'Date & Time' }, ]; interface IAttributes { From 6d51eefa6ba02835ec2125b9f87b5343a0a05e2e Mon Sep 17 00:00:00 2001 From: sanjay-k1910 Date: Thu, 2 Nov 2023 16:20:04 +0530 Subject: [PATCH 29/54] refactor: Added data type for time Signed-off-by: sanjay-k1910 --- src/components/Resources/Schema/Create.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Resources/Schema/Create.tsx b/src/components/Resources/Schema/Create.tsx index 3a5094d9e..1eefe2d06 100644 --- a/src/components/Resources/Schema/Create.tsx +++ b/src/components/Resources/Schema/Create.tsx @@ -20,6 +20,7 @@ import EcosystemProfileCard from '../../../commonComponents/EcosystemProfileCard const options = [ { value: 'string', label: 'String' }, { value: 'number', label: 'Number' }, + { value: 'time', label: 'Time' }, { value: 'datetime-local', label: 'Date & Time' }, ]; From d88473eaf4a949dff5f291f0bd8f8afc509f4303 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Thu, 2 Nov 2023 19:34:14 +0530 Subject: [PATCH 30/54] feat:auto endorsement functionality Signed-off-by: pranalidhanavade --- src/api/ecosystem.ts | 1 + .../CreateEcosystemOrgModal/index.tsx | 877 ++++++++++-------- src/components/Ecosystem/EcosystemList.tsx | 513 +++++----- src/components/Ecosystem/interfaces/index.ts | 2 + 4 files changed, 762 insertions(+), 631 deletions(-) diff --git a/src/api/ecosystem.ts b/src/api/ecosystem.ts index d42ee22d7..770edd9c9 100644 --- a/src/api/ecosystem.ts +++ b/src/api/ecosystem.ts @@ -11,6 +11,7 @@ interface CreateEcosystemPayload { logo: string; tags?: string; userId: number; + autoEndorsement: boolean; } export interface GetEndorsementListParameter { diff --git a/src/components/CreateEcosystemOrgModal/index.tsx b/src/components/CreateEcosystemOrgModal/index.tsx index 178aafa81..0b92e5292 100644 --- a/src/components/CreateEcosystemOrgModal/index.tsx +++ b/src/components/CreateEcosystemOrgModal/index.tsx @@ -1,427 +1,488 @@ - - -import * as yup from "yup" +import * as yup from 'yup'; import { Avatar, Button, Label, Modal } from 'flowbite-react'; import { Field, Form, Formik, FormikHelpers } from 'formik'; -import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, apiStatusCodes, imageSizeAccepted, storageKeys } from '../../config/CommonConstant' -import { calculateSize, dataURItoBlob } from "../../utils/CompressImage"; -import { useEffect, useState } from "react"; -import { AlertComponent } from "../AlertComponent"; +import { + IMG_MAX_HEIGHT, + IMG_MAX_WIDTH, + apiStatusCodes, + imageSizeAccepted, + storageKeys, +} from '../../config/CommonConstant'; +import { calculateSize, dataURItoBlob } from '../../utils/CompressImage'; +import { useEffect, useState } from 'react'; +import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import { asset } from '../../lib/data.js'; -import { createOrganization } from "../../api/organization"; -import { getFromLocalStorage } from "../../api/Auth"; -import { createEcosystems } from "../../api/ecosystem"; -import { getOrgDetails } from "../../config/ecosystem"; -import defaultUserIcon from "../../../public/images/person_FILL1_wght400_GRAD0_opsz24.svg" +import { createOrganization } from '../../api/organization'; +import { getFromLocalStorage } from '../../api/Auth'; +import { createEcosystems } from '../../api/ecosystem'; +import { getOrgDetails } from '../../config/ecosystem'; +import defaultUserIcon from '../../../public/images/person_FILL1_wght400_GRAD0_opsz24.svg'; interface Values { - name: string; - description: string; + name: string; + description: string; } interface ILogoImage { - logoFile: string | File - imagePreviewUrl: string | ArrayBuffer | null | File, - fileName: string + logoFile: string | File; + imagePreviewUrl: string | ArrayBuffer | null | File; + fileName: string; } interface EcoValues { - name: string; - description: string; + name: string; + description: string; + autoEndorsement: boolean; } interface IProps { - openModal: boolean; - isorgModal: boolean; - setMessage?: (message: string) => void; - setOpenModal: (flag: boolean) => void + openModal: boolean; + isorgModal: boolean; + setMessage?: (message: string) => void; + setOpenModal: (flag: boolean) => void; } const CreateEcosystemOrgModal = (props: IProps) => { - - const [logoImage, setLogoImage] = useState({ - logoFile: "", - imagePreviewUrl: "", - fileName: '' - }) - - const [loading, setLoading] = useState(false) - const [formData, setFormData] = useState({ - name: '', - description: '', - }) - const [errMsg, setErrMsg] = useState(null) - - const [imgError, setImgError] = useState('') - - const initialFormData = formData - useEffect(() => { - setFormData({ - name: '', - description: '', - }) - setLogoImage({ - ...logoImage, - logoFile: "", - imagePreviewUrl: "" - }) - }, [props.openModal]) - - - const ProcessImg = (e: any): string | undefined => { - - const imgfile = e?.target.files[0] - if (!imgfile) { return } - - const imgreader = new FileReader() - imgreader.readAsDataURL(imgfile) - - imgreader.onload = (event): void => { - const imgElement = document.createElement("img") - if (imgElement) { - imgElement.src = typeof event?.target?.result === 'string' ? event.target.result : "" - imgElement.onload = (e): void => { - let fileUpdated: File | string = imgfile - let srcEncoded = '' - const canvas = document.createElement("canvas") - - const { width, height, ev } = calculateSize(imgElement, IMG_MAX_WIDTH, IMG_MAX_HEIGHT) - canvas.width = width - canvas.height = height - - const ctx = canvas.getContext("2d") - if (ctx && e?.target) { - ctx.imageSmoothingEnabled = true - ctx.imageSmoothingQuality = "high" - ctx.drawImage(ev, 0, 0, canvas.width, canvas.height) - srcEncoded = ctx.canvas.toDataURL(ev, imgfile.type) - const blob = dataURItoBlob(srcEncoded, imgfile.type) - fileUpdated = new File([blob], imgfile.name, { type: imgfile.type, lastModified: new Date().getTime() }) - setLogoImage({ - logoFile: fileUpdated, - imagePreviewUrl: srcEncoded, - fileName: imgfile.name - }) - } - } - } - } - } - - const isEmpty = (object: any): boolean => { - - return true - } - const handleImageChange = (event: any): void => { - setImgError('') - const reader = new FileReader() - const file = event?.target?.files - - const imgfieSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)) - const extension = file[0]?.name?.substring(file[0]?.name?.lastIndexOf(".") + 1)?.toLowerCase() - if (extension === "png" || extension === "jpeg" || extension === "jpg") { - if (imgfieSize <= imageSizeAccepted) { - reader.onloadend = (): void => { - ProcessImg(event) - isEmpty(reader.result) - } - reader.readAsDataURL(file[0]) - event.preventDefault() - } else { - setImgError("Please check image size") - } - } else { - setImgError("Invalid image type") - } - } - - const submitCreateOrganization = async (values: Values) => { - setLoading(true) - - const orgData = { - name: values.name, - description: values.description, - logo: logoImage?.imagePreviewUrl as string || "", - website: "" - } - const resCreateOrg = await createOrganization(orgData) - - const { data } = resCreateOrg as AxiosResponse - setLoading(false) - - if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { - if (props.setMessage) { - props.setMessage(data?.message) - } - props.setOpenModal(false) - - } else { - setErrMsg(resCreateOrg as string) - } - } - const submitCreateEcosystem = async (values: EcoValues) => { - try { - setLoading(true) - const orgDetails = await getOrgDetails() - const user_data = JSON.parse(await getFromLocalStorage(storageKeys.USER_PROFILE)) - const ecoData = { - name: values.name, - description: values.description, - logo: logoImage?.imagePreviewUrl as string || "", - tags: "", - userId: Number(user_data?.id), - orgName: orgDetails?.orgName, - orgDid: orgDetails?.orgDid - } - const resCreateEco = await createEcosystems(ecoData) - - const { data } = resCreateEco as AxiosResponse - setLoading(false) - - if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { - if (props.setMessage) { - props.setMessage(data?.message) - } - props.setOpenModal(false) - } else { - setErrMsg(resCreateEco as string) - } - } - catch (error) { - console.error("An error occurred:", error); - setLoading(false); - } - } - - - const submit = (values: EcoValues | Values) => { - if (props.isorgModal) { - submitCreateOrganization(values) - } else { - submitCreateEcosystem(values) - } - - } - - const orgErrorMsg = { - name: yup - .string() - .min(2, 'Organization name must be at least 2 characters') - .max(50, 'Organization name must be at most 50 characters') - .required('Organization name is required') - .trim(), - description: yup - .string() - .min(2, 'Description must be at least 2 characters') - .max(255, 'Description must be at most 255 characters') - .required('Description is required'), - }; - - const ecoErrorMsg = { - name: yup - .string() - .min(2, 'Ecosystem name must be at least 2 characters') - .max(50, 'Ecosystem name must be at most 50 characters') - .required('Ecosystem name is required') - .trim(), - description: yup - .string() - .min(2, 'Description must be at least 2 characters') - .max(255, 'Description must be at most 255 characters') - .required('Description is required'), - }; - const renderEcosystemModal = () => { - const popupName = props.isorgModal ? "Organization" : "Ecosystem" - return ( - { - setLogoImage({ - logoFile: " ", - imagePreviewUrl: " ", - fileName: ' ' - }) - setFormData({ - name:" ", - description:" " - }) - props.setOpenModal(false) - } - }> - Create {popupName} - - { - setErrMsg(null) - }} - /> - - ) => { - submit(values) - resetForm(); - - }} - > - {(formikHandlers): JSX.Element => ( - -
      -
      -
      - { - typeof (logoImage.logoFile) === "string" ? - : - Jese picture - } - -
      -

      - {popupName} Logo -

      -
      - JPG, JPEG and PNG . Max size of 1MB -
      -
      - -
      - - -
      - -
      -
      -
      -
      -
      -
      -
      - { - const value = e.target.value; - formikHandlers.setFieldValue('name', value); - formikHandlers.setFieldTouched('name', true); - - if (value.length > 50) { - formikHandlers.setFieldError('name', props.isorgModal ? 'Organization name must be at most 50 characters' : 'Ecosystem name must be at most 50 characters'); - } else { - formikHandlers.setFieldError('name', undefined); - } - }} - /> - { - (formikHandlers?.errors?.name && formikHandlers?.touched?.name) && - {formikHandlers?.errors?.name} - } - -
      -
      -
      -
      - - { - const value = e.target.value; - formikHandlers.setFieldValue('description', value); - formikHandlers.setFieldTouched('description', true); - - if (value.length > 50) { - formikHandlers.setFieldError('description', 'Description must be at most 255 characters'); - } else { - formikHandlers.setFieldError('description', undefined); - } - }} - /> - { - (formikHandlers?.errors?.description && formikHandlers?.touched?.description) && - {formikHandlers?.errors?.description} - } -
      - - -
      - )} -
      -
      -
      - ) - } - return ( - <> - {renderEcosystemModal()} - - - ) - -} + const [logoImage, setLogoImage] = useState({ + logoFile: '', + imagePreviewUrl: '', + fileName: '', + }); + + const [loading, setLoading] = useState(false); + const [formData, setFormData] = useState({ + name: '', + description: '', + autoEndorsement: false + }); + const [errMsg, setErrMsg] = useState(null); + + const [imgError, setImgError] = useState(''); + const [autoEndorse, setautoEndorse] = useState(false) + + const initialFormData = formData; + useEffect(() => { + setFormData({ + name: '', + description: '', + autoEndorsement: false + }); + setLogoImage({ + ...logoImage, + logoFile: '', + imagePreviewUrl: '', + }); + }, [props.openModal]); + + const ProcessImg = (e: any): string | undefined => { + const imgfile = e?.target.files[0]; + if (!imgfile) { + return; + } + + const imgreader = new FileReader(); + imgreader.readAsDataURL(imgfile); + + imgreader.onload = (event): void => { + const imgElement = document.createElement('img'); + if (imgElement) { + imgElement.src = + typeof event?.target?.result === 'string' ? event.target.result : ''; + imgElement.onload = (e): void => { + let fileUpdated: File | string = imgfile; + let srcEncoded = ''; + const canvas = document.createElement('canvas'); + + const { width, height, ev } = calculateSize( + imgElement, + IMG_MAX_WIDTH, + IMG_MAX_HEIGHT, + ); + canvas.width = width; + canvas.height = height; + + const ctx = canvas.getContext('2d'); + if (ctx && e?.target) { + ctx.imageSmoothingEnabled = true; + ctx.imageSmoothingQuality = 'high'; + ctx.drawImage(ev, 0, 0, canvas.width, canvas.height); + srcEncoded = ctx.canvas.toDataURL(ev, imgfile.type); + const blob = dataURItoBlob(srcEncoded, imgfile.type); + fileUpdated = new File([blob], imgfile.name, { + type: imgfile.type, + lastModified: new Date().getTime(), + }); + setLogoImage({ + logoFile: fileUpdated, + imagePreviewUrl: srcEncoded, + fileName: imgfile.name, + }); + } + }; + } + }; + }; + + const isEmpty = (object: any): boolean => { + return true; + }; + const handleImageChange = (event: any): void => { + setImgError(''); + const reader = new FileReader(); + const file = event?.target?.files; + + const imgfieSize = Number((file[0]?.size / 1024 / 1024)?.toFixed(2)); + const extension = file[0]?.name + ?.substring(file[0]?.name?.lastIndexOf('.') + 1) + ?.toLowerCase(); + if (extension === 'png' || extension === 'jpeg' || extension === 'jpg') { + if (imgfieSize <= imageSizeAccepted) { + reader.onloadend = (): void => { + ProcessImg(event); + isEmpty(reader.result); + }; + reader.readAsDataURL(file[0]); + event.preventDefault(); + } else { + setImgError('Please check image size'); + } + } else { + setImgError('Invalid image type'); + } + }; + + const submitCreateOrganization = async (values: Values) => { + setLoading(true); + + const orgData = { + name: values.name, + description: values.description, + logo: (logoImage?.imagePreviewUrl as string) || '', + website: '', + }; + const resCreateOrg = await createOrganization(orgData); + + const { data } = resCreateOrg as AxiosResponse; + setLoading(false); + + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + if (props.setMessage) { + props.setMessage(data?.message); + } + props.setOpenModal(false); + } else { + setErrMsg(resCreateOrg as string); + } + }; + const submitCreateEcosystem = async (values: EcoValues) => { + try { + setLoading(true); + const orgDetails = await getOrgDetails(); + const user_data = JSON.parse( + await getFromLocalStorage(storageKeys.USER_PROFILE), + ); + const ecoData = { + name: values.name, + description: values.description, + logo: (logoImage?.imagePreviewUrl as string) || '', + tags: '', + userId: Number(user_data?.id), + orgName: orgDetails?.orgName, + orgDid: orgDetails?.orgDid, + autoEndorsement: autoEndorse, + + }; + const resCreateEco = await createEcosystems(ecoData); + + const { data } = resCreateEco as AxiosResponse; + setLoading(false); + + if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) { + if (props.setMessage) { + props.setMessage(data?.message); + } + props.setOpenModal(false); + } else { + setErrMsg(resCreateEco as string); + } + } catch (error) { + console.error('An error occurred:', error); + setLoading(false); + } + }; + + const submit = (values: EcoValues | Values) => { + if (props.isorgModal) { + submitCreateOrganization(values); + } else { + submitCreateEcosystem(values); + } + }; + + const orgErrorMsg = { + name: yup + .string() + .min(2, 'Organization name must be at least 2 characters') + .max(50, 'Organization name must be at most 50 characters') + .required('Organization name is required') + .trim(), + description: yup + .string() + .min(2, 'Description must be at least 2 characters') + .max(255, 'Description must be at most 255 characters') + .required('Description is required'), + }; + + const ecoErrorMsg = { + name: yup + .string() + .min(2, 'Ecosystem name must be at least 2 characters') + .max(50, 'Ecosystem name must be at most 50 characters') + .required('Ecosystem name is required') + .trim(), + description: yup + .string() + .min(2, 'Description must be at least 2 characters') + .max(255, 'Description must be at most 255 characters') + .required('Description is required'), + + }; + const renderEcosystemModal = () => { + const popupName = props.isorgModal ? 'Organization' : 'Ecosystem'; + return ( + { + setLogoImage({ + logoFile: ' ', + imagePreviewUrl: ' ', + fileName: ' ', + }); + setFormData({ + name: ' ', + description: ' ', + autoEndorsement: false + }); + props.setOpenModal(false); + }} + > + Create {popupName} + + { + setErrMsg(null); + }} + /> + , + ) => { + submit(values); + resetForm(); + }} + > + {(formikHandlers): JSX.Element => ( +
      +
      +
      + {typeof logoImage.logoFile === 'string' ? ( + + ) : ( + Jese picture + )} + +
      +

      + {popupName} Logo +

      +
      + JPG, JPEG and PNG . Max size of 1MB +
      +
      +
      + +
      +
      +
      +
      +
      +
      +
      +
      + { + const value = e.target.value; + formikHandlers.setFieldValue('name', value); + formikHandlers.setFieldTouched('name', true); + + if (value.length > 50) { + formikHandlers.setFieldError( + 'name', + props.isorgModal + ? 'Organization name must be at most 50 characters' + : 'Ecosystem name must be at most 50 characters', + ); + } else { + formikHandlers.setFieldError('name', undefined); + } + }} + /> + {formikHandlers?.errors?.name && + formikHandlers?.touched?.name && ( + + {formikHandlers?.errors?.name} + + )} +
      +
      +
      +
      + + { + const value = e.target.value; + formikHandlers.setFieldValue('description', value); + formikHandlers.setFieldTouched('description', true); + + if (value.length > 50) { + formikHandlers.setFieldError( + 'description', + 'Description must be at most 255 characters', + ); + } else { + formikHandlers.setFieldError('description', undefined); + } + }} + /> + {formikHandlers?.errors?.description && + formikHandlers?.touched?.description && ( + + {formikHandlers?.errors?.description} + + )} +
      + + {!props.isorgModal && ( +
      +
      + )} + +
      + )} +
      +
      +
      + ); + }; + return <>{renderEcosystemModal()}; +}; export default CreateEcosystemOrgModal; diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index 4e14b7cee..e7301b913 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -7,12 +7,16 @@ import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; import { AlertComponent } from '../AlertComponent'; import type { AxiosResponse } from 'axios'; import BreadCrumbs from '../BreadCrumbs'; -import CustomAvatar from '../Avatar' +import CustomAvatar from '../Avatar'; import { Features } from '../../utils/enums/features'; import RoleViewButton from '../RoleViewButton'; import SearchInput from '../SearchInput'; import { pathRoutes } from '../../config/pathRoutes'; -import { getFromLocalStorage, removeFromLocalStorage, setToLocalStorage } from '../../api/Auth'; +import { + getFromLocalStorage, + removeFromLocalStorage, + setToLocalStorage, +} from '../../api/Auth'; import { EmptyListMessage } from '../EmptyListComponent'; import CustomSpinner from '../CustomSpinner'; import CreateEcosystemOrgModal from '../CreateEcosystemOrgModal'; @@ -21,229 +25,292 @@ import type { IEcosystem } from './interfaces'; import { checkEcosystem, type ICheckEcosystem } from '../../config/ecosystem'; const initialPageState = { - pageNumber: 1, - pageSize: 9, - total: 100, + pageNumber: 1, + pageSize: 9, + total: 100, }; const EcosystemList = () => { - const [openModal, setOpenModal] = useState(false); - const [loading, setLoading] = useState(true) - const [message, setMessage] = useState(null) - const [error, setError] = useState(null) - const [currentPage, setCurrentPage] = useState(initialPageState); - const onPageChange = (page: number) => { - setCurrentPage({ - ...currentPage, - pageNumber: page - }) - }; - const [searchText, setSearchText] = useState(""); - - const [ecosystemList, setEcosystemList] = useState | null>(null) - const [isEcosystemData, setIsEcosystemData] = useState() - - const createOrganizationModel = () => { - setOpenModal(true) - } - - const fetchEcosystems = async () => { - setLoading(true); - const id = await getFromLocalStorage(storageKeys.ORG_ID); - // setOrgId(id); - if (id) { - const response = await getEcosystems(id, currentPage.pageNumber, currentPage.pageSize, searchText); - const { data } = response as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const ecosystemData = data?.data; - if (ecosystemData) { - console.log(6565, data) - setEcosystemList(ecosystemData) - } else { - await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); - setError(response as string) - } - } else { - await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); - setError(response as string) - } - } - setLoading(false); - }; - - //This useEffect is called when the searchText changes - useEffect(() => { - let getData: NodeJS.Timeout - - if (searchText.length >= 1) { - getData = setTimeout(() => { - fetchEcosystems() - }, 1000) - } else { - fetchEcosystems() - } - - return () => clearTimeout(getData) - }, [searchText, openModal, currentPage.pageNumber]) - - useEffect(() => { - const queryParameters = new URLSearchParams(window?.location?.search) - const isModel = queryParameters.get("orgModal") || '' - - if (isModel !== '') { - setOpenModal(true) - } - - const checkEcosystemData = async () => { - const data: ICheckEcosystem = await checkEcosystem(); - setIsEcosystemData(data) - } - checkEcosystemData(); - }, []) - - //onCHnage of Search input text - const searchInputChange = (e: ChangeEvent) => { - setSearchText(e.target.value); - } - - const redirectOrgDashboard = async (ecosystemId: string, ecosystemRole: string) => { - await setToLocalStorage(storageKeys.ECOSYSTEM_ID, ecosystemId); - await setToLocalStorage(storageKeys.ECOSYSTEM_ROLE, ecosystemRole); - window.location.href = pathRoutes.ecosystem.dashboard - } - - const isEcosystemList = Boolean(ecosystemList && ecosystemList?.length > 0) - const showCreateButton = Boolean(isEcosystemList && (isEcosystemData?.isMultiEcosystem || isEcosystemData?.isEcosystemLead)) - return ( -
      -
      - -
      -
      -

      - Ecosystems -

      - { - showCreateButton && - - - - -
      - } - onClickEvent={createOrganizationModel} - /> - } -
      -
      -
      -
      - -
      - - { - setMessage(null) - setError(null) - }} - /> - - {loading - ?
      - -
      - : isEcosystemList ? (
      - { - ecosystemList?.map((item) => { - const role = item?.ecosystemOrgs && item?.ecosystemOrgs.length > 0 && item?.ecosystemOrgs[0]?.ecosystemRole?.name || "" - return ( - redirectOrgDashboard(item.id, role)} className='transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden' style={{ maxHeight: '100%', maxWidth: '100%', overflow: 'auto' }}> -
      - {(item.logoUrl) ? : } - -
      -
      - {item.name} -
      -

      {item.description}

      -
      -
        -
      • -
        -
        - Roles: - {item?.ecosystemOrgs && item?.ecosystemOrgs?.length > 0 && item?.ecosystemOrgs[0].ecosystemRole && - item?.ecosystemOrgs[0]?.ecosystemRole?.name && - - {item?.ecosystemOrgs[0]?.ecosystemRole?.name} - - } -
        -
        -
      • -
      -
      -
      -
      -
      - ) - }) - } -
      ) - : ecosystemList && ( - - - } />) - } - -
      - { - isEcosystemList && ecosystemList && ecosystemList?.length > 10 && ( - - ) - } -
      - { - setMessage(value) - if (value) { - setTimeout(() => { - window.location.reload(); - }, 2000); - } else { - fetchEcosystems(); - } - }} - isorgModal={false} - /> -
      -
      -
      - ) -} + const [openModal, setOpenModal] = useState(false); + const [loading, setLoading] = useState(true); + const [message, setMessage] = useState(null); + const [error, setError] = useState(null); + const [currentPage, setCurrentPage] = useState(initialPageState); + const onPageChange = (page: number) => { + setCurrentPage({ + ...currentPage, + pageNumber: page, + }); + }; + const [searchText, setSearchText] = useState(''); + + const [ecosystemList, setEcosystemList] = useState | null>( + null, + ); + const [isEcosystemData, setIsEcosystemData] = useState(); + + const createOrganizationModel = () => { + setOpenModal(true); + }; + + const fetchEcosystems = async () => { + setLoading(true); + const id = await getFromLocalStorage(storageKeys.ORG_ID); + // setOrgId(id); + if (id) { + const response = await getEcosystems( + id, + currentPage.pageNumber, + currentPage.pageSize, + searchText, + ); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const ecosystemData = data?.data; + if (ecosystemData) { + console.log(6565, data); + setEcosystemList(ecosystemData); + } else { + await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); + setError(response as string); + } + } else { + await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); + setError(response as string); + } + } + setLoading(false); + }; + + //This useEffect is called when the searchText changes + useEffect(() => { + let getData: NodeJS.Timeout; + + if (searchText.length >= 1) { + getData = setTimeout(() => { + fetchEcosystems(); + }, 1000); + } else { + fetchEcosystems(); + } + + return () => clearTimeout(getData); + }, [searchText, openModal, currentPage.pageNumber]); + + useEffect(() => { + const queryParameters = new URLSearchParams(window?.location?.search); + const isModel = queryParameters.get('orgModal') || ''; + + if (isModel !== '') { + setOpenModal(true); + } + + const checkEcosystemData = async () => { + const data: ICheckEcosystem = await checkEcosystem(); + setIsEcosystemData(data); + }; + checkEcosystemData(); + }, []); + + //onCHnage of Search input text + const searchInputChange = (e: ChangeEvent) => { + setSearchText(e.target.value); + }; + + const redirectOrgDashboard = async ( + ecosystemId: string, + ecosystemRole: string, + ) => { + await setToLocalStorage(storageKeys.ECOSYSTEM_ID, ecosystemId); + await setToLocalStorage(storageKeys.ECOSYSTEM_ROLE, ecosystemRole); + window.location.href = pathRoutes.ecosystem.dashboard; + }; + + const isEcosystemList = Boolean(ecosystemList && ecosystemList?.length > 0); + const showCreateButton = Boolean( + isEcosystemList && + (isEcosystemData?.isMultiEcosystem || isEcosystemData?.isEcosystemLead), + ); + console.log('11', ecosystemList); + return ( +
      +
      + +
      +
      +

      + Ecosystems +

      + {showCreateButton && ( + + + + +
      + } + onClickEvent={createOrganizationModel} + /> + )} +
      +
      +
      +
      + +
      + + { + setMessage(null); + setError(null); + }} + /> + + {loading ? ( +
      + +
      + ) : isEcosystemList ? ( +
      + {ecosystemList?.map((item) => { + const role = + (item?.ecosystemOrgs && + item?.ecosystemOrgs.length > 0 && + item?.ecosystemOrgs[0]?.ecosystemRole?.name) || + ''; + return ( + redirectOrgDashboard(item.id, role)} + className="transform transition duration-500 hover:scale-105 hover:bg-gray-50 cursor-pointer overflow-hidden" + style={{ + maxHeight: '100%', + maxWidth: '100%', + overflow: 'auto', + }} + > +
      + {item.logoUrl ? ( + + ) : ( + + )} + +
      +
      + {item.name} +
      +

      + {item.description} +

      +
      +
        +
      • +
        +
        + Roles: + {item?.ecosystemOrgs && + item?.ecosystemOrgs?.length > 0 && + item?.ecosystemOrgs[0].ecosystemRole && + item?.ecosystemOrgs[0]?.ecosystemRole + ?.name && ( + + { + item?.ecosystemOrgs[0]?.ecosystemRole + ?.name + } + + )} +
        +
        +
        +

        + Auto Endorsement:{' '} + {item.autoEndorsement ? 'Yes' : 'No'} +

        +
        +
      • +
      +
      +
      +
      +
      + ); + })} +
      + ) : ( + ecosystemList && ( + + + + } + /> + ) + )} + +
      + {isEcosystemList && ecosystemList && ecosystemList?.length > 10 && ( + + )} +
      + { + setMessage(value); + if (value) { + setTimeout(() => { + window.location.reload(); + }, 2000); + } else { + fetchEcosystems(); + } + }} + isorgModal={false} + /> +
      +
      +
      + ); +}; export default EcosystemList; diff --git a/src/components/Ecosystem/interfaces/index.ts b/src/components/Ecosystem/interfaces/index.ts index 24e41c258..cdf99b631 100644 --- a/src/components/Ecosystem/interfaces/index.ts +++ b/src/components/Ecosystem/interfaces/index.ts @@ -5,6 +5,7 @@ export interface IEcosystem { logoUrl: string joinedDate?: string role?: string + autoEndorsement:boolean ecosystemOrgs?: { ecosystemRole: { name: string @@ -17,6 +18,7 @@ export interface Ecosystem { createDateTime: string createdBy: number lastChangedDateTime: string + autoEndorsement:boolean lastChangedBy: number name: string description: string From 02825e055568b19f7f603ed0fd590448122ffc82 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Fri, 3 Nov 2023 12:02:09 +0530 Subject: [PATCH 31/54] feat:auto endorsement functionality Signed-off-by: pranalidhanavade --- .../CreateEcosystemOrgModal/index.tsx | 4 +- src/components/Ecosystem/Dashboard.tsx | 959 +++++++++--------- .../EditEcosystemOrgModal/index.tsx | 49 +- 3 files changed, 534 insertions(+), 478 deletions(-) diff --git a/src/components/CreateEcosystemOrgModal/index.tsx b/src/components/CreateEcosystemOrgModal/index.tsx index 0b92e5292..213793284 100644 --- a/src/components/CreateEcosystemOrgModal/index.tsx +++ b/src/components/CreateEcosystemOrgModal/index.tsx @@ -435,7 +435,7 @@ const CreateEcosystemOrgModal = (props: IProps) => { /> Sign - +
      @@ -450,7 +450,7 @@ const CreateEcosystemOrgModal = (props: IProps) => { /> Sign and Submit - +
      diff --git a/src/components/Ecosystem/Dashboard.tsx b/src/components/Ecosystem/Dashboard.tsx index 13e927c63..b4fb8ce7e 100644 --- a/src/components/Ecosystem/Dashboard.tsx +++ b/src/components/Ecosystem/Dashboard.tsx @@ -14,16 +14,16 @@ import { EmptyListMessage } from '../EmptyListComponent'; import CreateEcosystemOrgModal from '../CreateEcosystemOrgModal'; import { AlertComponent } from '../AlertComponent'; import { - ICheckEcosystem, - checkEcosystem, - getEcosystemId, + ICheckEcosystem, + checkEcosystem, + getEcosystemId, } from '../../config/ecosystem'; import { Button, Dropdown } from 'flowbite-react'; import EditPopupModal from '../EditEcosystemOrgModal'; import { - getFromLocalStorage, - removeFromLocalStorage, - setToLocalStorage, + getFromLocalStorage, + removeFromLocalStorage, + setToLocalStorage, } from '../../api/Auth'; import { getUserEcosystemInvitations } from '../../api/invitations'; import { pathRoutes } from '../../config/pathRoutes'; @@ -33,486 +33,499 @@ import DateTooltip from '../Tooltip'; import DashboardCard from '../../commonComponents/DashboardCard'; interface IRoleTablet { - role: string; + role: string; } const initialPageState = { - pageNumber: 1, - pageSize: 10, - total: 0, + pageNumber: 1, + pageSize: 10, + total: 0, }; export const RoleTablet = ({ role }: IRoleTablet) => ( -
      - {role} -
      +
      + {role} +
      ); const Dashboard = () => { - const [ecosystemDetails, setEcosystemDetails] = useState(); - const [success, setSuccess] = useState(null); - const [failure, setFailure] = useState(null); - const [message, setMessage] = useState(null); - const [loading, setLoading] = useState(true); - const [editOpenModal, setEditOpenModal] = useState(false); - const [dropdownOpen, setDropdownOpen] = useState(true); - const [leadOrg, setLeadOrg] = useState("") - const [error, setError] = useState(null); - const [openModal, setOpenModal] = useState(false); - const [viewButton, setViewButton] = useState(false); - const [currentPage, setCurrentPage] = useState(initialPageState); - const [isEcosystemLead, setIsEcosystemLead] = useState(false); - const [ecosystemDashboard, setEcosystemDashboard] = - useState(null); - const [ecosystemDetailsNotFound, setEcosystemDetailsNotFound] = - useState(false); - const [orgId, setOrgId] = useState(''); - const [isOrgModal, setIsOrgModal] = useState(false); - - const createEcosystemModel = () => { - setOpenModal(true); - }; - - const EditEcosystemOrgModal = () => { - setEditOpenModal(true); - }; - - const handleEditModalClose = () => { - setEditOpenModal(false); - setDropdownOpen(false); - fetchEcosystemDetails(); - }; - - const getAllEcosystemInvitations = async () => { - setLoading(true); - const response = await getUserEcosystemInvitations( - currentPage.pageNumber, - currentPage.pageSize, - '', - ); - const { data } = response as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const totalPages = data?.data?.totalPages; - - const invitationPendingList = data?.data?.invitations.filter( - (invitation: { status: string }) => { - return invitation.status === 'pending'; - }, - ); - - if (invitationPendingList.length > 0) { - setMessage(`You have received invitation to join ecosystem `); - setViewButton(true); - } - setCurrentPage({ - ...currentPage, - total: totalPages, - }); - } else { - setError(response as string); - } - setLoading(false); - }; - - const fetchEcosystemDetails = async () => { - setLoading(true); - const id = await getFromLocalStorage(storageKeys.ORG_ID); - const ecosystemId = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID); - setOrgId(id); - if (id) { - const response = await getEcosystems(id); - const { data } = response as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - const ecosystemData = data?.data.find((item: { id: string }) => item.id === ecosystemId); - if (ecosystemData) { - const ecosystemOrg = - ecosystemData?.ecosystemOrgs && - ecosystemData?.ecosystemOrgs.length > 0 && - ecosystemData?.ecosystemOrgs[0]; - setEcosystemDetails({ - id: ecosystemData?.id, - logoUrl: ecosystemData?.logoUrl, - name: ecosystemData?.name, - description: ecosystemData?.description, - joinedDate: - ecosystemOrg && ecosystemOrg?.createDateTime - ? ecosystemOrg?.createDateTime - : '', - role: - ecosystemOrg && ecosystemOrg?.ecosystemRole?.name - ? ecosystemOrg?.ecosystemRole?.name - : '', - }); - } else { - await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); - } - } else { - await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); - setEcosystemDetailsNotFound(true); - } - } - setLoading(false); - }; - - const fetchEcosystemDashboard = async () => { - setLoading(true); - - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - const ecosystemId = await getEcosystemId(); - - if (ecosystemId && orgId) { - const response = await getEcosystemDashboard(ecosystemId, orgId); - - const { data } = response as AxiosResponse; - - if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - setEcosystemDashboard(data?.data); - setLeadOrg(data?.data?.ecosystemLead?.orgName || "") - } else { - setFailure(response as string); - setFailure(response as string); - setLoading(false); - } - } - setLoading(false); - }; - - const checkOrgId = async () => { - const orgId = await getFromLocalStorage(storageKeys.ORG_ID); - if (orgId) { - await getAllEcosystemInvitations(); - } - }; - - const getDashboardData = async () => { - await checkOrgId(); - await fetchEcosystemDetails(); - await fetchEcosystemDashboard(); - }; - - const navigateToInvitation = () => { - window.location.href = pathRoutes.ecosystem.sentinvitation; - }; - - useEffect(() => { - getDashboardData(); - - const checkEcosystemData = async () => { - const data: ICheckEcosystem = await checkEcosystem(); - setIsEcosystemLead(data.isEcosystemLead); - }; - checkEcosystemData(); - }, []); - - useEffect(() => { - setDropdownOpen(!editOpenModal); - }, [editOpenModal]); - - return ( -
      -
      - -
      - - {error ? ( - <> - {' '} - {(success || failure) && ( - { - setSuccess(null); - setFailure(null); - }} - /> - )} - - ) : ( - <> -
      - { - { - setMessage(null); - setError(null); - }} - /> - } -
      - - {(success || failure) && ( - { - setSuccess(null); - setFailure(null); - }} - /> - )} - - )} - - {ecosystemDetailsNotFound && ( - { - setEcosystemDetailsNotFound(false); - setFailure(null); - }} - /> - )} - - {ecosystemDetails ? ( -
      -
      -
      -
      - {ecosystemDetails?.logoUrl ? ( - - ) : ( - - )} -
      - {ecosystemDetails ? ( -
      -

      - {ecosystemDetails?.name} -

      - -

      - {ecosystemDetails?.description} -

      - {!isEcosystemLead ? ( -
      -
      - - Ecosystem Owner - - :{' '} - - {leadOrg} - -
      -
      - - Ecosystem Lead - {' '} - : - - {leadOrg} - -
      -
      - - Joined since - {' '} - : - - - {dateConversion(ecosystemDetails.joinedDate || '')} - - -
      -
      - ) : ( -
      - Role: {' '} - -
      - )} -
      - ) : ( - - )} - - {!isEcosystemLead && ( -
      - Role: {' '} - -
      - )} - - {isEcosystemLead && ( -
      - - {dropdownOpen ? ( - ( - - )} - dismissOnClick={true} - > - { - EditEcosystemOrgModal(); - }} - > -
      Edit Ecosystem
      -
      - {/* + const [ecosystemDetails, setEcosystemDetails] = useState(); + const [success, setSuccess] = useState(null); + const [failure, setFailure] = useState(null); + const [message, setMessage] = useState(null); + const [loading, setLoading] = useState(true); + const [editOpenModal, setEditOpenModal] = useState(false); + const [dropdownOpen, setDropdownOpen] = useState(true); + const [leadOrg, setLeadOrg] = useState(''); + const [error, setError] = useState(null); + const [openModal, setOpenModal] = useState(false); + const [viewButton, setViewButton] = useState(false); + const [currentPage, setCurrentPage] = useState(initialPageState); + const [isEcosystemLead, setIsEcosystemLead] = useState(false); + const [ecosystemDashboard, setEcosystemDashboard] = + useState(null); + const [ecosystemDetailsNotFound, setEcosystemDetailsNotFound] = + useState(false); + const [orgId, setOrgId] = useState(''); + const [isOrgModal, setIsOrgModal] = useState(false); + + const createEcosystemModel = () => { + setOpenModal(true); + }; + + const EditEcosystemOrgModal = () => { + setEditOpenModal(true); + }; + + const handleEditModalClose = () => { + setEditOpenModal(false); + setDropdownOpen(false); + fetchEcosystemDetails(); + }; + + const getAllEcosystemInvitations = async () => { + setLoading(true); + const response = await getUserEcosystemInvitations( + currentPage.pageNumber, + currentPage.pageSize, + '', + ); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const totalPages = data?.data?.totalPages; + + const invitationPendingList = data?.data?.invitations.filter( + (invitation: { status: string }) => { + return invitation.status === 'pending'; + }, + ); + + if (invitationPendingList.length > 0) { + setMessage(`You have received invitation to join ecosystem `); + setViewButton(true); + } + setCurrentPage({ + ...currentPage, + total: totalPages, + }); + } else { + setError(response as string); + } + setLoading(false); + }; + + const fetchEcosystemDetails = async () => { + setLoading(true); + const id = await getFromLocalStorage(storageKeys.ORG_ID); + const ecosystemId = await getFromLocalStorage(storageKeys.ECOSYSTEM_ID); + setOrgId(id); + if (id) { + const response = await getEcosystems(id); + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + const ecosystemData = data?.data.find( + (item: { id: string }) => item.id === ecosystemId, + ); + if (ecosystemData) { + const ecosystemOrg = + ecosystemData?.ecosystemOrgs && + ecosystemData?.ecosystemOrgs.length > 0 && + ecosystemData?.ecosystemOrgs[0]; + setEcosystemDetails({ + autoEndorsement:ecosystemData?.autoEndorsement, + id: ecosystemData?.id, + logoUrl: ecosystemData?.logoUrl, + name: ecosystemData?.name, + description: ecosystemData?.description, + joinedDate: + ecosystemOrg && ecosystemOrg?.createDateTime + ? ecosystemOrg?.createDateTime + : '', + role: + ecosystemOrg && ecosystemOrg?.ecosystemRole?.name + ? ecosystemOrg?.ecosystemRole?.name + : '', + }); + } else { + await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); + } + } else { + await removeFromLocalStorage(storageKeys.ECOSYSTEM_ID); + setEcosystemDetailsNotFound(true); + } + } + setLoading(false); + }; + + const fetchEcosystemDashboard = async () => { + setLoading(true); + + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + const ecosystemId = await getEcosystemId(); + + if (ecosystemId && orgId) { + const response = await getEcosystemDashboard(ecosystemId, orgId); + + const { data } = response as AxiosResponse; + + if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { + setEcosystemDashboard(data?.data); + setLeadOrg(data?.data?.ecosystemLead?.orgName || ''); + } else { + setFailure(response as string); + setFailure(response as string); + setLoading(false); + } + } + setLoading(false); + }; + + const checkOrgId = async () => { + const orgId = await getFromLocalStorage(storageKeys.ORG_ID); + if (orgId) { + await getAllEcosystemInvitations(); + } + }; + + const getDashboardData = async () => { + await checkOrgId(); + await fetchEcosystemDetails(); + await fetchEcosystemDashboard(); + }; + + const navigateToInvitation = () => { + window.location.href = pathRoutes.ecosystem.sentinvitation; + }; + + useEffect(() => { + getDashboardData(); + + const checkEcosystemData = async () => { + const data: ICheckEcosystem = await checkEcosystem(); + setIsEcosystemLead(data.isEcosystemLead); + }; + checkEcosystemData(); + }, []); + + useEffect(() => { + setDropdownOpen(!editOpenModal); + }, [editOpenModal]); + + return ( +
      +
      + +
      + + {error ? ( + <> + {' '} + {(success || failure) && ( + { + setSuccess(null); + setFailure(null); + }} + /> + )} + + ) : ( + <> +
      + { + { + setMessage(null); + setError(null); + }} + /> + } +
      + + {(success || failure) && ( + { + setSuccess(null); + setFailure(null); + }} + /> + )} + + )} + + {ecosystemDetailsNotFound && ( + { + setEcosystemDetailsNotFound(false); + setFailure(null); + }} + /> + )} + + {ecosystemDetails ? ( +
      +
      +
      +
      + {ecosystemDetails?.logoUrl ? ( + + ) : ( + + )} +
      + {ecosystemDetails ? ( +
      +

      + {ecosystemDetails?.name} +

      + +

      + {ecosystemDetails?.description} +

      + {!isEcosystemLead ? ( +
      +
      + + Ecosystem Owner + + :{' '} + + {leadOrg} + +
      +
      + + Ecosystem Lead + {' '} + : + + {leadOrg} + +
      +
      + + Joined since + {' '} + : + + + {dateConversion(ecosystemDetails.joinedDate || '')} + + +
      +
      + ) : ( +
      + Role: {' '} + +
      + )} +
      + Auto Endorsement:{' '} + {ecosystemDetails.autoEndorsement ? 'Yes' : 'No'} + +
      +
      + ) : ( + + )} + + {!isEcosystemLead && ( +
      + Role: {' '} + +
      + )} + + {isEcosystemLead && ( +
      + + {dropdownOpen ? ( + ( + + )} + dismissOnClick={true} + > + { + EditEcosystemOrgModal(); + }} + > +
      Edit Ecosystem
      +
      + {/*
      Enable/Disable Ecosystem
      */} - {/* + {/*
      Manual Registration
      */} -
      - ) : ( - - )} -
      - )} -
      -
      -
      -
      - - window.location.href = pathRoutes.ecosystem.endorsements} - /> -
      -
      -
      - -
      - { - setSuccess(value); - }} - isOrganization={false} - onEditSuccess={handleEditModalClose} - entityData={ecosystemDetails} - /> -
      - ) : ( -
      - {!ecosystemDetails && loading ? ( -
      - -
      - ) : ( -
      -
      - { - setSuccess(value); - if (isOrgModal && value) { - setTimeout(() => { - window.location.reload(); - }, 2000); - } else { - getDashboardData(); - } - }} - isorgModal={isOrgModal} - /> - - - - } - onClick={() => { - setIsOrgModal(Boolean(!orgId)); - createEcosystemModel(); - }} - /> -
      -
      - )} -
      - )} -
      - ); +
      + ) : ( + + )} +
      + )} +
      +
      +
      +
      + + + (window.location.href = pathRoutes.ecosystem.endorsements) + } + /> +
      +
      +
      + +
      + { + setSuccess(value); + }} + isOrganization={false} + onEditSuccess={handleEditModalClose} + entityData={ecosystemDetails} + /> +
      + ) : ( +
      + {!ecosystemDetails && loading ? ( +
      + +
      + ) : ( +
      +
      + { + setSuccess(value); + if (isOrgModal && value) { + setTimeout(() => { + window.location.reload(); + }, 2000); + } else { + getDashboardData(); + } + }} + isorgModal={isOrgModal} + /> + + + + } + onClick={() => { + setIsOrgModal(Boolean(!orgId)); + createEcosystemModel(); + }} + /> +
      +
      + )} +
      + )} +
      + ); }; export default Dashboard; diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index 986e5bba8..ab474caa5 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -16,13 +16,15 @@ interface EditEntityModalProps { setMessage: (message: string) => void; setOpenModal: (flag: boolean) => void; onEditSuccess?: () => void; - entityData: Organisation | Ecosystem | null; + entityData: Ecosystem | null; isOrganization: boolean; + } interface EditEntityValues { name: string; description: string; + autoEndorsement: boolean; } interface ILogoImage { @@ -43,14 +45,17 @@ const EditPopupModal = (props: EditEntityModalProps) => { const [initialEntityData, setInitialEntityData] = useState({ name: "", description: "", + autoEndorsement: false, }); useEffect(() => { - if (props.openModal && props.entityData) { + if (props.openModal && props.entityData) { setInitialEntityData({ name: props.entityData.name ?? "", description: props.entityData.description ?? "", + autoEndorsement: props.entityData.autoEndorsement ?? false }); + isSetautoEndorse(props.entityData.autoEndorsement) setLogoImage({ logoFile: "", imagePreviewUrl: props.entityData.logoUrl ?? "", @@ -61,6 +66,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { const [errMsg, setErrMsg] = useState(null); const [imgError, setImgError] = useState(''); + const [isautoEndorse, isSetautoEndorse] = useState(false) useEffect(() => { @@ -68,6 +74,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { setInitialEntityData({ name: "", description: "", + autoEndorsement: false }); setLogoImage({ @@ -157,7 +164,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { name: values.name, description: values.description, logo: logoImage?.imagePreviewUrl as string || props?.entityData?.logoUrl, - + autoEndorsement:isautoEndorse }; try { @@ -200,6 +207,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { setInitialEntityData({ name: "", description: "", + }); props.setOpenModal(false); }}> @@ -341,6 +349,41 @@ const EditPopupModal = (props: EditEntityModalProps) => { {formikHandlers?.errors?.description} )}
      +
      +
      +
      +
      +
      + ) : ( + <> + ); +}; diff --git a/src/components/User/UserDashBoard.tsx b/src/components/User/UserDashBoard.tsx index 74d7af343..1058b7c67 100644 --- a/src/components/User/UserDashBoard.tsx +++ b/src/components/User/UserDashBoard.tsx @@ -50,7 +50,7 @@ const UserDashBoard = () => { const totalPages = data?.data?.totalPages; const invitationList = data?.data?.invitations; if (invitationList.length > 0) { - setMessage(`You have received invitations to join organisation`); + setMessage(`You have received invitations to join organization`); setViewButton(true); } setCurrentPage({ From ad9c0dc0e4e05ed209654e97e96133843ca282f7 Mon Sep 17 00:00:00 2001 From: Moulika Kulkarni Date: Fri, 3 Nov 2023 16:36:10 +0530 Subject: [PATCH 33/54] fix:Breadcrumbs-space-fixes Signed-off-by: Moulika Kulkarni --- src/commonComponents/SchemaCard.tsx | 6 ++-- src/components/BreadCrumbs/index.tsx | 4 +-- src/components/Ecosystem/Dashboard.tsx | 2 +- src/components/Ecosystem/EcosystemList.tsx | 2 +- .../Ecosystem/Endorsement/index.tsx | 2 +- .../EcoSystemReceivedInvitations.tsx | 2 +- .../EcosystemInvite/SentInvitations.tsx | 2 +- src/components/Issuance/Connections.tsx | 2 +- src/components/Issuance/Issuance.tsx | 2 +- src/components/Issuance/IssuedCrdentials.tsx | 2 +- src/components/Resources/Schema/Create.tsx | 2 +- .../Resources/Schema/SchemasList.tsx | 2 +- .../Resources/Schema/ViewSchema.tsx | 30 +++++++++---------- src/components/Verification/Connections.tsx | 2 +- .../Verification/CredDefSelection.tsx | 4 +-- src/components/Verification/Verification.tsx | 2 +- .../VerificationCredentialList.tsx | 2 +- src/components/organization/Dashboard.tsx | 8 ++--- .../organization/OrganizationsList.tsx | 7 ++--- .../invitations/ReceivedInvitations.tsx | 2 +- src/components/organization/users/index.tsx | 2 +- 21 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/commonComponents/SchemaCard.tsx b/src/commonComponents/SchemaCard.tsx index daf881e7d..6663c9575 100644 --- a/src/commonComponents/SchemaCard.tsx +++ b/src/commonComponents/SchemaCard.tsx @@ -36,13 +36,13 @@ const SchemaCard = (props: IProps) => {
    -

    +

    Schema ID: {props.schemaId}

    -

    +

    Issuer DID: {props.issuerDid}

    -

    +

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

    diff --git a/src/components/BreadCrumbs/index.tsx b/src/components/BreadCrumbs/index.tsx index ee276da45..c7365b6d2 100644 --- a/src/components/BreadCrumbs/index.tsx +++ b/src/components/BreadCrumbs/index.tsx @@ -21,14 +21,14 @@ export default function BreadCrumbs() { const href = `/${asPathNestedRoutes.slice(0, idx + 1).join('/')}`; return { href, text: subpath }; }); - + setBreadcrumbList(crumblist); }, []); return (
    diff --git a/src/components/Ecosystem/Dashboard.tsx b/src/components/Ecosystem/Dashboard.tsx index 13e927c63..b233c2acc 100644 --- a/src/components/Ecosystem/Dashboard.tsx +++ b/src/components/Ecosystem/Dashboard.tsx @@ -211,7 +211,7 @@ const Dashboard = () => { }, [editOpenModal]); return ( -
    +
    diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index 4e14b7cee..4bd1b55e5 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -120,7 +120,7 @@ const EcosystemList = () => {
    -
    +

    Ecosystems

    diff --git a/src/components/Ecosystem/Endorsement/index.tsx b/src/components/Ecosystem/Endorsement/index.tsx index 0885ddd46..4bb389308 100644 --- a/src/components/Ecosystem/Endorsement/index.tsx +++ b/src/components/Ecosystem/Endorsement/index.tsx @@ -212,7 +212,7 @@ const EndorsementList = () => { }, []); return ( -
    +
    diff --git a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx index 85bb62408..96cab13dd 100644 --- a/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx +++ b/src/components/EcosystemInvite/EcoSystemReceivedInvitations.tsx @@ -254,7 +254,7 @@ const ReceivedInvitations = () => { return ( -
    +
    diff --git a/src/components/EcosystemInvite/SentInvitations.tsx b/src/components/EcosystemInvite/SentInvitations.tsx index 8f77d434b..eecbb3069 100644 --- a/src/components/EcosystemInvite/SentInvitations.tsx +++ b/src/components/EcosystemInvite/SentInvitations.tsx @@ -98,7 +98,7 @@ const SentInvitations = () => { }, [searchText, currentPage.pageNumber]); return ( -
    +
    diff --git a/src/components/Issuance/Connections.tsx b/src/components/Issuance/Connections.tsx index d7c3e316c..6b58cfa6f 100644 --- a/src/components/Issuance/Connections.tsx +++ b/src/components/Issuance/Connections.tsx @@ -34,7 +34,7 @@ const Connections = () => { } return ( -
    +
    diff --git a/src/components/Issuance/Issuance.tsx b/src/components/Issuance/Issuance.tsx index ae7f6491f..1e37378cd 100644 --- a/src/components/Issuance/Issuance.tsx +++ b/src/components/Issuance/Issuance.tsx @@ -187,7 +187,7 @@ const IssueCred = () => { }; return ( -
    +
    diff --git a/src/components/Issuance/IssuedCrdentials.tsx b/src/components/Issuance/IssuedCrdentials.tsx index 8758df007..657c68979 100644 --- a/src/components/Issuance/IssuedCrdentials.tsx +++ b/src/components/Issuance/IssuedCrdentials.tsx @@ -146,7 +146,7 @@ const CredentialList = () => { ] return ( -
    +
    diff --git a/src/components/Resources/Schema/Create.tsx b/src/components/Resources/Schema/Create.tsx index 814fa338d..8acc5795f 100644 --- a/src/components/Resources/Schema/Create.tsx +++ b/src/components/Resources/Schema/Create.tsx @@ -164,7 +164,7 @@ const CreateSchema = () => { } return ( -
    +
    diff --git a/src/components/Resources/Schema/SchemasList.tsx b/src/components/Resources/Schema/SchemasList.tsx index 671784910..05e18a7cf 100644 --- a/src/components/Resources/Schema/SchemasList.tsx +++ b/src/components/Resources/Schema/SchemasList.tsx @@ -166,7 +166,7 @@ const SchemaList = (props: { schemaSelectionCallback: (schemaId: string, schemaD const emptyListDesc = "Get started by creating a new Schema" const emptyListBtn = isEcosystemData?.isEcosystemMember ? { title: "Schema Endorsement", svg: schemaEndorsement } : { title: "Create Schema", svg: create } return ( -
    +
    diff --git a/src/components/Resources/Schema/ViewSchema.tsx b/src/components/Resources/Schema/ViewSchema.tsx index 0283e7ccb..84b6b02a9 100644 --- a/src/components/Resources/Schema/ViewSchema.tsx +++ b/src/components/Resources/Schema/ViewSchema.tsx @@ -214,7 +214,7 @@ const ViewSchemas = () => { } return ( -
    +
    @@ -278,19 +278,19 @@ const ViewSchemas = () => {

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

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

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

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

    @@ -368,7 +368,7 @@ const ViewSchemas = () => { }
    - +
    {/*
    */} {/* */} @@ -404,21 +404,22 @@ const ViewSchemas = () => {
    } -
    +
    +
    - -
    +
    +
    )}
    - }
    @@ -503,6 +503,4 @@ const ViewSchemas = () => {
    ) } - - export default ViewSchemas diff --git a/src/components/Verification/Connections.tsx b/src/components/Verification/Connections.tsx index 34d211f4c..79f0fee2b 100644 --- a/src/components/Verification/Connections.tsx +++ b/src/components/Verification/Connections.tsx @@ -32,7 +32,7 @@ const Connections = () => { } return ( -
    +
    diff --git a/src/components/Verification/CredDefSelection.tsx b/src/components/Verification/CredDefSelection.tsx index a52a4950e..2553675a5 100644 --- a/src/components/Verification/CredDefSelection.tsx +++ b/src/components/Verification/CredDefSelection.tsx @@ -60,7 +60,7 @@ const CredDefSelection = () => { const header = [ { columnName: 'Name' }, { columnName: 'Credential definition Id' }, - { columnName: 'Revocable?' }, + { columnName: 'Revocable' }, { columnName: 'check' } ] @@ -121,7 +121,7 @@ const CredDefSelection = () => { } return ( -
    +
    diff --git a/src/components/Verification/Verification.tsx b/src/components/Verification/Verification.tsx index 8d0365a04..5a7ae38e0 100644 --- a/src/components/Verification/Verification.tsx +++ b/src/components/Verification/Verification.tsx @@ -197,7 +197,7 @@ const VerificationCred = () => { return ( - <>
    + <>
    diff --git a/src/components/Verification/VerificationCredentialList.tsx b/src/components/Verification/VerificationCredentialList.tsx index 858961a55..58dde168d 100644 --- a/src/components/Verification/VerificationCredentialList.tsx +++ b/src/components/Verification/VerificationCredentialList.tsx @@ -272,7 +272,7 @@ const VerificationCredentialList = () => { ]; return ( -
    +
    diff --git a/src/components/organization/Dashboard.tsx b/src/components/organization/Dashboard.tsx index 69c1a7eb1..269f7cb4c 100644 --- a/src/components/organization/Dashboard.tsx +++ b/src/components/organization/Dashboard.tsx @@ -128,8 +128,8 @@ const Dashboard = () => { return ( -
    -
    +
    +

    @@ -139,7 +139,7 @@ const Dashboard = () => {
    {

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

    diff --git a/src/components/organization/OrganizationsList.tsx b/src/components/organization/OrganizationsList.tsx index fdbbe3d63..e831097bb 100644 --- a/src/components/organization/OrganizationsList.tsx +++ b/src/components/organization/OrganizationsList.tsx @@ -121,12 +121,11 @@ const OrganizationsList = () => { return ( -
    -
    - +
    +
    -
    +

    Organizations

    diff --git a/src/components/organization/invitations/ReceivedInvitations.tsx b/src/components/organization/invitations/ReceivedInvitations.tsx index 65ae411ec..59cc7e975 100644 --- a/src/components/organization/invitations/ReceivedInvitations.tsx +++ b/src/components/organization/invitations/ReceivedInvitations.tsx @@ -106,7 +106,7 @@ const ReceivedInvitations = () => { return ( -
    +
    diff --git a/src/components/organization/users/index.tsx b/src/components/organization/users/index.tsx index eec2e9e3e..ce4dfd582 100644 --- a/src/components/organization/users/index.tsx +++ b/src/components/organization/users/index.tsx @@ -19,7 +19,7 @@ const initialPageState = { const Users = () => { return ( -
    +
    From 9d77fdd2ef09e33671caba56c5f5eba700507365 Mon Sep 17 00:00:00 2001 From: Moulika Kulkarni Date: Fri, 3 Nov 2023 16:50:45 +0530 Subject: [PATCH 34/54] fix:Breadcrumbs-space-fixes Signed-off-by: Moulika Kulkarni --- src/components/Issuance/CredDefSelection.tsx | 247 ++++++++++++------- 1 file changed, 153 insertions(+), 94 deletions(-) diff --git a/src/components/Issuance/CredDefSelection.tsx b/src/components/Issuance/CredDefSelection.tsx index 1e835f1a9..275942156 100644 --- a/src/components/Issuance/CredDefSelection.tsx +++ b/src/components/Issuance/CredDefSelection.tsx @@ -1,116 +1,146 @@ 'use client'; -import type { CredDefData, SchemaState } from "./interface"; -import { apiStatusCodes, storageKeys } from "../../config/CommonConstant"; -import { getFromLocalStorage, setToLocalStorage } from "../../api/Auth"; -import { useEffect, useState } from "react"; - -import { AlertComponent } from "../AlertComponent"; -import type { AxiosResponse } from "axios"; -import BreadCrumbs from "../BreadCrumbs"; -import { Button } from "flowbite-react"; -import CustomSpinner from "../CustomSpinner"; -import DataTable from "../../commonComponents/datatable"; -import SchemaCard from "../../commonComponents/SchemaCard"; -import type { TableData } from "../../commonComponents/datatable/interface"; -import { dateConversion } from "../../utils/DateConversion"; -import { getCredentialDefinitions } from "../../api/issuance"; -import { pathRoutes } from "../../config/pathRoutes"; -import DateTooltip from "../Tooltip"; -import BackButton from '../../commonComponents/backbutton' - +import type { CredDefData, SchemaState } from './interface'; +import { apiStatusCodes, storageKeys } from '../../config/CommonConstant'; +import { getFromLocalStorage, setToLocalStorage } from '../../api/Auth'; +import { useEffect, useState } from 'react'; + +import { AlertComponent } from '../AlertComponent'; +import type { AxiosResponse } from 'axios'; +import BreadCrumbs from '../BreadCrumbs'; +import { Button } from 'flowbite-react'; +import CustomSpinner from '../CustomSpinner'; +import DataTable from '../../commonComponents/datatable'; +import SchemaCard from '../../commonComponents/SchemaCard'; +import type { TableData } from '../../commonComponents/datatable/interface'; +import { dateConversion } from '../../utils/DateConversion'; +import { getCredentialDefinitions } from '../../api/issuance'; +import { pathRoutes } from '../../config/pathRoutes'; +import DateTooltip from '../Tooltip'; +import BackButton from '../../commonComponents/backbutton'; const CredDefSelection = () => { - const [schemaState, setSchemaState] = useState({ schemaName: '', version: '' }) - const [loading, setLoading] = useState(true) - const [schemaLoader, setSchemaLoader] = useState(true) - const [error, setError] = useState(null) - const [credDefList, setCredDefList] = useState([]) - const [schemaDetailsState, setSchemaDetailsState] = useState({ schemaId: '', issuerDid: '', attributes: [], createdDateTime: ''}) - - + const [schemaState, setSchemaState] = useState({ + schemaName: '', + version: '', + }); + const [loading, setLoading] = useState(true); + const [schemaLoader, setSchemaLoader] = useState(true); + const [error, setError] = useState(null); + const [credDefList, setCredDefList] = useState([]); + const [schemaDetailsState, setSchemaDetailsState] = useState({ + schemaId: '', + issuerDid: '', + attributes: [], + createdDateTime: '', + }); + useEffect(() => { - getSchemaAndCredDef() + getSchemaAndCredDef(); }, []); const getSchemaAndCredDef = async () => { - const schemaId = await getFromLocalStorage(storageKeys.SCHEMA_ID) - + const schemaId = await getFromLocalStorage(storageKeys.SCHEMA_ID); + if (schemaId) { - getSchemaDetails(schemaId) - getCredDefs(schemaId) - const parts = schemaId.split(":"); + getSchemaDetails(schemaId); + getCredDefs(schemaId); + const parts = schemaId.split(':'); const schemaName = parts[2]; const version = parts[3]; - setSchemaState({ schemaName, version }) + setSchemaState({ schemaName, version }); } else { - setSchemaState({ schemaName: '', version: '' }) + setSchemaState({ schemaName: '', version: '' }); } - } + }; const getSchemaDetails = async (schemaId: string) => { - setSchemaLoader(true) - const schemaDid = await getFromLocalStorage(storageKeys.SCHEMA_ATTR) - const schemaDidObject = JSON.parse(schemaDid) + setSchemaLoader(true); + const schemaDid = await getFromLocalStorage(storageKeys.SCHEMA_ATTR); + const schemaDidObject = JSON.parse(schemaDid); if (schemaDidObject) { - setSchemaDetailsState({ schemaId: schemaId, issuerDid: schemaDidObject?.issuerDid, attributes: schemaDidObject?.attribute, createdDateTime: schemaDidObject?.createdDate }) + setSchemaDetailsState({ + schemaId: schemaId, + issuerDid: schemaDidObject?.issuerDid, + attributes: schemaDidObject?.attribute, + createdDateTime: schemaDidObject?.createdDate, + }); } - setSchemaLoader(false) - } - + setSchemaLoader(false); + }; const header = [ { columnName: 'Name' }, { columnName: 'Created on' }, - { columnName: 'Revocable?' }, - { columnName: ' ' } - ] + { columnName: 'Revocable' }, + { columnName: ' ' }, + ]; const getCredDefs = async (schemaId: string) => { - setLoading(true) + setLoading(true); const response = await getCredentialDefinitions(schemaId); - - const { data } = response as AxiosResponse + + const { data } = response as AxiosResponse; if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { const credDefs = data?.data?.data.map((ele: CredDefData) => { return { - clickId: ele.credentialDefinitionId, data: [{ data: ele.tag ? ele.tag : 'Not available' }, - { data: ele?.createDateTime ? {dateConversion(ele?.createDateTime)} : 'Not available' }, - { data: ele.revocable === true ? Yes : No } - ] - } - }) + clickId: ele.credentialDefinitionId, + data: [ + { data: ele.tag ? ele.tag : 'Not available' }, + { + data: ele?.createDateTime ? ( + + {' '} + {dateConversion(ele?.createDateTime)}{' '} + + ) : ( + 'Not available' + ), + }, + { + data: + ele.revocable === true ? ( + + Yes + + ) : ( + + No + + ), + }, + ], + }; + }); if (credDefs.length === 0) { - setError('No Data Found') + setError('No Data Found'); } - setCredDefList(credDefs) + setCredDefList(credDefs); } else { - setError(response as string) + setError(response as string); } - setLoading(false) - } + setLoading(false); + }; - const schemaSelectionCallback = () => { + const schemaSelectionCallback = () => {}; - } - - const selectCredDef = async(credDefId: string | null | undefined) => { + const selectCredDef = async (credDefId: string | null | undefined) => { if (credDefId) { - await setToLocalStorage(storageKeys.CRED_DEF_ID, credDefId) - window.location.href = `${pathRoutes.organizations.Issuance.connections}` + await setToLocalStorage(storageKeys.CRED_DEF_ID, credDefId); + window.location.href = `${pathRoutes.organizations.Issuance.connections}`; } - } + }; return ( -
    +
    - +

    @@ -118,45 +148,74 @@ const CredDefSelection = () => {

    - {schemaLoader ? -
    - + {schemaLoader ? ( +
    +
    - : + ) : (
    - -
    } + +
    + )}

    Credential definitions

    - +
    +
    + You can select only one credential definition at a time. +
    + { - setError(null) + setError(null); }} /> - +
    - ) -} + ); +}; -export default CredDefSelection +export default CredDefSelection; From e5f474d3b58660c3d5af126be09858384bc9bd3f Mon Sep 17 00:00:00 2001 From: Moulika Kulkarni Date: Fri, 3 Nov 2023 17:19:19 +0530 Subject: [PATCH 35/54] fix: org-dashboard-and-login Signed-off-by: Moulika Kulkarni --- src/components/Ecosystem/EcosystemList.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index f131ed8f8..c79aa6bfd 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -312,3 +312,4 @@ const EcosystemList = () => {
    ); }; +export default EcosystemList \ No newline at end of file From c826d673b9c55fe56bc7f4571c12096a3667a384 Mon Sep 17 00:00:00 2001 From: Moulika Kulkarni Date: Fri, 3 Nov 2023 17:39:11 +0530 Subject: [PATCH 36/54] fix: org-dashboard-and-login Signed-off-by: Moulika Kulkarni --- src/components/Ecosystem/EcosystemList.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index c79aa6bfd..9e7fa4164 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -253,6 +253,7 @@ const EcosystemList = () => { ); })}
    + ) : ( ecosystemList && ( Date: Fri, 3 Nov 2023 17:45:05 +0530 Subject: [PATCH 37/54] fix: org-dashboard-and-login Signed-off-by: Moulika Kulkarni --- src/components/Ecosystem/EcosystemList.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index 9e7fa4164..6dce0618c 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -311,6 +311,7 @@ const EcosystemList = () => {
    - ); -}; -export default EcosystemList \ No newline at end of file + +) +} +export default EcosystemList; \ No newline at end of file From 8df52c2cec595d417a9f49b687a074cd92c8e4b3 Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Mon, 6 Nov 2023 12:05:32 +0530 Subject: [PATCH 38/54] feat: developed landing page Signed-off-by: bhavanakarwade --- public/images/Frame.svg | 358 ++++++++ public/images/Rectangle 10620.svg | 9 + public/images/blue_background.png | Bin 0 -> 65859 bytes src/pages/index copy.astro | 284 ++++--- src/pages/index.astro | 1278 +++++++++++++++++++++++++---- 5 files changed, 1658 insertions(+), 271 deletions(-) create mode 100644 public/images/Frame.svg create mode 100644 public/images/Rectangle 10620.svg create mode 100644 public/images/blue_background.png diff --git a/public/images/Frame.svg b/public/images/Frame.svg new file mode 100644 index 000000000..8e2613e9f --- /dev/null +++ b/public/images/Frame.svg @@ -0,0 +1,358 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/Rectangle 10620.svg b/public/images/Rectangle 10620.svg new file mode 100644 index 000000000..613b6a421 --- /dev/null +++ b/public/images/Rectangle 10620.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/blue_background.png b/public/images/blue_background.png new file mode 100644 index 0000000000000000000000000000000000000000..ab8fbc5e1e2d28e751ca873c4d7df5d52b62a237 GIT binary patch literal 65859 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

    U^^jzBUGV#aM5%-dsw;E{ZpW?Ajpd1hDIf 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 As{jB1 literal 0 HcmV?d00001 diff --git a/src/pages/index copy.astro b/src/pages/index copy.astro index 77c469e45..f54a229ce 100644 --- a/src/pages/index copy.astro +++ b/src/pages/index copy.astro @@ -11,27 +11,26 @@ import { pathRoutes } from '../config/pathRoutes';

    Open Standards & Open Source @@ -232,32 +239,52 @@ import { pathRoutes } from '../config/pathRoutes'; Verifiable Credentials, DIF Protocols & Hyperledger Aries.

    -
    -
    +
    + - - - + + - -
    -

    - Ledger-agnostic & Ledger-less -

    -

    - Supports multiple ledgers such as Indy, Cheqd, Polygon. Also - issue ledger-less VCs using did methods like did:web, did:peer, - did:key -

    +

    + Ledger-agnostic & Ledger-less +

    +

    + Supports multiple ledgers such as Indy, Cheqd, Polygon. Also + issue ledger-less VCs using did methods like did:web, did:peer, + did:key +

    +
    - - - + + +

    Multiple credential exchange formats @@ -271,18 +298,29 @@ import { pathRoutes } from '../config/pathRoutes';
    - - - - - - - - - - - - + + + + + + + + + + +

    Digital Public Good (DPG) @@ -297,12 +335,27 @@ import { pathRoutes } from '../config/pathRoutes';
    - - - - - -
    + + + + + +

    Self-host on your cloud infra

    @@ -316,10 +369,18 @@ import { pathRoutes } from '../config/pathRoutes';
    - - - - + + +

    Enterprise Grade, Large Scale @@ -1064,46 +1125,71 @@ import { pathRoutes } from '../config/pathRoutes'; >Blockster Labs Private Limited. All Rights Reserved. - diff --git a/src/pages/index.astro b/src/pages/index.astro index c2722c6f4..4e3b6b90d 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -22,7 +22,8 @@ import { pathRoutes } from '../config/pathRoutes'; CREDEBL - Pricing @@ -35,6 +36,7 @@ import { pathRoutes } from '../config/pathRoutes'; class="text-gray-600 py-2 bg-white hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-md px-4 lg:px-3 lg:py-2.5 dark:bg-primary-600 dark:hover:bg-primary-700 focus:outline-none dark:focus:ring-primary-800" >Explore Organizations +

    @@ -68,6 +70,22 @@ import { pathRoutes } from '../config/pathRoutes'; > + + + + Sign Up +
    - -
    -
    -
    -
    -
    - - New - CREDEBL 2.0 is out! See what's new - - -

    - Build Self-Sovereign Identity (SSI) solutions
    faster - for - global scale. -

    -

    - CREDEBL aims to significantly reduce the tedious work required - to
    build SSI solutions from scratch. -

    -
    +
    +
    +
    +
    +
    - Get Started + New + CREDEBL 2.0 is out! See what's new +

    + Build Self-Sovereign Identity (SSI) solutions
    faster - for + global scale. +

    +

    + CREDEBL aims to significantly reduce the tedious work required + to
    build SSI solutions from scratch. +

    +
    +
    + banner +
    -
    - banner +
    + +
    +
    +

    + Build trusted digital ecosystems using the SSI core. +

    + + +

    + CREDEBL helps you build trusted digital ecosystems, by leveraging + global
    standards of W3C Decentralized Identifiers (DID) &
    Verifiable Credentials (VC) standards. +

    -
    -
    +
    +
    +
    +
    + + + +
    +

    + Open Standards & Open Source +

    +

    + Built upon open standards of W3C Decentralized
    + Identifiers, Verifiable Credentials, DIF Protocols
    & + Hyperledger Aries. +

    +
    +
    +
    + + + +
    +

    + Multiple credential exchange formats +

    +

    + Supports multiple verifiable credential exchange + formats such as AnonCreds, JSON-LD, JWT, etc. +

    +
    +
    +
    + + + +
    +

    + Ledger-agnostic & Ledger-less +

    +

    + Supports multiple ledgers such as Indy, Cheqd, + Polygon. Also issue ledger-less VCs using did methods like + did:web, did:peer, did:key +

    +
    +
    +
    + + + +
    +

    + Self-host on your cloud infra +

    +

    + You can self-host the entire CREDEBL platform and it's + components on your organization's cloud infrastructure + of choice. +

    +
    +
    +
    + + + + +
    +

    + Digital Public Good (DPG) +

    +

    + CREDEBL is an open-souce Digital Public Good (DPG), + designed to host Digital Public Infrastructure (DPI) for + trusted digital ecosystems. +

    +
    +
    +
    + + + +
    +

    + Enterprise Grade, Large Scale +

    +

    + Build for large scale using highly scalable micro- + services architecture, and asynchronous message-driven + communication. +

    +
    +
    +
    + + +
    +
    + Frame +
    +
    -
    -
    -

    +
    - Build trusted digital ecosystems using the SSI core. -

    -

    - CREDEBL helps you build trusted digital ecosystems, by leveraging - global standards of W3C Decentralized Identifiers (DID) &
    Verifiable Credentials (VC) standards. -

    -
    -
    -
    -
    +
    +
    +
    +

    + In-CREDEBL Team +

    +

    + Join our team & a community of open-source contributors by + tuning in with the CREDEBL Discord channel and become one of + the highlighted members. +

    +
    +
    +
    +
    + + ajile-in avatar +
    + +
    + + kkkulkarni avatar +
    + + +
    + amitayanworks avatar +
    + +
    + + nishad-ayanworks avatar +
    + +
    + KulkarniShashank avatar +
    + +
    + tipusinghaw avatar +
    + + +
    + vivekayanworks avatar +
    + +
    + Sheetal-ayanworks avatar +
    + + +
    + amitpadmani-awts avatar +
    + + +
    + sairanjit avatar +
    + + +
    + makrandshinde avatar +
    + + +
    + poonam-ghewande avatar +
    + + +
    + yogeshayanworks avatar +
    + + +
    + 16-karan avatar +
    + + +
    + Girish9960 avatar +
    + + +
    + bhavanakarwade avatar +
    + + +
    + sunilbade avatar +
    + + +
    + sayali-chavan96 avatar +
    + + +
    + MoulikaKulkarni avatar +
    + + +
    + ashwini-aher avatar +
    + + +
    + pranalidhanavade avatar +
    + + +
    + RinkalBhojani avatar +
    + +
    +
    +
    +
    + +
    +

    + Join Discord Community +

    +

    + Become a member of a community of SSI developers by + supporting CREDEBL +

    +
    Join discord +
    +
    +
    +
    +
    +
    + +
    -
    - - + + +
    From f94afc0d7cd2d1b40969cc3526d954501c63aaee Mon Sep 17 00:00:00 2001 From: bhavanakarwade Date: Mon, 6 Nov 2023 16:39:35 +0530 Subject: [PATCH 39/54] feat: developed landing page Signed-off-by: bhavanakarwade --- src/pages/index.astro | 1315 +++-------------------------------------- 1 file changed, 72 insertions(+), 1243 deletions(-) diff --git a/src/pages/index.astro b/src/pages/index.astro index 4e3b6b90d..4090f5b67 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,1257 +1,86 @@ --- +import LayoutCommon from '../app/LayoutCommon.astro'; import { pathRoutes } from '../config/pathRoutes'; --- - +
    -
    - -
    -
    -
    -
    -
    - - New - CREDEBL 2.0 is out! See what's new - - -

    - Build Self-Sovereign Identity (SSI) solutions
    faster - for - global scale. -

    -

    - CREDEBL aims to significantly reduce the tedious work required - to
    build SSI solutions from scratch. -

    - -
    -
    -
    - banner -
    -
    -
    - -
    -
    -

    - Build trusted digital ecosystems using the SSI core. -

    - - -

    - CREDEBL helps you build trusted digital ecosystems, by leveraging - global
    standards of W3C Decentralized Identifiers (DID) &
    Verifiable Credentials (VC) standards. -

    -
    -
    -
    -
    -
    - - - -
    -

    - Open Standards & Open Source -

    -

    - Built upon open standards of W3C Decentralized
    - Identifiers, Verifiable Credentials, DIF Protocols
    & - Hyperledger Aries. -

    -
    -
    -
    - - - -
    -

    - Multiple credential exchange formats -

    -

    - Supports multiple verifiable credential exchange - formats such as AnonCreds, JSON-LD, JWT, etc. -

    -
    -
    -
    - - - -
    -

    - Ledger-agnostic & Ledger-less -

    -

    - Supports multiple ledgers such as Indy, Cheqd, - Polygon. Also issue ledger-less VCs using did methods like - did:web, did:peer, did:key -

    -
    -
    -
    - - - -
    -

    - Self-host on your cloud infra -

    -

    - You can self-host the entire CREDEBL platform and it's - components on your organization's cloud infrastructure - of choice. -

    -
    -
    -
    - - - - -
    -

    - Digital Public Good (DPG) -

    -

    - CREDEBL is an open-souce Digital Public Good (DPG), - designed to host Digital Public Infrastructure (DPI) for - trusted digital ecosystems. -

    -
    -
    -
    - - - -
    -

    - Enterprise Grade, Large Scale -

    -

    - Build for large scale using highly scalable micro- - services architecture, and asynchronous message-driven - communication. -

    -
    -
    -
    -
    - -
    -
    - Frame -
    -
    - -
    -
    Open main menu +
    -
    -
    -

    - In-CREDEBL Team -

    -

    - Join our team & a community of open-source contributors by - tuning in with the CREDEBL Discord channel and become one of - the highlighted members. -

    -
    -
    -
    -
    - - ajile-in avatar -
    - -
    - - kkkulkarni avatar -
    - - -
    - amitayanworks avatar -
    - -
    - - nishad-ayanworks avatar -
    - -
    - KulkarniShashank avatar -
    - -
    - tipusinghaw avatar -
    - - -
    - vivekayanworks avatar -
    - -
    - Sheetal-ayanworks avatar -
    - - -
    - amitpadmani-awts avatar -
    - - -
    - sairanjit avatar -
    - - -
    - makrandshinde avatar -
    - - -
    - poonam-ghewande avatar -
    - - -
    - yogeshayanworks avatar -
    - - -
    - 16-karan avatar -
    - - -
    - Girish9960 avatar -
    - - -
    - bhavanakarwade avatar -
    - - -
    - sunilbade avatar -
    - - -
    - sayali-chavan96 avatar -
    - - -
    - MoulikaKulkarni avatar -
    - - -
    - ashwini-aher avatar -
    - - -
    - pranalidhanavade avatar -
    - - -
    - RinkalBhojani avatar -
    - -
    -
    -
    -
    - -
    -

    - Join Discord Community -

    -

    - Become a member of a community of SSI developers by - supporting CREDEBL -

    -
    Join discord -
    -
    -
    -
    -
    -
    - - -
    -
    + +
  • + Explore Organization +
  • + +
    +
    +
    +

    - + From 6b939cdc9c7a6a8adf464752d17dd5f3d3fef43b Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Mon, 6 Nov 2023 20:22:52 +0530 Subject: [PATCH 40/54] feat:auto endorsement hover design Signed-off-by: pranalidhanavade --- .../Endorsement_Infographic_Dark_Mode.svg | 2130 ++++++++++++++++ .../Endorsement_Infographic_Ligh_Mode.svg | 2131 +++++++++++++++++ .../CreateEcosystemOrgModal/index.tsx | 165 +- src/components/Ecosystem/Dashboard.tsx | 2 +- src/components/Ecosystem/EcosystemList.tsx | 3 +- .../EditEcosystemOrgModal/index.tsx | 501 ++-- 6 files changed, 4701 insertions(+), 231 deletions(-) create mode 100644 public/images/Endorsement_Infographic_Dark_Mode.svg create mode 100644 public/images/Endorsement_Infographic_Ligh_Mode.svg diff --git a/public/images/Endorsement_Infographic_Dark_Mode.svg b/public/images/Endorsement_Infographic_Dark_Mode.svg new file mode 100644 index 000000000..724d9f4d6 --- /dev/null +++ b/public/images/Endorsement_Infographic_Dark_Mode.svg @@ -0,0 +1,2130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/Endorsement_Infographic_Ligh_Mode.svg b/public/images/Endorsement_Infographic_Ligh_Mode.svg new file mode 100644 index 000000000..821dd877c --- /dev/null +++ b/public/images/Endorsement_Infographic_Ligh_Mode.svg @@ -0,0 +1,2131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/CreateEcosystemOrgModal/index.tsx b/src/components/CreateEcosystemOrgModal/index.tsx index 213793284..e18826b5d 100644 --- a/src/components/CreateEcosystemOrgModal/index.tsx +++ b/src/components/CreateEcosystemOrgModal/index.tsx @@ -1,7 +1,7 @@ import * as yup from 'yup'; -import { Avatar, Button, Label, Modal } from 'flowbite-react'; -import { Field, Form, Formik, FormikHelpers } from 'formik'; +import { Avatar, Button, Label, Modal, Tooltip } from 'flowbite-react'; +import { Field, Form, Formik, FormikHelpers} from 'formik'; import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, @@ -60,7 +60,7 @@ const CreateEcosystemOrgModal = (props: IProps) => { const [imgError, setImgError] = useState(''); const [autoEndorse, setautoEndorse] = useState(false) - const initialFormData = formData; + useEffect(() => { setFormData({ name: '', @@ -261,7 +261,7 @@ const CreateEcosystemOrgModal = (props: IProps) => { setFormData({ name: ' ', description: ' ', - autoEndorsement: false + autoEndorsement: false, }); props.setOpenModal(false); }} @@ -277,7 +277,11 @@ const CreateEcosystemOrgModal = (props: IProps) => { /> { {!props.isorgModal && (
    -
    )} - + + + + Reset + + +
    )} diff --git a/src/components/Ecosystem/Dashboard.tsx b/src/components/Ecosystem/Dashboard.tsx index b4fb8ce7e..ab513243f 100644 --- a/src/components/Ecosystem/Dashboard.tsx +++ b/src/components/Ecosystem/Dashboard.tsx @@ -350,7 +350,7 @@ const Dashboard = () => {
    )} -
    +
    Auto Endorsement:{' '} {ecosystemDetails.autoEndorsement ? 'Yes' : 'No'} diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index ac263700b..eb02a8bf8 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -23,6 +23,7 @@ import CreateEcosystemOrgModal from '../CreateEcosystemOrgModal'; import { getEcosystems } from '../../api/ecosystem'; import type { IEcosystem } from './interfaces'; import { checkEcosystem, type ICheckEcosystem } from '../../config/ecosystem'; +import React from 'react'; const initialPageState = { pageNumber: 1, @@ -239,7 +240,7 @@ const EcosystemList = () => {
    -

    +

    Auto Endorsement:{' '} {item.autoEndorsement ? 'Yes' : 'No'}

    diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index ab474caa5..e27cf37c2 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -1,5 +1,5 @@ import * as yup from "yup"; -import { Avatar, Button, Label, Modal } from 'flowbite-react'; +import { Avatar, Button, Label, Modal, Tooltip } from 'flowbite-react'; import { Field, Form, Formik, FormikHelpers } from 'formik'; import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, apiStatusCodes, imageSizeAccepted } from '../../config/CommonConstant'; import { calculateSize, dataURItoBlob } from "../../utils/CompressImage"; @@ -198,206 +198,317 @@ const EditPopupModal = (props: EditEntityModalProps) => { } }; return ( - { - setLogoImage({ - logoFile: "", - imagePreviewUrl: "", - fileName: '' - }); - setInitialEntityData({ - name: "", - description: "", - - }); - props.setOpenModal(false); - }}> - Edit {props.isOrganization ? "Organization" : "Ecosystem"} - - { - setErrMsg(null); - }} - /> - - ) => { - await submitUpdateEntity(values); - }} - > - {(formikHandlers): JSX.Element => ( -
    -
    -
    - {logoImage.imagePreviewUrl ? ( - {`${props.isOrganization - ) : ( - - )} - -
    -

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

    -
    - JPG, JPEG and PNG. Max size of 1MB -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - { - const value = e.target.value; - formikHandlers.setFieldValue('name', value); - formikHandlers.setFieldTouched('name', true); - - if (value.length > 50) { - formikHandlers.setFieldError('name', props.isOrganization ? 'Organization name must be at most 50 characters' : 'Ecosystem name must be at most 50 characters'); - } else { - formikHandlers.setFieldError('name', undefined); - } - }} + { + setLogoImage({ + logoFile: '', + imagePreviewUrl: '', + fileName: '', + }); + setInitialEntityData({ + name: '', + description: '', + + }); + props.setOpenModal(false); + }} + > + + Edit {props.isOrganization ? 'Organization' : 'Ecosystem'} + + + { + setErrMsg(null); + }} + /> + , + ) => { + await submitUpdateEntity(values); + }} + > + {(formikHandlers): JSX.Element => ( + +
    +
    + {logoImage.imagePreviewUrl ? ( + {`${ + ) : ( + + )} - /> - {formikHandlers?.errors?.name && formikHandlers?.touched?.name && ( - {formikHandlers?.errors?.name} - )} -
    -
    -
    -
    - { - const value = e.target.value; - formikHandlers.setFieldValue('description', value); - formikHandlers.setFieldTouched('description', true); - - if (value.length > 50) { - formikHandlers.setFieldError('description', 'Description must be at most 255 characters'); - } else { - formikHandlers.setFieldError('description', undefined); - } - }} +
    +

    + {props.isOrganization + ? 'Organization Logo' + : 'Ecosystem Logo'} +

    +
    + JPG, JPEG and PNG. Max size of 1MB +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    + { + const value = e.target.value; + formikHandlers.setFieldValue('name', value); + formikHandlers.setFieldTouched('name', true); - /> - {formikHandlers?.errors?.description && formikHandlers?.touched?.description && ( - {formikHandlers?.errors?.description} - )} -
    -
    -
    +
    +
    +
    + { + const value = e.target.value; + formikHandlers.setFieldValue('description', value); + formikHandlers.setFieldTouched('description', true); - -
    -
    +
    +
    +
    + + - Update - - - )} - - - - ); + +
    + + + )} +
    +
    +
    + ); }; export default EditPopupModal; From 7c12c071014fc7d0a64bfc0590e77ecb16c49e85 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Tue, 7 Nov 2023 19:55:13 +0530 Subject: [PATCH 41/54] feat:changes in auto endorsement hover image Signed-off-by: pranalidhanavade --- .../Endorsement_Infographic_Ligh_Mode.svg | 4010 +++++++++-------- .../CreateEcosystemOrgModal/index.tsx | 68 +- src/components/Ecosystem/Dashboard.tsx | 6 +- src/components/Ecosystem/EcosystemList.tsx | 8 +- .../EditEcosystemOrgModal/index.tsx | 15 +- 5 files changed, 2102 insertions(+), 2005 deletions(-) diff --git a/public/images/Endorsement_Infographic_Ligh_Mode.svg b/public/images/Endorsement_Infographic_Ligh_Mode.svg index 821dd877c..60b50c0fd 100644 --- a/public/images/Endorsement_Infographic_Ligh_Mode.svg +++ b/public/images/Endorsement_Infographic_Ligh_Mode.svg @@ -1,2131 +1,2195 @@ - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - + - - - - - - - + + + + + + + - - + + + + + + + + - - - - - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + - + - - - - - - - - + + + + + + + + - - + + + + + + + + - - - - - + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + - - - - - - - + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + diff --git a/src/components/CreateEcosystemOrgModal/index.tsx b/src/components/CreateEcosystemOrgModal/index.tsx index e18826b5d..61b47e659 100644 --- a/src/components/CreateEcosystemOrgModal/index.tsx +++ b/src/components/CreateEcosystemOrgModal/index.tsx @@ -1,7 +1,7 @@ import * as yup from 'yup'; import { Avatar, Button, Label, Modal, Tooltip } from 'flowbite-react'; -import { Field, Form, Formik, FormikHelpers} from 'formik'; +import { Field, Form, Formik, FormikHelpers } from 'formik'; import { IMG_MAX_HEIGHT, IMG_MAX_WIDTH, @@ -32,7 +32,7 @@ interface ILogoImage { interface EcoValues { name: string; description: string; - autoEndorsement: boolean; + autoEndorsement: boolean; } interface IProps { @@ -53,19 +53,18 @@ const CreateEcosystemOrgModal = (props: IProps) => { const [formData, setFormData] = useState({ name: '', description: '', - autoEndorsement: false + autoEndorsement: false, }); const [errMsg, setErrMsg] = useState(null); const [imgError, setImgError] = useState(''); - const [autoEndorse, setautoEndorse] = useState(false) + const [autoEndorse, setautoEndorse] = useState(false); - useEffect(() => { setFormData({ name: '', description: '', - autoEndorsement: false + autoEndorsement: false, }); setLogoImage({ ...logoImage, @@ -189,8 +188,7 @@ const CreateEcosystemOrgModal = (props: IProps) => { userId: Number(user_data?.id), orgName: orgDetails?.orgName, orgDid: orgDetails?.orgDid, - autoEndorsement: autoEndorse, - + autoEndorsement: autoEndorse, }; const resCreateEco = await createEcosystems(ecoData); @@ -245,12 +243,12 @@ const CreateEcosystemOrgModal = (props: IProps) => { .min(2, 'Description must be at least 2 characters') .max(255, 'Description must be at most 255 characters') .required('Description is required'), - }; const renderEcosystemModal = () => { const popupName = props.isorgModal ? 'Organization' : 'Ecosystem'; return ( { setLogoImage({ @@ -426,16 +424,50 @@ const CreateEcosystemOrgModal = (props: IProps) => {
    diff --git a/src/components/Ecosystem/Dashboard.tsx b/src/components/Ecosystem/Dashboard.tsx index fdb16565a..884e6bf91 100644 --- a/src/components/Ecosystem/Dashboard.tsx +++ b/src/components/Ecosystem/Dashboard.tsx @@ -346,13 +346,13 @@ const Dashboard = () => {
    ) : (
    - Role: {' '} + Role: {' '}
    )}
    - Auto Endorsement:{' '} - {ecosystemDetails.autoEndorsement ? 'Yes' : 'No'} + Endorsement Flow:{' '} + {ecosystemDetails.autoEndorsement ? 'Sign and Submit' : 'Sign'}
    diff --git a/src/components/Ecosystem/EcosystemList.tsx b/src/components/Ecosystem/EcosystemList.tsx index 8e8d3699c..bb0bac9e9 100644 --- a/src/components/Ecosystem/EcosystemList.tsx +++ b/src/components/Ecosystem/EcosystemList.tsx @@ -212,7 +212,7 @@ const EcosystemList = () => { )} -
    +
    {item.name}
    @@ -224,7 +224,7 @@ const EcosystemList = () => {
  • - Roles: + Role: {item?.ecosystemOrgs && item?.ecosystemOrgs?.length > 0 && item?.ecosystemOrgs[0].ecosystemRole && @@ -241,8 +241,8 @@ const EcosystemList = () => {

    - Auto Endorsement:{' '} - {item.autoEndorsement ? 'Yes' : 'No'} + Endorsement Flow:{' '} + {item.autoEndorsement ? 'Sign and Submit' : 'Sign'}

  • diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index e27cf37c2..fed0b78fd 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -199,6 +199,7 @@ const EditPopupModal = (props: EditEntityModalProps) => { }; return ( { setLogoImage({ @@ -401,13 +402,13 @@ const EditPopupModal = (props: EditEntityModalProps) => {
    } > @@ -435,18 +436,18 @@ const EditPopupModal = (props: EditEntityModalProps) => {
    } > { viewBox="0 0 12 12" > From 764234a8b861e0c983b959f439442f899fa6a369 Mon Sep 17 00:00:00 2001 From: pranalidhanavade Date: Tue, 7 Nov 2023 21:11:51 +0530 Subject: [PATCH 42/54] feat:changes in auto endorsement hover image Signed-off-by: pranalidhanavade --- .../EditEcosystemOrgModal/index.tsx | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/src/components/EditEcosystemOrgModal/index.tsx b/src/components/EditEcosystemOrgModal/index.tsx index fed0b78fd..6a689dfbe 100644 --- a/src/components/EditEcosystemOrgModal/index.tsx +++ b/src/components/EditEcosystemOrgModal/index.tsx @@ -399,14 +399,48 @@ const EditPopupModal = (props: EditEntityModalProps) => {