From df1fc6948ffafb50df93bdfb5e58839866dff317 Mon Sep 17 00:00:00 2001 From: mchami Date: Sun, 25 Aug 2024 16:00:21 +0200 Subject: [PATCH] student button clickable --- src/NotebookSelector.tsx | 49 ++----- src/VizContent.tsx | 274 +++++++++++++++++++-------------------- src/index.ts | 2 +- 3 files changed, 151 insertions(+), 174 deletions(-) diff --git a/src/NotebookSelector.tsx b/src/NotebookSelector.tsx index 1f8891f..648c79f 100644 --- a/src/NotebookSelector.tsx +++ b/src/NotebookSelector.tsx @@ -1,54 +1,33 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import '../style/notebookSelector.css'; interface NotebookSelectorProps { notebookIds: number[]; onSelectionChange: (selectedIds: number[]) => void; + selectedNotebooks: number[]; } -const NotebookSelector: React.FC = ({ notebookIds, onSelectionChange }) => { - const [shownNotebooks, setShownNotebooks] = useState>(new Set([-2])); // Initialize with "ALL" +const NotebookSelector: React.FC = ({ notebookIds, onSelectionChange, selectedNotebooks }) => { const [selectedValue, setSelectedValue] = useState(''); - useEffect(() => { - // Trigger the callback when shownNotebooks changes - onSelectionChange(Array.from(shownNotebooks)); - }, [shownNotebooks, onSelectionChange]); - - const handleRemoveNotebook = (notebookId: number) => { - const newShownNotebooks = new Set(shownNotebooks); - if (newShownNotebooks.has(notebookId)) { - newShownNotebooks.delete(notebookId); - // If the last notebook is removed, add "ALL" again - if (newShownNotebooks.size === 0) { - newShownNotebooks.add(-2); - } - setShownNotebooks(newShownNotebooks); + const newSelectedNotebooks = selectedNotebooks.filter(id => id !== notebookId); + if (newSelectedNotebooks.length === 0) { + onSelectionChange([-2]); // Add "ALL" if no notebooks are selected + } else { + onSelectionChange(newSelectedNotebooks); } }; const handleAddNotebook = () => { const notebookId = selectedValue === "ALL" ? -2 : Number(selectedValue); - + console.log('Current notebook IDs:', selectedNotebooks); if (notebookId === -2) { - // If "ALL" is selected, clear all other selections and set "ALL" - const newShownNotebooks = new Set(); - newShownNotebooks.add(-2); - setShownNotebooks(newShownNotebooks); - } else if (!shownNotebooks.has(notebookId) && notebookIds.includes(notebookId)) { - - console.log(notebookId); - const newShownNotebooks = new Set(shownNotebooks); - newShownNotebooks.add(notebookId); - if (newShownNotebooks.has(-2)) { - newShownNotebooks.delete(-2); // Remove "ALL" (-2) before adding a specific notebook - } - console.log(newShownNotebooks); - setShownNotebooks(newShownNotebooks); - console.log(newShownNotebooks); - + onSelectionChange([-2]); // If "ALL" is selected, clear other selections and set "ALL" + } else if (!selectedNotebooks.includes(notebookId) && notebookIds.includes(notebookId)) { + const newSelectedNotebooks = [...selectedNotebooks, notebookId].filter(id => id !== -2); // Remove "ALL" (-2) before adding a specific notebook + onSelectionChange(newSelectedNotebooks); } setSelectedValue(''); // Clear the input after adding }; @@ -57,7 +36,7 @@ const NotebookSelector: React.FC = ({ notebookIds, onSele
Current selection:
- {Array.from(shownNotebooks).map(notebookId => ( + {selectedNotebooks.map(notebookId => (
{notebookId === -2 ? "ALL" : notebookId} diff --git a/src/VizContent.tsx b/src/VizContent.tsx index 6fcfd70..c16bc62 100644 --- a/src/VizContent.tsx +++ b/src/VizContent.tsx @@ -10,164 +10,162 @@ import * as React from 'react'; import VizComponent, { LoadingComponent, DataNotFoundComponent, VizData, NotebookCellWithID, NotebookWithCellId } from './VizComponent'; import NotebookSelector from './NotebookSelector'; import { FlowchartWidget } from './Flowchart'; +import { useCallback, useEffect, useState } from 'react'; -class VizContent extends ReactWidget { - private context: DocumentRegistry.Context; - private selectedNotebookIds: number[] = []; - private flowchartWidget: FlowchartWidget; - - constructor(context: DocumentRegistry.Context, flowchartWidget: FlowchartWidget) { - super(); - this.context = context; - this.flowchartWidget = flowchartWidget; - this.addClass('jp-vizContent'); - - // Listen for changes in the document and re-render the content - context.ready.then(() => { - this.context.model.contentChanged.connect(this.update, this); - this.update(); - }); - } - - - handleNotebookSelection = (selectedIds: number[]) => { - // Remove every element from selectedNotebookIds directly in the - while(this.selectedNotebookIds.length > 0){ - this.selectedNotebookIds.pop(); - } - - // Add every element from selectedIds that is not in selectedNotebookIds - selectedIds.forEach(selectedId => { - if (!this.selectedNotebookIds.includes(selectedId)) { - this.selectedNotebookIds.push(selectedId); - } - }); - - this.update(); // Re-render the widget when the selection changes +interface VizContentProps { + context: DocumentRegistry.Context; + flowchartWidget: FlowchartWidget; +} - const content = this.context.model.toString(); +const VizContent: React.FC = ({ context, flowchartWidget }) => { + const [selectedNotebookIds, setSelectedNotebookIds] = useState([-2]); + const [isReady, setIsReady] = useState(context.isReady); - //console.log(content) - let jsonData: VizData = { notebooks: [] }; - let data: any = {}; - if (content.trim() !== "") { - try { - jsonData = JSON.parse(content); - data = JSON.parse(content); - } catch (error) { - console.error("Error parsing JSON", error); - return; - } - - - let newNotebook: NotebookWithCellId = { notebook_id: -2, cells: [] }; - - jsonData.notebooks.forEach(notebook => { - notebook.cells.forEach(cell => { - const classMetadata = data["metadata"]["clusters"][cell.class]["titles"]; - - if (classMetadata && classMetadata[cell.cluster]) { - cell.cluster = classMetadata[cell.cluster]; // Replace cluster ID with the title - - } - const cellWithNotebookId = { - ...cell, - originalNotebookId: notebook.notebook_id // Add a new property to store the original notebook ID - }; - - newNotebook.cells.push(cellWithNotebookId); } - ) + useEffect(() => { + if (!context.isReady) { + context.ready.then(() => { + setIsReady(true); }); - jsonData.notebooks.push(newNotebook); - this.update(); // Re-render the widget when the selection changes - - // Filter cells from selected notebooks only - const selectedCells: NotebookCellWithID[] = jsonData.notebooks - .filter(notebook => selectedIds.includes(notebook.notebook_id)) - .flatMap(notebook => - notebook.cells.map(cell => ({ - ...cell, - notebook_id: notebook.notebook_id, // Add notebook_id to each cell - })) - ); - - this.flowchartWidget.updateGraph(selectedCells); + } else { + setIsReady(true); } - }; + }, [context]); + + // Function to handle notebook selection + const handleNotebookSelection = useCallback((selectedIds: number[]) => { + setSelectedNotebookIds([...selectedIds]); + console.log("Selected notebooks", selectedIds); + }, []); + + // Function to update the flowchart widget when notebooks are selected + useEffect(() => { + if (isReady) { + const content = context.model.toString(); + + let jsonData: VizData = { notebooks: [] }; + let data: any = {}; + + if (content.trim() !== "") { + try { + jsonData = JSON.parse(content); + data = JSON.parse(content); + } catch (error) { + console.error("Error parsing JSON", error); + return; + } - protected render(): React.ReactElement { - if (!this.context.isReady) { - return ; + let newNotebook: NotebookWithCellId = { notebook_id: -2, cells: [] }; + + jsonData.notebooks.forEach(notebook => { + notebook.cells.forEach(cell => { + const classMetadata = data["metadata"]["clusters"][cell.class]["titles"]; + + if (classMetadata && classMetadata[cell.cluster]) { + cell.cluster = classMetadata[cell.cluster]; // Replace cluster ID with the title + } + const cellWithNotebookId = { + ...cell, + originalNotebookId: notebook.notebook_id // Add a new property to store the original notebook ID + }; + newNotebook.cells.push(cellWithNotebookId); + }); + }); + jsonData.notebooks.push(newNotebook); + + const selectedCells: NotebookCellWithID[] = jsonData.notebooks + .filter(notebook => selectedNotebookIds.includes(notebook.notebook_id)) + .flatMap(notebook => + notebook.cells.map(cell => ({ + ...cell, + notebook_id: notebook.notebook_id, // Add notebook_id to each cell + })) + ); + + flowchartWidget.updateGraph(selectedCells); + } } + }, [isReady, selectedNotebookIds, context, flowchartWidget]); - const content = this.context.model.toString(); - let jsonData: VizData = { notebooks: [] }; - let data: any = {}; + if (!isReady) { + return ; + } - if (content.trim() === "") { - return ; - } + const content = context.model.toString(); + let jsonData: VizData = { notebooks: [] }; + let data: any = {}; - try { - jsonData = JSON.parse(content); - data = JSON.parse(content); + if (content.trim() === "") { + return ; + } - } catch (error) { - console.error("Error parsing JSON", error); - } + try { + jsonData = JSON.parse(content); + data = JSON.parse(content); + } catch (error) { + console.error("Error parsing JSON", error); + } - jsonData.notebooks.forEach(notebook => { - notebook.cells.forEach(cell => { - const classMetadata = data["metadata"]["clusters"][cell.class]["titles"]; + jsonData.notebooks.forEach(notebook => { + notebook.cells.forEach(cell => { + const classMetadata = data["metadata"]["clusters"][cell.class]["titles"]; - if (classMetadata && classMetadata[cell.cluster]) { - cell.cluster = classMetadata[cell.cluster]; // Replace cluster ID with the title - - } + if (classMetadata && classMetadata[cell.cluster]) { + cell.cluster = classMetadata[cell.cluster]; // Replace cluster ID with the title } - ) }); + }); + let newNotebook: NotebookWithCellId = { notebook_id: -2, cells: [] }; - let newNotebook: NotebookWithCellId = { notebook_id: -2, cells: [] }; - - jsonData.notebooks.forEach(notebook => { - notebook.cells.forEach(cell => { - const classMetadata = data["metadata"]["clusters"][cell.class]["titles"]; + jsonData.notebooks.forEach(notebook => { + notebook.cells.forEach(cell => { + const classMetadata = data["metadata"]["clusters"][cell.class]["titles"]; - if (classMetadata && classMetadata[cell.cluster]) { - cell.cluster = classMetadata[cell.cluster]; // Replace cluster ID with the title - - - } - const cellWithNotebookId = { - ...cell, - originalNotebookId: notebook.notebook_id // Add a new property to store the original notebook ID - }; - - newNotebook.cells.push(cellWithNotebookId); + if (classMetadata && classMetadata[cell.cluster]) { + cell.cluster = classMetadata[cell.cluster]; // Replace cluster ID with the title } - ) + const cellWithNotebookId = { + ...cell, + originalNotebookId: notebook.notebook_id // Add a new property to store the original notebook ID + }; + newNotebook.cells.push(cellWithNotebookId); }); - jsonData.notebooks.push(newNotebook); - // Ensure only selected notebooks are displayed - const selectedNotebooks = jsonData.notebooks.filter(notebook => - this.selectedNotebookIds.includes(notebook.notebook_id) - ); - - return ( -
{/* Scrollable container */} - notebook.notebook_id)} - onSelectionChange={this.handleNotebookSelection} - /> - -
- ); + }); + jsonData.notebooks.push(newNotebook); + + const selectedNotebooks = jsonData.notebooks.filter(notebook => + selectedNotebookIds.includes(notebook.notebook_id) + ); + + return ( +
+ notebook.notebook_id)} + selectedNotebooks={selectedNotebookIds} + onSelectionChange={handleNotebookSelection} + /> + +
+ ); +}; + +class VizContentWidget extends ReactWidget { + private context: DocumentRegistry.Context; + private flowchartWidget: FlowchartWidget; + + constructor(context: DocumentRegistry.Context, flowchartWidget: FlowchartWidget) { + super(); + this.context = context; + this.flowchartWidget = flowchartWidget; + this.addClass('jp-vizContent'); + } + + protected render(): React.ReactElement { + return ; } } -export default VizContent; +export default VizContentWidget; diff --git a/src/index.ts b/src/index.ts index 0db5f33..ed7659a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ import { FlowchartWidget } from './Flowchart'; import { WidgetTracker } from '@jupyterlab/apputils'; const extension: JupyterFrontEndPlugin = { - id: 'viz-file-handler', + id: 'viz-file-ext', autoStart: true, activate: (app: JupyterFrontEnd) => { console.log('JupyterLab extension viz-file-handler is activated!');