Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{include reference="Store.Code.Macros" /}} | ||
2 | |||
3 | {{velocity output="false"}} | ||
4 | #macro (getPriceMatrix $skus) | ||
5 | ## Make sure the rows are sorted by support level. | ||
6 | #set ($priceMatrix = { | ||
7 | 'columns': $collectiontool.sortedSet, | ||
8 | 'rows': { | ||
9 | 'bronze': {}, | ||
10 | 'silver': {}, | ||
11 | 'gold': {}, | ||
12 | 'platinum': {}, | ||
13 | 'diamond': {} | ||
14 | } | ||
15 | }) | ||
16 | #foreach ($sku in $skus) | ||
17 | #set ($support = "$!sku.support") | ||
18 | #set ($users = $numbertool.toNumber($sku.users).intValue()) | ||
19 | #set ($price = "$!sku.price") | ||
20 | #if ($support && $users && $price) | ||
21 | #set ($pricePerUsers = $priceMatrix.rows.get($support)) | ||
22 | #if (!$pricePerUsers) | ||
23 | #set ($pricePerUsers = {}) | ||
24 | #set ($discard = $priceMatrix.rows.put($support, $pricePerUsers)) | ||
25 | #end | ||
26 | #set ($discard = $pricePerUsers.put($users, $price)) | ||
27 | #set ($discard = $priceMatrix.columns.add($users)) | ||
28 | #end | ||
29 | #end | ||
30 | #set ($emptyRows = []) | ||
31 | #foreach ($entry in $priceMatrix.rows.entrySet()) | ||
32 | #if ($entry.value.isEmpty()) | ||
33 | #set ($discard = $emptyRows.add($entry.key)) | ||
34 | #end | ||
35 | #end | ||
36 | #set ($discard = $priceMatrix.rows.keySet().removeAll($emptyRows)) | ||
37 | #end | ||
38 | |||
39 | #macro (findSKUMatchingCurrentLicense $priceMatrix $minUserCount $currentLicenseDetails) | ||
40 | #set ($skuMatchingCurrentLicense = $NULL) | ||
41 | #if ($priceMatrix.rows.containsKey($currentLicenseDetails.support)) | ||
42 | ## Select the best match for the specified support level. | ||
43 | #foreach ($column in $priceMatrix.columns) | ||
44 | #set ($price = $priceMatrix.rows.get($currentLicenseDetails.support).get($column)) | ||
45 | #if ($price && $column >= $mathtool.max($minUserCount, $currentLicenseDetails.maxUserCount)) | ||
46 | #set ($skuMatchingCurrentLicense = "$currentLicenseDetails.support,$column") | ||
47 | #break | ||
48 | #end | ||
49 | #end | ||
50 | #end | ||
51 | #if (!$skuMatchingCurrentLicense) | ||
52 | ## Select the best match for the specified user limit. | ||
53 | #foreach ($entry in $priceMatrix.rows.entrySet()) | ||
54 | #foreach ($column in $priceMatrix.columns) | ||
55 | #set ($price = $entry.value.get($column)) | ||
56 | #if ($price && $column >= $mathtool.max($minUserCount, $currentLicenseDetails.maxUserCount)) | ||
57 | #set ($skuMatchingCurrentLicense = "$entry.key,$column") | ||
58 | #break | ||
59 | #end | ||
60 | #end | ||
61 | #if ($skuMatchingCurrentLicense) | ||
62 | #break | ||
63 | #end | ||
64 | #end | ||
65 | #end | ||
66 | #end | ||
67 | |||
68 | #macro (displayPriceMatrix $priceMatrix $minUserCount $currentLicenseDetails $readOnly) | ||
69 | <table class="prices"> | ||
70 | <tr> | ||
71 | <th class="legend">$escapetool.xml($services.localization.render('store.buyLicense.support')) | ||
72 | / $escapetool.xml($services.localization.render('store.buyLicense.users'))</th> | ||
73 | #foreach ($column in $priceMatrix.columns) | ||
74 | #if ($column < 0) | ||
75 | #set ($columnLabel = $services.localization.render('store.buyLicense.unlimitedUsers')) | ||
76 | #set ($columnHint = $services.localization.render('store.buyLicense.unlimitedUsers.hint')) | ||
77 | #else | ||
78 | #set ($columnLabel = $column) | ||
79 | #set ($columnHint = $services.localization.render('store.buyLicense.users.hint', [$column])) | ||
80 | #end | ||
81 | #set ($disabled = $column >= 0 && $column < $minUserCount) | ||
82 | <th class="users#if ($disabled) disabled#end" title="$escapetool.xml($columnHint)" | ||
83 | >$escapetool.xml($columnLabel)<span class="icon">$services.icon.renderHTML('user')</span></th> | ||
84 | #end | ||
85 | </tr> | ||
86 | #set ($selectedSKU = $NULL) | ||
87 | #if (!$readOnly && $currentLicenseDetails) | ||
88 | #findSKUMatchingCurrentLicense($priceMatrix $minUserCount $currentLicenseDetails) | ||
89 | #set ($selectedSKU = $skuMatchingCurrentLicense) | ||
90 | #end | ||
91 | #foreach ($entry in $priceMatrix.rows.entrySet()) | ||
92 | <tr class="support-$escapetool.xml($entry.key)"> | ||
93 | <th><a tabindex="0" role="button" data-toggle="popover" data-trigger="focus" data-html="true" | ||
94 | title="$escapetool.xml($services.localization.render("store.buyLicense.support.${entry.key}.title"))" | ||
95 | data-content="$escapetool.xml($services.localization.render( | ||
96 | "store.buyLicense.support.${entry.key}.description", ['<a href="https://xwiki.com/en/pricing/">', '</a>']))" | ||
97 | >$escapetool.xml($services.localization.render("store.buyLicense.support.$entry.key"))<span | ||
98 | class="icon">$services.icon.renderHTML('info')</span></a></th> | ||
99 | #foreach ($column in $priceMatrix.columns) | ||
100 | #set ($price = $entry.value.get($column)) | ||
101 | #if ($price) | ||
102 | #set ($sku = "$entry.key,$column") | ||
103 | #set ($disabled = $column >= 0 && $column < $minUserCount) | ||
104 | #if (!$disabled && !$selectedSKU && !$readOnly) | ||
105 | #set ($selectedSKU = $sku) | ||
106 | #end | ||
107 | <td class="price price-euro#if ($disabled) disabled#elseif ($selectedSKU == $sku) active#end" | ||
108 | data-support="$escapetool.xml($entry.key)" data-users="$escapetool.xml($column)"> | ||
109 | <label>#if (!$readOnly)<input type="radio" name="sku" value="$escapetool.xml($sku)" required="required" | ||
110 | #if ($disabled)disabled="disabled"#elseif ($selectedSKU == $sku)checked="checked"#end | ||
111 | />#end$escapetool.xml($price)</label> | ||
112 | </td> | ||
113 | #else | ||
114 | <td/> | ||
115 | #end | ||
116 | #end | ||
117 | </tr> | ||
118 | #end | ||
119 | </table> | ||
120 | #end | ||
121 | |||
122 | #macro (getLicenseDetails) | ||
123 | #set ($licenseDetails = {}) | ||
124 | #foreach ($name in ['firstName', 'lastName', 'email', 'instanceId']) | ||
125 | #set ($discard = $licenseDetails.put($name, $request.session.getAttribute("com.xwiki.store.buyer.$name"))) | ||
126 | #end | ||
127 | #set ($licenseDetails.featureId = $doc.getValue('id')) | ||
128 | #set ($licenseDetails.extensionVersion = $request.version) | ||
129 | #if ("$!licenseDetails.extensionVersion" == '') | ||
130 | ## Use the latest stable version. | ||
131 | #set ($versions = $services.extension.resolveVersions($licenseDetails.featureId, 0, -1)) | ||
132 | ## The versions are returned in ascending order and we want the latest. | ||
133 | ## Note that we can't access the last item directly. We're forced to iterate. | ||
134 | #foreach ($version in $versions) | ||
135 | #if ($version.type == 'STABLE') | ||
136 | #set ($licenseDetails.extensionVersion = $version.value) | ||
137 | #end | ||
138 | #end | ||
139 | #end | ||
140 | #set ($licenseDetails.licenseType = 'paid') | ||
141 | #end | ||
142 | |||
143 | #macro (getPackageExtension $packageDoc) | ||
144 | #set ($extension = $services.extension.resolve($packageDoc.getValue('id'), $packageDoc.getValue('lastVersion'))) | ||
145 | #set ($packageId = $extension.getProperty('xwiki.extension.licensing.packageId')) | ||
146 | #if ("$!packageId" != '') | ||
147 | ## See XWIKI-15051: SafeExtension#getProperty(key, defaultValue) ignores the default value | ||
148 | #set ($packageVersion = $extension.getProperty('xwiki.extension.licensing.packageVersion')) | ||
149 | #if ("$!packageVersion" == '') | ||
150 | #set ($packageVersion = $extension.id.version.toString()) | ||
151 | #end | ||
152 | #set ($packageExtension = $services.extension.resolve($packageId, $packageVersion)) | ||
153 | #end | ||
154 | #end | ||
155 | |||
156 | #macro (displayPackageExtensions) | ||
157 | #getPackageExtension($doc) | ||
158 | #if ($packageExtension) | ||
159 | <div class="packageDependencies"> | ||
160 | $services.localization.render('store.extension.packageDependencies.info', [$doc.getValue('name')]) | ||
161 | <ul> | ||
162 | #foreach ($dependency in $packageExtension.dependencies) | ||
163 | #set ($extension = $services.extension.resolve($dependency)) | ||
164 | #getExtensionPageName($extension.id.id) | ||
165 | #if ($extensionPageName.size() > 0) | ||
166 | #set ($extensionPageName = $extensionPageName[0]) | ||
167 | #else | ||
168 | #set ($extensionPageName = $extension.name) | ||
169 | #end | ||
170 | <li> | ||
171 | ## Add a nice separator between extension names. | ||
172 | $services.icon.renderHTML('certificate') | ||
173 | #if ($xwiki.exists($extensionPageName)) | ||
174 | #set ($extensionDoc = $xwiki.getDocument($extensionPageName)) | ||
175 | <a href="$extensionDoc.URL#pricing" target="_blank">$extensionDoc.getValue('name')</a> | ||
176 | #else | ||
177 | <a href="http://extensions.xwiki.org?id=$extension.id.id" class="wikiexternallink" target="_blank"> | ||
178 | $extensionPageName (Free) | ||
179 | </a> | ||
180 | #end | ||
181 | </li> | ||
182 | #end | ||
183 | </ul> | ||
184 | </div> | ||
185 | #end | ||
186 | #end | ||
187 | |||
188 | #macro (displayParentPackageInfo $licenseDetails) | ||
189 | ## Get all packages of extensions from store. | ||
190 | #set ($statement = "from doc.object(Store.Code.PayingAppsClass) as app where app.isPackage = '1'") | ||
191 | #set ($results = $services.query.xwql($statement).execute()) | ||
192 | ## Get all licenses of the user. | ||
193 | #if ("$!licenseDetails.instanceId" != '') | ||
194 | #getLicenses($licenseDetails.instanceId) | ||
195 | #else | ||
196 | #set ($licenses = []) | ||
197 | #end | ||
198 | #foreach ($packageName in $results) | ||
199 | #set ($packageDoc = $xwiki.getDocument($packageName)) | ||
200 | #getPackageExtension($packageDoc) | ||
201 | #set ($packageLink = "<a href='$packageDoc.URL#pricing' target='_blank'>$packageDoc.getValue('name')</a>") | ||
202 | ## Check if the current extension belongs to the currently analyzed package. | ||
203 | #isInPackage($doc.getValue('id') $packageExtension) | ||
204 | #if ($isInPackage) | ||
205 | #getPackageAppsSuggestions($packageExtension $licenses) | ||
206 | <div class="parentPackageInfo"> | ||
207 | #if ($packageApps.size() > 0) | ||
208 | #set ($extraInfo = " $services.localization.render('store.extension.parentPackage.extraInfo', [$stringtool.join($packageApps, ', ')])") | ||
209 | #end | ||
210 | $services.localization.render('store.extension.parentPackage.info', [$doc.getValue('name'), $packageLink, "$!extraInfo"]) | ||
211 | </div> | ||
212 | #end | ||
213 | #end | ||
214 | #end | ||
215 | |||
216 | #macro (isInPackage $extensionId $package) | ||
217 | #set ($isInPackage = false) | ||
218 | #foreach ($dependency in $package.dependencies) | ||
219 | #if ($dependency.id.equals($extensionId)) | ||
220 | #set ($isInPackage = true) | ||
221 | #break | ||
222 | #end | ||
223 | #end | ||
224 | #end | ||
225 | |||
226 | #macro (getPackageAppsSuggestions $packageExtension $licenses) | ||
227 | ## Collect all the apps that are covered by a license, for the current user/instance id. | ||
228 | #set ($packageApps = []) | ||
229 | #foreach ($license in $licenses) | ||
230 | #set ($licenseDoc = $xwiki.getDocument($license)) | ||
231 | ## Check if the user's licensed extensions belong to the currently analyzed package. | ||
232 | #isInPackage($licenseDoc.getValue('featureId') $packageExtension) | ||
233 | #if ($isInPackage) | ||
234 | #getExtensionPageName($licenseDoc.getValue('featureId')) | ||
235 | #if ($extensionPageName.size() > 0) | ||
236 | #set ($extensionDoc = $xwiki.getDocument($extensionPageName[0])) | ||
237 | ## Exclude the current extension from the list of suggested extensions. | ||
238 | #if (!$doc.documentReference.equals($extensionDoc.documentReference)) | ||
239 | #set ($discard = $packageApps.add("<a href='$extensionDoc.URL' target='_blank'>$extensionDoc.getValue('name')</a>")) | ||
240 | #end | ||
241 | #end | ||
242 | #end | ||
243 | #end | ||
244 | #end | ||
245 | |||
246 | #macro (benefits) | ||
247 | <p>What do you get when you purchase an XWiki extension?</p> | ||
248 | <div class="row" id="benefits"> | ||
249 | <div class="col-xs-12 col-sm-4"> | ||
250 | <div class="icon">$services.icon.renderHTML('key')</div> | ||
251 | <h2>1 year license</h2> | ||
252 | <p>By purchasing an XWiki extension license, you'll benefit from it during one year.</p> | ||
253 | </div> | ||
254 | <div class="col-xs-12 col-sm-4"> | ||
255 | <div class="icon">$services.icon.renderHTML('refresh')</div> | ||
256 | <h2>Free updates</h2> | ||
257 | <p>You benefit from all the extension updates during one year. You are always up to date.</p> | ||
258 | </div> | ||
259 | <div class="col-xs-12 col-sm-4"> | ||
260 | <div class="icon">$services.icon.renderHTML('wrench')</div> | ||
261 | <h2>Support included</h2> | ||
262 | <p>If you are facing an issue, you can reach the XWiki support. Our team is always available to help.</p> | ||
263 | </div> | ||
264 | </div> | ||
265 | #end | ||
266 | |||
267 | #macro (getCurrentLicense $licenseDetails) | ||
268 | ## Get the best license for the specified instance and feature. | ||
269 | #set ($currentLicenseDetails = $NULL) | ||
270 | #getLicenseQuery($licenseDetails.instanceId $licenseDetails.featureId $query) | ||
271 | #set ($results = $query.setLimit(1).execute()) | ||
272 | #if ($results && $results.size() > 0) | ||
273 | #set ($currentLicenseDetailsDocument = $xwiki.getDocument($results[0])) | ||
274 | #set ($oldLicenseDetails = $licenseDetails) | ||
275 | #readLicenseDetailsFromDocument($currentLicenseDetailsDocument) | ||
276 | ## Check if the best license is paid and still active. | ||
277 | #if ($licenseDetails.type == 'paid' && $licenseDetails.expirationDate | ||
278 | && $licenseDetails.expirationDate.time > $datetool.date.time) | ||
279 | #set ($currentLicenseDetails = $licenseDetails) | ||
280 | #end | ||
281 | #set ($licenseDetails = $oldLicenseDetails) | ||
282 | #end | ||
283 | #end | ||
284 | |||
285 | #macro (displayCurrentLicense $currentLicenseDetails) | ||
286 | #if ($currentLicenseDetails) | ||
287 | <dt> | ||
288 | <label>$escapetool.xml($services.localization.render('store.buyLicense.currentLicense'))</label> | ||
289 | </dt> | ||
290 | <dd> | ||
291 | ## | ||
292 | ## Extension name | ||
293 | ## | ||
294 | #if ("$!currentLicenseDetails.extensionName" == '') | ||
295 | #getLicensedExtension($currentLicenseDetails) | ||
296 | #if ($extension) | ||
297 | #set ($currentLicenseDetails.extensionName = $extension.name) | ||
298 | #else | ||
299 | #set ($currentLicenseDetails.extensionName = $currentLicenseDetails.featureId) | ||
300 | #end | ||
301 | #end | ||
302 | ## | ||
303 | ## User limit | ||
304 | ## | ||
305 | #set ($LONG_MAX_VALUE = $mathtool.pow(2,63)) | ||
306 | #if (!$currentLicenseDetails.maxUserCount || $currentLicenseDetails.maxUserCount == $LONG_MAX_VALUE) | ||
307 | ## Unlimited user count. | ||
308 | #set ($currentLicenseDetails.maxUserCount = -1) | ||
309 | #end | ||
310 | ## | ||
311 | ## Days left | ||
312 | ## | ||
313 | #set ($remainingTime = $currentLicenseDetails.expirationDate.time - $datetool.date.time) | ||
314 | #set ($daysLeft = $xwiki.jodatime.getDuration($remainingTime).standardDays) | ||
315 | ## | ||
316 | ## Support | ||
317 | ## | ||
318 | #if ("$!currentLicenseDetails.support" != '') | ||
319 | #set ($support = $services.localization.render("store.buyLicense.support.$currentLicenseDetails.support")) | ||
320 | $escapetool.xml($services.localization.render('store.buyLicense.currentLicense.summary', | ||
321 | [$currentLicenseDetails.extensionName, $support, $currentLicenseDetails.maxUserCount, $daysLeft])) | ||
322 | #else | ||
323 | <div class="text-info"> | ||
324 | $services.icon.renderHTML('info') | ||
325 | $escapetool.xml($services.localization.render('store.buyLicense.currentLicense.summaryWithoutSupport', | ||
326 | [$currentLicenseDetails.extensionName, $currentLicenseDetails.maxUserCount, $daysLeft])) | ||
327 | </div> | ||
328 | <p class="xHint">$escapetool.xml($services.localization.render('store.buyLicense.currentLicense.hint'))</p> | ||
329 | #end | ||
330 | </dd> | ||
331 | #end | ||
332 | #end | ||
333 | |||
334 | #macro (buyLicenseForm $licenseDetails $priceMatrix $minUserCount) | ||
335 | <form id="buyLicense" class="xform" action="" method="post"> | ||
336 | <p>Fill in the form below to get your license.</p> | ||
337 | <div class="hidden"> | ||
338 | <input type="hidden" name="instanceId" value="$!escapetool.xml($licenseDetails.instanceId)"/> | ||
339 | <input type="hidden" name="featureId" value="$!escapetool.xml($licenseDetails.featureId)"/> | ||
340 | <input type="hidden" name="extensionVersion" value="$!escapetool.xml($licenseDetails.extensionVersion)"/> | ||
341 | </div> | ||
342 | <dl> | ||
343 | <dt> | ||
344 | <label>$escapetool.xml($services.localization.render('store.buyLicense.buyer'))</label> | ||
345 | </dt> | ||
346 | <dd> | ||
347 | $!licenseDetails.firstName $!licenseDetails.lastName, $licenseDetails.email | ||
348 | <a href="#editBuyer" class="editBuyer" | ||
349 | title="$escapetool.xml($services.localization.render('store.buyLicense.buyer.edit'))" | ||
350 | >$services.icon.renderHTML('pencil')</a> | ||
351 | </dd> | ||
352 | <dt class="hidden"> | ||
353 | <label for="firstName"> | ||
354 | $escapetool.xml($services.localization.render('store.buyLicense.firstName')) | ||
355 | </label> | ||
356 | </dt> | ||
357 | <dd class="hidden"> | ||
358 | <input type="text" name="firstName" id="firstName" value="$!escapetool.xml($licenseDetails.firstName)" | ||
359 | required="required"/> | ||
360 | </dd> | ||
361 | <dt class="hidden"> | ||
362 | <label for="lastName"> | ||
363 | $escapetool.xml($services.localization.render('store.buyLicense.lastName')) | ||
364 | </label> | ||
365 | </dt> | ||
366 | <dd class="hidden"> | ||
367 | <input type="text" name="lastName" id="lastName" value="$!escapetool.xml($licenseDetails.lastName)" | ||
368 | required="required"/> | ||
369 | </dd> | ||
370 | <dt class="hidden"> | ||
371 | <label for="email"> | ||
372 | $escapetool.xml($services.localization.render('store.buyLicense.email')) | ||
373 | </label> | ||
374 | <span class="xHint"> | ||
375 | $escapetool.xml($services.localization.render('store.buyLicense.email.hint')) | ||
376 | </span> | ||
377 | </dt> | ||
378 | <dd class="hidden"> | ||
379 | <input type="email" name="email" id="email" value="$!escapetool.xml($licenseDetails.email)" | ||
380 | class="form-control" required="required"/> | ||
381 | </dd> | ||
382 | #getCurrentLicense($licenseDetails) | ||
383 | #displayCurrentLicense($currentLicenseDetails) | ||
384 | <dt> | ||
385 | <label>$escapetool.xml($services.localization.render('store.buyLicense.options'))</label> | ||
386 | <span class="xHint">$escapetool.xml($services.localization.render('store.buyLicense.options.hint'))</span> | ||
387 | </dt> | ||
388 | <dd> | ||
389 | #displayPriceMatrix($priceMatrix $minUserCount $currentLicenseDetails) | ||
390 | </dd> | ||
391 | </dl> | ||
392 | #displayPackageExtensions | ||
393 | #displayParentPackageInfo($licenseDetails) | ||
394 | #benefits | ||
395 | <p> | ||
396 | #if ($selectedSKU) | ||
397 | <input type="submit" class="button btn-success" | ||
398 | value="$escapetool.xml($services.localization.render('store.buyLicense.submit'))"/> | ||
399 | #else | ||
400 | <input type="button" id="requestLicense" class="button btn-success" | ||
401 | value="$escapetool.xml($services.localization.render('store.requestLicense.button'))"/> | ||
402 | #end | ||
403 | </p> | ||
404 | </form> | ||
405 | #end | ||
406 | |||
407 | #macro (accessPurchaseOrderForm $licenseDetails) | ||
408 | <form id="accessPurchaseOrder" class="hidden" action="$services.extension.store.activePurchaseOrderURL" method="post"> | ||
409 | <input type="hidden" name="instanceId" value="$!escapetool.xml($licenseDetails.instanceId)"/> | ||
410 | <input type="hidden" name="email" value="$!escapetool.xml($licenseDetails.email)"/> | ||
411 | <input type="submit"/> | ||
412 | </form> | ||
413 | #end | ||
414 | {{/velocity}} | ||
415 | |||
416 | {{velocity}} | ||
417 | {{html clean="false"}} | ||
418 | #set ($discard = $xwiki.ssx.use('Store.Content.Pricing')) | ||
419 | #set ($discard = $xwiki.jsx.use('Store.Content.Pricing')) | ||
420 | #getLicenseDetails | ||
421 | #getPriceMatrix($prices.skus) | ||
422 | #set ($minUserCount = $request.session.getAttribute('com.xwiki.store.buyer.userCount')) | ||
423 | #if (!$minUserCount) | ||
424 | #set ($minUserCount = 1) | ||
425 | #end | ||
426 | #if ("$!licenseDetails.instanceId" != '' && "$!licenseDetails.featureId" != '') | ||
427 | #buyLicenseForm($licenseDetails $priceMatrix $minUserCount) | ||
428 | #accessPurchaseOrderForm($licenseDetails) | ||
429 | #else | ||
430 | <h2>Options</h2> | ||
431 | <p>The price is per year and varies depending on the support level and the number of users.</p> | ||
432 | #displayPriceMatrix($priceMatrix $minUserCount $NULL true) | ||
433 | #displayPackageExtensions | ||
434 | #displayParentPackageInfo($licenseDetails) | ||
435 | <h2>Benefits</h2> | ||
436 | #benefits | ||
437 | <h2>How to Buy</h2> | ||
438 | <p>To buy, install this extension from inside your XWiki instance and <a href="#installation">follow the instructions</a>.</p> | ||
439 | #end | ||
440 | {{/html}} | ||
441 | {{/velocity}} |