You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
3.2 KiB
89 lines
3.2 KiB
/** @odoo-module **/
|
|
import { registry } from "@web/core/registry";
|
|
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;
|
|
// Function for converting the time and return the value in each seconds.
|
|
function formatMinutes(value) {
|
|
if (value === false) {
|
|
return "";
|
|
}
|
|
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 {
|
|
//Extend component to add TaskTimer
|
|
setup() {
|
|
this.orm = useService('orm');
|
|
this.state = useState({
|
|
// Duration is expected to be given in minutes
|
|
duration:this.props?.value ? this.props.value : this.props.record.data.duration,
|
|
});
|
|
useInputField({
|
|
getValue: () => this.durationFormatted,
|
|
refName: "numpadDecimal",
|
|
parse: (v) => parseFloatTime(v),
|
|
});
|
|
|
|
this.ongoing =
|
|
this.props.ongoing !== undefined
|
|
? this.props.ongoing
|
|
: this.props.record.data.is_user_working;
|
|
|
|
onWillStart(async () => {
|
|
//Check the status while form rendering.
|
|
if(this.props.ongoing === undefined && !this.props.record.model.useSampleModel && this.props.record.data.stage_id[0] == this.props.record.data.check_stage) {
|
|
const additionalDuration = await this.orm.call('project.task', 'get_working_duration', [this.props.record.resId]);
|
|
this.state.duration += additionalDuration;
|
|
}
|
|
if (this.ongoing) {
|
|
this._runTimer();
|
|
}
|
|
});
|
|
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.record.data.duration;
|
|
this._runTimer();
|
|
}
|
|
else{
|
|
this.state.duration = nextProps.record.data.duration
|
|
}
|
|
});
|
|
onWillDestroy(() => clearTimeout(this.timer));
|
|
}
|
|
//Getting the formatted time duration
|
|
get durationFormatted() {
|
|
return formatMinutes(this.state.duration);
|
|
}
|
|
//Function for setting the interval and call in each 1000ms
|
|
_runTimer() {
|
|
this.timer = setTimeout(() => {
|
|
if (this.ongoing) {
|
|
this.state.duration += 1 / 60;
|
|
this._runTimer();
|
|
}
|
|
}, 1000);
|
|
}
|
|
}
|
|
|
|
TaskTimer.template = "TaskTimerTemplate";
|
|
export const taskTimer = {
|
|
component: TaskTimer,
|
|
supportedTypes : ["float"],
|
|
};
|
|
//Adding the widget to the field registry
|
|
registry.category("fields").add("task_timer", taskTimer);
|
|
registry.category("formatters").add("task_timer", formatMinutes);
|
|
|