Merge branch 'master' into git

This commit is contained in:
Jimmy Zelinskie 2015-04-16 17:38:35 -04:00
commit ba2cb08904
268 changed files with 7008 additions and 1535 deletions

View file

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

View file

@ -1,11 +1,6 @@
<div class="angular-tour-ui-element"
ng-class="[tour ? 'touring' : 'nottouring', inline ? 'inline' : 'overlay']">
<div class="tour-title">
<h4><i class="fa fa-dot-circle-o"></i> {{ tour.title }}</h4>
<button type="button" class="close" ng-click="stop()" aria-hidden="true">&times;</button>
</div>
<div class="tour-contents" ng-show="!supported">
Your browser does not support features required for this tour. Please upgrade and try again.
</div>

View file

@ -1,6 +1,6 @@
<div class="application-info-element" style="padding-bottom: 18px">
<div class="auth-header">
<span class="avatar" size="48" hash="application.avatar"></span>
<span class="avatar" size="48" data="application.avatar"></span>
<h2><a href="{{ application.url }}" target="_blank">{{ application.name }}</a></h2>
<h4>
{{ application.organization.name }}

View file

@ -1,17 +1,32 @@
<div class="application-manager-element">
<div class="quay-spinner" ng-show="loading"></div>
<div class="cor-container" ng-show="!loading">
<div class="side-controls">
<span class="popup-input-button" placeholder="'Application Name'" submitted="createApplication(value)">
<i class="fa fa-plus"></i> Create New Application
</span>
<div class="cor-loader" ng-show="loading"></div>
<div ng-show="!loading">
<div class="manager-header">
<div class="side-controls">
<span class="popup-input-button" placeholder="'Application Name'"
submitted="createApplication(value)">
<i class="fa fa-plus"></i> Create New Application
</span>
</div>
<h3>OAuth Applications</h3>
</div>
<table class="table">
<div class="manager-header 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="co-table" ng-show="applications.length">
<thead>
<th>Application Name</th>
<th>Application URI</th>
<td>Application Name</td>
<td>Application URI</td>
</thead>
<tr ng-repeat="app in applications">

View file

@ -0,0 +1,56 @@
<div class="authorized-apps-manager-element">
<div class="manager-header">
<h3>Authorized Applications</h3>
</div>
<div class="manager-header 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="co-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" target="_blank"
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

@ -1 +1,12 @@
<img class="avatar-element" ng-src="{{ AvatarService.getAvatar(_hash, size) }}">
<span class="avatar-element"
ng-style="{'width': size, 'height': size, 'backgroundColor': data.color, 'fontSize': fontSize, 'lineHeight': lineHeight}"
ng-class="data.kind">
<img ng-src="//www.gravatar.com/avatar/{{ data.hash }}?d=404&size={{ size }}"
ng-if="loadGravatar"
ng-show="hasGravatar"
ng-image-watch="imageCallback(result)">
<span class="default-avatar" ng-if="!isLoading && !hasGravatar">
<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

@ -1,25 +1,26 @@
<div class="billing-invoices-element">
<div ng-show="loading">
<div class="quay-spinner"></div>
</div>
<div class="cor-loader" ng-show="loading"></div>
<div ng-show="!loading && !invoices">
No invoices have been created
</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">
<table class="table">
<div ng-show="!loading && invoices.length">
<table class="co-table">
<thead>
<th>Billing Date/Time</th>
<th>Amount Due</th>
<th>Status</th>
<th></th>
<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 ng-click="toggleInvoice(invoice.id)"><span class="invoice-datetime">{{ invoice.date * 1000 | date:'medium' }}</span></td>
<td ng-click="toggleInvoice(invoice.id)"><span class="invoice-amount">{{ invoice.amount_due / 100 }}</span></td>
<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>
@ -28,24 +29,12 @@
<span class="pending" ng-show="!invoice.paid && !invoice.attempted">Payment pending</span>
</span>
</td>
<td>
<td class="options-col">
<a ng-show="invoice.paid" href="/receipt?id={{ invoice.id }}" download="receipt.pdf" target="_new">
<i class="fa fa-download" data-title="Download Receipt" bs-tooltip="tooltip.title"></i>
</a>
</td>
</tr>
<tr ng-class="invoiceExpanded[invoice.id] ? 'in' : 'out'" class="invoice-details panel-collapse collapse">
<td colspan="3">
<dl class="dl-normal">
<dt>Billing Period</dt>
<dd>
<span>{{ invoice.period_start * 1000 | date:'mediumDate' }}</span> -
<span>{{ invoice.period_end * 1000 | date:'mediumDate' }}</span>
</dd>
</dl>
</td>
</tr>
</tbody>
</table>
</div>

View file

@ -15,4 +15,4 @@
<div class="triggered-build-description" build="build" ng-if="build.trigger"></div>
<div ng-if="!build.trigger">Manually Started Build</div>
</div>
</div>

View file

@ -4,7 +4,7 @@
<span class="error-message" bo-text="error.message"></span>
<span ng-if="error.message == 'HTTP code: 403' && getLocalPullInfo().isLocal">
caused by attempting to pull private repository <a href="/repository/{{ getLocalPullInfo().repo }}">{{ getLocalPullInfo().repo }}</a>
<span ng-if="getLocalPullInfo().login">with inaccessible crdentials</span>
<span ng-if="getLocalPullInfo().login">with inaccessible credentials</span>
<span ng-if="!getLocalPullInfo().login">without credentials</span>
</span>
</span>

View file

@ -36,4 +36,4 @@
</div>
</div>
</div>
</div>
</div>

View file

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

View file

@ -34,7 +34,7 @@
</td>
</tr>
<tr>
<td>User Creation:</td>
<td class="non-input">User Creation:</td>
<td colspan="2">
<div class="co-checkbox">
<input id="ftuc" type="checkbox" ng-model="config.FEATURE_USER_CREATION">
@ -46,6 +46,23 @@
</div>
</td>
</tr>
<tr>
<td class="non-input">Encrypted Client Password:</td>
<td colspan="2">
<div class="co-checkbox">
<input id="ftet" type="checkbox" ng-model="config.FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH">
<label for="ftet">Require Encrypted Client Passwords</label>
</div>
<div class="help-text">
If enabled, users will not be able to login from the Docker command
line with a non-encrypted password and must generate an encrypted
password to use.
</div>
<div class="help-text" ng-if="config.AUTHENTICATION_TYPE == 'LDAP'">
This feature is <strong>highly recommended</strong> for setups with LDAP authentication, as Docker currently stores passwords in <strong>plaintext</strong> on user's machines.
</div>
</td>
</tr>
</table>
</div>
</div>
@ -293,6 +310,16 @@
</p>
</div>
<div class="alert alert-warning" ng-if="config.AUTHENTICATION_TYPE == 'LDAP' && !config.FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH">
It is <strong>highly recommended</strong> to require encrypted client passwords. LDAP passwords used in the Docker client will be stored in <strong>plaintext</strong>!
<a href="javascript:void(0)" ng-click="config.FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH = true">Enable this requirement now</a>.
</div>
<div class="alert alert-success" ng-if="config.AUTHENTICATION_TYPE == 'LDAP' && config.FEATURE_REQUIRE_ENCRYPTED_BASIC_AUTH">
Note: The "Require Encrypted Client Passwords" feature is currently enabled which will
prevent LDAP passwords from being saved as plaintext by the Docker client.
</div>
<table class="config-table">
<tr>
<td class="non-input">Authentication:</td>
@ -305,7 +332,6 @@
</tr>
</table>
<table class="config-table" ng-if="config.AUTHENTICATION_TYPE == 'LDAP'">
<tr>
<td>LDAP URI:</td>
@ -406,6 +432,28 @@
</span>
</td>
</tr>
<tr>
<td>Organization Filtering:</td>
<td>
<div class="co-checkbox">
<input id="ftghlof" type="checkbox"
ng-model="config.GITHUB_LOGIN_CONFIG.ORG_RESTRICT">
<label for="ftghlof">Restrict By Organization Membership</label>
</div>
<div class="help-text" style="margin-bottom: 20px;">
If enabled, only members of specified GitHub
<span ng-if="mapped.GITHUB_LOGIN_KIND == 'enterprise'">Enterprise</span> organizations will be allowed to login via GitHub
<span ng-if="mapped.GITHUB_LOGIN_KIND == 'enterprise'">Enterprise</span>.
</div>
<span class="config-list-field"
item-title="Organization ID"
binding="config.GITHUB_LOGIN_CONFIG.ALLOWED_ORGANIZATIONS"
ng-if="config.GITHUB_LOGIN_CONFIG.ORG_RESTRICT">
</span>
</td>
</tr>
</table>
</div>
</div> <!-- /GitHub Authentication -->

View file

