#268: Implement admin component stubs.

This commit is contained in:
Michael Jumper
2013-02-07 01:56:49 -08:00
parent c2d2bdf926
commit fd399ece85
4 changed files with 310 additions and 289 deletions

View File

@@ -41,10 +41,12 @@
on your access level, users can be added and deleted, and their on your access level, users can be added and deleted, and their
passwords can be changed. passwords can be changed.
</p> </p>
<!--
<div class="user"> <div class="user">
<div class="caption"><div class="type"><div class="icon add"/></div><span class="name"><input style="width: 20em; padding: 0.25em" type="text" placeholder="Add user"/></span></div> <div class="caption"><div class="type"><div class="icon add"/></div><span class="name"><input style="width: 20em; padding: 0.25em" type="text" placeholder="Add user"/></span></div>
</div> </div>
-->
</div> </div>
@@ -58,9 +60,11 @@
can be changed. can be changed.
</p> </p>
<!--
<div class="connection"> <div class="connection">
<div class="caption"><div class="protocol"><div class="icon add"/></div><span class="name"><input style="width: 20em; padding: 0.25em" type="text" placeholder="Add connection"/></span></div> <div class="caption"><div class="protocol"><div class="icon add"/></div><span class="name"><input style="width: 20em; padding: 0.25em" type="text" placeholder="Add connection"/></span></div>
</div> </div>
-->
</div> </div>
@@ -68,6 +72,7 @@
Guacamole ${project.version} Guacamole ${project.version}
</div> </div>
<script type="text/javascript" src="scripts/admin.js"></script>
<script type="text/javascript" src="scripts/service.js"></script> <script type="text/javascript" src="scripts/service.js"></script>
<script type="text/javascript" src="scripts/session.js"></script> <script type="text/javascript" src="scripts/session.js"></script>
<script type="text/javascript" src="scripts/history.js"></script> <script type="text/javascript" src="scripts/history.js"></script>
@@ -75,29 +80,10 @@
<script type="text/javascript"><![CDATA[ <script type="text/javascript"><![CDATA[
var connections = document.getElementById("connections");
var users = document.getElementById("users"); var users = document.getElementById("users");
var connection = new GuacamoleService.Connection("vnc", "Test connection"); var user_manager = new GuacAdmin.UserManager();
for (var i=0; i<10; i++) { users.appendChild(user_manager.getElement());
(function() {
var conn = new GuacUI.EditableConnection(connection);
connections.appendChild(conn.getElement());
conn.getElement().onclick = function() {
conn.setEditMode(!conn.edit);
};
})();
(function() {
var user = new GuacUI.EditableUser("testuser");
users.appendChild(user.getElement());
user.getElement().onclick = function() {
user.setEditMode(!user.edit);
};
})();
}
]]></script> ]]></script>

View File

