Merge "Introduce form-field directive"
This commit is contained in:
commit
8b1d09c454
@ -27,95 +27,44 @@
|
|||||||
'$uibModalInstance',
|
'$uibModalInstance',
|
||||||
'horizon.dashboard.admin.ironic.validMacAddressPattern',
|
'horizon.dashboard.admin.ironic.validMacAddressPattern',
|
||||||
'horizon.dashboard.admin.ironic.validDatapathIdPattern',
|
'horizon.dashboard.admin.ironic.validDatapathIdPattern',
|
||||||
|
'horizon.dashboard.admin.ironic.form-field.service',
|
||||||
'ctrl'
|
'ctrl'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
|
||||||
* @description Utility class for managing form fields
|
|
||||||
*
|
|
||||||
* @param {object} args - Valid properties are:
|
|
||||||
* value - Initial value of the field
|
|
||||||
* required - Does the field require a value
|
|
||||||
* desc - Field description
|
|
||||||
* pattern - Regular expression pattern used to match
|
|
||||||
* valid input values
|
|
||||||
* disabled - Is the field disabled
|
|
||||||
* info - Additional information about the current state of
|
|
||||||
* the field. It will be displayed in a tooltip associated
|
|
||||||
* with the field.
|
|
||||||
*
|
|
||||||
* @return {void}
|
|
||||||
*/
|
|
||||||
function Field(args) {
|
|
||||||
this.value = angular.isDefined(args.value) ? args.value : undefined;
|
|
||||||
this.required = angular.isDefined(args.required) ? args.required : false;
|
|
||||||
this.desc = angular.isDefined(args.desc) ? args.desc : undefined;
|
|
||||||
this.pattern = angular.isDefined(args.pattern)
|
|
||||||
? new RegExp(args.pattern) : undefined;
|
|
||||||
this.disabled = angular.isDefined(args.disabled) ? args.disabled : false;
|
|
||||||
this.info = angular.isDefined(args.info) ? args.info : undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the field has a non-empty value. Note that an
|
|
||||||
* empty value can be either '' or undefined in the case of a
|
|
||||||
* required field
|
|
||||||
*
|
|
||||||
* @return {boolean} Return true if the field has a value
|
|
||||||
*/
|
|
||||||
this.hasValue = function() {
|
|
||||||
return angular.isDefined(this.value) && this.value !== '';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the field has help-text
|
|
||||||
*
|
|
||||||
* @return {boolean} Return true if the field has help text
|
|
||||||
*/
|
|
||||||
this.hasHelpText = function() {
|
|
||||||
return this.desc || this.info;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the help-text associated with this field
|
|
||||||
*
|
|
||||||
* @return {string} Return true if the field has help text
|
|
||||||
*/
|
|
||||||
this.getHelpText = function() {
|
|
||||||
var text = angular.isDefined(this.desc) ? this.desc : '';
|
|
||||||
if (angular.isDefined(this.info)) {
|
|
||||||
if (text !== '') {
|
|
||||||
text += '<br><br>';
|
|
||||||
}
|
|
||||||
text += this.info;
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Utility class used to manage local-link-connection
|
* @description Utility class used to manage local-link-connection
|
||||||
* form fields.
|
* form fields.
|
||||||
*
|
*
|
||||||
|
* @param {string} formFieldService - Provider service for creating
|
||||||
|
* form fields.
|
||||||
* @param {string} validMacAddressPattern - Regular expression
|
* @param {string} validMacAddressPattern - Regular expression
|
||||||
* pattern used to test for valid mac addresses.
|
* pattern used to test for valid mac addresses.
|
||||||
* @param {string} validDatapathIdPattern - Regular expression
|
* @param {string} validDatapathIdPattern - Regular expression
|
||||||
* pattern used to test for valid datapath ids.
|
* pattern used to test for valid datapath ids.
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
function LocalLinkConnectionMgr(validMacAddressPattern,
|
function LocalLinkConnectionMgr(formFieldService,
|
||||||
|
validMacAddressPattern,
|
||||||
validDatapathIdPattern) {
|
validDatapathIdPattern) {
|
||||||
this.port_id = new Field({});
|
var mgr = this;
|
||||||
|
|
||||||
this.switch_id = new Field({
|
mgr.port_id = new formFieldService.FormField(
|
||||||
desc: gettext("MAC address or OpenFlow datapath ID"),
|
{id: 'port_id', title: 'port_id'});
|
||||||
pattern: validMacAddressPattern + '|' + validDatapathIdPattern});
|
|
||||||
|
|
||||||
this.switch_info = new Field({});
|
mgr.switch_id = new formFieldService.FormField(
|
||||||
|
{id: 'switch_id',
|
||||||
|
title: 'switch_id',
|
||||||
|
desc: gettext("MAC address or OpenFlow datapath ID"),
|
||||||
|
pattern: new RegExp(validMacAddressPattern + '|' +
|
||||||
|
validDatapathIdPattern)});
|
||||||
|
|
||||||
this.fields = {
|
mgr.switch_info = new formFieldService.FormField(
|
||||||
port_id: this.port_id,
|
{id: 'switch_info', title: 'switch_info'});
|
||||||
switch_id: this.switch_id,
|
|
||||||
switch_info: this.switch_info
|
mgr.fields = {
|
||||||
|
port_id: mgr.port_id,
|
||||||
|
switch_id: mgr.switch_id,
|
||||||
|
switch_info: mgr.switch_info
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,13 +72,17 @@
|
|||||||
*
|
*
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
this.update = function() {
|
mgr.update = function() {
|
||||||
var required = this.port_id.hasValue() || this.switch_id.hasValue();
|
var required = mgr.port_id.hasValue() || mgr.switch_id.hasValue();
|
||||||
|
mgr.port_id.required = required;
|
||||||
this.port_id.required = required;
|
mgr.switch_id.required = required;
|
||||||
this.switch_id.required = required;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add form field value change handlers
|
||||||
|
angular.forEach(mgr.fields, function(field) {
|
||||||
|
field.change = mgr.update;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate an attribute object that conforms to the format
|
* Generate an attribute object that conforms to the format
|
||||||
* required for port creation using the Ironic client
|
* required for port creation using the Ironic client
|
||||||
@ -138,33 +91,45 @@
|
|||||||
* A value of null is returned if the local-link-connection
|
* A value of null is returned if the local-link-connection
|
||||||
* information is incomplete.
|
* information is incomplete.
|
||||||
*/
|
*/
|
||||||
this.toPortAttr = function() {
|
mgr.toPortAttr = function() {
|
||||||
var attr = null;
|
var attr = null;
|
||||||
if (this.port_id.hasValue() &&
|
if (mgr.port_id.hasValue() &&
|
||||||
this.switch_id.hasValue()) {
|
mgr.switch_id.hasValue()) {
|
||||||
attr = {};
|
attr = {};
|
||||||
attr.port_id = this.port_id.value;
|
attr.port_id = mgr.port_id.value;
|
||||||
attr.switch_id = this.switch_id.value;
|
attr.switch_id = mgr.switch_id.value;
|
||||||
|
|
||||||
if (this.switch_info.hasValue()) {
|
if (mgr.switch_info.hasValue()) {
|
||||||
attr.switch_info = this.switch_info.value;
|
attr.switch_info = mgr.switch_info.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return attr;
|
return attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dis/enable the local-link-connection form fields
|
* @description Set values of form fields;
|
||||||
*
|
*
|
||||||
* @param {boolean} disabled - True if the local-link-connection form
|
* @param {object} values - Dictionary of values indexed by
|
||||||
* fields should be disabled
|
* property-name
|
||||||
* @param {string} reason - Optional reason for the state change
|
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
this.setDisabled = function(disabled, reason) {
|
mgr.setValues = function(values) {
|
||||||
angular.forEach(this.fields, function(field) {
|
angular.forEach(mgr.fields, function(field, propertyName) {
|
||||||
field.disabled = disabled;
|
if (angular.isDefined(values[propertyName])) {
|
||||||
field.info = reason;
|
field.value = values[propertyName];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Disable the local-link-connection form fields.
|
||||||
|
*
|
||||||
|
* @param {string} reason - Optional reason for disabling fields.
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
mgr.disable = function(reason) {
|
||||||
|
angular.forEach(mgr.fields, function(item) {
|
||||||
|
item.disable(reason);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -172,17 +137,35 @@
|
|||||||
function BasePortController($uibModalInstance,
|
function BasePortController($uibModalInstance,
|
||||||
validMacAddressPattern,
|
validMacAddressPattern,
|
||||||
validDatapathIdPattern,
|
validDatapathIdPattern,
|
||||||
|
formFieldService,
|
||||||
ctrl) {
|
ctrl) {
|
||||||
ctrl.port = {
|
ctrl.port = {
|
||||||
address: null,
|
|
||||||
extra: {}
|
extra: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
ctrl.pxeEnabled = new Field({value: 'True'});
|
ctrl.address = new formFieldService.FormField({
|
||||||
|
id: "macAddress",
|
||||||
|
title: gettext("MAC address"),
|
||||||
|
desc: gettext("MAC address for this port. Required."),
|
||||||
|
pattern: new RegExp(validMacAddressPattern),
|
||||||
|
value: null,
|
||||||
|
required: true,
|
||||||
|
autoFocus: true
|
||||||
|
});
|
||||||
|
|
||||||
|
ctrl.pxeEnabled = new formFieldService.FormField({
|
||||||
|
type: "radio",
|
||||||
|
id: "pxeEnabled",
|
||||||
|
title: gettext("PXE enabled"),
|
||||||
|
desc: gettext(
|
||||||
|
"Indicates whether this port should be used when PXE booting this node"),
|
||||||
|
options: ['True', 'False'],
|
||||||
|
value: 'True'});
|
||||||
|
|
||||||
// Object used to manage local-link-connection form fields
|
// Object used to manage local-link-connection form fields
|
||||||
ctrl.localLinkConnection =
|
ctrl.localLinkConnection =
|
||||||
new LocalLinkConnectionMgr(validMacAddressPattern,
|
new LocalLinkConnectionMgr(formFieldService,
|
||||||
|
validMacAddressPattern,
|
||||||
validDatapathIdPattern);
|
validDatapathIdPattern);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,50 +10,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form id="CreatePortForm" name="CreatePortForm">
|
<form id="CreatePortForm" name="CreatePortForm">
|
||||||
<div class="form-group"
|
<form-field field="ctrl.address" form="CreatePortForm"></form-field>
|
||||||
ng-class="{'has-error': CreatePortForm.macAddress.$invalid &&
|
<form-field field="ctrl.pxeEnabled" form="CreatePortForm"></form-field>
|
||||||
CreatePortForm.macAddress.$dirty}">
|
|
||||||
<label for="macAddress"
|
|
||||||
class="control-label"
|
|
||||||
translate>MAC address</label>
|
|
||||||
<span class="hz-icon-required fa fa-asterisk"></span>
|
|
||||||
<div>
|
|
||||||
<input type="text"
|
|
||||||
class="form-control"
|
|
||||||
ng-model="ctrl.port.address"
|
|
||||||
id="macAddress"
|
|
||||||
name="macAddress"
|
|
||||||
ng-required="true"
|
|
||||||
ng-pattern="'([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})'"
|
|
||||||
auto-focus
|
|
||||||
placeholder="{$ ::'MAC address for this port. Required.' | translate $}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div>
|
|
||||||
<label for="pxeEnabled"
|
|
||||||
class="control-label"
|
|
||||||
translate>
|
|
||||||
PXE enabled
|
|
||||||
</label>
|
|
||||||
<span ng-if="ctrl.pxeEnabled.hasHelpText()"
|
|
||||||
class="help-icon"
|
|
||||||
data-container="body"
|
|
||||||
data-html="true"
|
|
||||||
title=""
|
|
||||||
data-toggle="tooltip"
|
|
||||||
data-original-title="{$ ctrl.pxeEnabled.getHelpText() $}">
|
|
||||||
<span class="fa fa-question-circle"></span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="btn-group" id="pxeEnabled">
|
|
||||||
<label class="btn btn-default"
|
|
||||||
ng-model="ctrl.pxeEnabled.value"
|
|
||||||
ng-repeat="opt in ['True', 'False']"
|
|
||||||
ng-disabled="ctrl.pxeEnabled.disabled"
|
|
||||||
uib-btn-radio="opt">{$ opt $}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form id="LocalLinkConnectionForm"
|
<form id="LocalLinkConnectionForm"
|
||||||
@ -61,34 +19,9 @@
|
|||||||
class="well well-sm">
|
class="well well-sm">
|
||||||
<h4 translate>Local link connection</h4>
|
<h4 translate>Local link connection</h4>
|
||||||
<div class="form-group"
|
<div class="form-group"
|
||||||
ng-repeat="(propertyName, propertyObj) in
|
ng-repeat="(propertyName, propertyField) in
|
||||||
ctrl.localLinkConnection.fields"
|
ctrl.localLinkConnection.fields">
|
||||||
ng-class="{'has-error': LocalLinkConnectionForm.{$ propertyName $}.$invalid &&
|
<form-field field="propertyField" form="LocalLinkConnectionForm"></form-field>
|
||||||
LocalLinkConnectionForm.{$ propertyName $}.$dirty}">
|
|
||||||
<label class="control-label"
|
|
||||||
for="{$ propertyName $}">{$ propertyName $}
|
|
||||||
<span ng-if="propertyObj.required"
|
|
||||||
class="hz-icon-required fa fa-asterisk"></span>
|
|
||||||
<span ng-if="propertyObj.hasHelpText()"
|
|
||||||
class="help-icon"
|
|
||||||
data-container="body"
|
|
||||||
title=""
|
|
||||||
data-toggle="tooltip"
|
|
||||||
data-html="true"
|
|
||||||
data-original-title="{$ propertyObj.getHelpText() $}">
|
|
||||||
<span class="fa fa-question-circle"></span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
<input class="form-control"
|
|
||||||
type="text"
|
|
||||||
id="{$ propertyName $}"
|
|
||||||
name="{$ propertyName $}"
|
|
||||||
ng-model="propertyObj.value"
|
|
||||||
ng-required="propertyObj.required"
|
|
||||||
placeholder="{$ propertyObj.desc $}"
|
|
||||||
ng-pattern="propertyObj.pattern"
|
|
||||||
ng-disabled="propertyObj.disabled"
|
|
||||||
ng-change="ctrl.localLinkConnection.update()"/>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@
|
|||||||
var port = angular.copy(ctrl.port);
|
var port = angular.copy(ctrl.port);
|
||||||
port.node_uuid = node.id;
|
port.node_uuid = node.id;
|
||||||
|
|
||||||
|
port.address = ctrl.address.value;
|
||||||
|
|
||||||
var attr = ctrl.localLinkConnection.toPortAttr();
|
var attr = ctrl.localLinkConnection.toPortAttr();
|
||||||
if (attr) {
|
if (attr) {
|
||||||
port.local_link_connection = attr;
|
port.local_link_connection = attr;
|
||||||
|
@ -62,26 +62,22 @@
|
|||||||
node.provision_state === "manageable"));
|
node.provision_state === "manageable"));
|
||||||
|
|
||||||
// Initialize form fields
|
// Initialize form fields
|
||||||
ctrl.port.address = port.address;
|
ctrl.address.value = port.address;
|
||||||
|
if ((node.provision_state === "active" || node.instance_uuid) &&
|
||||||
|
!node.maintenance) {
|
||||||
|
ctrl.address.disable();
|
||||||
|
}
|
||||||
|
|
||||||
ctrl.pxeEnabled.value = port.pxe_enabled ? 'True' : 'False';
|
ctrl.pxeEnabled.value = port.pxe_enabled ? 'True' : 'False';
|
||||||
if (cannotEditConnectivityAttr) {
|
if (cannotEditConnectivityAttr) {
|
||||||
ctrl.pxeEnabled.disabled = true;
|
ctrl.pxeEnabled.disable(UNABLE_TO_UPDATE_CONNECTIVITY_ATTR_MSG);
|
||||||
ctrl.pxeEnabled.info = UNABLE_TO_UPDATE_CONNECTIVITY_ATTR_MSG;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
angular.forEach(
|
ctrl.localLinkConnection.setValues(
|
||||||
['port_id', 'switch_id', 'switch_info'],
|
port.local_link_connection);
|
||||||
function(prop) {
|
|
||||||
if (angular.isDefined(port.local_link_connection[prop])) {
|
|
||||||
ctrl.localLinkConnection[prop].value =
|
|
||||||
port.local_link_connection[prop];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (cannotEditConnectivityAttr) {
|
if (cannotEditConnectivityAttr) {
|
||||||
ctrl.localLinkConnection.setDisabled(
|
ctrl.localLinkConnection.disable(
|
||||||
true,
|
|
||||||
UNABLE_TO_UPDATE_CONNECTIVITY_ATTR_MSG);
|
UNABLE_TO_UPDATE_CONNECTIVITY_ATTR_MSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +93,7 @@
|
|||||||
|
|
||||||
$log.info("Updating port " + JSON.stringify(port));
|
$log.info("Updating port " + JSON.stringify(port));
|
||||||
|
|
||||||
patcher.buildPatch(port.address, ctrl.port.address, "/address");
|
patcher.buildPatch(port.address, ctrl.address.value, "/address");
|
||||||
patcher.buildPatch(port.pxe_enabled ? 'True' : 'False',
|
patcher.buildPatch(port.pxe_enabled ? 'True' : 'False',
|
||||||
ctrl.pxeEnabled.value,
|
ctrl.pxeEnabled.value,
|
||||||
"/pxe_enabled");
|
"/pxe_enabled");
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Cray Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('horizon.dashboard.admin.ironic')
|
||||||
|
.directive('formField', FormField);
|
||||||
|
|
||||||
|
FormField.$inject = [
|
||||||
|
'$timeout',
|
||||||
|
'$compile',
|
||||||
|
'horizon.dashboard.admin.ironic.basePath'
|
||||||
|
];
|
||||||
|
|
||||||
|
function FormField($timeout, $compile, basePath) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
field: '=',
|
||||||
|
form: '='
|
||||||
|
},
|
||||||
|
templateUrl: basePath + '/form-field.html',
|
||||||
|
link: function(scope, element) {
|
||||||
|
// Process the auto-focus attribute
|
||||||
|
if (scope.field.autoFocus) {
|
||||||
|
// Need to defer processing until the DOM is fully instantiated
|
||||||
|
$timeout(function() {
|
||||||
|
var inputs = element.find('input');
|
||||||
|
if (inputs[0]) {
|
||||||
|
inputs.attr('auto-focus', '');
|
||||||
|
$compile(element.contents())(scope);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})();
|
47
ironic_ui/static/dashboard/admin/ironic/form-field.html
Normal file
47
ironic_ui/static/dashboard/admin/ironic/form-field.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<div class="form-group"
|
||||||
|
ng-class="{'has-error': form[field.id].$invalid &&
|
||||||
|
form[field.id].$dirty}">
|
||||||
|
<label for="{$ field.id $}"
|
||||||
|
class="control-label">{$ field.title $}</label>
|
||||||
|
<span ng-if="field.getHelpText()"
|
||||||
|
class="help-icon"
|
||||||
|
data-container="body"
|
||||||
|
data-html="true"
|
||||||
|
title=""
|
||||||
|
data-toggle="tooltip"
|
||||||
|
data-original-title="{$ field.getHelpText() $}">
|
||||||
|
<span class="fa fa-question-circle"></span>
|
||||||
|
</span>
|
||||||
|
<span ng-if="field.required"
|
||||||
|
class="hz-icon-required fa fa-asterisk"></span>
|
||||||
|
<div ng-switch="field.type">
|
||||||
|
<input ng-switch-when="input"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
ng-model="field.value"
|
||||||
|
id="{$ field.id $}"
|
||||||
|
name="{$ field.id $}"
|
||||||
|
ng-required="field.required"
|
||||||
|
ng-disabled="field.disabled"
|
||||||
|
ng-pattern="field.pattern"
|
||||||
|
ng-change="field.change()"
|
||||||
|
placeholder="{$ field.getHelpText() $}"/>
|
||||||
|
<div ng-switch-when="radio"
|
||||||
|
class="btn-group"
|
||||||
|
id="{$ field.id $}">
|
||||||
|
<label class="btn btn-default"
|
||||||
|
ng-model="field.value"
|
||||||
|
ng-repeat="opt in field.options"
|
||||||
|
ng-disabled="field.disabled"
|
||||||
|
uib-btn-radio="opt">{$ opt $}</label>
|
||||||
|
</div>
|
||||||
|
<div ng-switch-when="select">
|
||||||
|
<select id="field.id"
|
||||||
|
class="form-control"
|
||||||
|
ng-disabled="field.disabled"
|
||||||
|
ng-options="{$ field.options $}"
|
||||||
|
ng-model="field.value">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
128
ironic_ui/static/dashboard/admin/ironic/form-field.service.js
Normal file
128
ironic_ui/static/dashboard/admin/ironic/form-field.service.js
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Cray Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('horizon.dashboard.admin.ironic')
|
||||||
|
.factory('horizon.dashboard.admin.ironic.form-field.service',
|
||||||
|
formFieldService);
|
||||||
|
|
||||||
|
function formFieldService() {
|
||||||
|
var service = {
|
||||||
|
FormField: FormField
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Utility class for managing form fields.
|
||||||
|
* Used is association with the form-field directive.
|
||||||
|
*
|
||||||
|
* @param {object} args - Base properties are:
|
||||||
|
* type [string] - Field type. One of: 'input', 'radio', 'select'
|
||||||
|
* id [string] - id/name of the DOM value element
|
||||||
|
* title [string] - Label used to identify the field to the user
|
||||||
|
* options - type == radio [array]:
|
||||||
|
* List of options for a radio field
|
||||||
|
* type == select [string]:
|
||||||
|
* String expression that is passed to ng-options
|
||||||
|
* value - Initial value of the field
|
||||||
|
* required [boolean] - Does the field require a value
|
||||||
|
* desc [string] - Field description
|
||||||
|
* pattern [RegExp] - Regular expression pattern used to match
|
||||||
|
* valid input values
|
||||||
|
* disabled [boolean] - Is the field disabled
|
||||||
|
* info [string] - Additional information about the current state of
|
||||||
|
* the field. It will be displayed in a tooltip
|
||||||
|
* associated with the field.
|
||||||
|
* autoFocus [boolean] - True if the focus should be set to this field. Only
|
||||||
|
* applies to fields of type input.
|
||||||
|
* change [string] - Expression to be evaluated when the value of this
|
||||||
|
* field changes. Only applies to fields of type input.
|
||||||
|
*
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
function FormField(args) {
|
||||||
|
var field = this;
|
||||||
|
field.type = 'input';
|
||||||
|
field.id = undefined;
|
||||||
|
field.title = undefined;
|
||||||
|
field.options = undefined;
|
||||||
|
field.value = undefined;
|
||||||
|
field.required = false;
|
||||||
|
field.desc = undefined;
|
||||||
|
field.pattern = undefined;
|
||||||
|
field.disabled = false;
|
||||||
|
field.info = undefined;
|
||||||
|
field.autoFocus = false;
|
||||||
|
field.change = undefined;
|
||||||
|
|
||||||
|
angular.forEach(args, function(value, arg) {
|
||||||
|
field[arg] = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Test whether the field has a non-empty value.
|
||||||
|
* Note that an empty value can be either '' or undefined in the
|
||||||
|
* case of a required field
|
||||||
|
*
|
||||||
|
* @return {boolean} Return true if the field has a value
|
||||||
|
*/
|
||||||
|
this.hasValue = function() {
|
||||||
|
return angular.isDefined(this.value) && this.value !== '';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Test whether the field has help-text.
|
||||||
|
*
|
||||||
|
* @return {boolean} Return true if the field has help text.
|
||||||
|
*/
|
||||||
|
this.hasHelpText = function() {
|
||||||
|
return angular.isDefined(this.desc) || angular.isDefined(this.info);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Get the help-text associated with this field
|
||||||
|
*
|
||||||
|
* @return {string} Return true if the field has help text
|
||||||
|
*/
|
||||||
|
this.getHelpText = function() {
|
||||||
|
var text = angular.isDefined(this.desc) ? this.desc : '';
|
||||||
|
if (angular.isDefined(this.info)) {
|
||||||
|
if (text !== '') {
|
||||||
|
text += '<br><br>';
|
||||||
|
}
|
||||||
|
text += this.info;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Disable this field.
|
||||||
|
*
|
||||||
|
* @param {string} reason - Optional reason for disabling this field.
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
this.disable = function(reason) {
|
||||||
|
this.disabled = true;
|
||||||
|
if (angular.isDefined(reason)) {
|
||||||
|
this.info = reason;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
})();
|
@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2017 Cray Inc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Unit tests for the form-field service
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe(
|
||||||
|
'horizon.dashboard.admin.ironic.form-field.service',
|
||||||
|
|
||||||
|
function() {
|
||||||
|
var formFieldService;
|
||||||
|
|
||||||
|
beforeEach(module('horizon.dashboard.admin.ironic'));
|
||||||
|
|
||||||
|
beforeEach(inject(function($injector) {
|
||||||
|
formFieldService =
|
||||||
|
$injector.get('horizon.dashboard.admin.ironic.form-field.service');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('defines the form-field service', function() {
|
||||||
|
expect(formFieldService).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('FormField - default construction', function() {
|
||||||
|
var field = new formFieldService.FormField({});
|
||||||
|
|
||||||
|
expect(field.type).toEqual('input');
|
||||||
|
expect(field.id).toBeUndefined();
|
||||||
|
expect(field.title).toBeUndefined();
|
||||||
|
expect(field.options).toBeUndefined();
|
||||||
|
expect(field.value).toBeUndefined();
|
||||||
|
expect(field.required).toBe(false);
|
||||||
|
expect(field.desc).toBeUndefined();
|
||||||
|
expect(field.pattern).toBeUndefined();
|
||||||
|
expect(field.disabled).toBe(false);
|
||||||
|
expect(field.info).toBeUndefined();
|
||||||
|
expect(field.autoFocus).toBe(false);
|
||||||
|
expect(field.change).toBeUndefined();
|
||||||
|
expect(formFieldService).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('FormField - local parameters', function() {
|
||||||
|
var title = "title";
|
||||||
|
var field = new formFieldService.FormField({
|
||||||
|
title: title
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(field.title).toBe(title);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hasValue', function() {
|
||||||
|
var field = new formFieldService.FormField({});
|
||||||
|
expect(field.hasValue()).toBe(false);
|
||||||
|
|
||||||
|
field.value = '';
|
||||||
|
expect(field.hasValue()).toBe(false);
|
||||||
|
|
||||||
|
field.value = null;
|
||||||
|
expect(field.hasValue()).toBe(true);
|
||||||
|
|
||||||
|
field.value = 'True';
|
||||||
|
expect(field.hasValue()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hasHelpText', function() {
|
||||||
|
var field = new formFieldService.FormField({});
|
||||||
|
expect(field.hasHelpText()).toBe(false);
|
||||||
|
expect(field.getHelpText()).toBe('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hasHelpText/getHelpText - desc', function() {
|
||||||
|
var field = new formFieldService.FormField({
|
||||||
|
desc: 'desc'
|
||||||
|
});
|
||||||
|
expect(field.hasHelpText()).toBe(true);
|
||||||
|
expect(field.getHelpText()).toBe('desc');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hasHelpText/getHelpText - info', function() {
|
||||||
|
var field = new formFieldService.FormField({
|
||||||
|
info: 'info'
|
||||||
|
});
|
||||||
|
expect(field.hasHelpText()).toBe(true);
|
||||||
|
expect(field.getHelpText()).toBe('info');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getHelpText - desc/info', function() {
|
||||||
|
var field = new formFieldService.FormField({
|
||||||
|
desc: 'desc',
|
||||||
|
info: 'info'
|
||||||
|
});
|
||||||
|
expect(field.hasHelpText()).toBe(true);
|
||||||
|
expect(field.getHelpText()).toBe('desc<br><br>info');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disable', function() {
|
||||||
|
var field = new formFieldService.FormField({});
|
||||||
|
expect(field.disabled).toBe(false);
|
||||||
|
field.disable();
|
||||||
|
expect(field.disabled).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
Loading…
Reference in New Issue
Block a user