forked from trent_larson/crowd-funder-for-time-pwa
Merge pull request 'separate account from other data for backup/restore' (#13) from separate-dbs into master
Reviewed-on: trent_larson/kick-starter-for-time-pwa#13
This commit is contained in:
@@ -44,13 +44,14 @@ New users require registration. This can be done with a claim payload like this
|
|||||||
|
|
||||||
On the test server, User #0 has rights to register others, so you can start playing one of two ways:
|
On the test server, User #0 has rights to register others, so you can start playing one of two ways:
|
||||||
|
|
||||||
- Import the keys for that test User `did:ethr:0x000Ee5654b9742f6Fe18ea970e32b97ee2247B51` by importing this seed phrase: `seminar accuse mystery assist delay law thing deal image undo guard initial shallow wrestle list fragile borrow velvet tomorrow awake explain test offer control`
|
- Import the keys for the test User `did:ethr:0x000Ee5654b9742f6Fe18ea970e32b97ee2247B51` by importing this seed phrase:
|
||||||
|
`seminar accuse mystery assist delay law thing deal image undo guard initial shallow wrestle list fragile borrow velvet tomorrow awake explain test offer control`
|
||||||
|
|
||||||
- Register someone else under User #0 on the `/account` page:
|
- Alternatively, register someone else under User #0 on the `/account` page:
|
||||||
|
|
||||||
* Edit the `src/views/AccountViewView.vue` file and uncomment the lines referring to "test".
|
* In the `src/views/AccountViewView.vue` file, uncomment the lines referring to "testServerRegisterUser".
|
||||||
|
|
||||||
* Use the [Vue Devtools browser extension](https://devtools.vuejs.org/) and type this into the console: `$vm.ctx.testRegisterUser()`
|
* Visit the `/account` page.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -26,6 +26,7 @@
|
|||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"core-js": "^3.26.1",
|
"core-js": "^3.26.1",
|
||||||
"dexie": "^3.2.2",
|
"dexie": "^3.2.2",
|
||||||
|
"dexie-export-import": "^4.0.6",
|
||||||
"did-jwt": "^6.9.0",
|
"did-jwt": "^6.9.0",
|
||||||
"ethereum-cryptography": "^1.1.2",
|
"ethereum-cryptography": "^1.1.2",
|
||||||
"ethereumjs-util": "^7.1.5",
|
"ethereumjs-util": "^7.1.5",
|
||||||
@@ -12187,6 +12188,14 @@
|
|||||||
"node": ">=6.0"
|
"node": ">=6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dexie-export-import": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/dexie-export-import/-/dexie-export-import-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-WFTSm/XB4MNHBZVQJTrWjWvqur7vfpx1mWEWMuTUB9zdW3FTXvkpm7SvsUX55r6y6wmJ3libwA5eRCbVUKmuTw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"dexie": "^2.0.4 || ^3.0.0 || ^4.0.1-alpha.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/did-jwt": {
|
"node_modules/did-jwt": {
|
||||||
"version": "6.9.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/did-jwt/-/did-jwt-6.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/did-jwt/-/did-jwt-6.9.0.tgz",
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
"class-transformer": "^0.5.1",
|
"class-transformer": "^0.5.1",
|
||||||
"core-js": "^3.26.1",
|
"core-js": "^3.26.1",
|
||||||
"dexie": "^3.2.2",
|
"dexie": "^3.2.2",
|
||||||
|
"dexie-export-import": "^4.0.6",
|
||||||
"did-jwt": "^6.9.0",
|
"did-jwt": "^6.9.0",
|
||||||
"ethereum-cryptography": "^1.1.2",
|
"ethereum-cryptography": "^1.1.2",
|
||||||
"ethereumjs-util": "^7.1.5",
|
"ethereumjs-util": "^7.1.5",
|
||||||
|
|||||||
15
project.yaml
15
project.yaml
@@ -11,11 +11,24 @@
|
|||||||
|
|
||||||
- replace user-affecting console.logs with error messages (eg. catches)
|
- replace user-affecting console.logs with error messages (eg. catches)
|
||||||
|
|
||||||
- contacts v1:
|
- contacts v1 :
|
||||||
|
- .2 show gives with new setting
|
||||||
|
- 01 show gives with confirmations
|
||||||
|
- .5 Add page to show seed.
|
||||||
|
- 01 Provide a way to import the non-sensitive data.
|
||||||
|
- 01 Provide way to share your contact info.
|
||||||
|
- .1 remove "scan new contact"
|
||||||
|
|
||||||
|
- contacts v+ :
|
||||||
- .5 make advanced "show/hide amounts" button into a nice UI toggle
|
- .5 make advanced "show/hide amounts" button into a nice UI toggle
|
||||||
- .2 show error to user when adding a duplicate contact
|
- .2 show error to user when adding a duplicate contact
|
||||||
- parse input more robustly (with CSV lib and not commas)
|
- parse input more robustly (with CSV lib and not commas)
|
||||||
|
|
||||||
|
- refactor UI :
|
||||||
|
- .5 Alerts show at the top and can be missed, eg. account data download
|
||||||
|
- 01 Code for "nav" tabs across the bottom is duplicated on each page.
|
||||||
|
- .2 Add "copied" feedback when they click "copy" on /account
|
||||||
|
|
||||||
- commit screen
|
- commit screen
|
||||||
|
|
||||||
- discover screen
|
- discover screen
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
import BaseDexie, { Table } from "dexie";
|
import BaseDexie, { Table } from "dexie";
|
||||||
import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon";
|
import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon";
|
||||||
|
import { Account, AccountsSchema } from "./tables/accounts";
|
||||||
|
import { Contact, ContactsSchema } from "./tables/contacts";
|
||||||
import {
|
import {
|
||||||
Account,
|
MASTER_SETTINGS_KEY,
|
||||||
AccountsSchema,
|
|
||||||
Contact,
|
|
||||||
ContactsSchema,
|
|
||||||
MASTER_SETTINGS,
|
|
||||||
Settings,
|
Settings,
|
||||||
SettingsSchema,
|
SettingsSchema,
|
||||||
} from "./tables";
|
} from "./tables/settings";
|
||||||
|
|
||||||
type AllTables = {
|
// a separate DB because the seed is super-sensitive data
|
||||||
|
type SensitiveTables = {
|
||||||
accounts: Table<Account>;
|
accounts: Table<Account>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type NonsensitiveTables = {
|
||||||
contacts: Table<Contact>;
|
contacts: Table<Contact>;
|
||||||
settings: Table<Settings>;
|
settings: Table<Settings>;
|
||||||
};
|
};
|
||||||
@@ -24,15 +26,14 @@ type AllTables = {
|
|||||||
*
|
*
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
type DexieTables = AllTables;
|
export type SensitiveDexie<T extends unknown = SensitiveTables> = BaseDexie & T;
|
||||||
export type Dexie<T extends unknown = DexieTables> = BaseDexie & T;
|
export const accountsDB = new BaseDexie("KickStartAccounts") as SensitiveDexie;
|
||||||
export const db = new BaseDexie("KickStart") as Dexie;
|
const SensitiveSchemas = Object.assign({}, AccountsSchema);
|
||||||
const AllSchemas = Object.assign(
|
|
||||||
{},
|
export type NonsensitiveDexie<T extends unknown = NonsensitiveTables> =
|
||||||
AccountsSchema,
|
BaseDexie & T;
|
||||||
ContactsSchema,
|
export const db = new BaseDexie("KickStart") as NonsensitiveDexie;
|
||||||
SettingsSchema
|
const NonsensitiveSchemas = Object.assign({}, ContactsSchema, SettingsSchema);
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needed to enable a special webpack setting to allow *await* below:
|
* Needed to enable a special webpack setting to allow *await* below:
|
||||||
@@ -48,11 +49,13 @@ if (localStorage.getItem("secret") == null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//console.log("IndexedDB Encryption Secret:", secret);
|
//console.log("IndexedDB Encryption Secret:", secret);
|
||||||
encrypted(db, { secretKey: secret });
|
encrypted(accountsDB, { secretKey: secret });
|
||||||
db.version(1).stores(AllSchemas);
|
accountsDB.version(1).stores(SensitiveSchemas);
|
||||||
|
|
||||||
|
db.version(1).stores(NonsensitiveSchemas);
|
||||||
|
|
||||||
// initialize, a la https://dexie.org/docs/Tutorial/Design#the-populate-event
|
// initialize, a la https://dexie.org/docs/Tutorial/Design#the-populate-event
|
||||||
db.on("populate", function () {
|
db.on("populate", function () {
|
||||||
// ensure there's an initial entry for settings
|
// ensure there's an initial entry for settings
|
||||||
db.settings.add({ id: MASTER_SETTINGS });
|
db.settings.add({ id: MASTER_SETTINGS_KEY });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,29 +13,3 @@ export const AccountsSchema = {
|
|||||||
accounts:
|
accounts:
|
||||||
"++id, dateCreated, derivationPath, $identity, $mnemonic, publicKeyHex",
|
"++id, dateCreated, derivationPath, $identity, $mnemonic, publicKeyHex",
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Contact {
|
|
||||||
did: string;
|
|
||||||
name?: string;
|
|
||||||
publicKeyBase64?: string;
|
|
||||||
seesMe?: boolean;
|
|
||||||
registered?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ContactsSchema = {
|
|
||||||
contacts: "++did, name, publicKeyBase64, registered, seesMe",
|
|
||||||
};
|
|
||||||
|
|
||||||
// a singleton
|
|
||||||
export type Settings = {
|
|
||||||
id: number;
|
|
||||||
firstName?: string;
|
|
||||||
lastName?: string;
|
|
||||||
showContactGivesInline?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SettingsSchema = {
|
|
||||||
settings: "id",
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MASTER_SETTINGS = 1;
|
|
||||||
11
src/db/tables/contacts.ts
Normal file
11
src/db/tables/contacts.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export interface Contact {
|
||||||
|
did: string;
|
||||||
|
name?: string;
|
||||||
|
publicKeyBase64?: string;
|
||||||
|
seesMe?: boolean;
|
||||||
|
registered?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ContactsSchema = {
|
||||||
|
contacts: "++did, name, publicKeyBase64, registered, seesMe",
|
||||||
|
};
|
||||||
13
src/db/tables/settings.ts
Normal file
13
src/db/tables/settings.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// a singleton
|
||||||
|
export type Settings = {
|
||||||
|
id: number;
|
||||||
|
firstName?: string;
|
||||||
|
lastName?: string;
|
||||||
|
showContactGivesInline?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SettingsSchema = {
|
||||||
|
settings: "id",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MASTER_SETTINGS_KEY = 1;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
|
||||||
import { db } from "@/db";
|
import { accountsDB } from "@/db";
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
@@ -8,8 +8,8 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "start" */ "../views/DiscoverView.vue"),
|
import(/* webpackChunkName: "start" */ "../views/DiscoverView.vue"),
|
||||||
beforeEnter: async (to, from, next) => {
|
beforeEnter: async (to, from, next) => {
|
||||||
await db.open();
|
await accountsDB.open();
|
||||||
const num_accounts = await db.accounts.count();
|
const num_accounts = await accountsDB.accounts.count();
|
||||||
if (num_accounts > 0) {
|
if (num_accounts > 0) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
@@ -63,6 +63,12 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
component: () =>
|
component: () =>
|
||||||
import(/* webpackChunkName: "discover" */ "../views/DiscoverView.vue"),
|
import(/* webpackChunkName: "discover" */ "../views/DiscoverView.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/help",
|
||||||
|
name: "help",
|
||||||
|
component: () =>
|
||||||
|
import(/* webpackChunkName: "help" */ "../views/HelpView.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/import-account",
|
path: "/import-account",
|
||||||
name: "import-account",
|
name: "import-account",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import * as didJwt from "did-jwt";
|
import * as didJwt from "did-jwt";
|
||||||
import { AppString } from "@/constants/app";
|
import { AppString } from "@/constants/app";
|
||||||
import { db } from "../db";
|
import { accountsDB } from "../db";
|
||||||
import { SERVICE_ID } from "../libs/veramo/setup";
|
import { SERVICE_ID } from "../libs/veramo/setup";
|
||||||
import { deriveAddress, newIdentifier } from "../libs/crypto";
|
import { deriveAddress, newIdentifier } from "../libs/crypto";
|
||||||
|
|
||||||
@@ -13,8 +13,8 @@ export async function testServerRegisterUser() {
|
|||||||
|
|
||||||
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
|
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
|
||||||
|
|
||||||
await db.open();
|
await accountsDB.open();
|
||||||
const accounts = await db.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
const thisIdentity = JSON.parse(accounts[0].identity);
|
const thisIdentity = JSON.parse(accounts[0].identity);
|
||||||
|
|
||||||
// Make a claim
|
// Make a claim
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<fa icon="folder-open" class="fa-fw"></fa>
|
<fa icon="folder-open" class="fa-fw"></fa>
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<!-- Commitments -->
|
<!-- Contacts -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'contacts' }"
|
:to="{ name: 'contacts' }"
|
||||||
@@ -54,6 +54,18 @@
|
|||||||
Your Identity
|
Your Identity
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
<div class="flex justify-between py-2">
|
||||||
|
<span />
|
||||||
|
<span>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'help' }"
|
||||||
|
class="text-xs uppercase bg-blue-500 text-white px-1.5 py-1 rounded-md ml-1"
|
||||||
|
>
|
||||||
|
Help
|
||||||
|
</router-link>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Friend referral requirement notice -->
|
<!-- Friend referral requirement notice -->
|
||||||
<div
|
<div
|
||||||
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
|
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
|
||||||
@@ -122,29 +134,34 @@
|
|||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'new-edit-account' }"
|
:to="{ name: 'new-edit-account' }"
|
||||||
class="block text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-8"
|
class="block text-center text-lg font-bold uppercase bg-blue-600 text-white px-2 py-3 rounded-md mb-8"
|
||||||
>Edit Identity</router-link
|
|
||||||
>
|
>
|
||||||
|
Edit Identity
|
||||||
|
</router-link>
|
||||||
|
|
||||||
<h3 class="text-sm uppercase font-semibold mb-3">Contact Actions</h3>
|
<h3 class="text-sm uppercase font-semibold mb-3">Contact Actions</h3>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="contact-scan.html"
|
href="contact-scan.html"
|
||||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6"
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6"
|
||||||
>Scan New Contact</a
|
|
||||||
>
|
>
|
||||||
|
Scan New Contact
|
||||||
|
</a>
|
||||||
|
|
||||||
<h3 class="text-sm uppercase font-semibold mb-3">Identity Actions</h3>
|
<h3 class="text-sm uppercase font-semibold mb-3">Data</h3>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href=""
|
href=""
|
||||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
|
||||||
>Backup Seed</a
|
|
||||||
>
|
>
|
||||||
|
Backup Identifier Seed
|
||||||
|
</a>
|
||||||
<a
|
<a
|
||||||
href=""
|
|
||||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6"
|
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6"
|
||||||
>Backup Other Data</a
|
@click="exportDatabase()"
|
||||||
>
|
>
|
||||||
|
Download Settings & Contacts (excluding Identifier Data)
|
||||||
|
</a>
|
||||||
|
<a ref="downloadLink" />
|
||||||
|
|
||||||
<!-- QR code popup -->
|
<!-- QR code popup -->
|
||||||
<dialog id="dlgQR" class="backdrop:bg-black/75 rounded-md">
|
<dialog id="dlgQR" class="backdrop:bg-black/75 rounded-md">
|
||||||
@@ -198,10 +215,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import "dexie-export-import";
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
import { db } from "@/db";
|
import { db, accountsDB } from "@/db";
|
||||||
import { MASTER_SETTINGS } from "@/db/tables";
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
||||||
//import { testServerRegisterUser } from "../test";
|
//import { testServerRegisterUser } from "../test";
|
||||||
|
|
||||||
@@ -209,9 +227,6 @@ import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
|||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class AccountViewView extends Vue {
|
export default class AccountViewView extends Vue {
|
||||||
// This registers current user in vue plugin with: $vm.ctx.testRegisterUser()
|
|
||||||
//testRegisterUser = testServerRegisterUser;
|
|
||||||
|
|
||||||
address = "";
|
address = "";
|
||||||
firstName = "";
|
firstName = "";
|
||||||
lastName = "";
|
lastName = "";
|
||||||
@@ -224,16 +239,23 @@ export default class AccountViewView extends Vue {
|
|||||||
|
|
||||||
// 'created' hook runs when the Vue instance is first created
|
// 'created' hook runs when the Vue instance is first created
|
||||||
async created() {
|
async created() {
|
||||||
await db.open();
|
// Uncomment to register this user on the test server.
|
||||||
|
// To manage within the vue devtools browser extension https://devtools.vuejs.org/
|
||||||
|
// assign this to a class variable, eg. "registerThisUser = testServerRegisterUser",
|
||||||
|
// select a component in the extension, and enter in the console: $vm.ctx.registerThisUser()
|
||||||
|
//testServerRegisterUser();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const settings = await db.settings.get(MASTER_SETTINGS);
|
await db.open();
|
||||||
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||||
if (settings) {
|
if (settings) {
|
||||||
this.firstName = settings.firstName || "";
|
this.firstName = settings.firstName || "";
|
||||||
this.lastName = settings.lastName || "";
|
this.lastName = settings.lastName || "";
|
||||||
this.showContactGives = !!settings.showContactGivesInline;
|
this.showContactGives = !!settings.showContactGivesInline;
|
||||||
}
|
}
|
||||||
|
|
||||||
const numAccounts = await db.accounts.count();
|
await accountsDB.open();
|
||||||
|
const numAccounts = await accountsDB.accounts.count();
|
||||||
if (numAccounts === 0) {
|
if (numAccounts === 0) {
|
||||||
let privateHex = "";
|
let privateHex = "";
|
||||||
this.mnemonic = generateSeed();
|
this.mnemonic = generateSeed();
|
||||||
@@ -246,7 +268,7 @@ export default class AccountViewView extends Vue {
|
|||||||
privateHex,
|
privateHex,
|
||||||
this.derivationPath
|
this.derivationPath
|
||||||
);
|
);
|
||||||
await db.accounts.add({
|
await accountsDB.accounts.add({
|
||||||
dateCreated: new Date().toISOString(),
|
dateCreated: new Date().toISOString(),
|
||||||
derivationPath: this.derivationPath,
|
derivationPath: this.derivationPath,
|
||||||
identity: JSON.stringify(newId),
|
identity: JSON.stringify(newId),
|
||||||
@@ -254,6 +276,12 @@ export default class AccountViewView extends Vue {
|
|||||||
publicKeyHex: newId.keys[0].publicKeyHex,
|
publicKeyHex: newId.keys[0].publicKeyHex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
|
const identity = JSON.parse(accounts[0].identity);
|
||||||
|
this.address = identity.did;
|
||||||
|
this.publicHex = identity.keys[0].publicKeyHex;
|
||||||
|
this.derivationPath = identity.keys[0].meta.derivationPath;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.alertMessage =
|
this.alertMessage =
|
||||||
"Clear your cache and start over (after data backup). See console log for more info.";
|
"Clear your cache and start over (after data backup). See console log for more info.";
|
||||||
@@ -261,21 +289,15 @@ export default class AccountViewView extends Vue {
|
|||||||
this.alertTitle = "Error Creating Account";
|
this.alertTitle = "Error Creating Account";
|
||||||
this.isAlertVisible = true;
|
this.isAlertVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const accounts = await db.accounts.toArray();
|
|
||||||
const identity = JSON.parse(accounts[0].identity);
|
|
||||||
this.address = identity.did;
|
|
||||||
this.publicHex = identity.keys[0].publicKeyHex;
|
|
||||||
this.derivationPath = identity.keys[0].meta.derivationPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async toggleShowContactAmounts() {
|
public async toggleShowContactAmounts() {
|
||||||
this.showContactGives = !this.showContactGives;
|
this.showContactGives = !this.showContactGives;
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await db.open();
|
||||||
const settings = await db.settings.get(MASTER_SETTINGS);
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||||
if (settings) {
|
if (settings) {
|
||||||
db.settings.update(MASTER_SETTINGS, {
|
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
showContactGivesInline: this.showContactGives,
|
showContactGivesInline: this.showContactGives,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -295,6 +317,29 @@ export default class AccountViewView extends Vue {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async exportDatabase() {
|
||||||
|
try {
|
||||||
|
const blob = await db.export({ prettyJson: true });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
const downloadAnchor = this.$refs.downloadLink as HTMLAnchorElement;
|
||||||
|
downloadAnchor.href = url;
|
||||||
|
downloadAnchor.download = db.name + "-backup.json";
|
||||||
|
downloadAnchor.click();
|
||||||
|
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
|
||||||
|
this.alertTitle = "Download Started";
|
||||||
|
this.alertMessage = "See your downloads directory for the backup.";
|
||||||
|
this.isAlertVisible = true;
|
||||||
|
} catch (error) {
|
||||||
|
this.alertTitle = "Export Error";
|
||||||
|
this.alertMessage = "See console logs for more info.";
|
||||||
|
this.isAlertVisible = true;
|
||||||
|
console.error("Export Error:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
alertMessage = "";
|
alertMessage = "";
|
||||||
alertTitle = "";
|
alertTitle = "";
|
||||||
isAlertVisible = false;
|
isAlertVisible = false;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
><fa icon="folder-open" class="fa-fw"></fa
|
><fa icon="folder-open" class="fa-fw"></fa
|
||||||
></router-link>
|
></router-link>
|
||||||
</li>
|
</li>
|
||||||
<!-- Commitments -->
|
<!-- Contacts -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'contacts' }"
|
:to="{ name: 'contacts' }"
|
||||||
@@ -140,8 +140,8 @@ import { Options, Vue } from "vue-class-component";
|
|||||||
import { AppString } from "@/constants/app";
|
import { AppString } from "@/constants/app";
|
||||||
import { accessToken, SimpleSigner } from "@/libs/crypto";
|
import { accessToken, SimpleSigner } from "@/libs/crypto";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
import { db } from "../db";
|
import { accountsDB, db } from "../db";
|
||||||
import { Contact } from "../db/tables";
|
import { Contact } from "../db/tables/contacts";
|
||||||
|
|
||||||
export interface GiveVerifiableCredential {
|
export interface GiveVerifiableCredential {
|
||||||
"@context": string;
|
"@context": string;
|
||||||
@@ -169,9 +169,11 @@ export default class ContactsView extends Vue {
|
|||||||
|
|
||||||
// 'created' hook runs when the Vue instance is first created
|
// 'created' hook runs when the Vue instance is first created
|
||||||
async created() {
|
async created() {
|
||||||
await db.open();
|
await accountsDB.open();
|
||||||
const accounts = await db.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
this.identity = JSON.parse(accounts[0].identity);
|
this.identity = JSON.parse(accounts[0].identity);
|
||||||
|
|
||||||
|
await db.open();
|
||||||
this.contacts = await db.contacts.toArray();
|
this.contacts = await db.contacts.toArray();
|
||||||
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
><fa icon="folder-open" class="fa-fw"></fa
|
><fa icon="folder-open" class="fa-fw"></fa
|
||||||
></router-link>
|
></router-link>
|
||||||
</li>
|
</li>
|
||||||
<!-- Commitments -->
|
<!-- Contacts -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'contacts' }"
|
:to="{ name: 'contacts' }"
|
||||||
|
|||||||
139
src/views/HelpView.vue
Normal file
139
src/views/HelpView.vue
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<!-- QUICK NAV -->
|
||||||
|
<nav id="QuickNav" class="fixed bottom-0 left-0 right-0 bg-slate-200">
|
||||||
|
<ul class="flex text-2xl p-2 gap-2">
|
||||||
|
<!-- Home Feed -->
|
||||||
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
|
<router-link :to="{ name: 'home' }" class="block text-center py-3 px-1">
|
||||||
|
<fa icon="house-chimney" class="fa-fw"></fa>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<!-- Search -->
|
||||||
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'discover' }"
|
||||||
|
class="block text-center py-3 px-1"
|
||||||
|
>
|
||||||
|
<fa icon="magnifying-glass" class="fa-fw"></fa>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<!-- Projects -->
|
||||||
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'projects' }"
|
||||||
|
class="block text-center py-3 px-1"
|
||||||
|
>
|
||||||
|
<fa icon="folder-open" class="fa-fw"></fa>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<!-- Contacts -->
|
||||||
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'contacts' }"
|
||||||
|
class="block text-center py-3 px-1"
|
||||||
|
>
|
||||||
|
<fa icon="users" class="fa-fw"></fa>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
<!-- Profile -->
|
||||||
|
<li class="basis-1/5 rounded-md text-slate-400">
|
||||||
|
<router-link
|
||||||
|
:to="{ name: 'account' }"
|
||||||
|
class="block text-center py-3 px-1"
|
||||||
|
>
|
||||||
|
<fa icon="circle-user" class="fa-fw"></fa>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- CONTENT -->
|
||||||
|
<section id="Content" class="p-6 pb-24">
|
||||||
|
<!-- Heading -->
|
||||||
|
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
|
||||||
|
Help
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 class="text-xl font-semibold">Introduction</h2>
|
||||||
|
<p>
|
||||||
|
This app is a window into data that you and your friends own, focused on
|
||||||
|
gifts and collaboration.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-xl font-semibold">How do I backup all my data?</h2>
|
||||||
|
<p>
|
||||||
|
There are two parts to backup your data: the identifier secrets and the
|
||||||
|
other data such as settings, contacts, etc.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="px-4">
|
||||||
|
<h2 class="text-xl font-semibold">
|
||||||
|
How do I backup my identifier (secret) data?
|
||||||
|
</h2>
|
||||||
|
<ul class="list-disc list-inside">
|
||||||
|
<li>
|
||||||
|
Go to Your Identity <fa icon="circle-user" class="fa-fw" /> page.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Click on "Backup Identifier Seed" and follow the instructions.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-xl font-semibold">
|
||||||
|
How do I backup my other (non-identifier-secret) data?
|
||||||
|
</h2>
|
||||||
|
<ul class="list-disc list-inside">
|
||||||
|
<li>
|
||||||
|
Go to Your Identity <fa icon="circle-user" class="fa-fw" /> page.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Click on "Download Settings...". That will save a file to your
|
||||||
|
downloads folder. That is your backup, so put it someplace where you
|
||||||
|
won't lose it.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-xl font-semibold">How do I restore my data?</h2>
|
||||||
|
<p>
|
||||||
|
There are two parts to restore your data: the identity secrets and the
|
||||||
|
other data such as settings, contacts, etc.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="px-4">
|
||||||
|
<h2 class="text-xl font-semibold">
|
||||||
|
How do I restore my identifier (secret) data?
|
||||||
|
</h2>
|
||||||
|
<ul class="list-disc list-inside">
|
||||||
|
<li>
|
||||||
|
You only have one identifier at a time. If you have an identifier on
|
||||||
|
Your Identity <fa icon="circle-user" class="fa-fw" /> page, you'll
|
||||||
|
need to clear it out;
|
||||||
|
<a
|
||||||
|
href="https://www.lifewire.com/how-to-clear-cache-2617980"
|
||||||
|
class="text-blue-500"
|
||||||
|
>
|
||||||
|
here are some helpful instructions.
|
||||||
|
</a>
|
||||||
|
But beware! This will also clear out your settings and contact data,
|
||||||
|
so be sure to back that up first.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<router-link class="text-blue-500" to="/">
|
||||||
|
Go to the start
|
||||||
|
</router-link>
|
||||||
|
and choose "Yes" to enter the identity you backed up.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-xl font-semibold">
|
||||||
|
How do I restore my other (non-identifier-secret) data?
|
||||||
|
</h2>
|
||||||
|
<ul class="list-disc list-inside">
|
||||||
|
<li>Make sure you have your backup file (above), then contact us.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { deriveAddress, newIdentifier } from "../libs/crypto";
|
import { deriveAddress, newIdentifier } from "../libs/crypto";
|
||||||
import { db } from "@/db";
|
import { accountsDB } from "@/db";
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
@@ -75,10 +75,10 @@ export default class ImportAccountView extends Vue {
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await accountsDB.open();
|
||||||
const num_accounts = await db.accounts.count();
|
const num_accounts = await accountsDB.accounts.count();
|
||||||
if (num_accounts === 0) {
|
if (num_accounts === 0) {
|
||||||
await db.accounts.add({
|
await accountsDB.accounts.add({
|
||||||
dateCreated: new Date().toISOString(),
|
dateCreated: new Date().toISOString(),
|
||||||
derivationPath: this.derivationPath,
|
derivationPath: this.derivationPath,
|
||||||
identity: JSON.stringify(newId),
|
identity: JSON.stringify(newId),
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { db } from "@/db";
|
import { db } from "@/db";
|
||||||
import { MASTER_SETTINGS } from "@/db/tables";
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
@@ -69,7 +69,7 @@ export default class NewEditAccountView extends Vue {
|
|||||||
// 'created' hook runs when the Vue instance is first created
|
// 'created' hook runs when the Vue instance is first created
|
||||||
async created() {
|
async created() {
|
||||||
await db.open();
|
await db.open();
|
||||||
const settings = await db.settings.get(MASTER_SETTINGS);
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||||
if (settings) {
|
if (settings) {
|
||||||
this.firstName = settings.firstName || "";
|
this.firstName = settings.firstName || "";
|
||||||
this.lastName = settings.lastName || "";
|
this.lastName = settings.lastName || "";
|
||||||
@@ -77,7 +77,7 @@ export default class NewEditAccountView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClickSaveChanges() {
|
onClickSaveChanges() {
|
||||||
db.settings.update(MASTER_SETTINGS, {
|
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
firstName: this.firstName,
|
firstName: this.firstName,
|
||||||
lastName: this.lastName,
|
lastName: this.lastName,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { AppString } from "@/constants/app";
|
import { AppString } from "@/constants/app";
|
||||||
import { db } from "../db";
|
import { accountsDB } from "../db";
|
||||||
import { accessToken, SimpleSigner } from "@/libs/crypto";
|
import { accessToken, SimpleSigner } from "@/libs/crypto";
|
||||||
import * as didJwt from "did-jwt";
|
import * as didJwt from "did-jwt";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
@@ -112,12 +112,12 @@ export default class NewEditProjectView extends Vue {
|
|||||||
if (this.projectId === "") {
|
if (this.projectId === "") {
|
||||||
console.log("This is a new project");
|
console.log("This is a new project");
|
||||||
} else {
|
} else {
|
||||||
await db.open();
|
await accountsDB.open();
|
||||||
const num_accounts = await db.accounts.count();
|
const num_accounts = await accountsDB.accounts.count();
|
||||||
if (num_accounts === 0) {
|
if (num_accounts === 0) {
|
||||||
console.log("Problem! Should have a profile!");
|
console.log("Problem! Should have a profile!");
|
||||||
} else {
|
} else {
|
||||||
const accounts = await db.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
const identity = JSON.parse(accounts[0].identity);
|
const identity = JSON.parse(accounts[0].identity);
|
||||||
this.LoadProject(identity);
|
this.LoadProject(identity);
|
||||||
}
|
}
|
||||||
@@ -126,8 +126,10 @@ export default class NewEditProjectView extends Vue {
|
|||||||
|
|
||||||
async LoadProject(identity: IIdentifier) {
|
async LoadProject(identity: IIdentifier) {
|
||||||
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
||||||
// eslint-disable-next-line prettier/prettier
|
const url =
|
||||||
const url = endorserApiServer + "/api/claim/byHandle/" + encodeURIComponent(this.projectId);
|
endorserApiServer +
|
||||||
|
"/api/claim/byHandle/" +
|
||||||
|
encodeURIComponent(this.projectId);
|
||||||
const token = await accessToken(identity);
|
const token = await accessToken(identity);
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -161,7 +163,6 @@ export default class NewEditProjectView extends Vue {
|
|||||||
}
|
}
|
||||||
// Make a payload for the claim
|
// Make a payload for the claim
|
||||||
const vcPayload = {
|
const vcPayload = {
|
||||||
sub: "PlanAction",
|
|
||||||
vc: {
|
vc: {
|
||||||
"@context": ["https://www.w3.org/2018/credentials/v1"],
|
"@context": ["https://www.w3.org/2018/credentials/v1"],
|
||||||
type: ["VerifiableCredential"],
|
type: ["VerifiableCredential"],
|
||||||
@@ -169,12 +170,8 @@ export default class NewEditProjectView extends Vue {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
// create a signature using private key of identity
|
// create a signature using private key of identity
|
||||||
if (
|
if (identity.keys[0].privateKeyHex != null) {
|
||||||
identity.keys[0].privateKeyHex !== "undefined" &&
|
const privateKeyHex: string = identity.keys[0].privateKeyHex;
|
||||||
identity.keys[0].privateKeyHex !== null
|
|
||||||
) {
|
|
||||||
// eslint-disable-next-line
|
|
||||||
const privateKeyHex: string = identity.keys[0].privateKeyHex!;
|
|
||||||
const signer = await SimpleSigner(privateKeyHex);
|
const signer = await SimpleSigner(privateKeyHex);
|
||||||
const alg = undefined;
|
const alg = undefined;
|
||||||
// create a JWT for the request
|
// create a JWT for the request
|
||||||
@@ -254,12 +251,12 @@ export default class NewEditProjectView extends Vue {
|
|||||||
public async onSaveProjectClick() {
|
public async onSaveProjectClick() {
|
||||||
this.isHiddenSave = true;
|
this.isHiddenSave = true;
|
||||||
this.isHiddenSpinner = false;
|
this.isHiddenSpinner = false;
|
||||||
await db.open();
|
await accountsDB.open();
|
||||||
const num_accounts = await db.accounts.count();
|
const num_accounts = await accountsDB.accounts.count();
|
||||||
if (num_accounts === 0) {
|
if (num_accounts === 0) {
|
||||||
console.log("Problem! Should have a profile!");
|
console.log("Problem! Should have a profile!");
|
||||||
} else {
|
} else {
|
||||||
const accounts = await db.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
const identity = JSON.parse(accounts[0].identity);
|
const identity = JSON.parse(accounts[0].identity);
|
||||||
this.SaveProject(identity);
|
this.SaveProject(identity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,11 @@
|
|||||||
><fa icon="folder-open" class="fa-fw"></fa
|
><fa icon="folder-open" class="fa-fw"></fa
|
||||||
></router-link>
|
></router-link>
|
||||||
</li>
|
</li>
|
||||||
<!-- Commitments -->
|
<!-- Contacts -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link :to="{ name: '' }" class="block text-center py-3 px-1"
|
<router-link
|
||||||
|
:to="{ name: 'contacts' }"
|
||||||
|
class="block text-center py-3 px-1"
|
||||||
><fa icon="hand" class="fa-fw"></fa
|
><fa icon="hand" class="fa-fw"></fa
|
||||||
></router-link>
|
></router-link>
|
||||||
</li>
|
</li>
|
||||||
@@ -146,7 +148,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
import { db } from "../db";
|
import { accountsDB } from "../db";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
import { AppString } from "@/constants/app";
|
import { AppString } from "@/constants/app";
|
||||||
import * as moment from "moment";
|
import * as moment from "moment";
|
||||||
@@ -224,12 +226,12 @@ export default class ProjectViewView extends Vue {
|
|||||||
|
|
||||||
// 'created' hook runs when the Vue instance is first created
|
// 'created' hook runs when the Vue instance is first created
|
||||||
async created() {
|
async created() {
|
||||||
await db.open();
|
await accountsDB.open();
|
||||||
const num_accounts = await db.accounts.count();
|
const num_accounts = await accountsDB.accounts.count();
|
||||||
if (num_accounts === 0) {
|
if (num_accounts === 0) {
|
||||||
console.log("Problem! Should have a profile!");
|
console.log("Problem! Should have a profile!");
|
||||||
} else {
|
} else {
|
||||||
const accounts = await db.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
const identity = JSON.parse(accounts[0].identity);
|
const identity = JSON.parse(accounts[0].identity);
|
||||||
this.LoadProject(identity);
|
this.LoadProject(identity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
><fa icon="folder-open" class="fa-fw"></fa
|
><fa icon="folder-open" class="fa-fw"></fa
|
||||||
></router-link>
|
></router-link>
|
||||||
</li>
|
</li>
|
||||||
<!-- Commitments -->
|
<!-- Contacts -->
|
||||||
<li class="basis-1/5 rounded-md text-slate-500">
|
<li class="basis-1/5 rounded-md text-slate-500">
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'contacts' }"
|
:to="{ name: 'contacts' }"
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Options, Vue } from "vue-class-component";
|
import { Options, Vue } from "vue-class-component";
|
||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
import { db } from "../db";
|
import { accountsDB } from "../db";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
import { AppString } from "@/constants/app";
|
import { AppString } from "@/constants/app";
|
||||||
|
|
||||||
@@ -155,12 +155,12 @@ export default class ProjectsView extends Vue {
|
|||||||
|
|
||||||
// 'created' hook runs when the Vue instance is first created
|
// 'created' hook runs when the Vue instance is first created
|
||||||
async created() {
|
async created() {
|
||||||
await db.open();
|
await accountsDB.open();
|
||||||
const num_accounts = await db.accounts.count();
|
const num_accounts = await accountsDB.accounts.count();
|
||||||
if (num_accounts === 0) {
|
if (num_accounts === 0) {
|
||||||
console.log("Problem! Should have a profile!");
|
console.log("Problem! Should have a profile!");
|
||||||
} else {
|
} else {
|
||||||
const accounts = await db.accounts.toArray();
|
const accounts = await accountsDB.accounts.toArray();
|
||||||
const identity = JSON.parse(accounts[0].identity);
|
const identity = JSON.parse(accounts[0].identity);
|
||||||
this.LoadProjects(identity);
|
this.LoadProjects(identity);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user