initial import for Open Source 🎉

This commit is contained in:
Jimmy Zelinskie 2019-11-12 11:09:47 -05:00
parent 1898c361f3
commit 9c0dd3b722
2048 changed files with 218743 additions and 0 deletions

View file

@ -0,0 +1,4 @@
<span class="anchor-element">
<a ng-href="{{ href }}" ng-show="href && !isOnlyText" target="{{ target }}"><span ng-transclude></span></a>
<span ng-show="!href || isOnlyText"><span ng-transclude></span></span>
</span>

View file

@ -0,0 +1,32 @@
<div class="angular-tour-ui-element"
ng-class="[tour ? 'touring' : 'nottouring', inline ? 'inline' : 'overlay']">
<div class="tour-contents" ng-show="!supported">
Your browser does not support features required for this tour. Please upgrade and try again.
</div>
<div class="co-alert co-alert-warning" ng-show="step.signal.$hasError">
There was an error registering to listen for server side events. Steps of the tutorial may not be
possible. If this problem persists, please contact support.
</div>
<div class="tour-contents" ng-show="supported">
<div class="step-title" ng-show="step.title">{{ step.title }}</div>
<div class="slide-animate-container">
<div class="step-content" ng-show="step.content" ng-bind-html="step.content || ''"></div>
<div class="step-content">
<ng:include src="step.templateUrl" scope="info"></ng:include>
</div>
</div>
<div class="controls" ng-show="(hasNextStep && !step.signal) || (!hasNextStep && !inline)">
<button class="btn btn-primary" ng-click="next()" ng-show="hasNextStep && !step.signal">Continue Tutorial</button>
<button class="btn btn-primary" ng-click="stop()" ng-show="!hasNextStep && !inline">Done</button>
</div>
<div class="wait-message" ng-show="step.waitMessage">
<div class="cor-loader-inline"></div> {{ step.waitMessage }}
<span class="skip-message" ng-show="step.skipTitle"><button class="btn btn-default" ng-click="next()">{{ step.skipTitle }}</button></span>
</div>
</div>
</div>

View file

@ -0,0 +1,12 @@
<div class="application-info-element" style="padding-bottom: 18px">
<div class="auth-header">
<span class="avatar" size="48" data="application.avatar"></span>
<h2><a href="{{ application.url }}" ng-safenewtab>{{ application.name }}</a></h2>
<h4>
{{ application.organization.name }}
</h4>
</div>
<div style="padding-top: 10px">
{{ application.description || '(No Description)' }}
</div>
</div>

View file

@ -0,0 +1,37 @@
<div class="application-manager-element">
<div class="feedback-bar" feedback="feedback"></div>
<div class="cor-loader" ng-show="loading"></div>
<div ng-show="!loading">
<div class="manager-header" header-title="OAuth Applications">
<span class="popup-input-button" placeholder="'Application Name'"
submitted="createApplication(value)">
<i class="fa fa-plus"></i> Create New Application
</span>
</div>
<div class="section-description-header">
The OAuth Applications panel allows organizations to define custom OAuth applications that can be used by internal or external customers to access <span class="registry-name"></span> data on behalf of the customers. More information about the <span class="registry-name"></span> API can be found by contacting support.
</div>
<div class="empty" ng-if="!applications.length">
<div class="empty-primary-msg">No OAuth applications defined.</div>
<div class="empty-secondary-msg">
Click the "Create New Application" button above to create a new OAuth application under
this organization.
</div>
</div>
<table class="cor-table" ng-show="applications.length">
<thead>
<td>Application Name</td>
<td>Application URI</td>
</thead>
<tr ng-repeat="app in applications">
<td><a href="/organization/{{ organization.name }}/application/{{ app.client_id }}">{{ app.name }}</a></td>
<td><a href="{{ app.application_uri }}" ng-if="app.application_uri" ng-safenewtab>{{ app.application_uri }}</a></td>
</tr>
</table>
</div>
</div>

View file

@ -0,0 +1,15 @@
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body" style="padding: 4px; padding-left: 20px;">
<button type="button" class="close" ng-click="$hide()" style="padding: 4px;">
&times;
</button>
<div class="application-info" application="applicationInfo"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$hide()">Close</button>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,4 @@
<span class="application-reference-element">
<i class="fa fa-cloud"></i>
<a ng-click="showAppDetails()">{{ title }}</a>
</span>

View file

@ -0,0 +1,54 @@
<div class="authorized-apps-manager-element">
<div class="manager-header" header-title="Authorized Applications"></div>
<div class="section-description-header">
The authorized applications panel lists applications you have authorized to view information and perform actions on your behalf. You can revoke any of your authorizations here by clicking the gear icon and clicking "Revoke Authorization".
</div>
<div class="resource-view" resource="authorizedAppsResource"
error-message="'Cannot load authorized applications'"></div>
<div class="empty" ng-if="!authorizedApps.length">
<div class="empty-primary-msg">You have not authorized any external applications.</div>
</div>
<table class="cor-table" ng-if="authorizedApps.length">
<thead>
<td>Application Name</td>
<td>Authorized Permissions</td>
<td class="options-col"></td>
</thead>
<tr class="auth-info" ng-repeat="authInfo in authorizedApps">
<td>
<span class="avatar" size="24" data="authInfo.application.avatar"></span>
<a href="{{ authInfo.application.url }}" ng-if="authInfo.application.url" ng-safenewtab
data-title="{{ authInfo.application.description || authInfo.application.name }}" bs-tooltip>
{{ authInfo.application.name }}
</a>
<span ng-if="!authInfo.application.url"
data-title="{{ authInfo.application.description || authInfo.application.name }}"
bs-tooltip>
{{ authInfo.application.name }}
</span>
<span class="by">{{ authInfo.application.organization.name }}</span>
</td>
<td>
<span class="label label-default scope"
ng-class="{'repo:admin': 'label-primary', 'repo:write': 'label-success', 'repo:create': 'label-success'}[scopeInfo.scope]"
ng-repeat="scopeInfo in authInfo.scopes" data-title="{{ scopeInfo.description }}"
bs-tooltip>
{{ scopeInfo.scope }}
</span>
</td>
<td class="options-col">
<span class="cor-options-menu">
<span class="cor-option" option-click="deleteAccess(authInfo)">
<i class="fa fa-times"></i> Revoke Authorization
</span>
</span>
</td>
</tr>
</table>
</div>
</div>

View file

@ -0,0 +1,14 @@
<span class="avatar-element"
ng-style="{'width': size, 'height': size, 'backgroundColor': (showGravatar || isLoading) ? 'transparent' : data.color, 'fontSize': fontSize, 'lineHeight': lineHeight}"
ng-class="data.kind">
<img ng-src="//www.gravatar.com/avatar/{{ data.hash }}?d=blank&size=512"
ng-if="loadGravatar"
ng-visible="showGravatar"
ng-image-watch="imageCallback(result)"
ng-style="{'width': imageSize + 'px', 'height': imageSize + 'px'}"
crossorigin="anonymous">
<span class="default-avatar" ng-if="!isLoading && !showGravatar">
<span class="letter" ng-if="data.kind != 'team' || data.name != 'owners'">{{ data.name.charAt(0).toUpperCase() }}</span>
<span class="letter" ng-if="data.kind == 'team' && data.name == 'owners'">&Omega;</span>
</span>
</span>

View file

@ -0,0 +1,85 @@
<div class="billing-invoices-element">
<div class="cor-loader" ng-show="loading"></div>
<div class="empty" ng-if="!loading && !invoices.length">
<div class="empty-primary-msg">No billing invoices found.</div>
<div class="empty-secondary-msg">
This account has not been billed by <span class="registry-name"></span>.
</div>
</div>
<div ng-show="!loading && invoices.length">
<div class="dropdown fields-menu" data-title="Custom Invoice Fields" bs-tooltip>
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">
<i class="fa fa-bars"></i>
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li role="presentation" ng-repeat="invoiceField in invoiceFields">
<a class="invoice-field" role="menuitem" tabindex="-1" >
{{ invoiceField.title }}: {{ invoiceField.value }}
<i class="fa fa-trash-o btn btn-danger" ng-click="askDeleteField(invoiceField)"></i>
</a>
</li>
<li role="presentation" class="disabled" ng-if="!invoiceFields.length">
<a role="menuitem" tabindex="-1">No Custom Fields Defined</a>
</li>
<li role="presentation" class="divider"></li>
<li role="presentation">
<a role="menuitem" tabindex="-1" ng-click="showCreateField()">
<i class="fa fa-plus"></i>Add Custom Invoice Field
</a>
</li>
</ul>
</div>
<table class="co-table">
<thead>
<td>Billing Date/Time</td>
<td>Amount Due</td>
<td>Status</td>
<td class="options-col"></td>
</thead>
<tbody class="invoice" ng-repeat="invoice in invoices">
<tr class="invoice-title">
<td><span class="invoice-datetime">{{ invoice.date * 1000 | date:'medium' }}</span></td>
<td><span class="invoice-amount">{{ invoice.amount_due / 100 }}</span></td>
<td>
<span class="invoice-status">
<span class="success" ng-show="invoice.paid">Paid - Thank you!</span>
<span class="danger" ng-show="!invoice.paid && invoice.attempted && invoice.closed">Payment failed</span>
<span class="danger" ng-show="!invoice.paid && invoice.attempted && !invoice.closed">Payment failed - Will retry soon</span>
<span class="pending" ng-show="!invoice.paid && !invoice.attempted">Payment pending</span>
</span>
</td>
<td class="options-col">
<a ng-show="invoice.paid" href="/receipt?id={{ invoice.id }}" target="_new" download>
<i class="fa fa-download" data-title="Download Receipt" bs-tooltip="tooltip.title"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Delete Tag Confirm -->
<div class="cor-confirm-dialog"
dialog-context="createFieldInfo"
dialog-action="createCustomField(info.title, info.value, callback)"
dialog-title="Create Custom Field"
dialog-action-title="Create Field">
<form>
<div class="form-group">
<label for="titleInput">Enter Field Title</label>
<input id="titleInput" type="text" class="form-control"ng-model="createFieldInfo.title" placeholder="Field Title">
</div>
<div class="form-group">
<label for="valueInput">Enter Field Value</label>
<input id="valueInput" type="text" class="form-control" ng-model="createFieldInfo.value" placeholder="Field Value">
</div>
</form>
</div>
</div>
</div>

View 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">
&#8226;&#8226;&#8226;&#8226;&nbsp;
&#8226;&#8226;&#8226;&#8226;&nbsp;
&#8226;&#8226;&#8226;&#8226;&nbsp;
{{ 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>

View file

@ -0,0 +1,18 @@
<div class="build-info-bar-element" ng-class="build.phase">
<!-- Phase icon/color -->
<span class="phase-icon" ng-class="build.phase"></span>
<!-- Side information -->
<div class="build-side-info">
<!-- Build ID -->
<div class="build-side-id" ng-if="!hideId">{{ build.id }}</div>
<!-- Timing -->
<div class="timing" ng-if="showTime">
<i class="fa fa-clock-o"></i><time-ago datetime="build.started"></time-ago>
</div>
</div>
<div class="triggered-build-description" build="build" ng-if="build.trigger || build.trigger_metadata"></div>
<div ng-if="!build.trigger && !build.trigger_metadata">Manually Started Build</div>
</div>

View file

@ -0,0 +1,4 @@
<div class="build-log-command-element" ng-class="::{'multistep-seperator': !!isSecondaryFrom(command.message) || fromName(command.message)}">
<span class="from-name" ng-if="::!!fromName(command.message)">{{ ::fromName(command.message) }}</span>
<dockerfile-command class="command" command="getWithoutStep(command.message)"></dockerfile-command>
</div>

View file

@ -0,0 +1,29 @@
<div bindonce class="build-log-error-element">
<!-- Errors -->
<span class="error-message-container">
<i class="fa fa-exclamation-triangle"></i>
<!-- Local Pull issue -->
<span bo-if="isPullError(error) && localPullInfo.isLocal">
<span bo-if="!localPullInfo.username" class="error-message">
Error 403: Could not pull private base image <a href="/repository/{{ localPullInfo.repo }}">{{ localPullInfo.repo }}</a> without robot account credentials. Please see
<a href="http://docs.quay.io/issues/base-pull-issue.html" ng-safenewtab>Setting up build trigger credentials</a> for more information.
</span>
<span bo-if="localPullInfo.username" class="error-message">
Error 403: Could not pull private base image <a href="/repository{{ localPullInfo.repo }}">{{ localPullInfo.repo }}</a> because robot account <strong>{{ localPullInfo.username}}</strong> does not have access. Please see
<a href="http://docs.quay.io/issues/base-pull-issue.html" ng-safenewtab>Setting up build trigger credentials</a> for more information.
</span>
</span>
<!-- Other issue -->
<span bo-if="!isPullError(error) || !localPullInfo.isLocal"
class="error-message" bo-text="error.message"></span>
<!-- Extended error information -->
<div bo-if="getBaseError(error) && isSuperuser">
Base Error Information: <pre>{{ getBaseError(entries) }}</pre>
</div>
<div bo-if="getInternalError(entries) && isSuperuser">
Internal Error Information: <pre>{{ getInternalError(entries) }}</pre>
</div>
</span>
</div>

View file

@ -0,0 +1,4 @@
<span bindonce class="build-log-phase-element">
<span class="phase-icon" ng-class="phase.message"></span>
<span class="build-message" phase="phase.message"></span>
</span>

View file

@ -0,0 +1,74 @@
<div class="build-logs-view-element" ng-class="useTimestamps ? 'with-timestamps' : ''">
<span ng-show="logEntries">
<button id="copyButton" class="btn btn-primary copy-button"
clipboard-copy="#{{ ::buildLogsText }}">
<i class="fa fa-clipboard"></i>Copy Logs
</button>
</span>
<a id="downloadButton" class="btn btn-primary download-button"
ng-href="/buildlogs/{{ currentBuild.id }}"
ng-safenewtab
ng-if="logEntries">
<i class="fa fa-download"></i>Download Logs
</a>
<span class="cor-loader" ng-if="!logEntries && !loadError"></span>
<div class="co-alert co-alert-warning" ng-if="loadError == 'blocked'">
Loading of build logs failed, most likely due to an ad blocker. Please
disable filtering and refresh this page.
</div>
<div class="co-alert co-alert-danger" ng-if="loadError == 'request-failed'">
Failed to load builds logs. Please reload and try again. If this problem persists,
please check for JavaScript or networking issues and contact support.
</div>
<div class="co-alert co-alert-danger" ng-if="loadError == 'unauthorized'">
You are not authorized to view builds logs. Please have the owner of the repository grant you
admin access to this repository.
</div>
<div ng-show="!loadError && pollChannel.skipping">
Refreshing Build Status...
<span class="cor-loader"></span>
</div>
<div ng-show="!loadError && !pollChannel.skipping && currentBuild.phase != 'expired'">
<span class="no-logs" ng-if="!logEntries.length && currentBuild.phase == 'waiting'">
(Waiting for build to start)
</span>
<div class="log-container" ng-class="container.type" ng-repeat="container in logEntries">
<div class="container-header" ng-class="container.type == 'phase' ? container.message : ''"
ng-switch on="container.type" ng-click="container.logs.toggle()">
<i class="fa chevron"
ng-class="container.logs.isVisible ? 'fa-chevron-down' : 'fa-chevron-right'"
ng-show="hasLogs(container)"></i>
<div ng-switch-when="phase">
<span class="container-content build-log-phase" phase="container"></span>
</div>
<div ng-switch-when="error">
<span class="container-content build-log-error" error="container" is-superuser="isSuperuser" entries="logEntries"></span>
</div>
<div ng-switch-when="command">
<span class="container-content build-log-command" command="container"></span>
</div>
</div>
<!-- Display the entries for the container -->
<div class="container-logs" ng-show="container.logs.isVisible">
<div class="log-entry" bindonce ng-repeat="entry in container.logs.visibleEntries">
<span class="id" bo-text="$index + container.index + 1" ng-if="!useTimestamps"></span>
<span class="id" bo-text="formatDatetime(entry.data.datetime)" ng-if="useTimestamps"></span>
<span class="message" bo-html="processANSI(entry.message, container)"></span>
<span class="timestamp" bo-text="formatDatetime(entry.data.datetime)" ng-if="!useTimestamps"></span>
</div>
<div ng-if="container.logs.hasHiddenEntries">
<div class="cor-loader-inline"></div>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1 @@
<span class="build-message-element">{{ getBuildMessage(phase) }}</span>

View file

@ -0,0 +1,14 @@
<span class="build-mini-status-element">
<span class="anchor"
href="/repository/{{ build.repository.namespace }}/{{ build.repository.name }}/build/{{ build.id }}"
is-only-text="!canView">
<div>
<span class="build-state-icon" build="build"></span>
<span class="timing">
<i class="fa fa-clock-o"></i><time-ago datetime="build.started"></time-ago>
</span>
<div class="build-description triggered-build-description" build="build"></div>
</div>
</span>
</span>

View file

@ -0,0 +1,6 @@
<div class="build-progress-element">
<div class="progress" ng-class="getPercentage(build) < 100 ? 'active progress-striped' : ''">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ getPercentage(build) }}" aria-valuemin="0" aria-valuemax="100" style="{{ 'width: ' + getPercentage(build) + '%' }}">
</div>
</div>
</div>

View file

@ -0,0 +1,10 @@
<span class="build-state-icon-element" ng-class="build.phase">
<span class="cor-loader-inline" ng-if="isBuilding(build)"></span>
<span ng-if="!isBuilding(build)">
<i class="fa fa-check-circle" ng-if="build.phase == 'complete'"></i>
<i class="fa fa-times-circle" ng-if="build.phase == 'error'"></i>
<i class="fa fa-exclamation-circle" ng-if="build.phase == 'expired'"></i>
<i class="fa fa-exclamation-circle" ng-if="build.phase == 'internalerror'"></i>
<i class="fa fa-minus-circle" ng-if="build.phase == 'cancelled'"></i>
</span>
</span>

View file

@ -0,0 +1,12 @@
<!-- NOTE: DEPRECATED -->
<div id="build-status-container" class="build-status-container">
<div>
<span class="phase-icon" ng-class="build.phase"></span>
<span class="build-message" phase="build.phase"></span>
</div>
<div class="timing">
<i class="fa fa-clock-o"></i>
Started: <time-ago datetime="build.started"></time-ago>
</div>
<div class="build-progress" build="build"></div>
</div>

