From 76b653058d9b9fc1c7b2f53f425724a46ed546ea Mon Sep 17 00:00:00 2001
From: LucasC <lucas.charpentier@xwiki.com>
Date: Tue, 27 Aug 2024 08:56:33 +0200
Subject: [PATCH] XWIKI-21878: Various close button modals do not use intended
 icons (#2888)

* Removed the hard coded values from the templates.
* Made a REST API call from modal.js to access the current icontheme icon.

Note: The only occurrence of `&times;` left in the project is the fallback value for the modal.js template.
---
 .../src/main/resources/js/attachment/move.js  |  2 +-
 .../templates/attachment/moveStep1.vm         |  2 +-
 .../src/main/webjar/xwiki-dialog/modal.js     | 63 +++++++++++++------
 .../extension/security/liveData/advice.vm     |  2 +-
 .../extension/security/liveData/cveID.vm      |  2 +-
 .../main/resources/flamingo/commentsinline.vm |  4 +-
 .../main/resources/flamingo/export_modal.vm   |  2 +-
 .../main/resources/flamingo/previewdiff.vm    |  2 +-
 .../main/resources/flamingo/syntaxPicker.js   | 15 +++--
 .../src/main/vue/utilities/XWikiIcon.vue      |  2 +-
 .../src/main/webjar/liveDataSource.js         |  4 +-
 .../src/main/webjar/l10n.js                   |  2 +-
 .../resources/templates/attachment_macros.vm  |  2 +-
 .../src/test/resources/xwiki-invalid.html     |  4 +-
 .../src/test/resources/xwiki-valid.html       |  4 +-
 15 files changed, 74 insertions(+), 38 deletions(-)

diff --git a/xwiki-platform-core/xwiki-platform-attachment/xwiki-platform-attachment-api/src/main/resources/js/attachment/move.js b/xwiki-platform-core/xwiki-platform-attachment/xwiki-platform-attachment-api/src/main/resources/js/attachment/move.js
index 6a42521f5d3..c0d5c3edf61 100644
--- a/xwiki-platform-core/xwiki-platform-attachment/xwiki-platform-attachment-api/src/main/resources/js/attachment/move.js
+++ b/xwiki-platform-core/xwiki-platform-attachment/xwiki-platform-attachment-api/src/main/resources/js/attachment/move.js
@@ -35,7 +35,7 @@ require(['jquery', config.treeWebjar], function ($) {
   // TODO: Should be moved to a common place (see XWIKI-19320).
   function getPageWhiteIcon() {
     if (pageWhiteIcon === undefined) {
-      const iconURL = `${XWiki.contextPath}/rest/wikis/${XWiki.currentWiki}/iconThemes/icons?name=page_white`;
+      const iconURL = `${XWiki.contextPath}/rest/wikis/${encodeURIComponent(XWiki.currentWiki)}/iconThemes/icons?name=page_white`;
       var response = window.fetch(iconURL, {
         headers: {
           'Accept': 'application/json'
diff --git a/xwiki-platform-core/xwiki-platform-attachment/xwiki-platform-attachment-api/src/main/resources/templates/attachment/moveStep1.vm b/xwiki-platform-core/xwiki-platform-attachment/xwiki-platform-attachment-api/src/main/resources/templates/attachment/moveStep1.vm
index e11c813b857..fea98d36436 100644
--- a/xwiki-platform-core/xwiki-platform-attachment/xwiki-platform-attachment-api/src/main/resources/templates/attachment/moveStep1.vm
+++ b/xwiki-platform-core/xwiki-platform-attachment/xwiki-platform-attachment-api/src/main/resources/templates/attachment/moveStep1.vm
@@ -124,7 +124,7 @@
               <div class="modal-content">
                 <div class="modal-header">
                   <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
+                    <span aria-hidden="true">$services.icon.renderHTML('cross')</span>
                   </button>
                   <h5 class="modal-title">
                     $escapetool.xml($services.localization.render('attachment.move.targetLocation.modal.title'))
diff --git a/xwiki-platform-core/xwiki-platform-ckeditor/xwiki-platform-ckeditor-plugins/src/main/webjar/xwiki-dialog/modal.js b/xwiki-platform-core/xwiki-platform-ckeditor/xwiki-platform-ckeditor-plugins/src/main/webjar/xwiki-dialog/modal.js
index 029db54ab33..94461947117 100644
--- a/xwiki-platform-core/xwiki-platform-ckeditor/xwiki-platform-ckeditor-plugins/src/main/webjar/xwiki-dialog/modal.js
+++ b/xwiki-platform-core/xwiki-platform-ckeditor/xwiki-platform-ckeditor-plugins/src/main/webjar/xwiki-dialog/modal.js
@@ -25,26 +25,53 @@ define('modalTranslationKeys', [], [
 
 define('modal', ['jquery', 'l10n!modal', 'bootstrap'], function($, translations) {
   'use strict';
-  var modalTemplate = 
-    '<div class="modal" tabindex="-1" role="dialog" data-backdrop="static">' +
-      '<div class="modal-dialog" role="document">' +
-        '<div class="modal-content">' +
-          '<div class="modal-header">' +
-            '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
-              '<span aria-hidden="true">&times;</span>' +
-            '</button>' +
-            '<h4 class="modal-title"></h4>' +
-          '</div>' +
-          '<div class="modal-body"></div>' +
-          '<div class="modal-footer">' +
-            '<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>' +
-            '<button type="button" class="btn btn-primary" disabled="disabled">OK</button>' +
-          '</div>' +
+  // Fetch the cross icon from the icon theme to fill up the modal template.
+  let iconURL = `${XWiki.contextPath}/rest/wikis/${encodeURIComponent(XWiki.currentWiki)}/iconThemes/icons?name=cross`;
+  // Default value taken until the fetch is fulfilled
+  var closeIconTemplate = `<span aria-hidden="true">&times;</span>`;
+  $.get(iconURL, function(response) {
+    // We override the close button content template if the request is successful
+    let iconMetadata = response.getElementsByTagName('icon')[0];
+    console.log(iconMetadata);
+    if (iconMetadata.getElementsByTagName('iconSetType')[0].textContent === 'IMAGE') {
+      closeIconTemplate = '<img src="' + iconMetadata.getElementsByTagName('url')[0].textContent +
+          '" alt="" />';
+    } else if (iconMetadata.getElementsByTagName('iconSetType')[0].textContent === 'FONT') {
+      closeIconTemplate = '<span class="' +
+          iconMetadata.getElementsByTagName('cssClass')[0].textContent +
+          '" aria-hidden="true"></span>';
+    }
+    // Once we retrieve the icon value, we
+    // 1. Replace all the uses of the icon in the DOM already generated
+    const closeButtons = document.querySelectorAll(
+      '.modal > .modal-dialog > .modal-content > .modal-header > button.close');
+    closeButtons.forEach((button)=> {
+      button.innerHTML = closeIconTemplate;
+    });
+    // 2. replace the modal template used to create new modals
+    closeButtonTemplate = closeIconTemplate;
+  });
+  let closeButtonTemplate = '<span aria-hidden="true">&times;</span>';
+  let modalTemplate = '<div class="modal" tabindex="-1" role="dialog" data-backdrop="static">' +
+    '<div class="modal-dialog" role="document">' +
+      '<div class="modal-content">' +
+        '<div class="modal-header">' +
+          '<button type="button" class="close" data-dismiss="modal" aria-label="Close">' +
+            closeButtonTemplate +
+          '</button>' +
+          '<h4 class="modal-title"></h4>' +
+        '</div>' +
+        '<div class="modal-body"></div>' +
+        '<div class="modal-footer">' +
+          '<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>' +
+          '<button type="button" class="btn btn-primary" disabled="disabled">OK</button>' +
         '</div>' +
       '</div>' +
-    '</div>',
+    '</div>' +
+  '</div>',
+  
 
-  createModal = function(definition) {
+  createModal = function (definition) {
     // form(Boolean): Whether the modal is a form. Some basic form semantics and behaviour will be added if this is true
     definition = $.extend({
       title: '',
@@ -53,7 +80,7 @@ define('modal', ['jquery', 'l10n!modal', 'bootstrap'], function($, translations)
       dismissLabel: translations.get('cancel'),
       form: false
     }, definition);
-    var modal = $(modalTemplate).addClass(definition['class']).appendTo(document.body);
+    let modal = $(modalTemplate).addClass(definition['class']).appendTo(document.body);
     modal.find('.close').attr({
       title: translations.get('close'),
       'aria-label': translations.get('close')
diff --git a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-security/xwiki-platform-extension-security-api/src/main/resources/templates/extension/security/liveData/advice.vm b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-security/xwiki-platform-extension-security-api/src/main/resources/templates/extension/security/liveData/advice.vm
index 15ef82829d3..e0627283378 100644
--- a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-security/xwiki-platform-extension-security-api/src/main/resources/templates/extension/security/liveData/advice.vm
+++ b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-security/xwiki-platform-extension-security-api/src/main/resources/templates/extension/security/liveData/advice.vm
@@ -42,7 +42,7 @@
     <div class="modal-content">
       <div class="modal-header">
         <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-          <span aria-hidden="true">&times;</span>
+          <span aria-hidden="true">$services.icon.renderHTML('cross')</span>
         </button>
         <h2 class="modal-title">
           $escapetool.xml($services.localization.render('extension.security.liveData.advice'))
diff --git a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-security/xwiki-platform-extension-security-api/src/main/resources/templates/extension/security/liveData/cveID.vm b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-security/xwiki-platform-extension-security-api/src/main/resources/templates/extension/security/liveData/cveID.vm
index a2be4779088..bfa9e6d3ec0 100644
--- a/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-security/xwiki-platform-extension-security-api/src/main/resources/templates/extension/security/liveData/cveID.vm
+++ b/xwiki-platform-core/xwiki-platform-extension/xwiki-platform-extension-security/xwiki-platform-extension-security-api/src/main/resources/templates/extension/security/liveData/cveID.vm
@@ -43,7 +43,7 @@
         <div class="modal-content">
           <div class="modal-header">
             <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-              <span aria-hidden="true">&times;</span>
+              <span aria-hidden="true">$services.icon.renderHTML('cross')</span>
             </button>
             <h2 class="modal-title">
               $escapetool.xml($services.localization.render(
diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/commentsinline.vm b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/commentsinline.vm
index c11d9123f33..7fedc5fba8e 100644
--- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/commentsinline.vm
+++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/commentsinline.vm
@@ -336,7 +336,7 @@ $xwiki.ssfx.use('uicomponents/viewers/comments.css', true)
     <div class="modal-dialog">
       <div class="modal-content">
         <div class="modal-header">
-          <button type="button" class="close" data-dismiss="modal">&times;</button>
+          <button type="button" class="close" data-dismiss="modal">$services.icon.renderHTML('cross')</button>
           <div class="modal-title">$services.localization.render('core.viewers.comments.permalink')</div>
         </div>
         <div class="modal-body">
@@ -363,7 +363,7 @@ $xwiki.ssfx.use('uicomponents/viewers/comments.css', true)
     <div class="modal-dialog">
       <div class="modal-content">
         <div class="modal-header">
-          <button type="button" class="close" data-dismiss="modal">&times;</button>
+          <button type="button" class="close" data-dismiss="modal">$services.icon.renderHTML('cross')</button>
           <div class="modal-title">$services.localization.render('core.viewers.comments.delete')</div>
         </div>
         <div class="modal-body">
diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/export_modal.vm b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/export_modal.vm
index 2d901538139..66f0b5365a3 100644
--- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/export_modal.vm
+++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/export_modal.vm
@@ -208,7 +208,7 @@
     <div class="modal-dialog">
       <div class="modal-content">
         <div class="modal-header">
-          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">$services.icon.renderHTML('cross')</button>
           <div class="modal-title" id="exportTreeModalLabel">
             <span class="modal-title-icon">$services.icon.renderHTML('download')</span>
             #set ($title = $escapetool.xml($services.localization.render('core.exporter.exportAs', ['__format__'])))
diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/previewdiff.vm b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/previewdiff.vm
index fe22cb77e4d..8b95f64418a 100644
--- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/previewdiff.vm
+++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/previewdiff.vm
@@ -59,7 +59,7 @@
   <div class="modal-dialog modal-lg">
     <div class="modal-content">
       <div class="modal-header">
-        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">$services.icon.renderHTML('cross')</button>
         <div class="modal-title" id="previewDiffModalTitle">$services.localization.render('core.editors.save.previewDiff.title')</div>
         <hr />
         <div class="xHint">
diff --git a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/syntaxPicker.js b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/syntaxPicker.js
index 5dbd9e20fb7..e08d7da8a5f 100644
--- a/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/syntaxPicker.js
+++ b/xwiki-platform-core/xwiki-platform-flamingo/xwiki-platform-flamingo-skin/xwiki-platform-flamingo-skin-resources/src/main/resources/flamingo/syntaxPicker.js
@@ -49,9 +49,14 @@
     #set ($discard = $l10n.put($key, $services.localization.render($key)))
   #end
 #end
+#set ($iconNames = ['cross'])
+#set ($icons = {})
+#foreach ($iconName in $iconNames)
+  #set ($discard = $icons.put($iconName, $services.icon.renderHTML($iconName)))
+#end
 #[[*/
 // Start JavaScript-only code.
-(function(l10n) {
+(function(l10n, icons) {
   "use strict";
 
 /**
@@ -114,9 +119,9 @@ require(['jquery', 'xwiki-syntax-converter', 'bootstrap'], function($, syntaxCon
       <div class="modal-dialog" role="document">
         <div class="modal-content">
           <div class="modal-header">
-            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-              <span aria-hidden="true">&times;</span>
-            </button>
+            <button type="button" class="close" data-dismiss="modal" aria-label="Close">`
+              + icons.cross +
+            `</button>
             <h4 class="modal-title"></h4>
           </div>
           <div class="modal-body"></div>
@@ -360,4 +365,4 @@ require(['jquery'], function($) {
 });
 
 // End JavaScript-only code.
-}).apply(']]#', $jsontool.serialize([$l10n]));
+}).apply(']]#', $jsontool.serialize([$l10n, $icons]));
diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/utilities/XWikiIcon.vue b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/utilities/XWikiIcon.vue
index ca0f22ed2cd..53693246fce 100644
--- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/utilities/XWikiIcon.vue
+++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/vue/utilities/XWikiIcon.vue
@@ -86,7 +86,7 @@ export default {
     async fetchRemoteIconDescriptor(iconName) {
       try {
         const parameters = `name=${encodeURIComponent(iconName)}`;
-        const iconURL = `${XWiki.contextPath}/rest/wikis/${XWiki.currentWiki}/iconThemes/icons?${parameters}`;
+        const iconURL = `${XWiki.contextPath}/rest/wikis/${encodeURIComponent(XWiki.currentWiki)}/iconThemes/icons?${parameters}`;
         const response = await window.fetch(iconURL, {
           headers: {
             'Accept': 'application/json'
diff --git a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/webjar/liveDataSource.js b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/webjar/liveDataSource.js
index 17511b759f5..1a7495d4ccf 100644
--- a/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/webjar/liveDataSource.js
+++ b/xwiki-platform-core/xwiki-platform-livedata/xwiki-platform-livedata-webjar/src/main/webjar/liveDataSource.js
@@ -90,7 +90,7 @@ define('xwiki-livedata-source', ['module', 'jquery'], function(module, $) {
       var parameters = {
         // Make sure the response is not retrieved from cache (IE11 doesn't obey the caching HTTP headers).
         timestamp: new Date().getTime(),
-        namespace: `wiki:${XWiki.currentWiki}`
+        namespace: `wiki:${encodeURIComponent(XWiki.currentWiki)}`
       };
       addSourceParameters(parameters, source);
       return `${url}?${$.param(parameters, true)}`;
@@ -140,7 +140,7 @@ define('xwiki-livedata-source', ['module', 'jquery'], function(module, $) {
     }
 
     var getTranslations = function(locale, prefix, keys) {
-      const translationsURL = `${module.config().contextPath}/rest/wikis/${XWiki.currentWiki}/localization/translations`;
+      const translationsURL = `${module.config().contextPath}/rest/wikis/${encodeURIComponent(XWiki.currentWiki)}/localization/translations`;
       return Promise.resolve($.getJSON(translationsURL, $.param({
         locale: locale,
         prefix: prefix,
diff --git a/xwiki-platform-core/xwiki-platform-localization/xwiki-platform-localization-webjar/src/main/webjar/l10n.js b/xwiki-platform-core/xwiki-platform-localization/xwiki-platform-localization-webjar/src/main/webjar/l10n.js
index 6332585f2f1..b27c3494af4 100644
--- a/xwiki-platform-core/xwiki-platform-localization/xwiki-platform-localization-webjar/src/main/webjar/l10n.js
+++ b/xwiki-platform-core/xwiki-platform-localization/xwiki-platform-localization-webjar/src/main/webjar/l10n.js
@@ -20,7 +20,7 @@
 require.config({
   config: {
     'xwiki-l10n': {
-      url: `${XWiki.contextPath}/rest/wikis/${XWiki.currentWiki}/localization/translations`
+      url: `${XWiki.contextPath}/rest/wikis/${encodeURIComponent(XWiki.currentWiki)}/localization/translations`
     }
   }
 });
diff --git a/xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/attachment_macros.vm b/xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/attachment_macros.vm
index 55d86ed30f7..a7091fd6bce 100644
--- a/xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/attachment_macros.vm
+++ b/xwiki-platform-core/xwiki-platform-web/xwiki-platform-web-templates/src/main/resources/templates/attachment_macros.vm
@@ -229,7 +229,7 @@
     <div class="modal-dialog">
       <div class="modal-content">
         <div class="modal-header">
-          <button type="button" class="close" data-dismiss="modal">&times;</button>
+          <button type="button" class="close" data-dismiss="modal">$services.icon.renderHTML('cross')</button>
           <div class="modal-title">$services.localization.render('core.viewers.attachments.delete')</div>
         </div>
         <div class="modal-body">
diff --git a/xwiki-platform-tools/xwiki-platform-tool-standards-validator/src/test/resources/xwiki-invalid.html b/xwiki-platform-tools/xwiki-platform-tool-standards-validator/src/test/resources/xwiki-invalid.html
index dea6a4e1447..59e41632070 100644
--- a/xwiki-platform-tools/xwiki-platform-tool-standards-validator/src/test/resources/xwiki-invalid.html
+++ b/xwiki-platform-tools/xwiki-platform-tool-standards-validator/src/test/resources/xwiki-invalid.html
@@ -389,7 +389,9 @@ window.docgeturl = "/xwiki/bin/get/Main/WebHome";
     <div class="modal-dialog">
       <div class="modal-content">
         <div class="modal-header">
-          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+              <span class="fa fa-times" aria-hidden="true"></span>
+          </button>
           <div class="modal-title" id="exportModalLabel">Export</div>
         </div>
         <div class="modal-body">
diff --git a/xwiki-platform-tools/xwiki-platform-tool-standards-validator/src/test/resources/xwiki-valid.html b/xwiki-platform-tools/xwiki-platform-tool-standards-validator/src/test/resources/xwiki-valid.html
index 2679626d2aa..ab1918429cd 100644
--- a/xwiki-platform-tools/xwiki-platform-tool-standards-validator/src/test/resources/xwiki-valid.html
+++ b/xwiki-platform-tools/xwiki-platform-tool-standards-validator/src/test/resources/xwiki-valid.html
@@ -392,7 +392,9 @@ window.docgeturl = "/xwiki/bin/get/Main/WebHome";
     <div class="modal-dialog">
       <div class="modal-content">
         <div class="modal-header">
-          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
+              <span class="fa fa-times" aria-hidden="true"></span>
+          </button>
           <div class="modal-title" id="exportModalLabel">Export</div>
         </div>
         <div class="modal-body">
-- 
GitLab