kpr-utils/templates/cron.html

212 lines
5.3 KiB
HTML
Raw Normal View History

2025-05-21 05:50:10 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Cronjob Syntax Helper</title>
<style>
body {
font-family: sans-serif;
padding: 1rem;
}
h1 {
text-align: center;
margin-bottom: 1rem;
}
.container {
display: flex;
gap: 2rem;
width: 60%;
/* margin: auto; */
}
.left,
.right {
flex: 1;
}
.field-row {
margin-bottom: 0.75rem;
display: flex;
align-items: center;
}
.field-row label {
width: 6rem;
}
.field-row input {
flex: 1;
padding: 0.25rem;
}
.left .field-row input {
/* fix inputs to ~6rem (≈96px) wide */
flex: 0 0 6rem;
width: 6rem;
}
#cron-desc {
padding: 0.5rem;
background: #f2f2f2;
border-radius: 4px;
min-height: 2em;
}
.bottom {
width: 60%;
margin: 1.5rem auto 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.bottom select,
.bottom button {
padding: 0.4rem 0.8rem;
margin-left: 0.5rem;
}
</style>
</head>
<body>
<div class="container">
<!-- Left column: build fields -->
<div class="left">
<div class="field-row">
<label for="minute">Minute</label>
<input type="text" id="minute" placeholder="*" />
</div>
<div class="field-row">
<label for="hour">Hour</label>
<input type="text" id="hour" placeholder="*" />
</div>
<div class="field-row">
<label for="dom">Day of Mo.</label>
<input type="text" id="dom" placeholder="*" />
</div>
<div class="field-row">
<label for="month">Month</label>
<input type="text" id="month" placeholder="*" />
</div>
<div class="field-row">
<label for="dow">Day of Wk.</label>
<input type="text" id="dow" placeholder="*" />
</div>
</div>
<!-- Right column: output -->
<div class="right">
<div class="field-row">
<label for="cron-expr">Cron Expr</label>
<input type="text" id="cron-expr" readonly />
</div>
<div class="field-row">
<label>Description</label>
<div id="cron-desc"></div>
</div>
</div>
</div>
<!-- Presets + Actions -->
<div class="bottom">
<div>
Presets:
<select id="preset">
<option value="">— choose —</option>
<option value="* * * * *">Every minute</option>
<option value="0 * * * *">Every hour</option>
<option value="0 0 * * *">Daily at midnight</option>
<option value="0 0 * * 1">Weekly Mon @ midnight</option>
<option value="0 0 1 * *">Monthly 1st @ midnight</option>
</select>
</div>
<div>
<button id="copy-btn">Copy cron expr</button>
<button id="reset-btn">Reset</button>
</div>
</div>
<script>
// grab elements
const minuteIn = document.getElementById('minute');
const hourIn = document.getElementById('hour');
const domIn = document.getElementById('dom');
const monthIn = document.getElementById('month');
const dowIn = document.getElementById('dow');
const cronExpr = document.getElementById('cron-expr');
const cronDesc = document.getElementById('cron-desc');
const preset = document.getElementById('preset');
const copyBtn = document.getElementById('copy-btn');
const resetBtn = document.getElementById('reset-btn');
// build the cron string
function updateCron() {
const parts = [
minuteIn.value.trim() || '*',
hourIn.value.trim() || '*',
domIn.value.trim() || '*',
monthIn.value.trim() || '*',
dowIn.value.trim() || '*'
];
cronExpr.value = parts.join(' ');
updateDesc(parts);
}
// basic plain-English breakdown
function updateDesc([min, hr, dom, mon, dow]) {
if ([min, hr, dom, mon, dow].every(v => v === '*')) {
cronDesc.textContent = 'Every minute';
return;
}
const parts = [];
if (min !== '*') parts.push(`minute = ${min}`);
if (hr !== '*') parts.push(`hour = ${hr}`);
if (dom !== '*') parts.push(`day of month = ${dom}`);
if (mon !== '*') parts.push(`month = ${mon}`);
if (dow !== '*') parts.push(`day of week = ${dow}`);
cronDesc.textContent = parts.join(', ');
}
// wire inputs
[minuteIn, hourIn, domIn, monthIn, dowIn].forEach(el => {
el.addEventListener('input', () => {
// clear preset selection when typing freeform
preset.value = '';
updateCron();
});
});
// presets
preset.addEventListener('change', () => {
const v = preset.value;
if (!v) return;
const p = v.split(' ');
[minuteIn.value, hourIn.value, domIn.value, monthIn.value, dowIn.value] = p;
updateCron();
});
// copy button
copyBtn.addEventListener('click', () => {
navigator.clipboard.writeText(cronExpr.value)
.then(() => alert('Copied to clipboard!'));
});
// reset button
resetBtn.addEventListener('click', () => {
minuteIn.value = hourIn.value = domIn.value = monthIn.value = dowIn.value = '*';
preset.value = '';
updateCron();
});
// init
window.addEventListener('DOMContentLoaded', () => {
resetBtn.click(); // sets everything to "* * * * *"
});
</script>
</body>
</html>