Zendesk Enhancements

Améliore l'interface Zendesk et ajoute des fonctionnalités supplémentaires

当前为 2025-02-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Zendesk Enhancements
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.2
  5. // @description Améliore l'interface Zendesk et ajoute des fonctionnalités supplémentaires
  6. // @author Morgan & gann
  7. // @match https://*.zendesk.com/*
  8. // @grant GM_addStyle
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // Définition d'un style commun pour les éléments personnalisés
  16. var customCSS = `
  17. .custom-button, .djm-task-link {
  18. padding: 5px 10px;
  19. background-color: limegreen;
  20. font-size: 16px;
  21. color: black;
  22. border: 1px solid transparent;
  23. border-radius: 4px;
  24. cursor: pointer;
  25. text-align: center;
  26. text-decoration: none;
  27. display: inline-block;
  28. margin: 5px;
  29. }
  30.  
  31. .sc-1oduqug-0.jdCBDY {
  32. margin-top: 30px;
  33. }
  34.  
  35. iframe#web-messenger-container {
  36. display: none;
  37. }
  38.  
  39. .app_view.app-1019154.apps_ticket_sidebar iframe {
  40. height: 80vh!important;
  41. }
  42. `;
  43.  
  44. GM_addStyle(customCSS);
  45.  
  46. // Initialisation des fonctions personnalisées
  47. setTimeout(function() {
  48. customFunction()
  49. }, 500);
  50.  
  51. function customFunction(message) {
  52. setTimeout(function() {
  53. checkUrlAndRunScriptInitializeInputLinks();
  54. checkUrlAndRunScriptTransformUrlsToLinks();
  55. }, 500);
  56. }
  57.  
  58. // Écoute les changements de navigation
  59. window.addEventListener('popstate', function() {
  60. customFunction('Chemin changé: ' + window.location.pathname);
  61. });
  62.  
  63. // Surcharge des méthodes d'historique
  64. function overrideHistoryMethod(methodName) {
  65. var originalMethod = history[methodName];
  66. history[methodName] = function(state) {
  67. if (typeof history['on' + methodName] == "function") {
  68. history['on' + methodName]({state: state});
  69. }
  70. customFunction('Chemin changé par ' + methodName + ': ' + window.location.pathname);
  71. return originalMethod.apply(history, arguments);
  72. };
  73. }
  74.  
  75. overrideHistoryMethod('pushState');
  76. overrideHistoryMethod('replaceState');
  77.  
  78. window.history.onpushstate = function(e) {
  79. window.dispatchEvent(new CustomEvent('pushstate', e));
  80. };
  81. window.history.onreplacestate = function(e) {
  82. window.dispatchEvent(new CustomEvent('replacestate', e));
  83. };
  84.  
  85. // Événements sur les en-têtes de tableau
  86. var theads = document.querySelectorAll('thead');
  87. theads.forEach(function(thead) {
  88. thead.addEventListener('click', function(event) {
  89. customFunction('Un thead a été cliqué' + event.target);
  90. });
  91. });
  92.  
  93. function transformUrlsToLinks() {
  94. const cells = document.querySelectorAll('.beWvMU');
  95. const urlRegex = /(https?:\/\/[^\s]+)/g;
  96.  
  97. if (cells.length > 0) {
  98. cells.forEach((cell, index) => {
  99. const textContent = cell.textContent;
  100.  
  101. if (urlRegex.test(textContent)) {
  102. const link = document.createElement('a');
  103. link.setAttribute('href', textContent.match(urlRegex)[0]);
  104. link.textContent = textContent.match(urlRegex)[0];
  105. link.classList.add('custom-button');
  106. cell.textContent = '';
  107. cell.appendChild(link);
  108. }
  109. });
  110. }
  111. }
  112.  
  113. function checkUrlAndRunScriptTransformUrlsToLinks() {
  114. if (window.location.pathname.startsWith('/agent/filters/')) {
  115. transformUrlsToLinks();
  116. }
  117. }
  118.  
  119. function initializeInputLinks() {
  120. var inputElements = document.querySelectorAll('.custom_field_14504424601628 input');
  121.  
  122. inputElements.forEach(function(inputElement) {
  123. var existingLink = inputElement.parentNode.parentNode.querySelector('.djm-task-link');
  124. if (existingLink) {
  125. existingLink.remove();
  126. }
  127.  
  128. var linkElement = document.createElement('a');
  129. linkElement.textContent = 'Tâche';
  130. linkElement.style.display = 'none';
  131. linkElement.classList.add('djm-task-link');
  132. inputElement.parentNode.parentNode.insertBefore(linkElement, inputElement.nextSibling);
  133.  
  134. checkForUrl(inputElement, linkElement);
  135.  
  136. inputElement.addEventListener('input', function() {
  137. console.log('Événement input détecté.');
  138. checkForUrl(inputElement, linkElement);
  139. });
  140. });
  141. }
  142.  
  143. function checkForUrl(inputElement, linkElement) {
  144. if (inputElement.value.match(/(https?:\/\/[^\s]+)/g)) {
  145. linkElement.href = inputElement.value;
  146. linkElement.style.display = 'inline-block';
  147. } else {
  148. linkElement.style.display = 'none';
  149. }
  150. }
  151.  
  152. function checkUrlAndRunScriptInitializeInputLinks() {
  153. if (window.location.pathname.startsWith('/agent/tickets/')) {
  154. initializeInputLinks();
  155. }
  156. }
  157.  
  158. // Fonction pour fermer tous les onglets inactifs
  159. function closeInactiveTabs() {
  160. const closeButtons = [...document.querySelectorAll('div[role="tab"][data-selected="false"] button[data-test-id="close-button"]')];
  161. closeButtons.forEach(btn => btn.click());
  162. }
  163.  
  164. // Fonction pour ajouter le bouton "Close All"
  165. function addCloseAllButton() {
  166. const toolbar = document.querySelector('div[data-test-id="header-tablist"] > div.sc-19uji9v-0');
  167. if (toolbar && !document.getElementById('close-all-button')) {
  168. const closeButton = document.createElement('button');
  169. closeButton.id = 'close-all-button';
  170. closeButton.textContent = 'X Close all';
  171. closeButton.className = 'custom-button';
  172. closeButton.addEventListener('click', closeInactiveTabs);
  173.  
  174. toolbar.appendChild(closeButton);
  175. }
  176. }
  177.  
  178. // Ajout du bouton "Close All" au chargement de la page
  179. window.addEventListener('load', addCloseAllButton);
  180.  
  181. // Observer les changements dans le DOM pour charger dynamiquement le bouton
  182. const observer = new MutationObserver(addCloseAllButton);
  183. observer.observe(document.body, { childList: true, subtree: true });
  184.  
  185. })();