Browse Source

Considerable cleanup and merge

kb/add-usage-guide
Matthew Raymer 1 year ago
parent
commit
3b41014083
  1. 8
      src/views/ContactAmountsView.vue
  2. 4
      src/views/ContactQRScanShowView.vue
  3. 2
      src/views/ContactsView.vue
  4. 89
      src/views/DiscoverView.vue
  5. 90
      src/views/HomeView.vue
  6. 9
      src/views/NewEditProjectView.vue
  7. 44
      src/views/ProjectViewView.vue
  8. 4
      src/views/ProjectsView.vue

8
src/views/ContactAmountsView.vue

@ -172,7 +172,9 @@ export default class ContactsView extends Vue {
const account = R.find((acc) => acc.did === activeDid, accounts); const account = R.find((acc) => acc.did === activeDid, accounts);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
// load all the time I have given to them // load all the time I have given to them
@ -271,7 +273,9 @@ export default class ContactsView extends Vue {
const account = R.find((acc) => acc.did === this.activeDid, accounts); const account = R.find((acc) => acc.did === this.activeDid, accounts);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
if (identity.keys[0].privateKeyHex !== null) { if (identity.keys[0].privateKeyHex !== null) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion

4
src/views/ContactQRScanShowView.vue

@ -64,7 +64,9 @@ export default class ContactQRScanShow extends Vue {
} else { } else {
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
const publicKeyHex = identity.keys[0].publicKeyHex; const publicKeyHex = identity.keys[0].publicKeyHex;

2
src/views/ContactsView.vue

@ -212,8 +212,6 @@ import {
RegisterVerifiableCredential, RegisterVerifiableCredential,
SERVICE_ID, SERVICE_ID,
} from "@/libs/endorserServer"; } from "@/libs/endorserServer";
import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav";
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
const Buffer = require("buffer/").Buffer; const Buffer = require("buffer/").Buffer;

89
src/views/DiscoverView.vue

@ -30,6 +30,7 @@
<li> <li>
<a <a
href="#" href="#"
@click="searchLocal()"
class="inline-block py-3 rounded-t-lg border-b-2 active text-blue-600 border-blue-600 font-semibold" class="inline-block py-3 rounded-t-lg border-b-2 active text-blue-600 border-blue-600 font-semibold"
> >
Nearby Nearby
@ -123,7 +124,6 @@ import { Component, Vue } from "vue-facing-decorator";
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";
import * as R from "ramda";
import { accessToken } from "@/libs/crypto"; import { accessToken } from "@/libs/crypto";
import AlertMessage from "@/components/AlertMessage"; import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav"; import QuickNav from "@/components/QuickNav";
@ -135,6 +135,8 @@ export default class DiscoverView extends Vue {
activeDid = ""; activeDid = "";
apiServer = ""; apiServer = "";
searchTerms = ""; searchTerms = "";
alertMessage = "";
alertTitle = "";
async mounted() { async mounted() {
await db.open(); await db.open();
@ -143,53 +145,100 @@ export default class DiscoverView extends Vue {
this.apiServer = settings?.apiServer || ""; this.apiServer = settings?.apiServer || "";
} }
public async search() { public async buildHeaders() {
const headers = { "Content-Type": "application/json" }; const headers = { "Content-Type": "application/json" };
if (this.activeDid) { if (this.activeDid) {
await accountsDB.open(); await accountsDB.open();
const allAccounts = await accountsDB.accounts.toArray(); const allAccounts = await accountsDB.accounts.toArray();
const account = R.find((acc) => acc.did === this.activeDid, allAccounts); const account = allAccounts.find((acc) => acc.did === this.activeDid);
//console.log("about to parse from", this.activeDid, account?.identity);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
const token = await accessToken(identity);
headers["Authorization"] = "Bearer " + token; headers["Authorization"] = "Bearer " + (await accessToken(identity));
} else { } else {
// it's OK without auth... we just won't get any identifiers // it's OK without auth... we just won't get any identifiers
} }
return headers;
}
public async search() {
const claimContents = const claimContents =
"claimContents=" + encodeURIComponent(this.searchTerms); "claimContents=" + encodeURIComponent(this.searchTerms);
const claimType = "claimType=PlanAction"; const claimType = "claimType=PlanAction";
const queryParams = [claimContents, claimType].join("&"); const queryParams = [claimContents, claimType].join("&");
return fetch(this.apiServer + "/api/v2/report/claims?" + queryParams, {
try {
const response = await fetch(
this.apiServer + "/api/v2/report/claims?" + queryParams,
{
method: "GET", method: "GET",
headers: headers, headers: await this.buildHeaders(),
}) }
.then(async (response) => { );
if (response.status !== 200) { if (response.status !== 200) {
const details = await response.text(); const details = await response.text();
throw details; throw details;
} }
return response.json();
}) const results = await response.json();
.then((results) => {
if (results.data) { if (results.data) {
console.log(results.data); console.log("Plans found in that search:", results.data);
} else { } else {
throw JSON.stringify(results); throw JSON.stringify(results);
} }
}) } catch (e) {
.catch((e) => {
console.log("Error with feed load:", e); console.log("Error with feed load:", e);
this.alertMessage = this.alertMessage =
e.userMessage || "There was an error retrieving projects."; e.userMessage || "There was an error retrieving projects.";
this.alertTitle = "Error"; this.alertTitle = "Error";
}); }
} }
alertMessage = ""; public async searchLocal() {
alertTitle = ""; const claimContents =
"claimContents=" + encodeURIComponent(this.searchTerms);
const queryParams = [
claimContents,
"minLocLat=40.901000",
"maxLocLat=40.904000",
"westLocLon=-111.914000",
"eastLocLon=-111.909000",
].join("&");
try {
const response = await fetch(
this.apiServer + "/api/v2/report/plansByLocation?" + queryParams,
{
method: "GET",
headers: await this.buildHeaders(),
}
);
if (response.status !== 200) {
throw await response.text();
}
const results = await response.json();
if (results.data) {
console.log("Plans found in that location:", results.data);
} else {
throw JSON.stringify(results);
}
} catch (e) {
console.log("Error with feed load:", e);
this.alertMessage =
e.userMessage || "There was an error retrieving projects.";
this.alertTitle = "Error";
}
}
} }
</script> </script>

90
src/views/HomeView.vue

@ -70,8 +70,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import * as R from "ramda"; import { Component, Vue } from "vue-facing-decorator";
import { Options, Vue } from "vue-class-component";
import GiftedDialog from "@/components/GiftedDialog.vue"; import GiftedDialog from "@/components/GiftedDialog.vue";
import { db, accountsDB } from "@/db"; import { db, accountsDB } from "@/db";
@ -83,7 +82,7 @@ import { Contact } from "@/db/tables/contacts";
import AlertMessage from "@/components/AlertMessage"; import AlertMessage from "@/components/AlertMessage";
import QuickNav from "@/components/QuickNav"; import QuickNav from "@/components/QuickNav";
@Options({ @Component({
components: { GiftedDialog, AlertMessage, QuickNav }, components: { GiftedDialog, AlertMessage, QuickNav },
}) })
export default class HomeView extends Vue { export default class HomeView extends Vue {
@ -99,7 +98,6 @@ export default class HomeView extends Vue {
alertTitle = ""; alertTitle = "";
alertMessage = ""; alertMessage = "";
// 'created' hook runs when the Vue instance is first created
async created() { async created() {
try { try {
await accountsDB.open(); await accountsDB.open();
@ -119,6 +117,28 @@ export default class HomeView extends Vue {
} }
} }
public async buildHeaders() {
const headers = { "Content-Type": "application/json" };
if (this.activeDid) {
await accountsDB.open();
const allAccounts = await accountsDB.accounts.toArray();
const account = allAccounts.find((acc) => acc.did === this.activeDid);
const identity = JSON.parse(account?.identity || "null");
if (!identity) {
throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
}
headers["Authorization"] = "Bearer " + (await accessToken(identity));
} else {
// it's OK without auth... we just won't get any identifiers
}
return headers;
}
updateAllFeed = async () => { updateAllFeed = async () => {
this.isHiddenSpinner = false; this.isHiddenSpinner = false;
@ -126,7 +146,6 @@ export default class HomeView extends Vue {
.then(async (results) => { .then(async (results) => {
if (results.data.length > 0) { if (results.data.length > 0) {
this.feedData = this.feedData.concat(results.data); this.feedData = this.feedData.concat(results.data);
//console.log("Feed data:", this.feedData);
this.feedAllLoaded = results.hitLimit; this.feedAllLoaded = results.hitLimit;
this.feedPreviousOldestId = this.feedPreviousOldestId =
results.data[results.data.length - 1].jwtId; results.data[results.data.length - 1].jwtId;
@ -134,7 +153,6 @@ export default class HomeView extends Vue {
this.feedLastViewedId == null || this.feedLastViewedId == null ||
this.feedLastViewedId < results.data[0].jwtId this.feedLastViewedId < results.data[0].jwtId
) { ) {
// save it to storage
await db.open(); await db.open();
db.settings.update(MASTER_SETTINGS_KEY, { db.settings.update(MASTER_SETTINGS_KEY, {
lastViewedClaimId: results.data[0].jwtId, lastViewedClaimId: results.data[0].jwtId,
@ -154,41 +172,26 @@ export default class HomeView extends Vue {
}; };
retrieveClaims = async (endorserApiServer, identifier, beforeId) => { retrieveClaims = async (endorserApiServer, identifier, beforeId) => {
//const afterQuery = afterId == null ? "" : "&afterId=" + afterId;
const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId; const beforeQuery = beforeId == null ? "" : "&beforeId=" + beforeId;
const headers = { "Content-Type": "application/json" }; const response = await fetch(
if (this.activeDid) { this.apiServer + "/api/v2/report/gives?" + beforeQuery,
const account = R.find( {
(acc) => acc.did === this.activeDid,
this.allAccounts
);
const identity = JSON.parse(account?.identity || "null");
if (!identity) {
throw new Error("No identity found.");
}
const token = await accessToken(identity);
headers["Authorization"] = "Bearer " + token;
} else {
// it's OK without auth... we just won't get any identifiers
}
return fetch(this.apiServer + "/api/v2/report/gives?" + beforeQuery, {
method: "GET", method: "GET",
headers: headers, headers: await buildHeaders(),
}) }
.then(async (response) => { );
if (response.status !== 200) { if (response.status !== 200) {
const details = await response.text(); throw await response.text();
throw details;
} }
return response.json();
}) const results = await response.json();
.then((results) => {
if (results.data) { if (results.data) {
return results; return results;
} else { } else {
throw JSON.stringify(results); throw JSON.stringify(results);
} }
});
}; };
giveDescription(giveRecord) { giveDescription(giveRecord) {
@ -235,6 +238,7 @@ export default class HomeView extends Vue {
openDialog(giver) { openDialog(giver) {
this.$refs.customDialog.open(giver); this.$refs.customDialog.open(giver);
} }
handleDialogResult(result) { handleDialogResult(result) {
if (result.action === "confirm") { if (result.action === "confirm") {
return new Promise((resolve) => { return new Promise((resolve) => {
@ -259,21 +263,23 @@ export default class HomeView extends Vue {
"You must select an identity before you can record a give."; "You must select an identity before you can record a give.";
return; return;
} }
if (!description && !hours) { if (!description && !hours) {
this.alertTitle = "Error"; this.alertTitle = "Error";
this.alertMessage = this.alertMessage =
"You must enter a description or some number of hours."; "You must enter a description or some number of hours.";
return; return;
} }
const account = R.find(
(acc) => acc.did === this.activeDid, const account = this.allAccounts.find((acc) => acc.did === this.activeDid);
this.allAccounts
);
//console.log("about to parse from", this.activeDid, account?.identity);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
createAndSubmitGive( createAndSubmitGive(
this.axios, this.axios,
this.apiServer, this.apiServer,
@ -284,20 +290,18 @@ export default class HomeView extends Vue {
hours hours
) )
.then((result) => { .then((result) => {
if (result.status != 201 || result.data?.error) { const error = result.data?.error;
if (result.status !== 201 || error) {
console.log("Error with give result:", result); console.log("Error with give result:", result);
this.alertTitle = "Error"; this.alertTitle = "Error";
this.alertMessage = this.alertMessage =
result.data?.error?.message || error?.message || "There was an error recording the give.";
"There was an error recording the give.";
} else { } else {
this.alertTitle = "Success"; this.alertTitle = "Success";
this.alertMessage = "That gift was recorded."; this.alertMessage = "That gift was recorded.";
//this.updateAllFeed(); // full update is overkill but we should show something
} }
}) })
.catch((e) => { .catch((e) => {
// axios throws errors on 400 responses
console.log("Error with give caught:", e); console.log("Error with give caught:", e);
this.alertTitle = "Error"; this.alertTitle = "Error";
this.alertMessage = this.alertMessage =

9
src/views/NewEditProjectView.vue

@ -105,7 +105,6 @@ export default class NewEditProjectView extends Vue {
isHiddenSave = false; isHiddenSave = false;
isHiddenSpinner = true; isHiddenSpinner = true;
// '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_KEY); const settings = await db.settings.get(MASTER_SETTINGS_KEY);
@ -122,7 +121,9 @@ export default class NewEditProjectView extends Vue {
const account = R.find((acc) => acc.did === this.activeDid, accounts); const account = R.find((acc) => acc.did === this.activeDid, accounts);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
this.LoadProject(identity); this.LoadProject(identity);
} }
@ -257,7 +258,9 @@ export default class NewEditProjectView extends Vue {
const account = R.find((acc) => acc.did === this.activeDid, accounts); const account = R.find((acc) => acc.did === this.activeDid, accounts);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
this.SaveProject(identity); this.SaveProject(identity);
} }

44
src/views/ProjectViewView.vue

@ -146,7 +146,6 @@
<script lang="ts"> <script lang="ts">
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import * as moment from "moment"; import * as moment from "moment";
import * as R from "ramda";
import { Component, Vue } from "vue-facing-decorator"; import { Component, Vue } from "vue-facing-decorator";
import GiftedDialog from "@/components/GiftedDialog.vue"; import GiftedDialog from "@/components/GiftedDialog.vue";
@ -174,6 +173,8 @@ export default class ProjectViewView extends Vue {
timeSince = ""; timeSince = "";
projectId = localStorage.getItem("projectId") || ""; // handle ID projectId = localStorage.getItem("projectId") || ""; // handle ID
errorMessage = ""; errorMessage = "";
alertMessage = "";
alertTitle = "";
onEditClick() { onEditClick() {
localStorage.setItem("projectId", this.projectId as string); localStorage.setItem("projectId", this.projectId as string);
@ -210,6 +211,7 @@ export default class ProjectViewView extends Vue {
const eventDate = new Date(startTime); const eventDate = new Date(startTime);
const now = moment.now(); const now = moment.now();
this.timeSince = moment.utc(now).to(eventDate); this.timeSince = moment.utc(now).to(eventDate);
errorMessage;
} }
this.name = resp.data.claim?.name || "(no name)"; this.name = resp.data.claim?.name || "(no name)";
this.description = resp.data.claim?.description || "(no description)"; this.description = resp.data.claim?.description || "(no description)";
@ -231,7 +233,6 @@ export default class ProjectViewView extends Vue {
} }
} }
// '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_KEY); const settings = await db.settings.get(MASTER_SETTINGS_KEY);
@ -245,10 +246,12 @@ export default class ProjectViewView extends Vue {
console.error("Problem! Should have a profile!"); console.error("Problem! Should have a profile!");
} else { } else {
const accounts = await accountsDB.accounts.toArray(); const accounts = await accountsDB.accounts.toArray();
const account = R.find((acc) => acc.did === this.activeDid, accounts); const account = accounts.find((acc) => acc.did === this.activeDid);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
this.LoadProject(identity); this.LoadProject(identity);
} }
@ -257,6 +260,7 @@ export default class ProjectViewView extends Vue {
openDialog(contact) { openDialog(contact) {
this.$refs.customDialog.open(contact); this.$refs.customDialog.open(contact);
} }
handleDialogResult(result) { handleDialogResult(result) {
if (result.action === "confirm") { if (result.action === "confirm") {
return new Promise((resolve) => { return new Promise((resolve) => {
@ -275,25 +279,32 @@ export default class ProjectViewView extends Vue {
* @param hours may be 0 * @param hours may be 0
*/ */
async recordGive(giverDid, description, hours) { async recordGive(giverDid, description, hours) {
if (this.activeDid == null) { if (!this.activeDid) {
this.alertTitle = "Error"; this.alertTitle = "Error";
this.alertMessage = this.alertMessage =
"You must select an identity before you can record a give."; "You must select an identity before you can record a give.";
return; return;
} }
if (!description && !hours) { if (!description && !hours) {
this.alertTitle = "Error"; this.alertTitle = "Error";
this.alertMessage = this.alertMessage =
"You must enter a description or some number of hours."; "You must enter a description or some number of hours.";
return; return;
} }
const accounts = await accountsDB.accounts.toArray(); const accounts = await accountsDB.accounts.toArray();
const account = R.find((acc) => acc.did === this.activeDid, accounts); const account = accounts.find((acc) => acc.did === this.activeDid);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
createAndSubmitGive(
try {
const result = await createAndSubmitGive(
this.axios, this.axios,
this.apiServer, this.apiServer,
identity, identity,
@ -302,9 +313,9 @@ export default class ProjectViewView extends Vue {
description, description,
hours, hours,
this.projectId this.projectId
) );
.then((result) => {
if (result.status != 201 || result.data?.error) { if (result.status !== 201 || result.data?.error) {
console.log("Error with give result:", result); console.log("Error with give result:", result);
this.alertTitle = "Error"; this.alertTitle = "Error";
this.alertMessage = this.alertMessage =
@ -313,22 +324,15 @@ export default class ProjectViewView extends Vue {
} else { } else {
this.alertTitle = "Success"; this.alertTitle = "Success";
this.alertMessage = "That gift was recorded."; this.alertMessage = "That gift was recorded.";
//this.updateAllFeed(); // full update is overkill but we should show something
} }
}) } catch (e) {
.catch((e) => {
// axios throws errors on 400 responses
console.log("Error with give caught:", e); console.log("Error with give caught:", e);
this.alertTitle = "Error"; this.alertTitle = "Error";
this.alertMessage = this.alertMessage =
e.userMessage || e.userMessage ||
e.response?.data?.error?.message || e.response?.data?.error?.message ||
"There was an error recording the give."; "There was an error recording the give.";
});
} }
}
// This same popup code is in many files.
alertMessage = "";
alertTitle = "";
} }
</script> </script>

4
src/views/ProjectsView.vue

@ -204,7 +204,9 @@ export default class ProjectsView extends Vue {
const account = R.find((acc) => acc.did === activeDid, accounts); const account = R.find((acc) => acc.did === activeDid, accounts);
const identity = JSON.parse(account?.identity || "null"); const identity = JSON.parse(account?.identity || "null");
if (!identity) { if (!identity) {
throw new Error("No identity found."); throw new Error(
"An ID is chosen but there are no keys for it so it cannot be used to talk with the service."
);
} }
this.current = identity; this.current = identity;
this.LoadProjects(identity); this.LoadProjects(identity);

Loading…
Cancel
Save