Add new React component 'ThingsboardIcon', a form to select an icon from datakey settings
This commit is contained in:
parent
6091f1a8d8
commit
dd03bf30d8
@ -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(){
|
||||||
|
|||||||
@ -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">
|
||||||
|
|||||||
@ -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 (
|
||||||
|
|||||||
134
ui/src/app/components/react/json-form-icon.jsx
Normal file
134
ui/src/app/components/react/json-form-icon.jsx
Normal 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);
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user