adjust storage implementation
This commit is contained in:
parent
f7b9416460
commit
37026e556f
2
jslib
2
jslib
|
@ -1 +1 @@
|
|||
Subproject commit ef897695e9b5bfecbfcbbd4ad3aec62b4ecdca25
|
||||
Subproject commit c0e7e588ed59832a6f579ff63d85bfcdfb400d78
|
|
@ -33,6 +33,7 @@ import { TwoFactorOptionsComponent } from './accounts/two-factor-options.compone
|
|||
import { TwoFactorComponent } from './accounts/two-factor.component';
|
||||
|
||||
import { AccountComponent } from './settings/account.component';
|
||||
import { AdjustStorageComponent } from './settings/adjust-storage.component';
|
||||
import { ChangeEmailComponent } from './settings/change-email.component';
|
||||
import { ChangePasswordComponent } from './settings/change-password.component';
|
||||
import { DeauthorizeSessionsComponent } from './settings/deauthorize-sessions.component';
|
||||
|
@ -106,6 +107,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
|
|||
declarations: [
|
||||
AccountComponent,
|
||||
AddEditComponent,
|
||||
AdjustStorageComponent,
|
||||
ApiActionDirective,
|
||||
AppComponent,
|
||||
AttachmentsComponent,
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<form #form class="card" (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-6">
|
||||
<label for="storageAdjustment">{{(add ? 'gbStorageAdd' : 'gbStorageRemove') | i18n}}</label>
|
||||
<input id="storageAdjustment" class="form-control" type="number" name="StroageGbAdjustment" [(ngModel)]="storageAdjustment"
|
||||
min="0" max="99" step="1">
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="add" class="mb-3">
|
||||
<strong>{{'total' | i18n}}:</strong> {{storageAdjustment || 0}} GB × {{storageGbPrice | currency:'$'}} = {{adjustedStorageTotal
|
||||
| currency:'$'}} /{{interval | i18n}}
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
||||
<i class="fa fa-spinner fa-spin"></i>
|
||||
<span>{{'submit' | i18n}}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="cancel()">
|
||||
{{'cancel' | i18n}}
|
||||
</button>
|
||||
<small class="d-block text-muted mt-3">
|
||||
{{(add ? 'storageAddNote' : 'storageRemoveNote') | i18n}}
|
||||
</small>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,60 @@
|
|||
import {
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
|
||||
import { ToasterService } from 'angular2-toaster';
|
||||
import { Angulartics2 } from 'angulartics2';
|
||||
|
||||
import { ApiService } from 'jslib/abstractions/api.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
import { StorageRequest } from 'jslib/models/request/storageRequest';
|
||||
|
||||
@Component({
|
||||
selector: 'app-adjust-storage',
|
||||
templateUrl: 'adjust-storage.component.html',
|
||||
})
|
||||
export class AdjustStorageComponent {
|
||||
@Input() storageGbPrice = 0;
|
||||
@Input() add = true;
|
||||
@Input() user = true;
|
||||
@Input() interval = 'year';
|
||||
@Output() onAdjusted = new EventEmitter<number>();
|
||||
@Output() onCanceled = new EventEmitter();
|
||||
|
||||
storageAdjustment = 0;
|
||||
formPromise: Promise<any>;
|
||||
|
||||
constructor(private apiService: ApiService, private i18nService: I18nService,
|
||||
private analytics: Angulartics2, private toasterService: ToasterService) { }
|
||||
|
||||
async submit() {
|
||||
try {
|
||||
const request = new StorageRequest();
|
||||
request.storageGbAdjustment = this.storageAdjustment;
|
||||
if (!this.add) {
|
||||
request.storageGbAdjustment *= -1;
|
||||
}
|
||||
|
||||
if (this.user) {
|
||||
this.formPromise = this.apiService.postAccountStorage(request);
|
||||
}
|
||||
await this.formPromise;
|
||||
this.analytics.eventTrack.next({ action: this.add ? 'Added Storage' : 'Removed Storage' });
|
||||
this.toasterService.popAsync('success', null,
|
||||
this.i18nService.t('adjustedStorage', request.storageGbAdjustment.toString()));
|
||||
this.onAdjusted.emit(this.storageAdjustment);
|
||||
} catch { }
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.onCanceled.emit();
|
||||
}
|
||||
|
||||
get adjustedStorageTotal(): number {
|
||||
return this.storageGbPrice * this.storageAdjustment;
|
||||
}
|
||||
}
|
|
@ -69,12 +69,16 @@
|
|||
</div>
|
||||
<ng-container *ngIf="subscription && !subscription.cancelled && !subscriptionMarkedForCancel && paymentSource">
|
||||
<div class="mt-3">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="adjustStorage(true)">
|
||||
{{'addStorage' | i18n}}
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="adjustStorage(false)">
|
||||
{{'removeStorage' | i18n}}
|
||||
</button>
|
||||
<ng-container *ngIf="!showAdjustStorage">
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="adjustStorage(true)">
|
||||
{{'addStorage' | i18n}}
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="adjustStorage(false)">
|
||||
{{'removeStorage' | i18n}}
|
||||
</button>
|
||||
</ng-container>
|
||||
<app-adjust-storage [storageGbPrice]="4" [add]="adjustStorageAdd" [user]="true" (onAdjusted)="adjustedStorage($event)" (onCanceled)="canceledAdjustStorage()"
|
||||
*ngIf="showAdjustStorage"></app-adjust-storage>
|
||||
</div>
|
||||
</ng-container>
|
||||
<h2 class="spaced-header">{{'paymentMethod' | i18n}}</h2>
|
||||
|
|
|
@ -15,6 +15,8 @@ import { TokenService } from 'jslib/abstractions/token.service';
|
|||
|
||||
import { PaymentMethodType } from 'jslib/enums/paymentMethodType';
|
||||
|
||||
import { AdjustStorageComponent } from './adjust-storage.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-billing',
|
||||
templateUrl: 'user-billing.component.html',
|
||||
|
@ -23,6 +25,8 @@ export class UserBillingComponent implements OnInit {
|
|||
premium = false;
|
||||
loading = false;
|
||||
firstLoaded = false;
|
||||
adjustStorageAdd = true;
|
||||
showAdjustStorage = false;
|
||||
billing: BillingResponse;
|
||||
paymentMethodType = PaymentMethodType;
|
||||
|
||||
|
@ -101,7 +105,17 @@ export class UserBillingComponent implements OnInit {
|
|||
}
|
||||
|
||||
adjustStorage(add: boolean) {
|
||||
this.adjustStorageAdd = add;
|
||||
this.showAdjustStorage = true;
|
||||
}
|
||||
|
||||
adjustedStorage(gbAmount: number) {
|
||||
this.showAdjustStorage = false;
|
||||
this.load();
|
||||
}
|
||||
|
||||
canceledAdjustStorage() {
|
||||
this.showAdjustStorage = false;
|
||||
}
|
||||
|
||||
changePayment() {
|
||||
|
|
|
@ -1383,5 +1383,26 @@
|
|||
"example": "BITWARDEN"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gbStorageAdd": {
|
||||
"message": "GB of Storage To Add"
|
||||
},
|
||||
"gbStorageRemove": {
|
||||
"message": "GB of Storage To Remove"
|
||||
},
|
||||
"storageAddNote": {
|
||||
"message": "Adding storage to your plan will result in adjustments to your billing totals and immediately charge your payment method on file. The first charge will be prorated for the remainder of the current billing cycle."
|
||||
},
|
||||
"storageRemoveNote": {
|
||||
"message": "Removing storage will result in adjustments to your billing totals that will be prorated as credits to your next billing charge."
|
||||
},
|
||||
"adjustedStorage": {
|
||||
"message": "Adjusted $AMOUNT$ GB of storage.",
|
||||
"placeholders": {
|
||||
"amount": {
|
||||
"content": "$1",
|
||||
"example": "5"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue