Commit dd03bf30d88eea55564914d1f0503456cb360e5c

Authored by Mirco Pizzichini
1 parent 6091f1a8

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

... ... @@ -22,13 +22,17 @@ import ReactSchemaForm from './react/json-form-react.jsx';
22 22 import jsonFormTemplate from './json-form.tpl.html';
23 23 import { utils } from 'react-schema-form';
24 24
  25 +import MaterialIconsDialogController from './material-icons-dialog.controller';
  26 +import materialIconsDialogTemplate from './material-icons-dialog.tpl.html';
  27 +
25 28 export default angular.module('thingsboard.directives.jsonForm', [])
26 29 .directive('tbJsonForm', JsonForm)
  30 + .controller('MaterialIconsDialogController', MaterialIconsDialogController)
27 31 .value('ReactSchemaForm', ReactSchemaForm)
28 32 .name;
29 33
30 34 /*@ngInject*/
31   -function JsonForm($compile, $templateCache, $mdColorPicker) {
  35 +function JsonForm($compile, $templateCache, $mdColorPicker, $mdDialog, $document) {
32 36
33 37 var linker = function (scope, element) {
34 38
... ... @@ -90,6 +94,9 @@ function JsonForm($compile, $templateCache, $mdColorPicker) {
90 94 onColorClick: function(event, key, val) {
91 95 scope.showColorPicker(event, val);
92 96 },
  97 + onIconClick: function(event) {
  98 + scope.openIconDialog(event);
  99 + },
93 100 onToggleFullscreen: function() {
94 101 scope.isFullscreen = !scope.isFullscreen;
95 102 scope.formProps.isFullscreen = scope.isFullscreen;
... ... @@ -123,6 +130,23 @@ function JsonForm($compile, $templateCache, $mdColorPicker) {
123 130 });
124 131 }
125 132
  133 + scope.openIconDialog = function(event) {
  134 + $mdDialog.show({
  135 + controller: 'MaterialIconsDialogController',
  136 + controllerAs: 'vm',
  137 + templateUrl: materialIconsDialogTemplate,
  138 + parent: angular.element($document[0].body),
  139 + locals: {icon: scope.icon},
  140 + multiple: true,
  141 + fullscreen: true,
  142 + targetEvent: event
  143 + }).then(function (icon) {
  144 + if (event.data && event.data.onValueChanged) {
  145 + event.data.onValueChanged(icon);
  146 + }
  147 + });
  148 + }
  149 +
126 150 scope.onFullscreenChanged = function() {}
127 151
128 152 scope.validate = function(){
... ...
... ... @@ -131,7 +131,7 @@ class ThingsboardArray extends React.Component {
131 131 }
132 132 let forms = this.props.form.items.map(function(form, index){
133 133 var copy = this.copyWithIndex(form, i);
134   - return this.props.builder(copy, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder);
  134 + 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);
135 135 }.bind(this));
136 136 arrays.push(
137 137 <li key={keys[i]} className="list-group-item">
... ...
... ... @@ -19,7 +19,7 @@ class ThingsboardFieldSet extends React.Component {
19 19
20 20 render() {
21 21 let forms = this.props.form.items.map(function(form, index){
22   - return this.props.builder(form, this.props.model, index, this.props.onChange, this.props.onColorClick, this.props.onToggleFullscreen, this.props.mapper, this.props.builder);
  22 + 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);
23 23 }.bind(this));
24 24
25 25 return (
... ...
  1 +/*
  2 + * Copyright © 2016-2019 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +import $ from 'jquery';
  17 +import React from 'react';
  18 +import ReactDOM from 'react-dom';
  19 +import ThingsboardBaseComponent from './json-form-base-component.jsx';
  20 +import reactCSS from 'reactcss';
  21 +import TextField from 'material-ui/TextField';
  22 +import IconButton from 'material-ui/IconButton';
  23 +
  24 +class ThingsboardIcon extends React.Component {
  25 +
  26 + constructor(props) {
  27 + super(props);
  28 + this.onValueChanged = this.onValueChanged.bind(this);
  29 + this.onIconClick = this.onIconClick.bind(this);
  30 + this.onClear = this.onClear.bind(this);
  31 + var icon = props.value ? props.value : '';
  32 + this.state = {
  33 + icon: icon
  34 + };
  35 + }
  36 +
  37 + componentDidMount() {
  38 + var node = ReactDOM.findDOMNode(this);
  39 + var iconContainer = $(node).children('#icon-container');
  40 + iconContainer.click(this, function(event) {
  41 + event.data.onIconClick(event);
  42 + });
  43 + }
  44 +
  45 + componentWillUnmount () {
  46 + var node = ReactDOM.findDOMNode(this);
  47 + var iconContainer = $(node).children('#icon-container');
  48 + iconContainer.off( "click" );
  49 + }
  50 +
  51 + onValueChanged(value) {
  52 + var icon = value;
  53 +
  54 + this.setState({
  55 + icon: value
  56 + })
  57 + this.props.onChange(this.props.form.key, value);
  58 + }
  59 +
  60 + onIconClick(event) {
  61 + this.props.onIconClick(event);
  62 + }
  63 +
  64 + onClear(event) {
  65 + if (event) {
  66 + event.stopPropagation();
  67 + }
  68 + this.onValueChanged('');
  69 + }
  70 +
  71 + render() {
  72 +
  73 + const styles = reactCSS({
  74 + 'default': {
  75 + clear: {
  76 + marginTop: '15px'
  77 + },
  78 + container: {
  79 + display: 'flex'
  80 + },
  81 + icon: {
  82 + display: 'inline-block',
  83 + marginRight: '10px',
  84 + marginTop: '16px',
  85 + marginBottom: 'auto',
  86 + cursor: 'pointer',
  87 + border: 'solid 1px rgba(0, 0, 0, .27)'
  88 + },
  89 + iconContainer: {
  90 + display: 'flex',
  91 + width: '100%'
  92 + },
  93 + iconText: {
  94 + display: 'inline-block',
  95 + width: '100%'
  96 + },
  97 + },
  98 + });
  99 +
  100 + var fieldClass = "tb-field";
  101 + if (this.props.form.required) {
  102 + fieldClass += " tb-required";
  103 + }
  104 + if (this.state.focused) {
  105 + fieldClass += " tb-focused";
  106 + }
  107 +
  108 + var pickedIcon = 'more_horiz';
  109 + if (this.state.icon != '') {
  110 + pickedIcon = this.state.icon;
  111 + }
  112 +
  113 + return (
  114 + <div style={ styles.container }>
  115 + <div id="icon-container" style={ styles.iconContainer }>
  116 + <IconButton iconClassName="material-icons" style={ styles.icon }>
  117 + {pickedIcon}
  118 + </IconButton>
  119 + <TextField
  120 + className={fieldClass}
  121 + floatingLabelText={this.props.form.title}
  122 + hintText={this.props.form.placeholder}
  123 + errorText={this.props.error}
  124 + value={this.state.icon}
  125 + disabled={this.props.form.readonly}
  126 + style={ styles.iconText } />
  127 + </div>
  128 + <IconButton iconClassName="material-icons" tooltip="Clear" onTouchTap={this.onClear}>clear</IconButton>
  129 + </div>
  130 + );
  131 + }
  132 +}
  133 +
  134 +export default ThingsboardBaseComponent(ThingsboardIcon);
... ...
... ... @@ -52,6 +52,7 @@ ReactSchemaForm.propTypes = {
52 52 option: React.PropTypes.object,
53 53 onModelChange: React.PropTypes.func,
54 54 onColorClick: React.PropTypes.func,
  55 + onIconClick: React.PropTypes.func,
55 56 onToggleFullscreen: React.PropTypes.func
56 57 }
57 58
... ...
... ... @@ -32,6 +32,7 @@ import ThingsboardImage from './json-form-image.jsx';
32 32 import ThingsboardCheckbox from './json-form-checkbox.jsx';
33 33 import Help from 'react-schema-form/lib/Help';
34 34 import ThingsboardFieldSet from './json-form-fieldset.jsx';
  35 +import ThingsboardIcon from './json-form-icon.jsx';
35 36
36 37 import _ from 'lodash';
37 38
... ... @@ -58,11 +59,13 @@ class ThingsboardSchemaForm extends React.Component {
58 59 'css': ThingsboardCss,
59 60 'color': ThingsboardColor,
60 61 'rc-select': ThingsboardRcSelect,
61   - 'fieldset': ThingsboardFieldSet
  62 + 'fieldset': ThingsboardFieldSet,
  63 + 'icon': ThingsboardIcon
62 64 };
63 65
64 66 this.onChange = this.onChange.bind(this);
65 67 this.onColorClick = this.onColorClick.bind(this);
  68 + this.onIconClick = this.onIconClick.bind(this);
66 69 this.onToggleFullscreen = this.onToggleFullscreen.bind(this);
67 70 this.hasConditions = false;
68 71 }
... ... @@ -84,7 +87,7 @@ class ThingsboardSchemaForm extends React.Component {
84 87 }
85 88
86 89
87   - builder(form, model, index, onChange, onColorClick, onToggleFullscreen, mapper) {
  90 + builder(form, model, index, onChange, onColorClick, onIconClick, onToggleFullscreen, mapper) {
88 91 var type = form.type;
89 92 let Field = this.mapper[type];
90 93 if(!Field) {
... ... @@ -97,7 +100,7 @@ class ThingsboardSchemaForm extends React.Component {
97 100 return null;
98 101 }
99 102 }
100   - return <Field model={model} form={form} key={index} onChange={onChange} onColorClick={onColorClick} onToggleFullscreen={onToggleFullscreen} mapper={mapper} builder={this.builder}/>
  103 + return <Field model={model} form={form} key={index} onChange={onChange} onColorClick={onColorClick} onIconClick={onIconClick} onToggleFullscreen={onToggleFullscreen} mapper={mapper} builder={this.builder}/>
101 104 }
102 105
103 106 createSchema(theForm) {
... ... @@ -107,7 +110,7 @@ class ThingsboardSchemaForm extends React.Component {
107 110 mapper = _.merge(this.mapper, this.props.mapper);
108 111 }
109 112 let forms = merged.map(function(form, index) {
110   - return this.builder(form, this.props.model, index, this.onChange, this.onColorClick, this.onToggleFullscreen, mapper);
  113 + return this.builder(form, this.props.model, index, this.onChange, this.onColorClick, this.onIconClick, this.onToggleFullscreen, mapper);
111 114 }.bind(this));
112 115
113 116 let formClass = 'SchemaForm';
... ... @@ -158,4 +161,4 @@ class ThingsboardSchemaGroup extends React.Component{
158 161 <div style={{padding: '20px'}} className={this.state.showGroup?"":"invisible"}>{this.props.forms}</div>
159 162 </section>);
160 163 }
161   -}
\ No newline at end of file
  164 +}
... ...