VirtualBox

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

Last change on this file since 98655 was 98655, checked in by vboxsync, 2 years ago

ValKit: Pylint 2.16.2 adjustments.

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