Add new React component 'ThingsboardIcon', a form to select an icon from datakey settings

This commit is contained in:
Mirco Pizzichini 2019-07-03 12:27:58 +02:00
parent 6091f1a8d8
commit dd03bf30d8
6 changed files with 170 additions and 8 deletions

View File

@ -22,13 +22,17 @@ import ReactSchemaForm from './react/json-form-react.jsx';
import jsonFormTemplate from './json-form.tpl.html'; import jsonFormTemplate from './json-form.tpl.html';
import { utils } from 'react-schema-form'; import { utils } from 'react-schema-form';
import MaterialIconsDialogController from './material-icons-dialog.controller';
import materialIconsDialogTemplate from './material-icons-dialog.tpl.html';
export default angular.module('thingsboard.directives.jsonForm', []) export default angular.module('thingsboard.directives.jsonForm', [])
.directive('tbJsonForm', JsonForm) .directive('tbJsonForm', JsonForm)
.controller('MaterialIconsDialogController', MaterialIconsDialogController)
.value('ReactSchemaForm', ReactSchemaForm) .value('ReactSchemaForm', ReactSchemaForm)
.name; .name;
/*@ngInject*/ /*@ngInject*/
function JsonForm($compile, $templateCache, $mdColorPicker) { function JsonForm($compile, $templateCache, $mdColorPicker, $mdDialog, $document) {
var linker = function (scope, element) { var linker = function (scope, element) {
@ -90,6 +94,9 @@ function JsonForm($compile, $templateCache, $mdColorPicker) {
onColorClick: function(event, key, val) { onColorClick: function(event, key, val) {
scope.showColorPicker(event, val); scope.showColorPicker(event, val);
}, },
onIconClick: function(event) {
scope.openIconDialog(event);
},
onToggleFullscreen: function() { onToggleFullscreen: function() {
scope.isFullscreen = !scope.isFullscreen; scope.isFullscreen = !scope.isFullscreen;
scope.formProps.isFullscreen = scope.isFullscreen; scope.formProps.isFullscreen = scope.isFullscreen;
@ -123,6 +130,23 @@ function JsonForm($compile, $templateCache, $mdColorPicker) {
}); });
} }
scope.openIconDialog = function(event) {
$mdDialog.show({
controller: 'MaterialIconsDialogController',
controllerAs: 'vm',
templateUrl: materialIconsDialogTemplate,
parent: angular.element($document[0].body),
locals: {icon: scope.icon},
multiple: true,
fullscreen: true,
targetEvent: event
}).then(function (icon) {
if (event.data && event.data.onValueChanged) {
event.data.onValueChanged(icon);
}
});
}
scope.onFullscreenChanged = function() {} scope.onFullscreenChanged = function() {}
scope.validate = function(){ scope.validate = function(){

View File

@ -131,7 +131,7 @@ class ThingsboardArray extends React.Component {
} }
let forms = this.props.form.items.map(function(form, index){ let forms = this.props.form.items.map(function(form, index){
var copy = this.copyWithIndex(form, i); var copy = this.copyWithIndex(form, i);
return this.props.builder(copy, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder); return this.props.builder(copy, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onIconClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder);
}.bind(this)); }.bind(this));
arrays.push( arrays.push(
<li key={keys[i]} className="list-group-item"> <li key={keys[i]} className="list-group-item">

View File

@ -19,7 +19,7 @@ class ThingsboardFieldSet extends React.Component {
render() { render() {
let forms = this.props.form.items.map(function(form, index){ let forms = this.props.form.items.map(function(form, index){
return this.props.builder(form, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder); return this.props.builder(form, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onIconClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder);
}.bind(this)); }.bind(this));
return ( return (

View File

@ -0,0 +1,134 @@
/*
* Copyright © 2016-2019 The Thingsboard Authors
*
* 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.
*/
import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import ThingsboardBaseComponent from './json-form-base-component.jsx';
import reactCSS from 'reactcss';
import TextField from 'material-ui/TextField';
import IconButton from 'material-ui/IconButton';
class ThingsboardIcon extends React.Component {
constructor(props) {
super(props);
this.onValueChanged = this.onValueChanged.bind(this);
this.onIconClick = this.onIconClick.bind(this);
this.onClear = this.onClear.bind(this);
var icon = props.value ? props.value : '';
this.state = {
icon: icon
};
}
componentDidMount() {
var node = ReactDOM.findDOMNode(this);
var iconContainer = $(node).children('#icon-container');
iconContainer.click(this, function(event) {
event.data.onIconClick(event);
});
}
componentWillUnmount () {
var node = ReactDOM.findDOMNode(this);
var iconContainer = $(node).children('#icon-container');
iconContainer.off( "click" );
}
onValueChanged(value) {
var icon = value;
this.setState({
icon: value
})
this.props.onChange(this.props.form.key, value);
}
onIconClick(event) {
this.props.onIconClick(event);
}
onClear(event) {
if (event) {
event.stopPropagation();
}
this.onValueChanged('');
}
render() {
const styles = reactCSS({
'default': {
clear: {
marginTop: '15px'
},
container: {
display: 'flex'
},
icon: {
display: 'inline-block',
marginRight: '10px',
marginTop: '16px',
marginBottom: 'auto',
cursor: 'pointer',
border: 'solid 1px rgba(0, 0, 0, .27)'
},
iconContainer: {
display: 'flex',
width: '100%'
},
iconText: {
display: 'inline-block',
width: '100%'
},
},
});
var fieldClass = "tb-field";
if (this.props.form.required) {
fieldClass += " tb-required";
}
if (this.state.focused) {
fieldClass += " tb-focused";
}
var pickedIcon = 'more_horiz';
if (this.state.icon != '') {
pickedIcon = this.state.icon;
}
return (
<div style={ styles.container }>
<div id="icon-container" style={ styles.iconContainer }>
<IconButton iconClassName="material-icons" style={ styles.icon }>
{pickedIcon}
</IconButton>
<TextField
className={fieldClass}
floatingLabelText={this.props.form.title}
hintText={this.props.form.placeholder}
errorText={this.props.error}
value={this.state.icon}
disabled={this.props.form.readonly}
style={ styles.iconText } />
</div>
<IconButton iconClassName="material-icons" tooltip="Clear" onTouchTap={this.onClear}>clear</IconButton>
</div>
);
}
}
export default ThingsboardBaseComponent(ThingsboardIcon);

View File

@ -52,6 +52,7 @@ ReactSchemaForm.propTypes = {
option: React.PropTypes.object, option: React.PropTypes.object,
onModelChange: React.PropTypes.func, onModelChange: React.PropTypes.func,
onColorClick: React.PropTypes.func, onColorClick: React.PropTypes.func,
onIconClick: React.PropTypes.func,
onToggleFullscreen: React.PropTypes.func onToggleFullscreen: React.PropTypes.func
} }

View File

@ -32,6 +32,7 @@ import ThingsboardImage from './json-form-image.jsx';
import ThingsboardCheckbox from './json-form-checkbox.jsx'; import ThingsboardCheckbox from './json-form-checkbox.jsx';
import Help from 'react-schema-form/lib/Help'; import Help from 'react-schema-form/lib/Help';
import ThingsboardFieldSet from './json-form-fieldset.jsx'; import ThingsboardFieldSet from './json-form-fieldset.jsx';
import ThingsboardIcon from './json-form-icon.jsx';
import _ from 'lodash'; import _ from 'lodash';
@ -58,11 +59,13 @@ class ThingsboardSchemaForm extends React.Component {
'css': ThingsboardCss, 'css': ThingsboardCss,
'color': ThingsboardColor, 'color': ThingsboardColor,
'rc-select': ThingsboardRcSelect, 'rc-select': ThingsboardRcSelect,
'fieldset': ThingsboardFieldSet 'fieldset': ThingsboardFieldSet,
'icon': ThingsboardIcon
}; };
this.onChange = this.onChange.bind(this); this.onChange = this.onChange.bind(this);
this.onColorClick = this.onColorClick.bind(this); this.onColorClick = this.onColorClick.bind(this);
this.onIconClick = this.onIconClick.bind(this);
this.onToggleFullscreen = this.onToggleFullscreen.bind(this); this.onToggleFullscreen = this.onToggleFullscreen.bind(this);
this.hasConditions = false; this.hasConditions = false;
} }
@ -84,7 +87,7 @@ class ThingsboardSchemaForm extends React.Component {
} }
builder(form, model, index, onChange, onColorClick, onToggleFullscreen, mapper) { builder(form, model, index, onChange, onColorClick, onIconClick, onToggleFullscreen, mapper) {
var type = form.type; var type = form.type;
let Field = this.mapper[type]; let Field = this.mapper[type];
if(!Field) { if(!Field) {
@ -97,7 +100,7 @@ class ThingsboardSchemaForm extends React.Component {
return null; return null;
} }
} }
return <Field model={model} form={form} key={index} onChange={onChange} onColorClick={onColorClick} onToggleFullscreen={onToggleFullscreen} mapper={mapper} builder={this.builder}/> return <Field model={model} form={form} key={index} onChange={onChange} onColorClick={onColorClick} onIconClick={onIconClick} onToggleFullscreen={onToggleFullscreen} mapper={mapper} builder={this.builder}/>
} }
createSchema(theForm) { createSchema(theForm) {
@ -107,7 +110,7 @@ class ThingsboardSchemaForm extends React.Component {
mapper = _.merge(this.mapper, this.props.mapper); mapper = _.merge(this.mapper, this.props.mapper);
} }
let forms = merged.map(function(form, index) { let forms = merged.map(function(form, index) {
return this.builder(form, this.props.model, index, this.onChange, this.onColorClick, this.onToggleFullscreen, mapper); return this.builder(form, this.props.model, index, this.onChange, this.onColorClick, this.onIconClick, this.onToggleFullscreen, mapper);
}.bind(this)); }.bind(this));
let formClass = 'SchemaForm'; let formClass = 'SchemaForm';