All of lore.kernel.org
 help / color / mirror / Atom feed
From: rmccabe@sourceware.org <rmccabe@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] conga/luci/homebase form-chooser form-macros i ...
Date: 20 Jun 2006 21:21:51 -0000	[thread overview]
Message-ID: <20060620212151.9499.qmail@sourceware.org> (raw)

CVSROOT:	/cvs/cluster
Module name:	conga
Changes by:	rmccabe at sourceware.org	2006-06-20 21:21:47

Modified files:
	luci/homebase  : form-chooser form-macros index_html 
	                 luci_homebase.css main_logo main_pathbar 
	                 main_personalbar main_sections portlet_homebase 
Added files:
	luci/homebase  : main_footer x.png 

Log message:
	

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/main_footer.diff?cvsroot=cluster&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/x.png.diff?cvsroot=cluster&r1=NONE&r2=1.1
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/form-chooser.diff?cvsroot=cluster&r1=1.7&r2=1.8
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/form-macros.diff?cvsroot=cluster&r1=1.21&r2=1.22
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/index_html.diff?cvsroot=cluster&r1=1.6&r2=1.7
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/luci_homebase.css.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/main_logo.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/main_pathbar.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/main_personalbar.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/main_sections.diff?cvsroot=cluster&r1=1.3&r2=1.4
http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/homebase/portlet_homebase.diff?cvsroot=cluster&r1=1.6&r2=1.7

/cvs/cluster/conga/luci/homebase/main_footer,v  -->  standard output
revision 1.1
--- conga/luci/homebase/main_footer
+++ -	2006-06-20 21:21:48.674641000 +0000
@@ -0,0 +1,31 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<body>
+<div id="portal-footer" metal:define-macro="portal_footer">
+
+<p>
+    <span i18n:translate="description_copyright" tal:omit-tag="">
+    The 
+    <span>
+        <a href="http://redhat.com">Conga&trade; Cluster and Storage Management System</a>
+    </span>
+    is Copyright
+    <acronym title="Copyright" i18n:name="copyright" i18n:attributes="title title_copyright;">&copy;</acronym>
+    2000-<span i18n:name="current_year" 
+               tal:define="now modules/DateTime/DateTime" 
+               tal:content="now/year" />
+    <a href="http://www.redhat.com/">Red Hat, Inc.</a>
+    </span>
+</p>
+
+<p>
+    <span i18n:translate="description_license">
+    Distributed under the 
+        <span i18n:name="license">
+            <a href="http://creativecommons.org/licenses/GPL/2.0/" i18n:translate="label_gnu_gpl_licence">GNU GPL license</a>
+        </span>.
+    </span>
+</p>
+
+</div>
+</body>
+</html>
/cvs/cluster/conga/luci/homebase/x.png,v  -->  standard output
revision 1.1
Binary files /cvs/cluster/conga/luci/homebase/x.png and - differ
--- conga/luci/homebase/form-chooser	2006/05/18 17:47:15	1.7
+++ conga/luci/homebase/form-chooser	2006/06/20 21:21:47	1.8
@@ -5,12 +5,13 @@
 </head>
 
 <tal:comment replace="nothing">
-	$Id: form-chooser,v 1.7 2006/05/18 17:47:15 rmccabe Exp $
+	$Id: form-chooser,v 1.8 2006/06/20 21:21:47 rmccabe Exp $
 </tal:comment>
 
 <body>
-  <metal:choose-form metal:define-macro="main-form">
-	<span tal:omit-tag="" tal:define="global ptype request/pagetype | request/form/pagetype |nothing"/>  
+
+<metal:choose-form metal:define-macro="main-form">
+	<span tal:omit-tag="" tal:define="global ptype request/pagetype | request/form/pagetype |nothing"/>
 
 	<span tal:omit-tag="" tal:condition="python: not ptype or ptype == '0'">
 		<div metal:use-macro="here/form-macros/macros/entry-form"/>
@@ -39,6 +40,7 @@
 	<span tal:omit-tag="" tal:condition="python: ptype == '6'">
 		<div metal:use-macro="here/form-macros/macros/cluster-add-form" />
 	</span>
-  </metal:choose-form>
+</metal:choose-form>
+
 </body>
 </html>
--- conga/luci/homebase/form-macros	2006/05/25 22:34:24	1.21
+++ conga/luci/homebase/form-macros	2006/06/20 21:21:47	1.22
@@ -1,7 +1,7 @@
 <html>
 
 <tal:comment replace="nothing">
-	$Id: form-macros,v 1.21 2006/05/25 22:34:24 rmccabe Exp $
+	$Id: form-macros,v 1.22 2006/06/20 21:21:47 rmccabe Exp $
 </tal:comment>
 
 <head>
@@ -11,24 +11,22 @@
 <body>
 
 <tal:comment replace="nothing">
+
+
 !###########################
 # ENTRY FORM               #
 ############################
-</tal:comment>
 
-	<div metal:define-macro="entry-form" tal:omit-tag="">
 
-		<div tal:condition="python:here.userAuthenticated()">
-			<h2 class="homebase">Luci Homebase</h2>
-			<p class="hbText">Welcome to Luci, <span tal:replace="string: ${user/getUserName}" />.</p>
-			<p class="hbText">Select an action from the list on the left.</p>
-		</div>
+</tal:comment>
 
-		<div tal:condition="python:not here.userAuthenticated()">
-			<p style="font-size:18px;font-weight:bold">Not Logged In</p>
-			<p class="hbText">Please <a tal:attributes="href python: here.getOrderedUserActions(keyed_actions=keyed_actions)[0]['url']">login</a> first.</p>
-		</div>
+<div metal:define-macro="entry-form" tal:omit-tag="">
+	<div>
+		<h2 class="homebase">Luci Homebase</h2>
+		<p class="hbText">Welcome to Luci, <span tal:replace="string: ${user/getUserName}" />.</p>
+		<p tal:condition="python:'children' in data and len(data['children']) > 0" tal:content="string: Select an action from the list on the left." />
 	</div>
+</div>
 
 <tal:comment replace="nothing">
 !###########################
@@ -36,52 +34,57 @@
 ############################
 </tal:comment>
 
