Changes for page Create Application
Last modified by Ludovic Dubost on 2024/07/22 15:51
From 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]
To version 4.1
edited by Ludovic Dubost
on 2015/09/01 11:46
on 2015/09/01 11:46
Change comment:
Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui-7.1]
Summary
-
Page properties (1 modified, 0 added, 0 removed)
-
Objects (2 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -1,136 +1,103 @@ 1 1 {{include reference="AppWithinMinutes.WizardStep"/}} 2 2 3 -{{template name="locationPicker_macros.vm" /}} 4 - 5 5 {{velocity output="false"}} 6 6 #macro(showStep) 7 7 {{html wiki="true"}} 8 - #appWizardHeader( 'name')6 + #appWizardHeader(1) 9 9 (% class="wizard-help" %) 10 10 ((( 11 11 **$services.localization.render('platform.appwithinminutes.wizardStepHelpTitle')** $services.localization.render('platform.appwithinminutes.wizardStepHelpDescription') 12 12 (% class="steps vertical" %) 13 - #foreach($ stepin$awmSteps)14 - * (% class="number" %)$ mathtool.add($foreach.index, 1)(%%) (% class="name" %)$services.localization.render("appWithinMinutes.wizardStep.${step}.name")(%%)15 - (% class="description" %)$services.localization.render("app WithinMinutes.wizardStep.${step}.description")11 + #foreach($index in [1, 2, 3]) 12 + * (% class="number" %)$index(%%) (% class="name" %)$services.localization.render("platform.appwithinminutes.wizardStep${index}Name")(%%) 13 + (% class="description" %)$services.localization.render("platform.appwithinminutes.wizardStep${index}Description") 16 16 #end 17 17 ))) 18 18 <form action="$doc.getURL()" method="post" class="xform wizard-body"> 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> 17 + ; <label for="appName">$services.localization.render('platform.appwithinminutes.appNameLabel')</label> 18 + (% class="xHint" %)$services.localization.render('platform.appwithinminutes.appNameHint') 19 + : <input type="text" id="appName" name="appName" /> 39 39 #appWizardFooter(1) 40 40 </form> 41 41 {{/html}} 42 42 #end 43 43 44 -#macro (processStep) 25 +#macro(getAppDescriptor $appName) 26 + #set($appDescriptorClassName = 'AppWithinMinutes.LiveTableClass') 27 + #set($appDescriptorStatement = "from doc.object($appDescriptorClassName) as obj where doc.space = :space") 28 + #set($appDescriptors = $services.query.xwql($appDescriptorStatement).bindValue('space', $appName).execute()) 29 + #if($appDescriptors.size() > 0) 30 + #set($appDescriptor = $xwiki.getDocument($appDescriptors.get(0))) 31 + #end 32 +#end 33 + 34 +#macro(processStep) 45 45 ## Check if the application already exists. 46 - # getAppReference47 - #getAppDescriptor($app Reference)48 - #if 36 + #set($appName = $request.appName) 37 + #getAppDescriptor($appName) 38 + #if($appDescriptor) 49 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))40 + #set($classStringRef = $appDescriptor.getObject($appDescriptorClassName).getProperty('class').value) 41 + ## The class string reference is relative to the document holding the application descriptor. 42 + #set($classRef = $services.model.resolveDocument($classStringRef, 'explicit', $appDescriptor.documentReference)) 53 53 #else 54 54 ## Create a new application. Use the default class name. 55 - #set ppCodeRef=$services.model.createSpaceReference('Code',$appReference))56 - #set appClassRef = $services.model.createDocumentReference("$!{appReference.name}Class", $appCodeRef))45 + #set($className = "#toXMLName($appName)") 46 + #set($classRef = $services.model.createDocumentReference($doc.wiki, "${className}Code", "${className}Class")) 57 57 #end 58 - #set ($queryString = {'wizard': true}) 59 - #if (!$xwiki.exists($appClassRef)) 60 - #set ($appHomeRef = $services.model.resolveDocument('', 'default', $appReference)) 61 - #set ($discard = $queryString.putAll({ 62 - 'template': 'AppWithinMinutes.ClassTemplate', 63 - 'parent': $services.model.serialize($appHomeRef), 64 - 'title': "$appReference.name Class" 65 - })) 48 + #set($queryString = 'wizard=true') 49 + #if(!$xwiki.exists($classRef)) 50 + #set($classTitle = "$appName Class") 51 + #set($appHomeRef = $services.model.createDocumentReference($doc.wiki, $appName, 'WebHome')) 52 + #set($classParent = $services.model.serialize($appHomeRef)) 53 + #set($queryString = "$queryString&editor=inline&template=AppWithinMinutes.ClassTemplate&parent=$escapetool.url($classParent)&title=$escapetool.url($classTitle)&AppWithinMinutes.MetadataClass_0_dataSpaceName=$escapetool.url($appName)") 66 66 #end 67 - $response.sendRedirect($xwiki.getURL($ appClassRef, 'edit', $escapetool.url($queryString)))55 + $response.sendRedirect($xwiki.getURL($classRef, 'edit', $queryString)) 68 68 #end 69 69 70 -#macro (validateAppName) 71 - #getAppReference 72 - #if (!$appReference) 73 - (% class="xErrorMsg" %)$services.localization.render('platform.appwithinminutes.appNameEmptyError') 58 +#macro(validateAppName $appName) 59 + #getAppDescriptor("$!appName") 60 + #if($appDescriptor) 61 + ## Edit an existing application. 62 + #set($appHomeRef = $appDescriptor.documentReference) 63 + #set($classStringRef = $appDescriptor.getObject($appDescriptorClassName).getProperty('class').value) 64 + ## The class string reference is relative to the document holding the application descriptor. 65 + #set($appClassRef = $services.model.resolveDocument($classStringRef, 'explicit', $appDescriptor.documentReference)) 74 74 #else 75 - #getAppDescriptor($appReference) 76 - #if ($appDescriptor) 77 - ## Edit an existing application. 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)) 82 - #else 83 - ## Create a new application. 84 - #set ($appCodeRef = $services.model.createSpaceReference('Code', $appReference)) 85 - #set ($appClassRef = $services.model.createDocumentReference("$!{appReference.name}Class", $appCodeRef)) 67 + ## Create a new application. 68 + #set($className = "#toXMLName($appName)") 69 + #if($className == '') 70 + (% class="xErrorMsg" %)$services.localization.render('platform.appwithinminutes.appNameInvalidClassNameError') 86 86 #end 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}} 91 - #set ($appHomeRef = $services.model.resolveDocument('', 'default', $appReference)) 92 - #if ($appDescriptor || $xwiki.exists($appHomeRef) || $xwiki.exists($appClassRef)) 93 - 94 - {{warning}}$services.localization.render('platform.appwithinminutes.appNameIsUsedWarning'){{/warning}} 95 - #end 72 + #set($appHomeRef = $services.model.createDocumentReference($doc.wiki, $appName, 'WebHome')) 73 + #set($appClassRef = $services.model.createDocumentReference($doc.wiki, "$!{className}Code", "$!{className}Class")) 96 96 #end 97 -#end 75 + #set($appHomeURL = $stringtool.removeEnd($xwiki.getDocument($appHomeRef).getExternalURL(), 'WebHome')) 76 + ; $services.localization.render('platform.appwithinminutes.appNamePreviewHomePageUrlLabel') 77 + : {{{$!appHomeURL}}} 78 + ; $services.localization.render('platform.appwithinminutes.appNamePreviewDataSpaceLabel') 79 + : {{{$appHomeRef.wikiReference.name}}} » {{{$appHomeRef.lastSpaceReference.name}}} 80 + ; $services.localization.render('platform.appwithinminutes.appNamePreviewCodeSpaceLabel') 81 + : {{{$appClassRef.wikiReference.name}}} » {{{$appClassRef.lastSpaceReference.name}}} 82 + ; $services.localization.render('platform.appwithinminutes.appNamePreviewClassReferenceLabel') 83 + : {{{$appClassRef.wikiReference.name}}} » {{{$appClassRef.lastSpaceReference.name}}} » {{{$appClassRef.name}}} 84 + #if($appDescriptor || $xwiki.exists($appHomeRef) || $xwiki.exists($appClassRef)) 98 98 99 -#macro (getAppReference) 100 - #if ($request.resolve == 'true') 101 - #set ($appReference = $services.model.resolveSpace($request.appName)) 102 - #elseif ("$!request.appName" != '') 103 - #set ($parentReference = $doc.documentReference.wikiReference) 104 - #if ("$!request.appParentReference" != '') 105 - #set ($parentReference = $services.model.resolveSpace($request.appParentReference)) 106 - #end 107 - #set ($appReference = $services.model.createSpaceReference($request.appName, $parentReference)) 108 - #else 109 - #set ($appReference = $NULL) 86 + {{warning}}$services.localization.render('platform.appwithinminutes.appNameIsUsedWarning'){{/warning}} 110 110 #end 111 111 #end 112 - 113 -#macro (getAppDescriptor $appReference) 114 - #set ($appDescriptorClassName = 'AppWithinMinutes.LiveTableClass') 115 - #set ($appDescriptorStatement = "from doc.object($appDescriptorClassName) as obj where doc.space = :space") 116 - #set ($localSpaceReference = $services.model.serialize($appReference, 'local')) 117 - #set ($appDescriptors = $services.query.xwql($appDescriptorStatement).bindValue('space', $localSpaceReference).execute()) 118 - #if ($appDescriptors.size() > 0) 119 - #set ($appDescriptor = $xwiki.getDocument($appDescriptors.get(0))) 120 - #end 121 -#end 122 122 {{/velocity}} 123 123 124 124 {{velocity}} 125 -#if 126 - #if 127 - #validateAppName 92 +#if("$!request.appName" != '') 93 + #if($xcontext.action == 'get') 94 + #validateAppName($request.appName) 128 128 #else 129 129 ## CSRF protection is not needed because this step only redirects to the next one passing data in the query string. 130 - #processStep 97 + #processStep() 131 131 #end 132 132 #else 133 - #showStep 100 + #showStep() 134 134 #end 135 -#set isplayDocExtra= false)102 +#set($docextras=[]) 136 136 {{/velocity}}
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,53 +1,89 @@ 1 -require(['jquery'], function($) { 2 - var appNameInput = $('input[name="appName"]'); 3 - var appParentInput = $('input[name="appParentReference"]'); 4 - var preview = $('.appName-preview'); 5 - var submitButton = $('#wizard-next').prop('disabled', true); 1 +var XWiki = (function (XWiki) { 6 6 7 - var errorMessage = appNameInput.closest('dd').prev('dt').find('.xErrorMsg'); 8 - if (errorMessage.size() == 0) { 9 - errorMessage = $(document.createElement('span')).addClass('xErrorMsg').hide().appendTo(errorMessage.addBack()); 3 +XWiki.DeferredUpdater = Class.create({ 4 + initialize : function(updatable) { 5 + this.elapsedHandler = updatable.onUpdate.bind(updatable); 6 + this.updatable = updatable; 7 + }, 8 + deferUpdate : function() { 9 + if (this.timer) { 10 + clearTimeout(this.timer); 11 + } 12 + this.timer = setTimeout(this.elapsedHandler, 500); 10 10 } 14 +}); 11 11 12 - var toggleValidationError = function(message) { 16 +XWiki.AppNameValidator = Class.create({ 17 + initialize : function(input, submitButton) { 18 + this.input = input; 19 + this.deferredUpdater = new XWiki.DeferredUpdater(this); 20 + var updateScheduler = this._scheduleUpdate.bindAsEventListener(this); 21 + ['keypress', 'paste', 'cut'].each(function(eventType) { 22 + input.observe(eventType, updateScheduler); 23 + }.bind(this)); 24 + 25 + this.submitButton = submitButton; 26 + this.submitButton.observe('click', this._onSubmit.bindAsEventListener(this)); 27 + 28 + this.preview = new Element('div', {'class': 'appName-preview'}); 29 + this.input.insert({after: this.preview}); 30 + 31 + var previousDT = input.up('dd').previous(); 32 + this.errorMessage = previousDT.down('xErrorMsg'); 33 + if (!this.errorMessage) { 34 + this.errorMessage = new Element('span', {'class': 'xErrorMsg'}); 35 + previousDT.insert(this.errorMessage.hide()); 36 + } 37 + }, 38 + _onSubmit : function(event) { 39 + if (!this.input._validated) { 40 + event.stop(); 41 + this._scheduleUpdate(); 42 + } 43 + }, 44 + _scheduleUpdate : function(event) { 45 + if(!this.input._validated || [9, 13, 35, 36, 37, 38, 39, 40].indexOf(event.keyCode) < 0) { 46 + this.input._validated = false; 47 + this.deferredUpdater.deferUpdate(); 48 + } 49 + }, 50 + _onValidate : function(response) { 51 + this.preview.removeClassName('loading').update(response.responseText); 52 + var error = this.preview.down('.xErrorMsg'); 53 + this.input._validated = !error; 54 + this._showError(error ? error.remove().firstChild.nodeValue : ''); 55 + }, 56 + _showError : function(message) { 13 13 if (message) { 14 - appNameInput.addClass('xErrorField').focus();15 - errorMessage.te xt(message).show();58 + this.input.addClassName('xErrorField').focus(); 59 + this.errorMessage.update(message.escapeHTML()).show(); 16 16 } else { 17 - appNameInput.removeClass('xErrorField');18 - errorMessage.hide(); 61 + this.input.removeClassName('xErrorField'); 62 + this.errorMessage.hide(); 19 19 } 20 - }; 21 - 22 - var updatePreview = function(content) { 23 - preview.removeClass('loading').html(content); 24 - var error = preview.find('.xErrorMsg'); 25 - submitButton.prop('disabled', error.size() > 0); 26 - toggleValidationError(error.remove().text()); 27 - }; 28 - 29 - var fetchPreviewUpdate = function() { 30 - if (appNameInput.val() == '') { 31 - updatePreview('<span class="xErrorMsg">$escapetool.javascript($services.localization.render("platform.appwithinminutes.appNameEmptyError"))</span>'); 64 + }, 65 + onUpdate : function() { 66 + if (this.input.value == '') { 67 + this._onValidate({ 68 + responseText: '<span class="xErrorMsg">$escapetool.javascript($services.localization.render('platform.appwithinminutes.appNameEmptyError'))</span>' 69 + }); 32 32 } else { 33 - preview.addClass('loading'); 34 - $.get(XWiki.currentDocument.getURL('get'), submitButton.closest('form').serialize(), updatePreview); 71 + this.preview.addClassName('loading'); 72 + new Ajax.Request('$doc.getURL('get')', { 73 + method: 'get', 74 + parameters: {'appName': this.input.value}, 75 + onSuccess: this._onValidate.bind(this) 76 + }); 35 35 } 36 - }; 78 + } 79 +}); 37 37 38 - var previewTimeout;39 - var schedulePreviewUpdate =function(){40 - clearTimeout(previewTimeout);41 - submitButton.prop('disabled', true);42 - setTimeout(fetchPreviewUpdate, 500);43 - };81 +function init() { 82 + var appNameInput = $('appName'); 83 + appNameInput && new XWiki.AppNameValidator(appNameInput, $('wizard-next')); 84 + return !!appNameInput; 85 +} 86 +(XWiki.domIsLoaded && init()) || document.observe('xwiki:dom:loaded', init); 44 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 - }); 53 -}); 88 +return XWiki; 89 +}(XWiki || {}));
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -24,6 +24,10 @@ 24 24 margin-bottom: 1em; 25 25 } 26 26 27 +.appName-preview dl tt { 28 + color: $theme.textColor; 29 +} 30 + 27 27 .appName-preview dt { 28 28 font-weight: normal; 29 29 margin-top: 1em; ... ... @@ -32,8 +32,3 @@ 32 32 .appName-preview dt:after { 33 33 content: ":" 34 34 } 35 - 36 -.appName-preview .breadcrumb { 37 - background-color: transparent; 38 - padding: 0; 39 -} - Content Type
-
... ... @@ -1,1 +1,0 @@ 1 -CSS