Highrise Enhancements

try to take over the world!

Versione datata 10/04/2017. Vedi la nuova versione l'ultima versione.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

You will need to install an extension such as Tampermonkey to install this script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Highrise Enhancements
// @namespace    http://tampermonkey.net/
// @version      0.61
// @description  try to take over the world!
// @author       You
// @require      https://code.jquery.com/jquery-latest.min.js
// @match        https://wodc.highrisehq.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

var products = ['pt', 'puretane', 'bf', 'bfb', 'bf-blend', 'blueflame', 'blue flame', 'nuggy', 's5'];
var company = '';
var comments_length = 0;
var dates_length = 0;

var orderBlock = document.createElement('div');
orderBlock.style.cssText = 'margin: 9px 0;';
var orderLineLabel = document.createElement('div');
orderLineLabel.style.cssText += 'font-size: 11px; color: #777;';
orderLineLabel.className = 'label';
var orderLineDiv = document.createElement('div');
orderBlock.appendChild(orderLineLabel);
orderBlock.appendChild(orderLineDiv);

var notesBlock = document.createElement('div');
notesBlock.style.cssText = 'margin: 9px 0;';
var notesLabel = document.createElement('div');
notesLabel.style.cssText += 'font-size: 11px; color: #777;';
notesLabel.className = 'label';
var notesDiv = document.createElement('div');
var noteOne = document.createElement('div');
var noteTwo = document.createElement('div');
notesBlock.appendChild(notesLabel);
notesBlock.appendChild(notesDiv);

var matched = [];

const start = () => {
    settingsMenu();
    settingsButton();
    
    if (GM_getValue('Highlight_overdue_tasks')) {
        highlightOverdue();
    }
    
	timestamp_opt = GM_getValue('Show_full_timestamp');
	tracking_opt = GM_getValue('Link_tracking_numbers');
	var feed = document.getElementById('recordings');
	if (feed !== null) {
		commentMods(timestamp_opt, tracking_opt);
	}
    
    if (GM_getValue('Show_recent_order_and_notes_in_tasks')) {
		var wait_for_popup = setInterval(popupScanner, 200);
    }
    
    if (GM_getValue('Auto_share_tasks')) {
        taskcheckbox();
    }
	
	if (GM_getValue('Pagination')) {
		if (window.location.href.indexOf('parties?') > -1) {
			pagination();
		}
	}
};

(function() {
    'use strict';
    
    var url = window.location.href;
    if (url.toLowerCase().indexOf('iframe') < 0) {
        window.load = start();
    }
})();

Object.size = function(obj) {
    var size = 0, key;
    for (key in obj) {
        if (obj.hasOwnProperty(key)) size++;
    }
    return size;
};

function pagination() {
	var div = document.createElement('div');
	var column = document.getElementById('page_main_column');
	var h3 = document.createElement('h3');
	h3.innerHTML = 'Jump to page:';
	div.appendChild(h3);
	var content = column.getElementsByClassName('party_selection')[0];
	var url = window.location.href;
	var par = url.split('n=')[1];
	var link = url.split('&n=')[0];
	var currnum = (parseInt(par.split('&')[0]) / 50) + 1;
	par = par.split('&')[1];
	
	var select = document.createElement('select');
	div.appendChild(select);
	select.style.cssText = 'width: 78%';
	var num;
	if (url.indexOf('https://wodc.highrisehq.com/parties') > -1) {
		num = parseInt(document.getElementsByClassName('count total')[0].innerHTML.replace(/,/g, ''));
	}
	
	var pagecount = Math.ceil(num / 50);
	for (var i = 0; i < pagecount; i++) {
		var option = document.createElement('option');
		option.innerHTML = i + 1;
		option.value = link + '&n=' + (i * 50) + '&' + par;
		select.appendChild(option);
	}
	
	content.insertBefore(div, content.firstChild);
	
	var button = document.createElement('button');
	button.innerHTML = 'Go';
	button.style.cssText = 'width: 18%; margin-left: 4%;';
	button.className = 'main-button';
	div.appendChild(button);
	select.options[currnum - 1].selected = true;

	button.addEventListener('click', function() {
		window.location.href = select.value;
	});
}