-	<div metal:define-macro="user-del-form">
-		<tal:comment replace="nothing">
-			XXX: to validate:
-				- user was selected,
-				- selected index is valid
-		</tal:comment>
-
-		<script type="text/javascript">
-			function validateForm(form) {
-				var errors = new Array();
-
-				if (!form || !form.deluserId)
-					return (-1);
-
-				var userIdx = form.deluserId.selectedIndex;
-				if (userIdx <= 0 ||
-					!form.deluserId.options[userIdx] ||
-					!form.deluserId.options[userIdx].value)
-				{
-					errors.push('You have not selected a valid user.');
-					return (-1);
-				}
-
-				if (!errors.length) {
-					if (confirm('Do you really want to remove the user \"' +
-						form.deluserId.options[userIdx].value + '\"?'))
-					{
-						form.submit();
-					}
-				} else {
-					alert(errors);
-					return (-1);
-				}
+<div metal:define-macro="user-del-form">
+	<tal:comment replace="nothing">
+		: to validate:
+			- user was selected,
+			- selected index is valid
+	</tal:comment>
+
+	<script type="text/javascript">
+		function validateForm(form) {
+			var errors = new Array();
+
+			if (!form || !form.deluserId)
+				return (-1);
 
-				return (0);
+			var userIdx = form.deluserId.selectedIndex;
+			if (userIdx <= 0 ||
+				!form.deluserId.options[userIdx] ||
+				!form.deluserId.options[userIdx].value)
+			{
+				errors.push('You have not selected a valid user.');
+				return (-1);
 			}
-		</script>
 
-	<form name="adminform" method="post" action="">
-		<h2 class="homebase">Delete a User</h2>
+			if (error_dialog(errors))
+				return (-1);
+
+			if (confirm('Do you really want to remove the user \"' +
+				form.deluserId.options[userIdx].value + '\"?'))
+			{
+				form.submit();
+			}
+
+			return (0);
+		}
+	</script>
+
+	<span tal:omit-tag=""
+		tal:define="global userList python:here.portal_membership.listMembers();
+					global blankForm python:1" />
+
+	<form name="adminform" method="post" action=""
+		tal:condition="python: userList and len(userList) > 0">
+
+		<h2 class="homebase" tal:define="global blankForm python:0">
+			Delete a User
+		</h2>
 
-		<span tal:omit-tag="" tal:define="global userList python:here.portal_membership.listMembers()" />
 
 		<select tal:condition="python:userList" name="deluserId" class="homebase">
 			<option class="homebase" value="" selected="1">Select a User</option>
-			<tal:block tal:repeat="user python:here.portal_membership.listMembers()">
+			<tal:block tal:repeat="user python:userList">
 				<option class="homebase"
 					tal:content="python:user"
 					tal:attributes="value python:user"
@@ -95,81 +98,68 @@
 		<input name="absoluteURL" type="hidden"
 			tal:attributes="value python:data['children'][data['curIndex']]['absolute_url']" />
 
-		<div class="hbSubmit" tal:condition="python:userList" style="padding-top:1em">
+		<div class="hbSubmit" tal:condition="python:userList" id="hbSubmit">
 			<input class="hbSubmit" name="Submit" type="button" value="Submit" onClick="validateForm(document.adminform);" />
 		</div>
+	</form>
 
-		<span tal:condition="python:not userList">
-			No users have been added.
-		</span>
-
-		</form>
+	<div tal:condition="python:blankForm">
+		No users have been added.
 	</div>
+</div>
+
 
 <tal:comment replace="nothing">
+
+
 !###########################
 # USER ADD FORM            #
 ############################
+
+
 </tal:comment>
 
-	<div metal:define-macro="user-add-form">
-		<tal:comment replace="nothing">
-			Things to validate:
-			 - user/passwd exist and are not blank
-			 - user doesn't contain invalid characters.
-			 - passwords match
-		</tal:comment>
-
-		<script type="text/javascript">
-			function validateForm(form) {
-				var errors = new Array()
-
-				if (!form)
-					return (-1);
-
-				if (!form.newUserName || !form.newUserName.value)
-					errors.push('You did not enter a user name.');
-
-				if (!form.newPassword || !form.newPassword.value)
-					errors.push('You did not enter a password.');
-
-				if (errors.length > 0) {
-					alert('The following errors were found:\n\n' + errors.join('\n'));
-					return (-1);
-				}
-
-				if (form.newUserName.value !=
-					form.newUserName.value.replace(/[^0-9A-Za-z_-]/g, ''))
-				{
-					errors.push("The username you specified contains invalid characters. Use only alphanumeric chararacters, '_', and '-'");
-				}
-
-				if (!form.newPassword.value.replace(/\s/g, '')) {
-					errors.push('Passwords may not be blank.');
-					alert('The following errors were found:\n\n' + errors.join('\n'));
-					return (-1);
-				}
-
-				if (form.newPassword.value.length < 5)
-					errors.push('Passwords must be@least five characters long.');
-
-				if (form.newPassword.value != form.newPasswordConfirm.value)
-					errors.push('The passwords you entered do not match.');
-
-				if (!errors.length) {
-					if (confirm('Do you really want to add the user \"' +
-						form.newUserName.value + '\"?'))
-					{
-						form.submit();
-					}
-				} else {
-					alert('The following errors were found:\n\n' + errors.join('\n'));
-					return (-1);
-				}
+<div metal:define-macro="user-add-form">
+	<tal:comment replace="nothing">
+		Things to validate:
+		 - user/passwd exist and are not blank
+		 - user doesn't contain invalid characters.
+		 - passwords match
+	</tal:comment>
+
+	<script type="text/javascript">
+		function validateForm(form) {
+			var errors = new Array()
 
-				return (0);
-			}
-		</script>
+			if (!form)
+				return (-1);
+
+			if (!form.newUserName || !form.newUserName.value)
+				errors.push('You did not enter a user name.');
+			if (!form.newPassword || !form.newPassword.value)
+				errors.push('You did not enter a password.');
+			if (error_dialog(errors))
+				return (-1);
+
+			var invalid = str_is_valid(form.newUserName.value, '/[0-9A-Za-z_]/g');
+			if (invalid)
+				errors.push('The user name you specified contains the following invalid characters: "' + invalid + '"');
+
+			if (str_is_blank(form.newPassword.value))
+				errors.push('Passwords may not be blank.');
+			else if (form.newPassword.value.length < 5)
+				errors.push('Passwords must be@least five characters long.');
+			else if (form.newPassword.value != form.newPasswordConfirm.value)
+				errors.push('The passwords you entered do not match.');
+
+			if (error_dialog(errors))
+				return (-1);
+
+			if (confirm('Do you really want to add the user \"' + form.newUserName.value + '\"?'))
+				form.submit();
+			return (0);
+		}
+	</script>
 
 	<form name="adminform" method="post" action="">
 		<h2 class="homebase">Add a User</h2>
@@ -178,20 +168,20 @@
 			<tr class="hbAddUser">
 				<td class="hbAddUser">User Name</td>
 				<td class="hbAddUser">
-					<input class="hbInputUser" name="newUserName" type="text" size="24" maxlength="256" />
+					<input class="hbInputUser" name="newUserName" type="text" />
 				</td>
 			</tr>
 
 			<tr class="hbAddUser">
 				<td class="hbAddUser">Password</td>
 				<td class="hbAddUser">
-					<input class="hbInputPasswd" name="newPassword" type="password" size="24" maxlength="256" />
+					<input class="hbInputPasswd" name="newPassword" type="password" />
 				</td>
 			</tr>
 
 			<tr class="hbAddUser">
 				<td class="hbAddUser">Confirm Password</td>
-				<td class="hbAddUser"><input class="hbInputPasswd" name="newPasswordConfirm" type="password" size="24" maxlength="256" /></td>
+				<td class="hbAddUser"><input class="hbInputPasswd" name="newPasswordConfirm" type="password" /></td>
 			</tr>
 		</table>
 
@@ -201,65 +191,94 @@
 		<input name="absoluteURL" type="hidden"
 			tal:attributes="value python:data['children'][data['curIndex']]['absolute_url']" />
 
-		<div class="hbSubmit">
+		<div class="hbSubmit" id="hbSubmit">
 			<input class="hbSubmit" name="Submit" type="button" value="Submit" onClick="validateForm(document.adminform);" />
 		</div>
-		</form>
-	</div>
+	</form>
+</div>
+
+
 
 <tal:comment replace="nothing">
+
+
 !###########################
 # PERMISSIONS FORM         #
 ############################
+
+
 </tal:comment>
 
-	<div metal:define-macro="perm-manage-form">
-		<tal:comment replace="nothing">
-			Things to validate:
-				- user is selected and valid index
-				- The rest is checked by the python form submit validator.
-		</tal:comment>
-
-        <script type="text/javascript">
-			function validateForm(form) {
-				var errors = new Array();
-
-				if (!form || !form.userList)
-					return (-1);
-
-				var userIdx = form.userList.selectedIndex;
-				if (userIdx < 0 || !form.userList.options[userIdx].value)
-					errors.push('You have not selected a valid user.');
-
-				if (!errors.length) {
-					if (confirm('Submit permissions for ' + form.userList.options[userIdx].value))
-						form.submit();
-				} else {
-					alert('The following errors were found:\n\n' + errors.join('\n'));
-					return (-1);
-				}
+<div metal:define-macro="perm-manage-form">
+	<tal:comment replace="nothing">
+		Things to validate:
+			- user is selected and valid index
+			- The rest is checked by the python form submit validator.
+	</tal:comment>
 
-				return (0);
+	<script type="text/javascript">
+		function validateForm(form) {
+			var errors = new Array();
+
+			if (!form || !form.userList)
+				return (-1);
+
+			var userIdx = form.userList.selectedIndex;
+			if (userIdx < 0 || !form.userList.options[userIdx].value)
+				errors.push('You have not selected a valid user.');
+
+			if (error_dialog(errors))
+				return (-1);
+
+			var selected_clusters = new Array();
+			var selected_storage = new Array();
+
+			if (!form)
+				return (-1);
+
+			var num_clusters = document.getElementById('numClusters').value;
+			for (var i = 0 ; i < num_clusters ; i++) {
+				var element = document.getElementById('__CLUSTER' + i);
+				if (!element || !element.value || !element.checked)
+					continue;
+				selected_clusters.push(element.value);
 			}
 
-            function checkAllBoxes(str, val) {
-                var i = 0;
-                while ((element = document.getElementById(str + i++)))
-                    element.checked = val;
-            }
-        </script>
+			var num_storage = document.getElementById('numStorage').value;
+			for (var i = 0 ; i < num_storage ; i++) {
+				var element = document.getElementById('__SYSTEM' + i);
+				if (!element || !element.value || !element.checked)
+					continue;
+				selected_storage.push(element.value);
+			}
 
-	<form name="adminform" method="post" action="">
-		<h2 class="homebase">User Permissions</h2>
+			if (selected_clusters.length + selected_storage.length < 1)
+				return (0);
+
+			if (error_dialog(errors))
+				return (-1);
+
+			if (confirm('Modify permissions for ' + form.userList.options[userIdx].value + '?'))
+				form.submit();
+			return (0);
+		}
+	</script>
+
+	<span
+		tal:omit-tag=""
+		tal:define="global perms python:here.getUserPerms();
+					global systems python:here.getSystems();
+					global num_clusters python:-1;
+					global num_systems python:-1;
+					global blankForm python:1;
+					global curUser request/form/user | request/user | python:here.getDefaultUser()" />
+
+	<form name="adminform" method="post" action=""
+		tal:condition="python: curUser and perms and systems and ((systems[0] and len(systems[0]) > 0) or (systems[1] and len(systems[1]) > 0))">
+
+		<span tal:omit-tag="" tal:define="global blankForm python:0" />
 
-		<span
-			tal:omit-tag=""
-			tal:define="global perms python:here.getUserPerms();
-						global clusters python:here.getClusters();
-						global storage python:here.getStorage();
-						global num_clusters python:-1;
-						global num_storage python:-1;
-						global curUser request/user | python:here.getDefaultUser()" />
+		<h2 class="homebase">User Permissions</h2>
 
 		<input name="absoluteURL" type="hidden"
 			tal:attributes="value python:data['children'][data['curIndex']]['absolute_url']" />
@@ -267,8 +286,9 @@
 		<input name="pagetype" type="hidden"
 			tal:attributes="value request/pagetype | request/form/pagetype | nothing" />
 
-		<span tal:condition="python:perms" class="hbText" tal:content="string:Select a User" />
-		<select tal:omit-tag="python: not perms" class="homebase" name="userList" onChange="document.location = adminPermForm.absoluteURL.value + '&user=' + adminPermForm.userList.options[adminPermForm.userList.selectedIndex].text">
+		<span tal:condition="python:perms" tal:content="string:Select a User" /><br/>
+
+		<select tal:omit-tag="python: not perms" class="homebase" name="userList" onChange="document.location = adminform.absoluteURL.value + '&user=' + adminform.userList.options[adminform.userList.selectedIndex].text">
 			<tal:block tal:repeat="user python:perms">
 				<option class="homebase"
 					tal:content="python:user"
@@ -278,75 +298,95 @@
 			</tal:block>
 		</select>
 
-		<span tal:condition="python:not perms" class="hbText">
-			No users have been added
-		</span>
-
-		<p />
-
-		<h2 class="homebase" tal:condition="python:curUser and perms and clusters">Clusters</h2>
-
-		<tal:block tal:condition="python:perms" tal:repeat="c python:clusters">
-			<input type="checkbox" class="hombase"
-				tal:define="global num_clusters python:num_clusters + 1"
-				tal:attributes="
-					checked python:perms[curUser]['cluster'][c[0]] and 'checked' or None;
-					name python:'__CLUSTER:' + here.strFilter('[^0-9A-Za-z_-]', '_', c[0]);
-					id python:'__CLUSTER' + str(num_clusters);
-					value python:c[0];"
-			/>
-			<span class="hbText" tal:omit-tag="" tal:content="python:c[0]"/>
+		<h3 class="homebase" tal:condition="python:systems[0] and len(systems[0]) > 0">
+			Clusters
+		</h3>
+
+		<tal:block tal:repeat="c python:systems[0]">
+			<div class="hbcheckdiv"
+					tal:define="cfname python: here.strFilter('[^0-9A-Za-z_-]', '_', c)"
+					tal:attributes="id python: cfname">
+
+				<input type="checkbox" class="homebase"
+					tal:define="global num_clusters python:num_clusters + 1"
+					tal:attributes="
+						checked python:perms[curUser]['cluster'][c] and 'checked' or None;
+						name python:'__CLUSTER:' + cfname;
+						id python:'__CLUSTER' + str(num_clusters);
+						onChange python: 'checkChildren(\'' + cfname + '\', this)';
+						value python: c"
+				/>
+				<span tal:omit-tag="" tal:content="python:c" />
+
+				<tal:block tal:repeat="cs python:systems[0][c]">
+					<div class="hbcheckdiv">
+						<input type="checkbox" class="hombase"
+							tal:define="global num_systems python:num_systems + 1"
+							tal:attributes="
+								checked python:perms[curUser]['storage'][cs] and 'checked' or None;
+								name python:'__SYSTEM:' + here.strFilter('[^0-9A-Za-z_-]', '_', cs);
+								id python:'__SYSTEM' + str(num_systems);
+								value python:cs"
+						/>
+						<span tal:omit-tag="" tal:content="python: cs" />
+					</div>
+				</tal:block>
+			</div>
 		</tal:block>
 
-		<input type="hidden" name="numClusters" id="numClusters"
-			tal:attributes="value python: num_clusters" />
+		<div tal:omit-tag="" tal:condition="python: systems[1] and len(systems[1]) > 0">
+			<h3 class="homebase">Unclustered Systems</h3>
 
-		<div tal:condition="python:curUser and perms and clusters" class="hbSubmit">
-			<input class="hbSubmit" type="button" name="allClustersB" id="allClustersB" value="Select All Clusters" onClick="checkAllBoxes('__CLUSTER', true);" />
-			<input class="hbSubmit" type="button" name="noClustersB" id="noClustersB" value="Select No Clusters" onClick="checkAllBoxes('__CLUSTER', false);" />
-		</div>
-
-		<h2 class="homebase" tal:condition="python:curUser and perms and storage">Storage</h2>
-		<tal:block tal:condition="python:perms" tal:repeat="s python:storage">
-			<input type="checkbox" class="homebase"
-				tal:define="global num_storage python:num_storage + 1"
-				tal:attributes="
-					checked python:perms[curUser]['storage'][s[0]] and 'checked' or None;
-					name python:'__STORAGE:' + here.strFilter('[^0-9A-Za-z_-]', '_', s[0]);
-					id python:'__STORAGE' + str(num_storage); 
-					value python:s[0];"
-			/>
+			<tal:block tal:repeat="s python: systems[1]">
+			<div class="hbcheckdiv">
+				<input type="checkbox" class="hombase"
+					tal:define="global num_systems python:num_systems + 1"
+					tal:attributes="
+						checked python:perms[curUser]['storage'][s] and 'checked' or None;
+						name python:'__SYSTEM:' + here.strFilter('[^0-9A-Za-z_-]', '_', s);
+						id python:'__SYSTEM' + str(num_systems);
+						value python:s"
+				/>
+				<span class="hbText" tal:omit-tag="" tal:content="python:s"/>
+				</div>
+			</tal:block>
+		</div>
 
-			<span class="hbText" tal:omit-tag="" tal:content="python:s[0]"/>
-			<br />
-		</tal:block>
-		<input type="hidden" name="numStorage" id="numStorage"
-			tal:attributes="value python: num_storage" />
+		<input type="hidden" id="numStorage"
+			tal:attributes="value python: num_systems + 1" />
 
-		<div tal:condition="python:curUser and perms and storage " class="hbSubmit">
-			<input class="hbSubmit" type="button" name="allStorageB" id="allStorageB" value="All Storage Systems" onClick="checkAllBoxes('__STORAGE', true);" />
-			<input class="hbSubmit" type="button" name="noStorageB" id="noStorageB" value="Select No Storage Systems" onClick="checkAllBoxes('__STORAGE', false);" />
-		</div>
+		<input type="hidden" id="numClusters"
+			tal:attributes="value python: num_clusters + 1" />
 
-		<div tal:condition="python:curUser and perms" class="hbSubmit">
-			<input class="hbSubmit" type="button" name="Submit" value="Submit" onClick="validateForm(document.adminform);" />
+		<div class="hbSubmit" id="hbSubmit">
+			<input type="button" class="hbSubmit" name="Submit" value="Submit" onClick="validateForm(document.adminform);" />
 		</div>
 	</form>
+
+	<div tal:condition="python: blankForm">
+		<p>Either no users have been added or no clusters or storage systems are being managed by Luci.</p>
 	</div>
+</div>
+
 
 <tal:comment replace="nothing">
+
+
 !###########################
 # SYSTEM DELETE FORM       #
 ############################
+
+
 </tal:comment>
 
+
 <div metal:define-macro="system-del-form">
 	<tal:comment replace="nothing">
 		To validate:
-			- confirm removal
-			- if it's a cluster, ask if they also want to remove
-			  associated storage systems.
-				-> if yes, confirm again, showing list
+			- 	confirm removal
+			- 	if it's a cluster, ask if they also want to remove
+				associated storage systems.
+					-> if yes, confirm again, showing list
 	</tal:comment>
 
 	<script type="text/javascript">
@@ -359,8 +399,6 @@
 				return (-1);
 
 			var num_clusters = document.getElementById('numClusters').value;
-			var num_storage = document.getElementById('numStorage').value;
-
 			for (var i = 0 ; i < num_clusters ; i++) {
 				var element = document.getElementById('__CLUSTER' + i);
 				if (!element || !element.value || !element.checked)
@@ -368,6 +406,7 @@
 				selected_clusters.push(element.value);
 			}
 
+			var num_storage = document.getElementById('numStorage').value;
 			for (var i = 0 ; i < num_storage ; i++) {
 				var element = document.getElementById('__SYSTEM' + i);
 				if (!element || !element.value || !element.checked)
@@ -375,97 +414,144 @@
 				selected_storage.push(element.value);
 			}
 
-			if (selected_clusters.length + selected_storage.length <= 0)
+			if (selected_clusters.length + selected_storage.length < 1)
+				return (0);
+
+			if (error_dialog(errors))
 				return (-1);
 
-			if (!errors.length) {
-				var confirm_str = 'Do you really want to remove the following Managed Systems:';
+			var confirm_str = 'Do you really want to remove the following managed systems:';
+			if (selected_clusters.length > 0)
+				confirm_str += '\nClusters:\n-' + selected_clusters.join('\n-');
 
+			if (selected_storage.length > 0) {
 				if (selected_clusters.length > 0)
-					confirm_str += '\nClusters:\n' + selected_clusters.join('\n');
-				if (selected_storage.length > 0) {
-					if (selected_clusters.length > 0)
-						confirm_str += '\n';
-					confirm_str += '\nStorage Systems:\n' + selected_storage.join('\n');
-				}
+					confirm_str += '\n';
 
-				if (confirm(confirm_str))
-					form.submit();
-			} else {
-				alert('The following errors were found:\n\n' + errors.join('\n'));
-				return (-1);
+				confirm_str += '\nStorage Systems:\n-' + selected_storage.join('\n-');
 			}
 
+			if (confirm(confirm_str))
+				form.submit();
 			return (0);
 		}
 	</script>
 
-	<form name="adminform" method="post" action="">
-		<span tal:omit-tag=""
-			tal:define="global clusters python:here.getClusters();
-						global systems python:here.getStorage();
-						global num_systems python:-1;
-						global num_clusters python:-1"
-		/>
-
-		<h2 class="homebase" tal:condition="python:systems">Remove Systems</h2>
-
-		<input type="hidden" name="numStorage" id="numStorage"
-			tal:attributes="value python: len(systems)" />
-		<input type="hidden" name="numClusters" id="numClusters"
-			tal:attributes="value python: len(clusters)" />
+	<span tal:omit-tag=""
+		tal:define="global systems python:here.getSystems();
+					global blankForm python:1;
+					global num_clusters python:-1;
+					global num_systems python:-1"
+	/>
+
+	<form name="adminform" method="post" action=""
+		tal:condition="python:(systems[0] and len(systems[0]) > 0) or (systems[1] and len(systems[1]) > 0)">
+
+		<span tal:omit-tag="" tal:define="global blankForm python:0" />
+
+		<h2 class="homebase" tal:condition="python:systems">
+			Remove Systems and Clusters
+		</h2>
+
 		<input type="hidden" name="pagetype"
 			tal:attributes="value request/pagetype | request/form/pagetype | nothing" />
-		<input type="hidden" name="absoluteURL"
-			tal:attributes="value python:data['children'][data['curIndex']]['absolute_url']" />
 
-		<tal:block tal:repeat="s python:systems">
-			<input type="checkbox" class="hombase"
-				tal:define="global num_systems python:num_systems + 1"
-				tal:attributes="
-					name python:'__SYSTEM:' + here.strFilter('[^0-9A-Za-z_-]', '_', s[0]);
-					id python:'__SYSTEM' + str(num_systems);
-					value python:s[0]"
-			/>
-			<input type="hidden" value=""
-				tal:attributes="name python:'__SYSTEM:' + here.strFilter('[^0-9A-Za-z_-]', '_', s[0])" />
-			<span class="hbText" tal:omit-tag="" tal:content="python:s[0]"/>
-			<br />
-		</tal:block>
+		<h3 class="homebase" tal:condition="python: systems[0] and len(systems[0]) > 0">
+			Clusters
+		</h3>
+
+		<tal:block tal:repeat="c python:systems[0]">
+			<div class="hbcheckdiv"
+					tal:define="cfname python: here.strFilter('[^0-9A-Za-z_-]', '_', c)"
+					tal:attributes="id python: cfname">
+
+				<input type="checkbox" class="homebase"
+					tal:define="global num_clusters python:num_clusters + 1"
+					tal:attributes="
+						name python:'__CLUSTER:' + cfname;
+						id python:'__CLUSTER' + str(num_clusters);
+						onChange python: 'checkChildren(\'' + cfname + '\', this)';
+						value python: c"
+				/>
+				<input type="hidden" value=""
+					tal:attributes="
+						name python:'__CLUSTER:' + cfname"
+				/>
+				<span tal:omit-tag="" tal:content="python:c" />
 
-		<h2 class="homebase" tal:condition="python:clusters">Remove Clusters</h2>
-		<tal:block tal:repeat="c python:clusters">
-			<input type="checkbox" class="hombase"
-				tal:define="global num_clusters python:num_clusters + 1"
-				tal:attributes="
-					name python:'__CLUSTER:' + here.strFilter('[^0-9A-Za-z_-]', '_', c[0]);
-					id python:'__CLUSTER' + str(num_clusters);
-					value python:c[0]"
-			/>
-			<input type="hidden" value=""
-				tal:attributes="name python:'__CLUSTER:' + here.strFilter('[^0-9A-Za-z_-]', '_', c[0])" />
-			<span class="hbText" tal:omit-tag="" tal:content="python:c[0]"/>
-			<br />
+				<tal:block tal:repeat="cs python:systems[0][c]">
+					<div class="hbcheckdiv"
+						tal:define="csfname python: here.strFilter('[^0-9A-Za-z_-]', '_', cs)">
+
+						<input type="checkbox" class="hombase"
+							tal:define="global num_systems python:num_systems + 1"
+							tal:attributes="
+								name python:'__SYSTEM:' + csfname;
+								id python:'__SYSTEM' + str(num_systems);
+								value python:cs"
+						/>
+
+						<input type="hidden" value=""
+							tal:attributes="name python:'__SYSTEM:' + csfname" />
+						<span class="hbText" tal:omit-tag="" tal:content="python:cs" />
+					</div>
+				</tal:block>
+			</div>
 		</tal:block>
 
+		<div tal:omit-tag="" tal:condition="python: systems[1] and len(systems[1]) > 0">
+			<h3 class="homebase">Unclustered Systems</h3>
+
+			<tal:block tal:repeat="s python: systems[1]">
+				<div class="hbcheckdiv"
+					tal:define="sfname python: here.strFilter('[^0-9A-Za-z_-]', '_', s)">
+
+					<input type="checkbox" class="hombase"
+						tal:define="global num_systems python:num_systems + 1"
+						tal:attributes="
+							name python:'__SYSTEM:' + sfname;
+							id python:'__SYSTEM' + str(num_systems);
+							value python:s"
+					/>
+
+					<input type="hidden" value=""
+						tal:attributes="name python:'__SYSTEM:' + sfname" />
+					<span class="hbText" tal:omit-tag="" tal:content="python:s"/>
+				</div>
+			</tal:block>
+		</div>
+
+		<input type="hidden" id="numStorage"
+			tal:attributes="value python: num_systems + 1" />
+
+		<input type="hidden" id="numClusters"
+			tal:attributes="value python: num_clusters + 1" />
 
-		<div class="hbSubmit" tal:condition="python: clusters or systems">
+		<div class="hbSubmit" id="hbSubmit">
 			<input type="button" class="hbSubmit" name="Submit" value="Submit" onClick="validateForm(document.adminform);" />
 		</div>
-		<span tal:condition="python:(not clusters) and (not systems)">
-			No clusters or storage systems.
-		</span>
 	</form>
+
+	<div tal:condition="python: blankForm">
+		<p>No clusters or storage systems are currently being managed by Luci.</p>
+	</div>
 </div>
 
+
+
 <tal:comment replace="nothing">
+
+
 !###########################
 # SYSTEM ADD FORM          #
 ############################
+
+
 </tal:comment>
 
+
+
 <div metal:define-macro="system-add-form">
-	<form name="adminform" method="post" action="">
 	<tal:comment replace="nothing">
 		To validate for each storage system:
 			- Hostname and Password are given. (skip if both are blank)
@@ -473,368 +559,161 @@
 			- If not IP, make sure it's a FQDN with no invalid chars.
 	</tal:comment>
 
-	<h2 class="homebase">Add a Storage System</h2>
-	<input name="pagetype" type="hidden"
-		tal:attributes="value request/pagetype | request/form/pagetype | nothing" />
-
-	<input name="numSystems" id="numSystems" type="hidden" value="0" />
-
-	<input name="absoluteURL" type="hidden"
-		tal:attributes="value python:data['children'][data['curIndex']]['absolute_url']" />
-
-<tal:comment replace="nothing">XXX: refactor</tal:comment>
 	<script type="text/javascript">
-		var num_systems = 1;
-
-		function isValidHost(str) {
-			var i = str.split('.');
-
-			if (i.length == 1)
-				return ('Hostnames must be fully qualified.');
-
-			if (i.length == 4 && !isNaN(parseInt(i[3]))) {
-				var o1 = parseInt(i[0]);
-				var o2 = parseInt(i[1]);
-				var o3 = parseInt(i[2]);
-				var o4 = parseInt(i[3]);
-
-				if (isNaN(o1) || isNaN(o2) || isNaN(o3) ||
-					((o1 & 0xff) != o1) ||
-					((o2 & 0xff) != o2) ||
-					((o3 & 0xff) != o3) ||
-					((o4 & 0xff) != o4))
-				{
-					return ('Invalid IP Address.');
-				}
-
-				return (null);
-			}
-
-			if (!isNaN(parseInt(i[i.length - 1])))
-				return ('Invalid IP Address');
-
-			return (null);
-		}
-
 		function validateForm(form) {
 			var errors = new Array();
-			var added_storage = new Array();
 
 			if (!form)
 				return (-1);
 
-			var allSameCB = document.getElementById('allSameCheckBox');
-			for (var i = 0 ; i < num_systems ; i++) {
-				var errmsg;
-				var element = document.getElementById('__SYSTEM' + i + ':Addr');
-
-				if (!element)
-					continue;
-
-				var pwdElem = document.getElementById('__SYSTEM' + i + ':Passwd');
-				if (!element.value) {
-					if (pwdElem.value) {
-						if (!allSameCB.checked) {
-							errors.push('You entered a password, but no hostname for system ' + (i + 1));
-							continue;
-						} else
-							pwdElem.value = '';
-					}
-
-					continue;
-				}
-
-				if ((errmsg = isValidHost(element.value)))
-					errors.push(element.value + ' is not a valid hostname: ' + errmsg);
-				else {
-					pwdElem.disabled = false;
-					added_storage.push(element.value);
-				}
-			}
-
-			if (!errors.length) {
-				if (added_storage.length > 0 &&
-					confirm("Do you really want to add the following Storage Systems:\n" + added_storage.join('\n')))
-				{
-					var e = document.getElementById('numSystems');
-					if (e) {
-						form.submit();
-						e.value = num_systems;
-					}
-				}
-			} else {
-				alert('The following errors were found:\n\n' + errors.join('\n'));
+			var added_storage = validate_systems(form, errors);
+			if (error_dialog(errors))
 				return (-1);
+
+			if (added_storage.length > 0 &&
+				confirm("Do you really want to add the following Storage Systems:\n" + added_storage.join('\n')))
+			{
+				form.submit();
 			}
 
 			return (0);
 		}
+	</script>
 
-		function allPasswdsSame() {
-			var cb = document.getElementById('allSameCheckBox');
-			if (!cb)
-				return (-1);
-			var state = cb.checked;
-
-			var i = 1;
-			var passwd = document.getElementById('__SYSTEM0:Passwd').value;
-
-			if (!passwd || !state)
-				passwd = '';
-
-			for (var i = 1 ; i < num_systems ; i++) {
-				var element = document.getElementById('__SYSTEM' + i + ':Passwd')
-				element.value = passwd;
-				element.disabled = state;
-			}
-		}
+	<form name="adminform" method="post" action="">
+		<h2 class="homebase">Add a Storage System</h2>
 
-		function pwd0Change() {
-			if (document.getElementById('allSameCheckBox').checked)
-				allPasswdsSame();
-		}
-				
-		function addSystem() {
-			var sldiv = document.getElementById('systemsList');
-			if (!sldiv)
-				return;
-
-			var newsys = document.createElement('input');
-			newsys.setAttribute('name', '__SYSTEM' + num_systems + ':Addr');
-			newsys.setAttribute('id', '__SYSTEM' + num_systems + ':Addr');
-			newsys.setAttribute('type', 'text');
-			newsys.setAttribute('size', 32);
-			newsys.setAttribute('value', '');
-			newsys.setAttribute('maxlength', 256);
-				
-			var newsysp = document.createElement('input');
-			newsysp.setAttribute('name', '__SYSTEM' + num_systems + ':Passwd');
-			newsysp.setAttribute('id', '__SYSTEM' + num_systems + ':Passwd');
-			newsysp.setAttribute('type', 'password');
-			newsysp.setAttribute('size', 24);
-			newsysp.setAttribute('maxlength', 256);
-			newsysp.setAttribute('value', '');
-
-			var allSameCB = document.getElementById('allSameCheckBox');
-			if (allSameCB && allSameCB.checked) {
-				newsysp.setAttribute('value', document.getElementById('__SYSTEM0:Passwd').value);
-				newsysp.setAttribute('disabled', true);
-			}
+		<input name="pagetype" type="hidden"
+			tal:attributes="value request/pagetype | request/form/pagetype | nothing" />
 
-			var newdiv = document.createElement('div');
-			newdiv.setAttribute('class', 'hbSSysList');
-			newdiv.innerHTML = 'System Hostname ';
-			newdiv.appendChild(newsys);
-			newdiv.innerHTML += ' Password ';
-			newdiv.appendChild(newsysp);
-
-			sldiv.appendChild(newdiv);
-			++num_systems;
-
-			if (num_systems == 2) {
-				var button = document.createElement('input');
-				if (!button)
-					return (-1);
-				button.setAttribute('type', 'checkbox');
-				button.setAttribute('class', 'homebase');
-				button.setAttribute('name', 'allSameCheckBox');
-				button.setAttribute('id', 'allSameCheckBox');
-				button.setAttribute('onChange', 'allPasswdsSame();');
-					
-				var temps = document.getElementById('samePwdSpan');
-				temps.innerHTML = 'All Storage System Passwords Are the Same';
-				temps.appendChild(button);
-			}
-		}
-	</script>
+		<input name="numStorage" id="numStorage" type="hidden" value="1" />
 
-	<div id="systemsList" class="hbSSysList">
-		<div class="hbSSysList">
-		System Hostname
-		<input class="hbInputSys" type="text" id="__SYSTEM0:Addr" name="__SYSTEM0:Addr" size="32" maxlength="256" />
-		Password
-		<input type="password" size="24" id="__SYSTEM0:Passwd" name="__SYSTEM0:Passwd" maxlength="256" class="hbInputPass" onChange="pwd0Change();" />
-		</div>
-	</div>
+		<input name="absoluteURL" type="hidden"
+			tal:attributes="value python:data['children'][data['curIndex']]['absolute_url']" />
 
-	<div class="hbSubmit">
-		<input type="button" class="hbSubmit" value="Add Another Row" onClick="addSystem();" />
-	</div>
 
-	<div id="samePwd" class="hbSubmit">
-		<span id="samePwdSpan" class="hbText" />
-	</div>
+		<div id="systemsList" class="hbSSysList">
+			<div class="hbSSysList">
+				System Hostname
+				<input class="hbInputSys" type="text" id="__SYSTEM0:Addr" name="__SYSTEM0:Addr" />
+				Password
+				<input type="password" id="__SYSTEM0:Passwd" name="__SYSTEM0:Passwd" class="hbInputPass" onChange="pwd0Change(adminform);" />
+			</div>
+		</div>
 
-	<div class="hbSubmit">
-		<input type="button" class="hbSubmit" name="Submit" value="Submit" onClick="validateForm(document.adminform);" />
-	</div>
+		<div class="hbSubmit">
+			<input type="button" class="hbSubmit" value="Add Another Row" onClick="addSystem(adminform);" />
+		</div>
 
-<tal:comment replace="nothing">end refactor</tal:comment>
+		<div id="samePwd" class="hbSubmit">
+			<span id="samePwdSpan" class="hbText" />
+		</div>
 
+		<div class="hbSubmit" id="hbSubmit">
+			<input type="button" class="hbSubmit" name="Submit" value="Submit" onClick="validateForm(document.adminform);" />
+		</div>
 	</form>
 </div>
 
 
 <tal:comment>
+
+
 !###########################
 # CLUSTER ADD FORM         #
 ############################
-</tal:comment>
-
-<div metal:define-macro="cluster-add-form">
-	<span tal:omit-tag=""
-		tal:define="global clusters python:here.getClusters()" />
-
-	<form name="adminform" action="" method="post">
-		<input name="pagetype" type="hidden"
-			tal:attributes="value request/pagetype | request/form/pagetype | nothing" />
-
-		<input name="numSystems" id="numSystems" type="hidden" value="0" />
-
-		<input name="absoluteURL" type="hidden"
-			tal:attributes="value python:data['children'][data['curIndex']]['absolute_url']" />
 
-		<h2 class="homebase">Add Cluster</h2>
 
-		<span class="hbText">Cluster Name</span>
-		<input class="hbInputSys" type="text" id="clusterName" name="clusterName" size="32" maxlength="256" />
-
-<tal:comment replace="nothing">XXX: refactor</tal:comment>
+</tal:comment>
 
+<div metal:define-macro="cluster-add-form">
 	<tal:comment replace="nothing">
-		XXX: things to validate
-		- Cluster name is specified and contains only valid chars
-		- At least one node name/password are given and are valid
+		Things to validate
+			- Cluster name is specified and contains only valid chars
+			- At least one node name/password are given and are valid
 	</tal:comment>
 
 	<script type="text/javascript">
-		var num_systems = 3;
-
 		function validateForm(form) {
 			var errors = new Array();
 
-			if (!form)
-				return (-1);
-
-			if (!errors.length) {
-				if (confirm("Submit form?")) {
-					var e = document.getElementById('numSystems');
-					if (e) {
-						form.submit();
-						e.value = num_systems;
-					}
-					form.submit();
-				}
+			if (!form || !form.clusterName ||
+				str_is_blank(form.clusterName.value))
+			{
+				errors.push('No cluster name was given.');
 			} else {
-				alert('The following errors were found:\n\n' + errors.join('\n'));
-				return (-1);
+				var invalid_chars = str_is_valid(form.clusterName.value, '/[0-9A-Za-z_. -]/g');
+				if (invalid_chars)
+					errors.push('The cluster name you gave contains the following invalid characters: "' + invalid_chars + '".');
 			}
 
-			return (0);
-		}
+			var added_storage = validate_systems(form, errors);
 
-		function allPasswdsSame() {
-			var cb = document.getElementById('allSameCheckBox');
-			if (!cb)
-				return (-1);
-			var state = cb.checked;
-
-			var i = 1;
-			var passwd = document.getElementById('__SYSTEM0:Passwd').value;
-
-			if (!passwd || !state)
-				passwd = '';
-
-			for (var i = 1 ; i < num_systems ; i++) {
-				var element = document.getElementById('__SYSTEM' + i + ':Passwd')
-				element.value = passwd;
-				element.disabled = state;
-			}
-		}
-
-		function pwd0Change() {
-			if (document.getElementById('allSameCheckBox').checked)
-				allPasswdsSame();
-		}
-				
-		function addSystem() {
-			var allSame = document.getElementById('allSameCheckBox').checked;
-			var sldiv = document.getElementById('systemsList');
-			if (!sldiv)
-				return;
-
-			var newsys = document.createElement('input');
-			newsys.setAttribute('name', '__SYSTEM' + num_systems + ':Addr');
-			newsys.setAttribute('id', '__SYSTEM' + num_systems + ':Addr');
-			newsys.setAttribute('type', 'text');
-			newsys.setAttribute('size', 32);
-			newsys.setAttribute('maxlength', 256);
-			newsys.setAttribute('value', '');
-			
-			var newsysp = document.createElement('input');
-			newsysp.setAttribute('name', '__SYSTEM' + num_systems + ':Passwd');
-			newsysp.setAttribute('id', '__SYSTEM' + num_systems + ':Passwd');
-			newsysp.setAttribute('type', 'password');
-			newsysp.setAttribute('size', 24);
-			newsysp.setAttribute('value', '');
-			newsysp.setAttribute('maxlength', 256);
-			if (allSame) {
-				newsysp.setAttribute('value', document.getElementById('__SYSTEM0:Passwd').value);
-				newsysp.setAttribute('disabled', true);
-			}
+			if (error_dialog(errors))
+				return (-1);
 
-			var newsdiv = document.createElement('div');
-			newdiv.setAttribute('class', 'hbSSysList');
-			newdiv.innerHTML = 'System Hostname ';
-			newdiv.appendChild(newsys);
-			newdiv.innerHTML += ' Password ';
-			newdiv.appendChild(newsysp);
+			if (confirm("Submit form?"))
+				form.submit();
 
-			sldiv.appendChild(newdiv);
-			++num_systems;
+			return (0);
 		}
 	</script>
 
-	<div id="systemsList" class="hbCSystems" style="margin-left:1em;padding-top:1em">
-		<div class="hbSSysList">
-			System Hostname
-			<input class="hbInputSys" type="text" id="__SYSTEM0:Addr" name="__SYSTEM0:Addr" size="32" maxlength="256" />
-
-			Password
-			<input type="password" size="32" id="__SYSTEM0:Passwd" name="__SYSTEM0:Passwd" maxlength="256" class="hbInputPass" onChange="pwd0Change();" />
-		</div>
- 
-		<div class="hbSSysList">
-			System Hostname
-			<input class="hbInputSys" type="text" id="__SYSTEM1:Addr" name="__SYSTEM1:Addr" size="32" maxlength="256" />
-			Password
-			<input type="password" size="32" id="__SYSTEM1:Passwd" name="__SYSTEM1:Passwd" maxlength="256" class="hbInputPass" />
-		</div>
-
-		<div class="hbSSysList">
-			System Hostname
-			<input class="hbInputSys" type="text" id="__SYSTEM2:Addr" name="__SYSTEM2:Addr" size="32" maxlength="256" />
-			Password
-			<input type="password" size="32" id="__SYSTEM2:Passwd" name="__SYSTEM2:Passwd" maxlength="256" class="hbInputPass" />
+	<form name="adminform" action="" method="post">
+		<div id="systemsList" class="hbCSystems">
+			<span tal:omit-tag=""
+				tal:define="global clusters python:here.getClusters()" />
+
+			<input name="pagetype" type="hidden"
+				tal:attributes="value request/pagetype | request/form/pagetype | nothing" />
+
+			<input name="numStorage" id="numStorage" type="hidden" value="3" />
+
+			<input name="absoluteURL" type="hidden"
+				tal:attributes="value python:data['children'][data['curIndex']]['absolute_url']" />
+
+			<h2 class="homebase">Add Cluster</h2>
+
+			<span class="hbText">Cluster Name</span>
+			<input class="hbInputSys" type="text" id="clusterName" name="clusterName" />
+
+			<div class="hbSSysList">
+				System Hostname
+				<input class="hbInputSys" type="text" id="__SYSTEM0:Addr" name="__SYSTEM0:Addr" />
+				Password
+				<input type="password" id="__SYSTEM0:Passwd" name="__SYSTEM0:Passwd" class="hbInputPass" onChange="pwd0Change(adminform);" />
+			</div>
+
+			<div class="hbSSysList">
+				System Hostname
+				<input class="hbInputSys" type="text" id="__SYSTEM1:Addr" name="__SYSTEM1:Addr" />
+				Password
+				<input type="password" id="__SYSTEM1:Passwd" name="__SYSTEM1:Passwd" class="hbInputPass" />
+			</div>
+
+			<div class="hbSSysList">
+				System Hostname
+				<input class="hbInputSys" type="text" id="__SYSTEM2:Addr" name="__SYSTEM2:Addr" />
+				Password
+				<input type="password" id="__SYSTEM2:Passwd" name="__SYSTEM2:Passwd" class="hbInputPass" />
+			</div>
 		</div>
-	</div>
 
-	<div class="hbSubmit" style="padding-top:1em">
-		<input type="button" class="hbSubmit" value="Add Another Row" onClick="addSystem();" />
-	</div>
-
-	<div class="hbSubmit">
-		All Storage System Passwords Are the Same
-		<input class="hbSubmit" type="checkbox" name="allSameCheckBox" id="allSameCheckBox" onClick="allPasswdsSame();" />
-	</div>
+		<div class="hbSubmit">
+			<input type="button" class="hbSubmit" value="Add Another Row" onClick="addSystem(adminform);" />
+		</div>
 
-	<div class="hbSubmit" style="padding-top:1em">
-		<input type="button" class="hbSubmit" name="Submit" value="Submit" onClick="validateForm(document.adminform);" />
-	</div>
+		<div class="hbSubmit">
+			All Storage System Passwords Are the Same
+			<input class="hbSubmit" type="checkbox" name="allSameCheckBox" id="allSameCheckBox" onClick="allPasswdsSame(adminform);" />
+		</div>
 
-<tal:comment replace="nothing">XXX: end refactor</tal:comment>
+		<div class="hbSubmit" id="hbSubmit">
+			<input type="button" class="hbSubmit" name="Submit" value="Submit" onClick="validateForm(document.adminform);" />
+		</div>
 	</form>
 </div>
 
+
 </body>
 </html>
--- conga/luci/homebase/index_html	2006/05/25 22:34:24	1.6
+++ conga/luci/homebase/index_html	2006/06/20 21:21:47	1.7
@@ -1,15 +1,21 @@
-<metal:page define-macro="master"><metal:doctype define-slot="doctype"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></metal:doctype>
+<metal:page define-macro="master">
+
+<metal:doctype define-slot="doctype">
+	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+</metal:doctype>
+
 <metal:block define-slot="top_slot" />
+
 <metal:block use-macro="here/global_defines/macros/defines" />
 
 <html xmlns="http://www.w3.org/1999/xhtml"
-      xml:lang="en"
-      lang="en"
-      tal:attributes="lang language;
-                      xml:lang language">
- 
+	xml:lang="en"
+	lang="en"
+	tal:attributes="lang language;
+					xml:lang language">
+
 <tal:comment replace="nothing">
-	$Id: index_html,v 1.6 2006/05/25 22:34:24 rmccabe Exp $
+	$Id: index_html,v 1.7 2006/06/20 21:21:47 rmccabe Exp $
 </tal:comment>
 
 <head metal:use-macro="here/header/macros/html_header">
@@ -19,115 +25,313 @@
 		</metal:baseslot>
 	</metal:fillbase>
 
-    <metal:headslot fill-slot="head_slot"
-                    tal:define="lang language;
-                                charset site_properties/default_charset|string:utf-8">
-
-      <metal:cache use-macro="here/global_cache_settings/macros/cacheheaders">
-        Get the global cache headers located in global_cache_settings.
-      </metal:cache>
-
-      <metal:headslot define-slot="head_slot" />
-      <tal:comment replace="nothing"> A slot where you can insert elements in the header from a template </tal:comment>
-    </metal:headslot>
-
-    <metal:cssslot fill-slot="css_slot">
-      <tal:comment replace="nothing"> A slot where you can insert CSS in the header from a template </tal:comment>
-    
-  <style type="text/css">
+	<metal:headslot fill-slot="head_slot"
+					tal:define="lang language;
+								charset site_properties/default_charset|string:utf-8">
+
+	<metal:cache use-macro="here/global_cache_settings/macros/cacheheaders">
+		Get the global cache headers located in global_cache_settings.
+	</metal:cache>
+
+	<metal:headslot define-slot="head_slot" />
+		<tal:comment replace="nothing"> A slot where you can insert elements in the header from a template </tal:comment>
+	</metal:headslot>
+
+	<metal:cssslot fill-slot="css_slot">
+		<tal:comment replace="nothing"> A slot where you can insert CSS in the header from a template </tal:comment>
+
+<style type="text/css">
 	<!-- @import url(../cluster/clusterportlet.css); -->
-  </style>
+</style>
 
-  <style media="all" type="text/css">
-	<!-- @import url("luci_homebase.css"); -->
-  </style>
-
-      <metal:cssslot define-slot="css_slot" />
-    </metal:cssslot>
-
-    <metal:javascriptslot fill-slot="javascript_head_slot">
-      <tal:comment replace="nothing"> A slot where you can insert javascript in the header from a template </tal:comment>
-      <metal:javascriptslot define-slot="javascript_head_slot" />
-    </metal:javascriptslot>
-  </head>
-
-  <body tal:attributes="class here/getSectionFromURL;
-                        dir python:test(isRTL, 'rtl', 'ltr')">
-    <div id="visual-portal-wrapper">
-
-      <div id="portal-top" i18n:domain="plone">
-
-        <div id="portal-header">
-          <a class="hiddenStructure"
-             accesskey="2"
-             tal:attributes="href string:${request/ACTUAL_URL}#documentContent"
-             i18n:translate="label_skiptocontent">Skip to content.</a>
-
-          <a class="hiddenStructure"
-             accesskey="6"
-             tal:attributes="href string:${request/ACTUAL_URL}#portlet-navigation-tree"
-             i18n:translate="label_skiptonavigation">Skip to navigation</a>
-
-             <a metal:use-macro="here/main_logo/macros/main_portal_logo">
-               The portal logo, linked to the portal root
-             </a>
-
-             <div metal:use-macro="here/main_sections/macros/portal_tabs" tal:condition="python:here.userAuthenticated()">
-               The global sections tabs. (Welcome, News etc)
-             </div>
-          </div>
-
-          <div metal:use-macro="here/main_personalbar/macros/personal_bar">
-             The personal bar. (log in, logout etc...)
-           </div>
-
-      <div class="visualClear"><!-- --></div>
-
-      <tal:comment replace="nothing">
-      The wrapper table. It contains the three columns. There's a table-less
-      alternative in the plone_tableless skin layer that you can use if you
-      prefer layouts that don't use tables.
-      </tal:comment> 
-
-      <table id="portal-columns">
-        <tbody>
-          <tr>
-            <tal:comment replace="nothing"> Start of the left column </tal:comment>
-            <td id="portal-column-one"
-                metal:define-slot="column_one_slot"
-                tal:condition="sl"
-				tal:omit-tag="python:not here.userAuthenticated()">
-              <div class="visualPadding">
-                <metal:portlets define-slot="portlets_one_slot">
-                  <metal:leftportlets use-macro="here/homebase_portlet_fetcher/macros/left_column">
-                    This instruction gets the portlets (boxes) for the left column.
-                  </metal:leftportlets>
-                </metal:portlets>
-                &nbsp;
-              </div>
-            </td>
-            <tal:comment replace="nothing"> End of the left column </tal:comment>
-
-            <tal:comment replace="nothing"> Start of main content block </tal:comment>
-            <td id="portal-column-content">
-
-              <metal:block define-slot="content">
-                <div id="content"
-                     metal:define-macro="content">
-
-  
-
-                  <div class="documentContent" id="region-content">
-
-                    <a name="documentContent"></a>
-
-                    <metal:bodytext metal:define-slot="main" tal:content="nothing">
-                
-                      Page body text
-                    </metal:bodytext>
+<style type="text/css">
+	<!-- @import url(/luci/homebase/luci_homebase.css); -->
+</style>
+
+<tal:block tal:omit-tag="" 
+	tal:define="global data python:here.homebaseControl(request)" />
+
+<metal:cssslot define-slot="css_slot" />
+	</metal:cssslot>
+
+	<metal:javascriptslot fill-slot="javascript_head_slot">
+		<tal:comment replace="nothing"> A slot where you can insert javascript in the header from a template </tal:comment>
+		<metal:javascriptslot define-slot="javascript_head_slot" />
+
+<script type="text/javascript">
+function error_dialog(errors) {
+	if (!errors || errors.length < 1)
+		return (null);
+	alert('The following errors were found:\n\n' + errors.join('\n'));
+	return (-1);
+}
+
+function str_is_blank(str) {
+	return (!str || !str.replace(/\s/g, ''));
+}
+
+function str_is_valid(str, valid_regex_str) {
+	if (!str || !valid_regex_str)
+		return (null);
+	var re = eval(valid_regex_str);
+	var invalid = str.replace(re, '');
+	if (!invalid)
+		return (null);
+	return (invalid);
+}
+
+function checkAllBoxes(str, val) {
+	var i = 0;
+	var element;
+	while ((element = document.getElementById(str + i++)))
+		element.checked = val;
+}
+
+function checkChildren(parent_cont, parent_input) {
+	if (!parent_cont || !parent_input)
+		return
+	parent = document.getElementById(parent_cont);
+	children = parent.getElementsByTagName('input')
+	for (var i = 0 ; i < children.length ; i++) {
+		if (children[i] == parent_input)
+			continue;
+		if (children[i].type == 'checkbox')
+			children[i].checked = parent_input.checked;
+	}
+}
+
+function hide_element(id) {
+	var elem = document.getElementById(id);
+	if (elem)
+		elem.style['visibility'] = 'hidden';
+}
+
+function isValidHost(str) {
+	var i = str.split('.');
+
+	if (i.length == 1)
+		return ('Hostnames must be fully qualified.');
+
+	if (i.length == 4 && !isNaN(parseInt(i[3]))) {
+		var o1 = parseInt(i[0]);
+		var o2 = parseInt(i[1]);
+		var o3 = parseInt(i[2]);
+		var o4 = parseInt(i[3]);
+
+		if (isNaN(o1) || isNaN(o2) || isNaN(o3) ||
+			((o1 & 0xff) != o1) ||
+			((o2 & 0xff) != o2) ||
+			((o3 & 0xff) != o3) ||
+			((o4 & 0xff) != o4))
+		{
+			return ('Invalid IP Address.');
+		}
+
+		return (null);
+	}
+
+	if (!isNaN(parseInt(i[i.length - 1])))
+		return ('Invalid IP Address.');
+
+	if (!str.match(/^[0-9A-Za-z][0-9A-Za-z.-]*$/))
+		return ('Hostnames can contain only alphanumeric characters and hyphens.');
+
+	return (null);
+}
+
+function allPasswdsSame(form) {
+	var cb = document.getElementById('allSameCheckBox');
+	if (!cb)
+		return (-1);
+	var num_systems = form.numStorage.value;
+
+	var state = cb.checked;
+	var passwd = document.getElementById('__SYSTEM0:Passwd').value;
+	if (!passwd || !state)
+		passwd = '';
+
+	for (var i = 1 ; i < num_systems ; i++) {
+		var element = document.getElementById('__SYSTEM' + i + ':Passwd')
+		if (element) {
+			element.value = passwd;
+			element.disabled = state;
+		}
+	}
+}
+
+function pwd0Change(form) {
+	var element = document.getElementById('allSameCheckBox');
+	if (element && element.checked)
+		allPasswdsSame(form);
+}
+
+function addSystem(form) {
+	var sldiv = document.getElementById('systemsList');
+	if (!sldiv)
+		return;
+	var num_systems = form.numStorage.value;
+
+	var newsys = document.createElement('input');
+	newsys.setAttribute('style', 'padding:.20em !important;width:200px;');
+	newsys.setAttribute('name', '__SYSTEM' + num_systems + ':Addr');
+	newsys.setAttribute('id', '__SYSTEM' + num_systems + ':Addr');
+	newsys.setAttribute('type', 'text');
+	newsys.setAttribute('value', '');
+
+	var newsysp = document.createElement('input');
+	newsysp.setAttribute('style', 'padding:.20em !important;width:160px;');
+	newsysp.setAttribute('name', '__SYSTEM' + num_systems + ':Passwd');
+	newsysp.setAttribute('id', '__SYSTEM' + num_systems + ':Passwd');
+	newsysp.setAttribute('type', 'password');
+	newsysp.setAttribute('value', '');
+
+	var allSameCB = document.getElementById('allSameCheckBox');
+	if (allSameCB && allSameCB.checked) {
+		newsysp.setAttribute('value', document.getElementById('__SYSTEM0:Passwd').value);
+		newsysp.setAttribute('disabled', true);
+	}
+
+	var newdiv = document.createElement('div');
+
+	newdiv.setAttribute('style', 'margin-top: .25em;margin-bottom:.25em');
+	newdiv.innerHTML = 'System Hostname ';
+	newdiv.appendChild(newsys);
+	newdiv.innerHTML += ' Password ';
+	newdiv.appendChild(newsysp);
+
+	sldiv.appendChild(newdiv);
+	form.numStorage.value = ++num_systems;
+
+	if (num_systems == 2) {
+		var button = document.createElement('input');
+		if (!button)
+			return (-1);
+		button.setAttribute('type', 'checkbox');
+		button.setAttribute('class', 'homebase');
+		button.setAttribute('name', 'allSameCheckBox');
+		button.setAttribute('id', 'allSameCheckBox');
+		button.setAttribute('onChange', 'allPasswdsSame(document.adminform);');
+
+		var temps = document.getElementById('samePwdSpan');
+		temps.innerHTML = 'All Storage System passwords are the same';
+		temps.appendChild(button);
+	}
+}
+
+function validate_systems(form, errors) {
+	var allSameCB = document.getElementById('allSameCheckBox');
+	var added_storage = new Array();
+	var num_systems = form.numStorage.value;
+
+	for (var i = 0 ; i < num_systems ; i++) {
+		var element = document.getElementById('__SYSTEM' + i + ':Addr');
+
+		if (!element)
+			continue;
+
+		var pwdElem = document.getElementById('__SYSTEM' + i + ':Passwd');
+		if (!element.value) {
+			if (pwdElem.value) {
+				if (!allSameCB.checked) {
+					errors.push('You entered a password, but no hostname for system ' + (i + 1));
+					continue;
+				} else
+					pwdElem.value = '';
+			}
+
+			continue;
+		} else if (!pwdElem || !pwdElem.value)
+			errors.push('No password was given for \"' + element.value + '\"');
+		else if (str_is_blank(pwdElem.value))
+			errors.push('The password entered for \"' + element.value + '\" is blank.');
+
+		if (str_is_blank(element.value)) {
+			errors.push('You entered a blank hostname for system ' + (i + 1));
+			element.value = '';
+		} else {
+			var errmsg;
+			if ((errmsg = isValidHost(element.value)))
+				errors.push('\"' + element.value + '\" is not a valid hostname: ' + errmsg);
+			else {
+				pwdElem.disabled = false;
+				added_storage.push(element.value);
+			}
+		}
+	}
+
+	return (added_storage);
+}
+</script>
+</metal:javascriptslot>
+
+</head>
+
+<body tal:attributes="class here/getSectionFromURL;
+						dir python:test(isRTL, 'rtl', 'ltr')">
+	<div id="visual-portal-wrapper">
+
+	<div id="portal-top" i18n:domain="plone">
+
+		<div id="portal-header">
+			<a	class="hiddenStructure"
+				accesskey="2"
+			 	tal:attributes="href string:${request/ACTUAL_URL}#documentContent"
+			 	i18n:translate="label_skiptocontent">Skip to content.</a>
+
+			<a	class="hiddenStructure"
+				accesskey="6"
+				tal:attributes="href string:${request/ACTUAL_URL}#portlet-navigation-tree"
+				i18n:translate="label_skiptonavigation">Skip to navigation</a>
+
+			 <a metal:use-macro="here/main_logo/macros/main_portal_logo">
+				The portal logo, linked to the portal root
+			 </a>
+
+			 <div metal:use-macro="here/main_sections/macros/portal_tabs" tal:condition="python:here.userAuthenticated()">
+				The global sections tabs. (Welcome, News etc)
+			</div>
+		</div>
+
+		<div metal:use-macro="here/main_personalbar/macros/personal_bar">
+			The personal bar. (log in, logout etc...)
+		</div>
 
-        	<metal:main_form use-macro="here/form-chooser/macros/main-form">
-                <h1 tal:content="string:${cname}"></h1>
+		<div class="visualClear"><!-- --></div>
+
+	  <table id="portal-columns">
+		<tbody>
+		  <tr>
+			<tal:comment replace="nothing"> Start of the left column </tal:comment>
+			<td id="portal-column-one"
+				metal:define-slot="column_one_slot"
+				tal:define="lccond1 sl;lccond2 isAnon"
+				tal:condition="python:lccond1 and not lccond2">
+			  <div class="visualPadding">
+				<metal:portlets define-slot="portlets_one_slot">
+				  <metal:leftportlets use-macro="here/homebase_portlet_fetcher/macros/left_column">
+					This instruction gets the portlets (boxes) for the left column.
+				  </metal:leftportlets>
+				</metal:portlets>
+				&nbsp;
+			  </div>
+			</td>
+			<tal:comment replace="nothing"> End of the left column </tal:comment>
+
+			<tal:comment replace="nothing"> Start of main content block </tal:comment>
+			<td id="portal-column-content">
+
+			  <metal:block define-slot="content">
+				<div id="content"
+					 metal:define-macro="content">
+
+				  <div class="documentContent" id="region-content">
+					<a name="documentContent"></a>
+					<metal:bodytext metal:define-slot="main" tal:content="nothing">
+						Page body text
+					</metal:bodytext>
+
+			<metal:main_form use-macro="here/form-chooser/macros/main-form">
+				<h1 tal:content="string:${cname}"></h1>
 				Homebase
 			</metal:main_form>
 
@@ -135,55 +339,63 @@
 			tal:define="global ret python: request.SESSION.get('checkRet')"
 		/>
 
-		<div style="margin-top: 2em" class="retmsgs" tal:condition="python:(ret and 'messages' in ret and len(ret['messages']))">
+		<span tal:omit-tag="" tal:condition="python:request.SESSION.set('checkRet',{})" />
+
+		<div class="retmsgs" id="retmsgsdiv" tal:condition="python:(ret and 'messages' in ret and len(ret['messages']))">
+			<div class="hbclosebox">
+				<a href="javascript:hide_element('retmsgsdiv');"><img src="x.png"></a>
+			</div>
 			<ul class="retmsgs">
-	        <tal:block repeat="e python:ret['messages']">
-				<li class="retmsgs" style="color:green" tal:content="python:e" />
-			</tal:block>
+				<tal:block repeat="e python:ret['messages']">
+					<li class="retmsgs" tal:content="python:e" />
+				</tal:block>
 			</ul>
 		</div>
 
-		<div class="errmsgs" style="margin-top: 2em" tal:condition="python:(ret and 'errors' in ret and len(ret['errors']))">
-	        <p class="errmsgs" style="font-weight:800;color:red"> The following errors occurred:</p>
+		<div id="errmsgsdiv" class="errmsgs" tal:condition="python:(ret and 'errors' in ret and len(ret['errors']))">
+			<div class="hbclosebox">
+				<a class="hbclosebox" href="javascript:hide_element('errmsgsdiv');"><img src="x.png"></a>
+			</div>
+			<p class="errmsgs">The following errors occurred:</p>
 			<ul class="errmsgs">
-	        <tal:block repeat="e python:ret['errors']">
-				<li class="errmsgs" style="color:red" tal:content="python:e" />
-			</tal:block>
+				<tal:block repeat="e python:ret['errors']">
+					<li class="errmsgs" tal:content="python:e" />
+				</tal:block>
 			</ul>
 		</div>
 
 
-                  </div>
+				  </div>
 
-                </div>
+				</div>
 
-              </metal:block>
-            </td>
-            <tal:comment replace="nothing"> End of main content block </tal:comment>
+			  </metal:block>
+			</td>
+			<tal:comment replace="nothing"> End of main content block </tal:comment>
 
-          </tr>
-        </tbody>
-      </table>
-      <tal:comment replace="nothing"> end column wrapper </tal:comment>
+		  </tr>
+		</tbody>
+	  </table>
+	  <tal:comment replace="nothing"> end column wrapper </tal:comment>
 
-      <div class="visualClear"><!-- --></div>
+	  <div class="visualClear"><!-- --></div>
 
 
-      <hr class="netscape4" />
+	  <hr class="netscape4" />
 
-      <metal:block i18n:domain="plone">
+	  <metal:block i18n:domain="plone">
 
-        <metal:footer use-macro="here/main_footer/macros/portal_footer">
-          Footer
-        </metal:footer>
+		<metal:footer use-macro="here/main_footer/macros/portal_footer">
+		  Footer
+		</metal:footer>
 
-        <metal:colophon use-macro="here/colophon/macros/colophon">
-          The colophon area - contains details about the production of
-          the site. Typically "powered by" buttons, standards, tools used.
-        </metal:colophon>
-      </metal:block>
+		<metal:colophon use-macro="here/colophon/macros/colophon">
+		  The colophon area - contains details about the production of
+		  the site. Typically "powered by" buttons, standards, tools used.
+		</metal:colophon>
+	  </metal:block>
 
-    </div>
+	</div>
 
 </body>
 </html>
--- conga/luci/homebase/luci_homebase.css	2006/05/25 22:34:24	1.3
+++ conga/luci/homebase/luci_homebase.css	2006/06/20 21:21:47	1.4
@@ -1,51 +1,105 @@
-/* $Id: luci_homebase.css,v 1.3 2006/05/25 22:34:24 rmccabe Exp $ */
+/* $Id: luci_homebase.css,v 1.4 2006/06/20 21:21:47 rmccabe Exp $ */
 
-ul.errmsgs {
+*.errmsgs,*.retmsgs {
+	list-style-image: none !important;
+	list-style-type: none !important;
 }
 
-ul.retmsgs {
+*.errmsgs {
+	color: red !important;
 }
 
-li.errmsgs {
+h3.homebase {
+	color: #436976;
+	margin-top: 1em;
+	margin-bottom: .5em;
+	font-size: 12px;
+	font-weight: 800;
 }
 
-li.retmsgs {
+h2.homebase {
+	margin-bottom: +1em;
+	inherit;
+}
+
+*.retmsgs {
+	color: green !important;
 }
 
 p.errmsgs {
+	font-weight: 800;
 }
 
 div.errmsgs {
+	padding: .5em;
+	border-style: dotted;
+	border-width: 2px;
+	border-color: red;
+	margin-top: 2em;
+	max-width: 600px;
 }
 
 div.retmsgs {
+	padding: .5em;
+	margin-top: 2em;
+	border-style: dotted;
+	border-width: 2px;
+	border-color: green;
+	max-width: 600px;
 }
 
-*.homebase {
+div.hbCSystems {
+	margin-left:1em !important;
+	padding-top:.5em !important;
 }
 
-*.hbCSystems {
+div.hbSSysList {
+	margin-top: .25em !important;
+	margin-bottom: .25em !important;
 }
 
 div.hbSubmit {
-	margin-top: 1em !important;
+	margin-top: .5em;
+	margin-bottom: .5em;
+	margin-right: .5em;
+}
+
+#hbSubmit {
+	margin-top: +1em;
+	margin-left: 40%;
 }
 
 td.hbAddUser {
-	padding: 1em;
+	margin-top:.5em;
+	padding: .1em;
 }
 
-*.hbInputSys {
-	padding: .5em !important;
+div.hbcheckdiv {
+	padding-top: .25em;
+	padding-bottom: .25em;
 }
 
-*.hbInputPass {
-	padding: .5em !important;
+div.hbcheckdiv > div.hbcheckdiv {
+	margin-left: +1.5em;
 }
 
-div.hbSSysList {
-	margin-top: .5em !important;
-	margin-bottom: .5em !important;
+input.hbInputSys {
+	padding: .20em !important;
+	width: 200px;
+}
+
+input.hbInputPass {
+	padding: .20em !important;
+	width: 160px;
+}
+
+*.hbclosebox {
+   text-align: right;
+}
+
+div.systemsList {
+  margin-top: .25em !important;
+  margin-bottom: .25em !important;
 }
 
 *.hbText {
--- conga/luci/homebase/main_logo	2006/05/18 17:47:15	1.3
+++ conga/luci/homebase/main_logo	2006/06/20 21:21:47	1.4
@@ -1,17 +1,17 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
-      i18n:domain="plone">
+	i18n:domain="plone">
+
+<head/>
 
 <body>
 
 <tal:comment replace="nothing">
-	$Id: main_logo,v 1.3 2006/05/18 17:47:15 rmccabe Exp $
+	$Id: main_logo,v 1.4 2006/06/20 21:21:47 rmccabe Exp $
 </tal:comment>
 
 <!--	THE PORTAL LOGO DEFINITION -->
 <h1 id="main-portal-logo" metal:define-macro="main_portal_logo">
-    <a href="/">
-        Luci
-    </a>
+	<a href="/">Luci</a>
 </h1>
 
 
--- conga/luci/homebase/main_pathbar	2006/05/18 17:47:15	1.3
+++ conga/luci/homebase/main_pathbar	2006/06/20 21:21:47	1.4
@@ -1,50 +1,57 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
-      i18n:domain="plone">
+	i18n:domain="plone">
+
+<head/>
 
 <body>
 
 <tal:comment replace="nothing">
-	$Id: main_pathbar,v 1.3 2006/05/18 17:47:15 rmccabe Exp $
+	$Id: main_pathbar,v 1.4 2006/06/20 21:21:47 rmccabe Exp $
 </tal:comment>
 
 <!-- THE PATHBAR (breadcrumbs) DEFINITION -->
 
 <div metal:define-macro="path_bar"
-     id="portal-breadcrumbs"
-     tal:define="breadcrumbs python:putils.createBreadCrumbs(here);
-                     portal_url portal_url|utool">
+	id="portal-breadcrumbs"
+	tal:define="breadcrumbs python:putils.createBreadCrumbs(here);
+				portal_url portal_url|utool">
 
-    <span id="breadcrumbs-you-are-here" i18n:translate="you_are_here">
+	<span id="breadcrumbs-you-are-here" i18n:translate="you_are_here">
 		You are here:
 	</span>
 
-    <a i18n:translate="tabs_home" tal:attributes="href python:portal_url">
+	<a i18n:translate="tabs_home" tal:attributes="href python:portal_url">
 		Home
 	</a>
 
-    <span tal:condition="breadcrumbs" class="breadcrumbSeparator">
-        <tal:ltr condition="not: isRTL">&rarr;</tal:ltr> 
-        <tal:rtl condition="isRTL">&larr;</tal:rtl> 
-    </span>
-
-    <span tal:repeat="crumb breadcrumbs"
-          tal:attributes="dir python:test(isRTL, 'rtl', 'ltr')">
-        <tal:last tal:define="is_last repeat/crumb/end">
-            <a href="#"
-               tal:omit-tag="not: crumb/absolute_url"
-               tal:condition="python:not is_last"
-               tal:attributes="href crumb/absolute_url"
-               tal:content="crumb/Title">
-                crumb
-            </a>
-            <span class="breadcrumbSeparator" tal:condition="not: is_last"> 
-                <tal:ltr condition="not: isRTL">&rarr;</tal:ltr> 
-                <tal:rtl condition="isRTL">&larr;</tal:rtl> 
-            </span>
-            <span tal:condition="is_last"
-                  tal:content="crumb/Title">crumb</span>
-         </tal:last>
-    </span>
+	<span tal:condition="breadcrumbs" class="breadcrumbSeparator">
+		<tal:ltr condition="not: isRTL">&rarr;</tal:ltr>
+		<tal:rtl condition="isRTL">&larr;</tal:rtl>
+	</span>
+
+	<span
+		tal:repeat="crumb breadcrumbs"
+		tal:attributes="dir python:test(isRTL, 'rtl', 'ltr')">
+
+		<tal:last tal:define="is_last repeat/crumb/end">
+			<a href="#"
+				tal:omit-tag="not: crumb/absolute_url"
+				tal:condition="python:not is_last"
+				tal:attributes="href crumb/absolute_url"
+				tal:content="crumb/Title">crumb
+			</a>
+
+			<span class="breadcrumbSeparator" tal:condition="not: is_last">
+				<tal:ltr condition="not: isRTL">&rarr;</tal:ltr>
+				<tal:rtl condition="isRTL">&larr;</tal:rtl>
+			</span>
+
+			<span
+				tal:condition="is_last"
+				tal:content="crumb/Title">crumb
+			</span>
+		</tal:last>
+	</span>
 </div>
 
 </body>
--- conga/luci/homebase/main_personalbar	2006/05/18 17:47:15	1.3
+++ conga/luci/homebase/main_personalbar	2006/06/20 21:21:47	1.4
@@ -1,45 +1,52 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
-      i18n:domain="plone">
+	i18n:domain="plone">
+
+<head/>
 
 <tal:comment replace="nothing">
-	$Id: main_personalbar,v 1.3 2006/05/18 17:47:15 rmccabe Exp $
+	$Id: main_personalbar,v 1.4 2006/06/20 21:21:47 rmccabe Exp $
 </tal:comment>
 
 <body>
 <!-- THE PERSONAL BAR DEFINITION -->
-<div metal:define-macro="personal_bar"
-      tal:define="display_actions python:user_actions[:-1]+global_actions+user_actions[-1:];
-                  getIconFor nocall:putils/getIconFor;"
-      tal:omit-tag="">
-
-<h5 class="hiddenStructure" i18n:translate="heading_personal_tools">Personal tools</h5>
-
-<ul id="portal-personaltools">
-    <li class="portalUser" 
-        tal:condition="not: isAnon"><a 
-        id="user-name"
-        tal:omit-tag="not: mtool/getHomeFolder"
-        tal:attributes="href string:${mtool/getHomeUrl}">
-        <span class="visualCaseSensitive"
-              tal:replace="user/getUserName">
-             John
-        </span>
-    </a></li>
-
-    <tal:actions tal:repeat="action python:here.getOrderedUserActions(keyed_actions=keyed_actions)">
-        <li tal:define="icon python:getIconFor(action['category'], action['id'], None);
-                        class_name string:actionicon-${action/category}-${action/id};
-                        class_name python:test(icon, class_name, nothing);"
-            tal:attributes="class class_name">
-            <a href=""
-               tal:attributes="href action/url;
-                               class python:test(icon, 'visualIconPadding', nothing);">
-               <tal:actionname i18n:translate="" tal:content="action/name">dummy</tal:actionname>
-            </a>
-        </li>
-    </tal:actions>
 
-</ul>
+<div metal:define-macro="personal_bar"
+	tal:define="display_actions python:user_actions[:-1]+global_actions+user_actions[-1:];
+				getIconFor nocall:putils/getIconFor;"
+	tal:omit-tag="">
+
+	<h5 class="hiddenStructure" i18n:translate="heading_personal_tools">Personal tools</h5>
+
+	<ul id="portal-personaltools">
+		<li class="portalUser"
+			tal:condition="not: isAnon">
+
+			<a	id="user-name"
+				tal:omit-tag="not: mtool/getHomeFolder"
+				tal:attributes="href string:${mtool/getHomeUrl}">
+				<span
+					class="visualCaseSensitive"
+					tal:replace="user/getUserName" />
+			</a>
+		</li>
+
+		<tal:actions
+			tal:repeat="action python:here.getOrderedUserActions(keyed_actions=keyed_actions)">
+
+			<li tal:define="icon python:getIconFor(action['category'], action['id'], None);
+				class_name string:actionicon-${action/category}-${action/id};
+				class_name python:test(icon, class_name, nothing);"
+				tal:attributes="class class_name">
+
+				<a	href=""
+					tal:attributes="href action/url;
+					class python:test(icon, 'visualIconPadding', nothing);">
+					<tal:actionname i18n:translate=""
+						tal:content="action/name">dummy</tal:actionname>
+				</a>
+			</li>
+		</tal:actions>
+	</ul>
 </div>
 
 </body>
--- conga/luci/homebase/main_sections	2006/05/18 17:47:15	1.3
+++ conga/luci/homebase/main_sections	2006/06/20 21:21:47	1.4
@@ -1,8 +1,10 @@
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
-      i18n:domain="plone">
+	i18n:domain="plone">
+
+<head/>
 
 <tal:comment replace="nothing">
-	$Id: main_sections,v 1.3 2006/05/18 17:47:15 rmccabe Exp $
+	$Id: main_sections,v 1.4 2006/06/20 21:21:47 rmccabe Exp $
 </tal:comment>
 
 <body>
@@ -12,19 +14,20 @@
 	tal:omit-tag=""
 	tal:define="tabs python:here.getTabs(request)">
 
-    <h5 class="hiddenStructure" i18n:translate="heading_sections">Sections</h5>
+	<h5 class="hiddenStructure" i18n:translate="heading_sections">Sections</h5>
 
-    <ul id="portal-globalnav" tal:condition="python:here.userAuthenticated()">
-       <tal:tabs tal:repeat="tab tabs">
-        <li tal:attributes="id string:portaltab-${tab/Title};
-                            class python:test(tab['isSelected'], 'selected', 'plain');">
-            <a href="" 
-               tal:content="tab/Title"
-               tal:attributes="href tab/Taburl;
-                               title tab/Description|nothing">
-            Tab Name
-            </a></li></tal:tabs>
-    </ul>
+	<ul id="portal-globalnav" tal:condition="python:here.userAuthenticated()">
+		<tal:tabs tal:repeat="tab tabs">
+			<li tal:attributes="id string:portaltab-${tab/Title};
+							class python:test(tab['isSelected'], 'selected', 'plain');">
+				<a href=""
+					tal:content="tab/Title"
+					tal:attributes="href tab/Taburl;
+					title tab/Description|nothing">
+				Tab Name</a>
+			</li>
+		</tal:tabs>
+	</ul>
 </div>
 
 </body>
--- conga/luci/homebase/portlet_homebase	2006/05/18 17:47:15	1.6
+++ conga/luci/homebase/portlet_homebase	2006/06/20 21:21:47	1.7
@@ -1,22 +1,21 @@
 <html xmlns:tal="http://xml.zope.org/namespaces/tal"
-      xmlns:metal="http://xml.zope.org/namespaces/metal">
+	xmlns:metal="http://xml.zope.org/namespaces/metal">
+
+<head/>
 
 <body>
 
 <tal:comment replace="nothing">
-	$Id: portlet_homebase,v 1.6 2006/05/18 17:47:15 rmccabe Exp $
+	$Id: portlet_homebase,v 1.7 2006/06/20 21:21:47 rmccabe Exp $
 </tal:comment>
 
-<div metal:define-macro="homebase_portlet" tal:condition="python: here.userAuthenticated()">
-	<span tal:omit-tag=""
-		tal:define="global data python:here.homebaseControl(request)" />
-
-	<div tal:condition="python:here.isAdmin()" class="type-node">
-		<dl class="portlet" id="portlet-homebase">
-		<dt class="portletHeader"><a href="#" tal:content="user/getUserName"></a></dt>
+<div metal:define-macro="homebase_portlet">
+	<div class="type-node">
+	<dl class="portlet" id="portlet-homebase">
+	<dt class="portletHeader"><a href="/luci/homebase" tal:content="user/getUserName"></a></dt>
 
-		<dd class="portletItemSingle">
-		<ul class="portletCluConfigTree cluConfigTreeLevel0">
+	<dd class="portletItemSingle">
+	<ul class="portletCluConfigTree cluConfigTreeLevel0">
 		<tal:portal repeat="c python:data.get('children',[])">
 			<li tal:condition="not: c/currentItem" class="cluConfigTreeItem visualNoMarker">
 			<div tal:condition="not: c/currentItem">
@@ -28,17 +27,17 @@
 			</li>
 
 			<li tal:condition="c/currentItem" class="cluConfigTreeCurrentItem visualNoMarker">
-			<div tal:condition="c/currentItem">
-				<a class="visualIconPadding"
-					tal:attributes="href c/absolute_url;
-						title c/Description |nothing"
-					tal:content="c/Title|nothing">Title</a>
-			</div>
+				<div tal:condition="c/currentItem">
+					<a class="visualIconPadding"
+						tal:attributes="href c/absolute_url;
+							title c/Description |nothing"
+						tal:content="c/Title|nothing">Title</a>
+				</div>
 			</li>
 		</tal:portal>
-		</ul>
-		</dd>
-		</dl>
+	</ul>
+	</dd>
+	</dl>
 	</div>
 </div>
 



                 reply	other threads:[~2006-06-20 21:21 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060620212151.9499.qmail@sourceware.org \
    --to=rmccabe@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.