Skip to content

Commit b9a157c

Browse files
authored
feat(dockerfile): show dockerfile in history page (#286)
2 parents 347e201 + c3fa2c9 commit b9a157c

File tree

2 files changed

+134
-16
lines changed

2 files changed

+134
-16
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<!--
2+
Copyright (C) 2016-2023 Jones Magloire @Joxit
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Affero General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Affero General Public License for more details.
13+
14+
You should have received a copy of the GNU Affero General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
-->
17+
<dockerfile>
18+
<material-popup opened="{ props.opened }" onClick="{ props.onClose }">
19+
<div class="material-popup-title">Dockerfile</div>
20+
<div class="material-popup-content">
21+
<template each="{ (_, idx) in props.elements }">
22+
<template
23+
each="{ element in props.elements[props.elements.length - 1 - idx].filter(e => e.key === 'created_by') }"
24+
>
25+
<div class="instruction">
26+
<span class="keyword">{ element.value }</span>
27+
<span>{ ' ' + element.content }</span>
28+
</div>
29+
</template>
30+
</template>
31+
</div>
32+
<div class="material-popup-action">
33+
<material-button
34+
class="dialog-button"
35+
waves-color="rgba(158,158,158,.4)"
36+
onClick="{ props.onClose }"
37+
color="inherit"
38+
text-color="var(--primary-text)"
39+
>
40+
Close
41+
</material-button>
42+
</div>
43+
</material-popup>
44+
<style>
45+
:host material-popup .popup material-button {
46+
margin-right: 1em;
47+
}
48+
:host material-popup .popup > .content {
49+
max-width: 75em;
50+
width: 80%;
51+
}
52+
:host .material-popup-content {
53+
background-color: var(--hover-background);
54+
}
55+
@media screen and (max-width: 800px) {
56+
:host material-popup .popup > .content {
57+
width: 100%;
58+
}
59+
}
60+
:host .instruction {
61+
font-family: 'Roboto Mono', monospace !important;
62+
margin: 0.75em 0;
63+
}
64+
:host .instruction .keyword {
65+
color: var(--accent-text);
66+
}
67+
</style>
68+
</dockerfile>

src/components/tag-history/tag-history.riot

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2929
<i class="material-icons">arrow_back</i>
3030
</material-button>
3131
<h2>History of { props.image }:{ props.tag } <i class="material-icons">history</i></h2>
32+
<material-button
33+
text-color="var(--accent-text)"
34+
color="inherit"
35+
waves-color="var(--hover-background)"
36+
waves-center="true"
37+
rounded="true"
38+
outlined
39+
onClick="{ showDockerfile }"
40+
>
41+
Dockerfile
42+
</material-button>
3243
</div>
3344
</material-card>
3445
<div if="{ !state.loadend }" class="spinner-wrapper">
3546
<material-spinner></material-spinner>
3647
</div>
48+
<dockerfile
49+
opened="{ state.showDockerfile }"
50+
on-close="{ onDockerfileClose }"
51+
elements="{ state.elements }"
52+
></dockerfile>
3753

3854
<material-tabs
3955
if="{ state.archs && state.loadend }"
@@ -57,11 +73,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
5773
<script>
5874
import { DockerImage } from '../../scripts/docker-image';
5975
import { bytesToSize } from '../../scripts/utils';
76+
import Dockerfile from '../dialogs/dockerfile.riot';
6077
import router from '../../scripts/router';
6178
import TagHistoryElement from './tag-history-element.riot';
6279
export default {
6380
components: {
6481
TagHistoryElement,
82+
Dockerfile,
6583
},
6684
onBeforeMount(props, state) {
6785
state.elements = [];
@@ -105,10 +123,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
105123
for (var attribute in elt) {
106124
if (elt.hasOwnProperty(attribute) && attribute != 'empty_layer') {
107125
const value = elt[attribute];
108-
const guiElement = {
109-
'key': attribute,
110-
'value': modifySpecificAttributeTypes(attribute, value),
111-
};
126+
const guiElement = modifySpecificAttributeTypes(attribute, value);
112127
guiElements.push(guiElement);
113128
}
114129
}
@@ -143,6 +158,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
143158
toTaglist() {
144159
return router.taglist(this.props.image);
145160
},
161+
showDockerfile() {
162+
console.log(this);
163+
this.update({ showDockerfile: true });
164+
},
165+
onDockerfileClose() {
166+
this.update({ showDockerfile: false });
167+
},
146168
};
147169
const eltIdx = function (e) {
148170
switch (e) {
@@ -171,27 +193,47 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
171193
return eltIdx(e1.key) - eltIdx(e2.key);
172194
};
173195
174-
const modifySpecificAttributeTypes = function (attribute, value) {
175-
switch (attribute) {
196+
const parseCreatedBy = (value) => {
197+
if (value.startsWith('COPY')) {
198+
return {
199+
value: 'COPY',
200+
content: value.replace(/^COPY /, ''),
201+
};
202+
}
203+
let cmd = value.match(/\/bin\/sh *-c *#\(nop\) *([A-Z]+) (.*)/);
204+
return {
205+
value: (cmd && cmd[1]) || 'RUN',
206+
content: (cmd && cmd[2]) || value.replace(/^\/bin\/sh *-c *(#\(nop\))?/, ''),
207+
};
208+
};
209+
210+
const modifySpecificAttributeTypes = function (key, value) {
211+
switch (key) {
176212
case 'created':
177-
return new Date(value).toLocaleString();
213+
return { key, value: new Date(value).toLocaleString() };
178214
case 'created_by':
179-
const cmd = value.match(/\/bin\/sh *-c *#\(nop\) *([A-Z]+)/);
180-
return (cmd && cmd[1]) || 'RUN';
215+
const cmd = value.match(/\/bin\/sh *-c *#\(nop\) *([A-Z]+) (.*)/);
216+
return {
217+
key,
218+
...parseCreatedBy(value),
219+
};
181220
case 'size':
182-
return bytesToSize(value);
221+
return { key, value: bytesToSize(value) };
183222
case 'Entrypoint':
184223
case 'Cmd':
185-
return (value || []).join(' ');
224+
return { key, value: (value || []).join(' ') };
186225
case 'Labels':
187-
return Object.keys(value || {}).map(function (elt) {
188-
return value[elt] ? elt + '=' + value[elt] : '';
189-
});
226+
return {
227+
key,
228+
value: Object.keys(value || {}).map(function (elt) {
229+
return value[elt] ? elt + '=' + value[elt] : '';
230+
}),
231+
};
190232
case 'Volumes':
191233
case 'ExposedPorts':
192-
return Object.keys(value);
234+
return { key, value: Object.keys(value) };
193235
}
194-
return value || '';
236+
return { key, value: value || '' };
195237
};
196238
197239
const getConfig = function (blobs, { historyCustomLabels }) {
@@ -238,4 +280,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
238280
return res;
239281
};
240282
</script>
283+
<style>
284+
h2 {
285+
flex-grow: 1;
286+
display: flex;
287+
flex-direction: row;
288+
align-items: center;
289+
}
290+
</style>
241291
</tag-history>

0 commit comments

Comments
 (0)