|
@ -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"> |
|
|
<p class="text-sm"> |
|
|
You have done <b>{{ limits.doneClaimsThisWeek }}</b> claims out of |
|
|
You have done |
|
|
<b>{{ limits.maxClaimsPerWeek }}</b> for this week. Your claims |
|
|
<b>{{ endorserLimits.doneClaimsThisWeek }} claims</b> out of |
|
|
counter resets at |
|
|
<b>{{ endorserLimits.maxClaimsPerWeek }}</b> for this week. Your |
|
|
|
|
|
claims counter resets at |
|
|
<b class="whitespace-nowrap">{{ |
|
|
<b class="whitespace-nowrap">{{ |
|
|
readableTime(limits.nextWeekBeginDateTime) |
|
|
readableDate(endorserLimits.nextWeekBeginDateTime) |
|
|
}}</b> |
|
|
}}</b> |
|
|
</p> |
|
|
</p> |
|
|
<p class="text-sm"> |
|
|
<p class="mt-3 text-sm"> |
|
|
You have done |
|
|
You have done |
|
|
<b>{{ limits.doneRegistrationsThisMonth }}</b> registrations out of |
|
|
<b>{{ endorserLimits.doneRegistrationsThisMonth }} registrations</b> |
|
|
<b>{{ limits.maxRegistrationsPerMonth }}</b> for this month. |
|
|
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. |
|
|
* |
|
|
* |
|
|