diff --git a/ui/src/components/connections/CredentialsTable.tsx b/ui/src/components/connections/CredentialsTable.tsx index 23b41b53..4d945544 100644 --- a/ui/src/components/connections/CredentialsTable.tsx +++ b/ui/src/components/connections/CredentialsTable.tsx @@ -76,11 +76,17 @@ export function CredentialsTable({ userID }: { userID: string }) { dataIndex: "schemaType", ellipsis: { showTitle: false }, key: "schemaType", - render: (schemaType: Credential["schemaType"]) => ( - - {schemaType} - + render: (schemaType: Credential["schemaType"], credential: Credential) => ( + + navigate(generatePath(ROUTES.credentialDetails.path, { credentialID: credential.id })) + } + strong + > + {schemaType} + ), + sorter: ({ schemaType: a }, { schemaType: b }) => a.localeCompare(b), title: "Credential", }, diff --git a/ui/src/components/credentials/CredentialsTable.tsx b/ui/src/components/credentials/CredentialsTable.tsx index a61baf69..efd289d1 100644 --- a/ui/src/components/credentials/CredentialsTable.tsx +++ b/ui/src/components/credentials/CredentialsTable.tsx @@ -109,10 +109,15 @@ export function CredentialsTable() { dataIndex: "schemaType", ellipsis: { showTitle: false }, key: "schemaType", - render: (schemaType: Credential["schemaType"]) => ( - - {schemaType} - + render: (schemaType: Credential["schemaType"], credential: Credential) => ( + + navigate(generatePath(ROUTES.credentialDetails.path, { credentialID: credential.id })) + } + strong + > + {schemaType} + ), sorter: { multiple: 1, diff --git a/ui/src/components/credentials/LinksTable.tsx b/ui/src/components/credentials/LinksTable.tsx index d9a68252..28c58ac5 100644 --- a/ui/src/components/credentials/LinksTable.tsx +++ b/ui/src/components/credentials/LinksTable.tsx @@ -13,7 +13,6 @@ import { Table, TableColumnsType, Tag, - Tooltip, Typography, } from "antd"; @@ -97,10 +96,13 @@ export function LinksTable() { dataIndex: "schemaType", ellipsis: true, key: "schemaType", - render: (schemaType: Link["schemaType"]) => ( - - {schemaType} - + render: (schemaType: Link["schemaType"], link: Link) => ( + navigate(generatePath(ROUTES.linkDetails.path, { linkID: link.id }))} + strong + > + {schemaType} + ), sorter: ({ schemaType: a }, { schemaType: b }) => a.localeCompare(b), title: "Credential", diff --git a/ui/src/components/identities/IdentitiesTable.tsx b/ui/src/components/identities/IdentitiesTable.tsx index 8bef8b7d..4f62204a 100644 --- a/ui/src/components/identities/IdentitiesTable.tsx +++ b/ui/src/components/identities/IdentitiesTable.tsx @@ -8,11 +8,14 @@ import { Table, TableColumnsType, Tag, + Tooltip, Typography, } from "antd"; import { useCallback, useEffect, useState } from "react"; import { generatePath, useNavigate, useSearchParams } from "react-router-dom"; import IconIssuers from "src/assets/icons/building-08.svg?react"; +import IconCheckMark from "src/assets/icons/check.svg?react"; +import IconCopy from "src/assets/icons/copy-01.svg?react"; import IconDots from "src/assets/icons/dots-vertical.svg?react"; import IconInfoCircle from "src/assets/icons/info-circle.svg?react"; import IconPlus from "src/assets/icons/plus.svg?react"; @@ -81,9 +84,18 @@ export function IdentitiesTable({ handleAddIdentity }: { handleAddIdentity: () = dataIndex: "displayName", key: "displayName", render: (displayName: Identity["displayName"], identity: Identity) => ( - + + navigate( + generatePath(ROUTES.identityDetails.path, { + identityID: identity.identifier, + }) + ) + } + strong + > {displayName || formatIdentifier(identity.identifier, { short: true })} - + ), sorter: (a, b) => (a.displayName || a.identifier).localeCompare(b.displayName || b.identifier), @@ -93,16 +105,36 @@ export function IdentitiesTable({ handleAddIdentity }: { handleAddIdentity: () = dataIndex: "identifier", key: "identifier", render: (identifier: Identity["identifier"]) => ( - {formatIdentifier(identifier)} + + , ], + }} + ellipsis={{ + suffix: identifier.slice(-5), + }} + > + {identifier} + + ), sorter: ({ identifier: a }, { identifier: b }) => a.localeCompare(b), title: "DID", }, + { + dataIndex: "credentialStatusType", + key: "credentialStatusType", + render: (credentialStatusType: Identity["credentialStatusType"]) => ( + {credentialStatusType} + ), + sorter: ({ identifier: a }, { identifier: b }) => a.localeCompare(b), + title: "Credential status", + }, { dataIndex: "blockchain", key: "blockchain", render: (blockchain: Identity["blockchain"]) => ( - {blockchain} + {blockchain} ), sorter: ({ blockchain: a }, { blockchain: b }) => a.localeCompare(b), title: "Blockchain", @@ -110,7 +142,7 @@ export function IdentitiesTable({ handleAddIdentity }: { handleAddIdentity: () = { dataIndex: "network", key: "network", - render: (network: Identity["network"]) => {network}, + render: (network: Identity["network"]) => {network}, sorter: ({ network: a }, { network: b }) => a.localeCompare(b), title: "Network", }, diff --git a/ui/src/components/identities/Identity.tsx b/ui/src/components/identities/Identity.tsx index 808b019d..90487a70 100644 --- a/ui/src/components/identities/Identity.tsx +++ b/ui/src/components/identities/Identity.tsx @@ -1,25 +1,19 @@ -import { App, Button, Card, Divider, Flex, Form, Input, Space } from "antd"; +import { App, Button, Card, Divider, Flex, Form, Input, Space, Typography } from "antd"; import { useCallback, useEffect, useState } from "react"; import { useParams } from "react-router-dom"; -import { useIdentityContext } from "../../contexts/Identity"; + import { getIdentity, updateIdentityDisplayName } from "src/adapters/api/identities"; import { IdentityDetailsFormData } from "src/adapters/parsers/view"; -import CheckIcon from "src/assets/icons/check.svg?react"; import EditIcon from "src/assets/icons/edit-02.svg?react"; -import CloseIcon from "src/assets/icons/x-close.svg?react"; import { IdentityAuthCredentials } from "src/components/identities/IdentityAuthCredentials"; import { Detail } from "src/components/shared/Detail"; +import { EditModal } from "src/components/shared/EditModal"; import { ErrorResult } from "src/components/shared/ErrorResult"; import { LoadingResult } from "src/components/shared/LoadingResult"; import { SiderLayoutContent } from "src/components/shared/SiderLayoutContent"; import { useEnvContext } from "src/contexts/Env"; import { AppError, IdentityDetails } from "src/domain"; -import { - AsyncTask, - hasAsyncTaskFailed, - isAsyncTaskDataAvailable, - isAsyncTaskStarting, -} from "src/utils/async"; +import { AsyncTask, hasAsyncTaskFailed, isAsyncTaskStarting } from "src/utils/async"; import { isAbortedError, makeRequestAbortable } from "src/utils/browser"; import { IDENTITY_DETAILS, VALUE_REQUIRED } from "src/utils/constants"; import { formatIdentifier } from "src/utils/forms"; @@ -29,9 +23,9 @@ export function Identity() { const [identity, setIdentity] = useState>({ status: "pending", }); - const { fetchIdentities, identityList } = useIdentityContext(); - const [displayNameEditable, setDisplayNameEditable] = useState(false); + const [isEditModalOpen, setIsEditModalOpen] = useState(false); + const { message } = App.useApp(); const [form] = Form.useForm(); @@ -70,27 +64,16 @@ export function Identity() { return ; } - const handleEditDisplayName = (formValues: IdentityDetailsFormData) => { - const isUnique = - isAsyncTaskDataAvailable(identityList) && - !identityList.data.some( - (identity) => - identity.identifier !== identifier && identity.displayName === formValues.displayName - ); - - if (!isUnique) { - return void message.error(`${formValues.displayName} already exists`); - } - - return void updateIdentityDisplayName({ - displayName: formValues.displayName.trim(), + const handleEdit = () => { + const { displayName } = form.getFieldsValue(); + void updateIdentityDisplayName({ + displayName, env, identifier, }).then((response) => { + setIsEditModalOpen(false); if (response.success) { void fetchIdentity().then(() => { - setDisplayNameEditable(false); - makeRequestAbortable(fetchIdentities); void message.success("Identity edited successfully"); }); } else { @@ -130,44 +113,19 @@ export function Identity() { <> - {displayNameEditable ? ( -
- - - - - -