function settingsMenu() {
    var options = {
		'Auto share tasks': 'Make sure checkbox "Let everyone see this task" is checked and hidden', 
		'Highlight overdue tasks': 'Highlight overdue text next to tasks link', 
		'Show full timestamp': 'Show the time and date on notes', 
		'Show recent order and notes in tasks': 'Show most recent order and last 2 notes in tasks popup window', 
		'Pagination': 'Show "jump to page #" option on search pages',
		'Load hours': 'Automatically find store hours on customer pages',
	    'Link tracking numbers': 'Clickable tracking numbers'
	};
    
    var page_cover = document.createElement('div');
    document.body.appendChild(page_cover);
    page_cover.setAttribute('id', 'page_cover');
    page_cover.style.cssText = 'display: none; position: fixed; top: 0px; left: 0px; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 1000;';

    var settings_div = document.createElement('div');
    document.body.appendChild(settings_div);
    settings_div.setAttribute('id', 'settings_div');
    settings_div.style.cssText = 'padding: 50px; width: 600px; left: 50%; margin-left: -17.5%; display: none; position: fixed; background: white; border-radius: 20px; text-align: center; z-index: 1001;';

    var ul = document.createElement('ul');
    settings_div.appendChild(ul);

    page_cover.addEventListener('click', function() {
        page_cover.style.display = 'none';
        settings_div.style.display = 'none';
    });
	
    for (var key in options) {
		if (options.hasOwnProperty(key)) {
			var liButton = document.createElement('li');
			var liDesc = document.createElement('li');
			var button = document.createElement('button');
			button.innerHTML = key;
			ul.appendChild(liButton);
			ul.appendChild(liDesc);
			liButton.appendChild(button);
			liDesc.innerHTML = options[key];
			liDesc.style.cssText = 'margin-bottom: 20px;';
			button.style.cssText = 'border: none !important; margin: 5px 0; border-radius: 5px; color: white;';

			var gm_var = key.replace(/ /g, '_');
			if (GM_getValue(gm_var) === undefined) {
				GM_setValue(gm_var, true);
			}

			if (GM_getValue(gm_var) === true) {
				button.style.backgroundColor = '#378622';
			}
			else {
				button.style.backgroundColor = '#bd4b4b';
			}

			button.addEventListener('click', function() {
				gm_var = this.innerHTML.replace(/ /g, '_');
				GM_setValue(gm_var, !GM_getValue(gm_var));

				if (GM_getValue(gm_var) === true) {
					this.style.backgroundColor = '#378622';
				}
				else {
					this.style.backgroundColor = '#bd4b4b';
				}
			});
		}
    }
	
	var update = document.createElement('a');
	update.innerHTML = 'Update';
	update.href = 'https://greasyfork.org/scripts/26136-highrise-enhancements/code/Highrise%20Enhancements.user.js';
	update.style.cssText = 'display: block; margin-top: 50px; font-size: 2em; font-weight: bold; text-decoration: none; color: gray;';
	settings_div.appendChild(update);
}

function settingsButton() {
    var menu = document.getElementsByClassName('global_links')[0];
    var li = document.createElement('li');
    menu.appendChild(li);
    var button = document.createElement('button');
    li.appendChild(button);
    
    button.style.cssText = 'border: none; color: #56778b; font-size: 12px;';
    
    button.innerHTML = 'Super Secret';
    button.addEventListener('mouseover', function() {
        button.style.color = 'black';
    });
    
    button.addEventListener('mouseout', function() {
        button.style.color = '#56778b';
    });
    
    button.addEventListener('click', settingsPopup);
}

function taskcheckbox() {
    var taskcheckbox = [];
    taskcheckbox.push(document.getElementById('public_checkbox_task_main'));
    if (document.getElementById('public_checkbox_task_page') !== null) {
        taskcheckbox.push(document.getElementById('public_checkbox_task_page'));
    }
    
    for (var i = 0; i < taskcheckbox.length; i++) {
        taskcheckbox[i].checked = 'checked';
        taskcheckbox[i].parentNode.style.display = 'none';

        var task = document.createElement('div');
        taskcheckbox[i].parentNode.parentNode.insertBefore(task, taskcheckbox[i].parentNode);

        if (taskcheckbox[i].checked) {
            task.innerHTML = '<i>Everyone can see this task</i>';
        }
        else {
            task.innerHTML = '<b>TASK HIDDEN</i>';
        }
        task.style.cssText = 'font-size: 15px !important;';
    }
}


function settingsPopup() {
    var page_cover = document.getElementById('page_cover');
    var settings_div = document.getElementById('settings_div');
    page_cover.style.display = 'block';
    settings_div.style.display = 'block';
}


function highlightOverdue() {
    var span = document.getElementsByTagName('span');
    var len = span.length;
	var overdue;
    
    for (var i = 0; i < len; i++) {
        if (span[i].innerHTML.indexOf('overdue') > -1) {
            var num = span[i].innerHTML.split('overdue')[0];
            num = num.split(' ');
            num = num[num.length - 2];
            var text = num + ' ' + 'overdue';
            span[i].innerHTML = span[i].innerHTML.replace(text, '<div id="highlightoverdue">' + text + '</div>');
        }
    }
    
	try {
		overdue = document.getElementById('highlightoverdue');
		overdue.style.cssText = 'color: red; display: inline-block; font-weight: bold;';
	} catch (e) {
		
	}
}

