forked from jsnbuchanan/crowd-funder-for-time-pwa
feat: implement ActiveDid migration to active_identity table
- Add $getActiveIdentity() method to PlatformServiceMixin interface - Update HomeView.vue to use new active_identity API methods - Update ContactsView.vue to use new active_identity API methods - Fix apiServer default handling in PlatformServiceMixin - Ensure DEFAULT_ENDORSER_API_SERVER is used when apiServer is empty - Add comprehensive logging for debugging ActiveDid migration - Resolve TypeScript interface issues with Vue mixins
This commit is contained in:
@@ -238,7 +238,7 @@ Raymer * @version 1.0.0 */
|
||||
|
||||
<script lang="ts">
|
||||
import { UAParser } from "ua-parser-js";
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { Component, Vue, Watch } from "vue-facing-decorator";
|
||||
import { Router } from "vue-router";
|
||||
|
||||
//import App from "../App.vue";
|
||||
@@ -283,6 +283,7 @@ import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
||||
import { NOTIFY_CONTACT_LOADING_ISSUE } from "@/constants/notifications";
|
||||
import * as Package from "../../package.json";
|
||||
import { UNNAMED_ENTITY_NAME } from "@/constants/entities";
|
||||
import { errorStringForLog } from "../libs/endorserServer";
|
||||
|
||||
// consolidate this with GiveActionClaim in src/interfaces/claims.ts
|
||||
interface Claim {
|
||||
@@ -399,6 +400,44 @@ export default class HomeView extends Vue {
|
||||
newOffersToUserProjectsHitLimit: boolean = false;
|
||||
numNewOffersToUser: number = 0; // number of new offers-to-user
|
||||
numNewOffersToUserProjects: number = 0; // number of new offers-to-user's-projects
|
||||
|
||||
/**
|
||||
* CRITICAL VUE REACTIVITY BUG WORKAROUND
|
||||
*
|
||||
* This watcher is required for the component to render correctly.
|
||||
* Without it, the newDirectOffersActivityNumber element fails to render
|
||||
* even when numNewOffersToUser has the correct value.
|
||||
*
|
||||
* This appears to be a Vue reactivity issue where property changes
|
||||
* don't trigger proper template updates.
|
||||
*
|
||||
* DO NOT REMOVE until the underlying Vue reactivity issue is resolved.
|
||||
*
|
||||
* See: doc/activeDid-migration-plan.md for details
|
||||
*/
|
||||
@Watch("numNewOffersToUser")
|
||||
onNumNewOffersToUserChange(newValue: number, oldValue: number) {
|
||||
logger.debug("[HomeView] numNewOffersToUser changed", {
|
||||
oldValue,
|
||||
newValue,
|
||||
willRender: !!newValue,
|
||||
vIfCondition: `v-if="numNewOffersToUser"`,
|
||||
elementTestId: "newDirectOffersActivityNumber",
|
||||
shouldShowElement: newValue > 0,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
|
||||
// get shouldShowNewOffersToUser() {
|
||||
// const shouldShow = !!this.numNewOffersToUser;
|
||||
// logger.debug("[HomeView] shouldShowNewOffersToUser computed", {
|
||||
// numNewOffersToUser: this.numNewOffersToUser,
|
||||
// shouldShow,
|
||||
// timestamp: new Date().toISOString()
|
||||
// });
|
||||
// return shouldShow;
|
||||
// }
|
||||
|
||||
searchBoxes: Array<{
|
||||
name: string;
|
||||
bbox: BoundingBox;
|
||||
@@ -432,13 +471,44 @@ export default class HomeView extends Vue {
|
||||
*/
|
||||
async mounted() {
|
||||
try {
|
||||
logger.info("[HomeView] mounted() - component lifecycle started", {
|
||||
timestamp: new Date().toISOString(),
|
||||
componentName: "HomeView",
|
||||
});
|
||||
|
||||
await this.initializeIdentity();
|
||||
// Settings already loaded in initializeIdentity()
|
||||
await this.loadContacts();
|
||||
// Registration check already handled in initializeIdentity()
|
||||
await this.loadFeedData();
|
||||
|
||||
logger.info("[HomeView] mounted() - about to call loadNewOffers()", {
|
||||
timestamp: new Date().toISOString(),
|
||||
activeDid: this.activeDid,
|
||||
hasActiveDid: !!this.activeDid,
|
||||
});
|
||||
|
||||
await this.loadNewOffers();
|
||||
|
||||
logger.info("[HomeView] mounted() - loadNewOffers() completed", {
|
||||
timestamp: new Date().toISOString(),
|
||||
numNewOffersToUser: this.numNewOffersToUser,
|
||||
numNewOffersToUserProjects: this.numNewOffersToUserProjects,
|
||||
shouldShowElement:
|
||||
this.numNewOffersToUser + this.numNewOffersToUserProjects > 0,
|
||||
});
|
||||
|
||||
await this.checkOnboarding();
|
||||
|
||||
logger.info("[HomeView] mounted() - component lifecycle completed", {
|
||||
timestamp: new Date().toISOString(),
|
||||
finalState: {
|
||||
numNewOffersToUser: this.numNewOffersToUser,
|
||||
numNewOffersToUserProjects: this.numNewOffersToUserProjects,
|
||||
shouldShowElement:
|
||||
this.numNewOffersToUser + this.numNewOffersToUserProjects > 0,
|
||||
},
|
||||
});
|
||||
} catch (err: unknown) {
|
||||
this.handleError(err);
|
||||
}
|
||||
@@ -515,7 +585,18 @@ export default class HomeView extends Vue {
|
||||
// **CRITICAL**: Ensure correct API server for platform
|
||||
await this.ensureCorrectApiServer();
|
||||
|
||||
this.activeDid = settings.activeDid || "";
|
||||
// Get activeDid from active_identity table (single source of truth)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const activeIdentity = await (this as any).$getActiveIdentity();
|
||||
this.activeDid = activeIdentity.activeDid || "";
|
||||
logger.info("[HomeView] ActiveDid migration - using new API", {
|
||||
activeDid: this.activeDid,
|
||||
source: "active_identity table",
|
||||
hasActiveDid: !!this.activeDid,
|
||||
activeIdentityResult: activeIdentity,
|
||||
isRegistered: this.isRegistered,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
// Load contacts with graceful fallback
|
||||
try {
|
||||
@@ -654,24 +735,100 @@ export default class HomeView extends Vue {
|
||||
* @requires Active DID
|
||||
*/
|
||||
private async loadNewOffers() {
|
||||
if (this.activeDid) {
|
||||
const offersToUserData = await getNewOffersToUser(
|
||||
this.axios,
|
||||
this.apiServer,
|
||||
this.activeDid,
|
||||
this.lastAckedOfferToUserJwtId,
|
||||
);
|
||||
this.numNewOffersToUser = offersToUserData.data.length;
|
||||
this.newOffersToUserHitLimit = offersToUserData.hitLimit;
|
||||
logger.info("[HomeView] loadNewOffers() called with activeDid:", {
|
||||
activeDid: this.activeDid,
|
||||
hasActiveDid: !!this.activeDid,
|
||||
length: this.activeDid?.length || 0,
|
||||
});
|
||||
|
||||
const offersToUserProjects = await getNewOffersToUserProjects(
|
||||
this.axios,
|
||||
this.apiServer,
|
||||
this.activeDid,
|
||||
this.lastAckedOfferToUserProjectsJwtId,
|
||||
);
|
||||
this.numNewOffersToUserProjects = offersToUserProjects.data.length;
|
||||
this.newOffersToUserProjectsHitLimit = offersToUserProjects.hitLimit;
|
||||
if (this.activeDid) {
|
||||
logger.info("[HomeView] loadNewOffers() - activeDid found, calling API", {
|
||||
activeDid: this.activeDid,
|
||||
apiServer: this.apiServer,
|
||||
isRegistered: this.isRegistered,
|
||||
lastAckedOfferToUserJwtId: this.lastAckedOfferToUserJwtId,
|
||||
});
|
||||
|
||||
try {
|
||||
const offersToUserData = await getNewOffersToUser(
|
||||
this.axios,
|
||||
this.apiServer,
|
||||
this.activeDid,
|
||||
this.lastAckedOfferToUserJwtId,
|
||||
);
|
||||
logger.info(
|
||||
"[HomeView] loadNewOffers() - getNewOffersToUser successful",
|
||||
{
|
||||
activeDid: this.activeDid,
|
||||
dataLength: offersToUserData.data.length,
|
||||
hitLimit: offersToUserData.hitLimit,
|
||||
},
|
||||
);
|
||||
|
||||
this.numNewOffersToUser = offersToUserData.data.length;
|
||||
this.newOffersToUserHitLimit = offersToUserData.hitLimit;
|
||||
|
||||
logger.info("[HomeView] loadNewOffers() - updated component state", {
|
||||
activeDid: this.activeDid,
|
||||
numNewOffersToUser: this.numNewOffersToUser,
|
||||
newOffersToUserHitLimit: this.newOffersToUserHitLimit,
|
||||
willRender: !!this.numNewOffersToUser,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
const offersToUserProjects = await getNewOffersToUserProjects(
|
||||
this.axios,
|
||||
this.apiServer,
|
||||
this.activeDid,
|
||||
this.lastAckedOfferToUserProjectsJwtId,
|
||||
);
|
||||
logger.info(
|
||||
"[HomeView] loadNewOffers() - getNewOffersToUserProjects successful",
|
||||
{
|
||||
activeDid: this.activeDid,
|
||||
dataLength: offersToUserProjects.data.length,
|
||||
hitLimit: offersToUserProjects.hitLimit,
|
||||
},
|
||||
);
|
||||
|
||||
this.numNewOffersToUserProjects = offersToUserProjects.data.length;
|
||||
this.newOffersToUserProjectsHitLimit = offersToUserProjects.hitLimit;
|
||||
|
||||
logger.info("[HomeView] loadNewOffers() - all API calls completed", {
|
||||
numNewOffersToUser: this.numNewOffersToUser,
|
||||
numNewOffersToUserProjects: this.numNewOffersToUserProjects,
|
||||
shouldRenderElement: !!this.numNewOffersToUser,
|
||||
elementTestId: "newDirectOffersActivityNumber",
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
// Additional logging for template rendering debugging
|
||||
logger.info("[HomeView] loadNewOffers() - template rendering check", {
|
||||
numNewOffersToUser: this.numNewOffersToUser,
|
||||
numNewOffersToUserProjects: this.numNewOffersToUserProjects,
|
||||
totalNewOffers:
|
||||
this.numNewOffersToUser + this.numNewOffersToUserProjects,
|
||||
shouldShowElement:
|
||||
this.numNewOffersToUser + this.numNewOffersToUserProjects > 0,
|
||||
vIfCondition: `v-if="numNewOffersToUser + numNewOffersToUserProjects"`,
|
||||
elementWillRender:
|
||||
this.numNewOffersToUser + this.numNewOffersToUserProjects > 0,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error("[HomeView] loadNewOffers() - API call failed", {
|
||||
activeDid: this.activeDid,
|
||||
apiServer: this.apiServer,
|
||||
isRegistered: this.isRegistered,
|
||||
error: errorStringForLog(error),
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
logger.warn("[HomeView] loadNewOffers() - no activeDid available", {
|
||||
activeDid: this.activeDid,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user