Changes for page LiveTable View Sheet
Last modified by Mark Kohlmann on 2025/01/19 06:47
From version 1.1
edited by Mark Kohlmann
on 2020/04/02 23:25
on 2020/04/02 23:25
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui-9.4]
To version 3.1
edited by Mark Kohlmann
on 2024/07/26 08:06
on 2024/07/26 08:06
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/16.5.0]
Summary
-
Page properties (2 modified, 0 added, 0 removed)
-
Attachments (0 modified, 0 added, 1 removed)
-
Objects (2 modified, 0 added, 0 removed)
Details
- Page properties
-
- Author
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. MarkKohlmann1 +XWiki.mark\.kohlmann@chiefintegrations\.com - Content
-
... ... @@ -1,110 +1,217 @@ 1 -{{ velocity}}2 - #set($liveTableObj = $doc.getObject('AppWithinMinutes.LiveTableClass'))3 - #if($liveTableObj)4 - set($discard= $doc.use($liveTableObj))5 - #set($discard = $xwiki.ssx.use('AppWithinMinutes.LiveTableViewSheet')) 6 - #set($discard = $xwiki.jsx.use('AppWithinMinutes.LiveTableViewSheet')) 1 +{{template name="locationPicker_macros.vm" /}} 2 + 3 +{{velocity output="false"}} 4 +#macro (displayApp) 5 + #set ($discard = $xwiki.ssx.use('AppWithinMinutes.LiveTableViewSheet')) 6 + #set ($discard = $xwiki.jsx.use('AppWithinMinutes.LiveTableViewSheet', {'currentApp': $doc.getDocumentReference()})) 7 7 #if (!$isReadOnly) 8 - ## Determine the user's rights 9 - #set($classFullName = $liveTableObj.getProperty('class').value) 10 - #set($className = $stringtool.removeEnd($classFullName, 'Class')) 11 - #set ($templateProviderReference = $services.model.resolveDocument("${className}TemplateProvider")) 12 - #set ($creationRestrictions = $xwiki.getDocument($templateProviderReference).getValue('creationRestrictions')) 13 - #if ($creationRestrictions) 14 - #if ($creationRestrictions.size() > 0) 15 - #set ($dataSpaceRef = $services.model.resolveSpace($creationRestrictions.get(0))) 16 - #else 17 - ## There is no data space as the user can create application entries anywhere. Let's use the application space 18 - ## when the user clicks on the Add New Entry link from the home page. 19 - #set ($dataSpaceRef = $doc.documentReference.parent) 20 - #end 21 - #else 22 - ## The template provider is missing. Fall-back on the old 'dataSpace' property. 23 - #set ($dataSpaceRef = $services.model.resolveSpace($liveTableObj.getValue('dataSpace'), 'explicit', 24 - $doc.documentReference)) 25 - #end 26 - #set($hasCreateData = $services.security.authorization.hasAccess('edit', $dataSpaceRef)) 27 - #set($hasDeleteData = $services.security.authorization.hasAccess('admin', $dataSpaceRef)) 28 - #set($classRef = $services.model.resolveDocument($classFullName)) 29 - #set($hasEditApplication = $services.security.authorization.hasAccess('edit', $classRef)) 30 - #set($translationsRef = $services.model.resolveDocument("${className}Translations")) 31 - #set($hasEditTranslations = $xwiki.isMultiLingual() && $xwiki.exists($translationsRef) 32 - && $services.security.authorization.hasAccess('edit', $translationsRef)) 33 - #set($hasDeleteApplication = $hasDeleteData 34 - && $services.security.authorization.hasAccess('admin', $doc.documentReference.parent) 35 - && $services.security.authorization.hasAccess('admin', $classRef.parent)) 36 - ## Display the application actions based on the user's rights 37 - #if($hasCreateData || $hasDeleteData || $hasEditApplication || $hasEditTranslations || $hasDeleteApplication) 38 - (% id="actionBox" class="floatinginfobox" %) 39 - ((( 40 - = $services.localization.render('platform.appwithinminutes.appHomePageActionsHeading') = 41 - #if($hasCreateData) 42 - * [[$services.localization.render('platform.appwithinminutes.appHomePageAddEntryHint')>>||anchor="AddNewEntry" class="action add"]]## 43 - #set($entryDoc = $services.model.resolveDocument('__entryName__', 'explicit', $dataSpaceRef)) 44 - ## We need to set the title if we want to be able to sort or filter the doc.title live table column. 45 - #set ($params = { 46 - 'template': "${className}Template", 47 - 'title': '__entryName__', 48 - 'parent': $services.model.serialize($doc.documentReference, 'local') 49 - }) 50 - #if ($xwiki.getDocument($classRef).xWikiClass.properties.size() > 0) 51 - ## The entry has properties so go in edit mode to edit them. 52 - #set ($action = 'edit') 53 - #set ($params.editor = 'inline') 54 - #else 55 - ## There are no properties to edit so create the new entry and get back to the home page. 56 - #set ($action = 'save') 57 - #set ($discard = $params.putAll({ 58 - 'xredirect': $doc.getURL(), 59 - 'form_token': $services.csrf.token 60 - })) 61 - #end 62 - {{html}}<input type="hidden" value="$xwiki.getURL($entryDoc, $action, $escapetool.url($params))" />{{/html}} 63 - #end 64 - #if($hasEditApplication) 65 - #set ($queryString = $escapetool.url({ 66 - 'appName': $doc.space, 67 - 'resolve': true 68 - })) 69 - * [[$services.localization.render('platform.appwithinminutes.appHomePageEditAppLabel')>>AppWithinMinutes.CreateApplication||queryString="$queryString" class="action edit"]] 70 - #end 71 - #if($hasEditTranslations) 72 - * [[$services.localization.render('platform.appwithinminutes.appHomePageTranslateAppLabel')>>path:$xwiki.getURL($translationsRef, 'edit', 'editor=wiki')||class="action translate"]] 73 - #end 74 - #if($hasDeleteData) 75 - #set ($deleteDataURL = $xwiki.getURL('AppWithinMinutes.DeleteApplication', 'view', $escapetool.url({ 76 - 'appName': $doc.space, 77 - 'resolve': true, 78 - 'scope': 'entries', 79 - 'xredirect': $doc.getURL() 80 - }))) 81 - * [[$services.localization.render('platform.appwithinminutes.appHomePageDeleteEntriesLabel')>>path:$deleteDataURL||class="action deleteData"]] 82 - #end 83 - #if($hasDeleteApplication) 84 - #set ($deleteAppURL = $xwiki.getURL('AppWithinMinutes.DeleteApplication', 'view', $escapetool.url({ 85 - 'appName': $doc.space, 86 - 'resolve': true, 87 - 'xredirect': $doc.getURL() 88 - }))) 89 - * [[$services.localization.render('platform.appwithinminutes.appHomePageDeleteAppLabel')>>path:$deleteAppURL||class="action delete"]] 90 - #end 91 - ))) 92 - #end 8 + #displayAppActions 93 93 #end 94 94 $doc.display('description') 95 95 ## Display the live table only if it was generated. 96 - #if($doc.content.length() > 0) 12 + #if ($doc.content.length() > 0) 97 97 = $services.localization.render('platform.appwithinminutes.appLiveTableHeading') = 98 - ## We don't use the Include macro (with empty reference) because we want the content to be executed with the rights 99 - ## of the current document rather than the rights of the sheet. This is important because the user can modify the 100 - ## content of the application home page which means we could execute untrusted content with the rights of the sheet. 101 - ## Ideally we should use the Display macro with a parameter to disable the sheet, but we don't have this parameter. 102 - ## We don't clean the HTML content because getRenderedContent() should produce clean HTML, unless the user has 103 - ## disabled the HTML cleaning, in which case he will get what he asked for. Note that one good reason to disable 104 - ## HTML cleaning is to preserve the whitespaces in the attribute values. 105 - ## Escape {{ in the rendered content to be sure that the HTML macro is not closed unintentionally. 106 - {{html clean="false"}}$doc.getRenderedContent($doc.content, 107 - $doc.syntax.toIdString()).replace('{{', '&#123;&#123;'){{/html}} 14 + 15 + {{include reference="" author="target"/}} 108 108 #end 109 109 #end 18 + 19 +#macro (displayAppActions) 20 + ## Determine the user's rights 21 + #set ($className = $stringtool.removeEnd($classFullName, 'Class')) 22 + #set ($templateProviderReference = $services.model.resolveDocument("${className}TemplateProvider")) 23 + #set ($templateProvider = $xwiki.getDocument($templateProviderReference)) 24 + #set ($creationRestrictions = $templateProvider.getValue('creationRestrictions')) 25 + #if ($creationRestrictions) 26 + #if ($creationRestrictions.size() > 0) 27 + #set ($dataSpaceRef = $services.model.resolveSpace($creationRestrictions.get(0))) 28 + #else 29 + ## There is no data space as the user can create application entries anywhere. Let's use the application space 30 + ## when the user clicks on the Add New Entry link from the home page. 31 + #set ($dataSpaceRef = $doc.documentReference.parent) 32 + #end 33 + #else 34 + ## The template provider is missing. Fall-back on the old 'dataSpace' property. 35 + #set ($dataSpaceRef = $services.model.resolveSpace($doc.getValue('dataSpace'), 'explicit', 36 + $doc.documentReference)) 37 + #end 38 + #set ($hasCreateData = $services.security.authorization.hasAccess('edit', $dataSpaceRef)) 39 + #set ($hasDeleteData = $services.security.authorization.hasAccess('admin', $dataSpaceRef)) 40 + #set ($translationsRef = $services.model.resolveDocument("${className}Translations")) 41 + #set ($hasEditTranslations = $xwiki.isMultiLingual() && $xwiki.exists($translationsRef) 42 + && $services.security.authorization.hasAccess('edit', $translationsRef)) 43 + #set ($classRef = $services.model.resolveDocument($classFullName)) 44 + #set ($hasEditApplication = $services.security.authorization.hasAccess('edit', $classRef)) 45 + #set ($hasDeleteApplication = $hasDeleteData 46 + && $services.security.authorization.hasAccess('admin', $doc.documentReference.parent) 47 + && $services.security.authorization.hasAccess('admin', $classRef.parent)) 48 + ## Display the application actions based on the user's rights 49 + #if ($hasCreateData || $hasDeleteData || $hasEditApplication || $hasEditTranslations || $hasDeleteApplication) 50 + (% id="actionBox" class="floatinginfobox" %) 51 + ((( 52 + = $services.localization.render('platform.appwithinminutes.appHomePageActionsHeading') = 53 + #if ($hasCreateData) 54 + * [[{{displayIcon name="add"/}} $services.localization.render('platform.appwithinminutes.appHomePageAddEntryHint')>>||anchor="AddNewEntry" class="action add"]]## 55 + #if ("$!templateProvider.getValue('terminal')" == '1') 56 + #set ($entryReference = $services.model.createDocumentReference('__entryName__', $dataSpaceRef)) 57 + #else 58 + #set ($entryReference = $services.model.resolveDocument('', 'default', 59 + $services.model.createSpaceReference('__entryName__', $dataSpaceRef))) 60 + #end 61 + ## We need to set the title if we want to be able to sort or filter the doc.title live table column. 62 + #set ($params = { 63 + 'form_token': $services.csrf.token, 64 + 'template': "${className}Template", 65 + 'title': '__entryName__', 66 + 'parent': $services.model.serialize($doc.documentReference, 'local') 67 + }) 68 + #if ($xwiki.getDocument($classRef).xWikiClass.properties.size() > 0) 69 + ## The entry has properties so go in edit mode to edit them. 70 + #set ($action = 'edit') 71 + #set ($params.editor = 'inline') 72 + #else 73 + ## There are no properties to edit so create the new entry and get back to the home page. 74 + #set ($action = 'save') 75 + #set ($discard = $params.putAll({ 76 + 'xredirect': $doc.getURL(), 77 + 'form_token': $services.csrf.token 78 + })) 79 + #end 80 + {{html}}<input type="hidden" value="$xwiki.getURL($entryReference, $action, $escapetool.url($params))" />{{/html}} 81 + #end 82 + #if ($hasEditApplication) 83 + #set ($queryString = $escapetool.url({ 84 + 'appName': $doc.space, 85 + 'resolve': true 86 + })) 87 + * [[{{displayIcon name="edit"/}} $services.localization.render('platform.appwithinminutes.appHomePageEditAppLabel')>>AppWithinMinutes.CreateApplication||queryString="$queryString" class="action edit"]] 88 + #end 89 + #if ($hasEditTranslations) 90 + * [[{{displayIcon name="translate"/}} $services.localization.render('platform.appwithinminutes.appHomePageTranslateAppLabel')>>path:${xwiki.getURL($translationsRef, 'edit', 'editor=wiki')}||class="action translate"]] 91 + #end 92 + #if ($hasDeleteData) 93 + #set ($deleteDataURL = $xwiki.getURL('AppWithinMinutes.DeleteApplication', 'view', $escapetool.url({ 94 + 'appName': $doc.space, 95 + 'resolve': true, 96 + 'scope': 'entries', 97 + 'xredirect': $doc.getURL() 98 + }))) 99 + * [[{{displayIcon name="cross"/}} $services.localization.render('platform.appwithinminutes.appHomePageDeleteEntriesLabel')>>path:${deleteDataURL}||class="action deleteData"]] 100 + #end 101 + #if ($hasDeleteApplication) 102 + #set ($deleteAppURL = $xwiki.getURL('AppWithinMinutes.DeleteApplication', 'view', $escapetool.url({ 103 + 'appName': $doc.space, 104 + 'resolve': true, 105 + 'xredirect': $doc.getURL() 106 + }))) 107 + * [[{{displayIcon name="trash"/}} $services.localization.render('platform.appwithinminutes.appHomePageDeleteAppLabel')>>path:${deleteAppURL}||class="action delete"]] 108 + #end 109 + ))) 110 + #end 111 +#end 112 + 113 +#macro (renameAppModal) 114 + <div class="modal" id="renameAppModal" tabindex="-1" role="dialog" aria-labelledby="renameAppModal-label" 115 + data-backdrop="static" data-keyboard="false"> 116 + <div class="modal-dialog" role="document"> 117 + <form class="modal-content xform"> 118 + ## The fieldset allows us to disable and enable the entire form quickly and easy. 119 + <fieldset> 120 + <div class="modal-header"> 121 + <button type="button" class="close" data-dismiss="modal" 122 + title="$escapetool.xml($services.localization.render('appWithinMinutes.renameApp.close'))" 123 + aria-label="$escapetool.xml($services.localization.render('appWithinMinutes.renameApp.close'))"> 124 + <span aria-hidden="true">×</span> 125 + </button> 126 + <span class="modal-title" id="renameAppModal-label"> 127 + $escapetool.xml($services.localization.render('appWithinMinutes.renameApp.label')) 128 + </span> 129 + </div> 130 + <div class="modal-body"> 131 + #renameAppModalBody 132 + </div> 133 + <div class="modal-footer"> 134 + <button type="button" class="btn btn-default" data-dismiss="modal"> 135 + $escapetool.xml($services.localization.render('cancel')) 136 + </button> 137 + <button type="submit" class="btn btn-primary" disabled="disabled"> 138 + $escapetool.xml($services.localization.render('core.rename.submit')) 139 + </button> 140 + </div> 141 + </fieldset> 142 + </form> 143 + </div> 144 + </div> 145 +#end 146 + 147 +#macro (renameAppModalBody) 148 + <div class="box infomessage"> 149 + $services.icon.renderHTML('info') 150 + $services.localization.render('appWithinMinutes.renameApp.changeAppTitleInfo') 151 + </div> 152 + <div class="box warningmessage"> 153 + $services.icon.renderHTML('warning') 154 + $services.localization.render('appWithinMinutes.renameApp.regenerateAppCodeWarning') 155 + </div> 156 + <div class="hidden"> 157 + <input type="hidden" name="form_token" value="$!escapetool.xml($services.csrf.token)" /> 158 + <input type="hidden" name="oldAppReference" value="$escapetool.xml( 159 + $services.model.serialize($doc.documentReference.parent, 'local'))"/> 160 + <span class="appNameEmptyError xErrorMsg"> 161 + $services.localization.render("platform.appwithinminutes.appNameEmptyError") 162 + </span> 163 + <span class="pageExistsError xErrorMsg"> 164 + $services.localization.render("appWithinMinutes.renameApp.pageExistsError") 165 + </span> 166 + <span class="locationForbiddenError xErrorMsg"> 167 + $services.localization.render("appWithinMinutes.renameApp.locationForbiddenError") 168 + </span> 169 + </div> 170 + #set ($appName = $doc.pageReference.name) 171 + #set ($isNestedPage = $doc.documentReference.name == $services.model.getEntityReference('DOCUMENT', 'default').name) 172 + #set ($parentReference = $doc.documentReference.parent) 173 + #if ($isNestedPage) 174 + #set ($parentReference = $parentReference.parent) 175 + #end 176 + #locationPicker({ 177 + 'id': 'renameApp', 178 + 'title': { 179 + 'label': 'appWithinMinutes.renameApp.newName.label', 180 + 'hint': 'platform.appwithinminutes.appNameHint', 181 + 'name': 'newAppName', 182 + 'value': $appName, 183 + 'placeholder': 'appWithinMinutes.renameApp.newName.label' 184 + }, 185 + 'preview': { 186 + 'label': 'appWithinMinutes.renameApp.location.label', 187 + 'hint': 'appWithinMinutes.renameApp.location.hint' 188 + }, 189 + 'parent': { 190 + 'label': 'appWithinMinutes.renameApp.parent.label', 191 + 'hint': 'appWithinMinutes.renameApp.parent.hint', 192 + 'name': 'newAppParentReference', 193 + 'reference': $parentReference, 194 + 'placeholder': 'appWithinMinutes.createApp.parent.placeholder' 195 + } 196 + }) 197 +#end 110 110 {{/velocity}} 199 + 200 +{{velocity}} 201 +#set ($liveTableObj = $doc.getObject('AppWithinMinutes.LiveTableClass')) 202 +#if ($liveTableObj) 203 + #set ($discard = $doc.use($liveTableObj)) 204 + #set ($classFullName = $doc.getValue('class')) 205 + #if ("$!classFullName" == '' || !$xwiki.exists($classFullName)) 206 + {{warning}} 207 + $services.icon.render('warning') {{translation key="platform.appwithinminutes.appHomePageMovedWarning"/}} 208 + {{/warning}} 209 + 210 + #end 211 + #displayApp() 212 + 213 + {{html clean="false"}} 214 + #renameAppModal() 215 + {{/html}} 216 +#end 217 +{{/velocity}}
- locate.png
-
- Author
-
... ... @@ -1,1 +1,0 @@ 1 -XWiki.MarkKohlmann - Size
-
... ... @@ -1,1 +1,0 @@ 1 -746 bytes - Content
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -6,7 +6,11 @@ 6 6 this.urlTemplate = trigger.up().next('input[type=hidden]').value; 7 7 8 8 this.input = new Element('input', {type: 'text'}); 9 - this.addButton = new Element('input', {type: 'image', src: '$xwiki.getSkinFile('icons/silk/add.png')', alt: '$escapetool.javascript($services.localization.render('platform.appwithinminutes.appHomePageAddEntryLabel'))'}); 9 + this.addButton = new Element('input', { 10 + type: 'image', 11 + src: '$xwiki.getSkinFile('icons/silk/add.png')', 12 + alt: '$escapetool.javascript($services.localization.render('platform.appwithinminutes.appHomePageAddEntryLabel'))' 13 + }); 10 10 11 11 var container = new Element('div', {id: 'entryNamePopup'}); 12 12 container.insert(this.input); ... ... @@ -50,3 +50,177 @@ 50 50 51 51 return XWiki; 52 52 }(XWiki || {})); 57 + 58 +/** 59 + * Rename Application 60 + */ 61 +require(['jquery', 'bootstrap', 'xwiki-form-validation-async'], function($) { 62 + ## Note: if not currentApp request param is not passed, we default to the wiki home page reference to avoid a NPE 63 + #set ($currentDocReference = $xwiki.getDocument("$!request.currentApp").getDocumentReference()) 64 + // if we cannot find any extension related to this page app, it's not part of an extension. 65 + var isNotAnExtension = $services.extension.xar.getInstalledExtensions($currentDocReference).isEmpty(); 66 + 67 + // double negation! if it's an extension, we stop there: we don't want to add custom AWM rename capabilities 68 + if (!isNotAnExtension) { 69 + return; 70 + } 71 + // Hijack the rename page action. 72 + var renameAppModal = $('#renameAppModal'); 73 + $('#tmActionRename').on('click', function(event) { 74 + event.preventDefault(); 75 + renameAppModal.modal(); 76 + }); 77 + 78 + // Form validation. 79 + var appNameInput = $('#renameAppTitle'); 80 + var appParentInput = $('#renameAppParentReference'); 81 + 82 + var appNameEmptyError = renameAppModal.find('.appNameEmptyError'); 83 + var pageExistsError = renameAppModal.find('.pageExistsError'); 84 + var locationForbiddenError = renameAppModal.find('.locationForbiddenError'); 85 + appNameEmptyError.add(pageExistsError).add(locationForbiddenError).hide().insertAfter(appNameInput); 86 + 87 + var getNewAppReference = function(local) { 88 + var appParentReference = local ? null : new XWiki.WikiReference(XWiki.currentWiki); 89 + if (appParentInput.val() !== '') { 90 + appParentReference = XWiki.Model.resolve(appParentInput.val(), XWiki.EntityType.SPACE, appParentReference); 91 + } 92 + return new XWiki.EntityReference(appNameInput.val(), XWiki.EntityType.SPACE, appParentReference); 93 + }; 94 + 95 + var getNewAppHomePage = function() { 96 + var newAppReference = getNewAppReference(); 97 + var newAppHomePageReference = new XWiki.EntityReference('WebHome', XWiki.EntityType.DOCUMENT, newAppReference); 98 + return new XWiki.Document(newAppHomePageReference); 99 + }; 100 + 101 + var startValidation = function() { 102 + if (appNameInput.val() === '') { 103 + return Promise.reject(appNameEmptyError); 104 + } else { 105 + var newAppHomePage = getNewAppHomePage(); 106 + if (newAppHomePage.documentReference.equals(XWiki.currentDocument.documentReference)) { 107 + return Promise.reject(pageExistsError); 108 + } else { 109 + return new Promise((resolve, reject) => { 110 + $.ajax({ 111 + type: 'HEAD', 112 + url: newAppHomePage.getURL() 113 + }).then(reject.bind(null, pageExistsError), response => { 114 + if (response.status === 404) { 115 + $.ajax({ 116 + type: 'HEAD', 117 + url: newAppHomePage.getURL('edit') 118 + }).then( 119 + () => resolve(), 120 + () => reject(locationForbiddenError) 121 + ); 122 + } else if (response.status === 403) { 123 + reject(locationForbiddenError); 124 + } else { 125 + resolve(); 126 + } 127 + }); 128 + }); 129 + } 130 + } 131 + }; 132 + 133 + var scheduleValidation = function() { 134 + // Hide all error messages before starting the asynchronous validation. 135 + renameAppModal.find('.xErrorMsg').hide(); 136 + appNameInput.addClass('loading').validateAsync(startValidation, 500, 'awm').catch((error) => { 137 + error.show(); 138 + }).finally(() => { 139 + appNameInput.removeClass('loading'); 140 + }); 141 + }; 142 + 143 + appNameInput.add(appParentInput).on('input', scheduleValidation); 144 + 145 + var locationPickerModal = renameAppModal.find('.location-picker .modal'); 146 + renameAppModal.on('shown.bs.modal', function(event) { 147 + // Nested modals are not supported so we have to move the location picker modal outside, but we shouldn't do this 148 + // before the location picker has been initialized. That's why we wait for the rename application modal to be shown 149 + // first. 150 + renameAppModal.after(locationPickerModal); 151 + appNameInput.focus(); 152 + }); 153 + 154 + // Hide the rename application modal when the location picker modal is shown. 155 + locationPickerModal.removeClass('fade').on('show.bs.modal', function(event) { 156 + renameAppModal.modal('hide'); 157 + // Show the rename application modal when the location picker modal is hidden. 158 + }).on('hidden.bs.modal', function(event) { 159 + renameAppModal.modal('show'); 160 + }); 161 + 162 + renameAppModal.find('form').on('submit', function(event) { 163 + event.preventDefault(); 164 + renameApp(getRenameData($(this))); 165 + }); 166 + 167 + var getRenameData = function(form) { 168 + var data = getFormData(form); 169 + data.newAppReference = XWiki.Model.serialize(getNewAppReference(true)); 170 + delete data.newAppName; 171 + delete data.newAppParentReference; 172 + data.outputSyntax = 'plain'; 173 + return data; 174 + }; 175 + 176 + var getFormData = function(form) { 177 + var data = {}; 178 + form.serializeArray().forEach(function(parameter) { 179 + // Keep the first value; 180 + if (!data.hasOwnProperty(parameter.name)) { 181 + data[parameter.name] = parameter.value; 182 + } 183 + }); 184 + return data; 185 + }; 186 + 187 + var renameApp = function(data) { 188 + // Disable the form to prevent it from being submitted twice. 189 + renameAppModal.find('fieldset').prop('disabled', true); 190 + var notification = new XWiki.widgets.Notification( 191 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.inProgress')), 192 + 'inprogress' 193 + ); 194 + var renameAppURL = new XWiki.Document('RenameApplication', 'AppWithinMinutes').getURL('get'); 195 + Promise.resolve($.post(renameAppURL, data)).then(updateAppHomePage).then(function() { 196 + renameAppModal.modal('hide'); 197 + notification.replace(new XWiki.widgets.Notification( 198 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.done')), 199 + 'done' 200 + )); 201 + // Delay a bit the redirect so that the user notices the success message. 202 + setTimeout(function() { 203 + window.location.href = getNewAppHomePage().getURL(); 204 + }, 0); 205 + }).catch(function() { 206 + notification.replace(new XWiki.widgets.Notification( 207 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.failed')), 208 + 'error' 209 + )); 210 + }).finally(function() { 211 + // Re-enable the form. 212 + renameAppModal.find('fieldset').prop('disabled', false); 213 + }); 214 + }; 215 + 216 + var updateAppHomePage = function() { 217 + return new Promise((resolve, reject) => { 218 + var newAppHomePageEditURL = getNewAppHomePage().getURL('edit'); 219 + $('<div/>').load(newAppHomePageEditURL + ' #inline', function() { 220 + var formData = $(this).children('form#inline').serializeArray(); 221 + if (formData.length) { 222 + formData.push({name: 'xaction_save', value: true}); 223 + $.post(newAppHomePageEditURL, formData).then(resolve, reject); 224 + } else { 225 + reject(); 226 + } 227 + }); 228 + }); 229 + } 230 +});
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -16,30 +16,10 @@ 16 16 background: none no-repeat scroll 0 center transparent; 17 17 display: block; 18 18 font-size: .8em; 19 - padding: .3em .3em .3em 20px;19 + padding: .3em .3em .3em .3em; 20 20 text-transform: uppercase; 21 21 } 22 22 23 -#actionBox .action.edit { 24 - background-image: url("$xwiki.getSkinFile('icons/silk/application_edit.png')"); 25 -} 26 - 27 -#actionBox .action.translate { 28 - background-image: url("$doc.getAttachmentURL('locate.png')"); 29 -} 30 - 31 -#actionBox .action.delete { 32 - background-image: url("$xwiki.getSkinFile('icons/silk/application_delete.png')"); 33 -} 34 - 35 -#actionBox .action.deleteData { 36 - background-image: url("$xwiki.getSkinFile('icons/silk/application_form_delete.png')"); 37 -} 38 - 39 -#actionBox .action.add { 40 - background-image: url("$xwiki.getSkinFile('icons/silk/add.png')"); 41 -} 42 - 43 43 #entryNamePopup { 44 44 margin-right: 20px; 45 45 } ... ... @@ -58,3 +58,12 @@ 58 58 /* Make sure the live table doesn't overflow the action panel. */ 59 59 clear: right; 60 60 } 41 + 42 +/** 43 + * Rename Application 44 + */ 45 +#renameAppTitle.loading { 46 + background-position: right .3em center; 47 + padding-left: 12px; 48 + padding-right: 2em; 49 +}