Skip to content

Commit

Permalink
Merge branch 'IN-128-add-display-method-for-schemas' of github.com:0x…
Browse files Browse the repository at this point in the history
…PolygonID/issuer-node into IN-128-add-display-method-for-schemas
  • Loading branch information
martinsaporiti committed Dec 27, 2024
2 parents 8108273 + d95c45b commit 51625d8
Show file tree
Hide file tree
Showing 4 changed files with 208 additions and 71 deletions.
37 changes: 35 additions & 2 deletions ui/src/adapters/api/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import axios from "axios";
import { z } from "zod";

import { Response, buildErrorResponse, buildSuccessResponse } from "src/adapters";
import { ID, IDParser, buildAuthorizationHeader } from "src/adapters/api";
import { ID, IDParser, Message, buildAuthorizationHeader, messageParser } from "src/adapters/api";
import { datetimeParser, getListParser, getStrictParser } from "src/adapters/parsers";
import { ApiSchema, Env, JsonLdType } from "src/domain";
import { getStorageByKey } from "src/utils/browser";
Expand All @@ -18,6 +18,7 @@ const apiSchemaParser = getStrictParser<ApiSchemaInput, ApiSchema>()(
bigInt: z.string(),
createdAt: datetimeParser,
description: z.string().nullable(),
displayMethodID: z.string().nullable(),
hash: z.string(),
id: z.string(),
title: z.string().nullable(),
Expand Down Expand Up @@ -75,7 +76,7 @@ export async function getApiSchema({
env: Env;
identifier: string;
schemaID: string;
signal: AbortSignal;
signal?: AbortSignal;
}): Promise<Response<ApiSchema>> {
try {
const response = await axios({
Expand Down Expand Up @@ -132,6 +133,38 @@ export async function getApiSchemas({
}
}

export type UpdateSchema = {
displayMethodID: string | null;
};

export async function updateSchema({
env,
identifier,
payload,
schemaID,
}: {
env: Env;
identifier: string;
payload: UpdateSchema;
schemaID: string;
}): Promise<Response<Message>> {
try {
const response = await axios({
baseURL: env.api.url,
data: payload,
headers: {
Authorization: buildAuthorizationHeader(env),
},
method: "PATCH",
url: `${API_VERSION}/identities/${identifier}/schemas/${schemaID}`,
});

return buildSuccessResponse(messageParser.parse(response.data));
} catch (error) {
return buildErrorResponse(error);
}
}

export const getIPFSGatewayUrl = (env: Env, ipfsUrl: string): Response<string> => {
const ipfsGatewayUrl = getStorageByKey({
defaultValue: env.ipfsGatewayUrl,
Expand Down
90 changes: 81 additions & 9 deletions ui/src/components/schemas/SchemaDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Button, Card, Space, Typography } from "antd";
import { App, Button, Card, Space, Typography } from "antd";
import { useCallback, useEffect, useState } from "react";
import { generatePath, useNavigate, useParams } from "react-router-dom";
import { getDisplayMethods } from "src/adapters/api/display-method";

import { getApiSchema, processUrl } from "src/adapters/api/schemas";
import { UpdateSchema, getApiSchema, processUrl, updateSchema } from "src/adapters/api/schemas";
import { getJsonSchemaFromUrl, getSchemaJsonLdTypes } from "src/adapters/jsonSchemas";
import {
buildAppError,
jsonLdContextErrorToString,
jsonSchemaErrorToString,
notifyErrors,
} from "src/adapters/parsers";
import CreditCardIcon from "src/assets/icons/credit-card-plus.svg?react";
import { DownloadSchema } from "src/components/schemas/DownloadSchema";
Expand All @@ -18,9 +20,14 @@ import { LoadingResult } from "src/components/shared/LoadingResult";
import { SiderLayoutContent } from "src/components/shared/SiderLayoutContent";
import { useEnvContext } from "src/contexts/Env";
import { useIdentityContext } from "src/contexts/Identity";
import { ApiSchema, AppError, Json, JsonLdType, JsonSchema } from "src/domain";
import { ApiSchema, AppError, DisplayMethod, Json, JsonLdType, JsonSchema } from "src/domain";
import { ROUTES } from "src/routes";
import { AsyncTask, hasAsyncTaskFailed, isAsyncTaskStarting } from "src/utils/async";
import {
AsyncTask,
hasAsyncTaskFailed,
isAsyncTaskDataAvailable,
isAsyncTaskStarting,
} from "src/utils/async";
import { isAbortedError, makeRequestAbortable } from "src/utils/browser";
import { SCHEMA_SEARCH_PARAM } from "src/utils/constants";
import { formatDate } from "src/utils/forms";
Expand All @@ -29,7 +36,7 @@ export function SchemaDetails() {
const { identifier } = useIdentityContext();
const navigate = useNavigate();
const { schemaID } = useParams();

const { message } = App.useApp();
const env = useEnvContext();

const [jsonSchemaTuple, setJsonSchemaTuple] = useState<AsyncTask<[JsonSchema, Json], AppError>>({
Expand All @@ -42,6 +49,10 @@ export function SchemaDetails() {
status: "pending",
});

const [displayMethods, setDisplayMethods] = useState<AsyncTask<DisplayMethod[], AppError>>({
status: "pending",
});

const fetchJsonSchemaFromUrl = useCallback(
(schema: ApiSchema): void => {
setJsonSchemaTuple({ status: "loading" });
Expand Down Expand Up @@ -90,8 +101,34 @@ export function SchemaDetails() {
[env]
);

const fetchDisplayMethods = useCallback(async () => {
setDisplayMethods((previousDisplayMethods) =>
isAsyncTaskDataAvailable(previousDisplayMethods)
? { data: previousDisplayMethods.data, status: "reloading" }
: { status: "loading" }
);

const response = await getDisplayMethods({
env,
identifier,
params: {},
});
if (response.success) {
setDisplayMethods({
data: response.data.items.successful,
status: "successful",
});

void notifyErrors(response.data.items.failed);
} else {
if (!isAbortedError(response.error)) {
setDisplayMethods({ error: response.error, status: "failed" });
}
}
}, [env, identifier]);

const fetchApiSchema = useCallback(
async (signal: AbortSignal) => {
async (signal?: AbortSignal) => {
if (schemaID) {
setSchema({ status: "loading" });

Expand All @@ -105,14 +142,15 @@ export function SchemaDetails() {
if (response.success) {
setSchema({ data: response.data, status: "successful" });
fetchJsonSchemaFromUrl(response.data);
void fetchDisplayMethods();
} else {
if (!isAbortedError(response.error)) {
setSchema({ error: response.error, status: "failed" });
}
}
}
},
[env, fetchJsonSchemaFromUrl, schemaID, identifier]
[env, fetchJsonSchemaFromUrl, schemaID, identifier, fetchDisplayMethods]
);

useEffect(() => {
Expand All @@ -126,12 +164,30 @@ export function SchemaDetails() {
const loading =
isAsyncTaskStarting(schema) ||
isAsyncTaskStarting(jsonSchemaTuple) ||
isAsyncTaskStarting(contextTuple);
isAsyncTaskStarting(contextTuple) ||
isAsyncTaskStarting(displayMethods);

if (!schemaID) {
return <ErrorResult error="No schema ID provided." />;
}

const handleEdit = (formValues: UpdateSchema) => {
void updateSchema({
env,
identifier,
payload: formValues,
schemaID,
}).then((response) => {
if (response.success) {
void fetchApiSchema().then(() => {
void message.success("Schema edited successfully");
});
} else {
void message.error(response.error.message);
}
});
};

return (
<SiderLayoutContent
description="Schema details include a hash, schema URL and attributes. The schema can be viewed formatted by its attributes, as the JSON LD Context or as a JSON."
Expand Down Expand Up @@ -170,10 +226,14 @@ export function SchemaDetails() {
</Card>
);
} else {
const { bigInt, createdAt, hash, url, version } = schema.data;
const { bigInt, createdAt, displayMethodID, hash, url, version } = schema.data;
const processedSchemaUrl = processUrl(url, env);
const [jsonSchema, jsonSchemaObject] = jsonSchemaTuple.data;
const [jsonLdType, jsonLdContextObject] = contextTuple.data;
const displayMethodsList = isAsyncTaskDataAvailable(displayMethods)
? displayMethods.data
: [];
const displayMethod = displayMethodsList.find(({ id }) => id === displayMethodID);

return (
<SchemaViewer
Expand Down Expand Up @@ -212,15 +272,27 @@ export function SchemaDetails() {
text={url}
/>

{displayMethod && (
<Detail
copyable
href={generatePath(ROUTES.displayMethodDetails.path, { displayMethodID })}
label="Default display method"
text={displayMethod.name}
/>
)}

<Detail label="Import date" text={formatDate(createdAt)} />

<DownloadSchema env={env} fileName={jsonSchema.name} url={url} />
</Space>
}
displayMethodID={displayMethodID}
displayMethods={displayMethodsList}
jsonLdContextObject={jsonLdContextObject}
jsonLdType={jsonLdType}
jsonSchema={jsonSchema}
jsonSchemaObject={jsonSchemaObject}
onEdit={handleEdit}
/>
);
}
Expand Down
Loading

0 comments on commit 51625d8

Please sign in to comment.