2020-08-12 23:16:38 +02:00
|
|
|
<ng-container *ngIf="loading">
|
|
|
|
<i class="fa fa-spinner fa-spin text-muted" title="{{'loading' | i18n}}" aria-hidden="true"></i>
|
|
|
|
<span class="sr-only">{{'loading' | i18n}}</span>
|
|
|
|
</ng-container>
|
2019-03-21 18:11:40 +01:00
|
|
|
<ng-container *ngIf="createOrganization && selfHosted">
|
|
|
|
<p>{{'uploadLicenseFileOrg' | i18n}}</p>
|
|
|
|
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate>
|
|
|
|
<div class="form-group">
|
|
|
|
<label for="file">{{'licenseFile' | i18n}}</label>
|
|
|
|
<input type="file" id="file" class="form-control-file" name="file" required>
|
2021-08-03 16:33:08 +02:00
|
|
|
<small class="form-text text-muted">{{'licenseFileDesc' | i18n :
|
|
|
|
'bitwarden_organization_license.json'}}</small>
|
2019-03-21 18:11:40 +01:00
|
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
2019-10-11 17:22:21 +02:00
|
|
|
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
|
2019-03-21 18:11:40 +01:00
|
|
|
<span>{{'submit' | i18n}}</span>
|
|
|
|
</button>
|
|
|
|
</form>
|
|
|
|
</ng-container>
|
2020-08-12 23:16:38 +02:00
|
|
|
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate
|
|
|
|
*ngIf="!loading && !selfHosted && this.plans">
|
2019-03-21 18:11:40 +01:00
|
|
|
<h2 class="mt-5">{{'generalInformation' | i18n}}</h2>
|
|
|
|
<div class="row" *ngIf="createOrganization">
|
|
|
|
<div class="form-group col-6">
|
|
|
|
<label for="name">{{'organizationName' | i18n}}</label>
|
|
|
|
<input id="name" class="form-control" type="text" name="Name" [(ngModel)]="name" required>
|
|
|
|
</div>
|
|
|
|
<div class="form-group col-6">
|
|
|
|
<label for="billingEmail">{{'billingEmail' | i18n}}</label>
|
|
|
|
<input id="billingEmail" class="form-control" type="text" name="BillingEmail" [(ngModel)]="billingEmail"
|
|
|
|
required>
|
|
|
|
</div>
|
2021-07-30 15:10:00 +02:00
|
|
|
<div class="form-group col-6" *ngIf="!!providerId">
|
|
|
|
<label for="email">{{'clientOwnerEmail' | i18n}}</label>
|
|
|
|
<input id="email" class="form-control" type="text" name="Email" [(ngModel)]="clientOwnerEmail" required>
|
2021-08-09 19:24:12 +02:00
|
|
|
<small class="text-muted">{{'clientOwnerDesc' | i18n : '20'}}</small>
|
2021-07-30 15:10:00 +02:00
|
|
|
</div>
|
2021-08-03 16:33:08 +02:00
|
|
|
</div>
|
|
|
|
<div *ngIf="!providerId">
|
2021-07-30 15:10:00 +02:00
|
|
|
<div class="form-group form-check">
|
2021-08-03 16:33:08 +02:00
|
|
|
<input id="ownedBusiness" class="form-check-input" type="checkbox" name="OwnedBusiness"
|
|
|
|
[(ngModel)]="ownedBusiness" (change)="changedOwnedBusiness()">
|
2021-07-30 15:10:00 +02:00
|
|
|
<label for="ownedBusiness" class="form-check-label">{{'accountOwnedBusiness' | i18n}}</label>
|
|
|
|
</div>
|
|
|
|
<div class="row" *ngIf="ownedBusiness">
|
|
|
|
<div class="form-group col-6">
|
|
|
|
<label for="businessName">{{'businessName' | i18n}}</label>
|
2021-08-03 16:33:08 +02:00
|
|
|
<input id="businessName" class="form-control" type="text" name="BusinessName"
|
|
|
|
[(ngModel)]="businessName">
|
|
|
|
</div>
|
2021-07-30 15:10:00 +02:00
|
|
|
</div>
|
2019-03-21 18:11:40 +01:00
|
|
|
</div>
|
|
|
|
<h2 class="mt-5">{{'chooseYourPlan' | i18n}}</h2>
|
2020-08-12 23:16:38 +02:00
|
|
|
<div *ngFor="let selectableProduct of selectableProducts" class="form-check form-check-block">
|
|
|
|
<input class="form-check-input" type="radio" name="product" id="product{{selectableProduct.product}}"
|
|
|
|
[value]="selectableProduct.product" [(ngModel)]="product" (change)="changedProduct()">
|
2020-08-25 20:21:03 +02:00
|
|
|
<label class="form-check-label" for="product{{selectableProduct.product}}">
|
2020-08-12 23:16:38 +02:00
|
|
|
{{ selectableProduct.nameLocalizationKey | i18n}}
|
|
|
|
<small class="mb-1">{{ selectableProduct.descriptionLocalizationKey | i18n : '1'}}</small>
|
2020-08-26 20:44:15 +02:00
|
|
|
<ng-container *ngIf="selectableProduct.product === productTypes.Enterprise; else fullFeatureList">
|
|
|
|
<small>• {{'includeAllTeamsFeatures' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.hasSelfHost">• {{'onPremHostingOptional' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.hasSso">• {{'includeSsoAuthentication' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.hasPolicies">• {{'includeEnterprisePolicies' | i18n}}</small>
|
2021-04-21 23:15:37 +02:00
|
|
|
<small *ngIf="selectableProduct.trialPeriodDays && createOrganization">•
|
2021-01-15 20:46:25 +01:00
|
|
|
{{'xDayFreeTrial' | i18n : selectableProduct.trialPeriodDays }}
|
|
|
|
</small>
|
2020-08-26 20:44:15 +02:00
|
|
|
</ng-container>
|
|
|
|
<ng-template #fullFeatureList>
|
|
|
|
<small *ngIf="selectableProduct.product == productTypes.Free">•
|
|
|
|
{{'limitedUsers' | i18n : selectableProduct.maxUsers }}</small>
|
|
|
|
<small *ngIf="selectableProduct.product != productTypes.Free && selectableProduct.maxUsers">•
|
|
|
|
{{'addShareLimitedUsers' | i18n : selectableProduct.maxUsers}}</small>
|
|
|
|
<small *ngIf="!selectableProduct.maxUsers">•
|
|
|
|
{{'addShareUnlimitedUsers' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.maxCollections">•
|
|
|
|
{{'limitedCollections' | i18n : selectableProduct.maxCollections }}</small>
|
|
|
|
<small *ngIf="selectableProduct.maxAdditionalSeats">•
|
|
|
|
{{'addShareLimitedUsers' | i18n : selectableProduct.maxAdditionalSeats }}</small>
|
|
|
|
<small *ngIf="!selectableProduct.maxCollections">• {{'createUnlimitedCollections' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.baseStorageGb">•
|
|
|
|
{{'gbEncryptedFileStorage' | i18n : selectableProduct.baseStorageGb + 'GB'}}</small>
|
|
|
|
<small *ngIf="selectableProduct.hasGroups">• {{'controlAccessWithGroups' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.hasApi">• {{'trackAuditLogs' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.hasDirectory">• {{'syncUsersFromDirectory' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.hasSelfHost">• {{'onPremHostingOptional' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.usersGetPremium">• {{'usersGetPremium' | i18n}}</small>
|
|
|
|
<small *ngIf="selectableProduct.product != productTypes.Free">•
|
|
|
|
{{'priorityCustomerSupport' | i18n}}</small>
|
2021-04-21 23:15:37 +02:00
|
|
|
<small *ngIf="selectableProduct.trialPeriodDays && createOrganization">•
|
2020-08-26 20:44:15 +02:00
|
|
|
{{'xDayFreeTrial' | i18n : selectableProduct.trialPeriodDays }}
|
|
|
|
</small>
|
|
|
|
</ng-template>
|
2020-08-12 23:16:38 +02:00
|
|
|
<span *ngIf="selectableProduct.product != productTypes.Free">
|
|
|
|
<ng-container *ngIf="selectableProduct.basePrice">
|
|
|
|
{{selectableProduct.basePrice / 12 | currency:'$'}} /{{'month' | i18n}},
|
|
|
|
{{'includesXUsers' | i18n : selectableProduct.baseSeats}}
|
|
|
|
<ng-container *ngIf="selectableProduct.hasAdditionalSeatsOption">
|
|
|
|
{{('additionalUsers' | i18n).toLowerCase()}}
|
2021-08-03 16:33:08 +02:00
|
|
|
{{selectableProduct.seatPrice / 12 | currency:'$'}} /{{'month' | i18n}}
|
2020-08-12 23:16:38 +02:00
|
|
|
</ng-container>
|
|
|
|
</ng-container>
|
|
|
|
</span>
|
|
|
|
<span *ngIf="!selectableProduct.basePrice && selectableProduct.hasAdditionalSeatsOption">
|
|
|
|
{{'costPerUser' | i18n : (selectableProduct.seatPrice / 12 | currency:'$')}} /{{'month' | i18n}}
|
|
|
|
</span>
|
|
|
|
<span *ngIf="selectableProduct.product == productTypes.Free">{{'freeForever' | i18n}}</span>
|
2019-03-21 18:11:40 +01:00
|
|
|
</label>
|
|
|
|
</div>
|
2020-08-12 23:16:38 +02:00
|
|
|
<div *ngIf="product !== productTypes.Free">
|
|
|
|
<ng-container *ngIf="selectedPlan.hasAdditionalSeatsOption && !selectedPlan.baseSeats">
|
2019-03-21 18:11:40 +01:00
|
|
|
<h2 class="mt-5">{{'users' | i18n}}</h2>
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-6">
|
|
|
|
<label for="additionalSeats">{{'userSeats' | i18n}}</label>
|
|
|
|
<input id="additionalSeats" class="form-control" type="number" name="AdditionalSeats"
|
|
|
|
[(ngModel)]="additionalSeats" min="1" max="100000" placeholder="{{'userSeatsDesc' | i18n}}"
|
|
|
|
required>
|
|
|
|
<small class="text-muted form-text">{{'userSeatsHowManyDesc' | i18n}}</small>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</ng-container>
|
|
|
|
<h2 class="mt-5">{{'addons' | i18n}}</h2>
|
2020-08-12 23:16:38 +02:00
|
|
|
<div class="row" *ngIf="selectedPlan.hasAdditionalSeatsOption && selectedPlan.baseSeats">
|
2019-03-21 18:11:40 +01:00
|
|
|
<div class="form-group col-6">
|
|
|
|
<label for="additionalSeats">{{'additionalUserSeats' | i18n}}</label>
|
|
|
|
<input id="additionalSeats" class="form-control" type="number" name="AdditionalSeats"
|
|
|
|
[(ngModel)]="additionalSeats" min="0" max="100000" placeholder="{{'userSeatsDesc' | i18n}}">
|
2021-08-03 16:33:08 +02:00
|
|
|
<small class="text-muted form-text">{{'userSeatsAdditionalDesc' | i18n : selectedPlan.baseSeats :
|
|
|
|
(seatPriceMonthly(selectedPlan) | currency:'$')}}</small>
|
2019-03-21 18:11:40 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="row">
|
|
|
|
<div class="form-group col-6">
|
|
|
|
<label for="additionalStorage">{{'additionalStorageGb' | i18n}}</label>
|
|
|
|
<input id="additionalStorage" class="form-control" type="number" name="AdditionalStorageGb"
|
|
|
|
[(ngModel)]="additionalStorage" min="0" max="99" step="1"
|
|
|
|
placeholder="{{'additionalStorageGbDesc' | i18n}}">
|
2021-08-03 16:33:08 +02:00
|
|
|
<small class="text-muted form-text">{{'additionalStorageIntervalDesc' | i18n : '1 GB' :
|
|
|
|
(additionalStoragePriceMonthly(selectedPlan) | currency:'$') : ('month' | i18n)}}</small>
|
2019-03-21 18:11:40 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="row">
|
2020-08-12 23:16:38 +02:00
|
|
|
<div class="form-group col-6" *ngIf="selectedPlan.hasPremiumAccessOption">
|
2019-03-21 18:11:40 +01:00
|
|
|
<div class="form-check">
|
|
|
|
<input id="premiumAccess" class="form-check-input" type="checkbox" name="PremiumAccessAddon"
|
|
|
|
[(ngModel)]="premiumAccessAddon">
|
|
|
|
<label for="premiumAccess" class="form-check-label bold">{{'premiumAccess' | i18n}}</label>
|
|
|
|
</div>
|
2021-08-03 16:33:08 +02:00
|
|
|
<small class="text-muted form-text">{{'premiumAccessDesc' | i18n : (3.33 | currency:'$') : ('month' |
|
|
|
|
i18n)}}</small>
|
2019-03-21 18:11:40 +01:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<h2 class="spaced-header">{{'summary' | i18n}}</h2>
|
2020-08-12 23:16:38 +02:00
|
|
|
<div class="form-check form-check-block" *ngFor="let selectablePlan of selectablePlans">
|
|
|
|
<input class="form-check-input" type="radio" name="BillingInterval" id="interval{{selectablePlan.type}}"
|
|
|
|
[value]="selectablePlan.type" [(ngModel)]="plan">
|
|
|
|
<label class="form-check-label" for="interval{{selectablePlan.type}}">
|
|
|
|
<ng-container *ngIf="selectablePlan.isAnnual">
|
|
|
|
{{'annually' | i18n}}
|
|
|
|
<small *ngIf="selectablePlan.basePrice">
|
2020-08-25 20:21:03 +02:00
|
|
|
{{'basePrice' | i18n}}: {{ selectablePlan.basePrice / 12 | currency:'$'}} × 12
|
2020-08-12 23:16:38 +02:00
|
|
|
{{'monthAbbr' | i18n}}
|
|
|
|
=
|
|
|
|
{{selectablePlan.basePrice | currency:'$'}}
|
|
|
|
/{{'year' | i18n}}
|
|
|
|
</small>
|
|
|
|
<small *ngIf="selectablePlan.hasAdditionalSeatsOption">
|
|
|
|
<span *ngIf="selectablePlan.baseSeats">{{'additionalUsers' | i18n}}:</span>
|
|
|
|
<span *ngIf="!selectablePlan.baseSeats">{{'users' | i18n}}:</span>
|
2020-08-25 20:21:03 +02:00
|
|
|
{{additionalSeats || 0}} × {{selectablePlan.seatPrice / 12 | currency:'$'}} × 12
|
2020-08-12 23:16:38 +02:00
|
|
|
{{'monthAbbr' | i18n}} = {{seatTotal(selectablePlan)
|
2021-08-03 16:33:08 +02:00
|
|
|
| currency:'$'}} /{{'year' | i18n}}
|
2020-08-12 23:16:38 +02:00
|
|
|
</small>
|
|
|
|
<small *ngIf="selectablePlan.hasAdditionalStorageOption">
|
|
|
|
{{'additionalStorageGb' | i18n}}: {{additionalStorage || 0}} ×
|
2020-08-25 20:21:03 +02:00
|
|
|
{{selectablePlan.additionalStoragePricePerGb / 12 | currency:'$'}} × 12 {{'monthAbbr'
|
2020-08-12 23:16:38 +02:00
|
|
|
| i18n}} = {{additionalStorageTotal(selectablePlan) | currency:'$'}}
|
|
|
|
/{{'year' | i18n}}
|
|
|
|
</small>
|
|
|
|
<small *ngIf="selectablePlan.hasPremiumAccessOption && premiumAccessAddon">
|
|
|
|
{{'premiumAccess' | i18n}}:
|
2020-08-25 20:21:03 +02:00
|
|
|
{{selectablePlan.premiumAccessOptionCost / 12 | currency:'$'}} × 12 {{'monthAbbr' | i18n}}
|
2020-08-12 23:16:38 +02:00
|
|
|
=
|
|
|
|
{{40 | currency:'$'}}
|
|
|
|
/{{'year' | i18n}}
|
|
|
|
</small>
|
|
|
|
</ng-container>
|
|
|
|
<ng-container *ngIf="!selectablePlan.isAnnual">
|
|
|
|
{{'monthly' | i18n}}
|
|
|
|
<small *ngIf="selectablePlan.basePrice">
|
|
|
|
{{'basePrice' | i18n}}: {{selectablePlan.basePrice | currency:'$'}} {{'monthAbbr' | i18n}}
|
|
|
|
=
|
|
|
|
{{selectablePlan.basePrice | currency:'$'}}
|
|
|
|
/{{'month' | i18n}}
|
|
|
|
</small>
|
|
|
|
<small *ngIf="selectablePlan.hasAdditionalSeatsOption">
|
|
|
|
<span *ngIf="selectablePlan.baseSeats">{{'additionalUsers' | i18n}}:</span>
|
|
|
|
<span *ngIf="!selectablePlan.baseSeats">{{'users' | i18n}}:</span>
|
|
|
|
{{additionalSeats || 0}} × {{selectablePlan.seatPrice | currency:'$'}}
|
|
|
|
{{'monthAbbr' | i18n}} = {{seatTotal(selectablePlan)
|
2021-08-03 16:33:08 +02:00
|
|
|
| currency:'$'}} /{{'month' | i18n}}
|
2020-08-12 23:16:38 +02:00
|
|
|
</small>
|
|
|
|
<small *ngIf="selectablePlan.hasAdditionalStorageOption">
|
|
|
|
{{'additionalStorageGb' | i18n}}: {{additionalStorage || 0}} ×
|
|
|
|
{{selectablePlan.additionalStoragePricePerGb | currency:'$'}} {{'monthAbbr'
|
|
|
|
| i18n}} = {{additionalStorageTotal(selectablePlan) | currency:'$'}}
|
|
|
|
/{{'month' | i18n}}
|
|
|
|
</small>
|
|
|
|
<small *ngIf="selectablePlan.hasPremiumAccessOption && premiumAccessAddon">
|
|
|
|
{{'premiumAccess' | i18n}}:
|
|
|
|
{{selectablePlan.premiumAccessOptionCost | currency:'$'}} {{'monthAbbr' | i18n}} =
|
|
|
|
{{40 | currency:'$'}}
|
|
|
|
/{{'month' | i18n}}
|
|
|
|
</small>
|
|
|
|
</ng-container>
|
2019-03-21 18:11:40 +01:00
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
<hr class="my-3">
|
2021-08-03 16:33:08 +02:00
|
|
|
<h2 class="spaced-header mb-4">{{ (createOrganization ? 'paymentInformation' : 'billingInformation') | i18n}}
|
|
|
|
</h2>
|
2021-11-08 19:14:57 +01:00
|
|
|
<small class="text-muted font-italic mb-3 d-block" *ngIf="freeTrial && createOrganization; else paymentChargedImmediately">
|
2021-11-05 19:59:45 +01:00
|
|
|
{{'paymentChargedWithTrial' | i18n}}
|
|
|
|
</small>
|
|
|
|
<ng-template #paymentChargedImmediately>
|
|
|
|
<small class="text-muted font-italic mb-3 d-block">
|
|
|
|
{{'paymentCharged' | i18n : (selectedPlanInterval | i18n) }}
|
|
|
|
</small>
|
|
|
|
</ng-template>
|
2020-12-04 18:05:44 +01:00
|
|
|
<app-payment *ngIf="createOrganization" [hideCredit]="true"></app-payment>
|
|
|
|
<app-tax-info (onCountryChanged)="changedCountry()"></app-tax-info>
|
|
|
|
<div id="price" class="my-4">
|
|
|
|
<div class="text-muted text-sm">
|
|
|
|
{{ 'planPrice' | i18n }}: {{ subtotal | currency: 'USD $' }}
|
|
|
|
<br />
|
|
|
|
<ng-container>
|
|
|
|
{{ 'estimatedTax' | i18n }}: {{ taxCharges | currency: 'USD $' }}
|
|
|
|
</ng-container>
|
|
|
|
</div>
|
|
|
|
<hr class="my-1 col-3 ml-0">
|
|
|
|
<p class="text-lg"><strong>{{'total' | i18n}}:</strong>
|
|
|
|
{{total | currency:'USD $'}}/{{selectedPlanInterval | i18n}}</p>
|
2019-03-21 18:11:40 +01:00
|
|
|
</div>
|
2019-08-10 05:57:30 +02:00
|
|
|
<ng-container *ngIf="!createOrganization">
|
|
|
|
<app-payment [showMethods]="false"></app-payment>
|
|
|
|
</ng-container>
|
2020-08-12 23:16:38 +02:00
|
|
|
</div>
|
2020-10-27 15:28:57 +01:00
|
|
|
<div *ngIf="singleOrgPolicyBlock" class="mt-4">
|
|
|
|
<app-callout [type]="'error'">{{'singleOrgBlockCreateMessage' | i18n}}</app-callout>
|
2020-10-16 21:36:06 +02:00
|
|
|
</div>
|
2020-08-12 23:16:38 +02:00
|
|
|
<div class="mt-4">
|
2019-03-21 18:11:40 +01:00
|
|
|
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
|
2019-10-11 17:22:21 +02:00
|
|
|
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}" aria-hidden="true"></i>
|
2019-03-21 18:11:40 +01:00
|
|
|
<span>{{'submit' | i18n}}</span>
|
|
|
|
</button>
|
|
|
|
<button type="button" class="btn btn-outline-secondary" (click)="cancel()" *ngIf="showCancel">
|
|
|
|
{{'cancel' | i18n}}
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</form>
|