Browse Source

add URL for plans

kb/add-usage-guide
Trent Larson 11 months ago
parent
commit
bb122be319
  1. 4
      project.task.yaml
  2. 6
      src/libs/endorserServer.ts
  3. 3
      src/libs/util.ts
  4. 2
      src/main.ts
  5. 8
      src/views/NewEditProjectView.vue
  6. 41
      src/views/ProjectViewView.vue

4
project.task.yaml

@ -11,10 +11,10 @@ tasks:
- .5 Add infinite scroll to gifts on the home page - .5 Add infinite scroll to gifts on the home page
- Discuss whether the remaining tasks are worthwhile before MVP release.
- .5 If notifications are not enabled, add message to front page with link/button to enable - .5 If notifications are not enabled, add message to front page with link/button to enable
- Discuss whether the remaining tasks are worthwhile before MVP release.
- .5 make a VC details page, or link to endorser.ch (including confirmations) - .5 make a VC details page, or link to endorser.ch (including confirmations)
- .3 Add URL for project - .3 Add URL for project
- .5 Add start date to project - .5 Add start date to project

6
src/libs/endorserServer.ts

@ -69,6 +69,8 @@ export interface OfferServerRecord {
validThrough: string; validThrough: string;
} }
// Note that previous VCs may have additional fields.
// https://endorser.ch/doc/html/transactions.html#id4
export interface GiveVerifiableCredential { export interface GiveVerifiableCredential {
"@context"?: string; // optional when embedded, eg. in an Agree "@context"?: string; // optional when embedded, eg. in an Agree
"@type": "GiveAction"; "@type": "GiveAction";
@ -80,6 +82,8 @@ export interface GiveVerifiableCredential {
recipient?: { identifier: string }; recipient?: { identifier: string };
} }
// Note that previous VCs may have additional fields.
// https://endorser.ch/doc/html/transactions.html#id8
export interface OfferVerifiableCredential { export interface OfferVerifiableCredential {
"@context"?: string; // optional when embedded, eg. in an Agree "@context"?: string; // optional when embedded, eg. in an Agree
"@type": "Offer"; "@type": "Offer";
@ -93,6 +97,8 @@ export interface OfferVerifiableCredential {
validThrough?: string; validThrough?: string;
} }
// Note that previous VCs may have additional fields.
// https://endorser.ch/doc/html/transactions.html#id7
export interface PlanVerifiableCredential { export interface PlanVerifiableCredential {
"@context": "https://schema.org"; "@context": "https://schema.org";
"@type": "PlanAction"; "@type": "PlanAction";

3
src/libs/util.ts

@ -0,0 +1,3 @@
export const isGlobalUri = (uri: string) => {
return uri && uri.match(new RegExp(/^[A-Za-z][A-Za-z0-9+.-]+:/));
};

2
src/main.ts

@ -36,6 +36,7 @@ import {
faFloppyDisk, faFloppyDisk,
faFolderOpen, faFolderOpen,
faGift, faGift,
faGlobe,
faHand, faHand,
faHouseChimney, faHouseChimney,
faLocationDot, faLocationDot,
@ -86,6 +87,7 @@ library.add(
faFloppyDisk, faFloppyDisk,
faFolderOpen, faFolderOpen,
faGift, faGift,
faGlobe,
faHand, faHand,
faHouseChimney, faHouseChimney,
faLocationDot, faLocationDot,

8
src/views/NewEditProjectView.vue

@ -40,6 +40,12 @@
{{ fullClaim.description.length }}/5000 max. characters {{ fullClaim.description.length }}/5000 max. characters
</div> </div>
<input
v-model="fullClaim.url"
placeholder="Website"
class="block w-full rounded border border-slate-400 mb-4 px-3 py-2"
/>
<div class="flex items-center mb-4"> <div class="flex items-center mb-4">
<input <input
type="checkbox" type="checkbox"
@ -142,7 +148,7 @@ export default class NewEditProjectView extends Vue {
"@type": "PlanAction", "@type": "PlanAction",
name: "", name: "",
description: "", description: "",
}; }; // this default is only to avoid errors before plan is loaded
includeLocation = false; includeLocation = false;
latitude = 0; latitude = 0;
longitude = 0; longitude = 0;

41
src/views/ProjectViewView.vue

@ -45,8 +45,13 @@
:href="getOpenStreetMapUrl()" :href="getOpenStreetMapUrl()"
target="_blank" target="_blank"
class="underline" class="underline"
> >Map View
Map View </a>
</div>
<div v-if="url">
<fa icon="globe" class="fa-fw text-slate-400"></fa>
<a :href="addScheme(url)" target="_blank" class="underline"
>{{ domainForWebsite(this.url) }}
</a> </a>
</div> </div>
</div> </div>
@ -272,6 +277,7 @@ import { accountsDB, db } from "@/db/index";
import { Contact } from "@/db/tables/contacts"; import { Contact } from "@/db/tables/contacts";
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto"; import { accessToken } from "@/libs/crypto";
import { isGlobalUri } from "@/libs/util";
import { import {
didInfo, didInfo,
GiverInputInfo, GiverInputInfo,
@ -314,6 +320,7 @@ export default class ProjectViewView extends Vue {
timeSince = ""; timeSince = "";
truncatedDesc = ""; truncatedDesc = "";
truncateLength = 40; truncateLength = 40;
url = "";
async created() { async created() {
await db.open(); await db.open();
@ -415,6 +422,7 @@ export default class ProjectViewView extends Vue {
this.truncatedDesc = this.description.slice(0, this.truncateLength); this.truncatedDesc = this.description.slice(0, this.truncateLength);
this.latitude = resp.data.claim?.location?.geo?.latitude || 0; this.latitude = resp.data.claim?.location?.geo?.latitude || 0;
this.longitude = resp.data.claim?.location?.geo?.longitude || 0; this.longitude = resp.data.claim?.location?.geo?.longitude || 0;
this.url = resp.data.claim?.url || "";
} else if (resp.status === 404) { } else if (resp.status === 404) {
// actually, axios throws an error so we never get here // actually, axios throws an error so we never get here
this.$notify( this.$notify(
@ -651,5 +659,34 @@ export default class ProjectViewView extends Vue {
iconForUnitCode(unitCode: string) { iconForUnitCode(unitCode: string) {
return this.UNIT_CODES[unitCode]?.faIcon || "question"; return this.UNIT_CODES[unitCode]?.faIcon || "question";
} }
// return an HTTPS URL if it's not a global URL
addScheme(url: string) {
if (!isGlobalUri(url)) {
return "https://" + url;
}
return url;
}
// return just the domain for display, if possible
domainForWebsite(url: string) {
try {
const hostname = new URL(url).hostname;
console.log("hostname", hostname);
if (!hostname) {
// happens for non-http URLs
return url;
} else if (url.endsWith(hostname)) {
// it's just the domain
return hostname;
} else {
// there's more, but don't bother displaying the whole thing
return hostname + "...";
}
} catch (error: unknown) {
// must not be a valid URL
return url;
}
}
} }
</script> </script>

Loading…
Cancel
Save