View file

@ -0,0 +1,108 @@
<div class="convert-user-to-org-element">
<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">&times;</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">
<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>
<!-- 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="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="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>
</div>
<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 -->
</div>

View file

@ -0,0 +1,18 @@
<div class="copy-box-element" ng-class="disabled ? 'disabled' : ''">
<div class="id-container">
<div class="copy-container">
<input id="{{ ::inputId }}" type="text" class="form-control"
value="{{ value }}"
readonly>
<span class="copy-icon"
clipboard-copy="#{{ ::inputId }}"
data-title="Copy to Clipboard" data-container="body" data-placement="bottom" bs-tooltip>
<i class="fa fa-clipboard"></i>
</span>
</div>
</div>
<div class="clipboard-copied-message" style="display: none">
Copied to clipboard
</div>
</div>

View file

@ -0,0 +1,3 @@
<span class="co-checkable-item" ng-mousedown="toggleItem($event)"
ng-class="controller.isChecked(item, controller.checked) ? 'checked': 'not-checked'">
</span>

View file

@ -0,0 +1 @@
<li><a ng-click="selected()"><span ng-transclude/></a></li>

View file

@ -0,0 +1,12 @@
<span class="co-checkable-menu">
<span class="dropdown" style="text-align: left;">
<span class="btn btn-default" data-toggle="dropdown">
<span class="co-checkable-menu-state"
ng-class="getClass(controller.items, controller.checked)"
ng-click="toggleItems($event)">
</span>
<span class="caret"></span>
</span>
<ul class="dropdown-menu" ng-transclude></ul>
</span>
</span>

View file

@ -0,0 +1,31 @@
<div class="cor-confirm-dialog-element">
<div class="modal fade co-dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-show="!working"
data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">{{ dialogTitle }}</h4>
</div>
<div class="modal-body" ng-show="working">
<div class="cor-loader" ng-if="!dialogContext.progress"></div>
<div class="progress-message" ng-if="dialogContext.progressMessage">
{{ dialogContext.progressMessage }}
</div>
<div class="cor-progress-bar" ng-if="dialogContext.progress" progress="dialogContext.progress">
</div>
</div>
<div class="modal-body" ng-show="!working">
<span ng-transclude/>
</div>
<div class="modal-footer" ng-show="!working">
<button type="button" class="btn btn-primary" ng-class="dialogButtonClass || 'btn-primary'"
ng-click="performAction()" ng-disabled="dialogForm && dialogForm.$invalid">
{{ dialogActionTitle }}
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>

View file

@ -0,0 +1,3 @@
<div class="co-floating-bottom-bar">
<span ng-transclude/>
</div>

View file

@ -0,0 +1,5 @@
<div class="co-m-inline-loader co-an-fade-in-out">
<div class="co-m-loader-dot__one"></div>
<div class="co-m-loader-dot__two"></div>
<div class="co-m-loader-dot__three"></div>
</div>

View file

@ -0,0 +1,5 @@
<div class="co-m-loader co-an-fade-in-out">
<div class="co-m-loader-dot__one"></div>
<div class="co-m-loader-dot__two"></div>
<div class="co-m-loader-dot__three"></div>
</div>

View file

@ -0,0 +1,11 @@
<div class="co-log-box-element">
<div id="co-log-viewer" class="co-log-viewer" ng-if="logs">
<div class="quay-spinner" ng-if="!logs"></div>
<div class="co-log-container">
<div id="co-log-content" class="co-log-content">{{ logs }}</div>
</div>
</div>
<div class="co-log-viewer-new-logs" ng-show="hasNewLogs" ng-click="moveToBottom()">
New Logs <i class="fa fa-lg fa-arrow-circle-down"></i>
</div>
</div>

View file

@ -0,0 +1,3 @@
<li>
<a ng-click="optionClick()" ng-transclude></a>
</li>

View file

@ -0,0 +1,6 @@
<span class="co-options-menu">
<div class="dropdown" style="text-align: left;">
<i class="fa fa-gear fa-lg dropdown-toggle" data-toggle="dropdown" data-title="Options" bs-tooltip></i>
<ul class="dropdown-menu pull-right" ng-transclude></ul>
</div>
</span>

View file

@ -0,0 +1,4 @@
<div class="cor-progress-bar-element progress">
<div class="progress-bar" ng-style="{'width': (progress * 100) + '%'}"
aria-valuenow="{{ (progress * 100) }}" aria-valuemin="0" aria-valuemax="100"></div>
</div>

View file

@ -0,0 +1,3 @@
<div class="co-step-bar">
<span class="transclude" ng-transclude/>
</div>

View file

@ -0,0 +1,6 @@
<span ng-class="text ? 'co-step-element text' : 'co-step-element icon'">
<span data-title="{{ title }}" bs-tooltip>
<span class="text" ng-if="text">{{ text }}</span>
<i class="fa fa-lg" ng-if="icon" ng-class="'fa-' + icon"></i>
</span>
</span>

View file

@ -0,0 +1,3 @@
<div class="col-lg-3 col-md-3 col-sm-4">
<span class="co-nav-title-action co-fx-text-shadow" ng-transclude></span>
</div>

View file

@ -0,0 +1,3 @@
<div class="col-lg-6 col-md-6 col-sm-5 col-xs-12">
<h2 class="co-nav-title-content co-fx-text-shadow" ng-transclude></h2>
</div>

View file

@ -0,0 +1 @@
<div class="col-lg-3 col-md-3 col-sm-3 hidden-xs" ng-transclude></div>

View file

@ -0,0 +1,2 @@
<div class="co-nav-title" ng-transclude></div>

View file

@ -0,0 +1,62 @@
<div class="create-entity-dialog-element">
<div class="modal fade co-dialog wider">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="hide()" aria-hidden="true">&times;</button>
<h4 class="modal-title" ng-show="view == 'enterName' || view == 'creating'">
<i class="fa {{ entityIcon }}"></i>
Create {{ entityTitle }}
</h4>
<h4 class="modal-title" ng-show="view == 'setperms' || view == 'settingperms'">
Add permissions for <i class="fa {{ entityIcon }}"></i> {{ entity.name }}
</h4>
</div> <!-- /.model-header -->
<div class="modal-body" ng-show="view == 'creating' || view == 'settingperms'">
<div class="cor-loader"></div>
</div>
<div class="modal-body co-modal-body-scrollable" ng-show="view == 'setperms'">
<div class="set-repo-permissions"
namespace="info.namespace"
entity-name="entity.name"
entity-kind="entityKind"
has-changed-repositories="context.hasChangedRepositories"
has-checked-repositories="context.hasCheckedRepositories"
repositories-loaded="repositoriesLoaded(repositories)"
setting-permissions="settingPermissions()"
permissions-set="permissionsSet(repositories)"
set-permissions="context.setPermissionsCounter"
ng-if="entity"></div>
</div>
<div class="modal-body" ng-show="view == 'enterName'">
<form name="enterNameForm" ng-submit="enterNameForm.$valid && createEntity()">
<label>Provide a name for your new {{ entityTitle }}:</label>
<input type="text" class="form-control" ng-model="entityName" ng-pattern="entityNameRegexObj" required>
<div class="help-text">
Choose a name to inform your teammates
about this {{ entityTitle }}. Must match {{ entityNameRegex }}.
</div>
<div ng-show="allowEntityDescription" style="margin-top: 20px;">
<label>Provide an optional description for your new {{ entityTitle }}:</label>
<input type="text" class="form-control" ng-model="entityDescription" max-length="255">
<div class="help-text">
Enter a description to provide extra information to your teammates about this {{ entityTitle }}.
</div>
</div>
</form>
</div> <!-- /.modal-body -->
<div class="modal-footer" ng-show="view == 'setperms'">
<button type="button" class="btn btn-primary" ng-click="setPermissions()"
ng-show="context.hasCheckedRepositories">Add permissions</button>
<button type="button" class="btn btn-default" ng-click="hide()">Close</button>
</div> <!-- /.footer-body -->
<div class="modal-footer" ng-show="view == 'enterName'">
<button type="button" class="btn btn-primary" ng-click="createEntity()"
ng-disabled="enterNameForm.$invalid">Create {{ entityTitle }}</button>
<button type="button" class="btn btn-default" ng-click="hide()">Cancel</button>
</div> <!-- /.footer-body -->
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,237 @@
<div class="create-external-notification-element">
<form id="createForm" name="createForm" ng-submit="createNotification()">
<!-- Creating spinner -->
<div class="cor-loader" ng-show="status == 'creating'"></div>
<!-- Event -->
<table class="help-table">
<tr>
<td>
<table class="options-table">
<tr><td class="section-header" colspan="2">When this event occurs</td></tr>
<tr>
<td class="span-col" colspan="2">
<div class="dropdown-select" placeholder="'Please select the event'" selected-item="currentEvent.title"
handle-item-selected="handleEventSelected(datum)" clear-value="clearCounter">
<!-- Icons -->
<i class="dropdown-select-icon fa fa-lg" ng-class="currentEvent.icon"></i>
<!-- Dropdown menu -->
<ul class="dropdown-select-menu pull-right" role="menu">
<li ng-repeat="event in events">
<a ng-click="setEvent(event)">
<i class="fa fa-lg" ng-class="event.icon"></i> {{ event.title }}
</a>
</li>
</ul>
</div>
</td>
</tr>
<tr ng-repeat="field in currentEvent.fields">
<td class="name" valign="top">With {{ field.title }} <span ng-if="field.optional">(optional)</span>:</td>
<td class="value">
<div ng-switch on="field.type">
<!-- Enum -->
<select class="form-control" ng-if="field.type == 'enum'"
ng-model="currentEventConfig[field.name]" required>
<option ng-repeat="(key, info) in field.values | orderObjectBy: 'index'" value="{{key}}">{{ info.title }}</option>
</select>
<!-- Regular expression -->
<div ng-switch-when="regex">
<div class="regex-editor" placeholder="{{field.placeholder || '' }}"
binding="currentEventConfig[field.name]" optional="field.optional"></div>
</div>
<!-- Value description -->
<div class="co-alert co-alert-info"
style="margin-top: 6px; margin-bottom: 10px;"
ng-if="field.values[currentEventConfig[field.name]].description">
{{ field.values[currentEventConfig[field.name]].description }}
</div>
<!-- Help text -->
<div class="help-text" ng-if="field.help_text">
{{ field.help_text }}
</div>
</div>
</td>
</tr>
</table>
</td>
<td class="help-col hidden-sm hidden-xs">
<span class="registry-name"></span> supports a number of events around repositories (such as push completed), building (build queued, build completed, etc) and security (vulnerability detected). Some events also allow for filtering, for further granular control of when notifications fire.
</td>
</tr>
</table>
<div class="config-section" ng-show="currentEvent">
<!-- Notification -->
<table class="help-table">
<tr>
<td>
<table class="options-table">
<tr><td class="section-header" colspan="2">Then issue a notification</td></tr>
<tr>
<td class="span-col" colspan="2">
<div class="dropdown-select" placeholder="'Please select a notification method'" selected-item="currentMethod.title"
handle-item-selected="handleMethodSelected(datum)" clear-value="clearCounter">
<!-- Icons -->
<i class="dropdown-select-icon fa fa-lg" ng-class="currentMethod.icon"></i>
<!-- Dropdown menu -->
<ul class="dropdown-select-menu pull-right" role="menu">
<li ng-repeat="method in methods">
<a ng-click="setMethod(method)">
<i class="fa fa-lg" ng-class="method.icon"></i> {{ method.title }}
</a>
</li>
</ul>
</div>
</td>
</tr>
<tr ng-repeat="field in currentMethod.fields">
<td valign="top" class="name">{{ field.title }}:</td>
<td class="value">
<div ng-switch on="field.type">
<!-- Email -->
<span ng-switch-when="email">
<input type="email" class="form-control" ng-model="currentConfig[field.name]" ng-required="!field.optional">
</span>
<!-- URL -->
<input type="url" class="form-control" ng-model="currentConfig[field.name]" ng-switch-when="url" ng-required="!field.optional">
<!-- String -->
<input type="text" class="form-control" ng-model="currentConfig[field.name]" ng-switch-when="string" ng-required="!field.optional">
<!-- Pattern (regex match) -->
<div ng-switch-when="pattern">
<input type="text" class="form-control" ng-model="currentConfig[field.name]"
ng-pattern="getPattern(field)"
placeholder="{{ field.placeholder }}"
ng-name="field.name"
id="{{ field.name }}"
ng-required="!field.optional">
<div class="alert alert-warning" style="margin-top: 10px; margin-bottom: 10px"
ng-if="field.pattern_fail_message && hasRegexMismatch(createForm.$error, field.name)">
<span ng-bind-html="field.pattern_fail_message"></span>
</div>
</div>
<!-- Entity -->
<div class="entity-search" namespace="repository.namespace"
placeholder="''"
current-entity="currentConfig[field.name]"
ng-model="currentConfig[field.name]"
allowed-entities="['user', 'team', 'org']"
ng-switch-when="entity"></div>
<div ng-if="getHelpUrl(field, currentConfig)"
style="margin-top: 10px; margin-bottom: 10px">
See: <a href="{{ getHelpUrl(field, currentConfig) }}" ng-safenewtab>{{ getHelpUrl(field, currentConfig) }}</a>
</div>
<div class="help-text" ng-if="currentMethod.id == 'webhook'"
style="margin-top: 6px; margin-bottom: 0px">
JSON metadata representing the event will be <b>POST</b>ed to the URL. All requests made to TLS-enabled URLs will be signed with the <span class="registry-name"></span> key.
<br><br>
The contents for each event can be found in the user guide:
<a href="http://docs.quay.io/guides/notifications.html#webhook{{ currentEvent.id ? '_' + currentEvent.id : '' }}"
ng-safenewtab>
http://docs.quay.io/guides/notifications.html
</a>
</div>
</div>
<!-- Help text -->
<div class="help-text" ng-if="field.help_text">
{{ field.help_text }}
</div>
</td>
</tr>
</table>
</td>
<td class="help-col hidden-sm hidden-xs">
Once an event has fired, <span class="registry-name"></span> supports a number of notification methods, including various chat systems (Slack, HipChat, etc), notification via e-mail or programatic handling via the firing of a webhook.
</td>
</tr>
</table>
</div>
<div class="config-section" ng-show="currentMethod">
<table class="help-table">
<tr>
<td>
<table class="options-table">
<tr><td class="section-header" colspan="2">With extra configuration</td></tr>
<tr>
<td class="name">Notification title:</td>
<td class="value">
<input class="form-control" type="text" placeholder="Enter an optional title" ng-model="currentTitle">
</td>
</tr>
</table>
</td>
<td class="help-col hidden-sm hidden-xs">
The title for a notification is an optional field for a human-readable title for the notification.
</td>
</tr>
</table>
</div>
<!-- Buttons -->
<div class="button-bar">
<button type="submit" class="btn btn-primary"
ng-disabled="createForm.$invalid || !currentMethod.id || !currentEvent.id || creating">
Create Notification
</button>
</div>
</form>
</div>
<!-- Authorize email dialog -->
<div class="modal" tabindex="-1" role="dialog" id="authorizeEmailModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" ng-click="cancelEmailAuth()">
&times;
</button>
<h4 class="modal-title">E-mail authorization</h4>
</div>
<div class="modal-body" style="padding: 4px; padding-left: 20px;">
<!-- Authorize e-mail view -->
<div ng-if="status == 'authorizing-email-sent'">
An e-mail has been sent to <code>{{ ::currentConfig.email }}</code>. Please click the link contained
in the e-mail.
</div>
<!-- Authorize e-mail view -->
<div ng-if="status == 'unauthorized-email'">
The e-mail address <code>{{ ::currentConfig.email }}</code> has not been authorized to receive
notifications from this repository. Please click "Send Authorization E-mail" below to start
the authorization process.
</div>
</div>
<!-- Auth e-mail button bar -->
<div class="modal-footer" ng-if="status == 'unauthorized-email'">
<button type="button" class="btn btn-success" ng-click="sendAuthEmail()">
Send Authorization E-mail
</button>
<button type="button" class="btn btn-default" ng-click="cancelEmailAuth()" ng-disabled="creating">Cancel</button>
</div>
<!-- Loading -->
<div ng-if="status != 'unauthorized-email'"
class="loading-container">
<span class="cor-loader-inline"></span>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,10 @@
<div class="create-robot-dialog-element">
<div ng-if="info">
<div class="create-entity-dialog" info="info" entity-title="robot account"
entity-kind="robot"
entity-icon="ci-robot" entity-name-regex="{{ ROBOT_PATTERN }}"
allow-entity-description="true"
entity-create-requested="createRobot(name, description, callback)"
entity-create-completed="robotFinished(entity)"></div>
</div>
</div>

View file

@ -0,0 +1,9 @@
<div class="create-team-dialog-element">
<div ng-if="info">
<div class="create-entity-dialog" info="info" entity-title="team"
entity-kind="team"
entity-icon="fa-group" entity-name-regex="{{ TEAM_PATTERN }}"
entity-create-requested="createTeam(name, callback)"
entity-create-completed="teamFinished(entity)"></div>
</div>
</div>

View file

