UI fixes for all the new trigger stuff
This commit is contained in:
parent
de29a441c8
commit
b7317f894b
25 changed files with 260 additions and 149 deletions
|
@ -14,7 +14,9 @@ from endpoints.building import start_build, PreparedBuild
|
||||||
from endpoints.trigger import BuildTriggerHandler
|
from endpoints.trigger import BuildTriggerHandler
|
||||||
from data import model, database
|
from data import model, database
|
||||||
from auth.auth_context import get_authenticated_user
|
from auth.auth_context import get_authenticated_user
|
||||||
from auth.permissions import ModifyRepositoryPermission, AdministerOrganizationPermission
|
from auth.permissions import (ReadRepositoryPermission, ModifyRepositoryPermission,
|
||||||
|
AdministerRepositoryPermission, AdministerOrganizationPermission)
|
||||||
|
|
||||||
from data.buildlogs import BuildStatusRetrievalError
|
from data.buildlogs import BuildStatusRetrievalError
|
||||||
from util.names import parse_robot_username
|
from util.names import parse_robot_username
|
||||||
|
|
||||||
|
@ -33,7 +35,7 @@ def get_job_config(build_obj):
|
||||||
try:
|
try:
|
||||||
return json.loads(build_obj.job_config)
|
return json.loads(build_obj.job_config)
|
||||||
except:
|
except:
|
||||||
return None
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def user_view(user):
|
def user_view(user):
|
||||||
|
@ -43,11 +45,12 @@ def user_view(user):
|
||||||
'is_robot': user.robot,
|
'is_robot': user.robot,
|
||||||
}
|
}
|
||||||
|
|
||||||
def trigger_view(trigger, can_admin=False):
|
def trigger_view(trigger, can_read=False, can_admin=False):
|
||||||
if trigger and trigger.uuid:
|
if trigger and trigger.uuid:
|
||||||
build_trigger = BuildTriggerHandler.get_handler(trigger)
|
build_trigger = BuildTriggerHandler.get_handler(trigger)
|
||||||
return {
|
return {
|
||||||
'service': trigger.service.name,
|
'service': trigger.service.name,
|
||||||
|
'build_source': build_trigger.config.get('build_source') if can_read else None,
|
||||||
'config': build_trigger.config if can_admin else {},
|
'config': build_trigger.config if can_admin else {},
|
||||||
'id': trigger.uuid,
|
'id': trigger.uuid,
|
||||||
'connected_user': trigger.connected_user.username,
|
'connected_user': trigger.connected_user.username,
|
||||||
|
@ -58,7 +61,7 @@ def trigger_view(trigger, can_admin=False):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def build_status_view(build_obj, can_write=False, can_admin=False):
|
def build_status_view(build_obj):
|
||||||
phase = build_obj.phase
|
phase = build_obj.phase
|
||||||
try:
|
try:
|
||||||
status = build_logs.get_status(build_obj.uuid)
|
status = build_logs.get_status(build_obj.uuid)
|
||||||
|
@ -81,21 +84,32 @@ def build_status_view(build_obj, can_write=False, can_admin=False):
|
||||||
if not retry:
|
if not retry:
|
||||||
phase = database.BUILD_PHASE.ERROR
|
phase = database.BUILD_PHASE.ERROR
|
||||||
|
|
||||||
logger.debug('Can write: %s job_config: %s', can_write, build_obj.job_config)
|
repo_namespace = build_obj.repository.namespace_user.username
|
||||||
|
repo_name = build_obj.repository.name
|
||||||
|
|
||||||
|
can_read = ReadRepositoryPermission(repo_namespace, repo_name).can()
|
||||||
|
can_write = ModifyRepositoryPermission(repo_namespace, repo_name).can()
|
||||||
|
can_admin = AdministerRepositoryPermission(repo_namespace, repo_name).can()
|
||||||
|
|
||||||
|
job_config = get_job_config(build_obj)
|
||||||
|
|
||||||
resp = {
|
resp = {
|
||||||
'id': build_obj.uuid,
|
'id': build_obj.uuid,
|
||||||
'phase': phase,
|
'phase': phase,
|
||||||
'started': format_date(build_obj.started),
|
'started': format_date(build_obj.started),
|
||||||
'display_name': build_obj.display_name,
|
'display_name': build_obj.display_name,
|
||||||
'status': status or {},
|
'status': status or {},
|
||||||
'job_config': get_job_config(build_obj) if can_write else None,
|
'subdirectory': job_config.get('build_subdir', ''),
|
||||||
|
'tags': job_config.get('docker_tags', []),
|
||||||
|
'manual_user': job_config.get('manual_user', None),
|
||||||
'is_writer': can_write,
|
'is_writer': can_write,
|
||||||
'trigger': trigger_view(build_obj.trigger, can_admin),
|
'trigger': trigger_view(build_obj.trigger, can_read, can_admin),
|
||||||
|
'trigger_metadata': job_config.get('trigger_metadata', None) if can_read else None,
|
||||||
'resource_key': build_obj.resource_key,
|
'resource_key': build_obj.resource_key,
|
||||||
'pull_robot': user_view(build_obj.pull_robot) if build_obj.pull_robot else None,
|
'pull_robot': user_view(build_obj.pull_robot) if build_obj.pull_robot else None,
|
||||||
'repository': {
|
'repository': {
|
||||||
'namespace': build_obj.repository.namespace_user.username,
|
'namespace': repo_namespace,
|
||||||
'name': build_obj.repository.name
|
'name': repo_name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,9 +171,8 @@ class RepositoryBuildList(RepositoryParamResource):
|
||||||
since = datetime.datetime.utcfromtimestamp(since)
|
since = datetime.datetime.utcfromtimestamp(since)
|
||||||
|
|
||||||
builds = model.list_repository_builds(namespace, repository, limit, since=since)
|
builds = model.list_repository_builds(namespace, repository, limit, since=since)
|
||||||
can_write = ModifyRepositoryPermission(namespace, repository).can()
|
|
||||||
return {
|
return {
|
||||||
'builds': [build_status_view(build, can_write) for build in builds]
|
'builds': [build_status_view(build) for build in builds]
|
||||||
}
|
}
|
||||||
|
|
||||||
@require_repo_write
|
@require_repo_write
|
||||||
|
@ -211,7 +224,7 @@ class RepositoryBuildList(RepositoryParamResource):
|
||||||
prepared.metadata = {}
|
prepared.metadata = {}
|
||||||
|
|
||||||
build_request = start_build(repo, prepared, pull_robot_name=pull_robot_name)
|
build_request = start_build(repo, prepared, pull_robot_name=pull_robot_name)
|
||||||
resp = build_status_view(build_request, can_write=True)
|
resp = build_status_view(build_request)
|
||||||
repo_string = '%s/%s' % (namespace, repository)
|
repo_string = '%s/%s' % (namespace, repository)
|
||||||
headers = {
|
headers = {
|
||||||
'Location': api.url_for(RepositoryBuildStatus, repository=repo_string,
|
'Location': api.url_for(RepositoryBuildStatus, repository=repo_string,
|
||||||
|
@ -236,8 +249,7 @@ class RepositoryBuildResource(RepositoryParamResource):
|
||||||
except model.InvalidRepositoryBuildException:
|
except model.InvalidRepositoryBuildException:
|
||||||
raise NotFound()
|
raise NotFound()
|
||||||
|
|
||||||
can_write = ModifyRepositoryPermission(namespace, repository).can()
|
return build_status_view(build)
|
||||||
return build_status_view(build, can_write)
|
|
||||||
|
|
||||||
@require_repo_admin
|
@require_repo_admin
|
||||||
@nickname('cancelRepoBuild')
|
@nickname('cancelRepoBuild')
|
||||||
|
@ -271,8 +283,7 @@ class RepositoryBuildStatus(RepositoryParamResource):
|
||||||
build.repository.namespace_user.username != namespace):
|
build.repository.namespace_user.username != namespace):
|
||||||
raise NotFound()
|
raise NotFound()
|
||||||
|
|
||||||
can_write = ModifyRepositoryPermission(namespace, repository).can()
|
return build_status_view(build)
|
||||||
return build_status_view(build, can_write)
|
|
||||||
|
|
||||||
|
|
||||||
@resource('/v1/repository/<repopath:repository>/build/<build_uuid>/logs')
|
@resource('/v1/repository/<repopath:repository>/build/<build_uuid>/logs')
|
||||||
|
|
|
@ -432,7 +432,7 @@ class ActivateBuildTrigger(RepositoryParamResource):
|
||||||
except TriggerStartException as tse:
|
except TriggerStartException as tse:
|
||||||
raise InvalidRequest(tse.message)
|
raise InvalidRequest(tse.message)
|
||||||
|
|
||||||
resp = build_status_view(build_request, can_write=True)
|
resp = build_status_view(build_request)
|
||||||
repo_string = '%s/%s' % (namespace, repository)
|
repo_string = '%s/%s' % (namespace, repository)
|
||||||
headers = {
|
headers = {
|
||||||
'Location': api.url_for(RepositoryBuildStatus, repository=repo_string,
|
'Location': api.url_for(RepositoryBuildStatus, repository=repo_string,
|
||||||
|
@ -456,7 +456,7 @@ class TriggerBuildList(RepositoryParamResource):
|
||||||
builds = list(model.list_trigger_builds(namespace, repository,
|
builds = list(model.list_trigger_builds(namespace, repository,
|
||||||
trigger_uuid, limit))
|
trigger_uuid, limit))
|
||||||
return {
|
return {
|
||||||
'builds': [build_status_view(build, can_write=True) for build in builds]
|
'builds': [build_status_view(build) for build in builds]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ EXTERNAL_JS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
EXTERNAL_CSS = [
|
EXTERNAL_CSS = [
|
||||||
'netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.css',
|
'netdna.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.css',
|
||||||
'netdna.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css',
|
'netdna.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css',
|
||||||
'fonts.googleapis.com/css?family=Source+Sans+Pro:400,700',
|
'fonts.googleapis.com/css?family=Source+Sans+Pro:400,700',
|
||||||
's3.amazonaws.com/cdn.core-os.net/icons/core-icons.css'
|
's3.amazonaws.com/cdn.core-os.net/icons/core-icons.css'
|
||||||
|
|
28
static/css/directives/ui/setup-trigger-dialog.css
Normal file
28
static/css/directives/ui/setup-trigger-dialog.css
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
.setup-trigger-directive-element .dockerfile-found-content {
|
||||||
|
margin-left: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-trigger-directive-element .dockerfile-found-content:before {
|
||||||
|
content: "\f071";
|
||||||
|
font-family: FontAwesome;
|
||||||
|
color: rgb(255, 194, 0);
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-trigger-directive-element .loading {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-trigger-directive-element .loading .cor-loader-inline {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setup-trigger-directive-element .dockerfile-found {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
|
@ -1,8 +1,42 @@
|
||||||
.source-commit-link-element .fa {
|
.source-commit-link-element .commit-circle {
|
||||||
margin-right: 4px;
|
margin-right: 6px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.source-commit-link-element .commit-circle {
|
||||||
|
display: inline-block;
|
||||||
|
border: 2px solid #999;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-commit-link-element .commit-circle:before,
|
||||||
|
.source-commit-link-element .commit-circle:after {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
border-top: 2px solid #999;
|
||||||
|
height: 10px;
|
||||||
|
width: 4px;
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-commit-link-element .commit-circle:before {
|
||||||
|
left: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-commit-link-element .commit-circle:after {
|
||||||
|
left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.source-commit-link-element {
|
.source-commit-link-element {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-commit-link-element .anchor {
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
9
static/css/directives/ui/step-view-step.css
Normal file
9
static/css/directives/ui/step-view-step.css
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.step-view-step-content .loading-message {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-view-step-content .loading-message .cor-loader-inline {
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
|
@ -42,7 +42,7 @@
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.trigger-setup-githost-element li.repo-listing i {
|
.trigger-setup-githost-element li.host-repo-listing i {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,8 @@
|
||||||
.triggered-build-description-element .commit-who img {
|
.triggered-build-description-element .commit-who img {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin-left: 2px;
|
margin-left: 4px;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
border-radius: 50%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.triggered-build-description-element .fa-github {
|
.triggered-build-description-element .fa-github {
|
||||||
|
|
|
@ -3768,27 +3768,6 @@ pre.command:before {
|
||||||
border-bottom-left-radius: 0px;
|
border-bottom-left-radius: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup-trigger-directive-element .dockerfile-found-content {
|
|
||||||
margin-left: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.setup-trigger-directive-element .dockerfile-found-content:before {
|
|
||||||
content: "\f071";
|
|
||||||
font-family: FontAwesome;
|
|
||||||
color: rgb(255, 194, 0);
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.setup-trigger-directive-element .dockerfile-found {
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
padding-bottom: 16px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.slideinout {
|
.slideinout {
|
||||||
-webkit-transition:0.5s all;
|
-webkit-transition:0.5s all;
|
||||||
transition:0.5s linear all;
|
transition:0.5s linear all;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<span class="anchor-element">
|
<span class="anchor-element">
|
||||||
<a ng-href="{{ href }}" ng-show="href && !isOnlyText"><span ng-transclude></span></a>
|
<a ng-href="{{ href }}" ng-show="href && !isOnlyText" target="{{ target }}"><span ng-transclude></span></a>
|
||||||
<span ng-show="!href || isOnlyText"><span ng-transclude></span></span>
|
<span ng-show="!href || isOnlyText"><span ng-transclude></span></span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
style="min-width: 66px;">
|
style="min-width: 66px;">
|
||||||
<a href="javascript:void(0)" ng-click="orderBy('tags')">Tags</a>
|
<a href="javascript:void(0)" ng-click="orderBy('tags')">Tags</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="options-col hidden-xs"></td>
|
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tr ng-repeat="build in fullBuilds">
|
<tr ng-repeat="build in fullBuilds">
|
||||||
|
@ -139,6 +138,7 @@
|
||||||
<td>{{ trigger.config.branchtag_regex || 'All' }}</td>
|
<td>{{ trigger.config.branchtag_regex || 'All' }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="entity-reference" entity="trigger.pull_robot" ng-if="trigger.pull_robot"></span>
|
<span class="entity-reference" entity="trigger.pull_robot" ng-if="trigger.pull_robot"></span>
|
||||||
|
<span class="empty" ng-if="!trigger.pull_robot">(None)</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="cor-options-menu">
|
<span class="cor-options-menu">
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<div class="setup-trigger-directive-element">
|
<div class="setup-trigger-directive-element">
|
||||||
|
|
||||||
<!-- Modal message dialog -->
|
<!-- Modal message dialog -->
|
||||||
<div class="modal fade" id="setupTriggerModal">
|
<div class="modal fade" id="setupTriggerModal">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
|
@ -8,8 +7,8 @@
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<h4 class="modal-title">Setup new build trigger</h4>
|
<h4 class="modal-title">Setup new build trigger</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" ng-show="currentView == 'activating'">
|
<div class="modal-body loading" ng-show="currentView == 'activating'">
|
||||||
<span class="quay-spinner"></span> Setting up trigger...
|
<span class="cor-loader-inline"></span> Setting up trigger...
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" ng-show="currentView != 'activating'">
|
<div class="modal-body" ng-show="currentView != 'activating'">
|
||||||
<!-- Trigger-specific setup -->
|
<!-- Trigger-specific setup -->
|
||||||
|
@ -34,8 +33,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Loading pull information -->
|
<!-- Loading pull information -->
|
||||||
<div ng-show="currentView == 'analyzing'">
|
<div ng-show="currentView == 'analyzing'" class="loading">
|
||||||
<span class="quay-spinner"></span> Checking pull credential requirements...
|
<span class="cor-loader-inline"></span> Checking pull credential requirements...
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Pull information -->
|
<!-- Pull information -->
|
||||||
|
@ -125,7 +124,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer" ng-show="currentView != 'activating'">
|
||||||
<button type="button" class="btn btn-primary" ng-disabled="!state.stepValid"
|
<button type="button" class="btn btn-primary" ng-disabled="!state.stepValid"
|
||||||
ng-click="nextStepCounter = nextStepCounter + 1"
|
ng-click="nextStepCounter = nextStepCounter + 1"
|
||||||
ng-show="currentView == 'config'">Next</button>
|
ng-show="currentView == 'config'">Next</button>
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
<span class="source-commit-link-elememt">
|
<span class="source-commit-link-element">
|
||||||
<i class="fa fa-dot-circle-o" data-title="Commit" data-container="body" bs-tooltip></i>
|
<soan class="commit-circle-container" data-title="Commit" data-container="body" bs-tooltip>
|
||||||
<span class="anchor" href="getUrl(commitSha, urlTemplate)" target="_blank" is-only-text="!urlTemplate">
|
<span class="commit-circle"></span>
|
||||||
{{ commitSha.substring(0, 8) }}
|
</span>
|
||||||
|
<span class="anchor" href="{{ getUrl(commitSha, urlTemplate) }}" target="_blank"
|
||||||
|
is-only-text="!urlTemplate">
|
||||||
|
{{ commitSha.substring(0, 8) }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
<!-- Branch -->
|
<!-- Branch -->
|
||||||
<span ng-switch-when="heads">
|
<span ng-switch-when="heads">
|
||||||
<i class="fa fa-code-fork" data-container="body" data-title="Branch" bs-tooltip></i>
|
<i class="fa fa-code-fork" data-container="body" data-title="Branch" bs-tooltip></i>
|
||||||
<span href="getUrl(ref, branchTemplate, 'branch')" is-only-text="!branchTemplate" target="_blank">{{ getTitle(ref) }}</span>
|
<span class="anchor" href="{{ getUrl(ref, branchTemplate, 'branch') }}" is-only-text="!branchTemplate" target="_blank">{{ getTitle(ref) }}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!-- Tag -->
|
<!-- Tag -->
|
||||||
<span ng-switch-when="tags">
|
<span ng-switch-when="tags">
|
||||||
<i class="fa fa-tag" data-container="body" data-title="Tag" bs-tooltip></i>
|
<i class="fa fa-tag" data-container="body" data-title="Tag" bs-tooltip></i>
|
||||||
<span href="getUrl(ref, tagTemplate, 'tag')" is-only-text="!tagTemplate" target="_blank">{{ getTitle(ref) }}</span>
|
<span class="anchor" href="{{ getUrl(ref, tagTemplate, 'tag') }}" is-only-text="!tagTemplate" target="_blank">{{ getTitle(ref) }}</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<span class="step-view-step-content">
|
<div class="step-view-step-content">
|
||||||
<span ng-show="!loading">
|
<div ng-show="!loading">
|
||||||
<span ng-transclude></span>
|
<div ng-transclude></div>
|
||||||
</span>
|
</div>
|
||||||
<span ng-show="loading">
|
<div ng-show="loading" class="loading-message">
|
||||||
<span class="quay-spinner"></span>
|
<span class="cor-loader-inline"></span>
|
||||||
{{ loadMessage }}
|
{{ loadMessage }}
|
||||||
</span>
|
</div>
|
||||||
</span>
|
</div>
|
||||||
|
|
|
@ -8,17 +8,12 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="current-repo">
|
<div class="current-repo">
|
||||||
|
<i class="dropdown-select-icon org-icon fa" ng-class="'fa-' + kind"
|
||||||
|
ng-show="!state.currentRepo.avatar_url"></i>
|
||||||
<img class="dropdown-select-icon org-icon"
|
<img class="dropdown-select-icon org-icon"
|
||||||
ng-src="{{ state.currentRepo.avatar_url ? state.currentRepo.avatar_url : '/static/img/empty.png' }}">
|
ng-src="{{ state.currentRepo.avatar_url ? state.currentRepo.avatar_url : '/static/img/empty.png' }}"
|
||||||
|
ng-show="state.currentRepo.avatar_url">
|
||||||
<!-- Kind Switch -->
|
{{ state.currentRepo.repo }}
|
||||||
<a ng-href="https://github.com/{{ state.currentRepo.repo }}" target="_blank" ng-if="kind == 'github'">
|
|
||||||
{{ state.currentRepo.repo }}
|
|
||||||
</a>
|
|
||||||
<a ng-href="https://bitbucket.org/{{ state.currentRepo.repo }}" target="_blank" ng-if="kind == 'bitbucket'">
|
|
||||||
{{ state.currentRepo.repo }}
|
|
||||||
</a>
|
|
||||||
<!-- /Kind Switch -->
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -61,14 +56,17 @@
|
||||||
<!-- Icons -->
|
<!-- Icons -->
|
||||||
<i class="dropdown-select-icon none-icon fa fa-lg" ng-class="'fa-' + kind"></i>
|
<i class="dropdown-select-icon none-icon fa fa-lg" ng-class="'fa-' + kind"></i>
|
||||||
<img class="dropdown-select-icon org-icon"
|
<img class="dropdown-select-icon org-icon"
|
||||||
ng-src="{{ state.currentRepo.avatar_url ? state.currentRepo.avatar_url : '/static/image/empty.png' }}">
|
ng-show="state.currentRepo.avatar_url"
|
||||||
|
ng-src="{{ state.currentRepo.avatar_url ? state.currentRepo.avatar_url : '/static/img/empty.png' }}">
|
||||||
|
<i class="dropdown-select-icon org-icon fa fa-lg" ng-class="'fa-' + kind"
|
||||||
|
ng-show="!state.currentRepo.avatar_url"></i>
|
||||||
|
|
||||||
<!-- Dropdown menu -->
|
<!-- Dropdown menu -->
|
||||||
<ul class="dropdown-select-menu scrollable-menu" role="menu">
|
<ul class="dropdown-select-menu scrollable-menu" role="menu">
|
||||||
<li ng-repeat-start="org in orgs" role="presentation" class="dropdown-header org-header">
|
<li ng-repeat-start="org in orgs" role="presentation" class="dropdown-header org-header">
|
||||||
<img ng-src="{{ org.info.avatar_url }}" class="org-icon">{{ org.info.name }}
|
<img ng-src="{{ org.info.avatar_url }}" class="org-icon">{{ org.info.name }}
|
||||||
</li>
|
</li>
|
||||||
<li ng-repeat="repo in org.repos" class="repo-listing">
|
<li ng-repeat="repo in org.repos" class="trigger-repo-listing">
|
||||||
<a href="javascript:void(0)" ng-click="selectRepo(repo, org)">
|
<a href="javascript:void(0)" ng-click="selectRepo(repo, org)">
|
||||||
<i class="fa fa-lg" ng-class="'fa-' + kind"></i> {{ repo }}
|
<i class="fa fa-lg" ng-class="'fa-' + kind"></i> {{ repo }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -187,7 +185,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="quay-spinner" ng-show="!locations && !locationError"></div>
|
<div class="cor-loader" ng-show="!locations && !locationError"></div>
|
||||||
<div class="alert alert-warning" ng-show="locationError">
|
<div class="alert alert-warning" ng-show="locationError">
|
||||||
{{ locationError }}
|
{{ locationError }}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,39 +7,51 @@
|
||||||
|
|
||||||
<!-- Manually built with a user -->
|
<!-- Manually built with a user -->
|
||||||
<div class="tbd-content" ng-switch-when="manual+user">
|
<div class="tbd-content" ng-switch-when="manual+user">
|
||||||
<i class="fa fa-user"></i> {{ build.job_config.manual_user }}
|
<i class="fa fa-user"></i> {{ build.manual_user }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Source information only (i.e. no info) -->
|
<!-- Source information only (i.e. no info) -->
|
||||||
<div class="tbd-content" ng-switch-when="source">
|
<div class="tbd-content" ng-switch-when="source">
|
||||||
Triggered by commit to
|
Triggered by
|
||||||
<div class="trigger-description" short="true" trigger="build.trigger"></div>
|
<div class="trigger-description" short="true" trigger="build.trigger"
|
||||||
|
style="display: inline-block; margin-left: 4px;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Just commit SHA -->
|
<!-- Just commit SHA -->
|
||||||
<div class="tbd-content" ng-switch-when="commitsha">
|
<div class="tbd-content" ng-switch-when="commitsha">
|
||||||
Triggered by commit
|
Triggered by commit
|
||||||
<span class="source-commit-link"
|
<span class="source-commit-link"
|
||||||
commit-sha="build.job_config.trigger_metadata.commit_sha"></span>
|
commit-sha="build.trigger_metadata.commit_sha"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Full Commit Information -->
|
<!-- Full Commit Information -->
|
||||||
<div class="tbd-content" ng-switch-when="fullcommit">
|
<div class="tbd-content" ng-switch-when="fullcommit">
|
||||||
<div class="commit-message">
|
<div class="commit-message">
|
||||||
{{ build.job_config.trigger_metadata.commit_info.message }}
|
<span class="anchor" is-only-text="!TriggerService.getFullLinkTemplate(build, 'commit')"
|
||||||
|
target="_blank" href="{{ TriggerService.getFullLinkTemplate(build, 'commit').replace('{sha}', build.trigger_metadata.commit_sha) }}">
|
||||||
|
{{ build.trigger_metadata.commit_info.message }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="commit-information">
|
<div class="commit-information">
|
||||||
<span class="commit-who-when">
|
<span class="commit-who-when">
|
||||||
Authored
|
Authored
|
||||||
<span am-time-ago="build.job_config.trigger_metadata.commit_info.date"></span>
|
<span am-time-ago="build.trigger_metadata.commit_info.date"></span>
|
||||||
<span class="commit-who">
|
<span class="anchor commit-who"
|
||||||
{{ build.job_config.trigger_metadata.commit_info.author.username }}
|
href="{{ build.trigger_metadata.commit_info.author.url }}"
|
||||||
|
is-only-text="!build.trigger_metadata.commit_info.author.url"
|
||||||
|
target="_blank">
|
||||||
|
<img ng-src="{{ build.trigger_metadata.commit_info.author.avatar_url }}"
|
||||||
|
ng-if="build.trigger_metadata.commit_info.author.avatar_url">
|
||||||
|
{{ build.trigger_metadata.commit_info.author.username }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="source-commit-link"
|
<span class="source-commit-link"
|
||||||
commit-sha="build.job_config.trigger_metadata.commit_sha"></span>
|
commit-sha="build.trigger_metadata.commit_sha"
|
||||||
|
url-template="TriggerService.getFullLinkTemplate(build, 'commit')"></span>
|
||||||
<span class="source-ref-link"
|
<span class="source-ref-link"
|
||||||
ref="build.job_config.trigger_metadata.ref"></span>
|
ref="build.trigger_metadata.ref"
|
||||||
|
branch-template="TriggerService.getFullLinkTemplate(build, 'branch')"
|
||||||
|
tag-template="TriggerService.getFullLinkTemplate(build, 'tag')"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -42,15 +42,14 @@ angular.module('quay').directive('repoPanelBuilds', function () {
|
||||||
|
|
||||||
var unordered = $scope.allBuilds.map(function(build_info) {
|
var unordered = $scope.allBuilds.map(function(build_info) {
|
||||||
var commit_sha = null;
|
var commit_sha = null;
|
||||||
var job_config = build_info.job_config || {};
|
|
||||||
|
|
||||||
if (job_config.trigger_metadata) {
|
if (build_info.trigger_metadata) {
|
||||||
commit_sha = job_config.trigger_metadata.commit_sha;
|
commit_sha = build_info.trigger_metadata.commit_sha;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $.extend(build_info, {
|
return $.extend(build_info, {
|
||||||
'started_datetime': (new Date(build_info.started)).valueOf() * (-1),
|
'started_datetime': (new Date(build_info.started)).valueOf() * (-1),
|
||||||
'building_tags': job_config.docker_tags || [],
|
'building_tags': build_info.tags || [],
|
||||||
'commit_sha': commit_sha
|
'commit_sha': commit_sha
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,7 @@ angular.module('quay').directive('anchor', function () {
|
||||||
restrict: 'C',
|
restrict: 'C',
|
||||||
scope: {
|
scope: {
|
||||||
'href': '@href',
|
'href': '@href',
|
||||||
|
'target': '@target',
|
||||||
'isOnlyText': '=isOnlyText'
|
'isOnlyText': '=isOnlyText'
|
||||||
},
|
},
|
||||||
controller: function($scope, $element) {
|
controller: function($scope, $element) {
|
||||||
|
|
|
@ -6,11 +6,12 @@ angular.module('quay').directive('sourceCommitLink', function () {
|
||||||
priority: 0,
|
priority: 0,
|
||||||
templateUrl: '/static/directives/source-commit-link.html',
|
templateUrl: '/static/directives/source-commit-link.html',
|
||||||
replace: false,
|
replace: false,
|
||||||
transclude: false,
|
transclude: true,
|
||||||
restrict: 'C',
|
restrict: 'C',
|
||||||
scope: {
|
scope: {
|
||||||
'commitSha': '=commitSha',
|
'commitSha': '=commitSha',
|
||||||
'urlTemplate': '=urlTemplate'
|
'urlTemplate': '=urlTemplate',
|
||||||
|
'showTransclude': '=showTransclude'
|
||||||
},
|
},
|
||||||
controller: function($scope, $element) {
|
controller: function($scope, $element) {
|
||||||
$scope.getUrl = function(sha, template) {
|
$scope.getUrl = function(sha, template) {
|
||||||
|
|
|
@ -16,26 +16,38 @@ angular.module('quay').directive('stepView', function ($compile) {
|
||||||
'stepsCompleted': '&stepsCompleted'
|
'stepsCompleted': '&stepsCompleted'
|
||||||
},
|
},
|
||||||
controller: function($scope, $element, $rootScope) {
|
controller: function($scope, $element, $rootScope) {
|
||||||
this.currentStepIndex = -1;
|
var currentStepIndex = -1;
|
||||||
this.steps = [];
|
var steps = [];
|
||||||
this.watcher = null;
|
var watcher = null;
|
||||||
|
|
||||||
this.getCurrentStep = function() {
|
// Members on 'this' are accessed by the individual steps.
|
||||||
return this.steps[this.currentStepIndex];
|
this.register = function(scope, element) {
|
||||||
|
element.hide();
|
||||||
|
|
||||||
|
steps.push({
|
||||||
|
'scope': scope,
|
||||||
|
'element': element
|
||||||
|
});
|
||||||
|
|
||||||
|
nextStep();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.reset = function() {
|
var getCurrentStep = function() {
|
||||||
this.currentStepIndex = -1;
|
return steps[currentStepIndex];
|
||||||
for (var i = 0; i < this.steps.length; ++i) {
|
};
|
||||||
this.steps[i].element.hide();
|
|
||||||
|
var reset = function() {
|
||||||
|
currentStepIndex = -1;
|
||||||
|
for (var i = 0; i < steps.length; ++i) {
|
||||||
|
steps[i].element.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.currentStepValid = false;
|
$scope.currentStepValid = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.next = function() {
|
var next = function() {
|
||||||
if (this.currentStepIndex >= 0) {
|
if (currentStepIndex >= 0) {
|
||||||
var currentStep = this.getCurrentStep();
|
var currentStep = getCurrentStep();
|
||||||
if (!currentStep || !currentStep.scope) { return; }
|
if (!currentStep || !currentStep.scope) { return; }
|
||||||
|
|
||||||
if (!currentStep.scope.completeCondition) {
|
if (!currentStep.scope.completeCondition) {
|
||||||
|
@ -44,20 +56,20 @@ angular.module('quay').directive('stepView', function ($compile) {
|
||||||
|
|
||||||
currentStep.element.hide();
|
currentStep.element.hide();
|
||||||
|
|
||||||
if (this.unwatch) {
|
if (unwatch) {
|
||||||
this.unwatch();
|
unwatch();
|
||||||
this.unwatch = null;
|
unwatch = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentStepIndex++;
|
currentStepIndex++;
|
||||||
|
|
||||||
if (this.currentStepIndex < this.steps.length) {
|
if (currentStepIndex < steps.length) {
|
||||||
var currentStep = this.getCurrentStep();
|
var currentStep = getCurrentStep();
|
||||||
currentStep.element.show();
|
currentStep.element.show();
|
||||||
currentStep.scope.load()
|
currentStep.scope.load()
|
||||||
|
|
||||||
this.unwatch = currentStep.scope.$watch('completeCondition', function(cc) {
|
unwatch = currentStep.scope.$watch('completeCondition', function(cc) {
|
||||||
$scope.currentStepValid = !!cc;
|
$scope.currentStepValid = !!cc;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,23 +77,17 @@ angular.module('quay').directive('stepView', function ($compile) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.register = function(scope, element) {
|
var nextStep = function() {
|
||||||
element.hide();
|
if (!steps || !steps.length) { return; }
|
||||||
|
|
||||||
this.steps.push({
|
if ($scope.nextStepCounter >= 0) {
|
||||||
'scope': scope,
|
next();
|
||||||
'element': element
|
} else {
|
||||||
});
|
reset();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var that = this;
|
$scope.$watch('nextStepCounter', nextStep);
|
||||||
$scope.$watch('nextStepCounter', function(nsc) {
|
|
||||||
if (nsc >= 0) {
|
|
||||||
that.next();
|
|
||||||
} else {
|
|
||||||
that.reset();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return directiveDefinitionObject;
|
return directiveDefinitionObject;
|
||||||
|
|
|
@ -12,29 +12,30 @@ angular.module('quay').directive('triggeredBuildDescription', function () {
|
||||||
'build': '=build'
|
'build': '=build'
|
||||||
},
|
},
|
||||||
controller: function($scope, $element, KeyService, TriggerService) {
|
controller: function($scope, $element, KeyService, TriggerService) {
|
||||||
|
$scope.TriggerService = TriggerService;
|
||||||
$scope.$watch('build', function(build) {
|
$scope.$watch('build', function(build) {
|
||||||
if (!build) { return; }
|
if (!build) { return; }
|
||||||
|
|
||||||
var jobConfig = build.job_config || {};
|
var triggerMetadata = build.trigger_metadata || {};
|
||||||
var triggerMetadata = jobConfig.trigger_metadata || {};
|
|
||||||
|
|
||||||
if (!build.trigger && !jobConfig.manual_user) {
|
if (!build.trigger && !build.manual_user) {
|
||||||
$scope.infoDisplay = 'manual';
|
$scope.infoDisplay = 'manual';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!build.trigger && jobConfig.manual_user) {
|
if (!build.trigger && build.manual_user) {
|
||||||
$scope.infoDisplay = 'manual+user';
|
$scope.infoDisplay = 'manual+user';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggerMetadata.commit_info) {
|
if (build.trigger && triggerMetadata.commit_info) {
|
||||||
$scope.infoDisplay = 'fullcommit';
|
$scope.infoDisplay = 'fullcommit';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggerMetadata.commit_sha) {
|
if (build.trigger && build.trigger.build_source && triggerMetadata.commit_sha) {
|
||||||
$scope.infoDisplay = 'commitsha';
|
$scope.infoDisplay = 'commitsha';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.infoDisplay = 'source';
|
$scope.infoDisplay = 'source';
|
||||||
|
|
|
@ -30,16 +30,14 @@
|
||||||
|
|
||||||
var determineDockerfilePath = function() {
|
var determineDockerfilePath = function() {
|
||||||
var dockerfilePath = 'Dockerfile';
|
var dockerfilePath = 'Dockerfile';
|
||||||
if ($scope.repobuild['job_config']) {
|
var dockerfileFolder = ($scope.repobuild['subdirectory'] || '');
|
||||||
var dockerfileFolder = ($scope.repobuild['job_config']['build_subdir'] || '');
|
if (dockerfileFolder[0] == '/') {
|
||||||
if (dockerfileFolder[0] == '/') {
|
dockerfileFolder = dockerfileFolder.substr(1);
|
||||||
dockerfileFolder = dockerfileFolder.substr(1);
|
|
||||||
}
|
|
||||||
if (dockerfileFolder && dockerfileFolder[dockerfileFolder.length - 1] != '/') {
|
|
||||||
dockerfileFolder += '/';
|
|
||||||
}
|
|
||||||
dockerfilePath = dockerfileFolder + 'Dockerfile';
|
|
||||||
}
|
}
|
||||||
|
if (dockerfileFolder && dockerfileFolder[dockerfileFolder.length - 1] != '/') {
|
||||||
|
dockerfileFolder += '/';
|
||||||
|
}
|
||||||
|
dockerfilePath = dockerfileFolder + 'Dockerfile';
|
||||||
return dockerfilePath;
|
return dockerfilePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -70,15 +70,12 @@
|
||||||
$scope.restartBuild = function(build) {
|
$scope.restartBuild = function(build) {
|
||||||
$('#confirmRestartBuildModal').modal('hide');
|
$('#confirmRestartBuildModal').modal('hide');
|
||||||
|
|
||||||
var subdirectory = '';
|
var subdirectory = build['subdirectory'] || '';
|
||||||
if (build['job_config']) {
|
|
||||||
subdirectory = build['job_config']['build_subdir'] || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
'file_id': build['resource_key'],
|
'file_id': build['resource_key'],
|
||||||
'subdirectory': subdirectory,
|
'subdirectory': subdirectory,
|
||||||
'docker_tags': build['job_config']['docker_tags']
|
'docker_tags': build['tags']
|
||||||
};
|
};
|
||||||
|
|
||||||
if (build['pull_robot']) {
|
if (build['pull_robot']) {
|
||||||
|
|
|
@ -54,6 +54,14 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
|
||||||
'templates': {
|
'templates': {
|
||||||
'credentials': '/static/directives/trigger/githost/credentials.html',
|
'credentials': '/static/directives/trigger/githost/credentials.html',
|
||||||
'trigger-description': '/static/directives/trigger/github/trigger-description.html'
|
'trigger-description': '/static/directives/trigger/github/trigger-description.html'
|
||||||
|
},
|
||||||
|
'repository_url': function(build) {
|
||||||
|
return KeyService['githubTriggerEndpoint'] + build.trigger.build_source;
|
||||||
|
},
|
||||||
|
'link_templates': {
|
||||||
|
'commit': '/commit/{sha}',
|
||||||
|
'branch': '/tree/{branch}',
|
||||||
|
'tag': '/releases/tag/{tag}',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -85,6 +93,14 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
|
||||||
'templates': {
|
'templates': {
|
||||||
'credentials': '/static/directives/trigger/githost/credentials.html',
|
'credentials': '/static/directives/trigger/githost/credentials.html',
|
||||||
'trigger-description': '/static/directives/trigger/bitbucket/trigger-description.html'
|
'trigger-description': '/static/directives/trigger/bitbucket/trigger-description.html'
|
||||||
|
},
|
||||||
|
'repository_url': function(build) {
|
||||||
|
return 'https://bitbucket.org/' + build.trigger.build_source;
|
||||||
|
},
|
||||||
|
'link_templates': {
|
||||||
|
'commit': '/commits/{sha}',
|
||||||
|
'branch': '/branch/{branch}',
|
||||||
|
'tag': '/commits/tag/{tag}',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -125,6 +141,26 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
triggerService.getFullLinkTemplate = function(build, templateName) {
|
||||||
|
var name = build.trigger.service;
|
||||||
|
var type = triggerTypes[name];
|
||||||
|
if (!type) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var repositoryUrl = type.repository_url;
|
||||||
|
if (!repositoryUrl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkTemplate = type.link_templates;
|
||||||
|
if (!linkTemplate || !linkTemplate[templateName]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return repositoryUrl(build) + linkTemplate[templateName];
|
||||||
|
};
|
||||||
|
|
||||||
triggerService.supportsFullListing = function(name) {
|
triggerService.supportsFullListing = function(name) {
|
||||||
var type = triggerTypes[name];
|
var type = triggerTypes[name];
|
||||||
if (!type) {
|
if (!type) {
|
||||||
|
|
Reference in a new issue