@@ -0,0 +1,267 @@
/*
* Guacamole - Clientless Remote Desktop
* Copyright (C) 2010 Michael Jumper
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Main Guacamole admin namespace.
* @namespace
*/
var GuacAdmin = GuacAdmin || {};
/**
* An arbitrary input field. Note that this object is not a component, and has
* no corresponding element. Other objects which use GuacAdmin.Field may
* interpret its values and render an element, however.
*
* @constructor
* @param {String} title A human-readable title for the field.
* @param {String} type The type of the input field.
* @param {String} value The default value, if any.
*/
GuacAdmin.Field = function(title, type, value) {
/**
* A human-readable title describing this field.
*/
this.title = title;
/**
* The type of this field. Possible values are "text", "password", and
* "checkbox".
*/
this.type = type;
/**
* The default value of this field.
*/
this.value = value;
};
/**
* An arbitrary button. Note that this object is not a component, and has
* no corresponding element. Other objects which use GuacAdmin.Button may
* interpret its values and render an element, however.
*
* @constructor
* @param {String} title A human-readable title for the button.
*/
GuacAdmin.Button = function(title) {
/**
* A human-readable title describing this button.
*/
this.title = title;
};
/**
* An arbitrary table-based form. Given an array of fields and an array
* of buttons, GuacAdmin.Form constructs a clean HTML form using DOM Elements.
*
* @constructor
* @param {GuacAdmin.Field[]} fields An array of all fields to include in the
* form.
* @param {GuacAdmin.Button[]} buttons An array of all buttons to include in the
* form.
*/
GuacAdmin.Form = function(fields, buttons) {
// Main div and fields
var element = GuacUI.createElement("div", "form");
var field_table = GuacUI.createChildElement(element, "table", "fields");
// Buttons
var button_div = GuacUI.createChildElement(element, "div", "object-buttons");
/**
* Returns the DOM element representing this form.
*/
this.getElement = function() {
return element;
};
/*
* Add all fields
*/
var i;
for (i=0; i<fields.length; i++) {
// Get field
var field = fields[i];
// Add elements
var row = GuacUI.createChildElement(field_table, "tr");
var header = GuacUI.createChildElement(row, "th");
var cell = GuacUI.createChildElement(row, "td");
// Set title
header.textContent = field.title;
switch (field.type) {
// HTML types
case "text":
case "password":
case "checkbox":
var input = GuacUI.createChildElement(cell, "input");
// Set type and value
input.setAttribute("type", field.type);
if (field.value) input.setAttribute("value", field.value);
break;
// Connection list
case "connections":
var connection_selector = GuacUI.createChildElement(cell, "div", "connection-list");
break;
}
}
/*
* Add all buttons
*/
for (i=0; i<buttons.length; i++) {
// Add new button
var button = GuacUI.createChildElement(button_div, "button", name);
button.textContent = buttons[i].title;
}
};
/**
* An arbitrary list item with an icon and caption.
*/
GuacAdmin.ListItem = function(type, title) {
// Create connection display elements
var element = GuacUI.createElement("div", "list-item");
var icon = GuacUI.createChildElement(element, "div", "icon");
var name = GuacUI.createChildElement(element, "span", "name");
GuacUI.addClass(icon, type);
// Set name
name.textContent = title;
/**
* Returns the DOM element representing this connection.
*/
this.getElement = function() {
return element;
};
};
/**
* User management component.
* @constructor
*/
GuacAdmin.UserManager = function() {
/**
* Reference to this UserManager.
*/
var user_manager = this;
/**
* Container element for UserManager.
*/
var element = GuacUI.createElement("div", "user-list");
/**
* User property form.
*/
var user_properties = new GuacAdmin.Form(
/* Fields */
[new GuacAdmin.Field("Password:", "password", "12341234"),
new GuacAdmin.Field("Re-enter Password:", "password", "12341234"),
new GuacAdmin.Field("Connections:", "connections")],
/* Buttons */
[new GuacAdmin.Button("Save"),
new GuacAdmin.Button("Cancel"),
new GuacAdmin.Button("Delete")]
);
/**
* Returns the DOM element representing this UserManager.
*/
this.getElement = function() {
return element;
};
/**
* Adds the given username to the users visible within this UserManager.
*/
this.add = function(username) {
// Create and append item
var item = new GuacAdmin.ListItem("user", username);
element.appendChild(item.getElement());
};
/**
* Removes the given username from the users visible within this UserManager.
*/
this.remove = function(username) {
/* STUB */
};
/**
* Sets all visible usernames.
*/
this.setUsers = function(users) {
/* STUB */
};
/**
* Event handler called when the user wishes to add a given user.
*
* @event
* @param {String} username The username added.
*/
this.onadd = null;
/**
* Event handler called when the user wishes to remove a given user.
*
* @event
* @param {String} username The username removed.
*/
this.onremove = null;
/**
* Event handler called when the user has edited a given user, and wishes
* to save the updated user to the server.
*
* @event
* @param {String} username The username edited.
*/
this.onsave = null;
};

View File