@ -0,0 +1,168 @@
<div class="credentials-dialog-element">
<div class="modal fade co-dialog wider">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body" ng-show="credentials.loading">
<div class="cor-loader"></div>
</div>
<div class="co-tab-modal-body" ng-show="!credentials.loading">
<cor-tab-panel orientation="vertical" cor-cookie-tabs="quay.credentialsTab">
<!-- Tabs -->
<cor-tabs>
<cor-tab tab-active="true" tab-id="cred-secret">
<i class="fa" ng-class="entityIcon"></i> {{ secretTitle }}
</cor-tab>
<cor-tab tab-id="cred-kubernetes">
<i class="fa kubernetes-icon icon"></i> Kubernetes Secret
</cor-tab>
<cor-tab tab-id="cred-rkt">
<i class="fa rocket-icon icon"></i> rkt Configuration
</cor-tab>
<cor-tab tab-id="cred-docker">
<i class="fa docker-icon icon"></i> Docker Login
</cor-tab>
<cor-tab tab-id="cred-docker-config">
<i class="fa docker-icon icon"></i> Docker Configuration
</cor-tab>
<cor-tab tab-id="cred-mesos" quay-show="isDownloadSupported()">
<i class="fa mesos-icon icon"></i> Mesos Credentials
</cor-tab>
</cor-tabs>
<!-- Tab contents -->
<cor-tab-content>
<h3 class="dialog-title-header">
<div class="dialog-title">Credentials for {{ credentials.title || credentials.username }}</div>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
</h3>
<cor-tab-pane id="cred-secret">
<label>Username & {{ secretTitle }}:</label>
<div class="conjoined-box-wrapper">
<div class="copy-box conjoined-box-top" value="credentials.username"></div>
<div class="copy-box conjoined-box-bottom" value="credentials.password"></div>
</div>
<div ng-transclude/>
</cor-tab-pane>
<cor-tab-pane id="cred-kubernetes">
<label>Step 1: Download secret</label>
<div class="action-text">First, download the Kubernetes pull secret for the {{ entityTitle }}:</div>
<ul class="action-bar">
<li><a ng-click="downloadFile(getKubernetesFile(credentials))" ng-if="isDownloadSupported()"><i class="fa fa-download"></i> Download {{ getKubernetesFilename(credentials) }}</li></a>
<li><a ng-click="viewFile(k8s)"><i class="fa fa-code"></i> View {{ getKubernetesFilename(credentials) }}</li></a>
</ul>
<textarea class="form-control viewing-file" ng-if="k8s.viewingFile" readonly>{{ getKubernetesFile(credentials).contents }}</textarea>
<label>Step 2: Submit</label>
<div class="action-text">Second, submit the secret to the cluster using this command:</div>
<div class="copy-box" value="'kubectl create -f ' + getKubernetesFilename(credentials) + ' --namespace=NAMESPACEHERE'"></div>
<label>Step 3: Update Kubernetes configuration</label>
<div class="action-text">
Finally, <a href="http://kubernetes.io/docs/user-guide/images/#specifying-imagepullsecrets-on-a-pod" ng-safenewtab>add a reference to the secret to your Kuberenetes pod config</a> via an <code>imagePullSecrets</code> field. For example:
<pre>
apiVersion: v1
kind: Pod
metadata:
name: somepod
namespace: all
spec:
containers:
- name: web
image: {{ Config.SERVER_HOSTNAME }}/{{ getNamespace(credentials) }}/somerepo
<code style="font-weight: bold;">
imagePullSecrets:
- name: {{ getKubernetesSecretName(credentials) }}</code></pre>
</div>
</cor-tab-pane>
<cor-tab-pane id="cred-mesos">
<label>Step 1: Download credentials bundle</label>
<div class="action-text">First, download the Docker credentials file as a bundle:</div>
<ul class="action-bar">
<li><a ng-click="downloadFile(getMesosFile(credentials))" ng-if="isDownloadSupported()"><i class="fa fa-download"></i> Download {{ getMesosFilename(credentials) }}</li></a>
</ul>
<label>Step 2: Copy credentials bundle</label>
<div class="action-text">
Second, copy the credentials bundle file <strong>{{ getMesosFilename(credentials) }}</strong>
into a location accessible to Mesos:
</div>
<div class="copy-box" value="'cp ' + getMesosFilename(credentials) + ' /etc/'"></div>
<label>Step 3: Update Mesos configuration</label>
<div class="action-text">
Finally, <a href="https://mesosphere.github.io/marathon/docs/native-docker-private-registry.html" ng-safenewtab>add a reference to the bundle to your Mesos config</a> via a <code>uris</code> field. For example:
<pre>
{
"id": "/some/name/or/id",
"cpus": 1,
"mem": 1024,
"instances": 1,
"container": {
"type": "DOCKER",
"docker": {
"image": "{{ Config.SERVER_HOSTNAME }}/{{ getNamespace(credentials) }}/somerepo",
"network": "HOST"
}
},
<code style="font-weight: bold;">
"uris": [
"file:///etc/{{ getMesosFilename(credentials) }}"
]</code>
}</pre>
</div>
</cor-tab-pane>
<cor-tab-pane id="cred-rkt">
<label>Step 1: Download credentials config</label>
<div class="action-text">First, download the rkt credentials file for the {{ entityTitle }}:</div>
<ul class="action-bar">
<li><a ng-click="downloadFile(getRktFile(credentials))" ng-if="isDownloadSupported()"><i class="fa fa-download"></i> Download {{ getRktFilename(credentials) }}</li></a>
<li><a ng-click="viewFile(rkt)"><i class="fa fa-code"></i> View {{ getRktFilename(credentials) }}</li></a>
</ul>
<textarea class="form-control viewing-file" ng-if="rkt.viewingFile" readonly>{{ getRktFile(credentials).contents }}</textarea>
<label>Step 2: Write to disk</label>
<div class="action-text">Second, place the file in the rkt configuration directory:</div>
<div class="copy-box" value="'mv ' + getRktFilename(credentials) + ' /etc/rkt/auth.d/'"></div>
</cor-tab-pane>
<cor-tab-pane id="cred-docker">
<label>Run docker login</label>
<div class="action-text">Enter the following command on the command line:</div>
<div class="copy-box" value="getDockerLogin(credentials)"></div>
</cor-tab-pane>
<cor-tab-pane id="cred-docker-config">
<label>Step 1: Download credentials config</label>
<div class="action-text">First, download the Docker credentials file for the {{ entityTitle }}:</div>
<ul class="action-bar">
<li><a ng-click="downloadFile(getDockerFile(credentials))" ng-if="isDownloadSupported()"><i class="fa fa-download"></i> Download {{ getDockerFilename(credentials) }}</li></a>
<li><a ng-click="viewFile(docker)"><i class="fa fa-code"></i> View {{ getDockerFilename(credentials) }}</li></a>
</ul>
<textarea class="form-control viewing-file" ng-if="docker.viewingFile" readonly>{{ getDockerFile(credentials).contents }}</textarea>
<label>Step 2: Write to disk</label>
<div class="action-text">Second, place the file in the Docker configuration directory. <strong>Note:</strong> This will <strong>overwrite</strong> existing credentials:</div>
<div class="copy-box" value="'mv ' + getDockerFilename(credentials) + ' ~/.docker/config.json'"></div>
</cor-tab-pane>
</cor-tab-content>
</cor-tab-panel>
</div><!-- /.co-tab-modal-body -->
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>

View file

@ -0,0 +1,10 @@
<div ng-switch on="trigger.service">
<!-- Message -->
<div ng-include="triggerTemplate" ng-if="triggerTemplate"></div>
<!-- Credentials -->
<div ng-repeat="credential in trigger.config.credentials">
{{ credential.name }}:
<div class="copy-box" value="credential.value"></div>
</div>
</div>

View file

@ -0,0 +1,3 @@
<span class="datetime-picker-element">
<input class="form-control" type="text" ng-model="selected_datetime"/>
</span>

View file

@ -0,0 +1,35 @@
<div class="delete-namespace-view-element" quay-show="!Features.BILLING || subscriptionStatus != 'loading'">
<table class="co-list-table">
<tr>
<td>Delete {{ namespaceTitle }}:</td>
<td quay-show="!Features.BILLING || subscriptionStatus == 'none'">
<a class="co-modify-link" ng-click="showDeleteNamespace()">Begin deletion</a>
</td>
<td quay-show="Features.BILLING && subscriptionStatus == 'valid'">
<i class="fa fa-exclamation-triangle yellow"></i> You must cancel your billing subscription before this {{ namespaceTitle }} can be deleted.
</td>
</tr>
</table>
<!-- Delete account dialog -->
<div class="cor-confirm-dialog"
dialog-context="deleteNamespaceInfo"
dialog-action="deleteNamespace(info, callback)"
dialog-title="Delete {{ namespaceTitle }}"
dialog-action-title="Delete {{ namespaceTitle }}"
dialog-form="context.deleteform"
dialog-button-class="btn-danger">
<form name="context.deleteform" class="co-single-field-dialog">
<div class="co-alert co-alert-danger">
Deleting an {{ namespaceTitle }} is <strong>non-reversable</strong> and will delete
<strong>all of the {{ namespaceTitle }}'s data</strong> including repositories, created build triggers,
and notifications.
</div>
You must type <code>{{ deleteNamespaceInfo.namespace }}</code> below to confirm deletion is requested:
<input type="text" class="form-control" placeholder="Enter namespace here"
ng-model="deleteNamespaceInfo.verification" ng-pattern="deleteNamespaceInfo.namespace"
required>
</form>
</div>
</div>

View file

@ -0,0 +1,4 @@
<span class="delete-ui-element" ng-click="focus()">
<span class="delete-ui-button" ng-click="performDelete()"><button class="btn btn-danger" type="button">{{ buttonTitleInternal }}</button></span>
<i class="fa fa-times" bs-tooltip="tooltip.title" data-placement="left" data-title="{{ deleteTitle }}"></i>
</span>

View file

@ -0,0 +1,75 @@
<div class="dockerfile-build-dialog-element">
<!-- Modal message dialog -->
<div class="modal fade dockerfilebuildModal">
<div class="co-dialog modal-dialog modal-lg">
<div class="modal-content" ng-show="triggersResource && triggersResource.loading">
<div class="cor-loader"></div>
</div>
<div class="modal-content" ng-show="!triggersResource || !triggersResource.loading">
<div class="modal-header ahead-of-tabs">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"
ng-show="!buildStarting">&times;</button>
<h4 class="modal-title">
Start Repository Build
</h4>
</div>
<ul class="co-top-tab-bar" ng-show="triggers.length > 0">
<li class="co-top-tab" ng-class="viewTriggers ? 'active': ''" ng-click="showTriggers(true)">Invoke Build Trigger</li>
<li class="co-top-tab" ng-class="!viewTriggers ? 'active': ''" ng-click="showTriggers(false)">Upload Dockerfile</li>
</ul>
<div class="modal-body">
<div class="co-alert co-alert-danger" ng-show="errorMessage">
{{ errorMessage }}
</div>
<!-- Upload Dockerfile -->
<div ng-show="!viewTriggers">
<div class="dockerfile-build-form" repository="repository" is-ready="hasDockerfile"
ready-for-build="readyForBuild(startBuild)" reset="viewCounter"></div>
</div>
<!-- Start Build Trigger -->
<div ng-show="viewTriggers">
<p style="padding: 10px;">Manually running a build trigger provides the means for invoking a build trigger as-if
called from the underlying service for the latest commit to a particular branch or tag.</p>
<table class="cor-table">
<thead>
<tr>
<td>Trigger Description</td>
<td>Branches/Tags</td>
<td></td>
</tr>
</thead>
<tbody>
<tr ng-repeat="trigger in triggers">
<td><trigger-description trigger="trigger"></trigger-description></td>
<td>{{ trigger.config.branchtag_regex || 'All' }}</td>
<td>
<a href="javascript:void(0)" ng-click="runTriggerNow(trigger)"
ng-if="trigger.can_invoke">Run Trigger Now</a>
<span ng-if="!trigger.can_invoke"
data-title="You do not have permission to run this trigger" bs-tooltip>
<i class="fa fa-exclamation-triangle"></i> No permission to run
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="startBuild()"
ng-disabled="!hasDockerfile || buildStarting || !startBuildCallback"
ng-show="!viewTriggers">Start Build</button>
<button type="button" class="btn btn-default" data-dismiss="modal"
ng-disabled="buildStarting">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="manual-trigger-build-dialog" repository="repository" counter="startTriggerCounter"
trigger="startTrigger"
build-started="handleBuildStarted(build)"></div>
</div>

View file

@ -0,0 +1,36 @@
<div class="dockerfile-build-form-element">
<div ng-show="state == 'starting-build'" class="starting-build">
<div class="cor-loader-inline"></div>
<div>Please wait while <span class="registry-name" short="true"></span> starts the build</div>
</div>
<div ng-show="state != 'starting-build'">
<div class="file-upload-box"
select-message="Please select a Dockerfile or an archive (.tar.gz or .zip) containing a Dockerfile at the root directory"
files-cleared="handleFilesCleared()"
files-selected="handleFilesSelected(files, callback)"
files-validated="handleFilesValidated(uploadFiles)"
reset="reset"></div>
<div class="robot-permission" ng-show="privateBaseRepository && state != 'uploading-files'">
<div class="help-text">
<p>The selected Dockerfile contains a <code>FROM</code> that refers to private repository <strong>{{ privateBaseRepository }}</strong>.</p>
<p>
A robot account with read access to that repository is required for the build:
</p>
</div>
<div class="entity-search" namespace="repository.namespace"
placeholder="'Select robot account for pulling'"
current-entity="pullEntity"
pull-right="true"
allowed-entities="['robot']"></div>
<div class="co-alert co-alert-danger"
ng-if="currentRobotHasPermission === false">
Robot account <strong>{{ pullEntity.name }}</strong> does not have
read permission on repository <strong>{{ privateBaseRepository }}</strong>.
</div>
<div ng-if="state == 'checking-bot'" style="margin-top: 10px;">
<span class="cor-loader-inline"></span> Checking robot permissions...
</div>
</div>
</div>
</div>

View file

@ -0,0 +1 @@
<span class="donut-chart-element" ng-style="{'line-height': size + 'px'}"></span>

View file

@ -0,0 +1,22 @@
<div class="dropdown-select-element dropdown-select-direct-element" ng-class="selectedItem ? 'has-item' : ''">
<div class="current-item">
<i class="none-icon fa fa-lg" ng-class="noneIcon" ng-if="noneIcon"></i>
<i class="fa fa-lg dropdown-select-direct-icon" ng-repeat="item in items"
ng-class="iconMap[item[iconKey]]"
ng-show="selectedItem[valueKey] == item[valueKey]"></i>
<input type="text" class="lookahead-input form-control" placeholder="{{ placeholder }}"></input>
</div>
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu scrollable-menu" role="menu">
<li ng-repeat="item in items">
<a ng-click="setItem(item)">
<i class="fa" ng-class="iconMap[item[iconKey]]"></i>{{ item[titleKey] }}</a>
</li>
</ul>
</div>
</div>

View file

@ -0,0 +1 @@
<span></span>

View file

@ -0,0 +1 @@
<ul class="dropdown-menu" ng-transclude></ul>

View file

@ -0,0 +1,14 @@
<div class="dropdown-select-element" ng-class="selectedItem ? 'has-item' : ''">
<div class="current-item">
<div class="dropdown-select-icon-transclude"></div>
<input type="text" class="lookahead-input form-control" placeholder="{{ placeholder }}"
ng-readonly="!allowCustomInput"></input>
</div>
<div class="dropdown" ng-show="!hideDropdown">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">
<span class="caret"></span>
</button>
<div class="dropdown-select-menu-transclude"></div>
</div>
<div class="transcluded" ng-transclude>
</div>

View file

@ -0,0 +1,46 @@
<span class="entity-reference-element">
<span class="new-entity-reference" data-title="{{ getTitle(entity) }} {{ entity.name }}" bs-tooltip>
<span ng-switch on="entity.kind">
<!-- Team -->
<span ng-switch-when="team">
<span class="avatar" data="entity.avatar" size="avatarSize || 16"></span>
<span class="entity-name anchor"
href="/organization/{{ namespace }}/teams/{{ entity.name }}"
is-only-text="!getIsAdmin(namespace)">
{{ entity.name }}
</span>
</span>
<!-- Organization -->
<span ng-switch-when="org">
<span class="avatar" size="avatarSize || 16" data="entity.avatar"></span>
<span class="entity-name anchor" href="/organization/{{ entity.name }}"
is-only-text="!getIsAdmin(entity.name)">
{{ entity.name }}
</span>
</span>
<!-- User or Robot -->
<span ng-switch-when="user">
<!-- User -->
<span ng-if="!entity.is_robot">
<span class="avatar" size="avatarSize || 16" data="entity.avatar"></span>
<a class="entity-name" href="/user/{{ entity.name }}">{{ entity.name }}</a>
</span>
<!-- Robot -->
<span ng-if="entity.is_robot">
<i class="fa ci-robot fa-lg"></i>
<a class="entity-name" ng-if="getIsAdmin(getPrefix(entity.name))" ng-click="showRobotCredentials()">
<span class="prefix">{{ getPrefix(entity.name) }}+</span><span class="robot-shortname">{{ getShortenedName(entity.name) }}</span>
</a>
<span class="entity-name" ng-if="!getIsAdmin(getPrefix(entity.name))">
<span class="prefix">{{ getPrefix(entity.name) }}+</span><span class="robot-shortname">{{ getShortenedName(entity.name) }}</span>
</span>
</span>
</span>
</span>
</span>
<div class="robot-credentials-dialog" info="robotToShow" ng-if="robotToShow"></div>
</span>

View file

