VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/webui/wuihlpform.py@ 83403

Last change on this file since 83403 was 83403, checked in by vboxsync, 5 years ago

TestManager/webui: Better/generic testbox links.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 58.9 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuihlpform.py 83403 2020-03-25 12:09:58Z vboxsync $
3
4"""
5Test Manager Web-UI - Form Helpers.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2020 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 83403 $"
30
31# Standard python imports.
32import copy;
33import sys;
34
35# Validation Kit imports.
36from common import utils;
37from common.webutils import escapeAttr, escapeElem;
38from testmanager import config;
39from testmanager.core.schedgroup import SchedGroupMemberData, SchedGroupDataEx;
40from testmanager.core.testcaseargs import TestCaseArgsData;
41from testmanager.core.testgroup import TestGroupMemberData, TestGroupDataEx;
42from testmanager.core.testbox import TestBoxDataForSchedGroup;
43
44# Python 3 hacks:
45if sys.version_info[0] >= 3:
46 unicode = str; # pylint: disable=redefined-builtin,invalid-name
47
48
49class WuiHlpForm(object):
50 """
51 Helper for constructing a form.
52 """
53
54 ksItemsList = 'ksItemsList'
55
56 ksOnSubmit_AddReturnToFieldWithCurrentUrl = '+AddReturnToFieldWithCurrentUrl+';
57
58 def __init__(self, sId, sAction, dErrors = None, fReadOnly = False, sOnSubmit = None):
59 self._fFinalized = False;
60 self._fReadOnly = fReadOnly;
61 self._dErrors = dErrors if dErrors is not None else dict();
62
63 if sOnSubmit == self.ksOnSubmit_AddReturnToFieldWithCurrentUrl:
64 sOnSubmit = u'return addRedirectToInputFieldWithCurrentUrl(this)';
65 if sOnSubmit is None: sOnSubmit = u'';
66 else: sOnSubmit = u' onsubmit=\"%s\"' % (escapeAttr(sOnSubmit),);
67
68 self._sBody = u'\n' \
69 u'<div id="%s" class="tmform">\n' \
70 u' <form action="%s" method="post"%s>\n' \
71 u' <ul>\n' \
72 % (sId, sAction, sOnSubmit);
73
74 def _add(self, sText):
75 """Internal worker for appending text to the body."""
76 assert not self._fFinalized;
77 if not self._fFinalized:
78 self._sBody += utils.toUnicode(sText, errors='ignore');
79 return True;
80 return False;
81
82 def _escapeErrorText(self, sText):
83 """Escapes error text, preserving some predefined HTML tags."""
84 if sText.find('<br>') >= 0:
85 asParts = sText.split('<br>');
86 for i, _ in enumerate(asParts):
87 asParts[i] = escapeElem(asParts[i].strip());
88 sText = '<br>\n'.join(asParts);
89 else:
90 sText = escapeElem(sText);
91 return sText;
92
93 def _addLabel(self, sName, sLabel, sDivSubClass = 'normal'):
94 """Internal worker for adding a label."""
95 if sName in self._dErrors:
96 sError = self._dErrors[sName];
97 if utils.isString(sError): # List error trick (it's an associative array).
98 return self._add(u' <li>\n'
99 u' <div class="tmform-field"><div class="tmform-field-%s">\n'
100 u' <label for="%s" class="tmform-error-label">%s\n'
101 u' <span class="tmform-error-desc">%s</span>\n'
102 u' </label>\n'
103 % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel),
104 self._escapeErrorText(sError), ) );
105 return self._add(u' <li>\n'
106 u' <div class="tmform-field"><div class="tmform-field-%s">\n'
107 u' <label for="%s">%s</label>\n'
108 % (escapeAttr(sDivSubClass), escapeAttr(sName), escapeElem(sLabel)) );
109
110
111 def finalize(self):
112 """
113 Finalizes the form and returns the body.
114 """
115 if not self._fFinalized:
116 self._add(u' </ul>\n'
117 u' </form>\n'
118 u'</div>\n'
119 u'<div class="clear"></div>\n' );
120 return self._sBody;
121
122 def addTextHidden(self, sName, sValue, sExtraAttribs = ''):
123 """Adds a hidden text input."""
124 return self._add(u' <div class="tmform-field-hidden">\n'
125 u' <input name="%s" id="%s" type="text" hidden%s value="%s" class="tmform-hidden">\n'
126 u' </div>\n'
127 u' </li>\n'
128 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeElem(str(sValue)) ));
129 #
130 # Non-input stuff.
131 #
132 def addNonText(self, sValue, sLabel, sName = 'non-text', sPostHtml = ''):
133 """Adds a read-only text input."""
134 self._addLabel(sName, sLabel, 'string');
135 if sValue is None: sValue = '';
136 return self._add(u' <p>%s%s</p>\n'
137 u' </div></div>\n'
138 u' </li>\n'
139 % (escapeElem(unicode(sValue)), sPostHtml ));
140
141 def addRawHtml(self, sRawHtml, sLabel, sName = 'raw-html'):
142 """Adds a read-only text input."""
143 self._addLabel(sName, sLabel, 'string');
144 self._add(sRawHtml);
145 return self._add(u' </div></div>\n'
146 u' </li>\n');
147
148
149 #
150 # Text input fields.
151 #
152 def addText(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = '', sPostHtml = ''):
153 """Adds a text input."""
154 if self._fReadOnly:
155 return self.addTextRO(sName, sValue, sLabel, sSubClass, sExtraAttribs);
156 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass);
157 self._addLabel(sName, sLabel, sSubClass);
158 if sValue is None: sValue = '';
159 return self._add(u' <input name="%s" id="%s" type="text"%s value="%s">%s\n'
160 u' </div></div>\n'
161 u' </li>\n'
162 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeAttr(unicode(sValue)), sPostHtml ));
163
164 def addTextRO(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = '', sPostHtml = ''):
165 """Adds a read-only text input."""
166 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp', 'wide'): raise Exception(sSubClass);
167 self._addLabel(sName, sLabel, sSubClass);
168 if sValue is None: sValue = '';
169 return self._add(u' <input name="%s" id="%s" type="text" readonly%s value="%s" class="tmform-input-readonly">'
170 u'%s\n'
171 u' </div></div>\n'
172 u' </li>\n'
173 % ( escapeAttr(sName), escapeAttr(sName), sExtraAttribs, escapeAttr(unicode(sValue)), sPostHtml ));
174
175 def addWideText(self, sName, sValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
176 """Adds a wide text input."""
177 return self.addText(sName, sValue, sLabel, 'wide', sExtraAttribs, sPostHtml = sPostHtml);
178
179 def addWideTextRO(self, sName, sValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
180 """Adds a wide read-only text input."""
181 return self.addTextRO(sName, sValue, sLabel, 'wide', sExtraAttribs, sPostHtml = sPostHtml);
182
183 def _adjustMultilineTextAttribs(self, sExtraAttribs, sValue):
184 """ Internal helper for setting good default sizes for textarea based on content."""
185 if sExtraAttribs.find('cols') < 0 and sExtraAttribs.find('width') < 0:
186 sExtraAttribs = 'cols="96%" ' + sExtraAttribs;
187
188 if sExtraAttribs.find('rows') < 0 and sExtraAttribs.find('width') < 0:
189 if sValue is None: sValue = '';
190 else: sValue = sValue.strip();
191
192 cRows = sValue.count('\n') + (not sValue.endswith('\n'));
193 if cRows * 80 < len(sValue):
194 cRows += 2;
195 cRows = max(min(cRows, 16), 2);
196 sExtraAttribs = ('rows="%s" ' % (cRows,)) + sExtraAttribs;
197
198 return sExtraAttribs;
199
200 def addMultilineText(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = ''):
201 """Adds a multiline text input."""
202 if self._fReadOnly:
203 return self.addMultilineTextRO(sName, sValue, sLabel, sSubClass, sExtraAttribs);
204 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass)
205 self._addLabel(sName, sLabel, sSubClass)
206 if sValue is None: sValue = '';
207 sNewValue = unicode(sValue) if not isinstance(sValue, list) else '\n'.join(sValue)
208 return self._add(u' <textarea name="%s" id="%s" %s>%s</textarea>\n'
209 u' </div></div>\n'
210 u' </li>\n'
211 % ( escapeAttr(sName), escapeAttr(sName), self._adjustMultilineTextAttribs(sExtraAttribs, sNewValue),
212 escapeElem(sNewValue)))
213
214 def addMultilineTextRO(self, sName, sValue, sLabel, sSubClass = 'string', sExtraAttribs = ''):
215 """Adds a multiline read-only text input."""
216 if sSubClass not in ('int', 'long', 'string', 'uuid', 'timestamp'): raise Exception(sSubClass)
217 self._addLabel(sName, sLabel, sSubClass)
218 if sValue is None: sValue = '';
219 sNewValue = unicode(sValue) if not isinstance(sValue, list) else '\n'.join(sValue)
220 return self._add(u' <textarea name="%s" id="%s" readonly %s>%s</textarea>\n'
221 u' </div></div>\n'
222 u' </li>\n'
223 % ( escapeAttr(sName), escapeAttr(sName), self._adjustMultilineTextAttribs(sExtraAttribs, sNewValue),
224 escapeElem(sNewValue)))
225
226 def addInt(self, sName, iValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
227 """Adds an integer input."""
228 return self.addText(sName, unicode(iValue), sLabel, 'int', sExtraAttribs, sPostHtml = sPostHtml);
229
230 def addIntRO(self, sName, iValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
231 """Adds an integer input."""
232 return self.addTextRO(sName, unicode(iValue), sLabel, 'int', sExtraAttribs, sPostHtml = sPostHtml);
233
234 def addLong(self, sName, lValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
235 """Adds a long input."""
236 return self.addText(sName, unicode(lValue), sLabel, 'long', sExtraAttribs, sPostHtml = sPostHtml);
237
238 def addLongRO(self, sName, lValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
239 """Adds a long input."""
240 return self.addTextRO(sName, unicode(lValue), sLabel, 'long', sExtraAttribs, sPostHtml = sPostHtml);
241
242 def addUuid(self, sName, uuidValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
243 """Adds an UUID input."""
244 return self.addText(sName, unicode(uuidValue), sLabel, 'uuid', sExtraAttribs, sPostHtml = sPostHtml);
245
246 def addUuidRO(self, sName, uuidValue, sLabel, sExtraAttribs = '', sPostHtml = ''):
247 """Adds a read-only UUID input."""
248 return self.addTextRO(sName, unicode(uuidValue), sLabel, 'uuid', sExtraAttribs, sPostHtml = sPostHtml);
249
250 def addTimestampRO(self, sName, sTimestamp, sLabel, sExtraAttribs = '', sPostHtml = ''):
251 """Adds a read-only database string timstamp input."""
252 return self.addTextRO(sName, sTimestamp, sLabel, 'timestamp', sExtraAttribs, sPostHtml = sPostHtml);
253
254
255 #
256 # Text areas.
257 #
258
259
260 #
261 # Combo boxes.
262 #
263 def addComboBox(self, sName, sSelected, sLabel, aoOptions, sExtraAttribs = '', sPostHtml = ''):
264 """Adds a combo box."""
265 if self._fReadOnly:
266 return self.addComboBoxRO(sName, sSelected, sLabel, aoOptions, sExtraAttribs, sPostHtml);
267 self._addLabel(sName, sLabel, 'combobox');
268 self._add(' <select name="%s" id="%s" class="tmform-combobox"%s>\n'
269 % (escapeAttr(sName), escapeAttr(sName), sExtraAttribs));
270 sSelected = unicode(sSelected);
271 for iValue, sText, _ in aoOptions:
272 sValue = unicode(iValue);
273 self._add(' <option value="%s"%s>%s</option>\n'
274 % (escapeAttr(sValue), ' selected' if sValue == sSelected else '',
275 escapeElem(sText)));
276 return self._add(u' </select>' + sPostHtml + '\n'
277 u' </div></div>\n'
278 u' </li>\n');
279
280 def addComboBoxRO(self, sName, sSelected, sLabel, aoOptions, sExtraAttribs = '', sPostHtml = ''):
281 """Adds a read-only combo box."""
282 self.addTextHidden(sName, sSelected);
283 self._addLabel(sName, sLabel, 'combobox-readonly');
284 self._add(u' <select name="%s" id="%s" disabled class="tmform-combobox"%s>\n'
285 % (escapeAttr(sName), escapeAttr(sName), sExtraAttribs));
286 sSelected = unicode(sSelected);
287 for iValue, sText, _ in aoOptions:
288 sValue = unicode(iValue);
289 self._add(' <option value="%s"%s>%s</option>\n'
290 % (escapeAttr(sValue), ' selected' if sValue == sSelected else '',
291 escapeElem(sText)));
292 return self._add(u' </select>' + sPostHtml + '\n'
293 u' </div></div>\n'
294 u' </li>\n');
295
296 #
297 # Check boxes.
298 #
299 @staticmethod
300 def _reinterpretBool(fValue):
301 """Reinterprets a value as a boolean type."""
302 if fValue is not type(True):
303 if fValue is None:
304 fValue = False;
305 elif str(fValue) in ('True', 'true', '1'):
306 fValue = True;
307 else:
308 fValue = False;
309 return fValue;
310
311 def addCheckBox(self, sName, fChecked, sLabel, sExtraAttribs = ''):
312 """Adds an check box."""
313 if self._fReadOnly:
314 return self.addCheckBoxRO(sName, fChecked, sLabel, sExtraAttribs);
315 self._addLabel(sName, sLabel, 'checkbox');
316 fChecked = self._reinterpretBool(fChecked);
317 return self._add(u' <input name="%s" id="%s" type="checkbox"%s%s value="1" class="tmform-checkbox">\n'
318 u' </div></div>\n'
319 u' </li>\n'
320 % (escapeAttr(sName), escapeAttr(sName), ' checked' if fChecked else '', sExtraAttribs));
321
322 def addCheckBoxRO(self, sName, fChecked, sLabel, sExtraAttribs = ''):
323 """Adds an readonly check box."""
324 self._addLabel(sName, sLabel, 'checkbox');
325 fChecked = self._reinterpretBool(fChecked);
326 # Hack Alert! The onclick and onkeydown are for preventing editing and fake readonly/disabled.
327 return self._add(u' <input name="%s" id="%s" type="checkbox"%s readonly%s value="1" class="readonly"\n'
328 u' onclick="return false" onkeydown="return false">\n'
329 u' </div></div>\n'
330 u' </li>\n'
331 % (escapeAttr(sName), escapeAttr(sName), ' checked' if fChecked else '', sExtraAttribs));
332
333 #
334 # List of items to check
335 #
336 def _addList(self, sName, aoRows, sLabel, fUseTable = False, sId = 'dummy', sExtraAttribs = ''):
337 """
338 Adds a list of items to check.
339
340 @param sName Name of HTML form element
341 @param aoRows List of [sValue, fChecked, sName] sub-arrays.
342 @param sLabel Label of HTML form element
343 """
344 fReadOnly = self._fReadOnly; ## @todo add this as a parameter.
345 if fReadOnly:
346 sExtraAttribs += ' readonly onclick="return false" onkeydown="return false"';
347
348 self._addLabel(sName, sLabel, 'list');
349 if not aoRows:
350 return self._add('No items</div></div></li>')
351 sNameEscaped = escapeAttr(sName);
352
353 self._add(' <div class="tmform-checkboxes-container" id="%s">\n' % (escapeAttr(sId),));
354 if fUseTable:
355 self._add(' <table>\n');
356 for asRow in aoRows:
357 assert len(asRow) == 3; # Don't allow sloppy input data!
358 fChecked = self._reinterpretBool(asRow[1])
359 self._add(u' <tr>\n'
360 u' <td><input type="checkbox" name="%s" value="%s"%s%s></td>\n'
361 u' <td>%s</td>\n'
362 u' </tr>\n'
363 % ( sNameEscaped, escapeAttr(unicode(asRow[0])), ' checked' if fChecked else '', sExtraAttribs,
364 escapeElem(unicode(asRow[2])), ));
365 self._add(u' </table>\n');
366 else:
367 for asRow in aoRows:
368 assert len(asRow) == 3; # Don't allow sloppy input data!
369 fChecked = self._reinterpretBool(asRow[1])
370 self._add(u' <div class="tmform-checkbox-holder">'
371 u'<input type="checkbox" name="%s" value="%s"%s%s> %s</input></div>\n'
372 % ( sNameEscaped, escapeAttr(unicode(asRow[0])), ' checked' if fChecked else '', sExtraAttribs,
373 escapeElem(unicode(asRow[2])),));
374 return self._add(u' </div></div></div>\n'
375 u' </li>\n');
376
377
378 def addListOfOsArches(self, sName, aoOsArches, sLabel, sExtraAttribs = ''):
379 """
380 List of checkboxes for OS/ARCH selection.
381 asOsArches is a list of [sValue, fChecked, sName] sub-arrays.
382 """
383 return self._addList(sName, aoOsArches, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-os-arches',
384 sExtraAttribs = sExtraAttribs);
385
386 def addListOfTypes(self, sName, aoTypes, sLabel, sExtraAttribs = ''):
387 """
388 List of checkboxes for build type selection.
389 aoTypes is a list of [sValue, fChecked, sName] sub-arrays.
390 """
391 return self._addList(sName, aoTypes, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-build-types',
392 sExtraAttribs = sExtraAttribs);
393
394 def addListOfTestCases(self, sName, aoTestCases, sLabel, sExtraAttribs = ''):
395 """
396 List of checkboxes for test box (dependency) selection.
397 aoTestCases is a list of [sValue, fChecked, sName] sub-arrays.
398 """
399 return self._addList(sName, aoTestCases, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-testcases',
400 sExtraAttribs = sExtraAttribs);
401
402 def addListOfResources(self, sName, aoTestCases, sLabel, sExtraAttribs = ''):
403 """
404 List of checkboxes for resource selection.
405 aoTestCases is a list of [sValue, fChecked, sName] sub-arrays.
406 """
407 return self._addList(sName, aoTestCases, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-resources',
408 sExtraAttribs = sExtraAttribs);
409
410 def addListOfTestGroups(self, sName, aoTestGroups, sLabel, sExtraAttribs = ''):
411 """
412 List of checkboxes for test group selection.
413 aoTestGroups is a list of [sValue, fChecked, sName] sub-arrays.
414 """
415 return self._addList(sName, aoTestGroups, sLabel, fUseTable = False, sId = 'tmform-checkbox-list-testgroups',
416 sExtraAttribs = sExtraAttribs);
417
418 def addListOfTestCaseArgs(self, sName, aoVariations, sLabel): # pylint: disable=too-many-statements
419 """
420 Adds a list of test case argument variations to the form.
421
422 @param sName Name of HTML form element
423 @param aoVariations List of TestCaseArgsData instances.
424 @param sLabel Label of HTML form element
425 """
426 self._addLabel(sName, sLabel);
427
428 sTableId = u'TestArgsExtendingListRoot';
429 fReadOnly = self._fReadOnly; ## @todo argument?
430 sReadOnlyAttr = u' readonly class="tmform-input-readonly"' if fReadOnly else '';
431
432 sHtml = u'<li>\n'
433
434 #
435 # Define javascript function for extending the list of test case
436 # variations. Doing it here so we can use the python constants. This
437 # also permits multiple argument lists on one page should that ever be
438 # required...
439 #
440 if not fReadOnly:
441 sHtml += u'<script type="text/javascript">\n'
442 sHtml += u'\n';
443 sHtml += u'g_%s_aItems = { %s };\n' % (sName, ', '.join(('%s: 1' % (i,)) for i in range(len(aoVariations))),);
444 sHtml += u'g_%s_cItems = %s;\n' % (sName, len(aoVariations),);
445 sHtml += u'g_%s_iIdMod = %s;\n' % (sName, len(aoVariations) + 32);
446 sHtml += u'\n';
447 sHtml += u'function %s_removeEntry(sId)\n' % (sName,);
448 sHtml += u'{\n';
449 sHtml += u' if (g_%s_cItems > 1)\n' % (sName,);
450 sHtml += u' {\n';
451 sHtml += u' g_%s_cItems--;\n' % (sName,);
452 sHtml += u' delete g_%s_aItems[sId];\n' % (sName,);
453 sHtml += u' setElementValueToKeyList(\'%s\', g_%s_aItems);\n' % (sName, sName);
454 sHtml += u'\n';
455 for iInput in range(8):
456 sHtml += u' removeHtmlNode(\'%s[\' + sId + \'][%s]\');\n' % (sName, iInput,);
457 sHtml += u' }\n';
458 sHtml += u'}\n';
459 sHtml += u'\n';
460 sHtml += u'function %s_extendListEx(sSubName, cGangMembers, cSecTimeout, sArgs, sTestBoxReqExpr, sBuildReqExpr)\n' \
461 % (sName,);
462 sHtml += u'{\n';
463 sHtml += u' var oElement = document.getElementById(\'%s\');\n' % (sTableId,);
464 sHtml += u' var oTBody = document.createElement(\'tbody\');\n';
465 sHtml += u' var sHtml = \'\';\n';
466 sHtml += u' var sId;\n';
467 sHtml += u'\n';
468 sHtml += u' g_%s_iIdMod += 1;\n' % (sName,);
469 sHtml += u' sId = g_%s_iIdMod.toString();\n' % (sName,);
470
471 oVarDefaults = TestCaseArgsData();
472 oVarDefaults.convertToParamNull();
473 sHtml += u'\n';
474 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-first-row">\';\n';
475 sHtml += u' sHtml += \' <td>Sub-Name:</td>\';\n';
476 sHtml += u' sHtml += \' <td class="tmform-field-subname">' \
477 '<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][0]" value="\' + sSubName + \'"></td>\';\n' \
478 % (sName, TestCaseArgsData.ksParam_sSubName, sName,);
479 sHtml += u' sHtml += \' <td>Gang Members:</td>\';\n';
480 sHtml += u' sHtml += \' <td class="tmform-field-tiny-int">' \
481 '<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][0]" value="\' + cGangMembers + \'"></td>\';\n' \
482 % (sName, TestCaseArgsData.ksParam_cGangMembers, sName,);
483 sHtml += u' sHtml += \' <td>Timeout:</td>\';\n';
484 sHtml += u' sHtml += \' <td class="tmform-field-int">' \
485 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][1]" value="\'+ cSecTimeout + \'"></td>\';\n' \
486 % (sName, TestCaseArgsData.ksParam_cSecTimeout, sName,);
487 sHtml += u' sHtml += \' <td><a href="#" onclick="%s_removeEntry(\\\'\' + sId + \'\\\');"> Remove</a></td>\';\n' \
488 % (sName, );
489 sHtml += u' sHtml += \' <td></td>\';\n';
490 sHtml += u' sHtml += \'</tr>\';\n'
491 sHtml += u'\n';
492 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-inner-row">\';\n';
493 sHtml += u' sHtml += \' <td>Arguments:</td>\';\n';
494 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="6">' \
495 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sArgs + \'"></td>\';\n' \
496 % (sName, TestCaseArgsData.ksParam_sArgs, sName,);
497 sHtml += u' sHtml += \' <td></td>\';\n';
498 sHtml += u' sHtml += \'</tr>\';\n'
499 sHtml += u'\n';
500 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-inner-row">\';\n';
501 sHtml += u' sHtml += \' <td>TestBox Reqs:</td>\';\n';
502 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="6">' \
503 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sTestBoxReqExpr' \
504 u' + \'"></td>\';\n' \
505 % (sName, TestCaseArgsData.ksParam_sTestBoxReqExpr, sName,);
506 sHtml += u' sHtml += \' <td></td>\';\n';
507 sHtml += u' sHtml += \'</tr>\';\n'
508 sHtml += u'\n';
509 sHtml += u' sHtml += \'<tr class="tmform-testcasevars-final-row">\';\n';
510 sHtml += u' sHtml += \' <td>Build Reqs:</td>\';\n';
511 sHtml += u' sHtml += \' <td class="tmform-field-wide100" colspan="6">' \
512 u'<input name="%s[\' + sId + \'][%s]" id="%s[\' + sId + \'][2]" value="\' + sBuildReqExpr + \'"></td>\';\n' \
513 % (sName, TestCaseArgsData.ksParam_sBuildReqExpr, sName,);
514 sHtml += u' sHtml += \' <td></td>\';\n';
515 sHtml += u' sHtml += \'</tr>\';\n'
516 sHtml += u'\n';
517 sHtml += u' oTBody.id = \'%s[\' + sId + \'][6]\';\n' % (sName,);
518 sHtml += u' oTBody.innerHTML = sHtml;\n';
519 sHtml += u'\n';
520 sHtml += u' oElement.appendChild(oTBody);\n';
521 sHtml += u'\n';
522 sHtml += u' g_%s_aItems[sId] = 1;\n' % (sName,);
523 sHtml += u' g_%s_cItems++;\n' % (sName,);
524 sHtml += u' setElementValueToKeyList(\'%s\', g_%s_aItems);\n' % (sName, sName);
525 sHtml += u'}\n';
526 sHtml += u'function %s_extendList()\n' % (sName,);
527 sHtml += u'{\n';
528 sHtml += u' %s_extendListEx("%s", "%s", "%s", "%s", "%s", "%s");\n' % (sName,
529 escapeAttr(unicode(oVarDefaults.sSubName)), escapeAttr(unicode(oVarDefaults.cGangMembers)),
530 escapeAttr(unicode(oVarDefaults.cSecTimeout)), escapeAttr(oVarDefaults.sArgs),
531 escapeAttr(oVarDefaults.sTestBoxReqExpr), escapeAttr(oVarDefaults.sBuildReqExpr), );
532 sHtml += u'}\n';
533 if config.g_kfVBoxSpecific:
534 sSecTimeoutDef = escapeAttr(unicode(oVarDefaults.cSecTimeout));
535 sHtml += u'function vbox_%s_add_uni()\n' % (sName,);
536 sHtml += u'{\n';
537 sHtml += u' %s_extendListEx("1-raw", "1", "%s", "--cpu-counts 1 --virt-modes raw", ' \
538 u' "", "");\n' % (sName, sSecTimeoutDef);
539 sHtml += u' %s_extendListEx("1-hw", "1", "%s", "--cpu-counts 1 --virt-modes hwvirt", ' \
540 u' "fCpuHwVirt is True", "");\n' % (sName, sSecTimeoutDef);
541 sHtml += u' %s_extendListEx("1-np", "1", "%s", "--cpu-counts 1 --virt-modes hwvirt-np", ' \
542 u' "fCpuNestedPaging is True", "");\n' % (sName, sSecTimeoutDef);
543 sHtml += u'}\n';
544 sHtml += u'function vbox_%s_add_uni_amd64()\n' % (sName,);
545 sHtml += u'{\n';
546 sHtml += u' %s_extendListEx("1-hw", "1", "%s", "--cpu-counts 1 --virt-modes hwvirt", ' \
547 u' "fCpuHwVirt is True", "");\n' % (sName, sSecTimeoutDef);
548 sHtml += u' %s_extendListEx("1-np", "%s", "--cpu-counts 1 --virt-modes hwvirt-np", ' \
549 u' "fCpuNestedPaging is True", "");\n' % (sName, sSecTimeoutDef);
550 sHtml += u'}\n';
551 sHtml += u'function vbox_%s_add_smp()\n' % (sName,);
552 sHtml += u'{\n';
553 sHtml += u' %s_extendListEx("2-hw", "1", "%s", "--cpu-counts 2 --virt-modes hwvirt",' \
554 u' "fCpuHwVirt is True and cCpus >= 2", "");\n' % (sName, sSecTimeoutDef);
555 sHtml += u' %s_extendListEx("2-np", "1", "%s", "--cpu-counts 2 --virt-modes hwvirt-np",' \
556 u' "fCpuNestedPaging is True and cCpus >= 2", "");\n' % (sName, sSecTimeoutDef);
557 sHtml += u' %s_extendListEx("3-hw", "1", "%s", "--cpu-counts 3 --virt-modes hwvirt",' \
558 u' "fCpuHwVirt is True and cCpus >= 3", "");\n' % (sName, sSecTimeoutDef);
559 sHtml += u' %s_extendListEx("4-np", "1", "%s", "--cpu-counts 4 --virt-modes hwvirt-np ",' \
560 u' "fCpuNestedPaging is True and cCpus >= 4", "");\n' % (sName, sSecTimeoutDef);
561 #sHtml += u' %s_extendListEx("6-hw", "1", "%s", "--cpu-counts 6 --virt-modes hwvirt",' \
562 # u' "fCpuHwVirt is True and cCpus >= 6", "");\n' % (sName, sSecTimeoutDef);
563 #sHtml += u' %s_extendListEx("8-np", "1", "%s", "--cpu-counts 8 --virt-modes hwvirt-np",' \
564 # u' "fCpuNestedPaging is True and cCpus >= 8", "");\n' % (sName, sSecTimeoutDef);
565 sHtml += u'}\n';
566 sHtml += u'</script>\n';
567
568
569 #
570 # List current entries.
571 #
572 sHtml += u'<input type="hidden" name="%s" id="%s" value="%s">\n' \
573 % (sName, sName, ','.join(unicode(i) for i in range(len(aoVariations))), );
574 sHtml += u' <table id="%s" class="tmform-testcasevars">\n' % (sTableId,)
575 if not fReadOnly:
576 sHtml += u' <caption>\n' \
577 u' <a href="#" onClick="%s_extendList()">Add</a>\n' % (sName,);
578 if config.g_kfVBoxSpecific:
579 sHtml += u' [<a href="#" onClick="vbox_%s_add_uni()">Single CPU Variations</a>\n' % (sName,);
580 sHtml += u' <a href="#" onClick="vbox_%s_add_uni_amd64()">amd64</a>]\n' % (sName,);
581 sHtml += u' [<a href="#" onClick="vbox_%s_add_smp()">SMP Variations</a>]\n' % (sName,);
582 sHtml += u' </caption>\n';
583
584 dSubErrors = {};
585 if sName in self._dErrors and isinstance(self._dErrors[sName], dict):
586 dSubErrors = self._dErrors[sName];
587
588 for iVar, _ in enumerate(aoVariations):
589 oVar = copy.copy(aoVariations[iVar]);
590 oVar.convertToParamNull();
591
592 sHtml += u'<tbody id="%s[%s][6]">\n' % (sName, iVar,)
593 sHtml += u' <tr class="tmform-testcasevars-first-row">\n' \
594 u' <td>Sub-name:</td>' \
595 u' <td class="tmform-field-subname"><input name="%s[%s][%s]" id="%s[%s][1]" value="%s"%s></td>\n' \
596 u' <td>Gang Members:</td>' \
597 u' <td class="tmform-field-tiny-int"><input name="%s[%s][%s]" id="%s[%s][1]" value="%s"%s></td>\n' \
598 u' <td>Timeout:</td>' \
599 u' <td class="tmform-field-int"><input name="%s[%s][%s]" id="%s[%s][2]" value="%s"%s></td>\n' \
600 % ( sName, iVar, TestCaseArgsData.ksParam_sSubName, sName, iVar, oVar.sSubName, sReadOnlyAttr,
601 sName, iVar, TestCaseArgsData.ksParam_cGangMembers, sName, iVar, oVar.cGangMembers, sReadOnlyAttr,
602 sName, iVar, TestCaseArgsData.ksParam_cSecTimeout, sName, iVar,
603 utils.formatIntervalSeconds2(oVar.cSecTimeout), sReadOnlyAttr, );
604 if not fReadOnly:
605 sHtml += u' <td><a href="#" onclick="%s_removeEntry(\'%s\');">Remove</a></td>\n' \
606 % (sName, iVar);
607 else:
608 sHtml += u' <td></td>\n';
609 sHtml += u' <td class="tmform-testcasevars-stupid-border-column"></td>\n' \
610 u' </tr>\n';
611
612 sHtml += u' <tr class="tmform-testcasevars-inner-row">\n' \
613 u' <td>Arguments:</td>' \
614 u' <td class="tmform-field-wide100" colspan="6">' \
615 u'<input name="%s[%s][%s]" id="%s[%s][3]" value="%s"%s></td>\n' \
616 u' <td></td>\n' \
617 u' </tr>\n' \
618 % ( sName, iVar, TestCaseArgsData.ksParam_sArgs, sName, iVar, escapeAttr(oVar.sArgs), sReadOnlyAttr)
619
620 sHtml += u' <tr class="tmform-testcasevars-inner-row">\n' \
621 u' <td>TestBox Reqs:</td>' \
622 u' <td class="tmform-field-wide100" colspan="6">' \
623 u'<input name="%s[%s][%s]" id="%s[%s][4]" value="%s"%s></td>\n' \
624 u' <td></td>\n' \
625 u' </tr>\n' \
626 % ( sName, iVar, TestCaseArgsData.ksParam_sTestBoxReqExpr, sName, iVar,
627 escapeAttr(oVar.sTestBoxReqExpr), sReadOnlyAttr)
628
629 sHtml += u' <tr class="tmform-testcasevars-final-row">\n' \
630 u' <td>Build Reqs:</td>' \
631 u' <td class="tmform-field-wide100" colspan="6">' \
632 u'<input name="%s[%s][%s]" id="%s[%s][5]" value="%s"%s></td>\n' \
633 u' <td></td>\n' \
634 u' </tr>\n' \
635 % ( sName, iVar, TestCaseArgsData.ksParam_sBuildReqExpr, sName, iVar,
636 escapeAttr(oVar.sBuildReqExpr), sReadOnlyAttr)
637
638
639 if iVar in dSubErrors:
640 sHtml += u' <tr><td colspan="4"><p align="left" class="tmform-error-desc">%s</p></td></tr>\n' \
641 % (self._escapeErrorText(dSubErrors[iVar]),);
642
643 sHtml += u'</tbody>\n';
644 sHtml += u' </table>\n'
645 sHtml += u'</li>\n'
646
647 return self._add(sHtml)
648
649 def addListOfTestGroupMembers(self, sName, aoTestGroupMembers, aoAllTestCases, sLabel, # pylint: disable=too-many-locals
650 fReadOnly = True):
651 """
652 For WuiTestGroup.
653 """
654 assert len(aoTestGroupMembers) <= len(aoAllTestCases);
655 self._addLabel(sName, sLabel);
656 if not aoAllTestCases:
657 return self._add('<li>No testcases.</li>\n')
658
659 self._add(u'<input name="%s" type="hidden" value="%s">\n'
660 % ( TestGroupDataEx.ksParam_aidTestCases,
661 ','.join([unicode(oTestCase.idTestCase) for oTestCase in aoAllTestCases]), ));
662
663 self._add(u'<table class="tmformtbl">\n'
664 u' <thead>\n'
665 u' <tr>\n'
666 u' <th rowspan="2"></th>\n'
667 u' <th rowspan="2">Test Case</th>\n'
668 u' <th rowspan="2">All Vars</th>\n'
669 u' <th rowspan="2">Priority [0..31]</th>\n'
670 u' <th colspan="4" align="center">Variations</th>\n'
671 u' </tr>\n'
672 u' <tr>\n'
673 u' <th>Included</th>\n'
674 u' <th>Gang size</th>\n'
675 u' <th>Timeout</th>\n'
676 u' <th>Arguments</th>\n'
677 u' </tr>\n'
678 u' </thead>\n'
679 u' <tbody>\n'
680 );
681
682 if self._fReadOnly:
683 fReadOnly = True;
684 sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
685
686 oDefMember = TestGroupMemberData();
687 aoTestGroupMembers = list(aoTestGroupMembers); # Copy it so we can pop.
688 for iTestCase, _ in enumerate(aoAllTestCases):
689 oTestCase = aoAllTestCases[iTestCase];
690
691 # Is it a member?
692 oMember = None;
693 for i, _ in enumerate(aoTestGroupMembers):
694 if aoTestGroupMembers[i].oTestCase.idTestCase == oTestCase.idTestCase:
695 oMember = aoTestGroupMembers.pop(i);
696 break;
697
698 # Start on the rows...
699 sPrefix = u'%s[%d]' % (sName, oTestCase.idTestCase,);
700 self._add(u' <tr class="%s">\n'
701 u' <td rowspan="%d">\n'
702 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestCase
703 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestGroup
704 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
705 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
706 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
707 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
708 u' </td>\n'
709 % ( 'tmodd' if iTestCase & 1 else 'tmeven',
710 len(oTestCase.aoTestCaseArgs),
711 sPrefix, TestGroupMemberData.ksParam_idTestCase, oTestCase.idTestCase,
712 sPrefix, TestGroupMemberData.ksParam_idTestGroup, -1 if oMember is None else oMember.idTestGroup,
713 sPrefix, TestGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
714 sPrefix, TestGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
715 sPrefix, TestGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
716 TestGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr,
717 oTestCase.idTestCase, oTestCase.idTestCase, escapeElem(oTestCase.sName),
718 ));
719 self._add(u' <td rowspan="%d" align="left">%s</td>\n'
720 % ( len(oTestCase.aoTestCaseArgs), escapeElem(oTestCase.sName), ));
721
722 self._add(u' <td rowspan="%d" title="Include all variations (checked) or choose a set?">\n'
723 u' <input name="%s[%s]" type="checkbox"%s%s value="-1">\n'
724 u' </td>\n'
725 % ( len(oTestCase.aoTestCaseArgs),
726 sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs,
727 ' checked' if oMember is None or oMember.aidTestCaseArgs is None else '', sCheckBoxAttr, ));
728
729 self._add(u' <td rowspan="%d" align="center">\n'
730 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
731 u' </td>\n'
732 % ( len(oTestCase.aoTestCaseArgs),
733 sPrefix, TestGroupMemberData.ksParam_iSchedPriority,
734 (oMember if oMember is not None else oDefMember).iSchedPriority,
735 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
736
737 # Argument variations.
738 aidTestCaseArgs = [] if oMember is None or oMember.aidTestCaseArgs is None else oMember.aidTestCaseArgs;
739 for iVar in range(len(oTestCase.aoTestCaseArgs)):
740 oVar = oTestCase.aoTestCaseArgs[iVar];
741 if iVar > 0:
742 self._add(' <tr class="%s">\n' % ('tmodd' if iTestCase & 1 else 'tmeven',));
743 self._add(u' <td align="center">\n'
744 u' <input name="%s[%s]" type="checkbox"%s%s value="%d">'
745 u' </td>\n'
746 % ( sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs,
747 ' checked' if oVar.idTestCaseArgs in aidTestCaseArgs else '', sCheckBoxAttr, oVar.idTestCaseArgs,
748 ));
749 self._add(u' <td align="center">%s</td>\n'
750 u' <td align="center">%s</td>\n'
751 u' <td align="left">%s</td>\n'
752 % ( oVar.cGangMembers,
753 'Default' if oVar.cSecTimeout is None else oVar.cSecTimeout,
754 escapeElem(oVar.sArgs) ));
755
756 self._add(u' </tr>\n');
757
758
759
760 if not oTestCase.aoTestCaseArgs:
761 self._add(u' <td></td> <td></td> <td></td> <td></td>\n'
762 u' </tr>\n');
763 return self._add(u' </tbody>\n'
764 u'</table>\n');
765
766 def addListOfSchedGroupMembers(self, sName, aoSchedGroupMembers, aoAllRelevantTestGroups, # pylint: disable=too-many-locals
767 sLabel, idSchedGroup, fReadOnly = True):
768 """
769 For WuiAdminSchedGroup.
770 """
771 if fReadOnly is None or self._fReadOnly:
772 fReadOnly = self._fReadOnly;
773 assert len(aoSchedGroupMembers) <= len(aoAllRelevantTestGroups);
774 self._addLabel(sName, sLabel);
775 if not aoAllRelevantTestGroups:
776 return self._add(u'<li>No test groups.</li>\n')
777
778 self._add(u'<input name="%s" type="hidden" value="%s">\n'
779 % ( SchedGroupDataEx.ksParam_aidTestGroups,
780 ','.join([unicode(oTestGroup.idTestGroup) for oTestGroup in aoAllRelevantTestGroups]), ));
781
782 self._add(u'<table class="tmformtbl tmformtblschedgroupmembers">\n'
783 u' <thead>\n'
784 u' <tr>\n'
785 u' <th></th>\n'
786 u' <th>Test Group</th>\n'
787 u' <th>Priority [0..31]</th>\n'
788 u' <th>Prerequisite Test Group</th>\n'
789 u' <th>Weekly schedule</th>\n'
790 u' </tr>\n'
791 u' </thead>\n'
792 u' <tbody>\n'
793 );
794
795 sCheckBoxAttr = u' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
796 sComboBoxAttr = u' disabled' if fReadOnly else '';
797
798 oDefMember = SchedGroupMemberData();
799 aoSchedGroupMembers = list(aoSchedGroupMembers); # Copy it so we can pop.
800 for iTestGroup, _ in enumerate(aoAllRelevantTestGroups):
801 oTestGroup = aoAllRelevantTestGroups[iTestGroup];
802
803 # Is it a member?
804 oMember = None;
805 for i, _ in enumerate(aoSchedGroupMembers):
806 if aoSchedGroupMembers[i].oTestGroup.idTestGroup == oTestGroup.idTestGroup:
807 oMember = aoSchedGroupMembers.pop(i);
808 break;
809
810 # Start on the rows...
811 sPrefix = u'%s[%d]' % (sName, oTestGroup.idTestGroup,);
812 self._add(u' <tr class="%s">\n'
813 u' <td>\n'
814 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestGroup
815 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
816 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
817 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
818 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
819 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
820 u' </td>\n'
821 % ( 'tmodd' if iTestGroup & 1 else 'tmeven',
822 sPrefix, SchedGroupMemberData.ksParam_idTestGroup, oTestGroup.idTestGroup,
823 sPrefix, SchedGroupMemberData.ksParam_idSchedGroup, idSchedGroup,
824 sPrefix, SchedGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
825 sPrefix, SchedGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
826 sPrefix, SchedGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
827 SchedGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr,
828 oTestGroup.idTestGroup, oTestGroup.idTestGroup, escapeElem(oTestGroup.sName),
829 ));
830 self._add(u' <td>%s</td>\n' % ( escapeElem(oTestGroup.sName), ));
831
832 self._add(u' <td>\n'
833 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
834 u' </td>\n'
835 % ( sPrefix, SchedGroupMemberData.ksParam_iSchedPriority,
836 (oMember if oMember is not None else oDefMember).iSchedPriority,
837 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
838
839 self._add(u' <td>\n'
840 u' <select name="%s[%s]" id="%s[%s]" class="tmform-combobox"%s>\n'
841 u' <option value="-1"%s>None</option>\n'
842 % ( sPrefix, SchedGroupMemberData.ksParam_idTestGroupPreReq,
843 sPrefix, SchedGroupMemberData.ksParam_idTestGroupPreReq,
844 sComboBoxAttr,
845 ' selected' if oMember is None or oMember.idTestGroupPreReq is None else '',
846 ));
847 for oTestGroup2 in aoAllRelevantTestGroups:
848 if oTestGroup2 != oTestGroup:
849 fSelected = oMember is not None and oTestGroup2.idTestGroup == oMember.idTestGroupPreReq;
850 self._add(' <option value="%s"%s>%s</option>\n'
851 % ( oTestGroup2.idTestGroup, ' selected' if fSelected else '', escapeElem(oTestGroup2.sName), ));
852 self._add(u' </select>\n'
853 u' </td>\n');
854
855 self._add(u' <td>\n'
856 u' Todo<input name="%s[%s]" type="hidden" value="%s">\n'
857 u' </td>\n'
858 % ( sPrefix, SchedGroupMemberData.ksParam_bmHourlySchedule,
859 '' if oMember is None else oMember.bmHourlySchedule, ));
860
861 self._add(u' </tr>\n');
862 return self._add(u' </tbody>\n'
863 u'</table>\n');
864
865 def addListOfSchedGroupBoxes(self, sName, aoSchedGroupBoxes, # pylint: disable=too-many-locals
866 aoAllRelevantTestBoxes, sLabel, idSchedGroup, fReadOnly = True,
867 fUseTable = False): # (str, list[TestBoxDataEx], list[TestBoxDataEx], str, bool, bool) -> str
868 """
869 For WuiAdminSchedGroup.
870 """
871 if fReadOnly is None or self._fReadOnly:
872 fReadOnly = self._fReadOnly;
873 assert len(aoSchedGroupBoxes) <= len(aoAllRelevantTestBoxes);
874 self._addLabel(sName, sLabel);
875 if not aoAllRelevantTestBoxes:
876 return self._add(u'<li>No test boxes.</li>\n')
877
878 self._add(u'<input name="%s" type="hidden" value="%s">\n'
879 % ( SchedGroupDataEx.ksParam_aidTestBoxes,
880 ','.join([unicode(oTestBox.idTestBox) for oTestBox in aoAllRelevantTestBoxes]), ));
881
882 sCheckBoxAttr = u' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
883 oDefMember = TestBoxDataForSchedGroup();
884 aoSchedGroupBoxes = list(aoSchedGroupBoxes); # Copy it so we can pop.
885
886 from testmanager.webui.wuiadmin import WuiAdmin;
887 from testmanager.webui.wuicontentbase import WuiAdminLink;
888 from testmanager.webui.wuiadmintestbox import WuiTestBoxDetailsLink;
889
890 if not fUseTable:
891 #
892 # Non-table version (see also addListOfOsArches).
893 #
894 self._add(' <div class="tmform-checkboxes-container">\n');
895
896 for iTestBox, oTestBox in enumerate(aoAllRelevantTestBoxes):
897 # Is it a member?
898 oMember = None;
899 for i, _ in enumerate(aoSchedGroupBoxes):
900 if aoSchedGroupBoxes[i].oTestBox and aoSchedGroupBoxes[i].oTestBox.idTestBox == oTestBox.idTestBox:
901 oMember = aoSchedGroupBoxes.pop(i);
902 break;
903
904 # Start on the rows...
905 sPrf = u'%s[%d]' % (sName, oTestBox.idTestBox,);
906 self._add(u' <div class="tmform-checkbox-holder">\n'
907 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
908 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
909 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
910 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
911 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
912 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
913 % ( #'tmodd' if iTestBox & 1 else 'tmeven',
914 sPrf, TestBoxDataForSchedGroup.ksParam_idTestBox, oTestBox.idTestBox,
915 sPrf, TestBoxDataForSchedGroup.ksParam_idSchedGroup, idSchedGroup,
916 sPrf, TestBoxDataForSchedGroup.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
917 sPrf, TestBoxDataForSchedGroup.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
918 sPrf, TestBoxDataForSchedGroup.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
919 SchedGroupDataEx.ksParam_aoTestBoxes, '' if oMember is None else ' checked', sCheckBoxAttr,
920 oTestBox.idTestBox, oTestBox.idTestBox, escapeElem(oTestBox.sName),
921 ));
922
923 self._add(u' <span class="tmform-priority tmform-testbox-priority">'
924 u'<input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s title="%s"></span>\n'
925 % ( sPrf, TestBoxDataForSchedGroup.ksParam_iSchedPriority,
926 (oMember if oMember is not None else oDefMember).iSchedPriority,
927 ' readonly class="tmform-input-readonly"' if fReadOnly else '',
928 escapeAttr("Priority [0..31]. Higher value means run more often.") ));
929
930 self._add(u' <span class="tmform-testbox-name">%s</span>\n'
931 % ( WuiTestBoxDetailsLink(oTestBox, sName = '%s (%s)' % (oTestBox.sName, oTestBox.sOs,)),));
932 self._add(u' </div>\n');
933 return self._add(u' </div></div></div>\n'
934 u' </li>\n');
935
936 #
937 # Table version.
938 #
939 self._add(u'<table class="tmformtbl">\n'
940 u' <thead>\n'
941 u' <tr>\n'
942 u' <th></th>\n'
943 u' <th>Test Box</th>\n'
944 u' <th>Priority [0..31]</th>\n'
945 u' </tr>\n'
946 u' </thead>\n'
947 u' <tbody>\n'
948 );
949
950 for iTestBox, oTestBox in enumerate(aoAllRelevantTestBoxes):
951 # Is it a member?
952 oMember = None;
953 for i, _ in enumerate(aoSchedGroupBoxes):
954 if aoSchedGroupBoxes[i].oTestBox and aoSchedGroupBoxes[i].oTestBox.idTestBox == oTestBox.idTestBox:
955 oMember = aoSchedGroupBoxes.pop(i);
956 break;
957
958 # Start on the rows...
959 sPrefix = u'%s[%d]' % (sName, oTestBox.idTestBox,);
960 self._add(u' <tr class="%s">\n'
961 u' <td>\n'
962 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
963 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
964 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
965 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
966 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
967 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
968 u' </td>\n'
969 % ( 'tmodd' if iTestBox & 1 else 'tmeven',
970 sPrefix, TestBoxDataForSchedGroup.ksParam_idTestBox, oTestBox.idTestBox,
971 sPrefix, TestBoxDataForSchedGroup.ksParam_idSchedGroup, idSchedGroup,
972 sPrefix, TestBoxDataForSchedGroup.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
973 sPrefix, TestBoxDataForSchedGroup.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
974 sPrefix, TestBoxDataForSchedGroup.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
975 SchedGroupDataEx.ksParam_aoTestBoxes, '' if oMember is None else ' checked', sCheckBoxAttr,
976 oTestBox.idTestBox, oTestBox.idTestBox, escapeElem(oTestBox.sName),
977 ));
978 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oTestBox.sName), ));
979
980 self._add(u' <td align="center">\n'
981 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
982 u' </td>\n'
983 % ( sPrefix,
984 TestBoxDataForSchedGroup.ksParam_iSchedPriority,
985 (oMember if oMember is not None else oDefMember).iSchedPriority,
986 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
987
988 self._add(u' </tr>\n');
989 return self._add(u' </tbody>\n'
990 u'</table>\n');
991
992 def addListOfSchedGroupsForTestBox(self, sName, aoInSchedGroups, aoAllSchedGroups, sLabel, # pylint: disable=too-many-locals
993 idTestBox, fReadOnly = None):
994 # type: (str, TestBoxInSchedGroupDataEx, SchedGroupData, str, bool) -> str
995 """
996 For WuiTestGroup.
997 """
998 from testmanager.core.testbox import TestBoxInSchedGroupData, TestBoxDataEx;
999
1000 if fReadOnly is None or self._fReadOnly:
1001 fReadOnly = self._fReadOnly;
1002 assert len(aoInSchedGroups) <= len(aoAllSchedGroups);
1003
1004 # Only show selected groups in read-only mode.
1005 if fReadOnly:
1006 aoAllSchedGroups = [oCur.oSchedGroup for oCur in aoInSchedGroups]
1007
1008 self._addLabel(sName, sLabel);
1009 if not aoAllSchedGroups:
1010 return self._add('<li>No scheduling groups.</li>\n')
1011
1012 # Add special parameter with all the scheduling group IDs in the form.
1013 self._add(u'<input name="%s" type="hidden" value="%s">\n'
1014 % ( TestBoxDataEx.ksParam_aidSchedGroups,
1015 ','.join([unicode(oSchedGroup.idSchedGroup) for oSchedGroup in aoAllSchedGroups]), ));
1016
1017 # Table header.
1018 self._add(u'<table class="tmformtbl">\n'
1019 u' <thead>\n'
1020 u' <tr>\n'
1021 u' <th rowspan="2"></th>\n'
1022 u' <th rowspan="2">Schedulding Group</th>\n'
1023 u' <th rowspan="2">Priority [0..31]</th>\n'
1024 u' </tr>\n'
1025 u' </thead>\n'
1026 u' <tbody>\n'
1027 );
1028
1029 # Table body.
1030 if self._fReadOnly:
1031 fReadOnly = True;
1032 sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
1033
1034 oDefMember = TestBoxInSchedGroupData();
1035 aoInSchedGroups = list(aoInSchedGroups); # Copy it so we can pop.
1036 for iSchedGroup, oSchedGroup in enumerate(aoAllSchedGroups):
1037
1038 # Is it a member?
1039 oMember = None;
1040 for i, _ in enumerate(aoInSchedGroups):
1041 if aoInSchedGroups[i].idSchedGroup == oSchedGroup.idSchedGroup:
1042 oMember = aoInSchedGroups.pop(i);
1043 break;
1044
1045 # Start on the rows...
1046 sPrefix = u'%s[%d]' % (sName, oSchedGroup.idSchedGroup,);
1047 self._add(u' <tr class="%s">\n'
1048 u' <td>\n'
1049 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
1050 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
1051 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
1052 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
1053 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
1054 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
1055 u' </td>\n'
1056 % ( 'tmodd' if iSchedGroup & 1 else 'tmeven',
1057 sPrefix, TestBoxInSchedGroupData.ksParam_idSchedGroup, oSchedGroup.idSchedGroup,
1058 sPrefix, TestBoxInSchedGroupData.ksParam_idTestBox, idTestBox,
1059 sPrefix, TestBoxInSchedGroupData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
1060 sPrefix, TestBoxInSchedGroupData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
1061 sPrefix, TestBoxInSchedGroupData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
1062 TestBoxDataEx.ksParam_aoInSchedGroups, '' if oMember is None else ' checked', sCheckBoxAttr,
1063 oSchedGroup.idSchedGroup, oSchedGroup.idSchedGroup, escapeElem(oSchedGroup.sName),
1064 ));
1065 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oSchedGroup.sName), ));
1066
1067 self._add(u' <td align="center">\n'
1068 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
1069 u' </td>\n'
1070 % ( sPrefix, TestBoxInSchedGroupData.ksParam_iSchedPriority,
1071 (oMember if oMember is not None else oDefMember).iSchedPriority,
1072 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
1073 self._add(u' </tr>\n');
1074
1075 return self._add(u' </tbody>\n'
1076 u'</table>\n');
1077
1078
1079 #
1080 # Buttons.
1081 #
1082 def addSubmit(self, sLabel = 'Submit'):
1083 """Adds the submit button to the form."""
1084 if self._fReadOnly:
1085 return True;
1086 return self._add(u' <li>\n'
1087 u' <br>\n'
1088 u' <div class="tmform-field"><div class="tmform-field-submit">\n'
1089 u' <label>&nbsp;</label>\n'
1090 u' <input type="submit" value="%s">\n'
1091 u' </div></div>\n'
1092 u' </li>\n'
1093 % (escapeElem(sLabel),));
1094
1095 def addReset(self):
1096 """Adds a reset button to the form."""
1097 if self._fReadOnly:
1098 return True;
1099 return self._add(u' <li>\n'
1100 u' <div class="tmform-button"><div class="tmform-button-reset">\n'
1101 u' <input type="reset" value="%s">\n'
1102 u' </div></div>\n'
1103 u' </li>\n');
1104
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette