much miscellany for small features and documentation & testing #82

Merged
anomalist merged 5 commits from many-misc into master 1 year ago
  1. 159
      README.md
  2. 43
      project.task.yaml
  3. 5
      src/views/AccountViewView.vue
  4. 23
      src/views/ContactQRScanShowView.vue
  5. 60
      src/views/ContactsView.vue
  6. 19
      src/views/DiscoverView.vue
  7. 114
      src/views/HelpView.vue
  8. 2
      src/views/HomeView.vue
  9. 24
      src/views/NewIdentifierView.vue
  10. 5
      src/views/SearchAreaView.vue
  11. 21
      src/views/StartView.vue
  12. 26
      src/views/StatisticsView.vue
  13. 24
      src/views/TestView.vue

159
README.md

@ -26,31 +26,13 @@ npm run build
npm run lint
```
## Tests
### Web-push
For your own web-push tests, change the 'vapid' URL in App.vue, and install apps on the same domain.
### Test key contents
See [this page](openssl_signing_console.rst)
## Tests
### Register new user on test server
New users require registration. This can be done with a claim payload like this
by an existing user:
```
const vcClaim = {
"@context": "https://schema.org",
"@type": "RegisterAction",
agent: { identifier: identity0.did },
object: SERVICE_ID,
participant: { identifier: newIdentity.did },
};
```
On the test server, User #0 has rights to register others, so you can start
playing one of two ways:
@ -66,14 +48,35 @@ playing one of two ways:
### Create multiple identifiers
Go to /start and create or import a new one. Then switch identifiers on the bottom of the Your Identity page.
Under the "Your Identity" screen, click "Advanced", click "Switch Identity / No Identity", then "Add Another Identity...".
### Create keys with alternate tools
See [this page](openssl_signing_console.rst)
[This page](openssl_signing_console.rst) is a tool to create a JWT from a locally-generated keypair.
### Web-push
For your own web-push tests, change the 'vapid' URL in App.vue, and install apps on the same domain.
### Manual walk-through
- Clear the browser cache for localhost for a new user.
- See that it's using the test API.
- On each page, verify the messaging.
- On the home page, see the feed without names, and see a message prompting to generate an ID.
- On the discovery page, check that they can see projects, and set a search area to see projects nearby.
- As User #0 in another browser on the test API, add a give & a project. (See User #0 details above.)
- With the new user on the home page, see the feed that shows User #0 in network but without the name.
- As the new user on the contacts page, add User #0 as a contact.
- On the home page, see the feed that shows User #0 with a name.
- Generate an ID.
- On the home page, check that it now prompts them to get registered.
- On the account page, check that they see messages on limits.
- Register the ID from User #0.
- As the new user on the home page, check that they can now record a gift.
- On the contacts page, check that they cannot register someone else yet.
- Walk through the functions on each page.
### Customize Vue configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
## Scenarios
@ -90,8 +93,8 @@ See [Configuration Reference](https://cli.vuejs.org/config/).
### Clear data & restart
Clear cache for localhost, then go to http://localhost:8080/start
(because it'll generate a new one automatically if you start on the `/account` page).
Clear the browser cache for localhost.
@ -102,110 +105,10 @@ Clear cache for localhost, then go to http://localhost:8080/start
* Notifications can be type of `toast` (self-dismiss), `info`, `success`, `warning`, and `danger`.
They are done via [notiwind](https://www.npmjs.com/package/notiwind) and set up in App.vue.
```
// reference material from https://github.com/trentlarson/endorser-mobile/blob/8dc8e0353e0cc80ffa7ed89ded15c8b0da92726b/src/utility/idUtility.ts#L83
// Import an existing ID
export const importAndStoreIdentifier = async (mnemonic: string, mnemonicPassword: string, toLowercase: boolean, previousIdentifiers: Array<IIdentifier>) => {
// just to get rid of variability that might cause an error
mnemonic = mnemonic.trim().toLowerCase()
/**
// an approach I pieced together
// requires: yarn add elliptic
// ... plus:
// const EC = require('elliptic').ec
// const secp256k1 = new EC('secp256k1')
//
const keyHex: string = bip39.mnemonicToEntropy(mnemonic)
// returns a KeyPair from the elliptic.ec library
const keyPair = secp256k1.keyFromPrivate(keyHex, 'hex')
// this code is from did-provider-eth createIdentifier
const privateHex = keyPair.getPrivate('hex')
const publicHex = keyPair.getPublic('hex')
const address = didJwt.toEthereumAddress(publicHex)
**/
/**
// from https://github.com/uport-project/veramo/discussions/346#discussioncomment-302234
// ... which almost works but the didJwt.toEthereumAddress is wrong
// requires: yarn add bip32
// ... plus: import * as bip32 from 'bip32'
//
const seed: Buffer = await bip39.mnemonicToSeed(mnemonic)
const root = bip32.fromSeed(seed)
const node = root.derivePath(UPORT_ROOT_DERIVATION_PATH)
const privateHex = node.privateKey.toString("hex")
const publicHex = node.publicKey.toString("hex")
const address = didJwt.toEthereumAddress('0x' + publicHex)
**/
/**
// from https://github.com/uport-project/veramo/discussions/346#discussioncomment-302234
// requires: yarn add @ethersproject/hdnode
// ... plus: import { HDNode } from '@ethersproject/hdnode'
**/
const hdnode: HDNode = HDNode.fromMnemonic(mnemonic)
const rootNode: HDNode = hdnode.derivePath(UPORT_ROOT_DERIVATION_PATH)
const privateHex = rootNode.privateKey.substring(2) // original starts with '0x'
const publicHex = rootNode.publicKey.substring(2) // original starts with '0x'
let address = rootNode.address
const prevIds = previousIdentifiers || [];
if (toLowercase) {
const foundEqual = R.find(
(id) => utility.rawAddressOfDid(id.did) === address,
prevIds
)
if (foundEqual) {
// They're trying to create a lowercase version of one that exists in normal case.
// (We really should notify the user.)
appStore.dispatch(appSlice.actions.addLog({log: true, msg: "Will create a normal-case version of the DID since a regular version exists."}))
} else {
address = address.toLowerCase()
}
} else {
// They're not trying to convert to lowercase.
const foundLower = R.find((id) =>
utility.rawAddressOfDid(id.did) === address.toLowerCase(),
prevIds
)
if (foundLower) {
// They're trying to create a normal case version of one that exists in lowercase.
// (We really should notify the user.)
appStore.dispatch(appSlice.actions.addLog({log: true, msg: "Will create a lowercase version of the DID since a lowercase version exists."}))
address = address.toLowerCase()
}
}
appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... derived keys and address..."}))
const newId = newIdentifier(address, publicHex, privateHex, UPORT_ROOT_DERIVATION_PATH)
appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... created new ID..."}))
// awaiting because otherwise the UI may not see that a mnemonic was created
const savedId = await storeIdentifier(newId, mnemonic, mnemonicPassword)
appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... stored new ID..."}))
return savedId
}
// Create a totally new ID
export const createAndStoreIdentifier = async (mnemonicPassword) => {
// This doesn't give us the entropy/seed.
//const id = await agent.didManagerCreate()
const entropy = crypto.randomBytes(32)
const mnemonic = bip39.entropyToMnemonic(entropy)
appStore.dispatch(appSlice.actions.addLog({log: false, msg: "... generated mnemonic..."}))
return importAndStoreIdentifier(mnemonic, mnemonicPassword, false, [])
}
```
* [Customize Vue configuration](https://cli.vuejs.org/config/).
## Kudos
### Kudos
Gifts make the world go 'round!

43
project.task.yaml

@ -5,41 +5,32 @@ tasks:
- 40 notifications :
- push, where we trigger a ServiceWorker(?) in the app to reach out and check for new data assignee:matthew
- 01 Ensure each action sent to the server has a confirmation - eg registration (ie a toast something that dismisses after 5-10s)
- Home Feed & Quick Give screen :
- 01 save the feed-viewed status in settings storage ("afterQuery")
- 01 quick action - send action, maybe choose via canvas tool
- SEE: https://github.com/konvajs/vue-konva
- 24 Move to Vite assignee:matthew
- .5 add project ID to the URL of the project-view, to make a project publicly-accessible
- .5 add link to further project / people when a project pays ahead
- .5 show checkbox on "gave" modal to say that user is recipient (so it could be uncheked for someone unspecified)
- .5 allow to manage their notifications even without an identity
- .5 bug - on the discover page, enter a search term and search and see a duplicate project show at the end of the list
- 01 Ensure each action sent to the server has a confirmation - eg registration (ie a toast something that dismisses after 5-10s)
- .3 fix the Project-location-selection map display to not show on top of bottom icons (and any other UI tweaks on the map flow) assignee-group:ui
- .5 switch so DiscoverView shows anywhere by default, and no number unless search is done (and maybe a better filter UI, including "mine" to consolidate with ProjectsView)
- .5 Add infinite scroll to gifts on the home page
- .5 bug - search for "Safari" does not find the project, but if already on the "Anywhere" tab it shows all
- .2 figure out why endorser-mobile search doesn't find recently created PlanAction
- .1 when creating a plan, select location and then make sure you can deselect on Android
- .5 add link to further project / people when a project pays ahead
- .5 add project ID to the URL of the project-view, to make a project publicly-accessible
- .5 fix where user 0 sees no txns from user 1 on contacts page but sees them on list page
- .2 on ProjectViewView, show different messages for "to" and "from" sections if none exist
- .2 fix rate limit verbiage (with the new one-per-day allowance) assignee:trent
- .1 remove the logic to exclude beforeId in list of plans after server has commit 26b25af605e715600d4f12b6416ed9fd7142d164
- .1 remove the logic to exclude beforeId in list of plans after server has commit 26b25af605e715600d4f12b6416ed9fd7142d164 assignee:trent
- .2 in SeedBackupView, don't load the mnemonic and keep it in memory; only load it when they click "show"
- .1 Make give description text box into something that expands as they type
- .1 Make contact info specific to Time Safari - rather pointing at CommunityCred.org
- Discuss whether the remaining tasks are worthwhile before MVP release.
- .1 Make give description text box into something that expands as they type?
- 04 allow user to download claims, mine + ones I can see about me from others
- 02 allow user to create new DIDs from the same seed phrase (ie. increment derivation path)
- .5 on ProjectView page, show immediate feedback when a gift is given (on list?) -- and consider the same for Home & Contacts pages
- .5 customize favicon assignee-group:ui
- .2 Show a warning if both giver and recipient are the same (but still allow?)
- 01 Would it look better to shrink the buttons on many pages so they don't expand to the width of the screen? assignee-group:ui
- .5 Display a more appealing confirmation on the map when erasing the marker
- .5 make a VC details page
- .5 make a VC details page, or link to endorser.ch
- .1 Add units or different icon to the coins (to distinguish $, BTC, hours, etc)
- .5 include the hash of the latest commit on help page next to version
- .5 remove references to localStorage for projectId (now that it's pulling from the path)
@ -51,7 +42,7 @@ tasks:
- stats v1 :
- 01 show numeric stats
- 04 show different graphic for projects vs people on world
- 04 show different graphic for projects vs people (gnome?) on world
- 01 link to world for specific stats
- .5 don't load another instance of a bush if it already exists
- maybe - allow type annotations in World.js & landmarks.js (since we get this error - "Types are not supported by current JavaScript version")
@ -69,7 +60,9 @@ tasks:
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
- .5 show seed phrase in a QR code for transfer to another device
- .5 on DiscoverView, switch to a filter UI (eg. just from friend
- 24 Move to Vite
- 32 accept images for projects
- 32 accept images for contacts
@ -99,11 +92,10 @@ tasks:
- Multiple identities
- Peer DID
- DIDComm
- Write to or read from a different ledger (eg. private ACDC, attest.sh)
- Support KERI AIDs
- Support Peer DIDs
- Support messaging through DIDComm
- Write to or read from a different ledger (eg. private ACDC, EAS & attest.sh)
- Do we want split first name & last name?
@ -111,6 +103,7 @@ tasks:
- pull, w/ scheduled runs
- 01 On nearby search, if user starts changing their box but cancels and goes back to the map it is zoomed far out. Fix to fit the box better.
- 16 From the home screen, make the quick action even easier.
log:
- videos for multiple identities https://youtu.be/p8L87AeD76w and for adding time to contacts https://youtu.be/7Yylczevp10 done:2023-03-29

5
src/views/AccountViewView.vue

@ -186,8 +186,9 @@
</p>
<p>
You have done {{ limits.doneRegistrationsThisMonth }} registrations
out of {{ limits.maxRegistrationsPerMonth }} for this month. Your
registrations counter resets at
out of {{ limits.maxRegistrationsPerMonth }} for this month. (You can
register nobody on your first day, and after that only one a day in
your first month.) Your registration counter resets at
{{ readableTime(limits.nextMonthBeginDateTime) }}
</p>
</div>

23
src/views/ContactQRScanShowView.vue

@ -2,10 +2,23 @@
<QuickNav selected="Profile"></QuickNav>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4">
Your Contact Info
</h1>
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<fa icon="chevron-left" class="fa-fw"></fa>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4">
Your Contact Info
</h1>
</div>
<!--
Play with display options: https://qr-code-styling.com/
@ -137,7 +150,7 @@ export default class ContactQRScanShow extends Vue {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onScanDetect(content: any) {
if (content[0]?.rawValue) {
console.log("onDetect", content[0].rawValue);
//console.log("onDetect", content[0].rawValue);
localStorage.setItem("contactEndorserUrl", content[0].rawValue);
this.$router.push({ name: "contacts" });
} else {

60
src/views/ContactsView.vue

@ -113,7 +113,7 @@
<button
v-if="contact.seesMe"
class="text-sm uppercase bg-slate-500 text-white px-2 py-1.5 rounded-md"
@click="setVisibility(contact, false)"
@click="setVisibility(contact, false, true)"
title="They can see you"
>
<fa icon="eye" class="fa-fw" />
@ -121,7 +121,7 @@
<button
v-else
class="text-sm uppercase bg-slate-500 text-white px-2 py-1.5 rounded-md"
@click="setVisibility(contact, true)"
@click="setVisibility(contact, true, true)"
title="They cannot see you"
>
<fa icon="eye-slash" class="fa-fw" />
@ -137,7 +137,7 @@
<button
@click="register(contact)"
class="text-sm uppercase bg-slate-500 text-white px-2 py-1.5 rounded-md"
class="text-sm uppercase bg-slate-500 text-white ml-6 px-2 py-1.5 rounded-md"
>
<fa
v-if="contact.registered"
@ -155,7 +155,7 @@
<button
@click="deleteContact(contact)"
class="text-sm uppercase bg-red-600 text-white px-2 py-1.5 rounded-md"
class="text-sm uppercase bg-red-600 text-white ml-24 px-2 py-1.5 rounded-md"
title="Delete"
>
<fa icon="trash-can" class="fa-fw" />
@ -531,6 +531,7 @@ export default class ContactsView extends Vue {
);
return;
}
newContact.seesMe = true; // since we will immediately set that on the server
return db.contacts
.add(newContact)
.then(() => {
@ -539,12 +540,28 @@ export default class ContactsView extends Vue {
(a: Contact, b) => (a.name || "").localeCompare(b.name || ""),
allContacts,
);
this.setVisibility(newContact, true, false);
this.$notify(
{
group: "alert",
type: "success",
title: "Contact added",
text: newContact.name + " was added.",
title: "Contact Added",
text:
newContact.name +
" was added, and your activity is visible to them.",
},
-1,
);
// putting this last so that it shows on the top
this.$notify(
{
group: "alert",
type: "info",
title: "New User?",
text:
"If " +
newContact.name +
" is a new user, be sure to register them.",
},
-1,
);
@ -556,7 +573,7 @@ export default class ContactsView extends Vue {
group: "alert",
type: "danger",
title: "Contact Not Added",
text: "An error prevented importing.",
text: "An error prevented this import.",
},
-1,
);
@ -566,11 +583,13 @@ export default class ContactsView extends Vue {
async deleteContact(contact: Contact) {
if (
confirm(
"Are you sure you want to delete " +
"You should first make sure that your activity is no longer visible to them." +
" Note that this only deletes them from your contacts on this device." +
" \n\nAre you sure you want to remove " +
this.nameForDid(this.contacts, contact.did) +
" with DID " +
contact.did +
" ?",
" from your contact list?",
)
) {
await db.open();
@ -692,7 +711,11 @@ export default class ContactsView extends Vue {
}
}
async setVisibility(contact: Contact, visibility: boolean) {
async setVisibility(
contact: Contact,
visibility: boolean,
showSuccessAlert: boolean,
) {
const url =
this.apiServer +
"/api/report/" +
@ -704,6 +727,21 @@ export default class ContactsView extends Vue {
try {
const resp = await this.axios.post(url, payload, { headers });
if (resp.status === 200) {
if (showSuccessAlert) {
this.$notify(
{
group: "alert",
type: "success",
title: "Visibility Set",
text:
this.nameForDid(this.contacts, contact.did) +
" can " +
(visibility ? "" : "not ") +
"see your activity.",
},
-1,
);
}
contact.seesMe = visibility;
db.contacts.update(contact.did, { seesMe: visibility });
} else {
@ -756,7 +794,7 @@ export default class ContactsView extends Vue {
{
group: "alert",
type: "info",
title: "Refreshed",
title: "Visibility Refreshed",
text:
this.nameForContact(contact, true) +
" can " +

19
src/views/DiscoverView.vue

@ -41,7 +41,7 @@
Nearby
<span
class="font-semibold text-sm bg-slate-200 px-1.5 py-0.5 rounded-md"
>{{ localCount }}</span
>{{ localCount > -1 ? localCount : "?" }}</span
>
</a>
</li>
@ -59,7 +59,7 @@
Anywhere
<span
class="font-semibold text-sm bg-slate-200 px-1.5 py-0.5 rounded-md"
>{{ remoteCount }}</span
>{{ remoteCount > -1 ? remoteCount : "?" }}</span
>
</a>
</li>
@ -86,7 +86,7 @@
</div>
<!-- Results List -->
<InfiniteScroll @reached-bottom="loadMoreData" v-if="!isChoosingSearchBox">
<InfiniteScroll @reached-bottom="loadMoreData">
<ul>
<li
class="border-b border-slate-300"
@ -156,11 +156,10 @@ export default class DiscoverView extends Vue {
apiServer = "";
searchTerms = "";
projects: ProjectData[] = [];
isChoosingSearchBox = false;
isLocalActive = true;
isRemoteActive = false;
localCount = 0;
remoteCount = 0;
localCount = -1;
remoteCount = -1;
searchBox: { name: string; bbox: BoundingBox } | null = null;
isLoading = false;
@ -180,7 +179,13 @@ export default class DiscoverView extends Vue {
const allAccounts = await accountsDB.accounts.toArray();
this.allMyDids = allAccounts.map((acc) => acc.did);
this.searchLocal();
if (this.searchBox) {
await this.searchLocal();
} else {
this.isLocalActive = false;
this.isRemoteActive = true;
await this.searchAll();
}
}
public async buildHeaders(): Promise<HeadersInit> {

114
src/views/HelpView.vue

@ -1,11 +1,25 @@
<template>
<QuickNav selected="Profile"></QuickNav>
<QuickNav />
<!-- CONTENT -->
<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>
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<fa icon="chevron-left" class="fa-fw"></fa>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Help
</h1>
</div>
<div>
<p>
@ -15,7 +29,7 @@
<h2 class="text-xl font-semibold">What is the philosophy here?</h2>
<p>
We are building networks of people who want to grow a gifting society.
We are building networks of people who want to grow a giving society.
First of all, you can record ways you've seen people give, and that
leaves a permanent record -- one that came from you, and the recipient
can prove it was for them. This is personally gratifying, but it extends
@ -36,22 +50,39 @@
the control; this app gives you the control.
</p>
<h2 class="text-xl font-semibold">How do I take my first action?</h2>
<h2 class="text-xl font-semibold">How do I get started?</h2>
<p>
You need someone to register you -- usually the person who told you
about this app, on the Contacts
<fa icon="circle-user" class="fa-fw" /> page. After they register you,
you can select any contact on the home page (or "anonymous") and record
your appreciation for... whatever. The main goal is to record what
people have given you, to grow gifting economies. Each claim is recorded
on a custom ledger. The day after being registered, you'll be able to
able to register others; later, you can create projects, too.
<fa icon="users" class="fa-fw" /> page. After they register you, you can
select any contact on the home page (or "anonymous") and record your
appreciation for... whatever. The main goal is to record what people
have given you, to grow giving economies. Each claim is recorded on a
custom ledger. The day after being registered, you'll be able to able to
register others; later, you can create projects, too.
</p>
<p>
Note that there are limits to how many others each person can register,
so you may have to wait.
</p>
<h2 class="text-xl font-semibold">How do I add someone else?</h2>
<p>
<button class="text-blue-500" @click="showOnboardInfo">
Click here to show an alert with the steps.
</button>
To start scanning, go
<router-link class="text-blue-500" to="/contact-qr">here.</router-link>
</p>
<p>
If they are not nearby to scan QR codes, tell them to copy their ID from
their Identity <fa icon="circle-user" class="fa-fw" /> page, 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. To add a name, put a comma and then their name; to add their
public key, put another comma followed by the key.
</p>
<h2 class="text-xl font-semibold">How do I backup all my data?</h2>
<p>
There are two sets of data to backup: the identifier secrets and the
@ -113,27 +144,20 @@
How do I restore my other (non-identifier-secret) data?
</h2>
<ul class="list-disc list-inside">
<li>Make sure you have your backup file (above), then contact us.</li>
<li>
Make sure you have your backup file (above), then contact us with
your interest. This is functionality that has to be written, and
your interest will help us prioritize it, but there are also manual
ways to restore your data.
</li>
</ul>
</div>
<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="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">How do I create another identity?</h2>
<p>
Before doing this, note that it is an advanced feature that affects
functionality (eg. the words "Alt ID" next to results, backup features)
so beware if you think that may cause confusion. You can
so beware. You can
<router-link to="start" class="text-blue-500">
create another identity here.
</router-link>
@ -151,10 +175,10 @@
<fa icon="eye-slash" class="fa-fw" />.
</p>
<p>
Sometimes the reason you don't see something is because the search time
is limited. Go to the bottom and make sure to load all the data on a
list. If you still don't see it, try a search or view on a different
page.
Sometimes the reason you don't see something is because the search
results are limited. Go to the bottom and make sure to load all the data
on a list. If you still don't see it, try a search or view on a
different page.
</p>
<h2 class="text-xl font-semibold">What is your privacy policy?</h2>
@ -171,11 +195,11 @@
</p>
<h2 class="text-xl font-semibold">
For any other questions, including remove your data:
For any other questions, including removing your data:
</h2>
<p>
Contact us through
<a href="https://communitycred.org">CommunityCred.org</a>.
Contact us at
<a mailto="info@TimeSafari.app">info@TimeSafari.app</a>
</p>
</div>
</section>
@ -186,8 +210,30 @@ import * as Package from "../../package.json";
import { Component, Vue } from "vue-facing-decorator";
import QuickNav from "@/components/QuickNav.vue";
interface Notification {
group: string;
type: string;
title: string;
text: string;
}
@Component({ components: { QuickNav } })
export default class Help extends Vue {
$notify!: (notification: Notification, timeout?: number) => void;
package = Package;
showOnboardInfo() {
this.$notify(
{
group: "alert",
type: "info",
title: "Onboard Someone",
// If you edit this, check that the numbers still line up on the side in the alert (on mobile, preferably).
text: "1) Check that they've entered their name. 2) Go to the scanning page via the Identity page and then the through the QR icon at the top, and then scan and register them. 3) Have them go to that page and scan you.",
},
-1,
);
}
}
</script>

2
src/views/HomeView.vue

@ -29,7 +29,7 @@
<div v-else>
<!-- activeDid && isRegistered -->
<h2 class="text-xl font-bold">Record a Gift</h2>
<h2 class="text-xl font-bold">Record Something Given</h2>
<ul class="grid grid-cols-4 gap-x-3 gap-y-5 text-center mb-5">
<li @click="openDialog()">

24
src/views/NewIdentifierView.vue

@ -1,11 +1,25 @@
<template>
<QuickNav selected="Profile"></QuickNav>
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Your Identity
</h1>
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<fa icon="chevron-left" class="fa-fw"></fa>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Your Identity
</h1>
</div>
<div class="flex justify-center py-12">
<span />

5
src/views/SearchAreaView.vue

@ -1,4 +1,6 @@
<template>
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24">
<!-- Breadcrumb -->
@ -105,6 +107,7 @@ import {
import { db } from "@/db/index";
import { BoundingBox, MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import QuickNav from "@/components/QuickNav.vue";
const DEFAULT_LAT_LONG_DIFF = 0.01;
const WORLD_ZOOM = 2;
@ -119,6 +122,7 @@ interface Notification {
@Component({
components: {
QuickNav,
LRectangle,
LMap,
LMarker,
@ -214,6 +218,7 @@ export default class DiscoverView extends Vue {
},
-1,
);
this.$router.back();
} catch (err) {
this.$notify(
{

21
src/views/StartView.vue

@ -3,10 +3,23 @@
id="Content"
class="p-6 pb-24 min-h-screen flex flex-col justify-center"
>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Start Here
</h1>
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<fa icon="chevron-left" class="fa-fw"></fa>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Start Here
</h1>
</div>
<!-- id used by puppeteer test script -->
<div id="start-question" class="mt-8">

26
src/views/StatisticsView.vue

@ -1,11 +1,25 @@
<template>
<QuickNav selected="Profile"></QuickNav>
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Achievements & Statistics
</h1>
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<fa icon="chevron-left" class="fa-fw"></fa>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Achievements & Statistics
</h1>
</div>
<div>
Here is a view of the activity you can see.
@ -32,7 +46,7 @@
{{ worldProperties.animationDurationSeconds }} seconds
</div>
</div>
<button class="float-right" @click="captureGraphics()">Screenshot</button>
<button class="float-right text-blue-600" @click="captureGraphics()">Screenshot</button>
<div id="scene-container" class="h-screen"></div>
</section>
</template>

24
src/views/TestView.vue

@ -1,11 +1,25 @@
<template>
<QuickNav selected="Profile"></QuickNav>
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Test
</h1>
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<fa icon="chevron-left" class="fa-fw"></fa>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Test
</h1>
</div>
<div class="mb-8">
<h2 class="text-xl font-bold mb-4">Notiwind Alert Test Suite</h2>

Loading…
Cancel
Save