Browse Source

refactor: improve router type safety and usage

- Add explicit Router type imports across views
- Replace $router type casting with proper typing
- Use $router.back() instead of $router.go(-1) for consistency
- Add proper route and router typings to components
- Clean up router navigation methods
- Fix router push/back method calls

This commit improves type safety and consistency in router usage across
the application's view components.
side_step
Matthew Raymer 2 weeks ago
parent
commit
f6802cd160
  1. 20
      src/App.vue
  2. 3
      src/components/FeedFilters.vue
  3. 3
      src/components/GiftedPrompts.vue
  4. 5
      src/components/HiddenDidDialog.vue
  5. 6
      src/components/ImageMethodDialog.vue
  6. 3
      src/components/OnboardingDialog.vue
  7. 4
      src/components/PushNotificationPermission.vue
  8. 1
      src/interfaces/records.ts
  9. 60
      src/lib/capacitor/app.ts
  10. 6
      src/main.capacitor.ts
  11. 53
      src/views/AccountViewView.vue
  12. 5
      src/views/ClaimCertificateView.vue
  13. 75
      src/views/ClaimView.vue
  14. 45
      src/views/ConfirmGiftView.vue
  15. 22
      src/views/ContactAmountsView.vue
  16. 6
      src/views/ContactEditView.vue
  17. 9
      src/views/ContactGiftingView.vue
  18. 9
      src/views/ContactImportView.vue
  19. 2
      src/views/ContactQRScanShowView.vue
  20. 40
      src/views/ContactsView.vue
  21. 35
      src/views/DIDView.vue
  22. 17
      src/views/DiscoverView.vue
  23. 31
      src/views/GiftedDetailsView.vue
  24. 3
      src/views/HelpNotificationsView.vue
  25. 18
      src/views/HelpOnboardingView.vue
  26. 3
      src/views/HelpView.vue
  27. 5
      src/views/HomeView.vue
  28. 13
      src/views/IdentitySwitcherView.vue
  29. 5
      src/views/ImportAccountView.vue
  30. 9
      src/views/ImportDerivedAccountView.vue
  31. 3
      src/views/InviteOneAcceptView.vue
  32. 2
      src/views/InviteOneView.vue
  33. 16
      src/views/NewActivityView.vue
  34. 8
      src/views/NewEditAccountView.vue
  35. 12
      src/views/NewEditProjectView.vue
  36. 3
      src/views/NewIdentifierView.vue
  37. 13
      src/views/OfferDetailsView.vue
  38. 3
      src/views/OnboardMeetingListView.vue
  39. 12
      src/views/OnboardMeetingMembersView.vue
  40. 3
      src/views/OnboardMeetingSetupView.vue
  41. 92
      src/views/ProjectViewView.vue
  42. 24
      src/views/ProjectsView.vue
  43. 4
      src/views/QuickActionBvcBeginView.vue
  44. 8
      src/views/QuickActionBvcEndView.vue
  45. 6
      src/views/QuickActionBvcView.vue
  46. 10
      src/views/RecentOffersToUserProjectsView.vue
  47. 11
      src/views/RecentOffersToUserView.vue
  48. 3
      src/views/SearchAreaView.vue
  49. 14
      src/views/SeedBackupView.vue
  50. 3
      src/views/ShareMyContactInfoView.vue
  51. 18
      src/views/SharedPhotoView.vue
  52. 9
      src/views/StartView.vue
  53. 3
      src/views/StatisticsView.vue
  54. 2
      src/views/TestView.vue
  55. 2
      src/views/UserProfileView.vue

20
src/App.vue

@ -40,7 +40,10 @@
<div <div
class="flex items-center justify-center w-12 bg-slate-600 text-slate-100" class="flex items-center justify-center w-12 bg-slate-600 text-slate-100"
> >
<font-awesome icon="circle-info" class="fa-fw fa-xl"></font-awesome> <font-awesome
icon="circle-info"
class="fa-fw fa-xl"
></font-awesome>
</div> </div>
<div class="relative w-full pl-4 pr-8 py-2 text-slate-900"> <div class="relative w-full pl-4 pr-8 py-2 text-slate-900">
@ -63,7 +66,10 @@
<div <div
class="flex items-center justify-center w-12 bg-emerald-600 text-emerald-100" class="flex items-center justify-center w-12 bg-emerald-600 text-emerald-100"
> >
<font-awesome icon="circle-info" class="fa-fw fa-xl"></font-awesome> <font-awesome
icon="circle-info"
class="fa-fw fa-xl"
></font-awesome>
</div> </div>
<div class="relative w-full pl-4 pr-8 py-2 text-emerald-900"> <div class="relative w-full pl-4 pr-8 py-2 text-emerald-900">
@ -86,7 +92,10 @@
<div <div
class="flex items-center justify-center w-12 bg-amber-600 text-amber-100" class="flex items-center justify-center w-12 bg-amber-600 text-amber-100"
> >
<font-awesome icon="triangle-exclamation" class="fa-fw fa-xl"></font-awesome> <font-awesome
icon="triangle-exclamation"
class="fa-fw fa-xl"
></font-awesome>
</div> </div>
<div class="relative w-full pl-4 pr-8 py-2 text-amber-900"> <div class="relative w-full pl-4 pr-8 py-2 text-amber-900">
@ -109,7 +118,10 @@
<div <div
class="flex items-center justify-center w-12 bg-rose-600 text-rose-100" class="flex items-center justify-center w-12 bg-rose-600 text-rose-100"
> >
<font-awesome icon="triangle-exclamation" class="fa-fw fa-xl"></font-awesome> <font-awesome
icon="triangle-exclamation"
class="fa-fw fa-xl"
></font-awesome>
</div> </div>
<div class="relative w-full pl-4 pr-8 py-2 text-rose-900"> <div class="relative w-full pl-4 pr-8 py-2 text-rose-900">

3
src/components/FeedFilters.vue

