mirror of
https://github.com/dkmstr/openuds.git
synced 2025-01-10 01:17:59 +03:00
Fixed calendar rules. Almost finished :-)
This commit is contained in:
parent
522d493557
commit
037a4b523b
@ -36,6 +36,7 @@ from django.utils.translation import ugettext as _
|
|||||||
|
|
||||||
|
|
||||||
from uds.models.CalendarRule import freqs, CalendarRule
|
from uds.models.CalendarRule import freqs, CalendarRule
|
||||||
|
from uds.models.Util import getSqlDatetime
|
||||||
|
|
||||||
from uds.core.util import log
|
from uds.core.util import log
|
||||||
from uds.core.util import permissions
|
from uds.core.util import permissions
|
||||||
@ -47,6 +48,7 @@ from django.db import IntegrityError
|
|||||||
|
|
||||||
import six
|
import six
|
||||||
import logging
|
import logging
|
||||||
|
import datetime
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -95,7 +97,7 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
|
|||||||
return [
|
return [
|
||||||
{'name': {'title': _('Rule name')}},
|
{'name': {'title': _('Rule name')}},
|
||||||
{'start': {'title': _('Start'), 'type': 'datetime'}},
|
{'start': {'title': _('Start'), 'type': 'datetime'}},
|
||||||
{'end': {'title': _('End'), 'type': 'datetime'}},
|
{'end': {'title': _('End'), 'type': 'date'}},
|
||||||
{'frequency': {'title': _('Frequency'), 'type': 'dict', 'dict': dict((v[0], six.text_type(v[1])) for v in freqs) }},
|
{'frequency': {'title': _('Frequency'), 'type': 'dict', 'dict': dict((v[0], six.text_type(v[1])) for v in freqs) }},
|
||||||
{'interval': {'title': _('Interval'), 'type': 'callback'}},
|
{'interval': {'title': _('Interval'), 'type': 'callback'}},
|
||||||
{'duration': {'title': _('Duration'), 'type': 'callback'}},
|
{'duration': {'title': _('Duration'), 'type': 'callback'}},
|
||||||
@ -106,7 +108,12 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
|
|||||||
# Extract item db fields
|
# Extract item db fields
|
||||||
# We need this fields for all
|
# We need this fields for all
|
||||||
logger.debug('Saving rule {0} / {1}'.format(parent, item))
|
logger.debug('Saving rule {0} / {1}'.format(parent, item))
|
||||||
fields = self.readFieldsFromParams(['name', 'comments', 'data_type'])
|
fields = self.readFieldsFromParams(['name', 'comments', 'frequency', 'start', 'end', 'interval', 'duration'])
|
||||||
|
# Convert timestamps to datetimes
|
||||||
|
fields['start'] = datetime.datetime.fromtimestamp(fields['start'])
|
||||||
|
if fields['end'] != None:
|
||||||
|
fields['end'] = datetime.datetime.fromtimestamp(fields['end'])
|
||||||
|
|
||||||
calRule = None
|
calRule = None
|
||||||
try:
|
try:
|
||||||
if item is None: # Create new
|
if item is None: # Create new
|
||||||
@ -126,14 +133,14 @@ class CalendarRules(DetailHandler): # pylint: disable=too-many-public-methods
|
|||||||
return self.getItems(parent, calRule.uuid)
|
return self.getItems(parent, calRule.uuid)
|
||||||
|
|
||||||
def deleteItem(self, parent, item):
|
def deleteItem(self, parent, item):
|
||||||
|
logger.debug('Deleting rule {} from {}'.format(item, parent))
|
||||||
try:
|
try:
|
||||||
calRule = parent.rules.get(uuid=processUuid(item))
|
calRule = parent.rules.get(uuid=processUuid(item))
|
||||||
|
calRule.calendar.modified = getSqlDatetime()
|
||||||
if calRule.deployedServices.count() != 0:
|
calRule.calendar.save()
|
||||||
raise RequestError('Item has associated deployed rules')
|
|
||||||
|
|
||||||
calRule.delete()
|
calRule.delete()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
logger.exception('Exception')
|
||||||
self.invalidItemException()
|
self.invalidItemException()
|
||||||
|
|
||||||
return 'deleted'
|
return 'deleted'
|
||||||
|
@ -94,7 +94,9 @@ class ContentProcessor(object):
|
|||||||
'''
|
'''
|
||||||
Helper for renderers. Alters some types so they can be serialized correctly (as we want them to be)
|
Helper for renderers. Alters some types so they can be serialized correctly (as we want them to be)
|
||||||
'''
|
'''
|
||||||
if isinstance(obj, (bool, int, float, six.text_type)):
|
if obj is None:
|
||||||
|
return None
|
||||||
|
elif isinstance(obj, (bool, int, float, six.text_type)):
|
||||||
return obj
|
return obj
|
||||||
elif isinstance(obj, long):
|
elif isinstance(obj, long):
|
||||||
return int(obj)
|
return int(obj)
|
||||||
@ -108,7 +110,7 @@ class ContentProcessor(object):
|
|||||||
for v in obj:
|
for v in obj:
|
||||||
res.append(ContentProcessor.procesForRender(v))
|
res.append(ContentProcessor.procesForRender(v))
|
||||||
return res
|
return res
|
||||||
elif isinstance(obj, datetime.datetime):
|
elif isinstance(obj, (datetime.datetime, datetime.date)):
|
||||||
return int(time.mktime(obj.timetuple()))
|
return int(time.mktime(obj.timetuple()))
|
||||||
elif isinstance(obj, six.binary_type):
|
elif isinstance(obj, six.binary_type):
|
||||||
return obj.decode('utf-8')
|
return obj.decode('utf-8')
|
||||||
|
@ -42,7 +42,7 @@ import datetime
|
|||||||
import bitarray
|
import bitarray
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
__updated__ = '2015-09-09'
|
__updated__ = '2015-09-17'
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -51,6 +51,7 @@ class CalendarChecker(object):
|
|||||||
calendar = None
|
calendar = None
|
||||||
inverse = False
|
inverse = False
|
||||||
cache = None
|
cache = None
|
||||||
|
updates = 0
|
||||||
|
|
||||||
def __init__(self, calendar, inverse=False):
|
def __init__(self, calendar, inverse=False):
|
||||||
self.calendar = calendar
|
self.calendar = calendar
|
||||||
@ -60,25 +61,36 @@ class CalendarChecker(object):
|
|||||||
self.data_time = None
|
self.data_time = None
|
||||||
|
|
||||||
def _updateData(self, dtime):
|
def _updateData(self, dtime):
|
||||||
|
self.updates += 1
|
||||||
self.calendar_modified = self.calendar.modified
|
self.calendar_modified = self.calendar.modified
|
||||||
self.data_time = dtime.date()
|
self.data_time = dtime.date()
|
||||||
self.data = bitarray.bitarray(60 * 24) # Granurality is minute
|
self.data = bitarray.bitarray(60 * 24) # Granurality is minute
|
||||||
self.data.setall(False)
|
self.data.setall(False)
|
||||||
start = datetime.datetime.combine(datetime.date.today(), datetime.datetime.min.time())
|
|
||||||
end = datetime.datetime.combine(datetime.date.today(), datetime.datetime.max.time())
|
start = datetime.datetime.combine(self.data_time, datetime.datetime.min.time())
|
||||||
|
end = datetime.datetime.combine(self.data_time, datetime.datetime.max.time())
|
||||||
|
|
||||||
for rule in self.calendar.rules.all():
|
for rule in self.calendar.rules.all():
|
||||||
rr = rule.as_rrule()
|
rr = rule.as_rrule()
|
||||||
|
|
||||||
|
r_end = datetime.datetime.combine(rule.end, datetime.datetime.min.time()) if rule.end is not None else None
|
||||||
|
|
||||||
duration = rule.duration
|
duration = rule.duration
|
||||||
_start = start if start > rule.start else rule.start - datetime.timedelta(seconds=1)
|
# Relative start, rrule can "spawn" the days, so we get the start at least the duration of rule to see if it "matches"
|
||||||
_end = end if rule.end is None or end < rule.end else rule.end
|
_start = (start if start > rule.start else rule.start) - datetime.timedelta(minutes=rule.freqInMinutes())
|
||||||
print(_start, end)
|
_end = end if r_end is None or end < r_end else r_end
|
||||||
for val in rr.between(_start, _end, inc=True):
|
for val in rr.between(_start, _end, inc=True):
|
||||||
pos = val.hour * 60 + val.minute
|
if val.date() != self.data_time:
|
||||||
posdur = pos + duration
|
diff = int((start - val).total_seconds() / 60)
|
||||||
|
pos = 0
|
||||||
|
posdur = duration - diff
|
||||||
|
if posdur <= 0:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
pos = val.hour * 60 + val.minute
|
||||||
|
posdur = pos + duration
|
||||||
if posdur >= 60 * 24:
|
if posdur >= 60 * 24:
|
||||||
posdur = 60 * 24 - 1
|
posdur = 60 * 24 - 1
|
||||||
print(pos, posdur)
|
|
||||||
self.data[pos:posdur] = True
|
self.data[pos:posdur] = True
|
||||||
|
|
||||||
# Now self.data can be accessed as an array of booleans, and if
|
# Now self.data can be accessed as an array of booleans, and if
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
__updated__ = '2015-09-09'
|
__updated__ = '2015-09-17'
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
from django.utils.encoding import python_2_unicode_compatible
|
||||||
@ -42,7 +42,9 @@ from dateutil import rrule as rules
|
|||||||
|
|
||||||
from .UUIDModel import UUIDModel
|
from .UUIDModel import UUIDModel
|
||||||
from .Calendar import Calendar
|
from .Calendar import Calendar
|
||||||
|
from .Util import getSqlDatetime
|
||||||
|
|
||||||
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -63,6 +65,13 @@ frq_to_rrl = {
|
|||||||
'DAILY': rules.DAILY,
|
'DAILY': rules.DAILY,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frq_to_mins = {
|
||||||
|
'YEARLY': 366 * 24 * 60,
|
||||||
|
'MONTHLY': 31 * 24 * 60,
|
||||||
|
'WEEKLY': 7 * 24 * 60,
|
||||||
|
'DAILY': 24 * 60,
|
||||||
|
}
|
||||||
|
|
||||||
weekdays = [rules.SU, rules.MO, rules.TU, rules.WE, rules.TH, rules.FR, rules.SA]
|
weekdays = [rules.SU, rules.MO, rules.TU, rules.WE, rules.TH, rules.FR, rules.SA]
|
||||||
|
|
||||||
|
|
||||||
@ -98,6 +107,19 @@ class CalendarRule(UUIDModel):
|
|||||||
else:
|
else:
|
||||||
return rules.rrule(frq_to_rrl[self.frequency], interval=self.interval, dtstart=self.start)
|
return rules.rrule(frq_to_rrl[self.frequency], interval=self.interval, dtstart=self.start)
|
||||||
|
|
||||||
|
def freqInMinutes(self):
|
||||||
|
if self.frequency != WEEKDAYS:
|
||||||
|
return frq_to_mins.get(self.frequency, 0) * self.interval
|
||||||
|
else:
|
||||||
|
return 7 * 24 * 60
|
||||||
|
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
logger.debug('Saving...')
|
||||||
|
self.calendar.modified = getSqlDatetime()
|
||||||
|
self.calendar.save()
|
||||||
|
|
||||||
|
return UUIDModel.save(self, *args, **kwargs)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'Rule {0}: {1}-{2}, {3}, Interval: {4}, duration: {5}'.format(self.name, self.start, self.end, self.frequency, self.interval, self.duration)
|
return 'Rule {0}: {1}-{2}, {3}, Interval: {4}, duration: {5}'.format(self.name, self.start, self.end, self.frequency, self.interval, self.duration)
|
||||||
|
@ -1,12 +1,33 @@
|
|||||||
# jshint strict: true
|
# jshint strict: true
|
||||||
((api, $, undefined_) ->
|
((api, $, undefined_) ->
|
||||||
"use strict"
|
"use strict"
|
||||||
api.tools = base64: (s) ->
|
api.tools =
|
||||||
window.btoa unescape(encodeURIComponent(s))
|
base64: (s) ->
|
||||||
|
window.btoa unescape(encodeURIComponent(s))
|
||||||
|
input2timeStamp: (inputDate, inputTime) ->
|
||||||
|
# Just parses date & time in two separate inputs
|
||||||
|
# inputTime is in format hours:minutes
|
||||||
|
if inputDate is null or inputDate is undefined
|
||||||
|
v = new Date(0)
|
||||||
|
else
|
||||||
|
tmp = inputDate.split('-')
|
||||||
|
v = new Date(tmp[0], parseInt(tmp[1])-1, tmp[2])
|
||||||
|
|
||||||
|
if inputTime != null and inputTime != undefined
|
||||||
|
tmp = inputTime.split(':')
|
||||||
|
if v.getTime() != 0
|
||||||
|
v.setHours(tmp[0])
|
||||||
|
v.setMinutes(tmp[1])
|
||||||
|
else
|
||||||
|
return parseInt(tmp[0])*3600 + parseInt(tmp[1]) * 60
|
||||||
|
|
||||||
|
return v.getTime() / 1000
|
||||||
|
|
||||||
|
|
||||||
return
|
return
|
||||||
) window.api = window.api or {}, jQuery
|
) window.api = window.api or {}, jQuery
|
||||||
|
|
||||||
|
|
||||||
# Insert strftime into tools
|
# Insert strftime into tools
|
||||||
#
|
#
|
||||||
#strftime
|
#strftime
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
gui.calendars = new GuiElement(api.calendars, "imgal")
|
gui.calendars = new GuiElement(api.calendars, "calendars")
|
||||||
gui.calendars.link = ->
|
gui.calendars.link = ->
|
||||||
"use strict"
|
"use strict"
|
||||||
|
|
||||||
@ -45,17 +45,36 @@ gui.calendars.link = ->
|
|||||||
return Math.floor(data/60) + ":" + ("00" + data%60).slice(-2) + " " + gettext("hours")
|
return Math.floor(data/60) + ":" + ("00" + data%60).slice(-2) + " " + gettext("hours")
|
||||||
return fld
|
return fld
|
||||||
|
|
||||||
newEditFnc = (forEdit) ->
|
newEditFnc = (rules, forEdit) ->
|
||||||
realFnc = (value, refreshFnc) ->
|
days = (w.substr(0, 3) for w in weekDays)
|
||||||
sortFnc = (a, b) ->
|
sortFnc = (a, b) ->
|
||||||
return 1 if a.value > b.value
|
return 1 if a.value > b.value
|
||||||
return -1 if a.value < b.value
|
return -1 if a.value < b.value
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
fillDateTime = (idDate, stamp) ->
|
||||||
|
if stamp is null
|
||||||
|
return
|
||||||
|
date = new Date(stamp * 1000)
|
||||||
|
$(idDate).val(api.tools.strftime('%Y-%m-%d', date))
|
||||||
|
$(idDate + "-time").val(date.toTimeString().split(':')[0..1].join(':'))
|
||||||
|
|
||||||
|
getDateTime = (idDate, withoutTime) ->
|
||||||
|
date = $(idDate).val()
|
||||||
|
if date == '' or date == null
|
||||||
|
return null
|
||||||
|
|
||||||
|
if withoutTime is undefined
|
||||||
|
time = $(idDate + '-time').val()
|
||||||
|
return api.tools.input2timeStamp(date, time)
|
||||||
|
else
|
||||||
|
return apit.tools.input2timeStamp(date)
|
||||||
|
|
||||||
|
realFnc = (value, refreshFnc) ->
|
||||||
api.templates.get "calendar_rule", (tmpl) ->
|
api.templates.get "calendar_rule", (tmpl) ->
|
||||||
content = api.templates.evaluate(tmpl,
|
content = api.templates.evaluate(tmpl,
|
||||||
freqs: ( {id: key, value: val[2]} for own key, val of freqDct)
|
freqs: ( {id: key, value: val[2]} for own key, val of freqDct)
|
||||||
days: (w.substr(0, 3) for w in weekDays)
|
days: days
|
||||||
)
|
)
|
||||||
modalId = gui.launchModal((if value is null then gettext("New rule") else gettext("Edit rule") + ' <b>' + value.name + '</b>' ), content,
|
modalId = gui.launchModal((if value is null then gettext("New rule") else gettext("Edit rule") + ' <b>' + value.name + '</b>' ), content,
|
||||||
actionButton: "<button type=\"button\" class=\"btn btn-success button-accept\">" + gettext("Save") + "</button>"
|
actionButton: "<button type=\"button\" class=\"btn btn-success button-accept\">" + gettext("Save") + "</button>"
|
||||||
@ -63,15 +82,43 @@ gui.calendars.link = ->
|
|||||||
$('#div-interval').show()
|
$('#div-interval').show()
|
||||||
$('#div-weekdays').hide()
|
$('#div-weekdays').hide()
|
||||||
|
|
||||||
# Fill in fields if needed
|
#
|
||||||
|
# Fill in fields if needed (editing)
|
||||||
|
#
|
||||||
if value != null
|
if value != null
|
||||||
alert('ok')
|
gui.doLog "Value: ", value
|
||||||
|
$('#id-rule-name').val(value.name)
|
||||||
|
$('#id-rule-comments').val(value.comments)
|
||||||
|
fillDateTime '#id-rule-start', value.start
|
||||||
|
fillDateTime '#id-rule-end', value.end
|
||||||
|
$('#id-rule-duration').val(Math.floor(value.duration/60) + ':' + ("00" + value.duration%60).slice(-2))
|
||||||
|
|
||||||
|
# If weekdays, set checkboxes
|
||||||
|
$('#id-rule-freq').val(value.frequency)
|
||||||
|
if value.frequency == 'WEEKDAYS'
|
||||||
|
$('#div-interval').hide()
|
||||||
|
$('#div-weekdays').show()
|
||||||
|
|
||||||
|
gui.doLog "Interval", value.interval
|
||||||
|
n = value.interval
|
||||||
|
# Set up Weekdays
|
||||||
|
for i in [0..6]
|
||||||
|
if n & 1 != 0
|
||||||
|
chk = $('#rule-wd-'+days[i])
|
||||||
|
chk.prop('checked', true)
|
||||||
|
chk.parent().addClass('active')
|
||||||
|
n >>= 1
|
||||||
|
else
|
||||||
|
$('#id-rule-interval-num').val(value.interval)
|
||||||
|
|
||||||
|
#
|
||||||
# apply styles
|
# apply styles
|
||||||
|
#
|
||||||
gui.tools.applyCustoms modalId
|
gui.tools.applyCustoms modalId
|
||||||
|
|
||||||
|
#
|
||||||
# Event handlers
|
# Event handlers
|
||||||
|
#
|
||||||
|
|
||||||
# Change frequency
|
# Change frequency
|
||||||
$('#id-rule-freq').on 'change', () ->
|
$('#id-rule-freq').on 'change', () ->
|
||||||
@ -96,18 +143,39 @@ gui.calendars.link = ->
|
|||||||
return
|
return
|
||||||
|
|
||||||
$(modalId + ' :input[type=checkbox]').each ()->
|
$(modalId + ' :input[type=checkbox]').each ()->
|
||||||
gui.doLog this.name, $(this).prop('checked')
|
|
||||||
values[this.name] = $(this).prop('checked')
|
values[this.name] = $(this).prop('checked')
|
||||||
return
|
return
|
||||||
|
|
||||||
value.name = values.rule_name
|
data =
|
||||||
|
name: values.rule_name
|
||||||
|
comments: values.rule_comments
|
||||||
|
frequency: values.rule_frequency
|
||||||
|
start: getDateTime('#id-rule-start')
|
||||||
|
end: getDateTime('#id-rule-end')
|
||||||
|
duration: api.tools.input2timeStamp(null, values.rule_duration)/60
|
||||||
|
|
||||||
if $('#id-rule-freq').val() == 'WEEKDAYS'
|
if $('#id-rule-freq').val() == 'WEEKDAYS'
|
||||||
value.interval = -1
|
n = 1
|
||||||
|
val = 0
|
||||||
|
for i in [0..6]
|
||||||
|
if values['wd_'+days[i]] is true
|
||||||
|
val += n
|
||||||
|
n <<= 1
|
||||||
|
data.interval = val
|
||||||
else
|
else
|
||||||
value.interval = values.rule_interval
|
data.interval = values.rule_interval
|
||||||
|
|
||||||
gui.doLog value, values
|
closeAndRefresh = () ->
|
||||||
|
$(modalId).modal "hide"
|
||||||
|
refreshFnc()
|
||||||
|
|
||||||
|
if value is null
|
||||||
|
rules.rest.create data, closeAndRefresh, gui.failRequestModalFnc(gettext('Error creating rule'), true)
|
||||||
|
else
|
||||||
|
data.id = value.id
|
||||||
|
rules.rest.save data, closeAndRefresh, gui.failRequestModalFnc(gettext('Error saving rule'), true)
|
||||||
|
|
||||||
|
gui.doLog value, data
|
||||||
|
|
||||||
|
|
||||||
if forEdit is true
|
if forEdit is true
|
||||||
@ -148,8 +216,9 @@ gui.calendars.link = ->
|
|||||||
onLoad: (k) ->
|
onLoad: (k) ->
|
||||||
# gui.tools.unblockUI()
|
# gui.tools.unblockUI()
|
||||||
return # null return
|
return # null return
|
||||||
onNew: newEditFnc false
|
onNew: newEditFnc rules, false
|
||||||
onEdit: newEditFnc true
|
onEdit: newEditFnc rules, true
|
||||||
|
onDelete: gui.methods.del(rules, gettext("Delete rule"), gettext("Rule deletion error"))
|
||||||
|
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
@ -91,17 +91,18 @@
|
|||||||
# timepicker
|
# timepicker
|
||||||
$.each $(selector + " input[type=time]:not([readonly])"), (index, tspn) ->
|
$.each $(selector + " input[type=time]:not([readonly])"), (index, tspn) ->
|
||||||
$tspn = $(tspn)
|
$tspn = $(tspn)
|
||||||
$tspn.timepicker
|
opts =
|
||||||
showMeridian: false
|
showMeridian: false
|
||||||
defaultTime: false
|
defaultTime: false
|
||||||
|
|
||||||
|
$tspn.timepicker opts
|
||||||
|
|
||||||
# Activate "cool" selects
|
# Activate "cool" selects
|
||||||
$.each $(selector + " .selectpicker"), (index, tspn) ->
|
$.each $(selector + " .selectpicker"), (index, tspn) ->
|
||||||
$tspn = $(tspn)
|
$tspn = $(tspn)
|
||||||
length = $tspn.children('option').length
|
length = $tspn.children('option').length
|
||||||
if length >= 6
|
if length >= 6
|
||||||
$tspn.attr("data-live-search", "true")
|
$tspn.attr("data-live-search", "true")
|
||||||
gui.doLog "Length: " + length
|
|
||||||
$tspn.selectpicker()
|
$tspn.selectpicker()
|
||||||
|
|
||||||
# Activate Touchspinner
|
# Activate Touchspinner
|
||||||
@ -143,7 +144,7 @@
|
|||||||
# Datetime renderer (with specified format)
|
# Datetime renderer (with specified format)
|
||||||
renderDate: (format) ->
|
renderDate: (format) ->
|
||||||
(data, type, full) ->
|
(data, type, full) ->
|
||||||
if data == "None"
|
if data == "None" or data is null
|
||||||
data = 7226578800
|
data = 7226578800
|
||||||
val = gettext('Never')
|
val = gettext('Never')
|
||||||
else
|
else
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
if gui.debug
|
if gui.debug
|
||||||
try
|
try
|
||||||
console.log args
|
console.log args
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="input-group bootstrap-timepicker timepicker">
|
<div class="input-group bootstrap-timepicker timepicker">
|
||||||
<input type="time" value="00:00" name="rule_start_time" class="form-control input-small">
|
<input type="time" value="00:00" id="id-rule-start-time" name="rule_start_time" class="form-control input-small">
|
||||||
<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span>
|
<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -37,18 +37,8 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="id-rule-end" class="col-sm-3 control-label" data-toggle="tooltip" data-title="{% trans 'End date'%}">{% trans 'End' %}</label>
|
<label for="id-rule-end" class="col-sm-3 control-label" data-toggle="tooltip" data-title="{% trans 'End date'%}">{% trans 'End' %}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="row">
|
<div class="input-group date">
|
||||||
<div class="col-sm-6">
|
<input type="date" required placeholder="ending date for rule" id="id-rule-end" name="rule_end_date" clear="true" class="form-control modal_field_data " aria-required="true"><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span>
|
||||||
<div class="input-group date">
|
|
||||||
<input type="date" required placeholder="ending date for rule" id="id-rule-start" name="rule_end_date" class="form-control modal_field_data " aria-required="true"><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="input-group bootstrap-timepicker timepicker">
|
|
||||||
<input type="time" value="00:00" name="rule_end_time" class="form-control input-small">
|
|
||||||
<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -67,7 +57,7 @@
|
|||||||
<div class="form-group" id="div-interval">
|
<div class="form-group" id="div-interval">
|
||||||
<label for="id-rule-interval-num" class="col-sm-3 control-label" data-toggle="tooltip" data-title="{% trans 'Repeat interval for this rule in frequency units'%}">{% trans 'Interval' %}</label>
|
<label for="id-rule-interval-num" class="col-sm-3 control-label" data-toggle="tooltip" data-title="{% trans 'Repeat interval for this rule in frequency units'%}">{% trans 'Interval' %}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="id-rule-interval-num" name="rule_interval" type="numeric" class="form-control" placeholder="{% trans 'Repeat interval for rule' %}" autofocus required>
|
<input id="id-rule-interval-num" name="rule_interval" type="numeric" data-minval="0" class="form-control" placeholder="{% trans 'Repeat interval for rule' %}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -77,7 +67,7 @@
|
|||||||
<div class="btn-group" data-toggle="buttons">
|
<div class="btn-group" data-toggle="buttons">
|
||||||
{% verbatim %}{{#each days}}
|
{% verbatim %}{{#each days}}
|
||||||
<label class="btn btn-default">
|
<label class="btn btn-default">
|
||||||
<input type="checkbox" name="wd_{{ this }}" basic="true" autocomplete="off">{{ this }}
|
<input type="checkbox" name="wd_{{ this }}" id="rule-wd-{{ this }}" basic="true" autocomplete="off">{{ this }}
|
||||||
</label>
|
</label>
|
||||||
{{/each}}{% endverbatim %}
|
{{/each}}{% endverbatim %}
|
||||||
</div>
|
</div>
|
||||||
@ -85,9 +75,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="id-rule-duration" class="col-sm-3 control-label" data-toggle="tooltip" data-title="{% trans 'Duration for this rule'%}">{% trans 'Duration' %}</label>
|
<label for="id-rule-duration" class="col-sm-3 control-label" data-toggle="tooltip" data-title="{% trans 'Duration for this rule in hours:minutes (Max duration is 99 hours 59 minutes)'%}">{% trans 'Duration' %}</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="id-rule-duration" name="duration" type="numberic" class="form-control" placeholder="{% trans 'Duration for rule' %}" autofocus required>
|
<div class="input-group bootstrap-timepicker timepicker">
|
||||||
|
<input type="time" value="00:00" id="id-rule-duration" data-max-hours="24" name="rule_duration" class="form-control input-small">
|
||||||
|
<span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user