Browse Source

Multiple attributes input widget improvement (#2144)

* Extend multiple input widget

* Update multiple attributes widget

* Change bundle, minor changes

* Fix disablefor date input
pull/2163/head
Chantsova Ekaterina 7 years ago
committed by Igor Kulikov
parent
commit
a51c44e5db
  1. 6
      application/src/main/data/json/system/widget_bundles/input_widgets.json
  2. 306
      ui/src/app/widget/lib/multiple-input-widget.js
  3. 76
      ui/src/app/widget/lib/multiple-input-widget.scss
  4. 155
      ui/src/app/widget/lib/multiple-input-widget.tpl.html

6
application/src/main/data/json/system/widget_bundles/input_widgets.json

@ -319,9 +319,9 @@
"resources": [], "resources": [],
"templateHtml": "<tb-multiple-input-widget \n form-id=\"formId\"\n ctx=\"ctx\">\n</tb-multiple-input-widget>", "templateHtml": "<tb-multiple-input-widget \n form-id=\"formId\"\n ctx=\"ctx\">\n</tb-multiple-input-widget>",
"templateCss": "", "templateCss": "",
"controllerScript": "let $scope;\r\nlet settings;\r\nlet attributeService;\r\nlet toast;\r\nlet utils;\r\nlet types;\r\n\r\nself.onInit = function() {\r\n var scope = self.ctx.$scope;\r\n var id = self.ctx.$scope.$injector.get('utils').guid();\r\n scope.formId = \"form-\"+id;\r\n scope.ctx = self.ctx;\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n self.ctx.$scope.$broadcast('multiple-input-data-updated', self.ctx.$scope.formId);\r\n}\r\n", "controllerScript": "let $scope;\r\nlet settings;\r\nlet attributeService;\r\nlet toast;\r\nlet utils;\r\nlet types;\r\n\r\nself.onInit = function() {\r\n var scope = self.ctx.$scope;\r\n var id = self.ctx.$scope.$injector.get('utils').guid();\r\n scope.formId = \"form-\"+id;\r\n scope.ctx = self.ctx;\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n self.ctx.$scope.$broadcast('multiple-input-data-updated', self.ctx.$scope.formId);\r\n}\r\n\r\nself.typeParameters = function() {\r\n return {\r\n maxDatasources: 1\r\n }\r\n}\r\n\r\nself.onResize = function() {\r\n self.ctx.$scope.$broadcast('multiple-input-resize', self.ctx.$scope.formId);\r\n}\r\n",
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"MultipleInput\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Multiple input title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"attributesShared\": {\n \"title\": \"Attributes are 'shared' (default value is 'server')\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\":true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"attributesShared\",\n \"showResultMessage\"\n ]\n}", "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"MultipleInput\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showActionButtons\":{\n \"title\":\"Show action buttons\",\n \"type\":\"boolean\",\n \"default\": true\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\": true\n },\n \"fieldsAlignment\": {\n \"title\": \"Fields alignment\",\n \"type\": \"string\",\n \"default\": \"row\"\n },\n \"fieldsInRow\": {\n \"title\": \"Number of fields in the row\",\n \"type\": \"number\",\n \"default\": \"2\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showActionButtons\",\n \"showResultMessage\",\n {\n \"key\": \"fieldsAlignment\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"row\",\n \"label\": \"Row (default)\"\n },\n {\n \"value\": \"column\",\n \"label\": \"Column\"\n }\n ]\n },\n \"fieldsInRow\"\n ]\n}",
"dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"readOnly\": {\n \"title\": \"Value is read only\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"inputTypeNumber\": {\n \"title\": \"Datakey is a number\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"step\": {\n \"title\": \"Step interval between valid values (only for numbers)\",\n \"type\": \"number\",\n \"default\": \"1\"\n },\n \"icon\": {\n \"title\": \"Icon to show before input cell\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"readOnly\",\n \"inputTypeNumber\",\n \"step\",\n\t\t{\n \t\t\"key\": \"icon\",\n\t\t\t\"type\": \"icon\"\n\t\t},\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n }\n ]\n}\n", "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"dataKeyType\": {\n \"title\": \"Datakey type\",\n \"type\": \"string\",\n \"default\": \"server\"\n },\n \"dataKeyValueType\": {\n \"title\": \"Datakey value type\",\n \"type\": \"string\",\n \"default\": \"string\"\n },\n \"required\": {\n \"title\": \"Value is required\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"isEditable\": {\n \"title\": \"Ability to edit attribute\",\n \"type\": \"string\",\n \"default\": \"editable\"\n },\n \"disabledOnDataKey\": {\n \"title\": \"Disable on false value of another datakey (specify datakey name)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"dataKeyHidden\": {\n \"title\": \"Hide input field\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"step\": {\n \"title\": \"Step interval between values (only for numbers)\",\n \"type\": \"number\",\n \"default\": \"1\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"icon\": {\n \"title\": \"Icon to show before input cell\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"dataKeyType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"server\",\n \"label\": \"Server attribute (default)\"\n },\n {\n \"value\": \"shared\",\n \"label\": \"Shared attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Timeseries\"\n }\n ]\n },\n {\n \"key\": \"dataKeyValueType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"string\",\n \"label\": \"String\"\n },\n {\n \"value\": \"double\",\n \"label\": \"Double\"\n },\n {\n \"value\": \"integer\",\n \"label\": \"Integer\"\n },\n {\n \"value\": \"booleanCheckbox\",\n \"label\": \"Boolean (Checkbox)\"\n },\n {\n \"value\": \"booleanSwitch\",\n \"label\": \"Boolean (Switch)\"\n },\n {\n \"value\": \"dateTime\",\n \"label\": \"Date & Time\"\n },\n {\n \"value\": \"date\",\n \"label\": \"Date\"\n },\n {\n \"value\": \"time\",\n \"label\": \"Time\"\n }\n ]\n },\n \"required\",\n {\n \"key\": \"isEditable\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"editable\",\n \"label\": \"Editable (default)\"\n },\n {\n \"value\": \"disabled\",\n \"label\": \"Disabled\"\n },\n {\n \"value\": \"readonly\",\n \"label\": \"Read-only\"\n }\n ]\n },\n \"disabledOnDataKey\",\n \"dataKeyHidden\",\n \"step\",\n \"requiredErrorMessage\",\n\t\t{\n \t\t\"key\": \"icon\",\n\t\t\t\"type\": \"icon\"\n\t\t}\n ]\n}\n",
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.23592248334107624,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Update Multiple Attributes\",\"dropShadow\":true,\"enableFullscreen\":false,\"enableDataExport\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.23592248334107624,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Update Multiple Attributes\",\"dropShadow\":true,\"enableFullscreen\":false,\"enableDataExport\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
} }
}, },