@ -0,0 +1,100 @@
<div class="convert-user-to-org-element">
<!-- Step 0 -->
<div class="panel" ng-show="convertStep == 0">
<div class="panel-body" ng-show="user.organizations.length > 0">
<div class="co-alert co-alert-info">
Cannot convert this account into an organization, as it is a member of {{user.organizations.length}} other
organization{{user.organizations.length > 1 ? 's' : ''}}. Please leave
{{user.organizations.length > 1 ? 'those organizations' : 'that organization'}} first.
</div>
</div>
<div class="panel-body" ng-show="user.organizations.length == 0">
<div class="co-alert co-alert-warning">
Note: Converting a user account into an organization <b>cannot be undone</b>
</div>
<button class="btn btn-primary" ng-click="showConvertForm()">Start conversion process</button>
</div>
</div>
<!-- Step 1 -->
<div class="convert-form" ng-show="convertStep == 1">
<form method="post" name="convertForm" id="convertForm" ng-submit="convertToOrg()">
<div class="form-group">
<label for="orgName">Organization Name</label>
<div class="existing-data">
<span class="avatar" size="24" data="user.avatar"></span>
{{ user.username }}</div>
<span class="description">This will continue to be the namespace for your repositories</span>
</div>
<div class="form-group">
<label for="orgName">Admin User</label>
<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>
<!-- Plans Table -->
<div class="form-group plan-group" quay-require="['BILLING']">
<label>Organization Plan</label>
<div class="plans-table" plans="orgPlans" current-plan="org.plan"></div>
</div>
<div class="button-bar">
<button class="btn btn-large btn-danger" type="submit"
ng-disabled="convertForm.$invalid || (Features.BILLING && !org.plan)"
analytics-on analytics-event="convert_to_organization">
Convert To Organization
</button>
</div>
</form>
</div>
<!-- Modal message dialog -->
<div class="modal fade" id="cannotconvertModal">
<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">Cannot convert account</h4>
</div>
<div class="modal-body">
Your account could not be converted. Please try again in a moment.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal message dialog -->
<div class="modal fade" id="reallyconvertModal">
<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">Convert to organization?</h4>
</div>
<div class="modal-body">
<div class="co-alert co-alert-danger">You will not be able to login to this account once converted!</div>
<div>Are you <b>absolutely sure</b> you would like to convert this account to an organization? Once done, there is no going back.</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal" ng-click="reallyConvert()">Absolutely: Convert Now</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>

View file

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

View file

@ -1 +1 @@
<li><a href="javascript:void(0)" ng-click="selected()"><span ng-transclude/></a></li>
<li><a href="javascript:void(0)" ng-click="selected()"><span ng-transclude/></a></li>

View file

@ -9,4 +9,4 @@
</span>
<ul class="dropdown-menu" ng-transclude></ul>
</span>
</span>
</span>

View file

@ -22,4 +22,4 @@
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</div>
</div>

View file

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

View file

@ -2,4 +2,4 @@
<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>
</div>

View file

@ -2,4 +2,4 @@
<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>
</div>

View file

@ -8,4 +8,4 @@
<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>
</div>

View file

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

View file

@ -3,4 +3,4 @@
<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>
</span>

View file

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

View file

@ -3,4 +3,4 @@
<span class="text" ng-if="text">{{ text }}</span>
<i class="fa fa-lg" ng-if="icon" ng-class="'fa-' + icon"></i>
</span>
</span>
</span>

View file

@ -1 +1 @@
<div class="co-tab-content tab-content col-md-11" ng-transclude></div>
<div class="co-tab-content tab-content col-md-11" ng-transclude></div>

View file

@ -1,3 +1,3 @@
<div class="co-main-content-panel co-tab-panel co-fx-box-shadow-heavy">
<div class="co-tab-container" ng-transclude></div>
</div>
</div>

View file

@ -1,11 +1,13 @@
<li ng-class="tabActive == 'true' ? 'active' : ''">
<a href="javascript:void(0)" data-title="{{ tabTitle }}"
data-toggle="tab"
<a href="javascript:void(0)" data-toggle="tab"
data-target="{{ tabTarget }}"
data-placement="right"
data-container="body"
ng-click="tabInit()"
bs-tooltip>
<span ng-transclude/>
ng-click="tabInit()">
<span data-title="{{ tabTitle }}"
data-placement="right"
data-container="body"
style="display:inline-block"
bs-tooltip>
<span ng-transclude/></span>
</span>
</a>
</li>
</li>

View file

@ -1 +1 @@
<ul class="co-tabs col-md-1" ng-transclude></ul>
<ul class="co-tabs col-md-1" ng-transclude></ul>

View file

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

View file

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

View file

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

View file

@ -1,38 +1,3 @@
<span class="entity-reference-element">
<span ng-if="entity.kind == 'team'">
<i class="fa fa-group" data-title="Team" bs-tooltip="tooltip.title" data-container="body"></i>
<span class="entity-name">
<span ng-if="!getIsAdmin(namespace)">{{entity.name}}</span>
<span ng-if="getIsAdmin(namespace)"><a href="/organization/{{ namespace }}/teams/{{ entity.name }}">{{entity.name}}</a></span>
</span>
</span>
<span ng-if="entity.kind == 'org'">
<span class="avatar" size="avatarSize || 16" hash="entity.avatar"></span>
<span class="entity-name">
<span ng-if="!getIsAdmin(entity.name)">{{entity.name}}</span>
<span ng-if="getIsAdmin(entity.name)"><a href="/organization/{{ entity.name }}">{{entity.name}}</a></span>
</span>
</span>
<span ng-if="entity.kind != 'team' && entity.kind != 'org'">
<span class="avatar" size="avatarSize || 16" hash="entity.avatar" ng-if="showAvatar == 'true' && entity.avatar"></span>
<span ng-if="showAvatar != 'true' || !entity.avatar">
<i class="fa fa-user" ng-show="!entity.is_robot" data-title="User" bs-tooltip="tooltip.title" data-container="body"></i>
<i class="fa fa-wrench" ng-show="entity.is_robot" data-title="Robot Account" bs-tooltip="tooltip.title" data-container="body"></i>
</span>
<span class="entity-name" ng-if="entity.is_robot">
<a href="{{ getRobotUrl(entity.name) }}" ng-if="getIsAdmin(getPrefix(entity.name))">
<span class="prefix">{{ getPrefix(entity.name) }}+</span><span>{{ getShortenedName(entity.name) }}</span>
</a>
<span ng-if="!getIsAdmin(getPrefix(entity.name))">
<span class="prefix">{{ getPrefix(entity.name) }}+</span><span>{{ getShortenedName(entity.name) }}</span>
</span>
</span>
<span class="entity-name" ng-if="!entity.is_robot">
<span>{{getShortenedName(entity.name)}}</span>
</span>
</span>
<i class="fa fa-exclamation-triangle" ng-if="entity.is_org_member === false"
data-title="This user is not a member of the organization" bs-tooltip="tooltip.title" data-container="body">
</i>
<span quay-include="{'Config.isNewLayout()': 'directives/new-entity-reference.html', '!Config.isNewLayout()': 'directives/old-entity-reference.html'}"></span>
</span>

View file

@ -6,12 +6,26 @@
<span class="caret"></span>
</button>
<ul class="dropdown-menu" ng-class="pullRight == 'true' ? 'pull-right': ''" role="menu" aria-labelledby="entityDropdownMenu">
<li ng-show="lazyLoading" style="padding: 10px"><div class="quay-spinner"></div></li>
<li ng-show="lazyLoading" style="padding: 10px"><div class="cor-loader"></div></li>
<li role="presentation" class="dropdown-header" ng-show="!lazyLoading && !robots && !isAdmin && !teams">
You do not have permission to manage teams and robots for this organization
</li>
<li role="presentation" ng-show="includeTeams && isOrganization && !lazyLoading && isAdmin">
<a role="menuitem" class="new-action" tabindex="-1" href="javascript:void(0)" ng-click="createTeam()">
<i class="fa fa-group"></i> Create team
</a>
</li>
<li role="presentation" ng-show="includeRobots && !lazyLoading && isAdmin">
<a role="menuitem" class="new-action" tabindex="-1" href="javascript:void(0)" ng-click="createRobot()">
<i class="fa fa-wrench"></i>
Create robot account
</a>
</li>
<li role="presentation" class="divider" ng-show="!lazyLoading && robots && isAdmin"></li>
<li role="presentation" class="dropdown-header"
ng-show="!lazyLoading && !teams.length && !robots.length && !((includeTeams && isOrganization && isAdmin) || (includeRobots && isAdmin))">
<span ng-if="includeRobots && includeTeams && isOrganization">
@ -35,34 +49,29 @@
</span>
</li>
<li role="presentation" ng-repeat="team in teams" ng-show="!lazyLoading"
ng-click="setEntity(team.name, 'team', false)">
<li role="presentation" class="dropdown-header" ng-show="!lazyLoading && teams">Teams</li>
<li class="menuitem" role="presentation" ng-repeat="team in teams" ng-show="!lazyLoading"
ng-click="setEntity(team.name, 'team', false, team.avatar)">
<a role="menuitem" tabindex="-1" href="javascript:void(0)">
<i class="fa fa-group"></i> <span>{{ team.name }}</span>
<span ng-if="!Config.isNewLayout()">
<i class="fa fa-group"></i> <span>{{ team.name }}</span>
</span>
<span ng-if="Config.isNewLayout()">
<span class="avatar" data="team.avatar" size="16"></span> <span>{{ team.name }}</span>
</span>
</a>
</li>
<li role="presentation" class="divider" ng-show="!lazyLoading && teams && (isAdmin || robots)"></li>
<li role="presentation" ng-repeat="robot in robots" ng-show="!lazyLoading">
<li role="presentation" class="dropdown-header" ng-show="!lazyLoading && robots">Robot Accounts</li>
<li class="menuitem" role="presentation" ng-repeat="robot in robots" ng-show="!lazyLoading">
<a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-click="setEntity(robot.name, 'user', true)">
<i class="fa fa-wrench"></i> <span>{{ robot.name }}</span>
</a>
</li>
<li role="presentation" class="divider" ng-show="!lazyLoading && robots && isAdmin"></li>
<li role="presentation" ng-show="includeTeams && isOrganization && !lazyLoading && isAdmin">
<a role="menuitem" class="new-action" tabindex="-1" href="javascript:void(0)" ng-click="createTeam()">
<i class="fa fa-group"></i> Create team
</a>
</li>
<li role="presentation" ng-show="includeRobots && !lazyLoading && isAdmin">
<a role="menuitem" class="new-action" tabindex="-1" href="javascript:void(0)" ng-click="createRobot()">
<i class="fa fa-wrench"></i>
Create robot account
</a>
</li>
</ul>
</div>
</span>

