mirror of
https://github.com/bitwarden/browser.git
synced 2024-09-19 02:51:14 +02:00
create and mange org through licensing
This commit is contained in:
parent
4660ad824d
commit
995fc96a5d
@ -1,18 +1,26 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.organization')
|
.module('bit.organization')
|
||||||
|
|
||||||
.controller('organizationBillingController', function ($scope, apiService, $state, $uibModal, toastr, $analytics) {
|
.controller('organizationBillingController', function ($scope, apiService, $state, $uibModal, toastr, $analytics,
|
||||||
|
appSettings) {
|
||||||
|
$scope.selfHosted = appSettings.selfHosted;
|
||||||
$scope.charges = [];
|
$scope.charges = [];
|
||||||
$scope.paymentSource = null;
|
$scope.paymentSource = null;
|
||||||
$scope.plan = null;
|
$scope.plan = null;
|
||||||
$scope.subscription = null;
|
$scope.subscription = null;
|
||||||
$scope.loading = true;
|
$scope.loading = true;
|
||||||
|
var license = null;
|
||||||
|
$scope.expiration = null;
|
||||||
|
|
||||||
$scope.$on('$viewContentLoaded', function () {
|
$scope.$on('$viewContentLoaded', function () {
|
||||||
load();
|
load();
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.changePayment = function () {
|
$scope.changePayment = function () {
|
||||||
|
if ($scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var modal = $uibModal.open({
|
var modal = $uibModal.open({
|
||||||
animation: true,
|
animation: true,
|
||||||
templateUrl: 'app/settings/views/settingsBillingChangePayment.html',
|
templateUrl: 'app/settings/views/settingsBillingChangePayment.html',
|
||||||
@ -30,6 +38,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.changePlan = function () {
|
$scope.changePlan = function () {
|
||||||
|
if ($scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var modal = $uibModal.open({
|
var modal = $uibModal.open({
|
||||||
animation: true,
|
animation: true,
|
||||||
templateUrl: 'app/organization/views/organizationBillingChangePlan.html',
|
templateUrl: 'app/organization/views/organizationBillingChangePlan.html',
|
||||||
@ -47,6 +59,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.adjustSeats = function (add) {
|
$scope.adjustSeats = function (add) {
|
||||||
|
if ($scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var modal = $uibModal.open({
|
var modal = $uibModal.open({
|
||||||
animation: true,
|
animation: true,
|
||||||
templateUrl: 'app/organization/views/organizationBillingAdjustSeats.html',
|
templateUrl: 'app/organization/views/organizationBillingAdjustSeats.html',
|
||||||
@ -64,6 +80,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.adjustStorage = function (add) {
|
$scope.adjustStorage = function (add) {
|
||||||
|
if ($scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var modal = $uibModal.open({
|
var modal = $uibModal.open({
|
||||||
animation: true,
|
animation: true,
|
||||||
templateUrl: 'app/settings/views/settingsBillingAdjustStorage.html',
|
templateUrl: 'app/settings/views/settingsBillingAdjustStorage.html',
|
||||||
@ -81,6 +101,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.verifyBank = function () {
|
$scope.verifyBank = function () {
|
||||||
|
if ($scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var modal = $uibModal.open({
|
var modal = $uibModal.open({
|
||||||
animation: true,
|
animation: true,
|
||||||
templateUrl: 'app/organization/views/organizationBillingVerifyBank.html',
|
templateUrl: 'app/organization/views/organizationBillingVerifyBank.html',
|
||||||
@ -93,6 +117,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.cancel = function () {
|
$scope.cancel = function () {
|
||||||
|
if ($scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!confirm('Are you sure you want to cancel? All users will lose access to the organization ' +
|
if (!confirm('Are you sure you want to cancel? All users will lose access to the organization ' +
|
||||||
'at the end of this billing cycle.')) {
|
'at the end of this billing cycle.')) {
|
||||||
return;
|
return;
|
||||||
@ -107,6 +135,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.reinstate = function () {
|
$scope.reinstate = function () {
|
||||||
|
if ($scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!confirm('Are you sure you want to remove the cancellation request and reinstate this organization?')) {
|
if (!confirm('Are you sure you want to remove the cancellation request and reinstate this organization?')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -119,12 +151,54 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.updateLicense = function () {
|
||||||
|
if (!$scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var modal = $uibModal.open({
|
||||||
|
animation: true,
|
||||||
|
templateUrl: 'app/settings/views/settingsBillingUpdateLicense.html',
|
||||||
|
controller: 'organizationBillingUpdateLicenseController'
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.result.then(function () {
|
||||||
|
load();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.license = function () {
|
||||||
|
if ($scope.selfHosted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var licenseString = JSON.stringify(license, null, 2);
|
||||||
|
var licenseBlob = new Blob([licenseString]);
|
||||||
|
|
||||||
|
// IE hack. ref http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
|
||||||
|
if (window.navigator.msSaveOrOpenBlob) {
|
||||||
|
window.navigator.msSaveBlob(licenseBlob, 'bitwarden_organization_license.json');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var a = window.document.createElement('a');
|
||||||
|
a.href = window.URL.createObjectURL(licenseBlob, { type: 'text/plain' });
|
||||||
|
a.download = 'bitwarden_premium_license.json';
|
||||||
|
document.body.appendChild(a);
|
||||||
|
// IE: "Access is denied".
|
||||||
|
// ref: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function load() {
|
function load() {
|
||||||
apiService.organizations.getBilling({ id: $state.params.orgId }, function (org) {
|
apiService.organizations.getBilling({ id: $state.params.orgId }, function (org) {
|
||||||
$scope.loading = false;
|
$scope.loading = false;
|
||||||
$scope.noSubscription = org.PlanType === 0;
|
$scope.noSubscription = org.PlanType === 0;
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
$scope.expiration = org.Expiration;
|
||||||
|
license = org.License;
|
||||||
|
|
||||||
$scope.plan = {
|
$scope.plan = {
|
||||||
name: org.Plan,
|
name: org.Plan,
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
angular
|
||||||
|
.module('bit.organization')
|
||||||
|
|
||||||
|
.controller('organizationBillingUpdateLicenseController', function ($scope, $state, $uibModalInstance, apiService,
|
||||||
|
$analytics, toastr, validationService) {
|
||||||
|
$analytics.eventTrack('organizationBillingUpdateLicenseController', { category: 'Modal' });
|
||||||
|
|
||||||
|
$scope.submit = function (form) {
|
||||||
|
var fileEl = document.getElementById('file');
|
||||||
|
var files = fileEl.files;
|
||||||
|
if (!files || !files.length) {
|
||||||
|
validationService.addError(form, 'file', 'Select a license file.', true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fd = new FormData();
|
||||||
|
fd.append('license', files[0]);
|
||||||
|
|
||||||
|
$scope.submitPromise = apiService.organizations.putLicense({ id: $state.params.orgId }, fd)
|
||||||
|
.$promise.then(function (response) {
|
||||||
|
$analytics.eventTrack('Updated License');
|
||||||
|
toastr.success('You have updated your license.');
|
||||||
|
$uibModalInstance.close();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.close = function () {
|
||||||
|
$uibModalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
<section class="content-header">
|
<section class="content-header">
|
||||||
<h1>
|
<h1>
|
||||||
Billing
|
Billing
|
||||||
<small>manage your payments</small>
|
<small>manage your billing & licensing</small>
|
||||||
</h1>
|
</h1>
|
||||||
</section>
|
</section>
|
||||||
<section class="content">
|
<section class="content">
|
||||||
@ -26,14 +26,28 @@
|
|||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<dl>
|
<dl ng-if="selfHosted">
|
||||||
|
<dt>Name</dt>
|
||||||
|
<dd>{{plan.name || '-'}}</dd>
|
||||||
|
<dt>Expiration</dt>
|
||||||
|
<dd ng-if="loading">
|
||||||
|
Loading...
|
||||||
|
</dd>
|
||||||
|
<dd ng-if="!loading && expiration">
|
||||||
|
{{expiration | date: 'medium'}}
|
||||||
|
</dd>
|
||||||
|
<dd ng-if="!loading && !expiration">
|
||||||
|
Never expires
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<dl ng-if="!selfHosted">
|
||||||
<dt>Name</dt>
|
<dt>Name</dt>
|
||||||
<dd>{{plan.name || '-'}}</dd>
|
<dd>{{plan.name || '-'}}</dd>
|
||||||
<dt>Total Seats</dt>
|
<dt>Total Seats</dt>
|
||||||
<dd>{{plan.seats || '-'}}</dd>
|
<dd>{{plan.seats || '-'}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6" ng-if="!selfHosted">
|
||||||
<dl>
|
<dl>
|
||||||
<dt>Status</dt>
|
<dt>Status</dt>
|
||||||
<dd>
|
<dd>
|
||||||
@ -41,11 +55,11 @@
|
|||||||
<span ng-if="subscription.markedForCancel">- marked for cancellation</span>
|
<span ng-if="subscription.markedForCancel">- marked for cancellation</span>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>Next Charge</dt>
|
<dt>Next Charge</dt>
|
||||||
<dd>{{nextInvoice ? ((nextInvoice.date | date: format: mediumDate) + ', ' + (nextInvoice.amount | currency:'$')) : '-'}}</dd>
|
<dd>{{nextInvoice ? ((nextInvoice.date | date: 'mediumDate') + ', ' + (nextInvoice.amount | currency:'$')) : '-'}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" ng-if="!noSubscription">
|
<div class="row" ng-if="!selfHosted && !noSubscription">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<strong>Details</strong>
|
<strong>Details</strong>
|
||||||
<div ng-show="loading">
|
<div ng-show="loading">
|
||||||
@ -67,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-footer">
|
<div class="box-footer" ng-if="!selfHosted">
|
||||||
<button type="button" class="btn btn-default btn-flat" ng-click="changePlan()">
|
<button type="button" class="btn btn-default btn-flat" ng-click="changePlan()">
|
||||||
Change Plan
|
Change Plan
|
||||||
</button>
|
</button>
|
||||||
@ -79,6 +93,18 @@
|
|||||||
ng-if="!noSubscription && subscription.markedForCancel">
|
ng-if="!noSubscription && subscription.markedForCancel">
|
||||||
Reinstate Plan
|
Reinstate Plan
|
||||||
</button>
|
</button>
|
||||||
|
<button type="button" class="btn btn-default btn-flat" ng-click="license()"
|
||||||
|
ng-if="!subscription.cancelled">
|
||||||
|
Download License
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer" ng-if="selfHosted">
|
||||||
|
<button type="button" class="btn btn-default btn-flat" ng-click="updateLicense()">
|
||||||
|
Update License
|
||||||
|
</button>
|
||||||
|
<a href="https://vault.bitwarden.com" class="btn btn-default btn-flat" target="_blank">
|
||||||
|
Manage Billing
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box box-default">
|
<div class="box box-default">
|
||||||
@ -93,7 +119,7 @@
|
|||||||
You plan currently has a total of <b>{{plan.seats}}</b> seats.
|
You plan currently has a total of <b>{{plan.seats}}</b> seats.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-footer" ng-if="!noSubscription">
|
<div class="box-footer" ng-if="!selfHosted && !noSubscription">
|
||||||
<button type="button" class="btn btn-default btn-flat" ng-click="adjustSeats(true)">
|
<button type="button" class="btn btn-default btn-flat" ng-click="adjustSeats(true)">
|
||||||
Add Seats
|
Add Seats
|
||||||
</button>
|
</button>
|
||||||
@ -102,7 +128,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box box-default" ng-if="storage">
|
<div class="box box-default" ng-if="storage && !selfHosted">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">Storage</h3>
|
<h3 class="box-title">Storage</h3>
|
||||||
</div>
|
</div>
|
||||||
@ -128,7 +154,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box box-default">
|
<div class="box box-default" ng-if="!selfHosted">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">Payment Method</h3>
|
<h3 class="box-title">Payment Method</h3>
|
||||||
</div>
|
</div>
|
||||||
@ -160,7 +186,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box box-default">
|
<div class="box box-default" ng-if="!selfHosted">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">Charges</h3>
|
<h3 class="box-title">Charges</h3>
|
||||||
</div>
|
</div>
|
||||||
@ -176,7 +202,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="charge in charges">
|
<tr ng-repeat="charge in charges">
|
||||||
<td style="width: 200px">
|
<td style="width: 200px">
|
||||||
{{charge.date | date: format: mediumDate}}
|
{{charge.date | date: 'mediumDate'}}
|
||||||
</td>
|
</td>
|
||||||
<td style="min-width: 150px">
|
<td style="min-width: 150px">
|
||||||
{{charge.paymentSource}}
|
{{charge.paymentSource}}
|
||||||
|
@ -70,7 +70,17 @@
|
|||||||
putReinstate: { url: _apiUri + '/organizations/:id/reinstate', method: 'POST', params: { id: '@id' } },
|
putReinstate: { url: _apiUri + '/organizations/:id/reinstate', method: 'POST', params: { id: '@id' } },
|
||||||
postLeave: { url: _apiUri + '/organizations/:id/leave', method: 'POST', params: { id: '@id' } },
|
postLeave: { url: _apiUri + '/organizations/:id/leave', method: 'POST', params: { id: '@id' } },
|
||||||
postVerifyBank: { url: _apiUri + '/organizations/:id/verify-bank', method: 'POST', params: { id: '@id' } },
|
postVerifyBank: { url: _apiUri + '/organizations/:id/verify-bank', method: 'POST', params: { id: '@id' } },
|
||||||
del: { url: _apiUri + '/organizations/:id/delete', method: 'POST', params: { id: '@id' } }
|
del: { url: _apiUri + '/organizations/:id/delete', method: 'POST', params: { id: '@id' } },
|
||||||
|
postLicense: {
|
||||||
|
url: _apiUri + '/organizations/license',
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': undefined }
|
||||||
|
},
|
||||||
|
putLicense: {
|
||||||
|
url: _apiUri + '/organizations/:id/license',
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': undefined }
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_service.organizationUsers = $resource(_apiUri + '/organizations/:orgId/users/:id', {}, {
|
_service.organizationUsers = $resource(_apiUri + '/organizations/:orgId/users/:id', {}, {
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
.module('bit.settings')
|
.module('bit.settings')
|
||||||
|
|
||||||
.controller('settingsCreateOrganizationController', function ($scope, $state, apiService, cryptoService,
|
.controller('settingsCreateOrganizationController', function ($scope, $state, apiService, cryptoService,
|
||||||
toastr, $analytics, authService, stripe, constants) {
|
toastr, $analytics, authService, stripe, constants, appSettings, validationService) {
|
||||||
$scope.plans = constants.plans;
|
$scope.plans = constants.plans;
|
||||||
$scope.storageGb = constants.storageGb;
|
$scope.storageGb = constants.storageGb;
|
||||||
$scope.paymentMethod = 'card';
|
$scope.paymentMethod = 'card';
|
||||||
|
$scope.selfHosted = appSettings.selfHosted;
|
||||||
|
|
||||||
$scope.model = {
|
$scope.model = {
|
||||||
plan: 'free',
|
plan: 'free',
|
||||||
@ -52,50 +53,68 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.submit = function (model) {
|
$scope.submit = function (model, form) {
|
||||||
var shareKeyCt = cryptoService.makeShareKeyCt();
|
if ($scope.selfHosted) {
|
||||||
|
var fileEl = document.getElementById('file');
|
||||||
if (model.plan === 'free') {
|
var files = fileEl.files;
|
||||||
var freeRequest = {
|
if (!files || !files.length) {
|
||||||
name: model.name,
|
validationService.addError(form, 'file', 'Select a license file.', true);
|
||||||
planType: model.plan,
|
|
||||||
key: shareKeyCt,
|
|
||||||
billingEmail: model.billingEmail
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.submitPromise = apiService.organizations.post(freeRequest).$promise.then(finalizeCreate);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var stripeReq = null;
|
|
||||||
if ($scope.paymentMethod === 'card') {
|
|
||||||
stripeReq = stripe.card.createToken(model.card);
|
|
||||||
}
|
|
||||||
else if ($scope.paymentMethod === 'bank') {
|
|
||||||
model.bank.currency = 'USD';
|
|
||||||
model.bank.country = 'US';
|
|
||||||
stripeReq = stripe.bankAccount.createToken(model.bank);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.submitPromise = stripeReq.then(function (response) {
|
var fd = new FormData();
|
||||||
var paidRequest = {
|
fd.append('license', files[0]);
|
||||||
|
fd.append('key', shareKeyCt);
|
||||||
|
|
||||||
|
$scope.submitPromise = apiService.organizations.postLicense(fd).$promise.then(function (result) {
|
||||||
|
return finalizeCreate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var shareKeyCt = cryptoService.makeShareKeyCt();
|
||||||
|
|
||||||
|
if (model.plan === 'free') {
|
||||||
|
var freeRequest = {
|
||||||
name: model.name,
|
name: model.name,
|
||||||
planType: model.interval === 'month' ? $scope.plans[model.plan].monthPlanType :
|
planType: model.plan,
|
||||||
$scope.plans[model.plan].annualPlanType,
|
|
||||||
key: shareKeyCt,
|
key: shareKeyCt,
|
||||||
paymentToken: response.id,
|
billingEmail: model.billingEmail
|
||||||
additionalSeats: model.additionalSeats,
|
|
||||||
additionalStorageGb: model.additionalStorageGb,
|
|
||||||
billingEmail: model.billingEmail,
|
|
||||||
businessName: model.ownedBusiness ? model.businessName : null
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return apiService.organizations.post(paidRequest).$promise;
|
$scope.submitPromise = apiService.organizations.post(freeRequest).$promise.then(finalizeCreate);
|
||||||
}, function (err) {
|
}
|
||||||
throw err.message;
|
else {
|
||||||
}).then(finalizeCreate);
|
var stripeReq = null;
|
||||||
|
if ($scope.paymentMethod === 'card') {
|
||||||
|
stripeReq = stripe.card.createToken(model.card);
|
||||||
|
}
|
||||||
|
else if ($scope.paymentMethod === 'bank') {
|
||||||
|
model.bank.currency = 'USD';
|
||||||
|
model.bank.country = 'US';
|
||||||
|
stripeReq = stripe.bankAccount.createToken(model.bank);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.submitPromise = stripeReq.then(function (response) {
|
||||||
|
var paidRequest = {
|
||||||
|
name: model.name,
|
||||||
|
planType: model.interval === 'month' ? $scope.plans[model.plan].monthPlanType :
|
||||||
|
$scope.plans[model.plan].annualPlanType,
|
||||||
|
key: shareKeyCt,
|
||||||
|
paymentToken: response.id,
|
||||||
|
additionalSeats: model.additionalSeats,
|
||||||
|
additionalStorageGb: model.additionalStorageGb,
|
||||||
|
billingEmail: model.billingEmail,
|
||||||
|
businessName: model.ownedBusiness ? model.businessName : null
|
||||||
|
};
|
||||||
|
|
||||||
|
return apiService.organizations.post(paidRequest).$promise;
|
||||||
|
}, function (err) {
|
||||||
|
throw err.message;
|
||||||
|
}).then(finalizeCreate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function finalizeCreate(result) {
|
function finalizeCreate(result) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -202,6 +202,7 @@
|
|||||||
<script src="app/organization/organizationBillingChangePaymentController.js"></script>
|
<script src="app/organization/organizationBillingChangePaymentController.js"></script>
|
||||||
<script src="app/organization/organizationBillingAdjustSeatsController.js"></script>
|
<script src="app/organization/organizationBillingAdjustSeatsController.js"></script>
|
||||||
<script src="app/organization/organizationBillingAdjustStorageController.js"></script>
|
<script src="app/organization/organizationBillingAdjustStorageController.js"></script>
|
||||||
|
<script src="app/organization/organizationBillingUpdateLicenseController.js"></script>
|
||||||
<script src="app/organization/organizationDeleteController.js"></script>
|
<script src="app/organization/organizationDeleteController.js"></script>
|
||||||
<script src="app/organization/organizationBillingChangePlanController.js"></script>
|
<script src="app/organization/organizationBillingChangePlanController.js"></script>
|
||||||
<script src="app/organization/organizationBillingVerifyBankController.js"></script>
|
<script src="app/organization/organizationBillingVerifyBankController.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user