forked from trent_larson/crowd-funder-for-time-pwa
- Add platform-specific capability methods to PlatformService interface: - getExportInstructions() - getExportSuccessMessage() - needsSecondaryDownloadLink() - needsDownloadCleanup() - Update platform service implementations: - WebPlatformService: Implement web-specific export behavior - CapacitorPlatformService: Implement mobile-specific export behavior - ElectronPlatformService: Add placeholder for export functionality - PyWebViewPlatformService: Add placeholder for export functionality - Refactor DataExportSection component: - Remove direct platform checks (isWeb, isCapacitor, etc.) - Use platform service capabilities for UI behavior - Improve error handling and logging - Add proper cleanup for web platform downloads - Update PlatformServiceFactory: - Make getInstance() async to support dynamic imports - Improve platform service initialization - Fix code style and documentation: - Update JSDoc comments - Fix string quotes consistency - Add proper error handling - Improve logging messages - Update Vite config: - Add all Capacitor dependencies to external list - Ensure consistent handling across platforms
194 lines
5.7 KiB
Vue
194 lines
5.7 KiB
Vue
/** * Data Export Section Component * * Provides UI and functionality for
|
|
exporting user data and backing up identifier seeds. * Includes buttons for seed
|
|
backup and database export, with platform-specific download instructions. * *
|
|
@component * @displayName DataExportSection * @example * ```vue *
|
|
<DataExportSection :active-did="currentDid" />
|
|
* ``` */
|
|
|
|
<template>
|
|
<div
|
|
id="sectionDataExport"
|
|
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
|
|
>
|
|
<div class="mb-2 font-bold">Data Export</div>
|
|
<router-link
|
|
v-if="activeDid"
|
|
:to="{ name: 'seed-backup' }"
|
|
class="block w-full text-center text-md bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2 mt-2"
|
|
>
|
|
Backup Identifier Seed
|
|
</router-link>
|
|
|
|
<button
|
|
:class="computedStartDownloadLinkClassNames()"
|
|
class="block w-full text-center text-md bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md"
|
|
@click="exportDatabase()"
|
|
>
|
|
Download Settings & Contacts
|
|
<br />
|
|
(excluding Identifier Data)
|
|
</button>
|
|
<a
|
|
v-if="platformService?.needsSecondaryDownloadLink()"
|
|
ref="downloadLink"
|
|
:class="computedDownloadLinkClassNames()"
|
|
class="block w-full text-center text-md bg-gradient-to-b from-green-500 to-green-800 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-6"
|
|
>
|
|
If no download happened yet, click again here to download now.
|
|
</a>
|
|
<div
|
|
v-if="platformService?.getExportInstructions().length > 0"
|
|
class="mt-4"
|
|
>
|
|
<p
|
|
v-for="instruction in platformService?.getExportInstructions()"
|
|
:key="instruction"
|
|
class="list-disc list-outside ml-4"
|
|
>
|
|
{{ instruction }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Prop, Vue } from "vue-facing-decorator";
|
|
import { NotificationIface } from "../constants/app";
|
|
import { db } from "../db/index";
|
|
import { logger } from "../utils/logger";
|
|
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
|
|
import { PlatformService } from "../services/PlatformService";
|
|
|
|
/**
|
|
* @vue-component
|
|
* Data Export Section Component
|
|
* Handles database export and seed backup functionality with platform-specific behavior
|
|
*/
|
|
@Component
|
|
export default class DataExportSection extends Vue {
|
|
/**
|
|
* Notification function injected by Vue
|
|
* Used to show success/error messages to the user
|
|
*/
|
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
|
|
|
/**
|
|
* Active DID (Decentralized Identifier) of the user
|
|
* Controls visibility of seed backup option
|
|
* @required
|
|
*/
|
|
@Prop({ required: true }) readonly activeDid!: string;
|
|
|
|
/**
|
|
* URL for the database export download
|
|
* Created and revoked dynamically during export process
|
|
* Only used in web platform
|
|
*/
|
|
downloadUrl = "";
|
|
|
|
/**
|
|
* Platform service instance for platform-specific operations
|
|
*/
|
|
private platformService?: PlatformService;
|
|
|
|
/**
|
|
* Lifecycle hook to clean up resources
|
|
* Revokes object URL when component is unmounted (web platform only)
|
|
*/
|
|
beforeUnmount() {
|
|
if (this.downloadUrl && this.platformService?.needsDownloadCleanup()) {
|
|
URL.revokeObjectURL(this.downloadUrl);
|
|
}
|
|
}
|
|
|
|
async mounted() {
|
|
this.platformService = await PlatformServiceFactory.getInstance();
|
|
logger.log(
|
|
"DataExportSection mounted on platform:",
|
|
process.env.VITE_PLATFORM,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Exports the database to a JSON file
|
|
* Uses platform-specific methods for saving the exported data
|
|
* Shows success/error notifications to user
|
|
*
|
|
* @throws {Error} If export fails
|
|
* @emits {Notification} Success or error notification
|
|
*/
|
|
public async exportDatabase() {
|
|
try {
|
|
if (!this.platformService) {
|
|
this.platformService = await PlatformServiceFactory.getInstance();
|
|
}
|
|
logger.log(
|
|
"Starting database export on platform:",
|
|
process.env.VITE_PLATFORM,
|
|
);
|
|
|
|
const blob = await db.export({ prettyJson: true });
|
|
const fileName = `${db.name}-backup.json`;
|
|
logger.log("Database export details:", {
|
|
fileName,
|
|
blobSize: `${blob.size} bytes`,
|
|
platform: process.env.VITE_PLATFORM,
|
|
});
|
|
|
|
await this.platformService.exportDatabase(blob, fileName);
|
|
logger.log("Database export completed successfully:", {
|
|
fileName,
|
|
platform: process.env.VITE_PLATFORM,
|
|
});
|
|
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "success",
|
|
title: "Export Successful",
|
|
text: this.platformService.getExportSuccessMessage(),
|
|
},
|
|
-1,
|
|
);
|
|
} catch (error) {
|
|
logger.error("Database export failed:", {
|
|
error,
|
|
platform: process.env.VITE_PLATFORM,
|
|
});
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "danger",
|
|
title: "Export Error",
|
|
text: "There was an error exporting the data.",
|
|
},
|
|
3000,
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Computes class names for the initial download button
|
|
* @returns Object with 'hidden' class when download is in progress (web platform only)
|
|
*/
|
|
public computedStartDownloadLinkClassNames() {
|
|
return {
|
|
hidden:
|
|
this.downloadUrl && this.platformService?.needsSecondaryDownloadLink(),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Computes class names for the secondary download link
|
|
* @returns Object with 'hidden' class when no download is available or not on web platform
|
|
*/
|
|
public computedDownloadLinkClassNames() {
|
|
return {
|
|
hidden:
|
|
!this.downloadUrl ||
|
|
!this.platformService?.needsSecondaryDownloadLink(),
|
|
};
|
|
}
|
|
}
|
|
</script>
|