1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-18 23:42:25 +02:00

Working on the time tracker

This commit is contained in:
Hillel Coren 2017-09-29 12:59:53 +03:00
parent bea6f80d31
commit 6a0842b307
7 changed files with 111 additions and 2 deletions

View File

@ -37,7 +37,8 @@
"tablesorter": "jquery.tablesorter#^2.28.4",
"card": "^2.1.1",
"fullcalendar": "^3.5.1",
"toastr": "^2.1.3"
"toastr": "^2.1.3",
"jt.timepicker": "jquery-timepicker-jt#^1.11.12"
},
"resolutions": {
"jquery": "~1.11"

View File

@ -67,6 +67,10 @@ elixir(function(mix) {
bowerDir + '/bootstrap-daterangepicker/daterangepicker.css'
], 'public/css/daterangepicker.css');
mix.styles([
bowerDir + '/jt.timepicker/jquery.timepicker.css'
], 'public/css/jquery.timepicker.css');
mix.styles([
bowerDir + '/select2/dist/css/select2.css'
], 'public/css/select2.css');
@ -99,6 +103,10 @@ elixir(function(mix) {
bowerDir + '/bootstrap-daterangepicker/daterangepicker.js'
], 'public/js/daterangepicker.min.js');
mix.scripts([
bowerDir + '/jt.timepicker/jquery.timepicker.js'
], 'public/js/jquery.timepicker.js');
mix.scripts([
bowerDir + '/fullcalendar/dist/fullcalendar.js',
bowerDir + '/fullcalendar/dist/locale-all.js',

2
public/css/jquery.timepicker.css vendored Executable file
View File

@ -0,0 +1,2 @@
.ui-timepicker-wrapper{overflow-y:auto;max-height:150px;width:6.5em;background:#fff;border:1px solid #ddd;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);outline:0;z-index:10001;margin:0}.ui-timepicker-wrapper.ui-timepicker-with-duration{width:13em}.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30,.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60{width:11em}.ui-timepicker-list{margin:0;padding:0;list-style:none}.ui-timepicker-duration{margin-left:5px;color:#888}.ui-timepicker-list:hover .ui-timepicker-duration{color:#888}.ui-timepicker-list li{padding:3px 0 3px 5px;cursor:pointer;white-space:nowrap;color:#000;list-style:none;margin:0}.ui-timepicker-list:hover .ui-timepicker-selected{background:#fff;color:#000}.ui-timepicker-list .ui-timepicker-selected:hover,.ui-timepicker-list li:hover,li.ui-timepicker-selected{background:#1980EC;color:#fff}.ui-timepicker-list li:hover .ui-timepicker-duration,li.ui-timepicker-selected .ui-timepicker-duration{color:#ccc}.ui-timepicker-list li.ui-timepicker-disabled,.ui-timepicker-list li.ui-timepicker-disabled:hover,.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled{color:#888;cursor:default}.ui-timepicker-list li.ui-timepicker-disabled:hover,.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled{background:#f2f2f2}
/*# sourceMappingURL=jquery.timepicker.css.map */

View File

@ -0,0 +1 @@
{"version":3,"sources":["jquery.timepicker.css"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"jquery.timepicker.css","sourcesContent":[".ui-timepicker-wrapper {\n\toverflow-y: auto;\n\tmax-height: 150px;\n\twidth: 6.5em;\n\tbackground: #fff;\n\tborder: 1px solid #ddd;\n\t-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);\n\t-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);\n\tbox-shadow:0 5px 10px rgba(0,0,0,0.2);\n\toutline: none;\n\tz-index: 10001;\n\tmargin: 0;\n}\n\n.ui-timepicker-wrapper.ui-timepicker-with-duration {\n\twidth: 13em;\n}\n\n.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30,\n.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60 {\n\twidth: 11em;\n}\n\n.ui-timepicker-list {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n.ui-timepicker-duration {\n\tmargin-left: 5px; color: #888;\n}\n\n.ui-timepicker-list:hover .ui-timepicker-duration {\n\tcolor: #888;\n}\n\n.ui-timepicker-list li {\n\tpadding: 3px 0 3px 5px;\n\tcursor: pointer;\n\twhite-space: nowrap;\n\tcolor: #000;\n\tlist-style: none;\n\tmargin: 0;\n}\n\n.ui-timepicker-list:hover .ui-timepicker-selected {\n\tbackground: #fff; color: #000;\n}\n\nli.ui-timepicker-selected,\n.ui-timepicker-list li:hover,\n.ui-timepicker-list .ui-timepicker-selected:hover {\n\tbackground: #1980EC; color: #fff;\n}\n\nli.ui-timepicker-selected .ui-timepicker-duration,\n.ui-timepicker-list li:hover .ui-timepicker-duration {\n\tcolor: #ccc;\n}\n\n.ui-timepicker-list li.ui-timepicker-disabled,\n.ui-timepicker-list li.ui-timepicker-disabled:hover,\n.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {\n\tcolor: #888;\n\tcursor: default;\n}\n\n.ui-timepicker-list li.ui-timepicker-disabled:hover,\n.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled {\n\tbackground: #f2f2f2;\n}\n"]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,6 +4,8 @@
@parent
<link href="{{ asset('css/built.css') }}?no_cache={{ NINJA_VERSION }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/jquery.timepicker.css') }}?no_cache={{ NINJA_VERSION }}" rel="stylesheet" type="text/css"/>
<script src="{{ asset('js/jquery.timepicker.js') }}?no_cache={{ NINJA_VERSION }}" type="text/javascript"></script>
@stop
@ -108,13 +110,20 @@
bottom: 0;
width: 6px;
content: "";
background-color: #36c157;
xbackground-color: #36c157; /* green */
background-color: orange; /* orange */
}
body {
margin-bottom: 60px;
}
.times-table td {
xmargin: 0px !important;
xpadding: 0px !important;
xpadding-bottom: 10px !important;
}
.footer {
position: fixed;
bottom: 0;
@ -191,9 +200,62 @@
->data_bind("dropdown: selectedTask().project_id")
->label(trans('texts.project')) !!}
</div>
<div style="padding-bottom: 20px">
{!! Former::textarea('description')
->data_bind("value: selectedTask().description")
->rows(4) !!}
</div>
<label>{{ trans('texts.times') }}</label>
<table class="table times-table" style="margin-bottom: 0px !important;">
<tbody data-bind="foreach: selectedTask().time_log">
<tr data-bindx="event: { mouseover: showActions, mouseout: hideActions }">
<td style="padding: 0 6px 10px 0">
{!! Former::text('date')
->data_bindx('timepicker: startTime')
->raw() !!}
</td>
<td style="padding: 0 6px 10px 6px">
{!! Former::text('start_time')
->data_bind('timepicker: startTime')
->raw() !!}
</td>
<td style="padding: 0 6px 10px 6px">
{!! Former::text('end_time')
->data_bind('timepicker: endTime')
->raw() !!}
</td>
<td style="padding: 0 0 10px 6px">
{!! Former::text('duration')
->raw() !!}
</td>
<!--
<td style="padding: 0px 12px 12px 0 !important">
<div data-bind="css: { 'has-error': !isStartValid() }">
<input type="text" data-bind="dateTimePicker: startTime.pretty, event:{ change: $root.refresh }"
class="form-control time-input time-input-start" placeholder="{{ trans('texts.start_time') }}"/>
</div>
</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">
<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>
</td>
<td style="width:30px" class="td-icon">
<i style="width:12px;cursor:pointer" data-bind="click: $root.removeItem, visible: actionsVisible() &amp;&amp; !isEmpty()" class="fa fa-minus-circle redlink" title="Remove item"/>
</td>
-->
</tr>
</tbody>
</table>
</span>
<center id="buttons" style="padding-top: 30px">
@ -393,6 +455,38 @@
}, 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() {
// setup clients and project comboboxes