UX improvements

Fix calendar to better display in small windows
Bump the number of results for listing items
Quick workaround to successfully listing items after being created

Closes bug: 1556939
Change-Id: Ibaf0a999a729197900b18c1f22fd819f5e11e797
This commit is contained in:
Memo Garcia 2016-03-11 15:01:51 +00:00
parent b31f3c3665
commit a1541e6a59
19 changed files with 510 additions and 161 deletions

View File

@ -4,11 +4,8 @@
<h4>{% blocktrans %}Action{% endblocktrans %}</h4>
<p>{% blocktrans %}Specify the details for this action.{% endblocktrans %}</p>
<p>{% blocktrans %}An action is the simplest execution within a job, it could be a backup or a restore
and it contains rules that the action must follow (max retries, interval between intervals, etc)
.{% endblocktrans %}</p>
and it contains rules that the action must follow (max retries, interval between executions, etc).{% endblocktrans %}</p>
{% endblock %}

View File

@ -4,7 +4,7 @@
<h4>{% blocktrans %}Advanced configuration{% endblocktrans %}</h4>
<p>{% blocktrans %}Define extra information for the action to execute in the client.{% endblocktrans %}</p>
<p>{% blocktrans %}Define extra information for the action executed by the client.{% endblocktrans %}</p>
{% endblock %}

View File

@ -0,0 +1,16 @@
{% load i18n horizon humanize %}
{% block help_message %}
<h4>{% blocktrans %}Rules{% endblocktrans %}</h4>
<p>{% blocktrans %}Define the following action rules:
<ul>
<li>Number of retries</li>
<li>Retries interval</li>
<li>Action is mandatory</li>
</ul>
{% endblocktrans %}</p>
{% endblock %}

View File

@ -0,0 +1,13 @@
{% load i18n horizon humanize %}
{% block help_message %}
<h4>{% blocktrans %}Snapshot{% endblocktrans %}</h4>
<p>{% blocktrans %}The snapshot technologies currently supported are LVM for Linux and Volume Shadow Copy for Windows.{% endblocktrans %}</p>
<p>{% blocktrans %}For Linux, in order to use snapshot features, the data has to reside on an LVM volume.{% endblocktrans %}</p>
{% endblock %}
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/freezer.actions.snapshot.js'></script>

View File

