Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

Commit

Permalink
chore: added exchange fail tooltip, reformatted exchange issueance / …
Browse files Browse the repository at this point in the history
…presentation code (#65)
  • Loading branch information
mikeplotean authored Nov 2, 2023
1 parent 46996e4 commit 5ae931d
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 95 deletions.
123 changes: 50 additions & 73 deletions web/src/pages/exchange/issuance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
<PageHeader>
<template v-slot:title>
<div class="ml-3">
<h1
class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:leading-9"
>
<h1 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:leading-9">
Receive {{ credentialCount === 1 ? "single" : credentialCount }}
{{ credentialCount === 1 ? "credential" : "credentials" }}
</h1>
Expand All @@ -17,29 +15,24 @@

<template v-if="!immediateAccept" v-slot:menu>
<ActionButton
class="inline-flex items-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:scale-105 hover:animate-pulse hover:bg-red-700 focus:animate-none focus:outline focus:outline-offset-2 focus:outline-red-700"
display-text="Reject"
icon="heroicons:x-mark"
type="button"
@click="navigateTo('/')"
/>

<ActionButton
:class="[
failed
? 'animate-pulse bg-red-600 hover:scale-105 hover:bg-red-700 focus:outline focus:outline-offset-2 focus:outline-red-700'
: 'bg-green-600 hover:scale-105 hover:animate-pulse hover:bg-green-700 focus:animate-none focus:outline-green-700',
]"
:failed="failed"
class="inline-flex items-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:scale-105 hover:animate-pulse hover:bg-red-700 focus:animate-none focus:outline focus:outline-offset-2 focus:outline-red-700"
display-text="Reject" icon="heroicons:x-mark" type="button" @click="navigateTo('/')" />

<div class="group flex">
<ActionButton :class="[
failed
? 'animate-pulse bg-red-600 hover:scale-105 hover:bg-red-700 focus:outline focus:outline-offset-2 focus:outline-red-700'
: 'bg-green-600 hover:scale-105 hover:animate-pulse hover:bg-green-700 focus:animate-none focus:outline-green-700',
]" :failed="failed"
:disabled="(selectedDid === null || selectedDid === undefined) && !(dids && dids?.length === 1)"
class="inline-flex items-center rounded-md px-3 py-2 text-sm font-semibold
text-white shadow-sm focus:outline focus:outline-offset-2 disabled:bg-gray-200 disabled:cursor-not-allowed
"
display-text="Accept"
icon="heroicons:check"
type="button"
@click="acceptCredential"
/>
" display-text="Accept" icon="heroicons:check" type="button" @click="acceptCredential" />
<span v-if="failed"
class="group-hover:opacity-100 transition-opacity bg-gray-800 px-1 text-sm text-gray-100 rounded-md absolute -translate-x-1/2 opacity-0 m-4 mx-auto">
{{ failMessage }}
</span>
</div>
</template>
</PageHeader>

Expand All @@ -58,37 +51,34 @@

<div class="relative mt-2">
<ListboxButton v-if="selectedDid !== null"
class="relative w-full cursor-default rounded-md bg-white py-1.5 pl-3 pr-10 text-left text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 sm:text-sm sm:leading-6 h-9"
>
class="relative w-full cursor-default rounded-md bg-white py-1.5 pl-3 pr-10 text-left text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 sm:text-sm sm:leading-6 h-9">
<span class="flex items-center">
<p class="truncate font-bold">{{ selectedDid?.alias }}</p>
<span class="ml-3 block truncate">{{ selectedDid?.did }}</span>
</span>
<span class="pointer-events-none absolute inset-y-0 right-0 ml-3 flex items-center pr-2">
<ChevronUpDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true"/>
<ChevronUpDownIcon class="h-5 w-5 text-gray-400" aria-hidden="true" />
</span>
</ListboxButton>

