203 lines
6.7 KiB
Plaintext
203 lines
6.7 KiB
Plaintext
<!--
|
|
Copyright (C) 2016-2023 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/>.
|
|
-->
|
|
<tag-list>
|
|
<material-card class="header">
|
|
<div class="material-card-title-action">
|
|
<material-button
|
|
text-color="var(--neutral-text)"
|
|
color="inherit"
|
|
waves-color="var(--hover-background)"
|
|
waves-center="true"
|
|
href="{ router.home() }"
|
|
icon
|
|
>
|
|
<i class="material-icons">arrow_back</i>
|
|
</material-button>
|
|
<h2>
|
|
Tags of { props.image }
|
|
<div class="source-hint">Sourced from { state.registryName + '/' + props.image }</div>
|
|
<div class="item-count">{ state.tags.length } tags</div>
|
|
</h2>
|
|
</div>
|
|
</material-card>
|
|
|
|
<div if="{ !state.loadend }" class="spinner-wrapper">
|
|
<material-spinner></material-spinner>
|
|
</div>
|
|
|
|
<pagination
|
|
pages="{ getPageLabels(state.page, getNumPages(state.tags, props.tagsPerPage)) }"
|
|
onPageUpdate="{onPageUpdate}"
|
|
></pagination>
|
|
|
|
<tag-table
|
|
if="{ state.loadend }"
|
|
tags="{state.tags}"
|
|
asc="{state.asc}"
|
|
page="{ state.page }"
|
|
show-content-digest="{props.showContentDigest}"
|
|
show-tag-history="{props.showTagHistory}"
|
|
is-image-remove-activated="{props.isImageRemoveActivated}"
|
|
onReverseOrder="{ onReverseOrder }"
|
|
registry-url="{ props.registryUrl }"
|
|
pull-url="{ props.pullUrl }"
|
|
on-notify="{ props.onNotify }"
|
|
filter-results="{ props.filterResults }"
|
|
on-authentication="{ props.onAuthentication }"
|
|
tags-per-page="{ props.tagsPerPage }"
|
|
is-registry-secured="{ props.isRegistrySecured }"
|
|
on-image-deleted="{ () => state.reload() }"
|
|
>
|
|
</tag-table>
|
|
|
|
<pagination
|
|
pages="{ getPageLabels(state.page, getNumPages(state.tags, props.tagsPerPage)) }"
|
|
onPageUpdate="{onPageUpdate}"
|
|
></pagination>
|
|
|
|
<script>
|
|
import { Http } from '../../scripts/http';
|
|
import { DockerImage } from '../../scripts/docker-image';
|
|
import { getNumPages, getPageLabels } from '../../scripts/utils';
|
|
import Pagination from './pagination.riot';
|
|
import TagTable from './tag-table.riot';
|
|
import router from '../../scripts/router';
|
|
import { getTagComparator, taglistOrderParser } from '../../scripts/taglist-order';
|
|
|
|
export default {
|
|
components: {
|
|
Pagination,
|
|
TagTable,
|
|
},
|
|
onBeforeMount(props) {
|
|
this.state = {
|
|
registryName: props.registryName,
|
|
tags: [],
|
|
loadend: false,
|
|
asc: true,
|
|
page: router.getPageQueryParam() || 1,
|
|
};
|
|
try {
|
|
this.state.taglistOrder = taglistOrderParser(props.taglistOrder);
|
|
} catch (e) {
|
|
props.onNotify(e);
|
|
}
|
|
},
|
|
onMounted(props, state) {
|
|
this.display(props, state);
|
|
window.addEventListener('resize', this.onResize);
|
|
// this may be run before the final document size is available, so schedule
|
|
// a correction once everything is set up.
|
|
window.requestAnimationFrame(this.onResize);
|
|
this.tagComparator = getTagComparator(props.taglistOrder);
|
|
},
|
|
display(props, state) {
|
|
state.reload = () => setTimeout(() => this.display(props, state), 1000);
|
|
state.tags = [];
|
|
const self = this;
|
|
const oReq = new Http({
|
|
onAuthentication: props.onAuthentication,
|
|
withCredentials: props.isRegistrySecured,
|
|
});
|
|
oReq.addEventListener('load', function () {
|
|
if (this.status === 200) {
|
|
const tags = (JSON.parse(this.responseText).tags || [])
|
|
.map(
|
|
(tag) =>
|
|
new DockerImage(props.image, tag, {
|
|
list: true,
|
|
registryUrl: props.registryUrl,
|
|
onNotify: props.onNotify,
|
|
onAuthentication: props.onAuthentication,
|
|
useControlCacheHeader: props.useControlCacheHeader,
|
|
isRegistrySecured: props.isRegistrySecured,
|
|
})
|
|
)
|
|
.sort(self.tagComparator);
|
|
window.requestAnimationFrame(self.onResize);
|
|
self.update({
|
|
page: Math.min(state.page, getNumPages(tags, props.tagsPerPage)),
|
|
tags,
|
|
});
|
|
} else if (this.status === 404) {
|
|
self.props.onNotify('Server not found', true);
|
|
} else {
|
|
self.props.onNotify(this.responseText, true);
|
|
}
|
|
});
|
|
oReq.addEventListener('error', function () {
|
|
self.props.onNotify(this.getErrorMessage(), true);
|
|
state.tags = [];
|
|
});
|
|
oReq.addEventListener('loadend', function () {
|
|
self.update({
|
|
loadend: true,
|
|
});
|
|
});
|
|
oReq.open('GET', props.registryUrl + '/v2/' + props.image + '/tags/list');
|
|
oReq.send();
|
|
state.asc = true;
|
|
},
|
|
|
|
onPageUpdate(idx) {
|
|
const labels = getPageLabels(this.state.page, getNumPages(this.state.tags, this.props.tagsPerPage));
|
|
const page = labels[idx].page;
|
|
this.update({
|
|
page: page,
|
|
});
|
|
router.updatePageQueryParam(page);
|
|
},
|
|
|
|
onResize() {
|
|
// window.innerWidth is a blocking access, cache its result.
|
|
const innerWidth = window.innerWidth;
|
|
let chars = 0;
|
|
const max = this.state.tags.reduce(function (acc, e) {
|
|
return e.tag.length > acc ? e.tag.length : acc;
|
|
}, 0);
|
|
if (innerWidth >= 1440) {
|
|
chars = 71;
|
|
} else if (innerWidth < 1024) {
|
|
chars = 0;
|
|
} else {
|
|
// SHA256:12345678 + scaled between 1024 and 1440px
|
|
chars = 15 + 56 * ((innerWidth - 1024) / 416);
|
|
}
|
|
if (max > 20) chars -= max - 20;
|
|
chars = Math.floor(chars);
|
|
this.state.tags.map(function (image) {
|
|
image.trigger('content-digest-chars', chars);
|
|
});
|
|
},
|
|
|
|
onReverseOrder() {
|
|
if (this.state.asc) {
|
|
this.state.tags.reverse();
|
|
this.state.asc = false;
|
|
} else {
|
|
this.state.tags.sort(this.tagComparator);
|
|
this.state.asc = true;
|
|
}
|
|
this.update();
|
|
},
|
|
getPageLabels,
|
|
getNumPages,
|
|
router,
|
|
};
|
|
</script>
|
|
</tag-list>
|