diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..6d39387 --- /dev/null +++ b/.env.development @@ -0,0 +1,6 @@ +# Only the variables that start with VUE_APP_ are seen in the application process.env in Vue. + +# this won't resolve as a URL on production; it's a URN only found in the test system +VUE_APP_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HNTZYJJXTGT0EZS3VEJGX7AK +VUE_APP_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 +VUE_APP_DEFAULT_IMAGE_API_SERVER=http://localhost:3002 diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..9adc667 --- /dev/null +++ b/.env.production @@ -0,0 +1,4 @@ +# Only the variables that start with VUE_APP_ are seen in the application process.env in Vue. +VUE_APP_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01GXYPFF7FA03NXKPYY142PY4H +VUE_APP_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch +VUE_APP_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app diff --git a/CHANGELOG.md b/CHANGELOG.md index 96e74ad..280b723 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -### Changed in DB -- ? +### Added +- Photo on gift records +### Fixed +- Environment variable for BVC meetings project +### Changed in DB or environment +- Test that a new browser session will get the right default API +- Test that a new browser session will send the right BVC meetings project -## [0.2.17] - 2024.03.01- 3612ea42240c5e1b7d7eff29a39ff18f1b869b36 +## [0.2.17] - 2024.03.01 - 3612ea42240c5e1b7d7eff29a39ff18f1b869b36 ### Added - Shortcut page for Bountiful Voluntaryist Community ### Changed diff --git a/README.md b/README.md index be28ce0..04286a0 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,9 @@ npm run lint * Update the project.task.yaml & CHANGELOG.md & the version in package.json, run `npm install`. -* If production: change src/constants/app.ts DEFAULT_*_SERVER to be "PROD" and package.json to remove "_Test". Also record what version is on production. +* If production: change package.json to remove "_Test". Also record what version is on production. -* `npm run build` +* `npm run build-dev` for test servers or `npm run build` for production. * Get on the server and back up the time-safari folder. @@ -44,9 +44,9 @@ npm run lint * 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. Tag if you didn't before. Also record what version is on production. +* 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 wth the new version.](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) +* [Tag with the new version.](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) diff --git a/package-lock.json b/package-lock.json index 11bee50..6be25ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,7 @@ "readable-stream": "^4.4.2", "reflect-metadata": "^0.1.13", "register-service-worker": "^1.7.2", + "simple-vue-camera": "^1.1.3", "three": "^0.156.1", "ua-parser-js": "^1.0.37", "util": "^0.12.5", @@ -25438,6 +25439,11 @@ "node": ">= 5.10.0" } }, + "node_modules/simple-vue-camera": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/simple-vue-camera/-/simple-vue-camera-1.1.3.tgz", + "integrity": "sha512-GVAYq1BMI9cHt+h24tu2dfIFFvhjVQ1M8IkK5LmrKcYoBA8FZlLNlhrHC2NnTPbMAXIvJn1Bqx8X6Q31+Y2+jA==" + }, "node_modules/sirv": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", diff --git a/package.json b/package.json index 5844680..17b4044 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", + "build-dev": "vue-cli-service build --mode development", "lint": "vue-cli-service lint" }, "dependencies": { @@ -54,6 +55,7 @@ "readable-stream": "^4.4.2", "reflect-metadata": "^0.1.13", "register-service-worker": "^1.7.2", + "simple-vue-camera": "^1.1.3", "three": "^0.156.1", "ua-parser-js": "^1.0.37", "util": "^0.12.5", diff --git a/project.task.yaml b/project.task.yaml index 970760d..ea7b5cc 100644 --- a/project.task.yaml +++ b/project.task.yaml @@ -1,6 +1,12 @@ tasks : +- alert & stop if give amount < 0 +- onboarding video + +- .1 on feed, don't show "to someone anonymous" if it's to a project +- .1 on ideas, put an "x" to close it + - .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 - .5 stop from seeing an error on the first page when browser doesn't support service workers (which I've seen on iPhone; visible in Firefox private window) @@ -9,14 +15,14 @@ tasks : - .2 list the "show more" contacts alphabetically - 32 image on give : - - Show a camera to take a picture - - Scale the image to a reasonable size - - Upload to a public readable place - - check the rate limits - - use CID (hash?) - - put the image URL in the claim - - Rates - images erased? - - image not associated with JWT ULID since that's assigned later + - upload a photo from elsewhere + - go-live - create cert for new image domain, set up haproxy redirect, test-image-api.timesafari.app + - make Time Safari a share_target for images + +- 08 add image on profile + +- ask to detect location & record it in settings +- if personal location is set, show potential local affiliations - 24 compelling UI for credential presentations - discover who in my network has activity on a project @@ -37,6 +43,7 @@ tasks : - randomize (not show in order) - checkboxes - show non-person-oriented messages, show only contacts, show only projects +- .5 add a notice on the front page if their notifications are off - 08 allow user to add a time when they want their daily notification - .5 prompt for the name directly when they visit the QR scan page diff --git a/src/App.vue b/src/App.vue index 484d015..d8ee886 100644 --- a/src/App.vue +++ b/src/App.vue @@ -148,6 +148,37 @@ class="w-full" role="alert" > +
+
+
+

