forked from jsnbuchanan/crowd-funder-for-time-pwa
for BVC: finish submission of confirmations & final give
This commit is contained in:
@@ -22,7 +22,7 @@ export interface AgreeVerifiableCredential {
|
|||||||
"@type": string;
|
"@type": string;
|
||||||
// "any" because arbitrary objects can be subject of agreement
|
// "any" because arbitrary objects can be subject of agreement
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
object: Record<any, any>;
|
object: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GiverInputInfo {
|
export interface GiverInputInfo {
|
||||||
@@ -46,6 +46,7 @@ export interface ClaimResult {
|
|||||||
export interface GenericVerifiableCredential {
|
export interface GenericVerifiableCredential {
|
||||||
"@context": string;
|
"@context": string;
|
||||||
"@type": string;
|
"@type": string;
|
||||||
|
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GenericServerRecord extends GenericVerifiableCredential {
|
export interface GenericServerRecord extends GenericVerifiableCredential {
|
||||||
@@ -54,7 +55,7 @@ export interface GenericServerRecord extends GenericVerifiableCredential {
|
|||||||
issuedAt: string;
|
issuedAt: string;
|
||||||
issuer: string;
|
issuer: string;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
claim: Record<any, any>;
|
claim: Record<string, any>;
|
||||||
claimType?: string;
|
claimType?: string;
|
||||||
}
|
}
|
||||||
export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = {
|
export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = {
|
||||||
@@ -330,7 +331,7 @@ export function addLastClaimOrHandleAsIdIfMissing(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return clone of object without any nested *VisibleToDids keys
|
// return clone of object without any nested *VisibleToDids keys
|
||||||
// similar logic is found in endorser-mobile
|
// similar code is also contained in endorser-mobile
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export function removeVisibleToDids(input: any): any {
|
export function removeVisibleToDids(input: any): any {
|
||||||
if (input instanceof Object) {
|
if (input instanceof Object) {
|
||||||
@@ -340,7 +341,6 @@ export function removeVisibleToDids(input: any): any {
|
|||||||
const result: Record<string, any> = {};
|
const result: Record<string, any> = {};
|
||||||
for (const key in input) {
|
for (const key in input) {
|
||||||
if (!key.endsWith("VisibleToDids")) {
|
if (!key.endsWith("VisibleToDids")) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
result[key] = removeVisibleToDids(R.clone(input[key]));
|
result[key] = removeVisibleToDids(R.clone(input[key]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -349,7 +349,6 @@ export function removeVisibleToDids(input: any): any {
|
|||||||
// it's an array
|
// it's an array
|
||||||
return R.map(removeVisibleToDids, input);
|
return R.map(removeVisibleToDids, input);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
@@ -518,6 +517,28 @@ export async function createAndSubmitOffer(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// similar logic is found in endorser-mobile
|
||||||
|
export const createAndSubmitConfirmation = async (
|
||||||
|
identifier: IIdentifier,
|
||||||
|
claim: GenericVerifiableCredential,
|
||||||
|
lastClaimId: string, // used to set the lastClaimId
|
||||||
|
handleId: string | undefined,
|
||||||
|
apiServer: string,
|
||||||
|
axios: Axios,
|
||||||
|
) => {
|
||||||
|
const goodClaim = removeSchemaContext(
|
||||||
|
removeVisibleToDids(
|
||||||
|
addLastClaimOrHandleAsIdIfMissing(claim, lastClaimId, handleId),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const confirmationClaim: GenericVerifiableCredential = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "AgreeAction",
|
||||||
|
object: goodClaim,
|
||||||
|
};
|
||||||
|
return createAndSubmitClaim(confirmationClaim, identifier, apiServer, axios);
|
||||||
|
};
|
||||||
|
|
||||||
export async function createAndSubmitClaim(
|
export async function createAndSubmitClaim(
|
||||||
vcClaim: GenericVerifiableCredential,
|
vcClaim: GenericVerifiableCredential,
|
||||||
identity: IIdentifier,
|
identity: IIdentifier,
|
||||||
@@ -583,7 +604,7 @@ export async function createAndSubmitClaim(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export const isAccept = (claim: Record<any, any>) => {
|
export const isAccept = (claim: Record<string, any>) => {
|
||||||
return (
|
return (
|
||||||
claim &&
|
claim &&
|
||||||
claim["@context"] === SCHEMA_ORG_CONTEXT &&
|
claim["@context"] === SCHEMA_ORG_CONTEXT &&
|
||||||
@@ -592,7 +613,7 @@ export const isAccept = (claim: Record<any, any>) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export const isOffer = (claim: Record<any, any>) => {
|
export const isOffer = (claim: Record<string, any>) => {
|
||||||
return (
|
return (
|
||||||
claim &&
|
claim &&
|
||||||
claim["@context"] === SCHEMA_ORG_CONTEXT &&
|
claim["@context"] === SCHEMA_ORG_CONTEXT &&
|
||||||
@@ -622,7 +643,7 @@ export const capitalizeAndInsertSpacesBeforeCaps = (text: string) => {
|
|||||||
similar code is also contained in endorser-mobile
|
similar code is also contained in endorser-mobile
|
||||||
**/
|
**/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const claimSummary = (claim: Record<any, any>) => {
|
const claimSummary = (claim: Record<string, any>) => {
|
||||||
if (!claim) {
|
if (!claim) {
|
||||||
// to differentiate from "something" above
|
// to differentiate from "something" above
|
||||||
return "something";
|
return "something";
|
||||||
@@ -630,7 +651,7 @@ const claimSummary = (claim: Record<any, any>) => {
|
|||||||
if (claim.claim) {
|
if (claim.claim) {
|
||||||
// probably a Verified Credential
|
// probably a Verified Credential
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
claim = claim.claim as Record<any, any>;
|
claim = claim.claim as Record<string, any>;
|
||||||
}
|
}
|
||||||
if (Array.isArray(claim)) {
|
if (Array.isArray(claim)) {
|
||||||
if (claim.length === 1) {
|
if (claim.length === 1) {
|
||||||
|
|||||||
@@ -730,10 +730,7 @@ export default class ClaimView extends Vue {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const confirmationClaim: serverUtil.GenericVerifiableCredential & {
|
const confirmationClaim: serverUtil.GenericVerifiableCredential = {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
object: any;
|
|
||||||
} = {
|
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "AgreeAction",
|
"@type": "AgreeAction",
|
||||||
object: goodClaim,
|
object: goodClaim,
|
||||||
|
|||||||
@@ -800,10 +800,7 @@ export default class ProjectViewView extends Vue {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const confirmationClaim: serverUtil.GenericVerifiableCredential & {
|
const confirmationClaim: serverUtil.GenericVerifiableCredential = {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
object: any;
|
|
||||||
} = {
|
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "AgreeAction",
|
"@type": "AgreeAction",
|
||||||
object: goodClaim,
|
object: goodClaim,
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ export default class QuickActionBvcBeginView extends Vue {
|
|||||||
const hoursNum = libsUtil.numberOrZero(this.hoursStr);
|
const hoursNum = libsUtil.numberOrZero(this.hoursStr);
|
||||||
const identity = await libsUtil.getIdentity(activeDid);
|
const identity = await libsUtil.getIdentity(activeDid);
|
||||||
|
|
||||||
|
// first send the claim for time given
|
||||||
let timeSuccess = false;
|
let timeSuccess = false;
|
||||||
if (this.gaveTime && hoursNum > 0) {
|
if (this.gaveTime && hoursNum > 0) {
|
||||||
const timeResult = await createAndSubmitGive(
|
const timeResult = await createAndSubmitGive(
|
||||||
@@ -156,6 +157,7 @@ export default class QuickActionBvcBeginView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now send the claim for attendance
|
||||||
let attendedSuccess = false;
|
let attendedSuccess = false;
|
||||||
if (this.attended) {
|
if (this.attended) {
|
||||||
const attendResult = await createAndSubmitClaim(
|
const attendResult = await createAndSubmitClaim(
|
||||||
@@ -208,7 +210,7 @@ export default class QuickActionBvcBeginView extends Vue {
|
|||||||
group: "alert",
|
group: "alert",
|
||||||
type: "danger",
|
type: "danger",
|
||||||
title: "Error",
|
title: "Error",
|
||||||
text: error.userMessage || "There was an error sending those claims.",
|
text: error.userMessage || "There was an error sending claims.",
|
||||||
},
|
},
|
||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -117,6 +117,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import axios from "axios";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import * as R from "ramda";
|
import * as R from "ramda";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
@@ -131,10 +132,16 @@ import { Contact } from "@/db/tables/contacts";
|
|||||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
import {
|
import {
|
||||||
|
BVC_MEETUPS_PROJECT_CLAIM_ID,
|
||||||
claimSpecialDescription,
|
claimSpecialDescription,
|
||||||
containsHiddenDid,
|
containsHiddenDid,
|
||||||
|
createAndSubmitConfirmation,
|
||||||
|
createAndSubmitGive,
|
||||||
|
ErrorResult,
|
||||||
GenericServerRecord,
|
GenericServerRecord,
|
||||||
|
GenericVerifiableCredential,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
|
import * as libsUtil from "@/libs/util";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
methods: { claimSpecialDescription },
|
methods: { claimSpecialDescription },
|
||||||
@@ -246,8 +253,116 @@ export default class QuickActionBvcBeginView extends Vue {
|
|||||||
this.$router.push(route);
|
this.$router.push(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
record() {
|
async record() {
|
||||||
alert("Nope");
|
try {
|
||||||
|
const identity = await libsUtil.getIdentity(this.activeDid);
|
||||||
|
|
||||||
|
// in parallel, make a confirmation for each selected claim and send them all to the server
|
||||||
|
const confirmResults = await Promise.allSettled(
|
||||||
|
this.claimsToConfirmSelected.map(async (jwtId) => {
|
||||||
|
const record = this.claimsToConfirm.find(
|
||||||
|
(claim) => claim.id === jwtId,
|
||||||
|
);
|
||||||
|
if (!record) {
|
||||||
|
return { type: "error", error: "Record not found." };
|
||||||
|
}
|
||||||
|
const identity = await libsUtil.getIdentity(this.activeDid);
|
||||||
|
return createAndSubmitConfirmation(
|
||||||
|
identity,
|
||||||
|
record.claim as GenericVerifiableCredential,
|
||||||
|
record.id,
|
||||||
|
record.handleId,
|
||||||
|
this.apiServer,
|
||||||
|
axios,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
// check for any rejected confirmations
|
||||||
|
const confirmsSucceeded = confirmResults.filter(
|
||||||
|
(result) =>
|
||||||
|
result.status === "fulfilled" && result.value.type === "success",
|
||||||
|
);
|
||||||
|
if (confirmsSucceeded.length < this.claimsToConfirmSelected.length) {
|
||||||
|
console.error("Error sending confirmations:", confirmResults);
|
||||||
|
const howMany = confirmsSucceeded.length === 0 ? "all" : "some";
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error",
|
||||||
|
text: `There was an error sending ${howMany} of the confirmations.`,
|
||||||
|
},
|
||||||
|
-1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now send the give for the description
|
||||||
|
let giveSucceeded = false;
|
||||||
|
if (this.someoneGave) {
|
||||||
|
const giveResult = await createAndSubmitGive(
|
||||||
|
axios,
|
||||||
|
this.apiServer,
|
||||||
|
identity,
|
||||||
|
undefined,
|
||||||
|
this.activeDid,
|
||||||
|
this.description,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
BVC_MEETUPS_PROJECT_CLAIM_ID,
|
||||||
|
);
|
||||||
|
giveSucceeded = giveResult.type === "success";
|
||||||
|
if (!giveSucceeded) {
|
||||||
|
console.error("Error sending give:", giveResult);
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error",
|
||||||
|
text:
|
||||||
|
(giveResult as ErrorResult)?.error?.userMessage ||
|
||||||
|
"There was an error sending the give.",
|
||||||
|
},
|
||||||
|
-1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirmsSucceeded.length > 0 || giveSucceeded) {
|
||||||
|
const confirms =
|
||||||
|
confirmsSucceeded.length === 1 ? "confirmation" : "confirmations";
|
||||||
|
const actions =
|
||||||
|
confirmsSucceeded.length > 0 && giveSucceeded
|
||||||
|
? `${confirms} and give have been`
|
||||||
|
: giveSucceeded
|
||||||
|
? "give has been"
|
||||||
|
: confirms +
|
||||||
|
" " +
|
||||||
|
(confirmsSucceeded.length === 1 ? "has" : "have") +
|
||||||
|
" been";
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "success",
|
||||||
|
title: "Success",
|
||||||
|
text: `Your ${actions} recorded.`,
|
||||||
|
},
|
||||||
|
-1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error("Error sending claims.", error);
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error",
|
||||||
|
text: error.userMessage || "There was an error sending claims.",
|
||||||
|
},
|
||||||
|
-1,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user