NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name SFreadability // @namespace http://tampermonkey.net/ // @version 0.6 // @history Adapter to changes in SF UI change in 2010-02 // @description SalesForce readability // @author roylez // @include https://*.my.salesforce.com/500* // @license MIT // @grant GM_addStyle // @require https://code.jquery.com/jquery-2.2.4.min.js // @require https://code.jquery.com/ui/1.12.1/jquery-ui.min.js // @require https://unpkg.com/dayjs // @updateURL https://openuserjs.org/meta/roylez/SFreadability.meta.js // @run-at document-end // ==/UserScript== GM_addStyle ( ` .salesforce_comment.public { border-left: 3px solid #82b74b !important } .entityFeedLayout .mainSection { padding-left: 0; background: initial; } .entityFeedLayout .leftContent { display: none; } .efpPanelSelect.efpsTopTabs.efpViewSelect { display: none; } .pbBottomButtons { display: none; } ` ); $.fn.renameTag = function(replaceWithTag){ this.each(function(){ var outerHtml = this.outerHTML; var tagName = $(this).prop("tagName"); var regexStart = new RegExp("^<"+tagName,"i"); var regexEnd = new RegExp("</"+tagName+">$","i") outerHtml = outerHtml.replace(regexStart,"<"+replaceWithTag) outerHtml = outerHtml.replace(regexEnd,"</"+replaceWithTag+">"); $(this).replaceWith(outerHtml); }); return this; } function always_show_details() { $(".lowerMainSection").remove() $(".eflDetails").attr("style", "") } function inject_css() { $("head").append('<meta name="viewport" content="width=device-width, initial-scale=1">') $("head").append('<link ' + 'href="//code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" ' + 'rel="stylesheet" type="text/css">') $("head").append('<link ' + 'href="//unpkg.com/tachyons@4/css/tachyons.min.css" ' + 'rel="stylesheet" type="text/css">') } function move_sections() { // move related lists to tabs var list = $(".efdRelatedLists") list.children(".fewerMore").remove() let comments = list.children(".bRelatedList:has(#comments)") list.prepend(comments) list.prepend($("<ul/>")) var tab = list.children("ul") list.children(".bRelatedList").each(function() { var t = $(this).find(".pbTitle h3").text() var id = $(this).attr('id') if ( t = t.match(/(Emails|Time Cards|Team|Comments|Files|Case History)/) ) { t = t[0] if ( t == "Emails" ) { t = "📧" + t } else if ( t == "Time Cards" ) { t = "🕔" + t } else if ( t == "Team" ) { t = "🙉" + t } else if ( t == "Comments") { t = "✍️" + t } else if ( t == "Files" ) { t = "📁" + t } else if ( t == "Case History" ) { t = "🍉" + t } tab.append($("<li class='f6'><a href='#" + id + "'>" + t + "</a></li>")) } else { $(this).remove() } }) list.tabs({ active: 0 }) } function clear_comments() { var today = Date.parse(new Date().toISOString().split('T')[0]) var attachments = $(".pbBody[id$=RelatedFileList_body]").first() // replace table with div var table = $(".pbBody[id*='CommentsList'] > table") table.parent().prepend("<div id='comments' class='db mw-8 center sans-serif f6'/>") var div=table.parent().children().first() table.find("tr.dataRow").each(function() { div.append("<div class='comment_row flex items-center bb bw1 b--light-blue dark-gray'/>") var row = div.children().last() var title = $(this).find(".dataCell b").first() var author = $(this).find(".dataCell b a").first() var time = title.text().match(/\((\d+\/\d+\/\d{4}.*? [AP]M)\)/)[1] var content = $(this).children().last() title.remove() content.find("br").first().remove() row.append("<div class='w-25-ns tc pa3'>" + $(this).children(".actionColumn").html() + "</div>") var has_attachment=content.text().match(/New Attachment added: (.*)$/) // comment says there is an attachment if ( has_attachment ) { var candidates = attachments.find( `tr:contains('${has_attachment[1]}')` ) // attachment actually found in the list without going to next page if ( candidates.length == 1 ) { content = mark_attachment(has_attachment[1], time, candidates.first()) } } row.append("<div class='w-75-ns pa3 code f6'>" + content.prop('outerHTML') + "</div>") var action_column = row.children().first() var action_button = action_column.text() var author_text = author.text() // highlight public comments and comments from customers if ( /(portal|NTT)/.test(author_text) ) { row.addClass("bg-light-yellow") } else if ( /Private/.test(action_button) ) { row.addClass("bg-lightest-blue") } action_column.prepend("<p class='comment_time'><b>" + time + "</b></p>") action_column.prepend("<p><b>" + author.get(0).outerHTML + "</b></p>") }) table.remove() } function mark_attachment(file, time, attachment_row) { var link = attachment_row.find("td a.actionLink:contains('Download')").attr('href') var button = $(`<a class="f7 no-underline link dim br2 ba bw1 ph3 pv2 mb2 dib mid-gray b--blue" target="_blank" href="${link}">${file}</a>`) return button } function move_comment_form() { let iframe = $( ".efdFields " ).children(":has(iframe)") iframe.nextAll().before(iframe) } // must place this before moving comment form function set_comment_defaults() { var iframe = $( "iframe[title=NewCaseComment]" )[0] function time_delta(time) { return dayjs().diff(time, "minute") } var frame_win = iframe.contentWindow ? iframe.contentWindow : iframe.contentDocument.defaultView var last_comment_time = dayjs($(".comment_row:first-child .comment_time ").text()) function listener(event){ if ( event.data == "getTime" ) { let diff = 5 if ( last_comment_time ) { let delta = time_delta(last_comment_time) diff = delta > 720 ? diff : delta } frame_win.postMessage({ timecard: diff }, "*") } } var w; if (typeof unsafeWindow != undefined) { w = unsafeWindow } else { w = window; } w.addEventListener("message",listener,false) } function style_description() { let des = $("#cas15_ileinner") des.addClass("f7 bg-light-yellow code pv2") } inject_css() always_show_details() style_description() clear_comments() move_sections() set_comment_defaults() move_comment_form()