Modifications pour le document DiagramEditSheet
Modifié par Admin le 19/03/2025 - 19:24
Résumé
-
Objets (2 modifications, 0 ajouts, 0 suppressions)
Détails
- XWiki.JavaScriptExtension[1]
-
- Code
-
... ... @@ -105,18 +105,19 @@ 105 105 var attachmentReference = new XWiki.AttachmentReference(fileName, documentReference); 106 106 var uploadMethod = (diagramConfig.isTemporaryUploadSupported) ? xutils.temporaryUploadAttachment : xutils.uploadAttachment; 107 107 var uploadAttachment = $.proxy(uploadMethod, null, blob, attachmentReference); 108 - // Avoid creating too many versions of the attachment. Upload the attachment even if we failed to delete it first. 109 - return xutils.deleteAttachment(attachmentReference).then(uploadAttachment, uploadAttachment); 108 + return uploadAttachment(); 110 110 }; 111 111 112 112 var imageCache = {}; 113 - var saveFileAsPNGImageAttachment = function(file) { 112 + var saveFileAsPNGImageAttachment = function(file, index, originalPage) { 114 114 var deferred = $.Deferred(); 115 - file.getUi().exportToCanvas(/* callback */ function(canvas) { 114 + let page = file.ui.pages[index]; 115 + file.ui.selectPage(page, true, null); 116 + file.getUi().exportToCanvas(/* callback */ function (canvas) { 116 116 if (canvas) { 117 117 try { 118 - canvas.toBlob(function(blob) { 119 - pipeDeferred(saveBlobAsImageAttachment(blob, 'diagram.png', file.documentReference), deferred);119 + canvas.toBlob(function (blob) { 120 + pipeDeferred(saveBlobAsImageAttachment(blob, `${getXWikiAttachmentName(index)}.png`, file.documentReference), deferred); 120 120 }); 121 121 } catch(err) { 122 122 deferred.reject(); ... ... @@ -129,13 +129,17 @@ 129 129 $jsontool.serialize($services.localization.render('diagram.editor.saveAsImageAttachmentError')), 'error'); 130 130 deferred.reject(); 131 131 }, /* limitHeight */ null, /* ignoreSelection */ true, /* scale */ diagramConfig.pdfImageExportZoom); 133 + file.ui.selectPage(originalPage, true, null); 132 132 return deferred.promise(); 133 133 }; 134 134 135 - var saveFileAsSVGImageAttachment = function(file) { 136 - var deferred = $.Deferred(); 137 + var saveFileAsSVGImageAttachment = function(file, index, originalPage) { 138 + var deferred = $.Deferred() 139 + let page = file.ui.pages[index]; 140 + file.ui.selectPage(page, true, null); 137 137 var svgRoot = file.ui.editor.graph.getSvg(/* background: */ '#ffffff', /* scale: */ null, /* border: */ null, 138 138 /* nocrop: */ true, /* crisp: */ null, /* ignoreSelection: */ true); 143 + file.ui.selectPage(originalPage, true, null); 139 139 // Embed the images because the PDF exporter might not be able to access them. 140 140 file.ui.convertImages(svgRoot, function() { 141 141 var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + ... ... @@ -142,28 +142,62 @@ 142 142 '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n' + 143 143 mxUtils.getXml(svgRoot); 144 144 var blob = new Blob([svg], {type: 'image/svg+xml'}); 145 - pipeDeferred(saveBlobAsImageAttachment(blob, 'diagram.svg', file.documentReference), deferred); 150 + pipeDeferred(saveBlobAsImageAttachment(blob, `${getXWikiAttachmentName(index)}.svg`, file.documentReference), 151 + deferred); 146 146 }, imageCache); 147 147 return deferred.promise(); 148 148 }; 149 149 150 - var saveFileAsImageAttachments = function(file) { 156 + var saveFileAsImageAttachments = function(file, index, originalPage) { 151 151 // This is a workaround for https://github.com/jgraph/drawio/issues/490 152 152 // Stop editing for getting the latest content from diagram 153 153 file.ui.editor.graph.stopEditing(false); 154 154 // We upload the PNG image even if the SVG upload has failed. 155 - var pngUpload = $.proxy(saveFileAsPNGImageAttachment, null, file); 156 - return saveFileAsSVGImageAttachment(file).then(pngUpload, pngUpload); 161 + var pngUpload = $.proxy(saveFileAsPNGImageAttachment, null, file, index, originalPage); 162 + return saveFileAsSVGImageAttachment(file, index, originalPage).then(pngUpload, pngUpload); 157 157 }; 158 158 165 + var getXWikiAttachmentName = function (index) { 166 + if (index == 0) 167 + { 168 + // If is the first page we keep the old naming strategy -> diagram.png / diagram.svg 169 + return "diagram"; 170 + } 171 + return `diagram${index+1}`; 172 + }; 173 + 174 + var deleteAllDiagrams = function() { 175 + let baseUrl = `/xwiki/rest/diagram/${xm.documentReference.toString()}`; 176 + let queryString = $.param({"form_token": xm.form_token}); 177 + return $.post(`${baseUrl}?${queryString}`); 178 + }; 179 + 159 159 var saveFilesAsImageAttachments = function() { 160 - var uploadDeferred = $.Deferred().resolve(); 161 - forEachOpenedFile(function(file) { 162 - // We do the next upload even if the previous uploads have failed. 163 - var nextUpload = $.proxy(saveFileAsImageAttachments, null, file); 164 - uploadDeferred = uploadDeferred.then(nextUpload, nextUpload); 181 + var uploadDeferredList = [] 182 + 183 + forEachOpenedFile(function (file) { 184 + var uploadDeferred = $.Deferred().resolve(); 185 + // Get the current page so we know where to return after saving. 186 + let originalPage = file.ui.currentPage; 187 + 188 + file.ui.pages.forEach(function (page, index) { 189 + // We do the next upload even if the previous uploads have failed. 190 + var nextUpload = $.proxy(saveFileAsImageAttachments, null, file, index,originalPage); 191 + uploadDeferred = uploadDeferred.then(nextUpload, nextUpload); 192 + uploadDeferredList.push(uploadDeferred.promise()); 193 + }); 165 165 }); 166 - return uploadDeferred.promise(); 195 + // Wait for all deferreds to complete. 196 + return $.when.apply($, uploadDeferredList).then( 197 + function () { 198 + // Resolve the overall promise if all succeeded. 199 + return { status: 'success' }; 200 + }, 201 + function () { 202 + // Reject the overall promise if any failed. 203 + return $.Deferred().reject({ status: 'fail' }); 204 + } 205 + ).promise(); 167 167 }; 168 168 169 169 var uploadInProgress = false; ... ... @@ -175,10 +175,13 @@ 175 175 event.stopPropagation(); 176 176 var saveButton = $(event.target); 177 177 saveButton.prop('disabled', true); 178 - saveFilesAsImageAttachments().fail(function(e) { 217 + deleteAllDiagrams() 218 + .then(saveFilesAsImageAttachments) 219 + .catch(function(e) { 179 179 new XWiki.widgets.Notification( 180 180 $jsontool.serialize($services.localization.render('diagram.editor.saveAsImageAttachmentError')), 'error'); 181 - }).always(function() { 222 + }) 223 + .always(function() { 182 182 saveButton.prop('disabled', false).click(); 183 183 }); 184 184 } else { - Parser le contenu
-
... ... @@ -1,1 +1,1 @@ 1 - Oui1 +Non
- XWiki.JavaScriptExtension[2]
-
- Code
-
... ... @@ -18,6 +18,29 @@ 18 18 a.nodeName.toLowerCase() != b.toLowerCase() ? !1 : null == c || a.getAttribute(c) == d; 19 19 }; 20 20 21 +/** 22 + * TODO: When upgrading, make sure to check if this method has changed. 23 + * This method was copied directly from draw.io, and the only change made was the call to this.showDialog. 24 + * Both the width and height were modified to fit better within the XWiki UI. 25 + */ 26 +EditorUi.prototype.showBackgroundImageDialog = function (apply, img, color, showColor) { 27 + apply = (apply != null) ? apply : mxUtils.bind(this, function (image, failed, color, shadowVisible) { 28 + if (!failed) { 29 + var change = new ChangePageSetup(this, (showColor) ? color : null, image); 30 + change.ignoreColor = !showColor; 31 + if (shadowVisible != null && showColor) { 32 + change.shadowVisible = shadowVisible; 33 + } 34 + this.editor.graph.model.execute(change); 35 + } 36 + }); 37 + 38 + var dlg = new BackgroundImageDialog(this, apply, img, color, showColor); 39 + this.showDialog(dlg.container, 420, (showColor) ? 260 : 240, true, true); 40 + dlg.init(); 41 +}; 42 + 43 + 21 21 EditorUi.prototype.showLinkDialog = function(value, selectLabel, callback, showNewWindowOption, linkTarget) { 22 22 var resourceReference = diagramLinkHandler.getResourceReferenceFromCustomLink(value); 23 23 // We append the modal to the body element in order to fix Issue #108: "Inserting a link in full screen mode is not ... ... @@ -42,6 +42,32 @@ 42 42 // Do nothing. 43 43 } 44 44 68 + // Override the Graph.updateSvgLinks method to ensure that the links are preserved in the final SVG. 69 + // We need to directly modify the original method because drawio does not provide a parameter to override the default 70 + // behavior or a smaller method that only performs the replacement. 71 + Graph.prototype.updateSvgLinks = function (node, target, removeCustom) { 72 + var links = node.getElementsByTagName('a'); 73 + for (var i = 0; i < links.length; i++) { 74 + if (links[i].getAttribute('target') == null) { 75 + var href = links[i].getAttribute('href'); 76 + if (href == null) { 77 + href = links[i].getAttribute('xlink:href'); 78 + } 79 + 80 + if (href != null) { 81 + if (target != null && /^https?:\/\//.test(href)) { 82 + // If the href starts with http or https, set the target attribute. 83 + links[i].setAttribute('target', target); 84 + } else if (this.isCustomLink(href)) { 85 + // Handle custom links 86 + let absoluteLink = $('<a/>').attr('href', diagramLinkHandler.getURLFromCustomLink(href)).prop('href'); 87 + links[i].setAttribute('href', absoluteLink); 88 + } 89 + } 90 + } 91 + } 92 + }; 93 + 45 45 // Overwrite Graph.getSvg in order to replace XWiki custom links with absolute URLs. 46 46 // Also fix the text fallback for viewers with no support for foreignObjects. 47 47 var originalGraphGetSVG = Graph.prototype.getSvg; ... ... @@ -101,318 +101,6 @@ 101 101 return converter; 102 102 }; 103 103 104 - // Copied from the drawio version 24.5.4 to include a fix for importing a file in an empty diagram. This method should 105 - // be removed once we upgrade to a drawio version >= 24.4.0. Being a big method, the structure was altered just to 106 - // make it shorter. 107 - var importFilesNew = function(files, x, y, maxSize, fn, resultFn, filterFn, barrierFn, 108 - resizeDialog, maxBytes, resampleThreshold, ignoreEmbeddedXml, evt) { 109 - maxSize = (maxSize != null) ? maxSize : this.maxImageSize; 110 - maxBytes = (maxBytes != null) ? maxBytes : this.maxImageBytes; 111 - var crop = x != null && y != null; 112 - var resizeImages = true; 113 - x = (x != null) ? x : 0; 114 - y = (y != null) ? y : 0; 115 - // Checks if large images are imported 116 - var largeImages = false; 117 - if (!mxClient.IS_CHROMEAPP && files != null) { 118 - var thresh = resampleThreshold || this.resampleThreshold; 119 - for (var i = 0; i < files.length; i++) { 120 - if (files[i].type.substring(0, 9) !== 'image/svg' && 121 - files[i].type.substring(0, 6) === 'image/' && 122 - files[i].size > thresh) { 123 - largeImages = true; 124 - break; 125 - } 126 - } 127 - } 128 - var doImportFiles = mxUtils.bind(this, function() { 129 - var graph = this.editor.graph; 130 - var gs = graph.gridSize; 131 - fn = (fn != null) ? fn : mxUtils.bind(this, function(data, mimeType, x, y, w, h, filename, done, file) { 132 - try { 133 - if (data != null && data.substring(0, 10) == '<mxlibrary') { 134 - this.spinner.stop(); 135 - this.loadLibrary(new LocalLibrary(this, data, filename)); 136 - this.showSidebar(); 137 - return null; 138 - } 139 - else { 140 - // Drop on empty file ignores drop location 141 - if (this.isCompatibleString(data) && files.length == 1 && evt != null && 142 - evt.type == 'drop' && this.isBlankFile() && !this.canUndo()) { 143 - crop = false; 144 - x = 0; 145 - y = 0; 146 - } 147 - return this.importFile(data, mimeType, x, y, w, h, filename, 148 - done, file, crop, ignoreEmbeddedXml, evt); 149 - } 150 - } 151 - catch (e) { 152 - this.handleError(e); 153 - return null; 154 - } 155 - }); 156 - resultFn = (resultFn != null) ? resultFn : mxUtils.bind(this, function(cells) { 157 - graph.setSelectionCells(cells); 158 - }); 159 - if (this.spinner.spin(document.body, mxResources.get('loading'))) { 160 - var count = files.length; 161 - var remain = count; 162 - var queue = []; 163 - // Barrier waits for all files to be loaded asynchronously 164 - var barrier = mxUtils.bind(this, function(index, fnc) { 165 - queue[index] = fnc; 166 - if (--remain == 0) { 167 - this.spinner.stop(); 168 - if (barrierFn != null) { 169 - barrierFn(queue); 170 - } 171 - else { 172 - var cells = []; 173 - graph.getModel().beginUpdate(); 174 - try { 175 - for (var j = 0; j < queue.length; j++) { 176 - var tmp = queue[j](); 177 - if (tmp != null) { 178 - cells = cells.concat(tmp); 179 - } 180 - } 181 - } 182 - finally { 183 - graph.getModel().endUpdate(); 184 - } 185 - } 186 - resultFn(cells); 187 - } 188 - }); 189 - for (var i = 0; i < count; i++) { 190 - (mxUtils.bind(this, function(index) { 191 - var file = files[index]; 192 - if (file != null) { 193 - var reader = new FileReader(); 194 - reader.onload = mxUtils.bind(this, function(e) { 195 - if (filterFn == null || filterFn(file)) { 196 - try { 197 - if (file.type.substring(0, 6) == 'image/') { 198 - if (file.type.substring(0, 9) == 'image/svg') { 199 - // Checks if SVG contains content attribute 200 - var data = Graph.clipSvgDataUri(e.target.result); 201 - var comma = data.indexOf(','); 202 - var svgText = decodeURIComponent(escape(atob(data.substring(comma + 1)))); 203 - var root = mxUtils.parseXml(svgText); 204 - var svgs = root.getElementsByTagName('svg'); 205 - if (svgs.length > 0) { 206 - var svgRoot = svgs[0]; 207 - var cont = (ignoreEmbeddedXml) ? null : svgRoot.getAttribute('content'); 208 - if (cont != null && cont.charAt(0) != '<' && cont.charAt(0) != '%') { 209 - cont = unescape((window.atob) ? atob(cont) : Base64.decode(cont, true)); 210 - } 211 - if (cont != null && cont.charAt(0) == '%') { 212 - cont = decodeURIComponent(cont); 213 - } 214 - if (cont != null && (cont.substring(0, 8) === '<mxfile ' || 215 - cont.substring(0, 14) === '<mxGraphModel ')) { 216 - barrier(index, mxUtils.bind(this, function() { 217 - return fn(cont, 'text/xml', x + index * gs, y + index * gs, 0, 0, file.name); 218 - })); 219 - } 220 - else { 221 - // SVG needs special handling to add viewbox if missing and 222 - // find initial size from SVG attributes (only for IE11) 223 - barrier(index, mxUtils.bind(this, function() { 224 - try { 225 - // Parses SVG and find width and height 226 - if (root != null) { 227 - var svgs = root.getElementsByTagName('svg'); 228 - if (svgs.length > 0) { 229 - var svgRoot = svgs[0]; 230 - var w = svgRoot.getAttribute('width'); 231 - var h = svgRoot.getAttribute('height'); 232 - if (w != null && w.charAt(w.length - 1) != '%') { 233 - w = parseFloat(w); 234 - } 235 - else { 236 - w = NaN; 237 - } 238 - if (h != null && h.charAt(h.length - 1) != '%') { 239 - h = parseFloat(h); 240 - } 241 - else { 242 - h = NaN; 243 - } 244 - // Check if viewBox attribute already exists 245 - var vb = svgRoot.getAttribute('viewBox'); 246 - if (vb == null || vb.length == 0) { 247 - svgRoot.setAttribute('viewBox', '0 0 ' + w + ' ' + h); 248 - } 249 - // Uses width and height from viewbox for 250 - // missing width and height attributes 251 - else if (isNaN(w) || isNaN(h)) { 252 - var tokens = vb.split(' '); 253 - if (tokens.length > 3) { 254 - w = parseFloat(tokens[2]); 255 - h = parseFloat(tokens[3]); 256 - } 257 - } 258 - data = Editor.createSvgDataUri(mxUtils.getXml(svgRoot)); 259 - var s = Math.min(1, Math.min(maxSize / Math.max(1, w)), maxSize / Math.max(1, h)); 260 - var cells = fn(data, file.type, x + index * gs, y + index * gs, Math.max( 261 - 1, Math.round(w * s)), Math.max(1, Math.round(h * s)), file.name); 262 - // Hack to fix width and height asynchronously 263 - if (cells != null && (isNaN(w) || isNaN(h))) { 264 - var img = new Image(); 265 - img.onload = mxUtils.bind(this, function() { 266 - w = Math.max(1, img.width); 267 - h = Math.max(1, img.height); 268 - cells[0].geometry.width = w; 269 - cells[0].geometry.height = h; 270 - svgRoot.setAttribute('viewBox', '0 0 ' + w + ' ' + h); 271 - data = Editor.createSvgDataUri(mxUtils.getXml(svgRoot)); 272 - var semi = data.indexOf(';'); 273 - if (semi > 0) { 274 - data = data.substring(0, semi) + data.substring(data.indexOf(',', semi + 1)); 275 - } 276 - graph.setCellStyles('image', data, [cells[0]]); 277 - }); 278 - img.src = Editor.createSvgDataUri(mxUtils.getXml(svgRoot)); 279 - } 280 - return cells; 281 - } 282 - } 283 - } 284 - catch (e) { 285 - // ignores any SVG parsing errors 286 - } 287 - return null; 288 - })); 289 - } 290 - } 291 - else { 292 - barrier(index, mxUtils.bind(this, function() { 293 - return null; 294 - })); 295 - } 296 - } 297 - else { 298 - // Checks if PNG+XML is available to bypass code below 299 - var containsModel = false; 300 - if (file.type == 'image/png') { 301 - var xml = (ignoreEmbeddedXml) ? null : this.extractGraphModelFromPng(e.target.result); 302 - if (xml != null && xml.length > 0) { 303 - var img = new Image(); 304 - img.src = e.target.result; 305 - barrier(index, mxUtils.bind(this, function() { 306 - return fn(xml, 'text/xml', x + index * gs, y + index * gs, 307 - img.width, img.height, file.name); 308 - })); 309 - containsModel = true; 310 - } 311 - } 312 - // Additional asynchronous step for finding image size 313 - if (!containsModel) { 314 - // Cannot load local files in Chrome App 315 - if (mxClient.IS_CHROMEAPP) { 316 - this.spinner.stop(); 317 - this.showError(mxResources.get('error'), mxResources.get('dragAndDropNotSupported'), 318 - mxResources.get('cancel'), mxUtils.bind(this, function() 319 - { 320 - // Hides the dialog 321 - }), null, mxResources.get('ok'), mxUtils.bind(this, function() 322 - { 323 - // Redirects to import function 324 - this.actions.get('import').funct(); 325 - }) 326 - ); 327 - } 328 - else { 329 - this.loadImage(e.target.result, mxUtils.bind(this, function(img) { 330 - this.resizeImage(img, e.target.result, mxUtils.bind(this, function(data2, w2, h2) { 331 - barrier(index, mxUtils.bind(this, function() { 332 - // Refuses to insert images above a certain size as they kill the app 333 - if (data2 != null && data2.length < maxBytes) { 334 - var s = (!resizeImages || !this.isResampleImageSize( 335 - file.size, resampleThreshold)) ? 1 : 336 - Math.min(1, Math.min(maxSize / w2, maxSize / h2)); 337 - return fn(data2, file.type, x + index * gs, y + index * gs, 338 - Math.round(w2 * s), Math.round(h2 * s), file.name); 339 - } 340 - else { 341 - this.handleError({message: mxResources.get('imageTooBig')}); 342 - return null; 343 - } 344 - })); 345 - }), resizeImages, maxSize, resampleThreshold, file.size); 346 - }), mxUtils.bind(this, function() { 347 - this.handleError({message: mxResources.get('invalidOrMissingFile')}); 348 - })); 349 - } 350 - } 351 - } 352 - } 353 - else { 354 - var data = e.target.result; 355 - fn(data, file.type, x + index * gs, y + index * gs, 240, 160, file.name, function(cells) { 356 - barrier(index, function() { 357 - return cells; 358 - }); 359 - }, file); 360 - } 361 - } 362 - catch (e) { 363 - // Ignores file parsing error 364 - barrier(index, mxUtils.bind(this, function() { 365 - return null; 366 - })); 367 - if (window.console != null) { 368 - console.error(e, file); 369 - } 370 - } 371 - } 372 - else { 373 - // Ignores file and decrements counter 374 - barrier(index, mxUtils.bind(this, function() 375 - { 376 - return null; 377 - })); 378 - } 379 - }); 380 - // Handles special cases 381 - if (/(\.v(dx|sdx?))($|\?)/i.test(file.name) || /(\.vs(x|sx?))($|\?)/i.test(file.name)) { 382 - fn(null, file.type, x + index * gs, y + index * gs, 240, 160, file.name, function(cells) { 383 - barrier(index, function() { 384 - return cells; 385 - }); 386 - }, file); 387 - } 388 - else if (file.type.substring(0, 5) == 'image' || file.type == 'application/pdf') { 389 - reader.readAsDataURL(file); 390 - } 391 - else { 392 - reader.readAsText(file); 393 - } 394 - } 395 - }))(i); 396 - } 397 - } 398 - }); 399 - if (largeImages) { 400 - // Workaround for lost files array in async code 401 - var tmp = []; 402 - for (var i = 0; i < files.length; i++) { 403 - tmp.push(files[i]); 404 - } 405 - files = tmp; 406 - this.confirmImageResize(function(doResize) { 407 - resizeImages = doResize; 408 - doImportFiles(); 409 - }, resizeDialog); 410 - } 411 - else { 412 - doImportFiles(); 413 - } 414 - }; 415 - 416 416 // Override for uploading the image as attachment instead of encode it to Base64. 417 417 var originalImportFiles = EditorUi.prototype.importFiles; 418 418 EditorUi.prototype.importFiles = function(files, x, y, maxSize, fn, resultFn, filterFn, barrierFn, resizeDialog, ... ... @@ -442,7 +442,7 @@ 442 442 } 443 443 }; 444 444 } 445 - importFiles New.apply(this, importFilesArgs);182 + originalImportFiles.apply(this, importFilesArgs); 446 446 }; 447 447 448 448 // Add support for inserting images by specifying the XWiki attachment reference. ... ... @@ -576,6 +576,15 @@ 576 576 }; 577 577 }); 578 578 316 +define('diagramMenuTranslations', { 317 + prefix: 'diagram.editor.menu.', 318 + keys: [ 319 + // File menu. 320 + 'print.label', 321 + 'print.title' 322 + ] 323 +}); 324 + 579 579 /** 580 580 * Integrates draw.io diagram editor in XWiki. 581 581 */ ... ... @@ -585,11 +585,12 @@ 585 585 'diagram-utils', 586 586 'diagram-url-io', 587 587 'diagram-config', 334 + 'xwiki-l10n!diagramMenuTranslations', 588 588 'diagram-graph-xml-filter', 589 589 'diagram-link-editor', 590 590 'diagram-image-editor', 591 591 'diagram-external-services' 592 -], function($, diagramStore, diagramUtils, diagramUrlIO, diagramConfig) { 339 +], function($, diagramStore, diagramUtils, diagramUrlIO, diagramConfig, l10n) { 593 593 594 594 // These variables are used to decide if an image should be uploaded at original resolution or 595 595 // should be declined for being too big. ... ... @@ -621,6 +621,7 @@ 621 621 622 622 var fixEditorUI = function(editorUI) { 623 623 cleanMenu(editorUI); 371 + renameMenu(editorUI); 624 624 fixKeyboardShortcutsAction(editorUI); 625 625 fixEditorButtons($(editorUI.container)); 626 626 removeThemeButton(); ... ... @@ -646,8 +646,7 @@ 646 646 // 647 647 // Change the service name in order to disable notifications. 648 648 // 649 - EditorUi.prototype.getServiceName = function() 650 - { 397 + EditorUi.prototype.getServiceName = function() { 651 651 return 'xwiki.com'; 652 652 }; 653 653 ... ... @@ -660,11 +660,31 @@ 660 660 var originalAddSubmenu = Menus.prototype.addSubmenu; 661 661 Menus.prototype.addSubmenu = function(name, menu, parent, label) { 662 662 var subMenu = this.get(name); 663 - if (subMenu && subMenu. visible !== false) {664 - originalAddSubmenu.apply(this, arguments); 410 + if (subMenu && subMenu.isEnabled() !== false) { 411 + return originalAddSubmenu.apply(this, arguments); 665 665 } 666 666 }; 667 667 415 + 416 + /* 417 + * Map with all the menu items that we want to have a title. 418 + */ 419 + const titleMap = new Map([ 420 + ['print', l10n['print.title']] 421 + ]); 422 + 423 + /* 424 + * Update the title of the menu items. 425 + */ 426 + var originalAddMenuItem = Menus.prototype.addMenuItem; 427 + Menus.prototype.addMenuItem = function(menu, key, parent, trigger, sprite, label) { 428 + let item = originalAddMenuItem.apply(this, arguments); 429 + if (item != null && titleMap.has(key)) { 430 + item.title = titleMap.get(key); 431 + } 432 + return item; 433 + }; 434 + 668 668 // Remove the language picker because the diagram editor is configured to use the XWiki language. 669 669 var originalCreateMenubar = Menus.prototype.createMenubar; 670 670 Menus.prototype.createMenubar = function(container) { ... ... @@ -684,6 +684,24 @@ 684 684 }; 685 685 686 686 // 454 + // Rename menu options to fit our needs. 455 + // 456 + var renameMenu = function(editorUI) { 457 + const menuItems = [ 458 + // File menu 459 + ['print', l10n['print.label']] 460 + ]; 461 + 462 + // Iterate over the array of tuples 463 + menuItems.forEach(function([menuKey, newLabel]) { 464 + var action = editorUI.actions.actions[menuKey]; 465 + if (action) { 466 + action.label = newLabel; 467 + } 468 + }); 469 + }; 470 + 471 + // 687 687 // Clean the editor menu by removing the features that are not needed. 688 688 // 689 689 var cleanMenu = function(editorUI) { ... ... @@ -696,7 +696,7 @@ 696 696 // Help menu 697 697 'downloadDesktop', 'useOffline', 698 698 // ExportAs 699 - 'exportHtml' 484 + 'exportHtml', 'exportPdf' 700 700 ].forEach(function(actionName) { 701 701 var action = editorUI.actions.actions[actionName]; 702 702 if (action) {