@@ -495,218 +495,3 @@ GuacUI.Connection = function(connection) {
}; };
}; };
/**
* An arbitrary table-based form.
*/
GuacUI.Form = function() {
var element = GuacUI.createElement("table");
/**
* Returns the DOM element representing this form.
*/
this.getElement = function() {
return element;
};
this.addField = function(title, type, value) {
// Add elements
var row = GuacUI.createChildElement(element, "tr");
var header = GuacUI.createChildElement(row, "th");
var cell = GuacUI.createChildElement(row, "td");
var input = GuacUI.createChildElement(cell, "input");
// Set title
header.textContent = title;
// Set type and value
input.setAttribute("type", type);
if (value) input.setAttribute("value", value);
};
};
/**
* A user UI object.
*/
GuacUI.User = function(username) {
/**
* This user's username.
*/
this.username = username;
var user_type = "normal";
// Create connection display elements
var element = GuacUI.createElement("div", "user");
var caption = GuacUI.createChildElement(element ,"div", "caption");
var type = GuacUI.createChildElement(caption, "div", "type");
var name = GuacUI.createChildElement(caption, "span", "name");
GuacUI.createChildElement(type, "div", "icon " + user_type);
// Get URL
var url = "user.xhtml?name=" + encodeURIComponent(username);
// Create link to client
element.onclick = function() {
// Attempt to focus existing window
var current = window.open(null, username);
// If window did not already exist, set up as
// Guacamole client
if (!current.GuacUI)
window.open(url, username);
};
// Set name
name.textContent = username;
/**
* Returns the DOM element representing this connection.
*/
this.getElement = function() {
return element;
};
};
/**
* An editable user UI object.
*/
GuacUI.EditableUser = function(username) {
/**
* This user's username.
*/
this.username = username;
/**
* Current status of edit mode.
*/
this.edit = false;
// Create contained user
var user = new GuacUI.User(username);
var element = user.getElement();
GuacUI.addClass(element, "editable");
// Fields
var fields = GuacUI.createChildElement(element, "div", "fields");
var form = new GuacUI.Form();
// Add form
fields.appendChild(form.getElement());
// Add fields
form.addField("Password:", "password", "123412341234");
form.addField("Re-enter Password:", "password", "123412341234");
// Buttons
var buttons = GuacUI.createChildElement(fields, "div", "object-buttons");
var save = GuacUI.createChildElement(buttons, "button", "save");
save.textContent = "Save";
var cancel = GuacUI.createChildElement(buttons, "button", "cancel");
cancel.textContent = "Cancel";
var del = GuacUI.createChildElement(buttons, "button", "delete");
del.textContent = "Delete";
/**
* Returns the DOM element representing this connection.
*/
this.getElement = function() {
return element;
};
/**
* Sets/unsets edit mode. When edit mode is on, the user's properties
* will be visible and editable.
*/
this.setEditMode = function(enabled) {
// Set edit mode
this.edit = enabled;
// Alter class accordingly
if (enabled)
GuacUI.addClass(element, "edit");
else
GuacUI.removeClass(element, "edit");
};
};
/**
* An editable connection UI object.
*/
GuacUI.EditableConnection = function(connection) {
/**
* Current status of edit mode.
*/
this.edit = false;
// Create contained connection
var conn = new GuacUI.Connection(connection);
var element = conn.getElement();
GuacUI.addClass(element, "editable");
// Fields
var fields = GuacUI.createChildElement(element, "div", "fields");
var form = new GuacUI.Form();
// Add form
fields.appendChild(form.getElement());
// Add fields
form.addField("Password:", "password", "123412341234");
form.addField("Re-enter Password:", "password", "123412341234");
// Buttons
var buttons = GuacUI.createChildElement(fields, "div", "object-buttons");
var save = GuacUI.createChildElement(buttons, "button", "save");
save.textContent = "Save";
var cancel = GuacUI.createChildElement(buttons, "button", "cancel");
cancel.textContent = "Cancel";
var del = GuacUI.createChildElement(buttons, "button", "delete");
del.textContent = "Delete";
/**
* Returns the DOM element representing this connection.
*/
this.getElement = function() {
return element;
};
/**
* Sets/unsets edit mode. When edit mode is on, the connection's properties
* will be visible and editable.
*/
this.setEditMode = function(enabled) {
// Set edit mode
this.edit = enabled;
// Alter class accordingly
if (enabled)
GuacUI.addClass(element, "edit");
else
GuacUI.removeClass(element, "edit");
};
};

View File

