From 67e5a821d3f173490ab82284caf8c811ebcd2420 Mon Sep 17 00:00:00 2001 From: Ryan Zhang Date: Wed, 27 May 2026 20:24:13 -0700 Subject: [PATCH] added Docker related files for the Jupyter server --- .../src/main/resources/Dockerfile | 28 ++++++ .../src/main/resources/custom.js | 95 +++++++++++++++++++ .../src/main/resources/docker-compose.yml | 34 +++++++ 3 files changed, 157 insertions(+) create mode 100644 notebook-migration-service/src/main/resources/Dockerfile create mode 100644 notebook-migration-service/src/main/resources/custom.js create mode 100644 notebook-migration-service/src/main/resources/docker-compose.yml diff --git a/notebook-migration-service/src/main/resources/Dockerfile b/notebook-migration-service/src/main/resources/Dockerfile new file mode 100644 index 00000000000..ba64833ec03 --- /dev/null +++ b/notebook-migration-service/src/main/resources/Dockerfile @@ -0,0 +1,28 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +FROM jupyter/base-notebook:notebook-6.5.4 + +# Copy custom JavaScript for Jupyter +COPY custom.js /home/jovyan/.jupyter/custom/custom.js + +# Ensure correct permissions +USER root +RUN mkdir -p /home/jovyan/.jupyter/custom && \ + chown -R jovyan:users /home/jovyan/.jupyter + +USER jovyan \ No newline at end of file diff --git a/notebook-migration-service/src/main/resources/custom.js b/notebook-migration-service/src/main/resources/custom.js new file mode 100644 index 00000000000..789f95677ff --- /dev/null +++ b/notebook-migration-service/src/main/resources/custom.js @@ -0,0 +1,95 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// Use Jupyter's event system to ensure the notebook is fully loaded +require(["base/js/events"], function (events) { + events.on("kernel_ready.Kernel", function () { + + // Attach click event listener to cells + $("#notebook-container").on("click", ".cell", function (event) { + const cell = $(this); + const index = $(".cell").index(cell); + const cellContent = cell.find(".input_area").text(); + + // Get the UUID from the cell's metadata, or use "N/A" if it doesn't exist + const cellUUID = Jupyter.notebook.get_cell(index).metadata.uuid || 'N/A'; + + // Send a message to the parent window (Texera app) + window.parent.postMessage( + { action: "cellClicked", cellIndex: index, cellContent: cellContent, cellUUID: cellUUID }, + "http://localhost:4200" + ); + }); + }); +}); + +// Listen for messages from the Texera app (or parent window) +window.addEventListener("message", function (event) { + // Verify the message origin + if (event.origin !== 'http://localhost:4200') { + console.warn("Message received from unrecognized origin:", event.origin); + return; + } + + if (event.data.action === "triggerCellClick") { + const operatorCellUUIDs = event.data.operators || []; + + if (!operatorCellUUIDs.length) { + console.error("No valid operator UUIDs provided in the message."); + return; // Exit if no UUIDs are provided + } + + operatorCellUUIDs.forEach((cellUUID) => { + // Search for the cell by UUID + const allCells = Jupyter.notebook.get_cells(); + const targetCell = allCells.find((cell) => cell.metadata.uuid === cellUUID); + + if (targetCell) { + const cellIndex = Jupyter.notebook.find_cell_index(targetCell); + + // Scroll to and highlight the cell + let cell = document.querySelectorAll(".cell")[cellIndex]; + if (cell) { + cell.scrollIntoView({ behavior: 'smooth', block: 'center' }); + cell.classList.add("highlighted"); + + // Remove the highlight after 3 seconds + setTimeout(() => { + cell.classList.remove("highlighted"); + }, 3000); + } else { + console.error(`Cell not found in the DOM for index ${cellIndex}.`); + } + } else { + console.error(`No cell found with UUID: ${cellUUID}`); + } + }); + } else { + console.warn("Received unknown action:", event.data.action); + } +}, false); + +// Add custom CSS for highlighted cells +const style = document.createElement('style'); +style.innerHTML = ` + .cell.highlighted { + background-color: lightyellow; + } +`; +document.head.appendChild(style); diff --git a/notebook-migration-service/src/main/resources/docker-compose.yml b/notebook-migration-service/src/main/resources/docker-compose.yml new file mode 100644 index 00000000000..dc10d5bc980 --- /dev/null +++ b/notebook-migration-service/src/main/resources/docker-compose.yml @@ -0,0 +1,34 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: texera-jupyter +services: + + jupyter: + build: + context: . + dockerfile: Dockerfile + container_name: texera-jupyter + ports: + - "9100:8888" + command: > + start-notebook.sh + --NotebookApp.token='' + --NotebookApp.password='' + --NotebookApp.disable_check_xsrf=True + --NotebookApp.tornado_settings="{'headers': {'Content-Security-Policy': 'frame-ancestors http://localhost:*'}}" + --NotebookApp.default_url=/tree \ No newline at end of file