Changes for page Create Application

Last modified by Martin Výlet on 12.01.2024 08:04

From version 2.1
edited by superadmin
on 06.01.2023 13:11
Change comment: Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui/14.10.2]
To version 1.1
edited by XWiki Admin
on 26.05.2017 08:18
Change comment: Install extension [org.xwiki.platform:xwiki-platform-appwithinminutes-ui-9.3.1]

Summary

Details

Page properties
Author
... ... @@ -1,1 +1,1 @@
1 -XWiki.superadmin
1 +XWiki.Admin
Syntax
... ... @@ -1,1 +1,1 @@
1 -XWiki 2.1
1 +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="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))
... ... @@ -81,35 +81,29 @@
81 81  #macro (validateAppName)
82 82   #getAppReference
83 83   #if (!$appReference)
84 - <span class="xErrorMsg">$services.localization.render('platform.appwithinminutes.appNameEmptyError')</span>
73 + (% class="xErrorMsg" %)$services.localization.render('platform.appwithinminutes.appNameEmptyError')
85 85   #else
86 86   #getAppDescriptor($appReference)
87 87   #if ($appDescriptor)
88 88   ## Edit an existing application.
89 - #getAppClassReference($appDescriptor)
90 - #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))
91 91   #else
92 92   ## Create a new application.
93 93   #set ($appCodeRef = $services.model.createSpaceReference('Code', $appReference))
94 94   #set ($appClassRef = $services.model.createDocumentReference("$!{appReference.name}Class", $appCodeRef))
95 95   #end
96 - <dl>
97 - <dt>$services.localization.render('platform.appwithinminutes.appNamePreviewHomePageUrlLabel')</dt>
98 - <dd><pre>$!escapetool.xml($xwiki.getDocument($appReference).externalURL)</pre></dd>
99 - <dt>$services.localization.render('platform.appwithinminutes.appNamePreviewCodeSpaceLabel')</dt>
100 - <dd>#hierarchy($appClassRef.parent)</dd>
101 - </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}}
102 102   #set ($appHomeRef = $services.model.resolveDocument('', 'default', $appReference))
103 103   #if ($appDescriptor || $xwiki.exists($appHomeRef) || $xwiki.exists($appClassRef))
104 - <div class="box warningmessage">
105 - $services.localization.render('platform.appwithinminutes.appNameIsUsedWarning')
106 - </div>
93 +
94 + {{warning}}$services.localization.render('platform.appwithinminutes.appNameIsUsedWarning'){{/warning}}
107 107   #end
108 - #if (!$services.security.authorization.hasAccess('script', $xcontext.userReference, $appHomeRef))
109 - <div class="box errormessage">
110 - $escapetool.xml($services.localization.render('platform.appwithinminutes.appHomePageNoScriptRight'))
111 - </div>
112 - #end
113 113   #end
114 114  #end
115 115  
... ... @@ -134,14 +134,11 @@
134 134   #set ($appDescriptors = $services.query.xwql($appDescriptorStatement).bindValue('space', $localSpaceReference).execute())
135 135   #if ($appDescriptors.size() > 0)
136 136   #set ($appDescriptor = $xwiki.getDocument($appDescriptors.get(0)))
137 - #else
138 - #set ($appDescriptor = $NULL)
139 139   #end
140 140  #end
141 141  {{/velocity}}
142 142  
143 143  {{velocity}}
144 -{{html clean="false"}}
145 145  #if ("$!request.appName" != '')
146 146   #if ($xcontext.action == 'get')
147 147   #validateAppName
... ... @@ -149,9 +149,8 @@
149 149   ## CSRF protection is not needed because this step only redirects to the next one passing data in the query string.
150 150   #processStep
151 151   #end
152 -#elseif ($request.wizard == 'true')
132 +#else
153 153   #showStep
154 - #set ($displayDocExtra = false)
155 155  #end
156 -{{/html}}
135 +#set ($displayDocExtra = false)
157 157  {{/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  });