VirtualBox

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

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

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 58.9 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: wuihlpform.py 96407 2022-08-22 17:43:14Z vboxsync $
3
4"""
5Test Manager Web-UI - Form Helpers.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2022 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: 96407 $"
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 dict();
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, _ in enumerate(aoAllTestCases):
699 oTestCase = aoAllTestCases[iTestCase];
700
701 # Is it a member?
702 oMember = None;
703 for i, _ in enumerate(aoTestGroupMembers):
704 if aoTestGroupMembers[i].oTestCase.idTestCase == oTestCase.idTestCase:
705 oMember = aoTestGroupMembers.pop(i);
706 break;
707
708 # Start on the rows...
709 sPrefix = u'%s[%d]' % (sName, oTestCase.idTestCase,);
710 self._add(u' <tr class="%s">\n'
711 u' <td rowspan="%d">\n'
712 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestCase
713 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestGroup
714 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
715 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
716 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
717 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
718 u' </td>\n'
719 % ( 'tmodd' if iTestCase & 1 else 'tmeven',
720 len(oTestCase.aoTestCaseArgs),
721 sPrefix, TestGroupMemberData.ksParam_idTestCase, oTestCase.idTestCase,
722 sPrefix, TestGroupMemberData.ksParam_idTestGroup, -1 if oMember is None else oMember.idTestGroup,
723 sPrefix, TestGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
724 sPrefix, TestGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
725 sPrefix, TestGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
726 TestGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr,
727 oTestCase.idTestCase, oTestCase.idTestCase, escapeElem(oTestCase.sName),
728 ));
729 self._add(u' <td rowspan="%d" align="left">%s</td>\n'
730 % ( len(oTestCase.aoTestCaseArgs), escapeElem(oTestCase.sName), ));
731
732 self._add(u' <td rowspan="%d" title="Include all variations (checked) or choose a set?">\n'
733 u' <input name="%s[%s]" type="checkbox"%s%s value="-1">\n'
734 u' </td>\n'
735 % ( len(oTestCase.aoTestCaseArgs),
736 sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs,
737 ' checked' if oMember is None or oMember.aidTestCaseArgs is None else '', sCheckBoxAttr, ));
738
739 self._add(u' <td rowspan="%d" align="center">\n'
740 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
741 u' </td>\n'
742 % ( len(oTestCase.aoTestCaseArgs),
743 sPrefix, TestGroupMemberData.ksParam_iSchedPriority,
744 (oMember if oMember is not None else oDefMember).iSchedPriority,
745 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
746
747 # Argument variations.
748 aidTestCaseArgs = [] if oMember is None or oMember.aidTestCaseArgs is None else oMember.aidTestCaseArgs;
749 for iVar, oVar in enumerate(oTestCase.aoTestCaseArgs):
750 if iVar > 0:
751 self._add(' <tr class="%s">\n' % ('tmodd' if iTestCase & 1 else 'tmeven',));
752 self._add(u' <td align="center">\n'
753 u' <input name="%s[%s]" type="checkbox"%s%s value="%d">'
754 u' </td>\n'
755 % ( sPrefix, TestGroupMemberData.ksParam_aidTestCaseArgs,
756 ' checked' if oVar.idTestCaseArgs in aidTestCaseArgs else '', sCheckBoxAttr, oVar.idTestCaseArgs,
757 ));
758 self._add(u' <td align="center">%s</td>\n'
759 u' <td align="center">%s</td>\n'
760 u' <td align="left">%s</td>\n'
761 % ( oVar.cGangMembers,
762 'Default' if oVar.cSecTimeout is None else oVar.cSecTimeout,
763 escapeElem(oVar.sArgs) ));
764
765 self._add(u' </tr>\n');
766
767
768
769 if not oTestCase.aoTestCaseArgs:
770 self._add(u' <td></td> <td></td> <td></td> <td></td>\n'
771 u' </tr>\n');
772 return self._add(u' </tbody>\n'
773 u'</table>\n');
774
775 def addListOfSchedGroupMembers(self, sName, aoSchedGroupMembers, aoAllRelevantTestGroups, # pylint: disable=too-many-locals
776 sLabel, idSchedGroup, fReadOnly = True):
777 """
778 For WuiAdminSchedGroup.
779 """
780 if fReadOnly is None or self._fReadOnly:
781 fReadOnly = self._fReadOnly;
782 assert len(aoSchedGroupMembers) <= len(aoAllRelevantTestGroups);
783 self._addLabel(sName, sLabel);
784 if not aoAllRelevantTestGroups:
785 return self._add(u'<li>No test groups.</li>\n')
786
787 self._add(u'<input name="%s" type="hidden" value="%s">\n'
788 % ( SchedGroupDataEx.ksParam_aidTestGroups,
789 ','.join([unicode(oTestGroup.idTestGroup) for oTestGroup in aoAllRelevantTestGroups]), ));
790
791 self._add(u'<table class="tmformtbl tmformtblschedgroupmembers">\n'
792 u' <thead>\n'
793 u' <tr>\n'
794 u' <th></th>\n'
795 u' <th>Test Group</th>\n'
796 u' <th>Priority [0..31]</th>\n'
797 u' <th>Prerequisite Test Group</th>\n'
798 u' <th>Weekly schedule</th>\n'
799 u' </tr>\n'
800 u' </thead>\n'
801 u' <tbody>\n'
802 );
803
804 sCheckBoxAttr = u' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
805 sComboBoxAttr = u' disabled' if fReadOnly else '';
806
807 oDefMember = SchedGroupMemberData();
808 aoSchedGroupMembers = list(aoSchedGroupMembers); # Copy it so we can pop.
809 for iTestGroup, _ in enumerate(aoAllRelevantTestGroups):
810 oTestGroup = aoAllRelevantTestGroups[iTestGroup];
811
812 # Is it a member?
813 oMember = None;
814 for i, _ in enumerate(aoSchedGroupMembers):
815 if aoSchedGroupMembers[i].oTestGroup.idTestGroup == oTestGroup.idTestGroup:
816 oMember = aoSchedGroupMembers.pop(i);
817 break;
818
819 # Start on the rows...
820 sPrefix = u'%s[%d]' % (sName, oTestGroup.idTestGroup,);
821 self._add(u' <tr class="%s">\n'
822 u' <td>\n'
823 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestGroup
824 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
825 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
826 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
827 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
828 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
829 u' </td>\n'
830 % ( 'tmodd' if iTestGroup & 1 else 'tmeven',
831 sPrefix, SchedGroupMemberData.ksParam_idTestGroup, oTestGroup.idTestGroup,
832 sPrefix, SchedGroupMemberData.ksParam_idSchedGroup, idSchedGroup,
833 sPrefix, SchedGroupMemberData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
834 sPrefix, SchedGroupMemberData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
835 sPrefix, SchedGroupMemberData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
836 SchedGroupDataEx.ksParam_aoMembers, '' if oMember is None else ' checked', sCheckBoxAttr,
837 oTestGroup.idTestGroup, oTestGroup.idTestGroup, escapeElem(oTestGroup.sName),
838 ));
839 self._add(u' <td>%s</td>\n' % ( escapeElem(oTestGroup.sName), ));
840
841 self._add(u' <td>\n'
842 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
843 u' </td>\n'
844 % ( sPrefix, SchedGroupMemberData.ksParam_iSchedPriority,
845 (oMember if oMember is not None else oDefMember).iSchedPriority,
846 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
847
848 self._add(u' <td>\n'
849 u' <select name="%s[%s]" id="%s[%s]" class="tmform-combobox"%s>\n'
850 u' <option value="-1"%s>None</option>\n'
851 % ( sPrefix, SchedGroupMemberData.ksParam_idTestGroupPreReq,
852 sPrefix, SchedGroupMemberData.ksParam_idTestGroupPreReq,
853 sComboBoxAttr,
854 ' selected' if oMember is None or oMember.idTestGroupPreReq is None else '',
855 ));
856 for oTestGroup2 in aoAllRelevantTestGroups:
857 if oTestGroup2 != oTestGroup:
858 fSelected = oMember is not None and oTestGroup2.idTestGroup == oMember.idTestGroupPreReq;
859 self._add(' <option value="%s"%s>%s</option>\n'
860 % ( oTestGroup2.idTestGroup, ' selected' if fSelected else '', escapeElem(oTestGroup2.sName), ));
861 self._add(u' </select>\n'
862 u' </td>\n');
863
864 self._add(u' <td>\n'
865 u' Todo<input name="%s[%s]" type="hidden" value="%s">\n'
866 u' </td>\n'
867 % ( sPrefix, SchedGroupMemberData.ksParam_bmHourlySchedule,
868 '' if oMember is None else oMember.bmHourlySchedule, ));
869
870 self._add(u' </tr>\n');
871 return self._add(u' </tbody>\n'
872 u'</table>\n');
873
874 def addListOfSchedGroupBoxes(self, sName, aoSchedGroupBoxes, # pylint: disable=too-many-locals
875 aoAllRelevantTestBoxes, sLabel, idSchedGroup, fReadOnly = True,
876 fUseTable = False): # (str, list[TestBoxDataEx], list[TestBoxDataEx], str, bool, bool) -> str
877 """
878 For WuiAdminSchedGroup.
879 """
880 if fReadOnly is None or self._fReadOnly:
881 fReadOnly = self._fReadOnly;
882 assert len(aoSchedGroupBoxes) <= len(aoAllRelevantTestBoxes);
883 self._addLabel(sName, sLabel);
884 if not aoAllRelevantTestBoxes:
885 return self._add(u'<li>No test boxes.</li>\n')
886
887 self._add(u'<input name="%s" type="hidden" value="%s">\n'
888 % ( SchedGroupDataEx.ksParam_aidTestBoxes,
889 ','.join([unicode(oTestBox.idTestBox) for oTestBox in aoAllRelevantTestBoxes]), ));
890
891 sCheckBoxAttr = u' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
892 oDefMember = TestBoxDataForSchedGroup();
893 aoSchedGroupBoxes = list(aoSchedGroupBoxes); # Copy it so we can pop.
894
895 from testmanager.webui.wuiadmintestbox import WuiTestBoxDetailsLink;
896
897 if not fUseTable:
898 #
899 # Non-table version (see also addListOfOsArches).
900 #
901 self._add(' <div class="tmform-checkboxes-container">\n');
902
903 for iTestBox, oTestBox in enumerate(aoAllRelevantTestBoxes):
904 # Is it a member?
905 oMember = None;
906 for i, _ in enumerate(aoSchedGroupBoxes):
907 if aoSchedGroupBoxes[i].oTestBox and aoSchedGroupBoxes[i].oTestBox.idTestBox == oTestBox.idTestBox:
908 oMember = aoSchedGroupBoxes.pop(i);
909 break;
910
911 # Start on the rows...
912 sPrf = u'%s[%d]' % (sName, oTestBox.idTestBox,);
913 self._add(u' <div class="tmform-checkbox-holder tmshade%u">\n'
914 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
915 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
916 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
917 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
918 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
919 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
920 % ( iTestBox & 7,
921 sPrf, TestBoxDataForSchedGroup.ksParam_idTestBox, oTestBox.idTestBox,
922 sPrf, TestBoxDataForSchedGroup.ksParam_idSchedGroup, idSchedGroup,
923 sPrf, TestBoxDataForSchedGroup.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
924 sPrf, TestBoxDataForSchedGroup.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
925 sPrf, TestBoxDataForSchedGroup.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
926 SchedGroupDataEx.ksParam_aoTestBoxes, '' if oMember is None else ' checked', sCheckBoxAttr,
927 oTestBox.idTestBox, oTestBox.idTestBox, escapeElem(oTestBox.sName),
928 ));
929
930 self._add(u' <span class="tmform-priority tmform-testbox-priority">'
931 u'<input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s title="%s"></span>\n'
932 % ( sPrf, TestBoxDataForSchedGroup.ksParam_iSchedPriority,
933 (oMember if oMember is not None else oDefMember).iSchedPriority,
934 ' readonly class="tmform-input-readonly"' if fReadOnly else '',
935 escapeAttr("Priority [0..31]. Higher value means run more often.") ));
936
937 self._add(u' <span class="tmform-testbox-name">%s</span>\n'
938 % ( WuiTestBoxDetailsLink(oTestBox, sName = '%s (%s)' % (oTestBox.sName, oTestBox.sOs,)),));
939 self._add(u' </div>\n');
940 return self._add(u' </div></div></div>\n'
941 u' </li>\n');
942
943 #
944 # Table version.
945 #
946 self._add(u'<table class="tmformtbl">\n'
947 u' <thead>\n'
948 u' <tr>\n'
949 u' <th></th>\n'
950 u' <th>Test Box</th>\n'
951 u' <th>Priority [0..31]</th>\n'
952 u' </tr>\n'
953 u' </thead>\n'
954 u' <tbody>\n'
955 );
956
957 for iTestBox, oTestBox in enumerate(aoAllRelevantTestBoxes):
958 # Is it a member?
959 oMember = None;
960 for i, _ in enumerate(aoSchedGroupBoxes):
961 if aoSchedGroupBoxes[i].oTestBox and aoSchedGroupBoxes[i].oTestBox.idTestBox == oTestBox.idTestBox:
962 oMember = aoSchedGroupBoxes.pop(i);
963 break;
964
965 # Start on the rows...
966 sPrefix = u'%s[%d]' % (sName, oTestBox.idTestBox,);
967 self._add(u' <tr class="%s">\n'
968 u' <td>\n'
969 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
970 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
971 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
972 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
973 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
974 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
975 u' </td>\n'
976 % ( 'tmodd' if iTestBox & 1 else 'tmeven',
977 sPrefix, TestBoxDataForSchedGroup.ksParam_idTestBox, oTestBox.idTestBox,
978 sPrefix, TestBoxDataForSchedGroup.ksParam_idSchedGroup, idSchedGroup,
979 sPrefix, TestBoxDataForSchedGroup.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
980 sPrefix, TestBoxDataForSchedGroup.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
981 sPrefix, TestBoxDataForSchedGroup.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
982 SchedGroupDataEx.ksParam_aoTestBoxes, '' if oMember is None else ' checked', sCheckBoxAttr,
983 oTestBox.idTestBox, oTestBox.idTestBox, escapeElem(oTestBox.sName),
984 ));
985 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oTestBox.sName), ));
986
987 self._add(u' <td align="center">\n'
988 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
989 u' </td>\n'
990 % ( sPrefix,
991 TestBoxDataForSchedGroup.ksParam_iSchedPriority,
992 (oMember if oMember is not None else oDefMember).iSchedPriority,
993 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
994
995 self._add(u' </tr>\n');
996 return self._add(u' </tbody>\n'
997 u'</table>\n');
998
999 def addListOfSchedGroupsForTestBox(self, sName, aoInSchedGroups, aoAllSchedGroups, sLabel, # pylint: disable=too-many-locals
1000 idTestBox, fReadOnly = None):
1001 # type: (str, TestBoxInSchedGroupDataEx, SchedGroupData, str, bool) -> str
1002 """
1003 For WuiTestGroup.
1004 """
1005 from testmanager.core.testbox import TestBoxInSchedGroupData, TestBoxDataEx;
1006
1007 if fReadOnly is None or self._fReadOnly:
1008 fReadOnly = self._fReadOnly;
1009 assert len(aoInSchedGroups) <= len(aoAllSchedGroups);
1010
1011 # Only show selected groups in read-only mode.
1012 if fReadOnly:
1013 aoAllSchedGroups = [oCur.oSchedGroup for oCur in aoInSchedGroups]
1014
1015 self._addLabel(sName, sLabel);
1016 if not aoAllSchedGroups:
1017 return self._add('<li>No scheduling groups.</li>\n')
1018
1019 # Add special parameter with all the scheduling group IDs in the form.
1020 self._add(u'<input name="%s" type="hidden" value="%s">\n'
1021 % ( TestBoxDataEx.ksParam_aidSchedGroups,
1022 ','.join([unicode(oSchedGroup.idSchedGroup) for oSchedGroup in aoAllSchedGroups]), ));
1023
1024 # Table header.
1025 self._add(u'<table class="tmformtbl">\n'
1026 u' <thead>\n'
1027 u' <tr>\n'
1028 u' <th rowspan="2"></th>\n'
1029 u' <th rowspan="2">Schedulding Group</th>\n'
1030 u' <th rowspan="2">Priority [0..31]</th>\n'
1031 u' </tr>\n'
1032 u' </thead>\n'
1033 u' <tbody>\n'
1034 );
1035
1036 # Table body.
1037 if self._fReadOnly:
1038 fReadOnly = True;
1039 sCheckBoxAttr = ' readonly onclick="return false" onkeydown="return false"' if fReadOnly else '';
1040
1041 oDefMember = TestBoxInSchedGroupData();
1042 aoInSchedGroups = list(aoInSchedGroups); # Copy it so we can pop.
1043 for iSchedGroup, oSchedGroup in enumerate(aoAllSchedGroups):
1044
1045 # Is it a member?
1046 oMember = None;
1047 for i, _ in enumerate(aoInSchedGroups):
1048 if aoInSchedGroups[i].idSchedGroup == oSchedGroup.idSchedGroup:
1049 oMember = aoInSchedGroups.pop(i);
1050 break;
1051
1052 # Start on the rows...
1053 sPrefix = u'%s[%d]' % (sName, oSchedGroup.idSchedGroup,);
1054 self._add(u' <tr class="%s">\n'
1055 u' <td>\n'
1056 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idSchedGroup
1057 u' <input name="%s[%s]" type="hidden" value="%s">\n' # idTestBox
1058 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsExpire
1059 u' <input name="%s[%s]" type="hidden" value="%s">\n' # tsEffective
1060 u' <input name="%s[%s]" type="hidden" value="%s">\n' # uidAuthor
1061 u' <input name="%s" type="checkbox"%s%s value="%d" class="tmform-checkbox" title="#%d - %s">\n' #(list)
1062 u' </td>\n'
1063 % ( 'tmodd' if iSchedGroup & 1 else 'tmeven',
1064 sPrefix, TestBoxInSchedGroupData.ksParam_idSchedGroup, oSchedGroup.idSchedGroup,
1065 sPrefix, TestBoxInSchedGroupData.ksParam_idTestBox, idTestBox,
1066 sPrefix, TestBoxInSchedGroupData.ksParam_tsExpire, '' if oMember is None else oMember.tsExpire,
1067 sPrefix, TestBoxInSchedGroupData.ksParam_tsEffective, '' if oMember is None else oMember.tsEffective,
1068 sPrefix, TestBoxInSchedGroupData.ksParam_uidAuthor, '' if oMember is None else oMember.uidAuthor,
1069 TestBoxDataEx.ksParam_aoInSchedGroups, '' if oMember is None else ' checked', sCheckBoxAttr,
1070 oSchedGroup.idSchedGroup, oSchedGroup.idSchedGroup, escapeElem(oSchedGroup.sName),
1071 ));
1072 self._add(u' <td align="left">%s</td>\n' % ( escapeElem(oSchedGroup.sName), ));
1073
1074 self._add(u' <td align="center">\n'
1075 u' <input name="%s[%s]" type="text" value="%s" style="max-width:3em;" %s>\n'
1076 u' </td>\n'
1077 % ( sPrefix, TestBoxInSchedGroupData.ksParam_iSchedPriority,
1078 (oMember if oMember is not None else oDefMember).iSchedPriority,
1079 ' readonly class="tmform-input-readonly"' if fReadOnly else '', ));
1080 self._add(u' </tr>\n');
1081
1082 return self._add(u' </tbody>\n'
1083 u'</table>\n');
1084
1085
1086 #
1087 # Buttons.
1088 #
1089 def addSubmit(self, sLabel = 'Submit'):
1090 """Adds the submit button to the form."""
1091 if self._fReadOnly:
1092 return True;
1093 return self._add(u' <li>\n'
1094 u' <br>\n'
1095 u' <div class="tmform-field"><div class="tmform-field-submit">\n'
1096 u' <label>&nbsp;</label>\n'
1097 u' <input type="submit" value="%s">\n'
1098 u' </div></div>\n'
1099 u' </li>\n'
1100 % (escapeElem(sLabel),));
1101
1102 def addReset(self):
1103 """Adds a reset button to the form."""
1104 if self._fReadOnly:
1105 return True;
1106 return self._add(u' <li>\n'
1107 u' <div class="tmform-button"><div class="tmform-button-reset">\n'
1108 u' <input type="reset" value="%s">\n'
1109 u' </div></div>\n'
1110 u' </li>\n');
1111
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