@ -98,7 +98,7 @@ import {
LRectangle, LRectangle,
LTileLayer, LTileLayer,
} from "@vue-leaflet/vue-leaflet"; } from "@vue-leaflet/vue-leaflet";
import { Router } from "vue-router";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
@ -111,6 +111,7 @@ import { db, retrieveSettingsForActiveAccount } from "../db/index";
}, },
}) })
export default class FeedFilters extends Vue { export default class FeedFilters extends Vue {
$router!: Router;
onCloseIfChanged = () => {}; onCloseIfChanged = () => {};
hasSearchBox = false; hasSearchBox = false;
hasVisibleDid = false; hasVisibleDid = false;

3
src/components/GiftedPrompts.vue

@ -82,6 +82,7 @@ import { GiverReceiverInputInfo } from "../libs/util";
@Component @Component
export default class GivenPrompts extends Vue { export default class GivenPrompts extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
CATEGORY_CONTACTS = 1; CATEGORY_CONTACTS = 1;
CATEGORY_IDEAS = 0; CATEGORY_IDEAS = 0;
@ -145,7 +146,7 @@ export default class GivenPrompts extends Vue {
// proceed with logic but don't change values (just in case some actions are added later) // proceed with logic but don't change values (just in case some actions are added later)
this.visible = false; this.visible = false;
if (this.currentCategory === this.CATEGORY_IDEAS) { if (this.currentCategory === this.CATEGORY_IDEAS) {
(this.$router as Router).push({ this.$router.push({
name: "contact-gift", name: "contact-gift",
query: { query: {
prompt: this.IDEAS[this.currentIdeaIndex], prompt: this.IDEAS[this.currentIdeaIndex],

5
src/components/HiddenDidDialog.vue

@ -53,7 +53,10 @@
target="_blank" target="_blank"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="arrow-up-right-from-square" class="fa-fw" /> <font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a> </a>
</span> </span>
</span> </span>

6
src/components/ImageMethodDialog.vue

@ -41,7 +41,11 @@
@click="acceptUrl" @click="acceptUrl"
/> />
<!-- so that there's no shifting when it becomes visible --> <!-- so that there's no shifting when it becomes visible -->
<font-awesome v-else icon="check" class="text-white bg-white px-2 py-2" /> <font-awesome
v-else
icon="check"
class="text-white bg-white px-2 py-2"
/>
</span> </span>
</div> </div>
</div> </div>

3
src/components/OnboardingDialog.vue

@ -219,6 +219,7 @@ import { OnboardPage } from "../libs/util";
}) })
export default class OnboardingDialog extends Vue { export default class OnboardingDialog extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid = ""; activeDid = "";
firstContactName = null; firstContactName = null;
@ -254,7 +255,7 @@ export default class OnboardingDialog extends Vue {
finishedOnboarding: true, finishedOnboarding: true,
}); });
if (goHome) { if (goHome) {
(this.$router as Router).push({ name: "home" }); this.$router.push({ name: "home" });
} }
} }
} }

4
src/components/PushNotificationPermission.vue

@ -69,7 +69,9 @@
class="rounded-r border border-slate-400 bg-slate-200 text-center text-blue-500 mt-2 px-2 py-2 w-20" class="rounded-r border border-slate-400 bg-slate-200 text-center text-blue-500 mt-2 px-2 py-2 w-20"
@click="hourAm = !hourAm" @click="hourAm = !hourAm"
> >
<span v-if="hourAm"> AM <font-awesome icon="chevron-down" /> </span> <span v-if="hourAm">
AM <font-awesome icon="chevron-down" />
</span>
<span v-else> PM <font-awesome icon="chevron-up" /> </span> <span v-else> PM <font-awesome icon="chevron-up" /> </span>
</span> </span>
</span> </span>

1
src/interfaces/records.ts

@ -2,6 +2,7 @@ import { GiveVerifiableCredential, OfferVerifiableCredential } from "./claims";
// a summary record; the VC is found the fullClaim field // a summary record; the VC is found the fullClaim field
export interface GiveSummaryRecord { export interface GiveSummaryRecord {
[x: string]: PropertyKey | undefined | GiveVerifiableCredential;
type?: string; type?: string;
agentDid: string; agentDid: string;
amount: number; amount: number;

60
src/lib/capacitor/app.ts

@ -1,9 +1,59 @@
// Import from node_modules using relative path // Import from node_modules using relative path
import { App as CapacitorApp } from '../../../node_modules/@capacitor/app';
// Re-export the App interface with our own wrapper import {
export const App = { App as CapacitorApp,
addListener: (eventName: string, listenerFunc: (data: any) => void) => { AppLaunchUrl,
return CapacitorApp.addListener(eventName, listenerFunc); BackButtonListener,
} from "@capacitor/app";
import type { PluginListenerHandle } from "@capacitor/core";
/**
* Interface defining the app event listener functionality
* Supports 'backButton' and 'appUrlOpen' events from Capacitor
*/
interface AppInterface {
/**
* Add listener for back button events
* @param eventName - Must be 'backButton'
* @param listenerFunc - Callback function for back button events
* @returns Promise that resolves with a removable listener handle
*/
addListener(
eventName: "backButton",
listenerFunc: BackButtonListener,
): Promise<PluginListenerHandle> & PluginListenerHandle;
/**
* Add listener for app URL open events
* @param eventName - Must be 'appUrlOpen'
* @param listenerFunc - Callback function for URL open events
* @returns Promise that resolves with a removable listener handle
*/
addListener(
eventName: "appUrlOpen",
listenerFunc: (data: AppLaunchUrl) => void,
): Promise<PluginListenerHandle> & PluginListenerHandle;
}
/**
* App wrapper for Capacitor functionality
* Provides type-safe event listeners for back button and URL open events
*/
export const App: AppInterface = {
addListener(
eventName: "backButton" | "appUrlOpen",
listenerFunc: BackButtonListener | ((data: AppLaunchUrl) => void),
): Promise<PluginListenerHandle> & PluginListenerHandle {
if (eventName === "backButton") {
return CapacitorApp.addListener(
eventName,
listenerFunc as BackButtonListener,
) as Promise<PluginListenerHandle> & PluginListenerHandle;
} else {
return CapacitorApp.addListener(
eventName,
listenerFunc as (data: AppLaunchUrl) => void,
) as Promise<PluginListenerHandle> & PluginListenerHandle;
} }
},
}; };

6
src/main.capacitor.ts

@ -97,14 +97,14 @@ const handleDeepLink = async (data: { url: string }) => {
const paramRoutes = { const paramRoutes = {
"claim-add-raw": /^claim-add-raw\/(.+)$/, "claim-add-raw": /^claim-add-raw\/(.+)$/,
"claim-cert": /^claim-cert\/(.+)$/, "claim-cert": /^claim-cert\/(.+)$/,
"claim": /^claim\/(.+)$/, claim: /^claim\/(.+)$/,
"confirm-gift": /^confirm-gift\/(.+)$/, "confirm-gift": /^confirm-gift\/(.+)$/,
"contact-edit": /^contact-edit\/(.+)$/, "contact-edit": /^contact-edit\/(.+)$/,
"contact-import": /^contact-import\/(.+)$/, "contact-import": /^contact-import\/(.+)$/,
"did": /^did\/(.+)$/, did: /^did\/(.+)$/,
"invite-one-accept": /^invite-one-accept\/(.+)$/, "invite-one-accept": /^invite-one-accept\/(.+)$/,
"offer-details": /^offer-details\/(.+)$/, "offer-details": /^offer-details\/(.+)$/,
"project": /^project\/(.+)$/, project: /^project\/(.+)$/,
"user-profile": /^user-profile\/(.+)$/, "user-profile": /^user-profile\/(.+)$/,
}; };

53
src/views/AccountViewView.vue

@ -44,7 +44,10 @@
</span> </span>
{{ givenName }} {{ givenName }}
<router-link :to="{ name: 'new-edit-account' }"> <router-link :to="{ name: 'new-edit-account' }">
<font-awesome icon="pen" class="text-xs text-blue-500 ml-2 mb-1"></font-awesome> <font-awesome
icon="pen"
class="text-xs text-blue-500 ml-2 mb-1"
></font-awesome>
</router-link> </router-link>
</h2> </h2>
</div> </div>
@ -268,8 +271,11 @@
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8" class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
> >
<div v-if="loadingProfile" class="text-center mb-2"> <div v-if="loadingProfile" class="text-center mb-2">
<font-awesome icon="spinner" class="fa-spin text-slate-400"></font-awesome> Loading <font-awesome
profile... icon="spinner"
class="fa-spin text-slate-400"
></font-awesome>
Loading profile...
</div> </div>
<div v-else class="flex items-center mb-2"> <div v-else class="flex items-center mb-2">
<span class="font-bold">Public Profile</span> <span class="font-bold">Public Profile</span>
@ -363,7 +369,8 @@
<div class="mb-2 font-bold">Usage Limits</div> <div class="mb-2 font-bold">Usage Limits</div>
<!-- show spinner if loading limits --> <!-- show spinner if loading limits -->
<div v-if="loadingLimits" class="text-center"> <div v-if="loadingLimits" class="text-center">
Checking&hellip; <font-awesome icon="spinner" class="fa-spin"></font-awesome> Checking&hellip;
<font-awesome icon="spinner" class="fa-spin"></font-awesome>
</div> </div>
<div class="mb-4 text-center"> <div class="mb-4 text-center">
{{ limitsMessage }} {{ limitsMessage }}
@ -494,7 +501,10 @@
" "
class="ml-2" class="ml-2"
> >
<font-awesome icon="copy" class="text-slate-400 fa-fw"></font-awesome> <font-awesome
icon="copy"
class="text-slate-400 fa-fw"
></font-awesome>
</button> </button>
<span v-show="showB64Copy">Copied</span> <span v-show="showB64Copy">Copied</span>
</div> </div>
@ -510,7 +520,10 @@
" "
class="ml-2" class="ml-2"
> >
<font-awesome icon="copy" class="text-slate-400 fa-fw"></font-awesome> <font-awesome
icon="copy"
class="text-slate-400 fa-fw"
></font-awesome>
</button> </button>
<span v-show="showPubCopy">Copied</span> <span v-show="showPubCopy">Copied</span>
</div> </div>
@ -530,7 +543,10 @@
" "
class="ml-2" class="ml-2"
> >
<font-awesome icon="copy" class="text-slate-400 fa-fw"></font-awesome> <font-awesome
icon="copy"
class="text-slate-400 fa-fw"
></font-awesome>
</button> </button>
<span v-show="showDerCopy">Copied</span> <span v-show="showDerCopy">Copied</span>
</div> </div>
@ -631,7 +647,11 @@
class="w-full px-4 rounded bg-yellow-500 border border-slate-400" class="w-full px-4 rounded bg-yellow-500 border border-slate-400"
@click="onClickSaveApiServer()" @click="onClickSaveApiServer()"
> >
<font-awesome icon="floppy-disk" class="fa-fw" color="white"></font-awesome> <font-awesome
icon="floppy-disk"
class="fa-fw"
color="white"
></font-awesome>
</button> </button>
<button <button
class="px-3 rounded bg-slate-200 border border-slate-400" class="px-3 rounded bg-slate-200 border border-slate-400"
@ -708,7 +728,11 @@
class="w-full px-4 rounded bg-yellow-500 border border-slate-400" class="w-full px-4 rounded bg-yellow-500 border border-slate-400"
@click="onClickSavePushServer()" @click="onClickSavePushServer()"
> >
<font-awesome icon="floppy-disk" class="fa-fw" color="white"></font-awesome> <font-awesome
icon="floppy-disk"
class="fa-fw"
color="white"
></font-awesome>
</button> </button>
<button <button
class="px-3 rounded bg-slate-200 border border-slate-400" class="px-3 rounded bg-slate-200 border border-slate-400"
@ -747,7 +771,11 @@
class="w-full px-4 rounded bg-yellow-500 border border-slate-400" class="w-full px-4 rounded bg-yellow-500 border border-slate-400"
@click="onClickSavePartnerServer()" @click="onClickSavePartnerServer()"
> >
<font-awesome icon="floppy-disk" class="fa-fw" color="white"></font-awesome> <font-awesome
icon="floppy-disk"
class="fa-fw"
color="white"
></font-awesome>
</button> </button>
<button <button
class="px-3 rounded bg-slate-200 border border-slate-400" class="px-3 rounded bg-slate-200 border border-slate-400"
@ -901,7 +929,7 @@ import * as R from "ramda";
import { IIdentifier } from "@veramo/core"; import { IIdentifier } from "@veramo/core";
import { ref } from "vue"; import { ref } from "vue";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import { useClipboard } from "@vueuse/core"; import { useClipboard } from "@vueuse/core";
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet"; import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
@ -947,6 +975,7 @@ import {
DIRECT_PUSH_TITLE, DIRECT_PUSH_TITLE,
retrieveAccountMetadata, retrieveAccountMetadata,
} from "../libs/util"; } from "../libs/util";
import { UserProfile } from "@/libs/partnerServer";
const inputImportFileNameRef = ref<Blob>(); const inputImportFileNameRef = ref<Blob>();
@ -966,6 +995,8 @@ const inputImportFileNameRef = ref<Blob>();
}) })
export default class AccountViewView extends Vue { export default class AccountViewView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
AppConstants = AppString; AppConstants = AppString;
DEFAULT_PUSH_SERVER = DEFAULT_PUSH_SERVER; DEFAULT_PUSH_SERVER = DEFAULT_PUSH_SERVER;

5
src/views/ClaimCertificateView.vue

@ -14,11 +14,10 @@
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { nextTick } from "vue"; import { nextTick } from "vue";
import QRCode from "qrcode"; import QRCode from "qrcode";
import { GenericVerifiableCredential } from "../interfaces";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_SERVER, NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import { GenericCredWrapper, GenericVerifiableCredential } from "../interfaces";
@Component @Component
export default class ClaimCertificateView extends Vue { export default class ClaimCertificateView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
@ -81,7 +80,7 @@ export default class ClaimCertificateView extends Vue {
} }
async drawCanvas( async drawCanvas(
claimData: serverUtil.GenericCredWrapper<GenericVerifiableCredential>, claimData: GenericCredWrapper<GenericVerifiableCredential>,
confirmerIds: Array<string>, confirmerIds: Array<string>,
) { ) {
await db.open(); await db.open();

75
src/views/ClaimView.vue

@ -22,7 +22,9 @@
<div class="w-full"> <div class="w-full">
<div class="flex columns-3"> <div class="flex columns-3">
<h2 class="text-md font-bold w-full"> <h2 class="text-md font-bold w-full">
{{ capitalizeAndInsertSpacesBeforeCaps(veriClaim.claimType || '') }} {{
capitalizeAndInsertSpacesBeforeCaps(veriClaim.claimType || "")
}}
<button <button
v-if=" v-if="
['GiveAction', 'Offer', 'PlanAction'].includes( ['GiveAction', 'Offer', 'PlanAction'].includes(
@ -36,7 +38,10 @@
title="Edit" title="Edit"
data-testId="editClaimButton" data-testId="editClaimButton"
> >
<font-awesome icon="pen" class="text-sm text-blue-500 ml-2 mb-1" /> <font-awesome
icon="pen"
class="text-sm text-blue-500 ml-2 mb-1"
/>
</button> </button>
</h2> </h2>
<div class="flex justify-center w-full"> <div class="flex justify-center w-full">
@ -45,7 +50,10 @@
class="text-blue-500 mt-2" class="text-blue-500 mt-2"
title="Printable Certificate" title="Printable Certificate"
> >
<font-awesome icon="square" class="text-white bg-yellow-500 p-1" /> <font-awesome
icon="square"
class="text-white bg-yellow-500 p-1"
/>
</router-link> </router-link>
</div> </div>
<!-- show link icon to copy this URL to the clipboard --> <!-- show link icon to copy this URL to the clipboard -->
@ -66,7 +74,7 @@
{{ {{
(veriClaim.claim?.itemOffered as any)?.description || (veriClaim.claim?.itemOffered as any)?.description ||
(veriClaim.claim as any)?.description || (veriClaim.claim as any)?.description ||
'' ""
}} }}
</div> </div>
<div> <div>
@ -78,9 +86,15 @@
Recorded Recorded
{{ veriClaim.issuedAt?.replace(/T/, " ").replace(/Z/, " UTC") }} {{ veriClaim.issuedAt?.replace(/T/, " ").replace(/Z/, " UTC") }}
</div> </div>
<div v-if="(veriClaim.claim as any).image" class="flex justify-center"> <div
v-if="(veriClaim.claim as any).image"
class="flex justify-center"
>
<a :href="(veriClaim.claim as any).image" target="_blank"> <a :href="(veriClaim.claim as any).image" target="_blank">
<img :src="(veriClaim.claim as any).image" class="h-24 rounded-xl" /> <img
:src="(veriClaim.claim as any).image"
class="h-24 rounded-xl"
/>
</a> </a>
</div> </div>
@ -197,7 +211,10 @@
class="col-span-1 block w-fit text-center text-md 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-1.5 py-2 rounded-md" class="col-span-1 block w-fit text-center text-md 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-1.5 py-2 rounded-md"
> >
Affirm Delivery Affirm Delivery
<font-awesome icon="hand-holding-heart" class="ml-2 text-white cursor-pointer" /> <font-awesome
icon="hand-holding-heart"
class="ml-2 text-white cursor-pointer"
/>
</button> </button>
</div> </div>
<GiftedDialog ref="customGiveDialog" /> <GiftedDialog ref="customGiveDialog" />
@ -217,7 +234,10 @@
@click="confirmConfirmClaim()" @click="confirmConfirmClaim()"
> >
Confirm Confirm
<font-awesome icon="circle-check" class="ml-2 text-white cursor-pointer" /> <font-awesome
icon="circle-check"
class="ml-2 text-white cursor-pointer"
/>
</button> </button>
<h2 v-else class="font-bold uppercase text-xl mt-2">Confirmations</h2> <h2 v-else class="font-bold uppercase text-xl mt-2">Confirmations</h2>
@ -277,7 +297,10 @@
target="_blank" target="_blank"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="arrow-up-right-from-square" class="fa-fw" /> <font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a> </a>
</span> </span>
</div> </div>
@ -315,7 +338,10 @@
target="_blank" target="_blank"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="arrow-up-right-from-square" class="fa-fw" /> <font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a> </a>
</span> </span>
</div> </div>
@ -428,7 +454,10 @@
target="_blank" target="_blank"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="arrow-up-right-from-square" class="fa-fw" /> <font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a> </a>
</span> </span>
<span v-if="veriClaim.publicUrls?.[visDid]" <span v-if="veriClaim.publicUrls?.[visDid]"
@ -522,8 +551,8 @@ import * as serverUtil from "../libs/endorserServer";
import { import {
GenericCredWrapper, GenericCredWrapper,
OfferVerifiableCredential, OfferVerifiableCredential,
ProviderInfo ProviderInfo,
} from '../interfaces'; } from "../interfaces";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
@Component({ @Component({
@ -543,7 +572,11 @@ export default class ClaimView extends Vue {
confirmerIdList: string[] = []; // list of DIDs that have confirmed this claim excluding the issuer confirmerIdList: string[] = []; // list of DIDs that have confirmed this claim excluding the issuer
confsVisibleErrorMessage = ""; confsVisibleErrorMessage = "";
confsVisibleToIdList: string[] = []; // list of DIDs that can see any confirmer confsVisibleToIdList: string[] = []; // list of DIDs that can see any confirmer
detailsForGive: { fulfillsPlanHandleId?: string; fulfillsType?: string; fulfillsHandleId?: string } | null = null; detailsForGive: {
fulfillsPlanHandleId?: string;
fulfillsType?: string;
fulfillsHandleId?: string;
} | null = null;
detailsForOffer: { fulfillsPlanHandleId?: string } | null = null; detailsForOffer: { fulfillsPlanHandleId?: string } | null = null;
fullClaim = null; fullClaim = null;
fullClaimDump = ""; fullClaimDump = "";
@ -598,24 +631,30 @@ export default class ClaimView extends Vue {
"Error retrieving all account DIDs on home page:" + error, "Error retrieving all account DIDs on home page:" + error,
true, true,
); );
this.$notify({ this.$notify(
{
group: "alert", group: "alert",
type: "danger", type: "danger",
title: "Error Loading Profile", title: "Error Loading Profile",
text: "See the Help page for problems with your personal data.", text: "See the Help page for problems with your personal data.",
}, 5000); },
5000,
);
} }
const claimId = this.$route.params.id as string; const claimId = this.$route.params.id as string;
if (claimId) { if (claimId) {
await this.loadClaim(claimId, this.activeDid); await this.loadClaim(claimId, this.activeDid);
} else { } else {
this.$notify({ this.$notify(
{
group: "alert", group: "alert",
type: "danger", type: "danger",
title: "Error", title: "Error",
text: "No claim ID was provided.", text: "No claim ID was provided.",
}, 5000); },
5000,
);
} }
this.canShare = !!navigator.share; this.canShare = !!navigator.share;

45
src/views/ConfirmGiftView.vue

@ -44,7 +44,10 @@
@click="confirmConfirmClaim()" @click="confirmConfirmClaim()"
> >
Confirm Confirm
<font-awesome icon="circle-check" class="ml-2 text-white cursor-pointer" /> <font-awesome
icon="circle-check"
class="ml-2 text-white cursor-pointer"
/>
</button> </button>
<button <button
v-else v-else
@ -52,7 +55,10 @@
class="col-span-1 bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md" class="col-span-1 bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-4 py-2 rounded-md"
> >
Confirm Confirm
<font-awesome icon="circle-check" class="ml-2 text-white cursor-pointer" /> <font-awesome
icon="circle-check"
class="ml-2 text-white cursor-pointer"
/>
</button> </button>
</div> </div>
@ -67,7 +73,10 @@
</div> </div>
<div class="ml-6">gave</div> <div class="ml-6">gave</div>
<div v-if="giveDetails.amount"> <div v-if="giveDetails.amount">
<font-awesome icon="hand-holding-dollar" class="fa-fw text-slate-400" /> <font-awesome
icon="hand-holding-dollar"
class="fa-fw text-slate-400"
/>
{{ displayAmount(giveDetails.unit, giveDetails.amount) }} {{ displayAmount(giveDetails.unit, giveDetails.amount) }}
</div> </div>
<div v-if="giveDetails.description"> <div v-if="giveDetails.description">
@ -99,7 +108,10 @@
target="_blank" target="_blank"
> >
This fulfills a bigger plan This fulfills a bigger plan
<font-awesome icon="arrow-up-right-from-square" class="fa-fw" /> <font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</router-link> </router-link>
</div> </div>
<!-- if there's another, it's probably fulfilling an offer, too --> <!-- if there's another, it's probably fulfilling an offer, too -->
@ -125,7 +137,10 @@
giveDetails?.fulfillsType || "", giveDetails?.fulfillsType || "",
) )
}} }}
<font-awesome icon="arrow-up-right-from-square" class="fa-fw" /> <font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</router-link> </router-link>
</div> </div>
</div> </div>
@ -185,7 +200,10 @@
) )
" "
> >
<font-awesome icon="copy" class="text-slate-400 fa-fw" /> <font-awesome
icon="copy"
class="text-slate-400 fa-fw"
/>
</button> </button>
</span> </span>
</div> </div>
@ -228,7 +246,10 @@
) )
" "
> >
<font-awesome icon="copy" class="text-slate-400 fa-fw" /> <font-awesome
icon="copy"
class="text-slate-400 fa-fw"
/>
</button> </button>
</span> </span>
</div> </div>
@ -342,12 +363,18 @@
copyToClipboard('The DID of ' + visDid, visDid) copyToClipboard('The DID of ' + visDid, visDid)
" "
> >
<font-awesome icon="copy" class="text-slate-400 fa-fw" /> <font-awesome
icon="copy"
class="text-slate-400 fa-fw"
/>
</button> </button>
</span> </span>
<span v-if="veriClaim.publicUrls?.[visDid]" <span v-if="veriClaim.publicUrls?.[visDid]"
>, found at >, found at
<font-awesome icon="globe" class="fa-fw text-slate-400" /> <font-awesome
icon="globe"
class="fa-fw text-slate-400"
/>
<a <a
:href="veriClaim.publicUrls?.[visDid]" :href="veriClaim.publicUrls?.[visDid]"
class="text-blue-500" class="text-blue-500"

