From 2858944f27bb1743c1cb91ca0dcac8a7c30231ed Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 16 Apr 2015 16:50:05 -0700 Subject: [PATCH] GUAC-1160: Add a Form type. Allow the content of a guacForm to be a Form, Field, or an array of either. --- .../main/webapp/app/form/directives/form.js | 78 ++++++++++++++++++- .../src/main/webapp/app/form/styles/form.css | 2 +- .../main/webapp/app/form/templates/form.html | 23 +++--- .../manage/templates/manageConnection.html | 2 +- .../src/main/webapp/app/rest/types/Form.js | 69 ++++++++++++++++ 5 files changed, 160 insertions(+), 14 deletions(-) create mode 100644 guacamole/src/main/webapp/app/rest/types/Form.js diff --git a/guacamole/src/main/webapp/app/form/directives/form.js b/guacamole/src/main/webapp/app/form/directives/form.js index fbe5af881..8623e6f57 100644 --- a/guacamole/src/main/webapp/app/form/directives/form.js +++ b/guacamole/src/main/webapp/app/form/directives/form.js @@ -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: + * + * NAMESPACE.SECTION_HEADER_NAME + * + * where NAMESPACE is the namespace provided to the + * directive and NAME 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) { diff --git a/guacamole/src/main/webapp/app/form/styles/form.css b/guacamole/src/main/webapp/app/form/styles/form.css index 1c37abbb3..0e5228089 100644 --- a/guacamole/src/main/webapp/app/form/styles/form.css +++ b/guacamole/src/main/webapp/app/form/styles/form.css @@ -20,7 +20,7 @@ * THE SOFTWARE. */ -table.form th { +.form table.fields th { text-align: left; font-weight: normal; padding-right: 1em; diff --git a/guacamole/src/main/webapp/app/form/templates/form.html b/guacamole/src/main/webapp/app/form/templates/form.html index 5f93f52cf..962ce4931 100644 --- a/guacamole/src/main/webapp/app/form/templates/form.html +++ b/guacamole/src/main/webapp/app/form/templates/form.html @@ -1,4 +1,4 @@ - +
- -
- - - + +

{{getSectionHeader(form) | translate}}

-
{{getFieldHeader(field) | translate}} - -
+ + + + + + +
{{getFieldHeader(field) | translate}} + +
+ + diff --git a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html index 0a8635b56..d14b98255 100644 --- a/guacamole/src/main/webapp/app/manage/templates/manageConnection.html +++ b/guacamole/src/main/webapp/app/manage/templates/manageConnection.html @@ -61,7 +61,7 @@ THE SOFTWARE.

{{'MANAGE_CONNECTION.SECTION_HEADER_PARAMETERS' | translate}}

diff --git a/guacamole/src/main/webapp/app/rest/types/Form.js b/guacamole/src/main/webapp/app/rest/types/Form.js new file mode 100644 index 000000000..a402ccc07 --- /dev/null +++ b/guacamole/src/main/webapp/app/rest/types/Form.js @@ -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; + +}]);