Skip to content

Commit

Permalink
Merge pull request #1310 from DSD-DBS/editor-component
Browse files Browse the repository at this point in the history
refactor: Make YAML editor reusable
  • Loading branch information
MoritzWeber0 authored Feb 2, 2024
2 parents 46f79ec + fa396f9 commit 5ef2a56
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 75 deletions.
2 changes: 2 additions & 0 deletions frontend/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { CookieModule } from 'ngx-cookie';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { ToastrModule } from 'ngx-toastr';
import { EditorComponent } from 'src/app/helpers/editor/editor.component';
import {
HighlightPipeTransform,
ModelDiagramCodeBlockComponent,
Expand Down Expand Up @@ -178,6 +179,7 @@ import { UsersProfileComponent } from './users/users-profile/users-profile.compo
DeleteSessionDialogComponent,
DisplayValueComponent,
EditGitSettingsComponent,
EditorComponent,
EditProjectMetadataComponent,
EditT4CInstanceComponent,
EventsComponent,
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/app/helpers/editor/editor.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!--
~ SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
~ SPDX-License-Identifier: Apache-2.0
-->

<div id="editor" class="h-[70vh] min-h-[200px]"></div>
104 changes: 104 additions & 0 deletions frontend/src/app/helpers/editor/editor.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* SPDX-FileCopyrightText: Copyright DB InfraGO AG and contributors
* SPDX-License-Identifier: Apache-2.0
*/

import {
Component,
EventEmitter,
HostListener,
Input,
NgZone,
Output,
} from '@angular/core';

import * as monaco from 'monaco-editor';
import { MetadataService } from 'src/app/general/metadata/metadata.service';
import { ToastService } from 'src/app/helpers/toast/toast.service';
import { ConfigurationSettingsService } from 'src/app/settings/core/configuration-settings/configuration-settings.service';
import { stringify, parse, YAMLParseError } from 'yaml';

@Component({
selector: 'app-editor',
templateUrl: './editor.component.html',
})
export class EditorComponent {
private editor?: monaco.editor.IStandaloneCodeEditor = undefined;
intialValue = 'Loading...';

@Output()
submitted = new EventEmitter();

constructor(
private ngZone: NgZone,
private configurationSettingsService: ConfigurationSettingsService,
private toastService: ToastService,
private metadataService: MetadataService,
) {}

ngOnInit() {
this.ngZone.runOutsideAngular(() => {
this.initMonaco();
});
}

@Input()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
set value(data: any) {
const yaml = stringify(data, { indent: 4 });
this.intialValue = yaml;
this.editor?.setValue(yaml);
}

resetValue() {
this.editor?.setValue(this.intialValue);
}

submitValue() {
if (!this.editor?.getValue()) {
this.toastService.showError(
'Configuration is empty',
"The configuration editor doesn't contain any content. Make sure to enter a valid YAML configuration.",
);
return;
}
let jsonValue = '';

try {
jsonValue = parse(this.editor?.getValue());
} catch (e) {
if (e instanceof YAMLParseError) {
this.toastService.showError('YAML parsing error', e.message);
} else {
this.toastService.showError(
'YAML parsing error',
'Unknown error. Please check the console for more information.',
);
}
return;
}

this.submitted.emit(jsonValue);
}

private initMonaco() {
const configModel = monaco.editor.createModel(this.intialValue, 'yaml');

this.editor = monaco.editor.create(document.getElementById('editor')!, {
value: 'Loading...',
language: 'yaml',
scrollBeyondLastLine: false,
model: configModel,
automaticLayout: true,
});
}

@HostListener('document:keydown', ['$event'])
saveHandler(event: KeyboardEvent) {
if ((event.metaKey || event.ctrlKey) && event.key === 's') {
event.preventDefault();
event.stopPropagation();
this.submitValue();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
~ SPDX-License-Identifier: Apache-2.0
-->

<div id="editor" class="h-[70vh] min-h-[200px]"></div>
<app-editor #editor (submitted)="submitValue($event)" />
<div class="m-2 flex gap-2">
<button mat-stroked-button (click)="submitValue()" color="primary">
<button mat-stroked-button (click)="editor.submitValue()" color="primary">
<span>Save</span>
<mat-icon class="ml-2">save</mat-icon>
</button>
<button mat-stroked-button (click)="resetValue()" color="warn">
<button mat-stroked-button (click)="editor.resetValue()" color="warn">
<span>Reset</span> <mat-icon class="ml-2">clear</mat-icon>
</button>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -3,95 +3,42 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { Component, HostListener, NgZone } from '@angular/core';
import { Component, OnInit, ViewChild } from '@angular/core';

import * as monaco from 'monaco-editor';
import { MetadataService } from 'src/app/general/metadata/metadata.service';
import { EditorComponent } from 'src/app/helpers/editor/editor.component';
import { ToastService } from 'src/app/helpers/toast/toast.service';
import { ConfigurationSettingsService } from 'src/app/settings/core/configuration-settings/configuration-settings.service';
import { stringify, parse, YAMLParseError } from 'yaml';

@Component({
selector: 'app-configuration-settings',
templateUrl: './configuration-settings.component.html',
})
export class ConfigurationSettingsComponent {
private editor?: monaco.editor.IStandaloneCodeEditor = undefined;

intialValue = 'Loading...';
export class ConfigurationSettingsComponent implements OnInit {
@ViewChild(EditorComponent) editor: EditorComponent | undefined;

constructor(
private ngZone: NgZone,
private configurationSettingsService: ConfigurationSettingsService,
private toastService: ToastService,
private metadataService: MetadataService,
) {}

ngOnInit() {
this.ngZone.runOutsideAngular(() => {
this.initMonaco();
});

ngOnInit(): void {
this.fetchConfiguration();
}

ngOnDestroy() {
if (this.editor) {
this.editor.dispose();
}
}

private initMonaco() {
const configModel = monaco.editor.createModel(this.intialValue, 'yaml');

this.editor = monaco.editor.create(document.getElementById('editor')!, {
value: 'Loading...',
language: 'yaml',
scrollBeyondLastLine: false,
model: configModel,
automaticLayout: true,
});
}

fetchConfiguration() {
this.configurationSettingsService
.getConfigurationSettings('global')
.subscribe((data) => {
const yaml = stringify(data, { indent: 4 });
this.intialValue = yaml;
this.editor?.setValue(yaml);
this.editor!.value = data;
});
}

resetValue() {
this.editor?.setValue(this.intialValue);
}

submitValue() {
if (!this.editor?.getValue()) {
this.toastService.showError(
'Configuration is empty',
"The configuration editor doesn't contain any content. Make sure to enter a valid YAML configuration.",
);
return;
}
let jsonValue = '';

try {
jsonValue = parse(this.editor?.getValue());
} catch (e) {
if (e instanceof YAMLParseError) {
this.toastService.showError('YAML parsing error', e.message);
} else {
this.toastService.showError(
'YAML parsing error',
'Unknown error. Please check the console for more information.',
);
}
return;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
submitValue(value: any) {
this.configurationSettingsService
.putConfigurationSettings('global', jsonValue)
.putConfigurationSettings('global', value)
.subscribe({
next: () => {
this.toastService.showSuccess(
Expand All @@ -103,13 +50,4 @@ export class ConfigurationSettingsComponent {
},
});
}

@HostListener('document:keydown', ['$event'])
saveHandler(event: KeyboardEvent) {
if ((event.metaKey || event.ctrlKey) && event.key === 's') {
event.preventDefault();
event.stopPropagation();
this.submitValue();
}
}
}

0 comments on commit 5ef2a56

Please sign in to comment.