@ -0,0 +1,77 @@
<span class="entity-search-element" ng-class="autoClear ? '' : 'persistent'"><input class="entity-search-control form-control">
<span class="entity-reference block-reference" ng-show="!autoClear && currentEntityInternal" entity="currentEntityInternal"></span>
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="entityDropdownMenu" data-toggle="dropdown"
ng-click="lazyLoad()">
<span class="caret"></span>
</button>
<ul class="dropdown-menu entity-menu" ng-class="pullRight == 'true' ? 'pull-right': ''" role="menu"
aria-labelledby="entityDropdownMenu">
<li ng-show="requiresLazyLoading" style="padding: 10px"><div class="cor-loader"></div></li>
<li role="presentation" class="dropdown-header" ng-show="!requiresLazyLoading && !page.robots && !isAdmin && !teams">
You do not have permission to manage teams and robots for this organization
</li>
<li role="presentation" ng-show="includeTeams && isOrganization && !requiresLazyLoading && isAdmin && !inReadOnlyMode">
<a role="menuitem" class="new-action" tabindex="-1" ng-click="askCreateTeam()">
<i class="fa fa-group"></i> Create team
</a>
</li>
<li role="presentation" ng-show="includeRobots && !requiresLazyLoading && isAdmin && !inReadOnlyMode">
<a role="menuitem" class="new-action" tabindex="-1" ng-click="askCreateRobot()">
<i class="fa ci-robot"></i>
Create robot account
</a>
</li>
<li role="presentation" class="divider" ng-show="!requiresLazyLoading && page.robots && isAdmin && !inReadOnlyMode"></li>
<li role="presentation" class="dropdown-header"
ng-show="!requiresLazyLoading && !teams.length && !page.robots.length && !((includeTeams && isOrganization && isAdmin) || (includeRobots && isAdmin))">
<span ng-if="includeRobots && includeTeams && isOrganization">
No robot accounts or teams found
</span>
<span ng-if="!includeRobots && includeTeams && isOrganization">
No teams found
</span>
<span ng-if="includeRobots && !includeTeams && isOrganization">
No robot accounts found
</span>
<span ng-if="!includeRobots && !includeTeams && isOrganization">
Robot accounts and teams are not permitted
</span>
<span ng-if="includeRobots && !isOrganization">
No robot accounts found
</span>
<span ng-if="!includeRobots && !isOrganization">
Robot accounts are not permitted
</span>
</li>
<li role="presentation" class="dropdown-header" ng-show="!requiresLazyLoading && teams">Teams</li>
<li class="menuitem" role="presentation" ng-repeat="team in teams | orderBy: 'name'" ng-show="!requiresLazyLoading"
ng-click="setEntity(team.name, 'team', false, team.avatar)">
<a role="menuitem" tabindex="-1">
<span class="avatar" data="team.avatar" size="16"></span> <span>{{ team.name }}</span>
</a>
</li>
<li role="presentation" class="divider" ng-show="!requiresLazyLoading && teams && (isAdmin || page.robots)"></li>
<li role="presentation" class="dropdown-header" ng-show="!requiresLazyLoading && page.robots">Robot Accounts</li>
<li class="menuitem" role="presentation" ng-repeat="robot in page.robots | orderBy:'name'" ng-show="!requiresLazyLoading">
<a role="menuitem" tabindex="-1" ng-click="setEntity(robot.name, 'user', true)">
<i class="fa ci-robot"></i> <span>{{ robot.name }}</span>
</a>
</li>
</ul>
</div>
<div class="create-team-dialog" info="createTeamInfo"
team-created="handleTeamCreated(team)"></div>
<div class="create-robot-dialog" info="createRobotInfo"
robot-created="handleRobotCreated(robot)"></div>
</span>

View file

@ -0,0 +1,13 @@
<span class="external-login-button-element">
<a ng-class="isLink ? '' : 'btn btn-primary btn-block'"
ng-click="startSignin()" style="margin-bottom: 10px"
ng-disabled="signingIn">
<span class="icon-image-view" value="{{ provider.icon }}"></span>
<span class="login-text" ng-if="action != 'attach'" style="vertical-align: middle">
<span class="prefix">Sign in with&nbsp;</span><span class="suffix">{{ provider.title }}</span>
</span>
<span class="login-text" ng-if="action == 'attach'" style="vertical-align: middle">
Attach to {{ provider.title }}
</span>
</a>
</span>

View file

@ -0,0 +1,41 @@
<div class="external-logins-manager-element">
<div class="manager-header" header-title="External Logins"></div>
<div class="section-description-header">
The external logins panel lists all supported external login providers, which can be used for one-click OAuth-based login to <span class="registry-name"></span>. Accounts can be attached or detached by clicking the associated button below.
</div>
<table class="co-table">
<thead>
<td>Provider</td>
<td>Account Status</td>
<td quay-show="Features.DIRECT_LOGIN">Attach/Detach</td>
</thead>
<tr class="external-auth-provider" ng-repeat="provider in EXTERNAL_LOGINS">
<td class="external-auth-provider-title">
<span class="icon-image-view" value="{{ provider.icon }}"></span>
{{ provider.title }}
</td>
<td>
<span ng-if="externalLoginInfo[provider.id]">
Attached to {{ provider.title }} account
<b ng-if="externalLoginInfo[provider.id].metadata.service_username">
{{ externalLoginInfo[provider.id].metadata.service_username }}
</b>
</span>
<span class="empty" ng-if="!externalLoginInfo[provider.id]">
Not attached to {{ provider.title }}
</span>
</td>
<td>
<span class="external-login-button" provider="provider" action="attach" is-link="true"
ng-if="!externalLoginInfo[provider.id]"></span>
<a ng-if="externalLoginInfo[provider.id] && Features.DIRECT_LOGIN"
ng-click="detachExternalLogin(provider.id)">Detach Account</a>
</td>
</tr>
</table>
</div>

View file

@ -0,0 +1,62 @@
<div class="external-notification-view-element">
<div class="side-controls">
<div class="dropdown" style="display: inline-block">
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-cog"></i>
<b class="caret"></b>
</button>
<ul class="dropdown-menu dropdown-menu-right pull-right">
<li ng-if="methodInfo.id == 'webhook'">
<a href="http://docs.quay.io/guides/notifications.html#webhook_{{ eventInfo.id }}"
ng-safenewtab>
<i class="fa fa-book"></i>
Webhook Documentation</a>
</li>
<li class="divider" ng-if="methodInfo.id == 'webhook'"></li>
<li><a ng-click="testNotification()">
<i class="fa fa-send"></i>
Issue Test Notification</a>
</li>
<li><a ng-click="deleteNotification()">
<i class="fa fa-times"></i>
Delete</a>
</li>
</ul>
</div>
</div>
<div class="view-row">
<span class="flow-text">On</span>
<span class="notification-event">
<i class="fa fa-lg" ng-class="eventInfo.icon"></i>
{{ eventInfo.title }}
</span>
</div>
<div class="view-row">
<span class="flow-text">Issue A</span>
<span class="notification-method">
<i class="fa fa-lg" ng-class="methodInfo.icon"></i>
{{ methodInfo.title }}
</span>
</div>
<div class="view-row">
<span ng-switch on="methodInfo.id">
<span ng-switch-when="email">
<span class="flow-text">To</span>
<code>{{ config.email }}</code>
</span>
<span ng-switch-when="webhook">
<span class="flow-text">To</span>
<code>{{ config.url }}</code>
</span>
<span ng-switch-when="quay_notification">
<span class="flow-text">To</span>
<span class="entity-reference" entity="config.target" namespace="repository.namespace"></span>
</span>
</span>
</div>
</div>

View file

@ -0,0 +1,5 @@
<div class="feedback-bar-element" ng-class="feedback.kind" ng-show="viewCounter">
<div class="co-alert" ng-class="'co-alert-' + feedback.kind">
<span class="feedback-text" ng-bind-html="formattedMessage"></span>
</div>
</div>

View file

@ -0,0 +1,84 @@
<div class="fetch-tag-dialog-element">
<!-- Modal message dialog -->
<div class="co-dialog modal fade" id="fetchTagDialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">
Fetch Tag: <i class="fa fa-tag" style="margin-left: 6px; margin-right: 4px"></i> {{ currentTag.name }}
</h4>
</div>
<div class="modal-body">
<table class="modal-table">
<tr>
<td class="first-col">Image Format:</td>
<td>
<div class="dropdown-select"
placeholder="'(Select Image Format)'"
selected-item="currentFormat.title"
handle-item-selected="handleFormatSelected(datum)"
clear-value="clearCounter">
<!-- Icons -->
<i class="dropdown-select-icon fa fa-lg" ng-class="currentFormat.icon"></i>
<!-- Dropdown menu -->
<ul class="dropdown-select-menu pull-right" role="menu">
<li ng-repeat="format in formats">
<a ng-click="setFormat(format)">
<i class="fa fa-lg" ng-class="format.icon"></i> {{ format.title }}
</a>
</li>
</ul>
</div>
</td>
</tr>
<tr ng-show="currentFormat.require_creds">
<td class="first-col">Pull Credentials:</td>
<td>
<div class="entity-search" namespace="repository.namespace"
for-repository="repository"
placeholder="'Choose Pull Credentials'"
allowed-entities="['robot']"
clear-value="clearCounter"
auto-clear="false"
current-entity="currentEntity"
ng-show="currentFormat.has_creds"></div>
<div class="co-alert co-alert-warning" ng-show="!currentFormat.has_creds"
style="margin-top: 4px; margin-bottom: 0px">
Fetching a {{ currentFormat.title }} requires a robot account. You must therefore
have admin access on namespace <strong>{{ repository.namespace }}</strong> to setup
this fetch.
</div>
</td>
</tr>
</table>
<div class="cor-loader-inline" ng-if="currentEntity && !currentRobot"></div>
<div class="co-alert co-alert-warning"
ng-if="currentRobotHasPermission === false">
Warning: Robot account <strong>{{ currentRobot.name }}</strong> does not have
read permission on this repository, so the command below will fail with an authorization error.
</div>
<div ng-if="getCommand(currentFormat, currentRobot)">
Command:
<pre id="command-data" class="command">{{ getCommand(currentFormat, currentRobot) }}</pre>
</div>
</div>
<div class="modal-footer">
<div class="clipboard-copied-message" style="display: none">
Copied
</div>
<button type="button" class="btn btn-primary"
clipboard-copy="#command-data"
ng-show="getCommand(currentFormat, currentRobot)">Copy Command</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>

View file

@ -0,0 +1,46 @@
<div class="file-upload-box-element">
<div class="file-input-container">
<div ng-show="state != 'uploading'">
<form id="file-drop-form-{{ boxId }}">
<input id="file-drop-{{ boxId }}" name="file-drop-{{ boxId }}" class="file-drop"
type="file" files-changed="handleFilesChanged(files)"
accept="{{ getAccepts(extensions) }}">
<label for="file-drop-{{ boxId }}" ng-class="state">
<span class="chosen-file">
<span ng-if="selectedFiles.length">
{{ selectedFiles[0].name }}
<span ng-if="selectedFiles.length > 1">
and {{ selectedFiles.length - 1 }} others...
</span>
</span>
</span><span class="choose-button">
<span>Select file</span>
</span>
</label>
</form>
</div>
<div class="cor-loader-line" ng-if="state == 'checking'"></div>
<div class="status-message" ng-if="state == 'uploading'">
<div class="progress progress-striped active">
<div class="progress-bar" role="progressbar"
aria-valuenow="{{ uploadProgress }}" aria-valuemin="0" aria-valuemax="100"
style="{{ 'width: ' + uploadProgress + '%' }}">
</div>
</div>
Uploading file {{ currentlyUploadingFile.name }}...
</div>
<div class="select-message" ng-if="state == 'clear'">{{ selectMessage }}</div>
<div class="status-message error-message" ng-if="state == 'error'">
<i class="fa fa-times-circle"></i>
{{ message }}
</div>
<div class="status-message okay-message" ng-if="state == 'okay'">
<i class="fa fa-check-circle"></i>
{{ message }}
</div>
</div>
</div>

View file

@ -0,0 +1,6 @@
<div class="filter-box-element" ng-show="collection.length">
<span class="filter-message" ng-if="filterModel">
Showing {{ (collection|filter:filterModel).length }} of {{ collection.length }} {{ filterName }}
</span>
<input class="form-control" type="text" ng-model="filterModel" placeholder="Filter {{ filterName }}...">
</div>

View file

@ -0,0 +1,3 @@
<span class="filter-control-element" ng-class="filter == value ? 'selected': 'not-selected'">
<a ng-click="setFilter()"><span ng-transclude/></a>
</span>

View file

@ -0,0 +1,104 @@
<!-- Messages tab -->
<div class="global-message-tab-element">
<div class="cor-loader" ng-show="!messages"></div>
<div ng-show="messages">
<div class="manager-header" header-title="Messages">
<button class="create-button btn btn-primary" ng-click="showCreateMessage()"
ng-show="!inReadOnlyMode">
<i class="fa fa-plus" style="margin-right: 6px;"></i>Create Message
</button>
</div>
<table class="cor-table">
<thead>
<td>Message</td>
<td>Severity</td>
<td class="options-cols"></td>
</thead>
<tr ng-repeat="message in messages" class="user-row">
<td class="message-content">
<span ng-switch on="message.media_type">
<span ng-switch-when="text/markdown">
<markdown-view content="message.content"></markdown-view>
</span>
<span ng-switch-default>{{ message.content }}</span>
</span>
</td>
<td class="message-severity" ng-class="message.severity">
<span ng-switch on="message.severity">
<i class="fa fa-exclamation-triangle" ng-switch-when="warning"></i>
<i class="fa ci-stop" ng-switch-when="error"></i>
<i class="fa fa-info-circle" ng-switch-default></i>
</span>
{{ message.severity }}
</td>
<td class="options-col">
<span class="cor-options-menu" ng-show="!inReadOnlyMode">
<span class="cor-option" option-click="showDeleteMessage(message.uuid)">
<i class="fa fa-times"></i> Delete Message
</span>
</span>
</td>
</tr>
</table>
</div><!-- Messages tab -->
<!-- Modal delete message dialog -->
<div class="co-dialog modal fade" id="confirmDeleteMessageModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Delete Message?</h4>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" ng-click="deleteMessage(messageToDelete)">Delete Message</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal create message dialog -->
<div class="co-dialog modal fade" id="createMessageModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Create new message</h4>
</div>
<form name="createMessageForm" ng-submit="createNewMessage()">
<div class="modal-body" ng-show="creatingMessage">
<div class="cor-loader"></div>
</div>
<div class="modal-body" ng-show="!creatingMessage && !createdMessage">
<div class="form-group">
<label>Severity</label>
<select class="form-control" ng-model="newMessage.severity">
<option value="info">Normal (Info)</option>
<option value="warning">Warning</option>
<option value="error">Error</option>
</select>
<label>Message</label>
<markdown-input content="newMessage.content"
can-write="true"
(content-changed)="updateMessage($event.content)"
field-title="message"></markdown-input>
</div>
</div>
<div class="modal-footer" ng-show="createdMessage">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
<div class="modal-footer" ng-show="!creatingMessage && !createdMessage">
<button class="btn btn-primary" type="submit" ng-disabled="!createMessageForm.$valid">
Create Message
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</form>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>

View file

@ -0,0 +1,155 @@
<span class="header-bar-parent">
<div class="header-bar-element">
<div class="header-bar-content">
<!-- Quay -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
&equiv;
</button>
<a class="navbar-brand" ng-href="{{ user.anonymous ? '/' : '/repository/' }}">
<span id="quay-logo" ng-style="{'background-image': 'url(' + getEnterpriseLogo() + ')'}"></span>
</a>
</div>
<!-- Collapsable stuff -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<!-- Not signed in -->
<ul class="nav navbar-nav navbar-links" ng-if="user.anonymous">
<li ng-if="searchingAllowed"><a ng-href="/search" quay-section="search">Explore</a></li>
<li><a ng-href="/tutorial/" quay-section="tutorial" ng-if="!inReadOnlyMode">Tutorial</a></li>
<li quay-require="['BILLING']"><a ng-href="/plans/" quay-section="plans">Pricing</a></li>
</ul>
<!-- Signed in -->
<ul class="nav navbar-nav navbar-links" ng-if="!user.anonymous">
<li ng-if="searchingAllowed"><a ng-href="/search" quay-section="search">Explore</a></li>
<li quay-require="['APP_REGISTRY']"><a ng-href="/application/" quay-section="application">Applications</a></li>
<li><a ng-href="/repository/" quay-section="repository">Repositories</a></li>
<li><a ng-href="/tutorial/" quay-section="tutorial" ng-if="!inReadOnlyMode">Tutorial</a></li>
</ul>
<!-- Phone -->
<ul class="nav navbar-nav navbar-right visible-xs" ng-switch on="user.anonymous">
<li ng-switch-when="false">
<a href="/user/{{ user.username }}?tab=settings" class="user-view">
<span class="avatar" size="32" data="user.avatar"></span>
{{ user.username }}
</a>
<a ng-click="signout()">Sign out all sessions</a>
</li>
<li ng-switch-default>
<a class="user-view" href="/signin/" ng-if="!externalSigninUrl">Sign in</a>
<a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a>
</li>
</ul>
<!-- Normal -->
<ul class="nav navbar-nav navbar-right hidden-xs" ng-switch on="user.anonymous">
<li>
<span class="navbar-left user-tools"
ng-class="{'navbar-anon': user.anonymous, 'navbar-signedin': !user.anonymous}">
<search-box ng-if="searchingAllowed"></search-box>
</span>
</li>
<li>
<span class="navbar-left user-tools with-menu hidden-sm" ng-show="!user.anonymous && !inReadOnlyMode">
<span class="dropdown">
<a class="dropdown-toggle new-menu" data-toggle="dropdown">
<i class="fa fa-plus user-tool"
data-placement="bottom" data-title="Create New..." data-trigger="hover click" bs-tooltip></i>
<b class="caret"></b>
</a>
<ul class="dropdown-menu context-dropdown">
<li>
<a href="/organizations/new">
<span class="avatar" size="16" data="{'name': '+', color: '#ccc'}"></span>
New Organization
</a>
</li>
<li>
<a href="/new{{ getNamespace(currentPageContext) ? '?namespace=' + getNamespace(currentPageContext) : '' }}">
<i class="fa fa-hdd-o"></i> New Repository
</a>
</li>
<li role="presentation" class="divider" ng-if="getNamespace(currentPageContext) && canAdmin(getNamespace(currentPageContext))"></li>
<li role="presentation" class="dropdown-header"
ng-if="getNamespace(currentPageContext) && canAdmin(getNamespace(currentPageContext))">
Namespace {{ getNamespace(currentPageContext) }}
</li>
<li ng-if="isOrganization(getNamespace(currentPageContext)) && canAdmin(getNamespace(currentPageContext))">
<a ng-click="askCreateTeam(currentPageContext)">
<i class="fa fa-group"></i> New Team
</a>
</li>
<li ng-if="canAdmin(getNamespace(currentPageContext))">
<a ng-click="askCreateRobot(currentPageContext)">
<i class="fa ci-robot"></i> New Robot Account
</a>
</li>
<li role="presentation" class="divider" ng-if="currentPageContext.repository && currentPageContext.repository.can_write && !currentPageContext.repository.tag_operations_disabled && Features.BUILD_SUPPORT"></li>
<li role="presentation" class="dropdown-header"
ng-if="currentPageContext.repository && currentPageContext.repository.can_write &&
!currentPageContext.repository.tag_operations_disabled && Features.BUILD_SUPPORT">
Repository {{ currentPageContext.repository.namespace }}/{{ currentPageContext.repository.name }}
</li>
<li ng-if="currentPageContext.repository && currentPageContext.repository.can_write &&
!currentPageContext.repository.tag_operations_disabled && Features.BUILD_SUPPORT">
<a ng-click="startBuild()">
<i class="fa fa-tasks"></i> New Dockerfile Build
</a>
</li>
</ul>
</span>
</span>
</li>
<li>
<span class="navbar-left user-tools hidden-sm" ng-show="!user.anonymous">
<a data-template="/static/directives/notification-bar.html"
data-container="body" data-animation="am-slide-right" bs-aside>
<i class="fa fa-bell user-tool"
data-placement="bottom" data-title="Notifications" bs-tooltip></i>
<span class="notifications-bubble"></span>
</a>
</span>
</li>
<li class="dropdown" ng-switch-when="false">
<a class="dropdown-toggle user-dropdown user-view" data-toggle="dropdown">
<span class="avatar" size="32" data="user.avatar"></span>
{{ user.username }}
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li>
<a href="/user/{{ user.username }}?tab=settings">
Account Settings
</a>
</li>
<li ng-if="user.super_user"><a href="/superuser/"><strong>Super User Admin Panel</strong></a></li>
<li ng-if="!inReadOnlyMode"><a ng-click="signout()">Sign out all sessions</a></li>
</ul>
</li>
<li ng-switch-default>
<a class="user-view" href="/signin/" ng-if="!externalSigninUrl">Sign in</a>
<a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div>
<div class="create-robot-dialog" info="createRobotInfo"
robot-created="handleRobotCreated(robot, currentPageContext)">
</div>
<div class="create-team-dialog" info="createTeamInfo"
team-created="handleTeamCreated(team, currentPageContext)">
</div>
<div class="dockerfile-build-dialog"
show-now="showBuildDialogCounter"
repository="currentPageContext.repository"
build-started="handleBuildStarted(build, currentPageContext)">
</div>
</div>
</span>

