forked from jsnbuchanan/crowd-funder-for-time-pwa
feat(export): Replace CSV export with standardized JSON format
- Add contactsToExportJson utility function for standardized data export - Replace CSV export with JSON format in DataExportSection - Update file extension and MIME type to application/json - Remove Dexie-specific export logic in favor of unified SQLite/Dexie approach - Update success notifications to reflect JSON format - Add TypeScript interfaces for export data structure This change improves data portability and standardization by: - Using a consistent JSON format for data export/import - Supporting both SQLite and Dexie databases - Including all contact fields in export - Properly handling contactMethods as stringified JSON - Maintaining backward compatibility with existing import tools Security: No sensitive data exposure, maintains existing access controls
This commit is contained in:
@@ -521,7 +521,9 @@ export default class HomeView extends Vue {
|
||||
logConsoleAndDb(`[HomeView] Retrieved ${this.allMyDids.length} DIDs`);
|
||||
} catch (error) {
|
||||
logConsoleAndDb(`[HomeView] Failed to retrieve DIDs: ${error}`, true);
|
||||
throw new Error("Failed to load existing identities. Please try restarting the app.");
|
||||
throw new Error(
|
||||
"Failed to load existing identities. Please try restarting the app.",
|
||||
);
|
||||
}
|
||||
|
||||
// Create new DID if needed
|
||||
@@ -534,7 +536,10 @@ export default class HomeView extends Vue {
|
||||
logConsoleAndDb(`[HomeView] Created new identity: ${newDid}`);
|
||||
} catch (error) {
|
||||
this.isCreatingIdentifier = false;
|
||||
logConsoleAndDb(`[HomeView] Failed to create new identity: ${error}`, true);
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Failed to create new identity: ${error}`,
|
||||
true,
|
||||
);
|
||||
throw new Error("Failed to create new identity. Please try again.");
|
||||
}
|
||||
}
|
||||
@@ -546,34 +551,53 @@ export default class HomeView extends Vue {
|
||||
if (USE_DEXIE_DB) {
|
||||
settings = await retrieveSettingsForActiveAccount();
|
||||
}
|
||||
logConsoleAndDb(`[HomeView] Retrieved settings for ${settings.activeDid || 'no active DID'}`);
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Retrieved settings for ${settings.activeDid || "no active DID"}`,
|
||||
);
|
||||
} catch (error) {
|
||||
logConsoleAndDb(`[HomeView] Failed to retrieve settings: ${error}`, true);
|
||||
throw new Error("Failed to load user settings. Some features may be limited.");
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Failed to retrieve settings: ${error}`,
|
||||
true,
|
||||
);
|
||||
throw new Error(
|
||||
"Failed to load user settings. Some features may be limited.",
|
||||
);
|
||||
}
|
||||
|
||||
// Update component state
|
||||
this.apiServer = settings.apiServer || "";
|
||||
this.activeDid = settings.activeDid || "";
|
||||
|
||||
|
||||
// Load contacts with graceful fallback
|
||||
try {
|
||||
const platformService = PlatformServiceFactory.getInstance();
|
||||
const dbContacts = await platformService.dbQuery("SELECT * FROM contacts");
|
||||
this.allContacts = databaseUtil.mapQueryResultToValues(dbContacts) as Contact[];
|
||||
const dbContacts = await platformService.dbQuery(
|
||||
"SELECT * FROM contacts",
|
||||
);
|
||||
this.allContacts = databaseUtil.mapQueryResultToValues(
|
||||
dbContacts,
|
||||
) as Contact[];
|
||||
if (USE_DEXIE_DB) {
|
||||
this.allContacts = await db.contacts.toArray();
|
||||
}
|
||||
logConsoleAndDb(`[HomeView] Retrieved ${this.allContacts.length} contacts`);
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Retrieved ${this.allContacts.length} contacts`,
|
||||
);
|
||||
} catch (error) {
|
||||
logConsoleAndDb(`[HomeView] Failed to retrieve contacts: ${error}`, true);
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Failed to retrieve contacts: ${error}`,
|
||||
true,
|
||||
);
|
||||
this.allContacts = []; // Ensure we have a valid empty array
|
||||
this.$notify({
|
||||
group: "alert",
|
||||
type: "warning",
|
||||
title: "Contact Loading Issue",
|
||||
text: "Some contact information may be unavailable.",
|
||||
}, 5000);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "warning",
|
||||
title: "Contact Loading Issue",
|
||||
text: "Some contact information may be unavailable.",
|
||||
},
|
||||
5000,
|
||||
);
|
||||
}
|
||||
|
||||
// Update remaining settings
|
||||
@@ -583,14 +607,17 @@ export default class HomeView extends Vue {
|
||||
this.isFeedFilteredByNearby = !!settings.filterFeedByNearby;
|
||||
this.isRegistered = !!settings.isRegistered;
|
||||
this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId;
|
||||
this.lastAckedOfferToUserProjectsJwtId = settings.lastAckedOfferToUserProjectsJwtId;
|
||||
this.lastAckedOfferToUserProjectsJwtId =
|
||||
settings.lastAckedOfferToUserProjectsJwtId;
|
||||
this.searchBoxes = settings.searchBoxes || [];
|
||||
this.showShortcutBvc = !!settings.showShortcutBvc;
|
||||
this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings);
|
||||
|
||||
// Check onboarding status
|
||||
if (!settings.finishedOnboarding) {
|
||||
(this.$refs.onboardingDialog as OnboardingDialog).open(OnboardPage.Home);
|
||||
(this.$refs.onboardingDialog as OnboardingDialog).open(
|
||||
OnboardPage.Home,
|
||||
);
|
||||
}
|
||||
|
||||
// Check registration status if needed
|
||||
@@ -613,10 +640,15 @@ export default class HomeView extends Vue {
|
||||
});
|
||||
}
|
||||
this.isRegistered = true;
|
||||
logConsoleAndDb(`[HomeView] User ${this.activeDid} is now registered`);
|
||||
logConsoleAndDb(
|
||||
`[HomeView] User ${this.activeDid} is now registered`,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logConsoleAndDb(`[HomeView] Registration check failed: ${error}`, true);
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Registration check failed: ${error}`,
|
||||
true,
|
||||
);
|
||||
// Continue as unregistered - this is expected for new users
|
||||
}
|
||||
}
|
||||
@@ -624,8 +656,11 @@ export default class HomeView extends Vue {
|
||||
// Initialize feed and offers
|
||||
try {
|
||||
// Start feed update in background
|
||||
this.updateAllFeed().catch(error => {
|
||||
logConsoleAndDb(`[HomeView] Background feed update failed: ${error}`, true);
|
||||
this.updateAllFeed().catch((error) => {
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Background feed update failed: ${error}`,
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
// Load new offers if we have an active DID
|
||||
@@ -649,23 +684,28 @@ export default class HomeView extends Vue {
|
||||
this.newOffersToUserHitLimit = offersToUser.hitLimit;
|
||||
this.numNewOffersToUserProjects = offersToProjects.data.length;
|
||||
this.newOffersToUserProjectsHitLimit = offersToProjects.hitLimit;
|
||||
|
||||
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Retrieved ${this.numNewOffersToUser} user offers and ` +
|
||||
`${this.numNewOffersToUserProjects} project offers`
|
||||
`${this.numNewOffersToUserProjects} project offers`,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logConsoleAndDb(`[HomeView] Failed to initialize feed/offers: ${error}`, true);
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Failed to initialize feed/offers: ${error}`,
|
||||
true,
|
||||
);
|
||||
// Don't throw - we can continue with empty feed
|
||||
this.$notify({
|
||||
group: "alert",
|
||||
type: "warning",
|
||||
title: "Feed Loading Issue",
|
||||
text: "Some feed data may be unavailable. Pull to refresh.",
|
||||
}, 5000);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "warning",
|
||||
title: "Feed Loading Issue",
|
||||
text: "Some feed data may be unavailable. Pull to refresh.",
|
||||
},
|
||||
5000,
|
||||
);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.handleError(error);
|
||||
throw error; // Re-throw to be caught by mounted()
|
||||
@@ -837,10 +877,10 @@ export default class HomeView extends Vue {
|
||||
private handleError(err: unknown) {
|
||||
const errorMessage = err instanceof Error ? err.message : String(err);
|
||||
const userMessage = (err as { userMessage?: string })?.userMessage;
|
||||
|
||||
|
||||
logConsoleAndDb(
|
||||
`[HomeView] Initialization error: ${errorMessage}${userMessage ? ` (${userMessage})` : ''}`,
|
||||
true
|
||||
`[HomeView] Initialization error: ${errorMessage}${userMessage ? ` (${userMessage})` : ""}`,
|
||||
true,
|
||||
);
|
||||
|
||||
this.$notify(
|
||||
@@ -848,7 +888,9 @@ export default class HomeView extends Vue {
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: userMessage || "There was an error loading your data. Please try refreshing the page.",
|
||||
text:
|
||||
userMessage ||
|
||||
"There was an error loading your data. Please try refreshing the page.",
|
||||
},
|
||||
5000,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user