22
src/views/ContactAmountsView.vue

@ -59,7 +59,10 @@
<div class="font-bold"> <div class="font-bold">
{{ displayAmount(record.unit, record.amount) }} {{ displayAmount(record.unit, record.amount) }}
<span v-if="record.amountConfirmed" title="Confirmed"> <span v-if="record.amountConfirmed" title="Confirmed">
<font-awesome icon="circle-check" class="text-green-600 fa-fw" /> <font-awesome
icon="circle-check"
class="text-green-600 fa-fw"
/>
</span> </span>
<button v-else @click="confirm(record)" title="Unconfirmed"> <button v-else @click="confirm(record)" title="Unconfirmed">
<font-awesome icon="circle" class="text-blue-600 fa-fw" /> <font-awesome icon="circle" class="text-blue-600 fa-fw" />
@ -83,7 +86,10 @@
<div class="font-bold"> <div class="font-bold">
{{ displayAmount(record.unit, record.amount) }} {{ displayAmount(record.unit, record.amount) }}
<span v-if="record.amountConfirmed" title="Confirmed"> <span v-if="record.amountConfirmed" title="Confirmed">
<font-awesome icon="circle-check" class="text-green-600 fa-fw" /> <font-awesome
icon="circle-check"
class="text-green-600 fa-fw"
/>
</span> </span>
<button <button
v-else v-else
@ -108,7 +114,7 @@
import { AxiosError, AxiosRequestHeaders } from "axios"; import { AxiosError, AxiosRequestHeaders } from "axios";
import * as R from "ramda"; import * as R from "ramda";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
@ -116,11 +122,13 @@ import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { import {
AgreeVerifiableCredential, AgreeVerifiableCredential,
GiveSummaryRecord,
GiveVerifiableCredential,
} from "../interfaces";
import {
createEndorserJwtVcFromClaim, createEndorserJwtVcFromClaim,
displayAmount, displayAmount,
getHeaders, getHeaders,
GiveSummaryRecord,
GiveVerifiableCredential,
SCHEMA_ORG_CONTEXT, SCHEMA_ORG_CONTEXT,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { retrieveAccountCount } from "../libs/util"; import { retrieveAccountCount } from "../libs/util";
@ -128,6 +136,8 @@ import { retrieveAccountCount } from "../libs/util";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class ContactAmountssView extends Vue { export default class ContactAmountssView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
activeDid = ""; activeDid = "";
apiServer = ""; apiServer = "";
@ -143,7 +153,7 @@ export default class ContactAmountssView extends Vue {
async created() { async created() {
try { try {
const contactDid = (this.$route as Router).query["contactDid"] as string; const contactDid = this.$route.query["contactDid"] as string;
this.contact = (await db.contacts.get(contactDid)) || null; this.contact = (await db.contacts.get(contactDid)) || null;
const settings = await retrieveSettingsForActiveAccount(); const settings = await retrieveSettingsForActiveAccount();

6
src/views/ContactEditView.vue

@ -134,7 +134,7 @@
<script lang="ts"> <script lang="ts">
import * as R from "ramda"; import * as R from "ramda";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { RouteLocation, Router } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
@ -150,6 +150,8 @@ import { Contact, ContactMethod } from "../db/tables/contacts";
}) })
export default class ContactEditView extends Vue { export default class ContactEditView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
contact: Contact = { contact: Contact = {
did: "", did: "",
@ -164,7 +166,7 @@ export default class ContactEditView extends Vue {
AppString = AppString; AppString = AppString;
async created() { async created() {
const contactDid = (this.$route as RouteLocation).params.did; const contactDid = this.$route.params.did;
const contact = await db.contacts.get(contactDid || ""); const contact = await db.contacts.get(contactDid || "");
if (contact) { if (contact) {
this.contact = contact; this.contact = contact;

9
src/views/ContactGiftingView.vue

@ -71,7 +71,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import GiftedDialog from "../components/GiftedDialog.vue"; import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
@ -86,6 +86,8 @@ import { GiverReceiverInputInfo } from "../libs/util";
}) })
export default class ContactGiftingView extends Vue { export default class ContactGiftingView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
activeDid = ""; activeDid = "";
allContacts: Array<Contact> = []; allContacts: Array<Contact> = [];
@ -107,9 +109,8 @@ export default class ContactGiftingView extends Vue {
(a.name || "").localeCompare(b.name || ""), (a.name || "").localeCompare(b.name || ""),
); );
this.projectId = (this.$route as Router).query["projectId"] || ""; this.projectId = (this.$route.query["projectId"] as string) || "";
this.prompt = (this.$route.query["prompt"] as string) ?? this.prompt;
this.prompt = (this.$route as Router).query["prompt"] ?? this.prompt;
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) { } catch (err: any) {

9
src/views/ContactImportView.vue

@ -150,6 +150,8 @@ import { decodeEndorserJwt } from "../libs/crypto/vc";
}) })
export default class ContactImportView extends Vue { export default class ContactImportView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
AppString = AppString; AppString = AppString;
capitalizeAndInsertSpacesBeforeCaps = capitalizeAndInsertSpacesBeforeCaps; capitalizeAndInsertSpacesBeforeCaps = capitalizeAndInsertSpacesBeforeCaps;
@ -182,8 +184,7 @@ export default class ContactImportView extends Vue {
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
// look for any imported contact array from the query parameter // look for any imported contact array from the query parameter
const importedContacts = (this.$route as RouteLocationNormalizedLoaded) const importedContacts = this.$route.query["contacts"] as string;
.query["contacts"] as string;
if (importedContacts) { if (importedContacts) {
await this.setContactsSelected(JSON.parse(importedContacts)); await this.setContactsSelected(JSON.parse(importedContacts));
} }
@ -204,7 +205,7 @@ export default class ContactImportView extends Vue {
(Array.isArray(parsedJwt.payload) ? parsedJwt.payload : undefined); (Array.isArray(parsedJwt.payload) ? parsedJwt.payload : undefined);
if (!contacts && parsedJwt.payload.own) { if (!contacts && parsedJwt.payload.own) {
// handle this single-contact JWT in the contacts page, better suited to single additions // handle this single-contact JWT in the contacts page, better suited to single additions
(this.$router as Router).push({ this.$router.push({
name: "contacts", name: "contacts",
query: { contactJwt: jwt }, query: { contactJwt: jwt },
}); });
@ -386,7 +387,7 @@ export default class ContactImportView extends Vue {
}, },
3000, 3000,
); );
(this.$router as Router).push({ name: "contacts" }); this.$router.push({ name: "contacts" });
} }
} }
</script> </script>

2
src/views/ContactQRScanShowView.vue

@ -110,6 +110,7 @@ import {
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { decodeEndorserJwt, ETHR_DID_PREFIX } from "../libs/crypto/vc"; import { decodeEndorserJwt, ETHR_DID_PREFIX } from "../libs/crypto/vc";
import { retrieveAccountMetadata } from "../libs/util"; import { retrieveAccountMetadata } from "../libs/util";
import { Router } from "vue-router";
@Component({ @Component({
components: { components: {
@ -121,6 +122,7 @@ import { retrieveAccountMetadata } from "../libs/util";
}) })
export default class ContactQRScanShow extends Vue { export default class ContactQRScanShow extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid = ""; activeDid = "";
apiServer = ""; apiServer = "";

40
src/views/ContactsView.vue

@ -119,7 +119,10 @@
Copy Selections Copy Selections
</button> </button>
<button @click="showCopySelectionsInfo()"> <button @click="showCopySelectionsInfo()">
<font-awesome icon="circle-info" class="text-xl text-blue-500 ml-4" /> <font-awesome
icon="circle-info"
class="text-xl text-blue-500 ml-4"
/>
</button> </button>
</div> </div>
</div> </div>
@ -215,7 +218,10 @@
}" }"
title="See more about this person" title="See more about this person"
> >
<font-awesome icon="circle-info" class="text-xl text-blue-500 ml-4" /> <font-awesome
icon="circle-info"
class="text-xl text-blue-500 ml-4"
/>
</router-link> </router-link>
<span class="ml-4 text-sm overflow-hidden">{{ <span class="ml-4 text-sm overflow-hidden">{{
@ -399,6 +405,8 @@ import { generateSaveAndActivateIdentity } from "../libs/util";
}) })
export default class ContactsView extends Vue { export default class ContactsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
activeDid = ""; activeDid = "";
apiServer = ""; apiServer = "";
@ -465,8 +473,7 @@ export default class ContactsView extends Vue {
// //
// For external links, use /contact-import/:jwt with a JWT that has an array of contacts // For external links, use /contact-import/:jwt with a JWT that has an array of contacts
// because that will do better error checking for things like missing data on iOS platforms. // because that will do better error checking for things like missing data on iOS platforms.
const importedContactJwt = (this.$route as RouteLocationNormalizedLoaded) const importedContactJwt = this.$route.query["contactJwt"] as string;
.query["contactJwt"] as string;
if (importedContactJwt) { if (importedContactJwt) {
// really should fully verify contents // really should fully verify contents
const { payload } = decodeEndorserJwt(importedContactJwt); const { payload } = decodeEndorserJwt(importedContactJwt);
@ -481,14 +488,13 @@ export default class ContactsView extends Vue {
} as Contact; } as Contact;
await this.addContact(newContact); await this.addContact(newContact);
// if we're here, they haven't redirected anywhere, so we'll redirect here without a query parameter // if we're here, they haven't redirected anywhere, so we'll redirect here without a query parameter
(this.$router as Router).push({ path: "/contacts" }); this.$router.push({ path: "/contacts" });
} }
} }
private async processInviteJwt() { private async processInviteJwt() {
// handle an invite JWT sent via URL // handle an invite JWT sent via URL
const importedInviteJwt = (this.$route as RouteLocationNormalizedLoaded) const importedInviteJwt = this.$route.query["inviteJwt"] as string;
.query["inviteJwt"] as string;
if (importedInviteJwt === "") { if (importedInviteJwt === "") {
// this happens when a platform (eg iOS) doesn't include anything after the "=" in a shared link. // this happens when a platform (eg iOS) doesn't include anything after the "=" in a shared link.
this.$notify( this.$notify(
@ -590,7 +596,7 @@ export default class ContactsView extends Vue {
); );
} }
// if we're here, they haven't redirected anywhere, so we'll redirect here without a query parameter // if we're here, they haven't redirected anywhere, so we'll redirect here without a query parameter
(this.$router as Router).push({ path: "/contacts" }); this.$router.push({ path: "/contacts" });
} }
} }
@ -630,7 +636,7 @@ export default class ContactsView extends Vue {
title: "They're Added To Your List", title: "They're Added To Your List",
text: "Would you like to go to the main page now?", text: "Would you like to go to the main page now?",
onYes: async () => { onYes: async () => {
(this.$router as Router).push({ name: "home" }); this.$router.push({ name: "home" });
}, },
}, },
-1, -1,
@ -767,9 +773,7 @@ export default class ContactsView extends Vue {
if (contactInput.includes(CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI)) { if (contactInput.includes(CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI)) {
const jwt = getContactJwtFromJwtUrl(contactInput); const jwt = getContactJwtFromJwtUrl(contactInput);
(this.$router as Router).push({ this.$router.push({ path: "/contact-import/" + jwt });
path: "/contact-import/" + jwt,
});
return; return;
} }
@ -877,7 +881,7 @@ export default class ContactsView extends Vue {
); );
try { try {
const contacts = JSON.parse(jsonContactInput); const contacts = JSON.parse(jsonContactInput);
(this.$router as Router).push({ this.$router.push({
name: "contact-import", name: "contact-import",
query: { contacts: JSON.stringify(contacts) }, query: { contacts: JSON.stringify(contacts) },
}); });
@ -1203,7 +1207,7 @@ export default class ContactsView extends Vue {
this.showGiftedDialog(giverDid, recipientDid); this.showGiftedDialog(giverDid, recipientDid);
}, },
onYes: async () => { onYes: async () => {
(this.$router as Router).push({ this.$router.push({
name: "contact-amounts", name: "contact-amounts",
query: { contactDid: giverDid }, query: { contactDid: giverDid },
}); });
@ -1403,10 +1407,10 @@ export default class ContactsView extends Vue {
if (hostResponse.data.data) { if (hostResponse.data.data) {
// They're the host, take them to setup // They're the host, take them to setup
(this.$router as Router).push({ name: "onboard-meeting-setup" }); this.$router.push({ name: "onboard-meeting-setup" });
} else { } else {
// They're not the host, take them to list // They're not the host, take them to list
(this.$router as Router).push({ name: "onboard-meeting-list" }); this.$router.push({ name: "onboard-meeting-list" });
} }
} else { } else {
// They're not in a meeting, show the dialog // They're not in a meeting, show the dialog
@ -1417,11 +1421,11 @@ export default class ContactsView extends Vue {
title: "Onboarding Meeting", title: "Onboarding Meeting",
text: "Would you like to start a new meeting?", text: "Would you like to start a new meeting?",
onYes: async () => { onYes: async () => {
(this.$router as Router).push({ name: "onboard-meeting-setup" }); this.$router.push({ name: "onboard-meeting-setup" });
}, },
yesText: "Start New Meeting", yesText: "Start New Meeting",
onNo: async () => { onNo: async () => {
(this.$router as Router).push({ name: "onboard-meeting-list" }); this.$router.push({ name: "onboard-meeting-list" });
}, },
noText: "Join Existing Meeting", noText: "Join Existing Meeting",
}, },

35
src/views/DIDView.vue

@ -37,7 +37,11 @@
class="ml-2 mr-2 mt-4" class="ml-2 mr-2 mt-4"
> >
Details Details
<font-awesome v-if="showDidDetails" icon="chevron-down" class="text-blue-400" /> <font-awesome
v-if="showDidDetails"
icon="chevron-down"
class="text-blue-400"
/>
<font-awesome v-else icon="chevron-right" class="text-blue-400" /> <font-awesome v-else icon="chevron-right" class="text-blue-400" />
</button> </button>
<!-- Keep the dump contents directly between > and < to avoid weird spacing. --> <!-- Keep the dump contents directly between > and < to avoid weird spacing. -->
@ -106,7 +110,11 @@
icon="person-circle-check" icon="person-circle-check"
class="fa-fw" class="fa-fw"
/> />
<font-awesome v-else icon="person-circle-question" class="fa-fw" /> <font-awesome
v-else
icon="person-circle-question"
class="fa-fw"
/>
</button> </button>
</div> </div>
@ -194,7 +202,10 @@
</span> </span>
<span class="col-span-1"> <span class="col-span-1">
<a @click="onClickLoadClaim(claim.id)" class="cursor-pointer"> <a @click="onClickLoadClaim(claim.id)" class="cursor-pointer">
<font-awesome icon="file-lines" class="pl-2 pt-1 text-blue-500" /> <font-awesome
icon="file-lines"
class="pl-2 pt-1 text-blue-500"
/>
</a> </a>
</span> </span>
</div> </div>
@ -216,7 +227,7 @@
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import * as yaml from "js-yaml"; import * as yaml from "js-yaml";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import InfiniteScroll from "../components/InfiniteScroll.vue"; import InfiniteScroll from "../components/InfiniteScroll.vue";
@ -226,14 +237,16 @@ import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { BoundingBox } from "../db/tables/settings"; import { BoundingBox } from "../db/tables/settings";
import { import {
capitalizeAndInsertSpacesBeforeCaps,
didInfoForContact,
displayAmount,
getHeaders,
GenericCredWrapper, GenericCredWrapper,
GenericVerifiableCredential, GenericVerifiableCredential,
GiveVerifiableCredential, GiveVerifiableCredential,
OfferVerifiableCredential, OfferVerifiableCredential,
} from "../interfaces";
import {
capitalizeAndInsertSpacesBeforeCaps,
didInfoForContact,
displayAmount,
getHeaders,
register, register,
setVisibilityUtil, setVisibilityUtil,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
@ -250,6 +263,8 @@ import EntityIcon from "../components/EntityIcon.vue";
}) })
export default class DIDView extends Vue { export default class DIDView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
libsUtil = libsUtil; libsUtil = libsUtil;
yaml = yaml; yaml = yaml;
@ -352,7 +367,7 @@ export default class DIDView extends Vue {
}, },
3000, 3000,
); );
(this.$router as Router).push({ name: "contacts" }); this.$router.push({ name: "contacts" });
} }
// confirm to register a new contact // confirm to register a new contact
@ -505,7 +520,7 @@ export default class DIDView extends Vue {
const route = { const route = {
path: "/claim/" + encodeURIComponent(jwtId), path: "/claim/" + encodeURIComponent(jwtId),
}; };
(this.$router as Router).push(route); this.$router.push(route);
} }
public claimAmount(claim: GenericVerifiableCredential) { public claimAmount(claim: GenericVerifiableCredential) {

17
src/views/DiscoverView.vue

@ -225,7 +225,10 @@
<div class="grow"> <div class="grow">
<h2 class="text-base font-semibold">{{ project.name }}</h2> <h2 class="text-base font-semibold">{{ project.name }}</h2>
<div class="text-sm"> <div class="text-sm">
<font-awesome icon="user" class="fa-fw text-slate-400"></font-awesome> <font-awesome
icon="user"
class="fa-fw text-slate-400"
></font-awesome>
{{ {{
didInfo( didInfo(
project.issuerDid, project.issuerDid,
@ -253,7 +256,10 @@
> >
<div class="grow"> <div class="grow">
<div class="text-sm"> <div class="text-sm">
<font-awesome icon="user" class="fa-fw text-slate-400"></font-awesome> <font-awesome
icon="user"
class="fa-fw text-slate-400"
></font-awesome>
{{ {{
didInfo( didInfo(
profile.issuerDid, profile.issuerDid,
@ -273,7 +279,10 @@
v-if="isAnywhereActive && profile.locLat && profile.locLon" v-if="isAnywhereActive && profile.locLat && profile.locLon"
class="mt-1 text-xs text-slate-500" class="mt-1 text-xs text-slate-500"
> >
<font-awesome icon="location-dot" class="fa-fw"></font-awesome> <font-awesome
icon="location-dot"
class="fa-fw"
></font-awesome>
{{ {{
(profile.locLat > 0 ? "North" : "South") + (profile.locLat > 0 ? "North" : "South") +
" in " + " in " +
@ -313,11 +322,11 @@ import {
} from "../db/index"; } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { BoundingBox } from "../db/tables/settings"; import { BoundingBox } from "../db/tables/settings";
import { PlanData } from "../interfaces";
import { import {
didInfo, didInfo,
errorStringForLog, errorStringForLog,
getHeaders, getHeaders,
PlanData,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { OnboardPage, retrieveAccountDids } from "../libs/util"; import { OnboardPage, retrieveAccountDids } from "../libs/util";

31
src/views/GiftedDetailsView.vue

@ -325,7 +325,7 @@ export default class GiftedDetails extends Vue {
try { try {
this.prevCredToEdit = (this.$route.query["prevCredToEdit"] as string) this.prevCredToEdit = (this.$route.query["prevCredToEdit"] as string)
? (JSON.parse( ? (JSON.parse(
(this.$route.query["prevCredToEdit"] as string), this.$route.query["prevCredToEdit"] as string,
) as GenericCredWrapper<GiveVerifiableCredential>) ) as GenericCredWrapper<GiveVerifiableCredential>)
: undefined; : undefined;
} catch (error) { } catch (error) {
@ -349,15 +349,16 @@ export default class GiftedDetails extends Vue {
(this.$route.query["description"] as string) || (this.$route.query["description"] as string) ||
this.prevCredToEdit?.claim?.description || this.prevCredToEdit?.claim?.description ||
this.description; this.description;
this.destinationPathAfter = (this.$route.query["destinationPathAfter"] as string) || ""; this.destinationPathAfter =
(this.$route.query["destinationPathAfter"] as string) || "";
this.giverDid = ((this.$route.query["giverDid"] as string) || this.giverDid = ((this.$route.query["giverDid"] as string) ||
(this.prevCredToEdit?.claim?.agent as any)?.identifier || (this.prevCredToEdit?.claim?.agent as unknown as { identifier: string })
?.identifier ||
this.giverDid) as string; this.giverDid) as string;
this.giverName = this.giverName = (this.$route.query["giverName"] as string) || "";
((this.$route.query["giverName"] as string) || "");
this.hideBackButton = this.hideBackButton =
(this.$route.query["hideBackButton"] as string) === "true"; (this.$route.query["hideBackButton"] as string) === "true";
this.message = ((this.$route.query["message"] as string) || ""); this.message = (this.$route.query["message"] as string) || "";
// find any offer ID // find any offer ID
const fulfills = this.prevCredToEdit?.claim?.fulfills; const fulfills = this.prevCredToEdit?.claim?.fulfills;
@ -391,38 +392,38 @@ export default class GiftedDetails extends Vue {
const providerProject = providerArray.find( const providerProject = providerArray.find(
(rec) => rec["@type"] === "PlanAction", (rec) => rec["@type"] === "PlanAction",
); );
this.providerProjectId = ((this.$route.query["providerProjectId"] as string) || this.providerProjectId = ((this.$route.query[
"providerProjectId"
] as string) ||
providerProject?.identifier || providerProject?.identifier ||
this.providerProjectId) as string; this.providerProjectId) as string;
this.recipientDid = ((this.$route.query["recipientDid"] as string) || this.recipientDid = ((this.$route.query["recipientDid"] as string) ||
this.prevCredToEdit?.claim?.recipient?.identifier) as string; this.prevCredToEdit?.claim?.recipient?.identifier) as string;
this.recipientName = this.recipientName = (this.$route.query["recipientName"] as string) || "";
((this.$route.query["recipientName"] as string) || "");
this.unitCode = ((this.$route.query["unitCode"] as string) || this.unitCode = ((this.$route.query["unitCode"] as string) ||
this.prevCredToEdit?.claim?.object?.unitCode || this.prevCredToEdit?.claim?.object?.unitCode ||
this.unitCode) as string; this.unitCode) as string;
this.imageUrl = this.imageUrl = ((this.$route.query["imageUrl"] as string) ||
((this.$route.query["imageUrl"] as string) ||
this.prevCredToEdit?.claim?.image || this.prevCredToEdit?.claim?.image ||
localStorage.getItem("imageUrl") || localStorage.getItem("imageUrl") ||
this.imageUrl) as string; this.imageUrl) as string;
// this is an endpoint for sharing project info to highlight something given // this is an endpoint for sharing project info to highlight something given
// https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target // https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target
if ((this.$route.query["shareTitle"] as string)) { if (this.$route.query["shareTitle"] as string) {
this.description = this.description =
((this.$route.query["shareTitle"] as string) || "") + ((this.$route.query["shareTitle"] as string) || "") +
(this.description ? "\n" + this.description : ""); (this.description ? "\n" + this.description : "");
} }
if ((this.$route.query["shareText"] as string)) { if (this.$route.query["shareText"] as string) {
this.description = this.description =
(this.description ? this.description + "\n" : "") + (this.description ? this.description + "\n" : "") +
((this.$route.query["shareText"] as string) || ""); ((this.$route.query["shareText"] as string) || "");
} }
if ((this.$route.query["shareUrl"] as string)) { if (this.$route.query["shareUrl"] as string) {
this.imageUrl = (this.$route.query["shareUrl"] as string); this.imageUrl = this.$route.query["shareUrl"] as string;
} }
const settings = await retrieveSettingsForActiveAccount(); const settings = await retrieveSettingsForActiveAccount();

3
src/views/HelpNotificationsView.vue

@ -313,11 +313,12 @@ import { DIRECT_PUSH_TITLE, sendTestThroughPushServer } from "../libs/util";
import PushNotificationPermission from "../components/PushNotificationPermission.vue"; import PushNotificationPermission from "../components/PushNotificationPermission.vue";
import { db } from "../db/index"; import { db } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { Router } from "vue-router";
@Component({ components: { PushNotificationPermission, QuickNav } }) @Component({ components: { PushNotificationPermission, QuickNav } })
export default class HelpNotificationsView extends Vue { export default class HelpNotificationsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
subscriptionJSON?: PushSubscriptionJSON; subscriptionJSON?: PushSubscriptionJSON;
async mounted() { async mounted() {

18
src/views/HelpOnboardingView.vue

@ -24,8 +24,9 @@
</p> </p>
<p>Then watch that page to see when they accept their invite.</p> <p>Then watch that page to see when they accept their invite.</p>
<p> <p>
(That page is also reachable from the Contacts <font-awesome icon="users" /> page (That page is also reachable from the Contacts
though the invitation <font-awesome icon="envelope-open-text" /> icon.) <font-awesome icon="users" /> page though the invitation
<font-awesome icon="envelope-open-text" /> icon.)
</p> </p>
<h1 class="mt-4 font-bold text-xl">Next Steps</h1> <h1 class="mt-4 font-bold text-xl">Next Steps</h1>
@ -35,12 +36,13 @@
<h1 class="font-bold text-xl">Without a backup, you can lose data.</h1> <h1 class="font-bold text-xl">Without a backup, you can lose data.</h1>
<div> <div>
<p> <p>
Exporting backups (from the Account <font-awesome icon="circle-user" /> screen) Exporting backups (from the Account
is important for the case where they lose their device. This is <font-awesome icon="circle-user" /> screen) is important for the case
especially true for the Identifier Seed: that is theirs and and theirs where they lose their device. This is especially true for the
alone, and currently nobody else can recover it if they lose it. The Identifier Seed: that is theirs and and theirs alone, and currently
good thing is that anyone can create a new account and simply inform nobody else can recover it if they lose it. The good thing is that
their network of their new ID. anyone can create a new account and simply inform their network of
their new ID.
</p> </p>
</div> </div>
</div> </div>

3
src/views/HelpView.vue

@ -588,6 +588,7 @@ import {
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class Help extends Vue { export default class Help extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
package = Package; package = Package;
commitHash = import.meta.env.VITE_GIT_HASH; commitHash = import.meta.env.VITE_GIT_HASH;
@ -614,7 +615,7 @@ export default class Help extends Vue {
finishedOnboarding: false, finishedOnboarding: false,
}); });
} }
(this.$router as Router).push({ name: "home" }); this.$router.push({ name: "home" });
} }
} }
</script> </script>

5
src/views/HomeView.vue

@ -37,8 +37,7 @@
You should see a prompt to install, or you can click on the You should see a prompt to install, or you can click on the
top-right dots top-right dots
<font-awesome icon="ellipsis-vertical" title="vertical ellipsis" /> <font-awesome icon="ellipsis-vertical" title="vertical ellipsis" />
/> /> and then "Install"<img
and then "Install"<img
src="../assets/help/install-android-chrome.png" src="../assets/help/install-android-chrome.png"
alt="Android 'install' icon" alt="Android 'install' icon"
width="30" width="30"
@ -435,6 +434,7 @@ import {
} from "../libs/util"; } from "../libs/util";
interface GiveRecordWithContactInfo extends GiveSummaryRecord { interface GiveRecordWithContactInfo extends GiveSummaryRecord {
jwtId: string;
giver: { giver: {
displayName: string; displayName: string;
known: boolean; known: boolean;
@ -728,6 +728,7 @@ export default class HomeView extends Vue {
const newRecord: GiveRecordWithContactInfo = { const newRecord: GiveRecordWithContactInfo = {
...record, ...record,
jwtId: record.jwtId,
giver: didInfoForContact( giver: didInfoForContact(
giverDid, giverDid,
this.activeDid, this.activeDid,

13
src/views/IdentitySwitcherView.vue

@ -22,7 +22,10 @@
v-if="activeDid && !activeDidInIdentities" v-if="activeDid && !activeDidInIdentities"
class="block bg-slate-100 rounded-md flex items-center px-4 py-3 mb-4" class="block bg-slate-100 rounded-md flex items-center px-4 py-3 mb-4"
> >
<font-awesome icon="circle-check" class="fa-fw text-red-600 text-xl mr-3"></font-awesome> <font-awesome
icon="circle-check"
class="fa-fw text-red-600 text-xl mr-3"
></font-awesome>
<div class="text-sm text-slate-500"> <div class="text-sm text-slate-500">
<div class="overflow-hidden truncate"> <div class="overflow-hidden truncate">
<b>ID:</b> <code>{{ activeDid }}</code> <b>ID:</b> <code>{{ activeDid }}</code>
@ -114,6 +117,7 @@ import { retrieveAllAccountsMetadata } from "../libs/util";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class IdentitySwitcherView extends Vue { export default class IdentitySwitcherView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
public activeDid = ""; public activeDid = "";
public activeDidInIdentities = false; public activeDidInIdentities = false;
@ -131,7 +135,10 @@ export default class IdentitySwitcherView extends Vue {
const accounts = await retrieveAllAccountsMetadata(); const accounts = await retrieveAllAccountsMetadata();
for (let n = 0; n < accounts.length; n++) { for (let n = 0; n < accounts.length; n++) {
const acct = accounts[n]; const acct = accounts[n];
this.otherIdentities.push({ id: acct.id as string, did: acct.did }); this.otherIdentities.push({
id: (acct.id ?? 0).toString(),
did: acct.did,
});
if (acct.did && this.activeDid === acct.did) { if (acct.did && this.activeDid === acct.did) {
this.activeDidInIdentities = true; this.activeDidInIdentities = true;
} }
@ -159,7 +166,7 @@ export default class IdentitySwitcherView extends Vue {
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
activeDid: did, activeDid: did,
}); });
(this.$router as Router).push({ name: "account" }); this.$router.push({ name: "account" });
} }
async deleteAccount(id: string) { async deleteAccount(id: string) {

5
src/views/ImportAccountView.vue

@ -111,6 +111,7 @@ export default class ImportAccountView extends Vue {
AppString = AppString; AppString = AppString;
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
apiServer = ""; apiServer = "";
address = ""; address = "";
@ -130,7 +131,7 @@ export default class ImportAccountView extends Vue {
} }
public onCancelClick() { public onCancelClick() {
(this.$router as Router).back(); this.$router.back();
} }
public isNotProdServer() { public isNotProdServer() {
@ -170,7 +171,7 @@ export default class ImportAccountView extends Vue {
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
activeDid: newId.did, activeDid: newId.did,
}); });
(this.$router as Router).push({ name: "account" }); this.$router.push({ name: "account" });
// 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 saving mnemonic & updating settings:", err); console.error("Error saving mnemonic & updating settings:", err);

9
src/views/ImportDerivedAccountView.vue

@ -70,7 +70,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router"; import { Router, RouteLocationNormalizedLoaded } from "vue-router";
import { import {
DEFAULT_ROOT_DERIVATION_PATH, DEFAULT_ROOT_DERIVATION_PATH,
@ -86,6 +86,9 @@ import { retrieveAllFullyDecryptedAccounts } from "../libs/util";
components: {}, components: {},
}) })
export default class ImportAccountView extends Vue { export default class ImportAccountView extends Vue {
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
derivationPath = DEFAULT_ROOT_DERIVATION_PATH; derivationPath = DEFAULT_ROOT_DERIVATION_PATH;
didArrays: Array<Array<string>> = []; didArrays: Array<Array<string>> = [];
selectedArrayFirstDid = ""; selectedArrayFirstDid = "";
@ -102,7 +105,7 @@ export default class ImportAccountView extends Vue {
} }
public onCancelClick() { public onCancelClick() {
(this.$router as Router).back(); this.$router.back();
} }
public switchAccount(did: string) { public switchAccount(did: string) {
@ -151,7 +154,7 @@ export default class ImportAccountView extends Vue {
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
activeDid: newId.did, activeDid: newId.did,
}); });
(this.$router as Router).push({ name: "account" }); this.$router.push({ name: "account" });
} catch (err) { } catch (err) {
console.error("Error saving mnemonic & updating settings:", err); console.error("Error saving mnemonic & updating settings:", err);
} }

3
src/views/InviteOneAcceptView.vue

@ -55,6 +55,7 @@ import { generateSaveAndActivateIdentity } from "../libs/util";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class InviteOneAcceptView extends Vue { export default class InviteOneAcceptView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid: string = ""; activeDid: string = "";
apiServer: string = ""; apiServer: string = "";
@ -123,7 +124,7 @@ export default class InviteOneAcceptView extends Vue {
// That's good enough for an initial check. // That's good enough for an initial check.
// Send them to the contacts page to finish, with inviteJwt in the query string. // Send them to the contacts page to finish, with inviteJwt in the query string.
(this.$router as Router).push({ this.$router.push({
name: "contacts", name: "contacts",
query: { inviteJwt: jwt }, query: { inviteJwt: jwt },
}); });

2
src/views/InviteOneView.vue

@ -132,6 +132,7 @@
import axios from "axios"; import axios from "axios";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { useClipboard } from "@vueuse/core"; import { useClipboard } from "@vueuse/core";
import { Router } from "vue-router";
import ContactNameDialog from "../components/ContactNameDialog.vue"; import ContactNameDialog from "../components/ContactNameDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
@ -156,6 +157,7 @@ interface Invite {
}) })
export default class InviteOneView extends Vue { export default class InviteOneView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
invites: Invite[] = []; invites: Invite[] = [];
activeDid: string = ""; activeDid: string = "";

16
src/views/NewActivityView.vue

@ -59,7 +59,10 @@
:to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }" :to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="file-lines" class="pl-2 text-blue-500 cursor-pointer" /> <font-awesome
icon="file-lines"
class="pl-2 text-blue-500 cursor-pointer"
/>
</router-link> </router-link>
<!-- New line that appears on hover or when the offer is clicked --> <!-- New line that appears on hover or when the offer is clicked -->
<div <div
@ -125,7 +128,10 @@
:to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }" :to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="file-lines" class="pl-2 text-blue-500 cursor-pointer" /> <font-awesome
icon="file-lines"
class="pl-2 text-blue-500 cursor-pointer"
/>
</router-link> </router-link>
<!-- New line that appears on hover --> <!-- New line that appears on hover -->
<div <div
@ -154,13 +160,13 @@ import {
updateAccountSettings, updateAccountSettings,
} from "../db/index"; } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { Router } from "vue-router";
import { OfferSummaryRecord, OfferToPlanSummaryRecord } from "../interfaces";
import { import {
didInfo, didInfo,
displayAmount, displayAmount,
getNewOffersToUser, getNewOffersToUser,
getNewOffersToUserProjects, getNewOffersToUserProjects,
OfferSummaryRecord,
OfferToPlanSummaryRecord,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
@ -169,7 +175,7 @@ import { retrieveAccountDids } from "../libs/util";
}) })
export default class NewActivityView extends Vue { export default class NewActivityView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid = ""; activeDid = "";
allContacts: Array<Contact> = []; allContacts: Array<Contact> = [];
allMyDids: string[] = []; allMyDids: string[] = [];

8
src/views/NewEditAccountView.vue

@ -5,7 +5,7 @@
<h1 class="text-lg text-center font-light relative px-7"> <h1 class="text-lg text-center font-light relative px-7">
<!-- Cancel --> <!-- Cancel -->
<button <button
@click="$router.go(-1)" @click="$router.back()"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1" class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
> >
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome> <font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
@ -54,6 +54,8 @@ import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
components: {}, components: {},
}) })
export default class NewEditAccountView extends Vue { export default class NewEditAccountView extends Vue {
$router!: Router;
givenName = ""; givenName = "";
// 'created' hook runs when the Vue instance is first created // 'created' hook runs when the Vue instance is first created
@ -69,11 +71,11 @@ export default class NewEditAccountView extends Vue {
firstName: this.givenName, firstName: this.givenName,
lastName: "", // deprecated, pre v 0.1.3 lastName: "", // deprecated, pre v 0.1.3
}); });
(this.$router as Router).back(); this.$router.back();
} }
onClickCancel() { onClickCancel() {
(this.$router as Router).back(); this.$router.back();
} }
} }
</script> </script>

12
src/views/NewEditProjectView.vue

@ -8,7 +8,7 @@
<!-- Cancel --> <!-- Cancel -->
<!-- Back --> <!-- Back -->
<button <button
@click="$router.go(-1)" @click="$router.back()"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1" class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
> >
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome> <font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
@ -267,6 +267,9 @@ import { serializeEvent } from "nostr-tools/lib/esm/index.js";
}) })
export default class NewEditProjectView extends Vue { export default class NewEditProjectView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
errNote(message: string) { errNote(message: string) {
this.$notify( this.$notify(
{ group: "alert", type: "danger", title: "Error", text: message }, { group: "alert", type: "danger", title: "Error", text: message },
@ -312,8 +315,7 @@ export default class NewEditProjectView extends Vue {
this.apiServer = settings.apiServer || ""; this.apiServer = settings.apiServer || "";
this.showGeneralAdvanced = !!settings.showGeneralAdvanced; this.showGeneralAdvanced = !!settings.showGeneralAdvanced;
this.projectId = this.projectId = (this.$route.query["projectId"] as string) || "";
(this.$route as RouteLocationNormalizedLoaded).query["projectId"] || "";
if (this.projectId) { if (this.projectId) {
if (this.numAccounts === 0) { if (this.numAccounts === 0) {
@ -598,7 +600,7 @@ export default class NewEditProjectView extends Vue {
} }
} }
(this.$router as Router).push({ path: "/project/" + projectPath }); this.$router.push({ path: "/project/" + projectPath });
} else { } else {
console.error( console.error(
"Got unexpected 'data' inside response from server", "Got unexpected 'data' inside response from server",
@ -816,7 +818,7 @@ export default class NewEditProjectView extends Vue {
} }
public onCancelClick() { public onCancelClick() {
(this.$router as Router).back(); this.$router.back();
} }
public showNostrPartnerInfo() { public showNostrPartnerInfo() {

3
src/views/NewIdentifierView.vue

@ -62,12 +62,13 @@ import QuickNav from "../components/QuickNav.vue";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class NewIdentifierView extends Vue { export default class NewIdentifierView extends Vue {
loading = true; loading = true;
$router!: Router;
async mounted() { async mounted() {
await generateSaveAndActivateIdentity(); await generateSaveAndActivateIdentity();
this.loading = false; this.loading = false;
setTimeout(() => { setTimeout(() => {
(this.$router as Router).push({ name: "home" }); this.$router.push({ name: "home" });
}, 1000); }, 1000);
} }
} }

13
src/views/OfferDetailsView.vue

@ -232,7 +232,7 @@ export default class OfferDetailsView extends Vue {
try { try {
this.prevCredToEdit = (this.$route.query["prevCredToEdit"] as string) this.prevCredToEdit = (this.$route.query["prevCredToEdit"] as string)
? (JSON.parse( ? (JSON.parse(
(this.$route.query["prevCredToEdit"] as string), this.$route.query["prevCredToEdit"] as string,
) as GenericCredWrapper<OfferVerifiableCredential>) ) as GenericCredWrapper<OfferVerifiableCredential>)
: undefined; : undefined;
} catch (error) { } catch (error) {
@ -263,13 +263,15 @@ export default class OfferDetailsView extends Vue {
(this.$route.query["description"] as string) || (this.$route.query["description"] as string) ||
this.prevCredToEdit?.claim?.itemOffered?.description || this.prevCredToEdit?.claim?.itemOffered?.description ||
this.descriptionOfItem; this.descriptionOfItem;
this.destinationPathAfter = (this.$route.query["destinationPathAfter"] as string) || ""; this.destinationPathAfter =
(this.$route.query["destinationPathAfter"] as string) || "";
this.offererDid = ((this.$route.query["offererDid"] as string) || this.offererDid = ((this.$route.query["offererDid"] as string) ||
(this.prevCredToEdit?.claim?.agent as any)?.identifier || (this.prevCredToEdit?.claim?.agent as unknown as { identifier: string })
?.identifier ||
this.offererDid) as string; this.offererDid) as string;
this.hideBackButton = this.hideBackButton =
(this.$route.query["hideBackButton"] as string) === "true"; (this.$route.query["hideBackButton"] as string) === "true";
this.message = ((this.$route.query["message"] as string) || ""); this.message = (this.$route.query["message"] as string) || "";
// find any project ID // find any project ID
let project; let project;
@ -288,8 +290,7 @@ export default class OfferDetailsView extends Vue {
this.recipientDid = ((this.$route.query["recipientDid"] as string) || this.recipientDid = ((this.$route.query["recipientDid"] as string) ||
this.prevCredToEdit?.claim?.recipient?.identifier) as string; this.prevCredToEdit?.claim?.recipient?.identifier) as string;
this.recipientName = this.recipientName = (this.$route.query["recipientName"] as string) || "";
((this.$route.query["recipientName"] as string) || "");
this.validThroughDateInput = this.validThroughDateInput =
this.prevCredToEdit?.claim?.validThrough || this.validThroughDateInput; this.prevCredToEdit?.claim?.validThrough || this.validThroughDateInput;

3
src/views/OnboardMeetingListView.vue

@ -120,6 +120,7 @@ export default class OnboardMeetingListView extends Vue {
}, },
timeout?: number, timeout?: number,
) => void; ) => void;
$router!: Router;
activeDid = ""; activeDid = "";
apiServer = ""; apiServer = "";
@ -257,7 +258,7 @@ export default class OnboardMeetingListView extends Vue {
if (postResult.data && postResult.data.success) { if (postResult.data && postResult.data.success) {
// Navigate to members view with password and groupId // Navigate to members view with password and groupId
(this.$router as Router).push({ this.$router.push({
name: "onboard-meeting-members", name: "onboard-meeting-members",
params: { params: {
groupId: this.selectedMeeting.groupId.toString(), groupId: this.selectedMeeting.groupId.toString(),

12
src/views/OnboardMeetingMembersView.vue

@ -39,7 +39,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { RouteLocation } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
@ -69,17 +69,17 @@ export default class OnboardMeetingMembersView extends Vue {
firstName = ""; firstName = "";
isRegistered = false; isRegistered = false;
isLoading = true; isLoading = true;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
$refs!: { userNameDialog!: InstanceType<typeof UserNameDialog>;
userNameDialog: InstanceType<typeof UserNameDialog>;
};
get groupId(): string { get groupId(): string {
return (this.$route as RouteLocation).params.groupId as string; return (this.$route.params.groupId as string) || "";
} }
get password(): string { get password(): string {
return (this.$route as RouteLocation).query.password as string; return (this.$route.query.password as string) || "";
} }
async created() { async created() {

3
src/views/OnboardMeetingSetupView.vue

@ -204,7 +204,8 @@
class="inline-block text-blue-600" class="inline-block text-blue-600"
target="_blank" target="_blank"
> >
&bull; Open shortcut page for members <font-awesome icon="external-link" /> &bull; Open shortcut page for members
<font-awesome icon="external-link" />
</router-link> </router-link>
<MembersList <MembersList

92
src/views/ProjectViewView.vue

@ -10,7 +10,7 @@
<h1 class="text-center text-lg font-light relative px-7"> <h1 class="text-center text-lg font-light relative px-7">
<!-- Back --> <!-- Back -->
<button <button
@click="$router.go(-1)" @click="$router.back()"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1" class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
> >
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome> <font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
@ -48,7 +48,10 @@
<div class="overflow-hidden"> <div class="overflow-hidden">
<div class="text-sm mb-3"> <div class="text-sm mb-3">
<div class="truncate"> <div class="truncate">
<font-awesome icon="user" class="fa-fw text-slate-400"></font-awesome> <font-awesome
icon="user"
class="fa-fw text-slate-400"
></font-awesome>
{{ issuerInfoObject?.displayName }} {{ issuerInfoObject?.displayName }}
<span v-if="!serverUtil.isEmptyOrHiddenDid(issuer)"> <span v-if="!serverUtil.isEmptyOrHiddenDid(issuer)">
<a <a
@ -56,7 +59,10 @@
target="_blank" target="_blank"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="arrow-up-right-from-square" class="fa-fw" /> <font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a> </a>
</span> </span>
<span v-else-if="serverUtil.isHiddenDid(issuer)"> <span v-else-if="serverUtil.isHiddenDid(issuer)">
@ -68,15 +74,24 @@
</span> </span>
</div> </div>
<div v-if="startTime"> <div v-if="startTime">
<font-awesome icon="calendar" class="fa-fw text-slate-400"></font-awesome> <font-awesome
icon="calendar"
class="fa-fw text-slate-400"
></font-awesome>
Starts {{ startTime }} Starts {{ startTime }}
</div> </div>
<div v-if="endTime"> <div v-if="endTime">
<font-awesome icon="calendar" class="fa-fw text-slate-400"></font-awesome> <font-awesome
icon="calendar"
class="fa-fw text-slate-400"
></font-awesome>
Ends {{ endTime }} Ends {{ endTime }}
</div> </div>
<div v-if="latitude || longitude"> <div v-if="latitude || longitude">
<font-awesome icon="location-dot" class="fa-fw text-slate-400"></font-awesome> <font-awesome
icon="location-dot"
class="fa-fw text-slate-400"
></font-awesome>
<a <a
:href="getOpenStreetMapUrl()" :href="getOpenStreetMapUrl()"
target="_blank" target="_blank"
@ -89,14 +104,20 @@
</a> </a>
</div> </div>
<div v-if="url"> <div v-if="url">
<font-awesome icon="globe" class="fa-fw text-slate-400"></font-awesome> <font-awesome
icon="globe"
class="fa-fw text-slate-400"
></font-awesome>
<a <a
:href="addScheme(url)" :href="addScheme(url)"
target="_blank" target="_blank"
class="underline text-blue-500" class="underline text-blue-500"
> >
{{ domainForWebsite(this.url) }} {{ domainForWebsite(this.url) }}
<font-awesome icon="arrow-up-right-from-square" class="fa-fw" /> <font-awesome
icon="arrow-up-right-from-square"
class="fa-fw"
/>
</a> </a>
</div> </div>
</div> </div>
@ -181,7 +202,10 @@
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" 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="openGiftDialogToProject({ name: 'you', did: activeDid })"> <li @click="openGiftDialogToProject({ name: 'you', did: activeDid })">
<font-awesome icon="hand" class="fa-fw text-blue-500 text-5xl cursor-pointer" /> <font-awesome
icon="hand"
class="fa-fw text-blue-500 text-5xl cursor-pointer"
/>
<h3 <h3
class="mt-5 text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer" class="mt-5 text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden cursor-pointer"
> >
@ -266,7 +290,10 @@
> >
<div class="flex justify-between gap-4"> <div class="flex justify-between gap-4">
<span> <span>
<font-awesome icon="user" class="fa-fw text-slate-400"></font-awesome> <font-awesome
icon="user"
class="fa-fw text-slate-400"
></font-awesome>
{{ {{
serverUtil.didInfo( serverUtil.didInfo(
offer.offeredByDid, offer.offeredByDid,
@ -292,7 +319,10 @@
@click="onClickLoadClaim(offer.jwtId as string)" @click="onClickLoadClaim(offer.jwtId as string)"
class="cursor-pointer" class="cursor-pointer"
> >
<font-awesome icon="file-lines" class="pl-2 pt-1 text-blue-500" /> <font-awesome
icon="file-lines"
class="pl-2 pt-1 text-blue-500"
/>
</a> </a>
<a <a
v-if="checkIsFulfillable(offer)" v-if="checkIsFulfillable(offer)"
@ -367,7 +397,10 @@
</div> </div>
<div class="flex justify-between"> <div class="flex justify-between">
<a @click="onClickLoadClaim(give.jwtId)"> <a @click="onClickLoadClaim(give.jwtId)">
<font-awesome icon="file-lines" class="text-blue-500 cursor-pointer" /> <font-awesome
icon="file-lines"
class="text-blue-500 cursor-pointer"
/>
</a> </a>
<a <a
@ -377,13 +410,19 @@
" "
@click="deepCheckConfirmable(give)" @click="deepCheckConfirmable(give)"
> >
<font-awesome icon="circle-check" class="text-blue-500 cursor-pointer" /> <font-awesome
icon="circle-check"
class="text-blue-500 cursor-pointer"
/>
</a> </a>
<a v-else-if="checkingConfirmationForJwtId === give.jwtId"> <a v-else-if="checkingConfirmationForJwtId === give.jwtId">
<font-awesome icon="spinner" class="fa-spin-pulse" /> <font-awesome icon="spinner" class="fa-spin-pulse" />
</a> </a>
<a v-else @click="shallowNotifyWhyCannotConfirm(give)"> <a v-else @click="shallowNotifyWhyCannotConfirm(give)">
<font-awesome icon="circle-check" class="text-slate-500 cursor-pointer" /> <font-awesome
icon="circle-check"
class="text-slate-500 cursor-pointer"
/>
</a> </a>
</div> </div>
<div v-if="give.fullClaim.image" class="flex justify-center"> <div v-if="give.fullClaim.image" class="flex justify-center">
@ -456,7 +495,10 @@
</div> </div>
<div class="flex justify-between"> <div class="flex justify-between">
<a @click="onClickLoadClaim(give.jwtId)"> <a @click="onClickLoadClaim(give.jwtId)">
<font-awesome icon="file-lines" class="text-blue-500 cursor-pointer" /> <font-awesome
icon="file-lines"
class="text-blue-500 cursor-pointer"
/>
</a> </a>
<a <a
@ -466,13 +508,19 @@
" "
@click="deepCheckConfirmable(give)" @click="deepCheckConfirmable(give)"
> >
<font-awesome icon="circle-check" class="text-blue-500 cursor-pointer" /> <font-awesome
icon="circle-check"
class="text-blue-500 cursor-pointer"
/>
</a> </a>
<a v-else-if="checkingConfirmationForJwtId === give.jwtId"> <a v-else-if="checkingConfirmationForJwtId === give.jwtId">
<font-awesome icon="spinner" class="fa-spin-pulse" /> <font-awesome icon="spinner" class="fa-spin-pulse" />
</a> </a>
<a v-else @click="shallowNotifyWhyCannotConfirm(give)"> <a v-else @click="shallowNotifyWhyCannotConfirm(give)">
<font-awesome icon="circle-check" class="text-slate-500 cursor-pointer" /> <font-awesome
icon="circle-check"
class="text-slate-500 cursor-pointer"
/>
</a> </a>
</div> </div>
<div v-if="give.fullClaim.image" class="flex justify-center"> <div v-if="give.fullClaim.image" class="flex justify-center">
@ -536,7 +584,7 @@ import HiddenDidDialog from "../components/HiddenDidDialog.vue";
}) })
export default class ProjectViewView extends Vue { export default class ProjectViewView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid = ""; activeDid = "";
agentDid = ""; agentDid = "";
agentDidVisibleToDids: Array<string> = []; agentDidVisibleToDids: Array<string> = [];
@ -616,7 +664,7 @@ export default class ProjectViewView extends Vue {
name: "new-edit-project", name: "new-edit-project",
query: { projectId: this.projectId }, query: { projectId: this.projectId },
}; };
(this.$router as Router).push(route); this.$router.push(route);
} }
// Isn't there a better way to make this available to the template? // Isn't there a better way to make this available to the template?
@ -953,7 +1001,7 @@ export default class ProjectViewView extends Vue {
const route = { const route = {
path: "/project/" + encodeURIComponent(projectId), path: "/project/" + encodeURIComponent(projectId),
}; };
(this.$router as Router).push(route); this.$router.push(route);
this.loadProject(projectId, this.activeDid); this.loadProject(projectId, this.activeDid);
} }
@ -1000,14 +1048,14 @@ export default class ProjectViewView extends Vue {
projectId: this.projectId, projectId: this.projectId,
}, },
}; };
(this.$router as Router).push(route); this.$router.push(route);
} }
onClickLoadClaim(jwtId: string) { onClickLoadClaim(jwtId: string) {
const route = { const route = {
path: "/claim/" + encodeURIComponent(jwtId), path: "/claim/" + encodeURIComponent(jwtId),
}; };
(this.$router as Router).push(route); this.$router.push(route);
} }
checkIsFulfillable(offer: OfferSummaryRecord) { checkIsFulfillable(offer: OfferSummaryRecord) {

24
src/views/ProjectsView.vue

@ -136,7 +136,10 @@
/> />
<span v-if="offer.amountGiven >= offer.amount"> <span v-if="offer.amountGiven >= offer.amount">
<font-awesome icon="check-circle" class="fa-fw text-green-500" /> <font-awesome
icon="check-circle"
class="fa-fw text-green-500"
/>
All {{ offer.amount }} given All {{ offer.amount }} given
</span> </span>
<span v-else> <span v-else>
@ -176,7 +179,10 @@
<span v-else> <span v-else>
<!-- Non-amount offer --> <!-- Non-amount offer -->
<span v-if="offer.nonAmountGivenConfirmed"> <span v-if="offer.nonAmountGivenConfirmed">
<font-awesome icon="check-circle" class="fa-fw text-green-500" /> <font-awesome
icon="check-circle"
class="fa-fw text-green-500"
/>
{{ offer.nonAmountGivenConfirmed }} {{ offer.nonAmountGivenConfirmed }}
{{ offer.nonAmountGivenConfirmed == 1 ? "give" : "gives" }} {{ offer.nonAmountGivenConfirmed == 1 ? "give" : "gives" }}
are confirmed. are confirmed.
@ -295,7 +301,9 @@ import { OnboardPage } from "../libs/util";
}) })
export default class ProjectsView extends Vue { export default class ProjectsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
errNote(message) { $router!: Router;
errNote(message: string) {
this.$notify( this.$notify(
{ group: "alert", type: "danger", title: "Error", text: message }, { group: "alert", type: "danger", title: "Error", text: message },
5000, 5000,
@ -417,7 +425,7 @@ export default class ProjectsView extends Vue {
const route = { const route = {
path: "/project/" + encodeURIComponent(id), path: "/project/" + encodeURIComponent(id),
}; };
(this.$router as Router).push(route); this.$router.push(route);
} }
/** /**
@ -427,14 +435,14 @@ export default class ProjectsView extends Vue {
const route = { const route = {
name: "new-edit-project", name: "new-edit-project",
}; };
(this.$router as Router).push(route); this.$router.push(route);
} }
onClickLoadClaim(jwtId: string) { onClickLoadClaim(jwtId: string) {
const route = { const route = {
path: "/claim/" + encodeURIComponent(jwtId), path: "/claim/" + encodeURIComponent(jwtId),
}; };
(this.$router as Router).push(route); this.$router.push(route);
} }
/** /**
@ -537,10 +545,10 @@ export default class ProjectsView extends Vue {
text: "If so, we'll use those with QR codes to share.", text: "If so, we'll use those with QR codes to share.",
onCancel: async () => {}, onCancel: async () => {},
onNo: async () => { onNo: async () => {
(this.$router as Router).push({ name: "share-my-contact-info" }); this.$router.push({ name: "share-my-contact-info" });
}, },
onYes: async () => { onYes: async () => {
(this.$router as Router).push({ name: "contact-qr" }); this.$router.push({ name: "contact-qr" });
}, },
noText: "we will share another way", noText: "we will share another way",
yesText: "we are nearby with cameras", yesText: "we are nearby with cameras",

4
src/views/QuickActionBvcBeginView.vue

@ -90,7 +90,7 @@ import * as libsUtil from "../libs/util";
}) })
export default class QuickActionBvcBeginView extends Vue { export default class QuickActionBvcBeginView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
attended = true; attended = true;
gaveTime = true; gaveTime = true;
hoursStr = "1"; hoursStr = "1";
@ -201,7 +201,7 @@ export default class QuickActionBvcBeginView extends Vue {
}, },
3000, 3000,
); );
(this.$router as Router).push({ path: "/quick-action-bvc" }); this.$router.push({ path: "/quick-action-bvc" });
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any

8
src/views/QuickActionBvcEndView.vue

@ -151,16 +151,18 @@ import {
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
} from "../db/index"; } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import {
GenericCredWrapper,
GenericVerifiableCredential,
ErrorResult,
} from "../interfaces";
import { import {
BVC_MEETUPS_PROJECT_CLAIM_ID, BVC_MEETUPS_PROJECT_CLAIM_ID,
claimSpecialDescription, claimSpecialDescription,
containsHiddenDid, containsHiddenDid,
createAndSubmitConfirmation, createAndSubmitConfirmation,
createAndSubmitGive, createAndSubmitGive,
GenericCredWrapper,
GenericVerifiableCredential,
getHeaders, getHeaders,
ErrorResult,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
@Component({ @Component({

6
src/views/QuickActionBvcView.vue

@ -41,12 +41,14 @@ import { Component, Vue } from "vue-facing-decorator";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { Router } from "vue-router";
@Component({ @Component({
components: { components: {
QuickNav, QuickNav,
TopMessage, TopMessage,
}, },
}) })
export default class QuickActionBvcView extends Vue {} export default class QuickActionBvcView extends Vue {
$router!: Router;
}
</script> </script>

10
src/views/RecentOffersToUserProjectsView.vue

@ -65,7 +65,10 @@
:to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }" :to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="file-lines" class="pl-2 text-blue-500 cursor-pointer" /> <font-awesome
icon="file-lines"
class="pl-2 text-blue-500 cursor-pointer"
/>
</router-link> </router-link>
</li> </li>
</ul> </ul>
@ -83,11 +86,12 @@ import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { Router } from "vue-router";
import { OfferToPlanSummaryRecord } from "../interfaces";
import { import {
didInfo, didInfo,
displayAmount, displayAmount,
getNewOffersToUserProjects, getNewOffersToUserProjects,
OfferToPlanSummaryRecord,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
@ -96,7 +100,7 @@ import { retrieveAccountDids } from "../libs/util";
}) })
export default class RecentOffersToUserView extends Vue { export default class RecentOffersToUserView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid = ""; activeDid = "";
allContacts: Array<Contact> = []; allContacts: Array<Contact> = [];
allMyDids: string[] = []; allMyDids: string[] = [];

11
src/views/RecentOffersToUserView.vue

@ -58,7 +58,10 @@
:to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }" :to="{ path: '/claim/' + encodeURIComponent(offer.jwtId) }"
class="text-blue-500" class="text-blue-500"
> >
<font-awesome icon="file-lines" class="pl-2 text-blue-500 cursor-pointer" /> <font-awesome
icon="file-lines"
class="pl-2 text-blue-500 cursor-pointer"
/>
</router-link> </router-link>
</li> </li>
</ul> </ul>
@ -68,7 +71,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router";
import GiftedDialog from "../components/GiftedDialog.vue"; import GiftedDialog from "../components/GiftedDialog.vue";
import EntityIcon from "../components/EntityIcon.vue"; import EntityIcon from "../components/EntityIcon.vue";
import InfiniteScroll from "../components/InfiniteScroll.vue"; import InfiniteScroll from "../components/InfiniteScroll.vue";
@ -76,11 +79,11 @@ import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index"; import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { OfferSummaryRecord } from "../interfaces";
import { import {
didInfo, didInfo,
displayAmount, displayAmount,
getNewOffersToUser, getNewOffersToUser,
OfferSummaryRecord,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";
@ -89,7 +92,7 @@ import { retrieveAccountDids } from "../libs/util";
}) })
export default class RecentOffersToUserView extends Vue { export default class RecentOffersToUserView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid = ""; activeDid = "";
allContacts: Array<Contact> = []; allContacts: Array<Contact> = [];
allMyDids: string[] = []; allMyDids: string[] = [];

3
src/views/SearchAreaView.vue

@ -131,6 +131,7 @@ const DEFAULT_ZOOM = 2;
}) })
export default class SearchAreaView extends Vue { export default class SearchAreaView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
isChoosingSearchBox = false; isChoosingSearchBox = false;
isNewMarkerSet = false; isNewMarkerSet = false;
@ -219,7 +220,7 @@ export default class SearchAreaView extends Vue {
}, },
7000, 7000,
); );
(this.$router as Router).back(); this.$router.back();
} catch (err) { } catch (err) {
this.$notify( this.$notify(
{ {

14
src/views/SeedBackupView.vue

@ -62,7 +62,10 @@
) )
" "
> >
<font-awesome icon="copy" class="text-slate-400 fa-fw"></font-awesome> <font-awesome
icon="copy"
class="text-slate-400 fa-fw"
></font-awesome>
</button> </button>
<span v-show="showCopiedSeed" class="text-sm text-green-500"> <span v-show="showCopiedSeed" class="text-sm text-green-500">
Copied Copied
@ -79,7 +82,10 @@
) )
" "
> >
<font-awesome icon="copy" class="text-slate-400 fa-fw"></font-awesome> <font-awesome
icon="copy"
class="text-slate-400 fa-fw"
></font-awesome>
</button> </button>
<span v-show="showCopiedDeri" class="text-sm text-green-500" <span v-show="showCopiedDeri" class="text-sm text-green-500"
>Copied</span >Copied</span
@ -110,11 +116,11 @@ import {
retrieveAccountCount, retrieveAccountCount,
retrieveFullyDecryptedAccount, retrieveFullyDecryptedAccount,
} from "../libs/util"; } from "../libs/util";
import { Router } from "vue-router";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class SeedBackupView extends Vue { export default class SeedBackupView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeAccount: Account | null | undefined = null; activeAccount: Account | null | undefined = null;
numAccounts = 0; numAccounts = 0;
showCopiedDeri = false; showCopiedDeri = false;

3
src/views/ShareMyContactInfoView.vue

@ -56,6 +56,7 @@ import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer";
}) })
export default class ShareMyContactInfoView extends Vue { export default class ShareMyContactInfoView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
mounted() { mounted() {
console.log("APP_SERVER in mounted:", APP_SERVER); console.log("APP_SERVER in mounted:", APP_SERVER);
@ -106,7 +107,7 @@ export default class ShareMyContactInfoView extends Vue {
}, 3000); }, 3000);
} }
}); });
(this.$router as Router).push({ name: "contacts" }); this.$router.push({ name: "contacts" });
} else { } else {
this.$notify( this.$notify(
{ {

18
src/views/SharedPhotoView.vue

@ -66,7 +66,11 @@
<script lang="ts"> <script lang="ts">
import axios from "axios"; import axios from "axios";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { RouteLocationRaw, Router } from "vue-router"; import {
RouteLocationNormalizedLoaded,
RouteLocationRaw,
Router,
} from "vue-router";
import PhotoDialog from "../components/PhotoDialog.vue"; import PhotoDialog from "../components/PhotoDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
@ -83,6 +87,8 @@ import { base64ToBlob, SHARED_PHOTO_BASE64_KEY } from "../libs/util";
@Component({ components: { PhotoDialog, QuickNav } }) @Component({ components: { PhotoDialog, QuickNav } })
export default class SharedPhotoView extends Vue { export default class SharedPhotoView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
$route!: RouteLocationNormalizedLoaded;
activeDid: string | undefined = undefined; activeDid: string | undefined = undefined;
imageBlob: Blob | undefined = undefined; imageBlob: Blob | undefined = undefined;
@ -105,9 +111,7 @@ export default class SharedPhotoView extends Vue {
// clear the temp image // clear the temp image
db.temp.delete(SHARED_PHOTO_BASE64_KEY); db.temp.delete(SHARED_PHOTO_BASE64_KEY);
this.imageFileName = (this.$route as Router).query[ this.imageFileName = this.$route.query["fileName"] as string;
"fileName"
] as string;
} else { } else {
console.error("No appropriate image found in temp storage.", temp); console.error("No appropriate image found in temp storage.", temp);
} }
@ -138,7 +142,7 @@ export default class SharedPhotoView extends Vue {
recipientDid: this.activeDid, recipientDid: this.activeDid,
}, },
} as RouteLocationRaw; } as RouteLocationRaw;
(this.$router as Router).push(route); this.$router.push(route);
} }
}); });
} }
@ -149,7 +153,7 @@ export default class SharedPhotoView extends Vue {
await db.settings.update(MASTER_SETTINGS_KEY, { await db.settings.update(MASTER_SETTINGS_KEY, {
profileImageUrl: imgUrl, profileImageUrl: imgUrl,
}); });
(this.$router as Router).push({ name: "account" }); this.$router.push({ name: "account" });
}, },
IMAGE_TYPE_PROFILE, IMAGE_TYPE_PROFILE,
true, true,
@ -161,7 +165,7 @@ export default class SharedPhotoView extends Vue {
async cancel() { async cancel() {
this.imageBlob = undefined; this.imageBlob = undefined;
this.imageFileName = undefined; this.imageFileName = undefined;
(this.$router as Router).push({ name: "home" }); this.$router.push({ name: "home" });
} }
async sendToImageServer(imageType: string) { async sendToImageServer(imageType: string) {

9
src/views/StartView.vue

@ -102,6 +102,7 @@ import {
components: {}, components: {},
}) })
export default class StartView extends Vue { export default class StartView extends Vue {
$router!: Router;
PASSKEYS_ENABLED = PASSKEYS_ENABLED; PASSKEYS_ENABLED = PASSKEYS_ENABLED;
givenName = ""; givenName = "";
@ -115,22 +116,22 @@ export default class StartView extends Vue {
} }
public onClickNewSeed() { public onClickNewSeed() {
(this.$router as Router).push({ name: "new-identifier" }); this.$router.push({ name: "new-identifier" });
} }
public async onClickNewPasskey() { public async onClickNewPasskey() {
const keyName = const keyName =
AppString.APP_NAME + (this.givenName ? " - " + this.givenName : ""); AppString.APP_NAME + (this.givenName ? " - " + this.givenName : "");
await registerSaveAndActivatePasskey(keyName); await registerSaveAndActivatePasskey(keyName);
(this.$router as Router).push({ name: "account" }); this.$router.push({ name: "account" });
} }
public onClickNo() { public onClickNo() {
(this.$router as Router).push({ name: "import-account" }); this.$router.push({ name: "import-account" });
} }
public onClickDerive() { public onClickDerive() {
(this.$router as Router).push({ name: "import-derive" }); this.$router.push({ name: "import-derive" });
} }
} }
</script> </script>

3
src/views/StatisticsView.vue

@ -56,7 +56,7 @@
<script lang="ts"> <script lang="ts">
import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js"; import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router";
import { World } from "../components/World/World.js"; import { World } from "../components/World/World.js";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
@ -72,6 +72,7 @@ interface Dictionary<T> {
@Component({ components: { World, QuickNav } }) @Component({ components: { World, QuickNav } })
export default class StatisticsView extends Vue { export default class StatisticsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
world: World; world: World;
worldProperties: Dictionary<number> = {}; worldProperties: Dictionary<number> = {};

2
src/views/TestView.vue

@ -378,7 +378,7 @@ export default class Help extends Vue {
this.userName = DEFAULT_USERNAME; this.userName = DEFAULT_USERNAME;
}, },
onYes: async () => { onYes: async () => {
(this.$router as Router).push({ name: "new-edit-account" }); this.$router.push({ name: "new-edit-account" });
}, },
noText: "try again and use " + DEFAULT_USERNAME, noText: "try again and use " + DEFAULT_USERNAME,
}, },

2
src/views/UserProfileView.vue

@ -9,7 +9,7 @@
<h1 id="ViewHeading" class="text-lg text-center font-light relative px-7"> <h1 id="ViewHeading" class="text-lg text-center font-light relative px-7">
<!-- Back --> <!-- Back -->
<button <button
@click="$router.go(-1)" @click="$router.back()"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1" class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
> >
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome> <font-awesome icon="chevron-left" class="fa-fw"></font-awesome>

Loading…
Cancel
Save