Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 152 additions & 2 deletions flower/static/js/flower.js
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,95 @@ var flower = (function () {
return true;
}

function isGregorianLeapYear(year) {
return year % 400 === 0 || year % 100 !== 0 && year % 4 === 0;
}

function daysInGregorianMonth(year, month) {
var days;

if (month == 2) {
days = 28;
if (isGregorianLeapYear(year)) {
days += 1;
}
} else {
days = 31 - ((month - 1) % 7 % 2);
}

return days;
}

function validateDateString(dateString) {
var dateTime,
date,
time,
value,
re = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/;

if (typeof dateString !== "string") {
return false;
}

if (!dateString.match(re)) {
return false
}

dateTime = dateString.split(" ");
if (dateTime.length !== 2) {
return false;
}

date = dateTime[0].split("-");
if (date.length !== 3) {
return false;
}

// validate year
value = +date[0];
if (date[0].length !== 4 || value < -9999 || value > 9999) {
return false;
}

// validate month
value = +date[1];
if (date[1].length !== 2 || value < 1 || value > 12) {
return false;
}

// validate date
value = +date[2];
if (date[2].length !== 2 || value < 1 || value > daysInGregorianMonth(+date[0], +date[1])) {
return false;
}

time = dateTime[1].split(":");
if (time.length !== 3) {
return false;
}

// validate hour
value = +time[0];
if (time[0].length !== 2 || value < 0 || value > 23) {
return false;
}

// validate minutes
value = +time[1];
if (time[1].length !== 2 || value < 0 || value > 59) {
return false;
}

// validate second
value = +time[2];
if (time[2].length !== 2 || value < 0 || value > 59) {
return false;
}

return true;
}


$.urlParam = function (name) {
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
return (results && results[1]) || 0;
Expand Down Expand Up @@ -715,7 +804,7 @@ var flower = (function () {
return;
}

$('#tasks-table').DataTable({
var oTable = $('#tasks-table').DataTable({
rowId: 'uuid',
searching: true,
paginate: true,
Expand All @@ -726,7 +815,22 @@ var flower = (function () {
colReorder: true,
ajax: {
type: 'POST',
url: url_prefix() + '/tasks/datatable'
url: url_prefix() + '/tasks/datatable',
data: function (d) {
var from = $("#datetimepicker_from").val(),
to = $("#datetimepicker_to").val();

if (!from || !validateDateString(from)) {
from = null;
}

if (!to || !validateDateString(to)) {
to = null
}

d.from = from;
d.to = to;
}
},
order: [
[7, "asc"]
Expand Down Expand Up @@ -844,6 +948,52 @@ var flower = (function () {
}, ],
});

function reevaluateTableDates() {
var from = $("#datetimepicker_from").val(),
to = $("#datetimepicker_to").val(),
fromDate,
toDate;

if (from && to && validateDateString(from) && validateDateString(to)) {
fromDate = moment(from, "yyyy-mm-dd hh:ii:ss");
toDate = moment(to, "yyyy-mm-dd hh:ii:ss");
if (fromDate.diff(toDate) >= 0) {
oTable.clear();
} else {
oTable.ajax.reload();
}
} else {
oTable.ajax.reload();
}
}

$("#datetimepicker_from").datetimepicker({
format: "yyyy-mm-dd hh:ii:ss",
todayBtn: true,
autoclose: true,
forceParse: false,
}).on('changeDate', function(ev){
reevaluateTableDates();
}).keyup(function() {
var dateString = $("#datetimepicker_from").val();
if (validateDateString(dateString) || !dateString) {
reevaluateTableDates();
}
});

$("#datetimepicker_to").datetimepicker({
format: "yyyy-mm-dd hh:ii:ss",
todayBtn: true,
autoclose: true,
forceParse: false,
}).on('changeDate', function(ev){
reevaluateTableDates();
}).keyup(function() {
var dateString = $("#datetimepicker_to").val();
if (validateDateString(dateString) || !dateString) {
reevaluateTableDates();
}
});
});

return {
Expand Down
5 changes: 4 additions & 1 deletion flower/templates/tasks.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
<input type="hidden" value="{{ columns }}" id='columns'>

<div class="container-fluid">

<p id="date_filter">
<span id="date-label-from" class="date-label">From: </span><input class="date_range_filter date" type="text" id="datetimepicker_from" />
<span id="date-label-to" class="date-label">To: <input class="date_range_filter date" type="text" id="datetimepicker_to" />
</p>
<table id="tasks-table" class="table table-bordered table-striped">
<thead>
<tr>
Expand Down
9 changes: 9 additions & 0 deletions flower/views/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from ..views import BaseHandler
from ..utils.tasks import iter_tasks, get_task_by_id, as_dict
from datetime import datetime

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -60,6 +61,14 @@ def get(self):
column = self.get_argument('order[0][column]', type=int)
sort_by = self.get_argument('columns[%s][data]' % column, type=str)
sort_order = self.get_argument('order[0][dir]', type=str) == 'desc'
start_time = self.get_argument('from', type=str)
end_time = self.get_argument('to', type=str)

if start_time:
start_time = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')

if end_time:
end_time = datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')

def key(item):
return Comparable(getattr(item[1], sort_by))
Expand Down