added scheduler v2
All checks were successful
Test Build / test-build (push) Successful in 25s

This commit is contained in:
2025-07-31 03:50:08 +03:00
parent 4f66edbb21
commit 0a17b31c06
6 changed files with 430 additions and 94 deletions

View File

@@ -196,26 +196,26 @@
</tr>
</thead>
<tbody>
{% for sheet in sheets %}
{% set mappings = mappings.get(sheet.title) %}
{% if mapping_info and mapping_info.get('report_id') %}
{% set report_id = mapping_info.get('report_id') %}
{% set matching_presets = presets | selectattr('id', 'equalto', report_id) | list %}
{% set preset_name = _('ID: ') + report_id %}
{% if matching_presets %}
{% set preset = matching_presets[0] %}
{% set preset_name = preset.get('name', _('Unnamed Preset')) %}
{% endif %}
{% for sheet_title, mapping_info in mappings.items() %}
{% if mapping_info and mapping_info.get('report_id') %}
{% set report_id = mapping_info.get('report_id') %}
{% set matching_presets = presets | selectattr('id', 'equalto', report_id) | list %}
<!-- Отображаем строку только если для этого report_id найден соответствующий пресет -->
{% if matching_presets %}
{% set preset = matching_presets[0] %}
{% set preset_name = preset.get('name', _('Unnamed Preset')) %}
<tr>
<td>{{ sheet.title }}</td>
<td>{{ preset_name }}</td>
<td>
<button type="submit" name="render_{{ sheet.title }}">
{{ _('Render to sheet') }}
</button>
</td>
</tr>
<tr>
<td>{{ sheet_title }}</td>
<td>{{ preset_name }}</td>
<td>
<button type="submit" name="render_{{ sheet_title }}">
{{ _('Render to sheet') }}
</button>
</td>
</tr>
{% endif %}
{% endif %}
{% endfor %}
</tbody>
@@ -248,7 +248,7 @@
<select id="cron-day-of-week"><option value="*">*</option><option value="1">{{_('Mon')}}</option><option value="2">{{_('Tue')}}</option><option value="3">{{_('Wed')}}</option><option value="4">{{_('Thu')}}</option><option value="5">{{_('Fri')}}</option><option value="6">{{_('Sat')}}</option><option value="0">{{_('Sun')}}</option></select>
</div>
<label for="cron-output">{{ _('Generated Cron String:') }}</label>
<input type="text" id="cron-output" readonly>
<input type="text" id="cron-output">
<p id="cron-human-readable"></p>
</div>
<hr>
@@ -260,6 +260,7 @@
<th>{{ _('Worksheet') }}</th>
<th>{{ _('Schedule (Cron)') }}</th>
<th>{{ _('Report Period') }}</th>
<th>{{ _('Action') }}</th>
</tr>
</thead>
<tbody>
@@ -318,39 +319,83 @@
}
document.addEventListener('DOMContentLoaded', function() {
// Cron конструктор
const cronInputs = ['cron-minute', 'cron-hour', 'cron-day', 'cron-month', 'cron-day-of-week'];
const cronOutput = document.getElementById('cron-output');
function updateCronString() {
if (!cronOutput) return;
const values = cronInputs.map(id => document.getElementById(id).value);
cronOutput.value = values.join(' ');
}
// --- Cron конструктор и переводчик ---
const cronInputs = ['cron-minute', 'cron-hour', 'cron-day', 'cron-month', 'cron-day-of-week'];
const cronOutput = document.getElementById('cron-output');
const humanReadableOutput = document.getElementById('cron-human-readable');
// Функция для перевода cron-строки
async function translateCronString(cronStr) {
if (!humanReadableOutput) return;
cronInputs.forEach(id => {
const el = document.getElementById(id);
if(el) el.addEventListener('change', updateCronString);
});
updateCronString(); // Initial call
// Управление видимостью поля "N дней"
document.querySelectorAll('.period-select').forEach(select => {
const targetId = select.dataset.target;
const targetDiv = document.getElementById(targetId);
function toggleCustomInput() {
if (select.value === 'last_N_days') {
targetDiv.style.display = 'block';
} else {
targetDiv.style.display = 'none';
}
}
try {
const response = await fetch("{{ url_for('.translate_cron') }}", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ cron_string: cronStr })
});
select.addEventListener('change', toggleCustomInput);
toggleCustomInput(); // Initial call on page load
});
if (!response.ok) {
humanReadableOutput.textContent = 'Error communicating with server.';
return;
}
const data = await response.json();
humanReadableOutput.textContent = data.description;
humanReadableOutput.style.color = data.description.startsWith('Invalid') ? 'red' : '#555';
} catch (error) {
console.error('Error translating cron string:', error);
humanReadableOutput.textContent = 'Translation error.';
}
}
// Функция для обновления строки (из селектов) и запуска перевода
function updateCronStringFromSelects() {
if (!cronOutput) return;
const values = cronInputs.map(id => document.getElementById(id).value);
const newCronString = values.join(' ');
cronOutput.value = newCronString;
// Вызываем перевод
translateCronString(newCronString);
}
// Слушаем изменения в выпадающих списках конструктора
cronInputs.forEach(id => {
const el = document.getElementById(id);
if (el) el.addEventListener('change', updateCronStringFromSelects);
});
if (cronOutput) {
cronOutput.addEventListener('input', function() {
translateCronString(this.value); // Переводим то, что введено вручную
});
}
// Первоначальный вызов при загрузке страницы (для начальной строки)
updateCronStringFromSelects();
// --- Управление видимостью поля "N дней" ---
document.querySelectorAll('.period-select').forEach(select => {
const targetId = select.dataset.target;
const targetDiv = document.getElementById(targetId);
function toggleCustomInput() {
if (!targetDiv) return;
if (select.value === 'last_N_days') {
targetDiv.style.display = 'block';
} else {
targetDiv.style.display = 'none';
}
}
select.addEventListener('change', toggleCustomInput);
toggleCustomInput();
});
});
</script>
{% else %}
<p style="text-align: center; margin-top: 50px;">{{ _('Please,') }} <a href="{{ url_for('.login') }}">{{ _('login') }}</a> {{ _('or') }} <a href="{{ url_for('.register') }}">{{ _('register') }}</a></p>