@ -32,6 +32,10 @@ class ActionConfigurationAction(workflows.Action):
widget=forms.HiddenInput(),
required=False)
backup_name = forms.CharField(
label=_("Action Name *"),
required=False)
action = forms.ChoiceField(
help_text=_("Set the action to be taken"),
required=True)
@ -44,10 +48,6 @@ class ActionConfigurationAction(workflows.Action):
help_text=_("Set storage backend for a backup"),
required=True)
backup_name = forms.CharField(
label=_("Action Name *"),
required=False)
mysql_conf = forms.CharField(
label=_("MySQL Configuration File *"),
help_text=_("Set the path where the MySQL configuration file "
@ -228,7 +228,7 @@ class ActionConfigurationAction(workflows.Action):
class Meta(object):
name = _("Action")
help_text_template = "disaster_recovery/jobs" \
help_text_template = "disaster_recovery/actions" \
"/_action.html"
@ -268,7 +268,7 @@ class SnapshotConfigurationAction(workflows.Action):
class Meta(object):
name = _("Snapshot")
help_text_template = "disaster_recovery/jobs" \
help_text_template = "disaster_recovery/actions" \
"/_snapshot.html"
@ -453,7 +453,7 @@ class AdvancedConfigurationAction(workflows.Action):
class Meta(object):
name = _("Advanced")
help_text_template = "disaster_recovery/jobs" \
help_text_template = "disaster_recovery/actions" \
"/_advanced.html"
@ -493,19 +493,19 @@ class RulesConfigurationAction(workflows.Action):
label=_("Max Retries Interval"),
initial=0,
min_value=0,
help_text=_("Set the interval between intervals "
help_text=_("Set the interval between executions "
"for retries in seconds"),
required=False)
mandatory = forms.BooleanField(
label=_("Mandatory"),
help_text=_("Set this job as mandatory"),
help_text=_("Set this action as mandatory"),
widget=forms.CheckboxInput(),
required=False)
class Meta(object):
name = _("Rules")
help_text_template = "disaster_recovery/jobs" \
help_text_template = "disaster_recovery/actions" \
"/_rules.html"

View File

@ -14,6 +14,7 @@
# from horizon.
import logging
import time
from django.conf import settings
@ -88,7 +89,7 @@ class Job(object):
self.request = request
self.client = client(request)
def list(self, json=False, limit=100, offset=0, search=None):
def list(self, json=False, limit=500, offset=0, search=None):
if search:
search = {"match": [{"_all": search}, ], }
@ -120,7 +121,13 @@ class Job(object):
job.get('client_id'))
def create(self, job):
return self._build(job)
job = self._build(job)
# due to elasticsearch replication time, sometimes the newly created
# file is not reflected in the ui immediately, so a quick and dirty
# workaround is to sleep for 3 seconds to make sure that the changes
# are reflected
time.sleep(3)
return job
def update(self, job_id, job):
scheduling = {}
@ -248,7 +255,7 @@ class Session(object):
self.request = request
self.client = client(request)
def list(self, json=False, limit=30, offset=0, search=None):
def list(self, json=False, limit=500, offset=0, search=None):
if search:
search = {"match": [{"_all": search}, ], }
@ -285,7 +292,13 @@ class Session(object):
session.get('schedule', {}).get('schedule_end_date'))
def create(self, session):
return self._build(session)
session = self._build(session)
# due to elasticsearch replication time, sometimes the newly created
# file is not reflected in the ui immediately, so a quick and dirty
# workaround is to sleep for 3 seconds to make sure that the changes
# are reflected
time.sleep(3)
return session
def update(self, session, session_id):
return self.client.sessions.update(session_id, session)
@ -338,7 +351,7 @@ class Action(object):
self.request = request
self.client = client(request)
def list(self, json=False, limit=100, offset=0, search=None):
def list(self, json=False, limit=500, offset=0, search=None):
if search:
search = {"match": [{"_all": search}, ], }
@ -374,7 +387,13 @@ class Action(object):
action['freezer_action'].get('storage'))
def create(self, action):
return self._build(action)
action = self._build(action)
# due to elasticsearch replication time, sometimes the newly created
# file is not reflected in the ui immediately, so a quick and dirty
# workaround is to sleep for 3 seconds to make sure that the changes
# are reflected
time.sleep(3)
return action
def update(self, action, action_id):
updated_action = {}
@ -427,7 +446,7 @@ class Client(object):
self.request = request
self.client = client(request)
def list(self, json=False, limit=100, offset=0, search=None):
def list(self, json=False, limit=500, offset=0, search=None):
if search:
search = {"match": [{"_all": search}, ], }
@ -465,7 +484,7 @@ class Backup(object):
self.request = request
self.client = client(request)
def list(self, json=False, limit=30, offset=0, search=None):
def list(self, json=False, limit=500, offset=0, search=None):
if search:
search = {"match": [{"_all": search}, ], }

View File

@ -49,12 +49,12 @@ def icons(backup):
placeholder = '<i class="fa fa-fw"></i>'
try:
level_txt = "Level: {} ({} backup) out of {}".format(
backup.level, "Full" if backup.level == 0 else "Incremental",
backup.max_level)
level_txt = "Level: {} ({} backup)".format(
backup.curr_backup_level, "Full"
if backup.curr_backup_level == 0 else "Incremental")
result.append(
'<i class="fa fa-fw fa-custom-number" title="{}">{}</i>'.format(
level_txt, backup.level))
level_txt, backup.curr_backup_level))
except Exception:
result.append("Level: {}".format("Full"))

View File

