commit
94c4ad1bb2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@ jQuery(document).ready(function ($) {
|
||||
if (confirm(l.js_sysinfo_restart_confirmation)) {
|
||||
$('body').html($('<div class="reboot">').html(l.js_sysinfo_restart_loading)).css({margin:200});
|
||||
$.ajax({
|
||||
url: '/sysinfo/restart?secret_key='+secret_key,
|
||||
url: route_sysinfo_restart + '?secret_key='+secret_key,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
data: '',
|
||||
method: 'POST',
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
const loadDateTimePicker = function ($els) {
|
||||
const loadDateTimePicker = function ($els, timeOnly) {
|
||||
const d = new Date();
|
||||
|
||||
$els.each(function () {
|
||||
var $el = $(this);
|
||||
$el.flatpickr({
|
||||
|
||||
const options = {
|
||||
enableTime: true,
|
||||
time_24hr: true,
|
||||
allowInput: false,
|
||||
noCalendar: false,
|
||||
allowInvalidPreload: false,
|
||||
dateFormat: 'Y-m-d H:i',
|
||||
defaultHour: d.getHours(),
|
||||
@ -19,9 +20,15 @@ jQuery(document).ready(function ($) {
|
||||
d ? `${d.getMinutes()} ${d.getHours()} ${d.getDate()} ${(d.getMonth() + 1)} * ${d.getFullYear()}` : ''
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (timeOnly) {
|
||||
options['noCalendar'] = true;
|
||||
}
|
||||
|
||||
$el.flatpickr(options);
|
||||
$el.addClass('hidden');
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
const getId = function ($el) {
|
||||
@ -36,31 +43,12 @@ jQuery(document).ready(function ($) {
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: '/slideshow/slide/position',
|
||||
url: route_slide_position,
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
data: JSON.stringify(positions),
|
||||
});
|
||||
};
|
||||
|
||||
const inputTypeUpdate = function () {
|
||||
const $modal = $('.modal-slide:visible');
|
||||
const $el = $('#slide-add-type');
|
||||
const value = $el.val();
|
||||
const inputType = $el.find('option').filter(function (i, el) {
|
||||
return $(el).val() === value;
|
||||
}).data('input');
|
||||
|
||||
if ($modal.find('.picker:visible').length === 0) {
|
||||
$('.slide-add-object-input')
|
||||
.addClass('hidden')
|
||||
.prop('disabled', true).prop('required', false)
|
||||
.filter('#slide-add-object-input-' + inputType)
|
||||
.removeClass('hidden')
|
||||
.prop('disabled', false).prop('required', true)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
const inputSchedulerUpdate = function () {
|
||||
const $modal = $('.modal-slide:visible');
|
||||
const $scheduleStartGroup = $modal.find('.slide-schedule-group');
|
||||
@ -76,48 +64,24 @@ jQuery(document).ready(function ($) {
|
||||
|
||||
const $datetimepickerStart = $scheduleStartGroup.find('.datetimepicker');
|
||||
const $datetimepickerEnd = $scheduleEndGroup.find('.datetimepicker');
|
||||
const $isNotification = $isNotificationGroup.find('.trigger');
|
||||
const $isNotification = $modal.find('#slide-edit-is-notification');
|
||||
|
||||
const isNotification = $isNotification.prop('checked');
|
||||
const isNotification = $isNotification.val() === '1';
|
||||
let isLoopStart = $triggerStart.val() === 'loop';
|
||||
let isCronStart = $triggerStart.val() === 'cron';
|
||||
|
||||
function updateScheduleChoices(isNotification, isLoopStart, isCronStart) {
|
||||
let scheduleStartChoices = $.extend({}, schedule_start_choices);
|
||||
let scheduleEndChoices = $.extend({}, schedule_end_choices);
|
||||
|
||||
if (!isNotification || isLoopStart) {
|
||||
delete scheduleStartChoices['cron'];
|
||||
delete scheduleEndChoices['duration'];
|
||||
}
|
||||
|
||||
if (isNotification) {
|
||||
delete scheduleStartChoices['loop'];
|
||||
delete scheduleEndChoices['stayloop'];
|
||||
|
||||
if (isCronStart) {
|
||||
delete scheduleEndChoices['datetime'];
|
||||
}
|
||||
}
|
||||
|
||||
return {scheduleStartChoices, scheduleEndChoices};
|
||||
}
|
||||
|
||||
function applyChoices() {
|
||||
const {
|
||||
scheduleStartChoices,
|
||||
scheduleEndChoices
|
||||
} = updateScheduleChoices(isNotification, isLoopStart, isCronStart);
|
||||
recreateSelectOptions($triggerStart, scheduleStartChoices);
|
||||
recreateSelectOptions($triggerEnd, scheduleEndChoices);
|
||||
}
|
||||
|
||||
applyChoices();
|
||||
const choice_map = choices_map[isNotification ? 'notification' : 'normal']
|
||||
recreateSelectOptions($triggerStart, Object.keys(choice_map).reduce((obj, key) => {
|
||||
obj[key] = choices_translations[key];
|
||||
return obj;
|
||||
}, {}));
|
||||
recreateSelectOptions($triggerEnd, choice_map[$triggerStart.val()]);
|
||||
|
||||
isLoopStart = $triggerStart.val() === 'loop';
|
||||
isCronStart = $triggerStart.val() === 'cron';
|
||||
|
||||
const isCronEnd = $triggerEnd.val() === 'cron';
|
||||
const isInWeekMomentStart = $triggerStart.val() === 'inweek';
|
||||
const isDatetimeStart = $triggerStart.val() === 'datetime';
|
||||
const isDatetimeEnd = $triggerEnd.val() === 'datetime';
|
||||
const isStayloopEnd = $triggerEnd.val() === 'stayloop';
|
||||
@ -126,6 +90,7 @@ jQuery(document).ready(function ($) {
|
||||
const flushValueStart = isLoopStart;
|
||||
const flushValueEnd = isLoopStart || isStayloopEnd || isDurationEnd;
|
||||
const flushDuration = isNotification && isDatetimeEnd;
|
||||
const datetimepickerWithCalendar = !isInWeekMomentStart;
|
||||
|
||||
function toggleVisibility() {
|
||||
$targetCronFieldStart.toggleClass('hidden', !isCronStart);
|
||||
@ -155,9 +120,9 @@ jQuery(document).ready(function ($) {
|
||||
}
|
||||
}
|
||||
|
||||
loadDateTimePicker($modal.find('.datetimepicker'), datetimepickerWithCalendar);
|
||||
toggleVisibility();
|
||||
flushValues();
|
||||
applyChoices();
|
||||
};
|
||||
|
||||
|
||||
@ -172,27 +137,12 @@ jQuery(document).ready(function ($) {
|
||||
inputSchedulerUpdate();
|
||||
});
|
||||
|
||||
$(document).on('change', '#slide-add-type', inputTypeUpdate);
|
||||
|
||||
// $(document).on('click', '.picker button', function () {
|
||||
// const $parent = $(this).parents('.modal-slide-add');
|
||||
// $parent.find('.picker').addClass('hidden').find('select').prop('disabled', true);
|
||||
// $parent.find('.upload').removeClass('hidden').find('input,select').prop('disabled', false);
|
||||
// inputTypeUpdate();
|
||||
// });
|
||||
|
||||
$(document).on('click', '.slide-add', function () {
|
||||
showModal('modal-slide-add');
|
||||
const $modal = $('.modal-slide-add:visible');
|
||||
loadDateTimePicker($modal.find('.datetimepicker'));
|
||||
// $modal.find('.picker').removeClass('hidden').find('select').prop('disabled', false);
|
||||
// $modal.find('.upload').addClass('hidden').find('input,select').prop('disabled', true);
|
||||
// $modal.find('button[type=submit]').removeClass('hidden');
|
||||
// $modal.find('.btn-loading').addClass('hidden');
|
||||
inputTypeUpdate();
|
||||
showModal($(this).attr('data-modal'));
|
||||
const $modal = $('.modal-slide:visible');
|
||||
inputSchedulerUpdate();
|
||||
inputContentUpdate();
|
||||
$('.modal-slide-add input:eq(0)').focus().select();
|
||||
$modal.find('input[type=text]:visible:eq(0)').focus().select();
|
||||
});
|
||||
|
||||
$(document).on('click', '.content-explr-picker', function () {
|
||||
@ -226,7 +176,8 @@ jQuery(document).ready(function ($) {
|
||||
|
||||
$(document).on('click', '.slide-edit', function () {
|
||||
const slide = JSON.parse($(this).parents('.slide-item:eq(0)').attr('data-entity'));
|
||||
showModal('modal-slide-edit');
|
||||
showModal($(this).attr('data-modal'));
|
||||
const $modal = $('.modal-slide:visible');
|
||||
|
||||
const hasCron = slide.cron_schedule && slide.cron_schedule.length > 0;
|
||||
const hasDateTime = hasCron && validateCronDateTime(slide.cron_schedule);
|
||||
@ -237,26 +188,25 @@ jQuery(document).ready(function ($) {
|
||||
|
||||
inputContentUpdate(slide.content);
|
||||
|
||||
$('.modal-slide-edit input:visible:eq(0)').focus().select();
|
||||
$('#slide-edit-duration').val(slide.duration);
|
||||
$('#slide-edit-is-notification').prop('checked', isNotification);
|
||||
$('#slide-edit-enabled').prop('checked', slide.enabled);
|
||||
$modal.find('input[type=text]:visible:eq(0)').focus().select();
|
||||
$modal.find('#slide-edit-duration').val(slide.duration);
|
||||
$modal.find('#slide-edit-enabled').prop('checked', slide.enabled);
|
||||
|
||||
$('#slide-edit-cron-schedule').val(slide.cron_schedule).toggleClass('hidden', !hasCron || hasDateTime);
|
||||
$('#slide-edit-cron-schedule-trigger').val(hasDateTime ? 'datetime' : (hasCron ? 'cron' : 'loop'));
|
||||
$modal.find('#slide-edit-cron-schedule').val(slide.cron_schedule).toggleClass('hidden', !hasCron || hasDateTime);
|
||||
$modal.find('#slide-edit-cron-schedule-trigger').val(hasDateTime ? 'datetime' : (hasCron ? 'cron' : 'loop'));
|
||||
|
||||
$('#slide-edit-cron-schedule-end').val(slide.cron_schedule_end).toggleClass('hidden', !hasCronEnd || hasDateTimeEnd);
|
||||
$('#slide-edit-cron-schedule-end-trigger').val(hasDateTimeEnd ? 'datetime' : (hasCronEnd ? 'cron' : (isNotification ? 'duration' : 'stayloop')));
|
||||
$modal.find('#slide-edit-cron-schedule-end').val(slide.cron_schedule_end).toggleClass('hidden', !hasCronEnd || hasDateTimeEnd);
|
||||
$modal.find('#slide-edit-cron-schedule-end-trigger').val(hasDateTimeEnd ? 'datetime' : (hasCronEnd ? 'cron' : (isNotification ? 'duration' : 'stayloop')));
|
||||
|
||||
$('#slide-edit-cron-schedule-datetimepicker').toggleClass('hidden', !hasDateTime).val(
|
||||
$modal.find('#slide-edit-cron-schedule-datetimepicker').toggleClass('hidden', !hasDateTime).val(
|
||||
hasDateTime ? getCronDateTime(slide.cron_schedule) : ''
|
||||
);
|
||||
|
||||
$('#slide-edit-cron-schedule-end-datetimepicker').toggleClass('hidden', !hasDateTimeEnd).val(
|
||||
$modal.find('#slide-edit-cron-schedule-end-datetimepicker').toggleClass('hidden', !hasDateTimeEnd).val(
|
||||
hasDateTimeEnd ? getCronDateTime(slide.cron_schedule_end) : ''
|
||||
);
|
||||
$('#slide-edit-id').val(slide.id);
|
||||
loadDateTimePicker($('.modal-slide-edit .datetimepicker'));
|
||||
$modal.find('#slide-edit-id').val(slide.id);
|
||||
loadDateTimePicker($modal.find('.datetimepicker'));
|
||||
|
||||
inputSchedulerUpdate();
|
||||
});
|
||||
@ -280,7 +230,7 @@ jQuery(document).ready(function ($) {
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('submit', '.modal-slide-add form', function () {
|
||||
$(document).on('submit', '.modal-slide form', function () {
|
||||
$(this).find('button[type=submit]').addClass('hidden');
|
||||
$(this).find('.btn-loading').removeClass('hidden');
|
||||
});
|
||||
|
||||
@ -57,7 +57,7 @@
|
||||
|
||||
h3 {
|
||||
align-self: stretch;
|
||||
margin: 0;
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -1,5 +1,13 @@
|
||||
.view-playlist-list main .main-container {
|
||||
|
||||
.page-content {
|
||||
.inner {
|
||||
h3.divide {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slides-holder {
|
||||
|
||||
ul.slides {
|
||||
|
||||
@ -75,8 +75,11 @@
|
||||
"playlist_button_add": "Add Playlist",
|
||||
"playlist_button_delete": "Delete Playlist",
|
||||
"playlist_panel_about_playlist": "About playlist",
|
||||
"playlist_panel_content_management": "Content management",
|
||||
"playlist_panel_content_management": "Playlist loop",
|
||||
"playlist_panel_content_management_desc": "You can add, modify, delete and rearrange the order of contents from this list. Disabled slides will not play in the slideshow.",
|
||||
"playlist_panel_content_management_notifications": "Playlist notifications",
|
||||
"playlist_panel_content_management_notifications_desc": "Notifications are slides that appear on top of everything at a time and for a duration you choose. The order in which they appear below is irrelevant.",
|
||||
"slideshow_slide_button_add_notification": "Add Notification",
|
||||
"playlist_panel_preview": "Playlist preview",
|
||||
"playlist_panel_preview_action": "Preview",
|
||||
"playlist_panel_inactive": "Inactive playlists",
|
||||
|
||||
@ -75,8 +75,11 @@
|
||||
"playlist_button_add": "Agregar Playlist",
|
||||
"playlist_button_delete": "Eliminar Playlist",
|
||||
"playlist_panel_about_playlist": "Acerca de la playlist",
|
||||
"playlist_panel_content_management": "Gestión de contenido",
|
||||
"playlist_panel_content_management": "Bucle de playlist ",
|
||||
"playlist_panel_content_management_desc": "Puedes agregar, modificar, eliminar y reorganizar el orden de los contenidos de esta lista. Las diapositivas deshabilitadas no se reproducirán en la presentación de diapositivas.",
|
||||
"playlist_panel_content_management_notifications": "Notificaciones de listas de reproducción",
|
||||
"playlist_panel_content_management_notifications_desc": "Las notificaciones son diapositivas que aparecen encima de todo en un momento y durante el tiempo que elijas. El orden en que aparecen a continuación es irrelevante.",
|
||||
"slideshow_slide_button_add_notification": "Agregar notificación",
|
||||
"playlist_panel_preview": "Vista previa de la playlist",
|
||||
"playlist_panel_preview_action": "Avance",
|
||||
"playlist_panel_inactive": "Playlist inactivas",
|
||||
|
||||
@ -75,8 +75,11 @@
|
||||
"playlist_button_add": "Ajouter Playlist",
|
||||
"playlist_button_delete": "Supprimer Playlist",
|
||||
"playlist_panel_about_playlist": "À propos de la playlist",
|
||||
"playlist_panel_content_management": "Elements de la playlist",
|
||||
"playlist_panel_content_management": "Boucle de la playlist",
|
||||
"playlist_panel_content_management_desc": "Vous pouvez ajouter, modifier, supprimer et réorganiser l'ordre des contenus depuis cette liste. Les slides désactivées ne seront pas lues dans le diaporama.",
|
||||
"playlist_panel_content_management_notifications": "Notifications de la playlist",
|
||||
"playlist_panel_content_management_notifications_desc": "Les notifications sont des slides qui apparaissent au dessus de tout à un moment et pendant une durée que vous choisissez. L'ordre dans lequel elles apparaissent ci-dessous n'a aucune importance.",
|
||||
"slideshow_slide_button_add_notification": "Ajouter une notification",
|
||||
"playlist_panel_preview": "Playlist preview",
|
||||
"playlist_panel_preview_action": "Prévisualiser",
|
||||
"playlist_panel_inactive": "Playlist inactives",
|
||||
|
||||
@ -75,8 +75,11 @@
|
||||
"playlist_button_add": "Aggiungi Playlist",
|
||||
"playlist_button_delete": "Elimina Playlist",
|
||||
"playlist_panel_about_playlist": "Informazioni sulla playlist",
|
||||
"playlist_panel_content_management": "Gestione dei contenuti",
|
||||
"playlist_panel_content_management": "Ciclo della playlist",
|
||||
"playlist_panel_content_management_desc": "Puoi aggiungere, modificare, eliminare e riorganizzare l'ordine dei contenuti da questo elenco. Le diapositive disabilitate non verranno riprodotte nella presentazione.",
|
||||
"playlist_panel_content_management_notifications": "Notifiche playlist",
|
||||
"playlist_panel_content_management_notifications_desc": "Le notifiche sono diapositive che appaiono sopra ogni cosa alla volta e per la durata da te scelta. L'ordine in cui appaiono di seguito è irrilevante.",
|
||||
"slideshow_slide_button_add_notification": "Aggiungi notifica",
|
||||
"playlist_panel_preview": "Anteprima della playlist",
|
||||
"playlist_panel_preview_action": "Anteprima",
|
||||
"playlist_panel_inactive": "Playlist inattive",
|
||||
|
||||
@ -9,7 +9,7 @@ from src.model.entity.Slide import Slide
|
||||
from src.exceptions.NoFallbackPlaylistException import NoFallbackPlaylistException
|
||||
from src.service.ModelStore import ModelStore
|
||||
from src.interface.ObController import ObController
|
||||
from src.util.utils import get_safe_cron_descriptor, is_valid_cron_date_time, get_cron_date_time
|
||||
from src.util.utils import get_safe_cron_descriptor, is_cron_calendar_moment, is_cron_in_day_moment, get_cron_date_time
|
||||
from src.util.UtilNetwork import get_safe_remote_addr, get_network_interfaces
|
||||
from src.model.enum.AnimationSpeed import animation_speed_duration
|
||||
|
||||
@ -144,14 +144,14 @@ class PlayerController(ObController):
|
||||
else:
|
||||
continue
|
||||
|
||||
has_valid_start_date = 'cron_schedule' in slide and slide['cron_schedule'] and get_safe_cron_descriptor(slide['cron_schedule']) and is_valid_cron_date_time(slide['cron_schedule'])
|
||||
has_valid_end_date = 'cron_schedule_end' in slide and slide['cron_schedule_end'] and get_safe_cron_descriptor(slide['cron_schedule_end']) and is_valid_cron_date_time(slide['cron_schedule_end'])
|
||||
has_valid_start_date = 'cron_schedule' in slide and slide['cron_schedule'] and get_safe_cron_descriptor(slide['cron_schedule']) and is_cron_calendar_moment(slide['cron_schedule'])
|
||||
has_valid_end_date = 'cron_schedule_end' in slide and slide['cron_schedule_end'] and get_safe_cron_descriptor(slide['cron_schedule_end']) and is_cron_calendar_moment(slide['cron_schedule_end'])
|
||||
|
||||
if slide['is_notification'] and has_valid_start_date:
|
||||
if slide['is_notification']:
|
||||
if has_valid_start_date:
|
||||
playlist_notifications.append(slide)
|
||||
else:
|
||||
logging.warn('Slide {} is notification but start date is invalid'.format(slide['name']))
|
||||
logging.warn('Slide \'{}\' is a notification but start date is invalid'.format(slide['name']))
|
||||
else:
|
||||
if has_valid_start_date:
|
||||
start_date = get_cron_date_time(slide['cron_schedule'], object=True)
|
||||
|
||||
@ -40,7 +40,8 @@ class PlaylistController(ObController):
|
||||
playlists=playlists,
|
||||
durations=durations,
|
||||
slides_with_content=slides_with_content,
|
||||
slides=self._model_store.slide().get_slides(playlist_id=current_playlist.id) if current_playlist else [],
|
||||
slides=self._model_store.slide().get_slides(playlist_id=current_playlist.id, is_notification=False) if current_playlist else [],
|
||||
notifications=self._model_store.slide().get_slides(playlist_id=current_playlist.id, is_notification=True) if current_playlist else [],
|
||||
foldered_contents=self._model_store.content().get_all_indexed('folder_id', multiple=True),
|
||||
contents={content.id: {"id": content.id, "name": content.name, "type": content.type.value} for content in self._model_store.content().get_contents()},
|
||||
working_folder_path=working_folder_path,
|
||||
|
||||
@ -64,7 +64,7 @@ class SlideController(ObController):
|
||||
content_id=request.form['content_id'],
|
||||
enabled='enabled' in request.form and request.form['enabled'],
|
||||
duration=request.form['duration'],
|
||||
is_notification=True if 'is_notification' in request.form else False,
|
||||
is_notification=True if 'is_notification' in request.form and request.form['is_notification'] == '1' else False,
|
||||
cron_schedule=request.form['cron_schedule'],
|
||||
cron_schedule_end=request.form['cron_schedule_end'],
|
||||
)
|
||||
|
||||
@ -87,12 +87,15 @@ class SlideManager(ModelManager):
|
||||
for slide_id, edits in edits_slides.items():
|
||||
self._db.update_by_id(self.TABLE_NAME, slide_id, edits)
|
||||
|
||||
def get_slides(self, playlist_id: Optional[int] = None, content_id: Optional[int] = None, enabled: Optional[bool] = None) -> List[Slide]:
|
||||
def get_slides(self, playlist_id: Optional[int] = None, content_id: Optional[int] = None, enabled: Optional[bool] = None, is_notification: Optional[bool] = None) -> List[Slide]:
|
||||
query = " 1=1 "
|
||||
|
||||
if enabled is not None:
|
||||
query = "{} AND enabled = {} ".format(query, "1" if enabled else "0")
|
||||
|
||||
if is_notification is not None:
|
||||
query = "{} AND is_notification = {} ".format(query, "1" if is_notification else "0")
|
||||
|
||||
if playlist_id:
|
||||
query = "{} {}".format(query, "AND playlist_id = {}".format(playlist_id))
|
||||
|
||||
|
||||
@ -10,7 +10,12 @@ from src.model.hook.HookRegistration import HookRegistration
|
||||
from src.model.hook.StaticHookRegistration import StaticHookRegistration
|
||||
from src.model.hook.FunctionalHookRegistration import FunctionalHookRegistration
|
||||
from src.constant.WebDirConstant import WebDirConstant
|
||||
from src.util.utils import get_safe_cron_descriptor, is_valid_cron_date_time, seconds_to_hhmmss, am_i_in_docker, truncate, merge_dicts, dictsort
|
||||
from src.util.utils import get_safe_cron_descriptor, \
|
||||
is_cron_calendar_moment, \
|
||||
is_cron_in_day_moment, \
|
||||
is_cron_in_week_moment, \
|
||||
seconds_to_hhmmss, am_i_in_docker, \
|
||||
truncate, merge_dicts, dictsort
|
||||
|
||||
|
||||
class TemplateRenderer:
|
||||
@ -43,7 +48,8 @@ class TemplateRenderer:
|
||||
cron_descriptor=self.cron_descriptor,
|
||||
str=str,
|
||||
seconds_to_hhmmss=seconds_to_hhmmss,
|
||||
is_valid_cron_date_time=is_valid_cron_date_time,
|
||||
is_cron_calendar_moment=is_cron_calendar_moment,
|
||||
is_cron_in_day_moment=is_cron_in_day_moment,
|
||||
json_dumps=json.dumps,
|
||||
merge_dicts=merge_dicts,
|
||||
dictsort=dictsort,
|
||||
|
||||
@ -59,11 +59,31 @@ def camel_to_snake(camel: str) -> str:
|
||||
return CAMEL_CASE_TO_SNAKE_CASE_PATTERN.sub('_', camel).lower()
|
||||
|
||||
|
||||
def is_valid_cron_date_time(expression: str) -> bool:
|
||||
def is_cron_calendar_moment(expression: str) -> bool:
|
||||
pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\*\s+(\d+)$')
|
||||
return bool(pattern.match(expression))
|
||||
|
||||
|
||||
def is_cron_in_year_moment(expression: str) -> bool:
|
||||
pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\*\s+\*$')
|
||||
return bool(pattern.match(expression))
|
||||
|
||||
|
||||
def is_cron_in_week_moment(expression: str) -> bool:
|
||||
pattern = re.compile(r'^(\d+)\s+(\d+)\s+\*\s+\*\s+(\d+)\s+\*$')
|
||||
return bool(pattern.match(expression))
|
||||
|
||||
|
||||
def is_cron_in_month_moment(expression: str) -> bool:
|
||||
pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+\*\s+\*\s+\*$')
|
||||
return bool(pattern.match(expression))
|
||||
|
||||
|
||||
def is_cron_in_day_moment(expression: str) -> bool:
|
||||
pattern = re.compile(r'^(\d+)\s+(\d+)\s+\*\s+\*\s+\*\s+\*$')
|
||||
return bool(pattern.match(expression))
|
||||
|
||||
|
||||
def get_cron_date_time(cron_expression: str, object: bool) -> str:
|
||||
minutes, hours, day, month, _, year = cron_expression.split(' ')
|
||||
formatted_date_time = f"{year}-{month.zfill(2)}-{day.zfill(2)} {hours.zfill(2)}:{minutes.zfill(2)}"
|
||||
@ -71,7 +91,7 @@ def get_cron_date_time(cron_expression: str, object: bool) -> str:
|
||||
|
||||
|
||||
def get_safe_cron_descriptor(expression: str, use_24hour_time_format=True, locale_code: Optional[str] = None) -> str:
|
||||
if is_valid_cron_date_time(expression):
|
||||
if is_cron_calendar_moment(expression):
|
||||
[minutes, hours, day, month, _, year] = expression.split(' ')
|
||||
return "{}-{}-{} at {}:{}".format(
|
||||
year,
|
||||
|
||||
@ -1 +1 @@
|
||||
2.0.2
|
||||
2.0.3
|
||||
|
||||
@ -1,45 +1,83 @@
|
||||
<table class="panes variables">
|
||||
<tbody>
|
||||
{% set ns = namespace(last_section='') %}
|
||||
{% for variable in variables %}
|
||||
{% set section_change = variable.plugin and ns.last_section != variable.plugin %}
|
||||
<form id="timeForm">
|
||||
<label for="timePeriod">Sélectionnez une période:</label>
|
||||
<select id="timePeriod" name="timePeriod" onchange="showFields()">
|
||||
<option value="">--Sélectionnez--</option>
|
||||
<option value="year">À un moment dans l'année</option>
|
||||
<option value="week">À un moment dans la semaine</option>
|
||||
<option value="month">À un moment dans le mois</option>
|
||||
<option value="day">À un moment de la journée</option>
|
||||
<option value="specificDate">À un jour précis dans le calendrier</option>
|
||||
</select>
|
||||
|
||||
{% if section_change %}
|
||||
{% if not loop.first %}</tbody><tbody>{% endif %}
|
||||
<tr class="title-item">
|
||||
<td colspan="3">
|
||||
{% set plugin = plugins[variable.plugin] %}
|
||||
{{ t(plugin.use_title()) }}
|
||||
<div id="yearFields" class="hidden">
|
||||
<label for="monthOfYear">Mois de l'année:</label>
|
||||
<input type="number" id="monthOfYear" name="monthOfYear" min="1" max="12">
|
||||
<label for="dayOfMonthYear">Jour du mois:</label>
|
||||
<input type="number" id="dayOfMonthYear" name="dayOfMonthYear" min="1" max="30">
|
||||
<label for="hourYear">Heure:</label>
|
||||
<input type="number" id="hourYear" name="hourYear" min="0" max="24">
|
||||
<label for="minuteYear">Minute:</label>
|
||||
<input type="number" id="minuteYear" name="minuteYear" min="0" max="60">
|
||||
</div>
|
||||
|
||||
{% if plugin.use_description() %}
|
||||
<div class="more">{{ t(plugin.use_description()) }}</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr class="variable-item variable-edit" data-level="{{ variable.id }}" data-entity="{{ variable.to_json() }}">
|
||||
<td class="description">
|
||||
{{ t(variable.description) }}
|
||||
</td>
|
||||
<td class="value">
|
||||
<i class="fa fa-pencil icon-legend"></i>
|
||||
{% if variable.value %}
|
||||
{% if variable.type.value == 'bool' %}
|
||||
{% if variable.display() %}
|
||||
<i class="fa fa-check alert-success alert-icon icon-value"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-times alert-error alert-icon icon-value"></i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ variable.display() }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="empty">{{ l.common_empty }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<div id="weekFields" class="hidden">
|
||||
<label for="dayOfWeek">Jour de la semaine:</label>
|
||||
<input type="number" id="dayOfWeek" name="dayOfWeek" min="1" max="7">
|
||||
<label for="hourWeek">Heure:</label>
|
||||
<input type="number" id="hourWeek" name="hourWeek" min="0" max="24">
|
||||
<label for="minuteWeek">Minute:</label>
|
||||
<input type="number" id="minuteWeek" name="minuteWeek" min="0" max="60">
|
||||
</div>
|
||||
|
||||
{% set ns.last_section = variable.plugin %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="monthFields" class="hidden">
|
||||
<label for="dayOfMonth">Jour du mois:</label>
|
||||
<input type="number" id="dayOfMonth" name="dayOfMonth" min="1" max="30">
|
||||
<label for="hourMonth">Heure:</label>
|
||||
<input type="number" id="hourMonth" name="hourMonth" min="0" max="24">
|
||||
<label for="minuteMonth">Minute:</label>
|
||||
<input type="number" id="minuteMonth" name="minuteMonth" min="0" max="60">
|
||||
</div>
|
||||
|
||||
<div id="dayFields" class="hidden">
|
||||
<label for="hourDay">Heure:</label>
|
||||
<input type="number" id="hourDay" name="hourDay" min="0" max="24">
|
||||
<label for="minuteDay">Minute:</label>
|
||||
<input type="number" id="minuteDay" name="minuteDay" min="0" max="60">
|
||||
</div>
|
||||
|
||||
<div id="specificDateFields" class="hidden">
|
||||
<label for="specificDate">Date complète (Y-m-d H-i):</label>
|
||||
<input type="datetime-local" id="specificDate" name="specificDate">
|
||||
</div>
|
||||
|
||||
<button type="submit">Soumettre</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
function showFields() {
|
||||
document.getElementById('yearFields').classList.add('hidden');
|
||||
document.getElementById('weekFields').classList.add('hidden');
|
||||
document.getElementById('monthFields').classList.add('hidden');
|
||||
document.getElementById('dayFields').classList.add('hidden');
|
||||
document.getElementById('specificDateFields').classList.add('hidden');
|
||||
|
||||
var timePeriod = document.getElementById('timePeriod').value;
|
||||
if (timePeriod === 'year') {
|
||||
document.getElementById('yearFields').classList.remove('hidden');
|
||||
} else if (timePeriod === 'week') {
|
||||
document.getElementById('weekFields').classList.remove('hidden');
|
||||
} else if (timePeriod === 'month') {
|
||||
document.getElementById('monthFields').classList.remove('hidden');
|
||||
} else if (timePeriod === 'day') {
|
||||
document.getElementById('dayFields').classList.remove('hidden');
|
||||
} else if (timePeriod === 'specificDate') {
|
||||
document.getElementById('specificDateFields').classList.remove('hidden');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block add_js %}
|
||||
<script>
|
||||
route_sysinfo_restart = '{{ url_for('sysinfo_restart') }}';
|
||||
</script>
|
||||
<script src="{{ STATIC_PREFIX }}js/restart.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@ -7,17 +7,30 @@
|
||||
{{ l.playlist_panel_content_management_desc }}
|
||||
</p>
|
||||
|
||||
{% with slides=slides %}
|
||||
{% with slides=slides, are_notifications=False %}
|
||||
{% include 'slideshow/slides/component/table.jinja.html' %}
|
||||
{% endwith %}
|
||||
|
||||
<div class="actions actions-right">
|
||||
<button type="button" class="btn btn-info slide-add">
|
||||
<button type="button" class="btn btn-info slide-add" data-modal="modal-slide-add">
|
||||
<i class="fa fa-plus"></i> {{ l.slideshow_slide_form_add_title }}
|
||||
</button>
|
||||
<a href="{{ url_for('slideshow_content_list') }}" class="btn btn-neutral" target="_blank">
|
||||
<i class="fa fa-upload"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h3 class="divide">
|
||||
{{ l.playlist_panel_content_management_notifications }}
|
||||
</h3>
|
||||
<p>
|
||||
{{ l.playlist_panel_content_management_notifications_desc }}
|
||||
</p>
|
||||
{% with slides=notifications, are_notifications=True %}
|
||||
{% include 'slideshow/slides/component/table.jinja.html' %}
|
||||
{% endwith %}
|
||||
|
||||
<div class="actions actions-right">
|
||||
<button type="button" class="btn btn-info slide-add" data-modal="modal-slide-notification-add">
|
||||
<i class="fa fa-bell"></i> {{ l.slideshow_slide_button_add_notification }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -12,18 +12,35 @@
|
||||
|
||||
{% block add_js %}
|
||||
<script type="text/javascript">
|
||||
var schedule_start_choices = {
|
||||
|
||||
var route_slide_position = '{{ url_for('slideshow_slide_position') }}';
|
||||
|
||||
var choices_translations = {
|
||||
'loop': '{{ l.slideshow_slide_form_label_cron_scheduled_loop }}',
|
||||
'datetime': '{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}',
|
||||
'cron': '{{ l.slideshow_slide_form_label_cron_scheduled_cron }}',
|
||||
};
|
||||
var schedule_end_choices = {
|
||||
'stayloop': '{{ l.slideshow_slide_form_label_cron_scheduled_stayloop }}',
|
||||
'datetime': '{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}',
|
||||
'duration': '{{ l.slideshow_slide_form_label_cron_scheduled_duration }}',
|
||||
'inweek': 'in week',
|
||||
};
|
||||
var contents =
|
||||
{{ json_dumps(contents) | safe }}
|
||||
var choices_map = {
|
||||
'normal': {
|
||||
'loop': {},
|
||||
'datetime': {
|
||||
'stayloop': choices_translations['stayloop'],
|
||||
'datetime': choices_translations['datetime']
|
||||
},
|
||||
{#'inweek': {'stayloop': choices_translations['stayloop'], 'inweek': choices_translations['inweek']},#}
|
||||
},
|
||||
'notification': {
|
||||
'datetime': {
|
||||
'datetime': choices_translations['datetime'],
|
||||
'duration': choices_translations['duration']
|
||||
},
|
||||
'cron': {'duration': choices_translations['duration']}
|
||||
}
|
||||
}
|
||||
var contents = {{ json_dumps(contents) | safe }}
|
||||
</script>
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/jquery-explr-1.4.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/jquery-ui.min.js"></script>
|
||||
@ -32,7 +49,6 @@
|
||||
<script src="{{ STATIC_PREFIX }}js/lib/qrcode.min.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/slideshow/slides.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/playlist/playlists.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/restart.js"></script>
|
||||
<script src="{{ STATIC_PREFIX }}js/explorer.js"></script>
|
||||
{{ HOOK(H_PLAYLIST_JAVASCRIPT) }}
|
||||
{% endblock %}
|
||||
@ -110,8 +126,11 @@
|
||||
<div class="modals-inner">
|
||||
{% include 'playlist/modal/add.jinja.html' %}
|
||||
{% include 'playlist/modal/qrcode.jinja.html' %}
|
||||
{% include 'slideshow/slides/modal/add.jinja.html' %}
|
||||
{% include 'slideshow/slides/modal/edit.jinja.html' %}
|
||||
|
||||
{% with is_notification=True %}{% include 'slideshow/slides/modal/edit.jinja.html' %}{% endwith %}
|
||||
{% with is_notification=False %}{% include 'slideshow/slides/modal/edit.jinja.html' %}{% endwith %}
|
||||
{% with is_notification=True %}{% include 'slideshow/slides/modal/add.jinja.html' %}{% endwith %}
|
||||
{% with is_notification=False %}{% include 'slideshow/slides/modal/add.jinja.html' %}{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -3,12 +3,14 @@
|
||||
{% set content = contents[slide.content_id] %}
|
||||
<li class="slide-item {{ 'disabled' if not slide.enabled }}" data-level="{{ slide.id }}"
|
||||
data-entity="{{ slide.to_json({"content": content}) }}">
|
||||
<div class="head sort">
|
||||
<a href="javascript:void(0);" class="item-sort slide-sort">
|
||||
<i class="fa fa-bars icon-left"></i>
|
||||
</a>
|
||||
</div>
|
||||
<a href="javascript:void(0);" class="infos item-edit slide-edit">
|
||||
{% if not are_notifications %}
|
||||
<div class="head sort">
|
||||
<a href="javascript:void(0);" class="item-sort slide-sort">
|
||||
<i class="fa fa-bars icon-left"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<a href="javascript:void(0);" class="infos item-edit slide-edit" data-modal="{% if are_notifications %}modal-slide-notification-edit{% else %}modal-slide-edit{% endif %}">
|
||||
<div class="type">
|
||||
{% set icon = enum_content_type.get_fa_icon(content.type) %}
|
||||
{% set color = enum_content_type.get_color_icon(content.type) %}
|
||||
@ -24,7 +26,7 @@
|
||||
{% if slide.cron_schedule %}
|
||||
{% set cron_desc = cron_descriptor(slide.cron_schedule) %}
|
||||
{% if cron_desc %}
|
||||
{% if is_valid_cron_date_time(slide.cron_schedule) %}
|
||||
{% if is_cron_calendar_moment(slide.cron_schedule) %}
|
||||
{% if slide.is_notification %}
|
||||
🔔 <span class="prefix">{{ l.slideshow_slide_panel_td_cron_scheduled_notify }}</span>
|
||||
<span class="cron-description">{{ cron_desc }}</span>
|
||||
@ -46,7 +48,7 @@
|
||||
{% if slide.cron_schedule_end %}
|
||||
{% set cron_desc_end = cron_descriptor(slide.cron_schedule_end) %}
|
||||
{% if cron_desc_end %}
|
||||
{% if is_valid_cron_date_time(slide.cron_schedule_end) %}
|
||||
{% if is_cron_calendar_moment(slide.cron_schedule_end) %}
|
||||
{% if slide.is_notification %}
|
||||
📆 <span class="prefix">{{ l.slideshow_slide_panel_td_cron_scheduled_date }}</span>
|
||||
<span class="cron-description">{{ cron_desc_end }}</span>
|
||||
@ -75,8 +77,12 @@
|
||||
</div>
|
||||
</li>
|
||||
{% else %}
|
||||
<div class="inner-empty empty-flag ">
|
||||
<i class="fa fa-image"></i>
|
||||
<div class="inner-empty empty-flag">
|
||||
{% if are_notifications %}
|
||||
<i class="fa fa-bell"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-image"></i>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="modal modal-slide-add modal-slide">
|
||||
<div class="modal modal-slide-{{ 'notification-' if is_notification }}add modal-slide">
|
||||
<h2>
|
||||
{{ l.slideshow_slide_form_add_title }}
|
||||
</h2>
|
||||
@ -13,6 +13,8 @@
|
||||
<input name="playlist_id" type="hidden" id="slide-add-playlist-id" value="{{ current_playlist.id }}">
|
||||
{% endif %}
|
||||
|
||||
<input type="text" name="is_notification" id="slide-add-is-notification" value="{{ '1' if is_notification else '0' }}" />
|
||||
|
||||
<div class="form-group form-group-horizontal">
|
||||
<label for="">{{ l.slideshow_slide_form_label_enabled }}</label>
|
||||
<div class="widget">
|
||||
@ -42,25 +44,11 @@
|
||||
{{ l.slideshow_slide_form_section_scheduling }}
|
||||
</h3>
|
||||
|
||||
<div class="form-group form-group-horizontal slide-notification-group">
|
||||
<label for="">{{ l.slideshow_slide_form_label_is_notification }}</label>
|
||||
<div class="widget">
|
||||
<div class="toggle">
|
||||
<input type="checkbox" class="trigger slide-is-notification" name="is_notification" value="1"
|
||||
id="slide-add-is-notification"/>
|
||||
<label for="slide-add-is-notification"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group slide-schedule-group">
|
||||
<label for="slide-add-cron-schedule">{{ l.slideshow_slide_form_label_cron_scheduled }}</label>
|
||||
<div class="widget">
|
||||
<select id="slide-add-cron-schedule-trigger" class="trigger">
|
||||
<option value="loop">{{ l.slideshow_slide_form_label_cron_scheduled_loop }}</option>
|
||||
<option value="datetime">{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}</option>
|
||||
<option value="cron">{{ l.slideshow_slide_form_label_cron_scheduled_cron }}</option>
|
||||
</select>
|
||||
<select id="slide-add-cron-schedule-trigger" class="trigger"></select>
|
||||
<input type="text" id="slide-add-cron-schedule-datetimepicker" class="input-naked datetimepicker"
|
||||
value=""
|
||||
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
|
||||
@ -72,11 +60,7 @@
|
||||
<div class="form-group slide-schedule-end-group">
|
||||
<label for="slide-add-cron-schedule-end">{{ l.slideshow_slide_form_label_cron_scheduled_end }}</label>
|
||||
<div class="widget">
|
||||
<select id="slide-add-cron-schedule-end-trigger" class="trigger">
|
||||
<option value="duration">{{ l.slideshow_slide_form_label_cron_scheduled_duration }}</option>
|
||||
<option value="datetime">{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}</option>
|
||||
<option value="cron">{{ l.slideshow_slide_form_label_cron_scheduled_cron }}</option>
|
||||
</select>
|
||||
<select id="slide-add-cron-schedule-end-trigger" class="trigger"> </select>
|
||||
<input type="text" id="slide-add-cron-schedule-end-datetimepicker" class="input-naked datetimepicker"
|
||||
value=""
|
||||
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
<div class="modal modal-slide-edit modal-slide hidden">
|
||||
<div class="modal modal-slide-{{ 'notification-' if is_notification }}edit modal-slide hidden">
|
||||
<h2>
|
||||
{{ l.slideshow_slide_form_edit_title }}
|
||||
</h2>
|
||||
|
||||
|
||||
<form class="form" action="{{ url_for('slideshow_slide_edit') }}" method="POST">
|
||||
|
||||
<h3>
|
||||
{{ l.slideshow_slide_form_section_content }}
|
||||
</h3>
|
||||
|
||||
|
||||
<input type="hidden" name="id" id="slide-edit-id"/>
|
||||
|
||||
<input type="hidden" name="is_notification" id="slide-edit-is-notification" value="{{ '1' if is_notification else '0' }}" />
|
||||
|
||||
<div class="form-group form-group-horizontal">
|
||||
<label for="">{{ l.slideshow_slide_form_label_enabled }}</label>
|
||||
@ -45,25 +44,10 @@
|
||||
{{ l.slideshow_slide_form_section_scheduling }}
|
||||
</h3>
|
||||
|
||||
<div class="form-group slide-notification-group">
|
||||
<label for="slide-edit-is-notification">{{ l.slideshow_slide_form_label_is_notification }}</label>
|
||||
<div class="widget">
|
||||
<div class="toggle">
|
||||
<input type="checkbox" class="trigger slide-is-notification" name="is_notification" value="1"
|
||||
id="slide-edit-is-notification"/>
|
||||
<label for="slide-edit-is-notification"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group slide-schedule-group">
|
||||
<label for="slide-edit-cron-schedule">{{ l.slideshow_slide_form_label_cron_scheduled }}</label>
|
||||
<div class="widget">
|
||||
<select id="slide-edit-cron-schedule-trigger" class="trigger">
|
||||
<option value="loop">{{ l.slideshow_slide_form_label_cron_scheduled_loop }}</option>
|
||||
<option value="datetime">{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}</option>
|
||||
<option value="cron">{{ l.slideshow_slide_form_label_cron_scheduled_cron }}</option>
|
||||
</select>
|
||||
<select id="slide-edit-cron-schedule-trigger" class="trigger"></select>
|
||||
<input type="text" id="slide-edit-cron-schedule-datetimepicker" class="input-naked datetimepicker"
|
||||
value=""
|
||||
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
|
||||
@ -75,10 +59,7 @@
|
||||
<div class="form-group slide-schedule-end-group">
|
||||
<label for="slide-edit-cron-schedule-end">{{ l.slideshow_slide_form_label_cron_scheduled_end }}</label>
|
||||
<div class="widget">
|
||||
<select id="slide-edit-cron-schedule-end-trigger" class="trigger">
|
||||
<option value="duration">{{ l.slideshow_slide_form_label_cron_scheduled_duration }}</option>
|
||||
<option value="datetime">{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}</option>
|
||||
</select>
|
||||
<select id="slide-edit-cron-schedule-end-trigger" class="trigger"></select>
|
||||
<input type="text" id="slide-edit-cron-schedule-end-datetimepicker" class="input-naked datetimepicker"
|
||||
value=""
|
||||
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user