forked from jsnbuchanan/crowd-funder-for-time-pwa
show the image rate limits
This commit is contained in:
@@ -6,6 +6,8 @@ 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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Added
|
||||||
|
- Photo on gift records
|
||||||
### Fixed
|
### Fixed
|
||||||
- Environment variable for BVC meetings project
|
- Environment variable for BVC meetings project
|
||||||
### Changed in DB or environment
|
### Changed in DB or environment
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
tasks :
|
tasks :
|
||||||
|
|
||||||
- alert & stop if give amount < 0
|
- 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 feed, don't show "to someone anonymous" if it's to a project
|
||||||
- .1 on ideas, put an "x" to close it
|
- .1 on ideas, put an "x" to close it
|
||||||
@@ -14,12 +15,11 @@ tasks :
|
|||||||
- .2 list the "show more" contacts alphabetically
|
- .2 list the "show more" contacts alphabetically
|
||||||
|
|
||||||
- 32 image on give :
|
- 32 image on give :
|
||||||
- ping endpoint
|
|
||||||
- limits endpoint
|
|
||||||
- upload a photo from elsewhere
|
- upload a photo from elsewhere
|
||||||
- go-live - create cert for new image domain, set up haproxy redirect
|
- 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 image on profile
|
- 08 add image on profile
|
||||||
|
|
||||||
- ask to detect location & record it in settings
|
- ask to detect location & record it in settings
|
||||||
- if personal location is set, show potential local affiliations
|
- if personal location is set, show potential local affiliations
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ export interface PlanData {
|
|||||||
rowid?: string;
|
rowid?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RateLimits {
|
export interface EndorserRateLimits {
|
||||||
doneClaimsThisWeek: string;
|
doneClaimsThisWeek: string;
|
||||||
doneRegistrationsThisMonth: string;
|
doneRegistrationsThisMonth: string;
|
||||||
maxClaimsPerWeek: string;
|
maxClaimsPerWeek: string;
|
||||||
@@ -196,6 +196,12 @@ export interface RateLimits {
|
|||||||
nextWeekBeginDateTime: string;
|
nextWeekBeginDateTime: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ImageRateLimits {
|
||||||
|
doneImagesThisWeek: string;
|
||||||
|
maxImagesPerWeek: string;
|
||||||
|
nextWeekBeginDateTime: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface VerifiableCredential {
|
export interface VerifiableCredential {
|
||||||
"@context": string;
|
"@context": string;
|
||||||
"@type": string;
|
"@type": string;
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
<!-- Registration notice -->
|
<!-- Registration notice -->
|
||||||
<!-- We won't show any loading indicator because it usually doesn't change anything. We'll just pop the message in only if we discover that they need it. -->
|
<!-- We won't show any loading indicator because it usually doesn't change anything. We'll just pop the message in only if we discover that they need it. -->
|
||||||
<div
|
<div
|
||||||
v-if="!loadingLimits && !limits?.nextWeekBeginDateTime"
|
v-if="!loadingLimits && !endorserLimits?.nextWeekBeginDateTime"
|
||||||
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
|
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
|
||||||
>
|
>
|
||||||
<p class="mb-4">
|
<p class="mb-4">
|
||||||
@@ -157,28 +157,39 @@
|
|||||||
<div>
|
<div>
|
||||||
{{ limitsMessage }}
|
{{ limitsMessage }}
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!!limits?.nextWeekBeginDateTime">
|
<div v-if="!!endorserLimits?.nextWeekBeginDateTime">
|
||||||
<p class="mb-3 text-sm">
|
|
||||||
You have done <b>{{ limits.doneClaimsThisWeek }}</b> claims out of
|
|
||||||
<b>{{ limits.maxClaimsPerWeek }}</b> for this week. Your claims
|
|
||||||
counter resets at
|
|
||||||
<b class="whitespace-nowrap">{{
|
|
||||||
readableTime(limits.nextWeekBeginDateTime)
|
|
||||||
}}</b>
|
|
||||||
</p>
|
|
||||||
<p class="text-sm">
|
<p class="text-sm">
|
||||||
You have done
|
You have done
|
||||||
<b>{{ limits.doneRegistrationsThisMonth }}</b> registrations out of
|
<b>{{ endorserLimits.doneClaimsThisWeek }} claims</b> out of
|
||||||
<b>{{ limits.maxRegistrationsPerMonth }}</b> for this month.
|
<b>{{ endorserLimits.maxClaimsPerWeek }}</b> for this week. Your
|
||||||
|
claims counter resets at
|
||||||
|
<b class="whitespace-nowrap">{{
|
||||||
|
readableDate(endorserLimits.nextWeekBeginDateTime)
|
||||||
|
}}</b>
|
||||||
|
</p>
|
||||||
|
<p class="mt-3 text-sm">
|
||||||
|
You have done
|
||||||
|
<b>{{ endorserLimits.doneRegistrationsThisMonth }} registrations</b>
|
||||||
|
out of <b>{{ endorserLimits.maxRegistrationsPerMonth }}</b> for this
|
||||||
|
month.
|
||||||
<i
|
<i
|
||||||
>(You can register nobody on your first day, and after that only one
|
>(You can register nobody on your first day, and after that only one
|
||||||
a day in your first month.)</i
|
a day in your first month.)</i
|
||||||
>
|
>
|
||||||
Your registration counter resets at
|
Your registration counter resets at
|
||||||
<b class="whitespace-nowrap">
|
<b class="whitespace-nowrap">
|
||||||
{{ readableTime(limits.nextMonthBeginDateTime) }}
|
{{ readableDate(endorserLimits.nextMonthBeginDateTime) }}
|
||||||
</b>
|
</b>
|
||||||
</p>
|
</p>
|
||||||
|
<p class="mt-3 text-sm" v-if="!!imageLimits">
|
||||||
|
You have uploaded
|
||||||
|
<b>{{ imageLimits?.doneImagesThisWeek }} images</b> out of
|
||||||
|
<b>{{ imageLimits?.maxImagesPerWeek }}</b> for this week. Your image
|
||||||
|
counter resets at
|
||||||
|
<b class="whitespace-nowrap">{{
|
||||||
|
readableDate(imageLimits?.nextWeekBeginDateTime)
|
||||||
|
}}</b>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="block float-right w-fit text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mt-2"
|
class="block float-right w-fit text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mt-2"
|
||||||
@@ -509,6 +520,7 @@ import QuickNav from "@/components/QuickNav.vue";
|
|||||||
import TopMessage from "@/components/TopMessage.vue";
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import {
|
import {
|
||||||
AppString,
|
AppString,
|
||||||
|
DEFAULT_IMAGE_API_SERVER,
|
||||||
DEFAULT_PUSH_SERVER,
|
DEFAULT_PUSH_SERVER,
|
||||||
NotificationIface,
|
NotificationIface,
|
||||||
} from "@/constants/app";
|
} from "@/constants/app";
|
||||||
@@ -516,7 +528,11 @@ import { db, accountsDB } from "@/db/index";
|
|||||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
import { IIdentifier } from "@veramo/core";
|
import { IIdentifier } from "@veramo/core";
|
||||||
import { ErrorResponse, RateLimits } from "@/libs/endorserServer";
|
import {
|
||||||
|
ErrorResponse,
|
||||||
|
EndorserRateLimits,
|
||||||
|
ImageRateLimits,
|
||||||
|
} from "@/libs/endorserServer";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const Buffer = require("buffer/").Buffer;
|
const Buffer = require("buffer/").Buffer;
|
||||||
@@ -542,7 +558,9 @@ export default class AccountViewView extends Vue {
|
|||||||
apiServerInput = "";
|
apiServerInput = "";
|
||||||
derivationPath = "";
|
derivationPath = "";
|
||||||
downloadUrl = ""; // because DuckDuckGo doesn't download on automated call to "click" on the anchor
|
downloadUrl = ""; // because DuckDuckGo doesn't download on automated call to "click" on the anchor
|
||||||
|
endorserLimits: EndorserRateLimits | null = null;
|
||||||
givenName = "";
|
givenName = "";
|
||||||
|
imageLimits: ImageRateLimits | null = null;
|
||||||
isRegistered = false;
|
isRegistered = false;
|
||||||
isSubscribed = false;
|
isSubscribed = false;
|
||||||
notificationMaybeChanged = false;
|
notificationMaybeChanged = false;
|
||||||
@@ -550,7 +568,6 @@ export default class AccountViewView extends Vue {
|
|||||||
publicBase64 = "";
|
publicBase64 = "";
|
||||||
webPushServer = "";
|
webPushServer = "";
|
||||||
webPushServerInput = "";
|
webPushServerInput = "";
|
||||||
limits: RateLimits | null = null;
|
|
||||||
limitsMessage = "";
|
limitsMessage = "";
|
||||||
loadingLimits = false;
|
loadingLimits = false;
|
||||||
showContactGives = false;
|
showContactGives = false;
|
||||||
@@ -697,7 +714,7 @@ export default class AccountViewView extends Vue {
|
|||||||
this.updateShowShortcutBvc(this.showShortcutBvc);
|
this.updateShowShortcutBvc(this.showShortcutBvc);
|
||||||
}
|
}
|
||||||
|
|
||||||
readableTime(timeStr: string) {
|
readableDate(timeStr: string) {
|
||||||
return timeStr.substring(0, timeStr.indexOf("T"));
|
return timeStr.substring(0, timeStr.indexOf("T"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1038,11 +1055,11 @@ export default class AccountViewView extends Vue {
|
|||||||
this.limitsMessage = "";
|
this.limitsMessage = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await this.fetchRateLimits(identity);
|
const resp = await this.fetchEndorserRateLimits(identity);
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
this.limits = resp.data;
|
this.endorserLimits = resp.data;
|
||||||
if (!this.isRegistered) {
|
if (!this.isRegistered) {
|
||||||
// the user is not known to be registered, but they are so let's record it
|
// the user was not known to be registered, but now they are (because we got no error) so let's record it
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
@@ -1062,6 +1079,10 @@ export default class AccountViewView extends Vue {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const imageResp = await this.fetchImageRateLimits(identity);
|
||||||
|
if (imageResp.status === 200) {
|
||||||
|
this.imageLimits = imageResp.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.handleRateLimitsError(error);
|
this.handleRateLimitsError(error);
|
||||||
@@ -1082,17 +1103,29 @@ export default class AccountViewView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches rate limits from the server.
|
* Fetches rate limits from the Endorser server.
|
||||||
*
|
*
|
||||||
* @param {IIdentifier} identity - The identity object to check rate limits for.
|
* @param {IIdentifier} identity - The identity object to check rate limits for.
|
||||||
* @returns {Promise<AxiosResponse>} The Axios response object.
|
* @returns {Promise<AxiosResponse>} The Axios response object.
|
||||||
*/
|
*/
|
||||||
private async fetchRateLimits(identity: IIdentifier) {
|
private async fetchEndorserRateLimits(identity: IIdentifier) {
|
||||||
const url = `${this.apiServer}/api/report/rateLimits`;
|
const url = `${this.apiServer}/api/report/rateLimits`;
|
||||||
const headers = await this.getHeaders(identity);
|
const headers = await this.getHeaders(identity);
|
||||||
return await this.axios.get(url, { headers } as AxiosRequestConfig);
|
return await this.axios.get(url, { headers } as AxiosRequestConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches rate limits from the image server.
|
||||||
|
*
|
||||||
|
* @param {IIdentifier} identity - The identity object to check rate limits for.
|
||||||
|
* @returns {Promise<AxiosResponse>} The Axios response object.
|
||||||
|
*/
|
||||||
|
private async fetchImageRateLimits(identity: IIdentifier) {
|
||||||
|
const url = DEFAULT_IMAGE_API_SERVER + "/image-limits";
|
||||||
|
const headers = await this.getHeaders(identity);
|
||||||
|
return await this.axios.get(url, { headers } as AxiosRequestConfig);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles errors that occur while fetching rate limits.
|
* Handles errors that occur while fetching rate limits.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user