Wiki source code of Nested Pages Migration
Last modified by Admin on 2018/02/14 08:28
Show last authors
1 | {{velocity}} |
2 | #if (!$services.security.authorization.hasAccess('admin', $xcontext.userReference, $doc.documentReference.wikiReference)) |
3 | {{error}} |
4 | You don't have the right to use this tool on this wiki. You need to be administrator. |
5 | {{/error}} |
6 | #else |
7 | ## Both job.css and extension.css are needed because the ui-progress classes that we need to display |
8 | ## a progress bar are in one of these 2 files depending on the XWiki version |
9 | #set ($discard = $xwiki.ssfx.use('uicomponents/job/job.css', true)) |
10 | #set ($discard = $xwiki.ssfx.use('uicomponents/extension/extension.css', true)) |
11 | #set ($discard = $xwiki.ssfx.use('uicomponents/logging/logging.css', true)) |
12 | #set ($discard = $xwiki.linkx.use($services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'tree.min.css', |
13 | {'evaluate': true}), {'type': 'text/css', 'rel': 'stylesheet'})) |
14 | {{html clean="false"}} |
15 | <!------------------------------------------ |
16 | Migration Action Template |
17 | -------------------------------------------> |
18 | <script id="MigrationActionTemplate" type="text/html"> |
19 | <!-- ko foreach: ${escapetool.d}data.actions --> |
20 | <li class="jstree-node" data-bind=" |
21 | visible: (!targetDocument.equals(sourceDocument) || getNumberOfChildren() > 0 || getNumberOfPreferences() > 0 || getNumberOfRights()> 0), |
22 | css: { |
23 | 'jstree-closed': !displayChildren(), |
24 | 'jstree-open' : displayChildren(), |
25 | 'jstree-leaf' : getNumberOfChildren() == 0 && getNumberOfPreferences() == 0, |
26 | 'jstree-last' : ${escapetool.d}index() == ${escapetool.d}parent.actions.length - 1 |
27 | }"> |
28 | ## Display the tree branch |
29 | <i class="jstree-icon jstree-ocl" role="presentation" data-bind="click: toggleDisplayChildren"></i> |
30 | ## Display the checbox |
31 | <input type="checkbox" data-bind="checked: enabled" /> |
32 | ## Display the 'all' link |
33 | <a href="#" data-bind="visible: !enabled() && (getNumberOfChildren() > 0 || getNumberOfPreferences() > 0 || getNumberOfRights()> 0), click: enableWithChildren" >(all)</a> |
34 | ## Display the document name |
35 | <strong class="documentName" data-bind="text: getTargetName(), click: toggleDisplayChildren, css: { 'bg-danger': isTooLong() }"></strong> |
36 | ## Display the target location |
37 | [<span data-bind="text: serializedTargetDocument()" class="monospace"></span>] |
38 | ## Display if the action is a change or not |
39 | <em data-bind="visible: targetDocument.equals(sourceDocument)">(unchanged)</em> |
40 | ## Display if a previous document will be deleted |
41 | <strong data-bind="visible: deletePrevious">(duplicated document will be deleted)</strong> |
42 | ## Display the exclude page button |
43 | <button class="btn btn-default btn-xs" data-bind="click: ${escapetool.d}root.excludePage, disable: targetDocument.equals(sourceDocument)">exclude page</button> |
44 | ## Display the exclude space button |
45 | <button class="btn btn-default btn-xs" data-bind="click: ${escapetool.d}root.excludeSpace">exclude space</button> |
46 | ## Display th button to change the parent of ht document |
47 | <button class="btn btn-default btn-xs" data-bind="click: ${escapetool.d}root.setParent">set parent</button> |
48 | ## Display the number of children |
49 | (<span data-bind="text: getNumberOfChildren()"></span> children, |
50 | ## Display the number of preferences |
51 | <span data-bind="text: getNumberOfPreferences()"></span> preferences, |
52 | ## Display the number of rights |
53 | <span data-bind="text: getNumberOfRights()"></span> rights) |
54 | ## Display the original location |
55 | from <a target="_blank" class="monospace" data-bind="text: serializedSourceDocument(), attr: {href: getSourceLink()}"></a> |
56 | ## Display all children |
57 | <!-- ko if: displayChildren() --> |
58 | ## Display preferences |
59 | <!-- ko if: preferences.length > 0 --> |
60 | <ul data-bind="foreach: preferences" class="jstree-children"> |
61 | <li class="text-warning jstree-node jstree-leaf"> |
62 | <i class="jstree-icon jstree-ocl" role="presentation"></i> |
63 | <input type="checkbox" data-bind="checked: enabled"/> <strong>[Preferences] <span data-bind="text: property"></span> : <span data-bind="text: value"></span></strong> (coming from <a target="_blank" class="monospace" data-bind="text: getSerializedOrigin(), attr: {href: getOriginLink()}"></a>) |
64 | </li> |
65 | </ul> |
66 | <!-- /ko --> |
67 | ## Display rights |
68 | <!-- ko if: rights.length > 0 --> |
69 | <ul data-bind="foreach: rights" class="jstree-children"> |
70 | <li class="text-danger jstree-node jstree-leaf"> |
71 | <i class="jstree-icon jstree-ocl" role="presentation"></i> |
72 | <input type="checkbox" data-bind="checked: enabled"/> <strong>[Right] <span data-bind="text: toString()"></span></strong> (coming from <a target="_blank" class="monospace" data-bind="text: getSerializedOrigin(), attr: {href: getOriginLink()}"></a>) |
73 | </li> |
74 | </ul> |
75 | <!-- /ko --> |
76 | ## Display children documents |
77 | <ul data-bind="template: { name: 'MigrationActionTemplate', data: {'actions': children()} }" class="jstree-children"/> |
78 | <!-- /ko --> |
79 | </li> |
80 | <!-- /ko --> |
81 | </script> |
82 | <!------------------------------------------ |
83 | Display Logs |
84 | -------------------------------------------> |
85 | <script id="DisplayLogs" type="text/html"> |
86 | <h2 class="log-title">Logs: </h2> |
87 | <ul class="log" data-bind="if: logs().length > 0"> |
88 | <!-- ko foreach: logs --> |
89 | <li class="log-item" data-bind="css: getClass()"> |
90 | <div data-bind="text: message"></div> |
91 | <!-- ko if: stackTrace --> |
92 | <pre data-bind="text: stackTrace"></pre> |
93 | <!-- /ko --> |
94 | </li> |
95 | <!-- /ko --> |
96 | </ul> |
97 | </script> |
98 | <!------------------------------------------ |
99 | Display plan |
100 | -------------------------------------------> |
101 | <script id="DisplayPlan" type="text/html"> |
102 | <h2>Plan</h2> |
103 | <div class="migration-plan box"> |
104 | <div data-bind="if: isComputing()" id="planComputing"> |
105 | <p>The plan is being computed and it could take some time. Please wait...</p> |
106 | <div class="ui-progress-background"> |
107 | <div class="ui-progress-bar green" data-bind="style: {width: progress() + '%'}"></div> |
108 | </div> |
109 | </div> |
110 | <div class="box warningmessage" data-bind="visible: duplicates().length > 0"> |
111 | <p>The migration have detected some duplicated documents, that are probably the consequences of a failed attempt to run the migrator.<br /> |
112 | <p>If it's the first time you run the migrator, you might have a problem.</p> |
113 | <p>Theses documents are:</p> |
114 | <ul data-bind="foreach: {data: duplicates(), as: 'doc'}"> |
115 | <li data-bind="text: doc"></li> |
116 | </ul> |
117 | <p>If you are ok with it, just run the migrator and these documents will be overwritten.</p> |
118 | </div> |
119 | <div class="box errormessage" data-bind="visible: tooLongs().length > 0"> |
120 | <p>We have detected some pages that will have too long path after the migration (limit is 255). You should rename them (or rename one of their parents) before computing a new plan.</p> |
121 | <p>Theses pages are:</p> |
122 | <ul data-bind="foreach: {data: tooLongs(), as: 'action'}"> |
123 | <li class="monospace"><a data-bind="attr: {href: action.getSourceLink()}" target="_blank"><span data-bind="text: action.serializedSourceDocument()"></span></a> -> <span data-bind="text: action.serializedTargetDocument()"></span></li> |
124 | </ul> |
125 | </div> |
126 | <ul data-bind="if: actions() && !isComputing() && !isPlanEmpty()" id="planTree" class="jstree jstree-xwiki jstree-xwiki-responsive jstree-container-ul"> |
127 | <!-- ko template: {name: 'MigrationActionTemplate', data: {'actions': actions() }} --> |
128 | <!-- /ko --> |
129 | </ul> |
130 | <!-- ko if: !isComputing() && isPlanEmpty() --> |
131 | <div class="box infomessage"> |
132 | <p>There is nothing to do!</p> |
133 | </div> |
134 | <!-- /ko --> |
135 | <!-- ko template: {name: 'DisplayLogs', data: ${escapetool.d}root} --> |
136 | <!-- /ko --> |
137 | </div> |
138 | </Script> |
139 | <!------------------------------------------ |
140 | Display configuration |
141 | -------------------------------------------> |
142 | <h2>Configuration</h2> |
143 | <form class="xform"> |
144 | <div class="row"> |
145 | <div class="col-xs-12 col-md-6"> |
146 | <dl> |
147 | <!-- Excluded pages --> |
148 | <dt><label for="excludedPages">Excluded pages</label></dt> |
149 | <dd> |
150 | <p class="xHint">Page references separated by commas (',')</p> |
151 | <p><input type="text" id="excludedPages" data-bind="value: configuration.excludedPages"></p> |
152 | </dd> |
153 | <!-- Excluded spaces --> |
154 | <dt><label for="excludedSpaces">Excluded spaces</label></dt> |
155 | <dd> |
156 | <p class="xHint">Space references separated by commas (',')</p> |
157 | <p><input type="text" id="excludedSpaces" data-bind="value: configuration.excludedSpaces"> </p> |
158 | </dd> |
159 | <!-- Included spaces --> |
160 | <dt><label for="includedSpaces">Included spaces</label></dt> |
161 | <dd> |
162 | <p class="xHint">Space references separated by commas (',')</p> |
163 | <p><input type="text" id="includedSpaces" data-bind="value: configuration.includedSpaces"> </p> |
164 | </dd> |
165 | </dl> |
166 | </div> |
167 | <div class="col-xs-12 col-md-6"> |
168 | <p><button class="btn btn-default" type="button" data-toggle="collapse" data-target="#advancedSettings" aria-expanded="false" aria-controls="advancedSettings">Advanced Settings</button></p> |
169 | <dl id="advancedSettings" class="collapse well"> |
170 | <!-- Exclude hidden pages --> |
171 | <dt><input type="checkbox" id="excludeHiddenPages" data-bind="checked: configuration.excludeHiddenPages"> <label for="excludeHiddenPages">Exclude hidden pages</label></dt> |
172 | <dd><span class="xHint">Most of the hidden pages are techinal content. Moving them can break applications.</span></dd> |
173 | <!-- Exclude class pages --> |
174 | <dt><input type="checkbox" id="excludeClassPages" data-bind="checked: configuration.excludeClassPages"> <label for="excludeClassPages">Exclude pages having a class</label></dt> |
175 | <dd><span class="xHint">The pages are technical and moving them can break applications.</span></dd> |
176 | <!-- Don't move children --> |
177 | <dt><input type="checkbox" id="dontMoveChildren" data-bind="checked: configuration.dontMoveChildren"> <label for="dontMoveChildren">Do not move children</label></dt> |
178 | <dd><span class="xHint">Only convert terminal pages to nested pages, without moving them under their parent.</span></dd> |
179 | <!-- Add redirection --> |
180 | <dt><input type="checkbox" id="addRedirection" data-bind="checked: configuration.addRedirection"> <label for="addRedirection">Add redirection</label></dt> |
181 | <dd><span class="xHint">Add a redirection in the old location.</span></dd> |
182 | <!-- Convert preferences --> |
183 | <dt><input type="checkbox" id="convertPreferences" data-bind="checked: configuration.convertPreferences"> <label for="convertPreferences">Convert preferences</label></dt> |
184 | <dd><span class="xHint">Make sure that the preferences applied on the page remain the same after the move, by dupplicating the preferences on the target document.</span></dd> |
185 | <!-- Convert rights --> |
186 | <dt><input type="checkbox" id="convertRights" data-bind="checked: configuration.convertRights"> <label for="convertRights">Convert rights (experimental)</label></dt> |
187 | <dd><span class="xHint">Make sure that the rights applied on the page remain the same after the move <span class="text-danger">(Currently bugged)</span>.</span></dd> |
188 | <!-- Excluded Object Classes --> |
189 | <dt><label for="excludedObjectClasses" data-bind="click: toggleXClassList">Exclude classes</label></dt> |
190 | <dd> |
191 | <p class="xHint" data-bind="click: toggleXClassList">Exclude pages holding an object of one of the specified classes (separated by a coma ',').</p> |
192 | <p><textarea id="excludedObjectClasses" data-bind="textInput: configuration.excludedObjectClasses, click: showXClassList" data-xclasses="#foreach($class in $xwiki.classList)#if($velocityCount>1),#end${class}#end"></textarea></p> |
193 | <div data-bind="visible: xclassListVisible"> |
194 | <a data-bind="click: hideXClassList" href="#">$services.icon.renderHTML('remove') Hide</a> |
195 | <ul data-bind="foreach: {data: xclasses, as: 'xclass'}" style="list-style-type: none; padding: 0;"> |
196 | <li><label><input type="checkbox" data-bind="checked: xclass.selected"/> <span data-bind="text: xclass.name"</span></label></li> |
197 | </ul> |
198 | </div> |
199 | </dd> |
200 | </dl> |
201 | </div> |
202 | </div> |
203 | <div class="clearfix"> |
204 | <h2>Actions</h2> |
205 | <button class="btn btn-success" data-bind="click: startBreakageDetection, disable: isComputing() || isPlanExecuting()">Detect breakages</button> |
206 | <button class="btn btn-primary" data-bind="click: computePlan, disable: isComputing() || isPlanExecuting()">Compute plan</button> |
207 | <button class="btn btn-primary" data-bind="disable: actions().length == 0 || isPlanExecuting() || tooLongs().length > 0, click: executePlan">Execute plan</button> |
208 | <button class="btn btn-default" data-bind="disable: actions().length == 0 || isPlanExecuting(), click: cleanPlan">Clean plan (to free the memory)</button> |
209 | </div> |
210 | </form> |
211 | <!------------------------------------------ |
212 | Display plan |
213 | -------------------------------------------> |
214 | <div data-bind="if: isPlanRequested() && !isPlanExecuting()"> |
215 | ## We escape the dollar of the knockout variable '$root' because $root also exists in velocity |
216 | <!-- ko template: {name: 'DisplayPlan', data: ${escapetool.d}root} --> |
217 | <!-- /ko --> |
218 | </div> |
219 | <!------------------------------------------ |
220 | Execute Plan |
221 | -------------------------------------------> |
222 | <!-- ko if: isPlanExecuting() && !success()--> |
223 | <div class="box" id="planExecuting"> |
224 | <p>The plan is being executed and it could take some time. Please wait...</p> |
225 | <div class="ui-progress-background"> |
226 | <div class="ui-progress-bar green" data-bind="style: {width: progress() + '%'}"></div> |
227 | </div> |
228 | <!-- ko template: {name: 'DisplayLogs', data: ${escapetool.d}root} --> |
229 | <!-- /ko --> |
230 | </div> |
231 | <!-- /ko --> |
232 | <!------------------------------------------ |
233 | Display breakages |
234 | -------------------------------------------> |
235 | <!-- ko if: isBreakageListRequested--> |
236 | <h2>Breakages</h2> |
237 | <div class="box"> |
238 | <div data-bind="if: isComputing"> |
239 | <p>The list of broken pages is being computed, please wait...</p> |
240 | <div class="ui-progress-background"> |
241 | <div class="ui-progress-bar green" data-bind="style: {width: progress() + '%'}"></div> |
242 | </div> |
243 | <!-- ko template: {name: 'DisplayLogs', data: ${escapetool.d}root} --> |
244 | <!-- /ko --> |
245 | </div> |
246 | <div data-bind="ifnot: isComputing"> |
247 | <p>If you don't migrate your pages, <strong data-bind="text: breakageList().size()"></strong> documents will lose their current parent.</p> |
248 | <ul data-bind="foreach: breakageList"> |
249 | <li>Page <span data-bind="text: document" class="monospace box infomessage" ></span> will lose its current parent <span data-bind="text: actualParent" class="monospace box infomessage"></span> because its location parent is <span data-bind="text: locationParent" class="monospace box infomessage"></span>.</li> |
250 | </ul> |
251 | </div> |
252 | </div> |
253 | <!-- /ko --> |
254 | <!------------------------------------------ |
255 | End message |
256 | -------------------------------------------> |
257 | <!-- ko if: success() --> |
258 | <div class="box successmessage" id="planExecuted"> |
259 | The plan have been executed! |
260 | </div> |
261 | <!-- ko template: {name: 'DisplayLogs', data: ${escapetool.d}root} --> |
262 | <!-- /ko --> |
263 | <!-- /ko --> |
264 | {{/html}} |
265 | #end |
266 | {{/velocity}} |