View file

@ -1,6 +1,6 @@
<span class="external-login-button-element">
<span ng-if="provider == 'github'">
<a href="javascript:void(0)" class="btn btn-primary btn-block" quay-require="['GITHUB_LOGIN']" ng-click="startSignin('github')" style="margin-bottom: 10px" ng-disabled="signingIn">
<a href="javascript:void(0)" ng-class="isLink ? '' : 'btn btn-primary btn-block'" quay-require="['GITHUB_LOGIN']" ng-click="startSignin('github')" style="margin-bottom: 10px" ng-disabled="signingIn">
<i class="fa fa-github fa-lg"></i>
<span ng-if="action != 'attach'">
Sign In with GitHub
@ -15,7 +15,7 @@
</span>
<span ng-if="provider == 'google'">
<a href="javascript:void(0)" class="btn btn-primary btn-block" quay-require="['GOOGLE_LOGIN']" ng-click="startSignin('google')" ng-disabled="signingIn">
<a href="javascript:void(0)" ng-class="isLink ? '' : 'btn btn-primary btn-block'" quay-require="['GOOGLE_LOGIN']" ng-click="startSignin('google')" ng-disabled="signingIn">
<i class="fa fa-google fa-lg"></i>
<span ng-if="action != 'attach'">Sign In with Google</span>
<span ng-if="action == 'attach'">Attach to Google Account</span>

View file

@ -0,0 +1,63 @@
<div class="external-logins-manager-element">
<div class="manager-header">
<h3>External Logins</h3>
</div>
<div class="manager-header 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>Attach/Detach</td>
</thead>
<!-- GitHub Login -->
<tr class="external-auth-provider" ng-show="Features.GITHUB_LOGIN">
<td>
<i class="fa fa-github"></i> GitHub <span ng-if="KeyService.isEnterprise('github')">Enterprise</span>
</td>
<td>
<span ng-if="hasGithubLogin">
Attached to GitHub <span ng-if="KeyService.isEnterprise('github')">Enterprise</span> account <b><a href="{{githubEndpoint}}{{githubLogin}}" target="_blank">{{githubLogin}}</a></b>
</span>
<span class="empty" ng-if="!hasGithubLogin">
(Not attached to GitHub<span ng-if="KeyService.isEnterprise('github')"> Enterprise</span>)
</span>
</td>
<td>
<span class="external-login-button" provider="github" action="attach" is-link="true"
ng-if="!hasGithubLogin"></span>
<a href="javascript:void(0)" ng-if="hasGithubLogin"
ng-click="detachExternalLogin('github')">Detach Account</a>
</td>
</tr>
<!-- Google Login -->
<tr class="external-auth-provider" ng-show="Features.GOOGLE_LOGIN">
<td>
<i class="fa fa-google"></i> Google Account
</td>
<td>
<span ng-if="hasGoogleLogin">
Attached to Google account <b>{{ googleLogin }}</b>
</span>
<span class="empty" ng-if="!hasGoogleLogin">
(Not attached to a Google account)
</span>
</td>
<td>
<span class="external-login-button" provider="google" action="attach" is-link="true"
ng-if="!hasGoogleLogin"></span>
<a href="javascript:void(0)" ng-if="hasGoogleLogin"
ng-click="detachExternalLogin('google')">Detach Account</a>
</td>
</tr>
</table>
</div>

View file

@ -0,0 +1,70 @@
<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 href="javascript:void(0)" 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"
placeholder="'Choose Pull Credentials'"
allowed-entities="['robot']"
clear-value="clearCounter"
auto-clear="false"
current-entity="currentEntity"></div>
</td>
</tr>
</table>
<div class="cor-loader-inline" ng-if="currentEntity && !currentRobot"></div>
<div ng-if="getCommand(currentFormat, currentRobot)">
Command:
<pre class="command">{{ getCommand(currentFormat, currentRobot) }}</pre>
</div>
</div>
<div class="modal-footer">
<div class="clipboard-copied-message" style="display: none">
Copied
</div>
<input type="hidden" name="command-data" id="command-data"
value="{{ getCommand(currentFormat, currentRobot) }}">
<button id="copyClipboard" type="button" class="btn btn-primary"
data-clipboard-target="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

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

View file

@ -1,78 +1,3 @@
<!-- Quay -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse" style="padding: 0px; padding-left: 4px; padding-right: 4px;">
&equiv;
</button>
<a class="navbar-brand" href="/" target="{{ appLinkTarget() }}">
<span id="quay-logo" ng-style="{'background-image': 'url(' + getEnterpriseLogo() + ')'}"></span>
</a>
</div>
<!-- Collapsable stuff -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav navbar-links">
<li><a ng-href="/tour/" target="{{ appLinkTarget() }}" quay-section="tour">Tour</a></li>
<li><a ng-href="/repository/" target="{{ appLinkTarget() }}" quay-section="repository">Repositories</a></li>
<li><a href="http://docs.quay.io/" target="_blank">Docs</a></li>
<li><a ng-href="/tutorial/" target="{{ appLinkTarget() }}" quay-section="tutorial">Tutorial</a></li>
<li quay-require="['BILLING']"><a ng-href="/plans/" target="{{ appLinkTarget() }}" quay-section="plans">Pricing</a></li>
<li><a ng-href="{{ user.organizations.length ? '/organizations/' : '/tour/organizations/' }}" target="{{ appLinkTarget() }}" quay-section="organization">Organizations</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/" class="user-view" target="{{ appLinkTarget() }}">
<span class="avatar" size="32" hash="user.avatar"></span>
{{ user.username }}
</a>
</li>
<li ng-switch-default>
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}">Sign in</a>
</li>
</ul>
<!-- Normal -->
<ul class="nav navbar-nav navbar-right hidden-xs" ng-switch on="user.anonymous">
<li>
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<span class="repo-search"></span>
</div>
</form>
<span class="navbar-left user-tools" ng-show="!user.anonymous">
<a href="/new/"><i class="fa fa-upload user-tool" bs-tooltip="tooltip.title" data-placement="bottom" data-title="Create new repository" data-container="body"></i></a>
</span>
</li>
<li class="dropdown" ng-switch-when="false">
<a href="javascript:void(0)" class="dropdown-toggle user-dropdown user-view" data-toggle="dropdown">
<span class="avatar" size="32" hash="user.avatar"></span>
{{ user.username }}
<span class="notifications-bubble"></span>
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li>
<a href="/user/" target="{{ appLinkTarget() }}">
Account Settings
</a>
</li>
<li ng-if="notificationService.notifications.length">
<a href="javascript:void(0)" data-template="/static/directives/notification-bar.html"
data-animation="am-slide-right" bs-aside="aside" data-container="body">
Notifications
<span class="notifications-bubble"></span>
</a>
</li>
<li><a ng-href="/organizations/" target="{{ appLinkTarget() }}">Organizations</a></li>
<li ng-if="user.super_user"><a href="/superuser/"><strong>Super User Admin Panel</strong></a></li>
<li><a href="javascript:void(0)" ng-click="signout()">Sign out</a></li>
</ul>
</li>
<li ng-switch-default>
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}">Sign in</a>
</li>
</ul>
</div><!-- /.navbar-collapse -->
<span class="header-bar-parent">
<span quay-include="{'Config.isNewLayout()': 'directives/new-header-bar.html', '!Config.isNewLayout()': 'directives/old-header-bar.html'}"></span>
</span>

View file

@ -30,4 +30,4 @@
</span>
</div>
</div>
</div>
</div>

View file

@ -102,4 +102,4 @@
has-changes="hasImageChanges"></div>
</span>
</div>
</div>
</div>

View file

@ -0,0 +1,2 @@
<a href="/repository/{{ repository.namespace }}/{{ repository.name }}/image/{{ imageId }}"
class="image-link-element">{{ imageId.substr(0, 12) }}</a>

View file

@ -0,0 +1,15 @@
<div class="image-view-layer-element" ng-class="getClass()">
<div class="image-id">
<a href="/repository/{{ repository.namespace }}/{{ repository.name }}/image/{{ image.id }}">
{{ image.id.substr(0, 12) }}
</a>
</div>
<div class="image-comment" ng-if="image.comment">{{ image.comment }}</div>
<div class="image-command">
<div class="nondocker-command" ng-if="!getDockerfileCommand(image.command) && image.command.length">{{ image.command.join(' ') }}</div>
<div class="dockerfile-command" command="getDockerfileCommand(image.command)"
ng-if="getDockerfileCommand(image.command)"></div>
</div>
<div class="image-layer-dot"></div>
<div class="image-layer-line"></div>
</div>

View file

@ -4,7 +4,7 @@
<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">Manully Start Build Trigger</h4>
<h4 class="modal-title">Manually Start Build Trigger</h4>
</div>
<div class="modal-body">
<div class="trigger-description" trigger="trigger"></div>

View file

