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 -
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.
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.
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.
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.
+ + +