forked from trent_larson/crowd-funder-for-time-pwa
Compare commits
10 Commits
home-infin
...
claim-view
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4b78f6a2c | ||
|
|
3c0f6ce0de | ||
| 5534f8fa50 | |||
| a5004d475e | |||
| b445b1234f | |||
| 17c96dd01a | |||
| 6ad17101b2 | |||
| b4085ffaa7 | |||
| 4f2cb55753 | |||
| ebf9164ecc |
@@ -9,7 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
|
||||||
## [0.1.6]
|
## [0.1.6] - 2023.12.17
|
||||||
|
### Added
|
||||||
|
- Infinite scroll on home page
|
||||||
|
### Changed
|
||||||
|
- UI improvements
|
||||||
|
- Show web-push subscription info
|
||||||
|
- Icon
|
||||||
|
|
||||||
|
|
||||||
## [0.1.5] - 2023.12.09 - 9c36bb509a9bae9bb3306d3bd9eeb144b67aa8ad
|
## [0.1.5] - 2023.12.09 - 9c36bb509a9bae9bb3306d3bd9eeb144b67aa8ad
|
||||||
|
|||||||
@@ -26,13 +26,15 @@ If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js,
|
|||||||
|
|
||||||
...to make sure the service worker scripts are in proper form
|
...to make sure the service worker scripts are in proper form
|
||||||
|
|
||||||
* Update the CHANGELOG.md & the version in package.json, run `npm install`, and commit. Tag wth the new version: `git tag 0.1.0`
|
* Update the CHANGELOG.md & the version in package.json, run `npm install`, and commit.
|
||||||
|
|
||||||
|
* Tag wth the new version: `git tag 0.1.0`. Increment version, add "-beta", `npm install`, and commit.
|
||||||
|
|
||||||
* If production, change src/constants/app.ts DEFAULT_*_SERVER to be PROD.
|
* If production, change src/constants/app.ts DEFAULT_*_SERVER to be PROD.
|
||||||
|
|
||||||
* `npm run build`
|
* `npm run build`
|
||||||
|
|
||||||
* Revert src/constants/app.ts & change version to "-beta"
|
* Revert src/constants/app.ts
|
||||||
|
|
||||||
* `cp sw_scripts/[ns]* dist/`
|
* `cp sw_scripts/[ns]* dist/`
|
||||||
|
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "TimeSafari",
|
"name": "TimeSafari",
|
||||||
"version": "0.1.6-beta",
|
"version": "0.1.7-beta",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "TimeSafari",
|
"name": "TimeSafari",
|
||||||
"version": "0.1.6-beta",
|
"version": "0.1.7-beta",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ethersproject/hdnode": "^5.7.0",
|
"@ethersproject/hdnode": "^5.7.0",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "TimeSafari",
|
"name": "TimeSafari",
|
||||||
"version": "0.1.6-beta",
|
"version": "0.1.7-beta",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
|
|||||||
@@ -2,30 +2,26 @@
|
|||||||
tasks:
|
tasks:
|
||||||
|
|
||||||
- 08 notifications :
|
- 08 notifications :
|
||||||
- get it to work on Android
|
- get it to work on Android - background data in apps
|
||||||
- get it to work on iOS
|
- get it to work on iOS
|
||||||
- lock down regenerate_vapid endpoint (so only we admins can do it on demand)
|
|
||||||
- make the app behave correctly when App Notifications are turned off
|
- make the app behave correctly when App Notifications are turned off
|
||||||
- remove sleep in py-push-server app.py?
|
|
||||||
- write troubleshooting docs for notifications
|
- write troubleshooting docs for notifications
|
||||||
- make the "App Notifications" toggle on when they turn notifications on
|
- hide the "App Notifications" toggle when they switch notifications
|
||||||
- make the "App Notifications" toggle off when they turn notifications off
|
- prompt user to install on their home screen https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getInstalledRelatedApps
|
||||||
- in py-push-server, when sending a push to a subscriber and we get on a 410 "error #106", delete the subscription record
|
- warn if they're using the web (android only?)
|
||||||
- https://gitea.anomalistdesign.com/trent_larson/py-push-server/pulls/3/files
|
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getInstalledRelatedApps
|
||||||
- remove "notification push server" advanced setting since it only makes sense on the current domain
|
https://web.dev/articles/get-installed-related-apps
|
||||||
- prompt user to install on their home screen
|
- add windows & mac help at OS & browser level
|
||||||
|
|
||||||
- back-and-forth on discovery & project pages led to "You need an identity to load your projects." error on product page when I had an identity
|
- back-and-forth on discovery & project pages led to "You need an identity to load your projects." error on product page when I had an identity
|
||||||
- fix the projects on /discover to show the issuer (currently all "Someone Anonymous")
|
- fix the projects on /discover to show the issuer (currently all "Someone Anonymous")
|
||||||
|
|
||||||
- .3 bug - make or edit a project, choose "Include location", and see the map display shows on top of the bottom icons assignee-group:ui
|
- .3 bug - make or edit a project, choose "Include location", and see the map display shows on top of the bottom icons assignee-group:ui
|
||||||
|
- Got error adding on Firefox user #0 as contact for themselves
|
||||||
- .5 Add infinite scroll to gifts on the home page
|
|
||||||
|
|
||||||
- .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
|
||||||
|
|
||||||
- 01 server - show all claim details when issued by the issuer
|
- 01 server - show all claim details when issued by the issuer
|
||||||
- add note after contact addition that they can see your info
|
|
||||||
- enhance help page instructions for debugging
|
- enhance help page instructions for debugging
|
||||||
- add way to test quickly a push notification
|
- add way to test quickly a push notification
|
||||||
- help instructions for PWA install problems (secret failed, must reinstall)
|
- help instructions for PWA install problems (secret failed, must reinstall)
|
||||||
@@ -50,10 +46,10 @@ tasks:
|
|||||||
- Other features - donation vs give, show offers, show give & outstanding totals, show network view, restrict registration, connect to contacts
|
- Other features - donation vs give, show offers, show give & outstanding totals, show network view, restrict registration, connect to contacts
|
||||||
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
|
||||||
|
|
||||||
|
- 01 send visibility signal as a VC and store it
|
||||||
- remove 'rowid' references (that are sqlite-specific)
|
- remove 'rowid' references (that are sqlite-specific)
|
||||||
- make identicons for contacts into more-memorable faces (and maybe change project identicons, too)
|
- make identicons for contacts into more-memorable faces (and maybe change project identicons, too)
|
||||||
- 01 make the prod build copy the sw_scripts
|
- 01 make the prod build copy the sw_scripts
|
||||||
- 01 send visibility signal as a VC and store it
|
|
||||||
- .5 Add start date to project
|
- .5 Add start date to project
|
||||||
- .3 check that Android shows "back" buttons on screens without bottom tray
|
- .3 check that Android shows "back" buttons on screens without bottom tray
|
||||||
- .1 Make give description text box into something that expands as they type?
|
- .1 Make give description text box into something that expands as they type?
|
||||||
|
|||||||
58
src/components/TopMessage.vue
Normal file
58
src/components/TopMessage.vue
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<div class="text-center text-red-500">{{ message }}</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue, Prop } from "vue-facing-decorator";
|
||||||
|
import { db } from "@/db/index";
|
||||||
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
|
import { AppString } from "@/constants/app";
|
||||||
|
|
||||||
|
interface Notification {
|
||||||
|
group: string;
|
||||||
|
type: string;
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class TopMessage extends Vue {
|
||||||
|
$notify!: (notification: Notification, timeout?: number) => void;
|
||||||
|
|
||||||
|
@Prop selected = "";
|
||||||
|
|
||||||
|
message = "";
|
||||||
|
|
||||||
|
async mounted() {
|
||||||
|
try {
|
||||||
|
await db.open();
|
||||||
|
|
||||||
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||||
|
if (
|
||||||
|
settings?.warnIfTestServer &&
|
||||||
|
window.location.hostname !== AppString.PROD_TIME_SAFARI_SERVER_HOST
|
||||||
|
) {
|
||||||
|
const didPrefix = settings.activeDid?.slice(11, 14);
|
||||||
|
this.message = "You're linked to a test server, user " + didPrefix;
|
||||||
|
} else if (
|
||||||
|
settings?.warnIfProdServer &&
|
||||||
|
window.location.hostname === AppString.PROD_TIME_SAFARI_SERVER_HOST
|
||||||
|
) {
|
||||||
|
const didPrefix = settings.activeDid?.slice(1, 14);
|
||||||
|
this.message =
|
||||||
|
"You're linked to the production server, user " + didPrefix;
|
||||||
|
}
|
||||||
|
} catch (err: unknown) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error Detecting Server",
|
||||||
|
text: JSON.stringify(err),
|
||||||
|
},
|
||||||
|
10000,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -6,12 +6,16 @@
|
|||||||
export enum AppString {
|
export enum AppString {
|
||||||
APP_NAME = "Time Safari",
|
APP_NAME = "Time Safari",
|
||||||
|
|
||||||
|
PROD_TIME_SAFARI_SERVER_HOST = "timesafari.app",
|
||||||
|
PROD_TIME_SAFARI_SERVER = "https://" + PROD_TIME_SAFARI_SERVER_HOST,
|
||||||
|
|
||||||
PROD_ENDORSER_API_SERVER = "https://api.endorser.ch",
|
PROD_ENDORSER_API_SERVER = "https://api.endorser.ch",
|
||||||
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",
|
||||||
|
|
||||||
DEFAULT_ENDORSER_API_SERVER = TEST_ENDORSER_API_SERVER,
|
DEFAULT_ENDORSER_API_SERVER = TEST_ENDORSER_API_SERVER,
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
|
||||||
PROD_PUSH_SERVER = "https://timesafari.app",
|
PROD_PUSH_SERVER = "https://timesafari.app",
|
||||||
TEST1_PUSH_SERVER = "https://test.timesafari.app",
|
TEST1_PUSH_SERVER = "https://test.timesafari.app",
|
||||||
TEST2_PUSH_SERVER = "https://timesafari-pwa.anomalistlabs.com",
|
TEST2_PUSH_SERVER = "https://timesafari-pwa.anomalistlabs.com",
|
||||||
|
|||||||
@@ -45,8 +45,5 @@ db.on("populate", () => {
|
|||||||
db.settings.add({
|
db.settings.add({
|
||||||
id: MASTER_SETTINGS_KEY,
|
id: MASTER_SETTINGS_KEY,
|
||||||
apiServer: AppString.DEFAULT_ENDORSER_API_SERVER,
|
apiServer: AppString.DEFAULT_ENDORSER_API_SERVER,
|
||||||
|
|
||||||
// remember that things you add from now on aren't automatically in the DB for old users
|
|
||||||
webPushServer: AppString.DEFAULT_PUSH_SERVER,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,15 +12,17 @@ export type BoundingBox = {
|
|||||||
* Settings type encompasses user-specific configuration details.
|
* Settings type encompasses user-specific configuration details.
|
||||||
*/
|
*/
|
||||||
export type Settings = {
|
export type Settings = {
|
||||||
id: number; // Only one entry using MASTER_SETTINGS_KEY
|
id: number; // Only one entry, keyed with MASTER_SETTINGS_KEY
|
||||||
|
|
||||||
activeDid?: string; // Active Decentralized ID
|
activeDid?: string; // Active Decentralized ID
|
||||||
apiServer?: string; // API server URL
|
apiServer?: string; // API server URL
|
||||||
firstName?: string; // User's first name
|
firstName?: string; // User's first name
|
||||||
lastName?: string; // deprecated - put all names in firstName
|
|
||||||
lastViewedClaimId?: string; // Last viewed claim ID
|
|
||||||
lastNotifiedClaimId?: string; // Last notified claim ID
|
|
||||||
isRegistered?: boolean;
|
isRegistered?: boolean;
|
||||||
webPushServer?: string; // Web Push server URL
|
lastName?: string; // deprecated - put all names in firstName
|
||||||
|
lastNotifiedClaimId?: string; // Last notified claim ID
|
||||||
|
lastViewedClaimId?: string; // Last viewed claim ID
|
||||||
|
reminderTime?: number; // Time in milliseconds since UNIX epoch for reminders
|
||||||
|
reminderOn?: boolean; // Toggle to enable or disable reminders
|
||||||
|
|
||||||
// Array of named search boxes defined by bounding boxes
|
// Array of named search boxes defined by bounding boxes
|
||||||
searchBoxes?: Array<{
|
searchBoxes?: Array<{
|
||||||
@@ -30,8 +32,9 @@ export type Settings = {
|
|||||||
|
|
||||||
showContactGivesInline?: boolean; // Display contact inline or not
|
showContactGivesInline?: boolean; // Display contact inline or not
|
||||||
vapid?: string; // VAPID (Voluntary Application Server Identification) field for web push
|
vapid?: string; // VAPID (Voluntary Application Server Identification) field for web push
|
||||||
reminderTime?: number; // Time in milliseconds since UNIX epoch for reminders
|
warnIfProdServer?: boolean; // Warn if using a production server
|
||||||
reminderOn?: boolean; // Toggle to enable or disable reminders
|
warnIfTestServer?: boolean; // Warn if using a testing server
|
||||||
|
webPushServer?: string; // Web Push server URL
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<QuickNav selected="Profile"></QuickNav>
|
<QuickNav selected="Profile"></QuickNav>
|
||||||
|
<TopMessage />
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<section id="Content" class="p-6 pb-24">
|
<section id="Content" class="p-6 pb-24">
|
||||||
<!-- Heading -->
|
<!-- Heading -->
|
||||||
@@ -104,6 +106,7 @@
|
|||||||
|
|
||||||
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8">
|
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8">
|
||||||
<label
|
<label
|
||||||
|
v-if="notificationUnchanged"
|
||||||
for="toggleNotifications"
|
for="toggleNotifications"
|
||||||
class="flex items-center justify-between cursor-pointer"
|
class="flex items-center justify-between cursor-pointer"
|
||||||
@click="
|
@click="
|
||||||
@@ -143,6 +146,10 @@
|
|||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
<label v-else>
|
||||||
|
Notification status may have changed. Revisit this page to see the
|
||||||
|
latest setting.
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 class="text-sm uppercase font-semibold mb-3">Data</h3>
|
<h3 class="text-sm uppercase font-semibold mb-3">Data</h3>
|
||||||
@@ -215,7 +222,7 @@
|
|||||||
<div v-if="showAdvanced">
|
<div v-if="showAdvanced">
|
||||||
<p class="text-rose-600 mb-8">
|
<p class="text-rose-600 mb-8">
|
||||||
Beware: the features here can be confusing and even change data in ways
|
Beware: the features here can be confusing and even change data in ways
|
||||||
you do not expect. But we support your freedoms!
|
you do not expect. But we support your freedom!
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- Deep Identity Details -->
|
<!-- Deep Identity Details -->
|
||||||
@@ -357,6 +364,46 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label
|
||||||
|
for="toggleProdWarningMessage"
|
||||||
|
class="flex items-center justify-between cursor-pointer my-4"
|
||||||
|
@click="toggleProdWarning"
|
||||||
|
>
|
||||||
|
<!-- label -->
|
||||||
|
<h2>Show warning if on prod server</h2>
|
||||||
|
<!-- toggle -->
|
||||||
|
<div class="relative ml-2">
|
||||||
|
<!-- input -->
|
||||||
|
<input type="checkbox" v-model="warnIfProdServer" class="sr-only" />
|
||||||
|
<!-- line -->
|
||||||
|
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
|
||||||
|
<!-- dot -->
|
||||||
|
<div
|
||||||
|
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label
|
||||||
|
for="toggleTestWarningMessage"
|
||||||
|
class="flex items-center justify-between cursor-pointer my-4"
|
||||||
|
@click="toggleTestWarning"
|
||||||
|
>
|
||||||
|
<!-- label -->
|
||||||
|
<h2>Show warning if on test server</h2>
|
||||||
|
<!-- toggle -->
|
||||||
|
<div class="relative ml-2">
|
||||||
|
<!-- input -->
|
||||||
|
<input type="checkbox" v-model="warnIfTestServer" class="sr-only" />
|
||||||
|
<!-- line -->
|
||||||
|
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
|
||||||
|
<!-- dot -->
|
||||||
|
<div
|
||||||
|
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
|
||||||
<div class="flex py-4">
|
<div class="flex py-4">
|
||||||
<h2 class="text-slate-500 text-sm font-bold mb-2">
|
<h2 class="text-slate-500 text-sm font-bold mb-2">
|
||||||
Notification Push Server
|
Notification Push Server
|
||||||
@@ -408,6 +455,7 @@ import { Component, Vue } from "vue-facing-decorator";
|
|||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
|
|
||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import { AppString } from "@/constants/app";
|
import { AppString } from "@/constants/app";
|
||||||
import { db, accountsDB } from "@/db/index";
|
import { db, accountsDB } from "@/db/index";
|
||||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||||
@@ -432,7 +480,7 @@ interface IAccount {
|
|||||||
derivationPath: string;
|
derivationPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({ components: { QuickNav } })
|
@Component({ components: { QuickNav, TopMessage } })
|
||||||
export default class AccountViewView extends Vue {
|
export default class AccountViewView extends Vue {
|
||||||
$notify!: (notification: Notification, timeout?: number) => void;
|
$notify!: (notification: Notification, timeout?: number) => void;
|
||||||
|
|
||||||
@@ -444,6 +492,7 @@ export default class AccountViewView extends Vue {
|
|||||||
derivationPath = "";
|
derivationPath = "";
|
||||||
givenName = "";
|
givenName = "";
|
||||||
isRegistered = false;
|
isRegistered = false;
|
||||||
|
notificationUnchanged = true;
|
||||||
numAccounts = 0;
|
numAccounts = 0;
|
||||||
publicHex = "";
|
publicHex = "";
|
||||||
publicBase64 = "";
|
publicBase64 = "";
|
||||||
@@ -462,6 +511,8 @@ export default class AccountViewView extends Vue {
|
|||||||
showAdvanced = false;
|
showAdvanced = false;
|
||||||
|
|
||||||
subscription: PushSubscription | null = null;
|
subscription: PushSubscription | null = null;
|
||||||
|
warnIfProdServer = false;
|
||||||
|
warnIfTestServer = false;
|
||||||
|
|
||||||
private isSubscribed = false;
|
private isSubscribed = false;
|
||||||
get toggleNotifications() {
|
get toggleNotifications() {
|
||||||
@@ -469,6 +520,63 @@ export default class AccountViewView extends Vue {
|
|||||||
}
|
}
|
||||||
set toggleNotifications(value) {
|
set toggleNotifications(value) {
|
||||||
this.isSubscribed = value;
|
this.isSubscribed = value;
|
||||||
|
this.notificationUnchanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Async function executed when the component is created.
|
||||||
|
* Initializes the component's state with values from the database,
|
||||||
|
* handles identity-related tasks, and checks limitations.
|
||||||
|
*
|
||||||
|
* @throws Will display specific messages to the user based on different errors.
|
||||||
|
*/
|
||||||
|
async created() {
|
||||||
|
try {
|
||||||
|
await db.open();
|
||||||
|
|
||||||
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||||
|
|
||||||
|
// Initialize component state with values from the database or defaults
|
||||||
|
this.initializeState(settings);
|
||||||
|
|
||||||
|
// Get and process the identity
|
||||||
|
const identity = await this.getIdentity(this.activeDid);
|
||||||
|
if (identity) {
|
||||||
|
this.processIdentity(identity);
|
||||||
|
}
|
||||||
|
} catch (err: unknown) {
|
||||||
|
this.handleError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async mounted() {
|
||||||
|
try {
|
||||||
|
const registration = await navigator.serviceWorker.ready;
|
||||||
|
this.subscription = await registration.pushManager.getSubscription();
|
||||||
|
this.toggleNotifications = !!this.subscription;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Mount error:", error);
|
||||||
|
this.toggleNotifications = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes component state with values from the database or defaults.
|
||||||
|
* @param {SettingsType} settings - Object containing settings from the database.
|
||||||
|
*/
|
||||||
|
initializeState(settings: Settings | undefined) {
|
||||||
|
this.activeDid = (settings?.activeDid as string) || "";
|
||||||
|
this.apiServer = (settings?.apiServer as string) || "";
|
||||||
|
this.apiServerInput = (settings?.apiServer as string) || "";
|
||||||
|
this.givenName =
|
||||||
|
(settings?.firstName || "") +
|
||||||
|
(settings?.lastName ? ` ${settings.lastName}` : ""); // pre v 0.1.3
|
||||||
|
this.isRegistered = !!settings?.isRegistered;
|
||||||
|
this.showContactGives = !!settings?.showContactGivesInline;
|
||||||
|
this.warnIfProdServer = !!settings?.warnIfProdServer;
|
||||||
|
this.warnIfTestServer = !!settings?.warnIfTestServer;
|
||||||
|
this.webPushServer = (settings?.webPushServer as string) || "";
|
||||||
|
this.webPushServerInput = (settings?.webPushServer as string) || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getIdentity(activeDid: string): Promise<IIdentifier | null> {
|
public async getIdentity(activeDid: string): Promise<IIdentifier | null> {
|
||||||
@@ -536,6 +644,16 @@ export default class AccountViewView extends Vue {
|
|||||||
this.updateShowContactAmounts();
|
this.updateShowContactAmounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleProdWarning() {
|
||||||
|
this.warnIfProdServer = !this.warnIfProdServer;
|
||||||
|
this.updateWarnIfProdServer(this.warnIfProdServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleTestWarning() {
|
||||||
|
this.warnIfTestServer = !this.warnIfTestServer;
|
||||||
|
this.updateWarnIfTestServer(this.warnIfTestServer);
|
||||||
|
}
|
||||||
|
|
||||||
readableTime(timeStr: string) {
|
readableTime(timeStr: string) {
|
||||||
return timeStr.substring(0, timeStr.indexOf("T"));
|
return timeStr.substring(0, timeStr.indexOf("T"));
|
||||||
}
|
}
|
||||||
@@ -545,60 +663,6 @@ export default class AccountViewView extends Vue {
|
|||||||
this.numAccounts = await accountsDB.accounts.count();
|
this.numAccounts = await accountsDB.accounts.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Async function executed when the component is created.
|
|
||||||
* Initializes the component's state with values from the database,
|
|
||||||
* handles identity-related tasks, and checks limitations.
|
|
||||||
*
|
|
||||||
* @throws Will display specific messages to the user based on different errors.
|
|
||||||
*/
|
|
||||||
async created() {
|
|
||||||
try {
|
|
||||||
await db.open();
|
|
||||||
|
|
||||||
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
|
||||||
|
|
||||||
// Initialize component state with values from the database or defaults
|
|
||||||
this.initializeState(settings);
|
|
||||||
|
|
||||||
// Get and process the identity
|
|
||||||
const identity = await this.getIdentity(this.activeDid);
|
|
||||||
if (identity) {
|
|
||||||
this.processIdentity(identity);
|
|
||||||
}
|
|
||||||
} catch (err: unknown) {
|
|
||||||
this.handleError(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async mounted() {
|
|
||||||
try {
|
|
||||||
const registration = await navigator.serviceWorker.ready;
|
|
||||||
this.subscription = await registration.pushManager.getSubscription();
|
|
||||||
this.toggleNotifications = !!this.subscription;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Mount error:", error);
|
|
||||||
this.toggleNotifications = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes component state with values from the database or defaults.
|
|
||||||
* @param {SettingsType} settings - Object containing settings from the database.
|
|
||||||
*/
|
|
||||||
initializeState(settings: Settings | undefined) {
|
|
||||||
this.activeDid = (settings?.activeDid as string) || "";
|
|
||||||
this.apiServer = (settings?.apiServer as string) || "";
|
|
||||||
this.apiServerInput = (settings?.apiServer as string) || "";
|
|
||||||
this.givenName =
|
|
||||||
(settings?.firstName || "") +
|
|
||||||
(settings?.lastName ? ` ${settings.lastName}` : ""); // pre v 0.1.3
|
|
||||||
this.isRegistered = !!settings?.isRegistered;
|
|
||||||
this.webPushServer = (settings?.webPushServer as string) || "";
|
|
||||||
this.webPushServerInput = (settings?.webPushServer as string) || "";
|
|
||||||
this.showContactGives = !!settings?.showContactGivesInline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes the identity and updates the component's state.
|
* Processes the identity and updates the component's state.
|
||||||
* @param {IdentityType} identity - Object containing identity information.
|
* @param {IdentityType} identity - Object containing identity information.
|
||||||
@@ -672,6 +736,52 @@ export default class AccountViewView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updateWarnIfProdServer(newSetting: boolean) {
|
||||||
|
try {
|
||||||
|
await db.open();
|
||||||
|
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
|
warnIfProdServer: newSetting,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error Updating Prod Warning",
|
||||||
|
text: "Clear your cache and start over (after data backup).",
|
||||||
|
},
|
||||||
|
-1,
|
||||||
|
);
|
||||||
|
console.error(
|
||||||
|
"Telling user to clear cache after contact setting update because:",
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateWarnIfTestServer(newSetting: boolean) {
|
||||||
|
try {
|
||||||
|
await db.open();
|
||||||
|
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
|
warnIfTestServer: newSetting,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error Updating Test Warning",
|
||||||
|
text: "Clear your cache and start over (after data backup).",
|
||||||
|
},
|
||||||
|
-1,
|
||||||
|
);
|
||||||
|
console.error(
|
||||||
|
"Telling user to clear cache after contact setting update because:",
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously exports the database into a downloadable JSON file.
|
* Asynchronously exports the database into a downloadable JSON file.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
<!-- Details -->
|
<!-- 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>
|
||||||
<div class="block pb-4 flex gap-4 overflow-hidden">
|
<div class="block flex gap-4 overflow-hidden">
|
||||||
<div class="overflow-hidden">
|
<div class="overflow-hidden">
|
||||||
<h2 class="text-xl">{{ veriClaim.id }}</h2>
|
<h2 class="text-md font-bold">{{ veriClaim.id }}</h2>
|
||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
<div>
|
<div>
|
||||||
{{ veriClaim.claimType }}
|
{{ veriClaim.claimType }}
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="font-bold text-2xl">Confirmations</h2>
|
<h2 class="font-bold uppercase text-xl mt-8 mb-2">Confirmations</h2>
|
||||||
|
|
||||||
<span v-if="totalConfirmers() === 0">Nobody has confirmed this.</span>
|
<span v-if="totalConfirmers() === 0">Nobody has confirmed this.</span>
|
||||||
<span v-else-if="totalConfirmers() === 1">
|
<span v-else-if="totalConfirmers() === 1">
|
||||||
@@ -136,22 +136,24 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="font-bold text-2xl mt-8">Claim</h2>
|
<h2 class="font-bold uppercase text-xl mt-8 mb-2">Claim</h2>
|
||||||
<pre>{{ util.inspect(veriClaim, false, null) }}</pre>
|
<pre class="text-sm overflow-x-scroll px-4 py-3 bg-slate-100 rounded-md">
|
||||||
|
{{ util.inspect(veriClaim, false, null) }}
|
||||||
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 class="font-bold text-2xl mt-8">Full Claim</h2>
|
<h2 class="font-bold uppercase text-xl mt-8 mb-2">Full Claim</h2>
|
||||||
<p>
|
<p class="mb-4">
|
||||||
The full claim includes the claim as it was originally issued, including
|
The full claim includes the claim as it was originally issued, including
|
||||||
the signature (ie. the proof of issuance by that person).
|
the signature (ie. the proof of issuance by that person).
|
||||||
</p>
|
</p>
|
||||||
<div v-if="!fullClaim">
|
<div v-if="!fullClaim">
|
||||||
<div v-if="fullClaimMessage">
|
<p v-if="fullClaimMessage" class="mb-4">
|
||||||
{{ fullClaimMessage }}
|
{{ fullClaimMessage }}
|
||||||
</div>
|
</p>
|
||||||
<button
|
<button
|
||||||
v-else
|
v-else
|
||||||
class="bg-blue-600 text-white mt-4 px-4 py-2 rounded-md mb-4"
|
class="block w-full text-center text-md uppercase bg-blue-600 text-white px-1.5 py-2 rounded-md mb-2"
|
||||||
@click="showFullClaim(veriClaim.id)"
|
@click="showFullClaim(veriClaim.id)"
|
||||||
>
|
>
|
||||||
Load Full Claim Details
|
Load Full Claim Details
|
||||||
@@ -161,10 +163,12 @@
|
|||||||
<pre>{{ util.inspect(fullClaim, false, null) }}</pre>
|
<pre>{{ util.inspect(fullClaim, false, null) }}</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a :href="apiServer + '/api/claim/' + veriClaim.id" target="_blank">
|
<a
|
||||||
<button class="bg-blue-600 text-white mt-4 px-4 py-2 rounded-md mb-4">
|
:href="apiServer + '/api/claim/' + veriClaim.id"
|
||||||
|
target="_blank"
|
||||||
|
class="block w-full text-center text-md uppercase bg-blue-600 text-white px-1.5 py-2 rounded-md mb-2"
|
||||||
|
>
|
||||||
View on the Public Server
|
View on the Public Server
|
||||||
</button>
|
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<QuickNav selected="Discover"></QuickNav>
|
<QuickNav selected="Discover"></QuickNav>
|
||||||
|
<TopMessage />
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<section id="Content" class="p-6 pb-24">
|
<section id="Content" class="p-6 pb-24">
|
||||||
@@ -136,6 +137,7 @@ import { didInfo, ProjectData } from "@/libs/endorserServer";
|
|||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
||||||
import EntityIcon from "@/components/EntityIcon.vue";
|
import EntityIcon from "@/components/EntityIcon.vue";
|
||||||
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
|
|
||||||
interface Notification {
|
interface Notification {
|
||||||
group: string;
|
group: string;
|
||||||
@@ -149,6 +151,7 @@ interface Notification {
|
|||||||
QuickNav,
|
QuickNav,
|
||||||
InfiniteScroll,
|
InfiniteScroll,
|
||||||
EntityIcon,
|
EntityIcon,
|
||||||
|
TopMessage,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class DiscoverView extends Vue {
|
export default class DiscoverView extends Vue {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<QuickNav selected="Home"></QuickNav>
|
<QuickNav selected="Home"></QuickNav>
|
||||||
|
<TopMessage />
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<section id="Content" class="p-6 pb-24">
|
<section id="Content" class="p-6 pb-24">
|
||||||
<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">
|
||||||
@@ -146,6 +148,7 @@ import EntityIcon from "@/components/EntityIcon.vue";
|
|||||||
import GiftedDialog from "@/components/GiftedDialog.vue";
|
import GiftedDialog from "@/components/GiftedDialog.vue";
|
||||||
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import { db, accountsDB } from "@/db/index";
|
import { db, accountsDB } from "@/db/index";
|
||||||
import { Account } from "@/db/tables/accounts";
|
import { Account } from "@/db/tables/accounts";
|
||||||
import { Contact } from "@/db/tables/contacts";
|
import { Contact } from "@/db/tables/contacts";
|
||||||
@@ -166,7 +169,13 @@ interface Notification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { GiftedDialog, QuickNav, EntityIcon, InfiniteScroll },
|
components: {
|
||||||
|
GiftedDialog,
|
||||||
|
QuickNav,
|
||||||
|
EntityIcon,
|
||||||
|
InfiniteScroll,
|
||||||
|
TopMessage,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
export default class HomeView extends Vue {
|
export default class HomeView extends Vue {
|
||||||
$notify!: (notification: Notification, timeout?: number) => void;
|
$notify!: (notification: Notification, timeout?: number) => void;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<QuickNav />
|
<QuickNav />
|
||||||
|
<TopMessage />
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<section id="Content" class="p-6 pb-24">
|
<section id="Content" class="p-6 pb-24">
|
||||||
<!-- Breadcrumb -->
|
<!-- Breadcrumb -->
|
||||||
@@ -282,6 +284,7 @@ import { Component, Vue } from "vue-facing-decorator";
|
|||||||
|
|
||||||
import GiftedDialog from "@/components/GiftedDialog.vue";
|
import GiftedDialog from "@/components/GiftedDialog.vue";
|
||||||
import OfferDialog from "@/components/OfferDialog.vue";
|
import OfferDialog from "@/components/OfferDialog.vue";
|
||||||
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import { accountsDB, db } from "@/db/index";
|
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";
|
||||||
@@ -306,7 +309,7 @@ interface Notification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { EntityIcon, GiftedDialog, OfferDialog, QuickNav },
|
components: { EntityIcon, GiftedDialog, OfferDialog, QuickNav, TopMessage },
|
||||||
})
|
})
|
||||||
export default class ProjectViewView extends Vue {
|
export default class ProjectViewView extends Vue {
|
||||||
$notify!: (notification: Notification, timeout?: number) => void;
|
$notify!: (notification: Notification, timeout?: number) => void;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<QuickNav selected="Projects"></QuickNav>
|
<QuickNav selected="Projects"></QuickNav>
|
||||||
|
<TopMessage />
|
||||||
|
|
||||||
<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">
|
||||||
@@ -79,6 +81,7 @@ import { IIdentifier } from "@veramo/core";
|
|||||||
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
import EntityIcon from "@/components/EntityIcon.vue";
|
import EntityIcon from "@/components/EntityIcon.vue";
|
||||||
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import { ProjectData } from "@/libs/endorserServer";
|
import { ProjectData } from "@/libs/endorserServer";
|
||||||
|
|
||||||
interface Notification {
|
interface Notification {
|
||||||
@@ -89,7 +92,7 @@ interface Notification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: { InfiniteScroll, QuickNav, EntityIcon },
|
components: { InfiniteScroll, QuickNav, EntityIcon, TopMessage },
|
||||||
})
|
})
|
||||||
export default class ProjectsView extends Vue {
|
export default class ProjectsView extends Vue {
|
||||||
$notify!: (notification: Notification, timeout?: number) => void;
|
$notify!: (notification: Notification, timeout?: number) => void;
|
||||||
|
|||||||
Reference in New Issue
Block a user