forked from trent_larson/crowd-funder-for-time-pwa
Compare commits
21 Commits
1befff0abd
...
v-onboardi
| Author | SHA1 | Date | |
|---|---|---|---|
| cf8f0e3ab7 | |||
|
|
05601f1e15 | ||
|
|
2e795b71ac | ||
|
|
948eb2ef26 | ||
|
|
7d611725c4 | ||
|
|
def6cafc17 | ||
| 340d0a5219 | |||
| 7412d67c33 | |||
| 83db5302ad | |||
| 75f9f20ea3 | |||
| e43c45ebea | |||
| 708032311a | |||
| 214a264179 | |||
| 9b183a4b6c | |||
| f365cc9e3c | |||
| 9059f7a9a7 | |||
| e6cd86618e | |||
| c3fd27b140 | |||
| cf2e800dec | |||
| b60383cfe9 | |||
| c7d93db6f2 |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -10,7 +10,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Nothing
|
||||
|
||||
|
||||
## [0.3.4] - 2024.03.21
|
||||
## [0.3.6] - 2024.03.24 - 3a07e31d6313ab95711265562d9023c42916e141
|
||||
### Added
|
||||
- Button to mirror photo during video
|
||||
- More detailed onboarding help screen
|
||||
- Public-data blurb
|
||||
### Changed in DB or environment
|
||||
- Nothing
|
||||
|
||||
|
||||
## [0.3.5] - 2024.03.23 - 28754bdfb1e11aa221dd49a5dce4219b69cf6a9d
|
||||
### Added
|
||||
- Photo on gift records
|
||||
### Fixed
|
||||
|
||||
@@ -55,8 +55,6 @@ npm run build
|
||||
|
||||
* `rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari`
|
||||
|
||||
* Revert src/constants/app.ts and package.json (if that was prod).
|
||||
|
||||
* Commit changes. Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, and commit. Also record what version is on production.
|
||||
|
||||
* [Tag with the new version.](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases)
|
||||
@@ -128,7 +126,7 @@ To add an icon, add to main.ts and reference with `fa` element and `icon` attrib
|
||||
|
||||
* Clear cache for site. (In Chrome, go to `chrome://settings/cookies` and "all site data and permissions"; in Firefox, go to `about:preferences` and search for "cache" then "Manage Data", and also manually remove the IndexedDB data if the DBs still show.)
|
||||
* Clear notification permission. (In Chrome, go to `chrome://settings/content/notifications`; in Firefox, go to `about:preferences` and search for "notifications".)
|
||||
* Unregister service worker. (In Chrome, go to `chrome://serviceworker-internals/`; in Firefox, go to `about:serviceworkers`.)
|
||||
* Unregister service worker. (In Chrome, go to `chrome://serviceworker-internals`; in Firefox, go to `about:serviceworkers`.)
|
||||
* Clear Cache Storage manually, possibly deleting the DB. (In Chrome, in dev tools under Application; in Firefox, in dev tools under Storage.)
|
||||
|
||||
(If you find more, add them to the HelpNotificationsView.vue file.)
|
||||
|
||||
207
package-lock.json
generated
207
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "TimeSafari",
|
||||
"version": "0.3.4",
|
||||
"version": "0.3.7-beta",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "TimeSafari",
|
||||
"version": "0.3.4",
|
||||
"version": "0.3.7-beta",
|
||||
"dependencies": {
|
||||
"@dicebear/collection": "^5.3.5",
|
||||
"@dicebear/core": "^5.3.5",
|
||||
@@ -58,6 +58,7 @@
|
||||
"three": "^0.156.1",
|
||||
"ua-parser-js": "^1.0.37",
|
||||
"util": "^0.12.5",
|
||||
"v-onboarding": "^2.8.1",
|
||||
"vue": "^3.3.4",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-facing-decorator": "^3.0.2",
|
||||
@@ -6643,6 +6644,15 @@
|
||||
"integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@pvermeer/dexie-encrypted-addon": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@pvermeer/dexie-encrypted-addon/-/dexie-encrypted-addon-3.0.0.tgz",
|
||||
@@ -9351,9 +9361,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.18.tgz",
|
||||
"integrity": "sha512-v/ZHEj9xh82usl8LMR3GarzFY1IrbXJw5L4QfQhokjRV91q+SelFqxQWSep1ucXEZ22+dSTwLFkXeur25sPIbw=="
|
||||
"version": "0.0.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz",
|
||||
"integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
|
||||
},
|
||||
"node_modules/@types/webpack-env": {
|
||||
"version": "1.18.2",
|
||||
@@ -10853,23 +10863,113 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@vueuse/core": {
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.5.0.tgz",
|
||||
"integrity": "sha512-z/tI2eSvxwLRjOhDm0h/SXAjNm8N5ld6/SC/JQs6o6kpJ6Ya50LnEL8g5hoYu005i28L0zqB5L5yAl8Jl26K3A==",
|
||||
"version": "10.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.1.tgz",
|
||||
"integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==",
|
||||
"dependencies": {
|
||||
"@types/web-bluetooth": "^0.0.18",
|
||||
"@vueuse/metadata": "10.5.0",
|
||||
"@vueuse/shared": "10.5.0",
|
||||
"vue-demi": ">=0.14.6"
|
||||
"@types/web-bluetooth": "^0.0.20",
|
||||
"@vueuse/metadata": "10.11.1",
|
||||
"@vueuse/shared": "10.11.1",
|
||||
"vue-demi": ">=0.14.8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/core/node_modules/vue-demi": {
|
||||
"version": "0.14.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
|
||||
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
|
||||
"version": "0.14.10",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
|
||||
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@vue/composition-api": "^1.0.0-rc.1",
|
||||
"vue": "^3.0.0-0 || ^2.6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@vue/composition-api": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/integrations": {
|
||||
"version": "10.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.11.1.tgz",
|
||||
"integrity": "sha512-Y5hCGBguN+vuVYTZmdd/IMXLOdfS60zAmDmFYc4BKBcMUPZH1n4tdyDECCPjXm0bNT3ZRUy1xzTLGaUje8Xyaw==",
|
||||
"dependencies": {
|
||||
"@vueuse/core": "10.11.1",
|
||||
"@vueuse/shared": "10.11.1",
|
||||
"vue-demi": ">=0.14.8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"async-validator": "^4",
|
||||
"axios": "^1",
|
||||
"change-case": "^4",
|
||||
"drauu": "^0.3",
|
||||
"focus-trap": "^7",
|
||||
"fuse.js": "^6",
|
||||
"idb-keyval": "^6",
|
||||
"jwt-decode": "^3",
|
||||
"nprogress": "^0.2",
|
||||
"qrcode": "^1.5",
|
||||
"sortablejs": "^1",
|
||||
"universal-cookie": "^6"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"async-validator": {
|
||||
"optional": true
|
||||
},
|
||||
"axios": {
|
||||
"optional": true
|
||||
},
|
||||
"change-case": {
|
||||
"optional": true
|
||||
},
|
||||
"drauu": {
|
||||
"optional": true
|
||||
},
|
||||
"focus-trap": {
|
||||
"optional": true
|
||||
},
|
||||
"fuse.js": {
|
||||
"optional": true
|
||||
},
|
||||
"idb-keyval": {
|
||||
"optional": true
|
||||
},
|
||||
"jwt-decode": {
|
||||
"optional": true
|
||||
},
|
||||
"nprogress": {
|
||||
"optional": true
|
||||
},
|
||||
"qrcode": {
|
||||
"optional": true
|
||||
},
|
||||
"sortablejs": {
|
||||
"optional": true
|
||||
},
|
||||
"universal-cookie": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/integrations/node_modules/vue-demi": {
|
||||
"version": "0.14.10",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
|
||||
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
@@ -10892,28 +10992,28 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/metadata": {
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.5.0.tgz",
|
||||
"integrity": "sha512-fEbElR+MaIYyCkeM0SzWkdoMtOpIwO72x8WsZHRE7IggiOlILttqttM69AS13nrDxosnDBYdyy3C5mR1LCxHsw==",
|
||||
"version": "10.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.1.tgz",
|
||||
"integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/shared": {
|
||||
"version": "10.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.5.0.tgz",
|
||||
"integrity": "sha512-18iyxbbHYLst9MqU1X1QNdMHIjks6wC7XTVf0KNOv5es/Ms6gjVFCAAWTVP2JStuGqydg3DT+ExpFORUEi9yhg==",
|
||||
"version": "10.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz",
|
||||
"integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==",
|
||||
"dependencies": {
|
||||
"vue-demi": ">=0.14.6"
|
||||
"vue-demi": ">=0.14.8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
}
|
||||
},
|
||||
"node_modules/@vueuse/shared/node_modules/vue-demi": {
|
||||
"version": "0.14.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
|
||||
"integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
|
||||
"version": "0.14.10",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
|
||||
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||
@@ -16239,10 +16339,18 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/focus-trap": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.0.tgz",
|
||||
"integrity": "sha512-1td0l3pMkWJLFipobUcGaf+5DTY4PLDDrcqoSaKP8ediO/CoWCCYk/fT/Y2A4e6TNB+Sh6clRJCjOPPnKoNHnQ==",
|
||||
"dependencies": {
|
||||
"tabbable": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -17449,9 +17557,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ip": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
|
||||
"integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==",
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz",
|
||||
"integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==",
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
@@ -18941,9 +19049,9 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/jose": {
|
||||
"version": "4.15.4",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.4.tgz",
|
||||
"integrity": "sha512-W+oqK4H+r5sITxfxpSU+MMdr/YSWGvgZMQDIsNoBDGGy4i7GBPTtvFKibQzW06n3U3TqHjhvBJsirShsEJ6eeQ==",
|
||||
"version": "4.15.5",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz",
|
||||
"integrity": "sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==",
|
||||
"optional": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
@@ -26130,6 +26238,11 @@
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/tabbable": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
|
||||
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
|
||||
@@ -27295,9 +27408,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "5.26.3",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.26.3.tgz",
|
||||
"integrity": "sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw==",
|
||||
"version": "5.28.3",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz",
|
||||
"integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
@@ -27536,6 +27649,20 @@
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/v-onboarding": {
|
||||
"version": "2.8.2",
|
||||
"resolved": "https://registry.npmjs.org/v-onboarding/-/v-onboarding-2.8.2.tgz",
|
||||
"integrity": "sha512-QiUEV/AWdLIWuhK2vp7aT5CKVBGanSgRL/rySbYM3sFtk8Gd/azWnfo5whuLi+BEJhlMvRekP/Gq7TInLQwqJA==",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"@vueuse/integrations": "^10.7.2",
|
||||
"focus-trap": "^7",
|
||||
"vue": "^3.2.21"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.21"
|
||||
}
|
||||
},
|
||||
"node_modules/valid-url": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
|
||||
@@ -28018,9 +28145,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-dev-middleware": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz",
|
||||
"integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==",
|
||||
"version": "5.3.4",
|
||||
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz",
|
||||
"integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"colorette": "^2.0.10",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TimeSafari",
|
||||
"version": "0.3.4",
|
||||
"version": "0.3.7-beta",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
@@ -58,6 +58,7 @@
|
||||
"three": "^0.156.1",
|
||||
"ua-parser-js": "^1.0.37",
|
||||
"util": "^0.12.5",
|
||||
"v-onboarding": "^2.8.1",
|
||||
"vue": "^3.3.4",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-facing-decorator": "^3.0.2",
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
|
||||
tasks :
|
||||
|
||||
- bug - landscape doesn't show full camera
|
||||
- bug - got blank screen and errors on iPhone with no bottom tabs
|
||||
- add to readme - check version, close tabs & restart phone if necessary
|
||||
- bug maybe - a new give remembers the previous project
|
||||
- alert & stop if give amount < 0
|
||||
- add warning that all data (except ID) is public
|
||||
- onboarding video
|
||||
- .2 when adding a claim on home screen, push that claim to the top of the list
|
||||
- 24 contextual tutorials https://docs.google.com/document/d/11C_K3RM0rgo0onih20KFhcIzukZyq_CRWqaWX5om_kM/edit#heading=h.iwiwcydou5hw
|
||||
|
||||
- 24 allow a person record with interests, including location; purpose? contact methods? enhance other connections the same? (suggestion from Philippines) assignee-group:ui
|
||||
- 24 Move to Vite
|
||||
|
||||
- .1 add KindSpring link to ideas
|
||||
- .1 on feed, don't show "to someone anonymous" if it's to a project
|
||||
- .1 on ideas, put an "x" to close it assignee-group:ui
|
||||
- 16 save data backups in Google
|
||||
- 16 generate and use passkeys for identities
|
||||
- .5 show "give" buttons (eg. from anonymous) even if they can't give, greyed out, and give them a warning and instructions
|
||||
- .2 when adding a claim on home screen, push that claim to the top of the list
|
||||
|
||||
- .2 fix give dialog from "more contacts" off home page to allow giving to this user
|
||||
- .2 fix bottom of project selection map, where the icons are hidden but a tap goes to the icon's page assignee-group:ui
|
||||
@@ -66,6 +62,7 @@ tasks :
|
||||
- .1 add cursor-pointer on the icons for giving on the project page, and on the list of projects on the discover page
|
||||
- .2 record when InfiniteScroll hits the end of the list and don't trigger any more loads (feed, project list, give & offer lists)
|
||||
|
||||
- bug (that is hard to reproduce) - got blank screen and errors on iPhone with no bottom tabs
|
||||
- bug - turning notifications on from the help screen did not stay, though account screen toggle did stay (From Jason on iPhone.)
|
||||
- refactor - supply the projectId to the OfferDialog just like we do with the GiftedDialog offerId (in the "open" method, maybe as well as an attribute)
|
||||
- the confirm button on each give on the ProjectViewView page doesn't have all the context of the ClaimView page, so it can show sometimes inappropriately; consider consolidation
|
||||
@@ -128,7 +125,10 @@ tasks :
|
||||
- .5 don't show "Offer" on project screen if they aren't registered
|
||||
- 01 especially for iOS, check for new version & update, eg. https://stackoverflow.com/questions/52221805/any-way-yet-to-auto-update-or-just-clear-the-cache-on-a-pwa-on-ios
|
||||
|
||||
- 24 Move to Vite
|
||||
- 24 allow a person record with interests, including location; purpose? contact methods? enhance other connections the same? (suggestion from Philippines) assignee-group:ui
|
||||
- 24 brief introduction slides https://docs.google.com/document/d/11C_K3RM0rgo0onih20KFhcIzukZyq_CRWqaWX5om_kM/edit#heading=h.iwiwcydou5hw
|
||||
- 12 feedback https://docs.google.com/document/d/11C_K3RM0rgo0onih20KFhcIzukZyq_CRWqaWX5om_kM/edit#heading=h.iwiwcydou5hw
|
||||
|
||||
- 32 accept images for projects
|
||||
- 32 accept images for contacts
|
||||
- import project interactions from GitHub/GitLab and manage signing
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<router-view />
|
||||
|
||||
<!-- https://github.com/emmanuelsw/notiwind -->
|
||||
<!-- Messages in the upper-right - https://github.com/emmanuelsw/notiwind -->
|
||||
<NotificationGroup group="alert">
|
||||
<div
|
||||
class="fixed top-4 right-4 w-full max-w-sm flex flex-col items-start justify-end"
|
||||
@@ -129,6 +129,7 @@
|
||||
</div>
|
||||
</NotificationGroup>
|
||||
|
||||
<!-- These are general-purpose messages - except there are some for turning app notifications on and off. -->
|
||||
<NotificationGroup group="modal">
|
||||
<div class="fixed z-[100] top-0 inset-x-0 w-full">
|
||||
<Notification
|
||||
@@ -148,6 +149,7 @@
|
||||
class="w-full"
|
||||
role="alert"
|
||||
>
|
||||
<!-- type "confirm" will post a message and, with onYes function, show a "Yes" button to call that function -->
|
||||
<div
|
||||
v-if="notification.type === 'confirm'"
|
||||
class="absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50"
|
||||
@@ -161,6 +163,7 @@
|
||||
</p>
|
||||
|
||||
<button
|
||||
v-if="notification.onYes"
|
||||
@click="
|
||||
notification.onYes();
|
||||
close(notification.id);
|
||||
@@ -174,7 +177,7 @@
|
||||
@click="close(notification.id)"
|
||||
class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
|
||||
>
|
||||
Cancel
|
||||
{{ notification.onYes ? "Cancel" : "Close" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,12 +53,17 @@
|
||||
}"
|
||||
class="text-blue-500"
|
||||
>
|
||||
More Options
|
||||
Photo, ...
|
||||
</router-link>
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-center mb-2 mt-6 italic">
|
||||
Sign & Send to publish to the world
|
||||
<fa
|
||||
icon="circle-info"
|
||||
class="pl-2 text-blue-500 cursor-pointer"
|
||||
@click="explainData()"
|
||||
/>
|
||||
</p>
|
||||
<button
|
||||
class="block w-full text-center text-lg font-bold uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md mb-2"
|
||||
@@ -195,6 +200,45 @@ export default class GiftedDialog extends Vue {
|
||||
}
|
||||
|
||||
async confirm() {
|
||||
if (!this.activeDid) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: "You must select an identifier before you can record a give.",
|
||||
},
|
||||
3000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (parseFloat(this.amountInput) < 0) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
text: "You may not send a negative number.",
|
||||
title: "",
|
||||
},
|
||||
2000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!this.description && !parseFloat(this.amountInput)) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: `You must enter a description or some number of ${
|
||||
this.libsUtil.UNIT_LONG[this.unitCode]
|
||||
}.`,
|
||||
},
|
||||
2000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.close();
|
||||
this.$notify(
|
||||
{
|
||||
@@ -229,32 +273,6 @@ export default class GiftedDialog extends Vue {
|
||||
amountInput: number,
|
||||
unitCode: string = "HUR",
|
||||
) {
|
||||
if (!this.activeDid) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: "You must select an identifier before you can record a give.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!description && !amountInput) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: `You must enter a description or some number of ${this.libsUtil.UNIT_LONG[unitCode]}.`,
|
||||
},
|
||||
-1,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const identity = await libsUtil.getIdentity(this.activeDid);
|
||||
const result = await createAndSubmitGive(
|
||||
@@ -339,6 +357,18 @@ export default class GiftedDialog extends Vue {
|
||||
result.response?.data?.error?.message
|
||||
);
|
||||
}
|
||||
|
||||
explainData() {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Data Sharing",
|
||||
text: libsUtil.PRIVACY_MESSAGE,
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -43,22 +43,45 @@
|
||||
<img :src="URL.createObjectURL(blob)" class="mt-2 rounded" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<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:
|
||||
:resolution="{ width: 375, height: 812 }"
|
||||
-->
|
||||
<camera facingMode="environment" autoplay ref="camera">
|
||||
<camera
|
||||
facingMode="environment"
|
||||
autoplay
|
||||
ref="camera"
|
||||
@started="cameraStarted()"
|
||||
>
|
||||
<div
|
||||
class="absolute portrait:bottom-0 portrait:left-0 portrait:right-0 landscape:right-0 landscape:top-0 landscape:bottom-0 flex landscape:flex-row justify-center items-center portrait:pb-2 landscape:pr-4"
|
||||
class="absolute portrait:bottom-0 portrait:left-0 portrait:right-0 portrait:pb-2 landscape:right-0 landscape:top-0 landscape:bottom-0 landscape:pr-4 flex landscape:flex-row justify-center items-center"
|
||||
>
|
||||
<button
|
||||
@click="takeImage"
|
||||
@click="takeImage()"
|
||||
class="bg-blue-500 hover:bg-blue-700 text-white font-bold p-3 rounded-full text-2xl leading-none"
|
||||
>
|
||||
<fa icon="camera" class="w-[1em]"></fa>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="absolute portrait:bottom-2 portrait:right-16 landscape:right-0 landscape:bottom-16 landscape:pr-4 flex justify-center items-center"
|
||||
>
|
||||
<button
|
||||
@click="swapMirrorClass()"
|
||||
class="bg-blue-500 hover:bg-blue-700 text-white font-bold p-3 rounded-full text-2xl leading-none"
|
||||
>
|
||||
<fa icon="left-right" class="w-[1em]"></fa>
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="numDevices > 1" class="absolute bottom-2 right-4">
|
||||
<button
|
||||
@click="switchCamera()"
|
||||
class="bg-blue-500 hover:bg-blue-700 text-white font-bold p-3 rounded-full text-2xl leading-none"
|
||||
>
|
||||
<fa icon="rotate" class="w-[1em]"></fa>
|
||||
</button>
|
||||
</div>
|
||||
</camera>
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,12 +103,12 @@ import { accessToken } from "@/libs/crypto";
|
||||
export default class GiftedPhotoDialog extends Vue {
|
||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||
|
||||
activeDeviceNumber = 0;
|
||||
activeDid = "";
|
||||
blob: Blob | null = null;
|
||||
mirror = false;
|
||||
numDevices = 0;
|
||||
setImage: (arg: string) => void = () => {};
|
||||
imageHeight?: number = window.innerHeight / 2;
|
||||
imageWidth?: number = window.innerWidth / 2;
|
||||
imageWarning = ".";
|
||||
uploading = false;
|
||||
visible = false;
|
||||
|
||||
@@ -129,6 +152,21 @@ export default class GiftedPhotoDialog extends Vue {
|
||||
this.blob = null;
|
||||
}
|
||||
|
||||
async cameraStarted() {
|
||||
const cameraComponent = this.$refs.camera as InstanceType<typeof Camera>;
|
||||
if (cameraComponent) {
|
||||
this.numDevices = (await cameraComponent.devices(["videoinput"])).length;
|
||||
this.mirror = cameraComponent.facingMode === "user";
|
||||
}
|
||||
}
|
||||
|
||||
async switchCamera() {
|
||||
const cameraComponent = this.$refs.camera as InstanceType<typeof Camera>;
|
||||
this.activeDeviceNumber = (this.activeDeviceNumber + 1) % this.numDevices;
|
||||
const devices = await cameraComponent?.devices(["videoinput"]);
|
||||
cameraComponent?.changeCamera(devices[this.activeDeviceNumber].deviceId);
|
||||
}
|
||||
|
||||
async takeImage(/* payload: MouseEvent */) {
|
||||
const cameraComponent = this.$refs.camera as InstanceType<typeof Camera>;
|
||||
|
||||
@@ -200,7 +238,6 @@ export default class GiftedPhotoDialog extends Vue {
|
||||
<canvas id="canvas" width="320" height="240"></canvas>
|
||||
|
||||
async cameraClicked() {
|
||||
console.log("camera_button clicked");
|
||||
const video = document.querySelector("#video");
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: true,
|
||||
@@ -211,7 +248,6 @@ export default class GiftedPhotoDialog extends Vue {
|
||||
}
|
||||
}
|
||||
photoSnapped() {
|
||||
console.log("snap_photo clicked");
|
||||
const video = document.querySelector("#video");
|
||||
const canvas = document.querySelector("#canvas");
|
||||
if (
|
||||
@@ -232,7 +268,6 @@ export default class GiftedPhotoDialog extends Vue {
|
||||
|
||||
// data url of the image
|
||||
const image_data_url = canvas?.toDataURL("image/jpeg");
|
||||
console.log(image_data_url);
|
||||
}
|
||||
}
|
||||
****/
|
||||
@@ -287,6 +322,17 @@ export default class GiftedPhotoDialog extends Vue {
|
||||
this.blob = null;
|
||||
}
|
||||
}
|
||||
|
||||
swapMirrorClass() {
|
||||
this.mirror = !this.mirror;
|
||||
if (this.mirror) {
|
||||
(this.$refs.cameraContainer as HTMLElement).classList.add("mirror-video");
|
||||
} else {
|
||||
(this.$refs.cameraContainer as HTMLElement).classList.remove(
|
||||
"mirror-video",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -311,4 +357,12 @@ export default class GiftedPhotoDialog extends Vue {
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
.mirror-video {
|
||||
transform: scaleX(-1);
|
||||
-webkit-transform: scaleX(-1); /* For Safari */
|
||||
-moz-transform: scaleX(-1); /* For Firefox */
|
||||
-ms-transform: scaleX(-1); /* For IE */
|
||||
-o-transform: scaleX(-1); /* For Opera */
|
||||
}
|
||||
</style>
|
||||
|
||||
164
src/components/OnboardingDialog.vue
Normal file
164
src/components/OnboardingDialog.vue
Normal file
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<div>
|
||||
<VOnboardingWrapper ref="wrapper" :steps="steps">
|
||||
<template
|
||||
#default="{ previous, next, step, exit, isFirst, isLast, index }"
|
||||
>
|
||||
<VOnboardingStep>
|
||||
<div class="bg-white shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:p-6">
|
||||
<div class="sm:flex sm:items-center sm:justify-between">
|
||||
<div v-if="step.content">
|
||||
<h3 v-if="step.content.title" class="flex justify-between">
|
||||
<span
|
||||
class="text-lg font-medium leading-normal text-gray-900"
|
||||
>
|
||||
{{ step.content.title }}
|
||||
</span>
|
||||
<button
|
||||
@click="exit"
|
||||
class="inline-flex align-center justify-center w-6 h-6 shrink-0 rounded-full"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
</h3>
|
||||
<div
|
||||
v-if="step.content.description"
|
||||
class="mt-2 max-w-xl text-sm text-gray-500"
|
||||
>
|
||||
<p>{{ step.content.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mt-5 space-x-4 sm:mt-0 sm:ml-6 sm:flex sm:flex-shrink-0 sm:items-center relative"
|
||||
>
|
||||
<span
|
||||
class="absolute right-0 bottom-full mb-2 mr-2 text-gray-600 font-medium text-xs"
|
||||
>
|
||||
{{ `${index + 1}/${steps.length}` }}
|
||||
</span>
|
||||
<template v-if="!isFirst">
|
||||
<button
|
||||
@click="previous"
|
||||
type="button"
|
||||
class="inline-flex items-center justify-center rounded-md border border-transparent bg-yellow-100 px-4 py-2 font-medium text-yellow-700 hover:bg-yellow-200 focus:outline-none focus:ring-2 focus:ring-yellow-500 focus:ring-offset-2 sm:text-sm"
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
</template>
|
||||
<button
|
||||
@click="next"
|
||||
type="button"
|
||||
class="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:text-sm"
|
||||
>
|
||||
{{ isLast ? "Finish" : "Next" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</VOnboardingStep>
|
||||
</template>
|
||||
</VOnboardingWrapper>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Vue, Component } from "vue-facing-decorator";
|
||||
import { ref } from "vue";
|
||||
import {
|
||||
VOnboardingWrapper,
|
||||
VOnboardingStep,
|
||||
useVOnboarding,
|
||||
} from "v-onboarding";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
VOnboardingWrapper,
|
||||
VOnboardingStep,
|
||||
},
|
||||
})
|
||||
export default class OnboardingDialog extends Vue {
|
||||
setup() {
|
||||
const wrapper = ref(null);
|
||||
const { start, goToStep, finish } = useVOnboarding(wrapper);
|
||||
const steps = [
|
||||
{
|
||||
attachTo: { element: "#headingRecordSomething" },
|
||||
content: { title: "Welcome!" },
|
||||
},
|
||||
{
|
||||
attachTo: { element: "#headingLatestActivity" },
|
||||
content: {
|
||||
title: "Testing v-onboarding..",
|
||||
description:
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return {
|
||||
wrapper,
|
||||
steps,
|
||||
start,
|
||||
finish,
|
||||
goToStep,
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
[data-v-onboarding-wrapper] [data-popper-arrow]::before {
|
||||
content: "";
|
||||
background: var(--v-onboarding-step-arrow-background, white);
|
||||
top: 0;
|
||||
left: 0;
|
||||
transition:
|
||||
transform 0.2s ease-out,
|
||||
visibility 0.2s ease-out;
|
||||
visibility: visible;
|
||||
transform: translateX(0px) rotate(45deg);
|
||||
transform-origin: center;
|
||||
width: var(--v-onboarding-step-arrow-size, 10px);
|
||||
height: var(--v-onboarding-step-arrow-size, 10px);
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
[data-v-onboarding-wrapper]
|
||||
[data-popper-placement^="top"]
|
||||
> [data-popper-arrow] {
|
||||
bottom: 5px;
|
||||
}
|
||||
|
||||
[data-v-onboarding-wrapper]
|
||||
[data-popper-placement^="right"]
|
||||
> [data-popper-arrow] {
|
||||
left: -4px;
|
||||
}
|
||||
|
||||
[data-v-onboarding-wrapper]
|
||||
[data-popper-placement^="bottom"]
|
||||
> [data-popper-arrow] {
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
[data-v-onboarding-wrapper]
|
||||
[data-popper-placement^="left"]
|
||||
> [data-popper-arrow] {
|
||||
right: -4px;
|
||||
}
|
||||
</style>
|
||||
@@ -15,10 +15,8 @@ import * as serverUtil from "@/libs/endorserServer";
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const Buffer = require("buffer/").Buffer;
|
||||
|
||||
// If you edit this, check that the numbers still line up on the side in the alert (on mobile, too),
|
||||
// and make sure they can take all actions while the notification shows.
|
||||
export const ONBOARD_MESSAGE =
|
||||
"1) Read through all their yellow prompts. 2) Add them to your Contacts by scanning with the QR icon that is by the input box. 3) Click the person icon to register them. 4) Show them your QR so they'll scan you. 5) Have them enable notifications.";
|
||||
export const PRIVACY_MESSAGE =
|
||||
"The data you send be visible to the world -- except: your IDs and the IDs of anyone you tag will stay private, only visible to those you allow.";
|
||||
|
||||
/* eslint-disable prettier/prettier */
|
||||
export const UNIT_SHORT: Record<string, string> = {
|
||||
|
||||
@@ -6,6 +6,7 @@ import router from "./router";
|
||||
import axios from "axios";
|
||||
import VueAxios from "vue-axios";
|
||||
import Notifications from "notiwind";
|
||||
import { useVOnboarding } from "v-onboarding";
|
||||
|
||||
import "./assets/styles/tailwind.css";
|
||||
|
||||
@@ -45,6 +46,7 @@ import {
|
||||
faHand,
|
||||
faHandHoldingHeart,
|
||||
faHouseChimney,
|
||||
faLeftRight,
|
||||
faLocationDot,
|
||||
faLongArrowAltLeft,
|
||||
faLongArrowAltRight,
|
||||
@@ -105,6 +107,7 @@ library.add(
|
||||
faHand,
|
||||
faHandHoldingHeart,
|
||||
faHouseChimney,
|
||||
faLeftRight,
|
||||
faLocationDot,
|
||||
faLongArrowAltLeft,
|
||||
faLongArrowAltRight,
|
||||
@@ -140,4 +143,5 @@ createApp(App)
|
||||
.use(VueAxios, axios)
|
||||
.use(router)
|
||||
.use(Notifications)
|
||||
.use(useVOnboarding)
|
||||
.mount("#app");
|
||||
|
||||
@@ -98,12 +98,6 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "help" */ "../views/HelpView.vue"),
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
name: "home",
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "home" */ "../views/HomeView.vue"),
|
||||
},
|
||||
{
|
||||
path: "/help-notifications",
|
||||
name: "help-notifications",
|
||||
@@ -112,6 +106,20 @@ const routes: Array<RouteRecordRaw> = [
|
||||
/* webpackChunkName: "help-notifications" */ "../views/HelpNotificationsView.vue"
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/help-onboarding",
|
||||
name: "help-onboarding",
|
||||
component: () =>
|
||||
import(
|
||||
/* webpackChunkName: "help-onboarding" */ "../views/HelpOnboardingView.vue"
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
name: "home",
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "home" */ "../views/HomeView.vue"),
|
||||
},
|
||||
{
|
||||
path: "/identity-switcher",
|
||||
name: "identity-switcher",
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
<span />
|
||||
<span>
|
||||
<a
|
||||
@click="showHintsForOnboarding()"
|
||||
href="/help-onboarding"
|
||||
target="_blank"
|
||||
class="text-xs uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-1 rounded-md ml-1"
|
||||
>
|
||||
Onboarding Guide
|
||||
@@ -510,18 +511,6 @@ export default class ContactsView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
showHintsForOnboarding() {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "info",
|
||||
title: "Onboard Someone",
|
||||
text: libsUtil.ONBOARD_MESSAGE,
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
|
||||
async onClickNewContact(): Promise<void> {
|
||||
if (!this.contactInput) {
|
||||
this.$notify(
|
||||
@@ -531,7 +520,7 @@ export default class ContactsView extends Vue {
|
||||
title: "No Contact",
|
||||
text: "There was no contact info to add.",
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -559,7 +548,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Contacts Added",
|
||||
text: "Each contact was added. Nothing was sent to the server.",
|
||||
},
|
||||
-1, // keeping it up so that the "visibility" message is seen
|
||||
3000, // keeping it up so that the "visibility" message is seen
|
||||
);
|
||||
} catch (e) {
|
||||
this.$notify(
|
||||
@@ -664,7 +653,7 @@ export default class ContactsView extends Vue {
|
||||
title: "No Contact Info",
|
||||
text: "The contact info could not be parsed.",
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
@@ -686,7 +675,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Incomplete Contact",
|
||||
text: "Cannot add a contact without a DID.",
|
||||
},
|
||||
-1,
|
||||
5000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -698,7 +687,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Invalid DID",
|
||||
text: "The DID is not valid. It must begin with 'did:'",
|
||||
},
|
||||
-1,
|
||||
5000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -737,7 +726,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Contact Added",
|
||||
text: addedMessage,
|
||||
},
|
||||
-1, // keeping it up so that the "visibility" message is seen
|
||||
3000,
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -853,7 +842,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Registration Still Unknown",
|
||||
text: message,
|
||||
},
|
||||
-1,
|
||||
5000,
|
||||
);
|
||||
} else if (resp.data?.success?.handleId) {
|
||||
contact.registered = true;
|
||||
@@ -892,7 +881,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Registration Error",
|
||||
text: userMessage,
|
||||
},
|
||||
-1,
|
||||
5000,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -933,7 +922,7 @@ export default class ContactsView extends Vue {
|
||||
(visibility ? "" : "not ") +
|
||||
"see your activity.",
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
}
|
||||
contact.seesMe = visibility;
|
||||
@@ -953,7 +942,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Error Setting Visibility",
|
||||
text: message,
|
||||
},
|
||||
-1,
|
||||
5000,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -965,7 +954,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Error Setting Visibility",
|
||||
text: "Check connectivity and try again.",
|
||||
},
|
||||
-1,
|
||||
5000,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -997,7 +986,7 @@ export default class ContactsView extends Vue {
|
||||
(visibility ? "" : "not ") +
|
||||
"see your activity.",
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
} else {
|
||||
console.error("Got bad server response checking visibility:", resp);
|
||||
@@ -1009,7 +998,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Error Checking Visibility",
|
||||
text: message,
|
||||
},
|
||||
-1,
|
||||
5000,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -1021,7 +1010,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Error Checking Visibility",
|
||||
text: "Check connectivity and try again.",
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1069,7 +1058,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Input Error",
|
||||
text: "This is not a valid number of hours: " + this.hourInput,
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
} else if (parseFloat(this.hourInput) == 0 && !this.hourDescriptionInput) {
|
||||
this.$notify(
|
||||
@@ -1079,7 +1068,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Input Error",
|
||||
text: "Giving no hours or description does nothing.",
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
} else if (!identity) {
|
||||
this.$notify(
|
||||
@@ -1089,7 +1078,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Status Error",
|
||||
text: "No identifier is available.",
|
||||
},
|
||||
-1,
|
||||
3000,
|
||||
);
|
||||
} else {
|
||||
// ask to confirm amount
|
||||
@@ -1218,7 +1207,7 @@ export default class ContactsView extends Vue {
|
||||
title: "Error Sending Give",
|
||||
text: userMessage,
|
||||
},
|
||||
-1,
|
||||
5000,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,11 @@
|
||||
|
||||
<p class="text-center mb-2 mt-6 italic">
|
||||
Sign & Send to publish to the world
|
||||
<fa
|
||||
icon="circle-info"
|
||||
class="pl-2 text-blue-500 cursor-pointer"
|
||||
@click="explainData()"
|
||||
/>
|
||||
</p>
|
||||
<button
|
||||
class="block w-full text-center text-lg font-bold uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md mb-2"
|
||||
@@ -288,6 +293,45 @@ export default class GiftedDetails extends Vue {
|
||||
}
|
||||
|
||||
async confirm() {
|
||||
if (!this.activeDid) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: "You must select an identifier before you can record a give.",
|
||||
},
|
||||
2000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (parseFloat(this.amountInput) < 0) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
text: "You may not send a negative number.",
|
||||
title: "",
|
||||
},
|
||||
2000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!this.description && !parseFloat(this.amountInput)) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: `You must enter a description or some number of ${
|
||||
this.libsUtil.UNIT_LONG[this.unitCode]
|
||||
}.`,
|
||||
},
|
||||
2000,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
@@ -297,6 +341,7 @@ export default class GiftedDetails extends Vue {
|
||||
},
|
||||
1000,
|
||||
);
|
||||
|
||||
// this is asynchronous, but we don't need to wait for it to complete
|
||||
await this.recordGive();
|
||||
}
|
||||
@@ -309,34 +354,6 @@ export default class GiftedDetails extends Vue {
|
||||
* @param unitCode may be omitted, defaults to "HUR"
|
||||
*/
|
||||
public async recordGive() {
|
||||
if (!this.activeDid) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: "You must select an identifier before you can record a give.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.description && !this.amountInput) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: `You must enter a description or some number of ${
|
||||
this.libsUtil.UNIT_LONG[this.unitCode]
|
||||
}.`,
|
||||
},
|
||||
-1,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const identity = await libsUtil.getIdentity(this.activeDid);
|
||||
const result = await createAndSubmitGive(
|
||||
@@ -424,5 +441,17 @@ export default class GiftedDetails extends Vue {
|
||||
result.response?.data?.error?.message
|
||||
);
|
||||
}
|
||||
|
||||
explainData() {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Data Sharing",
|
||||
text: libsUtil.PRIVACY_MESSAGE,
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
69
src/views/HelpOnboardingView.vue
Normal file
69
src/views/HelpOnboardingView.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<!-- Don't include nav buttons since this is shown in a different window. -->
|
||||
|
||||
<!-- CONTENT -->
|
||||
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
||||
<!-- Breadcrumb -->
|
||||
<div class="mb-8">
|
||||
<!-- Don't include 'back' button since this is shown in a different window. -->
|
||||
<!-- Heading -->
|
||||
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
|
||||
Time Safari Onboarding Instructions
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<!-- eslint-disable prettier/prettier -->
|
||||
<div class="ml-4">
|
||||
<h1 class="font-bold text-xl">Install</h1>
|
||||
<div>
|
||||
<p>
|
||||
1) Have them visit TimeSafari.app in a browser, preferably Chrome or Safari.
|
||||
</p>
|
||||
<p>
|
||||
2) Have them "Install" the site to their desktop.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h1 class="font-bold text-xl">Add Contact & Register</h1>
|
||||
<div>
|
||||
<p>
|
||||
3) Have them follow their yellow prompts.
|
||||
</p>
|
||||
<p>
|
||||
4) Add them to your contacts <fa icon="users" />
|
||||
</p>
|
||||
<p>
|
||||
5) Register them <fa icon="person-circle-question" />
|
||||
</p>
|
||||
<p>
|
||||
6) Add yourself to their contacts <fa icon="users" />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h1 class="font-bold text-xl">Enable Notifications</h1>
|
||||
<div>
|
||||
<p>
|
||||
7) Enable notifications from <fa icon="circle-user" />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h1 class="font-bold text-xl">Discuss Backups</h1>
|
||||
<div>
|
||||
<p>
|
||||
8) Exporting backups <fa icon="circle-user" /> are important if they lose their phone --- especially for the Identifier Seed!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- eslint enable -->
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
|
||||
@Component({ components: { QuickNav } })
|
||||
export default class Help extends Vue {}
|
||||
</script>
|
||||
@@ -39,22 +39,22 @@
|
||||
and network.
|
||||
</p>
|
||||
<p>
|
||||
You can show giving and also offer help to ideas, based on others'
|
||||
willingness to help out, too. You can record your own ideas and invite
|
||||
others to collaborate.
|
||||
You highlight giving and also offer help to ideas -- which could be
|
||||
conditional on others' willingness to help, too.
|
||||
You can record your own ideas and invite others to collaborate.
|
||||
</p>
|
||||
<p>
|
||||
This app uses the power of cryptography to build a reputation, recording
|
||||
activity that you can share at your discretion. You put some activity
|
||||
public, but your sensitive information is not shared with anyone,
|
||||
including our services. This is in contrast to Meta and Google, who hold
|
||||
your data and allow you use it. Those services are useful, but they have
|
||||
the control; this app gives you the control.
|
||||
public, but these services don't share your ID with others without explicit consent.
|
||||
This is in contrast to Meta and Google, who hold
|
||||
your data and allow you use it while they manage sharing...
|
||||
those services are useful but they have the control, whereas this app gives you the control.
|
||||
</p>
|
||||
|
||||
<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
|
||||
You need someone to register you, like the person who told you
|
||||
about this app, on the Contacts
|
||||
<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
|
||||
@@ -83,9 +83,9 @@
|
||||
|
||||
<h2 class="text-xl font-semibold">How do I add someone else?</h2>
|
||||
<p>
|
||||
<button class="text-blue-500" @click="showOnboardInfo">
|
||||
<a href="/help-onboarding" target="_blank" class="text-blue-500">
|
||||
Click here to show an alert with the steps.
|
||||
</button>
|
||||
</a>
|
||||
To start scanning, go
|
||||
<router-link class="text-blue-500" to="/contact-qr">here.</router-link>
|
||||
</p>
|
||||
@@ -198,9 +198,7 @@
|
||||
<ul>
|
||||
<li class="list-disc list-outside ml-4">
|
||||
Chrome:
|
||||
<a href="chrome://settings/content/all" class="text-blue-500"
|
||||
>clear here</a
|
||||
>
|
||||
Clear at chrome://settings/content/all and
|
||||
also clear under dev tools Application
|
||||
</li>
|
||||
<li class="list-disc list-outside ml-4">
|
||||
@@ -378,7 +376,6 @@ import { Component, Vue } from "vue-facing-decorator";
|
||||
import * as Package from "../../package.json";
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
import { NotificationIface } from "@/constants/app";
|
||||
import { ONBOARD_MESSAGE } from "@/libs/util";
|
||||
|
||||
@Component({ components: { QuickNav } })
|
||||
export default class Help extends Vue {
|
||||
@@ -386,17 +383,5 @@ export default class Help extends Vue {
|
||||
|
||||
package = Package;
|
||||
commitHash = process.env.VUE_APP_GIT_HASH;
|
||||
|
||||
showOnboardInfo() {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "info",
|
||||
title: "Onboard Someone",
|
||||
text: ONBOARD_MESSAGE,
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -115,7 +115,9 @@
|
||||
<div v-else>
|
||||
<!-- activeDid && isRegistered -->
|
||||
<div class="mb-4">
|
||||
<h2 class="text-xl font-bold">Record Something Given By:</h2>
|
||||
<h2 id="headingRecordSomething" class="text-xl font-bold">
|
||||
Record Something Given By:
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<ul class="grid grid-cols-4 gap-x-3 gap-y-5 text-center mb-5">
|
||||
@@ -162,6 +164,12 @@
|
||||
>
|
||||
Ideas...
|
||||
</button>
|
||||
<button
|
||||
@click="startOnboardingDialog()"
|
||||
class="block text-center text-md font-bold bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md"
|
||||
>
|
||||
(v-onboarding)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -172,10 +180,13 @@
|
||||
showGivenToUser="true"
|
||||
/>
|
||||
<GiftedPrompts ref="giftedPrompts" />
|
||||
<OnboardingDialog ref="onboardingDialog" />
|
||||
|
||||
<!-- Results List -->
|
||||
<div class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4">
|
||||
<h2 class="text-xl font-bold mb-4">Latest Activity</h2>
|
||||
<h2 id="headingLatestActivity" class="text-xl font-bold mb-4">
|
||||
Latest Activity
|
||||
</h2>
|
||||
<InfiniteScroll @reached-bottom="loadMoreGives">
|
||||
<ul class="border-t border-slate-300">
|
||||
<li
|
||||
@@ -207,7 +218,7 @@
|
||||
{{ giveDescription(record) }}
|
||||
<a @click="onClickLoadClaim(record.jwtId)">
|
||||
<fa
|
||||
icon="circle-info"
|
||||
icon="file-lines"
|
||||
class="pl-2 text-blue-500 cursor-pointer"
|
||||
></fa>
|
||||
</a>
|
||||
@@ -253,6 +264,7 @@ import GiftedPrompts from "@/components/GiftedPrompts.vue";
|
||||
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
import TopMessage from "@/components/TopMessage.vue";
|
||||
import OnboardingDialog from "@/components/OnboardingDialog.vue";
|
||||
import { NotificationIface } from "@/constants/app";
|
||||
import { db, accountsDB } from "@/db/index";
|
||||
import { Account } from "@/db/tables/accounts";
|
||||
@@ -287,6 +299,7 @@ interface GiveRecordWithContactInfo extends GiveServerRecord {
|
||||
EntityIcon,
|
||||
InfiniteScroll,
|
||||
TopMessage,
|
||||
OnboardingDialog,
|
||||
},
|
||||
})
|
||||
export default class HomeView extends Vue {
|
||||
@@ -350,6 +363,29 @@ export default class HomeView extends Vue {
|
||||
|
||||
await this.updateAllFeed();
|
||||
|
||||
// Other things attempted:
|
||||
//
|
||||
// Tried these above in the field area:
|
||||
// onboardingWrapper = ref(null);
|
||||
// onboardSteps = [
|
||||
// {
|
||||
// attachTo: { element: "#headingRecordSomething" },
|
||||
// content: { title: "Welcome!" },
|
||||
// },
|
||||
// {
|
||||
// attachTo: { element: "#headingLatestActivity" },
|
||||
// content: {
|
||||
// title: "Testing v-onboarding..",
|
||||
// description:
|
||||
// "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.",
|
||||
// },
|
||||
// },
|
||||
// ];
|
||||
//
|
||||
// Tried these inside this method:
|
||||
// const { start } = useVOnboarding(this.$refs.onboardingDialog);
|
||||
// start();
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} catch (err: any) {
|
||||
console.error("Error retrieving settings or feed.", err);
|
||||
@@ -574,5 +610,9 @@ export default class HomeView extends Vue {
|
||||
openGiftedPrompts() {
|
||||
(this.$refs.giftedPrompts as GiftedPrompts).open();
|
||||
}
|
||||
|
||||
startOnboardingDialog() {
|
||||
/* Start the onboarding dialog here. */
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -265,6 +265,8 @@ export default class NewEditProjectView extends Vue {
|
||||
vcClaim.agent = {
|
||||
identifier: this.agentDid,
|
||||
};
|
||||
} else {
|
||||
delete vcClaim.agent;
|
||||
}
|
||||
if (this.includeLocation) {
|
||||
vcClaim.location = {
|
||||
@@ -274,6 +276,8 @@ export default class NewEditProjectView extends Vue {
|
||||
longitude: this.longitude,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
delete vcClaim.location;
|
||||
}
|
||||
// Make a payload for the claim
|
||||
const vcPayload = {
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
</div>
|
||||
|
||||
<a @click="onClickLoadClaim(projectId)" class="cursor-pointer">
|
||||
<fa icon="circle-info" class="pl-2 pt-1 text-blue-500" />
|
||||
<fa icon="file-lines" class="pl-2 pt-1 text-blue-500" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
@click="onClickLoadClaim(offer.jwtId as string)"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<fa icon="circle-info" class="pl-2 pt-1 text-blue-500" />
|
||||
<fa icon="file-lines" class="pl-2 pt-1 text-blue-500" />
|
||||
</a>
|
||||
<a
|
||||
v-if="checkIsFulfillable(offer)"
|
||||
@@ -289,7 +289,7 @@
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<a @click="onClickLoadClaim(give.jwtId)">
|
||||
<fa icon="circle-info" class="text-blue-500 cursor-pointer" />
|
||||
<fa icon="file-lines" class="text-blue-500 cursor-pointer" />
|
||||
</a>
|
||||
<a v-if="checkIsConfirmable(give)" @click="confirmClaim(give)">
|
||||
<fa icon="circle-check" class="text-blue-500 cursor-pointer" />
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
|
||||
<a @click="onClickLoadClaim(offer.jwtId)">
|
||||
<fa
|
||||
icon="circle-info"
|
||||
icon="file-lines"
|
||||
class="pl-2 text-blue-500 cursor-pointer"
|
||||
></fa>
|
||||
</a>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
}}
|
||||
<a @click="onClickLoadClaim(record.id)">
|
||||
<fa
|
||||
icon="circle-info"
|
||||
icon="file-lines"
|
||||
class="pl-2 text-blue-500 cursor-pointer"
|
||||
/>
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user