Convert code editor to new format
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Garrett Mills 2020-10-14 07:37:14 -05:00
parent 0a6a775fdb
commit ae24674717
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246
5 changed files with 213 additions and 203 deletions

View File

@ -7,7 +7,7 @@
</ion-select> </ion-select>
</ion-item> </ion-item>
</ion-toolbar> </ion-toolbar>
<div class="ed-wrapper" style="width: 100%; height: 480px;"> <div class="ed-wrapper" style="width: 100%; height: 540px;">
<ngx-monaco-editor style="width: 100%; height: 100%;" <ngx-monaco-editor style="width: 100%; height: 100%;"
[options]="editorOptions" [options]="editorOptions"
[(ngModel)]="editorValue" [(ngModel)]="editorValue"
@ -15,10 +15,4 @@
#theEditor #theEditor
></ngx-monaco-editor> ></ngx-monaco-editor>
</div> </div>
<ion-toolbar *ngIf="!readonly">
<ion-buttons slot="end">
<ion-button (click)="onDropClick()"><ion-icon name="alert" color="danger"></ion-icon>&nbsp;Drop Editor</ion-button>
<ion-button (click)="onSaveClick()"><ion-icon name="save" [color]="dirty ? 'warning' : 'success'"></ion-icon>&nbsp;Save Changes</ion-button>
</ion-buttons>
</ion-toolbar>
</div> </div>

View File

