diff --git a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.html b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.html index 46a889ffda..111e6fffbd 100644 --- a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.html @@ -24,13 +24,14 @@ close -
- -
+
+
+ audit-log.action-data +
- - -
+
+ audit-log.failure-details +
diff --git a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.scss b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.scss index 57bd26c8ba..5f029ce4f1 100644 --- a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.scss @@ -13,13 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +@import '../../../../../scss/constants'; + :host { - .tb-audit-log-action-data, - .tb-audit-log-failure-details { - width: 100%; - min-width: 400px; - height: 100%; - min-height: 50px; + display: grid; + height: 100%; + max-width: 100%; + max-height: 100vh; + grid-template-rows: min-content minmax(auto, 1fr) min-content; + + @media #{$mat-gt-xs} { + .mat-mdc-dialog-content { + max-height: 80vh; + } + } + + .tb-audit-log { + min-width: max(400px, 100%); border: 1px solid #c0c0c0; + @media #{$mat-xs} { + min-width: 100%; + } } } diff --git a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts index c888fafebc..e3d8bbc582 100644 --- a/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/audit-log/audit-log-details-dialog.component.ts @@ -22,7 +22,11 @@ import { ActionStatus, AuditLog } from '@shared/models/audit-log.models'; import { Ace } from 'ace-builds'; import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; -import { getAce } from '@shared/models/ace/ace.models'; +import { getAce, updateEditorSize } from '@shared/models/ace/ace.models'; +import { Observable, of } from 'rxjs'; +import { isObject } from '@core/utils'; +import { ContentType, contentTypesMap } from '@shared/models/constants'; +import { beautifyJs } from '@shared/models/beautify.models'; export interface AuditLogDetailsDialogData { auditLog: AuditLog; @@ -41,11 +45,10 @@ export class AuditLogDetailsDialogComponent extends DialogComponent, protected router: Router, @@ -58,12 +61,10 @@ export class AuditLogDetailsDialogComponent extends DialogComponent = { - 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) => { - const editor = ace.edit(editorElement, editorOptions); - this.aceEditors.push(editor); - editor.session.setUseWrapMode(false); - editor.setValue(content, -1); - this.updateEditorSize(editorElement, content, editor); - } - ); - } - - 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 = 18 * lines.length + 16; - 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 = 9 * maxLineLength + 16; + let mode = 'java'; + let content$: Observable = null; + let contentType = ContentType.TEXT; + if (content && isObject(content)) { + contentType = ContentType.JSON; + mode = contentTypesMap.get(contentType).code; + content$ = beautifyJs(JSON.stringify(content), {indent_size: 2}); + } + if (!content$) { + content$ = of(content as string); } - // newHeight = Math.min(400, newHeight); - this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px'); - this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px'); - this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px'); - editor.resize(); + content$.subscribe((processedContent) => { + const isJSON = contentType === ContentType.JSON + const editorOptions: Partial = { + mode: `ace/mode/${mode}`, + theme: 'ace/theme/github', + showGutter: isJSON, + showFoldWidgets: true, + foldStyle: 'markbeginend', + showPrintMargin: false, + readOnly: true, + enableSnippets: false, + enableBasicAutocompletion: false, + enableLiveAutocompletion: false, + }; + getAce().subscribe( + (ace) => { + const editor = ace.edit(editorElement, editorOptions); + this.aceEditors.push(editor); + editor.session.setUseWrapMode(false); + editor.setValue(processedContent, -1); + updateEditorSize(editorElement, processedContent, editor, this.renderer, {showGutter: isJSON}); + } + ) + }); } } diff --git a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.html b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.html index 27280bfd9e..aa1f8754a5 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.html @@ -24,8 +24,8 @@ close -
-
+
+
diff --git a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss index 2dd61e2722..ee1ca74151 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.scss @@ -13,11 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +@import '../../../../../scss/constants'; + :host { + display: grid; + height: 100%; + max-width: 100%; + max-height: 100vh; + grid-template-rows: min-content minmax(auto, 1fr) min-content; + + @media #{$mat-gt-xs} { + .mat-mdc-dialog-content { + max-height: 80vh; + } + } + .tb-event-content { - width: 100%; min-width: 400px; - height: 100%; - min-height: 50px; + &.border { + border: 1px solid #c0c0c0; + } + @media #{$mat-xs} { + min-width: 100%; + } } } diff --git a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts index 2ae62dd890..9ca6ad8b43 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-content-dialog.component.ts @@ -23,7 +23,7 @@ import { Ace } from 'ace-builds'; import { DialogComponent } from '@shared/components/dialog.component'; import { Router } from '@angular/router'; import { ContentType, contentTypesMap } from '@shared/models/constants'; -import { getAce } from '@shared/models/ace/ace.models'; +import { getAce, updateEditorSize } from '@shared/models/ace/ace.models'; import { Observable } from 'rxjs/internal/Observable'; import { beautifyJs } from '@shared/models/beautify.models'; import { of } from 'rxjs'; @@ -40,40 +40,38 @@ export interface EventContentDialogData { templateUrl: './event-content-dialog.component.html', styleUrls: ['./event-content-dialog.component.scss'] }) -export class EventContentDialogComponent extends DialogComponent implements OnInit, OnDestroy { +export class EventContentDialogComponent extends DialogComponent implements OnInit, OnDestroy { @ViewChild('eventContentEditor', {static: true}) eventContentEditorElmRef: ElementRef; - content: string; title: string; - contentType: ContentType; - aceEditor: Ace.Editor; + showBorder = false; + + private contentType: ContentType; + private aceEditor: Ace.Editor; constructor(protected store: Store, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: EventContentDialogData, - public dialogRef: MatDialogRef, + protected dialogRef: MatDialogRef, private renderer: Renderer2) { super(store, router, dialogRef); } ngOnInit(): void { - this.content = this.data.content; this.title = this.data.title; this.contentType = this.data.contentType; - this.createEditor(this.eventContentEditorElmRef, this.content); + this.createEditor(this.eventContentEditorElmRef, this.data.content); } ngOnDestroy(): void { - if (this.aceEditor) { - this.aceEditor.destroy(); - } + this.aceEditor?.destroy(); super.ngOnDestroy(); } - isJson(str) { + private isJson(str: string) { try { return isLiteralObject(JSON.parse(str)); } catch (e) { @@ -81,78 +79,53 @@ export class EventContentDialogComponent extends DialogComponent = null; if (this.contentType) { mode = contentTypesMap.get(this.contentType).code; if (this.contentType === ContentType.JSON && content) { - content$ = beautifyJs(content, {indent_size: 4}); + content$ = beautifyJs(content, {indent_size: 2}); } else if (this.contentType === ContentType.BINARY && content) { try { const decodedData = base64toString(content); if (this.isJson(decodedData)) { mode = 'json'; - content$ = beautifyJs(decodedData, {indent_size: 4}); + content$ = beautifyJs(decodedData, {indent_size: 2}); } else { content$ = of(decodedData); } - } catch (e) {} + } catch (e) {/**/} } } if (!content$) { content$ = of(content); } - content$.subscribe( - (processedContent) => { - let editorOptions: Partial = { - mode: `ace/mode/${mode}`, - 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.aceEditor = ace.edit(editorElement, editorOptions); - this.aceEditor.session.setUseWrapMode(false); - this.aceEditor.setValue(processedContent, -1); - this.updateEditorSize(editorElement, processedContent, this.aceEditor); - } - ); - } - ); - } - - updateEditorSize(editorElement: any, content: string, editor: Ace.Editor) { - let newHeight = 400; - let newWidth = 600; - if (content && content.length > 0) { - const lines = content.split('\n'); - newHeight = 17 * lines.length + 16; - 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 = 9 * maxLineLength + 16; - } - // newHeight = Math.min(400, newHeight); - this.renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px'); - this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px'); - this.renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px'); - editor.resize(); + content$.subscribe((processedContent) => { + const isJSON = mode === 'json' && processedContent !== '{}'; + this.showBorder = isJSON; + const editorOptions: Partial = { + mode: `ace/mode/${mode}`, + theme: 'ace/theme/github', + showGutter: isJSON, + showFoldWidgets: true, + foldStyle: 'markbeginend', + showPrintMargin: false, + readOnly: true, + enableSnippets: false, + enableBasicAutocompletion: false, + enableLiveAutocompletion: false, + }; + getAce().subscribe( + (ace) => { + this.aceEditor = ace.edit(editorElement, editorOptions); + this.aceEditor.session.setUseWrapMode(false); + this.aceEditor.setValue(processedContent, -1); + updateEditorSize(editorElement, processedContent, this.aceEditor, this.renderer, {showGutter: isJSON}); + } + ) + }); } - } diff --git a/ui-ngx/src/app/shared/components/json-object-view.component.ts b/ui-ngx/src/app/shared/components/json-object-view.component.ts index e549dd03c1..20f8660279 100644 --- a/ui-ngx/src/app/shared/components/json-object-view.component.ts +++ b/ui-ngx/src/app/shared/components/json-object-view.component.ts @@ -15,14 +15,11 @@ /// import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, Renderer2, ViewChild } from '@angular/core'; -import { NG_VALUE_ACCESSOR } from '@angular/forms'; +import { ControlValueAccessor, 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'; +import { getAce, updateEditorSize } from '@shared/models/ace/ace.models'; +import { coerceBoolean } from '@shared/decorators/coercion'; @Component({ selector: 'tb-json-object-view', @@ -36,7 +33,7 @@ import { getAce } from '@shared/models/ace/ace.models'; } ] }) -export class JsonObjectViewComponent implements OnInit, OnDestroy { +export class JsonObjectViewComponent implements OnInit, OnDestroy, ControlValueAccessor { @ViewChild('jsonViewer', {static: true}) jsonViewerElmRef: ElementRef; @@ -55,96 +52,54 @@ export class JsonObjectViewComponent implements OnInit, OnDestroy { @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; - } + @coerceBoolean() + autoWidth: boolean @Input() - set autoHeight(value: boolean) { - this.heigthValue = coerceBooleanProperty(value); - } + @coerceBoolean() + autoHeight: boolean - constructor(public elementRef: ElementRef, - protected store: Store, - private raf: RafService, - private renderer: Renderer2) { + constructor(private renderer: Renderer2) { } ngOnInit(): void { this.viewerElement = this.jsonViewerElmRef.nativeElement; - let editorOptions: Partial = { + const editorOptions: Partial = { mode: 'ace/mode/java', theme: 'ace/theme/github', showGutter: false, showPrintMargin: false, - readOnly: true - }; - - const advancedOptions = { + readOnly: true, 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); + if (this.contentValue && (this.autoWidth || this.autoHeight)) { + updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer, this.renderer, { + ignoreHeight: !this.autoHeight, + ignoreWidth: !this.autoWidth + }); } } ); } ngOnDestroy(): void { - if (this.jsonViewer) { - this.jsonViewer.destroy(); - } + 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 { + registerOnTouched(_fn: any): void { } writeValue(value: any): void { @@ -162,8 +117,11 @@ export class JsonObjectViewComponent implements OnInit, OnDestroy { } 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); + if (this.contentValue && (this.autoWidth || this.autoHeight)) { + updateEditorSize(this.viewerElement, this.contentValue, this.jsonViewer, this.renderer, { + ignoreHeight: !this.autoHeight, + ignoreWidth: !this.autoWidth + }); } } } diff --git a/ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts b/ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts index a3d82952cc..90bd9f30ec 100644 --- a/ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts +++ b/ui-ngx/src/app/shared/import-export/import-dialog-csv.component.ts @@ -39,7 +39,7 @@ import { import { ImportExportService } from '@shared/import-export/import-export.service'; import { TableColumnsAssignmentComponent } from '@shared/import-export/table-columns-assignment.component'; import { Ace } from 'ace-builds'; -import { getAce } from '@shared/models/ace/ace.models'; +import { getAce, updateEditorSize } from '@shared/models/ace/ace.models'; export interface ImportDialogCsvData { entityType: EntityType; @@ -283,21 +283,9 @@ export class ImportDialogCsvComponent extends DialogComponent 0) { - const lines = content.split('\n'); - newHeight = 16 * lines.length + 24; - } - const minHeight = Math.min(200, newHeight); - this.renderer.setStyle(editorElement, 'minHeight', minHeight.toString() + 'px'); - this.renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px'); - editor.resize(); - } - } diff --git a/ui-ngx/src/app/shared/models/ace/ace.models.ts b/ui-ngx/src/app/shared/models/ace/ace.models.ts index 49cf670989..31b97ff144 100644 --- a/ui-ngx/src/app/shared/models/ace/ace.models.ts +++ b/ui-ngx/src/app/shared/models/ace/ace.models.ts @@ -19,6 +19,7 @@ import { Observable } from 'rxjs/internal/Observable'; import { forkJoin, from, of } from 'rxjs'; import { map, mergeMap, tap } from 'rxjs/operators'; import { unwrapModule } from '@core/utils'; +import { Renderer2 } from '@angular/core'; let aceDependenciesLoaded = false; let aceModule: any; @@ -98,6 +99,46 @@ export function getAceDiff(): Observable { } } +export function updateEditorSize(editorElement: any, content: string, editor: Ace.Editor, renderer: Renderer2, options?: { + showGutter?: boolean, + ignoreHeight?: boolean, + ignoreWidth?: boolean, + setMinHeight?: boolean +}): void { + let newHeight = 200; + let newWidth = 600; + if (content && content.length > 0) { + if (editor.renderer.lineHeight <= 0) { + editor.renderer.updateFull(true); + } + const lines = content.split('\n'); + newHeight = editor.renderer.lineHeight * lines.length + 16; + let maxLineLength = 0; + lines.forEach((row) => { + const line = row.replace(/\t/g, ' ').replace(/\n/g, ''); + const lineLength = line.length; + maxLineLength = Math.max(maxLineLength, lineLength); + }); + if (options?.showGutter) { + maxLineLength += lines.length.toString().length; + } + newWidth = 10 * maxLineLength + 16; + if (options?.showGutter) { + newWidth += 32; + } + } + if (!options.ignoreHeight) { + renderer.setStyle(editorElement, 'height', newHeight.toString() + 'px'); + } + if (options.setMinHeight) { + renderer.setStyle(editorElement, 'minHeight', newHeight.toString() + 'px'); + } + if (!options.ignoreWidth) { + renderer.setStyle(editorElement, 'width', newWidth.toString() + 'px'); + } + editor.resize(); +} + export class Range implements Ace.Range { public start: Ace.Point;