mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-21 05:59:18 +00:00
new dialog to create activity
This commit is contained in:
@@ -50,139 +50,51 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.total_hours && frm.doc.docstatus < 2) {
|
if (frm.doc.docstatus < 2) {
|
||||||
frm.add_custom_button(__('Start Timer'), function() {
|
|
||||||
frm.trigger("timer")
|
|
||||||
}).addClass("btn-primary");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
frm.add_custom_button(__('Start Timer'), function() {
|
||||||
|
var flag = true;
|
||||||
|
|
||||||
|
// Fetch the row for timer where status = Pending i.e in progress
|
||||||
|
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||||
|
if(row.status == 'Pending') {
|
||||||
|
timer(frm, row);
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Fetch the row for timer where status = Not Started
|
||||||
|
if (flag) {
|
||||||
|
$.each(frm.doc.time_logs || [], function(i, row) {
|
||||||
|
if(row.status == 'Not Started') {
|
||||||
|
timer(frm, row);
|
||||||
|
flag = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// If no activities found to start a timer
|
||||||
|
if (flag) {
|
||||||
|
frappe.msgprint(__("No activities remaining."));
|
||||||
|
}
|
||||||
|
}).addClass("btn-primary");
|
||||||
|
|
||||||
|
frm.add_custom_button(__("Create Activity"), function() {
|
||||||
|
create_activity(frm);
|
||||||
|
})
|
||||||
|
}
|
||||||
if(frm.doc.per_billed > 0) {
|
if(frm.doc.per_billed > 0) {
|
||||||
frm.fields_dict["time_logs"].grid.toggle_enable("billing_hours", false);
|
frm.fields_dict["time_logs"].grid.toggle_enable("billing_hours", false);
|
||||||
frm.fields_dict["time_logs"].grid.toggle_enable("billable", false);
|
frm.fields_dict["time_logs"].grid.toggle_enable("billable", false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
timer: function(frm) {
|
|
||||||
let dialog = new frappe.ui.Dialog({
|
|
||||||
title: __("Timer"),
|
|
||||||
fields: [
|
|
||||||
{"fieldtype": "Select", "label": __("Activity"),
|
|
||||||
"fieldname": "activity",
|
|
||||||
"options": frm.doc.time_logs.map(d => d.activity_type),
|
|
||||||
"reqd": 1,
|
|
||||||
onchange: () => {
|
|
||||||
const activity = dialog.get_value("activity")
|
|
||||||
const hours = frm.doc.time_logs.filter(d => d.activity_type == activity).map(d => d.hours);
|
|
||||||
const project = frm.doc.time_logs.filter(d => d.activity_type == activity).map(d => d.project)
|
|
||||||
|
|
||||||
dialog.set_value("hours", hours)
|
|
||||||
dialog.set_value("project", project)
|
|
||||||
}},
|
|
||||||
{"fieldtype": "Read Only", "label": __("Project"),
|
|
||||||
"fieldname": "project"},
|
|
||||||
{"fieldtype": "Read Only", "label": __("Hours"),
|
|
||||||
"fieldname": "hours"}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
dialog.wrapper.append(frappe.render_template("timesheet"));
|
|
||||||
frm.trigger("control_timer");
|
|
||||||
dialog.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
control_timer: function() {
|
|
||||||
var interval = null;
|
|
||||||
var currentIncrement = 0;
|
|
||||||
var isPaused = false;
|
|
||||||
var initialised = false;
|
|
||||||
var clicked = false;
|
|
||||||
var paused_time = 0;
|
|
||||||
|
|
||||||
$(".playpause").click(function(e) {
|
|
||||||
if (!cur_dialog.get_value('activity')) {
|
|
||||||
frappe.msgprint(__("Please select Activity"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clicked) {
|
|
||||||
e.preventDefault();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!initialised) {
|
|
||||||
initialised = true;
|
|
||||||
isPaused = false;
|
|
||||||
$(".playpause span").removeClass();
|
|
||||||
$(".playpause span").addClass("pause");
|
|
||||||
initialiseTimer();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$(".playpause span").removeClass();
|
|
||||||
if (isPaused) {
|
|
||||||
isPaused = false;
|
|
||||||
$(".playpause span").addClass("pause");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
isPaused = true;
|
|
||||||
$(".playpause span").addClass("play");
|
|
||||||
paused_time = currentIncrement;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$(".stop").click(function() {
|
|
||||||
console.log(currentIncrement);
|
|
||||||
reset();
|
|
||||||
});
|
|
||||||
|
|
||||||
function initialiseTimer() {
|
|
||||||
interval = setInterval(function() {
|
|
||||||
if (isPaused) return;
|
|
||||||
var current = setCurrentIncrement();
|
|
||||||
updateStopwatch(current);
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateStopwatch(increment) {
|
|
||||||
var hours = Math.floor(increment / 3600);
|
|
||||||
var minutes = Math.floor((increment - (hours * 3600)) / 60);
|
|
||||||
var seconds = increment - (hours * 3600) - (minutes * 60);
|
|
||||||
// if(!$('modal-open:visible')){
|
|
||||||
// reset();
|
|
||||||
// }
|
|
||||||
if (!$('.modal-dialog').is(':visible')) {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
if(hours > 99)
|
|
||||||
reset();
|
|
||||||
if(cur_dialog && cur_dialog.get_value('hours') == hours) {
|
|
||||||
isPaused = true;
|
|
||||||
initialised = false;
|
|
||||||
frappe.utils.play_sound("alert");
|
|
||||||
frappe.msgprint(__("Timer exceeded the given hours"));
|
|
||||||
}
|
|
||||||
$(".hours").text(hours < 10 ? ("0" + hours.toString()) : hours.toString());
|
|
||||||
$(".minutes").text(minutes < 10 ? ("0" + minutes.toString()) : minutes.toString());
|
|
||||||
$(".seconds").text(seconds < 10 ? ("0" + seconds.toString()) : seconds.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCurrentIncrement() {
|
|
||||||
currentIncrement += 1;
|
|
||||||
return currentIncrement;
|
|
||||||
}
|
|
||||||
|
|
||||||
function reset() {
|
|
||||||
currentIncrement = 0;
|
|
||||||
isPaused = true;
|
|
||||||
initialised = false;
|
|
||||||
clearInterval(interval);
|
|
||||||
$(".hours").text("00");
|
|
||||||
$(".minutes").text("00");
|
|
||||||
$(".seconds").text("00");
|
|
||||||
$(".playpause span").removeClass();
|
|
||||||
$(".playpause span").addClass("play");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
// var $trigger = $('.form-grid').find('.grid-row').find('.btn-open-row');
|
||||||
|
// $trigger.on('click', () => {
|
||||||
|
// $('.form-grid')
|
||||||
|
// .find('[data-fieldname="timer"]')
|
||||||
|
// .append(frappe.render_template("timesheet"));
|
||||||
|
// frm.trigger("control_timer");
|
||||||
|
// })
|
||||||
make_invoice: function(frm) {
|
make_invoice: function(frm) {
|
||||||
let dialog = new frappe.ui.Dialog({
|
let dialog = new frappe.ui.Dialog({
|
||||||
title: __("Select Item (optional)"),
|
title: __("Select Item (optional)"),
|
||||||
@@ -213,7 +125,6 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -241,7 +152,15 @@ frappe.ui.form.on("Timesheet Detail", {
|
|||||||
frappe.model.set_value(cdt, cdn, "hours", moment(child.to_time).diff(moment(child.from_time),
|
frappe.model.set_value(cdt, cdn, "hours", moment(child.to_time).diff(moment(child.from_time),
|
||||||
"seconds") / 3600);
|
"seconds") / 3600);
|
||||||
},
|
},
|
||||||
|
time_logs_add: function(frm) {
|
||||||
|
var $trigger_again = $('.form-grid').find('.grid-row').find('.btn-open-row');
|
||||||
|
$trigger_again.on('click', () => {
|
||||||
|
$('.form-grid')
|
||||||
|
.find('[data-fieldname="timer"]')
|
||||||
|
.append(frappe.render_template("timesheet"));
|
||||||
|
frm.trigger("control_timer");
|
||||||
|
})
|
||||||
|
},
|
||||||
hours: function(frm, cdt, cdn) {
|
hours: function(frm, cdt, cdn) {
|
||||||
calculate_end_time(frm, cdt, cdn)
|
calculate_end_time(frm, cdt, cdn)
|
||||||
},
|
},
|
||||||
@@ -285,6 +204,173 @@ frappe.ui.form.on("Timesheet Detail", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Spawn dialog for timer when clicked on 'Start RTimer' button
|
||||||
|
var timer = function(frm, row) {
|
||||||
|
let dialog = new frappe.ui.Dialog({
|
||||||
|
title: __("Timer"),
|
||||||
|
fields: [
|
||||||
|
{"fieldtype": "Read Only", "label": __("Activity"),
|
||||||
|
"fieldname": "activity"
|
||||||
|
// onchange: () => {
|
||||||
|
// const activity = dialog.get_value("activity")
|
||||||
|
// const hours = frm.doc.time_logs.filter(d => d.activity_type == activity).map(d => d.hours);
|
||||||
|
// const project = frm.doc.time_logs.filter(d => d.activity_type == activity).map(d => d.project)
|
||||||
|
|
||||||
|
// dialog.set_value("hours", hours)
|
||||||
|
// dialog.set_value("project", project)
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
{"fieldtype": "Read Only", "label": __("Project"),
|
||||||
|
"fieldname": "project"},
|
||||||
|
{"fieldtype": "Read Only", "label": __("Hours"),
|
||||||
|
"fieldname": "hours"}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
dialog.set_values({
|
||||||
|
'activity': row.activity_type,
|
||||||
|
'project': row.project,
|
||||||
|
'hours': row.hours
|
||||||
|
});
|
||||||
|
dialog.wrapper.append(frappe.render_template("timesheet"));
|
||||||
|
control_timer(frm, row, dialog);
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
var control_timer = function(frm, row, dialog) {
|
||||||
|
var interval = null;
|
||||||
|
var currentIncrement = 0;
|
||||||
|
var isPaused = false;
|
||||||
|
var initialised = row ? true : false;
|
||||||
|
var clicked = false;
|
||||||
|
var paused_time = 0;
|
||||||
|
|
||||||
|
// If row with status = Pending/ Not Completed found, initialize timer on click of 'Start Timer'
|
||||||
|
if (row) {
|
||||||
|
initialised = true;
|
||||||
|
$(".playpause span").removeClass();
|
||||||
|
$(".playpause span").addClass("pause");
|
||||||
|
initialiseTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".playpause").click(function(e) {
|
||||||
|
if (clicked) {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initialised) {
|
||||||
|
initialised = true;
|
||||||
|
isPaused = false;
|
||||||
|
$(".playpause span").removeClass();
|
||||||
|
$(".playpause span").addClass("pause");
|
||||||
|
initialiseTimer();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(".playpause span").removeClass();
|
||||||
|
if (isPaused) {
|
||||||
|
isPaused = false;
|
||||||
|
$(".playpause span").addClass("pause");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isPaused = true;
|
||||||
|
$(".playpause span").addClass("play");
|
||||||
|
paused_time = currentIncrement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// $(".stop").click(function() {
|
||||||
|
// reset();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Stop the timer and save the time logged by the timer on click of 'Complete' button
|
||||||
|
dialog.set_primary_action(__("Complete"), function() {
|
||||||
|
var grid_row = cur_frm.fields_dict['time_logs'].grid.grid_rows_by_docname[row.name];
|
||||||
|
// console.log(grid_row);
|
||||||
|
grid_row.doc.timer_timestamp = currentIncrement;
|
||||||
|
grid_row.doc.status = "Completed";
|
||||||
|
grid_row.refresh();
|
||||||
|
// Save the form
|
||||||
|
frm.save();
|
||||||
|
// frm.set_value(row.timer_timestamp, currentIncrement);
|
||||||
|
reset();
|
||||||
|
dialog.hide();
|
||||||
|
})
|
||||||
|
function initialiseTimer() {
|
||||||
|
interval = setInterval(function() {
|
||||||
|
if (isPaused) return;
|
||||||
|
var current = setCurrentIncrement();
|
||||||
|
updateStopwatch(current);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateStopwatch(increment) {
|
||||||
|
var hours = Math.floor(increment / 3600);
|
||||||
|
var minutes = Math.floor((increment - (hours * 3600)) / 60);
|
||||||
|
var seconds = increment - (hours * 3600) - (minutes * 60);
|
||||||
|
|
||||||
|
// If modal is closed by clicking outside anywhere the modal, reset the timer
|
||||||
|
if (!$('.modal-dialog').is(':visible')) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
if(hours > 99)
|
||||||
|
reset();
|
||||||
|
if(cur_dialog && cur_dialog.get_value('hours') == hours) {
|
||||||
|
isPaused = true;
|
||||||
|
initialised = false;
|
||||||
|
frappe.utils.play_sound("alert");
|
||||||
|
frappe.msgprint(__("Timer exceeded the given hours"));
|
||||||
|
}
|
||||||
|
$(".hours").text(hours < 10 ? ("0" + hours.toString()) : hours.toString());
|
||||||
|
$(".minutes").text(minutes < 10 ? ("0" + minutes.toString()) : minutes.toString());
|
||||||
|
$(".seconds").text(seconds < 10 ? ("0" + seconds.toString()) : seconds.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCurrentIncrement() {
|
||||||
|
currentIncrement += 1;
|
||||||
|
return currentIncrement;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
currentIncrement = 0;
|
||||||
|
isPaused = true;
|
||||||
|
initialised = false;
|
||||||
|
clearInterval(interval);
|
||||||
|
$(".hours").text("00");
|
||||||
|
$(".minutes").text("00");
|
||||||
|
$(".seconds").text("00");
|
||||||
|
$(".playpause span").removeClass();
|
||||||
|
$(".playpause span").addClass("play");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var create_activity = function(frm) {
|
||||||
|
let dialog = new frappe.ui.Dialog({
|
||||||
|
title: __("New Activity"),
|
||||||
|
fields: [
|
||||||
|
{"fieldtype": "Link", "label": __("Activity Type"), "fieldname": "activity_type",
|
||||||
|
"options": "Activity Type", "reqd": 1},
|
||||||
|
{"fieldtype": "Float", "label": __("Hrs"), "fieldname": "hours"},
|
||||||
|
{"fieldtype": "Link", "label": __("Project"), "fieldname": "project",
|
||||||
|
"options": "Project"}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
dialog.set_primary_action(__("Add Activity"), () => {
|
||||||
|
var args = dialog.get_values();
|
||||||
|
if(!args) return;
|
||||||
|
var row = frappe.model.add_child(frm.doc, "Timesheet Detail", "time_logs");
|
||||||
|
row.activity_type = args.activity_type;
|
||||||
|
row.hours = args.hours;
|
||||||
|
row.from_time = frappe.datetime.now_datetime();
|
||||||
|
row.project = args.project;
|
||||||
|
frm.refresh_field("time_logs");
|
||||||
|
dialog.hide();
|
||||||
|
timer(frm, row);
|
||||||
|
})
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
var calculate_end_time = function(frm, cdt, cdn) {
|
var calculate_end_time = function(frm, cdt, cdn) {
|
||||||
let child = locals[cdt][cdn];
|
let child = locals[cdt][cdn];
|
||||||
|
|
||||||
|
|||||||
@@ -166,8 +166,6 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -200,7 +198,6 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
>>>>>>> added status field/
|
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@@ -965,11 +962,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
<<<<<<< HEAD
|
|
||||||
"modified": "2018-01-07 11:46:04.045313",
|
|
||||||
=======
|
|
||||||
"modified": "2018-03-19 09:50:53.116469",
|
"modified": "2018-03-19 09:50:53.116469",
|
||||||
>>>>>>> added status field/
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Timesheet Detail",
|
"name": "Timesheet Detail",
|
||||||
|
|||||||
Reference in New Issue
Block a user