parent
d63ec8c6b0
commit
fe735b8048
25 changed files with 784 additions and 614 deletions
80
static/directives/billing-management-panel.html
Normal file
80
static/directives/billing-management-panel.html
Normal file
|
@ -0,0 +1,80 @@
|
|||
<div class="billing-management-panel-element">
|
||||
<div class="cor-loader-inline" ng-show="updating"></div>
|
||||
<div ng-show="!updating">
|
||||
<table class="co-list-table">
|
||||
<tr>
|
||||
<td>Current Plan:</td>
|
||||
<td>
|
||||
<div class="sub-usage" ng-if="subscription.usedPrivateRepos > currentPlan.privateRepos">
|
||||
<i class="fa fa-exclamation-triangle red"></i> <strong>{{ subscription.usedPrivateRepos }}</strong> private repositories exceeds the amount allowed by your plan. Upgrade your plan to avoid service disruptions.
|
||||
</div>
|
||||
|
||||
<div class="sub-usage" ng-if="subscription.usedPrivateRepos == currentPlan.privateRepos">
|
||||
<i class="fa fa-exclamation-triangle yellow"></i> <strong>{{ subscription.usedPrivateRepos }}</strong> private repositories is the maximum allowed by your plan. Upgrade your plan to create more private repositories.
|
||||
</div>
|
||||
|
||||
<a class="co-modify-link" ng-href="{{ getEntityPrefix() }}/billing">{{ currentPlan.privateRepos }} private repositories</a>
|
||||
<div class="help-text">Up to {{ currentPlan.privateRepos }} private repositories, unlimited public repositories</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="currentCard">
|
||||
<td>Credit Card:</td>
|
||||
<td>
|
||||
<img class="credit-card-image" ng-src="/static/img/creditcards/{{ getCreditImage(currentCard) }}">
|
||||
<span class="credit-card-number">
|
||||
••••
|
||||
••••
|
||||
••••
|
||||
{{ currentCard.last4 }}
|
||||
</span>
|
||||
<a class="co-modify-link" ng-click="changeCreditCard()">Change card</a>
|
||||
<div class="help-text">Expires {{ currentCard.exp_month }}/{{ currentCard.exp_year }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Invoices:</td>
|
||||
<td>
|
||||
<a ng-href="{{ getEntityPrefix() }}/billing/invoices">View Invoices</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Receipts:</td>
|
||||
<td>
|
||||
<a class="co-modify-link" ng-click="showChangeReceipts()" ng-show="!invoice_email">Do not email after successful charges</a>
|
||||
<a class="co-modify-link" ng-click="showChangeReceipts()" ng-show="invoice_email">Email receipts to {{ invoice_email_address }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Change receipts dialog -->
|
||||
<div class="cor-confirm-dialog"
|
||||
dialog-context="changeReceiptsInfo"
|
||||
dialog-action="changeReceipts(info, callback)"
|
||||
dialog-title="Receipts Settings"
|
||||
dialog-action-title="Update Setting"
|
||||
dialog-form="context.receiptform">
|
||||
<form class="receipt-form" name="context.receiptform">
|
||||
<table class="co-option-table">
|
||||
<tr>
|
||||
<td><input type="radio" id="emailReceiptNo" ng-model="changeReceiptsInfo.sendOption" ng-value="false"></td>
|
||||
<td>
|
||||
<label for="emailReceiptNo">Do not send email receipts</label>
|
||||
<div class="help-text">Log into your account to view invoices</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" id="emailReceiptYes" ng-model="changeReceiptsInfo.sendOption" ng-value="true"></td>
|
||||
<td>
|
||||
<label for="emailReceiptYes">Send receipts via email</label>
|
||||
<div class="help-text">
|
||||
After every successful charge send an email to:
|
||||
<div style="margin-top: 6px;"><input type="email" class="form-control" ng-model="changeReceiptsInfo.address" required></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -1,65 +0,0 @@
|
|||
<div class="billing-options-element">
|
||||
<!-- Credit Card -->
|
||||
<div style="margin-bottom: 20px">
|
||||
<div class="panel-title">
|
||||
Credit Card
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="cor-loader-inline" ng-show="!currentCard || changingCard"></div>
|
||||
<div class="current-card" ng-show="currentCard && !changingCard">
|
||||
<div class="alert alert-warning" ng-if="currentCard.last4 && isExpiringSoon(currentCard)">
|
||||
Your current credit card is expiring soon!
|
||||
</div>
|
||||
|
||||
<img ng-src="{{ '/static/img/creditcards/' + getCreditImage(currentCard) }}" ng-show="currentCard.last4">
|
||||
<span class="no-card-outline" ng-show="!currentCard.last4"></span>
|
||||
|
||||
<span class="last4" ng-show="currentCard.last4">****-****-****-<b>{{ currentCard.last4 }}</b></span>
|
||||
<span class="expires" ng-show="currentCard.last4">
|
||||
{{ currentCard.exp_month }} / {{ currentCard.exp_year }}
|
||||
</span>
|
||||
|
||||
<span class="not-found" ng-show="!currentCard.last4">No credit card found</span>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" ng-show="currentCard && !changingCard" ng-click="changeCard()">
|
||||
Change Credit Card
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Options -->
|
||||
<div style="margin-bottom: 20px">
|
||||
<div class="panel-title">
|
||||
Billing Receipts
|
||||
<div class="cor-loader-inline" ng-show="working"></div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="settings-option">
|
||||
<input id="invoiceEmail" type="checkbox" ng-model="invoice_email">
|
||||
<label for="invoiceEmail">Send Receipt Emails</label>
|
||||
<div class="settings-description">
|
||||
If checked, a receipt email will be sent to <a ng-click="changeInvoiceEmailAddress()">{{ obj.invoice_email_address || obj.email }}</a> on every successful charge
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal message dialog -->
|
||||
<div class="modal fade" id="cannotchangecardModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Cannot change credit card</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Your credit card could not be changed
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
</div>
|
|
@ -1,112 +1,108 @@
|
|||
<div class="convert-user-to-org-element">
|
||||
<!-- Step 0 -->
|
||||
<div ng-show="convertStep == 0">
|
||||
<div ng-show="user.organizations.length > 0">
|
||||
Cannot convert this account into an organization, as it is a member of {{user.organizations.length}} other
|
||||
organization{{user.organizations.length > 1 ? 's' : ''}}.
|
||||
<br><br>
|
||||
Please leave the following organizations first:
|
||||
<ul class="org-list">
|
||||
<li ng-repeat="org in user.organizations">
|
||||
<span class="avatar" size="avatarSize || 16" data="org.avatar"></span>
|
||||
<a href="/organization/{{ org.name }}">{{ org.name }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="co-dialog modal fade" id="convertAccountModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Change Account Type</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- Step 0 -->
|
||||
<div ng-show="convertStep == 0">
|
||||
<div ng-show="user.organizations.length > 0">
|
||||
This account cannot be converted into an organization, as it is a member of {{user.organizations.length}} other
|
||||
organization{{user.organizations.length > 1 ? 's' : ''}}.
|
||||
<br><br>
|
||||
Please leave the following organizations first:
|
||||
<ul class="org-list">
|
||||
<li ng-repeat="org in user.organizations">
|
||||
<span class="avatar" size="avatarSize || 16" data="org.avatar"></span>
|
||||
<a href="/organization/{{ org.name }}">{{ org.name }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div ng-show="user.organizations.length == 0">
|
||||
<button class="btn btn-primary" ng-click="showConvertForm()">Start conversion process <i class="fa fa-arrow-circle-right" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Step 1 -->
|
||||
<div class="convert-form" ng-show="convertStep == 1">
|
||||
Fill out the form below to convert your current user account into an organization. Your existing repositories will be maintained under the
|
||||
namespace. All <strong>direct</strong> permissions delegated to {{ user.username }} will be deleted.
|
||||
|
||||
<form method="post" name="convertForm" id="convertForm" ng-submit="convertToOrg()">
|
||||
<div class="form-group">
|
||||
<label for="orgName">Organization Name</label>
|
||||
<div class="form-group-content">
|
||||
<div class="existing-data">
|
||||
<span class="avatar" size="24" data="user.avatar"></span>
|
||||
<span class="username">{{ user.username }}</span>
|
||||
<div ng-show="user.organizations.length == 0">
|
||||
<table class="co-option-table">
|
||||
<tr>
|
||||
<td><input type="radio" id="accountTypeI" ng-model="accountType" value="user"></td>
|
||||
<td>
|
||||
<label for="accountTypeI">Individual account (current)</label>
|
||||
<div class="help-text">Single account with multiple repositories</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" id="accountTypeO" ng-model="accountType" value="organization"></td>
|
||||
<td>
|
||||
<label for="accountTypeO">Organization</label>
|
||||
<div class="help-text">Multiple users and teams that share access and billing under a single namespace</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<span class="description">This will continue to be the namespace for your repositories</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="orgName">Admin User</label>
|
||||
<div class="form-group-content">
|
||||
<input id="adminUsername" name="adminUsername" type="text" class="form-control" placeholder="Admin Username"
|
||||
ng-model="org.adminUser" required autofocus>
|
||||
<input id="adminPassword" name="adminPassword" type="password" class="form-control" placeholder="Admin Password"
|
||||
ng-model="org.adminPassword" required>
|
||||
<span class="description">
|
||||
The username and password for the account that will become an administrator of the organization.
|
||||
Note that this account <b>must be a separate registered account</b> from the account that you are
|
||||
trying to convert, and <b>must already exist</b>.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Step 1 -->
|
||||
<div class="convert-form" ng-show="convertStep == 1">
|
||||
Fill out the form below to convert your current user account into an organization. Your existing repositories will be maintained under the
|
||||
namespace. All <strong>direct</strong> permissions delegated to {{ user.username }} will be deleted.
|
||||
|
||||
<!-- Plans Table -->
|
||||
<div class="form-group plan-group" quay-require="['BILLING']">
|
||||
<label>Organization Plan</label>
|
||||
<div class="form-group-content">
|
||||
<div class="plans-table" plans="orgPlans" current-plan="org.plan"></div>
|
||||
<span class="description">The billing plan for the new organization. If private repositories are unneeded, select "Open Source".</span>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" name="convertForm" id="convertForm" ng-submit="nextStep()">
|
||||
<div class="form-group">
|
||||
<label for="orgName">Organization Name</label>
|
||||
<div class="form-group-content">
|
||||
<div class="existing-data">
|
||||
<span class="avatar" size="24" data="user.avatar"></span>
|
||||
<span class="username">{{ user.username }}</span>
|
||||
</div>
|
||||
<span class="description">This will continue to be the namespace for your repositories</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-bar">
|
||||
<button class="btn btn-large btn-danger" type="submit"
|
||||
ng-disabled="convertForm.$invalid || (Features.BILLING && !org.plan)"
|
||||
analytics-on analytics-event="convert_to_organization">
|
||||
Convert To Organization
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="orgName">Admin User</label>
|
||||
<div class="form-group-content">
|
||||
<input id="adminUsername" name="adminUsername" type="text" class="form-control" placeholder="Admin Username"
|
||||
ng-model="org.adminUser" required autofocus>
|
||||
<input id="adminPassword" name="adminPassword" type="password" class="form-control" placeholder="Admin Password"
|
||||
ng-model="org.adminPassword" required>
|
||||
<span class="description">
|
||||
The username and password for the account that will become an administrator of the organization.
|
||||
Note that this account <b>must be a separate registered account</b> from the account that you are
|
||||
trying to convert, and <b>must already exist</b>.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="convert-form" ng-show="convertStep == 2">
|
||||
Please select the billing plan to use for the new organization. Select "Open Source" to create an organization without
|
||||
private repositories.
|
||||
<div class="plans-table" plans="orgPlans" current-plan="org.plan"></div>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 (conversion) -->
|
||||
<div class="convert-form" ng-show="convertStep == 3">
|
||||
<div class="cor-loader"></div>
|
||||
</div>
|
||||
|
||||
<!-- Modal message dialog -->
|
||||
<div class="modal fade" id="cannotconvertModal">
|
||||
<div class="modal-dialog co-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Cannot convert account</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Your account could not be converted. Please try again in a moment.
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<div class="modal-footer" ng-show="convertStep < 3">
|
||||
<button class="btn btn-default" ng-show="convertStep == 0 && accountType == 'user'" data-dismiss="modal">Close</button>
|
||||
<button class="btn btn-primary" ng-show="convertStep == 0 && accountType == 'organization'" ng-click="showConvertForm()">Convert Account</button>
|
||||
<button class="btn btn-primary" ng-show="convertStep == 1" ng-disabled="convertForm.$invalid" ng-click="nextStep()">
|
||||
<span ng-if="Features.BILLING">Choose billing</span>
|
||||
<span ng-if="!Features.BILLING">Convert Account</span>
|
||||
</button>
|
||||
<button class="btn btn-primary" ng-show="convertStep == 2" ng-disabled="!org.plan" ng-click="performConversion()">
|
||||
Convert Account
|
||||
</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
|
||||
<!-- Modal message dialog -->
|
||||
<div class="modal co-modal fade" id="reallyconvertModal">
|
||||
<div class="modal-dialog co-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Convert to organization?</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="co-alert co-alert-danger">You will not be able to login to this account once converted!</div>
|
||||
<div>Are you <b>absolutely sure</b> you would like to convert this account to an organization? Once done, there is no going back.</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-dismiss="modal" ng-click="reallyConvert()">Absolutely: Convert Now</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
</div>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<span ng-transclude/>
|
||||
</div>
|
||||
<div class="modal-footer" ng-show="!working">
|
||||
<button type="button" class="btn btn-primary" ng-click="performAction()">
|
||||
<button type="button" class="btn btn-primary" ng-click="performAction()" ng-disabled="dialogForm && dialogForm.$invalid">
|
||||
{{ dialogActionTitle }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
|
|
Reference in a new issue