This commit is contained in:
jr-k 2024-07-23 00:44:07 +02:00
parent fc4273b585
commit 629ac4654d
30 changed files with 377 additions and 162 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,9 @@
jQuery(document).ready(function ($) { jQuery(document).ready(function ($) {
const loadDateTimePicker = function ($els, timeOnly) { const loadDateTimePicker = function ($els) {
const d = new Date(); const d = new Date();
$els.each(function () { $els.each(function () {
var $el = $(this); const $el = $(this);
const timeOnly = isScheduleInWeekMoment($el);
const options = { const options = {
enableTime: true, enableTime: true,
@ -10,27 +11,53 @@ jQuery(document).ready(function ($) {
allowInput: false, allowInput: false,
noCalendar: false, noCalendar: false,
allowInvalidPreload: false, allowInvalidPreload: false,
dateFormat: 'Y-m-d H:i', dateFormat: timeOnly ? 'H:i' : 'Y-m-d H:i',
defaultHour: d.getHours(), defaultHour: d.getHours(),
defaultMinute: d.getMinutes(), defaultMinute: d.getMinutes(),
onChange: function (selectedDates, dateStr, instance) { onChange: function (selectedDates, dateStr, instance) {
const d = selectedDates[0]; callScheduleChange($el);
const $target = $el.parents('.widget:eq(0)').find('.target');
$target.val(
d ? `${d.getMinutes()} ${d.getHours()} ${d.getDate()} ${(d.getMonth() + 1)} * ${d.getFullYear()}` : ''
);
} }
}; };
if (timeOnly) { if (timeOnly) {
// options['noCalendar'] = true; options['noCalendar'] = true;
} else {
if ($el.val().indexOf('-') < 0) {
$el.val('');
}
} }
$el.flatpickr(options); $el.flatpickr(options);
$el.addClass('hidden');
}); });
}; };
const onInDateTimeMomentChanged = function($el) {
const $holder = $el.parents('.widget:eq(0)');
const $datetimepicker = $holder.find('.datetimepicker');
const $cronTarget = $holder.find('.target');
const matches = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) (?<hour>\d{2}):(?<minute>\d{2})/.exec($datetimepicker.val());
if (matches) {
const {year, month, day, hour, minute} = matches.groups;
$cronTarget.val(`${parseInt(minute)} ${parseInt(hour)} ${parseInt(day)} ${parseInt(month)} * ${parseInt(year)}`);
} else {
$cronTarget.val('');
}
};
const onInWeekMomentChanged = function($el) {
const $holder = $el.parents('.widget:eq(0)');
const $datetimepicker = $holder.find('.datetimepicker');
const $weekdaypicker = $holder.find('.weekdaypicker');
const $cronTarget = $holder.find('.target');
const matches = $datetimepicker.val().split(':').map(function(e) { return parseInt(e) });
if (matches.length === 2) {
[hour, minute] = matches;
$cronTarget.val(`${minute} ${hour} * * ${$weekdaypicker.val()}`);
} else {
$cronTarget.val('');
}
};
const getId = function ($el) { const getId = function ($el) {
return $el.hasClass('slide-item') ? $el.attr('data-level') : $el.parents('.slide-item:eq(0)').attr('data-level'); return $el.hasClass('slide-item') ? $el.attr('data-level') : $el.parents('.slide-item:eq(0)').attr('data-level');
}; };
@ -49,6 +76,31 @@ jQuery(document).ready(function ($) {
}); });
}; };
const getScheduleValue = function ($el) {
const $scheduleGroup = $el.parents('.form-group:eq(0)');
const $cronTrigger = $scheduleGroup.find('.trigger');
return $cronTrigger.val();
};
const isScheduleInDateTimeMoment = function($el) {
const scheduleValue = getScheduleValue($el);
return scheduleValue === 'datetime';
};
const isScheduleInWeekMoment = function($el) {
const scheduleValue = getScheduleValue($el);
return scheduleValue === 'inweek';
};
const callScheduleChange = function($el) {
if (isScheduleInWeekMoment($el)) {
onInWeekMomentChanged($el);
}
if (isScheduleInDateTimeMoment($el)) {
onInDateTimeMomentChanged($el);
}
};
const inputSchedulerUpdate = function () { const inputSchedulerUpdate = function () {
const $modal = $('.modal-slide:visible'); const $modal = $('.modal-slide:visible');
const $scheduleStartGroup = $modal.find('.slide-schedule-group'); const $scheduleStartGroup = $modal.find('.slide-schedule-group');
@ -66,6 +118,9 @@ jQuery(document).ready(function ($) {
const $datetimepickerStart = $scheduleStartGroup.find('.datetimepicker'); const $datetimepickerStart = $scheduleStartGroup.find('.datetimepicker');
const $datetimepickerEnd = $scheduleEndGroup.find('.datetimepicker'); const $datetimepickerEnd = $scheduleEndGroup.find('.datetimepicker');
const $weekdaypickerStart = $scheduleStartGroup.find('.weekdaypicker');
const $weekdaypickerEnd = $scheduleEndGroup.find('.weekdaypicker');
const $isNotification = $modal.find('.slide-is-notification'); const $isNotification = $modal.find('.slide-is-notification');
const isNotification = $isNotification.val() === '1'; const isNotification = $isNotification.val() === '1';
@ -89,24 +144,27 @@ jQuery(document).ready(function ($) {
const isDatetimeEnd = $triggerEnd.val() === 'datetime'; const isDatetimeEnd = $triggerEnd.val() === 'datetime';
const isStayloopEnd = $triggerEnd.val() === 'stayloop'; const isStayloopEnd = $triggerEnd.val() === 'stayloop';
const isDurationEnd = $triggerEnd.val() === 'duration'; const isDurationEnd = $triggerEnd.val() === 'duration';
const isInWeekMomentEnd = $triggerEnd.val() === 'inweek';
const flushValueStart = isLoopStart; const flushValueStart = isLoopStart;
const flushValueEnd = isLoopStart || isStayloopEnd || isDurationEnd; const flushValueEnd = isLoopStart || isStayloopEnd || isDurationEnd;
const flushDuration = isNotification && isDatetimeEnd; const flushDuration = isNotification && isDatetimeEnd;
const datetimepickerWithCalendar = !isInWeekMomentStart; const delegateDuration = $targetDelegateDuration.prop('checked');
function toggleVisibility() { function toggleVisibility() {
$targetCronFieldStart.toggleClass('hidden', !isCronStart); $targetCronFieldStart.toggleClass('hidden', !isCronStart);
$targetCronFieldEnd.toggleClass('hidden', !isCronEnd); $targetCronFieldEnd.toggleClass('hidden', !isCronEnd);
$datetimepickerStart.toggleClass('hidden', !isDatetimeStart); $datetimepickerStart.toggleClass('hidden', !(isDatetimeStart || isInWeekMomentStart));
$datetimepickerEnd.toggleClass('hidden', !isDatetimeEnd); $datetimepickerEnd.toggleClass('hidden', !isDatetimeEnd && !isInWeekMomentEnd);
$weekdaypickerStart.toggleClass('hidden', !isInWeekMomentStart);
$weekdaypickerEnd.toggleClass('hidden', !isInWeekMomentEnd);
$delegateDurationGroup.toggleClass('hidden', (isNotification && isDatetimeEnd) || !isVideo); $delegateDurationGroup.toggleClass('hidden', (isNotification && isDatetimeEnd) || !isVideo);
$durationGroup.toggleClass('hidden', (isNotification && isDatetimeEnd) || $targetDelegateDuration.prop('checked')); $durationGroup.toggleClass('hidden', (isNotification && isDatetimeEnd) || delegateDuration);
$targetDuration.prop('required', $durationGroup.is(':visible')); $targetDuration.prop('required', $durationGroup.is(':visible'));
$targetDelegateDuration.prop('disabled', !$delegateDurationGroup.is(':visible')); $targetDelegateDuration.prop('disabled', !$delegateDurationGroup.is(':visible'));
$scheduleEndGroup.toggleClass('hidden', isLoopStart); $scheduleEndGroup.toggleClass('hidden', isLoopStart);
} }
@ -126,9 +184,14 @@ jQuery(document).ready(function ($) {
} }
} }
loadDateTimePicker($modal.find('.datetimepicker'), datetimepickerWithCalendar); loadDateTimePicker($modal.find('.datetimepicker'));
toggleVisibility(); toggleVisibility();
flushValues(); flushValues();
callScheduleChange($weekdaypickerStart);
callScheduleChange($weekdaypickerEnd);
callScheduleChange($datetimepickerStart);
callScheduleChange($weekdaypickerEnd);
}; };
const main = function () { const main = function () {
@ -138,6 +201,10 @@ jQuery(document).ready(function ($) {
}); });
}; };
$(document).on('change', '.weekdaypicker', function() {
callScheduleChange($(this));
});
$(document).on('change', '.modal-slide select.trigger, .modal-slide input.trigger', function () { $(document).on('change', '.modal-slide select.trigger, .modal-slide input.trigger', function () {
inputSchedulerUpdate(); inputSchedulerUpdate();
}); });
@ -193,10 +260,12 @@ jQuery(document).ready(function ($) {
const $modal = $('.modal-slide:visible'); const $modal = $('.modal-slide:visible');
const hasCron = slide.cron_schedule && slide.cron_schedule.length > 0; const hasCron = slide.cron_schedule && slide.cron_schedule.length > 0;
const hasDateTime = hasCron && validateCronDateTime(slide.cron_schedule); const isInDateTimeMomentStart = hasCron && isCronInDatetimeMoment(slide.cron_schedule);
const isInWeekMomentStart = hasCron && isCronInWeekMoment(slide.cron_schedule);
const hasCronEnd = slide.cron_schedule_end && slide.cron_schedule_end.length > 0; const hasCronEnd = slide.cron_schedule_end && slide.cron_schedule_end.length > 0;
const hasDateTimeEnd = hasCronEnd && validateCronDateTime(slide.cron_schedule_end); const isInDateTimeMomentEnd = hasCronEnd && isCronInDatetimeMoment(slide.cron_schedule_end);
const isInWeekMomentEnd = hasCronEnd && isCronInWeekMoment(slide.cron_schedule_end);
const isNotification = slide.is_notification; const isNotification = slide.is_notification;
const tclass = '#slide-' + (isNotification ? 'notification-' : '') + 'edit'; const tclass = '#slide-' + (isNotification ? 'notification-' : '') + 'edit';
@ -214,22 +283,31 @@ jQuery(document).ready(function ($) {
$modal.find(tclass + '-duration').val(slide.duration); $modal.find(tclass + '-duration').val(slide.duration);
$modal.find(tclass + '-enabled').prop('checked', slide.enabled); $modal.find(tclass + '-enabled').prop('checked', slide.enabled);
$modal.find(tclass + '-cron-schedule').val(slide.cron_schedule).toggleClass('hidden', !hasCron || hasDateTime); $modal.find(tclass + '-cron-schedule').val(slide.cron_schedule).toggleClass('hidden', !hasCron || isInDateTimeMomentStart || isInWeekMomentStart);
$modal.find(tclass + '-cron-schedule-trigger').val(hasDateTime ? 'datetime' : (hasCron ? 'cron' : 'loop')); $modal.find(tclass + '-cron-schedule-trigger').val(isInWeekMomentStart ? 'inweek' : (isInDateTimeMomentStart ? 'datetime' : (hasCron ? 'cron' : 'loop')));
$modal.find(tclass + '-cron-schedule-end').val(slide.cron_schedule_end).toggleClass('hidden', !hasCronEnd || hasDateTimeEnd);
$modal.find(tclass + '-cron-schedule-end-trigger').val(hasDateTimeEnd ? 'datetime' : (hasCronEnd ? 'cron' : (isNotification ? 'duration' : 'stayloop')));
$modal.find(tclass + '-cron-schedule-datetimepicker').toggleClass('hidden', !hasDateTime).val(
hasDateTime ? getCronDateTime(slide.cron_schedule) : ''
);
$modal.find(tclass + '-cron-schedule-end-datetimepicker').toggleClass('hidden', !hasDateTimeEnd).val(
hasDateTimeEnd ? getCronDateTime(slide.cron_schedule_end) : ''
);
$modal.find(tclass + '-id').val(slide.id);
loadDateTimePicker($modal.find('.datetimepicker'));
inputCallbacks(); inputCallbacks();
$modal.find(tclass + '-cron-schedule-end').val(slide.cron_schedule_end).toggleClass('hidden', !hasCronEnd || isInDateTimeMomentEnd || isInWeekMomentEnd);
$modal.find(tclass + '-cron-schedule-end-trigger').val(isInWeekMomentEnd ? 'inweek' : (isInDateTimeMomentEnd ? 'datetime' : (hasCronEnd ? 'cron' : (isNotification ? 'duration' : 'stayloop'))));
$modal.find(tclass + '-cron-schedule-datetimepicker').toggleClass('hidden', !(isInDateTimeMomentStart || isInWeekMomentStart)).val(
isInWeekMomentStart ? getCronTime(slide.cron_schedule) : (isInDateTimeMomentStart ? getCronDateTime(slide.cron_schedule) : '')
);
$modal.find(tclass + '-cron-schedule-weekdaypicker').toggleClass('hidden', !isInWeekMomentStart).val(
isInWeekMomentStart ? getCronDayInWeek(slide.cron_schedule) : '1'
);
$modal.find(tclass + '-cron-schedule-end-datetimepicker').toggleClass('hidden', !(isInDateTimeMomentEnd || isInWeekMomentEnd)).val(
isInWeekMomentEnd ? getCronTime(slide.cron_schedule_end) : (isInDateTimeMomentEnd ? getCronDateTime(slide.cron_schedule_end) : '')
);
$modal.find(tclass + '-cron-schedule-end-weekdaypicker').toggleClass('hidden', !isInWeekMomentEnd).val(
isInWeekMomentEnd ? getCronDayInWeek(slide.cron_schedule_end) : '1'
);
$modal.find(tclass + '-id').val(slide.id);
inputCallbacks();
loadDateTimePicker($modal.find('.datetimepicker'));
}); });
$(document).on('click', '.slide-delete', function () { $(document).on('click', '.slide-delete', function () {

View File

@ -8,13 +8,28 @@ const getCronDateTime = function(cronExpression) {
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hours.padStart(2, '0')}:${minutes.padStart(2, '0')}`; return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')} ${hours.padStart(2, '0')}:${minutes.padStart(2, '0')}`;
}; };
const validateCronDateTime = function(cronExpression) { const getCronTime = function(cronExpression) {
const [minutes, hours, day, month, _, year] = cronExpression.split(' ');
return `${hours.padStart(2, '0')}:${minutes.padStart(2, '0')}`;
};
const getCronDayInWeek = function(cronExpression) {
const [minutes, hours, day, month, day_week, year] = cronExpression.split(' ');
return day_week;
};
const isCronInDatetimeMoment = function(cronExpression) {
const pattern = /^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\*\s+(\d+)$/; const pattern = /^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\*\s+(\d+)$/;
return pattern.test(cronExpression); return pattern.test(cronExpression);
}; };
const isCronInWeekMoment = function(cronExpression) {
const pattern = /^(\d+)\s+(\d+)\s+\*\s+\*\s+(\d+)$/;
return pattern.test(cronExpression);
};
const cronToDateTimeObject = function(cronExpression) { const cronToDateTimeObject = function(cronExpression) {
if (!validateCronDateTime(cronExpression)) { if (!isCronInDatetimeMoment(cronExpression)) {
return null; return null;
} }

View File

@ -6,7 +6,7 @@
} }
html { html {
background-color: $gscale1; background-color: $layoutBackground;
} }
body, html { body, html {
@ -96,9 +96,7 @@ main {
align-items: flex-start; align-items: flex-start;
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
background: radial-gradient(circle at 0% 53%, rgba($pinkyRed, 0.8) 10%, transparent 45%), background: $fancyBackground;
radial-gradient(circle at 135% 53%, rgba($seaBlue, 0.8) 10%, transparent 95%),
radial-gradient(circle at 50% 80%, rgba($limeGreen, 0.8) 40%, transparent 95%);
.page-content { .page-content {
flex: 2; flex: 2;
@ -118,7 +116,7 @@ main {
justify-content: flex-start; justify-content: flex-start;
align-items: flex-start; align-items: flex-start;
padding: 0 10px 40px 10px; padding: 0 10px 40px 10px;
background: $gscale1; background: $layoutBackground;
align-self: stretch; align-self: stretch;
} }
} }
@ -127,7 +125,7 @@ main {
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
align-self: stretch; align-self: stretch;
background: $gscale1; background: $layoutBackground;
border-top: none; border-top: none;
&.left-panel { &.left-panel {
@ -138,7 +136,7 @@ main {
flex: 0.5; flex: 0.5;
overflow-y: auto; overflow-y: auto;
padding: 0; padding: 0;
background: $gscale1; background: $layoutBackground;
box-shadow: 1px 1px .5px .5px inset rgba($gscale0, 0.2); box-shadow: 1px 1px .5px .5px inset rgba($gscale0, 0.2);
max-width: 250px; max-width: 250px;
} }

View File

@ -1,6 +1,6 @@
menu { menu {
width: 300px; width: 300px;
background: $gscale1; background: $layoutBackground;
overflow-y: auto; overflow-y: auto;
overflow-x: visible; overflow-x: visible;
padding: 20px; padding: 20px;

View File

@ -197,7 +197,7 @@ ul.explr-dirview {
.img-holder { .img-holder {
width: 64px; width: 64px;
height: 64px; height: 64px;
background: $gscale07; background: $gscale17;
border-radius: 8px; border-radius: 8px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -41,7 +41,7 @@
padding-bottom: 2px; padding-bottom: 2px;
.modals-inner { .modals-inner {
background: $gscale1; background: $layoutBackground;
border-radius: 10px; border-radius: 10px;
color: lighten($gscale0, 20%); color: lighten($gscale0, 20%);
padding: 40px; padding: 40px;

View File

@ -14,7 +14,7 @@
align-items: flex-start; align-items: flex-start;
align-self: stretch; align-self: stretch;
margin: 1px 1px 28px 1px; margin: 1px 1px 28px 1px;
background: $gscale1; background: $layoutBackground;
border-radius: $baseRadius; border-radius: $baseRadius;
border: 4px solid rgba($gscaleF, .05); border: 4px solid rgba($gscaleF, .05);
@ -46,7 +46,7 @@
} }
&:nth-child(even) { &:nth-child(even) {
background-color: $gscale04; background-color: $gscale14;
} }
.pane-cell, .pane-cell,

View File

@ -36,7 +36,7 @@
&.active { &.active {
border-left: 4px solid $seaBlue; border-left: 4px solid $seaBlue;
border-radius: $baseRadius; border-radius: $baseRadius;
border-bottom: 2px solid $gscale07; border-bottom: 2px solid $gscale17;
background: $gscale2; background: $gscale2;
color: $seaBlue; color: $seaBlue;

View File

@ -0,0 +1,5 @@
$layoutBackground: $gscale1;
$fancyBackground: radial-gradient(circle at 0% 53%, rgba($pinkyRed, 0.8) 10%, transparent 45%),
radial-gradient(circle at 135% 53%, rgba($seaBlue, 0.8) 10%, transparent 95%),
radial-gradient(circle at 50% 80%, rgba($limeGreen, 0.8) 40%, transparent 95%);

View File

@ -1,2 +1,8 @@
$limeGreen: $bitterGreen; $limeGreen: $bitterGreen;
$yellow: rgb(255, 167, 10); $yellow: rgb(255, 167, 10);
$layoutBackground: $white;
$fancyBackground: radial-gradient(circle at 0% 53%, rgba($seaBlue, 0.8) 10%, transparent 45%),
radial-gradient(circle at 135% 53%, rgba($seaBlue, 0.8) 10%, transparent 95%),
radial-gradient(circle at 50% 80%, rgba($bitterPurple, 0.8) 40%, transparent 95%);

View File

@ -11,23 +11,60 @@ ul.explr-dirview li a i {
color: $seaBlue; color: $seaBlue;
} }
button.btn-neutral:hover, button,
.btn.btn-neutral:hover { .btn {
box-shadow: 0 2px 0 1px $gkscale6 inset; &.btn-pixel {
} background: $white;
color: $gkscale4;
button.btn-naked, @include pixel-box(4, $gkscaleC);
.btn.btn-naked {
&:hover {
@include pixel-box(6, $gkscaleC);
}
}
&.btn-naked {
color: $gkscale7; color: $gkscale7;
&:hover { &:hover {
box-shadow: 0 2px 0 1px $gkscale6 inset; box-shadow: 0 2px 0 1px $gkscale6 inset;
} }
}
&.btn-neutral:hover {
box-shadow: 0 2px 0 1px $gkscale6 inset;
}
} }
.tiles .tiles-inner .tile-item {
border-top: 2px solid transparent;
border-right: 2px solid transparent;
border-bottom: 2px solid transparent;
.tiles .tiles-inner .tile-item:hover, .tiles .tiles-inner .tile-item.active { &:hover,
&.active {
border-left: 2px solid $gscale17;
border-top: 2px solid $gscale17;
border-right: 2px solid $gscale17;
border-bottom: 2px solid $gscale17;
background: $white; background: $white;
}
&:hover,
&.active {
border-color: $seaBlue;
}
&:hover.starred,
&.active.starred {
border-color: $yellow;
}
&:hover.disabled,
&.active.disabled {
border-color: $gscale4;
}
} }
.panes { .panes {
@ -37,41 +74,44 @@ button.btn-naked,
.pane-item, .pane-item,
tr { tr {
&:nth-child(odd) { &:nth-child(odd) {
background-color: $gkscaleF4; background-color: $gkscaleF;
} }
&:nth-child(even) { &:nth-child(even) {
background-color: $gscale1; background-color: $gkscaleF7;
} }
} }
} }
} }
.form-group .widget select, .form-group .widget input, .form-group .widget textarea { .form-group .widget select, .form-group .widget input, .form-group .widget textarea {
box-shadow: 0 2px 1px $gkscaleA, 0 4px 2px $gkscaleA inset; box-shadow: 0 2px 1px $gkscaleD, 0 4px 2px $gkscaleD inset;
color: $gkscale5; color: $gkscale5;
background: $gkscaleC; background: $gkscaleE;
} }
.toggle label { .toggle {
box-shadow: 0 2px 2px $gkscaleA inset; label {
box-shadow: 0 2px 2px $gkscaleC inset;
&::after { &::after {
box-shadow: 0 2px rgba($gkscaleA, 0.9); box-shadow: 0 2px rgba($gkscaleC, 0.9);
}
}
input:checked + label {
box-shadow: 0 2px 2px rgba($gkscale0, .3) inset;
} }
} }
.modal-explr-picker {
.explr-tree {
background: $white;
}
}
ul.pills { ul.pills {
box-shadow: 1px 1px .5px .5px inset rgba($gkscaleA, 0.2); box-shadow: 1px 1px .5px .5px inset rgba($gkscaleA, 0.2);
background: #EEE;
li { li {
a { a {
color: $gkscale4; color: $gkscale4;
background: $white;
} }
&.active { &.active {
@ -85,6 +125,8 @@ ul.pills {
.breadcrumb-container ul.breadcrumb { .breadcrumb-container ul.breadcrumb {
box-shadow: 1px 1px .5px .5px inset rgba($gkscaleA, 0.2); box-shadow: 1px 1px .5px .5px inset rgba($gkscaleA, 0.2);
background: #EEE;
li a, li a,
li span, li span,
li { li {
@ -100,23 +142,14 @@ ul.pills {
} }
} }
.view-player-group-list main .main-container .bottom-content .page-content .inner .node-player-group-holder .preview,
.view-playlist-list main .main-container .bottom-content .page-content .inner .playlist-holder .preview {
border-color: $gkscaleC;
}
.view-player-group-list main .main-container .players-holder ul.players li.player-item .body,
.view-playlist-list main .main-container .slides-holder ul.slides li.slide-item .body {
background: $gkscaleD;
}
.dropdown ul.dropdown-menu li.danger:hover a { .dropdown ul.dropdown-menu li.danger:hover a {
color: $white; color: $white;
} }
.inner-empty i { .inner-empty i {
color: $gkscaleB; color: $gkscaleD;
text-shadow: 0 -1px $gkscale7, 0 0px .5px $gkscale4; text-shadow: 0 -1px $gkscale9, 0 0px .5px $gkscale6;
} }
.view-player-group-list main .main-container .players-holder ul.players li.player-item .tail a, .view-player-group-list main .main-container .players-holder ul.players li.player-item .tail a,
@ -127,3 +160,28 @@ ul.pills {
color: $white; color: $white;
} }
} }
.form-group {
.widget {
select,
input,
textarea {
&.disabled,
&[disabled] {
border: none;
background: $gkscaleE;
border-radius: $baseRadius;
padding-left: 10px;
padding-right: 10px;
}
}
}
}
.modal-explr-picker {
.explr-tree {
background: $gkscaleF7;
}
}

View File

@ -100,7 +100,7 @@
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
margin: 0 10px 0 10px; margin: 0 10px 0 10px;
background: $gscale0B; background: $gscale1B;
padding: 10px; padding: 10px;
align-self: stretch; align-self: stretch;
flex: 1; flex: 1;

View File

@ -115,7 +115,7 @@
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
margin: 0 10px 0 10px; margin: 0 10px 0 10px;
background: $gscale0B; background: $gscale1B;
padding: 10px; padding: 10px;
align-self: stretch; align-self: stretch;
flex: 1; flex: 1;

View File

@ -24,8 +24,8 @@
color: transparent; color: transparent;
} }
@mixin pixel-box($pixelOffset: 1) { @mixin pixel-box($pixelOffset: 1, $whiteColor: $white) {
box-shadow: #{$pixelOffset}px 0 0 $white, 0 #{$pixelOffset}px 0 $limeGreen, -#{$pixelOffset}px 0 0 $seaBlue, 0 -#{$pixelOffset}px 0 $pinkyRed; box-shadow: #{$pixelOffset}px 0 0 $whiteColor, 0 #{$pixelOffset}px 0 $limeGreen, -#{$pixelOffset}px 0 0 $seaBlue, 0 -#{$pixelOffset}px 0 $pinkyRed;
} }
@mixin generate-color-classes($color-map) { @mixin generate-color-classes($color-map) {

View File

@ -1,10 +1,11 @@
// Greyscales // Greyscales
$gscale0: #000000; $gscale0: #000000;
$gscale04: #141414; $gscale07: #070707;
$gscale05: #151515; $gscale14: #141414;
$gscale07: #171717; $gscale15: #151515;
$gscale0B: #1B1B1B; $gscale17: #171717;
$gscale1B: #1B1B1B;
$gscale1: #111; $gscale1: #111;
$gscale2: #222; $gscale2: #222;
$gscale3: #333; $gscale3: #333;
@ -19,17 +20,19 @@ $gscaleB: #BBB;
$gscaleC: #CCC; $gscaleC: #CCC;
$gscaleD: #DDD; $gscaleD: #DDD;
$gscaleE: #EEE; $gscaleE: #EEE;
$gscaleF4: #E4E4E4; $gscaleE4: #E4E4E4;
$gscaleF5: #E5E5E5; $gscaleE5: #E5E5E5;
$gscaleF7: #E7E7E7; $gscaleE7: #E7E7E7;
$gscaleFB: #EBEBEB; $gscaleEB: #EBEBEB;
$gscaleF7: #F7F7F7;
$gscaleF: #FFFFFF; $gscaleF: #FFFFFF;
$gkscale0: #000000; $gkscale0: #000000;
$gkscale04: #141414; $gkscale07: #070707;
$gkscale05: #151515; $gkscale14: #141414;
$gkscale07: #171717; $gkscale15: #151515;
$gkscale0B: #1B1B1B; $gkscale17: #171717;
$gkscale1B: #1B1B1B;
$gkscale1: #111; $gkscale1: #111;
$gkscale2: #222; $gkscale2: #222;
$gkscale3: #333; $gkscale3: #333;
@ -44,8 +47,9 @@ $gkscaleB: #BBB;
$gkscaleC: #CCC; $gkscaleC: #CCC;
$gkscaleD: #DDD; $gkscaleD: #DDD;
$gkscaleE: #EEE; $gkscaleE: #EEE;
$gkscaleF4: #E4E4E4; $gkscaleE4: #E4E4E4;
$gkscaleF5: #E5E5E5; $gkscaleE5: #E5E5E5;
$gkscaleF7: #E7E7E7; $gkscaleE7: #E7E7E7;
$gkscaleFB: #EBEBEB; $gkscaleEB: #EBEBEB;
$gkscaleF7: #F7F7F7;
$gkscaleF: #FFFFFF; $gkscaleF: #FFFFFF;

View File

@ -1,10 +1,11 @@
// Greyscales // Greyscales
$gscale0: #FFFFFF; $gscale0: #FFFFFF;
$gscale04: #E4E4E4; $gscale07: #F7F7F7;
$gscale05: #E5E5E5; $gscale1B: #EBEBEB;
$gscale07: #E7E7E7; $gscale17: #E7E7E7;
$gscale0B: #EBEBEB; $gscale15: #E5E5E5;
$gscale14: #E4E4E4;
$gscale1: #EEE; $gscale1: #EEE;
$gscale2: #DDD; $gscale2: #DDD;
$gscale3: #CCC; $gscale3: #CCC;
@ -19,17 +20,19 @@ $gscaleB: #444;
$gscaleC: #333; $gscaleC: #333;
$gscaleD: #222; $gscaleD: #222;
$gscaleE: #111; $gscaleE: #111;
$gscaleF4: #141414; $gscaleE4: #141414;
$gscaleF5: #151515; $gscaleE5: #151515;
$gscaleF7: #171717; $gscaleE7: #171717;
$gscaleFB: #1B1B1B; $gscaleEB: #1B1B1B;
$gscaleF7: #070707;
$gscaleF: #000000; $gscaleF: #000000;
$gkscale0: #000000; $gkscale0: #000000;
$gkscale04: #141414; $gkscale07: #070707;
$gkscale05: #151515; $gkscale14: #141414;
$gkscale07: #171717; $gkscale15: #151515;
$gkscale0B: #1B1B1B; $gkscale17: #171717;
$gkscale1B: #1B1B1B;
$gkscale1: #111; $gkscale1: #111;
$gkscale2: #222; $gkscale2: #222;
$gkscale3: #333; $gkscale3: #333;
@ -44,8 +47,9 @@ $gkscaleB: #BBB;
$gkscaleC: #CCC; $gkscaleC: #CCC;
$gkscaleD: #DDD; $gkscaleD: #DDD;
$gkscaleE: #EEE; $gkscaleE: #EEE;
$gkscaleF4: #E4E4E4; $gkscaleE4: #E4E4E4;
$gkscaleF5: #E5E5E5; $gkscaleE5: #E5E5E5;
$gkscaleF7: #E7E7E7; $gkscaleE7: #E7E7E7;
$gkscaleFB: #EBEBEB; $gkscaleEB: #EBEBEB;
$gkscaleF7: #F7F7F7;
$gkscaleF: #FFFFFF; $gkscaleF: #FFFFFF;

View File

@ -48,6 +48,7 @@
"slideshow_slide_form_label_cron_scheduled_end": "End", "slideshow_slide_form_label_cron_scheduled_end": "End",
"slideshow_slide_form_label_cron_scheduled_loop": "Always in loop", "slideshow_slide_form_label_cron_scheduled_loop": "Always in loop",
"slideshow_slide_form_label_cron_scheduled_duration": "Duration", "slideshow_slide_form_label_cron_scheduled_duration": "Duration",
"slideshow_slide_form_label_cron_scheduled_inweek": "Moment in week",
"slideshow_slide_form_label_cron_scheduled_stayloop": "Follow the loop", "slideshow_slide_form_label_cron_scheduled_stayloop": "Follow the loop",
"slideshow_slide_form_label_cron_scheduled_duration_unit": "seconds", "slideshow_slide_form_label_cron_scheduled_duration_unit": "seconds",
"slideshow_slide_form_label_cron_scheduled_datetime": "Date & Time", "slideshow_slide_form_label_cron_scheduled_datetime": "Date & Time",

View File

@ -48,6 +48,7 @@
"slideshow_slide_form_label_cron_scheduled_end": "Fin", "slideshow_slide_form_label_cron_scheduled_end": "Fin",
"slideshow_slide_form_label_cron_scheduled_loop": "Siempre en bucle", "slideshow_slide_form_label_cron_scheduled_loop": "Siempre en bucle",
"slideshow_slide_form_label_cron_scheduled_duration": "Duración", "slideshow_slide_form_label_cron_scheduled_duration": "Duración",
"slideshow_slide_form_label_cron_scheduled_inweek": "Momento de la semana",
"slideshow_slide_form_label_cron_scheduled_stayloop": "Seguir el bucle", "slideshow_slide_form_label_cron_scheduled_stayloop": "Seguir el bucle",
"slideshow_slide_form_label_cron_scheduled_duration_unit": "segundos", "slideshow_slide_form_label_cron_scheduled_duration_unit": "segundos",
"slideshow_slide_form_label_cron_scheduled_datetime": "Fecha y Hora", "slideshow_slide_form_label_cron_scheduled_datetime": "Fecha y Hora",

View File

@ -48,6 +48,7 @@
"slideshow_slide_form_label_cron_scheduled_end": "Fin", "slideshow_slide_form_label_cron_scheduled_end": "Fin",
"slideshow_slide_form_label_cron_scheduled_loop": "Toujours en boucle", "slideshow_slide_form_label_cron_scheduled_loop": "Toujours en boucle",
"slideshow_slide_form_label_cron_scheduled_duration": "Durée", "slideshow_slide_form_label_cron_scheduled_duration": "Durée",
"slideshow_slide_form_label_cron_scheduled_inweek": "Moment de la semaine",
"slideshow_slide_form_label_cron_scheduled_stayloop": "Suit la boucle", "slideshow_slide_form_label_cron_scheduled_stayloop": "Suit la boucle",
"slideshow_slide_form_label_cron_scheduled_duration_unit": "secondes", "slideshow_slide_form_label_cron_scheduled_duration_unit": "secondes",
"slideshow_slide_form_label_cron_scheduled_datetime": "Date & Heure", "slideshow_slide_form_label_cron_scheduled_datetime": "Date & Heure",

View File

@ -48,6 +48,7 @@
"slideshow_slide_form_label_cron_scheduled_end": "Fine", "slideshow_slide_form_label_cron_scheduled_end": "Fine",
"slideshow_slide_form_label_cron_scheduled_loop": "Sempre in loop", "slideshow_slide_form_label_cron_scheduled_loop": "Sempre in loop",
"slideshow_slide_form_label_cron_scheduled_duration": "Durata", "slideshow_slide_form_label_cron_scheduled_duration": "Durata",
"slideshow_slide_form_label_cron_scheduled_inweek": "Momento della settimana",
"slideshow_slide_form_label_cron_scheduled_stayloop": "Seguire il ciclo", "slideshow_slide_form_label_cron_scheduled_stayloop": "Seguire il ciclo",
"slideshow_slide_form_label_cron_scheduled_duration_unit": "secondi", "slideshow_slide_form_label_cron_scheduled_duration_unit": "secondi",
"slideshow_slide_form_label_cron_scheduled_datetime": "Data e ora", "slideshow_slide_form_label_cron_scheduled_datetime": "Data e ora",

View File

@ -12,7 +12,7 @@ from src.model.enum.ContentType import ContentType
from src.exceptions.NoFallbackPlaylistException import NoFallbackPlaylistException from src.exceptions.NoFallbackPlaylistException import NoFallbackPlaylistException
from src.service.ModelStore import ModelStore from src.service.ModelStore import ModelStore
from src.interface.ObController import ObController from src.interface.ObController import ObController
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.utils import get_safe_cron_descriptor, is_cron_in_datetime_moment, is_cron_in_week_moment, is_now_after_cron_date_time_moment, is_now_after_cron_week_moment
from src.util.UtilNetwork import get_safe_remote_addr, get_network_interfaces from src.util.UtilNetwork import get_safe_remote_addr, get_network_interfaces
from src.model.enum.AnimationSpeed import animation_speed_duration from src.model.enum.AnimationSpeed import animation_speed_duration
@ -170,22 +170,28 @@ class PlayerController(ObController):
return playlists return playlists
def _check_slide_enablement(self, loop: List, notifications: List, slide: Dict) -> None: def _check_slide_enablement(self, loop: List, notifications: List, slide: Dict) -> None:
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']) is_in_datetime_moment_start = 'cron_schedule' in slide and slide['cron_schedule'] and get_safe_cron_descriptor(slide['cron_schedule']) and is_cron_in_datetime_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']) is_in_datetime_moment_end = 'cron_schedule_end' in slide and slide['cron_schedule_end'] and get_safe_cron_descriptor(slide['cron_schedule_end']) and is_cron_in_datetime_moment(slide['cron_schedule_end'])
is_in_week_moment_start = 'cron_schedule' in slide and slide['cron_schedule'] and get_safe_cron_descriptor(slide['cron_schedule']) and is_cron_in_week_moment(slide['cron_schedule'])
is_in_week_moment_end = 'cron_schedule_end' in slide and slide['cron_schedule_end'] and get_safe_cron_descriptor(slide['cron_schedule_end']) and is_cron_in_week_moment(slide['cron_schedule_end'])
if slide['is_notification']: if slide['is_notification']:
if has_valid_start_date: if is_in_datetime_moment_start:
return notifications.append(slide) return notifications.append(slide)
return logging.warn('Slide \'{}\' is a notification but start date is invalid'.format(slide['name'])) return logging.warn('Slide \'{}\' is a notification but start date is invalid'.format(slide['name']))
if has_valid_start_date: if is_in_datetime_moment_start:
start_date = get_cron_date_time(slide['cron_schedule'], object=True) if not is_now_after_cron_date_time_moment(slide['cron_schedule']):
if datetime.now() <= start_date: return
elif is_in_week_moment_start:
if not is_now_after_cron_week_moment(slide['cron_schedule']):
return return
if has_valid_end_date: if is_in_datetime_moment_end:
end_date = get_cron_date_time(slide['cron_schedule_end'], object=True) if is_now_after_cron_date_time_moment(slide['cron_schedule_end']):
if datetime.now() >= end_date: return
elif is_in_week_moment_end:
if is_now_after_cron_week_moment(slide['cron_schedule_end']):
return return
loop.append(slide) loop.append(slide)

View File

@ -11,9 +11,7 @@ from src.model.hook.StaticHookRegistration import StaticHookRegistration
from src.model.hook.FunctionalHookRegistration import FunctionalHookRegistration from src.model.hook.FunctionalHookRegistration import FunctionalHookRegistration
from src.constant.WebDirConstant import WebDirConstant from src.constant.WebDirConstant import WebDirConstant
from src.util.utils import get_safe_cron_descriptor, \ from src.util.utils import get_safe_cron_descriptor, \
is_cron_calendar_moment, \ is_cron_in_datetime_moment, \
is_cron_in_day_moment, \
is_cron_in_week_moment, \
seconds_to_hhmmss, am_i_in_docker, \ seconds_to_hhmmss, am_i_in_docker, \
truncate, merge_dicts, dictsort truncate, merge_dicts, dictsort
@ -48,8 +46,7 @@ class TemplateRenderer:
cron_descriptor=self.cron_descriptor, cron_descriptor=self.cron_descriptor,
str=str, str=str,
seconds_to_hhmmss=seconds_to_hhmmss, seconds_to_hhmmss=seconds_to_hhmmss,
is_cron_calendar_moment=is_cron_calendar_moment, is_cron_in_datetime_moment=is_cron_in_datetime_moment,
is_cron_in_day_moment=is_cron_in_day_moment,
json_dumps=json.dumps, json_dumps=json.dumps,
merge_dicts=merge_dicts, merge_dicts=merge_dicts,
dictsort=dictsort, dictsort=dictsort,

View File

@ -8,7 +8,7 @@ import unicodedata
import platform import platform
from datetime import datetime from datetime import datetime, timedelta
from typing import Optional, List, Dict from typing import Optional, List, Dict
from enum import Enum from enum import Enum
from cron_descriptor import ExpressionDescriptor from cron_descriptor import ExpressionDescriptor
@ -59,21 +59,21 @@ def camel_to_snake(camel: str) -> str:
return CAMEL_CASE_TO_SNAKE_CASE_PATTERN.sub('_', camel).lower() return CAMEL_CASE_TO_SNAKE_CASE_PATTERN.sub('_', camel).lower()
def is_cron_calendar_moment(expression: str) -> bool: def is_cron_in_datetime_moment(expression: str) -> bool:
pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\*\s+(\d+)$') pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\*\s+(\d+)$')
return bool(pattern.match(expression)) 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+)$')
return bool(pattern.match(expression))
def is_cron_in_year_moment(expression: str) -> bool: def is_cron_in_year_moment(expression: str) -> bool:
pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\*\s+\*$') pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\*\s+\*$')
return bool(pattern.match(expression)) 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: def is_cron_in_month_moment(expression: str) -> bool:
pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+\*\s+\*\s+\*$') pattern = re.compile(r'^(\d+)\s+(\d+)\s+(\d+)\s+\*\s+\*\s+\*$')
return bool(pattern.match(expression)) return bool(pattern.match(expression))
@ -84,14 +84,29 @@ def is_cron_in_day_moment(expression: str) -> bool:
return bool(pattern.match(expression)) return bool(pattern.match(expression))
def get_cron_date_time(cron_expression: str, object: bool) -> str: def is_now_after_cron_date_time_moment(expression: str) -> bool:
minutes, hours, day, month, _, year = cron_expression.split(' ') minutes, hours, day, month, _, year = expression.split(' ')
formatted_date_time = f"{year}-{month.zfill(2)}-{day.zfill(2)} {hours.zfill(2)}:{minutes.zfill(2)}" formatted_date_time = f"{year}-{month.zfill(2)}-{day.zfill(2)} {hours.zfill(2)}:{minutes.zfill(2)}"
return datetime.strptime(formatted_date_time, '%Y-%m-%d %H:%M') if object else formatted_date_time start_date = datetime.strptime(formatted_date_time, '%Y-%m-%d %H:%M')
return datetime.now() >= start_date
def is_now_after_cron_week_moment(cron_expression: str) -> bool:
minutes, hours, day, month, day_of_week = cron_expression.split(' ')
now = datetime.now()
week_start = now - timedelta(days=now.isoweekday() - 1)
for day_offset in range(7):
check_date = week_start + timedelta(days=day_offset)
if check_date.isoweekday() == int(day_of_week):
check_date = check_date.replace(hour=int(hours), minute=int(minutes), second=0, microsecond=0)
if datetime.now() >= check_date:
return True
return False
def get_safe_cron_descriptor(expression: str, use_24hour_time_format=True, locale_code: Optional[str] = None) -> str: def get_safe_cron_descriptor(expression: str, use_24hour_time_format=True, locale_code: Optional[str] = None) -> str:
if is_cron_calendar_moment(expression): if is_cron_in_datetime_moment(expression):
[minutes, hours, day, month, _, year] = expression.split(' ') [minutes, hours, day, month, _, year] = expression.split(' ')
return "{}-{}-{} at {}:{}".format( return "{}-{}-{} at {}:{}".format(
year, year,

View File

@ -15,12 +15,6 @@
<button type="button" class="btn btn-info node-player-group-player-assign" data-route="{{ url_for('fleet_node_player_group_assign_player', player_group_id=current_player_group.id, player_id='__id__') }}"> <button type="button" class="btn btn-info node-player-group-player-assign" data-route="{{ url_for('fleet_node_player_group_assign_player', player_group_id=current_player_group.id, player_id='__id__') }}">
<i class="fa fa-plus"></i> {{ l.fleet_node_player_group_assign_player }} <i class="fa fa-plus"></i> {{ l.fleet_node_player_group_assign_player }}
</button> </button>
<a href="{{ url_for('fleet_node_player_list') }}" class="btn btn-neutral" target="_blank">
<i class="fa fa-display main"></i>
<sub>
<i class="fa fa-download"></i>
</sub>
</a>
</div> </div>
</div> </div>

View File

@ -399,8 +399,8 @@
const isFullyElapsedMinute = (new Date()).getSeconds() === 0; const isFullyElapsedMinute = (new Date()).getSeconds() === 0;
const hasCron = item.cron_schedule && item.cron_schedule.length > 0; const hasCron = item.cron_schedule && item.cron_schedule.length > 0;
const hasCronEnd = item.cron_schedule_end && item.cron_schedule_end.length > 0; const hasCronEnd = item.cron_schedule_end && item.cron_schedule_end.length > 0;
const hasDateTime = hasCron && validateCronDateTime(item.cron_schedule); const hasDateTime = hasCron && isCronInDatetimeMoment(item.cron_schedule);
const hasDateTimeEnd = hasCronEnd && validateCronDateTime(item.cron_schedule_end); const hasDateTimeEnd = hasCronEnd && isCronInDatetimeMoment(item.cron_schedule_end);
if (notificationItemIndex !== i && hasDateTime) { if (notificationItemIndex !== i && hasDateTime) {
const startDate = cronToDateTimeObject(item.cron_schedule); const startDate = cronToDateTimeObject(item.cron_schedule);

View File

@ -12,16 +12,14 @@
{% block add_js %} {% block add_js %}
<script type="text/javascript"> <script type="text/javascript">
var route_slide_position = '{{ url_for('slideshow_slide_position') }}'; var route_slide_position = '{{ url_for('slideshow_slide_position') }}';
var choices_translations = { var choices_translations = {
'loop': '{{ l.slideshow_slide_form_label_cron_scheduled_loop }}', 'loop': '{{ l.slideshow_slide_form_label_cron_scheduled_loop }}',
'datetime': '{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}', 'datetime': '{{ l.slideshow_slide_form_label_cron_scheduled_datetime }}',
'cron': '{{ l.slideshow_slide_form_label_cron_scheduled_cron }}', 'cron': '{{ l.slideshow_slide_form_label_cron_scheduled_cron }}',
'stayloop': '{{ l.slideshow_slide_form_label_cron_scheduled_stayloop }}', 'stayloop': '{{ l.slideshow_slide_form_label_cron_scheduled_stayloop }}',
'duration': '{{ l.slideshow_slide_form_label_cron_scheduled_duration }}', 'duration': '{{ l.slideshow_slide_form_label_cron_scheduled_duration }}',
'inweek': 'in week', 'inweek': '{{ l.slideshow_slide_form_label_cron_scheduled_inweek }}',
}; };
var choices_map = { var choices_map = {
'normal': { 'normal': {
@ -30,14 +28,19 @@
'stayloop': choices_translations['stayloop'], 'stayloop': choices_translations['stayloop'],
'datetime': choices_translations['datetime'] 'datetime': choices_translations['datetime']
}, },
{#'inweek': {'stayloop': choices_translations['stayloop'], 'inweek': choices_translations['inweek']},#} 'inweek': {
'stayloop': choices_translations['stayloop'],
'inweek': choices_translations['inweek']
}
}, },
'notification': { 'notification': {
'datetime': { 'datetime': {
'datetime': choices_translations['datetime'], 'datetime': choices_translations['datetime'],
'duration': choices_translations['duration'] 'duration': choices_translations['duration']
}, },
'cron': {'duration': choices_translations['duration']} 'cron': {
'duration': choices_translations['duration']
}
} }
} }
var contents = {{ json_dumps(contents) | safe }} var contents = {{ json_dumps(contents) | safe }}

View File

@ -26,7 +26,7 @@
{% if slide.cron_schedule %} {% if slide.cron_schedule %}
{% set cron_desc = cron_descriptor(slide.cron_schedule) %} {% set cron_desc = cron_descriptor(slide.cron_schedule) %}
{% if cron_desc %} {% if cron_desc %}
{% if is_cron_calendar_moment(slide.cron_schedule) %} {% if is_cron_in_datetime_moment(slide.cron_schedule) %}
{% if slide.is_notification %} {% if slide.is_notification %}
🔔 <span class="prefix">{{ l.slideshow_slide_panel_td_cron_scheduled_notify }}</span> 🔔 <span class="prefix">{{ l.slideshow_slide_panel_td_cron_scheduled_notify }}</span>
<span class="cron-description">{{ cron_desc }}</span> <span class="cron-description">{{ cron_desc }}</span>
@ -48,7 +48,7 @@
{% if slide.cron_schedule_end %} {% if slide.cron_schedule_end %}
{% set cron_desc_end = cron_descriptor(slide.cron_schedule_end) %} {% set cron_desc_end = cron_descriptor(slide.cron_schedule_end) %}
{% if cron_desc_end %} {% if cron_desc_end %}
{% if is_cron_calendar_moment(slide.cron_schedule_end) %} {% if is_cron_in_datetime_moment(slide.cron_schedule_end) %}
{% if slide.is_notification %} {% if slide.is_notification %}
📆 <span class="prefix">{{ l.slideshow_slide_panel_td_cron_scheduled_date }}</span> 📆 <span class="prefix">{{ l.slideshow_slide_panel_td_cron_scheduled_date }}</span>
<span class="cron-description">{{ cron_desc_end }}</span> <span class="cron-description">{{ cron_desc_end }}</span>

View File

@ -54,6 +54,13 @@
<label for="{{ tclass }}-cron-schedule">{{ l.slideshow_slide_form_label_cron_scheduled }}</label> <label for="{{ tclass }}-cron-schedule">{{ l.slideshow_slide_form_label_cron_scheduled }}</label>
<div class="widget"> <div class="widget">
<select id="{{ tclass }}-cron-schedule-trigger" class="trigger"></select> <select id="{{ tclass }}-cron-schedule-trigger" class="trigger"></select>
<select name="" id="{{ tclass }}-cron-schedule-weekdaypicker" class="input-naked weekdaypicker">
{% for day_number in range(1,8) %}
<option value="{{ day_number }}">
{{ t('basic_day_' ~ day_number) }}
</option>
{% endfor %}
</select>
<input type="text" id="{{ tclass }}-cron-schedule-datetimepicker" class="input-naked datetimepicker" <input type="text" id="{{ tclass }}-cron-schedule-datetimepicker" class="input-naked datetimepicker"
value="" value=""
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/> placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
@ -66,6 +73,13 @@
<label for="{{ tclass }}-cron-schedule-end">{{ l.slideshow_slide_form_label_cron_scheduled_end }}</label> <label for="{{ tclass }}-cron-schedule-end">{{ l.slideshow_slide_form_label_cron_scheduled_end }}</label>
<div class="widget"> <div class="widget">
<select id="{{ tclass }}-cron-schedule-end-trigger" class="trigger"> </select> <select id="{{ tclass }}-cron-schedule-end-trigger" class="trigger"> </select>
<select name="" id="{{ tclass }}-cron-schedule-end-weekdaypicker" class="input-naked weekdaypicker">
{% for day_number in range(1,8) %}
<option value="{{ day_number }}">
{{ t('basic_day_' ~ day_number) }}
</option>
{% endfor %}
</select>
<input type="text" id="{{ tclass }}-cron-schedule-end-datetimepicker" class="input-naked datetimepicker" <input type="text" id="{{ tclass }}-cron-schedule-end-datetimepicker" class="input-naked datetimepicker"
value="" value=""
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/> placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>

View File

@ -52,6 +52,13 @@
<label for="{{ tclass }}-cron-schedule">{{ l.slideshow_slide_form_label_cron_scheduled }}</label> <label for="{{ tclass }}-cron-schedule">{{ l.slideshow_slide_form_label_cron_scheduled }}</label>
<div class="widget"> <div class="widget">
<select id="{{ tclass }}-cron-schedule-trigger" class="trigger"></select> <select id="{{ tclass }}-cron-schedule-trigger" class="trigger"></select>
<select name="" id="{{ tclass }}-cron-schedule-weekdaypicker" class="input-naked weekdaypicker">
{% for day_number in range(1,8) %}
<option value="{{ day_number }}">
{{ t('basic_day_' ~ day_number) }}
</option>
{% endfor %}
</select>
<input type="text" id="{{ tclass }}-cron-schedule-datetimepicker" class="input-naked datetimepicker" <input type="text" id="{{ tclass }}-cron-schedule-datetimepicker" class="input-naked datetimepicker"
value="" value=""
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/> placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>
@ -64,6 +71,13 @@
<label for="{{ tclass }}-cron-schedule-end">{{ l.slideshow_slide_form_label_cron_scheduled_end }}</label> <label for="{{ tclass }}-cron-schedule-end">{{ l.slideshow_slide_form_label_cron_scheduled_end }}</label>
<div class="widget"> <div class="widget">
<select id="{{ tclass }}-cron-schedule-end-trigger" class="trigger"></select> <select id="{{ tclass }}-cron-schedule-end-trigger" class="trigger"></select>
<select name="" id="{{ tclass }}-cron-schedule-end-weekdaypicker" class="input-naked weekdaypicker">
{% for day_number in range(1,8) %}
<option value="{{ day_number }}">
{{ t('basic_day_' ~ day_number) }}
</option>
{% endfor %}
</select>
<input type="text" id="{{ tclass }}-cron-schedule-end-datetimepicker" class="input-naked datetimepicker" <input type="text" id="{{ tclass }}-cron-schedule-end-datetimepicker" class="input-naked datetimepicker"
value="" value=""
placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/> placeholder="{{ l.slideshow_slide_form_label_cron_scheduled_datetime_placeholder }}"/>