Browse Source

feat: add contacts DB & page

tweaks
Trent Larson 2 years ago
parent
commit
4fdfe2f824
  1. 3
      project.yaml
  2. 18
      src/db/index.ts
  3. 6
      src/db/tables/accounts.ts
  4. 12
      src/db/tables/contacts.ts
  5. 6
      src/router/index.ts
  6. 121
      src/views/ContactsView.vue
  7. 1
      src/views/NewEditProjectView.vue
  8. 1
      src/views/ProjectViewView.vue
  9. 1
      src/views/ProjectsView.vue

3
project.yaml

@ -14,7 +14,8 @@
- replace user-affecting console.logs with error messages (eg. catches)
- contacts
- contacts v1:
- parse input correctly (with CSV lib and not commas)
- commit screen

18
src/db/index.ts

@ -1,6 +1,12 @@
import BaseDexie from "dexie";
import BaseDexie, { Table } from "dexie";
import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon";
import { accountsSchema, AccountsTable } from "./tables/accounts";
import { accountsSchema, Account } from "./tables/accounts";
import { contactsSchema, Contact } from "./tables/contacts";
type AllTables = {
accounts: Table<Account>;
contacts: Table<Contact>;
};
/**
* In order to make the next line be acceptable, the program needs to have its linter suppress a rule:
@ -10,10 +16,9 @@ import { accountsSchema, AccountsTable } from "./tables/accounts";
*
* https://9to5answer.com/how-to-bypass-warning-unexpected-any-specify-a-different-type-typescript-eslint-no-explicit-any
*/
type DexieTables = AccountsTable;
type DexieTables = AllTables;
export type Dexie<T extends unknown = DexieTables> = BaseDexie & T;
export const db = new BaseDexie("kickStarter") as Dexie;
const schema = Object.assign({}, accountsSchema);
/**
* Needed to enable a special webpack setting to allow *await* below:
@ -27,6 +32,7 @@ const secret =
if (localStorage.getItem("secret") == null) {
localStorage.setItem("secret", secret);
}
console.log(secret);
console.log("DB encryption secretKey:", secret);
encrypted(db, { secretKey: secret });
db.version(1).stores(schema);
db.version(1).stores(accountsSchema);
db.version(2).stores(contactsSchema);

6
src/db/tables/accounts.ts

@ -1,5 +1,3 @@
import { Table } from "dexie";
export type Account = {
id?: number;
publicKey: string;
@ -8,10 +6,6 @@ export type Account = {
dateCreated: number;
};
export type AccountsTable = {
accounts: Table<Account>;
};
// mark encrypted field by starting with a $ character
export const accountsSchema = {
accounts: "++id, publicKey, $mnemonic, $identity, dateCreated",

12
src/db/tables/contacts.ts

@ -0,0 +1,12 @@
export interface Contact {
did: string;
name?: string;
publicKeyBase64?: string;
seesMe?: boolean;
registered?: boolean;
}
// mark encrypted field by starting with a $ character
export const contactsSchema = {
contacts: "++did, name, publicKeyBase64, seesMe, registered",
};

6
src/router/index.ts

@ -43,6 +43,12 @@ const routes: Array<RouteRecordRaw> = [
/* webpackChunkName: "confirm-contact" */ "../views/ConfirmContactView.vue"
),
},
{
path: "/contacts",
name: "contacts",
component: () =>
import(/* webpackChunkName: "contacts" */ "../views/ContactsView.vue"),
},
{
path: "/scan-contact",
name: "scan-contact",

121
src/views/ContactsView.vue

@ -0,0 +1,121 @@
<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 bg-slate-400 text-white">
<router-link
:to="{ name: 'discover' }"
class="block text-center py-3 px-1"
><fa icon="magnifying-glass" 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="folder-open" class="fa-fw"></fa
></router-link>
</li>
<!-- Commitments -->
<li class="basis-1/5 rounded-md text-slate-500">
<router-link :to="{ name: '' }" class="block text-center py-3 px-1"
><fa icon="hand" class="fa-fw"></fa
></router-link>
</li>
<!-- Profile -->
<li class="basis-1/5 rounded-md text-slate-500">
<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>
<section id="Content" class="p-6 pb-24">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
My Contacts
</h1>
<!-- New Contact -->
<div class="mb-4 flex">
<input
type="text"
placeholder="DID, Name, Public Key"
class="block w-full rounded-l border border-r-0 border-slate-400 px-3 py-2"
v-model="contactInput"
/>
<button
class="px-4 rounded-r bg-slate-200 border border-l-0 border-slate-400"
@click="onClickNewContact()"
>
<fa icon="plus" class="fa-fw"></fa>
</button>
</div>
<!-- Results List -->
<ul class="">
<li
class="border-b border-slate-300"
v-for="contact in contacts"
:key="contact.did"
>
<div class="grow overflow-hidden">
<h2 class="text-base font-semibold">
{{ contact.name || "(no name)" }}
</h2>
<div class="text-sm truncate">{{ contact.did }}</div>
<div class="text-sm truncate">{{ contact.publicKeyBase64 }}</div>
</div>
</li>
</ul>
</section>
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
import { db } from "../db";
import { Contact } from "../db/tables/contacts.ts";
@Options({
components: {},
})
export default class ContactsView extends Vue {
contactInput = "";
contacts: Contact[] = [];
// 'created' hook runs when the Vue instance is first created
async created() {
await db.open();
this.contacts = await db.contacts.toArray();
}
async onClickNewContact(): void {
let did = this.contactInput;
let name, publicKeyBase64;
const commaPos1 = this.contactInput.indexOf(",");
if (commaPos1 > -1) {
did = this.contactInput.substring(0, commaPos1).trim();
name = this.contactInput.substring(commaPos1 + 1).trim();
const commaPos2 = this.contactInput.indexOf(",", commaPos1 + 1);
if (commaPos2 > -1) {
name = this.contactInput.substring(commaPos1 + 1, commaPos2).trim();
publicKeyBase64 = this.contactInput.substring(commaPos2 + 1).trim();
}
}
const newContact = { did, name, publicKeyBase64 };
await db.contacts.add(newContact);
this.contacts = this.contacts.concat([newContact]);
}
}
</script>

1
src/views/NewEditProjectView.vue

@ -107,6 +107,7 @@ export default class NewEditProjectView extends Vue {
isHiddenSave = false;
isHiddenSpinner = true;
// 'created' hook runs when the Vue instance is first created
async created() {
if (this.projectId === "") {
console.log("This is a new project");

1
src/views/ProjectViewView.vue

@ -222,6 +222,7 @@ export default class ProjectViewView extends Vue {
}
}
// 'created' hook runs when the Vue instance is first created
async created() {
await db.open();
const num_accounts = await db.accounts.count();

1
src/views/ProjectsView.vue

@ -151,6 +151,7 @@ export default class ProjectsView extends Vue {
}
}
// 'created' hook runs when the Vue instance is first created
async created() {
await db.open();
const num_accounts = await db.accounts.count();

Loading…
Cancel
Save