Working on the time tracker

This commit is contained in:
Hillel Coren 2017-10-01 00:13:41 +03:00
parent 57a6f0c053
commit 6a66000db7
2 changed files with 80 additions and 46 deletions

View File

@ -14,11 +14,13 @@
<style type="text/css"> <style type="text/css">
/*
@media (max-width: 768px) { @media (max-width: 768px) {
#formDiv { #formDiv {
position: relative; position: relative;
} }
} }
*/
@media (max-width: 768px) { @media (max-width: 768px) {
#clock, #clock,
@ -124,6 +126,10 @@
xpadding-bottom: 10px !important; xpadding-bottom: 10px !important;
} }
.ui-timepicker-wrapper {
width: 10em !important;
}
.footer { .footer {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
@ -184,7 +190,7 @@
<!-- Task Form --> <!-- Task Form -->
<div class="col-sm-7 col-sm-push-5"> <div class="col-sm-7 col-sm-push-5">
<div id="formDiv" class="panel panel-default affix" data-bind="visible: selectedTask" style="margin:20px; display:none;"> <div id="formDiv" class="panel panel-default x-affix" data-bind="visible: selectedTask" style="margin:20px; display:none;">
<div class="panel-body"> <div class="panel-body">
<form id="taskForm"> <form id="taskForm">
<span data-bind="event: { keypress: onFormKeyPress, change: onFormChange, input: onFormChange }"> <span data-bind="event: { keypress: onFormKeyPress, change: onFormChange, input: onFormChange }">
@ -214,21 +220,22 @@
<tr data-bindx="event: { mouseover: showActions, mouseout: hideActions }"> <tr data-bindx="event: { mouseover: showActions, mouseout: hideActions }">
<td style="padding: 0 6px 10px 0"> <td style="padding: 0 6px 10px 0">
{!! Former::text('date') {!! Former::text('date')
->data_bindx('timepicker: startTime') ->data_bindx("")
->raw() !!} ->raw() !!}
</td> </td>
<td style="padding: 0 6px 10px 6px"> <td style="padding: 0 6px 10px 6px">
{!! Former::text('start_time') {!! Former::text('start_time')
->data_bind('timepicker: startTime') ->data_bind("timepicker: startTime, timepickerOptions: {scrollDefault: 'now', timeFormat: '" . ($account->military_time ? 'H:i:s' : 'g:i:s A') . "'}")
->raw() !!} ->raw() !!}
</td> </td>
<td style="padding: 0 6px 10px 6px"> <td style="padding: 0 6px 10px 6px">
{!! Former::text('end_time') {!! Former::text('end_time')
->data_bind('timepicker: endTime') ->data_bind("timepicker: endTime, timepickerOptions: {scrollDefault: 'now', timeFormat: '" . ($account->military_time ? 'H:i:s' : 'g:i:s A') . "'}")
->raw() !!} ->raw() !!}
</td> </td>
<td style="padding: 0 0 10px 6px"> <td style="padding: 0 0 10px 6px">
{!! Former::text('duration') {!! Former::text('duration')
->data_bind("timepicker: duration, timepickerOptions: {timeFormat: 'H:i:s', showAsDuration: true}")
->raw() !!} ->raw() !!}
</td> </td>
@ -239,12 +246,6 @@
class="form-control time-input time-input-start" placeholder="{{ trans('texts.start_time') }}"/> class="form-control time-input time-input-start" placeholder="{{ trans('texts.start_time') }}"/>
</div> </div>
</td> </td>
<td style="padding: 0px 12px 12px 0 !important">
<div data-bind="css: { 'has-error': !isEndValid() }">
<input type="text" data-bind="dateTimePicker: endTime.pretty, event:{ change: $root.refresh }"
class="form-control time-input time-input-end" placeholder="{{ trans('texts.end_time') }}"/>
</div>
</td>
<td style="padding: 0px 12px 12px 0 !important; width:100px"> <td style="padding: 0px 12px 12px 0 !important; width:100px">
<input type="text" data-bind="value: duration.pretty, visible: !isEmpty()" class="form-control"></div> <input type="text" data-bind="value: duration.pretty, visible: !isEmpty()" class="form-control"></div>
<a href="#" data-bind="click: function() { setNow(), $root.refresh() }, visible: isEmpty()">{{ trans('texts.set_now') }}</a> <a href="#" data-bind="click: function() { setNow(), $root.refresh() }, visible: isEmpty()">{{ trans('texts.set_now') }}</a>
@ -455,38 +456,6 @@
}, 1000 * 60 * 15); }, 1000 * 60 * 15);
} }
ko.bindingHandlers.timepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().dropdownOptions|| {};
var value = ko.utils.unwrapObservable(valueAccessor());
var options = {
scrollDefault: 'now',
showDuration: true,
step: 15,
};
$(element).timepicker(options);
ko.utils.registerEventHandler(element, "change", function () {
var value = valueAccessor();
value($(element).val());
});
/*
var id = (value && value.public_id) ? value.public_id() : (value && value.id) ? value.id() : value ? value : false;
if (id) $(element).val(id);
*/
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var field = $(element).attr('name');
if (field == 'start_time') {
$input = $(element).closest('td').next('td').find('input').show();
$input.timepicker('option', 'durationTime', $(element).val());
}
}
};
$(function() { $(function() {
// setup clients and project comboboxes // setup clients and project comboboxes

View File

@ -1,5 +1,63 @@
<script type="text/javascript"> <script type="text/javascript">
function intToTime(seconds)
{
if (seconds === null) {
return null;
}
// calculate seconds, minutes, hours
var duration = seconds*1000
var milliseconds = parseInt((duration%1000)/100)
, seconds = parseInt((duration/1000)%60)
, minutes = parseInt((duration/(1000*60))%60)
, hours = parseInt((duration/(1000*60*60))%24);
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return new Date(1970, 0, 1, hours, minutes, seconds, 0);
}
ko.bindingHandlers.timepicker = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().timepickerOptions || {};
$.extend(options, {
wrapHours: false,
showDuration: true,
step: 15,
});
$(element).timepicker(options);
ko.utils.registerEventHandler(element, 'change', function () {
var value = valueAccessor();
var dateTime = $(element).timepicker('getTime');
if (dateTime) {
time = dateTime.getTime() / 1000;
}
value(time);
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var field = $(element).attr('name');
if (field == 'duration') {
$(element).timepicker('setTime', intToTime(value));
} else {
$(element).timepicker('setTime', new Date(value * 1000));
}
//console.log(field + ': ' + value);
if (field == 'start_time') {
$input = $(element).closest('td').next('td').find('input').show();
$input.timepicker('option', 'durationTime', $(element).val());
}
}
};
function ViewModel() { function ViewModel() {
var self = this; var self = this;
self.tasks = ko.observableArray(); self.tasks = ko.observableArray();
@ -881,7 +939,6 @@
var self = this; var self = this;
self.startTime = ko.observable(0); self.startTime = ko.observable(0);
self.endTime = ko.observable(0); self.endTime = ko.observable(0);
self.duration = ko.observable(0);
self.actionsVisible = ko.observable(false); self.actionsVisible = ko.observable(false);
self.isStartValid = ko.observable(true); self.isStartValid = ko.observable(true);
self.isEndValid = ko.observable(true); self.isEndValid = ko.observable(true);
@ -908,9 +965,17 @@
return moment.unix(self.startTime()).fromNow(); return moment.unix(self.startTime()).fromNow();
}); });
self.duration = ko.computed(function() { self.duration = ko.computed({
read: function () {
model.clock(); // bind to the clock model.clock(); // bind to the clock
return (self.endTime() || moment().unix()) - self.startTime(); var endTime = self.endTime() ? self.endTime() : moment().unix();
//console.log('duration: ' + (endTime - self.startTime()));
return endTime - self.startTime();
},
write: function(value) {
console.log('duration: ' + value);
//self.endTime(value);
}
}); });