Änderungen von Dokument Attachments
Zuletzt geändert von xwikiadmin am 2025/05/21 09:22
Von Version 3.1
bearbeitet von xwikiadmin
am 2023/10/26 10:36
am 2023/10/26 10:36
Änderungskommentar:
Install extension [com.xwiki.pro:xwiki-pro-macros/1.12]
Auf Version 1.1
bearbeitet von xwikiadmin
am 2023/04/25 11:20
am 2023/04/25 11:20
Änderungskommentar:
Install extension [com.xwiki.pro:xwiki-pro-macros/1.7.1]
Zusammenfassung
-
Seiteneigenschaften (1 geändert, 0 hinzugefügt, 0 gelöscht)
-
Objekte (3 geändert, 0 hinzugefügt, 1 gelöscht)
Details
- Seiteneigenschaften
-
- Inhalt
-
... ... @@ -10,17 +10,17 @@ 10 10 = Parameters = 11 11 12 12 |=Parameter|=Description|=Required|=Default 13 -|**patterns**|Comma-separated list of regular expressions, used to filter attachments by name.|No| 13 +|**patterns**|Comma-separated list of regular expressions, used to filter attachments by name.|No| 14 14 |**sortBy**|Sort attachments by {{{ date }}}, {{{ size }}} or {{{ name }}}|No|{{{ date }}} 15 15 |**sortOrder**|Sort attachments in {{{ ascending }}} or {{{ descending }}} order|No|{{{ ascending }}} 16 16 |**upload**|Allow users to attach new files|No|{{{ true }}} 17 -|**page**|Pages containing the attachments to display. Current page if empty.|No| 17 +|**page**|Pages containing the attachments to display. Current page if empty.|No| 18 18 19 19 = Example Usage = 20 20 21 21 22 22 {{code}} 23 -{{ confluence_attachments23 +{{attachments 24 24 patterns=".*png" 25 25 sortBy="name" 26 26 /}}
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,95 +1,8 @@ 1 -define('xwiki-confluence-attachments-messages', { 2 - prefix: 'core.viewers.attachments.delete.', 3 - keys: [ 4 - 'inProgress', 5 - 'done', 6 - 'error' 7 - ] 8 -}); 9 - 10 -require(['jquery', 'xwiki-l10n!xwiki-confluence-attachments-messages'], function($, l10n) { 11 - var enhanceUploadInputs = function(liveDataElems) { 12 - $.each(liveDataElems.find('input[type=file]'), function() { 13 - // Since the attachments liveData is refreshed on file upload, there is no need for a response container. 14 - new XWiki.FileUploader(this, { 15 - 'progressAutohide': true, 16 - 'responseContainer' : document.createElement('div'), 17 - 'maxFilesize' : parseInt(this.readAttribute('data-max-file-size')) 18 - }); 19 - }) 20 - }; 21 - 22 - $(function() { 23 - enhanceUploadInputs($('.confluenceAttachmentsMacro')); 24 - }) 25 - 26 - $(document).on('xwiki:dom:updated', function(e, data) { 27 - let liveDataElems = $(data.elements).find('.confluenceAttachmentsMacro'); 28 - enhanceUploadInputs(liveDataElems); 29 - }); 30 - 31 - $(document).on('xwiki:html5upload:done', function(e) { 32 - if ($(e.target).prop('id').startsWith('confluenceAttachments')) { 33 - // Select the livedata above the upload form. 34 - const uploadForm = $(e.target).closest('form'); 35 - // The 'xwiki-livedata' CSS class is present only before XWiki version 14.4. 36 - let associatedLivedata = uploadForm.prevAll('.liveData, .xwiki-livedata').first(); 37 - // We do not have access to a liveData object before XWiki 14.4. 38 - if (associatedLivedata.data('liveData') === undefined) { 39 - location.reload(); 40 - } else { 41 - associatedLivedata.data('liveData').updateEntries(); 42 - } 1 +require(['jquery', 'xwiki-events-bridge'], function ($) { 2 + $('#xwikiuploadfile').on('xwiki:html5upload:message', function (event, data) { 3 + if (data.content === 'UPLOAD_FINISHED' && data.type === 'done') { 4 + location.reload(); 43 43 } 44 44 }); 45 - 46 - // 47 - // The delete action methods are similar to the ones from the attachments tab, but couldn't be reused. The problem is 48 - // that when the tab is not opened we cannot just load the attachments.js file, since it expects some elements to be 49 - // already loaded and it produces errors. 50 - // 51 - 52 - /** 53 - * Open the delete confirmation modal on liveData attachment delete button. 54 - */ 55 - $(document).on('click', '.confluenceAttachmentsMacro .attachmentActions .actiondelete', function(e) { 56 - e.preventDefault(); 57 - // The 'xwiki-livedata' CSS class is present only before XWiki version 14.4. 58 - let liveData = $(e.currentTarget).closest('.liveData, .xwiki-livedata'); 59 - var modal = liveData.nextAll('.deleteConfluenceAttachment'); 60 - modal.data('relatedTarget', e.currentTarget); 61 - modal.modal('show'); 62 - }); 63 - 64 - /** 65 - * On delete confirmation, delete attachment and refresh liveData. 66 - */ 67 - $(document).on('click', '.confluenceAttachmentsMacro .deleteConfluenceAttachment input.btn-danger', function(e) { 68 - e.preventDefault(); 69 - var modal = $(e.currentTarget).closest('.deleteConfluenceAttachment'); 70 - var button = $(modal.data('relatedTarget')); 71 - // The 'xwiki-livedata' CSS class is present only before XWiki version 14.4. 72 - let liveData = button.closest('.liveData, .xwiki-livedata'); 73 - var notification; 74 - 75 - $.ajax({ 76 - url : button.prop('href'), 77 - beforeSend : function() { 78 - notification = new XWiki.widgets.Notification(l10n['inProgress'], 'inprogress'); 79 - }, 80 - success : function() { 81 - // We do not have access to a liveData object before XWiki 14.4. 82 - if (liveData.data('liveData') !== undefined) { 83 - liveData.data('liveData').updateEntries(); 84 - notification.replace(new XWiki.widgets.Notification(l10n['done'], 'done')); 85 - } else { 86 - location.reload(); 87 - } 88 - }, 89 - error: function() { 90 - notification.replace(new XWiki.widgets.Notification(l10n['failed'], 'error')); 91 - } 92 - }); 93 - }); 94 94 }); 95 95 - Name
-
... ... @@ -1,1 +1,0 @@ 1 -Confluence Attachments Macro
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -1,15 +1,15 @@ 1 -.confluenceAttachmentsMacro legend { 2 - font-size: 1em; 1 +.confluence-attachment-macro { 2 + .upload-response { 3 + display: none; 4 + } 5 + 6 + #AddAttachment { 7 + margin-top: 15px; 8 + 9 + #attachform { 10 + .buttonwrapper { 11 + display: none; 12 + } 13 + } 14 + } 3 3 } 4 - /* These should be deleted after upgrading to a XWiki parent >= 14.6. */ 5 -.attachmentMimeType { 6 - color: $theme.textSecondaryColor; 7 - font-size: 32px; 8 - height: 32px; 9 - line-height: 32px; 10 - text-align: center; 11 -} 12 -.attachmentMimeType img { 13 - max-height: 32px; 14 - max-width: 48px; 15 -} - Content Type
-
... ... @@ -1,1 +1,1 @@ 1 - CSS1 +LESS - Name
-
... ... @@ -1,1 +1,0 @@ 1 -Confluence Attachments Macro
- XWiki.WikiMacroClass[0]
-
- Makro-Code
-
... ... @@ -1,6 +1,48 @@ 1 1 {{velocity output="false"}} 2 -#macro (getLiveDataSort $return) 3 - ##property 2 +#macro (filterAndSortAttachments $attachmentsFiltered $invalidSortBy $invalidSortOrder) 3 + $xwiki.ssx.use('Confluence.Macros.Attachments') 4 + $xwiki.jsx.use('Confluence.Macros.Attachments') 5 + #if ("$!{request.forceTestRights}" == "1")#template("xwikivars.vm")#end 6 + #template('attachment_macros.vm') 7 + ## Get attachments 8 + #if ("$!wikimacro.parameters.tags" != '') 9 + #set ($tags = $!wikimacro.parameters.tags.split(',')) 10 + #set ($pageReferenceSet = $collectiontool.getSet()) 11 + #foreach ($tag in $tags) 12 + #set ($references = $xwiki.tag.getDocumentsWithTag("$tag")) 13 + #set ($discard = $pageReferenceSet.addAll($references)) 14 + #end 15 + #set ($attachments = []) 16 + #foreach ($pageReference in $pageReferenceSet) 17 + #set ($document = $xwiki.getDocument($pageReference)) 18 + #set ($documentAttachments = $document.attachmentList) 19 + #set ($discard = $attachments.addAll($documentAttachments)) 20 + #end 21 + #else 22 + #set ($attachments = $doc.attachmentList) 23 + #if ("$!wikimacro.parameters.page" != '') 24 + #set ($document = $xwiki.getDocument("$!wikimacro.parameters.page")) 25 + #set ($attachments = $document.attachmentList) 26 + #end 27 + #end 28 + ## Filter attachments 29 + #set ($confluencePatterns = "$!wikimacro.parameters.patterns") 30 + #if ($confluencePatterns == '') 31 + #set($attachmentsFiltered = $attachments) 32 + #else 33 + #set ($patterns = $!confluencePatterns.split(',')) 34 + #set($attachmentsFiltered = []) 35 + #foreach ($attachment in $attachments) 36 + #foreach ($pattern in $patterns) 37 + #set ($matches = $attachment.filename.matches("(?i)$!pattern")) 38 + #if ($matches) 39 + #set ($discard = $attachmentsFiltered.add($attachment)) 40 + #break 41 + #end 42 + #end 43 + #end 44 + #end 45 + ## Sort attachments 4 4 #set ($confluenceSortBy = "$!wikimacro.parameters.sortBy") 5 5 #set ($invalidSortBy = false) 6 6 #if ($confluenceSortBy == 'date') ... ... @@ -14,7 +14,6 @@ 14 14 #else 15 15 #set ($invalidSortBy = true) 16 16 #end 17 - ## order 18 18 #set ($confluenceSortOrder = "$!wikimacro.parameters.sortOrder") 19 19 #set ($invalidSortOrder = false) 20 20 #set ($reverseSortOrderProperties = ['filesize', 'date']) ... ... @@ -31,178 +31,101 @@ 31 31 #set ($sortOrder = 'desc') 32 32 #end 33 33 #else 34 - #set ($invalidSortOrder = true)75 + #set ($invalidSortOrder = false) 35 35 #end 36 - ## return 37 - #if ($invalidSortBy || $invalidSortOrder) 38 - #setVariable("$return", {}) 39 - #else 40 - #setVariable("$return", "$sortBy:$sortOrder") 41 - #end 77 + #set ($attachmentsFiltered = $collectiontool.sort($attachmentsFiltered, "$sortBy:$sortOrder")) 42 42 #end 43 43 44 -#macro (deleteConfluenceAttachmentModal) 45 - ## Copied from the attachments tab code. The original macro cannot be used, since it will interfere with some js 46 - ## specific to attachments tab. Precisely, if the attachments tab is already opened, everything is working correctly. 47 - ## If it is not opened, we need to load the attachments.js code anyway, to use it's listeners, but there are parts 48 - ## that rightfully assume that some elements are present on the page and errors will occur. 49 - <div class="modal fade deleteConfluenceAttachment" tabindex="-1" role="dialog"> 50 - <div class="modal-dialog"> 51 - <div class="modal-content"> 52 - <div class="modal-header"> 53 - <button type="button" class="close" data-dismiss="modal">×</button> 54 - <div class="modal-title">$services.localization.render('core.viewers.attachments.delete')</div> 55 - </div> 56 - <div class="modal-body"> 57 - <div>$services.localization.render('core.viewers.attachments.delete.confirm')</div> 58 - </div> 59 - <div class="modal-footer"> 60 - <input type="button" class="btn btn-danger" data-dismiss="modal" 61 - value="$escapetool.xml($services.localization.render('core.viewers.attachments.delete'))"> 62 - <input type="button" class="btn btn-default" data-dismiss="modal" 63 - value="$escapetool.xml($services.localization.render('cancel'))"> 64 - </div> 65 - </div> 66 - </div> 67 - </div> 68 -#end 69 - 70 -#set ($confluenceAttachmentMacroIndex = -1) 71 -## Code taken and adapted 72 -#macro (showConfluenceAttachments $document) 73 - #template('display_macros.vm') 74 - #set ($confluenceAttachmentMacroIndex = $confluenceAttachmentMacroIndex + 1) 75 - #set ($confluenceAttachmentMacroId = "confluenceAttachments$confluenceAttachmentMacroIndex") 76 - ## 77 - #showConfluenceAttachmentsLiveData($document $confluenceAttachmentMacroId) 78 -#end 79 - 80 -#macro (uploadFileForm $liveDataId) 81 - #set ($upload = "$!wikimacro.parameters.upload") 82 - #if ($upload == 'true' && ($hasEdit || $hasAdmin) && $xcontext.action == 'view') 83 - <form action="$attachmentsDoc.getURL("upload")" enctype="multipart/form-data" method="post"> 84 - <div> 85 - ## CSRF prevention 86 - <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" /> 87 - <fieldset> 88 - <legend>$services.localization.render('promacros.attachments.upload.title')</legend> 89 - <div> 90 - #set ($inputID = "${liveDataId}-uploadFile") 91 - <label class="sr-only" for="${inputID}"> 92 - $services.localization.render('core.viewers.attachments.upload.file') 93 - </label> 94 - <input id="${inputID}" type="file" name="filepath" size="40" class="noitems" 95 - data-max-file-size="$!escapetool.xml($xwiki.getSpacePreference('upload_maxsize'))"/> 96 - </div> 97 - </fieldset> 98 - </div> 99 - </form> 100 - #end 101 -#end 102 - 103 -#macro (supportsAttachJSON $supportsAttachJSON) 104 - ## The attachments.json code uses macros from attachment_macro.vm, so the existence of the attachments livedata macro 105 - ## is an indicator that the template exists and is adapted for livedata. 106 - #template('attachment_macros.vm') 107 - #set ($macroResult = "#showAttachmentsLiveData($doc 'id')") 108 - #set ($supportsAttachJSON = $macroResult.startsWith('{{liveData')) 109 -#end 110 - 111 -## Display a liveData with attachments from the specified document. 112 -#macro (showConfluenceAttachmentsLiveData $attachmentsDoc $liveDataId) 113 - #set ($liveDataConfig = { 114 - 'meta': { 115 - 'propertyDescriptors': [ 116 - { 'id': 'mimeType', 'displayer': 'html'}, 117 - { 'id': 'filename', 'displayer': 'html' }, 118 - { 'id': 'filesize', 'displayer': 'html' }, 119 - { 'id': 'date', 'filter': 'date'}, 120 - { 'id': 'author', 'displayer': 'html' }, 121 - { 'id': 'actions', 'displayer': 'html' } 122 - ], 123 - 'entryDescriptor': { 124 - 'idProperty': 'id' 125 - } 126 - } 127 - }) 128 - 129 - #if ("$!wikimacro.parameters.patterns" != '') 130 - #set ($liveDataConfig.query = {}) 131 - #set ($liveDataConfig.query.filters = [ 132 - { 133 - "property": "filename", 134 - "matchAll": true, 135 - "constraints": [] 136 - } 137 - ]) 138 - #set ($filters = $stringtool.split($wikimacro.parameters.patterns, ',')) 139 - #foreach ($filter in $filters) 140 - #set ($discard = $liveDataConfig.query.filters[0].constraints.add( 141 - { "operator": "contains", "value": "$!filter.trim()" } 142 - )) 143 - #end 144 - #end 145 - #set ($sourceParams = { 146 - 'translationPrefix': 'core.viewers.attachments.livetable.', 147 - 'className': 'XWiki.AllAttachments', 148 - "\$doc": "$attachmentsDoc" 149 - }) 150 - ## Since the correct attachmentsjson.vm was added in XWiki 14.8, we use a copy of its code for backwards compatibility. 151 - #supportsAttachJSON($supportsAttachJSON) 152 - #if ($supportsAttachJSON) 153 - #set ($discard = $sourceParams.put('template', 'xpart.vm')) 154 - #set ($discard = $sourceParams.put('vm', 'attachmentsjson.vm')) 155 - #else 156 - #set ($discard = $sourceParams.put('resultPage', 'Confluence.Macros.AttachmentsJSON')) 157 - #end 158 - #getLiveDataSort($liveDataSort) 80 +#macro (executeMacro) 81 + #filterAndSortAttachments($attachmentsFiltered $invalidSortBy $invalidSortOrder) 159 159 #if ($invalidSortBy) 160 - {{warning}} 161 - Attachment macro: sortBy parameter must be one of 'date', 'size', or 'name' 162 - {{/warning}} 83 + {{error}} 84 + Attachment macro error: sortBy parameter must be one of 'date', 'size', or 'name' 85 + {{/error}} 86 + #break 163 163 #end 164 164 #if ($invalidSortOrder) 165 - {{warning}} 166 - Attachment macro: sortOrder parameter must be one of 'ascending' or 'descending' 167 - {{/warning}} 89 + {{error}} 90 + Attachment macro error: sortOrder parameter must be one of 'ascending' or 'descending' 91 + {{/error}} 92 + #break 168 168 #end 94 + ## Display attachments 95 + {{html clean="false"}} 96 + <div class="confluence-attachment-macro"> 97 + #if ($attachmentsFiltered.size() > 0) 98 + #displayAttachments($attachmentsFiltered) 99 + #deleteAttachmentModal() 100 + #else 101 + <p class="noitems"> 102 + $!escapetool.xml($services.localization.render('core.viewers.attachments.noAttachments')) 103 + </p> 104 + #end 169 169 170 - {{liveData 171 - id="$liveDataId" 172 - properties="mimeType,filename,filesize,date,author,actions" 173 - source='liveTable' 174 - sourceParameters="$escapetool.url($sourceParams)" 175 - sort="$liveDataSort" 176 - limit=5 177 - }}$jsontool.serialize($liveDataConfig){{/liveData}} 106 + ## Allow upload 107 + #set ($upload = "$!wikimacro.parameters.upload") 108 + #if ($upload == 'true' && ($hasEdit || $hasAdmin) && $xcontext.action == 'view') 109 + <form 110 + id="AddAttachment" 111 + action="$doc.getURL("upload")" 112 + method="post" 113 + enctype="multipart/form-data" 114 + > 115 + <div> 116 + ## CSRF prevention 117 + <input 118 + type="hidden" 119 + name="form_token" 120 + value="$!{services.csrf.getToken()}" 121 + /> 178 178 179 - {{html clean="false"}} 180 - #uploadFileForm($liveDataId) 181 - #deleteConfluenceAttachmentModal() 182 - {{/html}} 183 -#end 123 + <fieldset id="attachform"> 124 + <legend> 125 + $!escapetool.xml($services.localization.render('core.viewers.attachments.upload.title')) 126 + </legend> 184 184 128 + <div class="fileupload-field"> 129 + <label 130 + class="hidden" 131 + for="xwikiuploadfile" 132 + > 133 + $!escapetool.xml($services.localization.render('core.viewers.attachments.upload.file')) 134 + </label> 185 185 186 -#macro (executeMacro) 187 - #set ($discard = $xwiki.ssfx.use('js/xwiki/viewers/attachments.css', true)) 188 - #set ($discard = $xwiki.ssfx.use('uicomponents/widgets/upload.css', true)) 189 - #set ($discard = $xwiki.jsfx.use('uicomponents/widgets/upload.js', { 190 - 'forceSkinAction': true, 191 - 'language': $xcontext.locale 192 - })) 193 - #set ($discard = $xwiki.jsx.use("Confluence.Macros.Attachments")) 194 - #set ($discard = $xwiki.ssx.use("Confluence.Macros.Attachments")) 195 - #set ($document = $doc) 196 - #if ("$!wikimacro.parameters.page" != '') 197 - #set ($document = $xwiki.getDocument("$!wikimacro.parameters.page")) 198 - #end 136 + <input 137 + id="xwikiuploadfile" 138 + class="uploadFileInput noitems" 139 + type="file" 140 + name="filepath" 141 + size="40" 142 + data-max-file-size="$!escapetool.xml($xwiki.getSpacePreference('upload_maxsize'))" 143 + /> 144 + </div> 199 199 200 - {{html clean="false" wiki="true"}} 201 - <div class='confluenceAttachmentsMacro'> 202 - #showConfluenceAttachments($document) 203 - </div> 204 - {{/html}} 146 + <div> 147 + <span class="buttonwrapper"> 148 + <input 149 + class="button btn btn-primary" 150 + type="submit" 151 + value="$!escapetool.xml($services.localization.render('core.viewers.attachments.upload.submit'))" 152 + /> 153 + </span> 205 205 155 + <span class="buttonwrapper"> 156 + <a 157 + class="cancel secondary button btn btn-primary" 158 + href="$doc.getURL()" 159 + > 160 + $!escapetool.xml($services.localization.render('core.viewers.attachments.upload.cancel')) 161 + </a> 162 + </span> 163 + </div> 164 + </fieldset> 165 + </div> 166 + </form> 167 + #end 168 + </div> ## .confluence-attachment-macro 169 + {{/html}} 206 206 #end 207 207 {{/velocity}} 208 208 - Standardkategorie
-
... ... @@ -1,0 +1,1 @@ 1 +confluence
- XWiki.WikiMacroParameterClass[9]
-
- Parameter-Vorgabe
-
... ... @@ -1,1 +1,0 @@ 1 -true - Parameter-Beschreibung
-
... ... @@ -1,1 +1,0 @@ 1 -Display an option for uploading files to the selected page. - Parameter verpflichtend
-
... ... @@ -1,1 +1,0 @@ 1 -Nein - Parameter-Name
-
... ... @@ -1,1 +1,0 @@ 1 -upload - Parameter-Typ
-
... ... @@ -1,1 +1,0 @@ 1 -java.lang.Boolean