1+ // Copyright (C) 2023 Coretex LLC
2+
3+ // This file is part of Coretex.ai
4+
5+ // This program is free software: you can redistribute it and/or modify
6+ // it under the terms of the GNU Affero General Public License as
7+ // published by the Free Software Foundation, either version 3 of the
8+ // License, or (at your option) any later version.
9+
10+ // This program is distributed in the hope that it will be useful,
11+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ // GNU Affero General Public License for more details.
14+
15+ // You should have received a copy of the GNU Affero General Public License
16+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
18+ import * as vscode from 'vscode' ;
19+ import * as child_process from 'child_process' ;
20+ import { getNonce } from '../utilities/getNonce' ;
21+
22+ export class ProjectView implements vscode . WebviewViewProvider {
23+ viewId = 'coretex.project' ;
24+ private _view ?: vscode . WebviewView ;
25+
26+ constructor ( private readonly _extensionUri : vscode . Uri ) { }
27+
28+ public resolveWebviewView ( webviewView : vscode . WebviewView ) : void {
29+ this . _view = webviewView ;
30+
31+ webviewView . webview . options = {
32+ // Allow scripts in the webview
33+ enableScripts : true ,
34+
35+ localResourceRoots : [
36+ this . _extensionUri
37+ ]
38+ } ;
39+
40+ this . updateView ( ) ;
41+
42+ this . _view . onDidChangeVisibility ( async event => {
43+ this . updateView ( ) ;
44+ } ) ;
45+
46+ this . _view . webview . onDidReceiveMessage ( data => {
47+ this . runCommand ( data ) ;
48+ } ) ;
49+ }
50+
51+ private updateView ( ) : void {
52+ if ( ! this . _view ) {
53+ return ;
54+ }
55+
56+ const storagePath = this . checkStoragePath ( ) ;
57+ const text = storagePath == '' ? 'Storage path not set. Check your configuration.' : storagePath . substring ( storagePath . indexOf ( ':' ) + 1 , storagePath . length ) ;
58+
59+ this . _view . webview . html = this . getWebviewContent ( this . _view . webview , text ) ;
60+ }
61+
62+ private getRunCommand ( space : number , node : number , path : string ) : string {
63+ const platform = process . platform ;
64+ if ( platform === 'darwin' || platform === 'linux' ) {
65+ return `coretex run create ${ node } -s ${ space } -f ${ path } ` ;
66+ } else if ( platform === 'win32' ) {
67+ return `coretex.exe run create ${ node } -s ${ space } -f ${ path } ` ;
68+ }
69+
70+ return '' ;
71+ }
72+
73+ private async runCommand ( data : any ) {
74+ switch ( data . type ) {
75+ case 'start' :
76+ {
77+ const spaceConf = 'Space' ;
78+ const nodeConf = 'NodeID' ;
79+
80+ const conf = vscode . workspace . getConfiguration ( ) ;
81+ const spaceID = conf . get < { } > ( spaceConf ) ;
82+ const spaceDefaultValue = spaceID ? spaceID . toString ( ) : '' ;
83+
84+ const space = await vscode . window . showInputBox ( {
85+ prompt : 'Enter Space ID in which you wish to run the Job' ,
86+ placeHolder : 'Space' ,
87+ validateInput : ( value ) => ( value ? null : 'Space is required' ) ,
88+ value : spaceDefaultValue , // Default value
89+ } ) ;
90+
91+ if ( ! space ) {
92+ vscode . window . showErrorMessage (
93+ 'Space is required to run a Job.'
94+ ) ;
95+ return ;
96+ }
97+
98+ const nodeID = conf . get < { } > ( nodeConf ) ;
99+ const nodeDefaultValue = nodeID ? nodeID . toString ( ) : '' ;
100+
101+ const node = await vscode . window . showInputBox ( {
102+ prompt : 'Enter Node ID on which you wish to run the Job' ,
103+ placeHolder : 'Node' ,
104+ validateInput : ( value ) => ( value ? null : 'Node is required' ) ,
105+ value : nodeDefaultValue , // Default value
106+ } ) ;
107+
108+ if ( ! node ) {
109+ vscode . window . showErrorMessage (
110+ 'Node is required to run a Job.'
111+ ) ;
112+ return ;
113+ }
114+
115+ let currentWorkspacePath = '' ;
116+
117+ if ( vscode . workspace . workspaceFolders ) {
118+ currentWorkspacePath = vscode . workspace . workspaceFolders [ 0 ] . uri . path ;
119+ }
120+
121+ const command = this . getRunCommand ( Number ( space ) , Number ( node ) , currentWorkspacePath ) ;
122+
123+ vscode . window . terminals . forEach ( ( terminal ) => {
124+ terminal . dispose ( ) ;
125+ } ) ;
126+ const terminal = vscode . window . createTerminal ( ) ;
127+ terminal . show ( ) ;
128+ terminal . sendText ( command ) ;
129+ break ;
130+ }
131+ case 'nodes' :
132+ {
133+ vscode . commands . executeCommand ( 'coretex.listNodes' ) ;
134+ }
135+ }
136+ }
137+
138+ private checkStoragePath ( ) : string {
139+ const platform = process . platform ;
140+ if ( platform === 'darwin' || platform === 'linux' ) {
141+ try {
142+ const version = child_process . execSync ( 'coretex storage' ) ;
143+ return version . toString ( ) ;
144+ } catch ( error ) {
145+ return '' ;
146+ }
147+ } else if ( platform === 'win32' ) {
148+ try {
149+ const version = child_process . execSync ( 'coretex storage' ) ;
150+ return version . toString ( ) ;
151+ } catch ( error ) {
152+ try {
153+ const version = child_process . execSync ( 'coretex.exe storage' ) ;
154+ return version . toString ( ) ;
155+ } catch ( error ) {
156+ return '' ;
157+ }
158+ }
159+ }
160+
161+ return '' ;
162+ }
163+
164+ private getWebviewContent ( webview : vscode . Webview , text : string ) : string {
165+ const viewStyle = webview . asWebviewUri ( vscode . Uri . joinPath ( this . _extensionUri , 'media' , 'views.css' ) ) ;
166+ const runStyle = 'start-action button'
167+ const nodesStyle = 'update-action-new button'
168+
169+ const scriptUri = webview . asWebviewUri ( vscode . Uri . joinPath ( this . _extensionUri , 'media' , 'projectViewScripts.js' ) ) ;
170+
171+ // Use a nonce to only allow a specific script to be run.
172+ const nonce = getNonce ( ) ;
173+
174+ return `
175+ <!DOCTYPE html>
176+ <html lang="en">
177+ <head>
178+ <meta charset="UTF-8">
179+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${ webview . cspSource } ; script-src 'nonce-${ nonce } ';">
180+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
181+ <link href="${ viewStyle } " rel="stylesheet">
182+ <title>Project</title>
183+ </head>
184+ <body>
185+ <p>Run a Job with the current workspace contents:</p>
186+ <button class="${ runStyle } ">Run Job</button>
187+ <p>List nodes available for Job execution (set default in global extension settings):</p>
188+ <button class="${ nodesStyle } ">List Nodes</button>
189+ <p class="title">Storage path:</p>
190+ <p class="subtitle">${ text } </p>
191+ <script nonce="${ nonce } " src="${ scriptUri } "></script>
192+ </body>
193+ </html>
194+ ` ;
195+ }
196+ }
0 commit comments