Browse Source

refactor project screen: add action to record a give from it, and add checks to give confirmation buttons

split_build_process
Trent Larson 2 months ago
parent
commit
10bb79f695
  1. 10
      src/components/GiftedDialog.vue
  2. 153
      src/libs/util.ts
  3. 54
      src/views/ClaimView.vue
  4. 51
      src/views/ConfirmGiftView.vue
  5. 2
      src/views/ContactGiftingView.vue
  6. 2
      src/views/GiftedDetailsView.vue
  7. 2
      src/views/OfferDetailsView.vue
  8. 254
      src/views/ProjectViewView.vue

10
src/components/GiftedDialog.vue

@ -47,7 +47,8 @@
giverDid: giver?.did,
giverName: giver?.name,
offerId,
fulfillsProjectId: projectId,
fulfillsProjectId: toProjectId,
providerProjectId: fromProjectId,
recipientDid: receiver?.did,
recipientName: receiver?.name,
unitCode,
@ -98,7 +99,8 @@ import { Contact } from "@/db/tables/contacts";
export default class GiftedDialog extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
@Prop projectId = "";
@Prop fromProjectId = "";
@Prop toProjectId = "";
activeDid = "";
allContacts: Array<Contact> = [];
@ -294,9 +296,11 @@ export default class GiftedDialog extends Vue {
description,
amount,
unitCode,
this.projectId,
this.toProjectId,
this.offerId,
this.isTrade,
undefined,
this.fromProjectId,
);
if (

153
src/libs/util.ts

@ -5,7 +5,7 @@ import { Buffer } from "buffer";
import * as R from "ramda";
import { useClipboard } from "@vueuse/core";
import { DEFAULT_PUSH_SERVER } from "@/constants/app";
import { DEFAULT_PUSH_SERVER, NotificationIface } from "@/constants/app";
import {
accountsDB,
retrieveSettingsForActiveAccount,
@ -21,6 +21,7 @@ import {
containsHiddenDid,
GenericCredWrapper,
GenericVerifiableCredential,
GiveSummaryRecord,
OfferVerifiableCredential,
} from "@/libs/endorserServer";
import { KeyMeta } from "@/libs/crypto/vc";
@ -101,10 +102,14 @@ export const isGlobalUri = (uri: string) => {
return uri && uri.match(new RegExp(/^[A-Za-z][A-Za-z0-9+.-]+:/));
};
export const isGiveClaimType = (claimType?: string) => {
return claimType === "GiveAction";
};
export const isGiveAction = (
veriClaim: GenericCredWrapper<GenericVerifiableCredential>,
) => {
return veriClaim.claimType === "GiveAction";
return isGiveClaimType(veriClaim.claimType);
};
export const nameForDid = (
@ -136,16 +141,75 @@ export const doCopyTwoSecRedo = (text: string, fn: () => void) => {
.then(() => setTimeout(fn, 2000));
};
export interface ConfirmerData {
confirmerIdList: string[];
confsVisibleToIdList: string[];
numConfsNotVisible: number;
}
/**
* @return only confirmers, excluding the issuer and hidden DIDs
*/
export async function retrieveConfirmerIdList(
apiServer: string,
claimId: string,
claimIssuerId: string,
userDid: string,
): Promise<ConfirmerData | undefined> {
const confirmUrl =
apiServer +
"/api/report/issuersWhoClaimedOrConfirmed?claimId=" +
encodeURIComponent(serverUtil.stripEndorserPrefix(claimId));
const confirmHeaders = await serverUtil.getHeaders(userDid);
const response = await axios.get(confirmUrl, {
headers: confirmHeaders,
});
if (response.status === 200) {
const resultList1 = response.data.result || [];
//const publicUrls = resultList.publicUrls || [];
delete resultList1.publicUrls;
// exclude hidden DIDs
const resultList2 = R.reject(serverUtil.isHiddenDid, resultList1);
// exclude the issuer
const resultList3 = R.reject(
(did: string) => did === claimIssuerId,
resultList2,
);
const confirmerIdList = resultList3;
let numConfsNotVisible = resultList1.length - resultList2.length;
if (resultList3.length === resultList2.length) {
// the issuer was not in the "visible" list so they must be hidden
// so subtract them from the non-visible confirmers count
numConfsNotVisible = numConfsNotVisible - 1;
}
const confsVisibleToIdList = response.data.result.resultVisibleToDids || [];
const result: ConfirmerData = {
confirmerIdList,
confsVisibleToIdList,
numConfsNotVisible,
};
return result;
} else {
console.error(
"Bad response status of",
response.status,
"for confirmers:",
response,
);
return undefined;
}
}
/**
* @returns true if the user can confirm the claim
* @param veriClaim is expected to have fields: claim, claimType, and issuer
*/
export const isGiveRecordTheUserCanConfirm = (
export function isGiveRecordTheUserCanConfirm(
isRegistered: boolean,
veriClaim: GenericCredWrapper<GenericVerifiableCredential>,
activeDid: string,
confirmerIdList: string[] = [],
) => {
): boolean {
return (
isRegistered &&
isGiveAction(veriClaim) &&
@ -153,7 +217,78 @@ export const isGiveRecordTheUserCanConfirm = (
veriClaim.issuer !== activeDid &&
!containsHiddenDid(veriClaim.claim)
);
};
}
export function notifyWhyCannotConfirm(
notifyFun: (notification: NotificationIface, timeout: number) => void,
isRegistered: boolean,
claimType: string | undefined,
giveDetails: GiveSummaryRecord | undefined,
activeDid: string,
confirmerIdList: string[] = [],
) {
if (!isRegistered) {
notifyFun(
{
group: "alert",
type: "info",
title: "Not Registered",
text: "Someone needs to register you before you can confirm.",
},
3000,
);
} else if (!isGiveClaimType(claimType)) {
notifyFun(
{
group: "alert",
type: "info",
title: "Not A Give",
text: "This is not a giving action to confirm.",
},
3000,
);
} else if (confirmerIdList.includes(activeDid)) {
notifyFun(
{
group: "alert",
type: "info",
title: "Already Confirmed",
text: "You already confirmed this claim.",
},
3000,
);
} else if (giveDetails?.issuerDid == activeDid) {
notifyFun(
{
group: "alert",
type: "info",
title: "Cannot Confirm",
text: "You cannot confirm this because you issued this claim.",
},
3000,
);
} else if (serverUtil.containsHiddenDid(giveDetails?.fullClaim)) {
notifyFun(
{
group: "alert",
type: "info",
title: "Cannot Confirm",
text: "You cannot confirm this because some people are hidden.",
},
3000,
);
} else {
notifyFun(
{
group: "alert",
type: "info",
title: "Cannot Confirm",
text: "You cannot confirm this claim. There are no other details -- we can help more if you contact us and send us screenshots.",
},
3000,
);
}
}
export async function blobToBase64(blob: Blob): Promise<string> {
return new Promise((resolve, reject) => {
@ -191,9 +326,9 @@ export function base64ToBlob(base64DataUrl: string, sliceSize = 512) {
* @returns the DID of the person who offered, or undefined if hidden
* @param veriClaim is expected to have fields: claim and issuer
*/
export const offerGiverDid: (
arg0: GenericCredWrapper<OfferVerifiableCredential>,
) => string | undefined = (veriClaim) => {
export function offerGiverDid(
veriClaim: GenericCredWrapper<OfferVerifiableCredential>,
): string | undefined {
let giver;
if (
veriClaim.claim.offeredBy?.identifier &&
@ -204,7 +339,7 @@ export const offerGiverDid: (
giver = veriClaim.issuer;
}
return giver;
};
}
/**
* @returns true if the user can fulfill the offer

54
src/views/ClaimView.vue

@ -24,9 +24,11 @@
{{ capitalizeAndInsertSpacesBeforeCaps(veriClaim.claimType) }}
<button
v-if="
['GiveAction', 'Offer'].includes(
['GiveAction', 'Offer', 'PlanAction'].includes(
veriClaim.claimType as string,
) && veriClaim.issuer === activeDid
// a PlanAction agent also could edit one of those, but rather than add more Plan-specific logic to detect the agent
// we'll let them click the Project link and edit from there
"
@click="onClickEditClaim"
title="Edit"
@ -150,6 +152,10 @@
</div>
</div>
</div>
<div class="mt-2">
<fa icon="comment" class="text-slate-400" />
{{ issuerName }} posted that.
</div>
<div class="mt-8">
<button
@ -217,7 +223,7 @@
Nobody that you know has issued or confirmed this claim.
</div>
<div v-if="confirmerIdList.length > 0">
The following people have issued or confirmed this claim.
The following people have confirmed this claim.
<ul class="ml-4">
<li
v-for="confirmerId in confirmerIdList"
@ -503,6 +509,7 @@ export default class ClaimView extends Vue {
fullClaimMessage = "";
isEditedGlobalId = false;
isRegistered = false;
issuerName = "";
numConfsNotVisible = 0; // number of hidden DIDs in the confirmerIdList, minus the issuer if they aren't visible
providersForGive: ProviderInfo[] = [];
showIdCopy = false;
@ -545,6 +552,7 @@ export default class ClaimView extends Vue {
const accounts = accountsDB.accounts;
const accountsArr: Array<Account> = await accounts?.toArray();
this.allMyDids = accountsArr.map((acc) => acc.did);
this.issuerName = this.didInfo(this.veriClaim.issuer);
const pathParam = window.location.pathname.substring("/claim/".length);
let claimId;
@ -696,32 +704,16 @@ export default class ClaimView extends Vue {
}
// retrieve the list of confirmers
const confirmUrl =
this.apiServer +
"/api/report/issuersWhoClaimedOrConfirmed?claimId=" +
encodeURIComponent(serverUtil.stripEndorserPrefix(claimId));
const confirmHeaders = await serverUtil.getHeaders(userDid);
const response = await this.axios.get(confirmUrl, {
headers: confirmHeaders,
});
if (response.status === 200) {
const resultList1 = response.data.result || [];
//const publicUrls = resultList.publicUrls || [];
delete resultList1.publicUrls;
const resultList2 = R.reject(serverUtil.isHiddenDid, resultList1);
const resultList3 = R.reject(
(did: string) => did === this.veriClaim.issuer,
resultList2,
const confirmerInfo = await libsUtil.retrieveConfirmerIdList(
this.apiServer,
claimId,
this.veriClaim.issuer,
userDid,
);
this.confirmerIdList = resultList3;
this.numConfsNotVisible = resultList1.length - resultList2.length;
if (resultList3.length === resultList2.length) {
// the issuer was not in the "visible" list so they must be hidden
// so subtract them from the non-visible confirmers count
this.numConfsNotVisible = this.numConfsNotVisible - 1;
}
this.confsVisibleToIdList =
response.data.result.resultVisibleToDids || [];
if (confirmerInfo) {
this.confirmerIdList = confirmerInfo.confirmerIdList;
this.confsVisibleToIdList = confirmerInfo.confsVisibleToIdList;
this.numConfsNotVisible = confirmerInfo.numConfsNotVisible;
} else {
this.confsVisibleErrorMessage =
"Had problems retrieving confirmations.";
@ -736,7 +728,7 @@ export default class ClaimView extends Vue {
title: "Error",
text: "Something went wrong retrieving claim data.",
},
-1,
3000,
);
}
}
@ -921,6 +913,12 @@ export default class ClaimView extends Vue {
},
};
(this.$router as Router).push(route);
} else if (this.veriClaim.claimType === "PlanAction") {
const route = {
name: "new-edit-project",
query: { projectId: this.veriClaim.handleId },
};
(this.$router as Router).push(route);
} else {
console.error(
"Unrecognized claim type for edit:",

51
src/views/ConfirmGiftView.vue

@ -172,7 +172,7 @@
Nobody that you know issued or confirmed this claim.
</div>
<div v-if="confirmerIdList.length > 0">
The following people issued or confirmed this claim.
The following people confirmed this claim.
<ul class="ml-4">
<li
v-for="confirmerId in confirmerIdList"
@ -661,34 +661,16 @@ export default class ClaimView extends Vue {
}
// retrieve the list of confirmers
const confirmUrl =
this.apiServer +
"/api/report/issuersWhoClaimedOrConfirmed?claimId=" +
encodeURIComponent(serverUtil.stripEndorserPrefix(claimId));
const confirmHeaders = await serverUtil.getHeaders(userDid);
const response = await this.axios.get(confirmUrl, {
headers: confirmHeaders,
});
if (response.status === 200) {
const resultList1 = response.data.result || [];
//const publicUrls = resultList.publicUrls || [];
delete resultList1.publicUrls;
// remove any hidden DIDs
const resultList2 = R.reject(serverUtil.isHiddenDid, resultList1);
// remove confirmations by this user
const resultList3 = R.reject(
(did: string) => did === this.giveDetails?.issuerDid,
resultList2,
const confirmerInfo = await libsUtil.retrieveConfirmerIdList(
this.apiServer,
claimId,
this.veriClaim.issuer,
userDid,
);
this.confirmerIdList = resultList3;
this.numConfsNotVisible = resultList1.length - resultList2.length;
if (resultList3.length === resultList2.length) {
// the issuer was not in the "visible" list so they must be hidden
// so subtract them from the non-visible confirmers count
this.numConfsNotVisible = this.numConfsNotVisible - 1;
}
this.confsVisibleToIdList =
response.data.result.resultVisibleToDids || [];
if (confirmerInfo) {
this.confirmerIdList = confirmerInfo.confirmerIdList;
this.confsVisibleToIdList = confirmerInfo.confsVisibleToIdList;
this.numConfsNotVisible = confirmerInfo.numConfsNotVisible;
} else {
this.confsVisibleErrorMessage =
"Had problems retrieving confirmations.";
@ -797,6 +779,17 @@ export default class ClaimView extends Vue {
}
notifyWhyCannotConfirm() {
libsUtil.notifyWhyCannotConfirm(
this.$notify,
this.isRegistered,
this.veriClaim.claimType,
this.giveDetails,
this.activeDid,
this.confirmerIdList,
);
}
notifyWhyCannotConfirmBak() {
if (!this.isRegistered) {
this.$notify(
{
@ -853,7 +846,7 @@ export default class ClaimView extends Vue {
group: "alert",
type: "info",
title: "Cannot Confirm",
text: "You cannot confirm this claim.",
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,
);

2
src/views/ContactGiftingView.vue

@ -65,7 +65,7 @@
</li>
</ul>
<GiftedDialog ref="customDialog" :projectId="projectId" />
<GiftedDialog ref="customDialog" :toProjectId="projectId" />
</section>
</template>

2
src/views/GiftedDetailsView.vue

@ -39,7 +39,7 @@
? fulfillsProjectName
: givenToRecipient
? recipientName
: "someone unidentified"
: "someone not named"
}}</span
>
</h1>

2
src/views/OfferDetailsView.vue

@ -28,7 +28,7 @@
? projectName
: offeredToRecipient
? recipientName
: "someone unidentified"
: "someone not named"
}}</span
>
</h1>

254
src/views/ProjectViewView.vue

@ -15,7 +15,17 @@
<fa icon="chevron-left" class="fa-fw"></fa>
</button>
Idea
<h2 class="text-xl font-semibold">{{ name }}</h2>
<h2 class="text-xl font-semibold">
{{ name }}
<button
v-if="activeDid === issuer || activeDid === agentDid"
@click="onEditClick()"
title="Edit"
data-testId="editClaimButton"
>
<fa icon="pen" class="text-sm text-blue-500 ml-2 mb-1" />
</button>
</h2>
</h1>
</div>
@ -104,15 +114,6 @@
<fa icon="file-lines" class="pl-2 pt-1 text-blue-500" />
</a>
</div>
<button
v-if="activeDid === issuer || activeDid === agentDid"
type="button"
class="block w-full text-center text-md uppercase 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-1.5 py-2 rounded-md"
@click="onEditClick()"
>
Edit
</button>
</div>
<div class="grid items-start grid-cols-1 sm:grid-cols-2 gap-4 mt-4">
@ -159,31 +160,14 @@
</div>
</div>
<div v-if="activeDid && isRegistered" class="mt-4">
<div class="text-center">
<button
data-testId="offerButton"
@click="openOfferDialog()"
class="block w-full text-lg font-bold 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-2 py-3 rounded-md"
>
Offer (maybe with conditions)...
</button>
</div>
</div>
<OfferDialog
ref="customOfferDialog"
:projectId="this.projectId"
:projectName="this.name"
/>
<div v-if="activeDid && isRegistered">
<div class="text-center">
<p class="mt-2 mt-4 text-center">Record a contribution from:</p>
</div>
<ul
class="grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-x-3 gap-y-5 text-center mb-5"
class="grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-x-3 gap-y-5 text-center mb-5 mt-2"
>
<li @click="openGiftDialog({ name: 'you', did: activeDid })">
<li @click="openGiftDialogToProject({ name: 'you', did: activeDid })">
<fa icon="hand" class="fa-fw text-blue-500 text-5xl cursor-pointer" />
<h3
class="mt-5 text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer"
@ -191,7 +175,7 @@
You
</h3>
</li>
<li @click="openGiftDialog()">
<li @click="openGiftDialogToProject()">
<img
src="../assets/blank-square.svg"
class="mx-auto border border-blue-300 rounded-md mb-1 cursor-pointer"
@ -203,9 +187,9 @@
</h3>
</li>
<li
v-for="contact in allContacts.slice(0, 6)"
v-for="contact in allContacts.slice(0, 5)"
:key="contact.did"
@click="openGiftDialog(contact)"
@click="openGiftDialogToProject(contact)"
>
<EntityIcon
:contact="contact"
@ -218,27 +202,41 @@
{{ contact.name || "(no name)" }}
</h3>
</li>
</ul>
<!--
Ideally, this button should only be visible when the active account has more than 7 or 11 contacts in their list
(we want to limit the grid count above to 8 or 12 accounts to keep it compact)
-->
<a
v-if="allContacts.length >= 7"
<li>
<span
v-if="allContacts.length >= 5"
@click="onClickAllContactsGifting()"
class="block text-center text-md font-bold 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-2 py-3 rounded-md"
class="flex align-bottom text-xs text-blue-500 mt-12 cursor-pointer"
>
Show More Contacts&hellip;
</a>
<GiftedDialog ref="customGiveDialog" :projectId="this.projectId" />
... or someone else...
</span>
</li>
</ul>
<GiftedDialog ref="giveDialogToThis" :toProjectId="this.projectId" />
</div>
<!-- Offers & Gifts to & from this -->
<div class="grid items-start grid-cols-1 sm:grid-cols-3 gap-4 mt-4">
<!-- First, offers on the left-->
<div class="bg-slate-100 px-4 py-3 rounded-md">
<h3 class="text-sm font-semibold mb-3">Offered To This Idea</h3>
<div v-if="activeDid && isRegistered">
<div class="text-center">
<button
data-testId="offerButton"
@click="openOfferDialog()"
class="block w-full bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white rounded-md"
>
Offer (maybe with conditions)...
</button>
</div>
</div>
<OfferDialog
ref="customOfferDialog"
:projectId="this.projectId"
:projectName="this.name"
/>
<h3 class="text-lg font-bold mb-3 mt-4">Offered To This Idea</h3>
<div v-if="offersToThis.length === 0">
(None yet. Wanna
@ -300,15 +298,27 @@
</div>
</div>
<!-- Now, gives TO this project in the middle -->
<!-- (similar to "FROM" gift display below) -->
<div class="bg-slate-100 px-4 py-3 rounded-md">
<h3 class="text-sm font-semibold mb-3">Given To This Idea</h3>
<div v-if="activeDid && isRegistered">
<div class="text-center">
<button
@click="openGiftDialogToProject()"
class="block w-full bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white rounded-md"
>
Given To This...
</button>
</div>
</div>
<h3 class="text-lg font-bold mb-3 mt-4">Given To This Idea</h3>
<div v-if="givesToThis.length === 0">
(None yet. If you've seen something, say something by clicking a
contact above.)
</div>
<!-- similar to gift display below -->
<ul v-else class="text-sm border-t border-slate-300">
<li
v-for="give in givesToThis"
@ -346,12 +356,22 @@
<a @click="onClickLoadClaim(give.jwtId)">
<fa icon="file-lines" class="text-blue-500 cursor-pointer" />
</a>
<a
v-if="checkIsConfirmable(give)"
@click="confirmConfirmClaim(give)"
v-if="
checkIsConfirmable(give) &&
!recentlyCheckedAndUnconfirmableJwts.includes(give.jwtId)
"
@click="deepCheckConfirmable(give)"
>
<fa icon="circle-check" class="text-blue-500 cursor-pointer" />
</a>
<a v-else-if="checkingConfirmationForJwtId === give.jwtId">
<fa icon="spinner" class="fa-spin-pulse" />
</a>
<a v-else @click="shallowNotifyWhyCannotConfirm(give)">
<fa icon="circle-check" class="text-slate-500 cursor-pointer" />
</a>
</div>
<div v-if="give.fullClaim.image" class="flex justify-center">
<a :href="give.fullClaim.image" target="_blank">
@ -365,17 +385,29 @@
</div>
</div>
<div class="grid items-start grid-cols-1 gap-4">
<div
v-if="givesProvidedByThis.length > 0"
class="bg-slate-100 px-4 py-3 rounded-md"
<!-- Finally, gives FROM this project on the right -->
<!-- (similar to "TO" gift display above) -->
<div class="bg-slate-100 px-4 py-3 rounded-md">
<div v-if="activeDid && isRegistered">
<div class="text-center">
<button
@click="openGiftDialogFromProject()"
class="block w-full bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white rounded-md"
>
<div>
<h3 class="text-sm font-semibold border-b">
Individuals Getting Contributions From This
</h3>
<!-- similar to gift display above -->
<ul class="text-sm border-t border-slate-300">
Given By This...
</button>
</div>
</div>
<GiftedDialog
ref="giveDialogFromThis"
:fromProjectId="this.projectId"
/>
<h3 class="text-lg font-bold mb-3 mt-4">Benefitted By This</h3>
<div v-if="givesProvidedByThis.length === 0">(None yet.)</div>
<ul v-else class="text-sm border-t border-slate-300">
<li
v-for="give in givesProvidedByThis"
:key="give.id"
@ -407,9 +439,32 @@
<fa icon="comment" class="fa-fw text-slate-400" />
{{ give.description }}
</div>
<div class="flex justify-between">
<a @click="onClickLoadClaim(give.jwtId)">
<fa icon="file-lines" class="text-blue-500 cursor-pointer" />
</a>
<a
v-if="
checkIsConfirmable(give) &&
!recentlyCheckedAndUnconfirmableJwts.includes(give.jwtId)
"
@click="deepCheckConfirmable(give)"
>
<fa icon="circle-check" class="text-blue-500 cursor-pointer" />
</a>
<a v-else-if="checkingConfirmationForJwtId === give.jwtId">
<fa icon="spinner" class="fa-spin-pulse" />
</a>
<a v-else @click="shallowNotifyWhyCannotConfirm(give)">
<fa icon="circle-check" class="text-slate-500 cursor-pointer" />
</a>
</div>
<div v-if="give.fullClaim.image" class="flex justify-center">
<a :href="give.fullClaim.image" target="_blank">
<img :src="give.fullClaim.image" class="h-24 mt-2 rounded-xl" />
</a>
</div>
</li>
</ul>
<div v-if="givesProvidedByHitLimit" class="text-center">
@ -417,8 +472,6 @@
</div>
</div>
</div>
</div>
</div>
</section>
</template>
@ -468,6 +521,7 @@ export default class ProjectViewView extends Vue {
allMyDids: Array<string> = [];
allContacts: Array<Contact> = [];
apiServer = "";
checkingConfirmationForJwtId = "";
description = "";
expanded = false;
fulfilledByThis: PlanSummaryRecord | null = null;
@ -486,6 +540,7 @@ export default class ProjectViewView extends Vue {
offersToThis: Array<OfferSummaryRecord> = [];
offersHitLimit = false;
projectId = ""; // handle ID
recentlyCheckedAndUnconfirmableJwts = [];
showDidCopy = false;
startTime = "";
truncatedDesc = "";
@ -847,12 +902,21 @@ export default class ProjectViewView extends Vue {
);
}
openGiftDialog(contact?: libsUtil.GiverReceiverInputInfo) {
(this.$refs.customGiveDialog as GiftedDialog).open(
openGiftDialogToProject(contact?: libsUtil.GiverReceiverInputInfo) {
(this.$refs.giveDialogToThis as GiftedDialog).open(
contact,
undefined,
undefined,
"Given by " + (contact?.name || "someone not named"),
(contact?.name || "Someone not named") + ` gave to this project`,
);
}
openGiftDialogFromProject() {
(this.$refs.giveDialogFromThis as GiftedDialog).open(
undefined,
{ did: this.activeDid, name: "You" },
undefined,
`This project gave to you`,
);
}
@ -896,7 +960,7 @@ export default class ProjectViewView extends Vue {
const giver: libsUtil.GiverReceiverInputInfo = {
did: libsUtil.offerGiverDid(offerRecord),
};
(this.$refs.customGiveDialog as GiftedDialog).open(
(this.$refs.giveDialogToThis as GiftedDialog).open(
giver,
undefined,
offer.handleId,
@ -932,20 +996,70 @@ export default class ProjectViewView extends Vue {
}
}
checkIsConfirmable(give: GiveSummaryRecord) {
/**
* @param confirmerIdList optional list of DIDs who confirmed; if missing, doesn't do a full server check
*/
checkIsConfirmable(give: GiveSummaryRecord, confirmerIdList?: string[]) {
const giveDetails: GenericCredWrapper<GiveVerifiableCredential> = {
...BLANK_GENERIC_SERVER_RECORD,
claim: give.fullClaim,
claimType: "GiveAction",
issuer: give.agentDid,
issuer: give.issuerDid,
};
return libsUtil.isGiveRecordTheUserCanConfirm(
this.isRegistered,
giveDetails,
this.activeDid,
confirmerIdList,
);
}
shallowNotifyWhyCannotConfirm(give: GiveSummaryRecord) {
const confirmerIds = this.recentlyCheckedAndUnconfirmableJwts.includes(
give.jwtId,
)
? [this.activeDid]
: [];
libsUtil.notifyWhyCannotConfirm(
this.$notify,
this.isRegistered,
"GiveAction",
give,
this.activeDid,
confirmerIds,
);
}
async deepCheckConfirmable(give: GiveSummaryRecord) {
this.checkingConfirmationForJwtId = give.jwtId;
const confirmerInfo: libsUtil.ConfirmerData | undefined =
await libsUtil.retrieveConfirmerIdList(
this.apiServer,
give.jwtId,
give.issuerDid,
this.activeDid,
);
if (
this.checkIsConfirmable(give, confirmerInfo?.confirmerIdList as string[])
) {
this.confirmConfirmClaim(give);
} else {
this.recentlyCheckedAndUnconfirmableJwts = [
...this.recentlyCheckedAndUnconfirmableJwts,
give.jwtId,
];
libsUtil.notifyWhyCannotConfirm(
this.$notify,
this.isRegistered,
"GiveAction",
give,
this.activeDid,
confirmerInfo?.confirmerIdList as string[],
);
}
this.checkingConfirmationForJwtId = "";
}
confirmConfirmClaim(give: GiveSummaryRecord) {
this.$notify(
{
@ -994,6 +1108,10 @@ export default class ProjectViewView extends Vue {
},
5000,
);
this.recentlyCheckedAndUnconfirmableJwts = [
...this.recentlyCheckedAndUnconfirmableJwts,
give.jwtId,
];
} else {
console.error("Got error submitting the confirmation:", result);
const message =

Loading…
Cancel
Save