Changes for page LiveTable View Sheet
Last modified by Martin Výlet on 19.03.2025 21:26
From version 1.1
edited by XWiki Admin
on 26.05.2017 08:18
on 26.05.2017 08:18
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui-9.3.1]
To version 3.1
edited by Administrator
on 21.07.2023 12:40
on 21.07.2023 12:40
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/15.5]
Summary
-
Page properties (2 modified, 0 added, 0 removed)
-
Objects (2 modified, 0 added, 0 removed)
Details
- Page properties
-
- Author
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. Admin1 +XWiki.xwikiadm - 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 + * [[$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 + * [[$services.localization.render('platform.appwithinminutes.appHomePageEditAppLabel')>>AppWithinMinutes.CreateApplication||queryString="$queryString" class="action edit"]] 88 + #end 89 + #if ($hasEditTranslations) 90 + * [[$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 + * [[$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 + * [[$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}}
- 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,176 @@ 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 + #set ($currentDocReference = $xwiki.getDocument($request.currentApp).getDocumentReference()) 63 + // if we cannot find any extension related to this page app, it's not part of an extension. 64 + var isNotAnExtension = $services.extension.xar.getInstalledExtensions($currentDocReference).isEmpty(); 65 + 66 + // double negation! if it's an extension, we stop there: we don't want to add custom AWM rename capabilities 67 + if (!isNotAnExtension) { 68 + return; 69 + } 70 + // Hijack the rename page action. 71 + var renameAppModal = $('#renameAppModal'); 72 + $('#tmActionRename').on('click', function(event) { 73 + event.preventDefault(); 74 + renameAppModal.modal(); 75 + }); 76 + 77 + // Form validation. 78 + var appNameInput = $('#renameAppTitle'); 79 + var appParentInput = $('#renameAppParentReference'); 80 + 81 + var appNameEmptyError = renameAppModal.find('.appNameEmptyError'); 82 + var pageExistsError = renameAppModal.find('.pageExistsError'); 83 + var locationForbiddenError = renameAppModal.find('.locationForbiddenError'); 84 + appNameEmptyError.add(pageExistsError).add(locationForbiddenError).hide().insertAfter(appNameInput); 85 + 86 + var getNewAppReference = function(local) { 87 + var appParentReference = local ? null : new XWiki.WikiReference(XWiki.currentWiki); 88 + if (appParentInput.val() !== '') { 89 + appParentReference = XWiki.Model.resolve(appParentInput.val(), XWiki.EntityType.SPACE, appParentReference); 90 + } 91 + return new XWiki.EntityReference(appNameInput.val(), XWiki.EntityType.SPACE, appParentReference); 92 + }; 93 + 94 + var getNewAppHomePage = function() { 95 + var newAppReference = getNewAppReference(); 96 + var newAppHomePageReference = new XWiki.EntityReference('WebHome', XWiki.EntityType.DOCUMENT, newAppReference); 97 + return new XWiki.Document(newAppHomePageReference); 98 + }; 99 + 100 + var startValidation = function() { 101 + if (appNameInput.val() === '') { 102 + return Promise.reject(appNameEmptyError); 103 + } else { 104 + var newAppHomePage = getNewAppHomePage(); 105 + if (newAppHomePage.documentReference.equals(XWiki.currentDocument.documentReference)) { 106 + return Promise.reject(pageExistsError); 107 + } else { 108 + return new Promise((resolve, reject) => { 109 + $.ajax({ 110 + type: 'HEAD', 111 + url: newAppHomePage.getURL() 112 + }).then(reject.bind(null, pageExistsError), response => { 113 + if (response.status === 404) { 114 + $.ajax({ 115 + type: 'HEAD', 116 + url: newAppHomePage.getURL('edit') 117 + }).then( 118 + () => resolve(), 119 + () => reject(locationForbiddenError) 120 + ); 121 + } else if (response.status === 403) { 122 + reject(locationForbiddenError); 123 + } else { 124 + resolve(); 125 + } 126 + }); 127 + }); 128 + } 129 + } 130 + }; 131 + 132 + var scheduleValidation = function() { 133 + // Hide all error messages before starting the asynchronous validation. 134 + renameAppModal.find('.xErrorMsg').hide(); 135 + appNameInput.addClass('loading').validateAsync(startValidation, 500, 'awm').catch((error) => { 136 + error.show(); 137 + }).finally(() => { 138 + appNameInput.removeClass('loading'); 139 + }); 140 + }; 141 + 142 + appNameInput.add(appParentInput).on('input', scheduleValidation); 143 + 144 + var locationPickerModal = renameAppModal.find('.location-picker .modal'); 145 + renameAppModal.on('shown.bs.modal', function(event) { 146 + // Nested modals are not supported so we have to move the location picker modal outside, but we shouldn't do this 147 + // before the location picker has been initialized. That's why we wait for the rename application modal to be shown 148 + // first. 149 + renameAppModal.after(locationPickerModal); 150 + appNameInput.focus(); 151 + }); 152 + 153 + // Hide the rename application modal when the location picker modal is shown. 154 + locationPickerModal.removeClass('fade').on('show.bs.modal', function(event) { 155 + renameAppModal.modal('hide'); 156 + // Show the rename application modal when the location picker modal is hidden. 157 + }).on('hidden.bs.modal', function(event) { 158 + renameAppModal.modal('show'); 159 + }); 160 + 161 + renameAppModal.find('form').on('submit', function(event) { 162 + event.preventDefault(); 163 + renameApp(getRenameData($(this))); 164 + }); 165 + 166 + var getRenameData = function(form) { 167 + var data = getFormData(form); 168 + data.newAppReference = XWiki.Model.serialize(getNewAppReference(true)); 169 + delete data.newAppName; 170 + delete data.newAppParentReference; 171 + data.outputSyntax = 'plain'; 172 + return data; 173 + }; 174 + 175 + var getFormData = function(form) { 176 + var data = {}; 177 + form.serializeArray().forEach(function(parameter) { 178 + // Keep the first value; 179 + if (!data.hasOwnProperty(parameter.name)) { 180 + data[parameter.name] = parameter.value; 181 + } 182 + }); 183 + return data; 184 + }; 185 + 186 + var renameApp = function(data) { 187 + // Disable the form to prevent it from being submitted twice. 188 + renameAppModal.find('fieldset').prop('disabled', true); 189 + var notification = new XWiki.widgets.Notification( 190 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.inProgress')), 191 + 'inprogress' 192 + ); 193 + var renameAppURL = new XWiki.Document('RenameApplication', 'AppWithinMinutes').getURL('get'); 194 + Promise.resolve($.post(renameAppURL, data)).then(updateAppHomePage).then(function() { 195 + renameAppModal.modal('hide'); 196 + notification.replace(new XWiki.widgets.Notification( 197 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.done')), 198 + 'done' 199 + )); 200 + // Delay a bit the redirect so that the user notices the success message. 201 + setTimeout(function() { 202 + window.location.href = getNewAppHomePage().getURL(); 203 + }, 0); 204 + }).catch(function() { 205 + notification.replace(new XWiki.widgets.Notification( 206 + $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.failed')), 207 + 'error' 208 + )); 209 + }).finally(function() { 210 + // Re-enable the form. 211 + renameAppModal.find('fieldset').prop('disabled', false); 212 + }); 213 + }; 214 + 215 + var updateAppHomePage = function() { 216 + return new Promise((resolve, reject) => { 217 + var newAppHomePageEditURL = getNewAppHomePage().getURL('edit'); 218 + $('<div/>').load(newAppHomePageEditURL + ' #inline', function() { 219 + var formData = $(this).children('form#inline').serializeArray(); 220 + if (formData.length) { 221 + formData.push({name: 'xaction_save', value: true}); 222 + $.post(newAppHomePageEditURL, formData).then(resolve, reject); 223 + } else { 224 + reject(); 225 + } 226 + }); 227 + }); 228 + } 229 +});
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -58,3 +58,12 @@ 58 58 /* Make sure the live table doesn't overflow the action panel. */ 59 59 clear: right; 60 60 } 61 + 62 +/** 63 + * Rename Application 64 + */ 65 +#renameAppTitle.loading { 66 + background-position: right .3em center; 67 + padding-left: 12px; 68 + padding-right: 2em; 69 +}