Working on the time tracker

This commit is contained in:
Hillel Coren 2017-10-02 18:21:11 +03:00
parent 86db7be9db
commit b34c6456bc
2 changed files with 43 additions and 29 deletions

View File

@ -170,7 +170,7 @@
<div class="input-group input-group-lg"> <div class="input-group input-group-lg">
<span class="input-group-addon" style="width:1%;" data-bind="click: onFilterClick, style: { 'background-color': filterState() != 'all' ? '#ffffaa' : '' }" title="{{ trans('texts.filter_sort') }}"><span class="glyphicon glyphicon-filter"></span></span> <span class="input-group-addon" style="width:1%;" data-bind="click: onFilterClick, style: { 'background-color': filterState() != 'all' ? '#ffffaa' : '' }" title="{{ trans('texts.filter_sort') }}"><span class="glyphicon glyphicon-filter"></span></span>
<input id="search" type="search" class="form-control search" autocomplete="off" autofocus="autofocus" <input id="search" type="search" class="form-control search" autocomplete="off" autofocus="autofocus"
data-bind="event: { focus: onFilterFocus, input: onFilterChanged, keypress: onFilterKeyPress }, value: filter, valueUpdate: 'afterkeydown', attr: {placeholder: placeholder, style: filterStyle, disabled: formChanged }"> data-bind="event: { focus: onFilterFocus, input: onFilterChanged, keypress: onFilterKeyPress }, value: filter, valueUpdate: 'afterkeydown', attr: {placeholder: placeholder, style: filterStyle, disabled: selectedTask().isChanged }">
<span class="input-group-addon" style="width:1%;" data-bind="click: onRefreshClick" title="{{ trans('texts.refresh') }}"><span class="glyphicon glyphicon-repeat"></span></span> <span class="input-group-addon" style="width:1%;" data-bind="click: onRefreshClick" title="{{ trans('texts.refresh') }}"><span class="glyphicon glyphicon-repeat"></span></span>
</div> </div>
@ -197,7 +197,7 @@
<div id="formDiv" class="panel panel-default x-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 }">
<div style="padding-bottom: 20px" class="client-select"> <div style="padding-bottom: 20px" class="client-select">
{!! Former::select('client_id') {!! Former::select('client_id')
->addOption('', '') ->addOption('', '')
@ -284,7 +284,7 @@
->large() ->large()
->appendIcon(Icon::create('floppy-disk')) ->appendIcon(Icon::create('floppy-disk'))
->withAttributes([ ->withAttributes([
'data-bind' => 'click: onSaveClick, css: { disabled: ! formChanged() || ! isSaveEnabled() }', 'data-bind' => 'click: onSaveClick, css: { disabled: ! isSaveEnabled() }',
]) !!} ]) !!}
</center> </center>
</form> </form>
@ -624,7 +624,7 @@
if (model.isDesktop()) { if (model.isDesktop()) {
return undefined; return undefined;
} }
if (model.selectedTask() && model.formChanged()) { if (model.selectedTask() && model.isChanged()) {
return "{{ trans('texts.save_or_discard') }}"; return "{{ trans('texts.save_or_discard') }}";
} else { } else {
return undefined; return undefined;

View File

@ -157,7 +157,6 @@
self.filter = ko.observable(''); self.filter = ko.observable('');
self.clock = ko.observable(0); self.clock = ko.observable(0);
self.formChanged = ko.observable(false);
self.sendingRequest = ko.observable(false); self.sendingRequest = ko.observable(false);
self.sendingBulkRequest = ko.observable(false); self.sendingBulkRequest = ko.observable(false);
@ -184,12 +183,16 @@
return ! self.sendingRequest(); return ! self.sendingRequest();
}); });
self.isChanged = ko.computed(function() {
return self.selectedTask() && self.selectedTask().isChanged();
});
self.isSaveEnabled = ko.computed(function() { self.isSaveEnabled = ko.computed(function() {
return ! self.sendingRequest(); return self.selectedTask() && self.selectedTask().isChanged() && ! self.sendingRequest();
}); });
self.onSaveClick = function() { self.onSaveClick = function() {
if (! model.selectedTask() || ! model.formChanged()) { if (! model.selectedTask() || ! model.isChanged()) {
return; return;
} }
model.selectedTask().save(true); model.selectedTask().save(true);
@ -208,7 +211,7 @@
self.onRefreshClick = function() { self.onRefreshClick = function() {
if (self.isDesktop()) { if (self.isDesktop()) {
if (model.selectedTask() && model.formChanged()) { if (model.selectedTask() && model.isChanged()) {
swal("{{ trans('texts.save_or_discard') }}"); swal("{{ trans('texts.save_or_discard') }}");
return false; return false;
} else { } else {
@ -306,14 +309,12 @@
} else { } else {
task.update(task.data); task.update(task.data);
} }
self.formChanged(false);
}, "{{ trans('texts.discard_changes') }}"); }, "{{ trans('texts.discard_changes') }}");
return false; return false;
} }
self.onFilterFocus = function(data, event) { self.onFilterFocus = function(data, event) {
if (model.selectedTask() && model.formChanged()) { if (model.selectedTask() && model.isChanged()) {
return; return;
} }
self.selectedTask(false); self.selectedTask(false);
@ -332,11 +333,6 @@
return true; return true;
} }
self.onFormChange = function(data, event) {
self.formChanged(true);
return true;
}
self.onFormKeyPress = function(data, event) { self.onFormKeyPress = function(data, event) {
if (event.which == 13) { if (event.which == 13) {
if (event.target.type == 'textarea') { if (event.target.type == 'textarea') {
@ -348,7 +344,7 @@
} }
self.viewClient = function(task) { self.viewClient = function(task) {
if (model.selectedTask() && model.formChanged()) { if (model.isChanged()) {
swal("{{ trans('texts.save_or_discard') }}"); swal("{{ trans('texts.save_or_discard') }}");
return false; return false;
} }
@ -366,7 +362,7 @@
} }
self.viewProject = function(task) { self.viewProject = function(task) {
if (model.selectedTask() && model.formChanged()) { if (model.isChanged()) {
swal("{{ trans('texts.save_or_discard') }}"); swal("{{ trans('texts.save_or_discard') }}");
return false; return false;
} }
@ -404,7 +400,6 @@
self.selectedTask(task); self.selectedTask(task);
self.addTask(task); self.addTask(task);
model.refreshTitle(); model.refreshTitle();
model.formChanged(true);
self.filter(''); self.filter('');
task.focus(); task.focus();
} }
@ -430,7 +425,7 @@
if (! task) { if (! task) {
return false; return false;
} }
return task.isCreated() && ! self.formChanged(); return task.isCreated() && ! task.isChanged();
}); });
self.showCancel = ko.computed(function() { self.showCancel = ko.computed(function() {
@ -438,7 +433,7 @@
if (! task) { if (! task) {
return false; return false;
} }
return task.isNew() || self.formChanged(); return task.isChanged();
}); });
self.startIcon = ko.computed(function() { self.startIcon = ko.computed(function() {
@ -528,7 +523,6 @@
self.addTask = function(task) { self.addTask = function(task) {
self.tasks.push(task); self.tasks.push(task);
self.formChanged(true);
} }
self.removeTask = function(task) { self.removeTask = function(task) {
@ -536,7 +530,7 @@
} }
self.selectTask = function(task) { self.selectTask = function(task) {
if (model.selectedTask() && model.formChanged()) { if (model.isChanged()) {
swal("{{ trans('texts.save_or_discard') }}"); swal("{{ trans('texts.save_or_discard') }}");
return false; return false;
} }
@ -566,8 +560,6 @@
if (isStorageSupported()) { if (isStorageSupported()) {
localStorage.setItem('last:time_tracker:task_id', task ? task.public_id() : 0); localStorage.setItem('last:time_tracker:task_id', task ? task.public_id() : 0);
} }
self.formChanged(false);
} }
} }
@ -702,7 +694,6 @@
} }
var isNew = !self.public_id(); var isNew = !self.public_id();
self.update(response); self.update(response);
model.formChanged(false);
if (isStorageSupported()) { if (isStorageSupported()) {
localStorage.setItem('last:time_tracker:task_id', self.public_id()); localStorage.setItem('last:time_tracker:task_id', self.public_id());
} }
@ -811,6 +802,30 @@
return self.public_id(); return self.public_id();
}); });
self.isChanged = ko.computed(function() {
model.sendingRequest(); // bind to the request
var data = self.data;
if (! self.public_id()) {
return true;
}
var oldProjectId = data.project ? data.project.public_id : 0;
if (oldProjectId != (self.project_id()||0)) {
return true;
}
var oldClientId = data.client ? data.client.public_id : 0;
if (oldClientId != (self.client_id()||0)) {
return true;
}
if (data.description != self.description()) {
return true;
}
var times = data.time_log instanceof Array ? JSON.stringify(data.time_log) : data.time_log;
if (times != JSON.stringify(self.times())) {
return true;
}
return false;
});
self.sortedTimes = ko.computed(function() { self.sortedTimes = ko.computed(function() {
var times = self.time_log(); var times = self.time_log();
times.sort(function (left, right) { times.sort(function (left, right) {
@ -931,7 +946,7 @@
if (self.public_id()) { if (self.public_id()) {
var selectedTask = model.selectedTask(); var selectedTask = model.selectedTask();
if (model.formChanged() && selectedTask && selectedTask.public_id() == self.public_id()) { if (model.isChanged() && selectedTask && selectedTask.public_id() == self.public_id()) {
model.onSaveClick(); model.onSaveClick();
} else { } else {
self.save(); self.save();
@ -944,7 +959,7 @@
if (self == model.selectedTask()) { if (self == model.selectedTask()) {
str = 'active'; str = 'active';
if (! self.public_id() || model.formChanged()) { if (self.isChanged()) {
str += ' changed fade-color'; str += ' changed fade-color';
} }
} }
@ -1049,7 +1064,6 @@
}); });
self.removeTime = function(time) { self.removeTime = function(time) {
model.formChanged(true);
self.time_log.remove(time); self.time_log.remove(time);
} }