+ {{ notification.title }} +

+ + + + +
+
+
-
+
{{ libsUtil.UNIT_SHORT[unitCode] }}
-
- - - - +
- - + + More Options +

@@ -93,9 +104,9 @@ export default class GiftedDialog extends Vue { apiServer = ""; amountInput = "0"; - giver?: GiverInputInfo; // undefined means no identified giver agent description = ""; givenToUser = false; + giver?: GiverInputInfo; // undefined means no identified giver agent isTrade = false; offerId = ""; unitCode = "HUR"; diff --git a/src/components/GiftedPhotoDialog.vue b/src/components/GiftedPhotoDialog.vue new file mode 100644 index 0000000..3278787 --- /dev/null +++ b/src/components/GiftedPhotoDialog.vue @@ -0,0 +1,211 @@ + + + + + diff --git a/src/constants/app.ts b/src/constants/app.ts index 4e94d01..4504716 100644 --- a/src/constants/app.ts +++ b/src/constants/app.ts @@ -12,10 +12,20 @@ export enum AppString { TEST1_PUSH_SERVER = "https://test.timesafari.app", TEST2_PUSH_SERVER = "https://timesafari-pwa.anomalistlabs.com", + PROD_IMAGE_API_SERVER = "https://image-api.timesafari.app", + TEST_IMAGE_API_SERVER = "https://test-image-api.timesafari.app", + LOCAL_IMAGE_API_SERVER = "http://localhost:3001", + NO_CONTACT_NAME = "(no name)", } -export const DEFAULT_ENDORSER_API_SERVER = AppString.TEST_ENDORSER_API_SERVER; +export const DEFAULT_ENDORSER_API_SERVER = + process.env.VUE_APP_DEFAULT_ENDORSER_API_SERVER || + AppString.TEST_ENDORSER_API_SERVER; + +export const DEFAULT_IMAGE_API_SERVER = + process.env.VUE_APP_DEFAULT_IMAGE_API_SERVER || + AppString.TEST_IMAGE_API_SERVER; export const DEFAULT_PUSH_SERVER = window.location.protocol + "//" + window.location.host; @@ -29,4 +39,5 @@ export interface NotificationIface { type: string; // "toast" | "info" | "success" | "warning" | "danger" title: string; text: string; + onYes?: () => Promise; } diff --git a/src/libs/endorserServer.ts b/src/libs/endorserServer.ts index 4885611..5972708 100644 --- a/src/libs/endorserServer.ts +++ b/src/libs/endorserServer.ts @@ -67,6 +67,7 @@ export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = { issuer: "", }; +// a summary record; the VC is found the fullClaim field export interface GiveServerRecord { agentDid: string; amount: number; @@ -81,6 +82,7 @@ export interface GiveServerRecord { unit: string; } +// a summary record; the VC is found the fullClaim field export interface OfferServerRecord { amount: number; amountGiven: number; @@ -98,13 +100,14 @@ export interface OfferServerRecord { validThrough: string; } +// a summary record; the VC is not currently part of this record export interface PlanServerRecord { agentDid?: string; // optional, if the issuer wants someone else to manage as well description: string; endTime?: string; fulfillsPlanHandleId: string; - issuerDid: string; handleId: string; + issuerDid: string; locLat?: number; locLon?: number; startTime?: string; @@ -120,6 +123,7 @@ export interface GiveVerifiableCredential { description?: string; fulfills?: { "@type": string; identifier?: string; lastClaimId?: string }[]; identifier?: string; + image?: string; object?: { amountOfThisGood: number; unitCode: string }; recipient?: { identifier: string }; } @@ -183,7 +187,7 @@ export interface PlanData { rowid?: string; } -export interface RateLimits { +export interface EndorserRateLimits { doneClaimsThisWeek: string; doneRegistrationsThisMonth: string; maxClaimsPerWeek: string; @@ -192,6 +196,12 @@ export interface RateLimits { nextWeekBeginDateTime: string; } +export interface ImageRateLimits { + doneImagesThisWeek: string; + maxImagesPerWeek: string; + nextWeekBeginDateTime: string; +} + export interface VerifiableCredential { "@context": string; "@type": string; @@ -434,6 +444,7 @@ export async function createAndSubmitGive( fulfillsProjectHandleId?: string, fulfillsOfferHandleId?: string, isTrade: boolean = false, + imageUrl?: string, ): Promise { const vcClaim: GiveVerifiableCredential = { "@context": "https://schema.org", @@ -460,6 +471,9 @@ export async function createAndSubmitGive( identifier: fulfillsOfferHandleId, }); } + if (imageUrl) { + vcClaim.image = imageUrl; + } return createAndSubmitClaim( vcClaim as GenericServerRecord, identity, @@ -780,8 +794,8 @@ export const claimSpecialDescription = ( }; export const BVC_MEETUPS_PROJECT_CLAIM_ID = - //"https://endorser.ch/entity/01GXYPFF7FA03NXKPYY142PY4H"; - "https://endorser.ch/entity/01HNTZYJJXTGT0EZS3VEJGX7AK"; + process.env.VUE_APP_BVC_MEETUPS_PROJECT_CLAIM_ID || + "https://endorser.ch/entity/01HNTZYJJXTGT0EZS3VEJGX7AK"; // this won't resolve as a URL on production; it's a URN only found in the test system export const bvcMeetingJoinClaim = (did: string, startTime: string) => { return { diff --git a/src/main.ts b/src/main.ts index c97e44d..a99c82c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -18,6 +18,8 @@ import { faBitcoinSign, faBurst, faCalendar, + faCamera, + faCheck, faChevronLeft, faChevronRight, faCircle, @@ -76,6 +78,8 @@ library.add( faBitcoinSign, faBurst, faCalendar, + faCamera, + faCheck, faChevronLeft, faChevronRight, faCircle, @@ -127,9 +131,11 @@ library.add( ); import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; +import Camera from "simple-vue-camera"; createApp(App) .component("fa", FontAwesomeIcon) + .component("camera", Camera) .use(createPinia()) .use(VueAxios, axios) .use(router) diff --git a/src/router/index.ts b/src/router/index.ts index b3c078d..4f3e9fe 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -84,6 +84,14 @@ const routes: Array = [ component: () => import(/* webpackChunkName: "discover" */ "../views/DiscoverView.vue"), }, + { + path: "/gifted-details", + name: "gifted-details", + component: () => + import( + /* webpackChunkName: "gifted-details" */ "../views/GiftedDetails.vue" + ), + }, { path: "/help", name: "help", diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index 343871b..d5272f0 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -96,7 +96,7 @@

@@ -157,28 +157,39 @@

{{ limitsMessage }}
-
-

- You have done {{ limits.doneClaimsThisWeek }} claims out of - {{ limits.maxClaimsPerWeek }} for this week. Your claims - counter resets at +

+

+ You have done + {{ endorserLimits.doneClaimsThisWeek }} claims out of + {{ endorserLimits.maxClaimsPerWeek }} for this week. Your + claims counter resets at {{ - readableTime(limits.nextWeekBeginDateTime) + readableDate(endorserLimits.nextWeekBeginDateTime) }}

-

+

You have done - {{ limits.doneRegistrationsThisMonth }} registrations out of - {{ limits.maxRegistrationsPerMonth }} for this month. + {{ endorserLimits.doneRegistrationsThisMonth }} registrations + out of {{ endorserLimits.maxRegistrationsPerMonth }} for this + month. (You can register nobody on your first day, and after that only one a day in your first month.) Your registration counter resets at - {{ readableTime(limits.nextMonthBeginDateTime) }} + {{ readableDate(endorserLimits.nextMonthBeginDateTime) }}

+

+ You have uploaded + {{ imageLimits?.doneImagesThisWeek }} images out of + {{ imageLimits?.maxImagesPerWeek }} for this week. Your image + counter resets at + {{ + readableDate(imageLimits?.nextWeekBeginDateTime) + }} +