function commentMods(timestamp, track) {
	var debug = document.createElement('div');
	document.body.insertBefore(debug, document.body.firstChild);
	debug.style.cssText = 'position: fixed; top:100px; left: 0px;';
	var tracking_line, tracking_number, splits, i, j, pattern, match, link;
    var timer = setInterval(function() {
        var feed = document.getElementById('recordings');
        var dates = feed.getElementsByClassName('date-container');
		var contents = feed.getElementsByClassName('text-content');
        var dates_len = dates.length;
		var con_len = contents.length;
        var split, date, hour, min_sec, ampm, i;
		
		if (timestamp) {
			if (dates_length !== dates_len) {
				dates_length = dates_len;
				for (i = 0; i < dates_len; i++) {
							dates[i].parentNode.style.marginTop = '20px';
					split = dates[i].getAttribute('data-timestamp').split(' ');
					hour = parseInt(split[1].split(':')[0]);
					min_sec = split[1].split(':');
					min_sec = min_sec[1] + ':' + min_sec[2];

					if (hour >= 8) {
						hour -= 7;
					}
					else {
						hour += 17;
					}

					if (hour > 12) {
						hour -= 12;
						ampm = 'PM';
					}
					else if (hour == 12) {
						ampm = 'PM';
					}
					else {
						ampm = 'AM';
					}

					if (hour < 10) {
						hour = '0' + hour.toString();
					}
					
					if (dates[i].parentNode.getAttribute('id') !== null) {
						if (dates[i].parentNode.getAttribute('id').indexOf('description_task_recording') > -1) {
							dates[i].parentNode.style.marginTop = '28px';
							dates[i].parentNode.parentNode.insertBefore(dates[i], dates[i].parentNode.parentNode.firstChild);
						}
					}
					else {
						dates[i].parentNode.parentNode.insertBefore(dates[i], dates[i].parentNode.parentNode.firstChild);
					}
					
					dates[i].style.cssText = 'position: absolute; margin: 0 !important; top: 5px; left: 75%; font-size: 11px; color: #333; background: transparent; padding: 4px; border-radius: 6px; border: 1px solid #d7d7d7; text-align: center; display: block; width: 150px; height: 15px; float: right;';
					dates[i].innerHTML = fixDate(split[0]) + ' - ' + hour + ':' + min_sec + ' ' + ampm;
				}
			}
		}
		
		if (track) {
			if (comments_length !== con_len) {
				comments_length = con_len;
				for (i = 0; i < con_len; i++) {				
					if (contents[i].innerHTML.indexOf('YRC#') > -1 || contents[i].innerHTML.indexOf('YRC #') > -1) {
						pattern = /\d{3}-\d{6}-\S/;
						match = pattern.exec(contents[i].innerHTML).toString();
						if (matched.indexOf(match) == -1) {
							matched.push(match);
							link = '<a href="https://my.yrc.com/tools/#/track/shipments?endDate=&referenceNumber=<TRACKING>&referenceNumberType=PRO&startDate=2014-02-24">' + match + '</a>';
							link = link.replace('<TRACKING>', match);
							contents[i].innerHTML = contents[i].innerHTML.replace(match, link);
						}
					}
					else if (contents[i].innerHTML.indexOf('UPS#') > -1 || contents[i].innerHTML.indexOf('UPS #') > -1) {
						pattern = /1Z19169V\d{10}/;
						match = pattern.exec(contents[i].innerHTML).toString();
						if (matched.indexOf(match) == -1) {
							matched.push(match);
							link = '<a href="https://wwwapps.ups.com/WebTracking/processRequest?HTMLVersion=5.0&Requester=NES&AgreeToTermsAndConditions=yes&loc=en_US&tracknum=<TRACKING>">' + match + '</a>';
							link = link.replace('<TRACKING>', match);
							contents[i].innerHTML = contents[i].innerHTML.replace(match, link);
						}
					}
					else if (contents[i].innerHTML.indexOf('USPS#') > -1 || contents[i].innerHTML.indexOf('USPS #') > -1) {
						pattern = /\d{22}/;
						match = pattern.exec(contents[i].innerHTML).toString();
						if (matched.indexOf(match) == -1) {
							matched.push(match);
							link = '<a href="https://tools.usps.com/go/TrackConfirmAction.action?tLabels=<TRACKING>">' + match + '</a>';
							link = link.replace('<TRACKING>', match);
							contents[i].innerHTML = contents[i].innerHTML.replace(match, link);
						}
					}
				}
			}
		}
    }, 50);
}

