Skip to content

Commit 3d346d0

Browse files
authored
336 fix spark badge display (#337)
* Enhance notebook loading process with Spark integration - Added SparkModel import to App.js for improved Spark session handling. - Refactored handleExistingNotebookClick to use async/await for fetching notebook data and Spark application details concurrently. - Implemented error handling for fetching notebook and Spark app, ensuring better user feedback and session management. - Introduced a new method in SparkModel.js to retrieve Spark app details by notebook path, enhancing integration with the backend API. * Enhance App.js with notebook reference and improved Spark app ID handling - Added useRef for notebook reference to facilitate direct interaction with the Notebook component. - Updated Spark app ID handling to ensure it is set correctly when an active Spark application is detected. - Minor refactoring for improved clarity and maintainability of the code. * Enhance App.js with additional logging for notebook and Spark app integration - Added console log to display the associated Spark application after fetching notebook data. - Improved visibility into the notebook and Spark app interaction for better debugging and user feedback. * Refactor Notebook component to support forward refs and expose Spark app ID setter - Updated Notebook.js to use forwardRef, allowing parent components to directly interact with the Notebook's internal state. - Implemented useImperativeHandle to expose a method for setting the Spark app ID, enhancing integration with parent components. - Improved code clarity and maintainability by restructuring the component's function signature. * Enhance logging in App.js and Notebook.js for improved debugging - Added useEffect in App.js to log the current notebook reference, aiding in tracking its state. - Implemented useEffect in Notebook.js to log changes to sparkAppId, enhancing visibility into Spark application interactions. - Updated setSparkAppId method in Notebook.js to include logging when setting the Spark app ID, improving traceability during state changes. * Refactor Notebook.js to enhance Spark app ID handling and session management - Updated the Notebook component to reset sparkAppId when switching notebooks and immediately fetch the associated Spark app. - Improved error handling during the Spark app fetch process, logging any failures for better debugging. - Streamlined the useEffect hook to ensure proper state management and clarity in the notebook's functionality. * Update demo notebook to modify execution state and add Spark session termination cell - Changed the execution state of an existing code cell from true to false, indicating it was not executed. - Added a new code cell to the demo notebook for stopping the Spark session, including execution metadata and success status. - Enhanced the notebook structure for better clarity and usability in Spark session management.
1 parent 3b2dca7 commit 3d346d0

File tree

4 files changed

+104
-23
lines changed

4 files changed

+104
-23
lines changed

examples/[email protected]/demo.ipynb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
{
1515
"cell_type": "code",
16-
"isExecuted": true,
16+
"isExecuted": false,
1717
"lastExecutionResult": "success",
1818
"lastExecutionTime": "2024-12-10 10:26:03",
1919
"metadata": {},
@@ -43,6 +43,18 @@
4343
"spark = create_spark(\"work/[email protected]/demo.ipynb\")\n",
4444
"spark"
4545
]
46+
},
47+
{
48+
"cell_type": "code",
49+
"execution_count": null,
50+
"isExecuted": true,
51+
"lastExecutionResult": "success",
52+
"lastExecutionTime": "2024-12-10 12:27:14",
53+
"metadata": {},
54+
"outputs": [],
55+
"source": [
56+
"spark.stop()"
57+
]
4658
}
4759
],
4860
"metadata": {

webapp/src/App.js

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect } from 'react';
1+
import React, { useState, useEffect, useRef } from 'react';
22
import LoginForm from './components/auth/LoginForm';
33
import Sidebar from './components/sidebar/Sidebar';
44
import Notebook from './components/notebook/Notebook';
@@ -8,6 +8,7 @@ import { createTheme, ThemeProvider } from '@mui/material/styles';
88
import config from './config';
99
import NotebookModel from './models/NotebookModel';
1010
import DirectoryModel from './models/DirectoryModel';
11+
import SparkModel from './models/SparkModel';
1112

1213
const theme = createTheme({
1314
components: {
@@ -59,6 +60,12 @@ const App = () => {
5960
const [workspaceFiles, setWorkspaceFiles] = useState([]);
6061
const [refreshKey, setRefreshKey] = useState(0);
6162

63+
const notebookRef = useRef(null);
64+
65+
useEffect(() => {
66+
console.log('notebookRef current:', notebookRef.current);
67+
}, [notebookRef.current]);
68+
6269
// Auth
6370
useEffect(() => {
6471
const storedUsername = localStorage.getItem('username');
@@ -128,22 +135,36 @@ const App = () => {
128135
}
129136
};
130137

131-
const handleExistingNotebookClick = (path) => {
138+
const handleExistingNotebookClick = async (path) => {
132139
if (handleUnsavedChanges()) {
133-
NotebookModel.fetchNotebook(`${path}`).then((data) => {
134-
if (data.message == 'Token has expired') {
135-
console.error('Token has expired, please log in again');
136-
logout();
137-
} else {
138-
console.log('Fetched notebook:', data);
139-
setNotebook(data);
140-
setShowHistoryServer(false);
141-
setShowScheduler(false);
142-
setShowNotebook(true);
140+
try {
141+
const [notebookData, sparkApp] = await Promise.all([
142+
NotebookModel.fetchNotebook(`${path}`),
143+
SparkModel.getSparkAppByNotebookPath(path)
144+
]);
145+
146+
if (notebookData.message === 'Token has expired') {
147+
console.error('Token has expired, please log in again');
148+
logout();
149+
return;
150+
}
151+
152+
console.log('Fetched notebook:', notebookData);
153+
setNotebook(notebookData);
154+
155+
console.log('Associated Spark app:', sparkApp);
156+
157+
// Update Spark badge if there's an active Spark app
158+
if (sparkApp && sparkApp.spark_app_id) {
159+
notebookRef.current?.setSparkAppId(sparkApp.spark_app_id);
160+
}
161+
162+
setShowHistoryServer(false);
163+
setShowScheduler(false);
164+
setShowNotebook(true);
165+
} catch (error) {
166+
console.error('Failed to fetch notebook or Spark app:', error);
143167
}
144-
}).catch((error) => {
145-
console.error('Failed to fetch notebook:', error);
146-
});
147168
}
148169
}
149170

@@ -211,6 +232,7 @@ const App = () => {
211232
username={username}
212233
useremail={useremail}/>
213234
<Notebook
235+
ref={notebookRef}
214236
showNotebook={showNotebook}
215237
notebook={notebook}
216238
notebookState={notebookState}

webapp/src/components/notebook/Notebook.js

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect } from 'react';
1+
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
22
import NotebookHeader from './header/NotebookHeader';
33
import Code from './content/Code';
44
import Config from './content/Config';
@@ -13,15 +13,15 @@ import config from '../../config';
1313
import { Box } from '@mui/material';
1414

1515

16-
function Notebook({
16+
const Notebook = forwardRef(({
1717
showNotebook,
1818
notebook,
1919
notebookState,
2020
setNotebookState,
2121
isNotebookModified,
2222
setIsNotebookModified,
23-
handleDeleteNotebook }) {
24-
23+
handleDeleteNotebook
24+
}, ref) => {
2525
const jupyterBaseUrl= `${config.jupyterBaseUrl}`
2626
const baseUrl = `${jupyterBaseUrl}/api/contents/`
2727

@@ -61,7 +61,7 @@ function Notebook({
6161
isExecuted: cell.cell_type === 'code' ? false : cell.cell_type === 'markdown' ? true : cell.isExecuted,
6262
lastExecutionResult: cell.lastExecutionResult === null? null : cell.lastExecutionResult,
6363
lastExecutionTime: cell.lastExecutionTime === null? null : cell.lastExecutionTime
64-
}));
64+
}));
6565
setNotebookState({
6666
...notebook,
6767
content: {
@@ -70,12 +70,24 @@ function Notebook({
7070
}
7171
});
7272
setCurrentName(notebook.name);
73+
74+
// Reset sparkAppId when switching notebooks, but immediately fetch the associated Spark app
75+
setSparkAppId(null);
76+
SparkModel.getSparkAppByNotebookPath(notebook.path)
77+
.then(sparkApp => {
78+
if (sparkApp && sparkApp.spark_app_id) {
79+
setSparkAppId(sparkApp.spark_app_id);
80+
}
81+
})
82+
.catch(error => {
83+
console.error('Failed to fetch Spark app:', error);
84+
});
7385
}
86+
7487
SessionModel.getSession(notebook.path)
7588
.then((kernelId) => {
7689
setKernelId(kernelId);
7790
});
78-
setSparkAppId(null);
7991
}, [notebook]);
8092

8193
const clearOutputs = () => {
@@ -318,6 +330,19 @@ function Notebook({
318330
}
319331
};
320332

333+
// Add useEffect to log sparkAppId changes
334+
useEffect(() => {
335+
console.log('sparkAppId changed:', sparkAppId);
336+
}, [sparkAppId]);
337+
338+
// Expose setSparkAppId to parent through ref
339+
useImperativeHandle(ref, () => ({
340+
setSparkAppId: (id) => {
341+
console.log('setSparkAppId called with:', id);
342+
setSparkAppId(id);
343+
}
344+
}));
345+
321346
return (
322347
<div>
323348
{showNotebook && (
@@ -382,6 +407,6 @@ function Notebook({
382407
)}
383408
</div>
384409
);
385-
}
410+
});
386411

387412
export default Notebook;

webapp/src/models/SparkModel.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,28 @@ spark`;
9494
throw error;
9595
}
9696
}
97+
98+
static async getSparkAppByNotebookPath(notebookPath) {
99+
const token = sessionStorage.getItem('token');
100+
try {
101+
const response = await fetch(`${config.serverBaseUrl}/notebook/spark_app/${notebookPath}`, {
102+
headers: {
103+
'Authorization': `Bearer ${token}`,
104+
'Content-Type': 'application/json'
105+
}
106+
});
107+
108+
if (!response.ok) {
109+
return null;
110+
}
111+
112+
const sparkApps = await response.json();
113+
return sparkApps.length > 0 ? sparkApps[0] : null;
114+
} catch (error) {
115+
console.error('Failed to fetch Spark app:', error);
116+
return null;
117+
}
118+
}
97119
}
98120

99121
export default SparkModel;

0 commit comments

Comments
 (0)