@ -1,19 +1,19 @@
<span class="namespace-selector-dropdown">
<span ng-show="user.organizations.length == 0">
<span class="avatar" size="24" hash="user.avatar"></span>
<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" hash="namespaceObj.avatar"></span>
<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" href="javascript:void(0)" ng-click="setNamespace(org)">
<span class="avatar" size="24" hash="org.avatar"></span>
<span class="avatar" size="24" data="org.avatar"></span>
<span class="namespace-name">{{ org.name }}</span>
</a>
@ -25,7 +25,7 @@
<li class="divider"></li>
<li>
<a class="namespace" href="javascript:void(0)" ng-click="setNamespace(user)">
<span class="avatar" size="24" hash="user.avatar"></span>
<span class="avatar" size="24" data="user.avatar"></span>
<span class="namespace-name">{{ user.username }}</span>
</a>
</li>

View file

@ -0,0 +1,40 @@
<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)">
</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 fa-lg fa-wrench"></i>
<span class="entity-name anchor" href="{{ getRobotUrl(entity.name) }}"
is-only-text="!getIsAdmin(getPrefix(entity.name))">
<span class="prefix">{{ getPrefix(entity.name) }}+</span>
<span>{{ getShortenedName(entity.name) }}</span>
</span>
</span>
</span>
</span>
</span>

View file

@ -0,0 +1,201 @@
<div class="header-bar-element">
<div class="header-bar-content" ng-class="searchVisible ? 'search-visible' : ''">
<!-- Quay -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse" style="padding: 0px; padding-left: 4px; padding-right: 4px;">
&equiv;
</button>
<a class="navbar-brand" ng-href="{{ user.anonymous ? '/' : '/repository/' }}" target="{{ appLinkTarget() }}">
<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><a ng-href="/tour/" target="{{ appLinkTarget() }}" quay-section="tour">Tour</a></li>
<li><a ng-href="/tutorial/" target="{{ appLinkTarget() }}" quay-section="tutorial">Tutorial</a></li>
<li quay-require="['BILLING']"><a ng-href="/plans/" target="{{ appLinkTarget() }}" quay-section="plans">Pricing</a></li>
<li><a href="http://docs.quay.io/" target="_blank">Docs</a></li>
</ul>
<!-- Signed in -->
<ul class="nav navbar-nav navbar-links" ng-if="!user.anonymous">
<li><a ng-href="/repository/" target="{{ appLinkTarget() }}" quay-section="repository">Repositories</a></li>
<li><a ng-href="/tutorial/" target="{{ appLinkTarget() }}" quay-section="tutorial">Tutorial</a></li>
<li><a href="http://docs.quay.io/" target="_blank">Docs</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/" class="user-view" target="{{ appLinkTarget() }}">
<span class="avatar" size="32" data="user.avatar"></span>
{{ user.username }}
</a>
</li>
<li ng-switch-default>
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}">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">
<i class="fa fa-search fa-lg user-tool" ng-click="toggleSearch()"
data-placement="bottom" data-title="Search - Keyboard Shortcut: /" bs-tooltip></i>
</span>
</li>
<li>
<span class="navbar-left user-tools with-menu" ng-show="!user.anonymous">
<span class="dropdown">
<a href="javascript:void(0)" class="dropdown-toggle new-menu" data-toggle="dropdown">
<i class="fa fa-plus user-tool"
data-placement="bottom" data-title="Create New..." 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 href="javascript:void(0)" ng-click="createTeam(currentPageContext)">
<i class="fa fa-group"></i> New Team
</a>
</li>
<li ng-if="canAdmin(getNamespace(currentPageContext))">
<a href="javascript:void(0)" ng-click="createRobot(currentPageContext)">
<i class="fa fa-wrench"></i> New Robot Account
</a>
</li>
<li role="presentation" class="divider" ng-if="currentPageContext.repository"></li>
<li role="presentation" class="dropdown-header"
ng-if="currentPageContext.repository">
Repository {{ currentPageContext.repository.namespace }}/{{ currentPageContext.repository.name }}
</li>
<li ng-if="currentPageContext.repository">
<a href="javascript:void(0)" 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" ng-show="!user.anonymous">
<a href="javascript:void(0)" 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>
</a>
<span class="notifications-bubble"></span>
</span>
</li>
<li class="dropdown" ng-switch-when="false">
<a href="javascript:void(0)" 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" target="{{ appLinkTarget() }}" ng-if="isNewLayout">
Account Settings
</a>
<a href="/user/" target="{{ appLinkTarget() }}" ng-if="!isNewLayout">
Account Settings
</a>
</li>
<li ng-if="user.super_user"><a href="/superuser/"><strong>Super User Admin Panel</strong></a></li>
<li><a href="javascript:void(0)" ng-click="signout()">Sign out</a></li>
</ul>
</li>
<li ng-switch-default>
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}">Sign in</a>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div>
<div class="search-box" ng-class="getSearchBoxClasses(searchVisible, searchResultState)">
<div class="search-label">Search For</div>
<div class="search-box-wrapper">
<input id="search-box-input" type="text" placeholder="(Enter Search Terms)"
ng-model-options="{'debounce': 250}" ng-model="currentSearchQuery"
debounce="250"
ng-keydown="handleSearchKeyDown($event)">
</div>
</div>
<div class="search-results"
ng-class="searchVisible && searchResultState ? searchResultState.state : ''"
ng-class="{'height': (searchResultState.results.length * 40) + 28}">
<div class="cor-loader" ng-if="searchResultState.state == 'loading'"></div>
<div ng-if="searchResultState.state == 'no-results'">No matching results found</div>
<ul ng-if="searchResultState.state == 'results'">
<li ng-repeat="result in searchResultState.results" ng-mouseover="setCurrentResult($index)"
ng-class="searchResultState.current == $index ? 'current' : ''"
ng-click="showResult(result)">
<span class="kind">{{ result.kind }}</span>
<span class="score">{{ result.score }}</span>
<span ng-switch on="result.kind">
<!-- Team -->
<span ng-switch-when="team">
<strong>
<span class="avatar" data="result.avatar" size="16"></span>
<span class="result-name">{{ result.name }}</span>
</strong>
<span class="clarification">
under organization
<span class="avatar" data="result.organization.avatar" size="16"></span>
<span class="result-name">{{ result.organization.name }}</span>
</span>
</span>
<span ng-switch-when="user">
<span class="avatar" data="result.avatar" size="16"></span>
<span class="result-name">{{ result.name }}</span>
</span>
<span ng-switch-when="organization">
<span class="avatar" data="result.avatar" size="16"></span>
<span class="result-name">{{ result.name }}</span>
</span>
<span href="/user/{{ result.name }}" ng-switch-when="robot">
<i class="fa fa-wrench"></i>
<span class="result-name">{{ result.name }}</span>
</span>
<span ng-switch-when="repository">
<span class="avatar" data="result.namespace.avatar" size="16"></span>
<span class="result-name">{{ result.namespace.name }}/{{ result.name }}</span>
<div class="description" ng-if="result.description">
{{ result.description }}
</div>
</span>
</span>
</li>
</ul>
</div>
<div class="dockerfile-build-dialog"
show-now="showBuildDialogCounter"
repository="currentPageContext.repository"
build-started="handleBuildStarted(build, currentPageContext)">
</div>
</div>

View file

@ -3,7 +3,7 @@
<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" hash="getAvatar(notification.organization)"></span>
<span class="avatar" size="24" data="getAvatar(notification.organization)"></span>
<span class="orgname">{{ notification.organization }}</span>
</div>
</div>

View file

@ -0,0 +1,39 @@
<!-- DEPRECATED! -->
<span class="old-entity-reference">
<span ng-if="entity.kind == 'team'">
<i class="fa fa-group" data-title="Team" bs-tooltip="tooltip.title" data-container="body"></i>
<span class="entity-name">
<span ng-if="!getIsAdmin(namespace)">{{entity.name}}</span>
<span ng-if="getIsAdmin(namespace)"><a href="/organization/{{ namespace }}/teams/{{ entity.name }}">{{entity.name}}</a></span>
</span>
</span>
<span ng-if="entity.kind == 'org'">
<span class="avatar" size="avatarSize || 16" data="entity.avatar"></span>
<span class="entity-name">
<span ng-if="!getIsAdmin(entity.name)">{{entity.name}}</span>
<span ng-if="getIsAdmin(entity.name)"><a href="/organization/{{ entity.name }}">{{entity.name}}</a></span>
</span>
</span>
<span ng-if="entity.kind != 'team' && entity.kind != 'org'">
<span class="avatar" size="avatarSize || 16" data="entity.avatar" ng-if="showAvatar == 'true' && entity.avatar"></span>
<span ng-if="showAvatar != 'true' || !entity.avatar">
<i class="fa fa-user" ng-show="!entity.is_robot" data-title="User" bs-tooltip="tooltip.title" data-container="body"></i>
<i class="fa fa-wrench" ng-show="entity.is_robot" data-title="Robot Account" bs-tooltip="tooltip.title" data-container="body"></i>
</span>
<span class="entity-name" ng-if="entity.is_robot">
<a href="{{ getRobotUrl(entity.name) }}" ng-if="getIsAdmin(getPrefix(entity.name))">
<span class="prefix">{{ getPrefix(entity.name) }}+</span><span>{{ getShortenedName(entity.name) }}</span>
</a>
<span ng-if="!getIsAdmin(getPrefix(entity.name))">
<span class="prefix">{{ getPrefix(entity.name) }}+</span><span>{{ getShortenedName(entity.name) }}</span>
</span>
</span>
<span class="entity-name" ng-if="!entity.is_robot">
<span>{{getShortenedName(entity.name)}}</span>
</span>
</span>
<i class="fa fa-exclamation-triangle" ng-if="entity.is_org_member === false"
data-title="This user is not a member of the organization" bs-tooltip="tooltip.title" data-container="body">
</i>
</span>

View file

