Merge branch 'tagview'
This commit is contained in:
commit
3c305beeea
160 changed files with 151133 additions and 497 deletions
|
@ -5,7 +5,7 @@
|
|||
<!-- Side information -->
|
||||
<div class="build-side-info">
|
||||
<!-- Build ID -->
|
||||
<div class="build-side-id">{{ build.id }}</div>
|
||||
<div class="build-side-id" ng-if="!hideId">{{ build.id }}</div>
|
||||
|
||||
<!-- Timing -->
|
||||
<div class="timing" ng-if="showTime">
|
||||
|
|
10
static/directives/build-mini-status.html
Normal file
10
static/directives/build-mini-status.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<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>
|
||||
|
||||
<div class="build-description triggered-build-description" build="build"></div>
|
||||
</div>
|
||||
</a>
|
8
static/directives/build-state-icon.html
Normal file
8
static/directives/build-state-icon.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<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 == 'internalerror'"></i>
|
||||
</span>
|
||||
</span>
|
|
@ -1,3 +1,4 @@
|
|||
<!-- NOTE: DEPRECATED -->
|
||||
<div id="build-status-container" class="build-status-container">
|
||||
<div>
|
||||
<span class="phase-icon" ng-class="build.phase"></span>
|
||||
|
|
3
static/directives/cor-checkable-item.html
Normal file
3
static/directives/cor-checkable-item.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<span class="co-checkable-item" ng-click="toggleItem()"
|
||||
ng-class="controller.isChecked(item, controller.checked) ? 'checked': 'not-checked'">
|
||||
</span>
|
1
static/directives/cor-checkable-menu-item.html
Normal file
1
static/directives/cor-checkable-menu-item.html
Normal file
|
@ -0,0 +1 @@
|
|||
<li><a href="javascript:void(0)" ng-click="selected()"><span ng-transclude/></a></li>
|
12
static/directives/cor-checkable-menu.html
Normal file
12
static/directives/cor-checkable-menu.html
Normal 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>
|
25
static/directives/cor-confirm-dialog.html
Normal file
25
static/directives/cor-confirm-dialog.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<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">×</button>
|
||||
<h4 class="modal-title">{{ dialogTitle }}</h4>
|
||||
</div>
|
||||
<div class="modal-body" ng-show="working">
|
||||
<div class="cor-loader"></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-click="performAction()">
|
||||
{{ dialogActionTitle }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
</div>
|
|
@ -1,3 +1,3 @@
|
|||
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-6">
|
||||
<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>
|
|
@ -1 +1 @@
|
|||
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-6" ng-transclude></div>
|
||||
<div class="col-lg-3 col-md-3 col-sm-3 hidden-xs" ng-transclude></div>
|
3
static/directives/filter-control.html
Normal file
3
static/directives/filter-control.html
Normal file
|
@ -0,0 +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>
|
33
static/directives/image-changes-view.html
Normal file
33
static/directives/image-changes-view.html
Normal file
|
@ -0,0 +1,33 @@
|
|||
<div class="image-changes-view-element">
|
||||
<div class="resource-view" resource="imageChangesResource">
|
||||
<div class="changes-container" ng-show="hasChanges">
|
||||
<span class="change-count added"
|
||||
ng-show="changeData.added.length > 0"
|
||||
data-title="Files Added"
|
||||
data-placement="top"
|
||||
data-container="body"
|
||||
bs-tooltip>
|
||||
<i class="fa fa-plus-square"></i>
|
||||
<b>{{ changeData.added.length }}</b>
|
||||
</span>
|
||||
<span class="change-count removed"
|
||||
ng-show="changeData.removed.length > 0"
|
||||
data-title="Files Removed"
|
||||
data-placement="top"
|
||||
data-container="body"
|
||||
bs-tooltip>
|
||||
<i class="fa fa-minus-square"></i>
|
||||
<b>{{ changeData.removed.length }}</b>
|
||||
</span>
|
||||
<span class="change-count changed"
|
||||
ng-show="changeData.changed.length > 0"
|
||||
data-title="Files Changes"
|
||||
data-placement="top"
|
||||
data-container="body"
|
||||
bs-tooltip>
|
||||
<i class="fa fa-pencil-square"></i>
|
||||
<b>{{ changeData.changed.length }}</b>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
105
static/directives/image-info-sidebar.html
Normal file
105
static/directives/image-info-sidebar.html
Normal file
|
@ -0,0 +1,105 @@
|
|||
<div class="image-info-sidebar-element">
|
||||
<!-- Comment -->
|
||||
<div class="image-comment" ng-if="imageData.comment">
|
||||
<blockquote style="margin-top: 10px;">
|
||||
<span class="markdown-view" content="imageData.comment"></span>
|
||||
</blockquote>
|
||||
</div>
|
||||
|
||||
<!-- Image ID -->
|
||||
<div class="image-section">
|
||||
<i class="fa fa-code section-icon" bs-tooltip="tooltip.title" data-title="Full Image ID"></i>
|
||||
<span class="section-info">
|
||||
<a class="image-link" ng-href="{{ tracker.imageLink(image) }}">
|
||||
{{ imageData.id }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Tags -->
|
||||
<div class="image-section">
|
||||
<i class="fa fa-tag section-icon" data-title="Current Tags" bs-tooltip></i>
|
||||
<span class="section-info section-info-with-dropdown">
|
||||
<a class="label tag label-default" ng-repeat="tag in imageData.tags"
|
||||
href="javascript:void(0)" ng-click="tagSelected({'tag': tag})">
|
||||
{{ tag }}
|
||||
</a>
|
||||
<span style="color: #ccc;" ng-if="!imageData.tags.length">(No Tags)</span>
|
||||
|
||||
<div class="dropdown" data-placement="top"
|
||||
ng-if="tracker.repository.can_write || imageData.tags">
|
||||
<a href="javascript:void(0)" class="dropdown-button" data-toggle="dropdown"
|
||||
bs-tooltip="tooltip.title" data-title="Manage Tags"
|
||||
data-container="body">
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu pull-right">
|
||||
<li ng-repeat="tag in imageData.tags">
|
||||
<a href="javascript:void(0)" ng-click="tagSelected({'tag': tag})">
|
||||
<i class="fa fa-tag"></i>{{ tag }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider" role="presentation"
|
||||
ng-if="tracker.repository.can_write && imageData.tags"></li>
|
||||
<li>
|
||||
<a href="javascript:void(0)"
|
||||
ng-click="addTagRequested({'image': image})"
|
||||
ng-if="tracker.repository.can_write">
|
||||
<i class="fa fa-plus"></i>Add New Tag
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Command -->
|
||||
<div class="image-section" ng-if="imageData.command && imageData.command.length">
|
||||
<i class="fa fa-terminal section-icon" data-title="Image Command" bs-tooltip></i>
|
||||
<span class="section-info">
|
||||
<span class="formatted-command trimmed"
|
||||
data-html="true"
|
||||
data-title="{{ getTooltipCommand(imageData) }}"
|
||||
data-placement="top" bs-tooltip>{{ getFormattedCommand(imageData) }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Created -->
|
||||
<div class="image-section">
|
||||
<i class="fa fa-calendar section-icon" data-title="Created" bs-tooltip></i>
|
||||
<span class="section-info">
|
||||
<dd am-time-ago="parseDate(imageData.created)"></dd>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Size -->
|
||||
<div class="image-section">
|
||||
<i class="fa fa-cloud-upload section-icon"
|
||||
data-title="The amount of data sent between Docker and the registry when pushing/pulling"
|
||||
bs-tooltip></i>
|
||||
<span class="section-info">{{ imageData.size | bytes }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Locations -->
|
||||
<div class="image-section">
|
||||
<i class="fa fa-map-marker section-icon"
|
||||
data-title="The geographic region(s) in which this image data is located"
|
||||
bs-tooltip></i>
|
||||
<span class="section-info">
|
||||
<span class="location-view" location="location"
|
||||
ng-repeat="location in imageData.locations"></span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Changes -->
|
||||
<div class="image-section" ng-show="hasImageChanges">
|
||||
<i class="fa fa-code-fork section-icon"
|
||||
data-title="File Changes"
|
||||
bs-tooltip></i>
|
||||
<span class="section-info">
|
||||
<div class="image-changes-view" repository="tracker.repository" image="image"
|
||||
has-changes="hasImageChanges"></div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
|
@ -1,7 +1,7 @@
|
|||
<div class="markdown-input-container">
|
||||
<p ng-class="'lead ' + (canWrite ? 'editable' : 'noteditable')" ng-click="editContent()">
|
||||
<span class="markdown-view" content="content"></span>
|
||||
<span class="empty" ng-show="!content && canWrite">(Click to set {{ fieldTitle }})</span>
|
||||
<span class="empty" ng-show="!content && canWrite">Click to set {{ fieldTitle }}</span>
|
||||
<i class="fa fa-edit"></i>
|
||||
</p>
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
</a>
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-2 col-sm-2 col-xs-2">
|
||||
<i ng-class="repository.is_starred ? 'starred fa fa-star' : 'fa fa-star-o'" class="star-icon" ng-click="toggleStar({repository: repository})"></i>
|
||||
<span class="repo-star" repository="repository"
|
||||
star-toggled="starToggled({'repository': repository})"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description markdown-view" content="repository.description" first-line-only="true" placeholder-needed="true"></div>
|
||||
|
|
5
static/directives/repo-star.html
Normal file
5
static/directives/repo-star.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
<span class="repo-star-element">
|
||||
<i ng-class="repository.is_starred ? 'starred fa fa-star' : 'fa fa-star-o'"
|
||||
class="star-icon" ng-click="toggleStar()">
|
||||
</i>
|
||||
</span>
|
187
static/directives/repo-view/repo-panel-builds.html
Normal file
187
static/directives/repo-view/repo-panel-builds.html
Normal file
|
@ -0,0 +1,187 @@
|
|||
<div class="repo-panel-builds-element">
|
||||
<div class="tab-header-controls">
|
||||
<button class="btn btn-primary" ng-click="showNewBuildDialog()">
|
||||
<i class="fa fa-plus"></i>Start Build
|
||||
</button>
|
||||
</div>
|
||||
<h3 class="tab-header">Repository Builds</h3>
|
||||
|
||||
<!-- Builds -->
|
||||
<div class="co-panel">
|
||||
<!-- Builds header controls -->
|
||||
<div class="co-panel-heading">
|
||||
<div class="heading-controls hidden-sm hidden-xs">
|
||||
<span class="filter-control" filter="options.filter" value="recent">Recent Builds</span>
|
||||
<span class="filter-control" filter="options.filter" value="48hour">Last 48 Hours</span>
|
||||
<span class="filter-control" filter="options.filter" value="30day">Last 30 days</span>
|
||||
</div>
|
||||
<div class="heading-title">
|
||||
<i class="fa fa-tasks"></i>
|
||||
Build History
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Builds list content -->
|
||||
<div class="panel-body">
|
||||
<div class="resource-view" resource="buildsResource" error-message="'Could not load build information'">
|
||||
|
||||
<!-- No builds found -->
|
||||
<div class="empty" ng-if="!fullBuilds.length">
|
||||
<div class="empty-primary-msg">No matching builds found</div>
|
||||
<div class="empty-secondary-msg">
|
||||
Please change the filter above to search for more builds.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Builds list table -->
|
||||
<table class="co-table" ng-if="fullBuilds.length">
|
||||
<thead>
|
||||
<td class="status-col"></td>
|
||||
<td ng-class="tablePredicateClass('id', options.predicate, options.reverse)">
|
||||
<a href="javascript:void(0)" ng-click="orderBy('id')">Build ID</a>
|
||||
</td>
|
||||
<td ng-class="tablePredicateClass('tags', options.predicate, options.reverse)">
|
||||
<a href="javascript:void(0)" ng-click="orderBy('tags')">Tags</a>
|
||||
</td>
|
||||
<td ng-class="tablePredicateClass('commit_sha', options.predicate, options.reverse)">
|
||||
<a href="javascript:void(0)" ng-click="orderBy('commit_sha')">Triggered By</a>
|
||||
</td>
|
||||
<td ng-class="tablePredicateClass('started_datetime', options.predicate, options.reverse)">
|
||||
<a href="javascript:void(0)" ng-click="orderBy('started_datetime')">Date Started</a>
|
||||
</td>
|
||||
<td class="options-col"></td>
|
||||
</thead>
|
||||
|
||||
<tr ng-repeat="build in fullBuilds">
|
||||
<td><span class="build-state-icon" build="build"></span></td>
|
||||
<td>
|
||||
<a href="/repository/{{ repository.namespace }}/{{ repository.name }}/build/{{ build.id }}">{{ build.id.substr(0, 8) }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="building-tag" ng-repeat="tag in build.building_tags">
|
||||
<i class="fa fa-tag"></i>{{ tag }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="triggered-build-description" build="build"></div>
|
||||
</td>
|
||||
<td>{{ build.started | amCalendar }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /Builds -->
|
||||
|
||||
<!-- Build Triggers -->
|
||||
<div class="co-panel" ng-if="repository.can_admin && TriggerService.getTypes().length">
|
||||
<!-- Builds header controls -->
|
||||
<div class="co-panel-heading">
|
||||
<i class="fa fa-flash"></i>
|
||||
Build Triggers
|
||||
|
||||
<div class="heading-controls hidden-sm hidden-xs">
|
||||
<!-- Add Build Trigger -->
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
|
||||
Create Build Trigger
|
||||
<b class="caret"></b>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right pull-right">
|
||||
<li ng-repeat="type in TriggerService.getTypes()">
|
||||
<a href="{{ TriggerService.getRedirectUrl(type, repository.namespace, repository.name) }}">
|
||||
<i class="fa fa-lg" ng-class="TriggerService.getMetadata(type).icon"></i>
|
||||
{{ TriggerService.getTitle(type) }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Builds list content -->
|
||||
<div class="panel-body">
|
||||
<div class="resource-view" resource="triggersResource" error-message="'Could not load build triggers'">
|
||||
<!-- No Triggers defined -->
|
||||
<div class="empty" ng-if="!triggers.length">
|
||||
<div class="empty-primary-msg">No build triggers defined</div>
|
||||
<div class="empty-secondary-msg">
|
||||
Build triggers invoke builds whenever the triggered condition is met (source control push, webhook, etc)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Triggers list -->
|
||||
<table class="co-table" ng-if="triggers.length">
|
||||
<thead>
|
||||
<td>Trigger Name</td>
|
||||
<td>Dockerfile Location</td>
|
||||
<td>Branches/Tags</td>
|
||||
<td>Pull Robot</td>
|
||||
<td class="options-col"></td>
|
||||
</thead>
|
||||
|
||||
<tr ng-repeat="trigger in triggers | filter:{'is_active':false}">
|
||||
<td colspan="5" style="text-align: center">
|
||||
<span class="cor-loader-inline"></span>
|
||||
Trigger Setup in progress:
|
||||
<a href="javascript:void(0)" ng-click="setupTrigger(trigger)">Resume</a> |
|
||||
<a href="javascript:void(0)" ng-click="deleteTrigger(trigger)">Cancel</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr ng-repeat="trigger in triggers | filter:{'is_active':true}">
|
||||
<td><div class="trigger-description" trigger="trigger" short="true"></div></td>
|
||||
<td>{{ trigger.subdir || '(Root Directory)' }}</td>
|
||||
<td>{{ trigger.config.branchtag_regex || '(All)' }}</td>
|
||||
<td>
|
||||
<span class="entity-reference" entity="trigger.pull_robot" ng-if="trigger.pull_robot"></span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="cor-options-menu">
|
||||
<span class="cor-option" option-click="askRunTrigger(trigger)">
|
||||
<i class="fa fa-chevron-right"></i> Run Trigger Now
|
||||
</span>
|
||||
<span class="cor-option" option-click="askDeleteTrigger(trigger)">
|
||||
<i class="fa fa-times"></i> Delete Trigger
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /Build Triggers -->
|
||||
|
||||
<!-- Delete Tag Confirm -->
|
||||
<div class="cor-confirm-dialog"
|
||||
dialog-context="deleteTriggerInfo"
|
||||
dialog-action="deleteTrigger(info.trigger, callback)"
|
||||
dialog-title="Delete Build Trigger"
|
||||
dialog-action-title="Delete Trigger">
|
||||
Are you sure you want to delete this build trigger? No further builds will be automatically
|
||||
started.
|
||||
</div>
|
||||
|
||||
<!-- Dockerfile build dialog -->
|
||||
<div class="dockerfile-build-dialog"
|
||||
show-now="showBuildDialogCounter"
|
||||
repository="repository"
|
||||
build-started="handleBuildStarted(build)">
|
||||
</div>
|
||||
|
||||
<!-- Setup trigger dialog-->
|
||||
<div class="setup-trigger-dialog"
|
||||
repository="repository"
|
||||
trigger="currentSetupTrigger"
|
||||
canceled="cancelSetupTrigger(trigger)"
|
||||
counter="showTriggerSetupCounter"></div>
|
||||
|
||||
<!-- Manual trigger dialog -->
|
||||
<div class="manual-trigger-build-dialog"
|
||||
repository="repository"
|
||||
trigger="currentStartTrigger"
|
||||
counter="showTriggerStartDialogCounter"
|
||||
start-build="startTrigger(trigger, parameters)"></div>
|
||||
|
||||
</div>
|
63
static/directives/repo-view/repo-panel-changes.html
Normal file
63
static/directives/repo-view/repo-panel-changes.html
Normal file
|
@ -0,0 +1,63 @@
|
|||
<div class="repo-panel-changes-element">
|
||||
<!-- No Tags Selected -->
|
||||
<div class="empty" ng-if="!selectedTags.length">
|
||||
<div class="empty-primary-msg">No tags selected to view</div>
|
||||
<div class="empty-secondary-msg">
|
||||
Please select one or more tags in the <i class="fa fa-tags" style="margin-left: 4px; margin-right: 4px;"></i> Tags tab to visualize.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags Selected -->
|
||||
<div ng-if="selectedTags.length > 0">
|
||||
<h3 class="tab-header">
|
||||
Visualize Tags:
|
||||
<span class="visualized-tag" ng-repeat="tag in selectedTags">
|
||||
<i class="fa fa-tag"></i>{{ tag }}
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
<div id="image-history row" class="resource-view" resource="imagesResource"
|
||||
error-message="'Cannot load repository images'">
|
||||
|
||||
<!-- Tree View container -->
|
||||
<div class="col-md-8">
|
||||
<div class="panel panel-default">
|
||||
<!-- Image history tree -->
|
||||
<div id="image-history-container" onresize="tree.notifyResized()"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Side Panel -->
|
||||
<div class="col-md-4">
|
||||
<div class="side-panel-title" ng-if="currentTag">
|
||||
<i class="fa fa-tag"></i>{{ currentTag }}
|
||||
</div>
|
||||
<div class="side-panel-title" ng-if="currentImage">
|
||||
<i class="fa fa-archive"></i>{{ currentImage.substr(0, 12) }}
|
||||
</div>
|
||||
|
||||
<div class="side-panel">
|
||||
<!-- Tag Info -->
|
||||
<div class="tag-info-sidebar"
|
||||
tracker="tracker"
|
||||
tag="currentTag"
|
||||
image-selected="setImage(image)"
|
||||
delete-tag-requested="tagActionHandler.askDeleteTag(tag)"
|
||||
ng-if="currentTag">
|
||||
</div>
|
||||
|
||||
<!-- Image Info -->
|
||||
<div class="image-info-sidebar"
|
||||
tracker="tracker"
|
||||
image="currentImage"
|
||||
tag-selected="setTag(tag)"
|
||||
add-tag-requested="tagActionHandler.askAddTag(image)"
|
||||
ng-if="currentImage">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tag-operations-dialog" repository="repository" images="images"
|
||||
action-handler="tagActionHandler" tag-changed="handleTagChanged(data)"></div>
|
72
static/directives/repo-view/repo-panel-info.html
Normal file
72
static/directives/repo-view/repo-panel-info.html
Normal file
|
@ -0,0 +1,72 @@
|
|||
<div class="repo-panel-info-element">
|
||||
<!-- Repository stats and builds summary -->
|
||||
<div class="repository-stats row">
|
||||
<!-- Pull Stats -->
|
||||
<div class="col-sm-3 stat-col">
|
||||
<div class="stat-title">Repo Pulls</div>
|
||||
|
||||
<div class="stat">
|
||||
<div class="stat-value">{{ repository.stats.pulls.today }}</div>
|
||||
<div class="stat-subtitle">Last 24 hours</div>
|
||||
</div>
|
||||
|
||||
<div class="stat">
|
||||
<div class="stat-value">{{ repository.stats.pulls.thirty_day }}</div>
|
||||
<div class="stat-subtitle">Last 30 days</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Push Stats -->
|
||||
<div class="col-sm-3 stat-col">
|
||||
<div class="stat-title">Repo Pushes</div>
|
||||
|
||||
<div class="stat">
|
||||
<div class="stat-value">{{ repository.stats.pushes.today }}</div>
|
||||
<div class="stat-subtitle">Last 24 hours</div>
|
||||
</div>
|
||||
|
||||
<div class="stat">
|
||||
<div class="stat-value">{{ repository.stats.pushes.thirty_day }}</div>
|
||||
<div class="stat-subtitle">Last 30 days</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Builds -->
|
||||
<div class="col-sm-6">
|
||||
<div class="stat-title">Recent Repo Builds</div>
|
||||
|
||||
<!-- Loading -->
|
||||
<div class="cor-loader" ng-if="!builds"></div>
|
||||
|
||||
<!-- No Builds -->
|
||||
<div class="empty" ng-if="builds && !builds.length">
|
||||
<div class="empty-primary-msg">No builds have been run for this repository.</div>
|
||||
<div class="empty-secondary-msg" ng-if="repository.can_write">
|
||||
Click on the <i class="fa fa-tasks" style="margin-left: 6px"></i> Builds tab to start a new build.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Builds -->
|
||||
<div ng-if="builds && builds.length">
|
||||
<div class="build-mini-status" ng-repeat="build in builds" build="build"></div>
|
||||
</div>
|
||||
|
||||
<!-- View All -->
|
||||
<a href="/repository/{{ repository.namespace }}/{{ repository.name }}?tab=builds"
|
||||
class="view-all" ng-if="repository.can_admin && builds.length">
|
||||
View Build History
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Repository Description -->
|
||||
<div class="description-container">
|
||||
<h4 style="font-size:20px;">Description</h4>
|
||||
<div class="description markdown-input"
|
||||
content="repository.description"
|
||||
can-write="repository.can_write"
|
||||
content-changed="updateDescription"
|
||||
field-title="'repository description'">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
95
static/directives/repo-view/repo-panel-settings.html
Normal file
95
static/directives/repo-view/repo-panel-settings.html
Normal file
|
@ -0,0 +1,95 @@
|
|||
<div class="repo-panel-settings-element">
|
||||
<h3 class="tab-header">Repository Settings</h3>
|
||||
|
||||
<!-- 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="repository-permissions-table" repository="repository"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 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="repository-tokens-table" repository="repository" has-tokens="hasTokens"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Events and Notifications -->
|
||||
<div class="repository-events-table" repository="repository"></div>
|
||||
|
||||
<!-- Other settings -->
|
||||
<div class="co-panel">
|
||||
<div class="co-panel-heading"><i class="fa fa-gears"></i> Repository Settings</div>
|
||||
|
||||
<div class="cor-loader" ng-show="!repository"></div>
|
||||
|
||||
<div ng-show="repository">
|
||||
<!-- Public/Private -->
|
||||
<div class="panel-body panel-section lock-section" ng-if="!repository.is_public">
|
||||
<i class="fa fa-lock lock-icon"></i>
|
||||
<div>This repository is currently <b>private</b>. Only users on the permissions list may view and interact with it.</div>
|
||||
|
||||
<button class="btn btn-default" ng-click="askChangeAccess('public')">
|
||||
<i class="fa fa-unlock"></i>Make Public
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="panel-body panel-section lock-section" ng-if="repository.is_public">
|
||||
<i class="fa fa-unlock lock-icon"></i>
|
||||
|
||||
<div>This repository is currently <b>public</b> and is visible to all users, and may be pulled by all users.</div>
|
||||
|
||||
<button class="btn btn-default" ng-click="askChangeAccess('private')">
|
||||
<i class="fa fa-lock"></i>Make Private
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<!-- Build Status Badge -->
|
||||
<div class="panel-body panel-section">
|
||||
<!-- Status Image -->
|
||||
<a ng-href="/repository/{{ repository.namespace }}/{{ repository.name }}">
|
||||
<img ng-src="/repository/{{ repository.namespace }}/{{ repository.name }}/status?token={{ repository.status_token }}"
|
||||
data-title="Docker Repository on Quay.io">
|
||||
</a>
|
||||
|
||||
<!-- Embed formats -->
|
||||
<table style="margin-top: 20px; width: 600px;">
|
||||
<thead>
|
||||
<th style="width: 150px"></th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>Image (SVG):</td>
|
||||
<td>
|
||||
<div class="copy-box" hovering-message="true" value="getBadgeFormat('svg', repository)"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Markdown:</td>
|
||||
<td>
|
||||
<div class="copy-box" hovering-message="true" value="getBadgeFormat('md', repository)"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AsciiDoc:</td>
|
||||
<td>
|
||||
<div class="copy-box" hovering-message="true" value="getBadgeFormat('asciidoc', repository)"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
99
static/directives/repo-view/repo-panel-tags.html
Normal file
99
static/directives/repo-view/repo-panel-tags.html
Normal file
|
@ -0,0 +1,99 @@
|
|||
<div class="repo-panel-tags-element">
|
||||
<h3 class="tab-header">Repository Tags</h3>
|
||||
<div class="resource-view" resource="imagesResource" error-message="'Could not load images'">
|
||||
|
||||
<div class="co-check-bar">
|
||||
<span class="cor-checkable-menu" controller="checkedTags">
|
||||
<div class="cor-checkable-menu-item" item-filter="allTagFilter">
|
||||
<i class="fa fa-check-square-o"></i>All Tags
|
||||
</div>
|
||||
<div class="cor-checkable-menu-item" item-filter="noTagFilter(tag)">
|
||||
<i class="fa fa-square-o"></i>No Tags
|
||||
</div>
|
||||
<div class="cor-checkable-menu-item" item-filter="commitTagFilter(tag)">
|
||||
<i class="fa fa-git"></i>Commit SHAs
|
||||
</div>
|
||||
|
||||
<div class="cor-checkable-menu-item" item-filter="imageIDFilter(it.image_id, tag)"
|
||||
ng-repeat="it in imageTracks">
|
||||
<i class="fa fa-circle-o" ng-style="{'color': it.color}"></i> {{ it.image_id.substr(0, 12) }}
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span class="co-checked-actions" ng-if="checkedTags.checked.length">
|
||||
<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"
|
||||
ng-click="askDeleteMultipleTags(checkedTags.checked)"
|
||||
ng-if="repository.can_write">
|
||||
<i class="fa fa-times"></i> Delete
|
||||
</button>
|
||||
</span>
|
||||
|
||||
<span class="co-filter-box">
|
||||
<input class="form-control" type="text" ng-model="options.tagFilter" placeholder="Filter Tags...">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<table class="co-table">
|
||||
<thead>
|
||||
<td class="checkbox-col"></td>
|
||||
<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)">
|
||||
<a href="javascript:void(0)" ng-click="orderBy('last_modified_datetime')">Last Modified</a>
|
||||
</td>
|
||||
<td ng-class="tablePredicateClass('size', options.predicate, options.reverse)">
|
||||
<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 }}">
|
||||
<a href="javascript:void(0)" ng-click="orderBy('image_id')">Image</a>
|
||||
</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 am-time-ago="tag.last_modified"></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>
|
||||
</td>
|
||||
<td class="image-track" ng-repeat="it in imageTracks">
|
||||
<span class="image-track-dot" ng-if="it.image_id == tag.image_id"
|
||||
ng-style="{'borderColor': it.color}"></span>
|
||||
<span class="image-track-line" ng-class="trackLineClass($parent.$index, it)"
|
||||
ng-style="{'borderColor': it.color}"></span>
|
||||
</td>
|
||||
<td class="options-col">
|
||||
<span class="cor-options-menu" ng-if="repository.can_write">
|
||||
<span class="cor-option" option-click="askDeleteTag(tag.name)">
|
||||
<i class="fa fa-times"></i> Delete Tag
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="empty" ng-if="allTags.length && !tags.length">
|
||||
<div class="empty-primary-msg">No matching tags found.</div>
|
||||
<div class="empty-secondary-msg">Try expanding your filtering terms.</div>
|
||||
</div>
|
||||
|
||||
<div class="empty" ng-if="!allTags.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>
|
||||
</div>
|
||||
|
||||
<div class="tag-operations-dialog" repository="repository" images="images"
|
||||
action-handler="tagActionHandler"></div>
|
75
static/directives/repository-events-table.html
Normal file
75
static/directives/repository-events-table.html
Normal file
|
@ -0,0 +1,75 @@
|
|||
<div class="repository-events-table-element">
|
||||
<div class="co-panel">
|
||||
<div class="co-panel-heading">
|
||||
<i class="fa fa-bell"></i> Events and Notifications
|
||||
|
||||
<div class="heading-controls hidden-sm hidden-xs">
|
||||
<button class="btn btn-primary" ng-click="askCreateNotification()">
|
||||
<i class="fa fa-plus"></i> Create Notification
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="resource-view" resource="notificationsResource"
|
||||
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-secondary-msg" ng-if="repository.can_write">
|
||||
Click the "Create Notification" button above to add a new notification for a repository event.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="co-table permissions" ng-if="notifications.length">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Event</td>
|
||||
<td>Notification</td>
|
||||
<td class="options-col"></td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr class="notification-row" ng-repeat="notification in notifications">
|
||||
<td>
|
||||
<span class="notification-event">
|
||||
<i class="fa fa-lg" ng-class="getEventInfo(notification).icon"></i>
|
||||
{{ getEventInfo(notification).title }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="notification-method">
|
||||
<i class="fa fa-lg" ng-class="getMethodInfo(notification).icon"></i>
|
||||
{{ getMethodInfo(notification).title }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="cor-options-menu">
|
||||
<span class="cor-option" option-click="testNotification(notification)">
|
||||
<i class="fa fa-send"></i> Test Notification
|
||||
</span>
|
||||
<span class="cor-option" option-click="showWebhookInfo(notification)"
|
||||
ng-if="getMethodInfo(notification).id == 'webhook'">
|
||||
<i class="fa fa-book"></i>
|
||||
Webhook Documentation
|
||||
</span>
|
||||
<span class="cor-option" option-click="deleteNotification(notification)">
|
||||
<i class="fa fa-times"></i> Delete Notification
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- New notification dialog-->
|
||||
<div class="create-external-notification-dialog"
|
||||
repository="repository"
|
||||
counter="showNewNotificationCounter"
|
||||
notification-created="handleNotificationCreated(notification)"></div>
|
||||
</div>
|
82
static/directives/repository-permissions-table.html
Normal file
82
static/directives/repository-permissions-table.html
Normal file
|
@ -0,0 +1,82 @@
|
|||
<div class="repository-permissions-table-element">
|
||||
<div class="resource-view"
|
||||
resources="[permissionResources.team, permissionResources.user]"
|
||||
error-message="'Could not load repository permissions'">
|
||||
<table class="co-table permissions">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Account Name</td>
|
||||
<td style="width: 300px">Permissions</td>
|
||||
<td class="options-col"></td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<!-- Team Permissions -->
|
||||
<tr ng-repeat="(name, permission) in permissionResources.team.value">
|
||||
<td class="team entity">
|
||||
<span class="entity-reference" namespace="repository.namespace"
|
||||
entity="buildEntityForPermission(name, permission, 'team')">
|
||||
</span>
|
||||
</td>
|
||||
<td class="user-permissions">
|
||||
<span class="role-group" current-role="permission.role" role-changed="setRole(role, name, 'team')" roles="roles"></span>
|
||||
</td>
|
||||
|
||||
<td class="options-col">
|
||||
<span class="cor-options-menu">
|
||||
<span class="cor-option" option-click="deleteRole(name, 'team')">
|
||||
<i class="fa fa-times"></i> Delete Permission
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- User Permissions -->
|
||||
<tr ng-repeat="(name, permission) in permissionResources.user.value">
|
||||
<td class="{{ 'user entity ' + (permission.is_org_member ? '' : 'outside') }}">
|
||||
<span class="entity-reference" namespace="repository.namespace"
|
||||
entity="buildEntityForPermission(name, permission, 'user')">
|
||||
</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, 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')">
|
||||
<i class="fa fa-times"></i> Delete Permission
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="add-row">
|
||||
<td id="add-entity-permission" class="admin-search">
|
||||
<span class="entity-search" namespace="repository.namespace"
|
||||
placeholder="'Select a ' + (repository.is_organization ? 'team or ' : '') + 'user...'"
|
||||
current-entity="addPermissionInfo.entity"></span>
|
||||
</td>
|
||||
<td colspan="2">
|
||||
<span class="role-group" current-role="addPermissionInfo.role" roles="roles"
|
||||
role-changed="addPermissionInfo.role = role"></span>
|
||||
<button class="btn btn-success" style="margin-left: 10px"
|
||||
ng-disabled="!addPermissionInfo.role || !addPermissionInfo.entity"
|
||||
ng-click="addPermission()">
|
||||
Add Permission
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Grant Permission Confirm -->
|
||||
<div class="cor-confirm-dialog"
|
||||
dialog-context="grantPermissionInfo"
|
||||
dialog-action="grantPermission(info.entity, callback)"
|
||||
dialog-title="Grant Permission"
|
||||
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>
|
35
static/directives/repository-tokens-table.html
Normal file
35
static/directives/repository-tokens-table.html
Normal file
|
@ -0,0 +1,35 @@
|
|||
<div class="repository-tokens-table-element">
|
||||
<div class="resource-view" resource="tokensResource"
|
||||
error-message="'Could not load repository tokens'">
|
||||
<div class="alert alert-warning">Note: Access tokens are <strong>deprecated</strong> and will be removed in the near future. <a href="http://docs.quay.io/glossary/robot-accounts.html">Robot accounts</a> are the recommended replacement.
|
||||
</div>
|
||||
|
||||
<table class="co-table permissions">
|
||||
<thead>
|
||||
<tr>
|
||||
<td style="min-width: 400px;">Token Name</td>
|
||||
<td>Permissions</td>
|
||||
<td style="width: 95px;"></td>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr ng-repeat="(code, token) in tokens">
|
||||
<td class="user token">
|
||||
<i class="fa fa-key"></i>
|
||||
<a ng-click="showToken(token.code)">{{ token.friendlyName }}</a>
|
||||
</td>
|
||||
<td class="user-permissions">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" class="btn btn-default" ng-click="changeTokenAccess(token.code, 'read')" ng-class="{read: 'active', write: ''}[token.role]">Read only</button>
|
||||
<button type="button" class="btn btn-default" ng-click="changeTokenAccess(token.code, 'write')" ng-class="{read: '', write: 'active'}[token.role]">Write</button>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="delete-ui" delete-title="'Delete Token'" perform-delete="deleteToken(token.code)"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
|
@ -3,7 +3,7 @@
|
|||
<div class="resource-error alert alert-info" ng-show="getState(resources) == 'error'">
|
||||
{{ errorMessage }}
|
||||
</div>
|
||||
<div class="resource-content" ng-class="getState(resources) == 'ready' ? 'visible' : ''">
|
||||
<div class="resource-content" ng-class="getState(resources) == 'ready' ? 'visible' : 'hidden'">
|
||||
<span ng-transclude></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
42
static/directives/tag-info-sidebar.html
Normal file
42
static/directives/tag-info-sidebar.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
<div class="tag-info-sidebar-element">
|
||||
<dl class="dl-normal">
|
||||
<dt>Last Modified</dt>
|
||||
<dd am-time-ago="parseDate(tagImage.created)"></dd>
|
||||
|
||||
<dt>Total Compressed Size</dt>
|
||||
<dd>
|
||||
<span class="context-tooltip"
|
||||
data-title="The amount of data sent between Docker and the registry when pushing/pulling"
|
||||
data-container="body"
|
||||
bs-tooltip>
|
||||
{{ tracker.getTotalSize(tag) | bytes }}
|
||||
</span>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<div class="tag-image-sizes">
|
||||
<div class="tag-image-size" ng-repeat="image in tracker.getImagesForTagBySize(tag) | limitTo: 10">
|
||||
<span class="size-limiter">
|
||||
<span class="size-bar"
|
||||
ng-style="{'width': (image.size / tracker.getTotalSize(tag)) * 100 + '%'}"
|
||||
data-title="{{ image.size | bytes }}"
|
||||
bs-tooltip>
|
||||
</span>
|
||||
</span>
|
||||
<span class="size-title">
|
||||
<a class="image-size-link"
|
||||
href="javascript:void(0)"
|
||||
ng-click="imageSelected({'image': image.id})"
|
||||
data-image="{{ image.id.substr(0, 12) }}">
|
||||
{{ image.id.substr(0, 12) }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-bar" ng-show="tracker.repository.can_admin">
|
||||
<button class="btn btn-default" ng-click="deleteTagRequested({'tag': tag})">
|
||||
<i class="fa fa-times" style="margin-right: 6px;"></i>Delete Tag
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
87
static/directives/tag-operations-dialog.html
Normal file
87
static/directives/tag-operations-dialog.html
Normal file
|
@ -0,0 +1,87 @@
|
|||
<div class="tag-operations-dialog-element">
|
||||
<!-- Add Tag Dialog -->
|
||||
<div class="modal fade" id="createOrMoveTagModal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-hidden="true" ng-show="!addingTag">×</button>
|
||||
<h4 class="modal-title">{{ isAnotherImageTag(toTagImage, tagToCreate) ? 'Move' : 'Add' }} Tag to Image {{ toTagImage.substr(0, 12) }}</h4>
|
||||
</div>
|
||||
<form name="addTagForm" ng-submit="createOrMoveTag(toTagImage, tagToCreate);">
|
||||
<div class="modal-body">
|
||||
<div class="cor-loader" ng-show="addingTag"></div>
|
||||
<div ng-show="!addingTag">
|
||||
<input type="text" class="form-control" id="tagName"
|
||||
placeholder="Enter tag name"
|
||||
ng-model="tagToCreate" ng-pattern="/^([a-z0-9_\.-]){3,30}$/"
|
||||
ng-disabled="creatingTag" autofocus required>
|
||||
|
||||
<div style="margin: 10px; margin-top: 20px;"
|
||||
ng-show="isOwnedTag(toTagImage, tagToCreate)">
|
||||
Note: <span class="label tag label-default">{{ tagToCreate }}</span> is already applied to this image.
|
||||
</div>
|
||||
|
||||
<div style="margin: 10px; margin-top: 20px;"
|
||||
ng-show="isAnotherImageTag(toTagImage, tagToCreate)">
|
||||
Note: <span class="label tag label-default">{{ tagToCreate }}</span> is already applied to another image. This will <b>move</b> the tag.
|
||||
</div>
|
||||
|
||||
<div class="tag-specific-images-view"
|
||||
tag="tagToCreate"
|
||||
repository="repo"
|
||||
images="images"
|
||||
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:
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer" ng-show="!addingTag">
|
||||
<button type="submit" class="btn btn-primary"
|
||||
ng-disabled="addTagForm.$invalid || isOwnedTag(toTagImage, tagToCreate)"
|
||||
ng-class="isAnotherImageTag(toTagImage, tagToCreate) ? 'btn-warning' : 'btn-primary'"
|
||||
ng-show="!creatingTag">
|
||||
{{ isAnotherImageTag(toTagImage, tagToCreate) ? 'Move Tag' : 'Create Tag' }}
|
||||
</button>
|
||||
<button class="btn btn-default" data-dismiss="modal" ng-show="!addingTag">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<!-- Delete Tags Confirm -->
|
||||
<div class="cor-confirm-dialog"
|
||||
dialog-context="deleteMultipleTagsInfo"
|
||||
dialog-action="deleteMultipleTags(info.tags, callback)"
|
||||
dialog-title="Delete Tags"
|
||||
dialog-action-title="Delete Tags">
|
||||
Are you sure you want to delete the following tags:
|
||||
<ul>
|
||||
<li ng-repeat="tag_info in deleteMultipleTagsInfo.tags">
|
||||
<span class="label label-default tag">{{ tag_info.name }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div style="margin-top: 20px">
|
||||
<strong>Note: </strong>This operation can take several minutes.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Delete Tag Confirm -->
|
||||
<div class="cor-confirm-dialog"
|
||||
dialog-context="deleteTagInfo"
|
||||
dialog-action="deleteTag(info.tag, callback)"
|
||||
dialog-title="Delete Tag"
|
||||
dialog-action-title="Delete Tag">
|
||||
Are you sure you want to delete tag
|
||||
<span class="label label-default tag">{{ deleteTagInfo.tag }}</span>?
|
||||
|
||||
<div class="tag-specific-images-view" tag="deleteTagInfo.tag" repository="repository"
|
||||
images="images" style="margin-top: 20px">
|
||||
The following images and any other images not referenced by a tag will be deleted:
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,5 +1,14 @@
|
|||
<div class="triggered-build-description-element">
|
||||
<span ng-switch on="build.trigger.service">
|
||||
|
||||
<span 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">
|
||||
<i class="fa fa-user"></i> {{ build.job_config.manual_user }}
|
||||
</span>
|
||||
|
||||
<span ng-switch on="build.trigger.service" ng-if="build.trigger">
|
||||
<!-- GitHub -->
|
||||
<span ng-switch-when="github">
|
||||
<!-- Full Commit Information -->
|
||||
|
|
Reference in a new issue