From 8059e10759c603447e7275a2a2f23f5e478940b1 Mon Sep 17 00:00:00 2001 From: shrihari7396 Date: Mon, 23 Feb 2026 00:24:36 +0530 Subject: [PATCH 1/2] feat(docs): integrate Kapa.ai Ask AI widget into layout --- src/views/Layout/index.jsx | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/views/Layout/index.jsx b/src/views/Layout/index.jsx index a90b6349696..e9f5910e0eb 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,32 @@ const Content = () => { }; const Layout = () => { + useEffect(() => { + // 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"; // 🔴 Replace with official script from Kapa + script.async = true; + + // If Kapa requires attributes, uncomment and adjust: + // script.setAttribute("data-kapa-project", "apache-dolphinscheduler"); + + 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 +69,9 @@ const Layout = () => {
document.getElementById("ds-scroll-content")} + target={() => + document.getElementById("ds-scroll-content") + } />
@@ -56,4 +84,4 @@ const Layout = () => { return ; }; -export default Layout; +export default Layout; \ No newline at end of file From 5bfba88c72ed40a39f867ee8edb137dc3da8b766 Mon Sep 17 00:00:00 2001 From: shrihari7396 Date: Mon, 23 Feb 2026 10:36:59 +0530 Subject: [PATCH 2/2] feat: integrate Kapa.ai Docs AI widget --- src/views/Layout/index.jsx | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/views/Layout/index.jsx b/src/views/Layout/index.jsx index e9f5910e0eb..fb6cf8656f8 100644 --- a/src/views/Layout/index.jsx +++ b/src/views/Layout/index.jsx @@ -19,6 +19,18 @@ 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; @@ -26,12 +38,15 @@ const Layout = () => { const script = document.createElement("script"); script.id = "kapa-ai-widget"; - script.src = "https://widget.kapa.ai/kapa-widget.bundle.js"; // 🔴 Replace with official script from Kapa + 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; - // If Kapa requires attributes, uncomment and adjust: - // script.setAttribute("data-kapa-project", "apache-dolphinscheduler"); - document.body.appendChild(script); return () => {