View file

@ -0,0 +1 @@
<div class="heatmap-element"></div>

View file

@ -0,0 +1,4 @@
<span class="icon-image-view-element">
<img ng-src="{{ value }}" ng-if="value.indexOf('http') == 0">
<i class="fa" ng-class="value" ng-if="value.indexOf('http') < 0"></i>
</span>

View file

@ -0,0 +1,9 @@
<div class="interval-input-element">
<input class="form-control"
ng-model="vm.quantity"
ng-change="vm.updateSeconds()"></input>
<select class="form-control"
ng-options="period.label for period in vm.periods"
ng-model="vm.selectedPeriod"
ng-change="vm.updateSeconds()"></select>
</div>

View file

@ -0,0 +1,12 @@
<div class="label-input-element">
<tags-input class="quay-labels"
ng-model="tags"
display-property="keyValue"
placeholder="git-sha=123456ab"
add-on-paste="true"
add-on-comma="false"
spellcheck="false"
replace-spaces-with-dashes="false"
allowed-tags-pattern="^[0-9A-Za-z/\-_.]+=.+$"
enable-editing-last-tag="true"></tags-input>
</div>

View file

@ -0,0 +1,10 @@
<div class="label-list-element">
<div class="label-view"
ng-repeat="label in labels"
expand="{{expand}}"
label="label">
</div>
<div class="empty-list" ng-if="!labels.length">
No labels found
</div>
</div>

View file

@ -0,0 +1,8 @@
<a class="label-view-element" ng-click="viewLabelValue()">
<span class="kind">{{ getKind(label) }}</span>
<span class="label-value">
<span class="key">{{ label.key }}</span>
<span class="equals">=</span>
<span class="value">{{ label.value }}</span>
</span>
</a>

View file

@ -0,0 +1,8 @@
<div class="loading-status-element">
<div ng-show="hasError && !loading">
<span ng-transclude></span>
</div>
<div ng-show="loading">
Loading...
</div>
</div>

View file

@ -0,0 +1,7 @@
<span class="location-view-element" data-title="{{ getLocationTooltip(location, locationPing) }}" data-html="true" bs-tooltip>
<span class="flag" ng-class="locationPing == -1 ? 'error' : ''">
<img ng-src="{{ '/static/img/flags/' + getLocationImage(location) }}">
</span>
<span class="strength-indicator" value="1000 - (locationPing || 0)" maximum="1000"></span>
</span>

View file

