Browse Source

feat: enhance GenericVerifiableCredential interface with explicit optional properties

- Add name, description, and agent as optional properties to GenericVerifiableCredential
- Improve type safety and IntelliSense for common claim properties
- Maintain backward compatibility with existing code
- Reduce need for type assertions when accessing claim properties
streamline-attempt
Matthew Raymer 2 weeks ago
parent
commit
2b0e60dfc2
  1. 8
      doc/migration-to-wa-sqlite.md
  2. 2
      src/components/FeedFilters.vue
  3. 1
      src/components/GiftedDialog.vue
  4. 1
      src/components/GiftedPrompts.vue
  5. 29
      src/components/ImageMethodDialog.vue
  6. 6
      src/components/MembersList.vue
  7. 1
      src/components/OfferDialog.vue
  8. 1
      src/components/PhotoDialog.vue
  9. 6
      src/components/PushNotificationPermission.vue
  10. 1
      src/components/TopMessage.vue
  11. 1
      src/components/UserNameDialog.vue
  12. 1
      src/components/World/components/objects/landmarks.js
  13. 2
      src/interfaces/index.ts
  14. 15
      src/libs/endorserServer.ts
  15. 2
      src/libs/partnerServer.ts
  16. 9
      src/libs/util.ts
  17. 7
      src/services/platforms/CapacitorPlatformService.ts
  18. 33
      src/views/AccountViewView.vue
  19. 27
      src/views/ClaimAddRawView.vue
  20. 9
      src/views/ClaimReportCertificateView.vue
  21. 1
      src/views/ClaimView.vue
  22. 1
      src/views/ConfirmGiftView.vue
  23. 12
      src/views/ContactAmountsView.vue
  24. 3
      src/views/ContactEditView.vue
  25. 1
      src/views/ContactGiftingView.vue
  26. 25
      src/views/ContactImportView.vue
  27. 3
      src/views/ContactQRScanFullView.vue
  28. 23
      src/views/DiscoverView.vue
  29. 1
      src/views/GiftedDetailsView.vue
  30. 5
      src/views/HelpNotificationsView.vue
  31. 4
      src/views/HelpView.vue
  32. 8
      src/views/HomeView.vue
  33. 6
      src/views/IdentitySwitcherView.vue
  34. 2
      src/views/ImportDerivedAccountView.vue
  35. 10
      src/views/LogView.vue
  36. 20
      src/views/NewEditProjectView.vue
  37. 5
      src/views/OfferDetailsView.vue
  38. 1
      src/views/OnboardMeetingListView.vue
  39. 8
      src/views/OnboardMeetingMembersView.vue
  40. 4
      src/views/OnboardMeetingSetupView.vue
  41. 10
      src/views/ProjectViewView.vue
  42. 11
      src/views/QuickActionBvcEndView.vue
  43. 1
      src/views/RecentOffersToUserView.vue
  44. 1
      src/views/ShareMyContactInfoView.vue
  45. 2
      src/views/SharedPhotoView.vue
  46. 2
      src/views/StartView.vue
  47. 13
      src/views/TestView.vue
  48. 1
      src/views/UserProfileView.vue

8
doc/migration-to-wa-sqlite.md

@ -69,8 +69,8 @@ export async function migrateActiveDid(): Promise<MigrationResult> {
// 3. Update SQLite master settings // 3. Update SQLite master settings
await updateDefaultSettings({ activeDid: dexieActiveDid }); await updateDefaultSettings({ activeDid: dexieActiveDid });
} }
``` ```
#### Enhanced `migrateSettings()` Function #### Enhanced `migrateSettings()` Function
The settings migration now includes activeDid handling: The settings migration now includes activeDid handling:
@ -171,7 +171,7 @@ npm run test:migration
``` ```
### ActiveDid Testing ### ActiveDid Testing
```typescript ```typescript
// Test activeDid migration specifically // Test activeDid migration specifically
const result = await migrateActiveDid(); const result = await migrateActiveDid();
expect(result.success).toBe(true); expect(result.success).toBe(true);
@ -204,7 +204,7 @@ logger.setLevel('debug');
// Check migration status // Check migration status
const comparison = await compareDatabases(); const comparison = await compareDatabases();
console.log('Settings differences:', comparison.differences.settings); console.log('Settings differences:', comparison.differences.settings);
``` ```
## Future Enhancements ## Future Enhancements

2
src/components/FeedFilters.vue