@ -0,0 +1,78 @@
<!-- Quay -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse" style="padding: 0px; padding-left: 4px; padding-right: 4px;">
&equiv;
</button>
<a class="navbar-brand" href="/" target="{{ appLinkTarget() }}">
<span id="quay-logo" ng-style="{'background-image': 'url(' + getEnterpriseLogo() + ')'}"></span>
</a>
</div>
<!-- Collapsable stuff -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav navbar-links">
<li><a ng-href="/tour/" target="{{ appLinkTarget() }}" quay-section="tour">Tour</a></li>
<li><a ng-href="/repository/" target="{{ appLinkTarget() }}" quay-section="repository">Repositories</a></li>
<li><a href="http://docs.quay.io/" target="_blank">Docs</a></li>
<li><a ng-href="/tutorial/" target="{{ appLinkTarget() }}" quay-section="tutorial">Tutorial</a></li>
<li quay-require="['BILLING']"><a ng-href="/plans/" target="{{ appLinkTarget() }}" quay-section="plans">Pricing</a></li>
<li><a ng-href="{{ user.organizations.length ? '/organizations/' : '/tour/organizations/' }}" target="{{ appLinkTarget() }}" quay-section="organization">Organizations</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/" class="user-view" target="{{ appLinkTarget() }}">
<span class="avatar" size="32" data="user.avatar"></span>
{{ user.username }}
</a>
</li>
<li ng-switch-default>
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}">Sign in</a>
</li>
</ul>
<!-- Normal -->
<ul class="nav navbar-nav navbar-right hidden-xs" ng-switch on="user.anonymous">
<li>
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<span class="repo-search"></span>
</div>
</form>
<span class="navbar-left user-tools" ng-show="!user.anonymous">
<a href="/new/"><i class="fa fa-upload user-tool" bs-tooltip="tooltip.title" data-placement="bottom" data-title="Create new repository" data-container="body"></i></a>
</span>
</li>
<li class="dropdown" ng-switch-when="false">
<a href="javascript:void(0)" class="dropdown-toggle user-dropdown user-view" data-toggle="dropdown">
<span class="avatar" size="32" data="user.avatar"></span>
{{ user.username }}
<span class="notifications-bubble"></span>
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li>
<a href="/user/" target="{{ appLinkTarget() }}">
Account Settings
</a>
</li>
<li ng-if="notificationService.notifications.length">
<a href="javascript:void(0)" data-template="/static/directives/notification-bar.html"
data-animation="am-slide-right" bs-aside="aside" data-container="body">
Notifications
<span class="notifications-bubble"></span>
</a>
</li>
<li><a ng-href="/organizations/" target="{{ appLinkTarget() }}">Organizations</a></li>
<li ng-if="user.super_user"><a href="/superuser/"><strong>Super User Admin Panel</strong></a></li>
<li><a href="javascript:void(0)" ng-click="signout()">Sign out</a></li>
</ul>
</li>
<li ng-switch-default>
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}">Sign in</a>
</li>
</ul>
</div><!-- /.navbar-collapse -->

View file

@ -1,5 +1,5 @@
<div class="organization-header-element">
<span class="avatar" size="24" hash="organization.avatar"></span>
<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>

View file

@ -3,23 +3,23 @@
<div class="quay-spinner 3x" ng-show="planLoading"></div>
<!-- Alerts -->
<div class="alert alert-danger" ng-show="limit == 'over' && !planLoading">
<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="alert alert-warning" ng-show="limit == 'at' && !planLoading">
<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="alert alert-success" ng-show="limit == 'near' && !planLoading">
<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="alert alert-success" ng-show="subscription.trialEnd != null" style="font-size: 125%">
<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>

View file

@ -16,12 +16,12 @@
</ul>
<div class="hidden-xs">
<table class="table table-hover plans-table-table" ng-show="plans">
<table class="co-table plans-table-table" ng-show="plans">
<thead>
<th>Plan</th>
<th>Private Repositories</th>
<th style="min-width: 85px">Price</th>
<th></th>
<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' : ''">

View file

@ -1,4 +1,4 @@
<button class="btn btn-success" data-trigger="click"
<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>

View file

@ -1,54 +1,74 @@
<div class="prototype-manager-element">
<div class="quay-spinner" ng-show="loading"></div>
<div class="cor-container" ng-show="!loading">
<div class="alert alert-info">
Default permissions provide a means of specifying <span class="context-tooltip" data-title="By default, all repositories have the creating user added as an 'Admin'" bs-tooltip="tooltip.title">additional</span> permissions that should be granted automatically to a repository <strong>when it is created</strong>.
<div class="cor-loader" ng-show="loading"></div>
<div ng-show="!loading">
<div class="manager-header">
<div class="side-controls">
<button class="btn btn-primary" ng-click="showAddDialog()">
<i class="fa fa-plus"></i>
Create Default Permission
</button>
</div>
<h3>Default Permissions</h3>
</div>
<div class="side-controls">
<button class="btn btn-success" ng-click="showAddDialog()">
<i class="fa fa-plus"></i>
New Default Permission
</button>
<div class="manager-header 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>
<table class="table">
<div class="empty" ng-if="!prototypes.length">
<div class="empty-primary-msg">No default permissions defined.</div>
<div class="empty-secondary-msg">
Click the "Create Default Permission" button above to create a new default permission.
</div>
</div>
<table class="co-table" ng-show="prototypes.length">
<thead>
<th>
<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."
bs-tooltip="tooltip.title" data-container="body">
Repository Creator
data-container="body" bs-tooltip>
Repository Created By
</span>
</th>
<th>
<span class="context-tooltip" data-title="The user, robot or team that is being granted the permission"
bs-tooltip="tooltip.title" data-container="body">
Applies To User/Robot/Team
</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>
</th>
<th>Permission</th>
<th style="width: 150px"></th>
</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-show="prototype.activating_user"></span>
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;">
<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"></span>
<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="roles"></span>
</td>
<td>
<span class="delete-ui" delete-title="'Delete Permission'" perform-delete="deletePrototype(prototype)"></span>
<td class="options-col">
<span class="cor-options-menu">
<span class="cor-option" option-click="deletePrototype(prototype)">
<i class="fa fa-times"></i> Delete Permission
</span>
</span>
</td>
</tr>
</table>

View file

@ -72,4 +72,4 @@
<h4>Network Usage (Bytes)</h4>
<div class="realtime-line-chart" data="data.count.network" labels="['Bytes In', 'Bytes Out']" counter="counter"></div>
</div>
</div>
</div>

View file

@ -10,4 +10,4 @@
<i class="fa fa-calendar" style="margin-right: 6px;"></i>
<a ng-href="{{ scheduled.shortlink }}" class="quay-service-status-description">{{ scheduled.name }}</a>
</div>
</div>
</div>

View file

@ -3,4 +3,4 @@
ng-if="indicator != 'loading'"></span>
<span class="cor-loader-inline" ng-if="indicator == 'loading'"></span>
<a href="http://status.quay.io" class="quay-service-status-description">{{ description }}</a>
</span>
</span>

View file

@ -3,4 +3,4 @@
<div class="chart"></div>
</div>
<div class="cor-loader-inline" ng-if="counter < 1"></div>
</div>
</div>

View file

@ -3,4 +3,4 @@
<div class="chart"></div>
</div>
<div class="cor-loader-inline" ng-if="counter < 1"></div>
</div>
</div>

View file

@ -2,15 +2,18 @@
<div class="new-repo-listing">
<!-- Titles -->
<div ng-if="starred" class="repo-list-title">
<i class="fa fa-star starred"></i>
Starred
</div>
<div ng-if="!starred" class="repo-list-title">
<span class="avatar" size="24" hash="namespace.avatar"></span>
<span ng-if="!isOrganization(namespace.name)">{{ namespace.name }}</span>
<a ng-if="isOrganization(namespace.name)"
href="/organization/{{ namespace.name }}">{{ namespace.name }}</a>
<div ng-if="!hideTitle">
<div ng-if="starred" class="repo-list-title">
<i class="fa fa-star starred"></i>
Starred
</div>
<div ng-if="!starred" class="repo-list-title">
<span class="avatar" size="24" data="namespace.avatar"></span>
<a ng-if="!isOrganization(namespace.name)"
href="/user/{{ namespace.name }}">{{ namespace.name }}</a>
<a ng-if="isOrganization(namespace.name)"
href="/organization/{{ namespace.name }}">{{ namespace.name }}</a>
</div>
</div>
<!-- Repositories -->

View file

@ -2,4 +2,4 @@
<i ng-class="repository.is_starred ? 'starred fa fa-star' : 'fa fa-star-o'"
class="star-icon" ng-click="toggleStar()">
</i>
</span>
</span>

View file