@ -0,0 +1,145 @@
<div class="logs-view-element">
<div class="co-alert co-alert-info" quay-show="Features.DISABLE_PULL_LOGS_FOR_FREE_NAMESPACES && (repository.is_free_account || user.is_free_account || organization.is_free_account)">
To facilitate coming changes in the Quay.io service, pull statistics will not currently be
collected or rendered on accounts on an open source plan.
</div>
<div class="manager-header" header-title="Usage Logs">
<span id="logs-range" class="mini">
<span class="date-line">
<span class="date-line-caption">From</span>
<input type="text" class="logs-date-picker input-sm" name="start"
ng-model="options.logStartDate" data-min-date="{{ options.monthAgo }}"
ng-readonly="loading"
data-max-date="{{ options.logEndDate }}"
bs-datepicker>
</span>
<span class="date-line">
<span class="date-line-caption add-on">to</span>
<input type="text" class="logs-date-picker input-sm" name="end"
ng-model="options.logEndDate" data-min-date="{{ options.logStartDate }}"
ng-readonly="loading"
data-max-date="{{ options.now }}"
data-placement="bottom-right"
bs-datepicker>
</span>
</span>
<span class="hidden-xs right">
<i class="fa fa-bar-chart-o toggle-icon" ng-class="chartVisible ? 'active' : ''"
ng-click="toggleChart()" data-title="Toggle Chart" bs-tooltip="tooltip.title"
quay-show="Features.AGGREGATED_LOG_COUNT_RETRIEVAL"></i>
<button class="btn btn-default download-btn" ng-click="showExportLogs()"
ng-if="(user || organization || repository) && Features.LOG_EXPORT && !inReadOnlyMode"><i class="fa fa-download"></i>Export Logs</button>
</span>
</div>
<div>
<div id="bar-chart" style="width: 800px; height: 500px;"
quay-show="chartVisible && Features.AGGREGATED_LOG_COUNT_RETRIEVAL">
<svg style="width: 800px; height: 500px;"></svg>
<div class="cor-loader" ng-if="chartLoading"></div>
</div>
<div class="hidden-xs side-controls">
<div class="result-count">
Showing {{(logs | visibleLogFilter:kindsAllowed | filter:search).length}} matching logs
</div>
<div class="filter-input">
<input id="log-filter" class="form-control" placeholder="Filter Logs" type="text" ng-model="search.$">
</div>
</div>
<div class="table-container">
<table class="cor-table">
<thead>
<td>Description</td>
<td ng-if="allLogs == 'true'">Namespace</td>
<td ng-if="!repository">Repository</td>
<td style="min-width: 226px">Date/Time</td>
<td>Performing User/Token/App</td>
<td>IP Address</td>
</thead>
<tr class="log" ng-repeat="log in (logs | visibleLogFilter:kindsAllowed | filter:search)"
bindonce>
<td style="width: 100%;">
<i class="arrow fa"
ng-class="{'fa-chevron-right': !log._expanded, 'fa-chevron-down': log._expanded}"
ng-click="toggleExpanded(log)"></i>
<span class="circle" style="{{ 'background: ' + getColor(log.kind, chart) }}"></span>
<span class="log-description" ng-bind-html="getDescription(log, log._expanded)"></span>
</td>
<td ng-if="allLogs == 'true'">
<span ng-if="log.namespace">
<span class="entity-reference" entity="log.namespace" namespace="log.namespace.name"></span>
</span>
</td>
<td ng-if="!repository">
<span ng-if="log.metadata.namespace && log.metadata.repo">
<a href="/repository/{{ log.metadata.namespace }}/{{ log.metadata.repo }}">{{ log.metadata.repo }}</a>
</span>
</td>
<td class="log-datetime"><time-display datetime="log.datetime"></time-display></td>
<td>
<span class="log-performer" bo-if="log.metadata.oauth_token_application">
<div>
<span class="application-reference"
data-title="log.metadata.oauth_token_application"
client-id="log.metadata.oauth_token_application_id"></span>
</div>
<div style="text-align: center; font-size: 12px; color: #aaa; padding: 4px;">on behalf of</div>
<div>
<span class="entity-reference" entity="log.performer" namespace="organization.name"></span>
</div>
</span>
<span class="log-performer" bo-if="!log.metadata.oauth_token_application && log.performer">
<span class="entity-reference" entity="log.performer" namespace="organization.name"></span>
</span>
<span class="log-performer" bo-if="!log.performer && log.metadata.token">
<i class="fa fa-key"></i>
<span bo-text="log.metadata.token"></span>
</span>
<span bo-if="!log.performer && !log.metadata.token">
(anonymous)
</span>
</td>
<td>
<span bo-if="log.ip || log.metadata._ip"><span bo-text="log.ip || log.metadata._ip"></span></span>
<span class="empty" bo-if="!log.ip && !log.metadata._ip">(No data)</span>
</td>
</tr>
</table>
<div style="text-align: right; margin-top: 10px; position: relative;">
<button class="btn btn-default" ng-click="nextPage()" ng-show="!loading && hasAdditional">Load More Logs</button>
<div style="position: relative;" ng-show="loading">
Checking for additional logs...
<div class="cor-loader"></div>
</div>
</div>
</div>
</div>
<!-- Modal Dialog -->
<div class="cor-confirm-dialog"
dialog-context="exportLogsInfo"
dialog-action="exportLogs(exportLogsInfo, callback)"
dialog-title="Export Usage Logs"
dialog-action-title="Start Logs Export"
dialog-form="context.exportform">
<form name="context.exportform">
<div style="margin-bottom: 14px;">
Enter an e-mail address or callback URL (must start with <code>http://</code> or <code>https://</code>)
at which to receive the exported logs once they have been fully processed:
</div>
<input class="form-control" type="text" ng-model="exportLogsInfo.urlOrEmail"
placeholder="E-mail address or callback URL"
ng-pattern="'(http(s)?:.+)|.+@.+'">
<div class="help-text">
Note: The export process can take <strong>up to an hour</strong> to process if there are many logs. As well,
only a <strong>single</strong> export process can run at a time for each namespace. Additional export requests will be
queued.
</div>
</form>
</div>
</div>

View file

@ -0,0 +1,236 @@
<div class="manage-users-tab-element">
<div class="cor-loader" ng-show="!users"></div>
<div class="alert alert-error" ng-show="usersError">
{{ usersError }}
</div>
<div ng-show="users">
<div class="manager-header" header-title="Users">
<button class="create-button btn btn-primary" ng-click="showCreateUser()"
quay-show="Config.AUTHENTICATION_TYPE == 'Database' && !inReadOnlyMode">
<i class="fa fa-plus" style="margin-right: 6px;"></i>Create User
</button>
<span class="co-alert co-alert-info" quay-show="Config.AUTHENTICATION_TYPE != 'Database' && Config.AUTHENTICATION_TYPE != 'AppToken'">
Note: <span class="registry-name"></span> is configured to use external authentication, so users can only be created in that system
</span>
</div>
<div class="co-top-bar">
<span class="co-filter-box">
<span class="page-controls" total-count="orderedUsers.entries.length" current-page="options.page" page-size="usersPerPage"></span>
<input class="form-control" type="text" ng-model="options.filter" placeholder="Filter Users..." style="margin-right: 10px;">
</span>
</div>
<table class="cor-table" ng-if="orderedUsers.entries.length && !isLoading">
<thead>
<td style="width: 24px;"></td>
<td ng-class="tablePredicateClass('username', options.predicate, options.reverse)">
<a ng-click="orderBy('username')">Username</a>
</td>
<td ng-class="tablePredicateClass('email', options.predicate, options.reverse)"
ng-if="Features.MAILING">
<a ng-click="orderBy('email')">E-mail address</a>
</td>
<td style="width: 24px;"></td>
</thead>
<tr ng-repeat="current_user in orderedUsers.entries | slice
:(usersPerPage * options.page)
:(usersPerPage * (options.page + 1))"
class="user-row"
ng-class="current_user.enabled ? 'enabled': 'disabled'">
<td>
<span class="avatar" data="current_user.avatar" size="24"></span>
</td>
<td>
<span class="labels">
<span class="label label-success" ng-if="user.username == current_user.username">You</span>
<span class="label label-primary"
ng-if="current_user.super_user">Superuser</span>
<span class="label label-default"
ng-if="!current_user.enabled">Disabled</span>
</span>
{{ current_user.username }}
</td>
<td ng-if="Features.MAILING">
<a href="mailto:{{ current_user.email }}">{{ current_user.email }}</a>
</td>
<td style="text-align: center;">
<span class="cor-options-menu"
ng-if="user.username != current_user.username && !current_user.super_user && !inReadOnlyMode">
<span class="cor-option" option-click="showChangeEmail(current_user)"
quay-show="Config.AUTHENTICATION_TYPE == 'Database' || Config>.AUTHENTICATION_TYPE == 'AppToken'">
<i class="fa fa-envelope-o"></i> Change E-mail Address
</span>
<span class="cor-option" option-click="showChangePassword(current_user)"
quay-show="Config.AUTHENTICATION_TYPE == 'Database'">
<i class="fa fa-key"></i> Change Password
</span>
<span class="cor-option" option-click="sendRecoveryEmail(current_user)"
quay-show="Features.MAILING && Config.AUTHENTICATION_TYPE == 'Database'">
<i class="fa fa-envelope"></i> Send Recovery E-mail
</span>
<span class="cor-option" option-click="showDeleteUser(current_user)">
<i class="fa fa-times"></i> Delete User
</span>
<span class="cor-option" option-click="askDisableUser(current_user)">
<i class="fa" ng-class="current_user.enabled ? 'fa-circle-o' : 'fa-check-circle-o'"></i> <span
ng-if="current_user.enabled">Disable</span> <span ng-if="!current_user.enabled">Enable</span> User
</span>
<span class="cor-option" option-click="askTakeOwnership(current_user)"
ng-if="user.username != current_user.username && !current_user.super_user">
<i class="fa fa-bolt"></i> Take Ownership
</span>
</span>
</td>
</tr>
</table>
</div> <!-- /show if users -->
<!-- Take ownership dialog -->
<div class="cor-confirm-dialog take-ownership-dialog"
dialog-context="takeOwnershipInfo"
dialog-action="takeOwnership(info, callback)"
dialog-title="Take Ownership"
dialog-action-title="Take Ownership">
Are you sure you want to take ownership of user namespace <span class="avatar" data="takeOwnershipInfo.entity.avatar"
size="16"></span> {{ takeOwnershipInfo .entity.username }}?</span>
<div class="co-alert co-alert-warning">
Note: This will convert the user namespace into an organization. <strong>The user will no longer be able to login
to
this account.</strong>
</div>
</div>
<!-- Modal message dialog -->
<div class="co-dialog modal fade" id="confirmDeleteUserModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Delete User?</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger">
This operation <strong>cannot be undone</strong> and will <strong>delete any repositories owned by the
user</strong>.
</div>
Are you <strong>sure</strong> you want to delete user <strong>{{ userToDelete.username }}</strong>?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" ng-click="deleteUser(userToDelete)">Delete User</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal create user dialog -->
<div class="co-dialog modal fade" id="createUserModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Create New User</h4>
</div>
<form name="createUserForm" ng-submit="createUser()">
<div class="modal-body" ng-show="createdUser">
<table class="table">
<thead>
<th>Username</th>
<th>E-mail address</th>
<th>Temporary Password</th>
</thead>
<tr class="user-row">
<td>{{ createdUser.username }}</td>
<td>{{ createdUser.email }}</td>
<td>{{ createdUser.password }}</td>
</tr>
</table>
</div>
<div class="modal-body" ng-show="creatingUser">
<div class="cor-loader"></div>
</div>
<div class="modal-body" ng-show="!creatingUser && !createdUser">
<div class="form-group">
<label>Username</label>
<input class="form-control" type="text" ng-model="newUser.username" ng-pattern="/^[a-z0-9_]{4,30}$/"
required>
</div>
<div class="form-group">
<label>Email address</label>
<input class="form-control" type="email" ng-model="newUser.email" required>
</div>
</div>
<div class="modal-footer" ng-show="createdUser">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
<div class="modal-footer" ng-show="!creatingUser && !createdUser">
<button class="btn btn-primary" type="submit" ng-disabled="!createUserForm.$valid">
Create User
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</form>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal change password dialog -->
<div class="co-dialog modal fade" id="changePasswordModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Change User Password</h4>
</div>
<div class="modal-body">
<div class="alert alert-warning">
The user will no longer be able to access the registry with their current password
</div>
<form class="form-change" id="changePasswordForm" name="changePasswordForm" data-trigger="manual">
<input type="password" class="form-control" placeholder="User's new password"
ng-model="userToChange.password"
required ng-pattern="/^.{8,}$/">
<input type="password" class="form-control" placeholder="Verify the new password"
ng-model="userToChange.repeatPassword"
match="userToChange.password" required ng-pattern="/^.{8,}$/">
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="changeUserPassword(userToChange)"
ng-disabled="changePasswordForm.$invalid">Change User Password
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal change email dialog -->
<div class="co-dialog modal fade" id="changeEmailModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Change User E-mail Address</h4>
</div>
<div class="modal-body">
<form class="form-change" id="changeEmailForm" name="changeEmailForm" data-trigger="manual">
<input type="email" class="form-control" placeholder="User's new email" ng-model="userToChange.newemail"
required>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="changeUserEmail(userToChange)"
ng-disabled="changeEmailForm.$invalid">Change User E-mail
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>

View file

@ -0,0 +1,4 @@
<div class="manager-header-element">
<div class="manager-header-side-controls" ng-transclude></div>
<h3>{{ headerTitle }}</h3>
</div>

View file

@ -0,0 +1,181 @@
<div class="manifest-feature-view-element">
<!-- Unable to load -->
<div class="empty" ng-if="securityStatus == 'error'">
<div class="empty-icon">
<i class="fa fa-times-circle"></i>
</div>
<div class="empty-primary-msg">Could not load security scan information</div>
<div class="empty-secondary-msg">
Please try again in a few minutes. If this problem persists, please contact support.
</div>
</div>
<!-- Not scanned -->
<div class="empty" ng-if="securityStatus == 'queued'">
<div class="empty-icon">
<i class="fa fa-ellipsis-h"></i>
</div>
<div class="empty-primary-msg">This manifest has not been indexed yet</div>
<div class="empty-secondary-msg">
Please try again in a few minutes.
</div>
</div>
<!-- Unable to scan -->
<div class="empty" ng-if="securityStatus == 'failed'">
<div class="empty-icon">
<i class="fa fa-times-circle"></i>
</div>
<div class="empty-primary-msg">This manifest could not be indexed</div>
<div class="empty-secondary-msg">
Quay security scanner was unable to index this manifest.
</div>
</div>
<!-- Scanned and has no features -->
<div ng-if="securityStatus == 'scanned' && !featuresInfo.features.length">
<div class="empty">
<div class="empty-icon">
<i class="fa ci-package"></i>
</div>
<div class="empty-primary-msg">Manifest is not supported by Quay Security Scanner</div>
<div class="empty-secondary-msg">
This manifest has an operating system or package manager unsupported by Quay Security Scanner.
</div>
</div>
</div>
<!-- Scanned -->
<div ng-if="securityStatus == 'scanned' && featuresInfo.features.length">
<!-- Header -->
<div class="security-header row">
<div class="donut-col col-md-3">
<div id="featureDonutChart" style="position: relative;">
<svg style="height:250px; width:250px"></svg>
<span class="donut-icon">
<i class="fa ci-package"></i>
</span>
</div>
</div>
<div class="summary-col col-md-9">
<ul class="summary-list">
<li class="title-item">Quay Security Scanner has recognized <strong>{{ featuresInfo.features.length }}</strong> packages.</li>
<li ng-repeat="severity in featuresInfo.severityBreakdown">
<span class="package-item" ng-if="severity.label != 'None'">
<i class="fa ci-package" ng-style="{'color': severity.color}"></i> <strong>{{ severity.value }}</strong> packages with {{ severity.label }}-level vulnerabilities.
</span>
<span class="package-item" ng-if="severity.label == 'None'" style="margin-top: 20px; display: inline-block;">
<i class="fa ci-package" ng-style="{'color': severity.color}"></i> <strong>{{ severity.value }}</strong> packages with no vulnerabilities.
</span>
</li>
</ul>
</div>
</div>
<!-- Filter -->
<span class="co-filter-box">
<span class="filter-message" ng-if="options.filter">
Showing {{ orderedFeatures.entries.length }} of {{ featuresInfo.features.length }} packages
</span>
<input class="form-control" type="text" ng-model="options.filter" placeholder="Filter Packages...">
</span>
<h3>Packages</h3>
<!-- Table -->
<table class="co-table">
<thead>
<td ng-class="TableService.tablePredicateClass('name', options.predicate, options.reverse)">
<a ng-click="TableService.orderBy('name', options)">Package Name</a>
</td>
<td class="hidden-xs">
Package Version
</td>
<td ng-class="TableService.tablePredicateClass('score', options.predicate, options.reverse)">
<a ng-click="TableService.orderBy('score', options)">Vulnerabilities</a>
</td>
<td class="hidden-xs hidden-sm hidden-md"
ng-class="TableService.tablePredicateClass('leftoverScore', options.predicate, options.reverse)"
data-title="Identified vulnerabilities remaining after the package is upgraded to the latest version"
data-container="body" bs-tooltip>
<a ng-click="TableService.orderBy('leftoverScore', options)">Remaining after upgrade</a>
</td>
<td ng-class="TableService.tablePredicateClass('fixableScore', options.predicate, options.reverse)">
<a ng-click="TableService.orderBy('fixableScore', options)"
data-title="Delta of the severity of vulnerabilities in the package before->after upgrading" data-container="body" bs-tooltip>Upgrade impact</a>
</td>
<td class="hidden-xs hidden-sm hidden-md">
Introduced In Layer
</td>
<td class="hidden-xs options-col"></td>
</thead>
<tbody ng-repeat="feature in orderedFeatures.visibleEntries" bindonce>
<tr ng-class="feature.primarySeverity.index == 0 ? 'defcon1' : ''">
<td class="single-col">
<span bo-text="feature.name"></span>
</td>
<td class="single-col hidden-xs">
<span bo-text="feature.version"></span>
</td>
<td>
<span class="no-vulns" bo-if="feature.vulnCount == 0">
<i class="fa fa-check-circle"></i>None Detected
</span>
<span class="vuln-summary" bo-if="feature.vulnCount != 0">
<span ng-style="{'color': feature.severityBreakdown[0].color}">
<i class="fa fa fa-exclamation-triangle"></i>
{{ feature.primarySeverity.value }}
{{ feature.primarySeverity.label }}
</span>
<span bo-if="feature.vulnCount - feature.primarySeverity.value > 0">
+ {{ feature.vulnCount - feature.primarySeverity.value }} additional
</span>
</span>
</td>
<td class="hidden-xs hidden-sm hidden-md">
<span class="empty" bo-if="feature.vulnCount == 0">
(N/A)
</span>
<span class="no-vulns" bo-if="feature.vulnCount != 0 && feature.leftoverCount == 0">
<i class="fa fa-arrow-circle-right"></i>
All identified vulnerabilities fixed
</span>
<span class="vuln-summary" bo-if="feature.vulnCount != 0 && feature.leftoverCount != 0">
<span ng-style="{'color': feature.primaryLeftover.color}">
<i class="fa fa-arrow-circle-right"></i>
{{ feature.primaryLeftover.value }}
{{ feature.primaryLeftover.label }}
</span>
<span bo-if="feature.leftoverCount - feature.primaryLeftover.value > 0">
+ {{ feature.leftoverCount - feature.primaryLeftover.value }} additional
</span>
</span>
</td>
<td class="impact-col">
<span class="empty" bo-if="feature.vulnCount == 0">
(N/A)
</span>
<span class="empty" bo-if="feature.fixableScore == 0">
(No changes)
</span>
<span bo-if="feature.vulnCount > 0 && feature.fixableScore > 0">
<span class="strength-indicator" value="feature.fixableScore" maximum="featuresInfo.highestFixableScore"
log-base="2"></span>
</span>
</td>
<td class="double-col image-col hidden-xs hidden-sm hidden-md">
<span bo-if="feature.imageCommand">
<image-command command="feature.imageCommand"></image-command>
</span>
<span bo-if="!feature.imageCommand">(No Command)</span>
</td>
<td></td>
</tr>
</tbody>
</table>
<div class="empty" ng-if="featuresInfo.features.length && !orderedFeatures.entries.length"
style="margin-top: 20px;">
<div class="empty-primary-msg">No matching packages found.</div>
<div class="empty-secondary-msg">Try expanding your filtering terms.</div>
</div>
</div>
</div>

View file

@ -0,0 +1,11 @@
<div class="manifest-label-list-element">
<div class="cor-loader-inline" ng-if="repository && manifestDigest && !labels && !loadError"></div>
<div class="none" ng-if="repository && !manifestDigest && !loadError">
This tag does not have an associated manifest
</div>
<div class="none" ng-if="repository && manifestDigest && loadError">
Could not load labels for this manifest
</div>
<div class="label-list" labels="labels"
ng-if="repository && manifestDigest && labels && !loadError"></div>
</div>

View file

@ -0,0 +1,9 @@
<div class="manifest-view-layer-element" ng-class="getClass()">
<div class="image-command">
<image-command command="layer.command" ng-if="layer.command"></image-command>
<i ng-if="!layer.command && layer.comment">{{ layer.comment }}</i>
<code ng-if="!layer.command && !layer.comment">{{ layer.blob_digest }}</code>
</div>
<div class="image-layer-dot"></div>
<div class="image-layer-line"></div>
</div>

View file

@ -0,0 +1 @@
<manifest-link repository="item.repository" manifest-digest="item.digest"></manifest-link>

View file

@ -0,0 +1,213 @@
<div class="manifest-vulnerability-view-element">
<!-- Unable to load -->
<div class="empty" ng-if="securityStatus == 'error'">
<div class="empty-icon">
<i class="fa fa-times-circle"></i>
</div>
<div class="empty-primary-msg">Could not load security scan information</div>
<div class="empty-secondary-msg">
Please try again in a few minutes. If this problem persists, please contact support.
</div>
</div>
<!-- Not scanned -->
<div class="empty" ng-if="securityStatus == 'queued'">
<div class="empty-icon">
<i class="fa fa-ellipsis-h"></i>
</div>
<div class="empty-primary-msg">This manifest has not been indexed yet</div>
<div class="empty-secondary-msg">
Please try again in a few minutes.
</div>
</div>
<!-- Unable to scan -->
<div class="empty" ng-if="securityStatus == 'failed'">
<div class="empty-icon">
<i class="fa fa-times-circle"></i>
</div>
<div class="empty-primary-msg">This manifest could not be indexed</div>
<div class="empty-secondary-msg">
Quay security scanner was unable to index this manifest.
</div>
</div>
<!-- Scanned and has no features -->
<div ng-if="securityStatus == 'scanned' && !vulnerabilitiesInfo.features.length">
<div class="empty">
<div class="empty-icon">
<i class="fa fa-bug"></i>
</div>
<div class="empty-primary-msg">Manifest is not supported by Quay Security Scanner</div>
<div class="empty-secondary-msg">
This manifest has an operating system or package manager unsupported by Quay Security Scanner.
</div>
</div>
</div>
<!-- Scanned and has features -->
<div ng-if="securityStatus == 'scanned' && vulnerabilitiesInfo.features.length">
<!-- Header -->
<div class="security-header">
<div class="donut-col">
<div id="vulnDonutChart" style="position: relative;">
<svg style="height:250px; width:250px"></svg>
<span class="donut-icon">
<i class="fa fa-bug"></i>
</span>
</div>
</div>
<div class="summary-col">
<ul class="summary-list" ng-if="vulnerabilitiesInfo.severityBreakdown.length">
<li class="title-item">Quay Security Scanner has detected <strong>{{ vulnerabilitiesInfo.vulnerabilities.length }}</strong> vulnerabilities.</li>
<li class="subtitle-item" ng-if="vulnerabilitiesInfo.fixable.length">
Patches are available for <strong>{{ vulnerabilitiesInfo.fixable.length }}</strong> vulnerabilities.
</li>
<li style="margin-bottom: 30px"></li>
<li class="severity-item" ng-repeat="severity in vulnerabilitiesInfo.severityBreakdown">
<i class="fa fa-exclamation-triangle" ng-style="{'color': severity.color}"></i> <strong>{{ severity.value }}</strong> {{ severity.label }}-level vulnerabilities.
</li>
</ul>
<div ng-if="!vulnerabilitiesInfo.severityBreakdown.length">
Quay Security Scanner has detected no vulnerabilities in this manifest.
</div>
</div>
</div>
<!-- Filter -->
<span class="co-filter-box with-options" ng-show="vulnerabilitiesInfo.vulnerabilities.length">
<span class="filter-message" ng-if="options.filter || options.fixableVulns">
Showing {{ orderedVulnerabilities.entries.length }} of {{ vulnerabilitiesInfo.vulnerabilities.length }} Vulnerabilities
</span>
<input class="form-control" type="text" ng-model="options.filter" placeholder="Filter Vulnerabilities...">
<div class="filter-options">
<label><input type="checkbox" ng-model="options.fixableVulns">Only show fixable</label>
</div>
</span>
<h3>Vulnerabilities</h3>
<!-- Table -->
<div class="empty" ng-if="!vulnerabilitiesInfo.vulnerabilities.length"
style="margin-top: 20px;">
<div class="empty-primary-msg">No vulnerabilities found.</div>
<div class="empty-secondary-msg">Quay Security Scanner has detected no vulnerabilities in this manifest.</div>
</div>
<table class="co-table" ng-show="vulnerabilitiesInfo.vulnerabilities.length">
<thead>
<td class="caret-col"></td>
<td ng-class="TableService.tablePredicateClass('name', options.predicate, options.reverse)">
<a ng-click="TableService.orderBy('name', options)">CVE</a>
</td>
<td ng-class="TableService.tablePredicateClass('score', options.predicate, options.reverse)">
<a ng-click="TableService.orderBy('score', options)">Severity</a>
</td>
<td class="hidden-xs" ng-class="TableService.tablePredicateClass('featureName', options.predicate, options.reverse)">
<a ng-click="TableService.orderBy('featureName', options)">Package</a>
</td>
<td class="hidden-xs">Current version</td>
<td class="hidden-xs hidden-sm">Fixed in version</td>
</td>
<td class="hidden-xs hidden-sm hidden-md">Introduced in layer</td>
<td class="hidden-xs options-col"></td>
</thead>
<tbody ng-repeat="vuln in orderedVulnerabilities.visibleEntries" bindonce>
<tr ng-class="vuln.severityInfo.index == 0 ? 'defcon1' : ''">
<td class="caret-col">
<span ng-click="toggleDetails(vuln)">
<i class="fa"
ng-class="vuln.expanded ? 'fa-caret-down' : 'fa-caret-right'"
data-title="View Details" bs-tooltip></i>
</span>
</td>
<td class="single-col nowrap-col">
<a bo-text="vuln.name" ng-click="toggleDetails(vuln)" class="expand-link"></a>
<a href="{{ vuln.link }}" class="external-link hidden-xs hidden-sm hidden-md" ng-safenewtab>
<i class="fa fa-link"></i>
</a>
</td>
<td class="single-col nowrap-col">
<span bo-if="vuln.cvssScore && !vuln.scoreDivergence">
<span class="cvss-text" bo-text="vuln.cvssScore"></span>
<span class="cvss"><span bo-style="{'width': (vuln.cvssScore * 10) + '%', 'background-color': vuln.cvssColor}"></span>
</span>
</span>
<span bo-if="!vuln.cvssScore || vuln.scoreDivergence" data-title="{{ getSeverityTooltip(vuln) }}" data-container="body" bs-tooltip>
<span class="vulnerability-priority-view" priority="vuln.severity"></span>
<span class="asterisk" ng-if="vuln.scoreDivergence == 'adjusted-lower'" ng-style="{'color': vuln.severityInfo.color}">
<i class="fa fa-asterisk"></i>
</span>
</span>
</td>
<td class="single-col hidden-xs"><span bo-text="vuln.featureName"></span></td>
<td class="single-col hidden-xs hidden-sm">
<span bo-text="vuln.introducedInVersion"></span>
</td>
<td class="single-col hidden-xs">
<span class="empty" bo-if="!vuln.fixedInVersion">(None)</span>
<span class="fixed-in-version" bo-if="vuln.fixedInVersion" bo-text="vuln.fixedInVersion"></span>
</td>
<td class="double-col image-col hidden-xs hidden-sm hidden-md">
<span bo-if="vuln.imageCommand">
<image-command command="vuln.imageCommand"></image-command>
</span>
<span bo-if="!vuln.imageCommand">(No Command)</span>
</td>
<td></td>
</tr>
<tr ng-if="vuln.expanded">
<td class="expansion-col" colspan="8">
<div class="visible-xs" style="margin-bottom: 20px">
<div class="subtitle">Summary</div>
<table>
<tr><td>Package:</td><td><span bo-text="vuln.featureName"></span></td></tr>
<tr>
<td>Introduced in version:</td>
<td>
<span bo-text="vuln.introducedInVersion"></span>
</td>
</tr>
<tr>
<td>Fixed in version:</td>
<td>
<span class="empty" bo-if="!vuln.fixedInVersion">(None)</span>
<span class="fixed-in-version" bo-if="vuln.fixedInVersion" bo-text="vuln.fixedInVersion"></span>
</td>
</tr>
<tr>
<td>Introduced in Layer:</td>
<td>{{ ::vuln.imageId }}</td>
</tr>
</table>
</div>
<div class="severity-note" bo-if="vuln.scoreDivergence">
<div class="subtitle">Severity note</div>
<span class="description">
Note that this vulnerability was originally given a CVSSv2 score of <strong bo-text="vuln.cvssScore"></strong> by NVD but was subsequently reclassified as
<span class="vulnerability-priority-view" priority="vuln.severity"></span>
by <span bo-text="getDistro(vuln)"></span>
</span>
</div>
<div class="vectors" bo-if="vuln.metadata.NVD.CVSSv2.Vectors">
<div class="subtitle">Vectors</div>
<div class="nvd-vectors-display" vectors="{{ vuln.metadata.NVD.CVSSv2.Vectors }}"></div>
</div>
<div class="subtitle">Description</div>
<span class="description" bo-text="vuln.description"></span>
</td>
</tr>
</tbody>
</table>
<div class="empty" ng-if="vulnerabilitiesInfo.vulnerabilities.length && !orderedVulnerabilities.entries.length"
style="margin-top: 20px;">
<div class="empty-primary-msg">No matching vulnerabilities found.</div>
<div class="empty-secondary-msg">Try expanding your filtering terms.</div>
</div>
</div>
</div>

View file

@ -0,0 +1,66 @@
<!-- Modal message dialog -->
<div class="modal fade startTriggerDialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Manually Start Build Trigger</h4>
</div>
<div class="modal-body">
<trigger-description trigger="trigger"></trigger-description>
<form name="runForm" id="runForm">
<table width="100%">
<tr ng-repeat="field in runParameters">
<td class="field-title" valign="middle">{{ field.title }}:</td>
<td>
<div ng-switch on="field.type">
<!-- Autocomplete -->
<div ng-switch-when="autocomplete">
<span class="cor-loader-inline" ng-show="!fieldOptions[field.name]"></span>
<div class="dropdown-select-direct"
placeholder="'Enter or select ' + field.title"
selected-item="parameters[field.name]"
value-key="name"
title-key="name"
icon-key="kind"
icon-map="field.iconMap"
items="fieldOptions[field.name]"
ng-show="fieldOptions[field.name]"
clear-value="counter"></div>
</div>
<!-- Option -->
<div ng-switch-when="option">
<span class="cor-loader-inline" ng-show="!fieldOptions[field.name]"></span>
<select ng-model="parameters[field.name]" ng-show="fieldOptions[field.name]"
ng-options="value for value in fieldOptions[field.name]"
required>
</select>
</div>
<!-- String -->
<input type="text" class="form-control" ng-model="parameters[field.name]" ng-switch-when="string" required>
<!-- Regex -->
<div ng-switch-when="regex">
<input type="text" class="form-control" ng-model="parameters[field.name]"
ng-pattern="field.regex"
placeholder="{{ field.placeholder }}"
ng-name="field.name"
id="{{ field.name }}"
required>
</div>
</div>
</td>
</tr>
</table>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-disabled="runForm.$invalid" ng-click="startTrigger()">Start Build</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->

View file

@ -0,0 +1,43 @@
<div class="multiselect-dropdown-element">
<div class="dropdown" style="text-align: left;">
<button class="btn-dropdown btn btn-default" data-toggle="dropdown">
<span class="selected-item-template" ng-repeat="item in selectedItems | limitTo:10" ng-transcope></span>
<span class="selected-item-template"
ng-if="(selectedItems | limitTo:11).length > 10">
and {{ selectedItems.length - 10 }} more...
</span>
<span class="none" ng-if="!selectedItems.length">(No {{ itemName }}s selected)</span>
<span class="caret" ng-if="!readOnly"></span>
</button>
<ul class="dropdown-menu noclose">
<li>
<input type="search" class="form-control" ng-model="filter" placeholder="{{ itemName }} filter...">
</li>
<li role="presentation" class="divider"></li>
<li ng-repeat="item in items | filter:filter | limitTo:10">
<a class="menu-item" ng-click="toggleItem(item)">
<span class="co-checkable-item" ng-class="isChecked(selectedItems, item) ? 'checked': 'not-checked'">
</span>
<span class="menu-item-template" ng-transcope></span>
</a>
</li>
<li role="presentation" ng-if="(items | filter:filter | limitTo:11).length == 11">
<div class="empty" style="margin-top: 10px;">
<div class="empty-secondary-msg">
+ {{ (items | filter:filter).length - 10 }} additional
</div>
</div>
</li>
<li role="presentation" ng-if="(items | filter:filter | limitTo:1).length == 0">
<div class="empty">
<div class="empty-primary-msg">No matching {{ itemName }}s found</div>
<div class="empty-secondary-msg">
Please reduce your filter above
</div>
</div>
</li>
</ul>
</div>
</div>

View file

@ -0,0 +1,7 @@
<span class="namespace-input-element">
<input type="text" class="form-control" placeholder="{{ namespaceTitle }}" ng-model="binding"
required autofocus ng-pattern="usernamePattern"
ng-model-options="{'debounce': 200}"
name="namespaceField"
ng-class="hasExternalError ? 'ng-invalid' : ''">
</span>

View file

@ -0,0 +1,34 @@
<span class="namespace-selector-dropdown">
<span ng-show="user.organizations.length == 0">
<span class="avatar" size="24" data="user.avatar"></span>
<span class="namespace-name">{{user.username}}</span>
</span>
<div class="btn-group" ng-show="user.organizations.length > 0">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="avatar" size="16" data="namespaceObj.avatar"></span>
{{namespace}} <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li class="namespace-item" ng-repeat="org in user.organizations"
ng-class="(requireCreate && !namespaces[org.name].can_create_repo) ? 'disabled' : ''">
<a class="namespace" ng-click="setNamespace(org)">
<span class="avatar" size="24" data="org.avatar"></span>
<span class="namespace-name">{{ org.name }}</span>
</a>
<i class="fa fa-exclamation-triangle" ng-show="requireCreate && !namespaces[org.name].can_create_repo"
data-title="You do not have permission to create repositories for this organization"
data-placement="right"
bs-tooltip="tooltip.title"></i>
</li>
<li class="divider"></li>
<li>
<a class="namespace" ng-click="setNamespace(user)">
<span class="avatar" size="24" data="user.avatar"></span>
<span class="namespace-name">{{ user.username }}</span>
</a>
</li>
</ul>
</div>
</span>

View file

@ -0,0 +1,18 @@
<div class="aside" tabindex="-1" role="dialog">
<div class="aside-dialog">
<div class="aside-content">
<div class="aside-header">
<button type="button" class="close" ng-click="$hide()">&times;</button>
<h4 class="aside-title">
Notifications
<span class="notifications-bubble"></span>
</h4>
</div>
<div class="aside-body">
<div ng-repeat="notification in notificationService.notifications">
<div class="notification-view" notification="notification" parent="this"></div>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,20 @@
<div class="notification-view-element">
<div class="notification-content" ng-click="showNotification();">
<div class="circle" ng-class="getClass(notification)"></div>
<div class="message" ng-bind-html="getMessage(notification)"></div>
<div class="orginfo" ng-if="notification.organization">
<span class="avatar" size="24" data="getAvatar(notification.organization)"></span>
<span class="orgname">{{ notification.organization }}</span>
</div>
</div>
<div class="right-controls" ng-show="!inReadOnlyMode">
<a ng-if="canDismiss(notification)" ng-click="dismissNotification(notification)" ng-show="!dismissing">
Dismiss Notification
</a>
<span class="cor-loader-inline" ng-show="dismissing"></span>
<button class="btn" ng-class="'btn-' + action.kind" ng-repeat="action in getActions(notification)" ng-click="action.handler(notification)">
{{ action.title }}
</button>
</div>
<div class="datetime">{{ parseDate(notification.created) | date:'medium'}}</div>
</div>

View file

@ -0,0 +1,7 @@
<span class="notifications-bubble-element">
<span class="badge user-notification notification-animated"
ng-show="notificationService.notifications.length"
ng-class="notificationService.notificationClasses">
{{ notificationService.notifications.length }}<span ng-if="notificationService.additionalNotifications">+</span>
</span>
</span>

View file

@ -0,0 +1,8 @@
<div class="nvd-vectors-display-element">
<dl ng-repeat="vector in parsedVectors" bindonce>
<dt bo-text="getVectorTitle(vector)" data-title="{{ getVectorDescription(vector) }}" data-container="body" bs-tooltip></dt>
<dd bo-class="getVectorClasses(option, vector)" ng-repeat="option in getVectorOptions(vector)" data-container="body" data-title="{{ option.description }}" bs-tooltip>
{{ option.title }}
</dd>
</dl>
</div>

View file

@ -0,0 +1,18 @@
<div class="organization-header-element">
<span class="avatar" size="24" data="organization.avatar"></span>
<span class="organization-name" ng-show="teamName || clickable">
<a href="/organization/{{ organization.name }}">{{ organization.name }}</a>
</span>
<span class="organization-name" ng-show="!teamName && !clickable">
{{ organization.name }}
</span>
<span ng-show="teamName">
<span class="divider">/</span>
<i class="fa fa-group"></i>
<span class="team-name">
{{ teamName }}
</span>
</span>
<span ng-transclude></span>
</div>

View file

@ -0,0 +1,20 @@
<div class="page-controls-element">
<span class="current-items dropdown">
<span class="page-view" data-toggle="dropdown">
{{ getPageStart(currentPage, pageSize, totalCount) }} - {{ getPageEnd(currentPage, pageSize, totalCount) }}
of {{ totalCount }}
</span>
<ul class="dropdown-menu">
<li><a ng-click="setPage(0)"><i class="fa fa-caret-square-o-left"></i>First Page</a></li>
<li><a ng-click="setPage(getPageCount(pageSize, totalCount) - 1)"><i class="fa fa-caret-square-o-right"></i>Last Page</a></li>
</ul>
</span>
<span class="page-buttons btn-group">
<button class="btn btn-default"
ng-disabled="currentPage == 0"
ng-click="changePage(-1)">&#10094;</button>
<button class="btn btn-default"
ng-disabled="currentPage >= getPageCount(pageSize, totalCount) - 1"
ng-click="changePage(1)">&#10095;</button>
</span>
</div>

View file

@ -0,0 +1,101 @@
<div class="plan-manager-element">
<!-- Loading/Changing -->
<div class="cor-loader" ng-show="planLoading"></div>
<!-- Alerts -->
<div class="co-alert co-alert-danger" ng-show="limit == 'over' && !planLoading">
You are using more private repositories than your plan allows. Please
upgrade your subscription to avoid disruptions in your <span ng-show="organization">organization's</span> service.
</div>
<div class="co-alert co-alert-warning" ng-show="limit == 'at' && !planLoading">
You are at your current plan's number of allowed private repositories. It might be time to think about
upgrading your subscription to avoid future disruptions in your <span ng-show="organization">organization's</span> service.
</div>
<div class="co-alert co-alert-info" ng-show="limit == 'near' && !planLoading">
You are nearing the number of allowed private repositories. It might be time to think about
upgrading your subscription to avoid future disruptions in your <span ng-show="organization">organization's</span> service.
</div>
<!-- Trial info -->
<div class="co-alert co-alert-success" ng-show="subscription.trialEnd != null" style="font-size: 125%">
Free trial until <strong>{{ parseDate(subscription.trialEnd) | date }}</strong>
</div>
<!-- QE Shoutout -->
<div class="qe-shoutout hidden-xs hidden-sm">
<table>
<tr>
<td>
<img src="/static/img/QuayEnterprise_horizontal_color.svg">
<div class="shoutout-text">
Run a private instance of Quay, with the same build features and geo-replication. Fixed price for unlimited users and repositories.
</div>
</td>
<td>
<a href="/plans?tab=enterprise" class="btn btn-default">Learn More</a>
</td>
</tr>
</table>
</div>
<!-- Chart -->
<div class="usage-chart" total="subscribedPlan.privateRepos || 0"
current="subscription.usedPrivateRepos || 0"
limit="limit"
usage-title="Repository Usage"
ng-show="!planLoading"></div>
<!-- Plans Table -->
<div class="visible-xs" style="margin-top: 10px"></div>
<table class="table table-hover plans-list-table" ng-show="!planLoading">
<thead>
<td>Plan</td>
<td>
<span class="hidden-xs">Private Repositories</span>
<span class="visible-xs"><i class="fa fa-hdd-o"></i></span>
</td>
<td style="min-width: 64px"><span class="hidden-xs">Price</span><span class="visible-xs">$/mo</span></td>
<td></td>
</thead>
<tr ng-repeat="plan in plans" ng-show="isPlanVisible(plan, subscribedPlan)"
ng-class="{'active':isPlanActive(plan, subscribedPlan)}">
<td>
{{ plan.title }}
<div class="deprecated-plan-label" ng-show="plan.deprecated">
<span class="context-tooltip" data-title="This plan has been discontinued. As a valued early adopter, you may continue to stay on this plan indefinitely." bs-tooltip="tooltip.title" data-placement="right">Discontinued Plan</span>
</div>
</td>
<td>{{ plan.privateRepos }}</td>
<td><div class="plan-price">${{ plan.price / 100 }}</div></td>
<td class="controls">
<div ng-switch='plan.deprecated'>
<div ng-switch-when='true'>
<button class="btn btn-danger" ng-click="cancelSubscription()">
<span class="cor-loader-inline" ng-show="planChanging"></span>
<span ng-show="!planChanging">Cancel</span>
</button>
</div>
<div ng-switch-default>
<button class="btn" ng-show="!isPlanActive(plan, subscribedPlan)"
ng-class="subscribedPlan.price == 0 ? 'btn-primary' : 'btn-default'"
ng-click="changeSubscription(plan.stripeId)">
<span class="cor-loader-inline" ng-show="planChanging"></span>
<span ng-show="!planChanging && subscribedPlan.price != 0">Change</span>
<span ng-show="!planChanging && subscribedPlan.price == 0 && !isExistingCustomer">Start Free Trial</span>
<span ng-show="!planChanging && subscribedPlan.price == 0 && isExistingCustomer">Subscribe</span>
</button>
<button class="btn btn-danger" ng-show="isPlanActive(plan, subscribedPlan) && plan.price > 0"
ng-click="cancelSubscription()">
<span class="cor-loader-inline" ng-show="planChanging"></span>
<span ng-show="!planChanging">Cancel</span>
</button>
</div>
</div>
</td>
</tr>
</table>
</div>

View file

@ -0,0 +1,494 @@
<div class="plans-display-element">
<!-- Header -->
<div class="plans-header">Use Quay in the cloud or hosted on your servers:</div>
<!-- Tabs -->
<ul class="nav nav-tabs plan-tabs" role="tablist">
<li role="presentation" class="active">
<a role="tab" data-toggle="tab" data-target="#hosted">
<div class="tab-logo">
<img src="/static/img/RH_QuayIO.svg">
</div>
<div class="tab-title">Hosted in the cloud and scales with you.</div>
<div class="tab-title">Priced by the number of private repositories.</div>
</a>
</li>
<li role="presentation">
<a role="tab" href="https://www.openshift.com/products/quay">
<div class="tab-logo">
<img src="/static/img/RH_Logo_Quay_Black_UX-horizontal.svg">
</div>
<div class="tab-title">Runs privately anywhere you can run a container.</div>
<div class="tab-title">Fixed price for unlimited users and repositories</div>
</a>
</li>
</ul>
<div class="tab-content">
<!-- Hosted -->
<div class="tab-pane active" id="hosted">
<!-- Plan columns -->
<div class="row-container">
<div class="row">
<!-- Developer Plan -->
<div class="col-md-3 col-sm-6 plan-col">
<div class="plan-box">
<div class="plan-header">
<span class="plan-box-price">$15/mo</span>
<b>Developer</b>
</div>
<ul>
<li>5 private repositories</li>
<li>Unlimited public repos</li>
</ul>
<div class="plan-description">Great for individuals</div>
<a class="btn btn-primary trial-button" ng-click="buyNow('personal-2018')">
Start Free Trial
<i class="fa fa-angle-double-right"></i>
</a>
</div>
<ul class="plan-features single-feature">
<li><i class="fa fa-clock-o"></i>30-day free trial</li>
</ul>
</div>
<!-- Micro Plan -->
<div class="col-md-3 col-sm-6 plan-col">
<div class="plan-box">
<div class="plan-header">
<span class="plan-box-price">$30/mo</span>
<b>Micro</b>
</div>
<ul>
<li>10 private repositories</li>
<li>Unlimited public repos</li>
<li>Team-based permissions</li>
</ul>
<div class="plan-description">Great for startups</div>
<a class="btn btn-primary trial-button" ng-click="buyNow('bus-micro-2018')">
Start Free Trial
<i class="fa fa-angle-double-right"></i>
</a>
</div>
<ul class="plan-features single-feature">
<li><i class="fa fa-clock-o"></i>30-day free trial</li>
</ul>
</div>
<!-- Small Plan -->
<div class="col-md-3 col-sm-6 plan-col popular">
<div class="plan-box">
<div class="plan-header">
<span class="plan-box-price">$60/mo</span>
<b>Small</b>
</div>
<ul>
<li>20 private repositories</li>
<li>Unlimited public repos</li>
<li>Team-based permissions</li>
</ul>
<div class="plan-description">Great for small businesses</div>
<a class="btn btn-primary trial-button" ng-click="buyNow('bus-small-2018')">
Start Free Trial
<i class="fa fa-angle-double-right"></i>
</a>
</div>
<ul class="plan-features single-feature">
<li><i class="fa fa-clock-o"></i>30-day free trial</li>
</ul>
</div>
<!-- Larger Plans -->
<div class="col-md-3 col-sm-6 plan-col">
<div class="plan-box">
<div class="plan-header">
<b>Larger Plans</b>
</div>
<select ng-model="dropdownPlan" class="form-control">
<option ng-repeat="plan in plans" ng-if="plan.privateRepos > 20 && !plan.plans_page_hidden"
value="{{ plan.stripeId }}">
{{ plan.privateRepos }} private repositories - ${{ plan.price / 100 }}/mo
</option>
</select>
<ul>
<li>Unlimited public repos</li>
<li>Team-based permissions</li>
</ul>
<div class="plan-description">Great for enterprises</div>
<a class="btn btn-primary trial-button" ng-click="buyNow(dropdownPlan)">
Start Free Trial
<i class="fa fa-angle-double-right"></i>
</a>
</div>
<ul class="plan-features single-feature">
<li><i class="fa fa-clock-o"></i>30-day free trial</li>
</ul>
</div>
</div>
</div>
<!-- FAQ and features -->
<div class="faq-features">
<div class="row-container-no-margin">
<div class="row">
<!-- Features -->
<div class="col-md-5 col-md-push-7 features-col">
<div class="features-title">All plans include:</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-6 col-xs-12">
<ul class="features-list">
<li><i class="fa fa-refresh"></i>
<b>Continuous Integration</b>
<p>Build your containers in response to git pushes: GitHub, BitBucket, Gitlab and others.</p>
</li>
<li><i class="fa fa-clock-o"></i>
<b>30-Day Free Trial</b>
<p>Your first 30 days are free on Quay. Test it out and start building containers!</p>
</li>
<li><i class="fa fa-hdd-o"></i>
<b>Public Repositories</b>
<p>Provide a public download page for your container. The best part, they're free!</p>
</li>
<li><i class="fa ci-robot"></i>
<b>Robot Accounts</b>
<p>Create credentials designed for deploying software automatically.</p>
</li>
</ul>
</div>
<div class="col-lg-12 col-md-12 col-sm-6 col-xs-12">
<ul class="features-list">
<li><i class="fa fa-group"></i>
<b>Teams</b>
<p>Teams can collectively have access to manage specific repositories on your account.</p>
</li>
<li><i class="fa fa-lock"></i>
<b>SSL Encryption</b>
<p>Transit between Quay and your servers is secured automatically.</p>
</li>
<li><i class="fa fa-bar-chart"></i>
<b>Logging &amp; Auditing</b>
<p>Auditing is essential for everything in your CI pipeline. Actions via API and UI are tracked.</p>
</li>
<li><i class="fa fa-calendar"></i>
<b>Invoice History</b>
<p>Download past invoices for your billing team or purchasing department.</p>
</li>
</ul>
</div>
</div>
</div>
<!-- FAQ -->
<div class="col-md-7 col-md-pull-5 faq-col">
<h4>How do I use Quay with my servers and code?</h4>
<p>Using Quay with your infrastructure is separated into two main actions: <b>building containers</b> and <b>distributing them to your servers</b>.</p>
<p>You can configure Quay to automatically build containers of your code on each commit. Integrations with GitHub, Bitbucket, GitLab and self-hosted Git repositories are supported. Each built container is stored on Quay and is available to be pulled down onto your servers.</p>
<p>To distribute your private containers onto your servers, Docker or rkt must be configured with the correct credentials. Quay has sophisticated access controls &mdash; organizations, teams, robot accounts, and more &mdash; to give you full control over which servers can pull down your containers. An API can be used to automate the creation and management of these credentials.</p>
<h4>How is Quay optimized for a team environment?</h4>
<p>Quay's permission model is designed for teams. Each new user can be assigned to one or more teams, with specific permissions. Robot accounts, used for automated deployments, can be managed per team as well. This system allows for each development team to manage their own credentials.</p>
<p>Full logging and auditing is integrated into every part of the application and API. Quay helps you dig into every action for more details.</p>
<h4>Additional FAQs</h4>
<b>Can I change my plan?</b>
<p>Yes, you can change your plan at any time and your account will be pro-rated for the difference. For large organizations, Red Hat Quay offers unlimited users and repos.</p>
<b>Do you offer special plans for business or academic institutions?</b>
<p>Please contact us at our support email address to discuss the details of your organization and intended usage.</p>
<b>Can I use Quay for free?</b>
<p>Yes! We offer unlimited storage and serving of public repositories. We strongly believe in the open source community and will do what we can to help!</p>
<b>What types of payment do you accept?</b>
<p>Quay uses Stripe as our payment processor, so we can accept any of the payment options they offer, which are currently: Visa, MasterCard, American Express, JCB, Discover and Diners Club.</p>
</div>
</div>
</div>
</div>
</div>
<!-- Enterprise -->
<div class="tab-pane" id="enterprise">
<h2 class="co-p-quay-enterprise-tagline">One container registry for your entire enterprise
<button class="btn btn-primary btn-lg trial-button hidden-xs hidden-sm" ng-click="qeStartTrial()">
Start a free trial
</button>
</h2>
<div class="flex-wrap top-section">
<div class="container">
<div class="co-p-quay-enterprise-values">
<div class="co-p-quay-enterprise-value">
<div class="co-p-quay-enterprise-value-text co-m-text-light">Highly Available</div>
<p class="co-p-quay-enterprise-value-desc">Run multiple instances of Quay for redundancy</p>
</div>
<div class="co-p-quay-enterprise-value">
<div class="co-p-quay-enterprise-value-text co-m-text-light">Geo-replication</div>
<p class="co-p-quay-enterprise-value-desc">Sync your container images between your datacenters</p>
</div>
<div class="co-p-quay-enterprise-value">
<div class="co-p-quay-enterprise-value-text co-m-text-light">Continuous Integration</div>
<p class="co-p-quay-enterprise-value-desc">Automatically build and push images when developers commit code</p>
</div>
<div class="co-p-quay-enterprise-value">
<div class="co-p-quay-enterprise-value-text co-m-text-light">Security Scanning</div>
<p class="co-p-quay-enterprise-value-desc">Automatically scan your container images for known security vulnerabilities</p>
</div>
<div class="co-p-quay-enterprise-value">
<div class="co-p-quay-enterprise-value-text co-m-text-light">24/7 Support</div>
<p class="co-p-quay-enterprise-value-desc">Enterprise-level support is available around the clock</p>
</div>
</div>
</div>
<div class="co-p-quay-diagram">
<img src="/static/img/QE-complex.svg" alt="Red Hat Quay System" class="vertical" />
<img src="/static/img/QE-complex-h.svg" alt="Red Hat Quay System" class="horizontal" />
<div class="co-p-quay-diagram-caption co-m-text-light">Highly available installation with geo-replication</div>
</div>
</div>
<div class="flex-wrap">
<div class="co-p-quay-enterprise-top-cta">
<div class="co-p-quay-enterprise-top-cta-text">Ready to try Red Hat Quay?</div>
<div class="co-p-quay-enterprise-top-cta-buttons">
<div class="co-p-quay-enterprise-top-cta-button-wrap">
<button class="btn btn-primary btn-lg trial-button" ng-click="qeStartTrial()">
Start a free trial
</button>
<div class="button-subtext co-m-text-light">No credit card required, 30-day trial</div>
</div>
</div>
<div class="co-p-quay-enterprise-top-cta-questions">
<p><strong>Questions?</strong> Give us a call at any time (800) 774-3507 or <a href="mailto:sales@coreos.com">contact sales</a></p>
</div>
</div>
</div>
<div class="co-p-quay-enterprise-faq">
<!-- FAQ and features -->
<div class="faq-features">
<div class="row-container-no-margin">
<div class="row">
<!-- Features -->
<div class="col-md-5 col-md-push-7 features-col">
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-6 col-xs-12">
<ul class="features-list">
<li><i class="fa fa-sign-in"></i>
<b>Enterprise Authentication</b>
<p>Integrate to your existing identity infrastructure: LDAP, Keystone, and more</p>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-6 col-xs-12">
<ul class="features-list">
<li><i class="fa fa-database"></i>
<b>Flexible Storage Backends</b>
<p>Store your containers on Amazon S3, OpenStack Swift, Google Cloud Storage, or directly to disk.</p>
</li>
<li><i class="fa fa-refresh"></i>
<b>Continuous Integration</b>
<p>Build your containers in response to git pushes: GitHub, BitBucket, Gitlab and others</p>
</li>
<li><i class="fa ci-robot"></i>
<b>Robot Accounts</b>
<p>Create credentials designed for deploying software automatically.</p>
</li>
</ul>
</div>
<div class="col-lg-12 col-md-12 col-sm-6 col-xs-12">
<ul class="features-list">
<li><i class="fa fa-group"></i>
<b>Teams</b>
<p>Teams can collectively have access to manage specific repositories on your account.</p>
</li>
<li><i class="fa fa-lock"></i>
<b>Supports SSL Encryption</b>
<p>Transit between Quay.io and your servers is secured automatically.</p>
</li>
<li><i class="fa fa-bar-chart"></i>
<b>Logging &amp; Auditing</b>
<p>Auditing is essential for everything in your CI pipeline. Actions via API and UI are tracked.</p>
</li>
</ul>
</div>
</div>
</div>
<!-- FAQ -->
<div class="col-md-7 col-md-pull-5 faq-col">
<h4>How can I run Red Hat Quay?</h4>
<p>
Red Hat Quay is delivered as a set of containers that can run on any infrastructure.
It is recommended to run Red Hat Quay in highly-available fashion, on multiple machines.
</p>
<h4>How is Red Hat Quay different than Quay.io?</h4>
<p>
Red Hat Quay is closely related to Quay.io, but runs on your own hardware or in your cloud environment.
Running the application yourself is more secure and is more performant when running on the same cluster as your containerized applications.
</p>
<p>
When running behind your firewall, Red Hat Quay can connect to private Git repositories, LDAP infrastructure, and more.
</p>
<h4>Additional FAQs</h4>
<b>Is there a free trial for Red Hat Quay?</b>
<p>
Yes, the first 30 days of usage are free, and then your license will be automatically converted to the standard rate.
Well send you an email before that happens as a reminder.
</p>
<b>What types of payment do you accept?</b>
<p>Red Hat Quay is billed annually with a purchase order.</p>
<b>Can I ugrade from Quay.io (hosted)?</b>
<p>Yes, you can upgrade from Quay.io to Red Hat Quay easily.</p>
<b>Data transfer limits?</b>
<p>These limits are selectively enforced in order to ensure that Quay.io can continue to provide a high quality service.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Modal message dialog -->
<div class="modal fade" id="signinModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<div class="user-setup" signed-in="signedIn()" redirect-url="'/plans/'"></div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal message dialog -->
<div class="co-dialog wider modal fade" id="redhatManagerDialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<h1>
Thank you for your interest in trying Red Hat&reg; Quay!
</h1>
<p class="text-left">
To get started, download the Red Hat&reg; Red Hat Quay container image. Red Hat&reg; Quay is distributed via container images only.
In previous versions of Quay a license file has been required to run Quay. This license file got deprecated with Quay v2.9.0
and is no longer required. To pull the Quay images from Quay.io a secret is provided inside the Red Hat&reg; Customer Portal.
</p>
<div class="row-container">
<div class="row">
<!-- create a free account -->
<div class="col-md-6 plan-col">
<div class="plan-box same-height text-left">
<div class="plan-header text-center">
<h3>Create a free Red Hat&reg; account</h3>
<h5>Sign up for Red Hat&reg; Developer Program</h5>
</div>
<div class="step-text">Step 1: Sign up</div>
<p>
<a href="https://developers.redhat.com/register/" target="_blank">
Sign up
</a> for a free Red Hat&reg; Developer Program account and accept the terms and conditions. With this account, developers can
also access various Red Hat&reg; products and their documentation. For more information about the Red Hat&reg; Developer Program,
check out the <a href="https://developers.redhat.com/articles/red-hat-developer-program-benefits/" target="_blank">benefits page</a>.
</p>
<div class="step-text">Step 2: Verify your email</div>
<p>
Verify the email that you used to register the account by clicking on the link in the confirmation email that will be
sent shortly after you create the developer account.
</p>
<div class="step-text">Step 3: Log in to the customer portal</div>
<p>
Go to the <a href="https://access.redhat.com/login" target="_blank">Red Hat&reg; customer portal</a> and log in using your
Red Hat Developer account credentials.
</p>
<div class="step-text">Step 4: Update your account</div>
<p>
Update your account information and accept the terms and conditions for the customer portal.
</p>
<div class="step-text">Step 5: Get the Red Hat&reg; Quay container image</div>
<p>
Visit the <a href="https://access.redhat.com/solutions/3533201" target="_blank">"Accessing Red Hat Quay without a
CoreOS login"</a> page in the customer portal. Follow the directions listed on that page for pulling the Red Hat&reg;
Quay container image.
</p>
<div class="step-text">Step 6: Install and configure quay</div>
<p>
Follow the <a href="https://access.redhat.com/documentation/en-us/red_hat_quay/2.9/html/getting_started_with_red_hat_quay/" target="_blank">
Red Hat&reg; Quay install documentation</a> to install and configure Quay.
</p>
</div>
</div>
<!-- already have an account -->
<div class="col-md-6 plan-col">
<div class="plan-box same-height text-left">
<div class="plan-header text-center">
<h3>Already have a Red Hat&reg; account?</h3>
<h5>Access Quay in Red Hat&reg; Customer Portal</h5>
</div>
<div class="step-text">Step 1: <a href="https://access.redhat.com/login" target="_blank">Log in</a> to the customer portal</div>
<div class="step-text">Step 2: Get the Red Hat&reg; Quay container image</div>
<p>
Visit the <a href="https://access.redhat.com/solutions/3533201" target="_blank">"Accessing Red Hat Quay without a
CoreOS login"</a> page in the customer portal. Follow the directions listed on that page for pulling the Red Hat&reg;
Quay container image.
</p>
<div class="step-text">Step 3: Install and configure quay</div>
<p>
Follow the <a href="https://access.redhat.com/documentation/en-us/red_hat_quay/2.9/html/getting_started_with_red_hat_quay/" target="_blank">
Red Hat&reg; Quay install documentation</a> to install and configure Quay.
</p>
</div>
</div>
</div>
</div><!-- /.row-container -->
</div><!-- /.modal-body -->
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>

View file

@ -0,0 +1,41 @@
<div class="plans-table-element">
<ul class="plans-table-list visible-xs">
<li ng-repeat="plan in plans" ng-class="currentPlan == plan ? 'active' : ''">
<a class="btn"
ng-class="currentPlan == plan ? 'btn-primary' : 'btn-default'"
ng-click="setPlan(plan)">
{{ plan.title }}
</a>
<div class="plan-info">
${{ plan.price / 100 }} / month -
{{ plan.privateRepos }} repositories
</div>
</li>
</ul>
<div class="hidden-xs">
<table class="co-table plans-table-table" ng-show="plans">
<thead>
<td>Plan</td>
<td>Private Repositories</td>
<td style="min-width: 85px">Price</td>
<td></td>
</thead>
<tr ng-repeat="plan in plans" ng-class="currentPlan == plan ? 'active' : ''">
<td>{{ plan.title }}</td>
<td>{{ plan.privateRepos }}</td>
<td><div class="plan-price">${{ plan.price / 100 }}</div></td>
<td class="controls">
<a class="btn"
ng-class="currentPlan == plan ? 'btn-primary' : 'btn-default'"
ng-click="setPlan(plan)">
{{ currentPlan == plan ? 'Selected' : 'Choose' }}
</a>
</td>
</tr>
</table>
</div>
</div>

View file

@ -0,0 +1,6 @@
<button class="btn btn-primary" data-trigger="click"
data-content-template="/static/directives/popup-input-dialog.html"
data-placement="bottom" ng-click="popupShown()" bs-popover>
<span ng-transclude></span>
</button>

View file

@ -0,0 +1,4 @@
<form name="popupinput" ng-submit="inputSubmit(); $hide()" novalidate>
<input id="input-box" type="text form-control" placeholder="{{ placeholder }}" ng-blur="$hide()"
ng-pattern="getRegexp(pattern)" ng-model="inputValue" ng-trim="false" ng-minlength="2" required>
</form>

View file

@ -0,0 +1,143 @@
<div class="prototype-manager-element">
<div class="feedback-bar" feedback="feedback"></div>
<div class="cor-loader" ng-show="loading"></div>
<div ng-show="!loading">
<div class="manager-header" header-title="Default Permissions">
<button class="btn btn-primary" ng-click="showAddDialog()" ng-show="!inReadOnlyMode">
<i class="fa fa-plus"></i>
Create Default Permission
</button>
</div>
<div class="section-description-header">
The Default permissions panel defines permissions that should be granted automatically to a repository when it is created, in addition to the default of the repository's
creator. Permissions are assigned based on the user who created the repository.
<br><br>
<strong>Note:</strong> Permissions added here do <strong>not</strong> automatically get added to
existing repositories.
</div>
<div class="empty" ng-if="!prototypes.length">
<div class="empty-primary-msg">No default permissions defined.</div>
<div class="empty-secondary-msg" ng-show="!inReadOnlyMode">
Click the "Create Default Permission" button above to create a new default permission.
</div>
</div>
<table class="cor-table" ng-show="prototypes.length">
<thead>
<td>
<span class="context-tooltip"
data-title="The user or robot that is creating a repository. If '(Organization Default)', then any repository created in this organization will be granted the permission."
data-container="body" bs-tooltip>
Repository Created By
</span>
</td>
<td>
<span class="context-tooltip"
data-title="The user, robot or team that is being granted the permission"
data-container="body" bs-tooltip>
Permission Applied To
</span>
</td>
<td>Permission</td>
<td class="options-col"></td>
</thead>
<tr ng-repeat="prototype in prototypes | orderBy:comparePrototypes">
<td>
<span class="entity-reference block-reference" entity="prototype.activating_user"
namespace="organization.name" ng-if="prototype.activating_user"
avatar-size="24"></span>
<span ng-show="!prototype.activating_user"
style="font-variant: small-caps; font-weight: bold; font-size: 16px;">
(Organization Default)
</span>
</td>
<td>
<span class="entity-reference block-reference" entity="prototype.delegate" namespace="organization.name" avatar-size="24"></span>
</td>
<td>
<span class="role-group" current-role="prototype.role"
role-changed="setRole(role, prototype)"
roles="repoRoles"
read-only="inReadOnlyMode"></span>
</td>
<td class="options-col">
<span class="cor-options-menu" ng-show="!inReadOnlyMode">
<span class="cor-option" option-click="deletePrototype(prototype)">
<i class="fa fa-times"></i> Delete Permission
</span>
</span>
</td>
</tr>
</table>
</div>
<!-- Modal message dialog -->
<div class="modal fade" id="addPermissionDialogModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Create Default Permission</h4>
</div>
<div class="modal-body">
<div class="super-option">
<table style="width: 100%;">
<tr>
<td>Applies when a repository is created by:</td>
<td>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-default"
ng-class="newForWholeOrg ? 'active btn-info' : ''" ng-click="setNewForWholeOrg(true)">Anyone</button>
<button type="button" class="btn btn-default"
ng-class="newForWholeOrg ? '' : 'active btn-info'" ng-click="setNewForWholeOrg(false)">A specific user</button>
</div>
</td>
</tr>
</table>
</div>
<table>
<tr ng-show="!newForWholeOrg">
<td>Repository Creator:</td>
<td>
<span class="entity-search" namespace="organization.name"
placeholder="'User/Robot'"
allowed-entities="['user', 'robot']"
current-entity="activatingForNew"
clear-value="clearCounter">
</span>
</td>
</tr>
<tr>
<td>Permission:</td>
<td>
<span class="role-group" current-role="newRole" role-changed="setRoleForNew(role)"
roles="repoRoles"></span>
</td>
</tr>
<tr>
<td>Applied To:</td>
<td>
<span class="entity-search" namespace="organization.name" placeholder="'User/Robot/Team'"
current-entity="delegateForNew"
clear-value="clearCounter">
</span>
</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button ype="button" class="btn btn-primary" ng-disabled="!(newForWholeOrg || activatingForNew) || !delegateForNew" ng-click="createPrototype()">
Create Permission
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>

View file

@ -0,0 +1,25 @@
<div class="announcement inline quay-message-bar-element" ng-show="messages.length || inReadOnlyMode">
<div class="quay-service-status-description info" ng-if="inReadOnlyMode">
<div style="display: inline-block">
<span class="registry-name"></span>&nbsp;is currently in read-only mode. Pulls and other read-only operations
will succeed but all other operations are currently suspended.
</div>
</div>
<div ng-repeat="token in NotificationService.expiringAppTokens">
<div class="quay-service-status-description warning">
Your external application token <strong style="display: inline-block; padding: 4px;">{{ token.title }}</strong>
will be expiring in <strong style="display: inline-block; padding: 4px;"><time-ago datetime="token.expiration"></time-ago></strong>.
Please create a new token and revoke this token in user settings.
</div>
</div>
<div ng-repeat="message in messages">
<div class="quay-service-status-description" ng-class="message.severity">
<span ng-switch on="message.media_type">
<span ng-switch-when="text/markdown">
<markdown-view content="message.content"></markdown-view>
</span>
<span ng-switch-default>{{ message.content }}</span>
</span>
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show more