@ -2,10 +2,12 @@
{% block help_message %}
<h4>{% blocktrans %}Job{% endblocktrans %}</h4>
<p>{% blocktrans %}Describes actions to be executed by a client.{% endblocktrans %}</p>
<p>{% blocktrans %}Job executions can be executed and scheduled, by providing the following settings.{% endblocktrans %}</p>
<p>{% blocktrans %}Specify the details for creating a job.{% endblocktrans %}</p>
<p>{% blocktrans %}A job defines an ordered list of actions to be executed in a client with scheduling information.{% endblocktrans %}</p>
<link rel="stylesheet" href="{{ STATIC_URL }}freezer/css/bootstrap-datetimepicker.min.css">
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/vendor/moment.js'></script>
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/vendor/bootstrap-datetimepicker.js'></script>
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/freezer.datetimepicker.js'></script>
{% endblock %}

View File

@ -1,11 +0,0 @@
{% load i18n horizon humanize %}
{% block help_message %}
<h4>{% blocktrans %}Rules{% endblocktrans %}</h4>
<p>{% blocktrans %}Define rules for this action, from how many times it will retry the action, the interval
between interval and whether or not the action is mandatory. {% endblocktrans %}</p>
{% endblock %}

View File

@ -1,24 +0,0 @@
{% load i18n horizon humanize %}
{% block help_message %}
<h4>{% blocktrans %}Start and End Date Time{% endblocktrans %}</h4>
<p>{% blocktrans %}Set a start date and time to execute jobs{% endblocktrans %}</p>
<h4>{% blocktrans %}Interval{% endblocktrans %}</h4>
<p>{% blocktrans %}Set the interval in the following format:{% endblocktrans %}</p>
<ul>
<li>continuous</li>
<li>N weeks</li>
<li>N days</li>
<li>N hours</li>
<li>N minutes</li>
<li>N seconds</li>
</ul>
<p>{% blocktrans %}If no start date is provided the job will start immediately{% endblocktrans %}</p>
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/vendor/moment.js'></script>
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/vendor/bootstrap-datetimepicker.js'></script>
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/freezer.datetimepicker.js'></script>
{% endblock %}

View File

@ -1,12 +0,0 @@
{% load i18n horizon humanize %}
{% block help_message %}
<h4>{% blocktrans %}Action{% endblocktrans %}</h4>
<p>{% blocktrans %}Specify whether this action should execute a snapshot on the client file system.
In Linux and it's distros it will use LVM and in Windows it will use Volume Shadow Copy{% endblocktrans %}</p>
{% endblock %}
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/freezer.actions.snapshot.js'></script>

View File

@ -1,61 +0,0 @@
{% load i18n %}
<noscript><h3>{{ step }}</h3></noscript>
<div class="membership {{ step.slug }}_membership dropdown_fix" data-show-roles="{{ step.show_roles }}">
<div class="header">
<div class="help_text">{{ step.help_text }}</div>
<div class="row">
<div class="col-xs-6">
<div class="fake_table fake_table_header fake_{{ step.slug }}_table clearfix">
<span class="members_title">{{ step.available_list_title }}</span>
<div class="form-group has-feedback">
<input type="text" name="available_{{ step.slug }}_filter" id="available_{{ step.slug }}" class="filter {{ step.slug }}_filter form-control input-sm" placeholder="{% trans "Filter" %}">
<span class="fa fa-search search-icon form-control-feedback"></span>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="fake_table fake_table_header fake_{{ step.slug }}_table clearfix">
<span class="members_title">{{ step.members_list_title }}</span>
<div class="form-group has-feedback">
<input type="text" name="{{ step.slug }}_members_filter" id="{{ step.slug }}_members" class="filter {{ step.slug }}_filter form-control input-sm" placeholder="{% trans "Filter" %}">
<span class="fa fa-search search-icon form-control-feedback"></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6 filterable {{ step.slug }}_filterable">
<div class="fake_table fake_{{ step.slug }}_table" id="available_{{ step.slug }}">
<ul class="available_members available_{{ step.slug }}"></ul>
<ul class="no_results" id="no_available_{{ step.slug }}"><li>{{ step.no_available_text }}</li></ul>
</div>
</div>
<div class="col-xs-6 filterable {{ step.slug }}_filterable">
<div class="fake_table fake_{{ step.slug }}_table" id="{{ step.slug }}_members">
<ul class="members {{ step.slug }}_members"></ul>
<ul class="no_results" id="no_{{ step.slug }}_members"><li>{{ step.no_members_text }}</li></ul>
</div>
</div>
</div>
</div>
<div class="hide">
{% include "horizon/common/_form_fields.html" %}
</div>
<script>
if (typeof horizon.membership !== 'undefined') {
horizon.membership.workflow_init($(".workflow"), "{{ step.slug }}", "{{ step.get_id }}");
} else {
addHorizonLoadEvent(function() {
horizon.membership.workflow_init($(".workflow"), "{{ step.slug }}", "{{ step.get_id }}");
});
}
</script>

