5 changed files with 92 additions and 107 deletions
@ -1,86 +1,82 @@ |
|||||
/** @odoo-module **/ |
odoo.define('project_task_timer.timer', function (require) { |
||||
|
"use strict"; |
||||
|
var AbstractField = require('web.AbstractField'); |
||||
|
var core = require('web.core'); |
||||
|
var field_registry = require('web.field_registry'); |
||||
|
var time = require('web.time'); |
||||
|
var FieldManagerMixin = require('web.FieldManagerMixin'); |
||||
|
|
||||
import { registry } from "@web/core/registry"; |
var _t = core._t; |
||||
import { useService } from "@web/core/utils/hooks"; |
|
||||
import { parseFloatTime } from "@web/views/fields/parsers"; |
|
||||
import { useInputField } from "@web/views/fields/input_field_hook"; |
|
||||
|
|
||||
const { Component, useState, onWillUpdateProps, onWillStart, onWillDestroy } = owl; |
// $(document).on('click','#timer', function(){
|
||||
|
// if ($(this).hasClass('btn-secondary'))
|
||||
|
// { $(this).removeClass('btn-secondary');
|
||||
|
// $(this).addClass('btn-primary');
|
||||
|
// }
|
||||
|
// });
|
||||
|
|
||||
function formatMinutes(value) { |
/** |
||||
if (value === false) { |
* Custom field type for displaying a time counter based on data from the account.analytic.line model. |
||||
return ""; |
* Inherits from the AbstractField class. |
||||
} |
*/ |
||||
const isNegative = value < 0; |
|
||||
if (isNegative) { |
|
||||
value = Math.abs(value); |
|
||||
} |
|
||||
let min = Math.floor(value); |
|
||||
let sec = Math.floor((value % 1) * 60); |
|
||||
sec = `${sec}`.padStart(2, "0"); |
|
||||
min = `${min}`.padStart(2, "0"); |
|
||||
return `${isNegative ? "-" : ""}${min}:${sec}`; |
|
||||
} |
|
||||
|
|
||||
export class TaskTimer extends Component { |
|
||||
setup() { |
|
||||
this.orm = useService('orm'); |
|
||||
this.state = useState({ |
|
||||
// duration is expected to be given in minutes
|
|
||||
duration: |
|
||||
this.props.value !== undefined ? this.props.value : this.props.record.data.duration, |
|
||||
}); |
|
||||
useInputField({ |
|
||||
getValue: () => this.durationFormatted, |
|
||||
refName: "numpadDecimal", |
|
||||
parse: (v) => parseFloatTime(v), |
|
||||
}); |
|
||||
|
|
||||
this.ongoing = |
var TimeCounter = AbstractField.extend({ |
||||
this.props.ongoing !== undefined |
|
||||
? this.props.ongoing |
|
||||
: this.props.record.data.is_user_working; |
|
||||
|
|
||||
onWillStart(async () => { |
willStart: function () { |
||||
if(this.props.ongoing === undefined && !this.props.record.model.useSampleModel && this.props.record.data.task_timer) { |
var self = this; |
||||
const additionalDuration = await this.orm.call('project.task', 'get_working_duration', [this.props.record.resId]); |
var def = this._rpc({ |
||||
this.state.duration += additionalDuration; |
model: 'account.analytic.line', |
||||
} |
method: 'search_read', |
||||
if (this.ongoing) { |
domain: [['task_id', '=', this.res_id], |
||||
this._runTimer(); |
['user_id', '=', self.record.context['uid']]], |
||||
} |
}).then(function (result) { |
||||
|
if (self.mode === 'readonly') { |
||||
|
var currentDate = new Date(); |
||||
|
self.duration = 0; |
||||
|
_.each(result, function (data) { |
||||
|
self.duration += data.date_end ? |
||||
|
self._getDateDifference(data.date_start, data.date_end): |
||||
|
self._getDateDifference(time.auto_str_to_date(data.date_start), currentDate); |
||||
}); |
}); |
||||
onWillUpdateProps((nextProps) => { |
|
||||
const newOngoing = |
|
||||
"ongoing" in nextProps |
|
||||
? nextProps.ongoing |
|
||||
: "record" in nextProps && nextProps.record.data.is_user_working; |
|
||||
const rerun = !this.ongoing && newOngoing; |
|
||||
this.ongoing = newOngoing; |
|
||||
if (rerun) { |
|
||||
this.state.duration = nextProps.value; |
|
||||
this._runTimer(); |
|
||||
} |
} |
||||
}); |
}); |
||||
onWillDestroy(() => clearTimeout(this.timer)); |
return $.when(this._super.apply(this, arguments), def); |
||||
} |
}, |
||||
|
destroy: function () { |
||||
|
this._super.apply(this, arguments); |
||||
|
clearTimeout(this.timer); |
||||
|
}, |
||||
|
isSet: function () { |
||||
|
return true; |
||||
|
}, |
||||
|
_getDateDifference: function (dateStart, dateEnd) { |
||||
|
return moment(dateEnd).diff(moment(dateStart)); |
||||
|
}, |
||||
|
|
||||
get durationFormatted() { |
_render: function () { |
||||
return formatMinutes(this.state.duration); |
this._startTimeCounter(); |
||||
} |
}, |
||||
|
|
||||
_runTimer() { |
/** |
||||
this.timer = setTimeout(() => { |
* Starts a timer to update the field every second if the user is working. |
||||
if (this.ongoing) { |
* Increments the duration by one second each time the timer runs. |
||||
this.state.duration += 1 / 60; |
* Updates the field with the new duration in HH:mm:ss format. |
||||
this._runTimer(); |
*/ |
||||
} |
_startTimeCounter: function () { |
||||
|
var self = this; |
||||
|
clearTimeout(this.timer); |
||||
|
if (this.record.data.is_user_working) { |
||||
|
this.timer = setTimeout(function () { |
||||
|
self.duration += 1000; |
||||
|
self._startTimeCounter(); |
||||
}, 1000); |
}, 1000); |
||||
|
} else { |
||||
|
clearTimeout(this.timer); |
||||
} |
} |
||||
} |
this.$el.html($('<span>' + moment.utc(this.duration).format("HH:mm:ss") + '</span>')); |
||||
|
}, |
||||
|
}); |
||||
|
field_registry.add('timesheet_uoms', TimeCounter); |
||||
|
}); |
||||
|
|
||||
TaskTimer.supportedTypes = ["float"]; |
|
||||
TaskTimer.template = "TaskTimerTemplate"; |
|
||||
|
|
||||
registry.category("fields").add("task_timer", TaskTimer); |
|
||||
registry.category("formatters").add("task_timer", formatMinutes); |
|
@ -1,7 +0,0 @@ |
|||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||
<templates id="template" xml:space="preserve"> |
|
||||
<t t-name="TaskTimerTemplate" owl="1"> |
|
||||
<span t-if="props.readonly" t-esc="durationFormatted"/> |
|
||||
<input t-else="" t-att-id="props.id" t-ref="numpadDecimal" t-att-placeholder="props.placeholder" inputmode="numeric" class="o_input" /> |
|
||||
</t> |
|
||||
</templates> |
|
Loading…
Reference in new issue