@ -1,209 +1,212 @@
import {Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {v4} from 'uuid'; import {v4} from 'uuid';
import HostRecord from '../../../structures/HostRecord';
import {Observable} from 'rxjs';
import {ApiService} from '../../../service/api.service'; import {ApiService} from '../../../service/api.service';
import {AlertController, LoadingController} from '@ionic/angular'; import {EditorNodeContract} from '../../nodes/EditorNode.contract';
import {EditorService} from '../../../service/editor.service';
@Component({ @Component({
selector: 'editor-code', selector: 'editor-code',
templateUrl: './code.component.html', templateUrl: './code.component.html',
styleUrls: ['./code.component.scss'], styleUrls: ['./code.component.scss'],
}) })
export class CodeComponent implements OnInit { export class CodeComponent extends EditorNodeContract implements OnInit {
@Input() readonly = false; @Input() nodeId: string;
@Input() hostRecord: HostRecord; public dirty = false;
@Output() hostRecordChange = new EventEmitter<HostRecord>(); protected dbRecord: any = {};
@Output() requestParentSave = new EventEmitter<CodeComponent>(); protected codeRefId!: string;
@Output() requestParentDelete = new EventEmitter<CodeComponent>();
@ViewChild('theEditor') theEditor;
public dirty = false; public editorOptions = {
public pendingSetup = true; language: 'javascript',
protected dbRecord: any = {}; uri: v4(),
readOnly: false,
};
public languageOptions: Array<string> = [ public editorValue = '';
'ABAP', public get readonly() {
'AES', return !this.node || !this.editorService.canEdit();
'Apex', }
'AZCLI',
'Bat',
'C',
'Cameligo',
'Clojure',
'CoffeeScript',
'Cpp',
'Csharp',
'CSP',
'CSS',
'Dockerfile',
'Fsharp',
'Go',
'GraphQL',
'Handlebars',
'HTML',
'INI',
'Java',
'JavaScript',
'JSON',
'Kotlin',
'LeSS',
'Lua',
'Markdown',
'MiPS',
'MSDAX',
'MySQL',
'Objective-C',
'Pascal',
'Pascaligo',
'Perl',
'pgSQL',
'PHP',
'Plaintext',
'Postiats',
'PowerQuery',
'PowerShell',
'Pug',
'Python',
'R',
'Razor',
'Redis',
'RedShift',
'RestructuredText',
'Ruby',
'Rust',
'SB',
'Scheme',
'SCSS',
'Shell',
'SOL',
'SQL',
'St',
'Swift',
'TCL',
'Twig',
'TypeScript',
'VB',
'XML',
'YAML',
];
public editorOptions = { public languageOptions: Array<string> = [
language: 'javascript', 'ABAP',
uri: v4(), 'AES',
readOnly: this.readonly, 'Apex',
}; 'AZCLI',
public editorValue = ''; 'Bat',
'C',
'Cameligo',
'Clojure',
'CoffeeScript',
'Cpp',
'Csharp',
'CSP',
'CSS',
'Dockerfile',
'Fsharp',
'Go',
'GraphQL',
'Handlebars',
'HTML',
'INI',
'Java',
'JavaScript',
'JSON',
'Kotlin',
'LeSS',
'Lua',
'Markdown',
'MiPS',
'MSDAX',
'MySQL',
'Objective-C',
'Pascal',
'Pascaligo',
'Perl',
'pgSQL',
'PHP',
'Plaintext',
'Postiats',
'PowerQuery',
'PowerShell',
'Pug',
'Python',
'R',
'Razor',
'Redis',
'RedShift',
'RestructuredText',
'Ruby',
'Rust',
'SB',
'Scheme',
'SCSS',
'Shell',
'SOL',
'SQL',
'St',
'Swift',
'TCL',
'Twig',
'TypeScript',
'VB',
'XML',
'YAML',
];
protected hadLoad = false;
constructor( constructor(
protected api: ApiService, public readonly editorService: EditorService,
protected loader: LoadingController, public readonly api: ApiService,
protected alerts: AlertController, ) { super(); }
) { }
ngOnInit() { public isDirty(): boolean | Promise<boolean> {
this.loader.create({message: 'Loading code...'}).then(loader => { return this.dirty;
loader.present().then(() => { }
this.getInitObservable().subscribe(() => {
this.editorOptions.language = this.dbRecord.Language; public needsSave(): boolean | Promise<boolean> {
this.editorOptions.readOnly = this.readonly; return this.dirty;
this.onSelectChange(false); }
loader.dismiss();
public writeChangesToNode(): void | Promise<void> {
this.node.Value.Mode = 'code';
this.node.Value.Value = this.codeRefId;
this.node.value = this.codeRefId;
}
public needsLoad(): boolean | Promise<boolean> {
return this.node && !this.hadLoad;
}
public performLoad(): void | Promise<void> {
return new Promise((res, rej) => {
if ( !this.node.Value ) {
this.node.Value = {};
}
if ( !this.node.Value.Value && this.editorService.canEdit() ) {
this.api.post(`/code/${this.page.UUID}/${this.node.UUID}/create`).subscribe({
next: result => {
this.dbRecord = result.data;
this.node.Value.Mode = 'code';
this.node.Value.Value = result.data.UUID;
this.node.value = result.data.UUID;
this.codeRefId = result.data.UUID;
this.editorOptions.readOnly = this.readonly;
this.onSelectChange(false);
this.hadLoad = true;
res();
},
error: rej,
});
} else {
this.api.get(`/code/${this.page.UUID}/${this.node.UUID}/get/${this.node.Value.Value}`).subscribe({
next: result => {
this.dbRecord = result.data;
this.initialValue = this.dbRecord.code;
this.editorValue = this.dbRecord.code;
this.editorOptions.language = this.dbRecord.Language;
this.codeRefId = this.node.Value.Value;
this.editorOptions.readOnly = this.readonly;
this.onSelectChange(false);
this.hadLoad = true;
res();
},
error: rej,
});
}
});
}
public performSave(): void | Promise<void> {
if ( !this.editorService.canEdit() ) {
return;
}
return new Promise((res, rej) => {
this.dbRecord.code = this.editorValue;
this.dbRecord.Language = this.editorOptions.language;
this.api.post(`/code/${this.page.UUID}/${this.node.UUID}/set/${this.node.Value.Value}`, this.dbRecord)
.subscribe({
next: result => {
this.dbRecord = result.data;
this.editorOptions.language = this.dbRecord.Language;
this.editorValue = this.dbRecord.code;
this.dirty = false;
res();
},
error: rej,
});
});
}
public performDelete(): void | Promise<void> {
return new Promise((res, rej) => {
this.api.post(`/code/${this.page.UUID}/${this.node.UUID}/delete/${this.node.Value.Value}`).subscribe({
next: result => {
res();
},
error: rej,
}); });
}); });
});
}
getInitObservable(): Observable<any> {
return new Observable<any>(sub => {
if ( this.hostRecord && this.pendingSetup ) {
if ( !this.hostRecord.Value ) {
this.hostRecord.Value = {};
}
if ( !this.hostRecord.Value.Value && !this.readonly ) {
this.api.post(`/code/${this.hostRecord.PageId}/${this.hostRecord.UUID}/create`).subscribe(res => {
this.dbRecord = res.data;
this.hostRecord.Value.Mode = 'code';
this.hostRecord.Value.Value = res.data.UUID;
this.hostRecord.value = res.data.UUID;
this.hostRecordChange.emit(this.hostRecord);
this.pendingSetup = false;
sub.next(true);
sub.complete();
});
} else {
this.api.get(`/code/${this.hostRecord.PageId}/${this.hostRecord.UUID}/get/${this.hostRecord.Value.Value}`).subscribe(res => {
this.dbRecord = res.data;
this.editorValue = this.dbRecord.code;
this.editorOptions.language = this.dbRecord.Language;
this.pendingSetup = false;
sub.next(true);
sub.complete();
});
}
} else {
this.pendingSetup = true;
}
});
}
onSaveClick() {
if ( this.readonly ) {
return;
}
this.dbRecord.code = this.editorValue;
this.dbRecord.Language = this.editorOptions.language;
this.api.post(`/code/${this.hostRecord.PageId}/${this.hostRecord.UUID}/set/${this.hostRecord.Value.Value}`, this.dbRecord)
.subscribe(res => {
this.dbRecord = res.data;
this.editorOptions.language = this.dbRecord.Language;
this.editorValue = this.dbRecord.code;
this.dirty = false;
});
}
async onDropClick() {
if ( this.readonly ) {
return;
}
const alert = await this.alerts.create({
header: 'Are you sure?',
message: `You are about to delete this code. This action cannot be undone.`,
buttons: [
{
text: 'Keep It',
role: 'cancel',
},
{
text: 'Delete It',
handler: async () => {
this.api.post(`/code/${this.hostRecord.PageId}/${this.hostRecord.UUID}/delete/${this.hostRecord.Value.Value}`)
.subscribe(res => {
this.requestParentDelete.emit(this);
});
},
},
],
});
await alert.present();
}
public onEditorModelChange($event) {
if ( this.editorValue !== this.dbRecord.code ) {
this.dirty = true;
}
}
onSelectChange(updateDbRecord = true) {
if ( updateDbRecord ) {
this.dbRecord.Language = this.editorOptions.language;
} }
this.editorOptions = {...this.editorOptions}; ngOnInit() {
} this.editorService.registerNodeEditor(this.nodeId, this).then(() => {
this.editorOptions.readOnly = !this.editorService.canEdit();
});
}
public onEditorModelChange($event) {
if ( this.editorValue !== this.dbRecord.code ) {
this.dirty = true;
}
}
public onSelectChange(updateDbRecord = true) {
if ( updateDbRecord ) {
this.dbRecord.Language = this.editorOptions.language;
}
this.editorOptions = {...this.editorOptions};
}
} }

View File

@ -19,11 +19,11 @@
<div class="editor-root ion-padding"> <div class="editor-root ion-padding">
<div <div
class="host-container" class="host-container"
style="display: flex;" style="display: flex; margin-bottom: 20px;"
*ngFor="let node of editorService.immutableNodes" *ngFor="let node of editorService.immutableNodes"
> >
<div class="host-icons"> <div class="host-icons">
<i class="type-icon norm fa" [ngClass]="typeIcons.norm" title="WYSIWYG Node"></i> <i class="type-icon fa" [ngClass]="typeIcons[(node.isNorm() ? 'node' : node.type)] + ' ' + (node.isNorm() ? 'node' : node.type)" title="WYSIWYG Node"></i>
<button (click)="onOptionsClick($event, node)"> <button (click)="onOptionsClick($event, node)">
<i class="fa fa-ellipsis-v" title="Node options"></i> <i class="fa fa-ellipsis-v" title="Node options"></i>
</button> </button>
@ -31,6 +31,9 @@
<ng-container *ngIf="node.isNorm()"> <ng-container *ngIf="node.isNorm()">
<editor-norm style="flex: 1;" [nodeId]="node.UUID"></editor-norm> <editor-norm style="flex: 1;" [nodeId]="node.UUID"></editor-norm>
</ng-container> </ng-container>
<ng-container *ngIf="node.type === 'code_ref'">
<editor-code style="flex: 1;" [nodeId]="node.UUID"></editor-code>
</ng-container>
</div> </div>
<button class="host-add-button" (click)="onAddClick($event)"> <button class="host-add-button" (click)="onAddClick($event)">
<i class="fa fa-plus"></i> Add Node <i class="fa fa-plus"></i> Add Node

View File

@ -15,10 +15,19 @@ ion-icon.invisible {
.type-icon { .type-icon {
margin-bottom: 15px; margin-bottom: 15px;
margin-top: 15px;
&.norm { &.node {
color: var(--noded-background-node); color: var(--noded-background-node);
} }
&.code_ref {
color: var(--noded-background-code);
}
&.db {
color: var(--noded-background-db);
}
} }
.host-add-button { .host-add-button {

View File

@ -24,6 +24,7 @@ export class EditorPage implements OnInit {
page: 'fa fa-sticky-note', page: 'fa fa-sticky-note',
db: 'fa fa-database', db: 'fa fa-database',
code: 'fa fa-code', code: 'fa fa-code',
code_ref: 'fa fa-code',
}; };
@Input() pageId: string; @Input() pageId: string;