Compare commits

...

15 Commits
0.6.0 ... 1.0.0

Author SHA1 Message Date
Joxit
2f014c1d8f Release v1.0.0: Image aggregation and catalog UI revamped 2019-01-09 22:56:05 +01:00
Jones Magloire
e6d9f11b83 Merge pull request #66 from Joxit/feat/56-image-aggregation
Image aggregation
2019-01-08 00:25:30 +01:00
Joxit
a36809408c [feat #56] Add image count for aggregated images 2019-01-07 07:41:08 +01:00
Joxit
7e2e4b6010 [feat #56] Add expand_more icon for aggregated images 2019-01-04 22:02:22 +01:00
Joxit
605e8a8d8e [feat #56] Add level aggregation with animation 2019-01-03 23:33:59 +01:00
Joxit
ac5a70c9df [feat #56] Create new tag catalog-elements with wave effect 2019-01-02 20:55:52 +01:00
Joxit
9b120bb6d5 [feat #56] Update catalog, use material-cards instead of list 2019-01-01 22:46:23 +01:00
Joxit
7446452b77 Release v0.6.1: Display image/tag count + button effect
Last release of the year !
2018-12-31 23:59:59 +01:00
Jones Magloire
d361068529 Merge pull request #65 from Joxit/feat/material-button
[material-button] Add material-button for all effective buttons
2018-12-30 22:29:24 +01:00
Joxit
b03f00ebe8 [material-button] Fix dialog buttons 2018-12-29 00:37:18 +01:00
Joxit
d0b7e7ddeb [material-button] Add material-button for all effective buttons 2018-12-28 20:44:25 +01:00
Jones Magloire
7366e709a4 Merge pull request #64 from Joxit/feat/docker-multi-stage
[docker-multi-stage] Add multi-stage-build for alpine version
2018-12-27 00:31:44 +01:00
Joxit
89e2782751 [docker-multi-stage] Add multi-stage-build for alpine version 2018-12-27 00:18:51 +01:00
Jones Magloire
3911310d89 Merge pull request #63 from Joxit/feat/image-tag-count
[feat #56] Add image and tags count
2018-12-25 23:23:33 +01:00
Joxit
d599c1c202 [feat #56] Add image and tags count 2018-12-21 23:55:23 +01:00
34 changed files with 296 additions and 113 deletions

View File

@@ -1,4 +1,7 @@
*
!dist
!bin
!nginx
!nginx
!src
!package.json
!gulpfile.js

View File

@@ -12,10 +12,22 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
FROM node:10-alpine AS builder
WORKDIR /usr/app
COPY package.json .
RUN yarn install
COPY . .
RUN yarn build
FROM nginx:alpine
LABEL maintainer="Jones MAGLOIRE @Joxit"
WORKDIR /usr/share/nginx/html/
COPY dist/ /usr/share/nginx/html/
COPY --from=builder /usr/app/dist/ /usr/share/nginx/html/

View File

@@ -11,7 +11,7 @@ This web user interface uses [Riot](https://github.com/Riot/riot) the react-like
## [GitHub Page](https://joxit.github.io/docker-registry-ui) and [Live Demo](https://joxit.github.io/docker-registry-ui/demo/)
![screenshot](https://raw.github.com/Joxit/docker-registry-ui/master/screenshot.png "Screenshot of Docker Registry UI")
![preview](https://raw.github.com/Joxit/docker-registry-ui/master/docker-registry-ui.gif "Screenshot of Docker Registry UI")
## Features
@@ -29,6 +29,8 @@ This web user interface uses [Riot](https://github.com/Riot/riot) the react-like
- Show sha256 for specific tag (hover image tag)
- Display image creation date (see #49)
- Display image history (see #58)
- Display image/tag count
- Image aggregation (see #56)
## Getting Started

2
dist/index.html vendored
View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/style.css vendored

File diff suppressed because one or more lines are too long

BIN
docker-registry-ui.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 KiB

View File

@@ -58,7 +58,7 @@ function appStatic() {
.pipe(license('agpl3', {
tiny: false,
project: 'docker-registry-ui',
year: '2016-2018',
year: '2016-2019',
organization: 'Jones Magloire @Joxit'
}))
.pipe(injectVersion())
@@ -72,7 +72,7 @@ function app() {
.pipe(license('agpl3', {
tiny: false,
project: 'docker-registry-ui',
year: '2016-2018',
year: '2016-2019',
organization: 'Jones Magloire @Joxit'
}))
.pipe(injectVersion())
@@ -94,7 +94,7 @@ function styles() {
.pipe(license('agpl3', {
tiny: false,
project: 'docker-registry-ui',
year: '2016-2018',
year: '2016-2019',
organization: 'Jones Magloire @Joxit'
}))
.pipe(gulp.dest('dist/'));

View File

@@ -1,6 +1,6 @@
{
"name": "docker-registry-ui",
"version": "0.6.0",
"version": "1.0.0",
"scripts": {
"build": "./node_modules/gulp/bin/gulp.js build"
},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -39,6 +39,7 @@
<!-- endbuild -->
<!-- build:js scripts/docker-registry-ui.js -->
<script src="tags/catalog.tag" type="riot/tag"></script>
<script src="tags/catalog-element.tag" type="riot/tag"></script>
<script src="tags/tag-history-button.tag" type="riot/tag"></script>
<script src="tags/tag-history.tag" type="riot/tag"></script>
<script src="tags/tag-history-element.tag" type="riot/tag"></script>

View File

@@ -11,7 +11,9 @@
url(fonts/MaterialIcons-Regular.ttf) format('truetype');
}
.material-icons {
material-button .content i.material-icons,
material-button[rounded=true] .content i.material-icons,
i.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
@@ -36,4 +38,9 @@
/* Support for IE. */
font-feature-settings: 'liga';
}
}
material-button .content i.material-icons,
material-button[rounded=true] .content i.material-icons {
margin: auto;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2018 Jones Magloire @Joxit
* Copyright (C) 2016-2019 Jones Magloire @Joxit
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2018 Jones Magloire @Joxit
* Copyright (C) 2016-2019 Jones Magloire @Joxit
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2018 Jones Magloire @Joxit
* Copyright (C) 2016-2019 Jones Magloire @Joxit
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by

View File

@@ -88,17 +88,23 @@ h2 {
overflow: hidden;
}
.material-card-title-action h2 .item-count {
font-size: 0.7em;
margin-left: 1em;
}
.list {
display: block;
padding: 8px 0;
list-style: none;
}
.list.highlight > li:hover {
.list.highlight:hover {
background-color: #eee;
cursor: pointer;
}
.list > span,
.list > li {
box-sizing: border-box;
line-height: 1;
@@ -107,6 +113,7 @@ h2 {
overflow: hidden;
}
.list > span i.material-icons,
.list > li i.material-icons {
margin-right: 32px;
height: 24px;
@@ -116,6 +123,28 @@ h2 {
color: #757575;
}
.list > span .right i.material-icons.animated {
transition: all 350ms cubic-bezier(.4,0,.2,1);
margin-right: 10px;
}
.list > span .right {
position: absolute;
align-self: end;
display: flex;
align-items: center;
right: 0;
}
.list > span i.material-icons.animated.expanded {
transform: rotate(180deg);
}
.list > span .item-count {
font-size: 0.75em;
}
.list > span,
.list > li > span {
height: 100%;
text-decoration: none;
@@ -128,6 +157,11 @@ h2 {
align-items: center;
}
material-card.list {
margin-top: 10px;
margin-bottom: 10px;
}
.material-card-title-action {
-webkit-align-items: center;
-ms-flex-align: center;
@@ -170,16 +204,21 @@ material-card table th {
text-align: left;
}
material-card material-button:hover,
material-card table tbody tr:hover {
background-color: #eee;
}
material-card material-button,
material-card table tbody tr {
transition-duration: .28s;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
transition-property: background-color;
}
material-card table tbody tr {
position: relative;
height: 48px;
transition-duration: .28s;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
transition-property: background-color;
}
material-card table td {
@@ -218,6 +257,7 @@ material-card table th.material-card-th-sorted-descending:before {
content: "\e5db";
}
material-button .content i.material-icons,
.material-icons {
color: #777;
}
@@ -295,6 +335,7 @@ material-popup .popup {
footer {
width: 100%;
position: fixed;
z-index: 75;
bottom: 0;
}
@@ -334,10 +375,7 @@ select {
text-align: center;
}
.copy-to-clipboard a:hover {
cursor: pointer;
}
catalog material-card,
tag-history material-card {
min-height: auto;
}
@@ -377,4 +415,34 @@ tag-history-element.id div.value {
tag-history-button button {
background: none;
border: none;
}
material-card material-button {
max-height: 30px;
max-width: 30px;
}
material-button:hover material-waves {
background: none;
}
material-card material-button {
background-color: inherit;
}
catalog-element material-card {
z-index: 2;
position: relative;
}
catalog-element catalog-element material-card {
transition: all 350ms cubic-bezier(.4,0,.2,1);
z-index: 1;
position: relative;
}
catalog-element catalog-element.showing material-card,
catalog-element catalog-element.hide material-card {
margin-top: -50px;
opacity: 0;
}

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -231,6 +231,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.ceil(bytes / Math.pow(1024, i)) + ' ' + sizes[i];
};
registryUI.taglist.go = function(image) {
route('taglist/' + image);
};
route.start(true);
</script>
</app>

View File

@@ -0,0 +1,59 @@
<!--
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<catalog-element>
<!-- Begin of tag -->
<material-card class="list highlight" item="{item}" expanded="{expanded}">
<material-waves onmousedown="{launch}" center="true" color="#ddd" />
<span>
<i class="material-icons">send</i>
{ typeof opts.item === "string" ? opts.item : opts.item.repo }
<div hide="{typeof opts.item === "string"}" class="item-count right">
{ opts.item.images && opts.item.images.length } images
<i class="material-icons animated {expanded: opts.expanded}">expand_more</i>
</div>
</span>
</material-card>
<catalog-element hide="{typeof opts.item === "string"}" class="animated {hide: !expanded, expanding: expanding}" each="{item in item.images}" />
<script>
this.on('mount', function() {
const self = this;
const card = this.tags['material-card'];
if (!card) {
return;
}
// Launch waves
card.launch = function(e) {
card.tags['material-waves'].trigger('launch',e);
}
if (this.item.images && this.item.images.length === 1) {
this.item = this.item.images[0];
}
card.root.onclick = function(e) {
if (!self.item.repo) {
registryUI.taglist.go(self.item);
} else {
self.expanded = !self.expanded;
self.update({expanded: self.expanded, expanding: true});
setTimeout(function() {
self.update({expanded: self.expanded, expanding: false});
}, 50)
}
}
})
</script>
<!-- End of tag -->
</catalog-element>

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -18,21 +18,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<!-- Begin of tag -->
<material-card ref="catalog-tag" class="catalog">
<div class="material-card-title-action">
<h2>Repositories of { registryUI.name() }</h2>
<h2>
Repositories of { registryUI.name() }
<div class="item-count">{ registryUI.catalog.length } images</div>
</h2>
</div>
<div hide="{ registryUI.catalog.loadend }" class="spinner-wrapper">
<material-spinner></material-spinner>
</div>
<ul class="list highlight" show="{ registryUI.catalog.loadend }">
<li each="{ item in registryUI.catalog.repositories }" onclick="registryUI.catalog.go('{item}');">
<span>
<i class="material-icons">send</i>
{ item }
</span>
</li>
</ul>
</material-card>
<catalog-element each="{ item in registryUI.catalog.repositories }" />
<script>
registryUI.catalog.instance = this;
registryUI.catalog.display = function() {
@@ -43,6 +38,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
if (this.status == 200) {
registryUI.catalog.repositories = JSON.parse(this.responseText).repositories || [];
registryUI.catalog.repositories.sort();
registryUI.catalog.length = registryUI.catalog.repositories.length; registryUI.catalog.repositories = registryUI.catalog.repositories.reduce(function(acc, e) {
const slash = e.indexOf('/');
if (slash > 0) {
const repoName = e.substring(0, slash) + '/';
if (acc.length == 0 || acc[acc.length - 1].repo != repoName) {
acc.push({repo: repoName, images: []});
}
acc[acc.length - 1].images.push(e);
return acc;
}
acc.push(e);
return acc;
}, []);
} else if (this.status == 404) {
registryUI.snackbar('Server not found', true);
} else {
@@ -60,9 +68,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
oReq.open('GET', registryUI.url() + '/v2/_catalog?n=100000');
oReq.send();
};
registryUI.catalog.go = function(image) {
route('taglist/' + image);
};
registryUI.catalog.display();
</script>
<!-- End of tag -->

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -16,9 +16,9 @@
-->
<copy-to-clipboard>
<input ref="input" style="display: none; width: 1px; height: 1px;" value="{ this.dockerCmd }">
<a onclick="{ this.copy }" title="Copy pull command.">
<material-button waves-center="true" rounded="true" waves-color="#ddd" onclick="{ this.copy }" title="Copy pull command.">
<i class="material-icons">content_copy</i>
</a>
</material-button>
<script type="text/javascript">
this.dockerCmd = 'docker pull ' + registryUI.cleanName() + '/' + opts.image.name + ':' + opts.image.tag;
this.copy = function () {

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -15,49 +15,51 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<remove-image>
<a href="#" title="This will delete the image."
onclick="registryUI.removeImage.remove('{ opts.image.name }', '{ opts.image.tag }')">
<material-button waves-center="true" rounded="true" waves-color="#ddd" title="This will delete the image.">
<i class="material-icons">delete</i>
</a>
</material-button>
<script type="text/javascript">
registryUI.removeImage = registryUI.removeImage || {};
registryUI.removeImage.remove = function(name, tag) {
const oReq = new Http();
oReq.addEventListener('loadend', function() {
registryUI.taglist.refresh();
if (this.status == 200) {
if (!this.hasHeader('Docker-Content-Digest')) {
registryUI.errorSnackbar('You need to add Access-Control-Expose-Headers: [\'Docker-Content-Digest\'] in your server configuration.');
return;
}
const digest = this.getResponseHeader('Docker-Content-Digest');
const oReq = new Http();
oReq.addEventListener('loadend', function() {
if (this.status == 200 || this.status == 202) {
registryUI.taglist.refresh();
registryUI.snackbar('Deleting ' + name + ':' + tag + ' image. Run `registry garbage-collect config.yml` on your registry');
} else if (this.status == 404) {
registryUI.errorSnackbar('Digest not found');
} else {
registryUI.snackbar(this.responseText);
const self = this;
this.on('mount', function() {
this.tags['material-button'].root.onclick = function() {
const name = self.opts.image.name;
const tag = self.opts.image.tag;
const oReq = new Http();
oReq.addEventListener('loadend', function() {
registryUI.taglist.go(name);
if (this.status == 200) {
if (!this.hasHeader('Docker-Content-Digest')) {
registryUI.errorSnackbar('You need to add Access-Control-Expose-Headers: [\'Docker-Content-Digest\'] in your server configuration.');
return;
}
});
oReq.open('DELETE', registryUI.url() + '/v2/' + name + '/manifests/' + digest);
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json');
oReq.addEventListener('error', function() {
registryUI.errorSnackbar('An error occurred when deleting image. Check if your server accept DELETE methods Access-Control-Allow-Methods: [\'DELETE\'].');
});
oReq.send();
} else if (this.status == 404) {
registryUI.errorSnackbar('Manifest for ' + name + ':' + tag + ' not found');
} else {
registryUI.snackbar(this.responseText);
}
});
oReq.open('HEAD', registryUI.url() + '/v2/' + name + '/manifests/' + tag);
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json');
oReq.send();
};
const digest = this.getResponseHeader('Docker-Content-Digest');
const oReq = new Http();
oReq.addEventListener('loadend', function() {
if (this.status == 200 || this.status == 202) {
registryUI.taglist.display()
registryUI.snackbar('Deleting ' + name + ':' + tag + ' image. Run `registry garbage-collect config.yml` on your registry');
} else if (this.status == 404) {
registryUI.errorSnackbar('Digest not found');
} else {
registryUI.snackbar(this.responseText);
}
});
oReq.open('DELETE', registryUI.url() + '/v2/' + name + '/manifests/' + digest);
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json');
oReq.addEventListener('error', function() {
registryUI.errorSnackbar('An error occurred when deleting image. Check if your server accept DELETE methods Access-Control-Allow-Methods: [\'DELETE\'].');
});
oReq.send();
} else if (this.status == 404) {
registryUI.errorSnackbar('Manifest for ' + name + ':' + tag + ' not found');
} else {
registryUI.snackbar(this.responseText);
}
});
oReq.open('HEAD', registryUI.url() + '/v2/' + name + '/manifests/' + tag);
oReq.setRequestHeader('Accept', 'application/vnd.docker.distribution.manifest.v2+json');
oReq.send();
};
});
</script>
</remove-image>

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -15,13 +15,13 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<tag-history-button>
<button ref="button" title="This will show the history of given tag">
<material-button ref="button" title="This will show the history of given tag" waves-center="true" rounded="true" waves-color="#ddd">
<i class="material-icons">history</i>
</button>
</material-button>
<script>
this.on('mount', function() {
const self = this;
this.refs.button.onclick = function() {
this.refs.button.root.onclick = function() {
registryUI.taghistory._image = self.opts.image;
registryUI.taghistory.go(self.opts.image.name, self.opts.image.tag);
};

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -17,9 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<tag-history>
<material-card ref="tag-history-tag" class="tag-history">
<div class="material-card-title-action">
<a href="#!taglist/{registryUI.taghistory.image}">
<material-button waves-center="true" rounded="true" waves-color="#ddd">
<i class="material-icons">arrow_back</i>
</a>
</material-button>
<h2>
History of { registryUI.taghistory.image }:{ registryUI.taghistory.tag } <i class="material-icons">history</i>
</h2>
@@ -118,13 +118,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
self.elements = []
const blobs = registryUI.taghistory._image && registryUI.taghistory._image.blobs;
if (blobs) {
return processBlobs(blobs)
window.scrollTo(0, 0);
return processBlobs(blobs);
}
const image = new registryUI.DockerImage(registryUI.taghistory.image, registryUI.taghistory.tag);
image.fillInfo()
image.on('blobs', processBlobs);
};
this.on('mount', function() {
self.refs['tag-history-tag'].tags['material-button'].root.onclick = function() {
registryUI.taglist.go(registryUI.taghistory.image);
};
});
registryUI.taghistory.display();
self.update();
</script>

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2016-2018 Jones Magloire @Joxit
Copyright (C) 2016-2019 Jones Magloire @Joxit
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
@@ -18,10 +18,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<!-- Begin of tag -->
<material-card ref="taglist-tag" class="taglist">
<div class="material-card-title-action">
<a href="#!" onclick="registryUI.home();">
<material-button waves-center="true" rounded="true" waves-color="#ddd" onclick="registryUI.home();">
<i class="material-icons">arrow_back</i>
</a>
<h2>Tags of { registryUI.name() + '/' + registryUI.taglist.name }</h2>
</material-button>
<h2>
Tags of { registryUI.name() + '/' + registryUI.taglist.name }
<div class="item-count">{ registryUI.taglist.tags.length } tags</div>
</h2>
</div>
<div hide="{ registryUI.taglist.loadend }" class="spinner-wrapper">
<material-spinner></material-spinner>
@@ -113,9 +116,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
}
registryUI.taglist.instance.update();
};
registryUI.taglist.refresh = function() {
route(registryUI.taglist.name);
};
</script>
<!-- End of tag -->
</taglist>

View File

@@ -12,6 +12,18 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
FROM node:10-alpine AS builder
WORKDIR /usr/app
COPY package.json .
RUN yarn install
COPY . .
RUN yarn build
FROM nginx:alpine
LABEL maintainer="Jones MAGLOIRE @Joxit"
@@ -19,8 +31,8 @@ LABEL maintainer="Jones MAGLOIRE @Joxit"
WORKDIR /usr/share/nginx/html/
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
COPY dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js
COPY --from=builder /usr/app/dist/ /usr/share/nginx/html/
COPY --from=builder /usr/app/dist/scripts/docker-registry-ui-static.js /usr/share/nginx/html/scripts/docker-registry-ui.js
COPY bin/entrypoint /bin
ENTRYPOINT entrypoint