Skip to content

Commit

Permalink
rough implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
lawwman committed Jan 19, 2024
1 parent db4c3ec commit 31d537d
Show file tree
Hide file tree
Showing 8 changed files with 275 additions and 70 deletions.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16
v14.15.0
9 changes: 7 additions & 2 deletions example/application/app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ReactDOM from "react-dom";
import { rawOpencerts } from "./fixtures/v2/opencerts";
// import { rawOpencerts } from "./fixtures/v2/opencerts";
import { misconfiguredCert } from "./fixtures/v2/test-certs";
import { driverLicense } from "./fixtures/v3/driverLicense";
import React from "react";
import { AppContainer } from "./container";
Expand All @@ -8,7 +9,11 @@ export const App: React.FunctionComponent = (): React.ReactElement => {
return (
<AppContainer
documents={[
{ name: "OpenCerts (v2)", document: rawOpencerts, frameSource: "http://localhost:9000" },
{
name: "OpenCerts (v2)",
document: misconfiguredCert,
frameSource: "http://localhost:9000",
},
{ name: "Driver License (V3)", document: driverLicense, frameSource: "http://localhost:9000" },
{ name: "Legacy (Penpal V4)", document: { id: "legacy" }, frameSource: "http://localhost:8080" },
]}
Expand Down
1 change: 1 addition & 0 deletions example/application/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ const Viewer: React.FunctionComponent<ViewerProps> = ({ document }): React.React
source={document.frameSource}
dispatch={fromFrame}
onConnected={fn}
onConnectionFailure={(setDocumentToRender) => setDocumentToRender(document.document)}
css={css`
display: block;
margin: auto;
Expand Down
48 changes: 48 additions & 0 deletions example/application/fixtures/v2/test-certs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { v2 } from "@govtechsg/open-attestation";

export const misconfiguredCert = {
message: "Sample OA document",
recipient: {
name: "Tan Chen Chen",
},
$template: {
name: "NO_MATCHING_NAME",
type: v2.TemplateType.EmbeddedRenderer,
url: "https://govtech-renderer.openattestation.com",
},
issuers: [
{
id: "did:ethr:0x3A655e6EdeBcDf1e7d69195dFf2AeA5fE126bC6E",
name: "GovTech Singapore",
revocation: {
type: "NONE",
},
identityProof: {
type: ":DNS-DID",
location: "staging.notarise.io",
key: "did:ethr:0x3A655e6EdeBcDf1e7d69195dFf2AeA5fE126bC6E#controller",
},
},
],
};

export const missingTemplate = {
message: "Sample OA document",
recipient: {
name: "Tan Chen Chen",
},
issuers: [
{
id: "did:ethr:0x3A655e6EdeBcDf1e7d69195dFf2AeA5fE126bC6E",
name: "GovTech Singapore",
revocation: {
type: "NONE",
},
identityProof: {
type: ":DNS-DID",
location: "staging.notarise.io",
key: "did:ethr:0x3A655e6EdeBcDf1e7d69195dFf2AeA5fE126bC6E#controller",
},
},
],
};
262 changes: 204 additions & 58 deletions src/DefaultTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
import React from "react";
import { TemplateProps, TemplateWithComponent } from "./types";
import { EmotionJSX } from "@emotion/react/types/jsx-namespace";

interface DefaultTemplateProps {
title: string;
description: EmotionJSX.Element;
document?: TemplateProps["document"];
}

interface ConnectionFailureProps {
source: string;
document?: TemplateProps["document"];
}

const container = {

Check warning on line 16 in src/DefaultTemplate.tsx

View workflow job for this annotation

GitHub Actions / Test

'container' is assigned a value but never used
maxWidth: "1024px",
Expand All @@ -12,61 +24,70 @@ const container = {
const textColor = `#333`;

Check warning on line 24 in src/DefaultTemplate.tsx

View workflow job for this annotation

GitHub Actions / Test

'textColor' is assigned a value but never used
const paddingBox = `.75rem 1.25rem`;

export const DefaultTemplate: React.FunctionComponent<TemplateProps> = (props) => {
function extractTemplateInfo(document: TemplateProps["document"]) {
let name = "";
let type = "";
let url = "";

if ("$template" in document) {
// v2 document
const template = document.$template;

if (typeof template === "string") {
// legacy open certs. uses centralised repository.
} else if (template !== undefined) {
name = template.name;
type = template.type;
url = template.url ?? "";
}
} else if ("openAttestationMetadata" in document) {
// v3 document
const template = document.openAttestationMetadata.template;
if (template !== undefined) {
name = template.name;
type = template.type;
url = template.url;
}
}

return { name, type, url };
}

interface ExampleProps {
template: {
name: string;
type: string;
url: string;
};
}

const Example: React.FunctionComponent<ExampleProps> = ({ template }) => {
return (
<div id="default-template">
<div style={{ ...container, ...{ color: textColor } }}>
<h1
style={{
fontSize: "26px",
}}
>
This is the OpenAttestation default renderer
</h1>
<div
role="alert"
style={{
marginTop: "1.5rem",
marginBottom: "1.5rem",
backgroundColor: "#fffbec",
padding: paddingBox,
}}
>
<div style={{ display: "flex", flexWrap: "nowrap", flexDirection: "row", alignItems: "center" }}>
<div style={{ flex: "0 0 50px", marginRight: "24px" }}>
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<g clipPath="url(#a)">
<path
d="m47.7 19.6.3 2.1c.7 5-.3 10.1-2.8 14.4-2.5 4.4-6.3 7.9-10.9 9.9-4.6 2.1-9.7 2.6-14.6 1.5s-9.3-3.8-12.6-7.6c-3.3-3.8-5.2-8.6-5.6-13.6-.3-5 1-10 3.7-14.2C8 7.9 12 4.7 16.7 3c4.7-1.7 9.9-1.9 14.7-.5M25.3 10.9v21"
stroke="#F57A29"
strokeWidth="3"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path d="M25.3 40.4a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" fill="#F57A29" />
</g>
<defs>
<clipPath id="a">
<rect width="49.7" height="49.7" fill="#fff" />
</clipPath>
</defs>
</svg>
</div>
<div style={{ flex: "1 1 auto" }}>
You see this template because the certificate issuer misconfigured the template configuration of your
document. Please check with the certificate issuer. More information is available in{" "}
<a
style={{ color: "initial", textDecoration: "underline" }}
href="https://openattestation.com/docs/advanced/custom-renderer"
target="_blank"
rel="noopener noreferrer"
>
the documentation
</a>
.
</div>
</div>
</div>
<span style={{ fontFamily: "Courier" }}>
Template Name : “{template.name}
<br />
Type: “{template.type}
<br />
URL: “{template.url}
</span>
);
};

export const DefaultTemplate: React.FunctionComponent<DefaultTemplateProps> = (props) => {
return (
<div id="default-template" style={{ fontFamily: "Arial" }}>
{/* Banner */}
<div style={{ backgroundColor: "#FDFDEA", borderLeft: "2px solid #8E4B10", padding: "16px 16px 16px 18px" }}>
<p style={{ margin: "0px", lineHeight: "21px", fontSize: "16px", color: "#8E4B10", fontWeight: "700" }}>
{props.title}
</p>
<p style={{ margin: "0px", lineHeight: "21px", fontSize: "14px", color: "#374151", marginTop: "6px" }}>
{props.description}
</p>
</div>

{/* plain text preview */}
{props.document && (
<pre
style={{
backgroundColor: "#f7f8fc",
Expand All @@ -77,13 +98,138 @@ export const DefaultTemplate: React.FunctionComponent<TemplateProps> = (props) =
>
{JSON.stringify(props.document, null, 2)}
</pre>
</div>
)}
</div>
);
};

export const defaultTemplate: TemplateWithComponent = {
id: "default-template",
export const NoTemplate: React.FunctionComponent<TemplateProps> = (props) => {
return (
<DefaultTemplate
title="This document is displayed in plain text"
description={<>As this document does not have a template, the current display is intended.</>}
document={props.document}
/>
);
};

export const WrongTemplate: React.FunctionComponent<TemplateProps> = (props) => {
return (
<DefaultTemplate
title="This document has display issues"
description={
<>
An incorrect template has been used for this document. Please contact the issuer with the information below:
<br />
<br />
<Example template={extractTemplateInfo(props.document)} />
</>
}
document={props.document}
/>
);
};

export const ConnectionFailureTemplate: React.FunctionComponent<ConnectionFailureProps> = (props) => {
return (
<DefaultTemplate
title="This document might be having loading issues"
description={
<>
Try refreshing the page or check your internet connection. If the issue continues, please contact the issuer
with the information below:
{props.document && (
<>
<br />
<br />
<Example template={extractTemplateInfo(props.document)} />
</>
)}
</>
}
document={props.document}
/>
);
};

// export const DefaultTemplate: React.FunctionComponent<TemplateProps> = (props) => {
// return (
// <div id="default-template">
// <div style={{ ...container, ...{ color: textColor } }}>
// <h1
// style={{
// fontSize: "26px",
// }}
// >
// This is the OpenAttestation default renderer
// </h1>
// <div
// role="alert"
// style={{
// marginTop: "1.5rem",
// marginBottom: "1.5rem",
// backgroundColor: "#fffbec",
// padding: paddingBox,
// }}
// >
// <div style={{ display: "flex", flexWrap: "nowrap", flexDirection: "row", alignItems: "center" }}>
// <div style={{ flex: "0 0 50px", marginRight: "24px" }}>
// <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
// <g clipPath="url(#a)">
// <path
// d="m47.7 19.6.3 2.1c.7 5-.3 10.1-2.8 14.4-2.5 4.4-6.3 7.9-10.9 9.9-4.6 2.1-9.7 2.6-14.6 1.5s-9.3-3.8-12.6-7.6c-3.3-3.8-5.2-8.6-5.6-13.6-.3-5 1-10 3.7-14.2C8 7.9 12 4.7 16.7 3c4.7-1.7 9.9-1.9 14.7-.5M25.3 10.9v21"
// stroke="#F57A29"
// strokeWidth="3"
// strokeLinecap="round"
// strokeLinejoin="round"
// />
// <path d="M25.3 40.4a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" fill="#F57A29" />
// </g>
// <defs>
// <clipPath id="a">
// <rect width="49.7" height="49.7" fill="#fff" />
// </clipPath>
// </defs>
// </svg>
// </div>
// <div style={{ flex: "1 1 auto" }}>
// You see this template because the certificate issuer misconfigured the template configuration of your
// document. Please check with the certificate issuer. More information is available in{" "}
// <a
// style={{ color: "initial", textDecoration: "underline" }}
// href="https://openattestation.com/docs/advanced/custom-renderer"
// target="_blank"
// rel="noopener noreferrer"
// >
// the documentation
// </a>
// .
// </div>
// </div>
// </div>
// <pre
// style={{
// backgroundColor: "#f7f8fc",
// padding: paddingBox,
// whiteSpace: "pre-wrap",
// wordWrap: "break-word",
// }}
// >
// {JSON.stringify(props.document, null, 2)}
// </pre>
// </div>
// </div>
// );
// };

export const wrongTemplate: TemplateWithComponent = {
id: "default-template", // whats this for? does it matter?
label: "Default",
template: WrongTemplate,
};

export const noTemplate: TemplateWithComponent = {
id: "default-template", // whats this for? does it matter?
label: "Default",
template: DefaultTemplate,
template: NoTemplate,
};
Loading

0 comments on commit 31d537d

Please sign in to comment.