@ -101,8 +101,6 @@ import {
import { Router } from "vue-router"; import { Router } from "vue-router";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
@Component({ @Component({
components: { components: {

1
src/components/GiftedDialog.vue

@ -96,7 +96,6 @@ import {
serverMessageForUser, serverMessageForUser,
} from "../libs/endorserServer"; } from "../libs/endorserServer";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveAccountDids } from "../libs/util"; import { retrieveAccountDids } from "../libs/util";

1
src/components/GiftedPrompts.vue

@ -75,7 +75,6 @@ import { Vue, Component } from "vue-facing-decorator";
import { Router } from "vue-router"; import { Router } from "vue-router";
import { AppString, NotificationIface } from "../constants/app"; import { AppString, NotificationIface } from "../constants/app";
import { db } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { GiverReceiverInputInfo } from "../libs/util"; import { GiverReceiverInputInfo } from "../libs/util";

29
src/components/ImageMethodDialog.vue

@ -262,30 +262,21 @@ import { Component, Vue } from "vue-facing-decorator";
import VuePictureCropper, { cropper } from "vue-picture-cropper"; import VuePictureCropper, { cropper } from "vue-picture-cropper";
import { Capacitor } from "@capacitor/core"; import { Capacitor } from "@capacitor/core";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app"; import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { accessToken } from "../libs/crypto"; import { accessToken } from "../libs/crypto";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory"; import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { Prop } from "vue-facing-decorator";
import { Router } from "vue-router";
const inputImageFileNameRef = ref<Blob>(); const inputImageFileNameRef = ref<Blob>();
@Component({ @Component({
components: { VuePictureCropper }, components: { VuePictureCropper },
props: {
isRegistered: {
type: Boolean,
default: true,
},
defaultCameraMode: {
type: String,
default: "environment",
validator: (value: string) => ["environment", "user"].includes(value),
},
},
}) })
export default class ImageMethodDialog extends Vue { export default class ImageMethodDialog extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
/** Active DID for user authentication */ /** Active DID for user authentication */
activeDid = ""; activeDid = "";
@ -303,7 +294,7 @@ export default class ImageMethodDialog extends Vue {
fileName?: string; fileName?: string;
/** Callback function to set image URL after upload */ /** Callback function to set image URL after upload */
imageCallback: (imageUrl?: string) => void = () => {}; imageCallback: (imageUrl: string) => void = () => {};
/** URL for image input */ /** URL for image input */
imageUrl?: string; imageUrl?: string;
@ -351,6 +342,14 @@ export default class ImageMethodDialog extends Vue {
cameraStateMessage?: string; cameraStateMessage?: string;
error: string | null = null; error: string | null = null;
// Props
@Prop({ default: true }) isRegistered!: boolean;
@Prop({
default: "environment",
validator: (value: string) => ["environment", "user"].includes(value),
})
defaultCameraMode!: string;
/** /**
* Lifecycle hook: Initializes component and retrieves user settings * Lifecycle hook: Initializes component and retrieves user settings
* @throws {Error} When settings retrieval fails * @throws {Error} When settings retrieval fails
@ -411,7 +410,7 @@ export default class ImageMethodDialog extends Vue {
type: file.type, type: file.type,
}); });
this.blob = blob; this.blob = blob;
this.fileName = file.name; this.fileName = (file as File).name;
this.showRetry = false; this.showRetry = false;
} }
}; };
@ -442,7 +441,7 @@ export default class ImageMethodDialog extends Vue {
); );
} }
} else { } else {
this.imageCallback(this.imageUrl); this.imageCallback(this.imageUrl as string);
this.close(); this.close();
} }
} }

6
src/components/MembersList.vue

@ -159,11 +159,7 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue, Prop } from "vue-facing-decorator"; import { Component, Vue, Prop } from "vue-facing-decorator";
import { import { logConsoleAndDb } from "../db/index";
logConsoleAndDb,
retrieveSettingsForActiveAccount,
db,
} from "../db/index";
import { import {
errorStringForLog, errorStringForLog,
getHeaders, getHeaders,

1
src/components/OfferDialog.vue

@ -86,7 +86,6 @@ import { NotificationIface } from "../constants/app";
import { createAndSubmitOffer } from "../libs/endorserServer"; import { createAndSubmitOffer } from "../libs/endorserServer";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@Component @Component

1
src/components/PhotoDialog.vue

@ -121,7 +121,6 @@ import { Component, Vue } from "vue-facing-decorator";
import VuePictureCropper, { cropper } from "vue-picture-cropper"; import VuePictureCropper, { cropper } from "vue-picture-cropper";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app"; import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { accessToken } from "../libs/crypto"; import { accessToken } from "../libs/crypto";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory"; import { PlatformServiceFactory } from "../services/PlatformServiceFactory";

6
src/components/PushNotificationPermission.vue

@ -104,11 +104,7 @@ import { Component, Vue } from "vue-facing-decorator";
import { DEFAULT_PUSH_SERVER, NotificationIface } from "../constants/app"; import { DEFAULT_PUSH_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { import { logConsoleAndDb, secretDB } from "../db/index";
logConsoleAndDb,
retrieveSettingsForActiveAccount,
secretDB,
} from "../db/index";
import { MASTER_SECRET_KEY } from "../db/tables/secret"; import { MASTER_SECRET_KEY } from "../db/tables/secret";
import { urlBase64ToUint8Array } from "../libs/crypto/vc/util"; import { urlBase64ToUint8Array } from "../libs/crypto/vc/util";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";

1
src/components/TopMessage.vue

@ -17,7 +17,6 @@ import { Component, Vue, Prop } from "vue-facing-decorator";
import { AppString, NotificationIface } from "../constants/app"; import { AppString, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
@Component @Component
export default class TopMessage extends Vue { export default class TopMessage extends Vue {

1
src/components/UserNameDialog.vue

@ -38,7 +38,6 @@
import { Vue, Component, Prop } from "vue-facing-decorator"; import { Vue, Component, Prop } from "vue-facing-decorator";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings"; import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";

1
src/components/World/components/objects/landmarks.js

@ -4,7 +4,6 @@ import { GLTFLoader } from "three/addons/loaders/GLTFLoader";
import * as SkeletonUtils from "three/addons/utils/SkeletonUtils"; import * as SkeletonUtils from "three/addons/utils/SkeletonUtils";
import * as TWEEN from "@tweenjs/tween.js"; import * as TWEEN from "@tweenjs/tween.js";
import * as databaseUtil from "../../../../db/databaseUtil"; import * as databaseUtil from "../../../../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../../../../db";
import { getHeaders } from "../../../../libs/endorserServer"; import { getHeaders } from "../../../../libs/endorserServer";
import { logger } from "../../../../utils/logger"; import { logger } from "../../../../utils/logger";

2
src/interfaces/index.ts

@ -32,3 +32,5 @@ export type {
export * from "./limits"; export * from "./limits";
export * from "./deepLinks"; export * from "./deepLinks";
export * from "./common"; export * from "./common";
export * from "./claims-result";
export * from "./records";

15
src/libs/endorserServer.ts

@ -29,7 +29,6 @@ import {
} from "../constants/app"; } from "../constants/app";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { accessToken, deriveAddress, nextDerivationPath } from "../libs/crypto"; import { accessToken, deriveAddress, nextDerivationPath } from "../libs/crypto";
import { NonsensitiveDexie } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import { import {
retrieveAccountMetadata, retrieveAccountMetadata,
@ -689,6 +688,7 @@ export function hydrateGive(
if (amount && !isNaN(amount)) { if (amount && !isNaN(amount)) {
const quantitativeValue: QuantitativeValue = { const quantitativeValue: QuantitativeValue = {
"@type": "QuantitativeValue",
amountOfThisGood: amount, amountOfThisGood: amount,
unitCode: unitCode || "HUR", unitCode: unitCode || "HUR",
}; };
@ -999,11 +999,12 @@ export async function createAndSubmitClaim(
axios: Axios, axios: Axios,
): Promise<CreateAndSubmitClaimResult> { ): Promise<CreateAndSubmitClaimResult> {
try { try {
const vcPayload = { const vcPayload: { vc: VerifiableCredentialClaim } = {
vc: { vc: {
"@context": ["https://www.w3.org/2018/credentials/v1"], "@context": "https://www.w3.org/2018/credentials/v1",
"@type": "VerifiableCredential",
type: ["VerifiableCredential"], type: ["VerifiableCredential"],
credentialSubject: vcClaim, credentialSubject: vcClaim as unknown as ClaimObject, // Type assertion needed due to object being string
}, },
}; };
@ -1330,7 +1331,8 @@ export async function createEndorserJwtVcFromClaim(
// Make a payload for the claim // Make a payload for the claim
const vcPayload = { const vcPayload = {
vc: { vc: {
"@context": ["https://www.w3.org/2018/credentials/v1"], "@context": "https://www.w3.org/2018/credentials/v1",
"@type": "VerifiableCredential",
type: ["VerifiableCredential"], type: ["VerifiableCredential"],
credentialSubject: claim, credentialSubject: claim,
}, },
@ -1367,7 +1369,7 @@ export async function createInviteJwt(
// Make a payload for the claim // Make a payload for the claim
const vcPayload: { vc: VerifiableCredentialClaim } = { const vcPayload: { vc: VerifiableCredentialClaim } = {
vc: { vc: {
"@context": ["https://www.w3.org/2018/credentials/v1"], "@context": "https://www.w3.org/2018/credentials/v1",
"@type": "VerifiableCredential", "@type": "VerifiableCredential",
type: ["VerifiableCredential"], type: ["VerifiableCredential"],
credentialSubject: vcClaim as unknown as ClaimObject, // Type assertion needed due to object being string credentialSubject: vcClaim as unknown as ClaimObject, // Type assertion needed due to object being string
@ -1431,7 +1433,6 @@ export async function setVisibilityUtil(
activeDid: string, activeDid: string,
apiServer: string, apiServer: string,
axios: Axios, axios: Axios,
db: NonsensitiveDexie,
contact: Contact, contact: Contact,
visibility: boolean, visibility: boolean,
) { ) {

2
src/libs/partnerServer.ts

@ -4,6 +4,6 @@ export interface UserProfile {
locLon?: number; locLon?: number;
locLat2?: number; locLat2?: number;
locLon2?: number; locLon2?: number;
issuerDid: string; issuerDid?: string;
rowId?: string; // set on profile retrieved from server rowId?: string; // set on profile retrieved from server
} }

9
src/libs/util.ts

@ -6,12 +6,6 @@ import * as R from "ramda";
import { useClipboard } from "@vueuse/core"; import { useClipboard } from "@vueuse/core";
import { DEFAULT_PUSH_SERVER, NotificationIface } from "../constants/app"; import { DEFAULT_PUSH_SERVER, NotificationIface } from "../constants/app";
import {
accountsDBPromise,
retrieveSettingsForActiveAccount,
updateAccountSettings,
updateDefaultSettings,
} from "../db/index";
import { Account, AccountEncrypted } from "../db/tables/accounts"; import { Account, AccountEncrypted } from "../db/tables/accounts";
import { Contact, ContactWithJsonStrings } from "../db/tables/contacts"; import { Contact, ContactWithJsonStrings } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
@ -38,9 +32,8 @@ import { createPeerDid } from "../libs/crypto/vc/didPeer";
import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer"; import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { sha256 } from "ethereum-cryptography/sha256";
import { IIdentifier } from "@veramo/core"; import { IIdentifier } from "@veramo/core";
import { insertDidSpecificSettings, parseJsonField } from "../db/databaseUtil"; import { parseJsonField } from "../db/databaseUtil";
import { DEFAULT_ROOT_DERIVATION_PATH } from "./crypto"; import { DEFAULT_ROOT_DERIVATION_PATH } from "./crypto";
export interface GiverReceiverInputInfo { export interface GiverReceiverInputInfo {

7
src/services/platforms/CapacitorPlatformService.ts

@ -42,7 +42,7 @@ interface QueuedOperation {
*/ */
export class CapacitorPlatformService implements PlatformService { export class CapacitorPlatformService implements PlatformService {
/** Current camera direction */ /** Current camera direction */
private currentDirection: CameraDirection = "BACK"; private currentDirection: CameraDirection = CameraDirection.Rear;
private sqlite: SQLiteConnection; private sqlite: SQLiteConnection;
private db: SQLiteDBConnection | null = null; private db: SQLiteDBConnection | null = null;
@ -702,7 +702,10 @@ export class CapacitorPlatformService implements PlatformService {
* @returns Promise that resolves when the camera is rotated * @returns Promise that resolves when the camera is rotated
*/ */
async rotateCamera(): Promise<void> { async rotateCamera(): Promise<void> {
this.currentDirection = this.currentDirection === "BACK" ? "FRONT" : "BACK"; this.currentDirection =
this.currentDirection === CameraDirection.Rear
? CameraDirection.Front
: CameraDirection.Rear;
logger.debug(`Camera rotated to ${this.currentDirection} camera`); logger.debug(`Camera rotated to ${this.currentDirection} camera`);
} }

33
src/views/AccountViewView.vue

@ -357,12 +357,7 @@
<l-map <l-map
ref="profileMap" ref="profileMap"
class="!z-40 rounded-md" class="!z-40 rounded-md"
@click=" @click="onProfileMapClick"
(event: LeafletMouseEvent) => {
userProfileLatitude = event.latlng.lat;
userProfileLongitude = event.latlng.lng;
}
"
@ready="onMapReady" @ready="onMapReady"
> >
<l-tile-layer <l-tile-layer
@ -437,7 +432,7 @@
You have done You have done
<b <b
>{{ endorserLimits?.doneClaimsThisWeek ?? "?" }} claim{{ >{{ endorserLimits?.doneClaimsThisWeek ?? "?" }} claim{{
endorserLimits?.doneClaimsThisWeek === 1 ? "" : "s" Number(endorserLimits?.doneClaimsThisWeek || 0) === 1 ? "" : "s"
}}</b }}</b
> >
out of <b>{{ endorserLimits?.maxClaimsPerWeek ?? "?" }}</b> for this out of <b>{{ endorserLimits?.maxClaimsPerWeek ?? "?" }}</b> for this
@ -453,7 +448,9 @@
endorserLimits?.doneRegistrationsThisMonth ?? "?" endorserLimits?.doneRegistrationsThisMonth ?? "?"
}} }}
registration{{ registration{{
endorserLimits?.doneRegistrationsThisMonth === 1 ? "" : "s" Number(endorserLimits?.doneRegistrationsThisMonth || 0) === 1
? ""
: "s"
}}</b }}</b
> >
out of out of
@ -469,13 +466,13 @@
You have uploaded You have uploaded
<b <b
>{{ imageLimits?.doneImagesThisWeek ?? "?" }} image{{ >{{ imageLimits?.doneImagesThisWeek ?? "?" }} image{{
imageLimits?.doneImagesThisWeek === 1 ? "" : "s" Number(imageLimits?.doneImagesThisWeek || 0) === 1 ? "" : "s"
}}</b }}</b
> >
out of <b>{{ imageLimits?.maxImagesPerWeek ?? "?" }}</b> for this out of <b>{{ imageLimits?.maxImagesPerWeek ?? "?" }}</b> for this
week. Your image counter resets at week. Your image counter resets at
<b class="whitespace-nowrap">{{ <b class="whitespace-nowrap">{{
readableDate(imageLimits?.nextWeekBeginDateTime) readableDate(imageLimits?.nextWeekBeginDateTime || "")
}}</b> }}</b>
</p> </p>
</div> </div>
@ -1037,7 +1034,10 @@ const inputImportFileNameRef = ref<Blob>();
// Type guard for API errors // Type guard for API errors
function isApiError(error: unknown): error is { function isApiError(error: unknown): error is {
response?: { data?: { error?: { message?: string } | string } }; response?: {
data?: { error?: { message?: string } | string };
status?: number;
};
} { } {
return typeof error === "object" && error !== null && "response" in error; return typeof error === "object" && error !== null && "response" in error;
} }
@ -1172,7 +1172,7 @@ export default class AccountViewView extends Vue {
throw Error("Unable to load profile."); throw Error("Unable to load profile.");
} }
} catch (error) { } catch (error) {
if (error.status === 404) { if (isApiError(error) && error.response?.status === 404) {
// this is ok: the profile is not yet created // this is ok: the profile is not yet created
} else { } else {
databaseUtil.logConsoleAndDb( databaseUtil.logConsoleAndDb(
@ -1610,7 +1610,9 @@ export default class AccountViewView extends Vue {
} }
async uploadImportFile(event: Event) { async uploadImportFile(event: Event) {
inputImportFileNameRef.value = (event.target as EventTarget).files[0]; inputImportFileNameRef.value = (
event.target as HTMLInputElement
).files?.[0];
} }
showContactImport() { showContactImport() {
@ -2093,5 +2095,10 @@ export default class AccountViewView extends Vue {
this.$router.push({ name: "contact-qr" }); this.$router.push({ name: "contact-qr" });
} }
} }
onProfileMapClick(event: LeafletMouseEvent) {
this.userProfileLatitude = event.latlng.lat;
this.userProfileLongitude = event.latlng.lng;
}
} }
</script> </script>

27
src/views/ClaimAddRawView.vue

@ -30,12 +30,11 @@
<script lang="ts"> <script lang="ts">
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { AxiosInstance } from "axios"; import { AxiosResponse, AxiosStatic } from "axios";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
@ -43,6 +42,16 @@ import { errorStringForLog } from "../libs/endorserServer";
import { Router, RouteLocationNormalizedLoaded } from "vue-router"; import { Router, RouteLocationNormalizedLoaded } from "vue-router";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
// Type guard for API responses
function isApiResponse(response: unknown): response is AxiosResponse {
return (
typeof response === "object" &&
response !== null &&
"status" in response &&
"data" in response
);
}
/** /**
* View component for adding or editing raw claim data * View component for adding or editing raw claim data
* Allows direct JSON editing of claim data with validation and submission * Allows direct JSON editing of claim data with validation and submission
@ -54,7 +63,7 @@ export default class ClaimAddRawView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded; $route!: RouteLocationNormalizedLoaded;
$router!: Router; $router!: Router;
axios!: AxiosInstance; axios!: AxiosStatic; // Using any to avoid type conflicts with Vue's axios property
accountIdentityStr: string = "null"; accountIdentityStr: string = "null";
activeDid = ""; activeDid = "";
@ -145,17 +154,19 @@ export default class ClaimAddRawView extends Vue {
* Format successful claim response data * Format successful claim response data
*/ */
private formatClaimResponse(response: unknown, claimJwtId: string) { private formatClaimResponse(response: unknown, claimJwtId: string) {
if (response.status === 200) { if (isApiResponse(response) && response.status === 200) {
const claim = response.data?.claim; const claim = response.data?.claim;
claim.lastClaimId = serverUtil.stripEndorserPrefix(claimJwtId); claim.lastClaimId = serverUtil.stripEndorserPrefix(claimJwtId);
this.claimStr = JSON.stringify(claim, null, 2); this.claimStr = JSON.stringify(claim, null, 2);
} else { } else {
throw { throw {
message: "Got an error loading that claim.", message: "Got an error loading that claim.",
response: { response: isApiResponse(response)
status: response.status, ? {
statusText: response.statusText, status: response.status,
}, statusText: response.statusText,
}
: { status: 0, statusText: "Unknown response type" },
}; };
} }
} }

9
src/views/ClaimReportCertificateView.vue

@ -12,9 +12,12 @@ import { nextTick } from "vue";
import QRCode from "qrcode"; import QRCode from "qrcode";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_SERVER, NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import * as endorserServer from "../libs/endorserServer"; import * as endorserServer from "../libs/endorserServer";
import {
GenericCredWrapper,
GenericVerifiableCredential,
} from "../interfaces/common";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts"; import { Contact } from "@/db/tables/contacts";
@ -66,9 +69,7 @@ export default class ClaimReportCertificateView extends Vue {
} }
} }
async drawCanvas( async drawCanvas(claimData: GenericCredWrapper<GenericVerifiableCredential>) {
claimData: endorserServer.GenericCredWrapper<endorserServer.GenericVerifiableCredential>,
) {
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const dbAllContacts = await platformService.dbQuery( const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts", "SELECT * FROM contacts",

1
src/views/ClaimView.vue

@ -559,7 +559,6 @@ import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";

1
src/views/ConfirmGiftView.vue

@ -437,7 +437,6 @@ import { useClipboard } from "@vueuse/core";
import { RouteLocationNormalizedLoaded, Router } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_SERVER, NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";

12
src/views/ContactAmountsView.vue

@ -48,7 +48,7 @@
<tbody> <tbody>
<tr <tr
v-for="record in giveRecords" v-for="record in giveRecords"
:key="record.id" :key="record.jwtId"
class="border-b border-slate-300" class="border-b border-slate-300"
> >
<td class="p-1 text-xs sm:text-sm text-left text-slate-500"> <td class="p-1 text-xs sm:text-sm text-left text-slate-500">
@ -118,14 +118,10 @@ 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";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { import { GiveSummaryRecord, GiveActionClaim } from "../interfaces";
AgreeVerifiableCredential, import { AgreeActionClaim } from "../interfaces/claims";
GiveSummaryRecord,
GiveActionClaim,
} from "../interfaces";
import { import {
createEndorserJwtVcFromClaim, createEndorserJwtVcFromClaim,
displayAmount, displayAmount,
@ -274,7 +270,7 @@ export default class ContactAmountssView extends Vue {
delete origClaim["@context"]; delete origClaim["@context"];
} }
origClaim["identifier"] = record.handleId; origClaim["identifier"] = record.handleId;
const vcClaim: AgreeVerifiableCredential = { const vcClaim: AgreeActionClaim = {
"@context": SCHEMA_ORG_CONTEXT, "@context": SCHEMA_ORG_CONTEXT,
"@type": "AgreeAction", "@type": "AgreeAction",
object: origClaim, object: origClaim,

3
src/views/ContactEditView.vue

@ -12,7 +12,7 @@
> >
<font-awesome icon="chevron-left" class="fa-fw" /> <font-awesome icon="chevron-left" class="fa-fw" />
</button> </button>
{{ contact.name || AppString.NO_CONTACT_NAME }} {{ contact?.name || AppString.NO_CONTACT_NAME }}
</h1> </h1>
</div> </div>
@ -141,7 +141,6 @@ import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { parseJsonField } from "../db/databaseUtil"; import { parseJsonField } from "../db/databaseUtil";
import { db } from "../db/index";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory"; import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import { Contact, ContactMethod } from "../db/tables/contacts"; import { Contact, ContactMethod } from "../db/tables/contacts";
import { AppString } from "../constants/app"; import { AppString } from "../constants/app";

1
src/views/ContactGiftingView.vue

@ -77,7 +77,6 @@ import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import EntityIcon from "../components/EntityIcon.vue"; import EntityIcon from "../components/EntityIcon.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { GiverReceiverInputInfo } from "../libs/util"; import { GiverReceiverInputInfo } from "../libs/util";

25
src/views/ContactImportView.vue

@ -201,14 +201,9 @@ import QuickNav from "../components/QuickNav.vue";
import EntityIcon from "../components/EntityIcon.vue"; import EntityIcon from "../components/EntityIcon.vue";
import OfferDialog from "../components/OfferDialog.vue"; import OfferDialog from "../components/OfferDialog.vue";
import { APP_SERVER, AppString, NotificationIface } from "../constants/app"; import { APP_SERVER, AppString, NotificationIface } from "../constants/app";
import { import { logConsoleAndDb } from "../db/index";
db,
logConsoleAndDb,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { Contact, ContactMethod } from "../db/tables/contacts"; import { Contact, ContactMethod } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { parseJsonField } from "../db/databaseUtil";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { import {
capitalizeAndInsertSpacesBeforeCaps, capitalizeAndInsertSpacesBeforeCaps,
@ -272,23 +267,6 @@ function contactToDbRecord(contact: Contact): ContactDbRecord {
}; };
} }
/**
* Converts a ContactDbRecord back to a Contact object
* @param record The database record to convert
* @returns A Contact object with parsed contactMethods array
*/
function dbRecordToContact(record: ContactDbRecord): Contact {
return {
...record,
name: safeString(record.name),
notes: safeString(record.notes),
profileImageUrl: safeString(record.profileImageUrl),
publicKeyBase64: safeString(record.publicKeyBase64),
nextPubKeyHashB64: safeString(record.nextPubKeyHashB64),
contactMethods: parseJsonField(record.contactMethods, []),
};
}
/** /**
* Contact Import View Component * Contact Import View Component
* @author Matthew Raymer * @author Matthew Raymer
@ -632,7 +610,6 @@ export default class ContactImportView extends Vue {
this.activeDid, this.activeDid,
this.apiServer, this.apiServer,
this.axios, this.axios,
db,
contact, contact,
true, true,
); );

3
src/views/ContactQRScanFullView.vue

@ -114,12 +114,10 @@ import { logger } from "../utils/logger";
import { QRScannerFactory } from "../services/QRScanner/QRScannerFactory"; import { QRScannerFactory } from "../services/QRScanner/QRScannerFactory";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import { db } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { getContactJwtFromJwtUrl } from "../libs/crypto"; import { getContactJwtFromJwtUrl } from "../libs/crypto";
import { decodeEndorserJwt, ETHR_DID_PREFIX } from "../libs/crypto/vc"; import { decodeEndorserJwt, ETHR_DID_PREFIX } from "../libs/crypto/vc";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import { retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { import {
CONTACT_CSV_HEADER, CONTACT_CSV_HEADER,
@ -444,7 +442,6 @@ export default class ContactQRScanFull extends Vue {
this.activeDid, this.activeDid,
this.apiServer, this.apiServer,
this.axios, this.axios,
db,
contact, contact,
visibility, visibility,
); );

23
src/views/DiscoverView.vue

@ -324,20 +324,12 @@ import {
NotificationIface, NotificationIface,
DEFAULT_PARTNER_API_SERVER, DEFAULT_PARTNER_API_SERVER,
} from "../constants/app"; } from "../constants/app";
import { import { logConsoleAndDb } from "../db/index";
db,
logConsoleAndDb,
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 * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { PlanData } from "../interfaces"; import { PlanData } from "../interfaces";
import { import { didInfo, errorStringForLog, getHeaders } from "../libs/endorserServer";
didInfo,
errorStringForLog,
getHeaders,
} from "../libs/endorserServer";
import { OnboardPage, retrieveAccountDids } from "../libs/util"; import { OnboardPage, retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { UserProfile } from "@/libs/partnerServer"; import { UserProfile } from "@/libs/partnerServer";
@ -396,7 +388,6 @@ export default class DiscoverView extends Vue {
didInfo = didInfo; didInfo = didInfo;
async mounted() { async mounted() {
this.searchTerms = this.$route.query["searchText"]?.toString() || ""; this.searchTerms = this.$route.query["searchText"]?.toString() || "";
const searchPeople = !!this.$route.query["searchPeople"]; const searchPeople = !!this.$route.query["searchPeople"];
@ -410,7 +401,9 @@ export default class DiscoverView extends Vue {
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const dbContacts = await platformService.dbQuery("SELECT * FROM contacts"); const dbContacts = await platformService.dbQuery("SELECT * FROM contacts");
this.allContacts = databaseUtil.mapQueryResultToValues(dbContacts) as unknown as Contact[]; this.allContacts = databaseUtil.mapQueryResultToValues(
dbContacts,
) as unknown as Contact[];
this.allMyDids = await retrieveAccountDids(); this.allMyDids = await retrieveAccountDids();
@ -504,7 +497,8 @@ export default class DiscoverView extends Vue {
} else { } else {
throw JSON.stringify(results); throw JSON.stringify(results);
} }
} else { // people search must be active } else {
// people search must be active
this.projects = []; this.projects = [];
const profiles: UserProfile[] = results.data; const profiles: UserProfile[] = results.data;
if (profiles) { if (profiles) {
@ -707,7 +701,8 @@ export default class DiscoverView extends Vue {
this.clearMarkers(); this.clearMarkers();
const results = await response.json(); const results = await response.json();
if (results.data?.tiles?.length > 0) { if (results.data?.tiles?.length > 0) {
for (const tile: Tile of results.data.tiles) { for (const t of results.data.tiles) {
const tile: Tile = t;
const pinLat = (tile.minFoundLat + tile.maxFoundLat) / 2; const pinLat = (tile.minFoundLat + tile.maxFoundLat) / 2;
const pinLon = (tile.minFoundLon + tile.maxFoundLon) / 2; const pinLon = (tile.minFoundLon + tile.maxFoundLon) / 2;
const numberIcon = L.divIcon({ const numberIcon = L.divIcon({

1
src/views/GiftedDetailsView.vue

@ -262,7 +262,6 @@ import ImageMethodDialog from "../components/ImageMethodDialog.vue";
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 { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app"; import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { GenericCredWrapper, GiveActionClaim } from "../interfaces"; import { GenericCredWrapper, GiveActionClaim } from "../interfaces";
import { import {

5
src/views/HelpNotificationsView.vue

@ -311,8 +311,6 @@ import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import { DIRECT_PUSH_TITLE, sendTestThroughPushServer } from "../libs/util"; 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 { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { Router } from "vue-router"; import { Router } from "vue-router";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
@ -322,6 +320,9 @@ export default class HelpNotificationsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router; $router!: Router;
subscriptionJSON?: PushSubscriptionJSON; subscriptionJSON?: PushSubscriptionJSON;
notifyingReminder = false;
notifyingReminderMessage = "";
notifyingReminderTime = "";
async mounted() { async mounted() {
try { try {

4
src/views/HelpView.vue

@ -603,10 +603,6 @@ import * as Package from "../../package.json";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import {
retrieveSettingsForActiveAccount,
updateAccountSettings,
} from "../db/index";
@Component({ components: { QuickNav } }) @Component({ components: { QuickNav } })
export default class HelpView extends Vue { export default class HelpView extends Vue {

8
src/views/HomeView.vue

@ -321,11 +321,7 @@ import {
} from "../constants/app"; } from "../constants/app";
import { logConsoleAndDb } from "../db/index"; import { logConsoleAndDb } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { import { BoundingBox, checkIsAnyFeedFilterOn } from "../db/tables/settings";
BoundingBox,
checkIsAnyFeedFilterOn,
MASTER_SETTINGS_KEY,
} from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { import {
contactForDid, contactForDid,
@ -1729,7 +1725,7 @@ export default class HomeView extends Vue {
* @param event Event object * @param event Event object
* @param imageUrl URL of image to cache * @param imageUrl URL of image to cache
*/ */
async cacheImageData(event: Event, imageUrl: string) { async cacheImageData(_event: Event, imageUrl: string) {
try { try {
// For images that might fail CORS, just store the URL // For images that might fail CORS, just store the URL
// The Web Share API will handle sharing the URL appropriately // The Web Share API will handle sharing the URL appropriately

6
src/views/IdentitySwitcherView.vue

@ -106,12 +106,6 @@ import { 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";
import {
accountsDBPromise,
db,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveAllAccountsMetadata } from "../libs/util"; import { retrieveAllAccountsMetadata } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";

2
src/views/ImportDerivedAccountView.vue

@ -80,8 +80,6 @@ import {
nextDerivationPath, nextDerivationPath,
} from "../libs/crypto"; } from "../libs/crypto";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { import {
retrieveAllAccountsMetadata, retrieveAllAccountsMetadata,
retrieveFullyDecryptedAccount, retrieveFullyDecryptedAccount,

10
src/views/LogView.vue

@ -58,12 +58,15 @@ import { 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";
import { db } from "../db/index";
import { Log } from "../db/tables/logs";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory"; import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
interface Log {
date: string;
message: string;
}
@Component({ @Component({
components: { components: {
QuickNav, QuickNav,
@ -74,8 +77,8 @@ export default class LogView extends Vue {
$router!: Router; $router!: Router;
loading = true; loading = true;
logs: Log[] = [];
error: string | null = null; error: string | null = null;
logs: Log[] = [];
memoryLogs: string[] = []; memoryLogs: string[] = [];
async mounted() { async mounted() {
@ -87,7 +90,6 @@ export default class LogView extends Vue {
this.error = null; // Clear any previous errors this.error = null; // Clear any previous errors
this.memoryLogs = databaseUtil.memoryLogs; this.memoryLogs = databaseUtil.memoryLogs;
const allLogs: Log[] = [];
const platformService = PlatformServiceFactory.getInstance(); const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery( const queryResult = await platformService.dbQuery(
"SELECT * FROM logs ORDER BY date DESC", "SELECT * FROM logs ORDER BY date DESC",

20
src/views/NewEditProjectView.vue

@ -154,12 +154,7 @@
v-model:zoom="zoom" v-model:zoom="zoom"
:center="[0, 0]" :center="[0, 0]"
class="!z-40 rounded-md" class="!z-40 rounded-md"
@click=" @click="onMapClick"
(event) => {
latitude = event.latlng.lat;
longitude = event.latlng.lng;
}
"
> >
<l-tile-layer <l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
@ -230,6 +225,7 @@ import {
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet"; import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
import { RouteLocationNormalizedLoaded, Router } from "vue-router"; import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import { LeafletMouseEvent } from "leaflet";
import ImageMethodDialog from "../components/ImageMethodDialog.vue"; import ImageMethodDialog from "../components/ImageMethodDialog.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
@ -239,8 +235,7 @@ import {
NotificationIface, NotificationIface,
} from "../constants/app"; } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index"; import { PlanActionClaim } from "../interfaces/claims";
import { PlanVerifiableCredential } from "../interfaces";
import { import {
createEndorserJwtVcFromClaim, createEndorserJwtVcFromClaim,
getHeaders, getHeaders,
@ -277,7 +272,7 @@ export default class NewEditProjectView extends Vue {
endDateInput?: string; endDateInput?: string;
endTimeInput?: string; endTimeInput?: string;
errorMessage = ""; errorMessage = "";
fullClaim: PlanVerifiableCredential = { fullClaim: PlanActionClaim = {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "PlanAction", "@type": "PlanAction",
name: "", name: "",
@ -445,7 +440,7 @@ export default class NewEditProjectView extends Vue {
private async saveProject() { private async saveProject() {
// Make a claim // Make a claim
const vcClaim: PlanVerifiableCredential = this.fullClaim; const vcClaim: PlanActionClaim = this.fullClaim;
if (this.projectId) { if (this.projectId) {
vcClaim.lastClaimId = this.lastClaimJwtId; vcClaim.lastClaimId = this.lastClaimJwtId;
} }
@ -823,5 +818,10 @@ export default class NewEditProjectView extends Vue {
7000, 7000,
); );
} }
onMapClick(event: LeafletMouseEvent) {
this.latitude = event.latlng.lat;
this.longitude = event.latlng.lng;
}
} }
</script> </script>

5
src/views/OfferDetailsView.vue

@ -181,7 +181,6 @@ 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";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { GenericCredWrapper, OfferClaim } from "../interfaces"; import { GenericCredWrapper, OfferClaim } from "../interfaces";
import { import {
createAndSubmitOffer, createAndSubmitOffer,
@ -314,7 +313,9 @@ export default class OfferDetailsView extends Vue {
group: "alert", group: "alert",
type: "danger", type: "danger",
title: "Error", title: "Error",
text: err.message || "There was an error loading the offer details.", text:
(err as Error)?.message ||
"There was an error loading the offer details.",
}, },
5000, 5000,
); );

1
src/views/OnboardMeetingListView.vue

@ -90,7 +90,6 @@ import { 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";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import { import {
errorStringForLog, errorStringForLog,

8
src/views/OnboardMeetingMembersView.vue

@ -123,7 +123,9 @@ export default class OnboardMeetingMembersView extends Vue {
const member = response.data?.data; const member = response.data?.data;
if (!member) { if (!member) {
if (!this.firstName) { if (!this.firstName) {
this.$refs.userNameDialog.open(this.addMemberToMeeting); (this.$refs.userNameDialog as UserNameDialog).open(
this.addMemberToMeeting,
);
// addMemberToMeeting sets isLoading to false // addMemberToMeeting sets isLoading to false
} else { } else {
await this.addMemberToMeeting(this.firstName); await this.addMemberToMeeting(this.firstName);
@ -136,7 +138,9 @@ export default class OnboardMeetingMembersView extends Vue {
} else { } else {
// must be already in the right meeting // must be already in the right meeting
if (!this.firstName) { if (!this.firstName) {
this.$refs.userNameDialog.open(this.updateMemberInMeeting); (this.$refs.userNameDialog as UserNameDialog).open(
this.updateMemberInMeeting,
);
// updateMemberInMeeting sets isLoading to false // updateMemberInMeeting sets isLoading to false
} else { } else {
await this.updateMemberInMeeting(this.firstName); await this.updateMemberInMeeting(this.firstName);

4
src/views/OnboardMeetingSetupView.vue

@ -271,12 +271,12 @@
<script lang="ts"> <script lang="ts">
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 { 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";
import MembersList from "../components/MembersList.vue"; import MembersList from "../components/MembersList.vue";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil"; import { logConsoleAndDb } from "../db/databaseUtil";
import { import {
errorStringForLog, errorStringForLog,
@ -315,6 +315,8 @@ export default class OnboardMeetingView extends Vue {
notification: { group: string; type: string; title: string; text: string }, notification: { group: string; type: string; title: string; text: string },
timeout?: number, timeout?: number,
) => void; ) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
currentMeeting: ServerMeeting | null = null; currentMeeting: ServerMeeting | null = null;
newOrUpdatedMeetingInputs: MeetingSetupInputs | null = null; newOrUpdatedMeetingInputs: MeetingSetupInputs | null = null;

10
src/views/ProjectViewView.vue

@ -447,7 +447,7 @@
<ul class="mt-2 text-sm border-t border-slate-300"> <ul class="mt-2 text-sm border-t border-slate-300">
<li <li
v-for="give in givesToThis" v-for="give in givesToThis"
:key="give.id" :key="give.jwtId"
class="py-1.5 border-b border-slate-300" class="py-1.5 border-b border-slate-300"
> >
<div class="flex justify-between gap-4"> <div class="flex justify-between gap-4">
@ -644,11 +644,7 @@ import EntityIcon from "../components/EntityIcon.vue";
import ProjectIcon from "../components/ProjectIcon.vue"; import ProjectIcon from "../components/ProjectIcon.vue";
import { APP_SERVER, NotificationIface } from "../constants/app"; import { APP_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { import { logConsoleAndDb } from "../db/index";
db,
logConsoleAndDb,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import * as libsUtil from "../libs/util"; import * as libsUtil from "../libs/util";
import * as serverUtil from "../libs/endorserServer"; import * as serverUtil from "../libs/endorserServer";
@ -1476,7 +1472,7 @@ export default class ProjectViewView extends Vue {
} else { } else {
logger.error("Got error submitting the confirmation:", result); logger.error("Got error submitting the confirmation:", result);
const message = const message =
(result.error?.error as string) || (result.error as string) ||
"There was a problem submitting the confirmation."; "There was a problem submitting the confirmation.";
this.$notify( this.$notify(
{ {

11
src/views/QuickActionBvcEndView.vue

@ -146,11 +146,6 @@ import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import {
accountsDBPromise,
db,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { import {
GenericCredWrapper, GenericCredWrapper,
@ -175,8 +170,9 @@ import { retrieveAllAccountsMetadata } from "@/libs/util";
TopMessage, TopMessage,
}, },
}) })
export default class QuickActionBvcBeginView extends Vue { export default class QuickActionBvcEndView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void; $notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid = ""; activeDid = "";
allContacts: Array<Contact> = []; allContacts: Array<Contact> = [];
@ -191,6 +187,9 @@ export default class QuickActionBvcBeginView extends Vue {
someoneGave = false; someoneGave = false;
supplyGiftDetails = false; supplyGiftDetails = false;
// Method used in template
claimSpecialDescription = claimSpecialDescription;
async created() { async created() {
this.loadingConfirms = true; this.loadingConfirms = true;

1
src/views/RecentOffersToUserView.vue

@ -78,7 +78,6 @@ import InfiniteScroll from "../components/InfiniteScroll.vue";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app"; import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { OfferSummaryRecord } from "../interfaces"; import { OfferSummaryRecord } from "../interfaces";
import { import {

1
src/views/ShareMyContactInfoView.vue

@ -48,7 +48,6 @@ import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue"; import TopMessage from "../components/TopMessage.vue";
import { NotificationIface, APP_SERVER } from "../constants/app"; import { NotificationIface, APP_SERVER } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { retrieveFullyDecryptedAccount } from "../libs/util"; import { retrieveFullyDecryptedAccount } from "../libs/util";
import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer"; import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";

2
src/views/SharedPhotoView.vue

@ -80,8 +80,6 @@ import {
NotificationIface, NotificationIface,
} from "../constants/app"; } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { accessToken } from "../libs/crypto"; import { accessToken } from "../libs/crypto";
import { base64ToBlob, SHARED_PHOTO_BASE64_KEY } from "../libs/util"; import { base64ToBlob, SHARED_PHOTO_BASE64_KEY } from "../libs/util";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";

2
src/views/StartView.vue

@ -105,7 +105,7 @@ import { Router } from "vue-router";
import { AppString, PASSKEYS_ENABLED } from "../constants/app"; import { AppString, PASSKEYS_ENABLED } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { import {
registerSaveAndActivatePasskey, registerSaveAndActivatePasskey,
retrieveAccountCount, retrieveAccountCount,

13
src/views/TestView.vue

@ -341,7 +341,6 @@ import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue"; import QuickNav from "../components/QuickNav.vue";
import { AppString, NotificationIface } from "../constants/app"; import { AppString, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as vcLib from "../libs/crypto/vc"; import * as vcLib from "../libs/crypto/vc";
import * as cryptoLib from "../libs/crypto"; import * as cryptoLib from "../libs/crypto";
@ -352,7 +351,6 @@ import {
verifyJwtWebCrypto, verifyJwtWebCrypto,
} from "../libs/crypto/vc/passkeyDidPeer"; } from "../libs/crypto/vc/passkeyDidPeer";
import { import {
AccountKeyInfo,
blobToBase64, blobToBase64,
retrieveAccountMetadata, retrieveAccountMetadata,
registerAndSavePasskey, registerAndSavePasskey,
@ -361,6 +359,7 @@ import {
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory"; import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Temp } from "@/db/tables/temp"; import { Temp } from "@/db/tables/temp";
import { Account } from "../db/tables/accounts";
const inputFileNameRef = ref<Blob>(); const inputFileNameRef = ref<Blob>();
const TEST_PAYLOAD = { const TEST_PAYLOAD = {
@ -498,7 +497,7 @@ export default class Help extends Vue {
} }
public async createJwtSimplewebauthn() { public async createJwtSimplewebauthn() {
const account: AccountKeyInfo | undefined = await retrieveAccountMetadata( const account: Account | undefined = await retrieveAccountMetadata(
this.activeDid || "", this.activeDid || "",
); );
if (!vcLib.isFromPasskey(account)) { if (!vcLib.isFromPasskey(account)) {
@ -515,7 +514,7 @@ export default class Help extends Vue {
} }
public async createJwtNavigator() { public async createJwtNavigator() {
const account: AccountKeyInfo | undefined = await retrieveAccountMetadata( const account: Account | undefined = await retrieveAccountMetadata(
this.activeDid || "", this.activeDid || "",
); );
if (!vcLib.isFromPasskey(account)) { if (!vcLib.isFromPasskey(account)) {
@ -533,11 +532,9 @@ export default class Help extends Vue {
public async verifyP256() { public async verifyP256() {
const decoded = await verifyJwtP256( const decoded = await verifyJwtP256(
this.credIdHex as string,
this.activeDid as string, this.activeDid as string,
this.peerSetup?.authenticatorData as ArrayBuffer, this.peerSetup?.authenticatorData as ArrayBuffer,
this.peerSetup?.challenge as Uint8Array, this.peerSetup?.challenge as Uint8Array,
this.peerSetup?.clientDataJsonBase64Url as Base64URLString,
this.peerSetup?.signature as Base64URLString, this.peerSetup?.signature as Base64URLString,
); );
logger.log("decoded", decoded); logger.log("decoded", decoded);
@ -557,11 +554,9 @@ export default class Help extends Vue {
public async verifyWebCrypto() { public async verifyWebCrypto() {
const decoded = await verifyJwtWebCrypto( const decoded = await verifyJwtWebCrypto(
this.credIdHex as string,
this.activeDid as string, this.activeDid as string,
this.peerSetup?.authenticatorData as ArrayBuffer, this.peerSetup?.authenticatorData as ArrayBuffer,
this.peerSetup?.challenge as Uint8Array, this.peerSetup?.challenge as Uint8Array,
this.peerSetup?.clientDataJsonBase64Url as Base64URLString,
this.peerSetup?.signature as Base64URLString, this.peerSetup?.signature as Base64URLString,
); );
logger.log("decoded", decoded); logger.log("decoded", decoded);
@ -583,11 +578,9 @@ export default class Help extends Vue {
const challenge = clientData.challenge; const challenge = clientData.challenge;
const signatureB64URL = pieces[2]; const signatureB64URL = pieces[2];
const decoded = await verifyJwtWebCrypto( const decoded = await verifyJwtWebCrypto(
this.credIdHex as string,
did, did,
authData, authData,
challenge, challenge,
payload["ClientDataJSONB64URL"],
signatureB64URL, signatureB64URL,
); );
logger.log("decoded", decoded); logger.log("decoded", decoded);

1
src/views/UserProfileView.vue

@ -112,7 +112,6 @@ import {
NotificationIface, NotificationIface,
} from "../constants/app"; } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil"; import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { Contact } from "../db/tables/contacts"; import { Contact } from "../db/tables/contacts";
import { didInfo, getHeaders } from "../libs/endorserServer"; import { didInfo, getHeaders } from "../libs/endorserServer";
import { UserProfile } from "../libs/partnerServer"; import { UserProfile } from "../libs/partnerServer";

Loading…
Cancel
Save