@ -37,16 +37,19 @@
<table class="co-table" ng-if="fullBuilds.length">
<thead>
<td class="status-col"></td>
<td ng-class="tablePredicateClass('id', options.predicate, options.reverse)">
<td ng-class="tablePredicateClass('id', options.predicate, options.reverse)"
style="min-width: 85px;">
<a href="javascript:void(0)" ng-click="orderBy('id')">Build ID</a>
</td>
<td ng-class="tablePredicateClass('commit_sha', options.predicate, options.reverse)">
<td ng-class="tablePredicateClass('commit_sha', options.predicate, options.reverse)"
style="min-width: 115px">
<a href="javascript:void(0)" ng-click="orderBy('commit_sha')">Triggered By</a>
</td>
<td ng-class="tablePredicateClass('started_datetime', options.predicate, options.reverse)">
<td ng-class="tablePredicateClass('started_datetime', options.predicate, options.reverse)" style="min-width: 120px;">
<a href="javascript:void(0)" ng-click="orderBy('started_datetime')">Date Started</a>
</td>
<td ng-class="tablePredicateClass('tags', options.predicate, options.reverse)">
<td ng-class="tablePredicateClass('tags', options.predicate, options.reverse)"
style="min-width: 66px;">
<a href="javascript:void(0)" ng-click="orderBy('tags')">Tags</a>
</td>
<td class="options-col"></td>
@ -63,7 +66,7 @@
<td>{{ build.started | amCalendar }}</td>
<td>
<span class="building-tag" ng-repeat="tag in build.building_tags">
<i class="fa fa-tag"></i>{{ tag }}
<span class="tag-span"><i class="fa fa-tag"></i>{{ tag }}</span>
</span>
</td>
</tr>
@ -140,7 +143,8 @@
<span class="cor-option" option-click="showTriggerCredentialsModal(trigger)" ng-show="trigger.service == 'custom'">
<i class="fa fa-unlock-alt"></i> View Credentials
</span>
<span class="cor-option" option-click="askRunTrigger(trigger)">
<span class="cor-option" option-click="askRunTrigger(trigger)"
ng-class="trigger.connected_user == user.username ? '' : 'disabled'">
<i class="fa fa-chevron-right"></i> Run Trigger Now
</span>
<span class="cor-option" option-click="askDeleteTrigger(trigger)">

View file

@ -48,7 +48,8 @@
<!-- Builds -->
<div ng-if="builds && builds.length">
<div class="build-mini-status" ng-repeat="build in builds" build="build"></div>
<div class="build-mini-status" ng-repeat="build in builds" build="build"
is-admin="repository.can_admin"></div>
</div>
<!-- View All -->
@ -61,7 +62,14 @@
<!-- Repository Description -->
<div class="description-container">
<!-- Pull Controls -->
<div class="right-controls hidden-sm hidden-xs">
Pull Full Repository: <div class="copy-box" hovering-message="true" value="pullCommand"></div>
</div>
<h4 style="font-size:20px;">Description</h4>
<div class="description markdown-input"
content="repository.description"
can-write="repository.can_write"

View file

@ -4,7 +4,7 @@
<!-- User/Team Permissions -->
<div class="co-panel">
<div class="co-panel-heading"><i class="fa fa-key"></i> User and Robot Permissions</div>
<div class="panel-body">
<div class="panel-body" style="padding-top: 5px;">
<div class="repository-permissions-table" repository="repository"></div>
</div>
</div>
@ -12,7 +12,7 @@
<!-- Access Tokens (DEPRECATED) -->
<div class="co-panel" ng-show="hasTokens">
<div class="co-panel-heading"><i class="fa fa-key"></i> Access Token Permissions</div>
<div class="panel-body">
<div class="panel-body" style="padding-top: 5px;">
<div class="repository-tokens-table" repository="repository" has-tokens="hasTokens"></div>
</div>
</div>
@ -49,11 +49,15 @@
<!-- Delete Repository -->
<div class="panel-body panel-section">
<div>Deleting a repository <b>cannot be undone</b>. Here be dragons!</div>
<button class="btn btn-danger" ng-click="askDelete()">
<i class="fa fa-trash"></i>
Delete Repository
</button>
<div class="co-alert co-alert-danger">
<button class="btn btn-danger" style="float: right; margin-top: -7px;"
ng-click="askDelete()">
<i class="fa fa-trash"></i>
Delete Repository
</button>
Deleting a repository <b>cannot be undone</b>. Here be dragons!
</div>
</div>
<!-- Build Status Badge -->

View file

