diff --git a/web/directives/channel-config.js b/web/directives/channel-config.js index db7cb5e..41a0f35 100644 --- a/web/directives/channel-config.js +++ b/web/directives/channel-config.js @@ -1465,6 +1465,10 @@ module.exports = function ($timeout, $location, dizquetv, resolutionOptions, get scope.videoRateDefault = "(Use global setting)"; scope.videoBufSizeDefault = "(Use global setting)"; + scope.randomizeBlockShuffle = false; + + scope.advancedTools = (localStorage.getItem("channel-programming-advanced-tools" ) === "show"); + let refreshScreenResolution = async () => { @@ -1653,13 +1657,21 @@ module.exports = function ($timeout, $location, dizquetv, resolutionOptions, get scope.onTimeSlotsDone = (slotsResult) => { - scope.channel.scheduleBackup = slotsResult.schedule; - readSlotsResult(slotsResult); + if (slotsResult === null) { + delete scope.channel.scheduleBackup; + } else { + scope.channel.scheduleBackup = slotsResult.schedule; + readSlotsResult(slotsResult); + } } scope.onRandomSlotsDone = (slotsResult) => { - scope.channel.randomScheduleBackup = slotsResult.schedule; - readSlotsResult(slotsResult); + if (slotsResult === null) { + delete scope.channel.randomScheduleBackup; + } else { + scope.channel.randomScheduleBackup = slotsResult.schedule; + readSlotsResult(slotsResult); + } } @@ -1672,6 +1684,73 @@ module.exports = function ($timeout, $location, dizquetv, resolutionOptions, get scope.randomSlots.startDialog(progs, scope.maxSize, scope.channel.randomScheduleBackup ); } + scope.rerollRandomSlots = () => { + let progs = commonProgramTools.removeDuplicates( scope.channel.programs ); + scope.randomSlots.startDialog( + progs, scope.maxSize, scope.channel.randomScheduleBackup, + true + ); + } + scope.hasNoRandomSlots = () => { + return ( + (typeof(scope.channel.randomScheduleBackup) === 'undefined' ) + || + (scope.channel.randomScheduleBackup == null) + ); + } + + scope.rerollTimeSlots = () => { + let progs = commonProgramTools.removeDuplicates( scope.channel.programs ); + scope.timeSlots.startDialog( + progs, scope.maxSize, scope.channel.scheduleBackup, + true + ); + } + scope.hasNoTimeSlots = () => { + return ( + (typeof(scope.channel.scheduleBackup) === 'undefined' ) + || + (scope.channel.scheduleBackup == null) + ); + } + scope.toggleAdvanced = () => { + scope.advancedTools = ! scope.advancedTools; + localStorage.setItem("channel-programming-advanced-tools" , scope.advancedTools ? "show" : "hide"); + } + scope.hasAdvancedTools = () => { + return scope.advancedTools; + } + + scope.toolWide = () => { + if ( scope.hasAdvancedTools()) { + return { + "col-xl-6": true, + "col-md-12" : true + } + } else { + return { + "col-xl-12": true, + "col-lg-12" : true + } + } + } + + scope.toolThin = () => { + if ( scope.hasAdvancedTools()) { + return { + "col-xl-3": true, + "col-lg-6" : true + } + } else { + return { + "col-xl-6": true, + "col-lg-6" : true + } + } + } + + + scope.logoOnChange = (event) => { const formData = new FormData(); formData.append('image', event.target.files[0]); diff --git a/web/directives/random-slots-schedule-editor.js b/web/directives/random-slots-schedule-editor.js index 0f88017..24fbc98 100644 --- a/web/directives/random-slots-schedule-editor.js +++ b/web/directives/random-slots-schedule-editor.js @@ -177,8 +177,22 @@ module.exports = function ($timeout, dizquetv, getShowData) { { id: "shuffle", description: "Shuffle" }, ]; - let doIt = async() => { + let doWait = (millis) => { + return new Promise( (resolve) => { + $timeout( resolve, millis ); + } ); + } + + let doIt = async(fromInstant) => { + let t0 = new Date().getTime(); let res = await dizquetv.calculateRandomSlots(scope.programs, scope.schedule ); + let t1 = new Date().getTime(); + + let w = Math.max(0, 250 - (t1 - t0) ); + if (fromInstant && (w > 0) ) { + await doWait(w); + } + for (let i = 0; i < scope.schedule.slots.length; i++) { delete scope.schedule.slots[i].weightPercentage; } @@ -189,7 +203,7 @@ module.exports = function ($timeout, dizquetv, getShowData) { - let startDialog = (programs, limit, backup) => { + let startDialog = (programs, limit, backup, instant) => { scope.limit = limit; scope.programs = programs; @@ -213,11 +227,15 @@ module.exports = function ($timeout, dizquetv, getShowData) { id: "flex.", description: "Flex", } ); - if (typeof(backup) !== 'undefined') { + scope.hadBackup = (typeof(backup) !== 'undefined'); + if (scope.hadBackup) { loadBackup(backup); } scope.visible = true; + if (instant) { + scope.finished(false, true); + } } @@ -225,13 +243,18 @@ module.exports = function ($timeout, dizquetv, getShowData) { startDialog: startDialog, } ); - scope.finished = async (cancel) => { + scope.finished = async (cancel, fromInstant) => { scope.error = null; if (!cancel) { + if ( scope.schedule.slots.length === 0) { + scope.onDone(null); + scope.visible = false; + return; + } try { scope.loading = true; $timeout(); - scope.onDone( await doIt() ); + scope.onDone( await doIt(fromInstant) ); scope.visible = false; } catch(err) { console.error("Unable to generate channel lineup", err); @@ -267,6 +290,20 @@ module.exports = function ($timeout, dizquetv, getShowData) { return false; } + scope.hideCreateLineup = () => { + return ( + scope.disableCreateLineup() + && (scope.schedule.slots.length == 0) + && scope.hadBackup + ); + } + + scope.showResetSlots = () => { + return scope.hideCreateLineup(); + } + + + scope.canShowSlot = (slot) => { return (slot.showId != 'flex.') && !(slot.showId.startsWith('redirect.')); } diff --git a/web/directives/time-slots-schedule-editor.js b/web/directives/time-slots-schedule-editor.js index 45b2522..90375f7 100644 --- a/web/directives/time-slots-schedule-editor.js +++ b/web/directives/time-slots-schedule-editor.js @@ -203,9 +203,23 @@ module.exports = function ($timeout, dizquetv, getShowData ) { { id: "shuffle", description: "Shuffle" }, ]; - let doIt = async() => { + let doWait = (millis) => { + return new Promise( (resolve) => { + $timeout( resolve, millis ); + } ); + } + + let doIt = async(fromInstant) => { scope.schedule.timeZoneOffset = (new Date()).getTimezoneOffset(); + let t0 = new Date().getTime(); let res = await dizquetv.calculateTimeSlots(scope.programs, scope.schedule ); + let t1 = new Date().getTime(); + + let w = Math.max(0, 250 - (t1 - t0) ); + if (fromInstant && (w > 0) ) { + await doWait(w); + } + res.schedule = scope.schedule; delete res.schedule.fake; return res; @@ -214,7 +228,7 @@ module.exports = function ($timeout, dizquetv, getShowData ) { - let startDialog = (programs, limit, backup) => { + let startDialog = (programs, limit, backup, instant) => { scope.limit = limit; scope.programs = programs; @@ -238,11 +252,15 @@ module.exports = function ($timeout, dizquetv, getShowData ) { id: "flex.", description: "Flex", } ); - if (typeof(backup) !== 'undefined') { + scope.hadBackup = (typeof(backup) !== 'undefined'); + if (scope.hadBackup) { loadBackup(backup); } scope.visible = true; + if (instant) { + scope.finished(false, true); + } } @@ -250,13 +268,19 @@ module.exports = function ($timeout, dizquetv, getShowData ) { startDialog: startDialog, } ); - scope.finished = async (cancel) => { + scope.finished = async (cancel, fromInstant) => { scope.error = null; if (!cancel) { + if ( scope.schedule.slots.length === 0) { + scope.onDone(null); + scope.visible = false; + return; + } + try { scope.loading = true; $timeout(); - scope.onDone( await doIt() ); + scope.onDone( await doIt(fromInstant) ); scope.visible = false; } catch(err) { console.error("Unable to generate channel lineup", err); @@ -292,6 +316,18 @@ module.exports = function ($timeout, dizquetv, getShowData ) { return false; } + scope.hideCreateLineup = () => { + return ( + scope.disableCreateLineup() + && (scope.schedule.slots.length == 0) + && scope.hadBackup + ); + } + + scope.showResetSlots = () => { + return scope.hideCreateLineup(); + } + scope.canShowSlot = (slot) => { return (slot.showId != 'flex.') && !(slot.showId.startsWith('redirect.')); } diff --git a/web/public/templates/channel-config.html b/web/public/templates/channel-config.html index da9a908..97dcddb 100644 --- a/web/public/templates/channel-config.html +++ b/web/public/templates/channel-config.html @@ -197,23 +197,29 @@ There are no programs in the channel, use the button to add programs from your media library or use the Tools to add Flex time or a Channel Redirect -
-
+
-
- - -   -
+
-
+
-
+
-
+
@@ -255,7 +261,7 @@

Makes multiple copies of the schedule and plays them in sequence. Normally this isn't necessary, because dizqueTV will always play the schedule back from the beginning when it finishes. But creating replicas is a useful intermediary step sometimes before applying other transformations. Note that because very large channels can be problematic, the number of replicas will be limited to avoid creating really large channels.

-
+
@@ -267,7 +273,7 @@

Like "Replicate", it will make multiple copies of the programming. In addition it will shuffle the programs, but it will make sure not to have too small a distance between two identical programs.

-
+
-
+
-
+
-
+
-
+
Adds Flex breaks after each TV episode or movie to ensure that the program starts at one of the allowed minute marks. For example, you can use this to ensure that all your programs start at either XX:00 times or XX:30 times. Removes any existing Flex periods before adding the new ones. This button might be disabled if the channel is already too large.

-
+
Divides the programming in blocks of 6, 8 or 12 hours then repeats each of the blocks the specified number of times. For example, you can make a channel that plays exactly the same channels in the morning and in the afternoon. This button might be disabled if the channel is already too large.

-
+
-
+
@@ -425,7 +431,7 @@

Will redirect to another channel while between the selected hours.

-
+
-
-
+
+
+
+ +
+
-

This allows to schedul specific shows to run at specific time slots of the day or a week. It's recommended you first populate the channel with the episodes from the shows you want to play and/or other content like movies and redirects.

+

This allows to schedule specific shows to run at specific time slots of the day or a week. It's recommended you first populate the channel with the episodes from the shows you want to play and/or other content like movies and redirects.

-
-
+
+ + +
+
+ +
+
-

This is similar to Time Slots, but instead of time sections, you pick a probability to play each tv show and the length of the block.

+

This is similar to Time Slots, but instead of time sections, you pick a probability to play each tv show and the length of the block. Once a channel has been configured with random slots, the reload button can re-evaluate them again, with the saved settings.

@@ -493,7 +523,7 @@

Removes any Flex periods from the schedule.

-
+

Wipes out the schedule so that you can start over.

+ + +
+
+ + +
+ + +
+

Use this button to show or hide a bunch of additional tools that might be useful.

+ + +
diff --git a/web/public/templates/random-slots-schedule-editor.html b/web/public/templates/random-slots-schedule-editor.html index 3cb0eff..80fa6d0 100644 --- a/web/public/templates/random-slots-schedule-editor.html +++ b/web/public/templates/random-slots-schedule-editor.html @@ -177,7 +177,8 @@
diff --git a/web/public/templates/time-slots-schedule-editor.html b/web/public/templates/time-slots-schedule-editor.html index 2f28bd0..ec8a416 100644 --- a/web/public/templates/time-slots-schedule-editor.html +++ b/web/public/templates/time-slots-schedule-editor.html @@ -148,7 +148,8 @@