forked from trent_larson/crowd-funder-for-time-pwa
change the "give" action on contact page to use dialog box
This commit is contained in:
@@ -10,6 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Nothing
|
- Nothing
|
||||||
|
|
||||||
|
|
||||||
|
## [0.3.9] - 2024.04-21
|
||||||
|
### Added
|
||||||
|
- Offer on contacts page
|
||||||
|
### Changed in DB or environment
|
||||||
|
- Nothing
|
||||||
|
|
||||||
|
|
||||||
## [0.3.8] - 2024.04-20 - 15c026c80ce03a26cae3ff80b0888934c101c7e2
|
## [0.3.8] - 2024.04-20 - 15c026c80ce03a26cae3ff80b0888934c101c7e2
|
||||||
### Added
|
### Added
|
||||||
- Profile image for user
|
- Profile image for user
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ export default class EntityIcon extends Vue {
|
|||||||
if (!identifier) {
|
if (!identifier) {
|
||||||
return `<img src="../src/assets/blank-square.svg" class="rounded" width="${this.iconSize}" height="${this.iconSize}" />`;
|
return `<img src="../src/assets/blank-square.svg" class="rounded" width="${this.iconSize}" height="${this.iconSize}" />`;
|
||||||
}
|
}
|
||||||
|
// https://api.dicebear.com/8.x/avataaars/svg?seed=
|
||||||
|
// ... does not render things with the same seed as this library.
|
||||||
|
// "did:ethr:0x222BB77E6Ff3774d34c751f3c1260866357B677b" yields a girl with flowers in her hair and a lightning earring
|
||||||
|
// ... which looks similar to '' at the dicebear site but which is different.
|
||||||
const options: StyleOptions<object> = {
|
const options: StyleOptions<object> = {
|
||||||
seed: (identifier as string) || "",
|
seed: (identifier as string) || "",
|
||||||
size: this.iconSize,
|
size: this.iconSize,
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
<div v-if="visible" class="dialog-overlay">
|
<div v-if="visible" class="dialog-overlay">
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<h1 class="text-xl font-bold text-center mb-4">
|
<h1 class="text-xl font-bold text-center mb-4">
|
||||||
{{ message }} {{ giver?.name || "somebody not named" }}
|
{{ customTitle || message + " " + giver?.name || "somebody not named" }}
|
||||||
</h1>
|
</h1>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="block w-full rounded border border-slate-400 mb-2 px-3 py-2"
|
class="block w-full rounded border border-slate-400 mb-2 px-3 py-2"
|
||||||
placeholder="What was received"
|
placeholder="What was given"
|
||||||
v-model="description"
|
v-model="description"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-row justify-center">
|
<div class="flex flex-row justify-center">
|
||||||
@@ -42,12 +42,15 @@
|
|||||||
name: 'gifted-details',
|
name: 'gifted-details',
|
||||||
query: {
|
query: {
|
||||||
amountInput,
|
amountInput,
|
||||||
|
customTitle,
|
||||||
description,
|
description,
|
||||||
giverDid: giver?.did,
|
giverDid: giver?.did,
|
||||||
giverName: giver?.name,
|
giverName: giver?.name,
|
||||||
message,
|
message,
|
||||||
offerId,
|
offerId,
|
||||||
projectId,
|
projectId,
|
||||||
|
recipientDid: receiver?.did,
|
||||||
|
recipientName: receiver?.name,
|
||||||
unitCode,
|
unitCode,
|
||||||
},
|
},
|
||||||
}"
|
}"
|
||||||
@@ -90,7 +93,7 @@ import { NotificationIface } from "@/constants/app";
|
|||||||
import {
|
import {
|
||||||
createAndSubmitGive,
|
createAndSubmitGive,
|
||||||
didInfo,
|
didInfo,
|
||||||
GiverInputInfo,
|
GiverReceiverInputInfo,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
import * as libsUtil from "@/libs/util";
|
import * as libsUtil from "@/libs/util";
|
||||||
import { accountsDB, db } from "@/db/index";
|
import { accountsDB, db } from "@/db/index";
|
||||||
@@ -103,7 +106,6 @@ export default class GiftedDialog extends Vue {
|
|||||||
|
|
||||||
@Prop message = "";
|
@Prop message = "";
|
||||||
@Prop projectId = "";
|
@Prop projectId = "";
|
||||||
@Prop showGivenToUser = false;
|
|
||||||
|
|
||||||
activeDid = "";
|
activeDid = "";
|
||||||
allContacts: Array<Contact> = [];
|
allContacts: Array<Contact> = [];
|
||||||
@@ -111,22 +113,32 @@ export default class GiftedDialog extends Vue {
|
|||||||
apiServer = "";
|
apiServer = "";
|
||||||
|
|
||||||
amountInput = "0";
|
amountInput = "0";
|
||||||
|
callbackOnSuccess?: (amount: number) => void = () => {};
|
||||||
|
customTitle?: string;
|
||||||
description = "";
|
description = "";
|
||||||
givenToUser = false;
|
giver?: GiverReceiverInputInfo; // undefined means no identified giver agent
|
||||||
giver?: GiverInputInfo; // undefined means no identified giver agent
|
|
||||||
isTrade = false;
|
isTrade = false;
|
||||||
offerId = "";
|
offerId = "";
|
||||||
|
receiver?: GiverReceiverInputInfo;
|
||||||
unitCode = "HUR";
|
unitCode = "HUR";
|
||||||
visible = false;
|
visible = false;
|
||||||
|
|
||||||
libsUtil = libsUtil;
|
libsUtil = libsUtil;
|
||||||
|
|
||||||
async open(giver?: GiverInputInfo, offerId?: string) {
|
async open(
|
||||||
|
giver?: GiverReceiverInputInfo,
|
||||||
|
receiver?: GiverReceiverInputInfo,
|
||||||
|
offerId?: string,
|
||||||
|
customTitle?: string,
|
||||||
|
callbackOnSuccess?: (amount: number) => void,
|
||||||
|
) {
|
||||||
|
this.customTitle = customTitle;
|
||||||
this.description = "";
|
this.description = "";
|
||||||
this.giver = giver || {};
|
this.giver = giver;
|
||||||
|
this.receiver = receiver;
|
||||||
// if we show "given to user" selection, default checkbox to true
|
// if we show "given to user" selection, default checkbox to true
|
||||||
this.givenToUser = this.showGivenToUser;
|
|
||||||
this.amountInput = "0";
|
this.amountInput = "0";
|
||||||
|
this.callbackOnSuccess = callbackOnSuccess;
|
||||||
this.offerId = offerId || "";
|
this.offerId = offerId || "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -141,7 +153,7 @@ export default class GiftedDialog extends Vue {
|
|||||||
const allAccounts = await accountsDB.accounts.toArray();
|
const allAccounts = await accountsDB.accounts.toArray();
|
||||||
this.allMyDids = allAccounts.map((acc) => acc.did);
|
this.allMyDids = allAccounts.map((acc) => acc.did);
|
||||||
|
|
||||||
if (!this.giver.name) {
|
if (this.giver && !this.giver.name) {
|
||||||
this.giver.name = didInfo(
|
this.giver.name = didInfo(
|
||||||
this.giver.did,
|
this.giver.did,
|
||||||
this.activeDid,
|
this.activeDid,
|
||||||
@@ -196,7 +208,6 @@ export default class GiftedDialog extends Vue {
|
|||||||
eraseValues() {
|
eraseValues() {
|
||||||
this.description = "";
|
this.description = "";
|
||||||
this.giver = undefined;
|
this.giver = undefined;
|
||||||
this.givenToUser = this.showGivenToUser;
|
|
||||||
this.amountInput = "0";
|
this.amountInput = "0";
|
||||||
this.unitCode = "HUR";
|
this.unitCode = "HUR";
|
||||||
}
|
}
|
||||||
@@ -254,6 +265,7 @@ export default class GiftedDialog extends Vue {
|
|||||||
// this is asynchronous, but we don't need to wait for it to complete
|
// this is asynchronous, but we don't need to wait for it to complete
|
||||||
await this.recordGive(
|
await this.recordGive(
|
||||||
(this.giver?.did as string) || null,
|
(this.giver?.did as string) || null,
|
||||||
|
(this.receiver?.did as string) || null,
|
||||||
this.description,
|
this.description,
|
||||||
parseFloat(this.amountInput),
|
parseFloat(this.amountInput),
|
||||||
this.unitCode,
|
this.unitCode,
|
||||||
@@ -265,14 +277,16 @@ export default class GiftedDialog extends Vue {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param giverDid may be null
|
* @param giverDid may be null
|
||||||
|
* @param recipientDid may be null
|
||||||
* @param description may be an empty string
|
* @param description may be an empty string
|
||||||
* @param amountInput may be 0
|
* @param amount may be 0
|
||||||
* @param unitCode may be omitted, defaults to "HUR"
|
* @param unitCode may be omitted, defaults to "HUR"
|
||||||
*/
|
*/
|
||||||
public async recordGive(
|
async recordGive(
|
||||||
giverDid: string | null,
|
giverDid: string | null,
|
||||||
|
recipientDid: string | null,
|
||||||
description: string,
|
description: string,
|
||||||
amountInput: number,
|
amount: number,
|
||||||
unitCode: string = "HUR",
|
unitCode: string = "HUR",
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
@@ -282,9 +296,9 @@ export default class GiftedDialog extends Vue {
|
|||||||
this.apiServer,
|
this.apiServer,
|
||||||
identity,
|
identity,
|
||||||
giverDid,
|
giverDid,
|
||||||
this.givenToUser ? this.activeDid : undefined,
|
this.receiver?.did as string,
|
||||||
description,
|
description,
|
||||||
amountInput,
|
amount,
|
||||||
unitCode,
|
unitCode,
|
||||||
this.projectId,
|
this.projectId,
|
||||||
this.offerId,
|
this.offerId,
|
||||||
@@ -316,6 +330,9 @@ export default class GiftedDialog extends Vue {
|
|||||||
},
|
},
|
||||||
7000,
|
7000,
|
||||||
);
|
);
|
||||||
|
if (this.callbackOnSuccess) {
|
||||||
|
this.callbackOnSuccess(amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="w-full border border-slate-400 px-2 py-2 rounded-r"
|
class="w-full border border-slate-400 px-2 py-2 rounded-r"
|
||||||
:placeholder="'Date, eg. ' + new Date().toISOString().slice(0, 10)"
|
:placeholder="datePlaceholder()"
|
||||||
v-model="expirationDateInput"
|
v-model="expirationDateInput"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,6 +69,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { DateTime } from "luxon";
|
||||||
import { Vue, Component, Prop } from "vue-facing-decorator";
|
import { Vue, Component, Prop } from "vue-facing-decorator";
|
||||||
|
|
||||||
import { NotificationIface } from "@/constants/app";
|
import { NotificationIface } from "@/constants/app";
|
||||||
@@ -143,6 +144,12 @@ export default class OfferDialog extends Vue {
|
|||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
datePlaceholder() {
|
||||||
|
return (
|
||||||
|
"Date, eg. " + DateTime.now().plus({ month: 1 }).toISO().slice(0, 10)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
this.close();
|
this.close();
|
||||||
this.eraseValues();
|
this.eraseValues();
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
:to="{ name: 'projects' }"
|
:to="{ name: 'projects' }"
|
||||||
class="block text-center py-3 px-1"
|
class="block text-center py-3 px-1"
|
||||||
>
|
>
|
||||||
<fa icon="folder-open" class="fa-fw"></fa>
|
<fa icon="hand" class="fa-fw"></fa>
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<!-- Contacts -->
|
<!-- Contacts -->
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ export interface AgreeVerifiableCredential {
|
|||||||
object: Record<string, any>;
|
object: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GiverInputInfo {
|
export interface GiverReceiverInputInfo {
|
||||||
did?: string;
|
did?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GiverOutputInfo {
|
export interface GiverOutputInfo {
|
||||||
action: string;
|
action: string;
|
||||||
giver?: GiverInputInfo;
|
giver?: GiverReceiverInputInfo;
|
||||||
description?: string;
|
description?: string;
|
||||||
amount?: number;
|
amount?: number;
|
||||||
unitCode?: string;
|
unitCode?: string;
|
||||||
@@ -481,7 +481,7 @@ export async function getPlanFromCache(
|
|||||||
cred = resp.data.data[0];
|
cred = resp.data.data[0];
|
||||||
planCache.set(handleId, cred);
|
planCache.set(handleId, cred);
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.error(
|
||||||
"Failed to load plan with handle",
|
"Failed to load plan with handle",
|
||||||
handleId,
|
handleId,
|
||||||
" Got data:",
|
" Got data:",
|
||||||
@@ -489,7 +489,7 @@ export async function getPlanFromCache(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(
|
console.error(
|
||||||
"Failed to load plan with handle",
|
"Failed to load plan with handle",
|
||||||
handleId,
|
handleId,
|
||||||
" Got error:",
|
" Got error:",
|
||||||
|
|||||||
@@ -104,7 +104,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
... and those without your image see this (if you let them see your activity):
|
... and those without your image see this (if you let them see your
|
||||||
|
activity):
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<EntityIcon
|
<EntityIcon
|
||||||
@@ -1400,7 +1401,7 @@ export default class AccountViewView extends Vue {
|
|||||||
console.error("Error deleting image:", error);
|
console.error("Error deleting image:", error);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
if ((error as any).response.status === 404) {
|
if ((error as any).response.status === 404) {
|
||||||
console.log("The image was already deleted:", error);
|
console.error("The image was already deleted:", error);
|
||||||
|
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ import * as serverUtil from "@/libs/endorserServer";
|
|||||||
import * as libsUtil from "@/libs/util";
|
import * as libsUtil from "@/libs/util";
|
||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
import { Account } from "@/db/tables/accounts";
|
import { Account } from "@/db/tables/accounts";
|
||||||
import { GiverInputInfo } from "@/libs/endorserServer";
|
import { GiverReceiverInputInfo } from "@/libs/endorserServer";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { GiftedDialog, QuickNav },
|
components: { GiftedDialog, QuickNav },
|
||||||
@@ -775,11 +775,12 @@ export default class ClaimView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openFulfillGiftDialog() {
|
openFulfillGiftDialog() {
|
||||||
const giver: GiverInputInfo = {
|
const giver: GiverReceiverInputInfo = {
|
||||||
did: libsUtil.offerGiverDid(this.veriClaim),
|
did: libsUtil.offerGiverDid(this.veriClaim),
|
||||||
};
|
};
|
||||||
(this.$refs.customGiveDialog as GiftedDialog).open(
|
(this.$refs.customGiveDialog as GiftedDialog).open(
|
||||||
giver,
|
giver,
|
||||||
|
undefined,
|
||||||
this.veriClaim.handleId,
|
this.veriClaim.handleId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ import { Account, AccountsSchema } from "@/db/tables/accounts";
|
|||||||
import { Contact } from "@/db/tables/contacts";
|
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 { GiverInputInfo } from "@/libs/endorserServer";
|
import { GiverReceiverInputInfo } from "@/libs/endorserServer";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { GiftedDialog, QuickNav, EntityIcon },
|
components: { GiftedDialog, QuickNav, EntityIcon },
|
||||||
@@ -163,8 +163,11 @@ export default class ContactGiftingView extends Vue {
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
openDialog(giver: GiverInputInfo) {
|
openDialog(giver: GiverReceiverInputInfo) {
|
||||||
(this.$refs.customDialog as GiftedDialog).open(giver);
|
const recipient = this.projectId
|
||||||
|
? undefined
|
||||||
|
: { did: this.activeDid, name: "you" };
|
||||||
|
(this.$refs.customDialog as GiftedDialog).open(giver, recipient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -188,7 +188,6 @@ export default class ContactQRScanShow extends Vue {
|
|||||||
if (url) {
|
if (url) {
|
||||||
try {
|
try {
|
||||||
const fullData = getContactPayloadFromJwtUrl(url);
|
const fullData = getContactPayloadFromJwtUrl(url);
|
||||||
console.log("fullData", fullData);
|
|
||||||
localStorage.setItem("contactEndorserUrl", url);
|
localStorage.setItem("contactEndorserUrl", url);
|
||||||
this.$router.push({ name: "contacts" });
|
this.$router.push({ name: "contacts" });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
<div class="flex justify-between" v-if="showGiveNumbers">
|
<div class="flex justify-between" v-if="showGiveNumbers">
|
||||||
<div class="w-full text-right">
|
<div class="w-full text-right">
|
||||||
|
<!--
|
||||||
Hours to Add:
|
Hours to Add:
|
||||||
<input
|
<input
|
||||||
class="border rounded border-slate-400 w-24 text-right"
|
class="border rounded border-slate-400 w-24 text-right"
|
||||||
@@ -57,30 +58,29 @@
|
|||||||
placeholder="Description"
|
placeholder="Description"
|
||||||
v-model="hourDescriptionInput"
|
v-model="hourDescriptionInput"
|
||||||
/>
|
/>
|
||||||
<br />
|
-->
|
||||||
<br />
|
In the following, only the most recent hours are included. To see more,
|
||||||
<button
|
click
|
||||||
href=""
|
|
||||||
class="text-center text-md text-white px-1.5 py-2 rounded-md mb-6"
|
|
||||||
v-bind:class="showGiveAmountsClassNames()"
|
|
||||||
@click="toggleShowGiveTotals()"
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
showGiveTotals
|
|
||||||
? "Total"
|
|
||||||
: showGiveConfirmed
|
|
||||||
? "Confirmed"
|
|
||||||
: "Unconfirmed"
|
|
||||||
}}
|
|
||||||
</button>
|
|
||||||
<br />
|
|
||||||
(Only most recent hours included. To see more, click
|
|
||||||
<span
|
<span
|
||||||
class="text-sm 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 py-1 rounded-md"
|
class="text-sm 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 py-1 rounded-md"
|
||||||
>
|
>
|
||||||
<fa icon="file-lines" class="fa-fw" />
|
<fa icon="file-lines" class="fa-fw" />
|
||||||
</span>
|
</span>
|
||||||
)
|
<br />
|
||||||
|
<button
|
||||||
|
href=""
|
||||||
|
class="text-center text-md text-white px-1.5 py-2 rounded-md mt-1"
|
||||||
|
v-bind:class="showGiveAmountsClassNames()"
|
||||||
|
@click="toggleShowGiveTotals()"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
showGiveTotals
|
||||||
|
? "Showing Total"
|
||||||
|
: showGiveConfirmed
|
||||||
|
? "Confirmed"
|
||||||
|
: "Unconfirmed"
|
||||||
|
}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -189,10 +189,11 @@
|
|||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="text-sm 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-1.5 rounded-l-md"
|
class="text-sm 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-1.5 rounded-l-md"
|
||||||
@click="onClickAddGive(activeDid, contact.did)"
|
@click="showGiftedDialog(activeDid, contact.did)"
|
||||||
:title="givenByMeDescriptions[contact.did] || ''"
|
:title="givenByMeDescriptions[contact.did] || ''"
|
||||||
>
|
>
|
||||||
To:
|
To:
|
||||||
|
<br />
|
||||||
{{
|
{{
|
||||||
/* eslint-disable prettier/prettier */
|
/* eslint-disable prettier/prettier */
|
||||||
this.showGiveTotals
|
this.showGiveTotals
|
||||||
@@ -203,15 +204,17 @@
|
|||||||
: (givenByMeUnconfirmed[contact.did] || 0)
|
: (givenByMeUnconfirmed[contact.did] || 0)
|
||||||
/* eslint-enable prettier/prettier */
|
/* eslint-enable prettier/prettier */
|
||||||
}}
|
}}
|
||||||
|
<br />
|
||||||
<fa icon="plus" />
|
<fa icon="plus" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="text-sm bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white -ml-1.5 px-2 py-1.5 rounded-r-md border-l"
|
class="text-sm bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white -ml-1.5 px-2 py-1.5 rounded-r-md border-l"
|
||||||
@click="onClickAddGive(contact.did, activeDid)"
|
@click="showGiftedDialog(contact.did, this.activeDid)"
|
||||||
:title="givenToMeDescriptions[contact.did] || ''"
|
:title="givenToMeDescriptions[contact.did] || ''"
|
||||||
>
|
>
|
||||||
From:
|
From:
|
||||||
|
<br />
|
||||||
{{
|
{{
|
||||||
/* eslint-disable prettier/prettier */
|
/* eslint-disable prettier/prettier */
|
||||||
this.showGiveTotals
|
this.showGiveTotals
|
||||||
@@ -222,6 +225,7 @@
|
|||||||
: (givenToMeUnconfirmed[contact.did] || 0)
|
: (givenToMeUnconfirmed[contact.did] || 0)
|
||||||
/* eslint-enable prettier/prettier */
|
/* eslint-enable prettier/prettier */
|
||||||
}}
|
}}
|
||||||
|
<br />
|
||||||
<fa icon="plus" />
|
<fa icon="plus" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -237,7 +241,7 @@
|
|||||||
name: 'contact-amounts',
|
name: 'contact-amounts',
|
||||||
query: { contactDid: contact.did },
|
query: { contactDid: contact.did },
|
||||||
}"
|
}"
|
||||||
class="text-sm 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-1.5 rounded-md"
|
class="text-sm 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-1.5 rounded-md border border-slate-400"
|
||||||
title="See more given activity"
|
title="See more given activity"
|
||||||
>
|
>
|
||||||
<fa icon="file-lines" class="fa-fw" />
|
<fa icon="file-lines" class="fa-fw" />
|
||||||
@@ -249,6 +253,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<p v-else>There are no contacts.</p>
|
<p v-else>There are no contacts.</p>
|
||||||
|
|
||||||
|
<GiftedDialog ref="customGivenDialog" />
|
||||||
<OfferDialog ref="customOfferDialog" />
|
<OfferDialog ref="customOfferDialog" />
|
||||||
|
|
||||||
<div v-if="showLargeIdenticon" class="fixed z-[100] top-0 inset-x-0 w-full">
|
<div v-if="showLargeIdenticon" class="fixed z-[100] top-0 inset-x-0 w-full">
|
||||||
@@ -313,8 +318,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
CONTACT_CSV_HEADER,
|
CONTACT_CSV_HEADER,
|
||||||
CONTACT_URL_PREFIX,
|
CONTACT_URL_PREFIX,
|
||||||
|
GiverReceiverInputInfo,
|
||||||
GiveSummaryRecord,
|
GiveSummaryRecord,
|
||||||
GiveVerifiableCredential,
|
|
||||||
isDid,
|
isDid,
|
||||||
RegisterVerifiableCredential,
|
RegisterVerifiableCredential,
|
||||||
SERVICE_ID,
|
SERVICE_ID,
|
||||||
@@ -322,13 +327,14 @@ import {
|
|||||||
import * as libsUtil from "@/libs/util";
|
import * as libsUtil from "@/libs/util";
|
||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
import EntityIcon from "@/components/EntityIcon.vue";
|
import EntityIcon from "@/components/EntityIcon.vue";
|
||||||
|
import GiftedDialog from "@/components/GiftedDialog.vue";
|
||||||
import OfferDialog from "@/components/OfferDialog.vue";
|
import OfferDialog from "@/components/OfferDialog.vue";
|
||||||
import { Account } from "@/db/tables/accounts";
|
import { Account } from "@/db/tables/accounts";
|
||||||
|
|
||||||
import { Buffer } from "buffer/";
|
import { Buffer } from "buffer/";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { EntityIcon, OfferDialog, QuickNav },
|
components: { GiftedDialog, EntityIcon, OfferDialog, QuickNav },
|
||||||
})
|
})
|
||||||
export default class ContactsView extends Vue {
|
export default class ContactsView extends Vue {
|
||||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||||
@@ -352,8 +358,6 @@ export default class ContactsView extends Vue {
|
|||||||
givenToMeConfirmed: Record<string, number> = {};
|
givenToMeConfirmed: Record<string, number> = {};
|
||||||
// { "did:...": amount } entry for each contact
|
// { "did:...": amount } entry for each contact
|
||||||
givenToMeUnconfirmed: Record<string, number> = {};
|
givenToMeUnconfirmed: Record<string, number> = {};
|
||||||
hourDescriptionInput = "";
|
|
||||||
hourInput = "0";
|
|
||||||
isRegistered = false;
|
isRegistered = false;
|
||||||
showDidCopy = false;
|
showDidCopy = false;
|
||||||
showGiveNumbers = false;
|
showGiveNumbers = false;
|
||||||
@@ -1041,27 +1045,33 @@ export default class ContactsView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private nameForDid(contacts: Array<Contact>, did: string): string {
|
private nameForDid(contacts: Array<Contact>, did: string): string {
|
||||||
|
if (did === this.activeDid) {
|
||||||
|
return "you";
|
||||||
|
}
|
||||||
const contact = R.find((con) => con.did == did, contacts);
|
const contact = R.find((con) => con.did == did, contacts);
|
||||||
return this.nameForContact(contact);
|
return this.nameForContact(contact);
|
||||||
}
|
}
|
||||||
|
|
||||||
private nameForContact(contact?: Contact, capitalize?: boolean): string {
|
private nameForContact(contact?: Contact, capitalize?: boolean): string {
|
||||||
return contact?.name || (capitalize ? "T" : "t") + "his unnamed user";
|
return (
|
||||||
|
(contact?.name as string) || (capitalize ? "T" : "t") + "his unnamed user"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onClickAddGive(fromDid: string, toDid: string): Promise<void> {
|
private showGiftedDialog(giverDid: string, recipientDid: string) {
|
||||||
const identity = await this.getIdentity(this.activeDid);
|
|
||||||
|
|
||||||
// if they have unconfirmed amounts, ask to confirm those first
|
// if they have unconfirmed amounts, ask to confirm those first
|
||||||
if (toDid == identity?.did && this.givenToMeUnconfirmed[fromDid] > 0) {
|
if (
|
||||||
const isare = this.givenToMeUnconfirmed[fromDid] == 1 ? "is" : "are";
|
recipientDid == this.activeDid &&
|
||||||
const hours = this.givenToMeUnconfirmed[fromDid] == 1 ? "hour" : "hours";
|
this.givenToMeUnconfirmed[giverDid] > 0
|
||||||
|
) {
|
||||||
|
const isAre = this.givenToMeUnconfirmed[giverDid] == 1 ? "is" : "are";
|
||||||
|
const hours = this.givenToMeUnconfirmed[giverDid] == 1 ? "hour" : "hours";
|
||||||
if (
|
if (
|
||||||
confirm(
|
confirm(
|
||||||
"There " +
|
"There " +
|
||||||
isare +
|
isAre +
|
||||||
" " +
|
" " +
|
||||||
this.givenToMeUnconfirmed[fromDid] +
|
this.givenToMeUnconfirmed[giverDid] +
|
||||||
" unconfirmed " +
|
" unconfirmed " +
|
||||||
hours +
|
hours +
|
||||||
" from them." +
|
" from them." +
|
||||||
@@ -1070,178 +1080,58 @@ export default class ContactsView extends Vue {
|
|||||||
) {
|
) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: "contact-amounts",
|
name: "contact-amounts",
|
||||||
query: { contactDid: fromDid },
|
query: { contactDid: giverDid },
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!libsUtil.isNumeric(this.hourInput)) {
|
|
||||||
this.$notify(
|
let giver: GiverReceiverInputInfo, receiver: GiverReceiverInputInfo;
|
||||||
{
|
if (giverDid) {
|
||||||
group: "alert",
|
giver = {
|
||||||
type: "danger",
|
did: giverDid,
|
||||||
title: "Input Error",
|
name: this.nameForDid(this.contacts, giverDid),
|
||||||
text: "This is not a valid number of hours: " + this.hourInput,
|
};
|
||||||
},
|
|
||||||
3000,
|
|
||||||
);
|
|
||||||
} else if (parseFloat(this.hourInput) == 0 && !this.hourDescriptionInput) {
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Input Error",
|
|
||||||
text: "Giving no hours or description does nothing.",
|
|
||||||
},
|
|
||||||
3000,
|
|
||||||
);
|
|
||||||
} else if (!identity) {
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Status Error",
|
|
||||||
text: "No identifier is available.",
|
|
||||||
},
|
|
||||||
3000,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// ask to confirm amount
|
|
||||||
let toFrom;
|
|
||||||
if (fromDid == identity?.did) {
|
|
||||||
toFrom = "from you to " + this.nameForDid(this.contacts, toDid);
|
|
||||||
} else {
|
|
||||||
toFrom = "from " + this.nameForDid(this.contacts, fromDid) + " to you";
|
|
||||||
}
|
|
||||||
let description;
|
|
||||||
if (this.hourDescriptionInput) {
|
|
||||||
description = " with description '" + this.hourDescriptionInput + "'";
|
|
||||||
} else {
|
|
||||||
description = " with no description";
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
confirm(
|
|
||||||
"Are you sure you want to record " +
|
|
||||||
this.hourInput +
|
|
||||||
" hour" +
|
|
||||||
(this.hourInput == "1" ? "" : "s") +
|
|
||||||
" " +
|
|
||||||
toFrom +
|
|
||||||
description +
|
|
||||||
"?",
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
this.createAndSubmitContactGive(
|
|
||||||
identity,
|
|
||||||
fromDid,
|
|
||||||
toDid,
|
|
||||||
parseFloat(this.hourInput),
|
|
||||||
this.hourDescriptionInput,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (recipientDid) {
|
||||||
|
receiver = {
|
||||||
|
did: recipientDid,
|
||||||
|
name: this.nameForDid(this.contacts, recipientDid),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let callback: (amount: number) => void;
|
||||||
|
let customTitle = "Given";
|
||||||
|
// choose whether to open dialog to user or from user
|
||||||
|
if (giverDid == this.activeDid) {
|
||||||
|
callback = (amount: number) => {
|
||||||
|
const newList = R.clone(this.givenByMeUnconfirmed);
|
||||||
|
newList[recipientDid] = (newList[recipientDid] || 0) + amount;
|
||||||
|
this.givenByMeUnconfirmed = newList;
|
||||||
|
};
|
||||||
|
customTitle = "To " + receiver.name;
|
||||||
|
} else {
|
||||||
|
// must be (recipientDid == this.activeDid)
|
||||||
|
callback = (amount: number) => {
|
||||||
|
const newList = R.clone(this.givenToMeUnconfirmed);
|
||||||
|
newList[giverDid] = (newList[giverDid] || 0) + amount;
|
||||||
|
this.givenToMeUnconfirmed = newList;
|
||||||
|
};
|
||||||
|
customTitle = "From " + giver.name;
|
||||||
|
}
|
||||||
|
(this.$refs.customGivenDialog as GiftedDialog).open(
|
||||||
|
giver,
|
||||||
|
receiver,
|
||||||
|
undefined as string,
|
||||||
|
customTitle,
|
||||||
|
callback,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
openOfferDialog(recipientDid: string) {
|
openOfferDialog(recipientDid: string) {
|
||||||
(this.$refs.customOfferDialog as OfferDialog).open(recipientDid);
|
(this.$refs.customOfferDialog as OfferDialog).open(recipientDid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// similar function is in endorserServer.ts
|
|
||||||
private async createAndSubmitContactGive(
|
|
||||||
identity: IIdentifier,
|
|
||||||
fromDid: string,
|
|
||||||
toDid: string,
|
|
||||||
amount: number,
|
|
||||||
description: string,
|
|
||||||
): Promise<void> {
|
|
||||||
// Make a claim
|
|
||||||
const vcClaim: GiveVerifiableCredential = {
|
|
||||||
"@context": "https://schema.org",
|
|
||||||
"@type": "GiveAction",
|
|
||||||
agent: { identifier: fromDid },
|
|
||||||
object: { amountOfThisGood: amount, unitCode: "HUR" },
|
|
||||||
recipient: { identifier: toDid },
|
|
||||||
};
|
|
||||||
if (description) {
|
|
||||||
vcClaim.description = description;
|
|
||||||
}
|
|
||||||
// Make a payload for the claim
|
|
||||||
const vcPayload = {
|
|
||||||
vc: {
|
|
||||||
"@context": ["https://www.w3.org/2018/credentials/v1"],
|
|
||||||
type: ["VerifiableCredential"],
|
|
||||||
credentialSubject: vcClaim,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// Create a signature using private key of identity
|
|
||||||
if (identity.keys[0].privateKeyHex !== null) {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
const privateKeyHex: string = identity.keys[0].privateKeyHex!;
|
|
||||||
const signer = await SimpleSigner(privateKeyHex);
|
|
||||||
const alg = undefined;
|
|
||||||
// Create a JWT for the request
|
|
||||||
const vcJwt: string = await didJwt.createJWT(vcPayload, {
|
|
||||||
alg: alg,
|
|
||||||
issuer: identity.did,
|
|
||||||
signer: signer,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Make the xhr request payload
|
|
||||||
|
|
||||||
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
|
||||||
const url = this.apiServer + "/api/v2/claim";
|
|
||||||
const headers = await this.getHeaders(identity);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const resp = await this.axios.post(url, payload, { headers });
|
|
||||||
if (resp.data?.success?.handleId) {
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "success",
|
|
||||||
title: "Done",
|
|
||||||
text: "Successfully logged time to the server.",
|
|
||||||
},
|
|
||||||
5000,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (fromDid === identity.did) {
|
|
||||||
const newList = R.clone(this.givenByMeUnconfirmed);
|
|
||||||
newList[toDid] = (newList[toDid] || 0) + amount;
|
|
||||||
this.givenByMeUnconfirmed = newList;
|
|
||||||
} else {
|
|
||||||
const newList = R.clone(this.givenToMeConfirmed);
|
|
||||||
newList[fromDid] = (newList[fromDid] || 0) + amount;
|
|
||||||
this.givenToMeConfirmed = newList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error in createAndSubmitContactGive: ", error);
|
|
||||||
let userMessage = "There was an error. See logs for more info.";
|
|
||||||
const serverError = error as AxiosError;
|
|
||||||
if (serverError) {
|
|
||||||
if (serverError.message) {
|
|
||||||
userMessage = serverError.message; // Info for the user
|
|
||||||
} else {
|
|
||||||
userMessage = JSON.stringify(serverError.toJSON());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
userMessage = error as string;
|
|
||||||
}
|
|
||||||
// Now set that error for the user to see.
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error Sending Give",
|
|
||||||
text: userMessage,
|
|
||||||
},
|
|
||||||
5000,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async onClickCancelName() {
|
private async onClickCancelName() {
|
||||||
this.contactEdit = null;
|
this.contactEdit = null;
|
||||||
this.contactNewName = "";
|
this.contactNewName = "";
|
||||||
|
|||||||
@@ -18,8 +18,12 @@
|
|||||||
<h1 class="text-4xl text-center font-light px-4 mb-4">What Was Given</h1>
|
<h1 class="text-4xl text-center font-light px-4 mb-4">What Was Given</h1>
|
||||||
|
|
||||||
<h1 class="text-xl font-bold text-center mb-4">
|
<h1 class="text-xl font-bold text-center mb-4">
|
||||||
{{ message }} {{ giverName || "somebody not named" }}
|
{{ customTitle || message + " " + giverName || "somebody not named" }}
|
||||||
</h1>
|
</h1>
|
||||||
|
<div>
|
||||||
|
<span>From {{ giverName || "somebody not named" }}</span>
|
||||||
|
<span> to {{ recipientName || "somebody not named" }}</span>
|
||||||
|
</div>
|
||||||
<textarea
|
<textarea
|
||||||
class="block w-full rounded border border-slate-400 mb-2 px-3 py-2"
|
class="block w-full rounded border border-slate-400 mb-2 px-3 py-2"
|
||||||
placeholder="What was received"
|
placeholder="What was received"
|
||||||
@@ -80,7 +84,7 @@
|
|||||||
<label class="text-sm">This is given to a project</label>
|
<label class="text-sm">This is given to a project</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="!projectId" class="mt-4">
|
<div v-if="showGivenToUser" class="mt-4">
|
||||||
<input type="checkbox" class="h-6 w-6 mr-2" v-model="givenToUser" />
|
<input type="checkbox" class="h-6 w-6 mr-2" v-model="givenToUser" />
|
||||||
<label class="text-sm">Given to you</label>
|
<label class="text-sm">Given to you</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -126,12 +130,10 @@ import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
|||||||
import { createAndSubmitGive } from "@/libs/endorserServer";
|
import { createAndSubmitGive } from "@/libs/endorserServer";
|
||||||
import * as libsUtil from "@/libs/util";
|
import * as libsUtil from "@/libs/util";
|
||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
import GiftedDialog from "@/components/GiftedDialog.vue";
|
|
||||||
import GiftedPhotoDialog from "@/components/GiftedPhotoDialog.vue";
|
import GiftedPhotoDialog from "@/components/GiftedPhotoDialog.vue";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
GiftedDialog,
|
|
||||||
GiftedPhotoDialog,
|
GiftedPhotoDialog,
|
||||||
QuickNav,
|
QuickNav,
|
||||||
TopMessage,
|
TopMessage,
|
||||||
@@ -144,6 +146,7 @@ export default class GiftedDetails extends Vue {
|
|||||||
apiServer = "";
|
apiServer = "";
|
||||||
|
|
||||||
amountInput = "0";
|
amountInput = "0";
|
||||||
|
customTitle = "";
|
||||||
description = "";
|
description = "";
|
||||||
givenToUser = false;
|
givenToUser = false;
|
||||||
giverDid: string | undefined;
|
giverDid: string | undefined;
|
||||||
@@ -153,30 +156,46 @@ export default class GiftedDetails extends Vue {
|
|||||||
message = "";
|
message = "";
|
||||||
offerId = "";
|
offerId = "";
|
||||||
projectId = "";
|
projectId = "";
|
||||||
|
recipientDid = "";
|
||||||
|
recipientName = "";
|
||||||
|
showGivenToUser = false;
|
||||||
unitCode = "HUR";
|
unitCode = "HUR";
|
||||||
|
|
||||||
libsUtil = libsUtil;
|
libsUtil = libsUtil;
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.amountInput = this.$route.query.amountInput as string;
|
this.amountInput = this.$route.query.amountInput as string;
|
||||||
|
this.customTitle = this.$route.query.customTitle as string;
|
||||||
this.description = this.$route.query.description as string;
|
this.description = this.$route.query.description as string;
|
||||||
this.giverDid = this.$route.query.giverDid as string;
|
this.giverDid = this.$route.query.giverDid as string;
|
||||||
this.giverName = this.$route.query.giverName as string;
|
this.giverName = this.$route.query.giverName as string;
|
||||||
|
if (this.giverDid && !this.giverName) {
|
||||||
|
this.giverName =
|
||||||
|
this.giverDid === this.activeDid ? "you" : "someone not named";
|
||||||
|
}
|
||||||
this.message = this.$route.query.message as string;
|
this.message = this.$route.query.message as string;
|
||||||
this.offerId = this.$route.query.offerId as string;
|
this.offerId = this.$route.query.offerId as string;
|
||||||
this.projectId = this.$route.query.projectId as string;
|
this.projectId = this.$route.query.projectId as string;
|
||||||
|
this.recipientDid = this.$route.query.recipientDid as string;
|
||||||
|
this.recipientName = this.$route.query.recipientName as string;
|
||||||
|
if (this.recipientDid && !this.recipientName) {
|
||||||
|
this.recipientName =
|
||||||
|
this.recipientDid === this.activeDid ? "you" : "someone not named";
|
||||||
|
}
|
||||||
this.unitCode = this.$route.query.unitCode as string;
|
this.unitCode = this.$route.query.unitCode as string;
|
||||||
|
|
||||||
this.imageUrl = localStorage.getItem("imageUrl") || "";
|
this.imageUrl = localStorage.getItem("imageUrl") || "";
|
||||||
|
|
||||||
this.givenToUser = !this.projectId;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await db.open();
|
||||||
const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings;
|
const settings = (await db.settings.get(MASTER_SETTINGS_KEY)) as Settings;
|
||||||
this.apiServer = settings?.apiServer || "";
|
this.apiServer = settings?.apiServer || "";
|
||||||
this.activeDid = settings?.activeDid || "";
|
this.activeDid = settings?.activeDid || "";
|
||||||
|
|
||||||
|
this.givenToUser = this.recipientDid === this.activeDid;
|
||||||
|
this.showGivenToUser =
|
||||||
|
!this.projectId && this.recipientDid === this.activeDid;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Error retrieving settings from database:", err);
|
console.error("Error retrieving settings from database:", err);
|
||||||
@@ -358,12 +377,18 @@ export default class GiftedDetails extends Vue {
|
|||||||
public async recordGive() {
|
public async recordGive() {
|
||||||
try {
|
try {
|
||||||
const identity = await libsUtil.getIdentity(this.activeDid);
|
const identity = await libsUtil.getIdentity(this.activeDid);
|
||||||
|
const recipientDid =
|
||||||
|
this.recipientDid === this.activeDid
|
||||||
|
? this.givenToUser
|
||||||
|
? this.activeDid
|
||||||
|
: undefined
|
||||||
|
: this.recipientDid;
|
||||||
const result = await createAndSubmitGive(
|
const result = await createAndSubmitGive(
|
||||||
this.axios,
|
this.axios,
|
||||||
this.apiServer,
|
this.apiServer,
|
||||||
identity,
|
identity,
|
||||||
this.giverDid,
|
this.giverDid,
|
||||||
this.givenToUser ? this.activeDid : undefined,
|
recipientDid,
|
||||||
this.description,
|
this.description,
|
||||||
parseFloat(this.amountInput),
|
parseFloat(this.amountInput),
|
||||||
this.unitCode,
|
this.unitCode,
|
||||||
|
|||||||
@@ -154,13 +154,13 @@
|
|||||||
<router-link
|
<router-link
|
||||||
v-if="allContacts.length >= 7"
|
v-if="allContacts.length >= 7"
|
||||||
:to="{ name: 'contact-gives' }"
|
:to="{ name: 'contact-gives' }"
|
||||||
class="block text-center text-md font-bold 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-2 py-3 rounded-md"
|
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"
|
||||||
>
|
>
|
||||||
Choose From All Contacts
|
Choose From All Contacts
|
||||||
</router-link>
|
</router-link>
|
||||||
<button
|
<button
|
||||||
@click="openGiftedPrompts()"
|
@click="openGiftedPrompts()"
|
||||||
class="block 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-4 py-2 rounded-md"
|
class="block text-center text-md 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"
|
||||||
>
|
>
|
||||||
Ideas...
|
Ideas...
|
||||||
</button>
|
</button>
|
||||||
@@ -168,11 +168,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<GiftedDialog
|
<GiftedDialog ref="customDialog" message="Received from" />
|
||||||
ref="customDialog"
|
|
||||||
message="Received from"
|
|
||||||
showGivenToUser="true"
|
|
||||||
/>
|
|
||||||
<GiftedPrompts ref="giftedPrompts" />
|
<GiftedPrompts ref="giftedPrompts" />
|
||||||
<FeedFilters ref="feedFilters" />
|
<FeedFilters ref="feedFilters" />
|
||||||
|
|
||||||
@@ -181,7 +177,7 @@
|
|||||||
<div class="flex items-center mb-4">
|
<div class="flex items-center mb-4">
|
||||||
<h2 class="text-xl font-bold">Latest Activity</h2>
|
<h2 class="text-xl font-bold">Latest Activity</h2>
|
||||||
<button @click="openFeedFilters()" class="block text-center ml-auto">
|
<button @click="openFeedFilters()" class="block text-center ml-auto">
|
||||||
<span class="text-sm uppercase text-white">
|
<span class="text-sm text-white">
|
||||||
<span
|
<span
|
||||||
v-if="resultsAreFiltered()"
|
v-if="resultsAreFiltered()"
|
||||||
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] px-3 py-1.5 rounded-md"
|
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] px-3 py-1.5 rounded-md"
|
||||||
@@ -328,7 +324,7 @@ import {
|
|||||||
containsNonHiddenDid,
|
containsNonHiddenDid,
|
||||||
didInfoForContact,
|
didInfoForContact,
|
||||||
getPlanFromCache,
|
getPlanFromCache,
|
||||||
GiverInputInfo,
|
GiverReceiverInputInfo,
|
||||||
GiveSummaryRecord,
|
GiveSummaryRecord,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
import { generateSaveAndActivateIdentity } from "@/libs/util";
|
import { generateSaveAndActivateIdentity } from "@/libs/util";
|
||||||
@@ -722,8 +718,11 @@ export default class HomeView extends Vue {
|
|||||||
return unitCode === "HUR" ? (single ? "hour" : "hours") : unitCode;
|
return unitCode === "HUR" ? (single ? "hour" : "hours") : unitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
openDialog(giver?: GiverInputInfo) {
|
openDialog(giver?: GiverReceiverInputInfo) {
|
||||||
(this.$refs.customDialog as GiftedDialog).open(giver);
|
(this.$refs.customDialog as GiftedDialog).open(giver, {
|
||||||
|
did: this.activeDid,
|
||||||
|
name: "you",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
openGiftedPrompts() {
|
openGiftedPrompts() {
|
||||||
|
|||||||
@@ -363,7 +363,7 @@ import * as libsUtil from "@/libs/util";
|
|||||||
import {
|
import {
|
||||||
BLANK_GENERIC_SERVER_RECORD,
|
BLANK_GENERIC_SERVER_RECORD,
|
||||||
GenericCredWrapper,
|
GenericCredWrapper,
|
||||||
GiverInputInfo,
|
GiverReceiverInputInfo,
|
||||||
GiveSummaryRecord,
|
GiveSummaryRecord,
|
||||||
OfferSummaryRecord,
|
OfferSummaryRecord,
|
||||||
PlanSummaryRecord,
|
PlanSummaryRecord,
|
||||||
@@ -697,7 +697,7 @@ export default class ProjectViewView extends Vue {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
openGiftDialog(contact?: GiverInputInfo) {
|
openGiftDialog(contact?: GiverReceiverInputInfo) {
|
||||||
(this.$refs.customGiveDialog as GiftedDialog).open(contact);
|
(this.$refs.customGiveDialog as GiftedDialog).open(contact);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,10 +736,14 @@ export default class ProjectViewView extends Vue {
|
|||||||
claim: offer.fullClaim,
|
claim: offer.fullClaim,
|
||||||
issuer: offer.offeredByDid,
|
issuer: offer.offeredByDid,
|
||||||
};
|
};
|
||||||
const giver: GiverInputInfo = {
|
const giver: GiverReceiverInputInfo = {
|
||||||
did: libsUtil.offerGiverDid(offerRecord),
|
did: libsUtil.offerGiverDid(offerRecord),
|
||||||
};
|
};
|
||||||
(this.$refs.customGiveDialog as GiftedDialog).open(giver, offer.handleId);
|
(this.$refs.customGiveDialog as GiftedDialog).open(
|
||||||
|
giver,
|
||||||
|
undefined,
|
||||||
|
offer.handleId,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return an HTTPS URL if it's not a global URL
|
// return an HTTPS URL if it's not a global URL
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ export default class ProjectsView extends Vue {
|
|||||||
try {
|
try {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
const resp = await this.axios.get(url, { headers });
|
const resp = await this.axios.get(url, { headers });
|
||||||
if (resp.status === 200 || !resp.data.data) {
|
if (resp.status === 200 && resp.data.data) {
|
||||||
const plans: PlanData[] = resp.data.data;
|
const plans: PlanData[] = resp.data.data;
|
||||||
for (const plan of plans) {
|
for (const plan of plans) {
|
||||||
const { name, description, handleId, issuerDid, rowid } = plan;
|
const { name, description, handleId, issuerDid, rowid } = plan;
|
||||||
@@ -423,7 +423,7 @@ export default class ProjectsView extends Vue {
|
|||||||
try {
|
try {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
const resp = await this.axios.get(url, { headers });
|
const resp = await this.axios.get(url, { headers });
|
||||||
if (resp.status === 200 || !resp.data.data) {
|
if (resp.status === 200 && resp.data.data) {
|
||||||
this.offers = this.offers.concat(resp.data.data);
|
this.offers = this.offers.concat(resp.data.data);
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ export default class QuickActionBvcBeginView extends Vue {
|
|||||||
todayOrPreviousStartDate = "";
|
todayOrPreviousStartDate = "";
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
// use the time zone for Bountiful
|
||||||
let currentOrPreviousSat = DateTime.now().setZone("America/Denver");
|
let currentOrPreviousSat = DateTime.now().setZone("America/Denver");
|
||||||
if (currentOrPreviousSat.weekday < 6) {
|
if (currentOrPreviousSat.weekday < 6) {
|
||||||
// it's not Saturday or Sunday,
|
// it's not Saturday or Sunday,
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ export default class QuickActionBvcBeginView extends Vue {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.log("Bad response", response);
|
console.error("Bad response", response);
|
||||||
throw new Error("Bad response when retrieving claims.");
|
throw new Error("Bad response when retrieving claims.");
|
||||||
}
|
}
|
||||||
await response.json().then((data) => {
|
await response.json().then((data) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user