306
ui/src/app/widget/lib/multiple-input-widget.js

@ -41,25 +41,18 @@ function MultipleInputWidget() {
} }
/*@ngInject*/ /*@ngInject*/
function MultipleInputWidgetController($q, $scope, attributeService, toast, types, utils) { function MultipleInputWidgetController($q, $scope, $translate, attributeService, toast, types, utils) {
var vm = this; var vm = this;
vm.dataKeyDetected = false;
vm.hasAnyChange = false;
vm.entityDetected = false; vm.entityDetected = false;
vm.isValidParameter = true; vm.isAllParametersValid = true;
vm.message = 'No entity selected';
vm.rows = [];
vm.rowIndex = 0;
vm.data = [];
vm.datasources = null; vm.datasources = null;
vm.cellStyle = cellStyle;
vm.textColor = textColor;
vm.discardAll = discardAll; vm.discardAll = discardAll;
vm.inputChanged = inputChanged; vm.inputChanged = inputChanged;
vm.postData = postData; vm.save = save;
$scope.$watch('vm.ctx', function() { $scope.$watch('vm.ctx', function() {
if (vm.ctx && vm.ctx.defaultSubscription) { if (vm.ctx && vm.ctx.defaultSubscription) {
@ -74,127 +67,109 @@ function MultipleInputWidgetController($q, $scope, attributeService, toast, type
$scope.$on('multiple-input-data-updated', function(event, formId) { $scope.$on('multiple-input-data-updated', function(event, formId) {
if (vm.formId == formId) { if (vm.formId == formId) {
updateRowData(vm.subscription.data); updateWidgetData(vm.subscription.data);
$scope.$digest(); $scope.$digest();
} }
}); });
function defaultStyle() { $scope.$on('multiple-input-resize', function(event, formId) {
return {}; if (vm.formId == formId) {
} updateWidgetDisplaying();
function cellStyle(key, rowIndex, firstKey, lastKey) {
var style = {};
if (key) {
var styleInfo = vm.stylesInfo[key.label];
var value = key.currentValue;
if (styleInfo.useCellStyleFunction && styleInfo.cellStyleFunction) {
try {
style = styleInfo.cellStyleFunction(value);
} catch (e) {
style = {};
}
} else {
style = defaultStyle();
}
}
if (vm.settings.rowMargin) {
if (angular.isUndefined(style.marginTop) && rowIndex != 0) {
style.marginTop = (vm.settings.rowMargin / 2) + 'px';
}
if (angular.isUndefined(style.marginBottom)) {
style.marginBottom = (vm.settings.rowMargin / 2) + 'px';
}
}
if (vm.settings.columnMargin) {
if (angular.isUndefined(style.marginLeft) && !firstKey) {
style.marginLeft = (vm.settings.columnMargin / 2) + 'px';
}
if (angular.isUndefined(style.marginRight) && !lastKey) {
style.marginRight = (vm.settings.columnMargin / 2) + 'px';
}
}
return style;
}
function textColor(key) {
var style = {};
if (key) {
var styleInfo = vm.stylesInfo[key.label];
if (styleInfo.color) {
style = { color: styleInfo.color };
}
} }
return style; });
}
function discardAll() { function discardAll() {
for (var r = 0; r < vm.rows.length; r++) { for (var i = 0; i < vm.data.length; i++) {
var row = vm.rows[r]; vm.data[i].data.currentValue = vm.data[i].data.originalValue;
for (var d = 0; d < row.data.length; d++ ) {
row.data[d].currentValue = row.data[d].originalValue;
}
} }
vm.hasAnyChange = false; $scope.multipleInputForm.$setPristine();
} }
function inputChanged() { function inputChanged(key) {
var newValue = false; if (!vm.settings.showActionButtons) {
for (var r = 0; r < vm.rows.length; r++) { if (!key.settings.required || (key.settings.required && key.data && angular.isDefined(key.data.currentValue))) {
var row = vm.rows[r]; vm.save(key);
for (var d = 0; d < row.data.length; d++ ) {
if (!row.data[d].currentValue) {
return;
}
if (row.data[d].currentValue !== row.data[d].originalValue) {
newValue = true;
}
} }
} }
vm.hasAnyChange = newValue;
} }
function postData() { function save(key) {
var promises = []; var tasks = [];
for (var r = 0; r < vm.rows.length; r++) { var serverAttributes = [], sharedAttributes = [], telemetry = [];
var row = vm.rows[r]; var config = {
var datasource = row.datasource; ignoreLoading: !vm.settings.showActionButtons
var attributes = []; };
var newValues = false; var data;
if (key) {
for (var d = 0; d < row.data.length; d++ ) { data = [key];
if (row.data[d].currentValue !== row.data[d].originalValue) { } else {
attributes.push({ data = vm.data;
key : row.data[d].name, }
value : row.data[d].currentValue, for (let i = 0; i < data.length; i++) {
}); var item = data[i];
newValues = true; if (item.data.currentValue !== item.data.originalValue) {
var attribute = {
key: item.name
};
switch (item.settings.dataKeyValueType) {
case 'dateTime':
case 'date':
attribute.value = item.data.currentValue.getTime();
break;
case 'time':
attribute.value = item.data.currentValue.getTime() - moment().startOf('day').valueOf();//eslint-disable-line
break;
default:
attribute.value = item.data.currentValue;
} }
}
if (newValues) { switch (item.settings.dataKeyType) {
promises.push(attributeService.saveEntityAttributes( case 'shared':
datasource.entityType, sharedAttributes.push(attribute);
datasource.entityId, break;
vm.attributeScope, case 'timeseries':
attributes)); telemetry.push(attribute);
break;
default:
serverAttributes.push(attribute);
}
} }
} }
for (let i = 0; i < serverAttributes.length; i++) {
if (promises.length) { tasks.push(attributeService.saveEntityAttributes(
$q.all(promises).then( vm.datasources[0].entityType,
vm.datasources[0].entityId,
types.attributesScope.server.value,
serverAttributes,
config));
}
for (let i = 0; i < sharedAttributes.length; i++) {
tasks.push(attributeService.saveEntityAttributes(
vm.datasources[0].entityType,
vm.datasources[0].entityId,
types.attributesScope.shared.value,
sharedAttributes,
config));
}
for (let i = 0; i < telemetry.length; i++) {
tasks.push(attributeService.saveEntityTimeseries(
vm.datasources[0].entityType,
vm.datasources[0].entityId,
types.latestTelemetry.value,
telemetry,
config));
}
if (tasks.length) {
$q.all(tasks).then(
function success() { function success() {
for (var d = 0; d < row.data.length; d++ ) { $scope.multipleInputForm.$setPristine();
row.data[d].originalValue = row.data[d].currentValue;
}
vm.hasAnyChange = false;
if (vm.settings.showResultMessage) { if (vm.settings.showResultMessage) {
toast.showSuccess('Update successful', 1000, angular.element(vm.ctx.$container), 'bottom left'); toast.showSuccess($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(vm.ctx.$container), 'bottom left');
} }
}, },
function fail() { function fail() {
if (vm.settings.showResultMessage) { if (vm.settings.showResultMessage) {
toast.showError('Update failed', angular.element(vm.ctx.$container), 'bottom left'); toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(vm.ctx.$container), 'bottom left');
} }
} }
); );
@ -211,78 +186,75 @@ function MultipleInputWidgetController($q, $scope, attributeService, toast, type
vm.ctx.widgetTitle = vm.widgetTitle; vm.ctx.widgetTitle = vm.widgetTitle;
vm.attributeScope = vm.settings.attributesShared ? types.attributesScope.shared.value : types.attributesScope.server.value; vm.isVerticalAlignment = !(vm.settings.fieldsAlignment === 'row');
if (!vm.isVerticalAlignment && vm.settings.fieldsInRow) {
vm.inputWidthSettings = 100 / vm.settings.fieldsInRow + '%';
}
} }
function updateDatasources() { function updateDatasources() {
if (vm.datasources && vm.datasources.length) {
var datasource = vm.datasources[0];
if (datasource.type === types.datasourceType.entity) {
for (var i = 0; i < datasource.dataKeys.length; i++) {
if ((datasource.entityType !== types.entityType.device) && (datasource.dataKeys[i].settings.dataKeyType !== 'server')) {
vm.isAllParametersValid = false;
}
vm.data.push(datasource.dataKeys[i]);
vm.data[i].data = {};
}
vm.entityDetected = true;
}
}
}
vm.stylesInfo = {}; function updateWidgetData(data) {
vm.rows = []; for (var i = 0; i < vm.data.length; i++) {
vm.rowIndex = 0; var keyData = data[i].data;
if (keyData && keyData.length) {
if (vm.datasources) { var value;
vm.entityDetected = true; switch (vm.data[i].settings.dataKeyValueType) {
for (var ds = 0; ds < vm.datasources.length; ds++) { case 'dateTime':
var row = {}; case 'date':
var datasource = vm.datasources[ds]; value = moment(keyData[0][1]).toDate(); // eslint-disable-line
row.datasource = datasource; break;
row.data = []; case 'time':
if (datasource.dataKeys) { value = moment().startOf('day').add(keyData[0][1], 'ms').toDate(); // eslint-disable-line
vm.dataKeyDetected = true; break;
for (var a = 0; a < datasource.dataKeys.length; a++ ) { case 'booleanCheckbox':
var dataKey = datasource.dataKeys[a]; case 'booleanSwitch':
value = (keyData[0][1] === 'true');
if (dataKey.units) { break;
dataKey.label += ' (' + dataKey.units + ')'; default:
} value = keyData[0][1];
}
var keySettings = dataKey.settings;
if (keySettings.inputTypeNumber) {
keySettings.inputType = 'number';
} else {
keySettings.inputType = 'text';
}
var cellStyleFunction = null; vm.data[i].data = {
var useCellStyleFunction = false; currentValue: value,
originalValue: value
};
if (keySettings.useCellStyleFunction === true) { if (vm.data[i].settings.isEditable === 'editable' && vm.data[i].settings.disabledOnDataKey) {
if (angular.isDefined(keySettings.cellStyleFunction) && keySettings.cellStyleFunction.length > 0) { var conditions = data.filter((item) => {
try { return item.dataKey.name === vm.data[i].settings.disabledOnDataKey;
cellStyleFunction = new Function('value', keySettings.cellStyleFunction); });
useCellStyleFunction = true; if (conditions && conditions.length) {
} catch (e) { if (conditions[0].data.length) {
cellStyleFunction = null; if (conditions[0].data[0][1] === 'false') {
useCellStyleFunction = false; vm.data[i].settings.disabledOnCondition = true;
} } else {
vm.data[i].settings.disabledOnCondition = !conditions[0].data[0][1];
} }
} }
vm.stylesInfo[dataKey.label] = {
useCellStyleFunction: useCellStyleFunction,
cellStyleFunction: cellStyleFunction,
color: keySettings.color
};
row.data.push(dataKey);
} }
vm.rows.push(row);
} }
} }
} }
} }
function updateRowData(data) { function updateWidgetDisplaying() {
var dataIndex = 0; vm.changeAlignment = (vm.ctx.$container[0].offsetWidth < 620);
for (var r = 0; r < vm.rows.length; r++) { vm.smallWidthContainer = (vm.ctx.$container[0].offsetWidth < 420);
var row = vm.rows[r];
for (var d = 0; d < row.data.length; d++ ) {
var keyData = data[dataIndex++].data;
if (keyData && keyData.length && keyData[0].length > 1) {
row.data[d].currentValue = row.data[d].originalValue = keyData[0][1];
}
}
}
} }
} }

76
ui/src/app/widget/lib/multiple-input-widget.scss

@ -15,15 +15,25 @@
*/ */
.tb-multiple-input { .tb-multiple-input {
height: 100%; height: 100%;
overflow-x: hidden;
overflow-y: auto;
.md-button.md-icon-button { .input-field {
width: 32px; padding-right: 10px;
min-width: 32px;
height: 32px; md-input-container,
min-height: 32px; md-checkbox,
padding: 0 !important; md-switch {
margin: 0; margin-bottom: 5px;
line-height: 20px; }
}
md-checkbox {
margin-top: 22px;
}
md-switch {
margin-top: 20px;
} }
.md-icon-button md-icon { .md-icon-button md-icon {
@ -32,10 +42,56 @@
height: 20px; height: 20px;
min-height: 20px; min-height: 20px;
font-size: 20px; font-size: 20px;
}
.date-time-input {
&__label {
margin-left: 36px;
font-size: 12px;
color: rgba(0, 0, 0, .54);
}
mdp-date-picker,
mdp-time-picker {
width: 100%;
.md-button.md-icon-button {
margin: 5px 0 0;
}
&:not([disabled]) { md-input-container {
color: #f66; width: 100%;
margin: 2px 0;
label {
display: none;
}
}
}
}
.vertical-alignment {
flex-direction: column;
md-checkbox,
md-switch {
margin-top: 18px;
} }
md-switch {
display: flex;
justify-content: space-between;
}
.date-time-input {
&__label {
margin-top: 10px;
}
}
}
.vertically-aligned {
flex-direction: column;
} }
} }

155
ui/src/app/widget/lib/multiple-input-widget.tpl.html

@ -15,53 +15,134 @@
limitations under the License. limitations under the License.
--> -->
<form class="tb-multiple-input" name="multipleInputForm" ng-submit="vm.postData($event)" novalidate> <form class="tb-multiple-input" name="multipleInputForm" ng-submit="vm.save()" novalidate autocomplete="off">
<div style="padding: 0 8px; margin: auto 0;"> <div style="padding: 0 8px; margin: auto 0;">
<div ng-show="vm.entityDetected" layout="row" flex ng-repeat="row in vm.rows" ng-init="rowIndex=$index"> <div ng-show="vm.entityDetected" layout="row" layout-wrap ng-class="{'vertical-alignment': vm.isVerticalAlignment || vm.changeAlignment}">
<div layout="column" flex ng-repeat="key in row.data track by $index" ng-init="keyIndex=$index"> <div ng-repeat="key in vm.data" ng-style="{'width': (vm.isVerticalAlignment || vm.changeAlignment) ? '100%' : vm.inputWidthSettings}">
<md-tooltip class="tb-tooltip-multiline" ng-if="key.settings.tooltipMessage && key.settings.tooltipMessage.length" md-direction="left"> <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'string') && !key.settings.dataKeyHidden">
<span ng-bind-html="key.settings.tooltipMessage"></span> <md-input-container class="md-block">
</md-tooltip> <label>{{key.label}}</label>
<md-input-container class="md-block" ng-style="vm.cellStyle(key, rowIndex, $first, $last)"> <md-icon class="material-icons" ng-if="key.settings.icon">
<label ng-style="vm.textColor(key)">{{key.label}}</label> {{key.settings.icon}}
<md-icon ng-style="vm.textColor(key)" class="material-icons" ng-if="key.settings.icon"> </md-icon>
{{key.settings.icon}} <input name="{{key.name}}"
</md-icon> ng-disabled="(key.settings.isEditable === 'disabled') || key.settings.disabledOnCondition"
<input name="value{{rowIndex}}{{keyIndex}}" ng-readonly="key.settings.isEditable === 'readonly'"
ng-style="vm.textColor(key)" ng-model="key.data.currentValue"
ng-disabled="key.settings.readOnly" ng-required="key.settings.required"
ng-model="key.currentValue" type="text"
min="{{key.settings.min}}" md-select-on-focus
max="{{key.settings.max}}" ng-blur="vm.inputChanged(key)">
ng-required="key.settings.required" <div ng-messages="multipleInputForm[key.name].$error">
type="{{key.settings.inputType}}" <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
step="{{key.settings.step}}" </div>
md-select-on-focus </md-input-container>
ng-change="vm.inputChanged()"> </div>
<div ng-messages="multipleInputForm['value' + rowIndex + keyIndex].$error"> <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'double') && !key.settings.dataKeyHidden">
<div ng-message="min">Value must be greater than {{key.settings.min}}</div> <md-input-container class="md-block">
<div ng-message="max">Value must be lower than {{key.settings.max}}</div> <label>{{key.label}}</label>
<div ng-message="required">This field is required</div> <md-icon class="material-icons" ng-if="key.settings.icon">
{{key.settings.icon}}
</md-icon>
<input name="{{key.name}}"
ng-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
ng-readonly="key.settings.isEditable === 'readonly'"
ng-model="key.data.currentValue"
ng-required="key.settings.required"
type="number"
step="key.settings.step"
md-select-on-focus
ng-blur="vm.inputChanged(key)">
<div ng-messages="multipleInputForm[key.name].$error">
<div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
</div>
</md-input-container>
</div>
<div class="input-field" ng-if="(key.settings.dataKeyValueType === 'integer') && !key.settings.dataKeyHidden">
<md-input-container class="md-block">
<label>{{key.label}}</label>
<md-icon class="material-icons" ng-if="key.settings.icon">
{{key.settings.icon}}
</md-icon>
<input name="{{key.name}}"
ng-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
ng-readonly="key.settings.isEditable === 'readonly'"
ng-model="key.data.currentValue"
ng-required="key.settings.required"
type="number"
step="key.settings.step"
md-select-on-focus
ng-pattern="/^-?[0-9]+$/"
ng-blur="vm.inputChanged(key)">
<div ng-messages="multipleInputForm[key.name].$error">
<div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
<div translate ng-message="pattern">value.invalid-integer-value</div>
</div>
</md-input-container>
</div>
<div class="input-field" ng-if="(key.settings.dataKeyValueType === 'booleanCheckbox') && !key.settings.dataKeyHidden" class="md-block">
<md-checkbox name="{{key.name}}"
ng-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
ng-model="key.data.currentValue"
ng-change="vm.inputChanged(key)">
{{key.label}}
</md-checkbox>
</div>
<div class="input-field" ng-if="(key.settings.dataKeyValueType === 'booleanSwitch') && !key.settings.dataKeyHidden" class="md-block">
<md-switch name="{{key.name}}"
ng-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
ng-model="key.data.currentValue"
ng-change="vm.inputChanged(key)"
aria-label="{{key.label}}"
md-invert>
{{key.label}}
</md-switch>
</div>
<div ng-if="(key.settings.dataKeyValueType === 'dateTime') ||
(key.settings.dataKeyValueType === 'date') ||
(key.settings.dataKeyValueType === 'time') && !key.settings.dataKeyHidden"
class="md-block input-field date-time-input" layout="column">
<label class="date-time-input__label">{{key.label}}</label>
<div layout="row" ng-class="{'vertically-aligned': vm.smallWidthContainer}">
<mdp-date-picker name="{{key.name + 'Date'}}"
ng-if="key.settings.dataKeyValueType !== 'time'"
mdp-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
ng-model="key.data.currentValue"
ng-change="vm.inputChanged(key)"
mdp-placeholder="{{ 'widgets.input-widgets.date' | translate }}">
<div ng-messages="multipleInputForm[key.name].$error">
<div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
</div>
</mdp-date-picker>
<mdp-time-picker name="{{key.name + 'Time'}}"
ng-if="key.settings.dataKeyValueType !== 'date'"
mdp-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
ng-model="key.data.currentValue"
ng-change="vm.inputChanged(key)"
mdp-placeholder="{{ 'widgets.input-widgets.time' | translate }}"
mdp-auto-switch="true">
<div ng-messages="multipleInputForm[key.name].$error">
<div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
</div>
</mdp-time-picker>
</div> </div>
</md-input-container> </div>
</div> </div>
</div> </div>
<div style="text-align: center; font-size: 18px; color: #a0a0a0;" ng-hide="vm.entityDetected" ng-bind="vm.message" <div style="text-align: center; font-size: 18px; color: #a0a0a0;" ng-hide="vm.entityDetected">
></div> {{ 'widgets.input-widgets.no-entity-selected' | translate }}
<div style="text-align: center; font-size: 18px; color: #a0a0a0;" ng-show="vm.entityDetected && !vm.dataKeyDetected">
No attribute is selected
</div> </div>
<div style="text-align: center; font-size: 18px; color: #a0a0a0;" ng-show="vm.entityDetected && !vm.isValidParameter"> <div style="text-align: center; font-size: 18px; color: #a0a0a0;" ng-show="vm.entityDetected && !vm.isAllParametersValid">
Timeseries parameter cannot be used in this widget {{ 'widgets.input-widgets.not-allowed-entity' | translate }}
</div> </div>
</div> </div>
<div class="md-padding" layout="row" layout-align="end center" ng-show="vm.entityDetected && vm.dataKeyDetected"> <div class="md-padding" layout="row" layout-align="end center" ng-if="vm.entityDetected && vm.settings.showActionButtons">
<md-button class="md-primary" ng-click="vm.discardAll()" style="max-height: 50px;margin-right:20px;" ng-disabled="!vm.hasAnyChange"> <md-button class="md-primary" ng-click="vm.discardAll()" style="max-height: 50px; margin-right:20px;" ng-disabled="!multipleInputForm.$dirty">
{{ 'action.undo' | translate }} {{ 'action.undo' | translate }}
</md-button> </md-button>
<md-button class="md-raised md-primary" type="submit" value="Submit" style="max-height: 50px;margin-right:20px;" <md-button class="md-raised md-primary" type="submit" value="Submit" style="max-height: 50px; margin-right:20px;"
ng-disabled="!vm.hasAnyChange || multipleInputForm.$invalid" ng-click="vm.isFocused = false"> ng-disabled="!multipleInputForm.$dirty || multipleInputForm.$invalid" ng-click="vm.isFocused = false">
{{ 'action.save' | translate }} {{ 'action.save' | translate }}
</md-button> </md-button>
</div> </div>

Loading…
Cancel
Save