roylez / SFreadability

// ==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()