blob: 0e5c0d3720e87acf3e27b0bf7816f9e593055aed [file] [log] [blame]
Shreya5bf24be2018-03-21 22:20:46 +05301frappe.provide("erpnext.timesheet");
Shreya68ec22a2018-03-21 19:25:56 +05302
Shreya8f062662018-03-21 22:20:11 +05303erpnext.timesheet.timer = function(frm, row, timestamp=0) {
Shreya68ec22a2018-03-21 19:25:56 +05304 let dialog = new frappe.ui.Dialog({
5 title: __("Timer"),
6 fields:
7 [
8 {"fieldtype": "Link", "label": __("Activity Type"), "fieldname": "activity_type",
Shreya8f062662018-03-21 22:20:11 +05309 "reqd": 1, "options": "Activity Type"},
10 {"fieldtype": "Link", "label": __("Project"), "fieldname": "project", "options": "Project"},
Shreya8bb0f052018-03-23 11:46:45 +053011 {"fieldtype": "Link", "label": __("Task"), "fieldname": "task", "options": "Task"},
Shreya68ec22a2018-03-21 19:25:56 +053012 {"fieldtype": "Float", "label": __("Expected Hrs"), "fieldname": "expected_hours"},
13 {"fieldtype": "Section Break"},
14 {"fieldtype": "HTML", "fieldname": "timer_html"}
15 ]
Shreya68ec22a2018-03-21 19:25:56 +053016 });
Shreya8f062662018-03-21 22:20:11 +053017
Shreya68ec22a2018-03-21 19:25:56 +053018 if (row) {
19 dialog.set_values({
20 'activity_type': row.activity_type,
21 'project': row.project,
Shreya8bb0f052018-03-23 11:46:45 +053022 'task': row.task,
Shreya68ec22a2018-03-21 19:25:56 +053023 'expected_hours': row.expected_hours
24 });
25 }
Shreya55901142018-03-22 11:40:38 +053026 dialog.get_field("timer_html").$wrapper.append(get_timer_html());
27 function get_timer_html() {
28 return `
29 <div class="stopwatch">
30 <span class="hours">00</span>
31 <span class="colon">:</span>
32 <span class="minutes">00</span>
33 <span class="colon">:</span>
34 <span class="seconds">00</span>
35 </div>
36 <div class="playpause text-center">
37 <button class= "btn btn-primary btn-start"> ${ __("Start") } </button>
38 <button class= "btn btn-primary btn-complete"> ${ __("Complete") } </button>
39 </div>
40 `;
Shreya822ba212018-03-22 11:56:05 +053041 }
Shreya55901142018-03-22 11:40:38 +053042 erpnext.timesheet.control_timer(frm, dialog, row, timestamp);
Shreya68ec22a2018-03-21 19:25:56 +053043 dialog.show();
Shreya5bf24be2018-03-21 22:20:46 +053044};
Shreya68ec22a2018-03-21 19:25:56 +053045
Shreya55901142018-03-22 11:40:38 +053046erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
shreyashah115@gmail.com5281fe82018-11-27 13:11:30 +053047 var $btn_start = dialog.$wrapper.find(".playpause .btn-start");
48 var $btn_complete = dialog.$wrapper.find(".playpause .btn-complete");
Shreya68ec22a2018-03-21 19:25:56 +053049 var interval = null;
Shreya5bf24be2018-03-21 22:20:46 +053050 var currentIncrement = timestamp;
Shreya68ec22a2018-03-21 19:25:56 +053051 var initialised = row ? true : false;
52 var clicked = false;
Shreya Shah5d716092018-04-02 10:32:39 +053053 var flag = true; // Alert only once
Shreya68ec22a2018-03-21 19:25:56 +053054 // If row with not completed status, initialize timer with the time elapsed on click of 'Start Timer'.
55 if (row) {
56 initialised = true;
Shreya8f062662018-03-21 22:20:11 +053057 $btn_start.hide();
58 $btn_complete.show();
Shreya68ec22a2018-03-21 19:25:56 +053059 initialiseTimer();
60 }
Shreya8f062662018-03-21 22:20:11 +053061 if (!initialised) {
62 $btn_complete.hide();
63 }
Shreya68ec22a2018-03-21 19:25:56 +053064 $btn_start.click(function(e) {
65 if (!initialised) {
66 // New activity if no activities found
67 var args = dialog.get_values();
68 if(!args) return;
Shreya Shah5d716092018-04-02 10:32:39 +053069 if (frm.doc.time_logs.length <= 1 && !frm.doc.time_logs[0].activity_type && !frm.doc.time_logs[0].from_time) {
Shreya68ec22a2018-03-21 19:25:56 +053070 frm.doc.time_logs = [];
71 }
72 row = frappe.model.add_child(frm.doc, "Timesheet Detail", "time_logs");
73 row.activity_type = args.activity_type;
74 row.from_time = frappe.datetime.get_datetime_as_string();
Shreya8bb0f052018-03-23 11:46:45 +053075 row.project = args.project;
76 row.task = args.task;
Shreya68ec22a2018-03-21 19:25:56 +053077 row.expected_hours = args.expected_hours;
78 row.completed = 0;
Shreya5bf24be2018-03-21 22:20:46 +053079 let d = moment(row.from_time);
Shreya68ec22a2018-03-21 19:25:56 +053080 if(row.expected_hours) {
81 d.add(row.expected_hours, "hours");
Rushabh Mehta096b9432018-06-25 22:37:43 +053082 row.to_time = d.format(frappe.defaultDatetimeFormat);
Shreya68ec22a2018-03-21 19:25:56 +053083 }
84 frm.refresh_field("time_logs");
Shreya8f062662018-03-21 22:20:11 +053085 frm.save();
Shreya68ec22a2018-03-21 19:25:56 +053086 }
Shreya8f062662018-03-21 22:20:11 +053087
Shreya68ec22a2018-03-21 19:25:56 +053088 if (clicked) {
89 e.preventDefault();
90 return false;
91 }
92
93 if (!initialised) {
94 initialised = true;
Shreya8f062662018-03-21 22:20:11 +053095 $btn_start.hide();
96 $btn_complete.show();
Shreya68ec22a2018-03-21 19:25:56 +053097 initialiseTimer();
98 }
Shreya68ec22a2018-03-21 19:25:56 +053099 });
100
Shreya8f062662018-03-21 22:20:11 +0530101 // Stop the timer and update the time logged by the timer on click of 'Complete' button
102 $btn_complete.click(function() {
Shreya822ba212018-03-22 11:56:05 +0530103 var grid_row = cur_frm.fields_dict['time_logs'].grid.get_row(row.idx - 1);
Shreya8f062662018-03-21 22:20:11 +0530104 var args = dialog.get_values();
Shreya68ec22a2018-03-21 19:25:56 +0530105 grid_row.doc.completed = 1;
Shreya8f062662018-03-21 22:20:11 +0530106 grid_row.doc.activity_type = args.activity_type;
107 grid_row.doc.project = args.project;
Shreya8bb0f052018-03-23 11:46:45 +0530108 grid_row.doc.task = args.task;
Shreya8f062662018-03-21 22:20:11 +0530109 grid_row.doc.expected_hours = args.expected_hours;
Shreya68ec22a2018-03-21 19:25:56 +0530110 grid_row.doc.hours = currentIncrement / 3600;
111 grid_row.doc.to_time = frappe.datetime.now_datetime();
112 grid_row.refresh();
Shreya68ec22a2018-03-21 19:25:56 +0530113 frm.save();
114 reset();
115 dialog.hide();
Shreya5bf24be2018-03-21 22:20:46 +0530116 });
Shreya68ec22a2018-03-21 19:25:56 +0530117 function initialiseTimer() {
118 interval = setInterval(function() {
Shreya68ec22a2018-03-21 19:25:56 +0530119 var current = setCurrentIncrement();
120 updateStopwatch(current);
121 }, 1000);
122 }
123
124 function updateStopwatch(increment) {
125 var hours = Math.floor(increment / 3600);
126 var minutes = Math.floor((increment - (hours * 3600)) / 60);
127 var seconds = increment - (hours * 3600) - (minutes * 60);
128
Shreya8f062662018-03-21 22:20:11 +0530129 // If modal is closed by clicking anywhere outside, reset the timer
Shreya68ec22a2018-03-21 19:25:56 +0530130 if (!$('.modal-dialog').is(':visible')) {
131 reset();
132 }
Shreya Shah5d716092018-04-02 10:32:39 +0530133 if(hours > 99999)
Shreya5bf24be2018-03-21 22:20:46 +0530134 reset();
Shreya Shah5d716092018-04-02 10:32:39 +0530135 if(cur_dialog && cur_dialog.get_value('expected_hours') > 0) {
136 if(flag && (currentIncrement >= (cur_dialog.get_value('expected_hours') * 3600))) {
137 frappe.utils.play_sound("alert");
138 frappe.msgprint(__("Timer exceeded the given hours."));
139 flag = false;
140 }
141 }
Shreya68ec22a2018-03-21 19:25:56 +0530142 $(".hours").text(hours < 10 ? ("0" + hours.toString()) : hours.toString());
143 $(".minutes").text(minutes < 10 ? ("0" + minutes.toString()) : minutes.toString());
144 $(".seconds").text(seconds < 10 ? ("0" + seconds.toString()) : seconds.toString());
145 }
146
147 function setCurrentIncrement() {
148 currentIncrement += 1;
149 return currentIncrement;
150 }
151
152 function reset() {
153 currentIncrement = 0;
Shreya68ec22a2018-03-21 19:25:56 +0530154 initialised = false;
155 clearInterval(interval);
156 $(".hours").text("00");
157 $(".minutes").text("00");
158 $(".seconds").text("00");
Shreya8f062662018-03-21 22:20:11 +0530159 $btn_complete.hide();
160 $btn_start.show();
Shreya68ec22a2018-03-21 19:25:56 +0530161 }
Ankush Menat4551d7d2021-08-19 13:41:10 +0530162};