@@ -152,8 +152,7 @@ div.section {
* List elements * List elements
*/ */
.user, .list-item {
.connection {
display: block; display: block;
text-align: left; text-align: left;
@@ -170,24 +169,7 @@ div.section {
} }
.connection .thumbnail { .list-item .icon {
margin: 0.5em;
display: none;
}
.connection .thumbnail img {
border: 1px solid black;
box-shadow: 1px 1px 5px black;
max-width: 75%;
}
.user .type,
.connection .protocol {
display: inline-block;
}
.user .icon,
.connection .icon {
width: 24px; width: 24px;
height: 24px; height: 24px;
background-size: 16px 16px; background-size: 16px 16px;
@@ -199,19 +181,15 @@ div.section {
opacity: 0.5; opacity: 0.5;
} }
.user .caption, .list-item .icon {
.connection .caption {
display: inline-block; display: inline-block;
vertical-align: top;
} }
.user .caption *, .list-item * {
.connection .caption * {
vertical-align: middle; vertical-align: middle;
} }
.user .name, .list-item .name {
.connection .name {
color: black; color: black;
font-weight: normal; font-weight: normal;
padding: 0.1em; padding: 0.1em;
@@ -219,31 +197,35 @@ div.section {
} }
/* /*
* List element edit / non-edit styling * List element styling
*/ */
.user.edit, .list-item.selected {
.connection.edit {
background: #DEB; background: #DEB;
border: 1px solid rgba(0, 0, 0, 0.25); border: 1px solid rgba(0, 0, 0, 0.25);
} }
.user.edit .icon, .list-item.selected.icon {
.connection.edit .icon {
opacity: 1.0; opacity: 1.0;
} }
.user:not(.edit):hover, .list-item:not(.selected):hover {
.connection:not(.edit):hover {
background: #CDA; background: #CDA;
} }
.disabled .list-item:not(.selected) {
opacity: 0.25;
}
.disabled .list-item:not(.selected):hover {
background: inherit;
}
/* /*
* List element fields (editing) * List element fields (editing)
*/ */
.user .fields, .form {
.connection .fields {
position: absolute; position: absolute;
display: inline-block; display: inline-block;
@@ -264,19 +246,14 @@ div.section {
} }
.user .fields th, .form .fields th {
.connection .fields th {
font-weight: normal; font-weight: normal;
font-size: 0.8em; font-size: 0.8em;
vertical-align: top;
text-align: left;
} }
.user:not(.edit) .fields, .form {
.connection:not(.edit) .fields {
display: none;
}
.user.edit .fields,
.connection.edit .fields {
cursor: auto; cursor: auto;
animation-name: fadein; animation-name: fadein;
-webkit-animation-name: fadein; -webkit-animation-name: fadein;
@@ -284,6 +261,12 @@ div.section {
-webkit-animation-duration: 0.125s; -webkit-animation-duration: 0.125s;
} }
.form .connection-list {
border: 1px solid gray;
min-width: 10em;
min-height: 10em;
}
.object-buttons { .object-buttons {
text-align: right; text-align: right;
@@ -299,28 +282,28 @@ div.section {
* List element icons * List element icons
*/ */
.user .icon { .list-item .icon.user {
background-image: url('../images/user-icons/guac-user.png'); background-image: url('../images/user-icons/guac-user.png');
} }
.user .icon.add { .list-item .icon.user.add {
background-image: url('../images/action-icons/guac-user-add.png'); background-image: url('../images/action-icons/guac-user-add.png');
} }
.protocol .icon { .list-item .icon.connection {
background-image: url('../images/protocol-icons/guac-plug.png'); background-image: url('../images/protocol-icons/guac-plug.png');
} }
.protocol .icon.ssh { .list-item .icon.connection.ssh {
background-image: url('../images/protocol-icons/guac-text.png'); background-image: url('../images/protocol-icons/guac-text.png');
} }
.protocol .icon.add{ .list-item .icon.connection.add {
background-image: url('../images/action-icons/guac-monitor-add.png'); background-image: url('../images/action-icons/guac-monitor-add.png');
} }
.protocol .icon.vnc, .list-item .icon.connection.vnc,
.protocol .icon.rdp { .list-item .icon.connection.rdp {
background-image: url('../images/protocol-icons/guac-monitor.png'); background-image: url('../images/protocol-icons/guac-monitor.png');
} }