forked from jsnbuchanan/crowd-funder-for-time-pwa
add a way to import contacts & settings
This commit is contained in:
@@ -82,6 +82,7 @@
|
||||
<router-link
|
||||
:to="{ name: 'new-edit-account' }"
|
||||
class="block text-center text-lg font-bold uppercase bg-slate-500 text-white px-2 py-3 rounded-md mb-2"
|
||||
v-if="activeDid"
|
||||
>
|
||||
Edit Identity
|
||||
</router-link>
|
||||
@@ -153,7 +154,7 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<h3 class="text-sm uppercase font-semibold mb-3">Data</h3>
|
||||
<h3 class="text-sm uppercase font-semibold mb-3">Data Export</h3>
|
||||
|
||||
<router-link
|
||||
:to="{ name: 'seed-backup' }"
|
||||
@@ -180,7 +181,7 @@
|
||||
If no download happened yet, click again here to download now.
|
||||
</a>
|
||||
|
||||
<div v-if="activeDid" class="flex py-2">
|
||||
<div v-if="activeDid" class="flex mt-8 py-2">
|
||||
<button class="text-center text-md text-blue-500" @click="checkLimits()">
|
||||
Check Limits
|
||||
</button>
|
||||
@@ -306,6 +307,21 @@
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<div class="grid-cols-2">
|
||||
<span class="text-slate-500 text-sm font-bold mb-2">Data Import</span>
|
||||
<input type="file" @change="uploadFile" class="ml-2" />
|
||||
<div v-if="showContactImport()">
|
||||
<button
|
||||
class="block text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6"
|
||||
@click="submitFile()"
|
||||
>
|
||||
Import Settings & Contacts
|
||||
<br />
|
||||
(excluding Identifier Data)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex py-2">
|
||||
<button class="text-blue-500">
|
||||
<router-link :to="{ name: 'statistics' }" class="block text-center">
|
||||
@@ -407,7 +423,9 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { AxiosError, AxiosRequestConfig } from "axios";
|
||||
import Dexie from "dexie";
|
||||
import "dexie-export-import";
|
||||
import { ref } from "vue";
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
|
||||
@@ -418,6 +436,7 @@ import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||
import { accessToken } from "@/libs/crypto";
|
||||
import { IIdentifier } from "@veramo/core";
|
||||
import { ErrorResponse, RateLimits } from "@/libs/endorserServer";
|
||||
import { ImportProgress } from "dexie-export-import/dist/import";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const Buffer = require("buffer/").Buffer;
|
||||
@@ -436,6 +455,8 @@ interface IAccount {
|
||||
derivationPath: string;
|
||||
}
|
||||
|
||||
const inputFileNameRef = ref<Blob>();
|
||||
|
||||
@Component({ components: { QuickNav } })
|
||||
export default class AccountViewView extends Vue {
|
||||
$notify!: (notification: Notification, timeout?: number) => void;
|
||||
@@ -480,26 +501,18 @@ export default class AccountViewView extends Vue {
|
||||
try {
|
||||
// Open the accounts database
|
||||
await accountsDB.open();
|
||||
} catch (error) {
|
||||
console.error("Failed to open accounts database:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
let account: { identity?: string } | undefined;
|
||||
|
||||
try {
|
||||
// Search for the account with the matching DID (decentralized identifier)
|
||||
account = await accountsDB.accounts
|
||||
.where("did")
|
||||
.equals(activeDid)
|
||||
.first();
|
||||
const account: { identity?: string } | undefined =
|
||||
await accountsDB.accounts.where("did").equals(activeDid).first();
|
||||
|
||||
accountsDB.close();
|
||||
// Return parsed identity or null if not found
|
||||
return JSON.parse((account?.identity as string) || "null");
|
||||
} catch (error) {
|
||||
console.error("Failed to find account:", error);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return parsed identity or null if not found
|
||||
return JSON.parse((account?.identity as string) || "null");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -548,6 +561,7 @@ export default class AccountViewView extends Vue {
|
||||
async beforeCreate() {
|
||||
await accountsDB.open();
|
||||
this.numAccounts = await accountsDB.accounts.count();
|
||||
accountsDB.close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -572,6 +586,7 @@ export default class AccountViewView extends Vue {
|
||||
if (identity) {
|
||||
this.processIdentity(identity);
|
||||
}
|
||||
db.close();
|
||||
} catch (err: unknown) {
|
||||
this.handleError(err);
|
||||
}
|
||||
@@ -668,6 +683,7 @@ export default class AccountViewView extends Vue {
|
||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||
showContactGivesInline: this.showContactGives,
|
||||
});
|
||||
db.close();
|
||||
} catch (err) {
|
||||
this.$notify(
|
||||
{
|
||||
@@ -787,6 +803,43 @@ export default class AccountViewView extends Vue {
|
||||
console.error("Export Error:", error);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
async uploadFile(event: any) {
|
||||
inputFileNameRef.value = event.target.files[0];
|
||||
}
|
||||
|
||||
showContactImport() {
|
||||
return !!inputFileNameRef.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously imports the database from a downloadable JSON file.
|
||||
*
|
||||
* @throws Will notify the user if there is an export error.
|
||||
*/
|
||||
async submitFile() {
|
||||
if (inputFileNameRef.value != null) {
|
||||
if (
|
||||
confirm(
|
||||
"This will replace all settings and contacts, so we recommend you first do the backup step above." +
|
||||
" Are you sure you want to import and replace all contacts and settings?",
|
||||
)
|
||||
) {
|
||||
await db.delete();
|
||||
await Dexie.import(inputFileNameRef.value, {
|
||||
progressCallback: this.progressCallback,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private progressCallback(progress: ImportProgress) {
|
||||
console.log(
|
||||
`Import progress: ${progress.completedRows} of ${progress.totalRows} rows completed.`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
async checkLimits() {
|
||||
const identity = await this.getIdentity(this.activeDid);
|
||||
if (identity) {
|
||||
@@ -815,6 +868,7 @@ export default class AccountViewView extends Vue {
|
||||
isRegistered: true,
|
||||
});
|
||||
this.isRegistered = true;
|
||||
db.close();
|
||||
} catch (err) {
|
||||
console.error("Got an error updating settings:", err);
|
||||
this.$notify(
|
||||
@@ -886,6 +940,7 @@ export default class AccountViewView extends Vue {
|
||||
} else {
|
||||
await this.switchToAccountNumber(accountNum);
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -916,9 +971,12 @@ export default class AccountViewView extends Vue {
|
||||
const accounts = await accountsDB.accounts.toArray();
|
||||
const account = accounts[accountNum - 1];
|
||||
|
||||
await db.open();
|
||||
await db.settings.update(MASTER_SETTINGS_KEY, { activeDid: account.did });
|
||||
|
||||
this.updateActiveAccountProperties(account);
|
||||
db.close();
|
||||
accountsDB.close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -946,6 +1004,7 @@ export default class AccountViewView extends Vue {
|
||||
apiServer: this.apiServerInput,
|
||||
});
|
||||
this.apiServer = this.apiServerInput;
|
||||
db.close();
|
||||
}
|
||||
|
||||
async onClickSavePushServer() {
|
||||
@@ -963,6 +1022,7 @@ export default class AccountViewView extends Vue {
|
||||
},
|
||||
-1,
|
||||
);
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user