<
From version < 4.2 >
edited by Administrator
on 2018/04/19 17:15
To version < 3.1 >
edited by Administrator
on 2017/04/21 15:53
>
Change comment: Install extension [com.xwiki.store:application-store-ui-1.4]

Summary

Details

Page properties
Title
... ... @@ -1,0 +1,1 @@
1 +Pricing tab
Hidden
... ... @@ -1,1 +1,1 @@
1 -true
1 +false
Content
... ... @@ -1,308 +1,46 @@
1 -{{include reference="Store.Code.Macros" /}}
1 +{{velocity}}
2 += Extension price =
3 +#if("$!price" == '' && $hasAdmin)
2 2  
3 -{{velocity output="false"}}
4 -#macro (getPriceMatrix $skus)
5 - #set ($priceMatrix = {
6 - 'columns': $collectionstool.sortedSet,
7 - 'rows': $collectionstool.orderedMap
8 - })
9 - #foreach ($sku in $skus)
10 - #set ($support = "$!sku.support")
11 - #set ($users = $mathtool.toNumber($sku.users))
12 - #set ($price = "$!sku.price")
13 - #if ($support && $users && $price)
14 - #set ($pricePerUsers = $priceMatrix.rows.get($support))
15 - #if (!$pricePerUsers)
16 - #set ($pricePerUsers = {})
17 - #set ($discard = $priceMatrix.rows.put($support, $pricePerUsers))
18 - #end
19 - #set ($discard = $pricePerUsers.put($users, $price))
20 - #set ($discard = $priceMatrix.columns.add($users))
21 - #end
22 - #end
23 -#end
5 + {{error}}Admin error: The price field is empty. Please set a price for this extension in the **Store.PayingApps.Code.PayingAppsClass**.{{/error}}
24 24  
25 -#macro (findSKUMatchingCurrentLicense $priceMatrix $minUserCount $currentLicenseDetails)
26 - #set ($skuMatchingCurrentLicense = $NULL)
27 - #if ($priceMatrix.rows.containsKey($currentLicenseDetails.support))
28 - ## Select the best match for the specified support level.
29 - #foreach ($column in $priceMatrix.columns)
30 - #set ($price = $priceMatrix.rows.get($currentLicenseDetails.support).get($column))
31 - #if ($price && $column >= $mathtool.max($minUserCount, $currentLicenseDetails.maxUserCount))
32 - #set ($skuMatchingCurrentLicense = "$currentLicenseDetails.support,$column")
33 - #break
34 - #end
35 - #end
36 - #end
37 - #if (!$skuMatchingCurrentLicense)
38 - ## Select the best match for the specified user limit.
39 - #foreach ($entry in $priceMatrix.rows.entrySet())
40 - #foreach ($column in $priceMatrix.columns)
41 - #set ($price = $entry.value.get($column))
42 - #if ($price && $column >= $mathtool.max($minUserCount, $currentLicenseDetails.maxUserCount))
43 - #set ($skuMatchingCurrentLicense = "$entry.key,$column")
44 - #break
45 - #end
46 - #end
47 - #if ($skuMatchingCurrentLicense)
48 - #break
49 - #end
50 - #end
51 - #end
7 + #set($price = "{{{--}}}")
52 52  #end
53 53  
54 -#macro (displayPriceMatrix $priceMatrix $minUserCount $currentLicenseDetails $readOnly)
55 - <table class="prices">
56 - <tr>
57 - <th class="legend">$escapetool.xml($services.localization.render('store.buyLicense.support'))
58 - / $escapetool.xml($services.localization.render('store.buyLicense.users'))</th>
59 - #foreach ($column in $priceMatrix.columns)
60 - <th class="users#if ($column < $minUserCount) disabled#end"
61 - title="$escapetool.xml($services.localization.render('store.buyLicense.users.hint', [$column]))"
62 - >$escapetool.xml($column)<span class="icon">$services.icon.renderHTML('user')</span></th>
63 - #end
64 - </tr>
65 - #set ($selectedSKU = $NULL)
66 - #if (!$readOnly && $currentLicenseDetails)
67 - #findSKUMatchingCurrentLicense($priceMatrix $minUserCount $currentLicenseDetails)
68 - #set ($selectedSKU = $skuMatchingCurrentLicense)
69 - #end
70 - #foreach ($entry in $priceMatrix.rows.entrySet())
71 - <tr class="support-$escapetool.xml($entry.key)">
72 - <th><a tabindex="0" role="button" data-toggle="popover" data-trigger="focus" data-html="true"
73 - title="$escapetool.xml($services.localization.render("store.buyLicense.support.${entry.key}.title"))"
74 - data-content="$escapetool.xml($services.localization.render(
75 - "store.buyLicense.support.${entry.key}.description"))"
76 - >$escapetool.xml($services.localization.render("store.buyLicense.support.$entry.key"))<span
77 - class="icon">$services.icon.renderHTML('info')</span></a></th>
78 - #foreach ($column in $priceMatrix.columns)
79 - #set ($price = $entry.value.get($column))
80 - #if ($price)
81 - #set ($sku = "$entry.key,$column")
82 - #set ($disabled = $column < $minUserCount)
83 - #if (!$disabled && !$selectedSKU && !$readOnly)
84 - #set ($selectedSKU = $sku)
85 - #end
86 - <td class="price price-euro#if ($disabled) disabled#elseif ($selectedSKU == $sku) active#end"
87 - data-support="$escapetool.xml($entry.key)" data-users="$escapetool.xml($column)">
88 - <label>#if (!$readOnly)<input type="radio" name="sku" value="$escapetool.xml($sku)" required="required"
89 - #if ($disabled)disabled="disabled"#elseif ($selectedSKU == $sku)checked="checked"#end
90 - />#end$escapetool.xml($price)</label>
91 - </td>
92 - #else
93 - <td/>
94 - #end
95 - #end
96 - </tr>
97 - #end
98 - </table>
99 -#end
10 +This application costs **$price euros/year** and you get the following:
100 100  
101 -#macro (getLicenseDetails)
102 - #set ($licenseDetails = {})
103 - #foreach ($name in ['firstName', 'lastName', 'email', 'instanceId'])
104 - #set ($discard = $licenseDetails.put($name, $request.session.getAttribute("com.xwiki.store.buyer.$name")))
105 - #end
106 - #set ($licenseDetails.featureId = $doc.getValue('id'))
107 - #set ($licenseDetails.extensionVersion = $request.version)
108 - #if ("$!licenseDetails.extensionVersion" == '')
109 - ## Use the latest stable version.
110 - #set ($versions = $services.extension.resolveVersions($licenseDetails.featureId, 0, -1))
111 - ## The versions are returned in ascending order and we want the latest.
112 - ## Note that we can't access the last item directly. We're forced to iterate.
113 - #foreach ($version in $versions)
114 - #if ($version.type == 'STABLE')
115 - #set ($licenseDetails.extensionVersion = $version.value)
116 - #end
117 - #end
118 - #end
119 - #set ($licenseDetails.licenseType = 'paid')
120 -#end
12 + (% class="col-xs-12 col-lg-12" id="benefits" %) (((
13 + (% class="col-xs-12 col-s-4 col-lg-4" %) (((
14 + image:key.png
15 + == 1 year license ==
16 + By purchasing an XWiki Application License, you'll benefit from it during one year.
17 + )))
18 + (% class="col-xs-12 col-s-4 col-lg-4" %) (((
19 + image:recycle.png
20 + == Free updates ==
21 + You benefit from all the application updates during one year. You are always up to date.
22 + )))
23 + (% class="col-xs-12 col-s-4 col-lg-4" %) (((
24 + image:tool.png
25 + == Support included ==
26 + If you are facing an issue, you can reach the XWiki support. Our team is always available to help.
27 + )))
28 + )))
121 121  
122 -#macro (benefits)
123 - <p>What do you get when you purchase an XWiki extension?</p>
124 - <div class="row" id="benefits">
125 - <div class="col-xs-12 col-sm-4">
126 - <div class="icon">$services.icon.renderHTML('key')</div>
127 - <h2>1 year license</h2>
128 - <p>By purchasing an XWiki extension license, you'll benefit from it during one year.</p>
129 - </div>
130 - <div class="col-xs-12 col-sm-4">
131 - <div class="icon">$services.icon.renderHTML('refresh')</div>
132 - <h2>Free updates</h2>
133 - <p>You benefit from all the extension updates during one year. You are always up to date.</p>
134 - </div>
135 - <div class="col-xs-12 col-sm-4">
136 - <div class="icon">$services.icon.renderHTML('wrench')</div>
137 - <h2>Support included</h2>
138 - <p>If you are facing an issue, you can reach the XWiki support. Our team is always available to help.</p>
139 - </div>
140 - </div>
141 -#end
30 +{{comment}}
31 +* __1 year license__: By purchasing an XWiki Application License, you'll benefit from it during one year.
32 +* __Free updates__: You benefit from all the application updates during one year. You are always up to date.
33 +* __Support included__: If you are facing an issue, you can reach the [[XWiki support>>mailto:support@xwiki.com]]. Our team is always available to help.
34 +{{/comment}}
142 142  
143 -#macro (getCurrentLicense $licenseDetails)
144 - ## Get the best license for the specified instance and feature.
145 - #set ($currentLicenseDetails = $NULL)
146 - #getLicenseQuery($licenseDetails.instanceId $licenseDetails.featureId $query)
147 - #set ($results = $query.setLimit(1).execute())
148 - #if ($results && $results.size() > 0)
149 - #set ($currentLicenseDetailsDocument = $xwiki.getDocument($results[0]))
150 - #set ($oldLicenseDetails = $licenseDetails)
151 - #readLicenseDetailsFromDocument($currentLicenseDetailsDocument)
152 - ## Check if the best license is paid and still active.
153 - #if ($licenseDetails.type == 'paid' && $licenseDetails.expirationDate
154 - && $licenseDetails.expirationDate.time > $datetool.date.time)
155 - #set ($currentLicenseDetails = $licenseDetails)
156 - #end
157 - #set ($licenseDetails = $oldLicenseDetails)
158 - #end
159 -#end
36 +== VAT information ==
160 160  
161 -#macro (displayCurrentLicense $currentLicenseDetails)
162 - #if ($currentLicenseDetails)
163 - <dt>
164 - <label>$escapetool.xml($services.localization.render('store.buyLicense.currentLicense'))</label>
165 - </dt>
166 - <dd>
167 - ##
168 - ## Extension name
169 - ##
170 - #if ("$!currentLicenseDetails.extensionName" == '')
171 - #getLicensedExtension($currentLicenseDetails)
172 - #if ($extension)
173 - #set ($currentLicenseDetails.extensionName = $extension.name)
174 - #else
175 - #set ($currentLicenseDetails.extensionName = $currentLicenseDetails.featureId)
176 - #end
177 - #end
178 - ##
179 - ## User limit
180 - ##
181 - #set ($LONG_MAX_VALUE = $mathtool.pow(2,63))
182 - #if (!$currentLicenseDetails.maxUserCount || $currentLicenseDetails.maxUserCount == $LONG_MAX_VALUE)
183 - ## Unlimited user count.
184 - #set ($currentLicenseDetails.maxUserCount = -1)
185 - #end
186 - ##
187 - ## Days left
188 - ##
189 - #set ($remainingTime = $currentLicenseDetails.expirationDate.time - $datetool.date.time)
190 - #set ($daysLeft = $xwiki.jodatime.getDuration($remainingTime).standardDays)
191 - ##
192 - ## Support
193 - ##
194 - #if ("$!currentLicenseDetails.support" != '')
195 - #set ($support = $services.localization.render("store.buyLicense.support.$currentLicenseDetails.support"))
196 - $escapetool.xml($services.localization.render('store.buyLicense.currentLicense.summary',
197 - [$currentLicenseDetails.extensionName, $support, $currentLicenseDetails.maxUserCount, $daysLeft]))
198 - #else
199 - <div class="text-info">
200 - $services.icon.renderHTML('info')
201 - $escapetool.xml($services.localization.render('store.buyLicense.currentLicense.summaryWithoutSupport',
202 - [$currentLicenseDetails.extensionName, $currentLicenseDetails.maxUserCount, $daysLeft]))
203 - </div>
204 - <p class="xHint">$escapetool.xml($services.localization.render('store.buyLicense.currentLicense.hint'))</p>
205 - #end
206 - </dd>
207 - #end
208 -#end
38 +* If you are in the EU and have a VAT number there is no VAT to add to the price
39 +* If you are in the EU and don't have a VAT number there is the VAT of your country to add to the price
40 +* If you are outside the EU there is no VAT to add to the price
209 209  
210 -#macro (buyLicenseForm $licenseDetails $priceMatrix $minUserCount)
211 - <form id="buyLicense" class="xform" action="" method="post">
212 - <p>Fill in the form below to get your license.</p>
213 - <div class="hidden">
214 - <input type="hidden" name="instanceId" value="$!escapetool.xml($licenseDetails.instanceId)"/>
215 - <input type="hidden" name="featureId" value="$!escapetool.xml($licenseDetails.featureId)"/>
216 - <input type="hidden" name="extensionVersion" value="$!escapetool.xml($licenseDetails.extensionVersion)"/>
217 - </div>
218 - <dl>
219 - <dt>
220 - <label>$escapetool.xml($services.localization.render('store.buyLicense.buyer'))</label>
221 - </dt>
222 - <dd>
223 - $!licenseDetails.firstName $!licenseDetails.lastName, $licenseDetails.email
224 - <a href="#editBuyer" class="editBuyer"
225 - title="$escapetool.xml($services.localization.render('store.buyLicense.buyer.edit'))"
226 - >$services.icon.renderHTML('pencil')</a>
227 - </dd>
228 - <dt class="hidden">
229 - <label for="firstName">
230 - $escapetool.xml($services.localization.render('store.buyLicense.firstName'))
231 - </label>
232 - </dt>
233 - <dd class="hidden">
234 - <input type="text" name="firstName" id="firstName" value="$!escapetool.xml($licenseDetails.firstName)"
235 - required="required"/>
236 - </dd>
237 - <dt class="hidden">
238 - <label for="lastName">
239 - $escapetool.xml($services.localization.render('store.buyLicense.lastName'))
240 - </label>
241 - </dt>
242 - <dd class="hidden">
243 - <input type="text" name="lastName" id="lastName" value="$!escapetool.xml($licenseDetails.lastName)"
244 - required="required"/>
245 - </dd>
246 - <dt class="hidden">
247 - <label for="email">
248 - $escapetool.xml($services.localization.render('store.buyLicense.email'))
249 - </label>
250 - <span class="xHint">
251 - $escapetool.xml($services.localization.render('store.buyLicense.email.hint'))
252 - </span>
253 - </dt>
254 - <dd class="hidden">
255 - <input type="email" name="email" id="email" value="$!escapetool.xml($licenseDetails.email)"
256 - class="form-control" required="required"/>
257 - </dd>
258 - #getCurrentLicense($licenseDetails)
259 - #displayCurrentLicense($currentLicenseDetails)
260 - <dt>
261 - <label>$escapetool.xml($services.localization.render('store.buyLicense.options'))</label>
262 - <span class="xHint">$escapetool.xml($services.localization.render('store.buyLicense.options.hint'))</span>
263 - </dt>
264 - <dd>
265 - #displayPriceMatrix($priceMatrix $minUserCount $currentLicenseDetails)
266 - </dd>
267 - </dl>
268 - #benefits
269 - <p>
270 - <input type="submit" class="button btn-success"#if (!$selectedSKU) disabled="disabled" #end
271 - value="$escapetool.xml($services.localization.render('store.buyLicense.submit'))"/>
272 - </p>
273 - </form>
274 -#end
42 +== How to buy ==
275 275  
276 -#macro (accessPurchaseOrderForm $licenseDetails)
277 - <form id="accessPurchaseOrder" class="hidden" action="$services.extension.store.activePurchaseOrderURL" method="post">
278 - <input type="hidden" name="instanceId" value="$!escapetool.xml($licenseDetails.instanceId)"/>
279 - <input type="hidden" name="email" value="$!escapetool.xml($licenseDetails.email)"/>
280 - <input type="submit"/>
281 - </form>
282 -#end
44 +## Note: this is temporary until we implement the buy button
45 +To buy, (% id='install' %)[[install this extension from inside your XWiki instance and follow the instructions>>path:#installation]](%%).
283 283  {{/velocity}}
284 -
285 -{{velocity}}
286 -{{html clean="false"}}
287 -#set ($discard = $xwiki.ssx.use('Store.Content.Pricing'))
288 -#set ($discard = $xwiki.jsx.use('Store.Content.Pricing'))
289 -#getLicenseDetails
290 -#getPriceMatrix($prices.skus)
291 -#set ($minUserCount = $request.session.getAttribute('com.xwiki.store.buyer.userCount'))
292 -#if (!$minUserCount)
293 - #set ($minUserCount = 1)
294 -#end
295 -#if ("$!licenseDetails.instanceId" != '')
296 - #buyLicenseForm($licenseDetails $priceMatrix $minUserCount)
297 - #accessPurchaseOrderForm($licenseDetails)
298 -#else
299 - <h2>Options</h2>
300 - <p>The price varies depending on the support level and the number of users.</p>
301 - #displayPriceMatrix($priceMatrix $minUserCount $NULL true)
302 - <h2>Benefits</h2>
303 - #benefits
304 - <h2>How to Buy</h2>
305 - <p>To buy, install this extension from inside your XWiki instance and <a href="#installation">follow the instructions</a>.</p>
306 -#end
307 -{{/html}}
308 -{{/velocity}}
key.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.Admin
Size
... ... @@ -1,0 +1,1 @@
1 +1.9 KB
Content
recycle.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.Admin
Size
... ... @@ -1,0 +1,1 @@
1 +1.9 KB
Content
tool.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.Admin
Size
... ... @@ -1,0 +1,1 @@
1 +1.9 KB
Content
XWiki.JavaScriptExtension[0]
Caching policy
... ... @@ -1,1 +1,0 @@
1 -long
Code
... ... @@ -1,57 +1,0 @@
1 -require(['jquery', 'bootstrap'], function($) {
2 - // Activate the support information.
3 - $('table.prices [data-toggle="popover"]').popover();
4 -
5 - // Manage the selected SKU from the price matrix.
6 - var updateSelectedSKU = function() {
7 - $(this).closest('table.prices').find('td.price.active').removeClass('active');
8 - $(this).closest('td.price').toggleClass('active');
9 - }
10 - $('form table.prices td.price input:checked').each(updateSelectedSKU);
11 - $('form table.prices').on('change', 'td.price input[type="radio"]', updateSelectedSKU);
12 -
13 - var showBuyerFields = function(editBuyerLink) {
14 - editBuyerLink.closest('dd').hide().prev('dt').hide()
15 - .nextAll('.hidden').removeClass('hidden')
16 - .first().css('margin-top', 0);
17 - };
18 -
19 - // Edit buyer details link.
20 - $('a.editBuyer').click(function (event) {
21 - event.preventDefault();
22 - showBuyerFields($(this));
23 - });
24 -
25 - // We need to register the event directly on the input field because it doesn't bubble up.
26 - $('form#buyLicense input').on('invalid', function() {
27 - if ($(this).is(':hidden')) {
28 - showBuyerFields($(this).closest('form').find('a.editBuyer'));
29 - }
30 - });
31 -
32 - $('form#buyLicense').submit(function(event) {
33 - event.preventDefault();
34 - var buyLicenseForm = $(this);
35 - var submitButton = buyLicenseForm.find('input[type="submit"]').prop('disabled', true);
36 - var progressNotification = new XWiki.widgets.Notification($jsontool.serialize($services.localization.render(
37 - 'store.buyLicense.submit.inProgress')), 'inprogress');
38 - var url = new XWiki.Document('BuyLicense', 'Store').getURL('get', 'outputSyntax=plain');
39 - $.post(url, buyLicenseForm.serialize()).done(function(result) {
40 - if (result && result.order) {
41 - progressNotification.replace(new XWiki.widgets.Notification($jsontool.serialize(
42 - $services.localization.render('store.buyLicense.submit.done')), 'done'));
43 - var accessPurchaseOrderForm = $('form#accessPurchaseOrder');
44 - accessPurchaseOrderForm.find('input[name="email"]').val(buyLicenseForm.find('input[name="email"]').val());
45 - accessPurchaseOrderForm.submit();
46 - } else {
47 - progressNotification.replace(new XWiki.widgets.Notification($jsontool.serialize(
48 - $services.localization.render('store.buyLicense.submit.failed')), 'error'));
49 - }
50 - }).fail(function() {
51 - progressNotification.replace(new XWiki.widgets.Notification($jsontool.serialize(
52 - $services.localization.render('store.buyLicense.submit.failed')), 'error'));
53 - }).always(function() {
54 - submitButton.prop('disabled', false);
55 - });
56 - });
57 -});
Parse content
... ... @@ -1,1 +1,0 @@
1 -1
Use this extension
... ... @@ -1,1 +1,0 @@
1 -onDemand
XWiki.StyleSheetExtension[0]
Caching policy
... ... @@ -1,1 +1,0 @@
1 -long
Code
... ... @@ -1,21 +1,0 @@
1 -table.prices a[data-toggle="popover"] {
2 - color: inherit;
3 - text-decoration: none;
4 -}
5 -
6 -table.prices th span.icon {
7 - margin-left: .3em;
8 -}
9 -
10 -table.prices th.users,
11 -table.prices td.price {
12 - text-align: right;
13 -}
14 -
15 -table.prices td.price-euro label {
16 - display: block;
17 -}
18 -
19 -table.prices td.price-euro label:after {
20 - content: ' \20ac';
21 -}
Content Type
... ... @@ -1,1 +1,0 @@
1 -CSS
Parse content
... ... @@ -1,1 +1,0 @@
1 -0
Use this extension
... ... @@ -1,1 +1,0 @@
1 -onDemand
XWiki SAS Copyright © 2024