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 ? (
-
- ) : (
- <>
- {identity.data.displayName}
- }
- onClick={() => setDisplayNameEditable(true)}
- size="small"
- type="text"
- />
- >
- )}
+
+
+ {identity.data.displayName}
+
+
+ }
+ onClick={() => setIsEditModalOpen(true)}
+ style={{ flexShrink: 0 }}
+ type="text"
+ />
+
}
>
@@ -195,8 +153,31 @@ export function Identity() {
{identity.data.authCredentialsIDs.length && (
-
+
)}
+
+ setIsEditModalOpen(false)}
+ onSubmit={handleEdit}
+ open={isEditModalOpen}
+ title="Edit identity"
+ >
+
+
+
+
+
>
);
}
diff --git a/ui/src/components/identities/IdentityAuthCredentials.tsx b/ui/src/components/identities/IdentityAuthCredentials.tsx
index b4cf048c..d842cb05 100644
--- a/ui/src/components/identities/IdentityAuthCredentials.tsx
+++ b/ui/src/components/identities/IdentityAuthCredentials.tsx
@@ -28,7 +28,6 @@ import { CredentialRevokeModal } from "src/components/shared/CredentialRevokeMod
import { TableCard } from "src/components/shared/TableCard";
import { useEnvContext } from "src/contexts/Env";
-import { useIdentityContext } from "src/contexts/Identity";
import { AppError, AuthCredential } from "src/domain";
import { ROUTES } from "src/routes";
import { AsyncTask, isAsyncTaskDataAvailable, isAsyncTaskStarting } from "src/utils/async";
@@ -36,9 +35,14 @@ import { isAbortedError, makeRequestAbortable } from "src/utils/browser";
import { DOTS_DROPDOWN_WIDTH, ISSUE_DATE, REVOCATION, REVOKE } from "src/utils/constants";
import { formatDate } from "src/utils/forms";
-export function IdentityAuthCredentials({ IDs }: { IDs: Array }) {
+export function IdentityAuthCredentials({
+ identityID,
+ IDs,
+}: {
+ IDs: Array;
+ identityID: string;
+}) {
const env = useEnvContext();
- const { identifier } = useIdentityContext();
const navigate = useNavigate();
const [credentials, setCredentials] = useState>({
@@ -57,7 +61,7 @@ export function IdentityAuthCredentials({ IDs }: { IDs: Array }) {
const response = await getAuthCredentialsByIDs({
env,
- identifier,
+ identifier: identityID,
IDs,
signal,
});
@@ -74,7 +78,7 @@ export function IdentityAuthCredentials({ IDs }: { IDs: Array }) {
}
}
},
- [env, identifier, IDs]
+ [env, identityID, IDs]
);
const tableColumns: TableColumnsType = [
diff --git a/ui/src/components/schemas/SchemasTable.tsx b/ui/src/components/schemas/SchemasTable.tsx
index ce181a3d..16ee0d4a 100644
--- a/ui/src/components/schemas/SchemasTable.tsx
+++ b/ui/src/components/schemas/SchemasTable.tsx
@@ -13,7 +13,7 @@ import {
} from "antd";
import { useCallback, useEffect, useState } from "react";
-import { Link, generatePath, useSearchParams } from "react-router-dom";
+import { Link, generatePath, useNavigate, useSearchParams } from "react-router-dom";
import { getApiSchemas } from "src/adapters/api/schemas";
import { notifyErrors } from "src/adapters/parsers";
@@ -40,7 +40,7 @@ import { formatDate } from "src/utils/forms";
export function SchemasTable() {
const env = useEnvContext();
const { identifier } = useIdentityContext();
-
+ const navigate = useNavigate();
const [apiSchemas, setApiSchemas] = useState>({
status: "pending",
});
@@ -56,12 +56,23 @@ export function SchemasTable() {
dataIndex: "type",
ellipsis: { showTitle: false },
key: "type",
- render: (type: ApiSchema["type"], { description, title }: ApiSchema) => (
+ render: (type: ApiSchema["type"], { description, id, title }: ApiSchema) => (
- {type}
+
+ navigate(
+ generatePath(ROUTES.schemaDetails.path, {
+ schemaID: id,
+ })
+ )
+ }
+ strong
+ >
+ {type}
+
),
sorter: {
@@ -74,7 +85,7 @@ export function SchemasTable() {
dataIndex: "version",
key: "version",
render: (version: ApiSchema["version"]) => (
- {version || "-"}
+ {version || "-"}
),
sorter: {
compare: ({ version: a }, { version: b }) => (a && b ? a.localeCompare(b) : 0),