Shreya | 5bf24be | 2018-03-21 22:20:46 +0530 | [diff] [blame] | 1 | frappe.provide("erpnext.timesheet"); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 2 | |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 3 | erpnext.timesheet.timer = function (frm, row, timestamp = 0) { |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 4 | let dialog = new frappe.ui.Dialog({ |
| 5 | title: __("Timer"), |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 6 | fields: [ |
| 7 | { |
| 8 | fieldtype: "Link", |
| 9 | label: __("Activity Type"), |
| 10 | fieldname: "activity_type", |
| 11 | reqd: 1, |
| 12 | options: "Activity Type", |
| 13 | }, |
| 14 | { fieldtype: "Link", label: __("Project"), fieldname: "project", options: "Project" }, |
| 15 | { fieldtype: "Link", label: __("Task"), fieldname: "task", options: "Task" }, |
| 16 | { fieldtype: "Float", label: __("Expected Hrs"), fieldname: "expected_hours" }, |
| 17 | { fieldtype: "Section Break" }, |
| 18 | { fieldtype: "HTML", fieldname: "timer_html" }, |
| 19 | ], |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 20 | }); |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 21 | |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 22 | if (row) { |
| 23 | dialog.set_values({ |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 24 | activity_type: row.activity_type, |
| 25 | project: row.project, |
| 26 | task: row.task, |
| 27 | expected_hours: row.expected_hours, |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 28 | }); |
| 29 | } |
Shreya | 5590114 | 2018-03-22 11:40:38 +0530 | [diff] [blame] | 30 | dialog.get_field("timer_html").$wrapper.append(get_timer_html()); |
| 31 | function get_timer_html() { |
| 32 | return ` |
| 33 | <div class="stopwatch"> |
| 34 | <span class="hours">00</span> |
| 35 | <span class="colon">:</span> |
| 36 | <span class="minutes">00</span> |
| 37 | <span class="colon">:</span> |
| 38 | <span class="seconds">00</span> |
| 39 | </div> |
| 40 | <div class="playpause text-center"> |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 41 | <button class= "btn btn-primary btn-start"> ${__("Start")} </button> |
| 42 | <button class= "btn btn-primary btn-complete"> ${__("Complete")} </button> |
Shreya | 5590114 | 2018-03-22 11:40:38 +0530 | [diff] [blame] | 43 | </div> |
| 44 | `; |
Shreya | 822ba21 | 2018-03-22 11:56:05 +0530 | [diff] [blame] | 45 | } |
Shreya | 5590114 | 2018-03-22 11:40:38 +0530 | [diff] [blame] | 46 | erpnext.timesheet.control_timer(frm, dialog, row, timestamp); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 47 | dialog.show(); |
Shreya | 5bf24be | 2018-03-21 22:20:46 +0530 | [diff] [blame] | 48 | }; |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 49 | |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 50 | erpnext.timesheet.control_timer = function (frm, dialog, row, timestamp = 0) { |
shreyashah115@gmail.com | 5281fe8 | 2018-11-27 13:11:30 +0530 | [diff] [blame] | 51 | var $btn_start = dialog.$wrapper.find(".playpause .btn-start"); |
| 52 | var $btn_complete = dialog.$wrapper.find(".playpause .btn-complete"); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 53 | var interval = null; |
Shreya | 5bf24be | 2018-03-21 22:20:46 +0530 | [diff] [blame] | 54 | var currentIncrement = timestamp; |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 55 | var initialized = row ? true : false; |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 56 | var clicked = false; |
Shreya Shah | 5d71609 | 2018-04-02 10:32:39 +0530 | [diff] [blame] | 57 | var flag = true; // Alert only once |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 58 | // If row with not completed status, initialize timer with the time elapsed on click of 'Start Timer'. |
| 59 | if (row) { |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 60 | initialized = true; |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 61 | $btn_start.hide(); |
| 62 | $btn_complete.show(); |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 63 | initializeTimer(); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 64 | } |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 65 | |
| 66 | if (!initialized) { |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 67 | $btn_complete.hide(); |
| 68 | } |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 69 | |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 70 | $btn_start.click(function (e) { |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 71 | if (!initialized) { |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 72 | // New activity if no activities found |
| 73 | var args = dialog.get_values(); |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 74 | if (!args) return; |
| 75 | if ( |
| 76 | frm.doc.time_logs.length == 1 && |
| 77 | !frm.doc.time_logs[0].activity_type && |
| 78 | !frm.doc.time_logs[0].from_time |
| 79 | ) { |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 80 | frm.doc.time_logs = []; |
| 81 | } |
| 82 | row = frappe.model.add_child(frm.doc, "Timesheet Detail", "time_logs"); |
| 83 | row.activity_type = args.activity_type; |
| 84 | row.from_time = frappe.datetime.get_datetime_as_string(); |
Shreya | 8bb0f05 | 2018-03-23 11:46:45 +0530 | [diff] [blame] | 85 | row.project = args.project; |
| 86 | row.task = args.task; |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 87 | row.expected_hours = args.expected_hours; |
| 88 | row.completed = 0; |
Shreya | 5bf24be | 2018-03-21 22:20:46 +0530 | [diff] [blame] | 89 | let d = moment(row.from_time); |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 90 | if (row.expected_hours) { |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 91 | d.add(row.expected_hours, "hours"); |
Rushabh Mehta | 096b943 | 2018-06-25 22:37:43 +0530 | [diff] [blame] | 92 | row.to_time = d.format(frappe.defaultDatetimeFormat); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 93 | } |
| 94 | frm.refresh_field("time_logs"); |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 95 | frm.save(); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 96 | } |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 97 | |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 98 | if (clicked) { |
| 99 | e.preventDefault(); |
| 100 | return false; |
| 101 | } |
| 102 | |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 103 | if (!initialized) { |
| 104 | initialized = true; |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 105 | $btn_start.hide(); |
| 106 | $btn_complete.show(); |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 107 | initializeTimer(); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 108 | } |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 109 | }); |
| 110 | |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 111 | // Stop the timer and update the time logged by the timer on click of 'Complete' button |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 112 | $btn_complete.click(function () { |
| 113 | var grid_row = cur_frm.fields_dict["time_logs"].grid.get_row(row.idx - 1); |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 114 | var args = dialog.get_values(); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 115 | grid_row.doc.completed = 1; |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 116 | grid_row.doc.activity_type = args.activity_type; |
| 117 | grid_row.doc.project = args.project; |
Shreya | 8bb0f05 | 2018-03-23 11:46:45 +0530 | [diff] [blame] | 118 | grid_row.doc.task = args.task; |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 119 | grid_row.doc.expected_hours = args.expected_hours; |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 120 | grid_row.doc.hours = currentIncrement / 3600; |
| 121 | grid_row.doc.to_time = frappe.datetime.now_datetime(); |
| 122 | grid_row.refresh(); |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 123 | frm.dirty(); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 124 | frm.save(); |
| 125 | reset(); |
| 126 | dialog.hide(); |
Shreya | 5bf24be | 2018-03-21 22:20:46 +0530 | [diff] [blame] | 127 | }); |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 128 | |
| 129 | function initializeTimer() { |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 130 | interval = setInterval(function () { |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 131 | var current = setCurrentIncrement(); |
| 132 | updateStopwatch(current); |
| 133 | }, 1000); |
| 134 | } |
| 135 | |
| 136 | function updateStopwatch(increment) { |
| 137 | var hours = Math.floor(increment / 3600); |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 138 | var minutes = Math.floor((increment - hours * 3600) / 60); |
| 139 | var seconds = increment - hours * 3600 - minutes * 60; |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 140 | |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 141 | // If modal is closed by clicking anywhere outside, reset the timer |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 142 | if (!$(".modal-dialog").is(":visible")) { |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 143 | reset(); |
| 144 | } |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 145 | if (hours > 99999) reset(); |
| 146 | if (cur_dialog && cur_dialog.get_value("expected_hours") > 0) { |
| 147 | if (flag && currentIncrement >= cur_dialog.get_value("expected_hours") * 3600) { |
Shreya Shah | 5d71609 | 2018-04-02 10:32:39 +0530 | [diff] [blame] | 148 | frappe.utils.play_sound("alert"); |
| 149 | frappe.msgprint(__("Timer exceeded the given hours.")); |
| 150 | flag = false; |
| 151 | } |
| 152 | } |
Ankush Menat | ec74a5e | 2024-03-10 19:45:40 +0530 | [diff] [blame] | 153 | $(".hours").text(hours < 10 ? "0" + hours.toString() : hours.toString()); |
| 154 | $(".minutes").text(minutes < 10 ? "0" + minutes.toString() : minutes.toString()); |
| 155 | $(".seconds").text(seconds < 10 ? "0" + seconds.toString() : seconds.toString()); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | function setCurrentIncrement() { |
| 159 | currentIncrement += 1; |
| 160 | return currentIncrement; |
| 161 | } |
| 162 | |
| 163 | function reset() { |
| 164 | currentIncrement = 0; |
Deepesh Garg | 64802d1 | 2022-11-20 19:45:51 +0530 | [diff] [blame] | 165 | initialized = false; |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 166 | clearInterval(interval); |
| 167 | $(".hours").text("00"); |
| 168 | $(".minutes").text("00"); |
| 169 | $(".seconds").text("00"); |
Shreya | 8f06266 | 2018-03-21 22:20:11 +0530 | [diff] [blame] | 170 | $btn_complete.hide(); |
| 171 | $btn_start.show(); |
Shreya | 68ec22a | 2018-03-21 19:25:56 +0530 | [diff] [blame] | 172 | } |
Ankush Menat | 4551d7d | 2021-08-19 13:41:10 +0530 | [diff] [blame] | 173 | }; |