Merge pull request 'update to new endpoints with the editable plan "handle"' (#7) from pull-only-plans into master
Reviewed-on: trent_larson/kick-starter-for-time-pwa#7
This commit was merged in pull request #7.
This commit is contained in:
@@ -42,9 +42,9 @@ New users require registration. This can be done with a claim payload like this
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
On the test server, the user starting 0x000 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 #0 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 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`
|
||||||
|
|
||||||
- Register someone else under User #0 on the `/account` page:
|
- Register someone else under User #0 on the `/account` page:
|
||||||
|
|
||||||
|
|||||||
30
project.yaml
30
project.yaml
@@ -1,18 +1,36 @@
|
|||||||
- top screens from img/screens.pdf :
|
- top screens from img/screens.pdf milestone:2 :
|
||||||
|
- new
|
||||||
|
- make sure to save with plan identifier if it isn't already assignee:trent
|
||||||
|
- feedback to show saving
|
||||||
|
- edit
|
||||||
|
- make sure to save with plan identifier if it isn't already assignee:trent
|
||||||
|
- feedback to show saved
|
||||||
- view all :
|
- view all :
|
||||||
- also extract plan identifier (instead of claim ID) assignee:trent
|
- also extract plan identifier (instead of claim ID) assignee:trent
|
||||||
- search bar isn't highlighted & icon on right doesn't show
|
- search bar isn't highlighted & icon on right doesn't show
|
||||||
- no tab bar across bottom
|
- no tab bar across bottom
|
||||||
|
- add spinner
|
||||||
- view one
|
- view one
|
||||||
- change lookup to pull from new /api/ext/plan with plan identifier assignee:trent
|
- change lookup to pull from new /api/ext/plan with plan identifier assignee:trent
|
||||||
- edit
|
- image
|
||||||
- make sure to save with plan identifier if it isn't already
|
|
||||||
- new
|
|
||||||
- make sure to save with plan identifier if it isn't already
|
|
||||||
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
|
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
|
||||||
|
|
||||||
- replace user-affecting console.logs with error messages
|
- replace user-affecting console.logs with error messages (eg. catches)
|
||||||
|
|
||||||
|
- contacts
|
||||||
|
|
||||||
- commit screen
|
- commit screen
|
||||||
|
|
||||||
- discover screen
|
- discover screen
|
||||||
|
|
||||||
|
- backup all data
|
||||||
|
|
||||||
|
- Next Viable Product afterward
|
||||||
|
|
||||||
|
- Connect with phone contacts
|
||||||
|
|
||||||
|
- Multiple identities
|
||||||
|
|
||||||
|
- Peer DID
|
||||||
|
|
||||||
|
- DIDComm
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ export enum AppString {
|
|||||||
APP_NAME = "Kickstart for time",
|
APP_NAME = "Kickstart for time",
|
||||||
VERSION = "0.1",
|
VERSION = "0.1",
|
||||||
DEFAULT_ENDORSER_API_SERVER = "https://test.endorser.ch:8000",
|
DEFAULT_ENDORSER_API_SERVER = "https://test.endorser.ch:8000",
|
||||||
DEFAULT_ENDORSER_VIEW_SERVER = "https://test.endorser.ch",
|
//DEFAULT_ENDORSER_API_SERVER = "http://localhost:3000",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,17 @@
|
|||||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||||
><fa icon="chevron-left" class="fa-fw"></fa
|
><fa icon="chevron-left" class="fa-fw"></fa
|
||||||
></router-link>
|
></router-link>
|
||||||
[New/Edit] Project
|
[New/Edit] Plan
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Project Details -->
|
<!-- Project Details -->
|
||||||
<!-- Image - (see design model) Empty -->
|
<!-- Image - (see design model) Empty -->
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{ errorMessage }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Project Name"
|
placeholder="Project Name"
|
||||||
@@ -61,16 +65,23 @@ import * as didJwt from "did-jwt";
|
|||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
import { useAppStore } from "@/store/app";
|
import { useAppStore } from "@/store/app";
|
||||||
|
|
||||||
|
interface VerifiableCredential {
|
||||||
|
"@context": string;
|
||||||
|
"@type": string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
identifier?: string;
|
||||||
|
}
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class NewEditProjectView extends Vue {
|
export default class NewEditProjectView extends Vue {
|
||||||
projectName = "";
|
projectName = "";
|
||||||
description = "";
|
description = "";
|
||||||
projectId =
|
errorMessage = "";
|
||||||
localStorage.getItem("projectId") === null
|
|
||||||
? ""
|
projectId = localStorage.getItem("projectId") || "";
|
||||||
: localStorage.getItem("projectId");
|
|
||||||
|
|
||||||
async created() {
|
async created() {
|
||||||
if (this.projectId === "") {
|
if (this.projectId === "") {
|
||||||
@@ -90,7 +101,8 @@ 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;
|
||||||
const url = endorserApiServer + "/api/claim/" + this.projectId;
|
// eslint-disable-next-line prettier/prettier
|
||||||
|
const url = 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",
|
||||||
@@ -111,15 +123,17 @@ export default class NewEditProjectView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async SaveProject(identity: IIdentifier) {
|
private async SaveProject(identity: IIdentifier) {
|
||||||
const address = identity.did;
|
|
||||||
// Make a claim
|
// Make a claim
|
||||||
const vcClaim = {
|
const vcClaim: VerifiableCredential = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "PlanAction",
|
"@type": "PlanAction",
|
||||||
identifier: address,
|
|
||||||
name: this.projectName,
|
name: this.projectName,
|
||||||
description: this.description,
|
description: this.description,
|
||||||
|
identifier: this.projectId || undefined,
|
||||||
};
|
};
|
||||||
|
if (this.projectId) {
|
||||||
|
vcClaim.identifier = this.projectId;
|
||||||
|
}
|
||||||
// Make a payload for the claim
|
// Make a payload for the claim
|
||||||
const vcPayload = {
|
const vcPayload = {
|
||||||
sub: "PlanAction",
|
sub: "PlanAction",
|
||||||
@@ -149,7 +163,7 @@ export default class NewEditProjectView extends Vue {
|
|||||||
|
|
||||||
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
||||||
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
||||||
const url = endorserApiServer + "/api/claim";
|
const url = endorserApiServer + "/api/v2/claim";
|
||||||
const token = await accessToken(identity);
|
const token = await accessToken(identity);
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -158,21 +172,37 @@ export default class NewEditProjectView extends Vue {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await this.axios.post(url, payload, { headers });
|
const resp = await this.axios.post(url, payload, { headers });
|
||||||
useAppStore().setProjectId(resp.data);
|
console.log("Got resp data:", resp.data);
|
||||||
setTimeout(
|
if (resp.data?.success?.fullIri) {
|
||||||
function (that: Vue) {
|
this.errorMessage = "";
|
||||||
console.log("THAT:", localStorage.getItem("projectId"));
|
useAppStore().setProjectId(resp.data.success.fullIri);
|
||||||
const route = {
|
setTimeout(
|
||||||
name: "project",
|
function (that: Vue) {
|
||||||
};
|
console.log("THAT:", localStorage.getItem("projectId"));
|
||||||
console.log(route);
|
const route = {
|
||||||
that.$router.push(route);
|
name: "project",
|
||||||
},
|
};
|
||||||
2000,
|
console.log(route);
|
||||||
this
|
that.$router.push(route);
|
||||||
);
|
},
|
||||||
} catch (error) {
|
2000,
|
||||||
console.log(error);
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
let userMessage = "There was an error. See logs for more info.";
|
||||||
|
const serverError = error.response?.data?.error;
|
||||||
|
if (serverError) {
|
||||||
|
if (serverError.message) {
|
||||||
|
userMessage = serverError.message; // This is info for the user.
|
||||||
|
} else {
|
||||||
|
console.log("Server gave an error:", serverError);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("Here's the full error trying to save the claim:", error);
|
||||||
|
}
|
||||||
|
// Now set that error for the user to see.
|
||||||
|
this.errorMessage = userMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,10 +60,14 @@
|
|||||||
><fa icon="ellipsis-vertical" class="fa-fw"></fa
|
><fa icon="ellipsis-vertical" class="fa-fw"></fa
|
||||||
></a>
|
></a>
|
||||||
|
|
||||||
View Project
|
View Plan
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{ errorMessage }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Project Details -->
|
<!-- Project Details -->
|
||||||
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
|
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -157,10 +161,8 @@ export default class ProjectViewView extends Vue {
|
|||||||
truncatedDesc = "";
|
truncatedDesc = "";
|
||||||
truncateLength = 40;
|
truncateLength = 40;
|
||||||
timeSince = "";
|
timeSince = "";
|
||||||
projectId =
|
projectId = localStorage.getItem("projectId") || "";
|
||||||
localStorage.getItem("projectId") === null
|
errorMessage = "";
|
||||||
? ""
|
|
||||||
: localStorage.getItem("projectId");
|
|
||||||
|
|
||||||
onEditClick() {
|
onEditClick() {
|
||||||
localStorage.setItem("projectId", this.projectId as string);
|
localStorage.setItem("projectId", this.projectId as string);
|
||||||
@@ -181,7 +183,8 @@ export default class ProjectViewView extends Vue {
|
|||||||
|
|
||||||
async LoadProject(identity: IIdentifier) {
|
async LoadProject(identity: IIdentifier) {
|
||||||
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
||||||
const url = endorserApiServer + "/api/claim/" + this.projectId;
|
// eslint-disable-next-line prettier/prettier
|
||||||
|
const url = 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",
|
||||||
@@ -190,19 +193,30 @@ export default class ProjectViewView extends Vue {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await this.axios.get(url, { headers });
|
const resp = await this.axios.get(url, { headers });
|
||||||
console.log(resp.status, resp.data);
|
console.log("resp.status, resp.data", resp.status, resp.data);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const claim = resp.data.claim;
|
const startTime = resp.data.startTime;
|
||||||
const issuedAt = resp.data.issuedAt;
|
if (startTime != null) {
|
||||||
const eventDate = new Date(issuedAt);
|
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);
|
||||||
this.name = claim.name;
|
}
|
||||||
this.description = claim.description;
|
this.name = resp.data.claim?.name || "(no name)";
|
||||||
|
this.description = resp.data.claim?.description || "(no description)";
|
||||||
this.truncatedDesc = this.description.slice(0, this.truncateLength);
|
this.truncatedDesc = this.description.slice(0, this.truncateLength);
|
||||||
|
} else if (resp.status === 404) {
|
||||||
|
// actually, axios throws an error so we never get here
|
||||||
|
this.errorMessage = "That project does not exist.";
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error?.response?.status === 404) {
|
||||||
|
this.errorMessage = "That project does not exist.";
|
||||||
|
} else {
|
||||||
|
this.errorMessage =
|
||||||
|
"Something went wrong retrieving that project." +
|
||||||
|
" See logs for more info.";
|
||||||
|
console.log("Error retrieving project:", error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<section id="Content" class="p-6 pb-24">
|
<section id="Content" class="p-6 pb-24">
|
||||||
<!-- Heading -->
|
<!-- Heading -->
|
||||||
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
|
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
|
||||||
My Projects
|
My Plans
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<!-- Quick Search -->
|
<!-- Quick Search -->
|
||||||
@@ -32,10 +32,10 @@
|
|||||||
<li
|
<li
|
||||||
class="border-b border-slate-300"
|
class="border-b border-slate-300"
|
||||||
v-for="project in projects"
|
v-for="project in projects"
|
||||||
:key="project.id"
|
:key="project.handleId"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
@click="onClickLoadProject(project.id)"
|
@click="onClickLoadProject(project.handleId)"
|
||||||
class="block py-4 flex gap-4"
|
class="block py-4 flex gap-4"
|
||||||
>
|
>
|
||||||
<div class="flex-none w-12">
|
<div class="flex-none w-12">
|
||||||
@@ -68,7 +68,7 @@ import { AppString } from "@/constants/app";
|
|||||||
components: {},
|
components: {},
|
||||||
})
|
})
|
||||||
export default class ProjectsView extends Vue {
|
export default class ProjectsView extends Vue {
|
||||||
projects: { id: string; name: string; description: string }[] = [];
|
projects: { handleId: string; name: string; description: string }[] = [];
|
||||||
|
|
||||||
onClickLoadProject(id: string) {
|
onClickLoadProject(id: string) {
|
||||||
console.log("projectId", id);
|
console.log("projectId", id);
|
||||||
@@ -82,10 +82,7 @@ export default class ProjectsView extends Vue {
|
|||||||
|
|
||||||
async LoadProjects(identity: IIdentifier) {
|
async LoadProjects(identity: IIdentifier) {
|
||||||
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
const endorserApiServer = AppString.DEFAULT_ENDORSER_API_SERVER;
|
||||||
const url =
|
const url = endorserApiServer + "/api/v2/report/plansByIssuer";
|
||||||
endorserApiServer +
|
|
||||||
"/api/claim/?claimType=PlanAction&issuer=" +
|
|
||||||
identity.did;
|
|
||||||
const token = await accessToken(identity);
|
const token = await accessToken(identity);
|
||||||
const headers = {
|
const headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -95,14 +92,13 @@ export default class ProjectsView extends Vue {
|
|||||||
try {
|
try {
|
||||||
const resp = await this.axios.get(url, { headers });
|
const resp = await this.axios.get(url, { headers });
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const claims = resp.data;
|
const plans = resp.data.data;
|
||||||
for (let i = 0; i < claims.length; i++) {
|
for (let i = 0; i < plans.length; i++) {
|
||||||
console.log(claims[i]);
|
const plan = plans[i];
|
||||||
const claim = claims[i].claim;
|
|
||||||
const data = {
|
const data = {
|
||||||
id: claims[i].id,
|
name: plan.name,
|
||||||
name: claim.name,
|
description: plan.description,
|
||||||
description: claim.description,
|
handleId: plan.fullIri,
|
||||||
};
|
};
|
||||||
this.projects.push(data);
|
this.projects.push(data);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user