Compare commits

..

9 Commits

14 changed files with 238 additions and 86 deletions

View File

@@ -6,14 +6,13 @@
- replace user-affecting console.logs with error messages (eg. catches)
- contacts v1 :
- .2 warn about amounts when you cannot see them
- .1 add confirmation message when 'copy' succeeds
- .5 switch to prod server
- .1 remove 'copy' until it works
- .5 Add page to show seed.
- 01 Provide a way to import the non-sensitive data.
- 01 Provide way to share your contact info.
- .2 move all "identity" references to temporary account access
- .5 make deploy for give-only features
- .5 get 'copy' to work on account page
- contacts v+ :
- .5 make advanced "show/hide amounts" button into a nice UI toggle
@@ -42,3 +41,6 @@
- Peer DID
- DIDComm
- v video for multiple identities https://youtu.be/p8L87AeD76w
- v video for adding time to contacts https://youtu.be/7Yylczevp10

View File

@@ -0,0 +1,42 @@
<template>
<div ref="scrollContainer">
<slot />
<div ref="sentinel" style="height: 1px"></div>
</div>
</template>
<script lang="ts">
import { Component, Emit, Prop, Vue } from "vue-facing-decorator";
@Component
export default class InfiniteScroll extends Vue {
@Prop({ default: 100 })
readonly distance!: number;
private observer!: IntersectionObserver;
mounted() {
const options = {
root: this.$refs.scrollContainer as HTMLElement,
rootMargin: `0px 0px ${this.distance}px 0px`,
threshold: 1.0,
};
this.observer = new IntersectionObserver(this.handleIntersection, options);
this.observer.observe(this.$refs.sentinel as HTMLElement);
}
beforeUnmount() {
this.observer.disconnect();
}
@Emit("reached-bottom")
handleIntersection(entries: IntersectionObserverEntry[]) {
const entry = entries[0];
if (entry.isIntersecting) {
return true;
}
return false;
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>

View File

@@ -2,8 +2,11 @@
* Generic strings that could be used throughout the app.
*/
export enum AppString {
APP_NAME = "KickStart with Time",
VERSION = "0.1",
DEFAULT_ENDORSER_API_SERVER = "https://test.endorser.ch:8000",
//DEFAULT_ENDORSER_API_SERVER = "http://localhost:3000",
APP_NAME = "Kick-Start with Time",
PROD_ENDORSER_API_SERVER = "https://endorser.ch:3000",
TEST_ENDORSER_API_SERVER = "https://test.endorser.ch:8000",
LOCAL_ENDORSER_API_SERVER = "http://localhost:3000",
DEFAULT_ENDORSER_API_SERVER = TEST_ENDORSER_API_SERVER,
}

View File

@@ -7,6 +7,7 @@ import {
Settings,
SettingsSchema,
} from "./tables/settings";
import { AppString } from "@/constants/app";
// a separate DB because the seed is super-sensitive data
type SensitiveTables = {
@@ -57,5 +58,8 @@ db.version(1).stores(NonsensitiveSchemas);
// initialize, a la https://dexie.org/docs/Tutorial/Design#the-populate-event
db.on("populate", function () {
// ensure there's an initial entry for settings
db.settings.add({ id: MASTER_SETTINGS_KEY });
db.settings.add({
id: MASTER_SETTINGS_KEY,
apiServer: AppString.DEFAULT_ENDORSER_API_SERVER,
});
});

View File

@@ -2,6 +2,7 @@
export type Settings = {
id: number; // there's only one entry: MASTER_SETTINGS_KEY
activeDid?: string;
apiServer?: string;
firstName?: string;
lastName?: string;
showContactGivesInline?: boolean;

View File

@@ -21,6 +21,7 @@ import {
faEye,
faEyeSlash,
faFileLines,
faFloppyDisk,
faFolderOpen,
faHand,
faHouseChimney,
@@ -53,6 +54,7 @@ library.add(
faEye,
faEyeSlash,
faFileLines,
faFloppyDisk,
faFolderOpen,
faHand,
faHouseChimney,

View File

@@ -49,7 +49,8 @@ export async function testServerRegisterUser() {
// Make the xhr request payload
const payload = JSON.stringify({ jwtEncoded: vcJwt });
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const endorserApiServer =
settings?.apiServer || AppString.TEST_ENDORSER_API_SERVER;
const url = endorserApiServer + "/api/claim";
const headers = {
"Content-Type": "application/json",

View File

@@ -89,9 +89,15 @@
<div class="text-slate-500 text-sm font-bold">ID</div>
<div class="text-sm text-slate-500 flex justify-start items-center mb-1">
<code class="truncate">{{ activeDid }}</code>
<button @click="copy(activeDid)" class="ml-2">
<button
@click="
doCopyTwoSecRedo(activeDid, () => (showDidCopy = !showDidCopy))
"
class="ml-2"
>
<fa icon="copy" class="text-slate-400 fa-fw"></fa>
</button>
<span v-show="showDidCopy">Copied!</span>
<span class="whitespace-nowrap ml-4">
<button
class="text-xs uppercase bg-slate-500 text-white px-1.5 py-1 rounded-md"
@@ -109,25 +115,43 @@
<div class="text-slate-500 text-sm font-bold">Public Key (base 64)</div>
<div class="text-sm text-slate-500 flex justify-start items-center mb-1">
<code class="truncate">{{ publicBase64 }}</code>
<button @click="copy(publicBase64)" class="ml-2">
<button
@click="
doCopyTwoSecRedo(publicBase64, () => (showB64Copy = !showB64Copy))
"
class="ml-2"
>
<fa icon="copy" class="text-slate-400 fa-fw"></fa>
</button>
<span v-show="showB64Copy">Copied!</span>
</div>
<div class="text-slate-500 text-sm font-bold">Public Key (hex)</div>
<div class="text-sm text-slate-500 flex justify-start items-center mb-1">
<code class="truncate">{{ publicHex }}</code>
<button @click="copy(publicHex)" class="ml-2">
<button
@click="
doCopyTwoSecRedo(publicHex, () => (showPubCopy = !showPubCopy))
"
class="ml-2"
>
<fa icon="copy" class="text-slate-400 fa-fw"></fa>
</button>
<span v-show="showPubCopy">Copied!</span>
</div>
<div class="text-slate-500 text-sm font-bold">Derivation Path</div>
<div class="text-sm text-slate-500 flex justify-start items-center mb-1">
<code class="truncate">{{ derivationPath }}</code>
<button @click="copy(derivationPath)" class="ml-2">
<button
@click="
doCopyTwoSecRedo(derivationPath, () => (showDerCopy = !showDerCopy))
"
class="ml-2"
>
<fa icon="copy" class="text-slate-400 fa-fw"></fa>
</button>
<span v-show="showDerCopy">Copied!</span>
</div>
</div>
@@ -206,7 +230,7 @@
<div class="flex py-2">
<button class="text-center text-md text-blue-500" @click="checkLimits()">
Check Registration and Claim Limits
Check Limits
</button>
<div v-if="!!limits?.nextWeekBeginDateTime" class="px-9">
<span class="font-bold">Rate Limits</span>
@@ -224,6 +248,40 @@
</div>
</div>
<div class="flex py-2">
Claim Server
<input
type="text"
class="block w-full rounded border border-slate-400 px-3 py-2"
v-model="apiServerInput"
/>
<button
v-if="apiServerInput != apiServer"
class="px-4 rounded bg-slate-200 border border-slate-400"
@click="onClickSaveApiServer()"
>
<fa icon="floppy-disk" class="fa-fw"></fa>
</button>
<button
class="px-4 rounded bg-slate-200 border border-slate-400"
@click="setApiServerInput(Constants.PROD_ENDORSER_API_SERVER)"
>
Use Prod
</button>
<button
class="px-4 rounded bg-slate-200 border border-slate-400"
@click="setApiServerInput(Constants.TEST_ENDORSER_API_SERVER)"
>
Use Test
</button>
<button
class="px-4 rounded bg-slate-200 border border-slate-400"
@click="setApiServerInput(Constants.LOCAL_ENDORSER_API_SERVER)"
>
Use Local
</button>
</div>
<div v-if="numAccounts > 0" class="flex py-2">
Switch Account
<span v-for="accountNum in numAccounts" :key="accountNum">
@@ -278,7 +336,11 @@ interface RateLimits {
@Component
export default class AccountViewView extends Vue {
Constants = AppString;
activeDid = "";
apiServer = "";
apiServerInput = "";
derivationPath = "";
firstName = "";
lastName = "";
@@ -288,7 +350,18 @@ export default class AccountViewView extends Vue {
limits: RateLimits | null = null;
showContactGives = false;
copy = useClipboard().copy;
showDidCopy = false;
showDerCopy = false;
showB64Copy = false;
showPubCopy = false;
// call fn, copy text to the clipboard, then redo fn after 2 seconds
doCopyTwoSecRedo(text, fn) {
fn();
useClipboard()
.copy(text)
.then(() => setTimeout(fn, 2000));
}
handleChange() {
this.showContactGives = !this.showContactGives;
@@ -306,11 +379,12 @@ export default class AccountViewView extends Vue {
// 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 {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
this.activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || "";
this.apiServerInput = settings?.apiServer || "";
this.firstName = settings?.firstName || "";
this.lastName = settings?.lastName || "";
this.showContactGives = !!settings?.showContactGivesInline;
@@ -399,8 +473,7 @@ export default class AccountViewView extends Vue {
}
async checkLimits() {
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url = endorserApiServer + "/api/report/rateLimits";
const url = this.apiServer + "/api/report/rateLimits";
await accountsDB.open();
const accounts = await accountsDB.accounts.toArray();
const account = R.find((acc) => acc.did === this.activeDid, accounts);
@@ -457,6 +530,18 @@ export default class AccountViewView extends Vue {
};
}
async onClickSaveApiServer() {
await db.open();
db.settings.update(MASTER_SETTINGS_KEY, {
apiServer: this.apiServerInput,
});
this.apiServer = this.apiServerInput;
}
setApiServerInput(value) {
this.apiServerInput = value;
}
alertMessage = "";
alertTitle = "";
isAlertVisible = false;

View File

@@ -72,7 +72,7 @@
<fa icon="circle-check" class="text-green-600 fa-fw ml-1" />
<span class="tooltiptext">Confirmed</span>
</span>
<button v-else class="tooltip" @click="confirmGiven(record)">
<button v-else class="tooltip" @click="confirm(record)">
<fa icon="circle" class="text-blue-600 fa-fw ml-1" />
<span class="tooltiptext">Unconfirmed</span>
</button>
@@ -144,6 +144,7 @@ import { AxiosError } from "axios";
@Options({})
export default class ContactsView extends Vue {
activeDid = "";
apiServer = "";
contact: Contact | null = null;
giveRecords: Array<GiveServerRecord> = [];
@@ -155,6 +156,7 @@ export default class ContactsView extends Vue {
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
this.activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || "";
if (this.activeDid && this.contact) {
this.loadGives(this.activeDid, this.contact);
@@ -168,14 +170,12 @@ export default class ContactsView extends Vue {
const account = R.find((acc) => acc.did === activeDid, accounts);
const identity = JSON.parse(account?.identity || "undefined");
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
// load all the time I have given to them
try {
let result = [];
const url =
endorserApiServer +
this.apiServer +
"/api/v2/report/gives?agentDid=" +
encodeURIComponent(identity.did) +
"&recipientDid=" +
@@ -201,7 +201,7 @@ export default class ContactsView extends Vue {
}
const url2 =
endorserApiServer +
this.apiServer +
"/api/v2/report/gives?agentDid=" +
encodeURIComponent(contact.did) +
"&recipientDid=" +
@@ -239,11 +239,7 @@ export default class ContactsView extends Vue {
}
}
async confirmGiven(record: GiveServerRecord) {
if (!confirm("Are you sure you want to mark this as confirmed?")) {
return;
}
async confirm(record: GiveServerRecord) {
// Make claim
// I use clone here because otherwise it gets a Proxy object.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -286,8 +282,7 @@ export default class ContactsView extends Vue {
// Make the xhr request payload
const payload = JSON.stringify({ jwtEncoded: vcJwt });
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url = endorserApiServer + "/api/v2/claim";
const url = this.apiServer + "/api/v2/claim";
const token = await accessToken(identity);
const headers = {
"Content-Type": "application/json",

View File

@@ -49,6 +49,18 @@
Your Contacts
</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>
<!-- New Contact -->
<div class="mb-4 flex">
<input
@@ -165,12 +177,11 @@
: (givenByMeUnconfirmed[contact.did] || 0)
/* eslint-enable prettier/prettier */
}}
<span class="tooltiptext-left">
{{
givenByMeDescriptions[contact.did]
? "Most recently: " + givenByMeDescriptions[contact.did]
: "(None given yet.)"
}}
<span
v-if="givenByMeDescriptions[contact.did]"
class="tooltiptext-left"
>
{{ givenByMeDescriptions[contact.did] }}
</span>
<button
class="text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6"
@@ -191,12 +202,11 @@
: (givenToMeUnconfirmed[contact.did] || 0)
/* eslint-enable prettier/prettier */
}}
<span class="tooltiptext-left">
{{
givenToMeDescriptions[contact.did]
? "Most recently: " + givenToMeDescriptions[contact.did]
: "(None received yet.)"
}}
<span
v-if="givenToMeDescriptions[contact.did]"
class="tooltiptext-left"
>
{{ givenToMeDescriptions[contact.did] }}
</span>
<button
class="text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-6"
@@ -261,6 +271,7 @@ const Buffer = require("buffer/").Buffer;
})
export default class ContactsView extends Vue {
activeDid = "";
apiServer = "";
contacts: Array<Contact> = [];
contactInput = "";
// { "did:...": concatenated-descriptions } entry for each contact
@@ -286,6 +297,7 @@ export default class ContactsView extends Vue {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
this.activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || "";
this.showGiveNumbers = !!settings?.showContactGivesInline;
if (this.showGiveNumbers) {
@@ -311,12 +323,10 @@ export default class ContactsView extends Vue {
return;
}
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
// load all the time I have given
try {
const url =
endorserApiServer +
this.apiServer +
"/api/v2/report/gives?agentDid=" +
encodeURIComponent(identity.did);
const token = await accessToken(identity);
@@ -325,15 +335,15 @@ export default class ContactsView extends Vue {
Authorization: "Bearer " + token,
};
const resp = await this.axios.get(url, { headers });
console.log("All gifts you've given:", resp.data);
//console.log("All gifts you've given:", resp.data);
if (resp.status === 200) {
const contactDescriptions: Record<string, string> = {};
const contactConfirmed: Record<string, number> = {};
const contactUnconfirmed: Record<string, number> = {};
const allData: Array<GiveServerRecord> = resp.data.data;
for (const give of allData) {
if (give.unit == "HUR") {
const recipDid: string = give.recipientDid;
if (recipDid && give.unit == "HUR") {
if (give.amountConfirmed) {
const prevAmount = contactConfirmed[recipDid] || 0;
contactConfirmed[recipDid] = prevAmount + give.amount;
@@ -347,6 +357,7 @@ export default class ContactsView extends Vue {
}
}
}
//console.log("Done retrieving gives", contactConfirmed);
this.givenByMeDescriptions = contactDescriptions;
this.givenByMeConfirmed = contactConfirmed;
this.givenByMeUnconfirmed = contactUnconfirmed;
@@ -370,7 +381,7 @@ export default class ContactsView extends Vue {
// load all the time I have received
try {
const url =
endorserApiServer +
this.apiServer +
"/api/v2/report/gives?recipientDid=" +
encodeURIComponent(identity.did);
const token = await accessToken(identity);
@@ -379,7 +390,7 @@ export default class ContactsView extends Vue {
Authorization: "Bearer " + token,
};
const resp = await this.axios.get(url, { headers });
console.log("All gifts you've recieved:", resp.data);
//console.log("All gifts you've recieved:", resp.data);
if (resp.status === 200) {
const contactDescriptions: Record<string, string> = {};
const contactConfirmed: Record<string, number> = {};
@@ -509,8 +520,7 @@ export default class ContactsView extends Vue {
// Make the xhr request payload
const payload = JSON.stringify({ jwtEncoded: vcJwt });
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url = endorserApiServer + "/api/v2/claim";
const url = this.apiServer + "/api/v2/claim";
const token = await accessToken(identity);
const headers = {
"Content-Type": "application/json",
@@ -550,9 +560,8 @@ export default class ContactsView extends Vue {
}
async setVisibility(contact: Contact, visibility: boolean) {
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url =
endorserApiServer +
this.apiServer +
"/api/report/" +
(visibility ? "canSeeMe" : "cannotSeeMe");
await accountsDB.open();
@@ -590,9 +599,8 @@ export default class ContactsView extends Vue {
}
async checkVisibility(contact: Contact) {
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url =
endorserApiServer +
this.apiServer +
"/api/report/canDidExplicitlySeeMe?did=" +
encodeURIComponent(contact.did);
await accountsDB.open();
@@ -763,8 +771,7 @@ export default class ContactsView extends Vue {
// Make the xhr request payload
const payload = JSON.stringify({ jwtEncoded: vcJwt });
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url = endorserApiServer + "/api/v2/claim";
const url = this.apiServer + "/api/v2/claim";
const token = await accessToken(identity);
const headers = {
"Content-Type": "application/json",

View File

@@ -48,20 +48,20 @@
</nav>
<!-- CONTENT -->
<section id="Content" class="p-4 pb-24">
<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 py-4">Introduction</h2>
<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 py-4">How do I backup all my data?</h2>
<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.
@@ -73,7 +73,7 @@
</h2>
<ul class="list-disc list-inside">
<li>
Go to your Identity <fa icon="circle-user" class="fa-fw" /> page.
Go to Your Identity <fa icon="circle-user" class="fa-fw" /> page.
</li>
<li>
Click on "Backup Identifier Seed" and follow the instructions.
@@ -85,7 +85,7 @@
</h2>
<ul class="list-disc list-inside">
<li>
Go to your Identity <fa icon="circle-user" class="fa-fw" /> page.
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
@@ -95,7 +95,7 @@
</ul>
</div>
<h2 class="text-xl font-semibold py-4">How do I restore my data?</h2>
<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.
@@ -135,24 +135,30 @@
</ul>
</div>
<h2 class="text-xl font-semibold py-4">
How do I get registered to make claims?
</h2>
<p>
Contact a current user. They will be able to register you on their
Contacts <fa icon="users" class="fa-fw" /> screen. Note that they have a
limited number of registrations.
</p>
<h2 class="text-xl font-semibold py-4">
<h2 class="text-xl font-semibold">
How do I add someone to my contacts?
</h2>
<p>
Tell them to copy their ID, which typically starts with "did:ethr:...",
and send it to you. Go to the Contacts
<fa icon="users" class="fa-fw" /> page and enter that into the top form.
You may add a name by adding a comma followed by their name; you may
also add their public key by adding another comma followed by the key.
<fa icon="circle-user" class="fa-fw" /> page and enter that into the top
form. You may add a name by adding a comma followed by their name; you
may also add their public key by adding another comma followed by the
key.
</p>
<h2 class="text-xl font-semibold">
I know there is a record from someone, so why can't I see that info?
</h2>
<p>
Sometimes someone else has made claims -- meaning they have given time,
or recognized time given, or declared a project -- but you cannot see
anything associated with them. The reason may be because they have not
given you permission to see their information. Ask them to add you to
their contact list and make sure the eye next to your name is open like
this
<fa icon="eye" class="fa-fw" /> and not closed like this
<fa icon="eye-slash" class="fa-fw" />.
</p>
</div>
</section>

View File

@@ -101,6 +101,7 @@ interface VerifiableCredential {
})
export default class NewEditProjectView extends Vue {
activeDid = "";
apiServer = "";
projectName = "";
description = "";
errorMessage = "";
@@ -116,6 +117,7 @@ export default class NewEditProjectView extends Vue {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
this.activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || "";
if (this.projectId) {
await accountsDB.open();
@@ -132,9 +134,8 @@ export default class NewEditProjectView extends Vue {
}
async LoadProject(identity: IIdentifier) {
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url =
endorserApiServer +
this.apiServer +
"/api/claim/byHandle/" +
encodeURIComponent(this.projectId);
const token = await accessToken(identity);
@@ -191,8 +192,7 @@ export default class NewEditProjectView extends Vue {
// Make the xhr request payload
const payload = JSON.stringify({ jwtEncoded: vcJwt });
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url = endorserApiServer + "/api/v2/claim";
const url = this.apiServer + "/api/v2/claim";
const token = await accessToken(identity);
const headers = {
"Content-Type": "application/json",

View File

@@ -161,6 +161,7 @@ import { IIdentifier } from "@veramo/core";
components: {},
})
export default class ProjectViewView extends Vue {
apiServer = "";
expanded = false;
name = "";
description = "";
@@ -188,9 +189,10 @@ export default class ProjectViewView extends Vue {
}
async LoadProject(identity: IIdentifier) {
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
// eslint-disable-next-line prettier/prettier
const url = endorserApiServer + "/api/claim/byHandle/" + encodeURIComponent(this.projectId);
const url =
this.apiServer +
"/api/claim/byHandle/" +
encodeURIComponent(this.projectId);
const token = await accessToken(identity);
const headers = {
"Content-Type": "application/json",
@@ -232,6 +234,7 @@ export default class ProjectViewView extends Vue {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
const activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || "";
await accountsDB.open();
const num_accounts = await accountsDB.accounts.count();

View File

@@ -114,6 +114,7 @@ import { IIdentifier } from "@veramo/core";
components: {},
})
export default class ProjectsView extends Vue {
apiServer = "";
projects: { handleId: string; name: string; description: string }[] = [];
onClickLoadProject(id: string) {
@@ -127,8 +128,7 @@ export default class ProjectsView extends Vue {
}
async LoadProjects(identity: IIdentifier) {
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
const url = endorserApiServer + "/api/v2/report/plansByIssuer";
const url = this.apiServer + "/api/v2/report/plansByIssuer";
const token = await accessToken(identity);
const headers = {
"Content-Type": "application/json",
@@ -161,6 +161,7 @@ export default class ProjectsView extends Vue {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
const activeDid = settings?.activeDid || "";
this.apiServer = settings?.apiServer || "";
await accountsDB.open();
const num_accounts = await accountsDB.accounts.count();