Search Here

Countdown Timer - Time Counter Custom Widget in Odoo

 In this article I am going to show you how to create countdown timer custom widget in Odoo8. To create time counter or countdown timer in Odoo we are going to use JavaScript.

How to Create Countdown Timer Custom Widget in Odoo

How to Create Countdown Timer Custom Widget in Odoo

Follow below steps to create timer widget:
  1. Create models|class to hold start_date, deadline_date and duration
  2. Create form view to show countdown timer
  3. Create JavaScript file for custom widget under static/src/js folder to show countdown timer

Create models|class to hold start_date, deadline_date and duration



# -*- coding: utf-8 -*-
from openerp import models, fields, api
from datetime import datetime, timedelta, date
class Time_Counter(models.Model):
_name = 'time.counter'
deadline = fields.Datetime(string="Deadline")
start_time = fields.Datetime(string="Start Time")
duration = fields.Integer(string="Durration")
time_left = fields.Float(string="Time Left", readonly=True)
@api.multi
def btn_start_time(self):
self.start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
@api.multi
def _calc_time_left(self, deadline, start_time, duration):
if deadline:
if start_time and self.duration:
new_time = datetime.strptime(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '%Y-%m-%d %H:%M:%S')
n_diff = datetime.strptime(deadline, '%Y-%m-%d %H:%M:%S') - new_time
n_duration_in_s = n_diff.total_seconds()
if n_duration_in_s > 0:
if int(n_duration_in_s) < (int(duration) * 60):
return n_duration_in_s
else:
return n_duration_in_s
deadline = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S') + timedelta(minutes=int(duration))
else:
deadline = datetime.strptime(deadline, '%Y-%m-%d %H:%M:%S')
now = datetime.strptime(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '%Y-%m-%d %H:%M:%S')
diff = deadline - now
duration_in_s = diff.total_seconds()
return duration_in_s
else:
return 0
def calc_time_js(self, cr ,uid, ids, context=None):
obj = self.pool.get('time.counter').browse(cr, uid, ids)
de = obj.deadline
ds = obj.start_time
dd = obj.duration
result = obj._calc_time_left(de,ds,dd)
return result

Create form view to show countdown timer


<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<template id="assets_backend" name="web_custom_assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/my_custom_module/static/src/js/time_counter.js" />
</xpath>
</template>
<record model="ir.ui.view" id="view_custom_time_counter_form">
<field name="name">custom.time.counter.form</field>
<field name="model">time.counter</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Time Counter">
<header>
<button name="btn_start_time" type="object" string="Start" class="oe_highlight" />
</header>
<sheet>
<group>
<field name="duration" />
<field name="deadline" />
<field name="start_time" readonly="1" />
</group>
<group>
<div class="text-center">
<div id="timecounter" class="btn btn-info cols-xs-6 " style="min-width:30%">
<strong>
<field class="text-monospace cols-xs-6" name="time_left" widget="time_counter" />
</strong>
</div>
</div>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="action_custom_time_counter">
<field name="name">Time Counter</field>
<field name="res_model">time.counter</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="custom_time_counter_menu" name="Show Time Counter" action="action_custom_time_counter" sequence="1" />
</data>
</openerp>

Create JavaScript file for custom widget under static/src/js folder to show countdown timer


openerp.my_custom_module = function (instance){
instance.web.form.MyCustomWidget = instance.web.form.AbstractField.extend(instance.web.form.ReinitializeFieldMixin,
{
init: function(field_manager, node) {
this._super.apply(this, arguments);
},
start: function() {
var self = this;
this._super.apply(this, arguments);
this.field_manager.on("view_content_has_changed", this, function () {
// your logic goes here
});
},
startTimeCounter: function(){
var self = this;
clearTimeout(this.timer);
if (self.duration) {
this.duration -= 1;
this.timer = setTimeout(function() {
// your logic goes here
}, 1000);
this.$el.html($('<span>' +self.secondsToDhms(self.duration) + '</span>'));
}
else {
this.$el.html($('<span>' +self.secondsToDhms(0.0) + '</span>'));
}
},
secondsToDhms: function(seconds) {
seconds = Number(seconds);
var d = Math.floor(seconds / (3600*24));
var h = // your logic goes here for hours
var m = // your logic goes here for min
var s = // your logic goes here for sec
var dDisplay = d >= 0 ? "<span style='font-family: Consolas;font-size:24px;letter-spacing: .25em'>"+("0" + d).slice(-2)+"</span>":"";
// your logic goes here for hours
// your logic goes here for min
// your logic goes here for sec
return dDisplay +"<span style='font-family: Consolas;font-size:18px;letter-spacing: .50em'>:</span>"+hDisplay+"<span style='font-family: Consolas;font-size:18px;letter-spacing: .50em'>:</span>"+ mDisplay +"<span style='font-family: Consolas;font-size:18px;letter-spacing: .50em'>:</span>"+ sDisplay;
},
updateValue: function() {
this._super.apply(this, arguments);
var self = this;
this.duration;
if (self.get("effective_readonly")) {
// your logic goes here
var model = new instance.web.Model(this.view.model);
model.call("calc_time_js", [[this.view.datarecord.id]], {context: new instance.web.CompoundContext()}).then(function(result)
{
// your logic goes here
}
});
this.$el.html($('<span>' +self.secondsToDhms(0.0) + '</span>'));
}
},
});
openerp.web.form.widgets.add('time_counter', 'instance.web.form.MyCustomWidget');
};

Post a Comment

5 Comments

  1. Thanks for de interesting widget. I try to implement but I can't, please you can to send me the code that the example. I have error on js file (I am not very familiar with odoo js). Please, thanks and I hope your answer.

    ReplyDelete
    Replies
    1. Thanks for ur comment, can u please share your code here

      Delete
  2. Replies
    1. I think the answer is no, Because Odoo14 uses different JS syntax

      Delete
    2. But you can use the same logic for latest versions of odoo

      Delete