mirror of
https://github.com/Joxit/docker-registry-ui.git
synced 2025-04-26 15:09:53 +03:00
feat(dockerfile): show dockerfile in history page (#286)
This commit is contained in:
commit
b9a157c943
2 changed files with 134 additions and 16 deletions
68
src/components/dialogs/dockerfile.riot
Normal file
68
src/components/dialogs/dockerfile.riot
Normal file
|
@ -0,0 +1,68 @@
|
|||
<!--
|
||||
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/>.
|
||||
-->
|
||||
<dockerfile>
|
||||
<material-popup opened="{ props.opened }" onClick="{ props.onClose }">
|
||||
<div class="material-popup-title">Dockerfile</div>
|
||||
<div class="material-popup-content">
|
||||
<template each="{ (_, idx) in props.elements }">
|
||||
<template
|
||||
each="{ element in props.elements[props.elements.length - 1 - idx].filter(e => e.key === 'created_by') }"
|
||||
>
|
||||
<div class="instruction">
|
||||
<span class="keyword">{ element.value }</span>
|
||||
<span>{ ' ' + element.content }</span>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
<div class="material-popup-action">
|
||||
<material-button
|
||||
class="dialog-button"
|
||||
waves-color="rgba(158,158,158,.4)"
|
||||
onClick="{ props.onClose }"
|
||||
color="inherit"
|
||||
text-color="var(--primary-text)"
|
||||
>
|
||||
Close
|
||||
</material-button>
|
||||
</div>
|
||||
</material-popup>
|
||||
<style>
|
||||
:host material-popup .popup material-button {
|
||||
margin-right: 1em;
|
||||
}
|
||||
:host material-popup .popup > .content {
|
||||
max-width: 75em;
|
||||
width: 80%;
|
||||
}
|
||||
:host .material-popup-content {
|
||||
background-color: var(--hover-background);
|
||||
}
|
||||
@media screen and (max-width: 800px) {
|
||||
:host material-popup .popup > .content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
:host .instruction {
|
||||
font-family: 'Roboto Mono', monospace !important;
|
||||
margin: 0.75em 0;
|
||||
}
|
||||
:host .instruction .keyword {
|
||||
color: var(--accent-text);
|
||||
}
|
||||
</style>
|
||||
</dockerfile>
|
|
@ -29,11 +29,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
<i class="material-icons">arrow_back</i>
|
||||
</material-button>
|
||||
<h2>History of { props.image }:{ props.tag } <i class="material-icons">history</i></h2>
|
||||
<material-button
|
||||
text-color="var(--accent-text)"
|
||||
color="inherit"
|
||||
waves-color="var(--hover-background)"
|
||||
waves-center="true"
|
||||
rounded="true"
|
||||
outlined
|
||||
onClick="{ showDockerfile }"
|
||||
>
|
||||
Dockerfile
|
||||
</material-button>
|
||||
</div>
|
||||
</material-card>
|
||||
<div if="{ !state.loadend }" class="spinner-wrapper">
|
||||
<material-spinner></material-spinner>
|
||||
</div>
|
||||
<dockerfile
|
||||
opened="{ state.showDockerfile }"
|
||||
on-close="{ onDockerfileClose }"
|
||||
elements="{ state.elements }"
|
||||
></dockerfile>
|
||||
|
||||
<material-tabs
|
||||
if="{ state.archs && state.loadend }"
|
||||
|
@ -57,11 +73,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
<script>
|
||||
import { DockerImage } from '../../scripts/docker-image';
|
||||
import { bytesToSize } from '../../scripts/utils';
|
||||
import Dockerfile from '../dialogs/dockerfile.riot';
|
||||
import router from '../../scripts/router';
|
||||
import TagHistoryElement from './tag-history-element.riot';
|
||||
export default {
|
||||
components: {
|
||||
TagHistoryElement,
|
||||
Dockerfile,
|
||||
},
|
||||
onBeforeMount(props, state) {
|
||||
state.elements = [];
|
||||
|
@ -105,10 +123,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
for (var attribute in elt) {
|
||||
if (elt.hasOwnProperty(attribute) && attribute != 'empty_layer') {
|
||||
const value = elt[attribute];
|
||||
const guiElement = {
|
||||
'key': attribute,
|
||||
'value': modifySpecificAttributeTypes(attribute, value),
|
||||
};
|
||||
const guiElement = modifySpecificAttributeTypes(attribute, value);
|
||||
guiElements.push(guiElement);
|
||||
}
|
||||
}
|
||||
|
@ -143,6 +158,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
toTaglist() {
|
||||
return router.taglist(this.props.image);
|
||||
},
|
||||
showDockerfile() {
|
||||
console.log(this);
|
||||
this.update({ showDockerfile: true });
|
||||
},
|
||||
onDockerfileClose() {
|
||||
this.update({ showDockerfile: false });
|
||||
},
|
||||
};
|
||||
const eltIdx = function (e) {
|
||||
switch (e) {
|
||||
|
@ -171,27 +193,47 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
return eltIdx(e1.key) - eltIdx(e2.key);
|
||||
};
|
||||
|
||||
const modifySpecificAttributeTypes = function (attribute, value) {
|
||||
switch (attribute) {
|
||||
const parseCreatedBy = (value) => {
|
||||
if (value.startsWith('COPY')) {
|
||||
return {
|
||||
value: 'COPY',
|
||||
content: value.replace(/^COPY /, ''),
|
||||
};
|
||||
}
|
||||
let cmd = value.match(/\/bin\/sh *-c *#\(nop\) *([A-Z]+) (.*)/);
|
||||
return {
|
||||
value: (cmd && cmd[1]) || 'RUN',
|
||||
content: (cmd && cmd[2]) || value.replace(/^\/bin\/sh *-c *(#\(nop\))?/, ''),
|
||||
};
|
||||
};
|
||||
|
||||
const modifySpecificAttributeTypes = function (key, value) {
|
||||
switch (key) {
|
||||
case 'created':
|
||||
return new Date(value).toLocaleString();
|
||||
return { key, value: new Date(value).toLocaleString() };
|
||||
case 'created_by':
|
||||
const cmd = value.match(/\/bin\/sh *-c *#\(nop\) *([A-Z]+)/);
|
||||
return (cmd && cmd[1]) || 'RUN';
|
||||
const cmd = value.match(/\/bin\/sh *-c *#\(nop\) *([A-Z]+) (.*)/);
|
||||
return {
|
||||
key,
|
||||
...parseCreatedBy(value),
|
||||
};
|
||||
case 'size':
|
||||
return bytesToSize(value);
|
||||
return { key, value: bytesToSize(value) };
|
||||
case 'Entrypoint':
|
||||
case 'Cmd':
|
||||
return (value || []).join(' ');
|
||||
return { key, value: (value || []).join(' ') };
|
||||
case 'Labels':
|
||||
return Object.keys(value || {}).map(function (elt) {
|
||||
return value[elt] ? elt + '=' + value[elt] : '';
|
||||
});
|
||||
return {
|
||||
key,
|
||||
value: Object.keys(value || {}).map(function (elt) {
|
||||
return value[elt] ? elt + '=' + value[elt] : '';
|
||||
}),
|
||||
};
|
||||
case 'Volumes':
|
||||
case 'ExposedPorts':
|
||||
return Object.keys(value);
|
||||
return { key, value: Object.keys(value) };
|
||||
}
|
||||
return value || '';
|
||||
return { key, value: value || '' };
|
||||
};
|
||||
|
||||
const getConfig = function (blobs, { historyCustomLabels }) {
|
||||
|
@ -238,4 +280,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
return res;
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
h2 {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</tag-history>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue