@@ -20,7 +20,7 @@ import {
20
20
Step ,
21
21
StepLabel ,
22
22
} from "@mui/material" ;
23
- import { Help , Insights , Refresh } from '@mui/icons-material' ;
23
+ import { Help , Insights , Refresh , Psychology } from '@mui/icons-material' ;
24
24
import { createDockerDesktopClient } from '@docker/extension-api-client' ;
25
25
import Confetti from 'react-confetti'
26
26
@@ -208,8 +208,12 @@ export default function NebulaGraphTabs() {
208
208
209
209
const [ coreContainers , setCoreContainers ] = React . useState < any [ ] > ( [ ] ) ;
210
210
const [ utilsContainers , setUtilsContainers ] = React . useState < any [ ] > ( [ ] ) ;
211
+ const [ ngaiContainers , setNgaiContainers ] = React . useState < any [ ] > ( [ ] ) ;
211
212
212
213
const [ storageActivated , setStorageActivated ] = React . useState ( false ) ;
214
+ const [ ngaiDeployed , setNgaiDeployed ] = React . useState ( false ) ;
215
+ const [ isNgaiDeploying , setNgaiIsDeploying ] = React . useState ( false ) ;
216
+ const [ isNgaiUndeploying , setNgaiIsUndeploying ] = React . useState ( false ) ;
213
217
214
218
const openExternalUrl = ( url : string ) => {
215
219
ddClient . host . openExternal ( url ) ;
@@ -270,13 +274,15 @@ export default function NebulaGraphTabs() {
270
274
// get started stepper tab end
271
275
272
276
const fetchContainerList = async ( ) => {
273
- ddClient . docker . cli . exec ( 'ps' , [ '--all' , '--format' , '"{{json .}}"' , '--filter' , 'label=com.vesoft.scope=core' ] ) . then ( ( result ) => {
277
+ ddClient . docker . cli . exec ( 'ps' , [ '--all' , '--format' , '"{{json .}}"' , '--filter' , 'label=com.vesoft.scope=core' ] ) . then ( ( result : any ) => {
274
278
setCoreContainers ( result . parseJsonLines ( ) ) ;
275
279
} ) ;
276
- ddClient . docker . cli . exec ( 'ps' , [ '--all' , '--format' , '"{{json .}}"' , '--filter' , 'label=com.vesoft.scope=utils' ] ) . then ( ( result ) => {
280
+ ddClient . docker . cli . exec ( 'ps' , [ '--all' , '--format' , '"{{json .}}"' , '--filter' , 'label=com.vesoft.scope=utils' ] ) . then ( ( result : any ) => {
277
281
setUtilsContainers ( result . parseJsonLines ( ) ) ;
278
282
} ) ;
279
-
283
+ ddClient . docker . cli . exec ( 'ps' , [ '--all' , '--format' , '"{{json .}}"' , '--filter' , 'label=com.vesoft.scope=ngai' ] ) . then ( ( result : any ) => {
284
+ setNgaiContainers ( result . parseJsonLines ( ) ) ;
285
+ } ) ;
280
286
setTimeout ( fetchContainerList , 60000 ) ;
281
287
addHostsIfStorageUnhealthy ( ) ;
282
288
} ;
@@ -298,7 +304,7 @@ export default function NebulaGraphTabs() {
298
304
}
299
305
const networkName = unhealthyStoragedContainers [ 0 ] [ "Networks" ]
300
306
if ( networkName ) {
301
- ddClient . docker . cli . exec ( 'run' , [ '--net' , networkName , '--rm' , 'vesoft/nebula-console:v3' , '-addr' , 'graphd' , '-port' , '9669' , '-u' , 'root' , '-p' , 'nebula' , '-e' , '\'ADD HOSTS "storaged0":9779,"storaged1":9779,"storaged2":9779\'' ] ) . then ( ( result ) => {
307
+ ddClient . docker . cli . exec ( 'run' , [ '--net' , networkName , '--rm' , 'vesoft/nebula-console:v3' , '-addr' , 'graphd' , '-port' , '9669' , '-u' , 'root' , '-p' , 'nebula' , '-e' , '\'ADD HOSTS "storaged0":9779,"storaged1":9779,"storaged2":9779\'' ] ) . then ( ( result : any ) => {
302
308
console . log ( "the result of adding hosts: " , result ) ;
303
309
if ( result . stdout . includes ( "existed" ) ) {
304
310
setStorageActivated ( true ) ;
@@ -307,6 +313,86 @@ export default function NebulaGraphTabs() {
307
313
}
308
314
} ;
309
315
316
+ // Deploy NebulaGraph ngai Playground
317
+ // 0.1 run docker exec nebulagraph_webshell mkdir -p /host_data/ngai
318
+ // 0.2 run docker exec nebulagraph_webshell mkdir -p /host_data/download
319
+ // 0.3 run docker exec nebulagraph_webshell mkdir -p /host_data/udf
320
+ // 1. run docker exec nebulagraph_webshell wget -O /host_data/ngai/docker-compose.yaml https://raw.githubusercontent.com/nebula-contrib/nebulagraph-docker-ext/main/optional_workload/docker-compose-ngai.yaml
321
+ // 2. run docker exec nebulagraph_webshell wget -O /host_data/download/nebula-algo.jar https://repo1.maven.org/maven2/com/vesoft/nebula-algorithm/$ALGO_VERSION/nebula-algorithm-$ALGO_VERSION.jar
322
+ // 3. run docker exec nebulagraph_webshell wget -O /host_data/download/nebula-spark-connector.jar https://repo1.maven.org/maven2/com/vesoft/nebula-spark-connector/$SPARK_C_VERSION/nebula-spark-connector-$SPARK_C_VERSION.jar
323
+ // 4. run docker exec nebulagraph_webshell wget -O /host_data/udf/ng_ai.so https://github.com/wey-gu/nebulagraph-ai/releases/download/0.2.9/ng_ai-ubuntu-2004-nebulagraph-nightly-2023.03.13.so
324
+ // 5. run docker exec nebulagraph_webshell chmod +x /host_data/udf/ng_ai.so
325
+ // 6. run docker-compose -f ~/.nebulagraph/ngai/docker-compose.yaml up -d --remove-orphans
326
+ // 7. run docker exec nebulagraph_webshell wget -O /host_data/ngai/AI_suite_demo.ipynb https://raw.githubusercontent.com/wey-gu/nebula-up/main/spark/AI_suite_demo.ipynb
327
+ // 8. run docker exec nebulagraph_webshell wget -O /host_data/ngai/AI_suite_nGQL_UDF.ipynb https://raw.githubusercontent.com/wey-gu/nebula-up/main/spark/AI_suite_nGQL_UDF.ipynb
328
+
329
+ const deployNgai = async ( ) => {
330
+ if ( isNgaiDeploying ) {
331
+ console . log ( "Ngai is deploying, please wait..." ) ;
332
+ return ;
333
+ }
334
+ setNgaiIsDeploying ( true ) ;
335
+ console . log ( "Start deploying Ngai..." ) ;
336
+ const mkdirPromises = [
337
+ ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'mkdir' , '-p' , '/host_data/ngai' ] ) . catch ( ( error : any ) => {
338
+ console . error ( "Error creating directory /host_data/ngai: " , error ) ;
339
+ } ) ,
340
+ ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'mkdir' , '-p' , '/host_data/download' ] ) . catch ( ( error : any ) => {
341
+ console . error ( "Error creating directory /host_data/download: " , error ) ;
342
+ } ) ,
343
+ ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'mkdir' , '-p' , '/host_data/udf' ] ) . catch ( ( error : any ) => {
344
+ console . error ( "Error creating directory /host_data/udf: " , error ) ;
345
+ } ) ,
346
+ ] ;
347
+ await Promise . all ( mkdirPromises ) ;
348
+
349
+ const downloadPromises = [
350
+ ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'wget' , '-O' , '/host_data/download/nebula-algo.jar' , 'https://repo1.maven.org/maven2/com/vesoft/nebula-algorithm/3.1.0/nebula-algorithm-3.1.0.jar' ] ) . catch ( ( error : any ) => {
351
+ console . error ( "Error downloading nebula-algo.jar: " , error ) ;
352
+ } ) ,
353
+ ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'wget' , '-O' , '/host_data/ngai/docker-compose.yaml' , 'https://raw.githubusercontent.com/nebula-contrib/nebulagraph-docker-ext/main/optional_workload/docker-compose-ngai.yaml' ] ) . catch ( ( error : any ) => {
354
+ console . error ( "Error downloading docker-compose.yaml: " , error ) ;
355
+ } ) ,
356
+ ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'wget' , '-O' , '/host_data/udf/ng_ai.so' , 'https://github.com/wey-gu/nebulagraph-ai/releases/download/0.2.9/ng_ai-ubuntu-2004-nebulagraph-nightly-2023.03.13.so' ] ) . catch ( ( error : any ) => {
357
+ console . error ( "Error downloading ng_ai.so: " , error ) ;
358
+ } ) ,
359
+ ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'wget' , '-O' , '/host_data/download/nebula-spark-connector.jar' , 'https://repo1.maven.org/maven2/com/vesoft/nebula-spark-connector/3.4.0/nebula-spark-connector-3.4.0.jar' ] ) . catch ( ( error : any ) => {
360
+ console . error ( "Error downloading nebula-spark-connector.jar: " , error ) ;
361
+ } ) ,
362
+ ] ;
363
+ const results = await Promise . all ( downloadPromises ) ;
364
+ results . forEach ( ( result : any ) => {
365
+ console . log ( "the result of wget: " , result ) ;
366
+ } ) ;
367
+
368
+ await ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'chmod' , '+x' , '/host_data/udf/ng_ai.so' ] ) ;
369
+ console . log ( "the result of chmod ng_ai.so" ) ;
370
+
371
+ await ddClient . docker . cli . exec ( 'compose' , [ '-f' , '~/.nebulagraph/ngai/docker-compose.yaml' , 'up' , '-d' , '--remove-orphans' ] ) ;
372
+ console . log ( "the result of docker-compose up" ) ;
373
+
374
+ await ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'wget' , '-O' , '/host_data/ngai/AI_suite_demo.ipynb' , 'https://raw.githubusercontent.com/wey-gu/nebula-up/main/spark/AI_suite_demo.ipynb' ] ) ;
375
+ console . log ( "the result of wget AI_suite_demo.ipynb" ) ;
376
+
377
+ await ddClient . docker . cli . exec ( 'exec' , [ 'nebulagraph_webshell' , 'wget' , '-O' , '/host_data/ngai/AI_suite_nGQL_UDF.ipynb' , 'https://raw.githubusercontent.com/wey-gu/nebula-up/main/spark/AI_suite_nGQL_UDF.ipynb' ] ) ;
378
+ console . log ( "the result of wget AI_suite_nGQL_UDF.ipynb" ) ;
379
+
380
+ setNgaiDeployed ( true ) ;
381
+ setNgaiIsDeploying ( false ) ;
382
+ } ;
383
+
384
+ // Undeploy NebulaGraph AI
385
+ const undeployNgai = async ( ) => {
386
+ if ( isNgaiUndeploying ) {
387
+ return ;
388
+ }
389
+ await ddClient . docker . cli . exec ( 'compose' , [ '-f' , '~/.nebulagraph/ngai/docker-compose.yaml' , 'down' ] ) ;
390
+ console . log ( "the result of docker-compose down" ) ;
391
+
392
+ setNgaiDeployed ( false ) ;
393
+ setNgaiIsUndeploying ( false ) ;
394
+ } ;
395
+
310
396
return (
311
397
< Box sx = { { width : '100%' } } >
312
398
< Box sx = { { borderBottom : 1 , borderColor : 'divider' } } >
@@ -316,6 +402,7 @@ export default function NebulaGraphTabs() {
316
402
< Tab label = "Get Started" { ...a11yProps ( 2 ) } />
317
403
< Tab label = "Docs" { ...a11yProps ( 3 ) } />
318
404
< Tab label = "Console" { ...a11yProps ( 4 ) } />
405
+ < Tab label = "NebulaGraph AI" { ...a11yProps ( 5 ) } />
319
406
</ Tabs >
320
407
</ Box >
321
408
< TabPanel value = { value } index = { 0 } >
@@ -399,6 +486,45 @@ export default function NebulaGraphTabs() {
399
486
</ Table >
400
487
</ TableContainer >
401
488
489
+
490
+
491
+ < Box sx = { { display : 'flex' , alignItems : 'center' } } >
492
+ < Typography variant = "h6" color = { ( theme ) => theme . palette . text . primary } sx = { { my : 2 , width : '95%' } } >
493
+ NebulaGraph AI Suite Resources
494
+ </ Typography >
495
+ < Fab onClick = { fetchContainerList } >
496
+ < Refresh />
497
+ </ Fab >
498
+ </ Box >
499
+
500
+
501
+
502
+ < TableContainer sx = { { mt :- 1 } } >
503
+ < Table >
504
+ < TableHead >
505
+ < TableRow >
506
+ < TableCell sx = { { width : '15%' } } > Container id</ TableCell >
507
+ < TableCell sx = { { width : '25%' } } > Image</ TableCell >
508
+ < TableCell sx = { { width : '35%' } } > Created</ TableCell >
509
+ < TableCell sx = { { width : '25%' } } > Status</ TableCell >
510
+ </ TableRow >
511
+ </ TableHead >
512
+ < TableBody >
513
+ { ngaiContainers . map ( ( container ) => (
514
+ < TableRow
515
+ key = { container . ID }
516
+ sx = { { '&:last-child td, &:last-child th' : { border : 0 } } }
517
+ >
518
+ < TableCell > { container . ID } </ TableCell >
519
+ < TableCell > { container . Image } </ TableCell >
520
+ < TableCell > { container . CreatedAt } </ TableCell >
521
+ < TableCell > { container . Status } </ TableCell >
522
+ </ TableRow >
523
+ ) ) }
524
+ </ TableBody >
525
+ </ Table >
526
+ </ TableContainer >
527
+
402
528
</ TabPanel >
403
529
404
530
< TabPanel value = { value } index = { 2 } >
@@ -711,7 +837,103 @@ export default function NebulaGraphTabs() {
711
837
</ TabPanel >
712
838
713
839
< TabPanel value = { value } index = { 5 } >
714
- { /* TBD */ }
840
+ < Box sx = { { display : 'flex' } } >
841
+ < Box sx = { { width : '80%' } } >
842
+ < img
843
+ src = "https://user-images.githubusercontent.com/1651790/226272763-61be3f05-e4f2-4108-a3f8-eb01462a8605.png"
844
+ alt = "celebrate"
845
+ width = "100%"
846
+ />
847
+ </ Box >
848
+
849
+ < Box sx = { { width : '20%' , display : 'flex' , flexDirection : 'column' , justifyContent : 'center' , alignItems : 'flex-end' } } >
850
+ < Button
851
+ variant = "contained"
852
+ color = "primary"
853
+ onClick = { deployNgai }
854
+ disabled = { isNgaiDeploying }
855
+ sx = { { mb : 1 , width : '70%' } }
856
+ >
857
+ Install
858
+ </ Button >
859
+ < Button
860
+ variant = "contained"
861
+ color = "secondary"
862
+ onClick = { undeployNgai }
863
+ disabled = { isNgaiUndeploying }
864
+ sx = { { width : '70%' } }
865
+ >
866
+ Uninstall
867
+ </ Button >
868
+ </ Box >
869
+
870
+ </ Box >
871
+
872
+ { /* Description of NebulaGraph AI Suite */ }
873
+ < Typography variant = "body1" color = { ( theme ) => theme . palette . text . primary } sx = { { my : 2 , mr : 6 } } >
874
+ < List component = "div" >
875
+ < ListItem >
876
+ < b > NebulaGraph AI Suite</ b > (< a href = "#" onClick = { ( ) => openExternalUrl ( "https://github.com/wey-gu/nebulagraph-ai" ) } > GitHub</ a > )
877
+ is a Python library to run Analytics, Algo & GNN on NebulaGraph .
878
+ </ ListItem >
879
+ < ListItem >
880
+ < b > Step 1 Install:</ b > It's not by default installed in NebulaGraph This Docker Extension, to install it, click the Install button.
881
+ </ ListItem >
882
+ < ListItem >
883
+ < b > Step 2 Run:</ b > After installation, you go to
884
+ < Box sx = { { display : 'inline-block' , ml : 2 , mr : 2 } } >
885
+ < Button
886
+ variant = "outlined"
887
+ onClick = { ( ) => openExternalUrl ( "http://127.0.0.1:18888/notebooks/ngai/AI_suite_demo.ipynb" ) }
888
+ endIcon = { < Psychology /> }
889
+ >
890
+ Jupyter Notebook
891
+ </ Button >
892
+ </ Box >
893
+ and its password is nebula.
894
+ </ ListItem >
895
+ < ListItem >
896
+ < b > Step 3 ng_ai API Gateway:</ b > Follow < a href = "#" onClick = { ( ) => openExternalUrl ( "http://127.0.0.1:18888/notebooks/ngai/AI_suite_nGQL_UDF.ipynb" ) } > this </ a > to run ng_ai API Gateway and call ng_ai from nGQL.
897
+ </ ListItem >
898
+ </ List >
899
+ </ Typography >
900
+
901
+
902
+ < Box sx = { { display : 'flex' , alignItems : 'center' } } >
903
+ < Typography variant = "h6" color = { ( theme ) => theme . palette . text . primary } sx = { { my : 2 , width : '95%' } } >
904
+ NebulaGraph AI Suite Resources
905
+ </ Typography >
906
+ < Fab onClick = { fetchContainerList } >
907
+ < Refresh />
908
+ </ Fab >
909
+ </ Box >
910
+
911
+ < TableContainer sx = { { mt :- 1 } } >
912
+ < Table >
913
+ < TableHead >
914
+ < TableRow >
915
+ < TableCell sx = { { width : '15%' } } > Container id</ TableCell >
916
+ < TableCell sx = { { width : '25%' } } > Image</ TableCell >
917
+ < TableCell sx = { { width : '35%' } } > Created</ TableCell >
918
+ < TableCell sx = { { width : '25%' } } > Status</ TableCell >
919
+ </ TableRow >
920
+ </ TableHead >
921
+ < TableBody >
922
+ { ngaiContainers . map ( ( container ) => (
923
+ < TableRow
924
+ key = { container . ID }
925
+ sx = { { '&:last-child td, &:last-child th' : { border : 0 } } }
926
+ >
927
+ < TableCell > { container . ID } </ TableCell >
928
+ < TableCell > { container . Image } </ TableCell >
929
+ < TableCell > { container . CreatedAt } </ TableCell >
930
+ < TableCell > { container . Status } </ TableCell >
931
+ </ TableRow >
932
+ ) ) }
933
+ </ TableBody >
934
+ </ Table >
935
+ </ TableContainer >
936
+
715
937
</ TabPanel >
716
938
</ Box >
717
939
) ;
0 commit comments