From ed6d14eccfe3fb58d2f358f7ede74d781b29fa3a Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Mon, 11 Mar 2019 10:52:14 -0700 Subject: [PATCH 1/2] App2app to open files and folders. Removed lsp websocket for now. Removed broken font ref Signed-off-by: 1000TurquoisePogs --- webClient/src/app/app.component.ts | 91 ++++++++++++++++++- .../code-editor/code-editor.component.html | 1 - .../code-editor/code-editor.component.ts | 3 +- .../code-editor/monaco/monaco.component.ts | 2 + .../project-tree/project-tree.component.ts | 64 +++++++------ .../editor-control/editor-control.service.ts | 9 +- 6 files changed, 138 insertions(+), 32 deletions(-) diff --git a/webClient/src/app/app.component.ts b/webClient/src/app/app.component.ts index 4eb802e8..a47d8089 100644 --- a/webClient/src/app/app.component.ts +++ b/webClient/src/app/app.component.ts @@ -10,6 +10,10 @@ */ import { Component, Inject } from '@angular/core'; import { Angular2InjectionTokens } from 'pluginlib/inject-resources'; +import { EditorControlService } from './shared/editor-control/editor-control.service'; +import { HttpService } from './shared/http/http.service'; +import { DataAdapterService } from './shared/http/http.data.adapter.service'; +import { UtilsService } from './shared/utils.service'; @Component({ selector: 'app-root', @@ -19,9 +23,94 @@ import { Angular2InjectionTokens } from 'pluginlib/inject-resources'; export class AppComponent { title = 'app'; - constructor(@Inject(Angular2InjectionTokens.LOGGER) private log: ZLUX.ComponentLogger) { + constructor(@Inject(Angular2InjectionTokens.LOGGER) private log: ZLUX.ComponentLogger, + @Inject(Angular2InjectionTokens.LAUNCH_METADATA) private launchMetadata: any, + private dataAdapter: DataAdapterService, + private httpService: HttpService, + private utils: UtilsService, + private editorControl: EditorControlService) { this.log.debug(`Monaco object=`,(window).monaco); } + + ngOnInit() { + if (this.launchMetadata && this.launchMetadata.data && this.launchMetadata.data.type) { + this.handleLaunchOrMessageObject(this.launchMetadata.data); + } + } + + handleLaunchOrMessageObject(data: any) { + switch (data.type) { + case 'openFile': + //TODO should this or must this also load the directory at the time that the file is + let lastSlash = data.name.lastIndexOf("/"); + let firstSlash = data.name.indexOf("/"); + if (lastSlash == data.name.length-1) { + this.log.warn(`Ignoring opening invalid file or dataset name=${data.name}`); + return; + } + let parenIsLast = data.name.lastIndexOf(")") == data.name.length-1; + let openParen = data.name.indexOf("("); + let hasSlash = lastSlash != -1; + let isDataset = false; + if (hasSlash && parenIsLast && openParen != -1 && firstSlash > openParen) { + isDataset = true; + } + let nodeData; + if (!isDataset) { + let uri = ZoweZLUX.uriBroker.unixFileUri('contents', data.name.substring(0,lastSlash)); + this.log.info(`I will be executing uri=${uri}, and looking for filename=${data.name.substring(lastSlash+1)}`); + this.httpService.get(uri) + .subscribe((response: any) => { + let nodes = this.dataAdapter.convertDirectoryList(response); + this.editorControl.setProjectNode(nodes); + let fileName = data.name.substring(lastSlash+1); + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].fileName == fileName) { + this.editorControl.openFile('', nodes[i]).subscribe(x => { + this.log.debug(`file loaded through app2app.`); + }); + } + } + }, e => { + let error = e.json().error; +// this.snackBarService.open(`Directory ${dirName} does not exist!`, 'Close', { duration: 2000, panelClass: 'center' }); + }); + } + break; + case 'openDir': + this.editorControl.loadDirectory(data.name); + break; + case 'openDSList': + this.editorControl.loadDirectory(data.name); + break; + default: + this.log.warn(`Unknown command (${data.type}) given in launch metadata.`); + } + } + + + /* I expect a JSON here*/ + zluxOnMessage(eventContext: any): Promise { + return new Promise((resolve,reject)=> { + if (eventContext != null && eventContext.data != null && eventContext.data.type != null) { + resolve(this.handleLaunchOrMessageObject(eventContext.data)); + } else { + let msg = 'Event context missing or malformed'; + this.log.warn('onMessage '+msg); + return reject(msg); + } + }); + } + + + provideZLUXDispatcherCallbacks(): ZLUX.ApplicationCallbacks { + return { + onMessage: (eventContext: any): Promise => { + return this.zluxOnMessage(eventContext); + } + } + } + } /* diff --git a/webClient/src/app/editor/code-editor/code-editor.component.html b/webClient/src/app/editor/code-editor/code-editor.component.html index d2fdab1c..151b6867 100644 --- a/webClient/src/app/editor/code-editor/code-editor.component.html +++ b/webClient/src/app/editor/code-editor/code-editor.component.html @@ -14,7 +14,6 @@

Welcome to the Zowe Editor!

Please open a file from File Explorer to start your journey! -

diff --git a/webClient/src/app/editor/code-editor/code-editor.component.ts b/webClient/src/app/editor/code-editor/code-editor.component.ts index 4eae0aea..f0edbabc 100644 --- a/webClient/src/app/editor/code-editor/code-editor.component.ts +++ b/webClient/src/app/editor/code-editor/code-editor.component.ts @@ -34,8 +34,7 @@ export class CodeEditorComponent implements OnInit { lightbulb: { enabled: true }, - theme: 'vs-dark', - fontFamily: 'monaco' + theme: 'vs-dark' }; public editorFile: { context: ProjectContext, reload: boolean, line?: number }; diff --git a/webClient/src/app/editor/code-editor/monaco/monaco.component.ts b/webClient/src/app/editor/code-editor/monaco/monaco.component.ts index 54689d5c..f6399e65 100644 --- a/webClient/src/app/editor/code-editor/monaco/monaco.component.ts +++ b/webClient/src/app/editor/code-editor/monaco/monaco.component.ts @@ -53,6 +53,7 @@ export class MonacoComponent implements OnInit, OnChanges { onMonacoInit(editor) { this.editorControl.editor.next(editor); this.keyBinds(editor); + /* disable for now... this.editorControl.connToLS.subscribe((lang) => { this.connectToLanguageServer(lang); }); @@ -61,6 +62,7 @@ export class MonacoComponent implements OnInit, OnChanges { }); this.connectToLanguageServer(); + */ } keyBinds(editor: any) { diff --git a/webClient/src/app/editor/project-tree/project-tree.component.ts b/webClient/src/app/editor/project-tree/project-tree.component.ts index 30b51067..3ca211a4 100644 --- a/webClient/src/app/editor/project-tree/project-tree.component.ts +++ b/webClient/src/app/editor/project-tree/project-tree.component.ts @@ -115,37 +115,46 @@ export class ProjectTreeComponent implements OnInit { }); this.editorControl.openDirectory.subscribe(dirName => { - this.log.debug(`Open Dir=${dirName}`); - if (dirName != null && dirName !== '') { - if (dirName[0] == '/') { - // start get project structure - dirName = ['/', '\\'].indexOf(dirName.substring(0, 1)) > -1 ? dirName.substring(1) : dirName; - let requestUrl = ZoweZLUX.uriBroker.unixFileUri('contents', dirName); - this.httpService.get(requestUrl) - .subscribe((response: any) => { - // TODO: nodes should check project context once the component is loaded. - this.nodes = this.dataAdapter.convertDirectoryList(response); - this.editorControl.setProjectNode(this.nodes); - this.editorControl.initProjectContext(this.utils.getFolderName(dirName), this.nodes); - }, e => { + this.loadDirectoryIntoTree(dirName); + }); + } + + public loadDirectoryIntoTree(dirName:string) { + this.log.debug(`Open Dir=${dirName}`); + if (dirName != null && dirName !== '') { + if (dirName[0] == '/') { + // start get project structure + dirName = ['/', '\\'].indexOf(dirName.substring(0, 1)) > -1 ? dirName.substring(1) : dirName; + let requestUrl = ZoweZLUX.uriBroker.unixFileUri('contents', dirName); + this.httpService.get(requestUrl) + .subscribe((response: any) => { + // TODO: nodes should check project context once the component is loaded. + this.nodes = this.dataAdapter.convertDirectoryList(response); + this.editorControl.setProjectNode(this.nodes); + this.editorControl.initProjectContext(this.utils.getFolderName(dirName), this.nodes); + }, e => { + try { let error = e.json().error; this.snackBarService.open(`Directory ${dirName} does not exist!`, 'Close', { duration: 2000, panelClass: 'center' }); - }); - } else { - // dataset - let requestUrl = ZoweZLUX.uriBroker.datasetMetadataUri(dirName, 'true'); - this.httpService.get(requestUrl) - .subscribe((response: any) => { - this.nodes = this.dataAdapter.convertDatasetList(response); - this.editorControl.setProjectNode(this.nodes); - this.editorControl.initProjectContext(dirName, this.nodes); - }, e => { - // TODO - }); - } + } catch (err) { + this.snackBarService.open(`${dirName} is not a directory.`, 'Close', { duration: 2000, panelClass: 'center' }); + } + }); + } else { + // dataset + let requestUrl = ZoweZLUX.uriBroker.datasetMetadataUri(dirName, 'true'); + this.httpService.get(requestUrl) + .subscribe((response: any) => { + this.nodes = this.dataAdapter.convertDatasetList(response); + this.editorControl.setProjectNode(this.nodes); + this.editorControl.initProjectContext(dirName, this.nodes); + }, e => { + // TODO + }); } - }); + } } + ngOnInit() { } @@ -179,6 +188,7 @@ export class ProjectTreeComponent implements OnInit { if (!$event.node.data.children && !$event.node.data.hasChildren) { const nodeData: ProjectStructure = $event.node.data; this.editorControl.openFile('', nodeData).subscribe(x => { + this.log.debug(`NodeData=`,nodeData); this.log.debug(`file loaded through project explorer.`); }); // this.editorControl.openFileEmitter.emit(nodeData); diff --git a/webClient/src/app/shared/editor-control/editor-control.service.ts b/webClient/src/app/shared/editor-control/editor-control.service.ts index 03deb0e8..5065656c 100644 --- a/webClient/src/app/shared/editor-control/editor-control.service.ts +++ b/webClient/src/app/shared/editor-control/editor-control.service.ts @@ -32,7 +32,9 @@ export let EditorServiceInstance: BehaviorSubject = new BehaviorSubject(und * @export * @class EditorControlService */ -@Injectable() +@Injectable({ + providedIn: 'root', +}) export class EditorControlService implements ZLUX.IEditor, ZLUX.IEditorMultiBuffer, ZLUX.IEditorSyntaxHighlighting { public createFileEmitter: EventEmitter = new EventEmitter(); public openProject: EventEmitter = new EventEmitter(); @@ -635,6 +637,11 @@ export class EditorControlService implements ZLUX.IEditor, ZLUX.IEditorMultiBuff this.openFileEmitter.emit(targetBuffer); return resultOpenObs; } + + loadDirectory(path: string) { + this.log.debug('Loading directory=',path); + this.openDirectory.next(path); + } /** * Save a buffer into a file. * From d068cc3f99cc72a4a7c9f62309905e6a67b7bed2 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Tue, 19 Mar 2019 15:47:42 -0400 Subject: [PATCH 2/2] Fixed bug where there was a timing issue opening initial edit window Signed-off-by: 1000TurquoisePogs --- .../code-editor/monaco/monaco.service.ts | 75 +++++++++++-------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/webClient/src/app/editor/code-editor/monaco/monaco.service.ts b/webClient/src/app/editor/code-editor/monaco/monaco.service.ts index 17a9c390..4f0a85d7 100644 --- a/webClient/src/app/editor/code-editor/monaco/monaco.service.ts +++ b/webClient/src/app/editor/code-editor/monaco/monaco.service.ts @@ -104,38 +104,51 @@ export class MonacoService { setMonacoModel(fileNode: ProjectContext, file: { contents: string, language: string }): Observable { return new Observable((obs) => { - const _editor = this.editorControl.editorCore.getValue().editor; - fileNode.model.contents = file['contents']; - this.editorControl.getRecommendedHighlightingModesForBuffer(fileNode).subscribe((supportLanguages: string[]) => { - let fileLang = 'plaintext'; - if (file['language']) { - fileLang = file['language']; - } else if (fileNode.model.language) { - fileLang = fileNode.model.language; - } else if (supportLanguages[0]) { - fileLang = supportLanguages[0]; - } - // sync language to context - fileNode.model.language = fileLang; - const model = { - value: file['contents'], - language: fileLang, - // language: 'json', - uri: this.generateUri(fileNode.model), - }; - const duplicate: boolean = this.fileDuplicateChecker(model.uri); - let newModel; - if (!duplicate) { - newModel = _editor.createModel(model.value, model.language, model.uri); - } else { - newModel = _editor.getModel(model.uri); - } - newModel.onDidChangeContent((e: any) => { - this.fileContentChangeHandler(e, fileNode, newModel); + let coreSubscription = this.editorControl.editorCore + .subscribe((value)=> { + if (value && value.editor) { + const editorCore = value.editor; + //getValue().editor; + + fileNode.model.contents = file['contents']; + this.editorControl.getRecommendedHighlightingModesForBuffer(fileNode).subscribe((supportLanguages: string[]) => { + let fileLang = 'plaintext'; + if (file['language']) { + fileLang = file['language']; + } else if (fileNode.model.language) { + fileLang = fileNode.model.language; + } else if (supportLanguages[0]) { + fileLang = supportLanguages[0]; + } + // sync language to context + fileNode.model.language = fileLang; + const model = { + value: file['contents'], + language: fileLang, + // language: 'json', + uri: this.generateUri(fileNode.model), + }; + const duplicate: boolean = this.fileDuplicateChecker(model.uri); + let newModel; + if (!duplicate) { + newModel = editorCore.createModel(model.value, model.language, model.uri); + } else { + newModel = editorCore.getModel(model.uri); + } + newModel.onDidChangeContent((e: any) => { + this.fileContentChangeHandler(e, fileNode, newModel); + }); + let editorSubscription = this.editorControl.editor.subscribe((value)=> { + if (value) { + value.setModel(newModel); + editorSubscription.unsubscribe(); + obs.next(); + } + }); + }); + coreSubscription.unsubscribe(); + } }); - this.editorControl.editor.getValue().setModel(newModel); - obs.next(); - }); }); }