<transition leave-active-class="transition ease-in duration-100"
leave-from-class="opacity-100" leave-to-class="opacity-0"
>
<transition leave-active-class="transition ease-in duration-100" leave-from-class="opacity-100"
leave-to-class="opacity-0">
<ListboxOptions
class="absolute z-10 mt-1 max-h-56 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
>
class="absolute z-10 mt-1 max-h-56 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
<ListboxOption as="template" v-for="did in dids" :key="did?.did" :value="did"
v-slot="{ active, selectedDid }"
>
<li :class="[active ? 'bg-indigo-600 text-white' : 'text-gray-900', 'relative cursor-default select-none py-2 pl-3 pr-9']">
v-slot="{ active, selectedDid }">
<li
:class="[active ? 'bg-indigo-600 text-white' : 'text-gray-900', 'relative cursor-default select-none py-2 pl-3 pr-9']">
<div class="flex items-center">
<p class="italic">{{ did.alias }}</p>
<span :class="[selectedDid ? 'font-semibold' : 'font-normal', 'ml-3 block truncate']">{{
<span
:class="[selectedDid ? 'font-semibold' : 'font-normal', 'ml-3 block truncate']">{{
did.did
}}</span>
</div>
<span v-if="selectedDid"
:class="[active ? 'text-white' : 'text-indigo-600', 'absolute inset-y-0 right-0 flex items-center pr-4']"
>
<CheckIcon class="h-5 w-5" aria-hidden="true"/>
:class="[active ? 'text-white' : 'text-indigo-600', 'absolute inset-y-0 right-0 flex items-center pr-4']">
<CheckIcon class="h-5 w-5" aria-hidden="true" />
</span>
</li>
</ListboxOption>
Expand All @@ -103,13 +93,13 @@
<InformationCircleIcon class="h-5 w-5 text-blue-400" aria-hidden="true" />
</div>-->
<div class="ml-3 flex-1 flex flex-col md:flex-row md:justify-between">
<span v-if="selectedDid != null" class="text-sm text-blue-700 max-w-xs overflow-x-scroll mr-3 truncate">
<span v-if="selectedDid != null"
class="text-sm text-blue-700 max-w-xs overflow-x-scroll mr-3 truncate">
Will issue to DID: {{ selectedDid.alias }} ({{ selectedDid.did }})
</span>
<button class="text-sm md:ml-6">
<NuxtLink to="/settings/dids"
class="whitespace-nowrap font-medium text-blue-700 hover:text-blue-600"
>
class="whitespace-nowrap font-medium text-blue-700 hover:text-blue-600">
DID management
<span aria-hidden="true"> &rarr;</span>
</NuxtLink>
Expand All @@ -122,44 +112,29 @@

<p class="mt-10 mb-1">The following credentials will be issued:</p>

<div
aria-label="Credential list"
class="h-full overflow-y-auto shadow-xl"
>
<div
v-for="group in groupedCredentialTypes.keys()"
:key="group.id"
class="relative"
>
<div aria-label="Credential list" class="h-full overflow-y-auto shadow-xl">
<div v-for="group in groupedCredentialTypes.keys()" :key="group.id" class="relative">
<div
class="top-0 z-10 border-y border-b-gray-200 border-t-gray-100 bg-gray-50 px-3 py-1.5 text-sm font-semibold leading-6 text-gray-900"
>
class="top-0 z-10 border-y border-b-gray-200 border-t-gray-100 bg-gray-50 px-3 py-1.5 text-sm font-semibold leading-6 text-gray-900">
<h3>{{ group }}s:</h3>
</div>
<ul class="divide-y divide-gray-100" role="list">
<li
v-for="credential in groupedCredentialTypes.get(group)"
:key="credential"
class="flex gap-x-4 px-3 py-5"
>
<CredentialIcon
:credentialType="credential.name"
class="h-6 w-6 flex-none rounded-full bg-gray-50"
></CredentialIcon>
<li v-for="credential in groupedCredentialTypes.get(group)" :key="credential"
class="flex gap-x-4 px-3 py-5">
<CredentialIcon :credentialType="credential.name"
class="h-6 w-6 flex-none rounded-full bg-gray-50"></CredentialIcon>

<div class="flex min-w-0 flex-row items-center">
<span class="text-lg font-semibold leading-6 text-gray-900"
>{{ credential.id }}.</span
>
<span class="text-lg font-semibold leading-6 text-gray-900">{{ credential.id }}.</span>
<span class="ml-1 truncate text-sm leading-5 text-gray-800">{{
credential.name
}}</span>
credential.name
}}</span>
</div>
</li>
</ul>
</div>
</div>
<br/>
<br />
<!-- <div class="h-full overflow-y-auto shadow-xl">
<select v-model="selectedDid">
<option v-for="did in dids.value" :value="did">
Expand All @@ -177,12 +152,12 @@ import PageHeader from "~/components/PageHeader.vue";
import CredentialIcon from "~/components/CredentialIcon.vue";
import ActionButton from "~/components/buttons/ActionButton.vue";
import LoadingIndicator from "~/components/loading/LoadingIndicator.vue";
import {Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions,} from "@headlessui/vue";
import {CheckIcon, ChevronUpDownIcon} from "@heroicons/vue/20/solid";
import {useTitle} from "@vueuse/core";
import {Ref} from "vue";
import { Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions, } from "@headlessui/vue";
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/20/solid";
import { useTitle } from "@vueuse/core";
import { Ref } from "vue";
const {data: dids, pending: pendingDids} = await useLazyAsyncData(
const { data: dids, pending: pendingDids } = await useLazyAsyncData(
() => $fetch("/r/wallet/dids")
)
Expand Down Expand Up @@ -252,12 +227,13 @@ const credentialCount = credentialTypes.length;
let i = 0;
const groupedCredentialTypes = groupBy(
credentialTypes.map((item) => {
return {id: ++i, name: item};
return { id: ++i, name: item };
}),
(c) => c.name
);
const failed = ref(false);
const failMessage = ref("Unknown error occurred.")
async function acceptCredential() {
Expand All @@ -278,6 +254,7 @@ async function acceptCredential() {
navigateTo("/");
} catch (e) {
failed.value = true;
failMessage.value = JSON.stringify(e);
throw e;
}
}
Expand Down
46 changes: 24 additions & 22 deletions web/src/pages/exchange/presentation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@

<template v-if="!immediateAccept" v-slot:menu>
<ActionButton
class="inline-flex focus:outline focus:outline-red-700 focus:outline-offset-2 items-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-700 hover:scale-105 hover:animate-pulse focus:animate-none"
display-text="Reject"
icon="heroicons:x-mark" type="button" @click="navigateTo('/')"
/>
class="inline-flex focus:outline focus:outline-red-700 focus:outline-offset-2 items-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-700 hover:scale-105 hover:animate-pulse focus:animate-none"
display-text="Reject" icon="heroicons:x-mark" type="button" @click="navigateTo('/')" />

<ActionButton
<div class="group flex">
<ActionButton
:class="[failed ? 'bg-red-600 animate-pulse focus:outline focus:outline-red-700 focus:outline-offset-2 hover:bg-red-700 hover:scale-105' : 'bg-green-600 focus:outline-green-700 hover:bg-green-700 hover:scale-105 hover:animate-pulse focus:animate-none']"
:failed="failed"
class="inline-flex focus:outline focus:outline-offset-2 items-center rounded-md px-3 py-2 text-sm font-semibold text-white shadow-sm"
display-text="Accept"
icon="heroicons:check" type="button" @click="acceptPresentation"
/>
display-text="Accept" icon="heroicons:check" type="button" @click="acceptPresentation" />
<!-- tooltip -->
<span v-if="failed"
class="group-hover:opacity-100 transition-opacity bg-gray-800 px-1 text-sm text-gray-100 rounded-md absolute -translate-x-1/2 opacity-0 m-4 mx-auto">
{{ failMessage }}
</span>
</div>
</template>
</PageHeader>
<CenterMain>
Expand All @@ -37,18 +40,15 @@
<div aria-label="Credential list" class="h-full overflow-y-auto shadow-xl">
<div v-for="group in groupedCredentialTypes.keys()" :key="group.id" class="relative">
<div
class="sticky top-0 z-10 border-y border-b-gray-200 border-t-gray-100 bg-gray-50 px-3 py-1.5 text-sm font-semibold leading-6 text-gray-900"
>
class="sticky top-0 z-10 border-y border-b-gray-200 border-t-gray-100 bg-gray-50 px-3 py-1.5 text-sm font-semibold leading-6 text-gray-900">
<h3>{{ group }}s:</h3>
</div>
<ul class="divide-y divide-gray-100" role="list">
<li v-for="credential in groupedCredentialTypes.get(group)" :key="credential"
class="flex gap-x-4 px-3 py-5"
>
class="flex gap-x-4 px-3 py-5">

<CredentialIcon :credentialType="credential.name"
class="h-6 w-6 flex-none rounded-full bg-gray-50"
></CredentialIcon>
class="h-6 w-6 flex-none rounded-full bg-gray-50"></CredentialIcon>

<div class="min-w-0 flex flex-row items-center">
<span class="text-lg font-semibold leading-6 text-gray-900">{{ credential.id }}.</span>
Expand All @@ -68,14 +68,14 @@ import PageHeader from "~/components/PageHeader.vue";
import CredentialIcon from "~/components/CredentialIcon.vue";
import ActionButton from "~/components/buttons/ActionButton.vue";
import LoadingIndicator from "~/components/loading/LoadingIndicator.vue";
import {groupBy} from "~/composables/groupings";
import {useTitle} from "@vueuse/core";
import {parseDate} from "@taquito/michel-codec/dist/types/utils";
import { groupBy } from "~/composables/groupings";
import { useTitle } from "@vueuse/core";
import { parseDate } from "@taquito/michel-codec/dist/types/utils";
async function resolvePresentationRequest(request) {
try {
console.log("RESOLVING request", request)
const response = await $fetch("/r/wallet/exchange/resolvePresentationRequest", {method: 'POST', body: request})
const response = await $fetch("/r/wallet/exchange/resolvePresentationRequest", { method: 'POST', body: request })
console.log(response)
return response
} catch (e) {
Expand Down Expand Up @@ -103,13 +103,14 @@ console.log("inputDescriptors: ", inputDescriptors)
let i = 0
let groupedCredentialTypes = groupBy(inputDescriptors.map(item => {
return {id: ++i, name: item.id}
return { id: ++i, name: item.id }
}), c => c.name)
console.log("groupedCredentialTypes: ", groupedCredentialTypes)
const immediateAccept = ref(false)
const failed = ref(false)
const failMessage = ref("Unknown error occurred.")
async function acceptPresentation() {
const response = await fetch("/r/wallet/exchange/usePresentationRequest", {
Expand All @@ -120,7 +121,7 @@ async function acceptPresentation() {
if (response.ok) {
console.log("Response: " + response)
const parsedResponse: {redirectUri: string} = await response.json()
const parsedResponse: { redirectUri: string } = await response.json()
if (parsedResponse.redirectUri) {
navigateTo(parsedResponse.redirectUri, {
Expand All @@ -133,10 +134,11 @@ async function acceptPresentation() {
}
} else {
failed.value = true
const error: {message: string, redirectUri: string | null | undefined} = await response.json()
const error: { message: string, redirectUri: string | null | undefined } = await response.json()
failMessage.value = error.message
console.log("Error response: " + JSON.stringify(error))
window.alert(error.message)
// window.alert(error.message)
if (error.redirectUri != null) {
navigateTo(error.redirectUri as string, {
Expand Down

0 comments on commit 5ae931d

Please sign in to comment.