| |
@@ -28,6 +28,30 @@
|
| |
"vmware": "VMware",
|
| |
"openstack": "OpenStack"
|
| |
}
|
| |
+ var data = {
|
| |
+ // currently selected stream
|
| |
+ stream: 'testing',
|
| |
+ // currently selected architecture
|
| |
+ architecture: 'x86_64',
|
| |
+ // current url to dir for stream
|
| |
+ streamUrl: "",
|
| |
+ // fetched {stream, metadata, architectures, updates} object from stream.json
|
| |
+ streamData: null,
|
| |
+ loading: false,
|
| |
+ // loaded stream data to render
|
| |
+ streamDisplay: {
|
| |
+ cloudLaunchable: {},
|
| |
+ bareMetal: {},
|
| |
+ virtualized: {},
|
| |
+ cloud: {}
|
| |
+ },
|
| |
+ // innerText of tab button
|
| |
+ tabInnerText: {
|
| |
+ cloud_launchable: "Cloud Launchable",
|
| |
+ metal_virt: "Bare Metal & Virtualized",
|
| |
+ cloud_operator: "For Cloud Operators"
|
| |
+ }
|
| |
+ }
|
| |
function getMember(obj, member) {
|
| |
return (member in obj) ? obj[member] : null;
|
| |
}
|
| |
@@ -65,39 +89,105 @@
|
| |
downloads[download] = entry;
|
| |
}
|
| |
}
|
| |
+ var jumbotron_buttons = new Vue ({
|
| |
+ el: '#jumbotron-buttons',
|
| |
+ data: data,
|
| |
+ methods: {
|
| |
+ getObjectUrl: function(path) {
|
| |
+ return getArtifactUrl(data.streamUrl, path);
|
| |
+ },
|
| |
+ // Adapted from https://stackoverflow.com/a/6109105
|
| |
+ timeSince: function(rfc3339_timestamp) {
|
| |
+ var current = Date.now();
|
| |
+ var timestamp = Date.parse(rfc3339_timestamp);
|
| |
+ var elapsed = current - timestamp;
|
| |
+ var msPerMinute = 60 * 1000;
|
| |
+ var msPerHour = msPerMinute * 60;
|
| |
+ var msPerDay = msPerHour * 24;
|
| |
+ var msPerMonth = msPerDay * 30;
|
| |
+ var msPerYear = msPerDay * 365;
|
| |
+ function stringize(n, s) {
|
| |
+ return n + ` ${s}` + (n == 1 ? "" : "s") + ' ago';
|
| |
+ };
|
| |
+ if (elapsed < msPerMinute) {
|
| |
+ return stringize(Math.floor(elapsed/1000), "second");
|
| |
+ } else if (elapsed < msPerHour) {
|
| |
+ return stringize(Math.floor(elapsed/msPerMinute), "minute");
|
| |
+ } else if (elapsed < msPerDay) {
|
| |
+ return stringize(Math.floor(elapsed/msPerHour), "hour");
|
| |
+ } else if (elapsed < msPerMonth) {
|
| |
+ return stringize(Math.floor(elapsed/msPerDay), "day");
|
| |
+ } else if (elapsed < msPerYear) {
|
| |
+ return stringize(Math.floor(elapsed/msPerMonth), "month");
|
| |
+ } else {
|
| |
+ return stringize(Math.floor(elapsed/msPerYear), "year");
|
| |
+ }
|
| |
+ },
|
| |
+ toggleHidden: function(e) {
|
| |
+ const id_list = ['cloud-launchable', 'metal-virt', 'cloud-operator'];
|
| |
+ switch(e.target.innerText) {
|
| |
+ case data.tabInnerText.cloud_launchable:
|
| |
+ show_id = 'cloud-launchable';
|
| |
+ id_list.map(id => document.getElementById(id).hidden = (id !== show_id));
|
| |
+ break;
|
| |
+ case data.tabInnerText.metal_virt:
|
| |
+ show_id = 'metal-virt';
|
| |
+ id_list.map(id => document.getElementById(id).hidden = (id !== show_id));
|
| |
+ break;
|
| |
+ case data.tabInnerText.cloud_operator:
|
| |
+ show_id = 'cloud-operator';
|
| |
+ id_list.map(id => document.getElementById(id).hidden = (id !== show_id));
|
| |
+ break;
|
| |
+ }
|
| |
+ },
|
| |
+ getNavbar: function(h) {
|
| |
+ cloud_icon = h('i', { class: "fas fa-cloud mr-2" })
|
| |
+ nav_cloud_launchable_btn = h('button', { class: "nav-link active col-12 h-100 overflow-hidden", attrs: { "data-toggle": "tab" }, on: { click: this.toggleHidden } }, [ cloud_icon, data.tabInnerText.cloud_launchable ]);
|
| |
+ nav_cloud_launchable = h('li', { class: "nav-item col-4" }, [ nav_cloud_launchable_btn ]);
|
| |
|
| |
- var coreos_download_app = new Vue({
|
| |
- el: '#coreos-download-app',
|
| |
- data: {
|
| |
- // currently selected stream
|
| |
- stream: 'testing',
|
| |
- // currently selected architecture
|
| |
- architecture: 'x86_64',
|
| |
- // current url to dir for stream
|
| |
- streamUrl: "",
|
| |
- // fetched {stream, metadata, architectures, updates} object from stream.json
|
| |
- streamData: null,
|
| |
- loading: false,
|
| |
- // loaded stream data to render
|
| |
- streamDisplay: {
|
| |
- cloudLaunchable: {},
|
| |
- bareMetal: {},
|
| |
- virtualized: {},
|
| |
- cloud: {}
|
| |
+ server_icon = h('i', { class: "fas fa-server mr-2" })
|
| |
+ nav_metal_virt_btn = h('button', { class: "nav-link col-12 h-100 overflow-hidden", attrs: { "data-toggle": "tab" }, on: { click: this.toggleHidden } }, [ server_icon, data.tabInnerText.metal_virt ]);
|
| |
+ nav_metal_virt = h('li', { class: "nav-item col-4" }, [ nav_metal_virt_btn ]);
|
| |
+
|
| |
+ cloud_upload_icon = h('i', { class: "fas fa-cloud-upload-alt mr-2" })
|
| |
+ nav_cloud_operator_btn = h('button', { class: "nav-link col-12 h-100 overflow-hidden", attrs: { "data-toggle": "tab" }, on: { click: this.toggleHidden } }, [ cloud_upload_icon, data.tabInnerText.cloud_operator ]);
|
| |
+ nav_cloud_operator = h('li', { class: "nav-item col-4" }, [ nav_cloud_operator_btn ]);
|
| |
+
|
| |
+ navbar = h('ul', { class: "nav nav-tabs" }, [ nav_cloud_launchable, nav_metal_virt, nav_cloud_operator ]);
|
| |
+ return navbar;
|
| |
},
|
| |
- // innerText of tab button
|
| |
- tabInnerText: {
|
| |
- cloud_launchable: "Cloud Launchable",
|
| |
- metal_virt: "Bare Metal & Virtualized",
|
| |
- cloud_operator: "For Cloud Operators"
|
| |
+ // Add dropdown options of streams
|
| |
+ getStreamName: function(h) {
|
| |
+ if (data.streamData === null) return;
|
| |
+ option_default = h('option', { attrs: { value: "testing", selected: "selected" }}, "testing" );
|
| |
+ selectOptions = h('select', { class: "mx-1" }, [ option_default ]);
|
| |
+ streamName = h('p', {}, [
|
| |
+ "Stream: ",
|
| |
+ selectOptions,
|
| |
+ " (",
|
| |
+ h('span', {}, [
|
| |
+ h('a', { attrs: { href: this.getObjectUrl(data.streamData.stream + '.json') } }, "JSON")
|
| |
+ ]),
|
| |
+ ")",
|
| |
+ "—",
|
| |
+ h('span', {}, this.timeSince(data.streamData.metadata['last-modified']))
|
| |
+ ]);
|
| |
+ return streamName;
|
| |
}
|
| |
},
|
| |
+ render: function(h) {
|
| |
+ navbar = this.getNavbar(h);
|
| |
+ streamName = this.getStreamName(h);
|
| |
+ container = h('div', { class: "container" }, [ streamName, navbar ]);
|
| |
+ return container
|
| |
+ }
|
| |
+ })
|
| |
+ var coreos_download_app = new Vue({
|
| |
+ el: '#coreos-download-app',
|
| |
created: function() { this.refreshStream() },
|
| |
- watch: { stream: 'refreshStream' },
|
| |
+ data: data,
|
| |
+ watch: { 'data.stream': 'refreshStream' },
|
| |
methods: {
|
| |
- getObjectUrl: function(path) {
|
| |
- return getArtifactUrl(this.streamUrl, path);
|
| |
- },
|
| |
isAws: function(platform) {
|
| |
return platform == "aws";
|
| |
},
|
| |
@@ -114,20 +204,20 @@
|
| |
// not deep-copy information from `streamData` or elsewhere into
|
| |
// `streamDisplay`.
|
| |
loadStreamDisplay: function() {
|
| |
- this.streamDisplay = {
|
| |
+ data.streamDisplay = {
|
| |
cloudLaunchable: {},
|
| |
bareMetal: {},
|
| |
virtualized: {},
|
| |
cloud: {}
|
| |
};
|
| |
- if (this.streamData == null) {
|
| |
+ if (data.streamData == null) {
|
| |
return;
|
| |
}
|
| |
- const architectures = getMember(this.streamData, "architectures");
|
| |
+ const architectures = getMember(data.streamData, "architectures");
|
| |
if (architectures == null) {
|
| |
return;
|
| |
}
|
| |
- const architectureData = getMember(architectures, this.architecture);
|
| |
+ const architectureData = getMember(architectures, data.architecture);
|
| |
if (architectureData == null) {
|
| |
return;
|
| |
}
|
| |
@@ -147,11 +237,11 @@
|
| |
displayEntries.push({platform: prettyPlatform, region: region, release: release, image: image});
|
| |
}
|
| |
}
|
| |
- Vue.set(this.streamDisplay.cloudLaunchable, platform, {list: displayEntries});
|
| |
+ Vue.set(data.streamDisplay.cloudLaunchable, platform, {list: displayEntries});
|
| |
}
|
| |
else {
|
| |
const image = getMember(images[platform], "image");
|
| |
- Vue.set(this.streamDisplay.cloudLaunchable, platform, {platform: prettyPlatform, image: image});
|
| |
+ Vue.set(data.streamDisplay.cloudLaunchable, platform, {platform: prettyPlatform, image: image});
|
| |
}
|
| |
}
|
| |
const artifacts = getMember(architectureData, "artifacts");
|
| |
@@ -176,32 +266,32 @@
|
| |
Vue.set(display, platform + "-" + format, displayEntry);
|
| |
}
|
| |
if (this.isCloudImage(platform)) {
|
| |
- addDisplayEntry(this.streamDisplay.cloud, platform, format, formats, release, prettyPlatform, extension);
|
| |
+ addDisplayEntry(data.streamDisplay.cloud, platform, format, formats, release, prettyPlatform, extension);
|
| |
}
|
| |
if (this.isVirtualizedImage(platform)) {
|
| |
- addDisplayEntry(this.streamDisplay.virtualized, platform, format, formats, release, prettyPlatform, extension);
|
| |
+ addDisplayEntry(data.streamDisplay.virtualized, platform, format, formats, release, prettyPlatform, extension);
|
| |
}
|
| |
if (this.isBareMetalImage(platform)) {
|
| |
- addDisplayEntry(this.streamDisplay.bareMetal, platform, format, formats, release, prettyPlatform, extension);
|
| |
+ addDisplayEntry(data.streamDisplay.bareMetal, platform, format, formats, release, prettyPlatform, extension);
|
| |
}
|
| |
}
|
| |
}
|
| |
}
|
| |
},
|
| |
refreshStream: function() {
|
| |
- this.loading = true
|
| |
- this.streamUrl = baseUrl
|
| |
- fetchStreamData(this.streamUrl, this.stream).then(streamData => {
|
| |
- this.loading = false;
|
| |
- this.streamData = streamData;
|
| |
+ data.loading = true
|
| |
+ data.streamUrl = baseUrl
|
| |
+ fetchStreamData(data.streamUrl, data.stream).then(streamData => {
|
| |
+ data.loading = false;
|
| |
+ data.streamData = streamData;
|
| |
this.loadStreamDisplay();
|
| |
});
|
| |
},
|
| |
toggleShowSignatureAndSha: function(imageType, platformFormat, contentType) {
|
| |
- if (!(platformFormat in this.streamDisplay[imageType])) {
|
| |
+ if (!(platformFormat in data.streamDisplay[imageType])) {
|
| |
return;
|
| |
}
|
| |
- const artifact = this.streamDisplay[imageType][platformFormat];
|
| |
+ const artifact = data.streamDisplay[imageType][platformFormat];
|
| |
if (!(contentType in artifact.downloads)) {
|
| |
return;
|
| |
}
|
| |
@@ -209,90 +299,21 @@
|
| |
artifact.downloads[contentType].showSignatureAndSha = !prev;
|
| |
},
|
| |
showSignatureAndSha: function(imageType, platformFormat, contentType) {
|
| |
- if (!(platformFormat in this.streamDisplay[imageType])) {
|
| |
+ if (!(platformFormat in data.streamDisplay[imageType])) {
|
| |
return false;
|
| |
}
|
| |
- const artifact = this.streamDisplay[imageType][platformFormat];
|
| |
+ const artifact = data.streamDisplay[imageType][platformFormat];
|
| |
if (!(contentType in artifact.downloads)) {
|
| |
return false;
|
| |
}
|
| |
return artifact.downloads[contentType].showSignatureAndSha;
|
| |
- },
|
| |
- // Adapted from https://stackoverflow.com/a/6109105
|
| |
- timeSince: function(rfc3339_timestamp) {
|
| |
- var current = Date.now();
|
| |
- var timestamp = Date.parse(rfc3339_timestamp);
|
| |
- var elapsed = current - timestamp;
|
| |
- var msPerMinute = 60 * 1000;
|
| |
- var msPerHour = msPerMinute * 60;
|
| |
- var msPerDay = msPerHour * 24;
|
| |
- var msPerMonth = msPerDay * 30;
|
| |
- var msPerYear = msPerDay * 365;
|
| |
- function stringize(n, s) {
|
| |
- return n + ` ${s}` + (n == 1 ? "" : "s") + ' ago';
|
| |
- };
|
| |
- if (elapsed < msPerMinute) {
|
| |
- return stringize(Math.floor(elapsed/1000), "second");
|
| |
- } else if (elapsed < msPerHour) {
|
| |
- return stringize(Math.floor(elapsed/msPerMinute), "minute");
|
| |
- } else if (elapsed < msPerDay) {
|
| |
- return stringize(Math.floor(elapsed/msPerHour), "hour");
|
| |
- } else if (elapsed < msPerMonth) {
|
| |
- return stringize(Math.floor(elapsed/msPerDay), "day");
|
| |
- } else if (elapsed < msPerYear) {
|
| |
- return stringize(Math.floor(elapsed/msPerMonth), "month");
|
| |
- } else {
|
| |
- return stringize(Math.floor(elapsed/msPerYear), "year");
|
| |
- }
|
| |
- },
|
| |
- toggleHidden: function(e) {
|
| |
- const id_list = ['cloud-launchable', 'metal-virt', 'cloud-operator'];
|
| |
- switch(e.target.innerText) {
|
| |
- case this.tabInnerText.cloud_launchable:
|
| |
- show_id = 'cloud-launchable';
|
| |
- id_list.map(id => document.getElementById(id).hidden = (id !== show_id));
|
| |
- break;
|
| |
- case this.tabInnerText.metal_virt:
|
| |
- show_id = 'metal-virt';
|
| |
- id_list.map(id => document.getElementById(id).hidden = (id !== show_id));
|
| |
- break;
|
| |
- case this.tabInnerText.cloud_operator:
|
| |
- show_id = 'cloud-operator';
|
| |
- id_list.map(id => document.getElementById(id).hidden = (id !== show_id));
|
| |
- break;
|
| |
- }
|
| |
- },
|
| |
- getNavbar: function(h) {
|
| |
- nav_cloud_launchable_btn = h('button', { class: "nav-link active", attrs: { "data-toggle": "tab" }, on: { click: this.toggleHidden } }, this.tabInnerText.cloud_launchable);
|
| |
- nav_cloud_launchable = h('li', { class: "nav-item mr-3 ml-3" }, [ nav_cloud_launchable_btn ]);
|
| |
-
|
| |
- nav_metal_virt_btn = h('button', { class: "nav-link", attrs: { "data-toggle": "tab" }, on: { click: this.toggleHidden } }, this.tabInnerText.metal_virt);
|
| |
- nav_metal_virt = h('li', { class: "nav-item mr-3" }, [ nav_metal_virt_btn ]);
|
| |
-
|
| |
- nav_cloud_operator_btn = h('button', { class: "nav-link", attrs: { "data-toggle": "tab" }, on: { click: this.toggleHidden } }, this.tabInnerText.cloud_operator);
|
| |
- nav_cloud_operator = h('li', { class: "nav-item" }, [ nav_cloud_operator_btn ]);
|
| |
-
|
| |
- navbar = h('ul', { class: "nav nav-tabs" }, [ nav_cloud_launchable, nav_metal_virt, nav_cloud_operator ]);
|
| |
- return navbar
|
| |
}
|
| |
},
|
| |
render: function(h) {
|
| |
- if (this.loading) {
|
| |
+ if (data.loading) {
|
| |
return h('div', {}, "Loading...");
|
| |
}
|
| |
- else if (this.streamData) {
|
| |
- streamName = h('p', {}, [
|
| |
- "Stream: ",
|
| |
- h('span', { "class":"font-weight-bold" }, this.streamData.stream),
|
| |
- " (",
|
| |
- h('span', {}, [
|
| |
- h('a', { attrs: { href: this.getObjectUrl(this.streamData.stream + '.json') } }, "JSON")
|
| |
- ]),
|
| |
- ")",
|
| |
- "—",
|
| |
- h('span', {}, this.timeSince(this.streamData.metadata['last-modified']))
|
| |
- ]);
|
| |
-
|
| |
+ else if (data.streamData) {
|
| |
cloudLaunchableTitle = h('h3', { class:"font-weight-light" }, "Cloud Launchable");
|
| |
cloudLaunchableSection = {};
|
| |
cloudLaunchable = {};
|
| |
@@ -306,19 +327,19 @@
|
| |
cloudSection = {};
|
| |
cloud = {};
|
| |
|
| |
- if (this.streamDisplay.cloudLaunchable) {
|
| |
- cloudLaunchableSection = h('div', {}, Object.entries(this.streamDisplay.cloudLaunchable).map(function(entry) {
|
| |
+ if (data.streamDisplay.cloudLaunchable) {
|
| |
+ cloudLaunchableSection = h('div', {}, Object.entries(data.streamDisplay.cloudLaunchable).map(function(entry) {
|
| |
platform = entry[0];
|
| |
displayInfo = entry[1];
|
| |
if (coreos_download_app.isAws(platform)) {
|
| |
if (displayInfo.list) {
|
| |
return h('div', {}, displayInfo.list.map(function(amiInfo) {
|
| |
- return h('div', {}, [
|
| |
+ return h('div', { class: "p-2 m-2" }, [
|
| |
amiInfo.platform ? h('div', { class: "font-weight-bold" }, amiInfo.platform) : null,
|
| |
amiInfo.region ? h('div', {}, [ "(", amiInfo.region, ")" ]) : null,
|
| |
amiInfo.release ? h('div', { class: "ml-2" }, [
|
| |
h('span', {}, [ amiInfo.release, " " ]),
|
| |
- h('span', { class: "text-secondary" }, coreos_download_app.streamData.stream)
|
| |
+ h('span', { class: "text-secondary" }, data.streamData.stream)
|
| |
]) : null,
|
| |
amiInfo.image ? h('div', { class: "ml-2" }, [
|
| |
h('a', {
|
| |
@@ -371,7 +392,7 @@
|
| |
}, "Verify signature & SHA256")
|
| |
]),
|
| |
coreos_download_app.showSignatureAndSha(imageType, platformFormat, contentType) ? h('div', { class: "bg-gray-100 p-2 my-2" }, [ h('p', {}, [
|
| |
- displayDownloads.sha256 ? h('div', {}, [
|
| |
+ displayDownloads.sha256 ? h('div', { class: "overflow-auto" }, [
|
| |
"SHA256: ",
|
| |
displayDownloads.sha256
|
| |
]) : null,
|
| |
@@ -415,12 +436,12 @@
|
| |
return h('div', {}, Object.entries(displayArtifacts).map(function(entry) {
|
| |
platformFormat = entry[0];
|
| |
displayInfo = entry[1];
|
| |
- return h('div', { class: "my-2" }, [
|
| |
+ return h('div', { class: "p-2 m-2" }, [
|
| |
displayInfo.platform ? h('div', { class: "font-weight-bold" }, displayInfo.platform) : null,
|
| |
displayInfo.extension ? h('div', {}, [ "(", displayInfo.extension, ")" ]) : null,
|
| |
displayInfo.release ? h('div', { class: "ml-2" }, [
|
| |
h('span', {}, [ displayInfo.release, " " ]),
|
| |
- h('span', { class: "text-secondary" }, coreos_download_app.streamData.stream)
|
| |
+ h('span', { class: "text-secondary" }, data.streamData.stream)
|
| |
]) : null,
|
| |
displayInfo.downloads ? h('div', { class: "ml-2" }, [
|
| |
createDownloadsSubSection(displayInfo.downloads.disk, 'disk', false, imageType),
|
| |
@@ -430,24 +451,24 @@
|
| |
]);
|
| |
}));
|
| |
}
|
| |
- if (this.streamDisplay.bareMetal) {
|
| |
- bareMetalSection = createArtifactsSection(this.streamDisplay.bareMetal, 'bareMetal');
|
| |
+ if (data.streamDisplay.bareMetal) {
|
| |
+ bareMetalSection = createArtifactsSection(data.streamDisplay.bareMetal, 'bareMetal');
|
| |
}
|
| |
else {
|
| |
bareMetalSection = h('div', {}, "No bare metal images found.");
|
| |
}
|
| |
bareMetal = h('div', { class: "col-12 py-2 my-2" }, [ bareMetalSection ]);
|
| |
|
| |
- if (this.streamDisplay.virtualized) {
|
| |
- virtualizedSection = createArtifactsSection(this.streamDisplay.virtualized, 'virtualized');
|
| |
+ if (data.streamDisplay.virtualized) {
|
| |
+ virtualizedSection = createArtifactsSection(data.streamDisplay.virtualized, 'virtualized');
|
| |
}
|
| |
else {
|
| |
virtualizedSection = h('div', {}, "No virtualized images found.");
|
| |
}
|
| |
virtualized = h('div', { class: "col-12 py-2 my-2" }, [ virtualizedSection ]);
|
| |
-
|
| |
- if (this.streamDisplay.cloud) {
|
| |
- cloudSection = createArtifactsSection(this.streamDisplay.cloud, 'cloud');
|
| |
+
|
| |
+ if (data.streamDisplay.cloud) {
|
| |
+ cloudSection = createArtifactsSection(data.streamDisplay.cloud, 'cloud');
|
| |
}
|
| |
else {
|
| |
cloudSection = h('div', {}, "No cloud images found.");
|
| |
@@ -462,17 +483,14 @@
|
| |
])
|
| |
]);
|
| |
|
| |
- let navbar = this.getNavbar(h);
|
| |
-
|
| |
- let bare_metal_container = h('div', { class: "col-12 p-0" }, [ bareMetalTitle, verifyBlurb, bareMetal ]);
|
| |
- let virtualized_container = h('div', { class: "col-12 p-0" }, [ virtualizedTitle, verifyBlurb, virtualized ]);
|
| |
+ let bare_metal_container = h('div', { class: "col-6" }, [ bareMetalTitle, verifyBlurb, bareMetal ]);
|
| |
+ let virtualized_container = h('div', { class: "col-6" }, [ virtualizedTitle, verifyBlurb, virtualized ]);
|
| |
|
| |
- let cloud_launchable_container = h('div', { class: "col-12 py-2 my-2", attrs: { id: "cloud-launchable", hidden: false} }, [ cloudLaunchableTitle, streamName, cloudLaunchable ]);
|
| |
- let metal_virt_container = h('div', { class: "col-12 py-2 my-2", attrs: { id: "metal-virt", hidden: true } }, [ bare_metal_container, virtualized_container ]);
|
| |
+ let cloud_launchable_container = h('div', { class: "col-12 py-2 my-2", attrs: { id: "cloud-launchable", hidden: false} }, [ cloudLaunchableTitle, cloudLaunchable ]);
|
| |
+ let metal_virt_container = h('div', { class: "row col-12 py-2 my-2", attrs: { id: "metal-virt", hidden: true } }, [ bare_metal_container, virtualized_container ]);
|
| |
let cloud_operators_container = h('div', { class: "col-12 py-2 my-2", attrs: { id: "cloud-operator", hidden: true } }, [ cloudTitle, verifyBlurb, cloud ]);
|
| |
|
| |
return h('div', {}, [
|
| |
- navbar,
|
| |
cloud_launchable_container,
|
| |
metal_virt_container,
|
| |
cloud_operators_container
|
| |
Mainly focus on styling of fedora coreos download page, changes include adding icons inside tabs and using bootstrap jumbotron instead of container.
Styling follows the design of @duffy, conversation happened here:
https://pagure.io/fedora-websites/issue/964#comment-576026
Works around adding stable stream will be on separate PR since we want to use stable stream metadata very soon and I believe design work and metadata work can happen in parallel, if not mistaken.