/// /// Copyright © 2016-2023 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 { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { Ace } from 'ace-builds'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { RafService } from '@core/services/raf.service'; import { isDefinedAndNotNull, isUndefined } from '@core/utils'; import { getAce } from '@shared/models/ace/ace.models'; @Component({ selector: 'tb-json-object-view', templateUrl: './json-object-view.component.html', styleUrls: ['./json-object-view.component.scss'], providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => JsonObjectViewComponent), multi: true } ] }) export class JsonObjectViewComponent implements OnInit, OnDestroy { @ViewChild('jsonViewer', {static: true}) jsonViewerElmRef: ElementRef; private jsonViewer: Ace.Editor; private viewerElement: Ace.Editor; private propagateChange = null; private modelValue: any; private contentValue: string; @Input() label: string; @Input() fillHeight: boolean; @Input() editorStyle: { [klass: string]: any }; @Input() sort: (key: string, value: any) => any; private widthValue: boolean; get autoWidth(): boolean { return this.widthValue; } @Input() set autoWidth(value: boolean) { this.widthValue = coerceBooleanProperty(value); } private heigthValue: boolean; get autoHeight(): boolean { return this.heigthValue; } @Input() set autoHeight(value: boolean) { this.heigthValue = coerceBooleanProperty(value); } constructor(public elementRef: ElementRef, protected store: Store, private raf: RafService, private renderer: Renderer2) { } ngOnInit(): void { this.viewerElement = this.jsonViewerElmRef.nativeElement; let editorOptions: Partial = { mode: 'ace/mode/java', theme: 'ace/theme/github', showGutter: false, showPrintMargin: false, readOnly: true }; const advancedOptions = { enableSnippets: false, enableBasicAutocompletion: false, enableLiveAutocompletion: false }; editorOptions = {...editorOptions, ...advancedOptions}; getAce().subscribe( (ace) => { this.jsonViewer = ace.edit(this.viewerElement, editorOptions); this.jsonViewer.session.setUseWrapMode(false); this.jsonViewer.setValue(this.contentValue ? this.contentValue : '', -1); if (this.contentValue && (this.widthValue || this.heigthValue)) { this.updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer); } } ); } ngOnDestroy(): void { if (this.jsonViewer) { this.jsonViewer.destroy(); } } updateEditorSize(editorElement: any, content: string, editor: Ace.Editor) { let newHeight = 200; let newWidth = 600; if (content && content.length > 0) { const lines = content.split('\n'); newHeight = 17 * lines.length + 17; let maxLineLength = 0; lines.forEach((row) => { const line = row.replace(/\t/g, ' ').replace(/\n/g, ''); const lineLength = line.length; maxLineLength = Math.max(maxLineLength, lineLength); }); newWidth = 8 * maxLineLength + 16; } if (this.heigthValue) { this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px'); } if (this.widthValue) { this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px'); } editor.resize(); } registerOnChange(fn: any): void { this.propagateChange = fn; } registerOnTouched(fn: any): void { } writeValue(value: any): void { this.modelValue = value; this.contentValue = ''; try { if (isDefinedAndNotNull(this.modelValue)) { this.contentValue = JSON.stringify(this.modelValue, isUndefined(this.sort) ? undefined : (key, objectValue) => { return this.sort(key, objectValue); }, 2); } } catch (e) { console.error(e); } if (this.jsonViewer) { this.jsonViewer.setValue(this.contentValue ? this.contentValue : '', -1); if (this.contentValue && (this.widthValue || this.heigthValue)) { this.updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer); } } } }