|
- (function ($) {
- $(function () {
-
- // http://davidwalsh.name/javascript-debounce-function
- function debounce(func, wait, immediate) {
- var timeout;
- return function () {
- var context = this, args = arguments;
- var later = function () {
- timeout = null;
- if (!immediate)
- func.apply(context, args);
- };
- var callNow = immediate && !timeout;
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- if (callNow)
- func.apply(context, args);
- };
- };
- /*____________________________________________________________________________________*/
- class People{
- constructor(selector, template, data){
- this.selector = selector;
- this.data = data;
- this.template = template;
- // this.sample_people = {
- // login: '01515b52-6936-46b2-a000-9ad4cd7a5b50',
- // firstname: "first",
- // lastname: "last",
- // phone: '041122221',
- // email: 'abc@gmail.com',
- // pay: 0,
- // hour: 12,
- // OT: 3,
- // petrol: 50,
- // rating: 1,
- // };
- this.load_data(this.data);
- }
-
- load_data(data){
- var template = $(this.template).html();
- var html = Mustache.render(template, data);
- $(this.selector).html(html);
- //save it
- $(this.selector).data({obj:this, data:data});
- //draw rating star
- this.set_ratings(this.data.rating);
- this.set_unconfirmed_job(this.data.unconfirmedjob);
- }
-
- set_ratings(num){
- for (var i=1; i<= 5; i++){
- if (i <=num){
- $(this.selector + " div[name='rating'] span:nth-child(" +i+ ")").addClass('checked');
- }else{
- $(this.selector + " div[name='rating'] span:nth-child(" +i+ ")").removeClass('checked');
- }
- }
- this.data.rating = num;
- }
-
- set_unconfirmed_job(num){
- if( num == 0 )
- $(this.selector + " span[name='badge']").hide();
- else
- $(this.selector + " span[name='badge']").show();
- this.data.unconfirmedjob = num;
- }
-
- reset_summary() {
- this.summary = {
- wages : 0,
- normal_hour : 0,
- ot_hour : 0,
- petrol : 0,
- };
- this.update_summary_in_gui();
- }
-
- add_payment_summary(ps)
- {
- //{ot: false, hour: "2.67", money: "76.90"}
- this.summary.wages += ps.money;
- if (! ps.ot )
- this.summary.normal_hour += ps.hour;
- else
- this.summary.ot_hour += ps.hour;
- this.update_summary_in_gui();
- }
-
- update_summary_in_gui()
- {
- var msg = '$' + this.summary.wages.toFixed(2);
- $(this.selector).find('div[name="wages"]').html(msg);
-
- msg = this.summary.normal_hour.toFixed(2) + '+' +this.summary.ot_hour.toFixed(2) + 'hr';
- $(this.selector).find('div[name="hours"]').html(msg);
-
- msg = 'petrol:' + this.summary.petrol.toFixed(2) + 'km';
- $(this.selector).find('div[name="petrol"]').html(msg);
- }
- }//end of class People
-
- function bts_staff_html(data){
- var template = $('#staff_item').html();
- var head = '<div class="peopleitem" id="p'+ data.login +'">';
- r = head + '</div>' ;
- return r;
- }
-
- function bts_client_html(data){
- var template = $('#client_item').html();
- var head = '<div class="peopleitem" id="p'+ data.login +'">';
- r = head + '</div>' ;
- return r;
- }
-
- function sample_staff(){
- for (var i=1; i<100; i++){
- var sample_people = {
- login: '01515b52-6936-46b2-a000-9ad4cd7a5b50' +i,
- firstname: "first"+i,
- lastname: "last",
- mobile: '041122221' +i,
- email: 'abc@gmail.com' + i,
- wages: 0,
- hour: i,
- OT: 3,
- petrol: 50 +i,
- rating: Math.floor(Math.random() * Math.floor(5)),
- unconfirmedjob: Math.floor(Math.random() * Math.floor(30)),
- };
- var html = bts_staff_html(sample_people);
- jQuery('div.stafflist').append(html);
- new People("#p" + sample_people.login, sample_people);
- }
- }
- function list_staff() {
- show_loading_staff();
- $('div.stafflist div.peopleitem').remove();
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "list_staff", // action
- }).done(function(response, status, xhr){
- if (response.status =='success'){
- bts().staff = response.users;
- bts().staff_map = {};
- response.users.forEach(function(u){
- bts().staff_map[u.login] = u;
- var html = bts_staff_html(u);
- jQuery('div.stafflist').append(html);
- new People("#p" + u.login,'#staff_item', u);
- });
- hide_loading_staff();
- calculate_total_hour_and_money();
- }else{
- alert('error getting staff list');
- }
- });
- }
-
- function list_clients() {
- show_loading_client();
- $('div.clientlist div.peopleitem').remove(); //clear it
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "list_client", // action
- }, function(response, status, xhr){
- if (response.status =='success'){
- bts().client = response.users;
- bts().client_map = {};
- response.users.forEach(function(u){
- bts().client_map[u.login] = u;
- hide_loading_client();
- var html = bts_client_html(u);
- jQuery('div.clientlist').append(html);
- new People("#p" + u.login, '#client_item' ,u);
- });
- }else{
- alert('error getting Client list');
- }
- });
- }
-
- function list_tos() {
- wifi(true);
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "list_tos", // action
- }, function(response, status, xhr){
- if (response.status =='success'){
- bts().tos = response.tos;
- wifi(false);
- }else{
- alert('error getting Type of Service list');
- }
- });
- }
-
- function show_loading_staff(){
- jQuery('div.stafflist img').attr('src', bts().load_user_img).show();
- }
- function show_loading_client(){
- jQuery('div.clientlist img').attr('src', bts().load_user_img).show();
- }
- function hide_loading_staff(){
- jQuery('div.stafflist img').hide();
- }
- function hide_loading_client(){
- jQuery('div.clientlist img').hide();
- }
-
- function show_loading_jobs(){
- jQuery('div.workspace img').attr('src', bts().load_job_img).show();
- }
- function hide_loading_jobs(){
- jQuery('div.workspace img').hide();
- }
-
- function xero(t){
- if (t)
- $('div.xero i').show();
- else
- $('div.xero i').hide();
- }
-
- function wifi(t){
- if (t)
- $('div.wifi i').show();
- else
- $('div.wifi i').hide();
- }
- function csv(t){
- if (t)
- $('div.csv i').show();
- else
- $('div.csv i').hide();
- }
-
-
- function init_user_search(){
- $('div.b_search input').keyup(debounce(function(e){
- filter_user(e.target);
- }, 500));
- }
-
- function filter_user(input){
- var value = $(input).attr('value');
- value = value.toLowerCase();
- var selector = get_selector_for_filter_people(input);
- $.each( $(selector).find('div.peopleitem'), function(index, e){
- //uncheck everyone
- $(e).find('input[type="checkbox"]').prop('checked', false);
-
- var html = $(e).find('div[name="title"] a').html();
- html = html.toLowerCase();
- if (-1 != html.indexOf(value)){//we find it;
- $(e).show();
- }else{
- $(e).hide();
- }
- });
- }
-
- function get_selector_for_filter_people(input){
- var selector='';
- var role = $(input).attr('placeholder');
- if (role == 'staff') //we filter staff
- selector = 'div.stafflist';
- else if (role = 'client')
- selector = 'div.clientlist';
- return selector;
- }
-
-
- $(document).on('click', 'div.divTableHead.bdelete', function(){
- add_new_empty_job();
- });
-
- function add_new_empty_job(){
- var o = new Job({empty:true});
- $('div.workspace').append(o.el);
- o.el.get(0).scrollIntoView();
- dtp_init();
- }
- $(document).on('click', 'div[name="copyschedule"]', function(e){
- e.stopPropagation();
- add_new_empty_job();
- });
-
- $(document).on('click', 'div.divTableCell.bdelete', function(){
- var el = $(this).closest('div.jobTable');
- var data = el.data();
- if (typeof data.id =='undefined' || data.id == '')
- el.remove();
- else{
- var id = data.id;
- if (confirm('delete this job?')){
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "delete_job", // action
- jobid: id,
- }, function(response, status, xhr){
- if (response.status=='success'){
- el.addClass('blink_me');
- el.fadeOut(900);
- setTimeout(function(){
- el.remove();
- }, 900);
-
- }else{
- alert( 'error saving data, please check your network');
- }
- });
- }
- }
- });
-
- $(document).on('mouseenter', 'div.divTableCell', function(){
- $(this).closest('div.divTable').addClass('highlight');
- });
- $(document).on('mouseleave', 'div.divTableCell', function(){
- $(this).closest('div.divTable').removeClass('highlight');
- });
-
- $(document).on('click', 'div.workspace span.ticon.ticon-save', function(){
- var table = $(this).closest('div.divTable');
- table.data().job.do_save_record();
- });
- $(document).on('click', '.divTableHeading span.ticon.ticon-save', function(){
- //save all
- $('div.workspace span.ticon.ticon-save').each(function (i,e){
- if ($(this).is(":visible"))
- $(this).trigger('click');
- });
- });
-
-
- $(document).on('click', 'span.ticon.ticon-copy', function(){
- if (!confirm("make a copy of this job?"))
- return;
- var table = $(this).closest('div.divTable');
- var job = table.data().job;
- var newj = clone_data_create_new_job(job.get_record_from_ui());
- $('div.workspace').append(newj.el);
- newj.el.get(0).scrollIntoView();//make sure it's visible;
- newj.mark_highlight_me(1000);//for 1 second;
- dtp_init();
- });
-
- class Job{ //save data for the record, and display it as GUI
- constructor(selector, data){
- this.el = $(selector);
- //this.load_data(data);
- //this.init_start_rating();
- }
-
- init_start_rating(){
- var self = this;
- this.el.find("div.brating span").click(function(){
- var r = $(this).attr('data-rating');
- self.mark_dirty();
- self.set_rating(r);
- })
-
- this.el.find("div.brating").mouseenter(function(){
- //change to all hollow star
- $(this).find('span').html('☆');
- });
-
- this.el.find("div.brating").mouseleave(function(){
- self.set_rating(self.data.rating);
- });
-
- }
-
- load_data(data)
- {
- //save to html element
- this.data = data;
- this.el.data({job:this, data:data});
-
- //draw GUI
- this.clear_err_msg();
- this.set_job_id(data.id);
- this.set_tos(data.tos);
- this.set_start(data.start);
- this.set_finish(data.finish);
- this.set_rate(data.rate);
- this.set_staff(data.staff);
- this.set_client(data.client);
- this.set_ack(data.ack);
- this.set_rating(data.rating);
-
- //draw GUI by other
- this.mark_dirty_on_new_record(data);
- this.mark_week_color();
- this.validate(); //also triggers mark errors
- }
-
- get_job_id(){
- return this.el.find('input[name="id"]').attr('value');
- }
- set_job_id(val){
- if (typeof val == 'undefined' || val == '')
- {//remove data-id and id
- this.el.removeAttr('data-id');
- this.el.removeAttr('id');
- }else{
- this.el.attr('data-id', val);
- this.el.attr('id', 'job_' + val);
- }
- }
- get_tos()
- {
- this.el.find('div.btos select').children("option:selected").val();
- }
- set_tos(val)
- {
- if (typeof(val) =="undefined")
- return;
- this.el.find('input.tos_name').attr('value', bts().tos[val].tos_full_str);
- }
- get_start(){
- return this.el.find('div.bstart').html();
- }
- set_start(val)
- {
- this.el.find('div.bstart').html(val);
- }
- get_finish()
- {
- return this.el.find('div.bfinish').html();
- }
- set_finish(val)
- {
- if (typeof(val) == "undefined")
- return;
- this.el.find('div.bfinish').html(val);
- }
- get_rate()
- {
- return this.el.find('div.brate').children("option:selected").val();
- }
- set_rate(val)
- {
- if (typeof(val) =="undefined")
- return;
- this.el.find('div.brate select option[value="'+val+'"]').prop('selected',true);
- }
- get_staff()
- {
- return this.el.find('div.bstaff select').children("option:selected").val();
- }
- set_staff(val)
- {
- if (typeof(val) =="undefined")
- return;
- this.el.find('div.bstaff select option[value="'+val+'"]').prop('selected',true);
- }
- get_client()
- {
- return this.el.find('div.bclient select').children("option:selected").val();
- }
- set_client(val)
- {
- if (typeof(val) =="undefined")
- return;
- this.el.find('div.bclient select option[value="'+val+'"]').prop('selected',true);
- }
- get_ack()
- {
- return this.el.find('div.bconfirmed input:checked').length > 0;
- }
- set_ack(val)
- {
- if (typeof(val) =="undefined")
- return;
- return this.el.find('div.bconfirmed input').prop('checked', val!=0);
- }
- get_rating(){
- var count =0;
- this.el.find('div.brating span').each(function(i,e){
- if ($(e).html()=='★')
- count +=1;
- });
- return count;
- }
- set_rating(num){
- if (!(1 <= num && num <=5))
- return;
- this.el.find('div.brating span').each(function(i,e){
- var rating = $(e).attr('data-rating');
- var rating = parseInt(rating);
- if (rating <= num)
- $(e).html('★');
- else
- $(e).html('☆');
- });
- }
-
- get_record_from_ui(){
- var record = {};
- record.id = this.get_job_id();
- record.tos = this.get_tos();
- record.start = this.get_start();
- record.finish = this.get_finish();
- record.rate = this.get_rate();
- record.staff = this.get_staff();
- record.client = this.get_client();
- record.ack = this.get_ack();
- record.rating = this.get_rating();
- return record;
- }
-
- do_save_record(){
- var self = this;
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "save_job", // action
- record: this.get_record_from_ui(),
- }, function(response, status, xhr){
- if (response.status=='success'){
- self.load_data(response.newdata);
- self.mark_saved();
- self.mark_old();
- }else{
- alert( 'error saving data, please check your network');
- }
- });
- }
-
- mark_dirty_on_new_record(data){
- if (typeof(data.id) === 'undefined' || data.id == ''){
- this.mark_dirty();
- this.mark_new();
- }
- else{
- this.mark_saved();
- }
- }
-
- mark_dirty() //need save
- {
- var d = this.el.find('.bsave');
- d.removeClass('saved');
- d.addClass('blink_me');
- setTimeout(function(){
- d.removeClass('blink_me');
- d.removeClass('saved');
- },1000);
- }
-
- mark_saved()
- {
- var d = this.el.find('.bsave');
-
- d.addClass('blink_me');
- setTimeout(function(){
- d.removeClass('blink_me');
- d.addClass('saved');
- },1000);
- }
-
- //newly created empty record
- mark_new()
- {
- this.el.addClass('emptyrecord');
- }
- mark_old()
- {
- this.el.removeClass('emptyrecord');
- }
-
- mark_highlight_me(ms){
- this.el.addClass('blink_me');
- this.el.addClass('highlight');
- this.el.addClass('newcopy');
- var self = this;
- setTimeout(function(){
- self.el.removeClass('blink_me');
- self.el.removeClass('highlight');
- self.el.removeClass('newcopy');
- },ms);
- }
-
- is_start_valid(){
- var s = this.get_start();
- return is_valid_date_str(s);
-
- }
- is_finish_valid(){
- var f = this.get_finish();
- if (!is_valid_date_str(f))
- return false;
- }
-
- is_finish_resonable(){
- var f = this.get_finish();
- if (!is_valid_date_str(f))
- return false;
- var s = this.get_start();
-
- s = new Date(s);
- f = new Date(f);
-
- return (s < f);
- }
-
- validate()
- {
- var ok_time = this.validate_start() &&
- this.validate_finish(); //finish might not be executed, if start is wrong
- var ok_tos = this.validate_tos(); //make sure this validate is executed;
- var ok_rate = this.validate_rate() ; //make sure this validate is executed
- var ok = ok_time && ok_tos && ok_rate;
- if (ok){
- this.el.removeClass('invalidjob');
- }else{
- this.el.addClass('invalidjob');
- }
- return ok;
- }
-
- validate_start(){
- var str = this.get_start();
- if ( is_valid_date_str(str) ){
- this.mark_start_valid();
- this.set_err_msg_start('');
- return true;
- }else{
- this.mark_start_invalid();
- this.set_err_msg_start('wrong date');
- return false;
- }
- }
- validate_finish()
- {
- var str = this.get_finish();
- if (! is_valid_date_str(str)){
- this.set_err_msg_finish('wrong date');
- this.mark_finish_invalid();
- return false;
- }
-
- if (!this.is_finish_resonable()){
- this.set_err_msg_finish("older than start")
- this.mark_finish_invalid();
- return false;
- }
- this.mark_finish_valid();
- this.set_err_msg_finish('');
- return true;
- }
- validate_rate()
- {
- var rate_info = this.get_rate_info_by_id(this.get_rate());
- if ( rate_info.RatePerUnit <= 0){
- this.set_err_msg_rate('bad rate');
- this.mark_rate_invalid();
- return false;
- }
- // if (this.get_rate() != this.data.rate){
- // this.set_err_msg_rate('rate@Xero inactive ' + this.data.rate);
- // this.mark_rate_invalid();
- // this.mark_dirty();
- // return false;
- // }
- this.set_err_msg_rate('');
- this.mark_rate_valid();
- return true;
- }
-
- validate_tos(){
- // if (this.get_tos() != this.data.tos){
- // this.set_err_msg_tos('require NDIS ' + this.data.tos);
- // this.mark_tos_invalid();
- // this.mark_dirty();
- // console.log('tos mark dirty');
- // return false;
- // }
- this.set_err_msg_tos('');
- this.mark_tos_valid();
- return true;
- }
-
- clear_err_msg(){
- this.el.find('.divTableRow.errmsg > div').html('');
- }
- set_err_msg_start(str)
- {
- this.el.find('div.bstart_err').html(str);
- }
- set_err_msg_finish(str)
- {
- this.el.find('div.bfinish_err').html(str);
- }
- set_err_msg_rate(str)
- {
- this.el.find('div.brate_err').html(str);
- }
- set_err_msg_save(str)
- {
- this.el.find('div.bsave_err').html(str);
- }
- set_err_msg_tos(str)
- {
- this.el.find('div.btos_err').html(str);
- }
-
- mark_tos_valid(){
- this.el.find('div.btos select').removeClass('invalid');
- }
- mark_tos_invalid(){
- this.el.find('div.btos select').addClass('invalid');
- }
- mark_start_valid(){
- this.el.find('div.bstart input').removeClass('invalid');
- }
- mark_start_invalid(){
- this.el.find('div.bstart input').addClass('invalid');
- }
-
- mark_finish_valid(){
- this.el.find('div.bfinish input').removeClass('invalid');
- }
- mark_finish_invalid(){
- this.el.find('div.bfinish input').addClass('invalid');
- }
- mark_rate_valid(){
- this.el.find('div.brate select').removeClass('invalid');
- }
- mark_rate_invalid(){
- this.el.find('div.brate select').addClass('invalid');
- }
-
- mark_week_color(){
- this.el.find('div.brating').removeClass('week1color');
- this.el.find('div.brating').removeClass('week2color');
-
- if (this.is_week1()){
- this.el.find('div.brating').addClass('week1color');
- }else if (this.is_week2()){
- this.el.find('div.brating').addClass('week2color');
- }
- }
-
- is_week1()
- {
- var w1_begin = new Date($('span[name="w1d1"]').data().date) ;
- var w1_end = new Date($('span[name="w1d7"]').data().date);
- w1_begin.setHours(0,0,0,0);
- w1_end.setHours(23,59,59);
- //console.log("week1 begin %o, end %o", w1_begin, w1_end);
- //w1_end = new Date (w1_end.setDate(w1_end.getDate()+1)); //from 00:00 to 23:59;
- var me = new Date(this.data.start);
- return (w1_begin <= me && me <= w1_end );
- }
-
- is_week2()
- {
- var w2_begin = new Date($('span[name="w2d1"]').data().date);
- var w2_end = new Date($('span[name="w2d7"]').data().date);
- w2_begin.setHours(0,0,0,0);
- w2_end.setHours(23,59,59);
- var me = new Date(this.data.start);
- return (w2_begin <= me && me <= w2_end );
- }
- get_payment_summary(){
- var result ={};
- result.ot = this.get_is_high_pay();
- result.hour = this.get_working_duration();
- result.money = this.get_wages();
- return result;
- }
- get_is_high_pay()
- {
- var rate_info = this.get_rate_info_by_id(this.get_rate());
- return this.is_high_pay_hour(rate_info);
- }
- get_working_duration()
- {
- //finish - start
- var f = new Date(this.get_finish());
- var s = new Date(this.get_start());
- var diff = f.getTime() - s.getTime();
- var hours = Math.floor(diff / 1000 / 60 / 60);
- diff -= hours * 1000 * 60 * 60;
- var minutes = Math.floor(diff / 1000 / 60);
- var minute_to_hour = minutes/60;
- return (hours + minute_to_hour);
- }
- get_wages(){
- var hour = this.get_working_duration();
- var rate_info = this.get_rate_info_by_id(this.get_rate());
- return hour * rate_info.RatePerUnit;
- }
-
- get_rate_info_by_id(id){
- var rate_info = {};
- var rates = bts().earnings_rate;
- for(var i =0; i< rates.length; i++){
- var r = rates[i];
- if(r.EarningsRateID == id){
- rate_info = $.extend(true,{}, r);//make a copy
- break;
- }
- }
- return rate_info;
- }
-
- is_high_pay_hour(rate_info){
- var keywords =bts().high_pay_keywords;
- var found = false;
- return false;
- keywords.forEach(function(e){
- if (-1 != rate_info.Name.toLowerCase().indexOf(e.toLowerCase()) )
- found = true;
- });
- return found;
- }
- }//end of class Job
-
- //global GUI summary
- function get_wages()
- {
- var txt = $('div.wages div').html();
- return parseInt(txt);
- }
- function set_wages(num){
- $('div.wages div').html(num);
- }
-
- function set_working_hours(num){
- $('input#woh').attr('value', num);
- }
-
- function get_working_hours(){
- var txt = $('input#woh').attr('value');
- return parseFloat(txt);
- }
-
-
- //modal box
- function set_modal_title(selector, title){
- var s = 'div.bts_'+ selector +' .ult_modal-title';
- $(s).html(title);
- }
-
- function set_modal_content(selector, content){
- var s = 'div.bts_'+ selector +' div.ult_modal-body.ult-html';
- $(s).html(content);
- }
-
- function open_modal (selector){
- var s='div.bts_'+selector+'_button';
- $(s).trigger('click');
- }
-
- // setTimeout(function(){
- // set_modal_title('warning', 'suck title');
- // set_modal_content('warning', 'fucking details');
- // //open_modal('warning');
- // }, 1000);
- //
- // setTimeout(function(){
- // set_modal_title('error', 'error title');
- // set_modal_content('error', 'error details');
- // //open_modal('error');
- // }, 5000);
-
- $(document).on('mouseenter', 'div.week1 div', function(){
- $(this).addClass('blink_me');
- get_week2_partner(this).addClass('blink_me');
- blink_same_date_by_div(this);
- });
- $(document).on('mouseleave', 'div.week1 div', function(){
- $(this).removeClass('blink_me');
- get_week2_partner(this).removeClass('blink_me');
- unblink_all_date();
- });
-
- function get_week2_partner(div){
- var index = $(div).index()+1;
- return $('div.week2 div:nth-child('+index+')');
- }
-
- function init_weekdays(){
- var curr = new Date; // get current date
- init_weekdays_by_anchor(curr, true);
- return;
- }
-
- function init_weekdays_by_anchor(anchor, is_week1){
- var curr = new Date(anchor); // get the date;
-
- if (!is_week1){ //it is week2, shift for 7 days;
- curr.setDate(curr.getDate() -7); //curr will be changed;
- }
-
- var first = curr.getDate() - curr.getDay() + 1; //+1 we want Mon as first
- var last = first + 6; // last day is the first day + 6
-
- if (curr.getDay() == 0 ){// it's Sunday;
- last = curr.getDate();
- first = last - 6;
- }
-
-
- var pos = 1; //first lot
- for (var i=first; i<=last; i++)
- {
- var now = new Date(curr);
- var d1 = new Date(now.setDate(i));
- now = new Date(curr);
- var d2 = new Date(now.setDate(i+7));
- set_day_number(1,pos, d1); //week 1
- set_day_number(2,pos, d2); //week 2
- pos +=1;
- }
- }
-
-
- function set_day_number(week, index, date){
- var selector = 'span[name="w'+week+'d'+index+'"]';
- $(selector).html(date.getDate());
- $(selector).data({date:date});
- //console.log('set w%d-d%d %o', week,index,date);
- }
-
- function set_today(){
- var selector = 'div.sheettitle span[name="today"]';
- var curr = new Date;
- $(selector).html(format_date(curr));
- }
-
- Date.prototype.get_week_number = function(){
- var d = new Date(Date.UTC(this.getFullYear(), this.getMonth(), this.getDate()));
- var dayNum = d.getUTCDay() || 7;
- d.setUTCDate(d.getUTCDate() + 4 - dayNum);
- var yearStart = new Date(Date.UTC(d.getUTCFullYear(),0,1));
- return Math.ceil((((d - yearStart) / 86400000) + 1)/7)
- };
-
- function set_week_number(){
- var date = $('span[name="w1d1"]').data().date;
- //console.log("date %o", date);
- var num = date.get_week_number();
- $('div.weekly span[name="week1"]').html(num);
- $('div.weekly span[name="week2"]').html(num+1);
-
- set_week_boundry();
- }
-
- function set_week_boundry()
- {
- var date = $('span[name="w1d1"]').data().date;
- $('#week1b').attr('value', format_date(date));
- var date = $('span[name="w2d7"]').data().date;
- $('#week2b').attr('value', format_date(date));
- }
-
- function number_of_unsaved_job(){
- var count =0;
- var total_job = $('div.bsave').length -1;//remove table header
- var total_saved = $('div.bsave.saved').length;
- var empty = $('div.emptyrecord').length;
- count = total_job - total_saved - empty;
- return count;
- }
-
- $('div.prevweek.left').click(function(){
- if (number_of_unsaved_job() > 0){
- if(!confirm("you have unsaved jobs, proceed will lost them"))
- return;
- }
- $('div.weekdays span.weekday').each(function(i, e){
- var date = $(e).data().date;
- var newdate = new Date(date.setDate(date.getDate() -7 ));
- $(e).html(newdate.getDate());
- $(e).data({data:newdate});
- });
- set_week_number();
- debounced_load_timesheet();
- });
- $('div.nextweek.right').click(function(){
- if (number_of_unsaved_job() > 0){
- if(!confirm("you have unsaved jobs,proceed will lost them"))
- return;
- }
-
- $('div.weekdays span.weekday').each(function(i, e){
- var date = $(e).data().date;
- var newdate = new Date(date.setDate(date.getDate() +7 ));
- $(e).html(newdate.getDate());
- $(e).data({data:newdate});
- });
- set_week_number();
- debounced_load_timesheet();
- });
-
- $('div.weekly div.weekname.prev >input ').click(function(e){
- e.stopPropagation();
- });
- $('div.weekly div.weekname.prev >input ').change(function(e){
- var date = $('#week1b').attr('value');
- init_weekdays_by_anchor(date, true);
- set_week_number();
- debounced_load_timesheet();
- });
-
- $('div.weekly div.weekname.prev').click(function(){
- if (!confirm ('copy entire week to next week? '))
- return;
- var jobs = [];
- var job_els =[];
- $('div.week1 >div').each(function(i,e){
- var date = new Date($(e).find('span.weekday').data().date);
- var strDate = format_date(date); //yyyy-mm-dd
- $('div.bstart input').each(function(i,e){
- var value = $(e).attr('value');
- if( -1 != value.indexOf(strDate) ) //found
- {
- var el = $(e).closest('div.divTable');
- if (el.is(":visible")){
- var j = el.data().job;
- var newj = clone_data_create_new_job(j.get_record_from_ui(),7);//add 7 days
- job_els.push(newj.el);
- }
- }
- });
- });
- show_jobs(job_els);
- debounced_calculate();
- });
-
- $('div.weekly div.weekname.next > input').click(function(e){
- e.stopPropagation();
- });
-
- $('div.weekly div.weekname.next >input ').change(function(e){
- e.stopPropagation();
- var date = $('#week2b').attr('value');
- init_weekdays_by_anchor(date, false);
- set_week_number();
- debounced_load_timesheet();
- });
-
-
- $('div.weekly div.weekname.next').click(function(e){
- $(e).find('input').trigger('click');
- });
-
-
- $('div.week1 > div').click(function(e){
- e.stopPropagation();
- if ($('div.bstart input.blink_me').length == 0){
- alert("nothing to copy");
- return;
- }
- if (!confirm ('copy to next week'))
- return;
- var jobs_el = [];
- $('div.bstart input.blink_me').each(function(i,e){
- var r = copy_single_day_to_next_week(e);
- if (r != false)
- jobs_el.push(r.el);
- });
- show_jobs(jobs_el);
- unblink_all_date();
- });
-
- $('div.week1,div.week2').click(function(e){
- e.stopPropagation();
- $(this).toggleClass('filtered');
- do_filter_workspace();
- });
-
- function copy_single_day_to_next_week(el){
- var tb = $(el).closest('div.divTable');
- if (tb.is(':visible')){
- var j = $(tb).data().job;
- var newj = clone_data_create_new_job(j.get_record_from_ui() , 7); // +7 days
- return newj;
- }
- return false;
- }
-
- function clone_data_create_new_job(val, num_of_shifted_days){
- var data = $.extend(true, {}, val);//make a copy
- num_of_shifted_days = typeof num_of_shifted_days !=='undefined'? num_of_shifted_days: 0;// 0 days
- //reset
- data.id='';
- data.ack = 0;
- data.rating = 0;
-
- if (is_valid_date_str(data.start)){
- var s = new Date(data.start);
- var s1 = s.getDate() + num_of_shifted_days;
- s = new Date(s.setDate(s1));
- data.start = format_date_time(s);
- }
- if (is_valid_date_str(data.finish)){
- var f = new Date(data.finish);
- var f1 = f.getDate() + num_of_shifted_days;
- f = new Date(f.setDate(f1));
- data.finish = format_date_time(f);
- }
- var newj = new Job(data);
- return newj;
- }
-
- function is_valid_date_str(val){
- var d = new Date(val);
- if (d.toString()== 'Invalid Date')
- return false;
- return true;
- }
-
- function blink_same_date_by_div(div){
- var date = new Date($(div).find('span.weekday').data().date);
- blink_same_date(date);
- }
-
- function blink_same_date(date){
- var strDate = format_date(date); //yyyy-mm-dd
- var els=[];
- unblink_all_date();
- $('div.bstart input').each(function(i,e){
- if ( $(e).is(":visible") ){
- var value = $(e).attr('value');
- if( -1 != value.indexOf(strDate) ) //found
- {
- els.push(e);
- $(e).addClass('blink_me');
- }
- }
- });
- }
-
-
- function unblink_all_date(){
- $('div.bstart input').removeClass('blink_me');
- }
-
- $('div.sheettitle h1 span').click(function(){
- reset_title_to_today();
- load_timesheet();
- });
-
- function reset_title_to_today(){
- set_today();
- init_weekdays();
- set_week_number();
- }
-
- var debounced_load_timesheet = debounce(load_timesheet,1000);
-
- function load_timesheet()
- {
- clear_workspace();
- var first = $('span[name="w1d1"]').data().date;
- var last = $('span[name="w2d7"]').data().date;
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "list_jobv1", // action
- start: format_date(first),
- finish: format_date(last),
- }, function(response, status, xhr){
- if (response.status =='success'){
- display_jobs_after_staff_client_tos_info_ready(response);
- }else{
- alert('error loading job');
- hide_loading_jobs();
- }
- });
-
- }
-
- function display_jobs_after_staff_client_tos_info_ready(response)
- {
- var b = bts();
- if ((typeof b.staff_map != "undefined" && Object.keys(b.staff_map).length > 0) &&
- (typeof b.client_map != "undefined" && Object.keys(b.client_map).length > 0) &&
- (typeof b.tos != "undefined" && Object.keys(b.tos).length > 0 ) &&
- (typeof b.earnings_rate != "undefined" && Object.keys(b.earnings_rate).length > 0 ))
- {
- //map data for each jobTable
- response.jobs.forEach(function(e){
- e.tos_name = bts().tos[e.tos].tos_full_str;
- e.staff_name = bts().staff_map[e.staff].display_name;
- e.client_name = bts().client_map[e.client].display_name;
- e.rate_name = bts().earnings_rate[e.rate].RatePerUnit + "-" + bts().earnings_rate[e.rate].Name;
- e.saved = true;
- if (e.ack != 0){
- e.is_confirmed = true;
- }
- //console.log('attach %s %o to %o ', e.id, e, div);
- });
-
- //we do works, load timesheets
- var template = $("#jobv1_item").html();
- var html = Mustache.render(template, response);
- $('div.workspace').append(html);
- hide_loading_jobs();
- //filter it if reqired
- debounced_filter_workspace();
- return;
- }
- //console.log('wating staff/client/tos info to be ready');
- setTimeout(function(){
- display_jobs_after_staff_client_tos_info_ready(response);
- }, 500); //try it half seconds later
- }
-
-
- function show_jobs(job_els, in_ajax){
- if (job_els.length >0){
- $('div.workspace').append(job_els);
- job_els[0].get(0).scrollIntoView();
- console.log('loading ... %d jobs', job_els.length);
- }
- if (typeof in_ajax =='undefined')
- dtp_init();
- }
-
- function format_date(date){
- var dd = date.getDate();
- var mm = date.getMonth() + 1; //January is 0!
-
- var yyyy = date.getFullYear();
- if (dd < 10) {
- dd = '0' + dd;
- }
- if (mm < 10) {
- mm = '0' + mm;
- }
- return yyyy + '-' + mm + '-' +dd ;
- }
-
- function format_date_time(date){
- var strdate = format_date(date);
- var hh = date.getHours();
- if (hh<10){
- hh= '0' + hh;
- }
- var mm = date.getMinutes();
- if (mm<10){
- mm='0' + mm;
- }
- return strdate + ' ' + hh + ":" + mm;
- }
-
- function clear_workspace()//clear all timesheet jobs
- {
- $('div.workspace > div.divTable').remove();
- //clear datetime picker
- $('div.xdsoft_datetimepicker').remove();
- //
- show_loading_jobs();
- }
-
- $('div.workinghours').click(function(){
- $('div.bts_message_button').trigger('click');
- });
-
- $('button[name="confirmschedule"]').click(function(){
- if (!confirm('sending email to each staff for their job arrangement?'))
- return;
- $('div.bts_message .ult-overlay-close-inside').hide();
- $('div.bts_message_button').trigger('click');
- setTimeout(do_email_jobs, 2000);//2 seconds for dialog to popup
- });
-
- $('button[name="confirmschedule"]').mouseenter(function(){
- $('div.week2').addClass('blink_me');
- })
- $('button[name="confirmschedule"]').mouseleave(function(){
- $('div.week2').removeClass('blink_me');
- })
- var debounced_filter_workspace = debounce(do_filter_workspace, 1000);
- $(document).on('click','div.userlist', debounced_filter_workspace);
-
- function do_filter_workspace(){
- var staffs =[];
- $('div.stafflist div.peopleitem :checked').each(function(i, e){
- if ($(e).parent().is(':visible')){
- var id = $(e).parent().attr('data-id');
- //console.log("%o, id=%s", e, id);
- staffs.push(id.substring(1));
- }
- });
-
- var clients =[];
- $('div.clientlist div.peopleitem :checked').each(function(i, e){
- if ($(e).parent().is(':visible')){
- var id = $(e).parent().attr('data-id');
- //console.log("%o, id=%s", e, id);
- clients.push(id.substring(1));
- }
- });
-
- filter_workspace(staffs, clients);
- filter_workspace_by_weeks();
- debounced_calculate();
- }
-
- function filter_workspace(staffs, clients){
-
- //if both array is empty
- if( (staffs === undefined || staffs.length ==0) &&
- (clients===undefined || clients.length ==0)){
- //show all
- $('div.workspace div.divTable').show();
- return;
- }
-
- //if staffs is empty, we only filter by client
- if (staffs === undefined || staffs.length ==0){
- filter_workspace_by_client(clients);
- return;
- }
-
- //if clients is empty, we only filter by staff
- if (clients===undefined || clients.length ==0){
- filter_workspace_by_staff(staffs);
- return;
- }
- //filter by both
- filter_workspace_by_both(staffs, clients);
-
- }
-
- function filter_workspace_by_staff(staffs)
- {
- var class_name='to_be_shown';
- //filter some of them;
- staffs.forEach(function(e){
- $('div.workspace div.jobTable[data-staff="' + e + '"]').addClass(class_name);
- });
-
- $('div.workspace div.jobTable.' + class_name).fadeIn();
- $('div.workspace div.jobTable:not(.'+ class_name +')').hide();
- $('.' + class_name).removeClass(class_name);
- }
-
- function filter_workspace_by_client(clients)
- {
- var class_name='to_be_shown';
- //filter some of them;
- clients.forEach(function(e){
- $('div.workspace div.jobTable[data-client="' + e + '"]').addClass(class_name);
- });
-
- $('div.workspace div.jobTable.' + class_name).fadeIn();
- $('div.workspace div.jobTable:not(.'+ class_name +')').hide();
- $('.' + class_name).removeClass(class_name);
- }
-
- function filter_workspace_by_both(staffs, clients)
- {
- var class_name='hide';
- //filter some of them;
- clients.forEach(function(e){
- $('div.workspace div.jobTable:not([data-client="' + e + '"])').addClass(class_name);
- });
-
- staffs.forEach(function(e){
- $('div.workspace div.jobTable:not([data-staff="' + e + '"])').addClass(class_name);
- });
-
- $('div.workspace div.jobTable.' + class_name).hide();
- $('div.workspace div.jobTable:not(.'+ class_name +')').show();
- $('.' + class_name).removeClass(class_name);
-
- }
-
- function filter_workspace_by_weeks(){
- var hide_week1 = $('div.week1').hasClass('filtered');
- var hide_week2 = $('div.week2').hasClass('filtered');
-
- if (hide_week1 && hide_week2 ){
- alert("You are hiding both weeks");
- }
-
- $('div.workspace div.divTable').each(function(i,e){
- var job = $(e).data().job;
- if ((hide_week1 && job.is_week1()) ||
- (hide_week2 && job.is_week2()) ){
- $(e).fadeOut();
- }
- });
- }
-
- var debounced_calculate = debounce(calculate_total_hour_and_money, 2000);
-
- function calculate_total_hour_and_money()
- {
- //init pays for all staff;
- var pays={
- total: 0,
- hours: 0,
- };
- $('.stafflist > div.peopleitem').each(function(i,e){
- var people = $(this).data().obj;
- people.reset_summary();
- });
-
- $('div.workspace > .divTable').each(function(i,e){
- if (! $(e).is(':visible'))
- return;
-
- var job = $(e).data().job; //class Job
- if (typeof job === 'undefined')
- return;
- var ps = job.get_payment_summary();
-
- pays.total += ps.money;
- pays.hours += ps.hour;
-
- var staff = job.get_staff();
- var people = find_staff(staff); //class People
- if (people !=false)
- people.add_payment_summary(ps);
- });
- set_wages(pays.total.toFixed(2));
- set_working_hours(pays.hours.toFixed(2));
- }
-
- function find_staff(login)
- {
- var d = $('#p'+login).data();
- if (typeof d === 'undefined')
- return false;
- return $('#p'+login).data().obj;
- }
-
- $(document).on('change', '.divTableRow input[name="ack"]', function(e) {
- var el = $(this).closest('.jobTable');
- var data = el.data();
- data.ack = e.checked? 1: 0;
- mark_dirty(el);
- });
-
- function mark_dirty(el)
- {
- el.removeClass('saved');
- el.addClass('dirty');
- }
-
- function mark_clean(el)
- {
- el.addClass('saved');
- el.removeClass('dirty');
- }
-
- function init_ts(){
- xero(false);
- wifi(false);
- csv(false);
-
- show_loading_jobs();
- list_staff();
- list_clients();
- list_tos();
- ajax_earning_rate();
- //setTimeout(list_staff, 5000); // for testing delayed loading of jobs only
- //setTimeout(list_clients, 8000); // for testing delayed loading of jobs only
- //setTimeout(list_tos, 10000); // for testing delayed loading of jobs only
- init_user_search();
- reset_title_to_today();
- load_timesheet();
- }
-
- function do_email_jobs()
- {
- var selector = 'div.bts_message div.ult_modal-body';
- $(selector).html('Analysis staff jobs ... ok');
- var staff = bts().staff.slice(0);//copy this array;
- var s = staff.pop();
-
- //week2 start
- var w2_begin = new Date($('span[name="w2d1"]').data().date);
- var w2_end = new Date($('span[name="w2d7"]').data().date);
- var start = format_date(w2_begin);
- var finish = format_date(w2_end);
-
- function do_staff(){
- var el = $('<p> Checking ' + s.firstname + "....</p>");
- $(selector).append(el);
- el[0].scrollIntoView();
-
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "email_job", // action
- staff : s.login,
- start : start,
- finish: finish,
- }, function(response, status, xhr){
- if (response.status == 'success'){
- if (response.sent){
- el.append('<span class="sent">' + response.emailstatus + '</span>');
- }else{
- el.append('<span class="nojob">' + response.emailstatus + '</span>');
- }
- }else{
- el.append('<span class="error"> Error[' + response.error + ' ...]</span>');
- }
- }).fail(function(){
- el.append('<span class="error">' + 'Network Error occured' + '</span>');
- //clear staff pending list, stop further processing
- s = [];
- }).always(function(){//next staff
- if (staff.length >0){
- s = staff.pop();
- setTimeout(do_staff, 100); //a short delay makes it looks nice
- }else{
- $('div.bts_message .ult-overlay-close-inside').show();
- $('div.bts_message .ult-overlay-close-inside').addClass('blink_me');
- $('div.week2').removeClass('blink_me');
- $(selector).append('<span class="sent">All staff confirmed! </span>');
- }
- });
- }
- //execute
- do_staff();
- }
-
- function ajax_earning_rate(){
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "earnings_rate", // action
- }, function(response, status, xhr){
- bts().earnings_rate = {};
- response.options.forEach(function(e){
- bts().earnings_rate[e.EarningsRateID]=e;
- });
- console.log("%o", bts().earnings_rate);
- });
- }
-
-
- $( ".boundary_datepicker" ).datepicker();
- $( ".boundary_datepicker" ).datepicker("option", "dateFormat", "yy-mm-dd");
-
- $(document).on('click', 'div.clientlist div[name="title"] a', function(e){
- e.preventDefault();
- e.stopPropagation();
- var id = $(this).closest('label.peopleitem').attr('data-id').substring(1);
- var str = 'https://acaresydncy.com.au/feedback_card/' + id;
- var name = $(this).html();
- if ( confirm ("Email feedback link of : " + name + "\n\n\n" + str + "\n\n\n to helen@acaresydney.com.au?")){
- $.post(bts().ajax_url, { // POST request
- _ajax_nonce: bts().nonce, // nonce
- action: "email_feedback_url", // action
- client : id,
- }, function(response, status, xhr){
- //alert('please check your email on the phone and SMS the link to your client');
- }).fail(function(){
- alert('network error ');
- });
- }
- });
-
- init_ts();
-
-
- /*________________________________________________________________________*/
- });
- })(jQuery);
-
-
- /*______________scrolling______________________________________________*/
- jQuery(document).ready(function(){
- var timeoutid =0;
-
- jQuery('button.peoplelist[name="down"]').mousedown(function(){
- var button = this;
- timeoutid = setInterval(function(){
- //console.log("down scrotop %d ", jQuery(button).parent().find(".userlist").get(0).scrollTop );
- jQuery(button).parent().find(".userlist").get(0).scrollTop +=240;
- }, 100);
- }).on('mouseup mouseleave', function(){
- clearTimeout(timeoutid);
- });
-
- jQuery('button.peoplelist[name="up"]').mousedown(function(){
- var button = this;
- timeoutid = setInterval(function(){
- //console.log("up scrotop %d ", jQuery(button).parent().find(".userlist").get(0).scrollTop );
- jQuery(button).parent().find(".userlist").get(0).scrollTop -=240;
- }, 100);
- }).on('mouseup mouseleave', function(){
- clearTimeout(timeoutid);
- });
-
- });
-
|