|
|
|
|
@@ -96,7 +96,7 @@
|
|
|
|
|
<!-- 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. -->
|
|
|
|
|
<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"
|
|
|
|
|
>
|
|
|
|
|
<p class="mb-4">
|
|
|
|
|
@@ -157,28 +157,39 @@
|
|
|
|
|
<div>
|
|
|
|
|
{{ limitsMessage }}
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="!!limits?.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>
|
|
|
|
|
<div v-if="!!endorserLimits?.nextWeekBeginDateTime">
|
|
|
|
|
<p class="text-sm">
|
|
|
|
|
You have done
|
|
|
|
|
<b>{{ limits.doneRegistrationsThisMonth }}</b> registrations out of
|
|
|
|
|
<b>{{ limits.maxRegistrationsPerMonth }}</b> for this month.
|
|
|
|
|
<b>{{ endorserLimits.doneClaimsThisWeek }} claims</b> out of
|
|
|
|
|
<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
|
|
|
|
|
>(You can register nobody on your first day, and after that only one
|
|
|
|
|
a day in your first month.)</i
|
|
|
|
|
>
|
|
|
|
|
Your registration counter resets at
|
|
|
|
|
<b class="whitespace-nowrap">
|
|
|
|
|
{{ readableTime(limits.nextMonthBeginDateTime) }}
|
|
|
|
|
{{ readableDate(endorserLimits.nextMonthBeginDateTime) }}
|
|
|
|
|
</b>
|
|
|
|
|
</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>
|
|
|
|
|
<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"
|
|
|
|
|
@@ -509,6 +520,7 @@ import QuickNav from "@/components/QuickNav.vue";
|
|
|
|
|
import TopMessage from "@/components/TopMessage.vue";
|
|
|
|
|
import {
|
|
|
|
|
AppString,
|
|
|
|
|
DEFAULT_IMAGE_API_SERVER,
|
|
|
|
|
DEFAULT_PUSH_SERVER,
|
|
|
|
|
NotificationIface,
|
|
|
|
|
} from "@/constants/app";
|
|
|
|
|
@@ -516,7 +528,11 @@ import { db, accountsDB } from "@/db/index";
|
|
|
|
|
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
|
|
|
|
import { accessToken } from "@/libs/crypto";
|
|
|
|
|
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
|
|
|
|
|
const Buffer = require("buffer/").Buffer;
|
|
|
|
|
@@ -542,7 +558,9 @@ export default class AccountViewView extends Vue {
|
|
|
|
|
apiServerInput = "";
|
|
|
|
|
derivationPath = "";
|
|
|
|
|
downloadUrl = ""; // because DuckDuckGo doesn't download on automated call to "click" on the anchor
|
|
|
|
|
endorserLimits: EndorserRateLimits | null = null;
|
|
|
|
|
givenName = "";
|
|
|
|
|
imageLimits: ImageRateLimits | null = null;
|
|
|
|
|
isRegistered = false;
|
|
|
|
|
isSubscribed = false;
|
|
|
|
|
notificationMaybeChanged = false;
|
|
|
|
|
@@ -550,7 +568,6 @@ export default class AccountViewView extends Vue {
|
|
|
|
|
publicBase64 = "";
|
|
|
|
|
webPushServer = "";
|
|
|
|
|
webPushServerInput = "";
|
|
|
|
|
limits: RateLimits | null = null;
|
|
|
|
|
limitsMessage = "";
|
|
|
|
|
loadingLimits = false;
|
|
|
|
|
showContactGives = false;
|
|
|
|
|
@@ -697,7 +714,7 @@ export default class AccountViewView extends Vue {
|
|
|
|
|
this.updateShowShortcutBvc(this.showShortcutBvc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
readableTime(timeStr: string) {
|
|
|
|
|
readableDate(timeStr: string) {
|
|
|
|
|
return timeStr.substring(0, timeStr.indexOf("T"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1038,11 +1055,11 @@ export default class AccountViewView extends Vue {
|
|
|
|
|
this.limitsMessage = "";
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const resp = await this.fetchRateLimits(identity);
|
|
|
|
|
const resp = await this.fetchEndorserRateLimits(identity);
|
|
|
|
|
if (resp.status === 200) {
|
|
|
|
|
this.limits = resp.data;
|
|
|
|
|
this.endorserLimits = resp.data;
|
|
|
|
|
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 {
|
|
|
|
|
await db.open();
|
|
|
|
|
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) {
|
|
|
|
|
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.
|
|
|
|
|
* @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 headers = await this.getHeaders(identity);
|
|
|
|
|
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.
|
|
|
|
|
*
|
|
|
|
|
|