From 1aadc0974d65154faf02a4fdf04d6653e44c563d Mon Sep 17 00:00:00 2001 From: Cameron Date: Fri, 29 Sep 2023 17:27:38 -0400 Subject: [PATCH] web/satellite: project limit increase request create modal to allow pro users to request project limit increase when trying to create a project if they have reached the project limit. github issue: https://github.com/storj/storj/issues/6298 Change-Id: I1799028e742c55197fa5d944c242053cf4dc3a2c --- web/satellite/src/api/auth.ts | 21 ++- web/satellite/src/store/modules/usersStore.ts | 7 +- web/satellite/src/types/users.ts | 18 +- .../dialogs/CreateProjectDialog.vue | 172 ++++++++++++++---- 4 files changed, 171 insertions(+), 47 deletions(-) diff --git a/web/satellite/src/api/auth.ts b/web/satellite/src/api/auth.ts index a9074844a..38f68433d 100644 --- a/web/satellite/src/api/auth.ts +++ b/web/satellite/src/api/auth.ts @@ -488,7 +488,7 @@ export class AuthHttpApi implements UsersApi { * * @throws Error */ - public async regenerateUserMFARecoveryCodes(passcode?: string, recoveryCode?:string): Promise { + public async regenerateUserMFARecoveryCodes(passcode?: string, recoveryCode?: string): Promise { if (!passcode && !recoveryCode) { throw new Error('Either passcode or recovery code should be provided'); } @@ -585,4 +585,23 @@ export class AuthHttpApi implements UsersApi { requestID: response.headers.get('x-request-id'), }); } + + /** + * Used to request increase for user's project limit. + * + * @param limit + */ + public async requestProjectLimitIncrease(limit: string): Promise { + const path = `${this.ROOT_PATH}/limit-increase`; + const response = await this.http.patch(path, limit); + + if (!response.ok) { + const result = await response.json(); + throw new APIError({ + status: response.status, + message: result.error, + requestID: response.headers.get('x-request-id'), + }); + } + } } diff --git a/web/satellite/src/store/modules/usersStore.ts b/web/satellite/src/store/modules/usersStore.ts index 09de1eaae..ae8f83dac 100644 --- a/web/satellite/src/store/modules/usersStore.ts +++ b/web/satellite/src/store/modules/usersStore.ts @@ -96,8 +96,12 @@ export const useUsersStore = defineStore('users', () => { state.user = user; } + async function requestProjectLimitIncrease(limit: string): Promise { + await api.requestProjectLimitIncrease(limit); + } + // Does nothing. It is called on login screen, and we just subscribe to this action in dashboard wrappers. - function login(): void {} + function login(): void { } function clear() { state.user = new User(); @@ -122,5 +126,6 @@ export const useUsersStore = defineStore('users', () => { setUser, updateSettings, getSettings, + requestProjectLimitIncrease, }; }); diff --git a/web/satellite/src/types/users.ts b/web/satellite/src/types/users.ts index 5170e93e9..6ab4588ba 100644 --- a/web/satellite/src/types/users.ts +++ b/web/satellite/src/types/users.ts @@ -76,6 +76,12 @@ export interface UsersApi { * @throws Error */ regenerateUserMFARecoveryCodes(passcode?: string, recoveryCode?: string): Promise; + /** + * Request increase for user's project limit. + * + * @throws Error + */ + requestProjectLimitIncrease(limit: string): Promise; } /** @@ -104,7 +110,7 @@ export class User { public _createdAt: string | null = null, public signupPromoCode: string = '', public freezeStatus: FreezeStatus = new FreezeStatus(), - ) {} + ) { } public get createdAt(): Date | null { if (!this._createdAt) { @@ -129,7 +135,7 @@ export class UpdatedUser { public constructor( public fullName: string = '', public shortName: string = '', - ) {} + ) { } public setFullName(value: string): void { this.fullName = value.trim(); @@ -151,7 +157,7 @@ export class DisableMFARequest { public constructor( public passcode: string = '', public recoveryCode: string = '', - ) {} + ) { } } /** @@ -161,7 +167,7 @@ export class TokenInfo { public constructor( public token: string, public expiresAt: Date, - ) {} + ) { } } /** @@ -174,7 +180,7 @@ export class UserSettings { public onboardingEnd = false, public passphrasePrompt = true, public onboardingStep: string | null = null, - ) {} + ) { } public get sessionDuration(): Duration | null { if (this._sessionDuration) { @@ -199,5 +205,5 @@ export class FreezeStatus { public constructor( public frozen = false, public warned = false, - ) {} + ) { } } diff --git a/web/satellite/vuetify-poc/src/components/dialogs/CreateProjectDialog.vue b/web/satellite/vuetify-poc/src/components/dialogs/CreateProjectDialog.vue index 66e70f1e3..e6dcb6f16 100644 --- a/web/satellite/vuetify-poc/src/components/dialogs/CreateProjectDialog.vue +++ b/web/satellite/vuetify-poc/src/components/dialogs/CreateProjectDialog.vue @@ -12,14 +12,15 @@ :scrim="false" @update:model-value="v => model = v" > - + - {{ isProjectLimitReached && billingEnabled ? 'Get More Projects' : 'Create New Project' }} + {{ cardTitle }}