Zendesk Enhancements

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

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

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