function popupScanner() {
    var company_name = '';
    var popup = document.getElementById('quick_show_window');
	var preview = popup.getElementsByClassName('preview')[0];
    
    var inner;
    
    if (popup.style.display !== 'none') {
		if (popup.getElementsByTagName('a').length > 0) {
			var link = popup.getElementsByTagName('img')[0].parentNode.href;

			company_name = popup.getElementsByTagName('h1')[0].innerHTML;
			if (company !== company_name) {
				var company_id = link.split('companies/')[1];
				company_id = company_id.split('-')[0];
				orderLineDiv.innerHTML = '<i>Loading notes...</i>';
				notesDiv.innerHTML = '';
				preview.appendChild(orderBlock);
				preview.appendChild(notesBlock);
				orderLineLabel.innerHTML = 'Most recent order:';
				notesLabel.innerHTML = 'Most recent notes:';
				company = company_name;
				get_notes(company_id);
			}
		}
    }
    else {
        company = '';
    }
}

function get_notes(company_id) {
	var last_order, last_notes = [], note_ids = [];
	$.get('/companies/' + company_id + '/notes.xml', function(data) {
		var json = xmlToJson(data);
		var notes = json.notes.note;
		console.log(notes);
		for (var note in notes) {
			if (notes[note].body !== undefined) {
				if (last_notes.length < 2) {
					last_notes.push(note);
				}
				if (last_order === undefined) {
					for (var product in products) {
						if (last_order === undefined) {
							if (notes[note].body['#text'].indexOf(product) > -1) {
								if (notes[note].attachments !== undefined) {
									last_order = notes[note];
								}
							}
						}
					}
				}
			}
		}
		if (last_order !== undefined) {
			var order_date = fixDate(last_order['created-at']['#text']);
			var note_text = last_order.body['#text'].toLowerCase();
			var order_type = '???';
			
			if (note_text.indexOf('sample') > -1) {
				order_type = 'Sample';
			}
			else if (note_text.indexOf('$') > -1) {
				order_type = 'Order';
			}
			orderLineDiv.innerHTML = order_type + ' sent on ' + order_date;
		}
		else {
			orderLineDiv.innerHTML = 'No shipments found';
		}
		for (note in last_notes) {
			if (last_notes.hasOwnProperty(note)) {
				var date = fixDate(notes[note]['created-at']['#text']);
				var body = notes[note].body['#text'];
				var note_container = document.createElement('div');
				var note_id = 'note_cont_' + note;
				note_container.setAttribute('id', note_id);
				notesDiv.appendChild(note_container);
				finish_call(date, body, note_id, notes[note]);
			}
		}
	});
}

function finish_call(date, body, note_id, note) {
	$.ajax({
		url: '/users/' + note['author-id']['#text'] + '.xml',
		success: function(data) {
			var json = xmlToJson(data);
			var author = json.user.name['#text'];
			var note_container = document.getElementById(note_id);
			note_container.innerHTML = '<font color="#777">' + Array(61).join('-') + '</font><font color="#777">' + author + ' - ' + date + '</font><br>' + body;
		}
	});
}

function fixDate(date) {
	date = date.split('T')[0];
    var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    var year = date.split('-')[0];
    var month = months[parseInt(date.split('-')[1]) - 1];
    var day = date.split('-')[2].substring(0, 2);
    
    return month + ' ' + day + ', ' + year;
}

function xmlToJson(xml) {
	
	// Create the return object
	var obj = {};

	if (xml.nodeType == 1) { // element
		// do attributes
		if (xml.attributes.length > 0) {
		obj["@attributes"] = {};
			for (var j = 0; j < xml.attributes.length; j++) {
				var attribute = xml.attributes.item(j);
				obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
			}
		}
	} else if (xml.nodeType == 3) { // text
		obj = xml.nodeValue;
	}

	// do children
	if (xml.hasChildNodes()) {
		for(var i = 0; i < xml.childNodes.length; i++) {
			var item = xml.childNodes.item(i);
			var nodeName = item.nodeName;
			if (typeof(obj[nodeName]) == "undefined") {
				obj[nodeName] = xmlToJson(item);
			} else {
				if (typeof(obj[nodeName].push) == "undefined") {
					var old = obj[nodeName];
					obj[nodeName] = [];
					obj[nodeName].push(old);
				}
				obj[nodeName].push(xmlToJson(item));
			}
		}
	}
	return obj;
}