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
Follow below steps to create timer widget:
- Create models|class to hold start_date, deadline_date and duration
- Create form view to show countdown timer
- 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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'); | |
}; |
5 Comments
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.
ReplyDeleteThanks for ur comment, can u please share your code here
Deletecan use this in odoo 14?
ReplyDeleteI think the answer is no, Because Odoo14 uses different JS syntax
DeleteBut you can use the same logic for latest versions of odoo
Delete