Last active
October 18, 2019 18:07
-
-
Save asimmon/88f15abce8fffb340c42860092dcae28 to your computer and use it in GitHub Desktop.
Zendesk Comment Permalinks UserScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Zendesk Comment Permalinks | |
// @namespace GSoft | |
// @description Adds new navigation capabilities to Zendesk | |
// @version 2.0.0 | |
// @match https://*.zendesk.com/agent/* | |
// @grant none | |
// ==/UserScript== | |
/******/ (function(modules) { // webpackBootstrap | |
/******/ // The module cache | |
/******/ var installedModules = {}; | |
/******/ | |
/******/ // The require function | |
/******/ function __webpack_require__(moduleId) { | |
/******/ | |
/******/ // Check if module is in cache | |
/******/ if(installedModules[moduleId]) { | |
/******/ return installedModules[moduleId].exports; | |
/******/ } | |
/******/ // Create a new module (and put it into the cache) | |
/******/ var module = installedModules[moduleId] = { | |
/******/ i: moduleId, | |
/******/ l: false, | |
/******/ exports: {} | |
/******/ }; | |
/******/ | |
/******/ // Execute the module function | |
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | |
/******/ | |
/******/ // Flag the module as loaded | |
/******/ module.l = true; | |
/******/ | |
/******/ // Return the exports of the module | |
/******/ return module.exports; | |
/******/ } | |
/******/ | |
/******/ | |
/******/ // expose the modules object (__webpack_modules__) | |
/******/ __webpack_require__.m = modules; | |
/******/ | |
/******/ // expose the module cache | |
/******/ __webpack_require__.c = installedModules; | |
/******/ | |
/******/ // define getter function for harmony exports | |
/******/ __webpack_require__.d = function(exports, name, getter) { | |
/******/ if(!__webpack_require__.o(exports, name)) { | |
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); | |
/******/ } | |
/******/ }; | |
/******/ | |
/******/ // define __esModule on exports | |
/******/ __webpack_require__.r = function(exports) { | |
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { | |
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | |
/******/ } | |
/******/ Object.defineProperty(exports, '__esModule', { value: true }); | |
/******/ }; | |
/******/ | |
/******/ // create a fake namespace object | |
/******/ // mode & 1: value is a module id, require it | |
/******/ // mode & 2: merge all properties of value into the ns | |
/******/ // mode & 4: return value when already ns object | |
/******/ // mode & 8|1: behave like require | |
/******/ __webpack_require__.t = function(value, mode) { | |
/******/ if(mode & 1) value = __webpack_require__(value); | |
/******/ if(mode & 8) return value; | |
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; | |
/******/ var ns = Object.create(null); | |
/******/ __webpack_require__.r(ns); | |
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); | |
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); | |
/******/ return ns; | |
/******/ }; | |
/******/ | |
/******/ // getDefaultExport function for compatibility with non-harmony modules | |
/******/ __webpack_require__.n = function(module) { | |
/******/ var getter = module && module.__esModule ? | |
/******/ function getDefault() { return module['default']; } : | |
/******/ function getModuleExports() { return module; }; | |
/******/ __webpack_require__.d(getter, 'a', getter); | |
/******/ return getter; | |
/******/ }; | |
/******/ | |
/******/ // Object.prototype.hasOwnProperty.call | |
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; | |
/******/ | |
/******/ // __webpack_public_path__ | |
/******/ __webpack_require__.p = ""; | |
/******/ | |
/******/ | |
/******/ // Load entry module and return exports | |
/******/ return __webpack_require__(__webpack_require__.s = 2); | |
/******/ }) | |
/************************************************************************/ | |
/******/ ([ | |
/* 0 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
function isInteger(text) { | |
var numberValue = Number(text); | |
return Number.isInteger(numberValue); | |
} | |
exports.isInteger = isInteger; | |
function copyToClipboard(text) { | |
var el = document.createElement('textarea'); | |
el.value = text; | |
el.setAttribute('readonly', ''); | |
el.style.position = 'absolute'; | |
el.style.left = '-9999px'; | |
document.body.appendChild(el); | |
el.select(); | |
document.execCommand('copy'); | |
document.body.removeChild(el); | |
} | |
exports.copyToClipboard = copyToClipboard; | |
function isDomReadyAsync() { | |
return new Promise(function (resolve) { | |
if (document.readyState === 'complete' || document.readyState === 'interactive') { | |
setTimeout(function () { return resolve(); }, 1); | |
} | |
else { | |
document.addEventListener('DOMContentLoaded', function () { return resolve(); }); | |
} | |
}); | |
} | |
exports.isDomReadyAsync = isDomReadyAsync; | |
function waitForPredicateAsync(predicate, timeout) { | |
return new Promise(function (resolve, reject) { | |
var pollingInterval = 100; | |
var totalWaitDuration = 0; | |
var setIntervalHandle = window.setInterval(function () { | |
totalWaitDuration += pollingInterval; | |
if (totalWaitDuration > timeout) { | |
window.clearInterval(setIntervalHandle); | |
reject(); | |
} | |
else if (predicate()) { | |
window.clearInterval(setIntervalHandle); | |
resolve(); | |
} | |
}, pollingInterval); | |
}); | |
} | |
exports.waitForPredicateAsync = waitForPredicateAsync; | |
function sleepAsync(duration) { | |
return new Promise(function (resolve) { return setTimeout(resolve, duration); }); | |
} | |
exports.sleepAsync = sleepAsync; | |
/***/ }), | |
/* 1 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
var utils_1 = __webpack_require__(0); | |
var ZendeskTicketLink = /** @class */ (function () { | |
function ZendeskTicketLink(ticketId, commentId) { | |
this.ticketId = ticketId; | |
this.commentId = typeof commentId === 'string' ? commentId : ''; | |
} | |
ZendeskTicketLink.prototype.toString = function () { | |
var origin = document.location.origin; | |
return this.commentId && this.commentId.length | |
? origin + "/agent/tickets/" + this.ticketId + "?comment=" + this.commentId | |
: origin + "/agent/tickets/" + this.ticketId; | |
}; | |
ZendeskTicketLink.getCurrent = function () { | |
return this.fromUrl(window.location.href.replace('/#/', '/')); | |
}; | |
ZendeskTicketLink.fromUrl = function (href) { | |
try { | |
var url = new URL(href); | |
var ticketId = this.getTicketIdFromUrl(url); | |
if (ticketId) { | |
var commentId = this.getCommentIdFromUrl(url); | |
return new ZendeskTicketLink(ticketId, commentId); | |
} | |
return null; | |
} | |
catch (err) { | |
return null; | |
} | |
}; | |
ZendeskTicketLink.getTicketIdFromUrl = function (url) { | |
var pathname = url.pathname; | |
var parts = pathname.split('/'); | |
for (var i = 0; i < parts.length; i++) { | |
var currPart = parts[i]; | |
var nextPart = parts[i + 1]; | |
if (currPart === 'tickets' && utils_1.isInteger(nextPart)) | |
return nextPart; | |
} | |
return null; | |
}; | |
ZendeskTicketLink.getCommentIdFromUrl = function (url) { | |
var queryString = new URLSearchParams(url.search); | |
var commentId = queryString.get('comment'); | |
return commentId && utils_1.isInteger(commentId) ? commentId : ''; | |
}; | |
return ZendeskTicketLink; | |
}()); | |
exports.default = ZendeskTicketLink; | |
/***/ }), | |
/* 2 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
"use strict"; | |
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | |
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | |
return new (P || (P = Promise))(function (resolve, reject) { | |
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | |
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | |
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | |
step((generator = generator.apply(thisArg, _arguments || [])).next()); | |
}); | |
}; | |
var __generator = (this && this.__generator) || function (thisArg, body) { | |
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | |
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | |
function verb(n) { return function (v) { return step([n, v]); }; } | |
function step(op) { | |
if (f) throw new TypeError("Generator is already executing."); | |
while (_) try { | |
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | |
if (y = 0, t) op = [op[0] & 2, t.value]; | |
switch (op[0]) { | |
case 0: case 1: t = op; break; | |
case 4: _.label++; return { value: op[1], done: false }; | |
case 5: _.label++; y = op[1]; op = [0]; continue; | |
case 7: op = _.ops.pop(); _.trys.pop(); continue; | |
default: | |
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | |
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | |
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | |
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | |
if (t[2]) _.ops.pop(); | |
_.trys.pop(); continue; | |
} | |
op = body.call(thisArg, _); | |
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | |
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | |
} | |
}; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
__webpack_require__(3); | |
var utils_1 = __webpack_require__(0); | |
var engine_1 = __webpack_require__(7); | |
function main() { | |
return __awaiter(this, void 0, void 0, function () { | |
return __generator(this, function (_a) { | |
switch (_a.label) { | |
case 0: return [4 /*yield*/, utils_1.isDomReadyAsync()]; | |
case 1: | |
_a.sent(); | |
new engine_1.default().start(); | |
return [2 /*return*/]; | |
} | |
}); | |
}); | |
} | |
main().catch(console.log); | |
/***/ }), | |
/* 3 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
var content = __webpack_require__(4); | |
if (typeof content === 'string') { | |
content = [[module.i, content, '']]; | |
} | |
var options = {} | |
options.insert = "head"; | |
options.singleton = false; | |
var update = __webpack_require__(6)(content, options); | |
if (content.locals) { | |
module.exports = content.locals; | |
} | |
/***/ }), | |
/* 4 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
exports = module.exports = __webpack_require__(5)(false); | |
// Module | |
exports.push([module.i, "/* Add custom CSS rules to be injected into pages here. */\r\n.event .header .actor .ez_copy_link {\r\n display: inline-block;\r\n padding-left: 4px;\r\n padding-top: 2px;\r\n}\r\n\r\n.section.ticket .audits .event {\r\n -webkit-transition: background-color 750ms linear;\r\n -ms-transition: background-color 750ms linear;\r\n transition: background-color 750ms linear;\r\n}\r\n\r\n.section.ticket .audits .event.ez-event-highlighted {\r\n background-color: #fffaeb;\r\n}\r\n", ""]); | |
/***/ }), | |
/* 5 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
"use strict"; | |
/* | |
MIT License http://www.opensource.org/licenses/mit-license.php | |
Author Tobias Koppers @sokra | |
*/ | |
// css base code, injected by the css-loader | |
// eslint-disable-next-line func-names | |
module.exports = function (useSourceMap) { | |
var list = []; // return the list of modules as css string | |
list.toString = function toString() { | |
return this.map(function (item) { | |
var content = cssWithMappingToString(item, useSourceMap); | |
if (item[2]) { | |
return "@media ".concat(item[2], "{").concat(content, "}"); | |
} | |
return content; | |
}).join(''); | |
}; // import a list of modules into the list | |
// eslint-disable-next-line func-names | |
list.i = function (modules, mediaQuery) { | |
if (typeof modules === 'string') { | |
// eslint-disable-next-line no-param-reassign | |
modules = [[null, modules, '']]; | |
} | |
var alreadyImportedModules = {}; | |
for (var i = 0; i < this.length; i++) { | |
// eslint-disable-next-line prefer-destructuring | |
var id = this[i][0]; | |
if (id != null) { | |
alreadyImportedModules[id] = true; | |
} | |
} | |
for (var _i = 0; _i < modules.length; _i++) { | |
var item = modules[_i]; // skip already imported module | |
// this implementation is not 100% perfect for weird media query combinations | |
// when a module is imported multiple times with different media queries. | |
// I hope this will never occur (Hey this way we have smaller bundles) | |
if (item[0] == null || !alreadyImportedModules[item[0]]) { | |
if (mediaQuery && !item[2]) { | |
item[2] = mediaQuery; | |
} else if (mediaQuery) { | |
item[2] = "(".concat(item[2], ") and (").concat(mediaQuery, ")"); | |
} | |
list.push(item); | |
} | |
} | |
}; | |
return list; | |
}; | |
function cssWithMappingToString(item, useSourceMap) { | |
var content = item[1] || ''; // eslint-disable-next-line prefer-destructuring | |
var cssMapping = item[3]; | |
if (!cssMapping) { | |
return content; | |
} | |
if (useSourceMap && typeof btoa === 'function') { | |
var sourceMapping = toComment(cssMapping); | |
var sourceURLs = cssMapping.sources.map(function (source) { | |
return "/*# sourceURL=".concat(cssMapping.sourceRoot).concat(source, " */"); | |
}); | |
return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); | |
} | |
return [content].join('\n'); | |
} // Adapted from convert-source-map (MIT) | |
function toComment(sourceMap) { | |
// eslint-disable-next-line no-undef | |
var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); | |
var data = "sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(base64); | |
return "/*# ".concat(data, " */"); | |
} | |
/***/ }), | |
/* 6 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
"use strict"; | |
var stylesInDom = {}; | |
var isOldIE = function isOldIE() { | |
var memo; | |
return function memorize() { | |
if (typeof memo === 'undefined') { | |
// Test for IE <= 9 as proposed by Browserhacks | |
// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805 | |
// Tests for existence of standard globals is to allow style-loader | |
// to operate correctly into non-standard environments | |
// @see https://github.com/webpack-contrib/style-loader/issues/177 | |
memo = Boolean(window && document && document.all && !window.atob); | |
} | |
return memo; | |
}; | |
}(); | |
var getTarget = function getTarget() { | |
var memo = {}; | |
return function memorize(target) { | |
if (typeof memo[target] === 'undefined') { | |
var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself | |
if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { | |
try { | |
// This will throw an exception if access to iframe is blocked | |
// due to cross-origin restrictions | |
styleTarget = styleTarget.contentDocument.head; | |
} catch (e) { | |
// istanbul ignore next | |
styleTarget = null; | |
} | |
} | |
memo[target] = styleTarget; | |
} | |
return memo[target]; | |
}; | |
}(); | |
function listToStyles(list, options) { | |
var styles = []; | |
var newStyles = {}; | |
for (var i = 0; i < list.length; i++) { | |
var item = list[i]; | |
var id = options.base ? item[0] + options.base : item[0]; | |
var css = item[1]; | |
var media = item[2]; | |
var sourceMap = item[3]; | |
var part = { | |
css: css, | |
media: media, | |
sourceMap: sourceMap | |
}; | |
if (!newStyles[id]) { | |
styles.push(newStyles[id] = { | |
id: id, | |
parts: [part] | |
}); | |
} else { | |
newStyles[id].parts.push(part); | |
} | |
} | |
return styles; | |
} | |
function addStylesToDom(styles, options) { | |
for (var i = 0; i < styles.length; i++) { | |
var item = styles[i]; | |
var domStyle = stylesInDom[item.id]; | |
var j = 0; | |
if (domStyle) { | |
domStyle.refs++; | |
for (; j < domStyle.parts.length; j++) { | |
domStyle.parts[j](item.parts[j]); | |
} | |
for (; j < item.parts.length; j++) { | |
domStyle.parts.push(addStyle(item.parts[j], options)); | |
} | |
} else { | |
var parts = []; | |
for (; j < item.parts.length; j++) { | |
parts.push(addStyle(item.parts[j], options)); | |
} | |
stylesInDom[item.id] = { | |
id: item.id, | |
refs: 1, | |
parts: parts | |
}; | |
} | |
} | |
} | |
function insertStyleElement(options) { | |
var style = document.createElement('style'); | |
if (typeof options.attributes.nonce === 'undefined') { | |
var nonce = true ? __webpack_require__.nc : undefined; | |
if (nonce) { | |
options.attributes.nonce = nonce; | |
} | |
} | |
Object.keys(options.attributes).forEach(function (key) { | |
style.setAttribute(key, options.attributes[key]); | |
}); | |
if (typeof options.insert === 'function') { | |
options.insert(style); | |
} else { | |
var target = getTarget(options.insert || 'head'); | |
if (!target) { | |
throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid."); | |
} | |
target.appendChild(style); | |
} | |
return style; | |
} | |
function removeStyleElement(style) { | |
// istanbul ignore if | |
if (style.parentNode === null) { | |
return false; | |
} | |
style.parentNode.removeChild(style); | |
} | |
/* istanbul ignore next */ | |
var replaceText = function replaceText() { | |
var textStore = []; | |
return function replace(index, replacement) { | |
textStore[index] = replacement; | |
return textStore.filter(Boolean).join('\n'); | |
}; | |
}(); | |
function applyToSingletonTag(style, index, remove, obj) { | |
var css = remove ? '' : obj.css; // For old IE | |
/* istanbul ignore if */ | |
if (style.styleSheet) { | |
style.styleSheet.cssText = replaceText(index, css); | |
} else { | |
var cssNode = document.createTextNode(css); | |
var childNodes = style.childNodes; | |
if (childNodes[index]) { | |
style.removeChild(childNodes[index]); | |
} | |
if (childNodes.length) { | |
style.insertBefore(cssNode, childNodes[index]); | |
} else { | |
style.appendChild(cssNode); | |
} | |
} | |
} | |
function applyToTag(style, options, obj) { | |
var css = obj.css; | |
var media = obj.media; | |
var sourceMap = obj.sourceMap; | |
if (media) { | |
style.setAttribute('media', media); | |
} | |
if (sourceMap && btoa) { | |
css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */"); | |
} // For old IE | |
/* istanbul ignore if */ | |
if (style.styleSheet) { | |
style.styleSheet.cssText = css; | |
} else { | |
while (style.firstChild) { | |
style.removeChild(style.firstChild); | |
} | |
style.appendChild(document.createTextNode(css)); | |
} | |
} | |
var singleton = null; | |
var singletonCounter = 0; | |
function addStyle(obj, options) { | |
var style; | |
var update; | |
var remove; | |
if (options.singleton) { | |
var styleIndex = singletonCounter++; | |
style = singleton || (singleton = insertStyleElement(options)); | |
update = applyToSingletonTag.bind(null, style, styleIndex, false); | |
remove = applyToSingletonTag.bind(null, style, styleIndex, true); | |
} else { | |
style = insertStyleElement(options); | |
update = applyToTag.bind(null, style, options); | |
remove = function remove() { | |
removeStyleElement(style); | |
}; | |
} | |
update(obj); | |
return function updateStyle(newObj) { | |
if (newObj) { | |
if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) { | |
return; | |
} | |
update(obj = newObj); | |
} else { | |
remove(); | |
} | |
}; | |
} | |
module.exports = function (list, options) { | |
options = options || {}; | |
options.attributes = typeof options.attributes === 'object' ? options.attributes : {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of <style> | |
// tags it will allow on a page | |
if (!options.singleton && typeof options.singleton !== 'boolean') { | |
options.singleton = isOldIE(); | |
} | |
var styles = listToStyles(list, options); | |
addStylesToDom(styles, options); | |
return function update(newList) { | |
var mayRemove = []; | |
for (var i = 0; i < styles.length; i++) { | |
var item = styles[i]; | |
var domStyle = stylesInDom[item.id]; | |
if (domStyle) { | |
domStyle.refs--; | |
mayRemove.push(domStyle); | |
} | |
} | |
if (newList) { | |
var newStyles = listToStyles(newList, options); | |
addStylesToDom(newStyles, options); | |
} | |
for (var _i = 0; _i < mayRemove.length; _i++) { | |
var _domStyle = mayRemove[_i]; | |
if (_domStyle.refs === 0) { | |
for (var j = 0; j < _domStyle.parts.length; j++) { | |
_domStyle.parts[j](); | |
} | |
delete stylesInDom[_domStyle.id]; | |
} | |
} | |
}; | |
}; | |
/***/ }), | |
/* 7 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
"use strict"; | |
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | |
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | |
return new (P || (P = Promise))(function (resolve, reject) { | |
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | |
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | |
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | |
step((generator = generator.apply(thisArg, _arguments || [])).next()); | |
}); | |
}; | |
var __generator = (this && this.__generator) || function (thisArg, body) { | |
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | |
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | |
function verb(n) { return function (v) { return step([n, v]); }; } | |
function step(op) { | |
if (f) throw new TypeError("Generator is already executing."); | |
while (_) try { | |
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | |
if (y = 0, t) op = [op[0] & 2, t.value]; | |
switch (op[0]) { | |
case 0: case 1: t = op; break; | |
case 4: _.label++; return { value: op[1], done: false }; | |
case 5: _.label++; y = op[1]; op = [0]; continue; | |
case 7: op = _.ops.pop(); _.trys.pop(); continue; | |
default: | |
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | |
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | |
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | |
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | |
if (t[2]) _.ops.pop(); | |
_.trys.pop(); continue; | |
} | |
op = body.call(thisArg, _); | |
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | |
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | |
} | |
}; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
var utils_1 = __webpack_require__(0); | |
var zendeskTicketLink_1 = __webpack_require__(1); | |
var zendeskComment_1 = __webpack_require__(8); | |
var Engine = /** @class */ (function () { | |
function Engine() { | |
this.started = false; | |
} | |
Engine.prototype.start = function () { | |
if (this.started) | |
return; | |
this.started = true; | |
this.startPeriodicallyAddCopyLinks(); | |
this.startListeningForClicksOnCopyLinks(); | |
this.startListeningForClicksOnCommentLinks(); | |
this.scrollToCommentSpecifiedInQueryString(); | |
}; | |
Engine.prototype.scrollToCommentSpecifiedInQueryString = function () { | |
var _this = this; | |
window.setTimeout(function () { return __awaiter(_this, void 0, void 0, function () { | |
var ticket, comment; | |
return __generator(this, function (_a) { | |
switch (_a.label) { | |
case 0: | |
ticket = zendeskTicketLink_1.default.getCurrent(); | |
console.log(ticket); | |
if (!(ticket && ticket.commentId && ticket.commentId.length > 0)) return [3 /*break*/, 3]; | |
return [4 /*yield*/, utils_1.waitForPredicateAsync(function () { | |
return zendeskComment_1.ZendeskComment.getComment(ticket.ticketId, ticket.commentId) !== null; | |
}, 10000)]; | |
case 1: | |
_a.sent(); | |
return [4 /*yield*/, utils_1.sleepAsync(1000)]; | |
case 2: | |
_a.sent(); | |
comment = zendeskComment_1.ZendeskComment.getComment(ticket.ticketId, ticket.commentId); | |
if (comment) | |
comment.highlight(); | |
_a.label = 3; | |
case 3: return [2 /*return*/]; | |
} | |
}); | |
}); }, 50); | |
}; | |
Engine.prototype.startPeriodicallyAddCopyLinks = function () { | |
window.setInterval(function () { return Engine.addOrReplaceCopyLinks(); }, 1000); | |
}; | |
Engine.addOrReplaceCopyLinks = function () { | |
var ticket = zendeskTicketLink_1.default.getCurrent(); | |
if (!ticket) | |
return; | |
var comments = zendeskComment_1.ZendeskComment.getComments(ticket.ticketId); | |
for (var commentId in comments) { | |
comments[commentId].addCopyLink(); | |
} | |
}; | |
Engine.prototype.startListeningForClicksOnCopyLinks = function () { | |
document.addEventListener('click', function (event) { | |
var el = (event.target || event.srcElement); | |
if (el && el.tagName === 'SPAN' && el.className.indexOf('ez_copy_link') >= 0 && el.dataset.href) { | |
event.stopImmediatePropagation(); | |
event.preventDefault(); | |
utils_1.copyToClipboard(el.dataset.href); | |
console.log(el.dataset.href); | |
} | |
}, false); | |
}; | |
Engine.prototype.startListeningForClicksOnCommentLinks = function () { | |
var _this = this; | |
document.addEventListener('click', function (event) { return __awaiter(_this, void 0, void 0, function () { | |
var el, href, ticket; | |
return __generator(this, function (_a) { | |
el = (event.target || event.srcElement); | |
if (el && el.tagName === 'A' && el.href && el.href.length > 0) { | |
href = el.href.replace('/#/', '/'); | |
ticket = zendeskTicketLink_1.default.fromUrl(href); | |
if (ticket && ticket.ticketId && ticket.commentId) { | |
this.onCommentLinkClickScrollToComment(ticket); | |
} | |
} | |
return [2 /*return*/]; | |
}); | |
}); }, false); | |
}; | |
Engine.prototype.onCommentLinkClickScrollToComment = function (ticket) { | |
return __awaiter(this, void 0, void 0, function () { | |
var expectedHref, comments, id, err_1; | |
return __generator(this, function (_a) { | |
switch (_a.label) { | |
case 0: | |
expectedHref = new zendeskTicketLink_1.default(ticket.ticketId).toString(); | |
_a.label = 1; | |
case 1: | |
_a.trys.push([1, 5, , 6]); | |
return [4 /*yield*/, utils_1.waitForPredicateAsync(function () { | |
return document.location.href === expectedHref; | |
}, 10000)]; | |
case 2: | |
_a.sent(); | |
return [4 /*yield*/, utils_1.waitForPredicateAsync(function () { | |
return zendeskComment_1.ZendeskComment.getComment(ticket.ticketId, ticket.commentId) !== null; | |
}, 10000)]; | |
case 3: | |
_a.sent(); | |
return [4 /*yield*/, utils_1.sleepAsync(500)]; | |
case 4: | |
_a.sent(); | |
comments = zendeskComment_1.ZendeskComment.getComments(ticket.ticketId); | |
for (id in comments) { | |
if (id === ticket.commentId) { | |
comments[id].highlight(); | |
} | |
else { | |
comments[id].removeHighlight(); | |
} | |
} | |
return [3 /*break*/, 6]; | |
case 5: | |
err_1 = _a.sent(); | |
console.log("Could not scroll to comment", err_1); | |
return [3 /*break*/, 6]; | |
case 6: return [2 /*return*/]; | |
} | |
}); | |
}); | |
}; | |
return Engine; | |
}()); | |
exports.default = Engine; | |
/***/ }), | |
/* 8 */ | |
/***/ (function(module, exports, __webpack_require__) { | |
"use strict"; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
var zendeskTicketLink_1 = __webpack_require__(1); | |
var ZendeskComment = /** @class */ (function () { | |
function ZendeskComment(ticketId, commentId, htmlElement) { | |
this.ticketId = ticketId; | |
this.commentId = commentId; | |
this.htmlElement = htmlElement; | |
} | |
ZendeskComment.getComments = function (ticketId) { | |
var elements = document.querySelectorAll("div[data-side-conversations-anchor-id=\"" + ticketId + "\"] div[data-comment-id]"); | |
var comments = {}; | |
for (var i = 0; i < elements.length; i++) { | |
var element = elements[i]; | |
var commentId = element.getAttribute('data-comment-id'); | |
var parentElement = element.parentElement; | |
if (commentId && parentElement && parentElement.classList.contains('event')) { | |
comments[commentId] = new ZendeskComment(ticketId, commentId, parentElement); | |
} | |
} | |
return comments; | |
}; | |
ZendeskComment.getComment = function (ticketId, commentId) { | |
var element = document.querySelector("div[data-side-conversations-anchor-id=\"" + ticketId + "\"] div[data-comment-id=\"" + commentId + "\"]"); | |
if (element && element.parentElement && element.parentElement.classList.contains('event')) { | |
return new ZendeskComment(ticketId, commentId, element.parentElement); | |
} | |
return null; | |
}; | |
ZendeskComment.prototype.addCopyLink = function () { | |
var eventHeaderEl = this.htmlElement.querySelector('.content .header .actor'); | |
if (!eventHeaderEl) | |
return; | |
var copyLinkEls = eventHeaderEl.querySelectorAll('span.ez_copy_link'); | |
if (copyLinkEls.length > 0) | |
return; | |
var copyLinkEl = document.createElement('span'); | |
copyLinkEl.setAttribute('role', 'button'); | |
copyLinkEl.setAttribute('tabindex', '0'); | |
copyLinkEl.setAttribute('class', 'link_light ez_copy_link'); | |
copyLinkEl.innerHTML = "(copy link)"; | |
copyLinkEl.dataset.href = new zendeskTicketLink_1.default(this.ticketId, this.commentId).toString(); | |
eventHeaderEl.appendChild(copyLinkEl); | |
}; | |
ZendeskComment.prototype.highlight = function () { | |
this.htmlElement.classList.add('ez-event-highlighted'); | |
this.htmlElement.scrollIntoView({ | |
behavior: 'smooth' | |
}); | |
}; | |
ZendeskComment.prototype.removeHighlight = function () { | |
this.htmlElement.classList.remove('ez-event-highlighted'); | |
}; | |
return ZendeskComment; | |
}()); | |
exports.ZendeskComment = ZendeskComment; | |
/***/ }) | |
/******/ ]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment