forked from jsnbuchanan/crowd-funder-for-time-pwa
Merge branch 'master' into notification-request-permission-dialog
This commit is contained in:
@@ -11,6 +11,9 @@ npm run serve
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Compiles and minifies for production
|
### Compiles and minifies for production
|
||||||
|
|
||||||
|
If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js, eg: `publicPath: "/app/time-tracker/",`
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ tasks:
|
|||||||
- 08 Scan QR code to import into contacts assignee:matthew
|
- 08 Scan QR code to import into contacts assignee:matthew
|
||||||
- SEE: https://github.com/gruhn/vue-qrcode-reader
|
- SEE: https://github.com/gruhn/vue-qrcode-reader
|
||||||
|
|
||||||
- Show pop-up or some message confirming that settings & contacts download has been initiated/finished assignee:matthew
|
- 01 Show pop-up or some message confirming that settings & contacts download has been initiated/finished assignee:matthew
|
||||||
|
|
||||||
- Ensure each action sent to the server has a confirmation - eg registration (ie a toast something that dismisses after 5-10s)
|
- 01 Ensure each action sent to the server has a confirmation - eg registration (ie a toast something that dismisses after 5-10s)
|
||||||
- SEE: https://github.com/emmanuelsw/notiwind assignee:jose
|
- SEE: https://github.com/emmanuelsw/notiwind assignee:jose
|
||||||
|
|
||||||
- Home Feed & Quick Give screen :
|
- Home Feed & Quick Give screen :
|
||||||
@@ -27,6 +27,7 @@ tasks:
|
|||||||
|
|
||||||
- 24 Move to Vite assignee:matthew
|
- 24 Move to Vite assignee:matthew
|
||||||
|
|
||||||
|
- .5 include the hash of the latest commit, and maybe a version
|
||||||
- .5 add link to further project / people when a project pays ahead
|
- .5 add link to further project / people when a project pays ahead
|
||||||
- .5 add project ID to the URL, to make a project publicly-accessible
|
- .5 add project ID to the URL, to make a project publicly-accessible
|
||||||
- .5 remove edit from project page for projects owned by others
|
- .5 remove edit from project page for projects owned by others
|
||||||
@@ -36,9 +37,18 @@ tasks:
|
|||||||
- .2 fix rate limit verbiage (with the new one-per-day allowance) assignee:trent
|
- .2 fix rate limit verbiage (with the new one-per-day allowance) assignee:trent
|
||||||
- .2 move 'switch identity' to the advanced section
|
- .2 move 'switch identity' to the advanced section
|
||||||
- .1 remove the logic to exclude beforeId in list of plans after server has commit 26b25af605e715600d4f12b6416ed9fd7142d164
|
- .1 remove the logic to exclude beforeId in list of plans after server has commit 26b25af605e715600d4f12b6416ed9fd7142d164
|
||||||
|
- .2 in SeedBackupView, don't load the mnemonic and keep it in memory; only load it when they click "show"
|
||||||
|
|
||||||
- Discuss whether the remaining tasks are worthwhile before MVP release.
|
- Discuss whether the remaining tasks are worthwhile before MVP release.
|
||||||
|
|
||||||
|
- 04 allow user to download claims, mine + ones I can see about me from others
|
||||||
|
- .5 change the derivation path, and regenerate test IDs
|
||||||
|
- 02 allow user to create new DIDs from the same seed phrase (ie. increment derivation path)
|
||||||
|
- .5 on ProjectView page, show immediate feedback when a gift is given (on list?) -- and consider the same for Home & Contacts pages
|
||||||
|
- .5 customize favicon
|
||||||
|
- .5 Do we want to combine first name & last name?
|
||||||
|
- .2 Show a warning if both giver and recipient are the same (but still allow?)
|
||||||
|
|
||||||
- contacts v+ :
|
- contacts v+ :
|
||||||
- 01 Import all the non-sensitive data (ie. contacts & settings).
|
- 01 Import all the non-sensitive data (ie. contacts & settings).
|
||||||
- .2 show error to user when adding a duplicate contact
|
- .2 show error to user when adding a duplicate contact
|
||||||
@@ -51,12 +61,6 @@ tasks:
|
|||||||
- maybe - allow type annotations in World.js & landmarks.js (since we get this error - "Types are not supported by current JavaScript version")
|
- maybe - allow type annotations in World.js & landmarks.js (since we get this error - "Types are not supported by current JavaScript version")
|
||||||
- 08 convert to cleaner implementation (maybe Drie -- https://github.com/janvorisek/drie)
|
- 08 convert to cleaner implementation (maybe Drie -- https://github.com/janvorisek/drie)
|
||||||
|
|
||||||
- .5 on ProjectView page, show immediate feedback when a gift is given (on list?) -- and consider the same for Home & Contacts pages
|
|
||||||
- .5 customize favicon
|
|
||||||
- 04 allow user to download claims, mine + ones I can see about me from others
|
|
||||||
- Do we want to combine first name & last name?
|
|
||||||
- Show a warning if both giver and recipient are the same (but still allow?)
|
|
||||||
|
|
||||||
- Release Minimum Viable Product :
|
- Release Minimum Viable Product :
|
||||||
- 08 thorough testing for errors & edge cases
|
- 08 thorough testing for errors & edge cases
|
||||||
- Turn off stats-world or ensure it's usable (eg. cannot zoom out too far and lose world, cannot screenshot).
|
- Turn off stats-world or ensure it's usable (eg. cannot zoom out too far and lose world, cannot screenshot).
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ type NonsensitiveTables = {
|
|||||||
* https://9to5answer.com/how-to-bypass-warning-unexpected-any-specify-a-different-type-typescript-eslint-no-explicit-any
|
* https://9to5answer.com/how-to-bypass-warning-unexpected-any-specify-a-different-type-typescript-eslint-no-explicit-any
|
||||||
*/
|
*/
|
||||||
export type SensitiveDexie<T extends unknown = SensitiveTables> = BaseDexie & T;
|
export type SensitiveDexie<T extends unknown = SensitiveTables> = BaseDexie & T;
|
||||||
export const accountsDB = new BaseDexie("KickStartAccounts") as SensitiveDexie;
|
export const accountsDB = new BaseDexie("TimeSafariAccounts") as SensitiveDexie;
|
||||||
const SensitiveSchemas = Object.assign({}, AccountsSchema);
|
const SensitiveSchemas = Object.assign({}, AccountsSchema);
|
||||||
|
|
||||||
export type NonsensitiveDexie<T extends unknown = NonsensitiveTables> =
|
export type NonsensitiveDexie<T extends unknown = NonsensitiveTables> =
|
||||||
BaseDexie & T;
|
BaseDexie & T;
|
||||||
export const db = new BaseDexie("KickStart") as NonsensitiveDexie;
|
export const db = new BaseDexie("TimeSafari") as NonsensitiveDexie;
|
||||||
const NonsensitiveSchemas = Object.assign({}, ContactsSchema, SettingsSchema);
|
const NonsensitiveSchemas = Object.assign({}, ContactsSchema, SettingsSchema);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import { HDNode } from "@ethersproject/hdnode";
|
|||||||
import * as didJwt from "did-jwt";
|
import * as didJwt from "did-jwt";
|
||||||
import * as u8a from "uint8arrays";
|
import * as u8a from "uint8arrays";
|
||||||
|
|
||||||
|
export const DEFAULT_ROOT_DERIVATION_PATH = "m/76798669'/0'/0'/0'";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@@ -47,17 +49,17 @@ export const newIdentifier = (
|
|||||||
*/
|
*/
|
||||||
export const deriveAddress = (
|
export const deriveAddress = (
|
||||||
mnemonic: string,
|
mnemonic: string,
|
||||||
|
derivationPath: string = DEFAULT_ROOT_DERIVATION_PATH,
|
||||||
): [string, string, string, string] => {
|
): [string, string, string, string] => {
|
||||||
const UPORT_ROOT_DERIVATION_PATH = "m/7696500'/0'/0'/0'";
|
|
||||||
mnemonic = mnemonic.trim().toLowerCase();
|
mnemonic = mnemonic.trim().toLowerCase();
|
||||||
|
|
||||||
const hdnode: HDNode = HDNode.fromMnemonic(mnemonic);
|
const hdnode: HDNode = HDNode.fromMnemonic(mnemonic);
|
||||||
const rootNode: HDNode = hdnode.derivePath(UPORT_ROOT_DERIVATION_PATH);
|
const rootNode: HDNode = hdnode.derivePath(derivationPath);
|
||||||
const privateHex = rootNode.privateKey.substring(2); // original starts with '0x'
|
const privateHex = rootNode.privateKey.substring(2); // original starts with '0x'
|
||||||
const publicHex = rootNode.publicKey.substring(2); // original starts with '0x'
|
const publicHex = rootNode.publicKey.substring(2); // original starts with '0x'
|
||||||
const address = rootNode.address;
|
const address = rootNode.address;
|
||||||
|
|
||||||
return [address, privateHex, publicHex, UPORT_ROOT_DERIVATION_PATH];
|
return [address, privateHex, publicHex, derivationPath];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -91,6 +91,14 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
/* webpackChunkName: "import-account" */ "../views/ImportAccountView.vue"
|
/* webpackChunkName: "import-account" */ "../views/ImportAccountView.vue"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/import-derive",
|
||||||
|
name: "import-derive",
|
||||||
|
component: () =>
|
||||||
|
import(
|
||||||
|
/* webpackChunkName: "import-derive" */ "../views/ImportDerivedAccountView.vue"
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/new-edit-account",
|
path: "/new-edit-account",
|
||||||
name: "new-edit-account",
|
name: "new-edit-account",
|
||||||
|
|||||||
@@ -24,6 +24,24 @@
|
|||||||
v-model="mnemonic"
|
v-model="mnemonic"
|
||||||
/>
|
/>
|
||||||
{{ mnemonic }}
|
{{ mnemonic }}
|
||||||
|
<h3
|
||||||
|
class="text-sm uppercase font-semibold mb-3"
|
||||||
|
@click="showAdvanced = !showAdvanced"
|
||||||
|
>
|
||||||
|
Advanced
|
||||||
|
</h3>
|
||||||
|
<div v-if="showAdvanced">
|
||||||
|
Enter a custom derivation path
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="block w-full rounded border border-slate-400 mb-4 px-3 py-2"
|
||||||
|
v-model="derivationPath"
|
||||||
|
/>
|
||||||
|
For previous uPort or Endorser users,
|
||||||
|
<a @click="derivationPath = UPORT_DERIVATION_PATH" class="text-blue-500">
|
||||||
|
click here to use that value.
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<button
|
<button
|
||||||
@click="from_mnemonic()"
|
@click="from_mnemonic()"
|
||||||
@@ -44,7 +62,11 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
import { deriveAddress, newIdentifier } from "../libs/crypto";
|
import {
|
||||||
|
DEFAULT_ROOT_DERIVATION_PATH,
|
||||||
|
deriveAddress,
|
||||||
|
newIdentifier,
|
||||||
|
} from "../libs/crypto";
|
||||||
import { accountsDB, db } from "@/db";
|
import { accountsDB, db } from "@/db";
|
||||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
|
|
||||||
@@ -52,11 +74,14 @@ import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
|||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class ImportAccountView extends Vue {
|
export default class ImportAccountView extends Vue {
|
||||||
|
UPORT_DERIVATION_PATH = "m/7696500'/0'/0'/0'";
|
||||||
|
|
||||||
mnemonic = "";
|
mnemonic = "";
|
||||||
address = "";
|
address = "";
|
||||||
privateHex = "";
|
privateHex = "";
|
||||||
publicHex = "";
|
publicHex = "";
|
||||||
derivationPath = "";
|
derivationPath = DEFAULT_ROOT_DERIVATION_PATH;
|
||||||
|
showAdvanced = false;
|
||||||
|
|
||||||
public onCancelClick() {
|
public onCancelClick() {
|
||||||
this.$router.back();
|
this.$router.back();
|
||||||
@@ -65,8 +90,10 @@ export default class ImportAccountView extends Vue {
|
|||||||
public async from_mnemonic() {
|
public async from_mnemonic() {
|
||||||
const mne: string = this.mnemonic.trim().toLowerCase();
|
const mne: string = this.mnemonic.trim().toLowerCase();
|
||||||
if (this.mnemonic.trim().length > 0) {
|
if (this.mnemonic.trim().length > 0) {
|
||||||
[this.address, this.privateHex, this.publicHex, this.derivationPath] =
|
[this.address, this.privateHex, this.publicHex] = deriveAddress(
|
||||||
deriveAddress(mne);
|
mne,
|
||||||
|
this.derivationPath,
|
||||||
|
);
|
||||||
|
|
||||||
const newId = newIdentifier(
|
const newId = newIdentifier(
|
||||||
this.address,
|
this.address,
|
||||||
|
|||||||
163
src/views/ImportDerivedAccountView.vue
Normal file
163
src/views/ImportDerivedAccountView.vue
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<template>
|
||||||
|
<section id="Content" class="p-6 pb-24">
|
||||||
|
<!-- Breadcrumb -->
|
||||||
|
<div id="ViewBreadcrumb" class="mb-8">
|
||||||
|
<h1 class="text-lg text-center font-light relative px-7">
|
||||||
|
<!-- Cancel -->
|
||||||
|
<button
|
||||||
|
@click="$router.go(-1)"
|
||||||
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
|
>
|
||||||
|
<fa icon="chevron-left"></fa>
|
||||||
|
</button>
|
||||||
|
Derive from Existing Identity
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<!-- Import Account Form -->
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p class="text-center text-xl mb-4 font-light">
|
||||||
|
Will increment the maximum derivation path from the existing seed.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p v-if="didArrays.length > 1">
|
||||||
|
Choose existing DIDs from same seed phrase to compute derivation.
|
||||||
|
</p>
|
||||||
|
<ul class="mb-4">
|
||||||
|
<li
|
||||||
|
class="block bg-slate-100 rounded-md flex items-center px-4 py-3 mb-2"
|
||||||
|
v-for="dids in didArrays"
|
||||||
|
:key="dids[0]"
|
||||||
|
@click="switchAccount(dids[0])"
|
||||||
|
>
|
||||||
|
<fa
|
||||||
|
v-if="dids[0] == selectedArrayFirstDid"
|
||||||
|
icon="circle"
|
||||||
|
class="fa-fw text-blue-400 text-xl mr-3"
|
||||||
|
></fa>
|
||||||
|
<fa
|
||||||
|
v-else
|
||||||
|
icon="circle"
|
||||||
|
class="fa-fw text-slate-400 text-xl mr-3"
|
||||||
|
></fa>
|
||||||
|
<span class="overflow-hidden">
|
||||||
|
<div class="text-sm text-slate-500 truncate">
|
||||||
|
<code>{{ dids.join(",") }}</code>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="mt-8">
|
||||||
|
<button
|
||||||
|
@click="incrementDerivation()"
|
||||||
|
class="block w-full text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-2"
|
||||||
|
>
|
||||||
|
Increment and Import
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="onCancelClick()"
|
||||||
|
type="button"
|
||||||
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
import {
|
||||||
|
DEFAULT_ROOT_DERIVATION_PATH,
|
||||||
|
deriveAddress,
|
||||||
|
newIdentifier,
|
||||||
|
} from "../libs/crypto";
|
||||||
|
import { accountsDB, db } from "@/db";
|
||||||
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {},
|
||||||
|
})
|
||||||
|
export default class ImportAccountView extends Vue {
|
||||||
|
derivationPath = DEFAULT_ROOT_DERIVATION_PATH;
|
||||||
|
didArrays: Array<Array<string>> = [];
|
||||||
|
selectedArrayFirstDid = "";
|
||||||
|
|
||||||
|
async mounted() {
|
||||||
|
await accountsDB.open();
|
||||||
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
|
const seedDids = {};
|
||||||
|
accounts.forEach((account) => {
|
||||||
|
const prevDids = seedDids[account.mnemonic] || [];
|
||||||
|
seedDids[account.mnemonic] = prevDids.concat([account.did]);
|
||||||
|
});
|
||||||
|
this.didArrays = Object.values(seedDids);
|
||||||
|
this.selectedArrayFirstDid = this.didArrays[0][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public onCancelClick() {
|
||||||
|
this.$router.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
public switchAccount(did: string) {
|
||||||
|
this.selectedArrayFirstDid = did;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async incrementDerivation() {
|
||||||
|
await accountsDB.open();
|
||||||
|
// find the maximum derivation path for the selected DIDs
|
||||||
|
const selectedArray: Array<string> = this.didArrays.find(
|
||||||
|
(dids) => dids[0] === this.selectedArrayFirstDid,
|
||||||
|
);
|
||||||
|
const allMatchingAccounts = await accountsDB.accounts
|
||||||
|
.where("did")
|
||||||
|
.anyOf(...selectedArray)
|
||||||
|
.toArray();
|
||||||
|
const accountWithMaxDeriv = allMatchingAccounts[0];
|
||||||
|
allMatchingAccounts.slice(1).forEach((account) => {
|
||||||
|
if (account.derivationPath > accountWithMaxDeriv.derivationPath) {
|
||||||
|
accountWithMaxDeriv.derivationPath = account.derivationPath;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// increment the last number in that max derivation path
|
||||||
|
let lastStr = accountWithMaxDeriv.derivationPath.split("/").slice(-1)[0];
|
||||||
|
if (lastStr.endsWith("'")) {
|
||||||
|
lastStr = lastStr.slice(0, -1);
|
||||||
|
}
|
||||||
|
const lastNum = parseInt(lastStr, 10);
|
||||||
|
const newLastNum = lastNum + 1;
|
||||||
|
const newDerivPath = accountWithMaxDeriv.derivationPath
|
||||||
|
.split("/")
|
||||||
|
.slice(0, -1)
|
||||||
|
.concat([newLastNum.toString() + "'"])
|
||||||
|
.join("/");
|
||||||
|
|
||||||
|
const mne: string = accountWithMaxDeriv.mnemonic;
|
||||||
|
|
||||||
|
const [address, privateHex, publicHex] = deriveAddress(mne, newDerivPath);
|
||||||
|
|
||||||
|
const newId = newIdentifier(address, publicHex, privateHex, newDerivPath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await accountsDB.accounts.add({
|
||||||
|
dateCreated: new Date().toISOString(),
|
||||||
|
derivationPath: newDerivPath,
|
||||||
|
did: newId.did,
|
||||||
|
identity: JSON.stringify(newId),
|
||||||
|
mnemonic: mne,
|
||||||
|
publicKeyHex: newId.keys[0].publicKeyHex,
|
||||||
|
});
|
||||||
|
|
||||||
|
// record that as the active DID
|
||||||
|
await db.open();
|
||||||
|
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
|
activeDid: newId.did,
|
||||||
|
});
|
||||||
|
this.$router.push({ name: "account" });
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error saving mnemonic & updating settings:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -28,6 +28,14 @@
|
|||||||
<i>Don't take a screenshot or send it to any online service.</i>
|
<i>Don't take a screenshot or send it to any online service.</i>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p v-if="numAccounts > 1">
|
||||||
|
<b class="text-orange-600">Note:</b> You have more than one identity
|
||||||
|
stored in this browser. If they are all based on the same seed as the
|
||||||
|
current identity, this one backup is sufficient; however, if you have
|
||||||
|
different seeds for other identities, you will have to back them up
|
||||||
|
separately.
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="bg-slate-100 rounded-md overflow-hidden p-4 mb-4">
|
<div class="bg-slate-100 rounded-md overflow-hidden p-4 mb-4">
|
||||||
<button
|
<button
|
||||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
|
||||||
@@ -60,6 +68,7 @@ import QuickNav from "@/components/QuickNav";
|
|||||||
@Component({ components: { AlertMessage, QuickNav } })
|
@Component({ components: { AlertMessage, QuickNav } })
|
||||||
export default class SeedBackupView extends Vue {
|
export default class SeedBackupView extends Vue {
|
||||||
activeAccount = null;
|
activeAccount = null;
|
||||||
|
numAccounts = 0;
|
||||||
showSeed = false;
|
showSeed = false;
|
||||||
alertMessage = "";
|
alertMessage = "";
|
||||||
alertTitle = "";
|
alertTitle = "";
|
||||||
@@ -73,6 +82,7 @@ export default class SeedBackupView extends Vue {
|
|||||||
|
|
||||||
await accountsDB.open();
|
await accountsDB.open();
|
||||||
const accounts = await accountsDB.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
|
this.numAccounts = accounts.length;
|
||||||
this.activeAccount = R.find((acc) => acc.did === activeDid, accounts);
|
this.activeAccount = R.find((acc) => acc.did === activeDid, accounts);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Got an error loading an identity:", err);
|
console.error("Got an error loading an identity:", err);
|
||||||
|
|||||||
@@ -10,30 +10,46 @@
|
|||||||
|
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<p class="text-center text-xl mb-4 font-light">
|
<p class="text-center text-xl mb-4 font-light">
|
||||||
Do you already have an identity to import?
|
Do you have an identity to import?
|
||||||
</p>
|
</p>
|
||||||
<a
|
<a
|
||||||
@click="onClickYes()"
|
@click="onClickYes()"
|
||||||
class="block w-full text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-2"
|
class="block w-full text-center text-lg uppercase bg-blue-600 text-white px-2 py-3 rounded-md"
|
||||||
>
|
>
|
||||||
No
|
No
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
@click="onClickNo()"
|
@click="onClickNo()"
|
||||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md"
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mt-2"
|
||||||
>Yes</a
|
|
||||||
>
|
>
|
||||||
|
Yes
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
v-if="numAccounts > 0"
|
||||||
|
@click="onClickDerive()"
|
||||||
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mt-2"
|
||||||
|
>
|
||||||
|
Derive from Existing Account
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
import { accountsDB } from "@/db";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class StartView extends Vue {
|
export default class StartView extends Vue {
|
||||||
|
numAccounts = 0;
|
||||||
|
|
||||||
|
async mounted() {
|
||||||
|
await accountsDB.open();
|
||||||
|
this.numAccounts = await accountsDB.accounts.count();
|
||||||
|
}
|
||||||
|
|
||||||
public onClickYes() {
|
public onClickYes() {
|
||||||
this.$router.push({ name: "new-identifier" });
|
this.$router.push({ name: "new-identifier" });
|
||||||
}
|
}
|
||||||
@@ -41,5 +57,9 @@ export default class StartView extends Vue {
|
|||||||
public onClickNo() {
|
public onClickNo() {
|
||||||
this.$router.push({ name: "import-account" });
|
this.$router.push({ name: "import-account" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onClickDerive() {
|
||||||
|
this.$router.push({ name: "import-derive" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user