From 6d1681cb075252656a72a31e295d49902c05e9e5 Mon Sep 17 00:00:00 2001 From: Trent Larson Date: Wed, 18 Dec 2024 16:05:43 -0700 Subject: [PATCH] refine claim certificate view --- src/libs/endorserServer.ts | 10 ++++ src/views/ClaimCertificateView.vue | 75 +++++++++++++++++++++++------- src/views/ClaimView.vue | 48 ++++++++++++------- 3 files changed, 98 insertions(+), 35 deletions(-) diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts index 54ff1d2..ff4c6f3 100644 --- a/src/libs/endorserServer.ts +++ b/src/libs/endorserServer.ts @@ -476,6 +476,16 @@ export function didInfo( return didInfoForContact(did, activeDid, contact, allMyDids).displayName; } +/** + * return text description without any references to "you" as user + */ +export function didInfoForCertificate( + did: string | undefined, + contacts: Contact[], +): string { + return didInfoForContact(did, undefined, contactForDid(did, contacts), []).displayName; +} + let passkeyAccessToken: string = ""; let passkeyTokenExpirationEpochSeconds: number = 0; diff --git a/src/views/ClaimCertificateView.vue b/src/views/ClaimCertificateView.vue index c87c39e..a39567a 100644 --- a/src/views/ClaimCertificateView.vue +++ b/src/views/ClaimCertificateView.vue @@ -21,8 +21,8 @@ import { Component, Vue } from "vue-facing-decorator"; import { nextTick } from "vue"; import QRCode from "qrcode"; -import { NotificationIface } from "@/constants/app"; -import { retrieveSettingsForActiveAccount } from "@/db/index"; +import { APP_SERVER, NotificationIface } from "@/constants/app"; +import { db, retrieveSettingsForActiveAccount } from "@/db/index"; import * as endorserServer from "@/libs/endorserServer"; @Component @@ -56,7 +56,9 @@ export default class ClaimViewCertificate extends Vue { if (response.ok) { this.claimData = await response.json(); await nextTick(); // Wait for the DOM to update - this.drawCanvas(); + if (this.claimData) { + this.drawCanvas(this.claimData); + } } else { throw new Error(`Error fetching claim: ${response.statusText}`); } @@ -71,7 +73,12 @@ export default class ClaimViewCertificate extends Vue { } } - drawCanvas() { + async drawCanvas( + claimData: endorserServer.GenericCredWrapper, + ) { + await db.open(); + const allContacts = await db.contacts.toArray(); + const canvas = this.$refs.claimCanvas as HTMLCanvasElement; if (canvas) { const CANVAS_WIDTH = 1100; @@ -96,21 +103,43 @@ export default class ClaimViewCertificate extends Vue { ctx.font = "bold 20px Arial"; const claimTypeText = this.endorserServer.capitalizeAndInsertSpacesBeforeCaps( - this.claimData.claimType, + claimData.claimType || "", ); const claimTypeWidth = ctx.measureText(claimTypeText).width; ctx.fillText( claimTypeText, (CANVAS_WIDTH - claimTypeWidth) / 2, // Center horizontally - CANVAS_HEIGHT * 0.35, + CANVAS_HEIGHT * 0.33, ); + if (claimData.claim.agent) { + const presentedText = "Presented to "; + ctx.font = "14px Arial"; + const presentedWidth = ctx.measureText(presentedText).width; + ctx.fillText( + presentedText, + (CANVAS_WIDTH - presentedWidth) / 2, // Center horizontally + CANVAS_HEIGHT * 0.37, + ); + const agentText = endorserServer.didInfoForCertificate( + claimData.claim.agent, + allContacts, + ); + ctx.font = "bold 20px Arial"; + const agentWidth = ctx.measureText(agentText).width; + ctx.fillText( + agentText, + (CANVAS_WIDTH - agentWidth) / 2, // Center horizontally + CANVAS_HEIGHT * 0.4, + ); + } + const descriptionText = - this.claimData.claim.description || this.claimData.claim.name; + claimData.claim.name || claimData.claim.description; if (descriptionText) { const descriptionLine = descriptionText.length > 50 - ? descriptionText.substring(0, 47) + "..." + ? descriptionText.substring(0, 85) + "..." : descriptionText; ctx.font = "14px Arial"; const descriptionWidth = ctx.measureText(descriptionLine).width; @@ -121,26 +150,38 @@ export default class ClaimViewCertificate extends Vue { ); } + // Draw claim issuer & recipient + if (claimData.issuer) { + ctx.font = "14px Arial"; + const issuerText = + "Issued by " + + endorserServer.didInfoForCertificate( + claimData.issuer, + allContacts, + ); + ctx.fillText(issuerText, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.6); + } + // Draw claim ID ctx.font = "14px Arial"; - ctx.fillText(this.claimId, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.62); + ctx.fillText(this.claimId, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.7); ctx.fillText( "via EndorserSearch.com", CANVAS_WIDTH * 0.3, - CANVAS_HEIGHT * 0.65, + CANVAS_HEIGHT * 0.73, ); // Generate and draw QR code const qrCodeCanvas = document.createElement("canvas"); - await QRCode.toCanvas(qrCodeCanvas, window.location.href, { - width: 150, - color: { light: "#0000" /* Transparent background */ }, - }); - ctx.drawImage( + await QRCode.toCanvas( qrCodeCanvas, - CANVAS_WIDTH * 0.57, - CANVAS_HEIGHT * 0.55, + APP_SERVER + "/claim/" + this.claimId, + { + width: 150, + color: { light: "#0000" /* Transparent background */ }, + }, ); + ctx.drawImage(qrCodeCanvas, CANVAS_WIDTH * 0.6, CANVAS_HEIGHT * 0.55); }; } } diff --git a/src/views/ClaimView.vue b/src/views/ClaimView.vue index 1e593e3..c8f2725 100644 --- a/src/views/ClaimView.vue +++ b/src/views/ClaimView.vue @@ -20,24 +20,36 @@
-

- {{ capitalizeAndInsertSpacesBeforeCaps(veriClaim.claimType) }} - -

+
+

+ {{ capitalizeAndInsertSpacesBeforeCaps(veriClaim.claimType) }} + +

+ +