diff --git a/src/views/Layout/index.jsx b/src/views/Layout/index.jsx index a90b6349696..fb6cf8656f8 100644 --- a/src/views/Layout/index.jsx +++ b/src/views/Layout/index.jsx @@ -1,3 +1,4 @@ +import React, { useEffect } from "react"; import { ConfigProvider, FloatButton } from "antd"; import { useParams, Navigate, Outlet } from "react-router-dom"; import { NavBar, Footer } from "../../components"; @@ -17,7 +18,47 @@ const Content = () => { }; const Layout = () => { + useEffect(() => { + // Polyfill for crypto.randomUUID (required for kapa.ai in non-secure contexts like HTTP localhost) + if (typeof window.crypto.randomUUID !== "function") { + window.crypto.randomUUID = function () { + return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => + ( + c ^ + (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4))) + ).toString(16) + ); + }; + } + + // Prevent duplicate script injection + if (document.getElementById("kapa-ai-widget")) { + return; + } + + const script = document.createElement("script"); + script.id = "kapa-ai-widget"; + script.src = "https://widget.kapa.ai/kapa-widget.bundle.js"; + script.setAttribute("data-website-id", "e3268e5d-c0f1-4e71-819c-c60ebb2215a7"); + script.setAttribute("data-project-name", "Apache DolphinScheduler"); + script.setAttribute("data-project-color", "#0097E0"); + script.setAttribute("data-project-logo", "https://dolphinscheduler.apache.org/images/logo_400x400.jpg"); + script.setAttribute("data-modal-disclaimer", "This is a custom LLM for Apache DolphinScheduler with access to all developer Documentation, Blog, GitHub issues and discussions."); + script.setAttribute("data-modal-example-questions", "Why we need DolphinScheduler?,How to deploy DolphinScheduler?,How to submit task?,How to contribute?"); + script.async = true; + + document.body.appendChild(script); + + return () => { + const existingScript = document.getElementById("kapa-ai-widget"); + if (existingScript) { + document.body.removeChild(existingScript); + } + }; + }, []); + const params = useParams(); + if (params.locale && ["en-us", "zh-cn"].includes(params.locale)) { const locales = JSON.parse(sessionStorage.getItem("locales")) || {}; @@ -43,7 +84,9 @@ const Layout = () => {
document.getElementById("ds-scroll-content")} + target={() => + document.getElementById("ds-scroll-content") + } />
@@ -56,4 +99,4 @@ const Layout = () => { return ; }; -export default Layout; +export default Layout; \ No newline at end of file