Merge pull request #5733 from vvlladd28/bugs/json-form/full-screen
[3.3.3] UI: Fixed incorrect work buttons in fullscreen mode at json-form
This commit is contained in:
		
						commit
						2caa534802
					
				@ -15,8 +15,9 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<div class="tb-json-form" style="background: #fff;" tb-fullscreen [fullscreenElement]="targetFullscreenElement"
 | 
			
		||||
<div class="tb-json-form" style="background: #fff;" tb-fullscreen [fullscreenElement]="reactFullscreen"
 | 
			
		||||
     [fullscreen]="isFullscreen"
 | 
			
		||||
     (fullscreenChanged)="onFullscreenChanged($event)">
 | 
			
		||||
  <div #reactRoot></div>
 | 
			
		||||
  <div class="tb-json-form" #reactFullscreen></div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -73,6 +73,9 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
 | 
			
		||||
  @ViewChild('reactRoot', {static: true})
 | 
			
		||||
  reactRootElmRef: ElementRef<HTMLElement>;
 | 
			
		||||
 | 
			
		||||
  @ViewChild('reactFullscreen', {static: true})
 | 
			
		||||
  reactFullscreenElmRef: ElementRef<HTMLElement>;
 | 
			
		||||
 | 
			
		||||
  private readonlyValue: boolean;
 | 
			
		||||
  get readonly(): boolean {
 | 
			
		||||
    return this.readonlyValue;
 | 
			
		||||
@ -106,8 +109,7 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
 | 
			
		||||
  isModelValid = true;
 | 
			
		||||
 | 
			
		||||
  isFullscreen = false;
 | 
			
		||||
  targetFullscreenElement: HTMLElement;
 | 
			
		||||
  fullscreenFinishFn: () => void;
 | 
			
		||||
  fullscreenFinishFn: (el: Element) => void;
 | 
			
		||||
 | 
			
		||||
  private propagateChange = null;
 | 
			
		||||
  private propagateChangePending = false;
 | 
			
		||||
@ -233,8 +235,7 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private onToggleFullscreen(element: HTMLElement, fullscreenFinishFn?: () => void) {
 | 
			
		||||
    this.targetFullscreenElement = element;
 | 
			
		||||
  private onToggleFullscreen(fullscreenFinishFn?: (el: Element) => void) {
 | 
			
		||||
    this.isFullscreen = !this.isFullscreen;
 | 
			
		||||
    this.fullscreenFinishFn = fullscreenFinishFn;
 | 
			
		||||
    this.cd.markForCheck();
 | 
			
		||||
@ -244,7 +245,7 @@ export class JsonFormComponent implements OnInit, ControlValueAccessor, Validato
 | 
			
		||||
    this.formProps.isFullscreen = fullscreen;
 | 
			
		||||
    this.renderReactSchemaForm(false);
 | 
			
		||||
    if (this.fullscreenFinishFn) {
 | 
			
		||||
      this.fullscreenFinishFn();
 | 
			
		||||
      this.fullscreenFinishFn(this.reactFullscreenElmRef.nativeElement);
 | 
			
		||||
      this.fullscreenFinishFn = null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,7 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
import * as React from 'react';
 | 
			
		||||
import * as ReactDOM from 'react-dom';
 | 
			
		||||
import ThingsboardBaseComponent from './json-form-base-component';
 | 
			
		||||
import reactCSS from 'reactcss';
 | 
			
		||||
import Button from '@material-ui/core/Button';
 | 
			
		||||
@ -42,6 +43,7 @@ interface ThingsboardAceEditorProps extends JsonFormFieldProps {
 | 
			
		||||
 | 
			
		||||
interface ThingsboardAceEditorState extends JsonFormFieldState {
 | 
			
		||||
  isFull: boolean;
 | 
			
		||||
  fullscreenContainerElement: Element;
 | 
			
		||||
  helpVisible: boolean;
 | 
			
		||||
  helpReady: boolean;
 | 
			
		||||
  focused: boolean;
 | 
			
		||||
@ -49,7 +51,6 @@ interface ThingsboardAceEditorState extends JsonFormFieldState {
 | 
			
		||||
 | 
			
		||||
class ThingsboardAceEditor extends React.Component<ThingsboardAceEditorProps, ThingsboardAceEditorState> {
 | 
			
		||||
 | 
			
		||||
    hostElement: HTMLElement;
 | 
			
		||||
    private aceEditor: IEditorProps;
 | 
			
		||||
 | 
			
		||||
    constructor(props) {
 | 
			
		||||
@ -64,6 +65,7 @@ class ThingsboardAceEditor extends React.Component<ThingsboardAceEditorProps, Th
 | 
			
		||||
        const value = props.value ? props.value + '' : '';
 | 
			
		||||
        this.state = {
 | 
			
		||||
            isFull: false,
 | 
			
		||||
            fullscreenContainerElement: null,
 | 
			
		||||
            helpVisible: false,
 | 
			
		||||
            helpReady: true,
 | 
			
		||||
            value,
 | 
			
		||||
@ -131,12 +133,8 @@ class ThingsboardAceEditor extends React.Component<ThingsboardAceEditorProps, Th
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onToggleFull() {
 | 
			
		||||
        this.setState({ isFull: !this.state.isFull });
 | 
			
		||||
        this.props.onToggleFullscreen(this.hostElement, () => {
 | 
			
		||||
          if (this.aceEditor) {
 | 
			
		||||
            this.aceEditor.resize();
 | 
			
		||||
            this.aceEditor.renderer.updateFull();
 | 
			
		||||
          }
 | 
			
		||||
        this.props.onToggleFullscreen((el) => {
 | 
			
		||||
          this.setState({ isFull: !this.state.isFull, fullscreenContainerElement: el });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -177,56 +175,61 @@ class ThingsboardAceEditor extends React.Component<ThingsboardAceEditorProps, Th
 | 
			
		||||
        if (this.state.isFull) {
 | 
			
		||||
            containerClass += ' fullscreen-form-field';
 | 
			
		||||
        }
 | 
			
		||||
        return (
 | 
			
		||||
          <div>
 | 
			
		||||
            <div className='tb-json-form' ref={c => (this.hostElement = c)}>
 | 
			
		||||
              <div className={containerClass}>
 | 
			
		||||
                  <label className={labelClass}>{this.props.form.title}</label>
 | 
			
		||||
                  <div className='json-form-ace-editor'>
 | 
			
		||||
                      <div className='title-panel'>
 | 
			
		||||
                          <label>{this.props.mode}</label>
 | 
			
		||||
                          { this.props.onTidy ? <Button style={ styles.tidyButtonStyle }
 | 
			
		||||
                                                       className='tidy-button' onClick={this.onTidy}>Tidy</Button> : null }
 | 
			
		||||
                          { this.props.form.helpId ? <div style={ {position: 'relative', display: 'inline-block', marginLeft: '5px'} }>
 | 
			
		||||
                            <IconButton color='primary'
 | 
			
		||||
                                        className='help-button' onClick={this.onHelp}>
 | 
			
		||||
                                        {this.state.helpVisible ? <Help /> : <HelpOutline /> }
 | 
			
		||||
                             </IconButton>
 | 
			
		||||
                            { this.state.helpVisible && !this.state.helpReady ?
 | 
			
		||||
                              <div className='tb-absolute-fill help-button-loading'>
 | 
			
		||||
                                <CircularProgress size={18} thickness={4}/>
 | 
			
		||||
                               </div> : null }</div> : null }
 | 
			
		||||
                          <Button style={ styles.tidyButtonStyle }
 | 
			
		||||
                                  className='tidy-button' onClick={this.onToggleFull}>
 | 
			
		||||
                            {this.state.isFull ?
 | 
			
		||||
                              'Exit fullscreen' : 'Fullscreen'}
 | 
			
		||||
                          </Button>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <React.Suspense fallback={<div>Loading...</div>}>
 | 
			
		||||
                        <ReactAce  mode={this.props.mode}
 | 
			
		||||
                                   theme={'textmate'}
 | 
			
		||||
                                   height={this.state.isFull ? '100%' : '150px'}
 | 
			
		||||
                                   width={this.state.isFull ? '100%' : '300px'}
 | 
			
		||||
                                   onChange={this.onValueChanged}
 | 
			
		||||
                                   onFocus={this.onFocus}
 | 
			
		||||
                                   onBlur={this.onBlur}
 | 
			
		||||
                                   onLoad={this.onLoad}
 | 
			
		||||
                                   name={this.props.form.title}
 | 
			
		||||
                                   value={this.state.value}
 | 
			
		||||
                                   readOnly={this.props.form.readonly}
 | 
			
		||||
                                   editorProps={{$blockScrolling: Infinity}}
 | 
			
		||||
                                   enableBasicAutocompletion={true}
 | 
			
		||||
                                   enableSnippets={true}
 | 
			
		||||
                                   enableLiveAutocompletion={true}
 | 
			
		||||
                                   style={style}/>
 | 
			
		||||
                      </React.Suspense>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div className='json-form-error'
 | 
			
		||||
                       style={{opacity: this.props.valid ? '0' : '1'}}>{this.props.error}</div>
 | 
			
		||||
        const formDom = (
 | 
			
		||||
          <div className={containerClass}>
 | 
			
		||||
            <label className={labelClass}>{this.props.form.title}</label>
 | 
			
		||||
            <div className='json-form-ace-editor'>
 | 
			
		||||
              <div className='title-panel'>
 | 
			
		||||
                <label>{this.props.mode}</label>
 | 
			
		||||
                { this.props.onTidy ? <Button style={ styles.tidyButtonStyle }
 | 
			
		||||
                                              className='tidy-button' onClick={this.onTidy}>Tidy</Button> : null }
 | 
			
		||||
                { this.props.form.helpId ? <div style={ {position: 'relative', display: 'inline-block', marginLeft: '5px'} }>
 | 
			
		||||
                  <IconButton color='primary'
 | 
			
		||||
                              className='help-button' onClick={this.onHelp}>
 | 
			
		||||
                    {this.state.helpVisible ? <Help /> : <HelpOutline /> }
 | 
			
		||||
                  </IconButton>
 | 
			
		||||
                  { this.state.helpVisible && !this.state.helpReady ?
 | 
			
		||||
                    <div className='tb-absolute-fill help-button-loading'>
 | 
			
		||||
                      <CircularProgress size={18} thickness={4}/>
 | 
			
		||||
                    </div> : null }</div> : null }
 | 
			
		||||
                <Button style={ styles.tidyButtonStyle }
 | 
			
		||||
                        className='tidy-button' onClick={this.onToggleFull}>
 | 
			
		||||
                  {this.state.isFull ?
 | 
			
		||||
                    'Exit fullscreen' : 'Fullscreen'}
 | 
			
		||||
                </Button>
 | 
			
		||||
              </div>
 | 
			
		||||
              <React.Suspense fallback={<div>Loading...</div>}>
 | 
			
		||||
                <ReactAce  mode={this.props.mode}
 | 
			
		||||
                           theme={'textmate'}
 | 
			
		||||
                           height={this.state.isFull ? '100%' : '150px'}
 | 
			
		||||
                           width={this.state.isFull ? '100%' : '300px'}
 | 
			
		||||
                           onChange={this.onValueChanged}
 | 
			
		||||
                           onFocus={this.onFocus}
 | 
			
		||||
                           onBlur={this.onBlur}
 | 
			
		||||
                           onLoad={this.onLoad}
 | 
			
		||||
                           name={this.props.form.title}
 | 
			
		||||
                           value={this.state.value}
 | 
			
		||||
                           readOnly={this.props.form.readonly}
 | 
			
		||||
                           editorProps={{$blockScrolling: Infinity}}
 | 
			
		||||
                           enableBasicAutocompletion={true}
 | 
			
		||||
                           enableSnippets={true}
 | 
			
		||||
                           enableLiveAutocompletion={true}
 | 
			
		||||
                           style={style}/>
 | 
			
		||||
              </React.Suspense>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className='json-form-error'
 | 
			
		||||
                 style={{opacity: this.props.valid ? '0' : '1'}}>{this.props.error}</div>
 | 
			
		||||
          </div>
 | 
			
		||||
        );
 | 
			
		||||
        if (this.state.isFull) {
 | 
			
		||||
          return ReactDOM.createPortal(formDom, this.state.fullscreenContainerElement);
 | 
			
		||||
        } else {
 | 
			
		||||
          return (
 | 
			
		||||
            <div>
 | 
			
		||||
                {formDom}
 | 
			
		||||
            </div>
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -106,8 +106,8 @@ class ThingsboardSchemaForm extends React.Component<JsonFormProps, any> {
 | 
			
		||||
    this.props.onIconClick(key, val, iconSelectedFn);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onToggleFullscreen(element: HTMLElement, fullscreenFinishFn?: () => void) {
 | 
			
		||||
    this.props.onToggleFullscreen(element, fullscreenFinishFn);
 | 
			
		||||
  onToggleFullscreen(fullscreenFinishFn?: (el: Element) => void) {
 | 
			
		||||
    this.props.onToggleFullscreen(fullscreenFinishFn);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onHelpClick(event: MouseEvent, helpId: string, helpVisibleFn: (visible: boolean) => void, helpReadyFn: (ready: boolean) => void) {
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,7 @@ export type OnColorClickFn = (key: (string | number)[], val: tinycolor.ColorForm
 | 
			
		||||
                              colorSelectedFn: (color: tinycolor.ColorFormats.RGBA) => void) => void;
 | 
			
		||||
export type OnIconClickFn = (key: (string | number)[], val: string,
 | 
			
		||||
                             iconSelectedFn: (icon: string) => void) => void;
 | 
			
		||||
export type onToggleFullscreenFn = (element: HTMLElement, fullscreenFinishFn?: () => void) => void;
 | 
			
		||||
export type onToggleFullscreenFn = (fullscreenFinishFn?: (el: Element) => void) => void;
 | 
			
		||||
export type onHelpClickFn = (event: MouseEvent, helpId: string, helpVisibleFn: (visible: boolean) => void,
 | 
			
		||||
                             helpReadyFn: (ready: boolean) => void) => void;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user