From 3dd0c1548145c7fc5c02281a149724fbf354acac Mon Sep 17 00:00:00 2001 From: dgtlmoon Date: Fri, 29 Nov 2024 17:32:27 +0100 Subject: [PATCH] Adding some UI feedback for times that extend into the next day --- changedetectionio/flask_app.py | 2 +- changedetectionio/static/js/watch-settings.js | 44 ++++++++++++++++--- changedetectionio/templates/_helpers.html | 8 ++++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/changedetectionio/flask_app.py b/changedetectionio/flask_app.py index 0122a5b9c82..5d4dd3d44f8 100644 --- a/changedetectionio/flask_app.py +++ b/changedetectionio/flask_app.py @@ -1811,7 +1811,7 @@ def ticker_thread_check_time_launch_checks(): if time_schedule_limit and time_schedule_limit.get('enabled'): result = watch.watch_recheck_is_within_schedule(default_tz=datastore.data['settings']['application'].get('timezone', 'UTC')) if not result: - logger.debug(f"{uuid} time scheduler - not within schedule skipping.") + logger.trace(f"{uuid} Time scheduler - not within schedule skipping.") continue # If they supplied an individual entry minutes to threshold. diff --git a/changedetectionio/static/js/watch-settings.js b/changedetectionio/static/js/watch-settings.js index 0a40e4e139a..89b3f57599c 100644 --- a/changedetectionio/static/js/watch-settings.js +++ b/changedetectionio/static/js/watch-settings.js @@ -1,12 +1,14 @@ function toggleOpacity(checkboxSelector, fieldSelector, inverted) { const checkbox = document.querySelector(checkboxSelector); const fields = document.querySelectorAll(fieldSelector); + function updateOpacity() { const opacityValue = !checkbox.checked ? (inverted ? 0.6 : 1) : (inverted ? 1 : 0.6); fields.forEach(field => { field.style.opacity = opacityValue; }); } + // Initial setup updateOpacity(); checkbox.addEventListener('change', updateOpacity); @@ -15,12 +17,14 @@ function toggleOpacity(checkboxSelector, fieldSelector, inverted) { function toggleVisibility(checkboxSelector, fieldSelector, inverted) { const checkbox = document.querySelector(checkboxSelector); const fields = document.querySelectorAll(fieldSelector); + function updateOpacity() { const opacityValue = !checkbox.checked ? (inverted ? 'none' : 'block') : (inverted ? 'block' : 'none'); fields.forEach(field => { field.style.display = opacityValue; }); } + // Initial setup updateOpacity(); checkbox.addEventListener('change', updateOpacity); @@ -45,7 +49,6 @@ function getTimeInTimezone(timezone) { } - function request_textpreview_update() { if (!$('body').hasClass('preview-text-enabled')) { console.error("Preview text was requested but body tag was not setup") @@ -92,6 +95,8 @@ function request_textpreview_update() { $(document).ready(function () { + let exceedsLimit = false; + const warning_text = $("#timespan-warning") window.setInterval(function () { if ($("#time_schedule_limit-timezone").val().length) { @@ -102,12 +107,39 @@ $(document).ready(function () { document.getElementById('local-time-in-tz').textContent = getTimeInTimezone($("#time_schedule_limit-timezone").attr('placeholder')); } + let allOk = true; + + $("li.day-schedule").each(function () { + const $schedule = $(this); + const $checkbox = $schedule.find("input[type='checkbox']"); + + if ($checkbox.is(":checked")) { + const timeValue = $schedule.find("input[type='time']").val(); + const durationHours = parseInt($schedule.find("select[name*='-duration-hours']").val(), 10) || 0; + const durationMinutes = parseInt($schedule.find("select[name*='-duration-minutes']").val(), 10) || 0; + + if (timeValue) { + const [startHours, startMinutes] = timeValue.split(":").map(Number); + const totalMinutes = (startHours * 60 + startMinutes) + (durationHours * 60 + durationMinutes); + + exceedsLimit = totalMinutes > 1440 + if (exceedsLimit) { + allOk = false + } + $schedule.toggleClass("warning", exceedsLimit); + } + } else { + $schedule.toggleClass("warning", false); + } + }); + + warning_text.toggle(!allOk) }, 500); $('#time_schedule_limit-saturday, #time_schedule_limit-sunday').addClass("weekend-day") - $(document).on('click', '[data-template].set-schedule', function() { - // Get the value of the 'data-template' attribute + $(document).on('click', '[data-template].set-schedule', function () { + // Get the value of the 'data-template' attribute switch ($(this).attr('data-template')) { case 'business-hours': @@ -138,7 +170,7 @@ $(document).ready(function () { break; } }); - + $('#notification-setting-reset-to-default').click(function (e) { $('#notification_title').val(''); $('#notification_body').val(''); @@ -155,8 +187,8 @@ $(document).ready(function () { toggleVisibility('#time_schedule_limit-enabled', '#schedule-day-limits-wrapper', true) const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0); - $("#text-preview-inner").css('max-height', (vh-300)+"px"); - $("#text-preview-before-inner").css('max-height', (vh-300)+"px"); + $("#text-preview-inner").css('max-height', (vh - 300) + "px"); + $("#text-preview-before-inner").css('max-height', (vh - 300) + "px"); $("#activate-text-preview").click(function (e) { $('body').toggleClass('preview-text-enabled') diff --git a/changedetectionio/templates/_helpers.html b/changedetectionio/templates/_helpers.html index 5864ded17eb..c7115e3e2f5 100644 --- a/changedetectionio/templates/_helpers.html +++ b/changedetectionio/templates/_helpers.html @@ -78,6 +78,12 @@ padding-left: 0.5rem; padding-right: 0.5rem; } + #timespan-warning { + color: #ff0000; + } + .day-schedule.warning table { + background-color: #ffbbc2; + } ul#day-wrapper { list-style: none; } @@ -121,6 +127,8 @@ {{ render_nolabel_field(form.time_schedule_limit[day]) }} {% endfor %} +
  • Warning, one or more of your 'days' has a duration that would extend into the next day.
    + This could have unintended consequences.
  • {{ render_field(form.time_schedule_limit.timezone) }}