Changes: - Move v-model directives before other attributes - Move v-bind directives before event handlers - Reorder attributes for better readability - Fix template attribute ordering across components - Improve eslint rules - add default vite config for testing (handles nostr error too) This follows Vue.js style guide recommendations for attribute ordering and improves template consistency.
898 lines
29 KiB
Vue
898 lines
29 KiB
Vue
<template>
|
|
<QuickNav />
|
|
<TopMessage />
|
|
<!-- CONTENT -->
|
|
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
|
<!-- Breadcrumb -->
|
|
<div id="ViewBreadcrumb" class="mb-8">
|
|
<h1 class="text-lg text-center font-light relative px-7">
|
|
<!-- Back -->
|
|
<button
|
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
|
@click="$router.go(-1)"
|
|
>
|
|
<font-awesome icon="chevron-left" class="fa-fw" />
|
|
</button>
|
|
<span
|
|
v-if="
|
|
libsUtil.isGiveRecordTheUserCanConfirm(
|
|
isRegistered,
|
|
veriClaim,
|
|
activeDid,
|
|
confirmerIdList,
|
|
)
|
|
"
|
|
>
|
|
Do you agree?
|
|
</span>
|
|
<span v-else> Confirmation Details </span>
|
|
</h1>
|
|
</div>
|
|
|
|
<div v-if="giveDetails && !isLoading">
|
|
<div class="flex justify-center">
|
|
<button
|
|
v-if="
|
|
libsUtil.isGiveRecordTheUserCanConfirm(
|
|
isRegistered,
|
|
veriClaim,
|
|
activeDid,
|
|
confirmerIdList,
|
|
)
|
|
"
|
|
class="col-span-1 bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
|
|
@click="confirmConfirmClaim()"
|
|
>
|
|
Confirm
|
|
<font-awesome
|
|
icon="circle-check"
|
|
class="ml-2 text-white cursor-pointer"
|
|
/>
|
|
</button>
|
|
<button
|
|
v-else
|
|
class="col-span-1 bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
|
|
@click="notifyWhyCannotConfirm()"
|
|
>
|
|
Confirm
|
|
<font-awesome
|
|
icon="circle-check"
|
|
class="ml-2 text-white cursor-pointer"
|
|
/>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Details -->
|
|
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mt-4">
|
|
<div class="flex gap-4 overflow-hidden">
|
|
<div class="overflow-hidden">
|
|
<div class="text-sm">
|
|
<div>
|
|
<font-awesome icon="arrow-left" class="fa-fw text-slate-400" />
|
|
{{ giverName }}
|
|
</div>
|
|
<div class="ml-6">gave</div>
|
|
<div v-if="giveDetails.amount">
|
|
<font-awesome
|
|
icon="hand-holding-dollar"
|
|
class="fa-fw text-slate-400"
|
|
/>
|
|
{{ displayAmount(giveDetails.unit, giveDetails.amount) }}
|
|
</div>
|
|
<div v-if="giveDetails.description">
|
|
<font-awesome icon="message" class="fa-fw text-slate-400" />
|
|
{{ giveDetails.amount ? "and:" : "" }}
|
|
{{ giveDetails.description }}
|
|
</div>
|
|
<div class="ml-6">to</div>
|
|
<div>
|
|
<font-awesome icon="arrow-right" class="fa-fw text-slate-400" />
|
|
{{ recipientName }}
|
|
</div>
|
|
<div>
|
|
<font-awesome icon="calendar" class="fa-fw text-slate-400" />
|
|
on
|
|
{{ giveDetails.issuedAt.substring(0, 10) }}
|
|
</div>
|
|
|
|
<!-- Fullfills Links -->
|
|
|
|
<!-- fullfills links for a give -->
|
|
<div v-if="giveDetails?.fulfillsPlanHandleId" class="mt-2">
|
|
<router-link
|
|
:to="
|
|
'/project/' +
|
|
encodeURIComponent(giveDetails?.fulfillsPlanHandleId || '')
|
|
"
|
|
class="text-blue-500 mt-2 cursor-pointer"
|
|
target="_blank"
|
|
>
|
|
This fulfills a bigger plan
|
|
<font-awesome
|
|
icon="arrow-up-right-from-square"
|
|
class="fa-fw"
|
|
/>
|
|
</router-link>
|
|
</div>
|
|
<!-- if there's another, it's probably fulfilling an offer, too -->
|
|
<div
|
|
v-if="
|
|
giveDetails?.fulfillsType &&
|
|
giveDetails?.fulfillsType !== 'PlanAction' &&
|
|
giveDetails?.fulfillsHandleId
|
|
"
|
|
>
|
|
<!-- router-link to /claim/ only changes URL path -->
|
|
<router-link
|
|
:to="
|
|
'/claim/' +
|
|
encodeURIComponent(giveDetails?.fulfillsHandleId || '')
|
|
"
|
|
class="text-blue-500 mt-2 cursor-pointer"
|
|
target="_blank"
|
|
>
|
|
This fulfills
|
|
{{
|
|
capitalizeAndInsertSpacesBeforeCapsWithAPrefix(
|
|
giveDetails?.fulfillsType || "",
|
|
)
|
|
}}
|
|
<font-awesome
|
|
icon="arrow-up-right-from-square"
|
|
class="fa-fw"
|
|
/>
|
|
</router-link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="mt-2">
|
|
<font-awesome icon="comment" class="text-slate-400" />
|
|
{{ issuerName }} posted that.
|
|
</div>
|
|
|
|
<div v-if="libsUtil.isGiveAction(veriClaim)" class="mt-4">
|
|
<h2 class="font-bold uppercase text-xl mt-8 mb-2">Confirmations</h2>
|
|
|
|
<span v-if="totalConfirmers() === 0">Nobody has confirmed this.</span>
|
|
<span v-else-if="totalConfirmers() === 1">
|
|
One person confirmed this.
|
|
</span>
|
|
<span v-else> {{ totalConfirmers() }} people confirmed this. </span>
|
|
|
|
<div v-if="totalConfirmers() > 0">
|
|
<div
|
|
v-if="
|
|
confirmerIdList.length === 0 && confsVisibleToIdList.length === 0
|
|
"
|
|
>
|
|
Nobody that you know confirmed this claim, nor do they have any
|
|
confirmers in their network.
|
|
</div>
|
|
|
|
<div
|
|
v-if="
|
|
confirmerIdList.length === 0 && confsVisibleToIdList.length > 0
|
|
"
|
|
>
|
|
<!-- Only show if this person has links to confirmers (below). -->
|
|
Nobody that you know issued or confirmed this claim.
|
|
</div>
|
|
<div v-if="confirmerIdList.length > 0">
|
|
The following people confirmed this claim.
|
|
<ul class="ml-4">
|
|
<li
|
|
v-for="confirmerId in confirmerIdList"
|
|
:key="confirmerId"
|
|
class="list-disc ml-4"
|
|
>
|
|
<div class="flex gap-4">
|
|
<div class="grow overflow-hidden">
|
|
<div class="text-sm">
|
|
{{ didInfo(confirmerId) }}
|
|
<span v-if="!serverUtil.isEmptyOrHiddenDid(confirmerId)">
|
|
<button
|
|
@click="
|
|
copyToClipboard(
|
|
'The DID of ' + confirmerId,
|
|
confirmerId,
|
|
)
|
|
"
|
|
>
|
|
<font-awesome
|
|
icon="copy"
|
|
class="text-slate-400 fa-fw"
|
|
/>
|
|
</button>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!--
|
|
Never need to show this message:
|
|
"Nobody that you know can see someone who confirmed this claim."
|
|
|
|
If there is nobody in the confirmerIdList then we'll show the combined "nobody" message.
|
|
If there is somebody in the confirmerIdList then that's all they need to show.
|
|
-->
|
|
|
|
<!-- Now show anyone linked to confirmers. -->
|
|
<div v-if="confsVisibleToIdList.length > 0">
|
|
The following people can connect you with people who issued or
|
|
confirmed this claim.
|
|
<ul class="ml-4">
|
|
<li
|
|
v-for="confsVisibleTo in confsVisibleToIdList"
|
|
:key="confsVisibleTo"
|
|
class="list-disc ml-4"
|
|
>
|
|
<div class="flex gap-4">
|
|
<div class="grow overflow-hidden">
|
|
<div class="text-sm">
|
|
{{ didInfo(confsVisibleTo) }}
|
|
<span
|
|
v-if="!serverUtil.isEmptyOrHiddenDid(confsVisibleTo)"
|
|
>
|
|
<button
|
|
@click="
|
|
copyToClipboard(
|
|
'The DID of ' + confsVisibleTo,
|
|
confsVisibleTo,
|
|
)
|
|
"
|
|
>
|
|
<font-awesome
|
|
icon="copy"
|
|
class="text-slate-400 fa-fw"
|
|
/>
|
|
</button>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- explain if user cannot confirm -->
|
|
<!-- Note that these conditions are mirrored in userCanConfirm(). -->
|
|
<div v-if="!isRegistered">
|
|
You cannot confirm this because you are not registered. Find someone
|
|
to register you, maybe on the Help page.
|
|
</div>
|
|
<div v-else-if="giveDetails.issuerDid == activeDid">
|
|
You cannot confirm this because you issued this claim, so you already
|
|
count as confirming it.
|
|
</div>
|
|
<div v-else-if="serverUtil.containsHiddenDid(veriClaim.claim)">
|
|
You cannot confirm this because some people are hidden.
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Note that a similar section is found in ClaimView.vue, and kinda in HiddenDidDialog.vue -->
|
|
<h2
|
|
class="font-bold uppercase text-xl text-blue-500 mt-8 cursor-pointer"
|
|
@click="showVeriClaimDump = !showVeriClaimDump"
|
|
>
|
|
Details
|
|
<font-awesome v-if="showVeriClaimDump" icon="chevron-up" />
|
|
<font-awesome v-else icon="chevron-right" />
|
|
</h2>
|
|
<div v-if="showVeriClaimDump">
|
|
<div
|
|
v-if="
|
|
serverUtil.containsHiddenDid(veriClaim) &&
|
|
R.isEmpty(veriClaimDidsVisible)
|
|
"
|
|
class="mb-2"
|
|
>
|
|
Some of the details are not visible to you; they show as "HIDDEN".
|
|
They are not visible to any of your direct contacts, either.
|
|
<span v-if="canShare">
|
|
You can ask one of your contacts to take a look and see if their
|
|
contacts can see more details:
|
|
<a class="text-blue-500" @click="onClickShareClaim()"
|
|
>click to send them this page info</a
|
|
>
|
|
and see if they can make an introduction. Someone is connected to
|
|
people closer to them; if you don't know who to ask, try the person
|
|
who registered you.
|
|
</span>
|
|
<span v-else>
|
|
You can ask one of your contacts to take a look and see if their
|
|
contacts can see more details:
|
|
<a
|
|
class="text-blue-500"
|
|
@click="copyToClipboard('A link to this page', windowLocation)"
|
|
>click to copy this page info</a
|
|
>
|
|
and see if they can make an introduction. Someone is connected to
|
|
people closer to them; if you don't know who to ask, try the person
|
|
who registered you.
|
|
</span>
|
|
</div>
|
|
|
|
<div v-if="!R.isEmpty(veriClaimDidsVisible)">
|
|
Some of the details are not visible to you but they are visible to
|
|
some of your contacts.
|
|
<span v-if="canShare">
|
|
If you'd like an introduction,
|
|
<a class="text-blue-500" @click="onClickShareClaim()"
|
|
>click to share the information with them and ask if they'll tell
|
|
you more about the participants.</a
|
|
>
|
|
</span>
|
|
<span v-else>
|
|
If you'd like an introduction,
|
|
<a
|
|
class="text-blue-500"
|
|
@click="copyToClipboard('A link to this page', windowLocation)"
|
|
>share this page with them and ask if they'll tell you more about
|
|
about the participants.</a
|
|
>
|
|
</span>
|
|
|
|
<div
|
|
v-for="(visibleDidPath, index) of Object.keys(veriClaimDidsVisible)"
|
|
:key="index"
|
|
class="list-disc p-4"
|
|
>
|
|
<div class="text-sm">
|
|
<font-awesome icon="minus" class="fa-fw" />
|
|
The {{ visibleDidPath }} is visible to:
|
|
</div>
|
|
<div class="ml-12 p-1">
|
|
<ul>
|
|
<li
|
|
v-for="(visDid, idx2) of veriClaimDidsVisible[visibleDidPath]"
|
|
:key="idx2"
|
|
class="list-disc"
|
|
>
|
|
<div class="text-sm mt-2">
|
|
<span>
|
|
{{ didInfo(visDid) }}
|
|
<span v-if="!serverUtil.isEmptyOrHiddenDid(visDid)">
|
|
<button
|
|
@click="
|
|
copyToClipboard('The DID of ' + visDid, visDid)
|
|
"
|
|
>
|
|
<font-awesome
|
|
icon="copy"
|
|
class="text-slate-400 fa-fw"
|
|
/>
|
|
</button>
|
|
</span>
|
|
<span v-if="veriClaim.publicUrls?.[visDid]"
|
|
>, found at
|
|
<font-awesome
|
|
icon="globe"
|
|
class="fa-fw text-slate-400"
|
|
/>
|
|
<a
|
|
:href="veriClaim.publicUrls?.[visDid]"
|
|
class="text-blue-500"
|
|
>{{
|
|
veriClaim.publicUrls[visDid].substring(
|
|
veriClaim.publicUrls[visDid].indexOf("//") + 2,
|
|
)
|
|
}}
|
|
</a>
|
|
</span>
|
|
</span>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Keep the dump contents directly between > and < to avoid weird spacing. -->
|
|
<pre
|
|
class="text-sm overflow-x-scroll px-4 py-3 bg-slate-100 rounded-md"
|
|
>{{ veriClaimDump }}</pre
|
|
>
|
|
<div class="mt-2 ml-2">
|
|
<a
|
|
class="text-blue-500 cursor-pointer"
|
|
@click="showClaimPage(veriClaim.id)"
|
|
>
|
|
<font-awesome icon="file-lines" />
|
|
See All Generic Info
|
|
</a>
|
|
</div>
|
|
<div class="mt-2 ml-2">
|
|
<a
|
|
v-if="isRegistered"
|
|
class="text-blue-500 cursor-pointer"
|
|
:href="urlForNewGive"
|
|
>
|
|
<font-awesome icon="file-lines" />
|
|
Record a Give Similar to the Original
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="!isLoading">This does not have details to confirm.</div>
|
|
|
|
<div
|
|
v-if="isLoading"
|
|
class="fixed left-6 bottom-24 text-center text-4xl leading-none bg-slate-400 text-white w-14 py-2.5 rounded-full"
|
|
>
|
|
<font-awesome icon="spinner" class="fa-spin-pulse"></font-awesome>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { AxiosError } from "axios";
|
|
import * as yaml from "js-yaml";
|
|
import * as R from "ramda";
|
|
import { Component, Vue } from "vue-facing-decorator";
|
|
import { useClipboard } from "@vueuse/core";
|
|
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
|
|
import { GenericVerifiableCredential } from "../interfaces";
|
|
import QuickNav from "../components/QuickNav.vue";
|
|
import { NotificationIface } from "../constants/app";
|
|
import { db, retrieveSettingsForActiveAccount } from "../db/index";
|
|
import { Contact } from "../db/tables/contacts";
|
|
import * as serverUtil from "../libs/endorserServer";
|
|
import { GiveSummaryRecord } from "../interfaces";
|
|
import { displayAmount } from "../libs/endorserServer";
|
|
import * as libsUtil from "../libs/util";
|
|
import { isGiveAction, retrieveAccountDids } from "../libs/util";
|
|
import TopMessage from "../components/TopMessage.vue";
|
|
|
|
@Component({
|
|
components: { TopMessage, QuickNav },
|
|
})
|
|
export default class ConfirmGiftView extends Vue {
|
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
|
$route!: RouteLocationNormalizedLoaded;
|
|
$router!: Router;
|
|
|
|
activeDid = "";
|
|
allMyDids: Array<string> = [];
|
|
allContacts: Array<Contact> = [];
|
|
apiServer = "";
|
|
|
|
canShare = false;
|
|
confirmerIdList: string[] = []; // list of DIDs that have confirmed this claim excluding the issuer
|
|
confsVisibleErrorMessage = "";
|
|
confsVisibleToIdList: string[] = []; // list of DIDs that can see any confirmer
|
|
giveDetails?: GiveSummaryRecord;
|
|
giverName = "";
|
|
issuerName = "";
|
|
isLoading = false;
|
|
isRegistered = false;
|
|
numConfsNotVisible = 0; // number of hidden DIDs in the confirmerIdList, minus the issuer if they aren't visible
|
|
recipientName = "";
|
|
showVeriClaimDump = false;
|
|
urlForNewGive = "";
|
|
veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
|
|
veriClaimDump = "";
|
|
veriClaimDidsVisible: { [key: string]: string[] } = {};
|
|
windowLocation = window.location.href;
|
|
|
|
R = R;
|
|
yaml = yaml;
|
|
libsUtil = libsUtil;
|
|
serverUtil = serverUtil;
|
|
displayAmount = displayAmount;
|
|
|
|
resetThisValues() {
|
|
this.confirmerIdList = [];
|
|
this.confsVisibleErrorMessage = "";
|
|
this.confsVisibleToIdList = [];
|
|
this.giveDetails = undefined;
|
|
this.isRegistered = false;
|
|
this.numConfsNotVisible = 0;
|
|
this.urlForNewGive = "";
|
|
this.veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
|
|
this.veriClaimDump = "";
|
|
}
|
|
|
|
async mounted() {
|
|
this.isLoading = true;
|
|
const settings = await retrieveSettingsForActiveAccount();
|
|
this.activeDid = settings.activeDid || "";
|
|
this.apiServer = settings.apiServer || "";
|
|
this.allContacts = await db.contacts.toArray();
|
|
this.isRegistered = settings.isRegistered || false;
|
|
|
|
this.allMyDids = await retrieveAccountDids();
|
|
|
|
const pathParam = window.location.pathname.substring(
|
|
"/confirm-gift/".length,
|
|
);
|
|
let claimId;
|
|
if (pathParam) {
|
|
claimId = decodeURIComponent(pathParam);
|
|
await this.loadClaim(claimId, this.activeDid);
|
|
} else {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "danger",
|
|
title: "Error",
|
|
text: "No claim ID was provided.",
|
|
},
|
|
3000,
|
|
);
|
|
}
|
|
|
|
// When Chrome compatibility is fixed https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API#api.navigator.canshare
|
|
// then use this truer check: navigator.canShare && navigator.canShare()
|
|
this.canShare = !!navigator.share;
|
|
|
|
this.isLoading = false;
|
|
}
|
|
|
|
// insert a space before any capital letters except the initial letter
|
|
// (and capitalize initial letter, just in case)
|
|
capitalizeAndInsertSpacesBeforeCaps(text: string) {
|
|
return !text
|
|
? ""
|
|
: text[0].toUpperCase() + text.substr(1).replace(/([A-Z])/g, " $1");
|
|
}
|
|
|
|
capitalizeAndInsertSpacesBeforeCapsWithAPrefix(text: string) {
|
|
const word = this.capitalizeAndInsertSpacesBeforeCaps(text);
|
|
if (word) {
|
|
// if the word starts with a vowel, use "an" instead of "a"
|
|
const firstLetter = word[0].toLowerCase();
|
|
const vowels = ["a", "e", "i", "o", "u"];
|
|
const particle = vowels.includes(firstLetter) ? "an" : "a";
|
|
return particle + " " + word;
|
|
} else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
totalConfirmers() {
|
|
return (
|
|
this.numConfsNotVisible +
|
|
this.confirmerIdList.length +
|
|
this.confsVisibleToIdList.length
|
|
);
|
|
}
|
|
|
|
// Isn't there a better way to make this available to the template?
|
|
didInfo(did: string | undefined) {
|
|
return serverUtil.didInfo(
|
|
did,
|
|
this.activeDid,
|
|
this.allMyDids,
|
|
this.allContacts,
|
|
);
|
|
}
|
|
|
|
async loadClaim(claimId: string, userDid: string) {
|
|
const urlPath = libsUtil.isGlobalUri(claimId)
|
|
? "/api/claim/byHandle/"
|
|
: "/api/claim/";
|
|
const url = this.apiServer + urlPath + encodeURIComponent(claimId);
|
|
|
|
try {
|
|
const headers = await serverUtil.getHeaders(userDid);
|
|
const resp = await this.axios.get(url, { headers });
|
|
// resp.data is:
|
|
// - a Jwt from https://api.endorser.ch/api-docs/
|
|
// - with a Give from https://endorser.ch/doc/html/transactions.html#id3
|
|
if (resp.status === 200) {
|
|
this.veriClaim = resp.data;
|
|
this.veriClaimDump = yaml.dump(this.veriClaim);
|
|
this.veriClaimDidsVisible = libsUtil.findAllVisibleToDids(
|
|
this.veriClaim,
|
|
true,
|
|
);
|
|
} else {
|
|
// actually, axios typically throws an error so we never get here
|
|
console.error("Error getting claim:", resp);
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "danger",
|
|
title: "Error",
|
|
text: "There was a problem retrieving that claim.",
|
|
},
|
|
3000,
|
|
);
|
|
return;
|
|
}
|
|
|
|
// retrieve more details on Give, Offer, or Plan
|
|
if (this.veriClaim.claimType !== "GiveAction") {
|
|
// no need to go further... this page is for gifts
|
|
return;
|
|
}
|
|
|
|
this.issuerName = this.didInfo(this.veriClaim.issuer);
|
|
|
|
// use give record when possible since it may include edits
|
|
const giveUrl =
|
|
this.apiServer +
|
|
"/api/v2/report/gives?handleId=" +
|
|
encodeURIComponent(this.veriClaim.handleId as string);
|
|
const giveHeaders = await serverUtil.getHeaders(userDid);
|
|
const giveResp = await this.axios.get(giveUrl, {
|
|
headers: giveHeaders,
|
|
});
|
|
// giveResp.data is a Give from https://api.endorser.ch/api-docs/
|
|
if (giveResp.status === 200) {
|
|
this.giveDetails = giveResp.data.data[0];
|
|
} else {
|
|
console.error("Error getting detailed give info:", giveResp);
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "danger",
|
|
title: "Error",
|
|
text: "Something went wrong retrieving gift data.",
|
|
},
|
|
3000,
|
|
);
|
|
return;
|
|
}
|
|
|
|
// the logic already stops earlier if the claim doesn't exist but this helps with typechecking
|
|
if (!this.giveDetails) {
|
|
return;
|
|
}
|
|
|
|
this.urlForNewGive = "/gifted-details?";
|
|
if (this.giveDetails.amount) {
|
|
this.urlForNewGive +=
|
|
"&amountInput=" + encodeURIComponent(String(this.giveDetails.amount));
|
|
}
|
|
if (this.giveDetails.unit) {
|
|
this.urlForNewGive +=
|
|
"&unitCode=" + encodeURIComponent(this.giveDetails.unit);
|
|
}
|
|
if (this.giveDetails.description) {
|
|
this.urlForNewGive +=
|
|
"&description=" + encodeURIComponent(this.giveDetails.description);
|
|
}
|
|
this.giverName = this.didInfo(this.giveDetails.agentDid);
|
|
if (this.giveDetails.agentDid) {
|
|
this.urlForNewGive +=
|
|
"&giverDid=" +
|
|
encodeURIComponent(this.giveDetails.agentDid) +
|
|
"&giverName=" +
|
|
encodeURIComponent(this.giverName);
|
|
}
|
|
this.recipientName = this.didInfo(this.giveDetails.recipientDid);
|
|
if (this.giveDetails.recipientDid) {
|
|
this.urlForNewGive +=
|
|
"&recipientDid=" +
|
|
encodeURIComponent(this.giveDetails.recipientDid) +
|
|
"&recipientName=" +
|
|
encodeURIComponent(this.recipientName);
|
|
}
|
|
if (this.giveDetails.fullClaim.image) {
|
|
this.urlForNewGive +=
|
|
"&image=" + encodeURIComponent(this.giveDetails.fullClaim.image);
|
|
}
|
|
if (
|
|
this.giveDetails.type == "Offer" &&
|
|
this.giveDetails.fulfillsHandleId
|
|
) {
|
|
this.urlForNewGive +=
|
|
"&offerId=" +
|
|
encodeURIComponent(this.giveDetails?.fulfillsHandleId as string);
|
|
}
|
|
if (this.giveDetails.fulfillsPlanHandleId) {
|
|
this.urlForNewGive +=
|
|
"&fulfillsProjectId=" +
|
|
encodeURIComponent(this.giveDetails.fulfillsPlanHandleId);
|
|
}
|
|
|
|
// retrieve the list of confirmers
|
|
const confirmerInfo = await libsUtil.retrieveConfirmerIdList(
|
|
this.apiServer,
|
|
claimId,
|
|
this.veriClaim.issuer,
|
|
userDid,
|
|
);
|
|
if (confirmerInfo) {
|
|
this.confirmerIdList = confirmerInfo.confirmerIdList;
|
|
this.confsVisibleToIdList = confirmerInfo.confsVisibleToIdList;
|
|
this.numConfsNotVisible = confirmerInfo.numConfsNotVisible;
|
|
} else {
|
|
this.confsVisibleErrorMessage =
|
|
"Had problems retrieving confirmations.";
|
|
}
|
|
} catch (error: unknown) {
|
|
const serverError = error as AxiosError;
|
|
console.error("Error retrieving claim:", serverError);
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "danger",
|
|
title: "Error",
|
|
text: "Something went wrong retrieving claim data.",
|
|
},
|
|
3000,
|
|
);
|
|
}
|
|
}
|
|
|
|
confirmConfirmClaim() {
|
|
this.$notify(
|
|
{
|
|
group: "modal",
|
|
type: "confirm",
|
|
title: "Confirm",
|
|
text: "Do you personally confirm that this is true?",
|
|
onYes: async () => {
|
|
await this.confirmClaim();
|
|
},
|
|
},
|
|
-1,
|
|
);
|
|
}
|
|
|
|
// similar code is found in ProjectViewView
|
|
async confirmClaim() {
|
|
// similar logic is found in endorser-mobile
|
|
const goodClaim = serverUtil.removeSchemaContext(
|
|
serverUtil.removeVisibleToDids(
|
|
serverUtil.addLastClaimOrHandleAsIdIfMissing(
|
|
this.veriClaim.claim,
|
|
this.veriClaim.id,
|
|
this.veriClaim.handleId,
|
|
),
|
|
),
|
|
);
|
|
const confirmationClaim: GenericVerifiableCredential = {
|
|
"@context": "https://schema.org",
|
|
"@type": "AgreeAction",
|
|
object: goodClaim,
|
|
};
|
|
const result = await serverUtil.createAndSubmitClaim(
|
|
confirmationClaim,
|
|
this.activeDid,
|
|
this.apiServer,
|
|
this.axios,
|
|
);
|
|
if (result.type === "success") {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "success",
|
|
title: "Success",
|
|
text: "Confirmation submitted.",
|
|
},
|
|
3000,
|
|
);
|
|
} else {
|
|
console.error("Got error submitting the confirmation:", result);
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "danger",
|
|
title: "Error",
|
|
text: "There was a problem submitting the confirmation.",
|
|
},
|
|
5000,
|
|
);
|
|
}
|
|
}
|
|
|
|
showClaimPage(claimId: string) {
|
|
const route = {
|
|
path: "/claim/" + encodeURIComponent(claimId),
|
|
};
|
|
(this.$router as Router).push(route).then(async () => {
|
|
this.resetThisValues();
|
|
await this.loadClaim(claimId, this.activeDid);
|
|
});
|
|
}
|
|
|
|
copyToClipboard(name: string, text: string) {
|
|
useClipboard()
|
|
.copy(text)
|
|
.then(() => {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "toast",
|
|
title: "Copied",
|
|
text: (name || "That") + " was copied to the clipboard.",
|
|
},
|
|
2000,
|
|
);
|
|
});
|
|
}
|
|
|
|
notifyWhyCannotConfirm() {
|
|
libsUtil.notifyWhyCannotConfirm(
|
|
this.$notify,
|
|
this.isRegistered,
|
|
this.veriClaim.claimType,
|
|
this.giveDetails,
|
|
this.activeDid,
|
|
this.confirmerIdList,
|
|
);
|
|
}
|
|
|
|
notifyWhyCannotConfirmBak() {
|
|
if (!this.isRegistered) {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "info",
|
|
title: "Not Registered",
|
|
text: "Someone needs to register you before you can contribute.",
|
|
},
|
|
3000,
|
|
);
|
|
} else if (!isGiveAction(this.veriClaim)) {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "info",
|
|
title: "Not A Give",
|
|
text: "This is not a giving action to confirm.",
|
|
},
|
|
3000,
|
|
);
|
|
} else if (this.confirmerIdList.includes(this.activeDid)) {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "info",
|
|
title: "Already Confirmed",
|
|
text: "You already confirmed this claim.",
|
|
},
|
|
3000,
|
|
);
|
|
} else if (this.giveDetails?.issuerDid == this.activeDid) {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "info",
|
|
title: "Cannot Confirm",
|
|
text: "You cannot confirm this because you issued this claim.",
|
|
},
|
|
3000,
|
|
);
|
|
} else if (serverUtil.containsHiddenDid(this.giveDetails?.fullClaim)) {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "info",
|
|
title: "Cannot Confirm",
|
|
text: "You cannot confirm this because some people are hidden.",
|
|
},
|
|
3000,
|
|
);
|
|
} else {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "info",
|
|
title: "Cannot Confirm",
|
|
text: "You cannot confirm this claim. There are no other details, but we can help more if you contact us and send us screenshots.",
|
|
},
|
|
3000,
|
|
);
|
|
}
|
|
}
|
|
|
|
onClickShareClaim() {
|
|
this.copyToClipboard("A link to this page", this.windowLocation);
|
|
window.navigator.share({
|
|
title: "Help Connect Me",
|
|
text: "I'm trying to find the full details of this claim. Can you help me?",
|
|
url: this.windowLocation,
|
|
});
|
|
}
|
|
}
|
|
</script>
|