mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-27 12:36:14 +01:00
org settings and billing
This commit is contained in:
parent
7591843220
commit
80e4d2329a
8
src/app/filters/jsonDateFilter.js
Normal file
8
src/app/filters/jsonDateFilter.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
angular
|
||||||
|
.module('bit.filters')
|
||||||
|
|
||||||
|
.filter('jsonDate', function () {
|
||||||
|
return function (input) {
|
||||||
|
return input.split('T').join(' ');
|
||||||
|
};
|
||||||
|
});
|
@ -1,6 +1,72 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.organization')
|
.module('bit.organization')
|
||||||
|
|
||||||
.controller('organizationBillingController', function ($scope) {
|
.controller('organizationBillingController', function ($scope, apiService, $state) {
|
||||||
|
$scope.charges = [];
|
||||||
|
$scope.paymentSource = null;
|
||||||
|
$scope.plan = null;
|
||||||
|
$scope.subscription = null;
|
||||||
|
$scope.loading = true;
|
||||||
|
|
||||||
|
$scope.$on('$viewContentLoaded', function () {
|
||||||
|
apiService.organizations.getBilling({ id: $state.params.orgId }, function (org) {
|
||||||
|
$scope.loading = false;
|
||||||
|
|
||||||
|
$scope.plan = {
|
||||||
|
name: org.Plan,
|
||||||
|
type: org.PlanType,
|
||||||
|
maxUsers: org.MaxUsers
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.subscription = {
|
||||||
|
trialEndDate: org.Subscription.TrialEndDate,
|
||||||
|
nextBillDate: org.Subscription.NextBillDate,
|
||||||
|
cancelNext: org.Subscription.CancelAtNextBillDate,
|
||||||
|
status: org.Subscription.Status
|
||||||
|
};
|
||||||
|
|
||||||
|
if (org.Subscription.Items) {
|
||||||
|
$scope.subscription.items = [];
|
||||||
|
for (var i = 0; i < org.Subscription.Items.length; i++) {
|
||||||
|
$scope.subscription.items.push({
|
||||||
|
amount: org.Subscription.Items[i].Amount,
|
||||||
|
name: org.Subscription.Items[i].Name,
|
||||||
|
interval: org.Subscription.Items[i].Interval,
|
||||||
|
qty: org.Subscription.Items[i].Quantity
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (org.PaymentSource) {
|
||||||
|
$scope.paymentSource = {
|
||||||
|
type: org.PaymentSource.Type,
|
||||||
|
description: org.PaymentSource.Description,
|
||||||
|
cardBrand: org.PaymentSource.CardBrand
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var charges = [];
|
||||||
|
for (var i = 0; i < org.Charges.length; i++) {
|
||||||
|
charges.push({
|
||||||
|
date: org.Charges[i].CreatedDate,
|
||||||
|
paymentSource: org.Charges[i].PaymentSource ? org.Charges[i].PaymentSource.Description : '-',
|
||||||
|
amount: org.Charges[i].Amount,
|
||||||
|
status: org.Charges[i].Status,
|
||||||
|
failureMessage: org.Charges[i].FailureMessage,
|
||||||
|
refunded: org.Charges[i].Refunded,
|
||||||
|
partiallyRefunded: org.Charges[i].PartiallyRefunded,
|
||||||
|
refundedAmount: org.Charges[i].RefundedAmount
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$scope.charges = charges;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.changePayment = function () {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancel = function () {
|
||||||
|
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,23 @@
|
|||||||
angular
|
angular
|
||||||
.module('bit.organization')
|
.module('bit.organization')
|
||||||
|
|
||||||
.controller('organizationSettingsController', function ($scope) {
|
.controller('organizationSettingsController', function ($scope, $state, apiService, toastr, authService) {
|
||||||
|
$scope.model = {};
|
||||||
|
$scope.$on('$viewContentLoaded', function () {
|
||||||
|
apiService.organizations.get({ id: $state.params.orgId }, function (org) {
|
||||||
|
$scope.model = {
|
||||||
|
name: org.Name,
|
||||||
|
billingEmail: org.BillingEmail,
|
||||||
|
businessName: org.BusinessName
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.generalSave = function () {
|
||||||
|
$scope.generalPromise = apiService.organizations.put({ id: $state.params.orgId }, $scope.model, function (org) {
|
||||||
|
authService.updateProfileOrganization(org).then(function (updatedOrg) {
|
||||||
|
toastr.success('Organization has been updated.', 'Success!');
|
||||||
|
});
|
||||||
|
}).$promise;
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
@ -7,10 +7,110 @@
|
|||||||
<section class="content">
|
<section class="content">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title"><i class="fa fa-server"></i> My Org</h3>
|
<h3 class="box-title">Plan</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
Some data
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<dl>
|
||||||
|
<dt>Name</dt>
|
||||||
|
<dd>{{plan.name}}</dd>
|
||||||
|
<dt>Maximum Users</dt>
|
||||||
|
<dd>{{plan.maxUsers}}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<dl>
|
||||||
|
<dt>Status</dt>
|
||||||
|
<dd style="text-transform: capitalize;">{{subscription.status}}</dd>
|
||||||
|
<dt>Next Bill Date</dt>
|
||||||
|
<dd>{{subscription.nextBillDate | jsonDate}}</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<strong>Details</strong>
|
||||||
|
<div ng-show="loading">
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive" style="margin: 0;" ng-show="!loading">
|
||||||
|
<table class="table" style="margin: 0;">
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="item in subscription.items">
|
||||||
|
<td>
|
||||||
|
{{item.name}} {{item.qty > 1 ? '×' + item.qty : ''}}
|
||||||
|
@ {{item.amount | currency:'$'}} /{{item.interval}}
|
||||||
|
</td>
|
||||||
|
<td class="text-right">{{(item.qty * item.amount) | currency:'$'}} /{{item.interval}}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
<button type="button" class="btn btn-default btn-flat" ng-click="changePlan()">
|
||||||
|
Change Plan
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-default btn-flat" ng-click="cancel()">
|
||||||
|
Cancel Plan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">Payment Method</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div ng-show="loading">
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
<div ng-show="!loading && !paymentMethod">
|
||||||
|
<i class="fa fa-credit-card"></i> No payment method on file.
|
||||||
|
</div>
|
||||||
|
<div ng-show="!loading && paymentMethod">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
<button type="button" class="btn btn-default btn-flat" ng-click="changePayment()">
|
||||||
|
{{ paymentMethod ? 'Change Payment Method' : 'Add Payment Method' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">Charges</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div ng-show="loading">
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
<div ng-show="!loading && !charges.length">
|
||||||
|
No charges.
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive" ng-show="charges.length">
|
||||||
|
<table class="table">
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="charge in charges">
|
||||||
|
<td style="width: 200px">
|
||||||
|
{{charge.date | jsonDate}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{charge.paymentSource}}
|
||||||
|
</td>
|
||||||
|
<td style="width: 150px; text-transform: capitalize;">
|
||||||
|
{{charge.status}}
|
||||||
|
</td>
|
||||||
|
<td class="text-right" style="width: 150px;">
|
||||||
|
{{charge.amount | currency:'$'}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -5,12 +5,48 @@
|
|||||||
</h1>
|
</h1>
|
||||||
</section>
|
</section>
|
||||||
<section class="content">
|
<section class="content">
|
||||||
<div class="box">
|
<div class="box box-default">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title"><i class="fa fa-server"></i> My Org</h3>
|
<h3 class="box-title">General</h3>
|
||||||
</div>
|
</div>
|
||||||
|
<form role="form" name="generalForm" ng-submit="generalForm.$valid && generalSave()" api-form="generalPromise">
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
Some data
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="callout callout-danger validation-errors" ng-show="generalForm.$errors">
|
||||||
|
<h4>Errors have occured</h4>
|
||||||
|
<ul>
|
||||||
|
<li ng-repeat="e in generalForm.$errors">{{e}}</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" show-errors>
|
||||||
|
<label for="name">Organization Name</label>
|
||||||
|
<input type="text" id="name" name="Name" ng-model="model.name" class="form-control"
|
||||||
|
required api-field />
|
||||||
|
</div>
|
||||||
|
<div class="form-group" show-errors>
|
||||||
|
<label for="name">Business Name</label>
|
||||||
|
<input type="text" id="businessName" name="BusinessName" ng-model="model.businessName"
|
||||||
|
class="form-control" api-field />
|
||||||
|
</div>
|
||||||
|
<div class="form-group" show-errors>
|
||||||
|
<label for="name">Billing Email</label>
|
||||||
|
<input type="email" id="billingEmail" name="BillingEmail" ng-model="model.billingEmail"
|
||||||
|
class="form-control" required api-field />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3 settings-photo">
|
||||||
|
<letter-avatar data="{{model.name}}" round="false"
|
||||||
|
avclass="img-responsive img-rounded" avwidth="200" avheight="200"
|
||||||
|
fontsize="90"></letter-avatar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
<button type="submit" class="btn btn-primary btn-flat" ng-disabled="generalForm.$loading">
|
||||||
|
<i class="fa fa-refresh fa-spin loading-icon" ng-show="generalForm.$loading"></i>Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
_service.organizations = $resource(_apiUri + '/organizations/:id', {}, {
|
_service.organizations = $resource(_apiUri + '/organizations/:id', {}, {
|
||||||
get: { method: 'GET', params: { id: '@id' } },
|
get: { method: 'GET', params: { id: '@id' } },
|
||||||
|
getBilling: { url: _apiUri + '/organizations/:id/billing', method: 'GET', params: { id: '@id' } },
|
||||||
list: { method: 'GET', params: {} },
|
list: { method: 'GET', params: {} },
|
||||||
post: { method: 'POST', params: {} },
|
post: { method: 'POST', params: {} },
|
||||||
put: { method: 'POST', params: { id: '@id' } },
|
put: { method: 'POST', params: { id: '@id' } },
|
||||||
|
@ -140,6 +140,17 @@ angular
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_service.updateProfileOrganization = function (org) {
|
||||||
|
return _service.getUserProfile().then(function (profile) {
|
||||||
|
if (profile) {
|
||||||
|
if (profile.organizations && org.Id in profile.organizations) {
|
||||||
|
profile.organizations[org.Id].name = org.Name;
|
||||||
|
_userProfile = profile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
_service.isAuthenticated = function () {
|
_service.isAuthenticated = function () {
|
||||||
return tokenService.getToken() !== null;
|
return tokenService.getToken() !== null;
|
||||||
};
|
};
|
||||||
|
@ -93,6 +93,7 @@
|
|||||||
<script src="app/filters/filtersModule.js"></script>
|
<script src="app/filters/filtersModule.js"></script>
|
||||||
<script src="app/filters/enumNameFilter.js"></script>
|
<script src="app/filters/enumNameFilter.js"></script>
|
||||||
<script src="app/filters/enumLabelClassFilter.js"></script>
|
<script src="app/filters/enumLabelClassFilter.js"></script>
|
||||||
|
<script src="app/filters/jsonDateFilter.js"></script>
|
||||||
|
|
||||||
<script src="app/services/servicesModule.js"></script>
|
<script src="app/services/servicesModule.js"></script>
|
||||||
<script src="app/services/tokenService.js"></script>
|
<script src="app/services/tokenService.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user