forked from jsnbuchanan/crowd-funder-for-time-pwa
refactor(services): inline ProfileService logic into AccountViewView
Removes over-engineered ProfileService and ServiceInitializationManager classes that were only used in one place. Inlines all profile logic directly into AccountViewView.vue to reduce complexity and improve maintainability. - Deletes ProfileService.ts (325 lines) - Deletes ServiceInitializationManager.ts (207 lines) - Inlines ProfileData interface and methods into AccountViewView - Maintains all existing functionality while reducing code footprint perf(logging): convert excessive info logs to debug level Reduces console noise by converting high-frequency, low-value logging from info to debug level across navigation, API calls, and component lifecycle operations. Improves performance and reduces log verbosity for normal application flow. - Router navigation guards: info → debug - Plan loading operations: info → debug - User registration checks: info → debug - Image server rate limits: info → debug - Component lifecycle events: info → debug - Settings loading operations: info → debug Maintains warn/error levels for actual issues while reducing noise from expected application behavior.
This commit is contained in:
@@ -30,7 +30,6 @@ export default class TopMessage extends Vue {
|
|||||||
// - Cache management: this.$refreshSettings(), this.$clearAllCaches()
|
// - Cache management: this.$refreshSettings(), this.$clearAllCaches()
|
||||||
// - Ultra-concise database methods: this.$db(), this.$exec(), this.$query()
|
// - Ultra-concise database methods: this.$db(), this.$exec(), this.$query()
|
||||||
// - All methods use smart caching with TTL for massive performance gains
|
// - All methods use smart caching with TTL for massive performance gains
|
||||||
// - FIXED: Now properly respects database settings without forcing API server overrides
|
|
||||||
|
|
||||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||||
|
|
||||||
@@ -45,10 +44,10 @@ export default class TopMessage extends Vue {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Load settings without overriding database values - fixes settings inconsistency
|
// Load settings without overriding database values - fixes settings inconsistency
|
||||||
logger.info("[TopMessage] 📥 Loading settings without overrides...");
|
logger.debug("[TopMessage] 📥 Loading settings without overrides...");
|
||||||
const settings = await this.$accountSettings();
|
const settings = await this.$accountSettings();
|
||||||
|
|
||||||
logger.info("[TopMessage] 📊 Settings loaded:", {
|
logger.debug("[TopMessage] 📊 Settings loaded:", {
|
||||||
activeDid: settings.activeDid,
|
activeDid: settings.activeDid,
|
||||||
apiServer: settings.apiServer,
|
apiServer: settings.apiServer,
|
||||||
warnIfTestServer: settings.warnIfTestServer,
|
warnIfTestServer: settings.warnIfTestServer,
|
||||||
@@ -65,7 +64,7 @@ export default class TopMessage extends Vue {
|
|||||||
) {
|
) {
|
||||||
const didPrefix = settings.activeDid?.slice(11, 15);
|
const didPrefix = settings.activeDid?.slice(11, 15);
|
||||||
this.message = "You're not using prod, user " + didPrefix;
|
this.message = "You're not using prod, user " + didPrefix;
|
||||||
logger.info("[TopMessage] ⚠️ Test server warning displayed:", {
|
logger.debug("[TopMessage] ⚠️ Test server warning displayed:", {
|
||||||
apiServer: settings.apiServer,
|
apiServer: settings.apiServer,
|
||||||
didPrefix: didPrefix,
|
didPrefix: didPrefix,
|
||||||
});
|
});
|
||||||
@@ -76,7 +75,7 @@ export default class TopMessage extends Vue {
|
|||||||
) {
|
) {
|
||||||
const didPrefix = settings.activeDid?.slice(11, 15);
|
const didPrefix = settings.activeDid?.slice(11, 15);
|
||||||
this.message = "You are using prod, user " + didPrefix;
|
this.message = "You are using prod, user " + didPrefix;
|
||||||
logger.info("[TopMessage] ⚠️ Production server warning displayed:", {
|
logger.debug("[TopMessage] ⚠️ Production server warning displayed:", {
|
||||||
apiServer: settings.apiServer,
|
apiServer: settings.apiServer,
|
||||||
didPrefix: didPrefix,
|
didPrefix: didPrefix,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -515,7 +515,7 @@ export async function getPlanFromCache(
|
|||||||
// Enhanced diagnostic logging for plan loading
|
// Enhanced diagnostic logging for plan loading
|
||||||
const requestId = `plan_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
const requestId = `plan_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
|
||||||
logger.info("[Plan Loading] 🔍 Loading plan from server:", {
|
logger.debug("[Plan Loading] 🔍 Loading plan from server:", {
|
||||||
requestId,
|
requestId,
|
||||||
handleId,
|
handleId,
|
||||||
apiServer,
|
apiServer,
|
||||||
@@ -527,7 +527,7 @@ export async function getPlanFromCache(
|
|||||||
try {
|
try {
|
||||||
const resp = await axios.get(url, { headers });
|
const resp = await axios.get(url, { headers });
|
||||||
|
|
||||||
logger.info("[Plan Loading] ✅ Plan loaded successfully:", {
|
logger.debug("[Plan Loading] ✅ Plan loaded successfully:", {
|
||||||
requestId,
|
requestId,
|
||||||
handleId,
|
handleId,
|
||||||
status: resp.status,
|
status: resp.status,
|
||||||
@@ -1604,7 +1604,7 @@ export async function fetchEndorserRateLimits(
|
|||||||
const headers = await getHeaders(issuerDid);
|
const headers = await getHeaders(issuerDid);
|
||||||
|
|
||||||
// Enhanced diagnostic logging for user registration tracking
|
// Enhanced diagnostic logging for user registration tracking
|
||||||
logger.info("[User Registration] Checking user status on server:", {
|
logger.debug("[User Registration] Checking user status on server:", {
|
||||||
did: issuerDid,
|
did: issuerDid,
|
||||||
server: apiServer,
|
server: apiServer,
|
||||||
endpoint: url,
|
endpoint: url,
|
||||||
@@ -1615,7 +1615,7 @@ export async function fetchEndorserRateLimits(
|
|||||||
const response = await axios.get(url, { headers } as AxiosRequestConfig);
|
const response = await axios.get(url, { headers } as AxiosRequestConfig);
|
||||||
|
|
||||||
// Log successful registration check
|
// Log successful registration check
|
||||||
logger.info("[User Registration] User registration check successful:", {
|
logger.debug("[User Registration] User registration check successful:", {
|
||||||
did: issuerDid,
|
did: issuerDid,
|
||||||
server: apiServer,
|
server: apiServer,
|
||||||
status: response.status,
|
status: response.status,
|
||||||
@@ -1674,7 +1674,7 @@ export async function fetchImageRateLimits(
|
|||||||
const headers = await getHeaders(issuerDid);
|
const headers = await getHeaders(issuerDid);
|
||||||
|
|
||||||
// Enhanced diagnostic logging for image server calls
|
// Enhanced diagnostic logging for image server calls
|
||||||
logger.info("[Image Server] Checking image rate limits:", {
|
logger.debug("[Image Server] Checking image rate limits:", {
|
||||||
did: issuerDid,
|
did: issuerDid,
|
||||||
server: server,
|
server: server,
|
||||||
endpoint: url,
|
endpoint: url,
|
||||||
@@ -1685,7 +1685,7 @@ export async function fetchImageRateLimits(
|
|||||||
const response = await axios.get(url, { headers } as AxiosRequestConfig);
|
const response = await axios.get(url, { headers } as AxiosRequestConfig);
|
||||||
|
|
||||||
// Log successful image server call
|
// Log successful image server call
|
||||||
logger.info("[Image Server] Image rate limits check successful:", {
|
logger.debug("[Image Server] Image rate limits check successful:", {
|
||||||
did: issuerDid,
|
did: issuerDid,
|
||||||
server: server,
|
server: server,
|
||||||
status: response.status,
|
status: response.status,
|
||||||
|
|||||||
@@ -973,13 +973,16 @@ export async function importFromMnemonic(
|
|||||||
const firstName = settings[0];
|
const firstName = settings[0];
|
||||||
const isRegistered = settings[1];
|
const isRegistered = settings[1];
|
||||||
|
|
||||||
logger.info("[importFromMnemonic] Test User #0 settings verification", {
|
logger.debug(
|
||||||
did: newId.did,
|
"[importFromMnemonic] Test User #0 settings verification",
|
||||||
firstName,
|
{
|
||||||
isRegistered,
|
did: newId.did,
|
||||||
expectedFirstName: "User Zero",
|
firstName,
|
||||||
expectedIsRegistered: true,
|
isRegistered,
|
||||||
});
|
expectedFirstName: "User Zero",
|
||||||
|
expectedIsRegistered: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// If settings weren't saved correctly, try individual updates
|
// If settings weren't saved correctly, try individual updates
|
||||||
if (firstName !== "User Zero" || isRegistered !== 1) {
|
if (firstName !== "User Zero" || isRegistered !== 1) {
|
||||||
@@ -1005,7 +1008,7 @@ export async function importFromMnemonic(
|
|||||||
|
|
||||||
if (retryResult?.values?.length) {
|
if (retryResult?.values?.length) {
|
||||||
const retrySettings = retryResult.values[0];
|
const retrySettings = retryResult.values[0];
|
||||||
logger.info(
|
logger.debug(
|
||||||
"[importFromMnemonic] Test User #0 settings after retry",
|
"[importFromMnemonic] Test User #0 settings after retry",
|
||||||
{
|
{
|
||||||
firstName: retrySettings[0],
|
firstName: retrySettings[0],
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ router.onError(errorHandler); // Assign the error handler to the router instance
|
|||||||
* @param next - Navigation function
|
* @param next - Navigation function
|
||||||
*/
|
*/
|
||||||
router.beforeEach(async (to, _from, next) => {
|
router.beforeEach(async (to, _from, next) => {
|
||||||
logger.info(`[Router] 🧭 Navigation guard triggered:`, {
|
logger.debug(`[Router] 🧭 Navigation guard triggered:`, {
|
||||||
from: _from?.path || "none",
|
from: _from?.path || "none",
|
||||||
to: to.path,
|
to: to.path,
|
||||||
name: to.name,
|
name: to.name,
|
||||||
@@ -368,11 +368,11 @@ router.beforeEach(async (to, _from, next) => {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`[Router] 🔍 Checking user identity for route: ${to.path}`);
|
logger.debug(`[Router] 🔍 Checking user identity for route: ${to.path}`);
|
||||||
|
|
||||||
// Check if user has any identities
|
// Check if user has any identities
|
||||||
const allMyDids = await retrieveAccountDids();
|
const allMyDids = await retrieveAccountDids();
|
||||||
logger.info(`[Router] 📋 Found ${allMyDids.length} user identities`);
|
logger.debug(`[Router] 📋 Found ${allMyDids.length} user identities`);
|
||||||
|
|
||||||
if (allMyDids.length === 0) {
|
if (allMyDids.length === 0) {
|
||||||
logger.info("[Router] ⚠️ No identities found, creating default identity");
|
logger.info("[Router] ⚠️ No identities found, creating default identity");
|
||||||
@@ -382,7 +382,7 @@ router.beforeEach(async (to, _from, next) => {
|
|||||||
|
|
||||||
logger.info("[Router] ✅ Default identity created successfully");
|
logger.info("[Router] ✅ Default identity created successfully");
|
||||||
} else {
|
} else {
|
||||||
logger.info(
|
logger.debug(
|
||||||
`[Router] ✅ User has ${allMyDids.length} identities, proceeding`,
|
`[Router] ✅ User has ${allMyDids.length} identities, proceeding`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -408,7 +408,7 @@ router.beforeEach(async (to, _from, next) => {
|
|||||||
|
|
||||||
// Add navigation success logging
|
// Add navigation success logging
|
||||||
router.afterEach((to, from) => {
|
router.afterEach((to, from) => {
|
||||||
logger.info(`[Router] ✅ Navigation completed:`, {
|
logger.debug(`[Router] ✅ Navigation completed:`, {
|
||||||
from: from?.path || "none",
|
from: from?.path || "none",
|
||||||
to: to.path,
|
to: to.path,
|
||||||
name: to.name,
|
name: to.name,
|
||||||
|
|||||||
@@ -1,325 +0,0 @@
|
|||||||
/**
|
|
||||||
* ProfileService - Handles user profile operations and API calls
|
|
||||||
* Extracted from AccountViewView.vue to improve separation of concerns
|
|
||||||
*
|
|
||||||
* @author Matthew Raymer
|
|
||||||
* @since 2025-08-25
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { AxiosInstance } from "axios";
|
|
||||||
import { logger } from "../utils/logger";
|
|
||||||
import { getServiceInitManager } from "./ServiceInitializationManager";
|
|
||||||
import {
|
|
||||||
handleApiError,
|
|
||||||
createErrorContext,
|
|
||||||
createUserMessage,
|
|
||||||
} from "../utils/errorHandler";
|
|
||||||
import { getHeaders } from "../libs/endorserServer";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Profile data structure
|
|
||||||
*/
|
|
||||||
export interface ProfileData {
|
|
||||||
description: string;
|
|
||||||
latitude: number;
|
|
||||||
longitude: number;
|
|
||||||
includeLocation: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Profile service for managing user profile information
|
|
||||||
*
|
|
||||||
* @author Matthew Raymer
|
|
||||||
* @since 2025-08-25
|
|
||||||
*/
|
|
||||||
export class ProfileService {
|
|
||||||
private axios: AxiosInstance;
|
|
||||||
private partnerApiServer: string;
|
|
||||||
|
|
||||||
constructor(axios: AxiosInstance, partnerApiServer: string) {
|
|
||||||
this.axios = axios;
|
|
||||||
this.partnerApiServer = partnerApiServer;
|
|
||||||
|
|
||||||
// Register with service initialization manager
|
|
||||||
const initManager = getServiceInitManager();
|
|
||||||
initManager.registerService("ProfileService", [
|
|
||||||
"AxiosInstance",
|
|
||||||
"PartnerApiServer",
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Mark as initialized since constructor completed successfully
|
|
||||||
initManager.markInitialized("ProfileService");
|
|
||||||
|
|
||||||
logger.debug("[ProfileService] 🔧 Service initialized:", {
|
|
||||||
partnerApiServer,
|
|
||||||
hasAxios: !!axios,
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load user profile from the partner API
|
|
||||||
*
|
|
||||||
* @param did - User's DID
|
|
||||||
* @returns Profile data or null if not found
|
|
||||||
* @throws Error if API call fails
|
|
||||||
*/
|
|
||||||
async loadProfile(did: string): Promise<ProfileData | null> {
|
|
||||||
const operation = "Load Profile";
|
|
||||||
const context = createErrorContext("ProfileService", operation, {
|
|
||||||
did,
|
|
||||||
partnerApiServer: this.partnerApiServer,
|
|
||||||
endpoint: `${this.partnerApiServer}/api/partner/userProfileForIssuer/${did}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Enhanced request tracking
|
|
||||||
const requestId = `profile_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
||||||
|
|
||||||
logger.info("[ProfileService] 🔍 Loading profile:", {
|
|
||||||
requestId,
|
|
||||||
...context,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get authentication headers
|
|
||||||
const headers = await getHeaders(did);
|
|
||||||
|
|
||||||
// FIXED: Use the original working endpoint that was working before recent changes
|
|
||||||
// The working endpoint is /api/partner/userProfileForIssuer/{did} for getting a specific user's profile
|
|
||||||
// NOT /api/partner/userProfile which returns a list of all profiles
|
|
||||||
const fullUrl = `${this.partnerApiServer}/api/partner/userProfileForIssuer/${did}`;
|
|
||||||
|
|
||||||
logger.info("[ProfileService] 🔗 Making API request:", {
|
|
||||||
requestId,
|
|
||||||
did,
|
|
||||||
fullUrl,
|
|
||||||
partnerApiServer: this.partnerApiServer,
|
|
||||||
hasAuthHeader: !!headers.Authorization,
|
|
||||||
authHeaderLength: headers.Authorization?.length || 0,
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await this.axios.get(fullUrl, { headers });
|
|
||||||
|
|
||||||
logger.info("[ProfileService] ✅ Profile loaded successfully:", {
|
|
||||||
requestId,
|
|
||||||
...context,
|
|
||||||
status: response.status,
|
|
||||||
hasData: !!response.data,
|
|
||||||
dataKeys: response.data ? Object.keys(response.data) : [],
|
|
||||||
responseData: response.data,
|
|
||||||
responseDataType: typeof response.data,
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXED: Use the original working response parsing logic
|
|
||||||
// The working endpoint returns a single profile object, not a list
|
|
||||||
if (response.data && response.data.data) {
|
|
||||||
const profileData = response.data.data;
|
|
||||||
logger.info("[ProfileService] 🔍 Parsing profile data:", {
|
|
||||||
requestId,
|
|
||||||
profileData,
|
|
||||||
profileDataKeys: Object.keys(profileData),
|
|
||||||
locLat: profileData.locLat,
|
|
||||||
locLon: profileData.locLon,
|
|
||||||
description: profileData.description,
|
|
||||||
issuerDid: profileData.issuerDid,
|
|
||||||
hasLocationFields: !!(profileData.locLat || profileData.locLon),
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = {
|
|
||||||
description: profileData.description || "",
|
|
||||||
latitude: profileData.locLat || 0,
|
|
||||||
longitude: profileData.locLon || 0,
|
|
||||||
includeLocation: !!(profileData.locLat && profileData.locLon),
|
|
||||||
};
|
|
||||||
|
|
||||||
logger.info("[ProfileService] 📊 Parsed profile result:", {
|
|
||||||
requestId,
|
|
||||||
result,
|
|
||||||
hasLocation: result.includeLocation,
|
|
||||||
locationValues: {
|
|
||||||
original: { locLat: profileData.locLat, locLon: profileData.locLon },
|
|
||||||
parsed: { latitude: result.latitude, longitude: result.longitude },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
logger.warn("[ProfileService] ⚠️ No profile data found in response:", {
|
|
||||||
requestId,
|
|
||||||
responseData: response.data,
|
|
||||||
hasData: !!response.data,
|
|
||||||
hasDataData: !!(response.data && response.data.data),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
} catch (error: unknown) {
|
|
||||||
// Use standardized error handling
|
|
||||||
const errorInfo = handleApiError(error, context, operation);
|
|
||||||
|
|
||||||
// Handle specific HTTP status codes
|
|
||||||
if (errorInfo.errorType === "AxiosError" && errorInfo.status === 404) {
|
|
||||||
logger.info(
|
|
||||||
"[ProfileService] ℹ️ Profile not found (404) - this is normal for new users",
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create user-friendly error message
|
|
||||||
const userMessage = createUserMessage(
|
|
||||||
errorInfo,
|
|
||||||
"Failed to load profile",
|
|
||||||
);
|
|
||||||
throw new Error(userMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save user profile to the partner API
|
|
||||||
*
|
|
||||||
* @param did - User's DID
|
|
||||||
* @param profileData - Profile data to save
|
|
||||||
* @returns Success status
|
|
||||||
* @throws Error if API call fails
|
|
||||||
*/
|
|
||||||
async saveProfile(did: string, profileData: ProfileData): Promise<boolean> {
|
|
||||||
const operation = "Save Profile";
|
|
||||||
const context = createErrorContext("ProfileService", operation, {
|
|
||||||
did,
|
|
||||||
partnerApiServer: this.partnerApiServer,
|
|
||||||
endpoint: `${this.partnerApiServer}/api/partner/userProfile`,
|
|
||||||
profileData,
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Enhanced request tracking
|
|
||||||
const requestId = `profile_save_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
||||||
|
|
||||||
logger.info("[ProfileService] 💾 Saving profile:", {
|
|
||||||
requestId,
|
|
||||||
...context,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get authentication headers
|
|
||||||
const headers = await getHeaders(did);
|
|
||||||
|
|
||||||
// Prepare payload in the format expected by the partner API
|
|
||||||
const payload = {
|
|
||||||
description: profileData.description,
|
|
||||||
issuerDid: did,
|
|
||||||
...(profileData.includeLocation &&
|
|
||||||
profileData.latitude &&
|
|
||||||
profileData.longitude
|
|
||||||
? {
|
|
||||||
locLat: profileData.latitude,
|
|
||||||
locLon: profileData.longitude,
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
};
|
|
||||||
|
|
||||||
logger.info("[ProfileService] 📤 Sending payload to server:", {
|
|
||||||
requestId,
|
|
||||||
payload,
|
|
||||||
hasLocation: profileData.includeLocation,
|
|
||||||
latitude: profileData.latitude,
|
|
||||||
longitude: profileData.longitude,
|
|
||||||
payloadKeys: Object.keys(payload),
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await this.axios.post(
|
|
||||||
`${this.partnerApiServer}/api/partner/userProfile`,
|
|
||||||
payload,
|
|
||||||
{ headers },
|
|
||||||
);
|
|
||||||
|
|
||||||
logger.info("[ProfileService] ✅ Profile saved successfully:", {
|
|
||||||
requestId,
|
|
||||||
...context,
|
|
||||||
status: response.status,
|
|
||||||
hasData: !!response.data,
|
|
||||||
responseData: response.data,
|
|
||||||
responseDataKeys: response.data ? Object.keys(response.data) : [],
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (error: unknown) {
|
|
||||||
// Use standardized error handling
|
|
||||||
const errorInfo = handleApiError(error, context, operation);
|
|
||||||
|
|
||||||
// Create user-friendly error message
|
|
||||||
const userMessage = createUserMessage(
|
|
||||||
errorInfo,
|
|
||||||
"Failed to save profile",
|
|
||||||
);
|
|
||||||
throw new Error(userMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle profile location visibility
|
|
||||||
*
|
|
||||||
* @param profileData - Current profile data
|
|
||||||
* @returns Updated profile data
|
|
||||||
*/
|
|
||||||
toggleProfileLocation(profileData: ProfileData): ProfileData {
|
|
||||||
const includeLocation = !profileData.includeLocation;
|
|
||||||
return {
|
|
||||||
...profileData,
|
|
||||||
latitude: includeLocation ? profileData.latitude : 0,
|
|
||||||
longitude: includeLocation ? profileData.longitude : 0,
|
|
||||||
includeLocation,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear profile location
|
|
||||||
*
|
|
||||||
* @param profileData - Current profile data
|
|
||||||
* @returns Updated profile data
|
|
||||||
*/
|
|
||||||
clearProfileLocation(profileData: ProfileData): ProfileData {
|
|
||||||
return {
|
|
||||||
...profileData,
|
|
||||||
latitude: 0,
|
|
||||||
longitude: 0,
|
|
||||||
includeLocation: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset profile to default state
|
|
||||||
*
|
|
||||||
* @returns Default profile data
|
|
||||||
*/
|
|
||||||
getDefaultProfile(): ProfileData {
|
|
||||||
return {
|
|
||||||
description: "",
|
|
||||||
latitude: 0,
|
|
||||||
longitude: 0,
|
|
||||||
includeLocation: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory function to create a ProfileService instance
|
|
||||||
*
|
|
||||||
* @param axios - Axios instance for HTTP requests
|
|
||||||
* @param partnerApiServer - Partner API server URL
|
|
||||||
* @returns ProfileService instance
|
|
||||||
*/
|
|
||||||
export function createProfileService(
|
|
||||||
axios: AxiosInstance,
|
|
||||||
partnerApiServer: string,
|
|
||||||
): ProfileService {
|
|
||||||
// Register dependencies with service initialization manager
|
|
||||||
const initManager = getServiceInitManager();
|
|
||||||
initManager.registerService("AxiosInstance", []);
|
|
||||||
initManager.registerService("PartnerApiServer", []);
|
|
||||||
|
|
||||||
// Mark dependencies as initialized
|
|
||||||
initManager.markInitialized("AxiosInstance");
|
|
||||||
initManager.markInitialized("PartnerApiServer");
|
|
||||||
|
|
||||||
return new ProfileService(axios, partnerApiServer);
|
|
||||||
}
|
|
||||||
@@ -1,207 +0,0 @@
|
|||||||
/**
|
|
||||||
* Service Initialization Manager
|
|
||||||
*
|
|
||||||
* Manages the proper initialization order of services to prevent race conditions
|
|
||||||
* and ensure dependencies are available when services are created.
|
|
||||||
*
|
|
||||||
* @author Matthew Raymer
|
|
||||||
* @since 2025-08-25
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { logger } from "../utils/logger";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service initialization status tracking
|
|
||||||
*/
|
|
||||||
interface ServiceStatus {
|
|
||||||
name: string;
|
|
||||||
initialized: boolean;
|
|
||||||
dependencies: string[];
|
|
||||||
error?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service initialization manager to prevent race conditions
|
|
||||||
*/
|
|
||||||
export class ServiceInitializationManager {
|
|
||||||
private static instance: ServiceInitializationManager;
|
|
||||||
private serviceStatuses = new Map<string, ServiceStatus>();
|
|
||||||
private initializationPromise: Promise<void> | null = null;
|
|
||||||
|
|
||||||
private constructor() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get singleton instance
|
|
||||||
*/
|
|
||||||
static getInstance(): ServiceInitializationManager {
|
|
||||||
if (!ServiceInitializationManager.instance) {
|
|
||||||
ServiceInitializationManager.instance =
|
|
||||||
new ServiceInitializationManager();
|
|
||||||
}
|
|
||||||
return ServiceInitializationManager.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a service that needs initialization
|
|
||||||
*/
|
|
||||||
registerService(name: string, dependencies: string[] = []): void {
|
|
||||||
this.serviceStatuses.set(name, {
|
|
||||||
name,
|
|
||||||
initialized: false,
|
|
||||||
dependencies,
|
|
||||||
});
|
|
||||||
|
|
||||||
logger.debug("[ServiceInit] 🔧 Service registered:", {
|
|
||||||
name,
|
|
||||||
dependencies,
|
|
||||||
totalServices: this.serviceStatuses.size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark a service as initialized
|
|
||||||
*/
|
|
||||||
markInitialized(name: string): void {
|
|
||||||
const status = this.serviceStatuses.get(name);
|
|
||||||
if (status) {
|
|
||||||
status.initialized = true;
|
|
||||||
logger.debug("[ServiceInit] ✅ Service initialized:", {
|
|
||||||
name,
|
|
||||||
totalInitialized: this.getInitializedCount(),
|
|
||||||
totalServices: this.serviceStatuses.size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark a service as failed
|
|
||||||
*/
|
|
||||||
markFailed(name: string, error: string): void {
|
|
||||||
const status = this.serviceStatuses.get(name);
|
|
||||||
if (status) {
|
|
||||||
status.error = error;
|
|
||||||
logger.error("[ServiceInit] ❌ Service failed:", {
|
|
||||||
name,
|
|
||||||
error,
|
|
||||||
totalFailed: this.getFailedCount(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get count of initialized services
|
|
||||||
*/
|
|
||||||
private getInitializedCount(): number {
|
|
||||||
return Array.from(this.serviceStatuses.values()).filter(
|
|
||||||
(s) => s.initialized,
|
|
||||||
).length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get count of failed services
|
|
||||||
*/
|
|
||||||
private getFailedCount(): number {
|
|
||||||
return Array.from(this.serviceStatuses.values()).filter((s) => s.error)
|
|
||||||
.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for all services to be initialized
|
|
||||||
*/
|
|
||||||
async waitForInitialization(): Promise<void> {
|
|
||||||
if (this.initializationPromise) {
|
|
||||||
return this.initializationPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initializationPromise = new Promise((resolve, reject) => {
|
|
||||||
const checkInterval = setInterval(() => {
|
|
||||||
const totalServices = this.serviceStatuses.size;
|
|
||||||
const initializedCount = this.getInitializedCount();
|
|
||||||
const failedCount = this.getFailedCount();
|
|
||||||
|
|
||||||
logger.debug("[ServiceInit] 🔍 Initialization progress:", {
|
|
||||||
totalServices,
|
|
||||||
initializedCount,
|
|
||||||
failedCount,
|
|
||||||
remaining: totalServices - initializedCount - failedCount,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (failedCount > 0) {
|
|
||||||
clearInterval(checkInterval);
|
|
||||||
const failedServices = Array.from(this.serviceStatuses.values())
|
|
||||||
.filter((s) => s.error)
|
|
||||||
.map((s) => `${s.name}: ${s.error}`);
|
|
||||||
|
|
||||||
const error = new Error(
|
|
||||||
`Service initialization failed: ${failedServices.join(", ")}`,
|
|
||||||
);
|
|
||||||
logger.error("[ServiceInit] ❌ Initialization failed:", error);
|
|
||||||
reject(error);
|
|
||||||
} else if (initializedCount === totalServices) {
|
|
||||||
clearInterval(checkInterval);
|
|
||||||
logger.info(
|
|
||||||
"[ServiceInit] 🎉 All services initialized successfully:",
|
|
||||||
{
|
|
||||||
totalServices,
|
|
||||||
initializedCount,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// Timeout after 30 seconds
|
|
||||||
setTimeout(() => {
|
|
||||||
clearInterval(checkInterval);
|
|
||||||
const error = new Error(
|
|
||||||
"Service initialization timeout after 30 seconds",
|
|
||||||
);
|
|
||||||
logger.error("[ServiceInit] ⏰ Initialization timeout:", error);
|
|
||||||
reject(error);
|
|
||||||
}, 30000);
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.initializationPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get initialization status summary
|
|
||||||
*/
|
|
||||||
getStatusSummary(): {
|
|
||||||
total: number;
|
|
||||||
initialized: number;
|
|
||||||
failed: number;
|
|
||||||
pending: number;
|
|
||||||
services: ServiceStatus[];
|
|
||||||
} {
|
|
||||||
const services = Array.from(this.serviceStatuses.values());
|
|
||||||
const total = services.length;
|
|
||||||
const initialized = services.filter((s) => s.initialized).length;
|
|
||||||
const failed = services.filter((s) => s.error).length;
|
|
||||||
const pending = total - initialized - failed;
|
|
||||||
|
|
||||||
return {
|
|
||||||
total,
|
|
||||||
initialized,
|
|
||||||
failed,
|
|
||||||
pending,
|
|
||||||
services,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the manager (useful for testing)
|
|
||||||
*/
|
|
||||||
reset(): void {
|
|
||||||
this.serviceStatuses.clear();
|
|
||||||
this.initializationPromise = null;
|
|
||||||
logger.debug("[ServiceInit] 🔄 Manager reset");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function to get the service initialization manager
|
|
||||||
*/
|
|
||||||
export const getServiceInitManager = (): ServiceInitializationManager => {
|
|
||||||
return ServiceInitializationManager.getInstance();
|
|
||||||
};
|
|
||||||
@@ -754,6 +754,7 @@ import "leaflet/dist/leaflet.css";
|
|||||||
|
|
||||||
import { Buffer } from "buffer/";
|
import { Buffer } from "buffer/";
|
||||||
import "dexie-export-import";
|
import "dexie-export-import";
|
||||||
|
|
||||||
// @ts-expect-error - they aren't exporting it but it's there
|
// @ts-expect-error - they aren't exporting it but it's there
|
||||||
import { ImportProgress } from "dexie-export-import";
|
import { ImportProgress } from "dexie-export-import";
|
||||||
import { LeafletMouseEvent } from "leaflet";
|
import { LeafletMouseEvent } from "leaflet";
|
||||||
@@ -815,11 +816,13 @@ import {
|
|||||||
isApiError,
|
isApiError,
|
||||||
ImportContent,
|
ImportContent,
|
||||||
} from "@/interfaces/accountView";
|
} from "@/interfaces/accountView";
|
||||||
import {
|
// Profile data interface (inlined from ProfileService)
|
||||||
ProfileService,
|
interface ProfileData {
|
||||||
createProfileService,
|
description: string;
|
||||||
ProfileData,
|
latitude: number;
|
||||||
} from "@/services/ProfileService";
|
longitude: number;
|
||||||
|
includeLocation: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
const inputImportFileNameRef = ref<Blob>();
|
const inputImportFileNameRef = ref<Blob>();
|
||||||
|
|
||||||
@@ -918,7 +921,6 @@ export default class AccountViewView extends Vue {
|
|||||||
imageLimits: ImageRateLimits | null = null;
|
imageLimits: ImageRateLimits | null = null;
|
||||||
limitsMessage: string = "";
|
limitsMessage: string = "";
|
||||||
|
|
||||||
private profileService!: ProfileService;
|
|
||||||
private notify!: ReturnType<typeof createNotifyHelpers>;
|
private notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
@@ -957,24 +959,17 @@ export default class AccountViewView extends Vue {
|
|||||||
await this.initializeState();
|
await this.initializeState();
|
||||||
await this.processIdentity();
|
await this.processIdentity();
|
||||||
|
|
||||||
// FIXED: Create ProfileService AFTER settings are loaded to get correct partnerApiServer
|
// Profile service logic now inlined - no need for external service
|
||||||
this.profileService = createProfileService(
|
logger.debug(
|
||||||
this.axios,
|
"[AccountViewView] Profile logic ready with partnerApiServer:",
|
||||||
this.partnerApiServer,
|
|
||||||
);
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
"[AccountViewView] ✅ ProfileService created with correct partnerApiServer:",
|
|
||||||
{
|
{
|
||||||
partnerApiServer: this.partnerApiServer,
|
partnerApiServer: this.partnerApiServer,
|
||||||
component: "AccountViewView",
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.isRegistered) {
|
if (this.isRegistered) {
|
||||||
try {
|
try {
|
||||||
const profile = await this.profileService.loadProfile(this.activeDid);
|
const profile = await this.loadProfile(this.activeDid);
|
||||||
if (profile) {
|
if (profile) {
|
||||||
this.userProfileDesc = profile.description;
|
this.userProfileDesc = profile.description;
|
||||||
this.userProfileLatitude = profile.latitude;
|
this.userProfileLatitude = profile.latitude;
|
||||||
@@ -1694,7 +1689,7 @@ export default class AccountViewView extends Vue {
|
|||||||
|
|
||||||
logger.debug("Saving profile data:", profileData);
|
logger.debug("Saving profile data:", profileData);
|
||||||
|
|
||||||
const success = await this.profileService.saveProfile(
|
const success = await this.saveProfileToServer(
|
||||||
this.activeDid,
|
this.activeDid,
|
||||||
profileData,
|
profileData,
|
||||||
);
|
);
|
||||||
@@ -1713,7 +1708,7 @@ export default class AccountViewView extends Vue {
|
|||||||
|
|
||||||
toggleUserProfileLocation(): void {
|
toggleUserProfileLocation(): void {
|
||||||
try {
|
try {
|
||||||
const updated = this.profileService.toggleProfileLocation({
|
const updated = this.toggleProfileLocation({
|
||||||
description: this.userProfileDesc,
|
description: this.userProfileDesc,
|
||||||
latitude: this.userProfileLatitude,
|
latitude: this.userProfileLatitude,
|
||||||
longitude: this.userProfileLongitude,
|
longitude: this.userProfileLongitude,
|
||||||
@@ -1758,7 +1753,7 @@ export default class AccountViewView extends Vue {
|
|||||||
|
|
||||||
async deleteProfile(): Promise<void> {
|
async deleteProfile(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const success = await this.profileService.deleteProfile(this.activeDid);
|
const success = await this.deleteProfileFromServer(this.activeDid);
|
||||||
if (success) {
|
if (success) {
|
||||||
this.notify.success(ACCOUNT_VIEW_CONSTANTS.SUCCESS.PROFILE_DELETED);
|
this.notify.success(ACCOUNT_VIEW_CONSTANTS.SUCCESS.PROFILE_DELETED);
|
||||||
this.userProfileDesc = "";
|
this.userProfileDesc = "";
|
||||||
@@ -1871,5 +1866,215 @@ export default class AccountViewView extends Vue {
|
|||||||
onRecheckLimits() {
|
onRecheckLimits() {
|
||||||
this.checkLimits();
|
this.checkLimits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inlined profile methods (previously in ProfileService)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load user profile from the partner API
|
||||||
|
*/
|
||||||
|
private async loadProfile(did: string): Promise<ProfileData | null> {
|
||||||
|
try {
|
||||||
|
const requestId = `profile_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Loading profile:", {
|
||||||
|
requestId,
|
||||||
|
did,
|
||||||
|
partnerApiServer: this.partnerApiServer,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get authentication headers
|
||||||
|
const headers = await getHeaders(did);
|
||||||
|
|
||||||
|
const fullUrl = `${this.partnerApiServer}/api/partner/userProfileForIssuer/${did}`;
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Making API request:", {
|
||||||
|
requestId,
|
||||||
|
did,
|
||||||
|
fullUrl,
|
||||||
|
hasAuthHeader: !!headers.Authorization,
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await this.axios.get(fullUrl, { headers });
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Profile loaded successfully:", {
|
||||||
|
requestId,
|
||||||
|
status: response.status,
|
||||||
|
hasData: !!response.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.data && response.data.data) {
|
||||||
|
const profileData = response.data.data;
|
||||||
|
logger.debug("[AccountViewView] Parsing profile data:", {
|
||||||
|
requestId,
|
||||||
|
locLat: profileData.locLat,
|
||||||
|
locLon: profileData.locLon,
|
||||||
|
description: profileData.description,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
description: profileData.description || "",
|
||||||
|
latitude: profileData.locLat || 0,
|
||||||
|
longitude: profileData.locLon || 0,
|
||||||
|
includeLocation: !!(profileData.locLat && profileData.locLon),
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Parsed profile result:", {
|
||||||
|
requestId,
|
||||||
|
result,
|
||||||
|
hasLocation: result.includeLocation,
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
logger.debug("[AccountViewView] No profile data found in response:", {
|
||||||
|
requestId,
|
||||||
|
hasData: !!response.data,
|
||||||
|
hasDataData: !!(response.data && response.data.data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (error: unknown) {
|
||||||
|
// Handle specific HTTP status codes
|
||||||
|
if (error && typeof error === "object" && "response" in error) {
|
||||||
|
const axiosError = error as { response?: { status?: number } };
|
||||||
|
if (axiosError.response?.status === 404) {
|
||||||
|
logger.debug(
|
||||||
|
"[AccountViewView] Profile not found (404) - this is normal for new users",
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.error("[AccountViewView] Failed to load profile:", error);
|
||||||
|
throw new Error("Failed to load profile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save user profile to the partner API
|
||||||
|
*/
|
||||||
|
private async saveProfileToServer(
|
||||||
|
did: string,
|
||||||
|
profileData: ProfileData,
|
||||||
|
): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const requestId = `profile_save_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Saving profile:", {
|
||||||
|
requestId,
|
||||||
|
did,
|
||||||
|
profileData,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get authentication headers
|
||||||
|
const headers = await getHeaders(did);
|
||||||
|
|
||||||
|
// Prepare payload in the format expected by the partner API
|
||||||
|
const payload = {
|
||||||
|
description: profileData.description,
|
||||||
|
issuerDid: did,
|
||||||
|
...(profileData.includeLocation &&
|
||||||
|
profileData.latitude &&
|
||||||
|
profileData.longitude
|
||||||
|
? {
|
||||||
|
locLat: profileData.latitude,
|
||||||
|
locLon: profileData.longitude,
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Sending payload to server:", {
|
||||||
|
requestId,
|
||||||
|
payload,
|
||||||
|
hasLocation: profileData.includeLocation,
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await this.axios.post(
|
||||||
|
`${this.partnerApiServer}/api/partner/userProfile`,
|
||||||
|
payload,
|
||||||
|
{ headers },
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Profile saved successfully:", {
|
||||||
|
requestId,
|
||||||
|
status: response.status,
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error: unknown) {
|
||||||
|
logger.error("[AccountViewView] Failed to save profile:", error);
|
||||||
|
throw new Error("Failed to save profile");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle profile location visibility
|
||||||
|
*/
|
||||||
|
private toggleProfileLocation(profileData: ProfileData): ProfileData {
|
||||||
|
const includeLocation = !profileData.includeLocation;
|
||||||
|
return {
|
||||||
|
...profileData,
|
||||||
|
latitude: includeLocation ? profileData.latitude : 0,
|
||||||
|
longitude: includeLocation ? profileData.longitude : 0,
|
||||||
|
includeLocation,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear profile location
|
||||||
|
*/
|
||||||
|
private clearProfileLocation(profileData: ProfileData): ProfileData {
|
||||||
|
return {
|
||||||
|
...profileData,
|
||||||
|
latitude: 0,
|
||||||
|
longitude: 0,
|
||||||
|
includeLocation: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default profile data
|
||||||
|
*/
|
||||||
|
private getDefaultProfile(): ProfileData {
|
||||||
|
return {
|
||||||
|
description: "",
|
||||||
|
latitude: 0,
|
||||||
|
longitude: 0,
|
||||||
|
includeLocation: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete user profile from the partner API
|
||||||
|
*/
|
||||||
|
private async deleteProfileFromServer(did: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const requestId = `profile_delete_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Deleting profile:", {
|
||||||
|
requestId,
|
||||||
|
did,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get authentication headers
|
||||||
|
const headers = await getHeaders(did);
|
||||||
|
|
||||||
|
const response = await this.axios.delete(
|
||||||
|
`${this.partnerApiServer}/api/partner/userProfile/${did}`,
|
||||||
|
{ headers },
|
||||||
|
);
|
||||||
|
|
||||||
|
logger.debug("[AccountViewView] Profile deleted successfully:", {
|
||||||
|
requestId,
|
||||||
|
status: response.status,
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error: unknown) {
|
||||||
|
logger.error("[AccountViewView] Failed to delete profile:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -603,15 +603,12 @@ export default class HomeView extends Vue {
|
|||||||
/**
|
/**
|
||||||
* Ensures correct API server configuration
|
* Ensures correct API server configuration
|
||||||
*
|
*
|
||||||
* FIXED: Now respects user preferences instead of forcing production server
|
|
||||||
*
|
|
||||||
* @internal
|
* @internal
|
||||||
* Called after loading settings to ensure correct API endpoint
|
* Called after loading settings to ensure correct API endpoint
|
||||||
*/
|
*/
|
||||||
private async ensureCorrectApiServer() {
|
private async ensureCorrectApiServer() {
|
||||||
const { DEFAULT_ENDORSER_API_SERVER } = await import("../constants/app");
|
const { DEFAULT_ENDORSER_API_SERVER } = await import("../constants/app");
|
||||||
|
|
||||||
// FIXED: Remove forced override - respect user preferences
|
|
||||||
// Only set default if no user preference exists
|
// Only set default if no user preference exists
|
||||||
if (!this.apiServer) {
|
if (!this.apiServer) {
|
||||||
// Set default API server for any platform if not already set
|
// Set default API server for any platform if not already set
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ export default class IdentitySwitcherView extends Vue {
|
|||||||
if (did) {
|
if (did) {
|
||||||
try {
|
try {
|
||||||
const newSettings = await this.$accountSettings(did);
|
const newSettings = await this.$accountSettings(did);
|
||||||
logger.info(
|
logger.debug(
|
||||||
"[IdentitySwitcher Settings Trace] ✅ New account settings loaded",
|
"[IdentitySwitcher Settings Trace] ✅ New account settings loaded",
|
||||||
{
|
{
|
||||||
did,
|
did,
|
||||||
@@ -252,7 +252,7 @@ export default class IdentitySwitcherView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(
|
logger.debug(
|
||||||
"[IdentitySwitcher Settings Trace] 🔄 Navigating to home to trigger watcher",
|
"[IdentitySwitcher Settings Trace] 🔄 Navigating to home to trigger watcher",
|
||||||
{
|
{
|
||||||
newDid: did,
|
newDid: did,
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ export default class StartView extends Vue {
|
|||||||
// Load account count for display logic
|
// Load account count for display logic
|
||||||
this.numAccounts = await retrieveAccountCount();
|
this.numAccounts = await retrieveAccountCount();
|
||||||
|
|
||||||
logger.info("[StartView] Component mounted", {
|
logger.debug("[StartView] Component mounted", {
|
||||||
hasGivenName: !!this.givenName,
|
hasGivenName: !!this.givenName,
|
||||||
accountCount: this.numAccounts,
|
accountCount: this.numAccounts,
|
||||||
passkeysEnabled: this.PASSKEYS_ENABLED,
|
passkeysEnabled: this.PASSKEYS_ENABLED,
|
||||||
@@ -221,7 +221,7 @@ export default class StartView extends Vue {
|
|||||||
* Routes user to new identifier creation flow with seed-based approach
|
* Routes user to new identifier creation flow with seed-based approach
|
||||||
*/
|
*/
|
||||||
public onClickNewSeed() {
|
public onClickNewSeed() {
|
||||||
logger.info("[StartView] User selected new seed generation");
|
logger.debug("[StartView] User selected new seed generation");
|
||||||
this.$router.push({ name: "new-identifier" });
|
this.$router.push({ name: "new-identifier" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,14 +235,14 @@ export default class StartView extends Vue {
|
|||||||
const keyName =
|
const keyName =
|
||||||
AppString.APP_NAME + (this.givenName ? " - " + this.givenName : "");
|
AppString.APP_NAME + (this.givenName ? " - " + this.givenName : "");
|
||||||
|
|
||||||
logger.info("[StartView] Initiating passkey registration", {
|
logger.debug("[StartView] Initiating passkey registration", {
|
||||||
keyName,
|
keyName,
|
||||||
hasGivenName: !!this.givenName,
|
hasGivenName: !!this.givenName,
|
||||||
});
|
});
|
||||||
|
|
||||||
await registerSaveAndActivatePasskey(keyName);
|
await registerSaveAndActivatePasskey(keyName);
|
||||||
|
|
||||||
logger.info("[StartView] Passkey registration successful");
|
logger.debug("[StartView] Passkey registration successful");
|
||||||
this.$router.push({ name: "account" });
|
this.$router.push({ name: "account" });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("[StartView] Passkey registration failed", error);
|
logger.error("[StartView] Passkey registration failed", error);
|
||||||
@@ -255,7 +255,7 @@ export default class StartView extends Vue {
|
|||||||
* Routes user to account import flow for existing seed phrase
|
* Routes user to account import flow for existing seed phrase
|
||||||
*/
|
*/
|
||||||
public onClickNo() {
|
public onClickNo() {
|
||||||
logger.info("[StartView] User selected existing seed import");
|
logger.debug("[StartView] User selected existing seed import");
|
||||||
this.$router.push({ name: "import-account" });
|
this.$router.push({ name: "import-account" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ export default class StartView extends Vue {
|
|||||||
* Routes user to address derivation flow for existing seed
|
* Routes user to address derivation flow for existing seed
|
||||||
*/
|
*/
|
||||||
public onClickDerive() {
|
public onClickDerive() {
|
||||||
logger.info("[StartView] User selected address derivation");
|
logger.debug("[StartView] User selected address derivation");
|
||||||
this.$router.push({ name: "import-derive" });
|
this.$router.push({ name: "import-derive" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user