Skip to content

Instantly share code, notes, and snippets.

@genedwards
Last active March 7, 2018 14:44
Show Gist options
  • Save genedwards/d06f302c73282ba39508605a9bfd9bdd to your computer and use it in GitHub Desktop.
Save genedwards/d06f302c73282ba39508605a9bfd9bdd to your computer and use it in GitHub Desktop.
javascript: (function () {
if (location.href !== 'https://jenkins1.ci.quickbaserocks.com/view/Huey/job/_huey/') {
location.href = 'https://jenkins1.ci.quickbaserocks.com/view/Huey/job/_huey/';
return;
}
const links = Array.from(document.querySelectorAll('#projectstatus .model-link.inside'));
const jobs = links
.filter(
a =>
a.href.indexOf('lastSuccessfulBuild') === -1 &&
a.href.indexOf('lastFailedBuild') === -1
)
.map(job => ({ name: job.innerText, href: job.href }));
/* jobs = [{ name: 'app-picker' }, { name: 'test' }]; */
const jobRowStyle = {
position: 'fixed',
top: '0',
left: '0',
width: '100vw',
height: '100vh',
'background-color': 'rgba(0, 0, 0, .7)',
'z-index': 10000,
display: 'flex',
'align-items': 'center',
'justify-content': 'center'
};
const modalContainer = document.createElement('div');
modalContainer.id = 'modal-container';
const style = {
position: 'fixed',
top: '0',
left: '0',
width: '100vw',
height: '100vh',
'background-color': 'rgba(0, 0, 0, .7)',
'z-index': 1000,
display: 'flex',
'align-items': 'center',
'justify-content': 'center'
};
Object.keys(style).forEach(s => (modalContainer.style[s] = style[s]));
const defaults = [
'app-picker',
'audit',
'automation',
'footer-message',
'IP-Filtering',
'reuse',
'trial-experience'
];
const disabled = ['server'];
/* that's right, raw html as a sting, kids, don't do this */
const innerHtml = `
<div style="width: 80vw; max-width: 700px; height: 90vh; background-color: #fff;
padding: 40px; overflow:auto; border-radius: 4px; position:relative;">
<div style="display: flex; align-items: center">
<h2 id="build-header" style="flex-grow:1">Pick builds to include in report</h2>
<button id="start-button" onClick="startBuildTimeCollection()"
style="height: 40px; width: 100px; text-align: center; border-radius: 8px;
border: 1px solid #00b1eb; font-size: 18px; color: #fff; cursor: pointer;
font-weight: 500; letter-spacing: 0.03em; background-color: #00b1eb;">
Start
</button>
<button onClick="closeModal()"
style="height: 40px; width: 100px; text-align: center; border-radius: 8px;
border: 1px solid #e8e8e8; font-size: 18px; color: #444; cursor: pointer;
font-weight: 500; letter-spacing: 0.03em; background-color: #e8e8e8;
margin-left: 8px">Close</button>
</div>
${jobs
.map(
job => `
<div style="min-height: 32px; padding: 8px; font-size: 16px;" id=${job.name}>
<input type="checkbox" id="build-${job.name}" name="build-${job.name}" ${
defaults.includes(job.name) ? 'checked' : ''
}
${disabled.includes(job.name) ? 'disabled' : ''}>
<label for="build-${job.name}" ${
disabled.includes(job.name) ? 'style="text-decoration: line-through;"' : ''
}>${job.name}</label>
<div id="${job.name}-time-container" style="display: flex;"></div>
</div>
`
)
.join('\n')}
</div>`;
modalContainer.innerHTML = innerHtml;
document.querySelector('body').appendChild(modalContainer);
/* time:
* 3 min 12 sec
* 14 min
* 39 sec
*/
const parseTime = time =>
time
.replace(/(\d+)\s*min\s*(\d)\s*sec/, '$1:0$2')
.replace(/(\d+)\s*min\s*(\d\d)\s*sec/, '$1:$2')
.replace(/(\d+)\s*min/, '$1:00')
.replace(/(\d)\s*sec/, '0:0$1')
.replace(/(\d\d)\s*sec/, '0:$1');
/* time: [
* 0:15,
* 1:39,
* 14:00
* ]
*/
const getAverageTime = times => {
const totalTime = times.reduce((totalSeconds, time) => {
let [__, m, s] = /(\d+):(\d+)/.exec(time);
return totalSeconds + Number(s) + (Number(m) * 60);
}, 0);
const average = ~~(totalTime / times.length);
const minutes = Math.floor(average / 60);
const seconds = ('0' + average % 60).slice(-2);
return `${minutes}:${seconds}`;
};
window.closeModal = () => {
const modalElement = document.querySelector(`#modal-container`);
modalElement.parentNode.removeChild(modalElement);
};
window.startBuildTimeCollection = () => {
let promises = jobs
.filter(job => {
const inputNode = document.querySelector(`#build-${job.name}`);
return inputNode.checked;
})
.map(job => {
console.log(job.name);
return new Promise((resolve, reject) => {
const winRef = window.open(job.href + 'job/master/buildTimeTrend');
console.log('opening' + job.href);
const check = () => {
const buildTimes = Array.from(
winRef.document.querySelectorAll('td[data="4"] + td + td')
).map(time => parseTime(time.innerText));
if (buildTimes.length) {
winRef.close();
let buildTimesNode = buildTimes
.map(time => `<div style="padding: 4px;">${time}</div>`)
.join('');
buildTimesNode += `<div class="average-time" style="flex-grow: 1; text-align: end;">${getAverageTime(buildTimes)}</div>`;
document.querySelector(
`#${job.name}-time-container`
).innerHTML = buildTimesNode;
resolve({ [job.name]: buildTimes });
} else {
setTimeout(check, 3000);
}
};
setTimeout(check, 3000);
});
});
Promise.all(promises)
.then(values => {
/* move focus back to parent page */
window.focus();
const averageTimes = Array.from(document.querySelectorAll('.average-time')).map(time => time.innerText);
const totalAverageTime = getAverageTime(averageTimes);
document.querySelector('#build-header').innerHTML = `Average time: ${totalAverageTime}`;
const startButton = document.querySelector('#start-button');
startButton.parentNode.removeChild(startButton);
})
.catch(err => {
console.log('err');
console.log(err);
});
};
}())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment