@@ -7,48 +7,36 @@ const POINT_CLOUDS = {
77 5 : generatePyramid ( 1000 )
88} ;
99
10- // Function to generate point cloud based on instruction
11- async function processInstruction ( ) {
12- const instruction = document . getElementById ( 'instruction' ) . value ;
13-
14- if ( ! instruction ) {
15- alert ( 'Please enter an instruction' ) ;
16- return ;
17- }
18-
19- // Show loading spinner
20- document . getElementById ( 'loading' ) . style . display = 'block' ;
10+ let isProcessing = false ; // Track if we're currently processing a request
2111
22- try {
23- // Call the server endpoint
24- // const response = await fetch('http://localhost:8080/generate', {
25- const response = await fetch ( 'https://yixuanwang.me/generate' , {
26- method : 'POST' ,
27- headers : {
28- 'Content-Type' : 'application/json' ,
29- 'Accept' : 'application/json'
30- } ,
31- body : JSON . stringify ( { instruction } )
32- } ) ;
12+ // Function to check if Plotly is loaded
13+ function isPlotlyReady ( ) {
14+ return typeof Plotly !== 'undefined' ;
15+ }
3316
34- const data = await response . json ( ) ;
35- if ( ! response . ok ) {
36- throw new Error ( data . error || 'Request failed' ) ;
17+ // Function to wait for Plotly to load
18+ function waitForPlotly ( callback , maxAttempts = 10 ) {
19+ let attempts = 0 ;
20+ const checkInterval = setInterval ( ( ) => {
21+ attempts ++ ;
22+ if ( isPlotlyReady ( ) ) {
23+ clearInterval ( checkInterval ) ;
24+ callback ( ) ;
25+ } else if ( attempts >= maxAttempts ) {
26+ clearInterval ( checkInterval ) ;
27+ console . error ( 'Plotly failed to load' ) ;
28+ alert ( 'Visualization library failed to load. Please refresh the page.' ) ;
3729 }
38-
39- // Visualize the point cloud
40- visualizePointCloud ( data . points ) ;
41- } catch ( error ) {
42- console . error ( 'Error:' , error ) ;
43- alert ( 'Error: ' + error . message ) ;
44- } finally {
45- // Hide loading spinner
46- document . getElementById ( 'loading' ) . style . display = 'none' ;
47- }
30+ } , 500 ) ;
4831}
4932
5033// Function to visualize point cloud using Plotly
5134function visualizePointCloud ( points ) {
35+ if ( ! isPlotlyReady ( ) ) {
36+ waitForPlotly ( ( ) => visualizePointCloud ( points ) ) ;
37+ return ;
38+ }
39+
5240 const x = points . map ( p => p [ 0 ] ) ;
5341 const y = points . map ( p => p [ 1 ] ) ;
5442 const z = points . map ( p => p [ 2 ] ) ;
@@ -82,7 +70,76 @@ function visualizePointCloud(points) {
8270 }
8371 } ;
8472
85- Plotly . newPlot ( 'visualization' , [ trace ] , layout ) ;
73+ try {
74+ Plotly . newPlot ( 'visualization' , [ trace ] , layout ) ;
75+ } catch ( error ) {
76+ console . error ( 'Error plotting:' , error ) ;
77+ alert ( 'Error creating visualization. Please try again.' ) ;
78+ }
79+ }
80+
81+ // Function to generate point cloud based on instruction
82+ async function processInstruction ( ) {
83+ if ( isProcessing ) return ; // Prevent multiple simultaneous submissions
84+
85+ const instructionInput = document . getElementById ( 'instruction' ) ;
86+ const submitButton = document . querySelector ( '.button.is-primary' ) ;
87+ const loadingSpinner = document . getElementById ( 'loading' ) ;
88+
89+ if ( ! instructionInput . value ) {
90+ alert ( 'Please enter an instruction' ) ;
91+ return ;
92+ }
93+
94+ // Disable UI elements and show loading state
95+ isProcessing = true ;
96+ instructionInput . disabled = true ;
97+ submitButton . disabled = true ;
98+ loadingSpinner . style . display = 'block' ;
99+
100+ // Setup request timeout
101+ const controller = new AbortController ( ) ;
102+ const timeoutId = setTimeout ( ( ) => controller . abort ( ) , 30000 ) ; // 30 second timeout
103+
104+ try {
105+ // Call the server endpoint
106+ const response = await fetch ( 'https://yixuanwang.me/generate' , {
107+ method : 'POST' ,
108+ headers : {
109+ 'Content-Type' : 'application/json' ,
110+ 'Accept' : 'application/json'
111+ } ,
112+ body : JSON . stringify ( { instruction : instructionInput . value } ) ,
113+ signal : controller . signal
114+ } ) ;
115+
116+ clearTimeout ( timeoutId ) ;
117+
118+ if ( ! response . ok ) {
119+ const data = await response . json ( ) ;
120+ throw new Error ( data . error || 'Request failed' ) ;
121+ }
122+
123+ const data = await response . json ( ) ;
124+ // Visualize the point cloud
125+ visualizePointCloud ( data . points ) ;
126+ } catch ( error ) {
127+ console . error ( 'Error:' , error ) ;
128+ if ( error . name === 'AbortError' ) {
129+ alert ( 'Request timed out. Please try again.' ) ;
130+ } else {
131+ alert ( 'Error: ' + error . message ) ;
132+ }
133+ // Show a precomputed point cloud as fallback
134+ visualizePointCloud ( POINT_CLOUDS [ 1 ] ) ;
135+ } finally {
136+ // Re-enable UI elements and hide loading state
137+ isProcessing = false ;
138+ instructionInput . disabled = false ;
139+ submitButton . disabled = false ;
140+ loadingSpinner . style . display = 'none' ;
141+ clearTimeout ( timeoutId ) ;
142+ }
86143}
87144
88145// Point cloud generation functions
@@ -165,14 +222,17 @@ function generatePyramid(numPoints) {
165222 return points ;
166223}
167224
225+ // Initialize visualization when the page loads
226+ document . addEventListener ( 'DOMContentLoaded' , function ( ) {
227+ // Wait for Plotly to load before showing initial visualization
228+ waitForPlotly ( ( ) => {
229+ visualizePointCloud ( POINT_CLOUDS [ 1 ] ) ; // Show initial sphere
230+ } ) ;
231+ } ) ;
232+
168233// Add event listener for Enter key
169234document . getElementById ( 'instruction' ) . addEventListener ( 'keypress' , function ( e ) {
170235 if ( e . key === 'Enter' ) {
171236 processInstruction ( ) ;
172237 }
173- } ) ;
174-
175- // On page load, show a precomputed point cloud (e.g., a sphere)
176- window . addEventListener ( 'DOMContentLoaded' , function ( ) {
177- visualizePointCloud ( POINT_CLOUDS [ 1 ] ) ; // or any other precomputed shape
178238} ) ;
0 commit comments