VirtualBox

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

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

TestManager/webui: Shade the testbox/schedgroup listing [arg].

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 58.7 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuihlpform.py 83411 2020-03-25 13:55:17Z 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: 83411 $"
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.wuiadmintestbox import WuiTestBoxDetailsLink;
887
888 if not fUseTable:
889 #
890 # Non-table version (see also addListOfOsArches).
891 #
892 self._add(' <div class="tmform-checkboxes-container">\n');
893
894 for iTestBox, oTestBox in enumerate(aoAllRelevantTestBoxes):
895 # Is it a member?
896 oMember = None;
897 for i, _ in enumerate(aoSchedGroupBoxes):
898 if aoSchedGroupBoxes[i].oTestBox and aoSchedGroupBoxes[i].oTestBox.idTestBox == oTestBox.idTestBox:
899 oMember = aoSchedGroupBoxes.pop(i);
900 break;
901
902 # Start on the rows...
903 sPrf = u'%s[%d]' % (sName, oTestBox.idTestBox,);
904 self._add(u' <div class="tmform-checkbox-holder tmshade%u">\n'
905 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
906 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
907 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
908 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
909 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
910 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
911 % ( iTestBox & 7,
912 sPrf, TestBoxDataForSchedGroup.ksParam_idTestBox, oTestBox.idTestBox,
913 sPrf, TestBoxDataForSchedGroup.ksParam_idSchedGroup, idSchedGroup,
914 sPrf, TestBoxDataForSchedGroup.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
915 sPrf, TestBoxDataForSchedGroup.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
916 sPrf, TestBoxDataForSchedGroup.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
917 SchedGroupDataEx.ksParam_aoTestBoxes, '' if oMember is None else ' checked', sCheckBoxAttr,
918 oTestBox.idTestBox, oTestBox.idTestBox, escapeElem(oTestBox.sName),
919 ));
920
921 self._add(u' <span class="tmform-priority tmform-testbox-priority">'
922 u'<input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s title="%s"></span>\n'
923 % ( sPrf, TestBoxDataForSchedGroup.ksParam_iSchedPriority,
924 (oMember if oMember is not None else oDefMember).iSchedPriority,
925 ' readonly class="tmform-input-readonly"' if fReadOnly else '',
926 escapeAttr("Priority [0..31]. Higher value means run more often.") ));
927
928 self._add(u' <span class="tmform-testbox-name">%s</span>\n'
929 % ( WuiTestBoxDetailsLink(oTestBox, sName = '%s (%s)' % (oTestBox.sName, oTestBox.sOs,)),));
930 self._add(u' </div>\n');
931 return self._add(u' </div></div></div>\n'
932 u' </li>\n');
933
934 #
935 # Table version.
936 #
937 self._add(u'<table class="tmformtbl">\n'
938 u' <thead>\n'
939 u' <tr>\n'
940 u' <th></th>\n'
941 u' <th>Test Box</th>\n'
942 u' <th>Priority [0..31]</th>\n'
943 u' </tr>\n'
944 u' </thead>\n'
945 u' <tbody>\n'
946 );
947
948 for iTestBox, oTestBox in enumerate(aoAllRelevantTestBoxes):
949 # Is it a member?
950 oMember = None;
951 for i, _ in enumerate(aoSchedGroupBoxes):
952 if aoSchedGroupBoxes[i].oTestBox and aoSchedGroupBoxes[i].oTestBox.idTestBox == oTestBox.idTestBox:
953 oMember = aoSchedGroupBoxes.pop(i);
954 break;
955
956 # Start on the rows...
957 sPrefix = u'%s[%d]' % (sName, oTestBox.idTestBox,);
958 self._add(u' <tr class="%s">\n'
959 u' <td>\n'
960 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
961 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
962 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
963 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
964 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
965 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
966 u' </td>\n'
967 % ( 'tmodd' if iTestBox & 1 else 'tmeven',
968 sPrefix, TestBoxDataForSchedGroup.ksParam_idTestBox, oTestBox.idTestBox,
969 sPrefix, TestBoxDataForSchedGroup.ksParam_idSchedGroup, idSchedGroup,
970 sPrefix, TestBoxDataForSchedGroup.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
971 sPrefix, TestBoxDataForSchedGroup.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
972 sPrefix, TestBoxDataForSchedGroup.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
973 SchedGroupDataEx.ksParam_aoTestBoxes, '' if oMember is None else ' checked', sCheckBoxAttr,
974 oTestBox.idTestBox, oTestBox.idTestBox, escapeElem(oTestBox.sName),
975 ));
976 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oTestBox.sName), ));
977
978 self._add(u' <td align="center">\n'
979 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
980 u' </td>\n'
981 % ( sPrefix,
982 TestBoxDataForSchedGroup.ksParam_iSchedPriority,
983 (oMember if oMember is not None else oDefMember).iSchedPriority,
984 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
985
986 self._add(u' </tr>\n');
987 return self._add(u' </tbody>\n'
988 u'</table>\n');
989
990 def addListOfSchedGroupsForTestBox(self, sName, aoInSchedGroups, aoAllSchedGroups, sLabel, # pylint: disable=too-many-locals
991 idTestBox, fReadOnly = None):
992 # type: (str, TestBoxInSchedGroupDataEx, SchedGroupData, str, bool) -> str
993 """
994 For WuiTestGroup.
995 """
996 from testmanager.core.testbox import TestBoxInSchedGroupData, TestBoxDataEx;
997
998 if fReadOnly is None or self._fReadOnly:
999 fReadOnly = self._fReadOnly;
1000 assert len(aoInSchedGroups) <= len(aoAllSchedGroups);
1001
1002 # Only show selected groups in read-only mode.
1003 if fReadOnly:
1004 aoAllSchedGroups = [oCur.oSchedGroup for oCur in aoInSchedGroups]
1005
1006 self._addLabel(sName, sLabel);
1007 if not aoAllSchedGroups:
1008 return self._add('<li>No scheduling groups.</li>\n')
1009
1010 # Add special parameter with all the scheduling group IDs in the form.
1011 self._add(u'<input name="%s" type="hidden" value="%s">\n'
1012 % ( TestBoxDataEx.ksParam_aidSchedGroups,
1013 ','.join([unicode(oSchedGroup.idSchedGroup) for oSchedGroup in aoAllSchedGroups]), ));
1014
1015 # Table header.
1016 self._add(u'<table class="tmformtbl">\n'
1017 u' <thead>\n'
1018 u' <tr>\n'
1019 u' <th rowspan="2"></th>\n'
1020 u' <th rowspan="2">Schedulding Group</th>\n'
1021 u' <th rowspan="2">Priority [0..31]</th>\n'
1022 u' </tr>\n'
1023 u' </thead>\n'
1024 u' <tbody>\n'
1025 );
1026
1027 # Table body.
1028 if self._fReadOnly:
1029 fReadOnly = True;
1030 sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
1031
1032 oDefMember = TestBoxInSchedGroupData();
1033 aoInSchedGroups = list(aoInSchedGroups); # Copy it so we can pop.
1034 for iSchedGroup, oSchedGroup in enumerate(aoAllSchedGroups):
1035
1036 # Is it a member?
1037 oMember = None;
1038 for i, _ in enumerate(aoInSchedGroups):
1039 if aoInSchedGroups[i].idSchedGroup == oSchedGroup.idSchedGroup:
1040 oMember = aoInSchedGroups.pop(i);
1041 break;
1042
1043 # Start on the rows...
1044 sPrefix = u'%s[%d]' % (sName, oSchedGroup.idSchedGroup,);
1045 self._add(u' <tr class="%s">\n'
1046 u' <td>\n'
1047 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
1048 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
1049 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
1050 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
1051 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
1052 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
1053 u' </td>\n'
1054 % ( 'tmodd' if iSchedGroup & 1 else 'tmeven',
1055 sPrefix, TestBoxInSchedGroupData.ksParam_idSchedGroup, oSchedGroup.idSchedGroup,
1056 sPrefix, TestBoxInSchedGroupData.ksParam_idTestBox, idTestBox,
1057 sPrefix, TestBoxInSchedGroupData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
1058 sPrefix, TestBoxInSchedGroupData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
1059 sPrefix, TestBoxInSchedGroupData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
1060 TestBoxDataEx.ksParam_aoInSchedGroups, '' if oMember is None else ' checked', sCheckBoxAttr,
1061 oSchedGroup.idSchedGroup, oSchedGroup.idSchedGroup, escapeElem(oSchedGroup.sName),
1062 ));
1063 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oSchedGroup.sName), ));
1064
1065 self._add(u' <td align="center">\n'
1066 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
1067 u' </td>\n'
1068 % ( sPrefix, TestBoxInSchedGroupData.ksParam_iSchedPriority,
1069 (oMember if oMember is not None else oDefMember).iSchedPriority,
1070 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
1071 self._add(u' </tr>\n');
1072
1073 return self._add(u' </tbody>\n'
1074 u'</table>\n');
1075
1076
1077 #
1078 # Buttons.
1079 #
1080 def addSubmit(self, sLabel = 'Submit'):
1081 """Adds the submit button to the form."""
1082 if self._fReadOnly:
1083 return True;
1084 return self._add(u' <li>\n'
1085 u' <br>\n'
1086 u' <div class="tmform-field"><div class="tmform-field-submit">\n'
1087 u' <label>&nbsp;</label>\n'
1088 u' <input type="submit" value="%s">\n'
1089 u' </div></div>\n'
1090 u' </li>\n'
1091 % (escapeElem(sLabel),));
1092
1093 def addReset(self):
1094 """Adds a reset button to the form."""
1095 if self._fReadOnly:
1096 return True;
1097 return self._add(u' <li>\n'
1098 u' <div class="tmform-button"><div class="tmform-button-reset">\n'
1099 u' <input type="reset" value="%s">\n'
1100 u' </div></div>\n'
1101 u' </li>\n');
1102
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