Changes for page Create Application
Last modified by Ludovic Dubost on 2024/07/22 15:51
From version 8.1
edited by Ludovic Dubost
on 2024/07/22 15:51
on 2024/07/22 15:51
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/16.5.0]
To version 6.1
edited by Ludovic Dubost
on 2017/01/07 20:21
on 2017/01/07 20:21
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui-8.4.3]
Summary
-
Page properties (2 modified, 0 added, 0 removed)
-
Objects (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Syntax
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki 2. 11 +XWiki 2.0 - Content
-
... ... @@ -1,56 +1,44 @@ 1 -{{include reference="AppWithinMinutes. VelocityMacros"/}}1 +{{include reference="AppWithinMinutes.WizardStep"/}} 2 2 3 -{{velocity}} 4 -#if ($request.wizard == 'true') 5 - {{include reference="AppWithinMinutes.WizardStep"/}} 6 -#end 7 -{{/velocity}} 8 - 9 9 {{template name="locationPicker_macros.vm" /}} 10 10 11 11 {{velocity output="false"}} 12 -#macro (showStep) 6 +#macro(showStep) 7 + {{html wiki="true"}} 13 13 #appWizardHeader('name') 14 - <div class="wizard-help"> 15 - <p> 16 - <strong>$services.localization.render('platform.appwithinminutes.wizardStepHelpTitle')</strong> 17 - $services.localization.render('platform.appwithinminutes.wizardStepHelpDescription') 18 - </p> 19 - <ul class="steps vertical"> 20 - #foreach($step in $awmSteps) 21 - <li> 22 - <span class="btn btn-xs number">$mathtool.add($foreach.index, 1)</span> 23 - <span class="name">$services.localization.render("appWithinMinutes.wizardStep.${step}.name")</span> 24 - <span class="description">$services.localization.render("appWithinMinutes.wizardStep.${step}.description")</span> 25 - </li> 26 - #end 27 - </ul> 28 - </div> 9 + (% class="wizard-help" %) 10 + ((( 11 + **$services.localization.render('platform.appwithinminutes.wizardStepHelpTitle')** $services.localization.render('platform.appwithinminutes.wizardStepHelpDescription') 12 + (% class="steps vertical" %) 13 + #foreach($step in $awmSteps) 14 + * (% class="number" %)$mathtool.add($foreach.index, 1)(%%) (% class="name" %)$services.localization.render("appWithinMinutes.wizardStep.${step}.name")(%%) 15 + (% class="description" %)$services.localization.render("appWithinMinutes.wizardStep.${step}.description") 16 + #end 17 + ))) 29 29 <form action="$doc.getURL()" method="post" class="xform wizard-body"> 30 - <fieldset> 31 - #locationPicker({ 32 - 'id': 'app', 33 - 'title': { 34 - 'label': 'platform.appwithinminutes.appNameLabel', 35 - 'hint': 'platform.appwithinminutes.appNameHint', 36 - 'name': 'appName' 37 - }, 38 - 'preview': { 39 - 'label': 'appWithinMinutes.createApp.location.label', 40 - 'hint': 'appWithinMinutes.createApp.location.hint' 41 - }, 42 - 'parent': { 43 - 'label': 'appWithinMinutes.createApp.parent.label', 44 - 'hint': 'appWithinMinutes.createApp.parent.hint', 45 - 'name': 'appParentReference', 46 - 'reference': $doc.documentReference.wikiReference, 47 - 'placeholder': 'appWithinMinutes.createApp.parent.placeholder' 48 - } 49 - }) 50 - <div class="appName-preview"></div> 51 - #appWizardFooter(1) 52 - </fieldset> 19 + #locationPicker({ 20 + 'id': 'app', 21 + 'title': { 22 + 'label': 'platform.appwithinminutes.appNameLabel', 23 + 'hint': 'platform.appwithinminutes.appNameHint', 24 + 'name': 'appName' 25 + }, 26 + 'preview': { 27 + 'label': 'appWithinMinutes.createApp.location.label', 28 + 'hint': 'appWithinMinutes.createApp.location.hint' 29 + }, 30 + 'parent': { 31 + 'label': 'appWithinMinutes.createApp.parent.label', 32 + 'hint': 'appWithinMinutes.createApp.parent.hint', 33 + 'name': 'appParentReference', 34 + 'reference': $doc.documentReference.wikiReference, 35 + 'placeholder': 'appWithinMinutes.createApp.parent.placeholder' 36 + } 37 + }) 38 + <div class="appName-preview"></div> 39 + #appWizardFooter(1) 53 53 </form> 41 + {{/html}} 54 54 #end 55 55 56 56 #macro (processStep) ... ... @@ -58,9 +58,10 @@ 58 58 #getAppReference 59 59 #getAppDescriptor($appReference) 60 60 #if ($appDescriptor) 61 - ## Edit an existing application. 62 - #getAppClassReference($appDescriptor) 63 - #set ($appClassRef = $classReference) 49 + ## Edit an existing application. Use the configured class name. 50 + #set ($appClassRef = $appDescriptor.getObject($appDescriptorClassName).getValue('class')) 51 + ## The class reference is relative to the document holding the application descriptor. 52 + #set ($appClassRef = $services.model.resolveDocument($appClassRef, 'explicit', $appDescriptor.documentReference)) 64 64 #else 65 65 ## Create a new application. Use the default class name. 66 66 #set ($appCodeRef = $services.model.createSpaceReference('Code', $appReference)) ... ... @@ -70,7 +70,6 @@ 70 70 #if (!$xwiki.exists($appClassRef)) 71 71 #set ($appHomeRef = $services.model.resolveDocument('', 'default', $appReference)) 72 72 #set ($discard = $queryString.putAll({ 73 - 'form_token': $services.csrf.getToken(), 74 74 'template': 'AppWithinMinutes.ClassTemplate', 75 75 'parent': $services.model.serialize($appHomeRef), 76 76 'title': "$appReference.name Class" ... ... @@ -82,35 +82,29 @@ 82 82 #macro (validateAppName) 83 83 #getAppReference 84 84 #if (!$appReference) 85 - <spanclass="xErrorMsg">$services.localization.render('platform.appwithinminutes.appNameEmptyError')</span>73 + (% class="xErrorMsg" %)$services.localization.render('platform.appwithinminutes.appNameEmptyError') 86 86 #else 87 87 #getAppDescriptor($appReference) 88 88 #if ($appDescriptor) 89 89 ## Edit an existing application. 90 - #getAppClassReference($appDescriptor) 91 - #set ($appClassRef = $classReference) 78 + #set ($appDescriptorObj = $appDescriptor.getObject($appDescriptorClassName)) 79 + #set ($appClassRef = $appDescriptorObj.getValue('class')) 80 + ## The class reference is relative to the document holding the application descriptor. 81 + #set ($appClassRef = $services.model.resolveDocument($appClassRef, 'explicit', $appDescriptor.documentReference)) 92 92 #else 93 93 ## Create a new application. 94 94 #set ($appCodeRef = $services.model.createSpaceReference('Code', $appReference)) 95 95 #set ($appClassRef = $services.model.createDocumentReference("$!{appReference.name}Class", $appCodeRef)) 96 96 #end 97 - <dl> 98 - <dt>$services.localization.render('platform.appwithinminutes.appNamePreviewHomePageUrlLabel')</dt> 99 - <dd><pre>$!escapetool.xml($xwiki.getDocument($appReference).externalURL)</pre></dd> 100 - <dt>$services.localization.render('platform.appwithinminutes.appNamePreviewCodeSpaceLabel')</dt> 101 - <dd>#hierarchy($appClassRef.parent)</dd> 102 - </dl> 87 + ; $services.localization.render('platform.appwithinminutes.appNamePreviewHomePageUrlLabel') 88 + : {{{$!xwiki.getDocument($appReference).externalURL}}} 89 + ; $services.localization.render('platform.appwithinminutes.appNamePreviewCodeSpaceLabel') 90 + : {{html clean="false"}}#hierarchy($appClassRef.parent){{/html}} 103 103 #set ($appHomeRef = $services.model.resolveDocument('', 'default', $appReference)) 104 104 #if ($appDescriptor || $xwiki.exists($appHomeRef) || $xwiki.exists($appClassRef)) 105 - <div class="box warningmessage"> 106 - $services.localization.render('platform.appwithinminutes.appNameIsUsedWarning') 107 - </div> 93 + 94 + {{warning}}$services.localization.render('platform.appwithinminutes.appNameIsUsedWarning'){{/warning}} 108 108 #end 109 - #if (!$services.security.authorization.hasAccess('script', $xcontext.userReference, $appHomeRef)) 110 - <div class="box errormessage"> 111 - $escapetool.xml($services.localization.render('platform.appwithinminutes.appHomePageNoScriptRight')) 112 - </div> 113 - #end 114 114 #end 115 115 #end 116 116 ... ... @@ -135,14 +135,11 @@ 135 135 #set ($appDescriptors = $services.query.xwql($appDescriptorStatement).bindValue('space', $localSpaceReference).execute()) 136 136 #if ($appDescriptors.size() > 0) 137 137 #set ($appDescriptor = $xwiki.getDocument($appDescriptors.get(0))) 138 - #else 139 - #set ($appDescriptor = $NULL) 140 140 #end 141 141 #end 142 142 {{/velocity}} 143 143 144 144 {{velocity}} 145 -{{html clean="false"}} 146 146 #if ("$!request.appName" != '') 147 147 #if ($xcontext.action == 'get') 148 148 #validateAppName ... ... @@ -150,9 +150,8 @@ 150 150 ## CSRF protection is not needed because this step only redirects to the next one passing data in the query string. 151 151 #processStep 152 152 #end 153 -#else if ($request.wizard == 'true')132 +#else 154 154 #showStep 155 - #set ($displayDocExtra = false) 156 156 #end 157 - {{/html}}135 +#set ($displayDocExtra = false) 158 158 {{/velocity}}
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,24 +1,18 @@ 1 -require(['jquery' , 'xwiki-form-validation-async'], function($) {1 +require(['jquery'], function($) { 2 2 var appNameInput = $('input[name="appName"]'); 3 3 var appParentInput = $('input[name="appParentReference"]'); 4 4 var preview = $('.appName-preview'); 5 + var submitButton = $('#wizard-next').prop('disabled', true); 5 5 6 - if (appNameInput.val() === '') { 7 - // We use a function instead of passing directly the promise because we want to avoid the "Uncaught (in promise)" 8 - // error. Basically, we want the rejected promise to be caught. 9 - appNameInput.validateAsync(() => Promise.reject(), 'awm'); 10 - } 11 - 12 12 var errorMessage = appNameInput.closest('dd').prev('dt').find('.xErrorMsg'); 13 - if ( !errorMessage.length) {8 + if (errorMessage.size() == 0) { 14 14 errorMessage = $(document.createElement('span')).addClass('xErrorMsg').hide().appendTo(errorMessage.addBack()); 15 15 } 16 16 17 17 var toggleValidationError = function(message) { 18 18 if (message) { 19 - appNameInput.addClass('xErrorField'); 14 + appNameInput.addClass('xErrorField').focus(); 20 20 errorMessage.text(message).show(); 21 - return Promise.reject(); 22 22 } else { 23 23 appNameInput.removeClass('xErrorField'); 24 24 errorMessage.hide(); ... ... @@ -28,24 +28,32 @@ 28 28 var updatePreview = function(content) { 29 29 preview.removeClass('loading').html(content); 30 30 var error = preview.find('.xErrorMsg'); 31 - return toggleValidationError(error.remove().text()); 25 + submitButton.prop('disabled', error.size() > 0); 26 + toggleValidationError(error.remove().text()); 32 32 }; 33 33 34 34 var fetchPreviewUpdate = function() { 35 - if (appNameInput.val() == ='') {36 - return updatePreview('<span class="xErrorMsg">$escapetool.javascript($services.localization.render("platform.appwithinminutes.appNameEmptyError"))</span>');30 + if (appNameInput.val() == '') { 31 + updatePreview('<span class="xErrorMsg">$escapetool.javascript($services.localization.render("platform.appwithinminutes.appNameEmptyError"))</span>'); 37 37 } else { 38 38 preview.addClass('loading'); 39 - return$.get(XWiki.currentDocument.getURL('get'),appNameInput.closest('form').serialize()).then(updatePreview);34 + $.get(XWiki.currentDocument.getURL('get'), submitButton.closest('form').serialize(), updatePreview); 40 40 } 41 41 }; 42 42 43 - appNameInput.add(appParentInput).on('input', () => { 44 - appNameInput.validateAsync(fetchPreviewUpdate, 500, 'awm'); 45 - }).on('keyup', function(event) { 46 - // Show the error message if the user presses Enter before typing anything. 47 - if (event.which === 13 && appNameInput.val() === '' && !appNameInput.hasClass('xErrorField')) { 48 - appNameInput.validateAsync(fetchPreviewUpdate, 'awm').catch(() => appNameInput.focus()); 49 - } 50 - }); 38 + var previewTimeout; 39 + var schedulePreviewUpdate = function() { 40 + clearTimeout(previewTimeout); 41 + submitButton.prop('disabled', true); 42 + setTimeout(fetchPreviewUpdate, 500); 43 + }; 44 + 45 + appNameInput.add(appParentInput) 46 + .on('input', schedulePreviewUpdate) 47 + .keyup(function(event) { 48 + // Show the error message if the user presses Enter before typing anything. 49 + if (event.which == 13 && appNameInput.val() == '' && !appNameInput.hasClass('xErrorField')) { 50 + fetchPreviewUpdate(); 51 + } 52 + }); 51 51 });