Fix manifest UI page to properly show the layers of manifests and show manifest lists
This commit is contained in:
parent
8cd3740c69
commit
4106f5ce51
13 changed files with 162 additions and 89 deletions
|
@ -1,19 +1,19 @@
|
|||
.image-view-layer-element {
|
||||
.manifest-view-layer-element {
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.image-view-layer-element .image-comment {
|
||||
.manifest-view-layer-element .image-comment {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.image-view-layer-element .nondocker-command {
|
||||
.manifest-view-layer-element .nondocker-command {
|
||||
font-family: monospace;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.image-view-layer-element .nondocker-command:before {
|
||||
.manifest-view-layer-element .nondocker-command:before {
|
||||
content: "\f120";
|
||||
font-family: "FontAwesome";
|
||||
font-size: 16px;
|
||||
|
@ -21,7 +21,7 @@
|
|||
color: #999;
|
||||
}
|
||||
|
||||
.image-view-layer-element .image-layer-line {
|
||||
.manifest-view-layer-element .image-layer-line {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
|
@ -31,15 +31,15 @@
|
|||
width: 0px;
|
||||
}
|
||||
|
||||
.image-view-layer-element.first .image-layer-line {
|
||||
.manifest-view-layer-element.first .image-layer-line {
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
.image-view-layer-element.last .image-layer-line {
|
||||
.manifest-view-layer-element.last .image-layer-line {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.image-view-layer-element .image-layer-dot {
|
||||
.manifest-view-layer-element .image-layer-dot {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: 5px;
|
||||
|
@ -52,17 +52,17 @@
|
|||
z-index: 2;
|
||||
}
|
||||
|
||||
.image-view-layer-element.first .image-layer-dot {
|
||||
.manifest-view-layer-element.first .image-layer-dot {
|
||||
background: #428bca;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.image-view-layer-element .dockerfile-command-element .label {
|
||||
.manifest-view-layer-element .dockerfile-command-element .label {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.image-view-layer-element .dockerfile-command-element .command-title {
|
||||
.manifest-view-layer-element .dockerfile-command-element .command-title {
|
||||
padding-top: 10px;
|
||||
padding-left: 0px;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
<div class="image-view-layer-element" ng-class="getClass()">
|
||||
<div class="image-command">
|
||||
<image-command command="image.command"></image-command>
|
||||
</div>
|
||||
<div class="image-layer-dot"></div>
|
||||
<div class="image-layer-line"></div>
|
||||
</div>
|
7
static/directives/manifest-view-layer.html
Normal file
7
static/directives/manifest-view-layer.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<div class="manifest-view-layer-element" ng-class="getClass()">
|
||||
<div class="image-command">
|
||||
<image-command command="layer.command"></image-command>
|
||||
</div>
|
||||
<div class="image-layer-dot"></div>
|
||||
<div class="image-layer-line"></div>
|
||||
</div>
|
1
static/directives/manifest-view-manifest-link.html
Normal file
1
static/directives/manifest-view-manifest-link.html
Normal file
|
@ -0,0 +1 @@
|
|||
<manifest-link repository="item.repository" manifest-digest="item.digest"></manifest-link>
|
|
@ -1,27 +1,26 @@
|
|||
/**
|
||||
* An element which displays a single layer representing an image in the image view.
|
||||
* An element which displays a single layer in the manifest view.
|
||||
*/
|
||||
angular.module('quay').directive('imageViewLayer', function () {
|
||||
angular.module('quay').directive('manifestViewLayer', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
templateUrl: '/static/directives/image-view-layer.html',
|
||||
templateUrl: '/static/directives/manifest-view-layer.html',
|
||||
replace: false,
|
||||
transclude: true,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
'repository': '=repository',
|
||||
'image': '=image',
|
||||
'images': '=images'
|
||||
'manifest': '=manifest',
|
||||
'layer': '=layer'
|
||||
},
|
||||
controller: function($scope, $element) {
|
||||
$scope.getClass = function() {
|
||||
var index = $.inArray($scope.image, $scope.images);
|
||||
if (index < 0) {
|
||||
return 'first';
|
||||
if ($scope.layer.index == 0) {
|
||||
return 'last';
|
||||
}
|
||||
|
||||
if (index == $scope.images.length - 1) {
|
||||
return 'last';
|
||||
if ($scope.layer.index == $scope.manifest.layers.length - 1) {
|
||||
return 'first';
|
||||
}
|
||||
|
||||
return '';
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
$scope.manifestResource = ApiService.getRepoManifestAsResource(params).get(function(manifest) {
|
||||
$scope.manifest = manifest;
|
||||
$scope.reversedHistory = manifest.image.history.reverse();
|
||||
$scope.reversedLayers = manifest.layers ? manifest.layers.reverse() : null;
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -57,5 +57,30 @@
|
|||
if (!Features.SECURITY_SCANNER) { return; }
|
||||
$scope.manifestPackageCounter++;
|
||||
};
|
||||
|
||||
$scope.manifestsOf = function(manifest) {
|
||||
if (!manifest || !manifest.is_manifest_list) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!manifest._mapped_manifests) {
|
||||
// Calculate once and cache to avoid angular digest cycles.
|
||||
var parsed_manifest = JSON.parse(manifest.manifest_data);
|
||||
|
||||
manifest._mapped_manifests = parsed_manifest.manifests.map(function(manifest) {
|
||||
return {
|
||||
'repository': $scope.repository,
|
||||
'raw': manifest,
|
||||
'os': manifest.platform.os,
|
||||
'architecture': manifest.platform.architecture,
|
||||
'size': manifest.size,
|
||||
'digest': manifest.digest,
|
||||
'description': `${manifest.platform.os} on ${manifest.platform.architecture}`,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return manifest._mapped_manifests;
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -10,51 +10,65 @@
|
|||
</a>
|
||||
</span>
|
||||
<span class="cor-title-content">
|
||||
<i class="fa fa-file fa-lg" style="margin-right: 10px"></i>
|
||||
<i class="fa fa-lg" ng-class="{'fa-file': !manifest.is_manifest_list, 'fa-file-text-o': manifest.is_manifest_list}" style="margin-right: 10px"></i>
|
||||
{{ manifest.digest.substr(7, 12) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<cor-tab-panel orientation="vertical" cor-nav-tabs>
|
||||
<cor-tabs>
|
||||
<cor-tab tab-title="Layers" tab-id="layers">
|
||||
<i class="fa ci-layers"></i>
|
||||
</cor-tab>
|
||||
<cor-tab tab-title="Security Scan" tab-id="vulnerabilities"
|
||||
tab-init="loadManifestSecurity()"
|
||||
quay-show="Features.SECURITY_SCANNER">
|
||||
<i class="fa fa-bug"></i>
|
||||
</cor-tab>
|
||||
<cor-tab tab-title="Packages" tab-id="packages"
|
||||
tab-init="loadManifestPackages()"
|
||||
quay-show="Features.SECURITY_SCANNER">
|
||||
<i class="fa ci-package"></i>
|
||||
</cor-tab>
|
||||
</cor-tabs>
|
||||
<!-- Manifest list -->
|
||||
<div ng-if="manifest.is_manifest_list">
|
||||
<div class="co-main-content-panel">
|
||||
<cor-table table-data="manifestsOf(manifest)" table-item-title="manifests" filter-fields="['digest', 'os', 'architecture']">
|
||||
<cor-table-col datafield="digest" sortfield="digest" title="Manifest"
|
||||
templateurl="/static/directives/manifest-view-manifest-link.html"></cor-table-col>
|
||||
<cor-table-col datafield="os" sortfield="os" title="Operating System"></cor-table-col>
|
||||
<cor-table-col datafield="architecture" sortfield="architecture" title="Architecture"></cor-table-col>
|
||||
</cor-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<cor-tab-content>
|
||||
<!-- Layers -->
|
||||
<cor-tab-pane id="layers">
|
||||
<h3>Manifest Layers</h3>
|
||||
<div class="image-view-layer" repository="repository" image="manifest.image" images="manifest.image.history"></div>
|
||||
<div class="image-view-layer" repository="repository" image="parent" images="manifest.image.history"
|
||||
ng-repeat="parent in reversedHistory"></div>
|
||||
</cor-tab-pane>
|
||||
<!-- Manifest -->
|
||||
<div ng-if="!manifest.is_manifest_list">
|
||||
<cor-tab-panel orientation="vertical" cor-nav-tabs>
|
||||
<cor-tabs>
|
||||
<cor-tab tab-title="Layers" tab-id="layers">
|
||||
<i class="fa ci-layers"></i>
|
||||
</cor-tab>
|
||||
<cor-tab tab-title="Security Scan" tab-id="vulnerabilities"
|
||||
tab-init="loadManifestSecurity()"
|
||||
quay-show="Features.SECURITY_SCANNER">
|
||||
<i class="fa fa-bug"></i>
|
||||
</cor-tab>
|
||||
<cor-tab tab-title="Packages" tab-id="packages"
|
||||
tab-init="loadManifestPackages()"
|
||||
quay-show="Features.SECURITY_SCANNER">
|
||||
<i class="fa ci-package"></i>
|
||||
</cor-tab>
|
||||
</cor-tabs>
|
||||
|
||||
<!-- Vulnerabilities -->
|
||||
<cor-tab-pane id="vulnerabilities" quay-show="Features.SECURITY_SCANNER">
|
||||
<div quay-require="['SECURITY_SCANNER']">
|
||||
<div class="manifest-vulnerability-view" repository="repository" manifest="manifest" is-enabled="manifestSecurityCounter"></div>
|
||||
</div>
|
||||
</cor-tab-pane>
|
||||
<cor-tab-content>
|
||||
<!-- Layers -->
|
||||
<cor-tab-pane id="layers">
|
||||
<h3>Manifest Layers</h3>
|
||||
<div class="manifest-view-layer" repository="repository" layer="layer"
|
||||
manifest="manifest" ng-repeat="layer in reversedLayers"></div>
|
||||
</cor-tab-pane>
|
||||
|
||||
<!-- Features -->
|
||||
<cor-tab-pane id="packages" quay-show="Features.SECURITY_SCANNER">
|
||||
<div quay-require="['SECURITY_SCANNER']">
|
||||
<div class="manifest-feature-view" repository="repository" manifest="manifest" is-enabled="manifestPackageCounter"></div>
|
||||
</div>
|
||||
</cor-tab-pane>
|
||||
</cor-tab-content>
|
||||
</cor-tab-panel>
|
||||
<!-- Vulnerabilities -->
|
||||
<cor-tab-pane id="vulnerabilities" quay-show="Features.SECURITY_SCANNER">
|
||||
<div quay-require="['SECURITY_SCANNER']">
|
||||
<div class="manifest-vulnerability-view" repository="repository" manifest="manifest" is-enabled="manifestSecurityCounter"></div>
|
||||
</div>
|
||||
</cor-tab-pane>
|
||||
|
||||
<!-- Features -->
|
||||
<cor-tab-pane id="packages" quay-show="Features.SECURITY_SCANNER">
|
||||
<div quay-require="['SECURITY_SCANNER']">
|
||||
<div class="manifest-feature-view" repository="repository" manifest="manifest" is-enabled="manifestPackageCounter"></div>
|
||||
</div>
|
||||
</cor-tab-pane>
|
||||
</cor-tab-content>
|
||||
</cor-tab-panel>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Reference in a new issue