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:
parent
b31f3c3665
commit
a1541e6a59
@ -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 %}
|
||||
|
@ -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 %}
|
||||
|
16
disaster_recovery/actions/templates/actions/_rules.html
Normal file
16
disaster_recovery/actions/templates/actions/_rules.html
Normal 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 %}
|
||||
|
13
disaster_recovery/actions/templates/actions/_snapshot.html
Normal file
13
disaster_recovery/actions/templates/actions/_snapshot.html
Normal 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>
|
@ -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"
|
||||
|
||||
|
||||
|
@ -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}, ], }
|
||||
|
||||
|
@ -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"))
|
||||
|
||||
|
@ -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 %}
|
@ -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 %}
|
||||
|
@ -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 %}
|
@ -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>
|
@ -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>
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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 %}
|
@ -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):
|
||||
|
373
disaster_recovery/static/freezer/css/bootstrap-datetimepicker.min.css
vendored
Normal file
373
disaster_recovery/static/freezer/css/bootstrap-datetimepicker.min.css
vendored
Normal 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;
|
||||
}
|
@ -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();
|
||||
@ -34,7 +28,4 @@ $("#id_no_incremental").click(function () {
|
||||
$("#id_always_level").closest(".form-group").show();
|
||||
$("#id_restart_always_level").closest(".form-group").show();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
hideIncrementalOptions();
|
||||
});
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user