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:
@@ -63,13 +63,18 @@ backup and database export, with platform-specific download instructions. * *
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from "vue-facing-decorator";
|
||||
import { AppString, NotificationIface, USE_DEXIE_DB } from "../constants/app";
|
||||
import { db } from "../db/index";
|
||||
|
||||
import { Contact } from "../db/tables/contacts";
|
||||
import * as databaseUtil from "../db/databaseUtil";
|
||||
|
||||
import { logger } from "../utils/logger";
|
||||
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
|
||||
import {
|
||||
PlatformService,
|
||||
PlatformCapabilities,
|
||||
} from "../services/PlatformService";
|
||||
import { contactsToExportJson } from "../libs/util";
|
||||
import { db } from "../db/index";
|
||||
|
||||
/**
|
||||
* @vue-component
|
||||
@@ -131,24 +136,25 @@ export default class DataExportSection extends Vue {
|
||||
*/
|
||||
public async exportDatabase() {
|
||||
try {
|
||||
if (!USE_DEXIE_DB) {
|
||||
throw new Error("Not implemented");
|
||||
let allContacts: Contact[] = [];
|
||||
const platformService = PlatformServiceFactory.getInstance();
|
||||
const result = await platformService.dbQuery(`SELECT * FROM contacts`);
|
||||
if (result) {
|
||||
allContacts = databaseUtil.mapQueryResultToValues(
|
||||
result,
|
||||
) as unknown as Contact[];
|
||||
}
|
||||
const blob = await db.export({
|
||||
prettyJson: true,
|
||||
transform: (table, value, key) => {
|
||||
if (table === "contacts") {
|
||||
// Dexie inserts a number 0 when some are undefined, so we need to totally remove them.
|
||||
Object.keys(value).forEach((prop) => {
|
||||
if (value[prop] === undefined) {
|
||||
delete value[prop];
|
||||
}
|
||||
});
|
||||
}
|
||||
return { value, key };
|
||||
},
|
||||
});
|
||||
const fileName = `${AppString.APP_NAME_NO_SPACES}-backup.json`;
|
||||
// if (USE_DEXIE_DB) {
|
||||
// await db.open();
|
||||
// allContacts = await db.contacts.toArray();
|
||||
// }
|
||||
|
||||
// Convert contacts to export format
|
||||
const exportData = contactsToExportJson(allContacts);
|
||||
const jsonStr = JSON.stringify(exportData, null, 2);
|
||||
const blob = new Blob([jsonStr], { type: "application/json" });
|
||||
|
||||
const fileName = `${AppString.APP_NAME_NO_SPACES}-backup-contacts.json`;
|
||||
|
||||
if (this.platformCapabilities.hasFileDownload) {
|
||||
// Web platform: Use download link
|
||||
@@ -160,8 +166,7 @@ export default class DataExportSection extends Vue {
|
||||
setTimeout(() => URL.revokeObjectURL(this.downloadUrl), 1000);
|
||||
} else if (this.platformCapabilities.hasFileSystem) {
|
||||
// Native platform: Write to app directory
|
||||
const content = await blob.text();
|
||||
await this.platformService.writeAndShareFile(fileName, content);
|
||||
await this.platformService.writeAndShareFile(fileName, jsonStr);
|
||||
} else {
|
||||
throw new Error("This platform does not support file downloads.");
|
||||
}
|
||||
@@ -172,10 +177,10 @@ export default class DataExportSection extends Vue {
|
||||
type: "success",
|
||||
title: "Export Successful",
|
||||
text: this.platformCapabilities.hasFileDownload
|
||||
? "See your downloads directory for the backup. It is in the Dexie format."
|
||||
: "You should have been prompted to save your backup file.",
|
||||
? "See your downloads directory for the backup. It is in JSON format."
|
||||
: "The backup file has been saved.",
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error("Export Error:", error);
|
||||
|
||||
Reference in New Issue
Block a user