GUAC-1160: Add a Form type. Allow the content of a guacForm to be a Form, Field, or an array of either.

This commit is contained in:
Michael Jumper
2015-04-16 16:50:05 -07:00
parent 60de1ff993
commit 2858944f27
5 changed files with 160 additions and 14 deletions

View File

@@ -44,11 +44,12 @@ angular.module('form').directive('guacForm', [function form() {
namespace : '=',
/**
* The fields to display.
* The form content to display. This may be a form, an array of
* forms, or a simple array of fields.
*
* @type Field[]
* @type Form[]|Form|Field[]|Field
*/
fields : '=',
content : '=',
/**
* The object which will receive all field values. Each field value
@@ -66,6 +67,13 @@ angular.module('form').directive('guacForm', [function form() {
// Required services
var translationStringService = $injector.get('translationStringService');
/**
* The array of all forms to display.
*
* @type Form[]
*/
$scope.forms = [];
/**
* The object which will receive all field values. Normally, this
* will be the object provided within the "model" attribute. If
@@ -77,6 +85,30 @@ angular.module('form').directive('guacForm', [function form() {
*/
$scope.values = {};
/**
* Produces the translation string for the section header of the
* given form. The translation string will be of the form:
*
* <code>NAMESPACE.SECTION_HEADER_NAME<code>
*
* where <code>NAMESPACE</code> is the namespace provided to the
* directive and <code>NAME</code> is the form name transformed
* via translationStringService.canonicalize().
*
* @param {Form} form
* The form for which to produce the translation string.
*
* @returns {String}
* The translation string which produces the translated header
* of the form.
*/
$scope.getSectionHeader = function getSectionHeader(form) {
return translationStringService.canonicalize($scope.namespace || 'MISSING_NAMESPACE')
+ '.SECTION_HEADER_' + translationStringService.canonicalize(form.name);
};
/**
* Produces the translation string for the header of the given
* field. The translation string will be of the form:
@@ -101,6 +133,46 @@ angular.module('form').directive('guacForm', [function form() {
};
/**
* Determines whether the given object is a form, under the
* assumption that the object is either a form or a field.
*
* @param {Form|Field} obj
* The object to test.
*
* @returns {Boolean}
* true if the given object appears to be a form, false
* otherwise.
*/
var isForm = function isForm(obj) {
return !!('name' in obj && 'fields' in obj);
};
// Produce set of forms from any given content
$scope.$watch('content', function setContent(content) {
// If no content provided, there are no forms
if (!content) {
$scope.forms = [];
return;
}
// Ensure content is an array
if (!angular.isArray(content))
content = [content];
// If content is an array of fields, convert to an array of forms
if (content.length && !isForm(content[0])) {
content = [{
fields : content
}];
}
// Content is now an array of forms
$scope.forms = content;
});
// Update string value and re-assign to model when field is changed
$scope.$watch('model', function setModel(model) {

View File

@@ -20,7 +20,7 @@
* THE SOFTWARE.
*/
table.form th {
.form table.fields th {
text-align: left;
font-weight: normal;
padding-right: 1em;

View File

@@ -1,4 +1,4 @@
<table class="form">
<div ng-repeat="form in forms" class="form">
<!--
Copyright 2015 Glyptodon LLC.
@@ -21,12 +21,17 @@
THE SOFTWARE.
-->
<!-- All fields in form -->
<tr ng-repeat="field in fields">
<th>{{getFieldHeader(field) | translate}}</th>
<td>
<guac-form-field namespace="namespace" field="field" model="values[field.name]"></guac-form-field>
</td>
</tr>
<!-- Form name -->
<h3 ng-show="form.name">{{getSectionHeader(form) | translate}}</h3>
</table>
<!-- All fields in form -->
<table class="fields">
<tr ng-repeat="field in form.fields">
<th>{{getFieldHeader(field) | translate}}</th>
<td>
<guac-form-field namespace="namespace" field="field" model="values[field.name]"></guac-form-field>
</td>
</tr>
</table>
</div>

View File

@@ -61,7 +61,7 @@ THE SOFTWARE.
<h2 class="header">{{'MANAGE_CONNECTION.SECTION_HEADER_PARAMETERS' | translate}}</h2>
<div class="section connection-parameters" ng-class="{loading: !parameters}">
<guac-form namespace="getNamespace(connection.protocol)"
fields="protocols[connection.protocol].parameters"
content="protocols[connection.protocol].parameters"
model="parameters"></guac-form>
</div>

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2014 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Service which defines the Form class.
*/
angular.module('rest').factory('Form', [function defineForm() {
/**
* The object returned by REST API calls when representing the data
* associated with a form or set of configuration parameters.
*
* @constructor
* @param {Form|Object} [template={}]
* The object whose properties should be copied within the new
* Form.
*/
var Form = function Form(template) {
// Use empty object by default
template = template || {};
/**
* The name which uniquely identifies this parameter, or null if this
* field has no name.
*
* @type String
*/
this.name = template.name;
/**
* A human-readable name for this form, or null if this form has no
* name.
*
* @type String
*/
this.title = template.title;
/**
* All fields contained within this form.
*
* @type Field[]
*/
this.fields = template.fields || [];
};
return Form;
}]);