diff --git a/src/components/ActivityListItem.vue b/src/components/ActivityListItem.vue index b3bb9035..d1525e8d 100644 --- a/src/components/ActivityListItem.vue +++ b/src/components/ActivityListItem.vue @@ -251,8 +251,7 @@ import { Component, Prop, Vue, Emit } from "vue-facing-decorator"; import { GiveRecordWithContactInfo } from "@/interfaces/give"; import EntityIcon from "./EntityIcon.vue"; -import { isGiveClaimType, notifyWhyCannotConfirm } from "../libs/util"; -import { containsHiddenDid, isHiddenDid } from "../libs/endorserServer"; +import { isHiddenDid } from "../libs/endorserServer"; import ProjectIcon from "./ProjectIcon.vue"; import { createNotifyHelpers } from "@/utils/notify"; import { @@ -272,7 +271,6 @@ export default class ActivityListItem extends Vue { @Prop() lastViewedClaimId?: string; @Prop() isRegistered!: boolean; @Prop() activeDid!: string; - @Prop() confirmerIdList?: string[]; /** * Function prop for handling image caching @@ -331,15 +329,6 @@ export default class ActivityListItem extends Vue { return unitCode === "HUR" ? (single ? "hour" : "hours") : unitCode; } - get canConfirm(): boolean { - if (!this.isRegistered) return false; - if (!isGiveClaimType(this.record.fullClaim?.["@type"])) return false; - if (this.confirmerIdList?.includes(this.activeDid)) return false; - if (this.record.issuerDid === this.activeDid) return false; - if (containsHiddenDid(this.record.fullClaim)) return false; - return true; - } - // Emit methods using @Emit decorator @Emit("viewImage") emitViewImage(imageUrl: string) { @@ -351,26 +340,6 @@ export default class ActivityListItem extends Vue { return jwtId; } - @Emit("confirmClaim") - emitConfirmClaim() { - if (!this.canConfirm) { - notifyWhyCannotConfirm( - (msg, timeout) => this.notify.info(msg.text ?? "", timeout), - this.isRegistered, - this.record.fullClaim?.["@type"], - this.record, - this.activeDid, - this.confirmerIdList, - ); - return; - } - return this.record; - } - - handleConfirmClick() { - this.emitConfirmClaim(); - } - get friendlyDate(): string { const date = new Date(this.record.issuedAt); return date.toLocaleDateString(undefined, { diff --git a/src/components/EntitySelectionStep.vue b/src/components/EntitySelectionStep.vue index ee144c75..56426462 100644 --- a/src/components/EntitySelectionStep.vue +++ b/src/components/EntitySelectionStep.vue @@ -261,12 +261,13 @@ export default class EntitySelectionStep extends Vue { giverProjectName: this.giver?.name || "", giverProjectImage: this.giver?.image || "", giverProjectHandleId: this.giver?.handleId || "", - giverDid: this.giver?.did || "", + giverDid: this.giverEntityType === "person" ? this.giver?.did || "" : "", recipientProjectId: this.toProjectId || "", recipientProjectName: this.receiver?.name || "", recipientProjectImage: this.receiver?.image || "", recipientProjectHandleId: this.receiver?.handleId || "", - recipientDid: this.receiver?.did || "", + recipientDid: + this.recipientEntityType === "person" ? this.receiver?.did || "" : "", }; } diff --git a/src/components/GiftDetailsStep.vue b/src/components/GiftDetailsStep.vue index 1841b4bb..f31ed095 100644 --- a/src/components/GiftDetailsStep.vue +++ b/src/components/GiftDetailsStep.vue @@ -315,16 +315,15 @@ export default class GiftDetailsStep extends Vue { giverName: this.giver?.name, offerId: this.offerId, fulfillsProjectId: - this.giverEntityType === "person" && - this.recipientEntityType === "project" - ? this.toProjectId - : undefined, + this.recipientEntityType === "project" ? this.toProjectId : undefined, providerProjectId: - this.giverEntityType === "project" && - this.recipientEntityType === "person" + this.giverEntityType === "project" ? this.giver?.handleId : this.fromProjectId, - recipientDid: this.receiver?.did, + recipientDid: + this.recipientEntityType === "person" + ? this.receiver?.did + : undefined, recipientName: this.receiver?.name, unitCode: this.localUnitCode, }, diff --git a/src/components/GiftedDialog.vue b/src/components/GiftedDialog.vue index cd70fd78..7fcc1747 100644 --- a/src/components/GiftedDialog.vue +++ b/src/components/GiftedDialog.vue @@ -81,6 +81,12 @@ import GiftDetailsStep from "../components/GiftDetailsStep.vue"; import { PlanData } from "../interfaces/records"; import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin"; import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify"; +import { + NOTIFY_GIFT_ERROR_NEGATIVE_AMOUNT, + NOTIFY_GIFT_ERROR_NO_DESCRIPTION, + NOTIFY_GIFTED_DETAILS_NO_IDENTIFIER, + NOTIFY_GIFTED_DETAILS_RECORDING_GIVE, +} from "@/constants/notifications"; @Component({ components: { @@ -288,23 +294,24 @@ export default class GiftedDialog extends Vue { async confirm() { if (!this.activeDid) { this.safeNotify.error( - "You must select an identifier before you can record a give.", - TIMEOUTS.STANDARD, + NOTIFY_GIFTED_DETAILS_NO_IDENTIFIER.message, + TIMEOUTS.SHORT, ); return; } if (parseFloat(this.amountInput) < 0) { this.safeNotify.error( - "You may not send a negative number.", + NOTIFY_GIFT_ERROR_NEGATIVE_AMOUNT.message, TIMEOUTS.SHORT, ); return; } if (!this.description && !parseFloat(this.amountInput)) { this.safeNotify.error( - `You must enter a description or some number of ${ - this.libsUtil.UNIT_LONG[this.unitCode] - }.`, + NOTIFY_GIFT_ERROR_NO_DESCRIPTION.message.replace( + "{unit}", + this.libsUtil.UNIT_SHORT[this.unitCode] || this.unitCode, + ), TIMEOUTS.SHORT, ); return; @@ -320,7 +327,11 @@ export default class GiftedDialog extends Vue { } this.close(); - this.safeNotify.toast("Recording the give...", undefined, TIMEOUTS.BRIEF); + this.safeNotify.toast( + NOTIFY_GIFTED_DETAILS_RECORDING_GIVE.message, + undefined, + TIMEOUTS.BRIEF, + ); // this is asynchronous, but we don't need to wait for it to complete await this.recordGive( (this.giver?.did as string) || null, @@ -447,10 +458,13 @@ export default class GiftedDialog extends Vue { name: contact.name || contact.did, }; } else { - this.giver = { - did: "", - name: "Unnamed", - }; + // Only set to "Unnamed" if no giver is currently set + if (!this.giver || !this.giver.did) { + this.giver = { + did: "", + name: "Unnamed", + }; + } } this.firstStep = false; } @@ -460,6 +474,10 @@ export default class GiftedDialog extends Vue { this.firstStep = true; } + moveToStep2() { + this.firstStep = false; + } + async loadProjects() { try { const response = await fetch(this.apiServer + "/api/v2/report/plans", { @@ -502,10 +520,13 @@ export default class GiftedDialog extends Vue { name: contact.name || contact.did, }; } else { - this.receiver = { - did: "", - name: "Unnamed", - }; + // Only set to "Unnamed" if no receiver is currently set + if (!this.receiver || !this.receiver.did) { + this.receiver = { + did: "", + name: "Unnamed", + }; + } } this.firstStep = false; } @@ -529,16 +550,13 @@ export default class GiftedDialog extends Vue { giverName: this.giver?.name, offerId: this.offerId, fulfillsProjectId: - this.giverEntityType === "person" && - this.recipientEntityType === "project" - ? this.toProjectId - : undefined, + this.recipientEntityType === "project" ? this.toProjectId : undefined, providerProjectId: - this.giverEntityType === "project" && - this.recipientEntityType === "person" + this.giverEntityType === "project" ? this.giver?.handleId : this.fromProjectId, - recipientDid: this.receiver?.did, + recipientDid: + this.recipientEntityType === "person" ? this.receiver?.did : undefined, recipientName: this.receiver?.name, unitCode: this.unitCode, }; diff --git a/src/views/ContactGiftingView.vue b/src/views/ContactGiftingView.vue index 75e8eea2..91d10c9c 100644 --- a/src/views/ContactGiftingView.vue +++ b/src/views/ContactGiftingView.vue @@ -195,7 +195,7 @@ export default class ContactGiftingView extends Vue { let giver: GiverReceiverInputInfo | undefined; if (this.stepType === "giver") { - // We're selecting a giver, so recipient is either a project or the current user + // We're selecting a giver, so preserve the existing recipient from context if (this.recipientEntityType === "project") { recipient = { did: this.recipientProjectHandleId, @@ -204,7 +204,20 @@ export default class ContactGiftingView extends Vue { handleId: this.recipientProjectHandleId, }; } else { - recipient = { did: this.activeDid, name: "You" }; + // Preserve the existing recipient from context + if (this.recipientDid === this.activeDid) { + // Recipient was "You" + recipient = { did: this.activeDid, name: "You" }; + } else if (this.recipientDid) { + // Recipient was a regular contact + recipient = { + did: this.recipientDid, + name: this.recipientProjectName || "Someone", + }; + } else { + // Fallback to "You" if no recipient was previously selected + recipient = { did: this.activeDid, name: "You" }; + } } giver = undefined; // Will be set to "Unnamed" in GiftedDialog } else { @@ -239,12 +252,8 @@ export default class ContactGiftingView extends Vue { this.unitCode, ); - // Immediately select "Unnamed" and move to Step 2 based on stepType - if (this.stepType === "giver") { - (this.$refs.giftedDialog as GiftedDialog).selectGiver(); - } else { - (this.$refs.giftedDialog as GiftedDialog).selectRecipient(); - } + // Move to Step 2 - entities are already set by the open() call + (this.$refs.giftedDialog as GiftedDialog).moveToStep2(); } else { // Regular case: contact is a GiverReceiverInputInfo let giver: GiverReceiverInputInfo; @@ -317,6 +326,9 @@ export default class ContactGiftingView extends Vue { this.amountInput, this.unitCode, ); + + // Move to Step 2 - entities are already set by the open() call + (this.$refs.giftedDialog as GiftedDialog).moveToStep2(); } } } diff --git a/src/views/ContactQRScanShowView.vue b/src/views/ContactQRScanShowView.vue index 8990df30..c23b7376 100644 --- a/src/views/ContactQRScanShowView.vue +++ b/src/views/ContactQRScanShowView.vue @@ -213,15 +213,11 @@ export default class ContactQRScanShow extends Vue { $router!: Router; // Notification helper system - private notify = createNotifyHelpers(this.$notify); + notify!: ReturnType; activeDid = ""; apiServer = ""; - // Axios instance for API calls - get axios() { - return (this as any).$platformService.axios; - } givenName = ""; hideRegisterPromptOnNewContact = false; isRegistered = false; @@ -288,6 +284,8 @@ export default class ContactQRScanShow extends Vue { } async created() { + this.notify = createNotifyHelpers(this.$notify); + try { const settings = await this.$accountSettings(); this.activeDid = settings.activeDid || ""; diff --git a/src/views/DIDView.vue b/src/views/DIDView.vue index 30361859..8a5aaa64 100644 --- a/src/views/DIDView.vue +++ b/src/views/DIDView.vue @@ -273,6 +273,7 @@ import { displayAmount, getHeaders, register, + setVisibilityUtil, } from "../libs/endorserServer"; import * as libsUtil from "../libs/util"; import EntityIcon from "../components/EntityIcon.vue"; @@ -324,6 +325,7 @@ export default class DIDView extends Vue { apiServer = ""; claims: Array> = []; contactFromDid?: Contact; + contactYaml = ""; hitEnd = false; isLoading = false; @@ -722,18 +724,31 @@ export default class DIDView extends Vue { visibility: boolean, showSuccessAlert: boolean, ) { - // Update contact visibility using mixin method - await this.$updateContact(contact.did, { seesMe: visibility }); + const result = await setVisibilityUtil( + this.activeDid, + this.apiServer, + this.axios, + contact, + visibility, + ); - if (showSuccessAlert) { + if (result.success) { + if (showSuccessAlert) { + const message = + (contact.name || "That user") + + " can " + + (visibility ? "" : "not ") + + "see your activity."; + this.notify.success(message, TIMEOUTS.SHORT); + } + return true; + } else { + logger.error("Got strange result from setting visibility:", result); const message = - (contact.name || "That user") + - " can " + - (visibility ? "" : "not ") + - "see your activity."; - this.notify.success(message, TIMEOUTS.SHORT); + (result.error as string) || "Could not set visibility on the server."; + this.notify.error(message, TIMEOUTS.LONG); + return false; } - return true; } /** diff --git a/src/views/GiftedDetailsView.vue b/src/views/GiftedDetailsView.vue index ede96ef8..ef5be5e9 100644 --- a/src/views/GiftedDetailsView.vue +++ b/src/views/GiftedDetailsView.vue @@ -48,24 +48,12 @@ placeholder="What was received" />
- - -