Merge branch 'nostr'
This commit is contained in:
@@ -2,3 +2,4 @@
|
|||||||
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01GXYPFF7FA03NXKPYY142PY4H
|
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01GXYPFF7FA03NXKPYY142PY4H
|
||||||
VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch
|
VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch
|
||||||
VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app
|
VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app
|
||||||
|
VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.timesafari.app
|
||||||
|
|||||||
13
.eslintrc.js
13
.eslintrc.js
@@ -14,8 +14,21 @@ module.exports = {
|
|||||||
// ecmaVersion: 2020,
|
// ecmaVersion: 2020,
|
||||||
// },
|
// },
|
||||||
rules: {
|
rules: {
|
||||||
|
"max-len": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
code: 120,
|
||||||
|
ignoreComments: true, // why does this not make it allow comment of any length?
|
||||||
|
ignorePattern: '^\\s*class="[^"]*"$',
|
||||||
|
ignoreStrings: true,
|
||||||
|
ignoreTemplateLiterals: true,
|
||||||
|
ignoreTrailingComments: true,
|
||||||
|
ignoreUrls: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||||
|
// "prettier/prettier": ["warn", { printWidth: 120 }], // removes errors but adds thousands of warnings
|
||||||
"@typescript-eslint/no-unnecessary-type-constraint": "off",
|
"@typescript-eslint/no-unnecessary-type-constraint": "off",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ npm install
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See the test locations for "IMAGE_API_SERVER" or "PARTNER_API_SERVER" below, or use http://localhost:3000 for local endorser.ch
|
||||||
|
|
||||||
### Build the test & production app
|
### Build the test & production app
|
||||||
```
|
```
|
||||||
npm run serve
|
npm run serve
|
||||||
@@ -57,7 +59,7 @@ npm run test-all
|
|||||||
```
|
```
|
||||||
# (Let's replace this with a .env.development or .env.staging file.)
|
# (Let's replace this with a .env.development or .env.staging file.)
|
||||||
# The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.
|
# The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.
|
||||||
TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_PASSKEYS_ENABLED=true npm run build
|
TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch VITE_PASSKEYS_ENABLED=true npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
* Production
|
* Production
|
||||||
|
|||||||
119
package-lock.json
generated
119
package-lock.json
generated
@@ -46,6 +46,7 @@
|
|||||||
"lru-cache": "^10.2.0",
|
"lru-cache": "^10.2.0",
|
||||||
"luxon": "^3.4.4",
|
"luxon": "^3.4.4",
|
||||||
"merkletreejs": "^0.3.11",
|
"merkletreejs": "^0.3.11",
|
||||||
|
"nostr-tools": "^2.7.2",
|
||||||
"notiwind": "^2.0.2",
|
"notiwind": "^2.0.2",
|
||||||
"papaparse": "^5.4.1",
|
"papaparse": "^5.4.1",
|
||||||
"pina": "^0.20.2204228",
|
"pina": "^0.20.2204228",
|
||||||
@@ -17368,6 +17369,124 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nostr-tools": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-Bq3Ug0SZFtgtL1+0wCnAe8AJtI7yx/00/a2nUug9SkhfOwlKS92Tef12iCK9FdwXw+oFZWMtRnSwcLayQso+xA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/ciphers": "^0.5.1",
|
||||||
|
"@noble/curves": "1.2.0",
|
||||||
|
"@noble/hashes": "1.3.1",
|
||||||
|
"@scure/base": "1.1.1",
|
||||||
|
"@scure/bip32": "1.3.1",
|
||||||
|
"@scure/bip39": "1.2.1"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"nostr-wasm": "v0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": ">=5.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@noble/ciphers": {
|
||||||
|
"version": "0.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.5.3.tgz",
|
||||||
|
"integrity": "sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@noble/curves": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "1.3.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@noble/curves/node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@noble/hashes": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@scure/base": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@scure/bip32": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/curves": "~1.1.0",
|
||||||
|
"@noble/hashes": "~1.3.1",
|
||||||
|
"@scure/base": "~1.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@scure/bip32/node_modules/@noble/curves": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "1.3.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-tools/node_modules/@scure/bip39": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@noble/hashes": "~1.3.0",
|
||||||
|
"@scure/base": "~1.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nostr-wasm": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/notiwind": {
|
"node_modules/notiwind": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
"lru-cache": "^10.2.0",
|
"lru-cache": "^10.2.0",
|
||||||
"luxon": "^3.4.4",
|
"luxon": "^3.4.4",
|
||||||
"merkletreejs": "^0.3.11",
|
"merkletreejs": "^0.3.11",
|
||||||
|
"nostr-tools": "^2.7.2",
|
||||||
"notiwind": "^2.0.2",
|
"notiwind": "^2.0.2",
|
||||||
"papaparse": "^5.4.1",
|
"papaparse": "^5.4.1",
|
||||||
"pina": "^0.20.2204228",
|
"pina": "^0.20.2204228",
|
||||||
|
|||||||
@@ -76,7 +76,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-else ref="cameraContainer">
|
<div v-else ref="cameraContainer">
|
||||||
<!--
|
<!--
|
||||||
Camera "resolution" doesn't change how it shows on screen but rather stretches the result, eg the following which just stretches it vertically:
|
Camera "resolution" doesn't change how it shows on screen but rather stretches the result,
|
||||||
|
eg. the following which just stretches it vertically:
|
||||||
:resolution="{ width: 375, height: 812 }"
|
:resolution="{ width: 375, height: 812 }"
|
||||||
-->
|
-->
|
||||||
<camera
|
<camera
|
||||||
|
|||||||
@@ -12,14 +12,18 @@ export enum AppString {
|
|||||||
TEST_ENDORSER_API_SERVER = "https://test-api.endorser.ch",
|
TEST_ENDORSER_API_SERVER = "https://test-api.endorser.ch",
|
||||||
LOCAL_ENDORSER_API_SERVER = "http://localhost:3000",
|
LOCAL_ENDORSER_API_SERVER = "http://localhost:3000",
|
||||||
|
|
||||||
PROD_PUSH_SERVER = "https://timesafari.app",
|
|
||||||
TEST1_PUSH_SERVER = "https://test.timesafari.app",
|
|
||||||
TEST2_PUSH_SERVER = "https://timesafari-pwa.anomalistlabs.com",
|
|
||||||
|
|
||||||
PROD_IMAGE_API_SERVER = "https://image-api.timesafari.app",
|
PROD_IMAGE_API_SERVER = "https://image-api.timesafari.app",
|
||||||
TEST_IMAGE_API_SERVER = "https://test-image-api.timesafari.app",
|
TEST_IMAGE_API_SERVER = "https://test-image-api.timesafari.app",
|
||||||
LOCAL_IMAGE_API_SERVER = "http://localhost:3001",
|
LOCAL_IMAGE_API_SERVER = "http://localhost:3001",
|
||||||
|
|
||||||
|
PROD_PARTNER_API_SERVER = "https://endorser.ch",
|
||||||
|
TEST_PARTNER_API_SERVER = "https://test-partner.endorser.ch",
|
||||||
|
LOCAL_PARTNER_API_SERVER = LOCAL_ENDORSER_API_SERVER,
|
||||||
|
|
||||||
|
PROD_PUSH_SERVER = "https://timesafari.app",
|
||||||
|
TEST1_PUSH_SERVER = "https://test.timesafari.app",
|
||||||
|
TEST2_PUSH_SERVER = "https://timesafari-pwa.anomalistlabs.com",
|
||||||
|
|
||||||
NO_CONTACT_NAME = "(no name)",
|
NO_CONTACT_NAME = "(no name)",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,6 +35,10 @@ export const DEFAULT_IMAGE_API_SERVER =
|
|||||||
import.meta.env.VITE_DEFAULT_IMAGE_API_SERVER ||
|
import.meta.env.VITE_DEFAULT_IMAGE_API_SERVER ||
|
||||||
AppString.TEST_IMAGE_API_SERVER;
|
AppString.TEST_IMAGE_API_SERVER;
|
||||||
|
|
||||||
|
export const DEFAULT_PARTNER_API_SERVER =
|
||||||
|
import.meta.env.VITE_DEFAULT_PARTNER_API_SERVER ||
|
||||||
|
AppString.TEST_PARTNER_API_SERVER;
|
||||||
|
|
||||||
export const DEFAULT_PUSH_SERVER =
|
export const DEFAULT_PUSH_SERVER =
|
||||||
window.location.protocol + "//" + window.location.host;
|
window.location.protocol + "//" + window.location.host;
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Registration notice -->
|
<!-- Registration notice -->
|
||||||
<!-- We won't show any loading indicator because it usually doesn't change anything. We'll just pop the message in only if we discover that they need it. -->
|
<!--
|
||||||
|
We won't show any loading indicator because it usually doesn't change anything.
|
||||||
|
We'll just pop the message in only if we discover that they need it.
|
||||||
|
-->
|
||||||
<div
|
<div
|
||||||
v-if="!loadingLimits && !endorserLimits?.nextWeekBeginDateTime"
|
v-if="!loadingLimits && !endorserLimits?.nextWeekBeginDateTime"
|
||||||
id="noticeBeforeAnnounce"
|
id="noticeBeforeAnnounce"
|
||||||
@@ -593,6 +596,11 @@
|
|||||||
<span class="text-sm">{{ DEFAULT_IMAGE_API_SERVER }}</span>
|
<span class="text-sm">{{ DEFAULT_IMAGE_API_SERVER }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="sectionPartnerServerURL" class="mt-2">
|
||||||
|
<span class="text-slate-500 text-sm font-bold">Partner Server URL</span>
|
||||||
|
<span class="text-sm">{{ DEFAULT_PARTNER_API_SERVER }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
for="toggleHideRegisterPromptOnNewContact"
|
for="toggleHideRegisterPromptOnNewContact"
|
||||||
class="flex items-center justify-between cursor-pointer mt-4"
|
class="flex items-center justify-between cursor-pointer mt-4"
|
||||||
@@ -722,6 +730,7 @@ import UserNameDialog from "@/components/UserNameDialog.vue";
|
|||||||
import {
|
import {
|
||||||
AppString,
|
AppString,
|
||||||
DEFAULT_IMAGE_API_SERVER,
|
DEFAULT_IMAGE_API_SERVER,
|
||||||
|
DEFAULT_PARTNER_API_SERVER,
|
||||||
DEFAULT_PUSH_SERVER,
|
DEFAULT_PUSH_SERVER,
|
||||||
IMAGE_TYPE_PROFILE,
|
IMAGE_TYPE_PROFILE,
|
||||||
NotificationIface,
|
NotificationIface,
|
||||||
@@ -767,6 +776,7 @@ export default class AccountViewView extends Vue {
|
|||||||
AppConstants = AppString;
|
AppConstants = AppString;
|
||||||
DEFAULT_PUSH_SERVER = DEFAULT_PUSH_SERVER;
|
DEFAULT_PUSH_SERVER = DEFAULT_PUSH_SERVER;
|
||||||
DEFAULT_IMAGE_API_SERVER = DEFAULT_IMAGE_API_SERVER;
|
DEFAULT_IMAGE_API_SERVER = DEFAULT_IMAGE_API_SERVER;
|
||||||
|
DEFAULT_PARTNER_API_SERVER = DEFAULT_PARTNER_API_SERVER;
|
||||||
|
|
||||||
activeDid = "";
|
activeDid = "";
|
||||||
apiServer = "";
|
apiServer = "";
|
||||||
|
|||||||
@@ -50,7 +50,8 @@
|
|||||||
<h1 class="font-bold text-xl">Discuss Backups</h1>
|
<h1 class="font-bold text-xl">Discuss Backups</h1>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
8) Exporting backups <fa icon="circle-user" /> are important if they lose their phone --- especially for the Identifier Seed!
|
8) Exporting backups <fa icon="circle-user" /> are important if they lose their phone
|
||||||
|
--- especially for the Identifier Seed!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- eslint-disable prettier/prettier -->
|
<!-- eslint-disable prettier/prettier max-len -->
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
This app focuses on gifts & gratitude, using them to build cool things together with your network.
|
This app focuses on gifts & gratitude, using them to build cool things together with your network.
|
||||||
|
|||||||
@@ -145,6 +145,30 @@
|
|||||||
</l-map>
|
</l-map>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="showGeneralAdvanced && includeLocation && false"
|
||||||
|
class="items-center mb-4"
|
||||||
|
>
|
||||||
|
<div class="flex">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
v-model="sendToTrustroots"
|
||||||
|
@click="sendToTrustroots = !sendToTrustroots"
|
||||||
|
/>
|
||||||
|
<label>Send to Trustroots</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="mr-2"
|
||||||
|
v-model="sendToTripHopping"
|
||||||
|
@click="sendToTripHopping = !sendToTripHopping"
|
||||||
|
/>
|
||||||
|
<label>Send to TripHopping</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mt-8">
|
<div class="mt-8">
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||||
<button
|
<button
|
||||||
@@ -178,19 +202,25 @@
|
|||||||
import "leaflet/dist/leaflet.css";
|
import "leaflet/dist/leaflet.css";
|
||||||
import { AxiosError, AxiosRequestHeaders } from "axios";
|
import { AxiosError, AxiosRequestHeaders } from "axios";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
|
import { accountFromSeedWords } from "nostr-tools/nip06";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
|
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
|
||||||
import { Router } from "vue-router";
|
import { Router } from "vue-router";
|
||||||
|
|
||||||
import ImageMethodDialog from "@/components/ImageMethodDialog.vue";
|
import ImageMethodDialog from "@/components/ImageMethodDialog.vue";
|
||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "@/constants/app";
|
import {
|
||||||
|
DEFAULT_IMAGE_API_SERVER,
|
||||||
|
DEFAULT_PARTNER_API_SERVER,
|
||||||
|
NotificationIface,
|
||||||
|
} from "@/constants/app";
|
||||||
import { accountsDB, retrieveSettingsForActiveAccount } from "@/db/index";
|
import { accountsDB, retrieveSettingsForActiveAccount } from "@/db/index";
|
||||||
import {
|
import {
|
||||||
createEndorserJwtVcFromClaim,
|
createEndorserJwtVcFromClaim,
|
||||||
getHeaders,
|
getHeaders,
|
||||||
PlanVerifiableCredential,
|
PlanVerifiableCredential,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
|
import { getAccount } from "@/libs/util";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { ImageMethodDialog, LMap, LMarker, LTileLayer, QuickNav },
|
components: { ImageMethodDialog, LMap, LMarker, LTileLayer, QuickNav },
|
||||||
@@ -224,6 +254,9 @@ export default class NewEditProjectView extends Vue {
|
|||||||
numAccounts = 0;
|
numAccounts = 0;
|
||||||
projectId = "";
|
projectId = "";
|
||||||
projectIssuerDid = "";
|
projectIssuerDid = "";
|
||||||
|
sendToTrustroots = false;
|
||||||
|
sendToTripHopping = false;
|
||||||
|
showGeneralAdvanced = false;
|
||||||
startDateInput?: string;
|
startDateInput?: string;
|
||||||
startTimeInput?: string;
|
startTimeInput?: string;
|
||||||
zoneName = DateTime.local().zoneName;
|
zoneName = DateTime.local().zoneName;
|
||||||
@@ -236,6 +269,7 @@ export default class NewEditProjectView extends Vue {
|
|||||||
const settings = await retrieveSettingsForActiveAccount();
|
const settings = await retrieveSettingsForActiveAccount();
|
||||||
this.activeDid = settings.activeDid || "";
|
this.activeDid = settings.activeDid || "";
|
||||||
this.apiServer = settings.apiServer || "";
|
this.apiServer = settings.apiServer || "";
|
||||||
|
this.showGeneralAdvanced = !!settings.showGeneralAdvanced;
|
||||||
|
|
||||||
this.projectId = (this.$route as Router).query["projectId"] || "";
|
this.projectId = (this.$route as Router).query["projectId"] || "";
|
||||||
|
|
||||||
@@ -356,7 +390,7 @@ export default class NewEditProjectView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveProject(issuerDid: string) {
|
private async saveProject() {
|
||||||
// Make a claim
|
// Make a claim
|
||||||
const vcClaim: PlanVerifiableCredential = this.fullClaim;
|
const vcClaim: PlanVerifiableCredential = this.fullClaim;
|
||||||
if (this.projectId) {
|
if (this.projectId) {
|
||||||
@@ -407,13 +441,13 @@ export default class NewEditProjectView extends Vue {
|
|||||||
} else {
|
} else {
|
||||||
delete vcClaim.startTime;
|
delete vcClaim.startTime;
|
||||||
}
|
}
|
||||||
const vcJwt = await createEndorserJwtVcFromClaim(issuerDid, vcClaim);
|
const vcJwt = await createEndorserJwtVcFromClaim(this.activeDid, vcClaim);
|
||||||
|
|
||||||
// Make the xhr request payload
|
// Make the xhr request payload
|
||||||
|
|
||||||
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
||||||
const url = this.apiServer + "/api/v2/claim";
|
const url = this.apiServer + "/api/v2/claim";
|
||||||
const headers = await getHeaders(issuerDid);
|
const headers = await getHeaders(this.activeDid);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await this.axios.post(url, payload, { headers });
|
const resp = await this.axios.post(url, payload, { headers });
|
||||||
@@ -421,6 +455,22 @@ export default class NewEditProjectView extends Vue {
|
|||||||
this.errorMessage = "";
|
this.errorMessage = "";
|
||||||
|
|
||||||
const projectPath = encodeURIComponent(resp.data.success.handleId);
|
const projectPath = encodeURIComponent(resp.data.success.handleId);
|
||||||
|
|
||||||
|
if (this.sendToTrustroots) {
|
||||||
|
this.sendToNostrPartner(
|
||||||
|
"NOSTR-EVENT-TRUSTROOTS",
|
||||||
|
"Trustroots",
|
||||||
|
resp.data.success.claimId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (this.sendToTripHopping) {
|
||||||
|
this.sendToNostrPartner(
|
||||||
|
"NOSTR-EVENT-TRIPHOPPING",
|
||||||
|
"TripHopping",
|
||||||
|
resp.data.success.claimId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
(this.$router as Router).push({ path: "/project/" + projectPath });
|
(this.$router as Router).push({ path: "/project/" + projectPath });
|
||||||
} else {
|
} else {
|
||||||
console.error(
|
console.error(
|
||||||
@@ -485,6 +535,82 @@ export default class NewEditProjectView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async sendToNostrPartner(
|
||||||
|
linkCode: string,
|
||||||
|
serviceName: string,
|
||||||
|
jwtId: string,
|
||||||
|
) {
|
||||||
|
// first, get the public key for nostr
|
||||||
|
const account = await getAccount(this.activeDid);
|
||||||
|
// get the last number of the derivationPath
|
||||||
|
const finalDerNum = account?.derivationPath?.split?.("/")?.reverse()[0];
|
||||||
|
// remove any trailing '
|
||||||
|
const finalDerNumNoApostrophe = finalDerNum?.replace(/'/g, "");
|
||||||
|
const accountNum = Number(finalDerNumNoApostrophe || 0);
|
||||||
|
const pubPri = accountFromSeedWords(
|
||||||
|
account?.mnemonic as string,
|
||||||
|
"",
|
||||||
|
accountNum,
|
||||||
|
);
|
||||||
|
const nostrPubKey = pubPri?.publicKey;
|
||||||
|
|
||||||
|
const trustrootsUrl = DEFAULT_PARTNER_API_SERVER + "/api/partner/link";
|
||||||
|
const timeSafariUrl = window.location.origin + "/claim/" + jwtId;
|
||||||
|
const content = this.fullClaim.name + " - see " + timeSafariUrl;
|
||||||
|
const trustrootsParams = {
|
||||||
|
jwtId: jwtId,
|
||||||
|
linkCode: linkCode,
|
||||||
|
inputJson: JSON.stringify(content),
|
||||||
|
nostrPubKeyHex: nostrPubKey,
|
||||||
|
};
|
||||||
|
const fullTrustrootsUrl = trustrootsUrl;
|
||||||
|
const headers = await getHeaders(this.activeDid);
|
||||||
|
try {
|
||||||
|
const linkResp = await this.axios.post(
|
||||||
|
fullTrustrootsUrl,
|
||||||
|
trustrootsParams,
|
||||||
|
{ headers },
|
||||||
|
);
|
||||||
|
if (linkResp.status === 201) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "success",
|
||||||
|
title: `Sent to ${serviceName}`,
|
||||||
|
text: `The project info was sent to ${serviceName}.`,
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// axios never gets here because it throws an error, but just in case
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: `Failed Sending to ${serviceName}`,
|
||||||
|
text: JSON.stringify(linkResp.data),
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error sending to ${serviceName}`, error);
|
||||||
|
let errorMessage = `There was an error sending to ${serviceName}.`;
|
||||||
|
if (error.response?.data?.error?.message) {
|
||||||
|
errorMessage = error.response.data.error.message;
|
||||||
|
}
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: `Error Sending to ${serviceName}`,
|
||||||
|
text: errorMessage,
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async onSaveProjectClick() {
|
public async onSaveProjectClick() {
|
||||||
this.isHiddenSave = true;
|
this.isHiddenSave = true;
|
||||||
this.isHiddenSpinner = false;
|
this.isHiddenSpinner = false;
|
||||||
@@ -492,7 +618,7 @@ export default class NewEditProjectView extends Vue {
|
|||||||
if (this.numAccounts === 0) {
|
if (this.numAccounts === 0) {
|
||||||
console.error("Error: there is no account.");
|
console.error("Error: there is no account.");
|
||||||
} else {
|
} else {
|
||||||
this.saveProject(this.activeDid);
|
this.saveProject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,10 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- Ideally, this button should only be visible when the active account has more than 7 or 11 contacts in their list (we want to limit the grid count above to 8 or 12 accounts to keep it compact) -->
|
<!--
|
||||||
|
Ideally, this button should only be visible when the active account has more than 7 or 11 contacts in their list
|
||||||
|
(we want to limit the grid count above to 8 or 12 accounts to keep it compact)
|
||||||
|
-->
|
||||||
<a
|
<a
|
||||||
v-if="allContacts.length >= 7"
|
v-if="allContacts.length >= 7"
|
||||||
@click="onClickAllContactsGifting()"
|
@click="onClickAllContactsGifting()"
|
||||||
|
|||||||
@@ -150,7 +150,10 @@
|
|||||||
<span
|
<span
|
||||||
v-if="offer.amountGivenConfirmed >= offer.amountGiven"
|
v-if="offer.amountGivenConfirmed >= offer.amountGiven"
|
||||||
>
|
>
|
||||||
<!-- no need for green icon; unnecessary if there's already a green, confusing if there's a yellow -->
|
<!--
|
||||||
|
There's no need for a green icon:
|
||||||
|
it's unnecessary if there's already a green, and confusing if there's a yellow.
|
||||||
|
-->
|
||||||
all
|
all
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
|
|||||||
@@ -25,12 +25,13 @@
|
|||||||
Here is a view of the activity you can see.
|
Here is a view of the activity you can see.
|
||||||
<ul class="list-disc outside ml-4">
|
<ul class="list-disc outside ml-4">
|
||||||
<li>Each identity and claim has a unique position.</li>
|
<li>Each identity and claim has a unique position.</li>
|
||||||
<!-- eslint-disable prettier/prettier --><!-- If we format prettier then there is extra space at the start of the line. -->
|
<li>
|
||||||
<li>Each will show at their time of appearance relative to all others.</li>
|
Each will show at their time of appearance relative to all others.
|
||||||
<li>Note that the ones on the left and right edges are randomized
|
</li>
|
||||||
because their data isn't all visible to you.
|
<li>
|
||||||
|
Note that the ones on the left and right edges are randomized because
|
||||||
|
their data isn't all visible to you.
|
||||||
</li>
|
</li>
|
||||||
<!-- eslint-enable -->
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -46,7 +47,9 @@
|
|||||||
{{ worldProperties.animationDurationSeconds }} seconds
|
{{ worldProperties.animationDurationSeconds }} seconds
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="float-right text-blue-600" @click="captureGraphics()">Screenshot</button>
|
<button class="float-right text-blue-600" @click="captureGraphics()">
|
||||||
|
Screenshot
|
||||||
|
</button>
|
||||||
<div id="scene-container" class="h-screen"></div>
|
<div id="scene-container" class="h-screen"></div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user