View File

@ -115,7 +115,15 @@ class InfoConfigurationAction(workflows.Action):
schedule_interval = forms.CharField(
label=_("Interval"),
required=False,
help_text=_("Repeat this configuration in a minutes interval."))
help_text=_("""Set the interval in the following format:
continuous,
N weeks,
N days,
N hours,
N minutes,
N seconds,
If no start date is provided the job
will start immediately"""))
schedule_end_date = forms.CharField(
label=_("End Date and Time"),
@ -170,7 +178,7 @@ class InfoConfigurationAction(workflows.Action):
name = _("Job Info")
slug = "info"
help_text_template = "disaster_recovery/jobs" \
"/_scheduling.html"
"/_info.html"
class InfoConfiguration(workflows.Step):

View File

@ -90,7 +90,7 @@ class InfoConfigurationAction(workflows.Action):
name = _("Job Info")
slug = "info"
help_text_template = "disaster_recovery/jobs" \
"/_scheduling.html"
"/_info.html"
class InfoConfiguration(workflows.Step):

View File

@ -3,10 +3,11 @@
{% block help_message %}
<h4>{% blocktrans %}Session{% endblocktrans %}</h4>
<p>{% blocktrans %}Specify the name for this session.{% endblocktrans %}</p>
<p>{% blocktrans %}A session is a collection of jobs which share scheduling information and will coordinate one
or more clients.{% endblocktrans %}</p>
<p>{% blocktrans %}A group of jobs which share the same scheduling time.{% endblocktrans %}</p>
<link rel="stylesheet" href="{{ STATIC_URL }}freezer/css/bootstrap-datetimepicker.min.css">
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/vendor/moment.js'></script>
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/vendor/bootstrap-datetimepicker.js'></script>
<script type='text/javascript' src='{{ STATIC_URL }}freezer/js/freezer.datetimepicker.js'></script>
{% endblock %}

View File

@ -44,7 +44,16 @@ class SessionConfigurationAction(workflows.Action):
schedule_interval = forms.CharField(
label=_("Interval"),
required=False)
required=False,
help_text=_("""Set the interval in the following format:
continuous,
N weeks,
N days,
N hours,
N minutes,
N seconds,
If no start date is provided the job
will start immediately"""))
schedule_end_date = forms.CharField(
label=_("End Date and Time"),
@ -80,8 +89,8 @@ class SessionConfigurationAction(workflows.Action):
class Meta:
name = _("Session Information")
slug = "sessions"
help_text_template = "disaster_recovery/jobs" \
"/_scheduling.html"
help_text_template = "disaster_recovery/sessions" \
"/_info.html"
class SessionConfiguration(workflows.Step):

View File

@ -0,0 +1,373 @@
/*!
* Datetimepicker for Bootstrap 3
* version : 4.17.37
* https://github.com/Eonasdan/bootstrap-datetimepicker/
*/
.bootstrap-datetimepicker-widget {
list-style: none;
}
.bootstrap-datetimepicker-widget.dropdown-menu {
margin: 2px 0;
padding: 4px;
width: 19em;
}
@media (min-width: 768px) {
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
width: 38em;
}
}
@media (min-width: 992px) {
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
width: 38em;
}
}
@media (min-width: 1200px) {
.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
width: 38em;
}
}
.bootstrap-datetimepicker-widget.dropdown-menu:before,
.bootstrap-datetimepicker-widget.dropdown-menu:after {
content: '';
display: inline-block;
position: absolute;
}
.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before {
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid #cccccc;
border-bottom-color: rgba(0, 0, 0, 0.2);
top: -7px;
left: 7px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after {
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid white;
top: -6px;
left: 8px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.top:before {
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-top: 7px solid #cccccc;
border-top-color: rgba(0, 0, 0, 0.2);
bottom: -7px;
left: 6px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.top:after {
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid white;
bottom: -6px;
left: 7px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before {
left: auto;
right: 6px;
}
.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after {
left: auto;
right: 7px;
}
.bootstrap-datetimepicker-widget .list-unstyled {
margin: 0;
}
.bootstrap-datetimepicker-widget a[data-action] {
padding: 6px 0;
}
.bootstrap-datetimepicker-widget a[data-action]:active {
box-shadow: none;
}
.bootstrap-datetimepicker-widget .timepicker-hour,
.bootstrap-datetimepicker-widget .timepicker-minute,
.bootstrap-datetimepicker-widget .timepicker-second {
width: 54px;
font-weight: bold;
font-size: 1.2em;
margin: 0;
}
.bootstrap-datetimepicker-widget button[data-action] {
padding: 6px;
}
.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Increment Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Increment Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Decrement Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Decrement Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Show Hours";
}
.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Show Minutes";
}
.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Toggle AM/PM";
}
.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Clear the picker";
}
.bootstrap-datetimepicker-widget .btn[data-action="today"]::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Set the date to today";
}
.bootstrap-datetimepicker-widget .picker-switch {
text-align: center;
}
.bootstrap-datetimepicker-widget .picker-switch::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Toggle Date and Time Screens";
}
.bootstrap-datetimepicker-widget .picker-switch td {
padding: 0;
margin: 0;
height: auto;
width: auto;
line-height: inherit;
}
.bootstrap-datetimepicker-widget .picker-switch td span {
line-height: 2.5;
height: 2.5em;
width: 100%;
}
.bootstrap-datetimepicker-widget table {
width: 100%;
margin: 0;
}
.bootstrap-datetimepicker-widget table td,
.bootstrap-datetimepicker-widget table th {
text-align: center;
border-radius: 4px;
}
.bootstrap-datetimepicker-widget table th {
height: 20px;
line-height: 20px;
width: 20px;
}
.bootstrap-datetimepicker-widget table th.picker-switch {
width: 145px;
}
.bootstrap-datetimepicker-widget table th.disabled,
.bootstrap-datetimepicker-widget table th.disabled:hover {
background: none;
color: #777777;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget table th.prev::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Previous Month";
}
.bootstrap-datetimepicker-widget table th.next::after {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
content: "Next Month";
}
.bootstrap-datetimepicker-widget table thead tr:first-child th {
cursor: pointer;
}
.bootstrap-datetimepicker-widget table thead tr:first-child th:hover {
background: #eeeeee;
}
.bootstrap-datetimepicker-widget table td {
height: 54px;
line-height: 54px;
width: 54px;
}
.bootstrap-datetimepicker-widget table td.cw {
font-size: .8em;
height: 20px;
line-height: 20px;
color: #777777;
}
.bootstrap-datetimepicker-widget table td.day {
height: 20px;
line-height: 20px;
width: 20px;
}
.bootstrap-datetimepicker-widget table td.day:hover,
.bootstrap-datetimepicker-widget table td.hour:hover,
.bootstrap-datetimepicker-widget table td.minute:hover,
.bootstrap-datetimepicker-widget table td.second:hover {
background: #eeeeee;
cursor: pointer;
}
.bootstrap-datetimepicker-widget table td.old,
.bootstrap-datetimepicker-widget table td.new {
color: #777777;
}
.bootstrap-datetimepicker-widget table td.today {
position: absolute;
}
.bootstrap-datetimepicker-widget table td.today:before {
content: '';
display: inline-block;
border: solid transparent;
border-width: 0 0 7px 7px;
border-bottom-color: #337ab7;
border-top-color: rgba(0, 0, 0, 0.2);
position: absolute;
bottom: 4px;
right: 4px;
}
.bootstrap-datetimepicker-widget table td.active,
.bootstrap-datetimepicker-widget table td.active:hover {
background-color: #337ab7;
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bootstrap-datetimepicker-widget table td.active.today:before {
border-bottom-color: #fff;
}
.bootstrap-datetimepicker-widget table td.disabled,
.bootstrap-datetimepicker-widget table td.disabled:hover {
background: none;
color: #777777;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget table td span {
display: inline-block;
width: 54px;
height: 54px;
line-height: 54px;
margin: 2px 1.5px;
cursor: pointer;
border-radius: 4px;
}
.bootstrap-datetimepicker-widget table td span:hover {
background: #eeeeee;
}
.bootstrap-datetimepicker-widget table td span.active {
background-color: #337ab7;
color: #ffffff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.bootstrap-datetimepicker-widget table td span.old {
color: #777777;
}
.bootstrap-datetimepicker-widget table td span.disabled,
.bootstrap-datetimepicker-widget table td span.disabled:hover {
background: none;
color: #777777;
cursor: not-allowed;
}
.bootstrap-datetimepicker-widget.usetwentyfour td.hour {
height: 27px;
line-height: 27px;
}
.bootstrap-datetimepicker-widget.wider {
width: 21em;
}
.bootstrap-datetimepicker-widget .datepicker-decades .decade {
line-height: 1.8em !important;
}
.input-group.date .input-group-addon {
cursor: pointer;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}

View File

@ -18,12 +18,6 @@
"use strict";
function hideIncrementalOptions () {
$("#id_max_level").closest(".form-group").hide();
$("#id_always_level").closest(".form-group").hide();
$("#id_restart_always_level").closest(".form-group").hide();
}
$("#id_no_incremental").click(function () {
if ($("#id_no_incremental").is(":checked")) {
$("#id_max_level").closest(".form-group").hide();
@ -35,6 +29,3 @@ $("#id_no_incremental").click(function () {
$("#id_restart_always_level").closest(".form-group").show();
}
});
hideIncrementalOptions();

View File

@ -20,10 +20,38 @@
$(function () {
$('#id_schedule_start_date').datetimepicker({
format: 'YYYY-MM-DDTHH:mm:ss'
format: 'YYYY-MM-DDTHH:mm:ss',
showClose: true,
tooltips: {
today: 'Go to today',
clear: 'Clear selection',
close: 'Close the picker'
},
widgetPositioning: {
horizontal: 'left',
vertical: 'bottom'
}
});
$('#id_schedule_end_date').datetimepicker({
format: 'YYYY-MM-DDTHH:mm:ss'
format: 'YYYY-MM-DDTHH:mm:ss',
showClose: true,
tooltips: {
today: 'Go to today',
clear: 'Clear selection',
close: 'Close the picker'
},
widgetPositioning: {
horizontal: 'left',
vertical: 'bottom'
},
useCurrent: false //Important! See issue #1075
});
$("#id_schedule_start_date").on("dp.change", function (e) {
$('#id_schedule_end_date').data("DateTimePicker").minDate(e.date);
});
$("#id_schedule_end_date").on("dp.change", function (e) {
$('#id_schedule_start_date').data("DateTimePicker").maxDate(e.date);
});
});