@ -1,6 +1,72 @@
<div class="repo-panel-tags-element">
<div class="tab-header-controls">
<div class="btn-group btn-group-sm" ng-show="repository.can_write">
<button class="btn" ng-class="!showingHistory ? 'btn-primary active' : 'btn-default'" ng-click="showHistory(false)">
<i class="fa fa-tags"></i>Current Tags
</button>
<button class="btn" ng-class="showingHistory ? 'btn-info active' : 'btn-default'" ng-click="showHistory(true)">
<i class="fa fa-history"></i>History
</button>
</div>
</div>
<h3 class="tab-header">Repository Tags</h3>
<div class="resource-view" resource="imagesResource" error-message="'Could not load images'">
<!-- History view -->
<div ng-show="showingHistory">
<div ng-show="showingHistory">
<div class="cor-loader" ng-if="!tagHistoryData"></div>
</div>
<div style="height: 40px;">
<span class="co-filter-box" style="float:right">
<input class="form-control" type="text" ng-model="options.historyFilter" placeholder="Filter History...">
</span>
</div>
<div class="history-list">
<div class="empty" ng-if="!tagHistoryData.length">
<div class="empty-primary-msg">This repository is empty.</div>
<div class="empty-secondary-msg">Push a tag or initiate a build to populate this repository.</div>
</div>
<div class="history-entry" ng-repeat="entry in tagHistoryData"
ng-class="getEntryClasses(entry, options.historyFilter)">
<div class="history-date-break" ng-if="entry.date_break">
{{ entry.date | amDateFormat:'dddd, MMMM Do YYYY' }}
</div>
<div ng-if="!entry.date_break">
<div class="history-icon"></div>
<div class="history-text">
<div class="history-description">
<span class="tag-span"
ng-class="isChecked(entry.tag_name, checkedTags.checked) ? 'checked' : ''"
ng-click="showHistory(true, entry.tag_name)">{{ entry.tag_name }}</span>
<span ng-switch on="entry.action">
<span ng-switch-when="create">
was created pointing to image <span class="image-link" repository="repository" image-id="entry.docker_image_id"></span>
</span>
<span ng-switch-when="delete">
was deleted
</span>
<span ng-switch-when="move">
was moved to image
<span class="image-link" repository="repository" image-id="entry.docker_image_id"></span>
from image
<span class="image-link" repository="repository" image-id="entry.old_docker_image_id"></span>
</span>
</span>
</div>
<div class="history-datetime">{{ entry.time | amDateFormat:'dddd, MMMM Do YYYY, h:mm:ss a' }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- Normal View -->
<div class="resource-view" resource="imagesResource" error-message="'Could not load images'"
ng-show="!showingHistory">
<div class="co-check-bar">
<span class="cor-checkable-menu" controller="checkedTags">
<div class="cor-checkable-menu-item" item-filter="allTagFilter">
@ -23,7 +89,12 @@
<a href="javascript:void(0)" class="btn btn-default" ng-click="setTab('changes')">
<i class="fa fa-code-fork"></i> Visualize
</a>
<button class="btn btn-default"
<a href="javascript:void(0)" class="btn btn-default"
ng-click="showHistory(true, getTagNames(checkedTags.checked))"
ng-if="repository.can_write">
<i class="fa fa-history"></i> View History
</a>
<button class="btn btn-primary"
ng-click="askDeleteMultipleTags(checkedTags.checked)"
ng-if="repository.can_write">
<i class="fa fa-times"></i> Delete
@ -41,33 +112,35 @@
<td ng-class="tablePredicateClass('name', options.predicate, options.reverse)">
<a href="javascript:void(0)" ng-click="orderBy('name')">Tag</a>
</td>
<td ng-class="tablePredicateClass('last_modified_datetime', options.predicate, options.reverse)">
<td ng-class="tablePredicateClass('last_modified_datetime', options.predicate, options.reverse)"
style="min-width: 120px;">
<a href="javascript:void(0)" ng-click="orderBy('last_modified_datetime')">Last Modified</a>
</td>
<td ng-class="tablePredicateClass('size', options.predicate, options.reverse)">
<td ng-class="tablePredicateClass('size', options.predicate, options.reverse)"
style="min-width: 62px;">
<a href="javascript:void(0)" ng-click="orderBy('size')">Size</a>
</td>
<td ng-class="tablePredicateClass('image_id', options.predicate, options.reverse)"
colspan="{{ imageTracks.length + 1 }}">
colspan="{{ imageTracks.length + 1 }}"
style="min-width: 120px;">
<a href="javascript:void(0)" ng-click="orderBy('image_id')">Image</a>
</td>
<td class="options-col"></td>
<td class="options-col"></td>
</thead>
<tr class="co-checkable-row"
ng-repeat="tag in tags"
ng-class="checkedTags.isChecked(tag, checkedTags.checked) ? 'checked' : ''">
<td><span class="cor-checkable-item" controller="checkedTags" item="tag"></span></td>
<td><i class="fa fa-tag"></i> {{ tag.name }}</td>
<td><span class="tag-span"><i class="fa fa-tag"></i> {{ tag.name }}</span></td>
<td>
<span am-time-ago="tag.last_modified" ng-if="tag.last_modified"></span>
<span ng-if="!tag.last_modified">Unknown</span>
</td>
<td>{{ tag.size | bytes }}</td>
<td class="image-id-col">
<a ng-href="/repository/{{ repository.namespace }}/{{ repository.name }}/image/{{ tag.image_id }}">
{{ tag.image_id.substr(0, 12) }}
</a>
<span class="image-link" repoository="repository" image-id="tag.image_id"></span>
</td>
<td class="image-track" ng-repeat="it in imageTracks">
<span class="image-track-dot" ng-if="it.image_id == tag.image_id"
@ -75,11 +148,23 @@
<span class="image-track-line" ng-class="trackLineClass($parent.$index, it)"
ng-style="{'borderColor': it.color}"></span>
</td>
<td class="options-col">
<i class="fa fa-download" data-title="Fetch Tag" bs-tooltip
ng-click="fetchTagActionHandler.askFetchTag(tag)">
</i>
</td>
<td class="options-col">
<span class="cor-options-menu" ng-if="repository.can_write">
<span class="cor-option" option-click="showHistory(true, tag.name)"
ng-if="tag.last_modified">
<i class="fa fa-history"></i> View Tag History
</span>
<span class="cor-option" option-click="askDeleteTag(tag.name)">
<i class="fa fa-times"></i> Delete Tag
</span>
<span class="cor-option" option-click="askAddTag(tag)">
<i class="fa fa-plus"></i> Add New Tag
</span>
</span>
</td>
</tr>
@ -98,4 +183,7 @@
</div>
<div class="tag-operations-dialog" repository="repository" images="images"
action-handler="tagActionHandler"></div>
action-handler="tagActionHandler"></div>
<div class="fetch-tag-dialog" repository="repository" action-handler="fetchTagActionHandler">
</div>

View file

@ -14,7 +14,7 @@
error-message="'Could not load repository events'">
<div class="empty" ng-if="!notifications.length">
<div class="empty-primary-msg">No notification have been setup for this repository.</div>
<div class="empty-primary-msg">No notifications have been setup for this repository.</div>
<div class="empty-secondary-msg" ng-if="repository.can_write">
Click the "Create Notification" button above to add a new notification for a repository event.
</div>
@ -72,4 +72,4 @@
repository="repository"
counter="showNewNotificationCounter"
notification-created="handleNotificationCreated(notification)"></div>
</div>
</div>

View file

@ -2,7 +2,7 @@
<div class="resource-view"
resources="[permissionResources.team, permissionResources.user]"
error-message="'Could not load repository permissions'">
<table class="co-table permissions">
<table class="co-table no-lines permissions">
<thead>
<tr>
<td>Account Name</td>
@ -11,11 +11,27 @@
</tr>
</thead>
<tr ng-show="!hasPermissions(permissionResources.team, permissionResources.user)">
<td colspan="3">
<div class="empty">
<div class="empty-primary-msg">No permissions found.</div>
<div class="empty-secondary-msg">
To add a permission, enter the information below and click "Add Permission".
</div>
</div>
</td>
</tr>
<!-- Team Permissions -->
<tr ng-repeat="(name, permission) in permissionResources.team.value">
<tr class="co-table-header-row"
ng-if="(permissionResources.team.value | objectFilter:allEntries).length">
<td colspan="3"><i class="fa fa-group"></i> Team Permissions</td>
</tr>
<tr class="indented-row" ng-repeat="(name, permission) in permissionResources.team.value">
<td class="team entity">
<span class="entity-reference" namespace="repository.namespace"
entity="buildEntityForPermission(name, permission, 'team')">
entity="buildEntityForPermission(permission, 'team')"
avatar-size="24">
</span>
</td>
<td class="user-permissions">
@ -32,26 +48,66 @@
</tr>
<!-- User Permissions -->
<tr ng-repeat="(name, permission) in permissionResources.user.value">
<td class="{{ 'user entity ' + (permission.is_org_member ? '' : 'outside') }}">
<tr class="co-table-header-row"
ng-if="(permissionResources.user.value | objectFilter:onlyUser).length">
<td colspan="3"><i class="fa fa-user"></i> User Permissions</td>
</tr>
<tr class="indented-row"
ng-repeat="permission in (permissionResources.user.value | objectFilter:onlyUser)">
<td class="user-permission-entity">
<span class="entity-reference" namespace="repository.namespace"
entity="buildEntityForPermission(name, permission, 'user')">
entity="buildEntityForPermission(permission, 'user')"
avatar-size="24">
</span>
<i class="fa fa-exclamation-triangle outside-org"
ng-if="permission.is_org_member === false"
data-title="This user is not a member of the organization" bs-tooltip></i>
</td>
<td class="user-permissions">
<div class="btn-group btn-group-sm">
<span class="role-group" current-role="permission.role" role-changed="setRole(role, name, 'user')" roles="roles"></span>
<span class="role-group" current-role="permission.role"
role-changed="setRole(role, permission.name, 'user')" roles="roles"></span>
</div>
</td>
<td class="options-col">
<span class="cor-options-menu">
<span class="cor-option" option-click="deleteRole(name, 'user')">
<span class="cor-option" option-click="deleteRole(permission.name, 'user')">
<i class="fa fa-times"></i> Delete Permission
</span>
</span>
</td>
</tr>
<!-- Robot Permissions -->
<tr class="co-table-header-row"
ng-if="(permissionResources.user.value | objectFilter:onlyRobot).length">
<td colspan="3"><i class="fa fa-wrench"></i> Robot Account Permissions</td>
</tr>
<tr class="indented-row"
ng-repeat="permission in (permissionResources.user.value | objectFilter:onlyRobot)">
<td class="user-permission-entity">
<span class="entity-reference" namespace="repository.namespace"
entity="buildEntityForPermission(permission, 'user')"
avatar-size="24">
</span>
</td>
<td class="user-permissions">
<div class="btn-group btn-group-sm">
<span class="role-group" current-role="permission.role"
role-changed="setRole(role, permission.name, 'user')" roles="roles"></span>
</div>
</td>
<td class="options-col">
<span class="cor-options-menu">
<span class="cor-option" option-click="deleteRole(permission.name, 'user')">
<i class="fa fa-times"></i> Delete Permission
</span>
</span>
</td>
</tr>
<tr class="add-row-spacer"><td colspan="3"></td></tr>
<tr class="add-row">
<td id="add-entity-permission" class="admin-search">
<span class="entity-search" namespace="repository.namespace"
@ -79,4 +135,4 @@
dialog-action-title="Grant Permission">
The selected user is outside of your organization. Are you sure you want to grant the user access to this repository?
</div>
</div>
</div>

View file

@ -32,4 +32,4 @@
</tbody>
</table>
</div>
</div>
</div>

View file

@ -1,32 +1,130 @@
<div class="robots-manager-element">
<div class="quay-spinner" ng-show="loading"></div>
<div class="alert alert-info">Robot accounts allow for delegating access in multiple repositories to role-based accounts that you manage</div>
<div class="cor-loader" ng-show="loading"></div>
<div ng-show="!loading">
<div class="side-controls">
<span class="popup-input-button" pattern="ROBOT_PATTERN" placeholder="'Robot Account Name'"
submitted="createRobot(value)">
<i class="fa fa-wrench"></i> Create Robot Account
</span>
<div class="manager-header">
<div class="side-controls">
<span class="popup-input-button" pattern="ROBOT_PATTERN"
placeholder="'Robot Account Name'"
submitted="createRobot(value)">
<i class="fa fa-plus"></i> Create Robot Account
</span>
</div>
<h3>Robot Accounts</h3>
</div>
<table class="table">
<div class="manager-header section-description-header">
Robot Accounts are named tokens that can be granted permissions on multiple repositories
under this <span ng-if="organization">organization</span><span ng-if="!organization">user namespace</span>. They are typically used in environments where credentials will
be shared, such as deployment systems.
</div>
<span class="co-filter-box" ng-show="robots.length">
<input class="form-control" type="text" ng-model="robotFilter" placeholder="Filter Robot Accounts...">
</span>
<div class="empty" ng-if="!robots.length">
<div class="empty-primary-msg">No robot accounts defined.</div>
<div class="empty-secondary-msg">
Click the "Create Robot Account" button above to create a robot account.
</div>
</div>
<div class="empty" ng-if="robots.length && !(robots | filter:robotFilter).length">
<div class="empty-primary-msg">No robot accounts found matching filter.</div>
<div class="empty-secondary-msg">
Please change your filter to display robot accounts.
</div>
</div>
<table class="co-table" ng-if="(robots | filter:robotFilter).length">
<thead>
<th>Robot Account Name</th>
<th style="width: 150px"></th>
<td class="caret-col" ng-if="(user || organization.is_admin) && Config.isNewLayout()"></td>
<td>Robot Account Name</td>
<td ng-if="organization && Config.isNewLayout()">Teams</td>
<td ng-if="Config.isNewLayout()">Repository Permissions</td>
<td class="options-col"></td>
</thead>
<tr ng-repeat="robotInfo in robots">
<td class="robot">
<i class="fa fa-wrench"></i>
<a ng-click="showRobot(robotInfo)">
<span class="prefix">{{ getPrefix(robotInfo.name) }}+</span>{{ getShortenedName(robotInfo.name) }}
</a>
</td>
<td>
<span class="delete-ui" delete-title="'Delete Robot Account'" perform-delete="deleteRobot(robotInfo)"></span>
</td>
</tr>
<tbody ng-repeat="robotInfo in robots | filter:robotFilter | orderBy:getShortenedRobotName">
<tr ng-class="robotInfo.showing_permissions ? 'open' : 'closed'">
<td class="caret-col" ng-if="(user || organization.is_admin) && Config.isNewLayout()">
<span ng-if="robotInfo.repositories.length > 0" ng-click="showPermissions(robotInfo)">
<i class="fa"
ng-class="robotInfo.showing_permissions ? 'fa-caret-down' : 'fa-caret-right'"
data-title="View Permissions List" bs-tooltip></i>
</span>
</td>
<td class="robot">
<i class="fa fa-wrench"></i>
<a ng-click="showRobot(robotInfo)">
<span class="prefix">{{ getPrefix(robotInfo.name) }}+</span>{{ getShortenedName(robotInfo.name) }}
</a>
</td>
<td ng-if="organization && Config.isNewLayout()">
<span class="empty" ng-if="robotInfo.teams.length == 0">
(Not a member of any team)
</span>
<span class="empty" ng-if="robotInfo.teams.length > 0">
<span ng-repeat="team in robotInfo.teams"
data-title="Team {{ team.name }}" bs-tooltip>
<span class="anchor" is-text-only="!organization.admin" href="/organization/{{ organization.name }}/teams/{{ team.name }}">
<span class="avatar" size="24" data="team.avatar"></span>
</span>
</span>
</span>
</td>
<td ng-if="Config.isNewLayout()">
<span class="empty" ng-if="robotInfo.repositories.length == 0">
(No permissions on any repositories)
</span>
<span class="member-perm-summary" ng-if="robotInfo.repositories.length > 0">
Permissions on
<span class="anchor" href="javascript:void(0)" is-text-only="!organization.is_admin" ng-click="showPermissions(robotInfo)">{{ robotInfo.repositories.length }}
<span ng-if="robotInfo.repositories.length == 1">repository</span>
<span ng-if="robotInfo.repositories.length > 1">repositories</span>
</span>
</span>
</td>
<td class="options-col">
<span class="cor-options-menu">
<span class="cor-option" option-click="showRobot(robotInfo)">
<i class="fa fa-key"></i> View Credentials
</span>
<span class="cor-option" option-click="deleteRobot(robotInfo)">
<i class="fa fa-times"></i> Delete Robot {{ robotInfo.name }}
</span>
</span>
</td>
</tr>
<tr ng-if="robotInfo.showing_permissions">
<td class="permissions-display-row" colspan="4">
<span class="cor-loader" ng-if="robotInfo.loading_permissions"></span>
<div class="permissions-table-wrapper">
<table class="permissions-table" ng-if="!robotInfo.loading_permissions">
<thead>
<td>Repository</td>
<td>Permission</td>
</thead>
<tr ng-repeat="permission in robotInfo.permissions">
<td>
<span class="repo-icon repo-circle no-background" repo="permission.repository"></span>
<a ng-href="/repository/{{ getPrefix(robotInfo.name) }}/{{ permission.repository.name }}?tab=settings">{{ getPrefix(robotInfo.name) }}/{{ permission.repository.name }}</a>
</td>
<td>
<div class="btn-group btn-group-sm">
<span class="role-group" current-role="permission.role" roles="roles"
read-only="true"></span>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>

View file

@ -1,5 +1,6 @@
<div class="btn-group btn-group-sm">
<button ng-repeat="role in roles"
type="button" class="btn" ng-click="setRole(role.id)"
ng-class="(currentRole == role.id) ? ('active btn-' + role.kind) : 'btn-default'">{{ role.title }}</button>
ng-class="(currentRole == role.id) ? ('active btn-' + role.kind) : 'btn-default'"
ng-disabled="readOnly">{{ role.title }}</button>
</div>

View file

@ -1,4 +1,4 @@
<span class="source-commit-link-elememt">
<i class="fa fa-dot-circle-o" data-title="Commit" data-container="body" bs-tooltip></i>
<a ng-href="{{ getUrl(commitSha, urlTemplate) }}" target="_blank">{{ commitSha.substring(0, 8) }}</a>
</span>
</span>

View file

@ -12,4 +12,4 @@
<a ng-href="{{ getUrl(ref, tagTemplate, 'tag') }}" target="_blank">{{ getTitle(ref) }}</a>
</span>
</span>
</span>
</span>

View file

@ -34,7 +34,7 @@
image-cutoff="toTagImage"
style="margin: 10px; margin-top: 20px; margin-bottom: -10px;"
ng-show="isAnotherImageTag(toTagImage, tagToCreate)">
This will also delete any unattach images and delete the following images:
This will also delete any unattached images and delete the following images:
</div>
</div>
</div>
@ -84,4 +84,4 @@
The following images and any other images not referenced by a tag will be deleted:
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,65 @@
<div class="teams-manager-element">
<div class="manager-header">
<span class="popup-input-button" pattern="TEAM_PATTERN" placeholder="'Team Name'"
submitted="createTeam(value)" ng-show="organization.is_admin">
<i class="fa fa-plus" style="margin-right: 6px;"></i> Create New Team
</span>
<h3>Teams</h3>
</div>
<div class="row hidden-xs">
<div class="col-md-4 col-md-offset-8 col-sm-5 col-sm-offset-7 header-col" ng-show="organization.is_admin">
<span class="header-text">Team Permissions</span>
<i class="info-icon fa fa-info-circle" data-placement="bottom" data-original-title="" data-title=""
data-content="Global permissions for the team and its members<br><br><dl><dt>Member</dt><dd>Permissions are assigned on a per repository basis</dd><dt>Creator</dt><dd>A team can create its own repositories</dd><dt>Admin</dt><dd>A team has full control of the organization</dd></dl>"
data-html="true"
data-trigger="hover"
bs-popover></i>
</div>
</div>
<div class="team-listing" ng-repeat="team in orderedTeams">
<div id="team-{{team.name}}" class="row">
<div class="col-sm-7 col-md-8">
<div class="team-title">
<span class="avatar" data="team.avatar" size="30"></span>
<span ng-show="team.can_view">
<a href="/organization/{{ organization.name }}/teams/{{ team.name }}">{{ team.name }}</a>
</span>
<span ng-show="!team.can_view">
{{ team.name }}
</span>
</div>
<div class="team-description markdown-view" content="team.description" first-line-only="true"></div>
<div class="team-member-list" ng-if="members[team.name]">
<div class="cor-loader" ng-if="!members[team.name].members"></div>
<span class="team-member"
ng-repeat="member in members[team.name].members | orderBy:'is_robot' | limitTo: 20">
<span data-title="{{ member.name }}" bs-tooltip>
<a href="/user/{{ member.name }}" ng-if="!member.is_robot">
<span class="avatar" data="member.avatar" size="26"></span>
</a>
<i class="fa fa-wrench fa-lg" ng-if="member.is_robot"></i>
</span>
</span>
<span class="team-member-more"
ng-if="members[team.name].members.length > 20">+ {{ members[team.name].members.length - 20 }} more team members.</span>
<span class="team-member-more"
ng-if="!members[team.name].members.length">(Empty Team)</span>
</div>
</div>
<div class="col-sm-5 col-md-4 control-col" ng-show="organization.is_admin">
<span class="role-group" current-role="team.role" role-changed="setRole(role, team.name)" roles="teamRoles"></span>
<span class="cor-options-menu">
<span class="cor-option" option-click="askDeleteTeam(team.name)">
<i class="fa fa-times"></i> Delete Team {{ team.name }}
</span>
</span>
</div>
</div>
</div>
</div>

View file

@ -24,7 +24,7 @@
<div class="tour-section row">
<div class="col-md-7 col-md-push-5"><img src="/static/img/repo-view.png" title="Repository View" data-screenshot-url="https://quay.io/repository/devtable/complex" class="img-responsive"></div>
<div class="col-md-5 col-md-pull-7">
<div class="tour-section-title">Useful views of respositories</div>
<div class="tour-section-title">Useful views of repositories</div>
<div class="tour-section-description">
Each repository is presented with the maximum amount of useful information, including its image history, <b>markdown</b>-based description, and tags.
</div>
@ -307,7 +307,7 @@
</svg>
</div>
<h4>Deployment Made Easy</h4>
<p>Trigger container builds when your code is checked into Github and passes tests. Automatically pushed into your repository for immediate access by your servers.</p>
<p>Trigger container builds when your code is checked into GitHub and passes tests. Automatically pushed into your repository for immediate access by your servers.</p>
</div>
<div class="col-lg-4 col-md-4 col-sm-4 feature-desc">
<div class="feature-illustration">

View file

@ -1,10 +1,10 @@
<div class="triggered-build-description-element">
<span class="manual" ng-if="!build.trigger && !build.job_config.manual_user">
<span class="tbd-content" class="manual" ng-if="!build.trigger && !build.job_config.manual_user">
(Manually Triggered Build)
</span>
<span ng-if="!build.trigger && build.job_config.manual_user">
<span class="tbd-content" ng-if="!build.trigger && build.job_config.manual_user">
<i class="fa fa-user"></i> {{ build.job_config.manual_user }}
</span>
@ -12,7 +12,7 @@
<!-- GitHub -->
<span ng-switch-when="github">
<!-- Full Commit Information -->
<span ng-if="build.job_config.trigger_metadata.commit_info">
<span class="tbd-content" ng-if="build.job_config.trigger_metadata.commit_info">
<div class="commit-message">
<a ng-href="{{ getGitHubRepoURL(build) }}/commit/{{ build.job_config.trigger_metadata.commit_sha }}"
target="_blank">
@ -42,7 +42,7 @@
</span>
<!-- Just commit SHA -->
<span ng-if="build.job_config.trigger_metadata && !build.job_config.trigger_metadata.commit_info">
<span class="tbd-content" ng-if="build.job_config.trigger_metadata && !build.job_config.trigger_metadata.commit_info">
Triggered by commit
<span class="source-commit-link"
commit-sha="build.job_config.trigger_metadata.commit_sha"
@ -50,9 +50,9 @@
</span>
<!-- No information -->
<span ng-if="!build.job_config.trigger_metadata">
<span class="tbd-content" ng-if="!build.job_config.trigger_metadata">
Triggered by commit to
<i class="fa fa-github fa-lg" data-title="GitHub" bs-tooltip="tooltip.title"></i>
<i class="fa fa-github fa-lg" data-title="GitHub" data-container="body" bs-tooltip></i>
<a ng-href="{{ getGitHubRepoURL(build) }}" target="_new">
{{ build.trigger.config.build_source }}
</a>