Merge pull request #974 from siiddhantt/fix/pr-960

fix/pr-960
This commit is contained in:
Alex 2024-06-03 22:44:36 +01:00 committed by GitHub
commit 34310cf420
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 2247 additions and 4233 deletions

View File

@ -1,6 +1,5 @@
# DocsGPT react widget
This widget will allow you to embed a DocsGPT assistant in your React app.
## Installation
@ -11,6 +10,8 @@ npm install docsgpt
## Usage
### React
```javascript
import { DocsGPTWidget } from "docsgpt";
@ -38,10 +39,65 @@ To link the widget to your api and your documents you can pass parameters to the
};
```
### Html
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DocsGPT Widget</title>
</head>
<body>
<div id="app"></div>
<!-- Include the widget script from dist/modern or dist/legacy -->
<script src="https://unpkg.com/docsgpt/dist/modern/main.js" type="module"></script>
<script type="module">
window.onload = function() {
renderDocsGPTWidget('app');
}
</script>
</body>
</html>
```
To link the widget to your api and your documents you can pass parameters to the **renderDocsGPTWidget('div id', { parameters })**.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DocsGPT Widget</title>
</head>
<body>
<div id="app"></div>
<!-- Include the widget script from dist/modern or dist/legacy -->
<script src="https://unpkg.com/docsgpt/dist/modern/main.js" type="module"></script>
<script type="module">
window.onload = function() {
renderDocsGPTWidget('app', , {
apiHost: 'http://localhost:7001',
selectDocs: 'default',
apiKey: '',
avatar: 'https://d3dg1063dc54p9.cloudfront.net/cute-docsgpt.png',
title: 'Get AI assistance',
description: "DocsGPT's AI Chatbot is here to help",
heroTitle: 'Welcome to DocsGPT !',
heroDescription: 'This chatbot is built with DocsGPT and utilises GenAI, please review important information using sources.'
});
}
</script>
</body>
</html>
```
## Our github
[DocsGPT](https://github.com/arc53/DocsGPT)
You can find the source code in the extensions/react-widget folder.

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "docsgpt",
"version": "0.3.7",
"version": "0.3.9",
"private": false,
"description": "DocsGPT 🦖 is an innovative open-source tool designed to simplify the retrieval of information from project documentation using advanced GPT models 🤖.",
"source": "./src/index.html",
@ -11,6 +11,18 @@
"dist",
"package.json"
],
"targets": {
"modern": {
"engines": {
"browsers": "Chrome 80"
}
},
"legacy": {
"engines": {
"browsers": "> 0.5%, last 2 versions, not dead"
}
}
},
"@parcel/resolver-default": {
"packageExports": true
},
@ -18,7 +30,7 @@
"styled-components": "^5"
},
"scripts": {
"build": "parcel build src/index.ts",
"build": "parcel build src/main.tsx --public-url ./",
"dev": "parcel src/index.html -p 3000",
"test": "jest",
"lint": "eslint",
@ -33,16 +45,13 @@
"@parcel/transformer-typescript-tsc": "^2.12.0",
"@parcel/validator-typescript": "^2.12.0",
"@radix-ui/react-icons": "^1.3.0",
"@types/react": "^18.2.61",
"@types/react-dom": "^18.2.19",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"dompurify": "^3.0.9",
"dompurify": "^3.1.5",
"flow-bin": "^0.229.2",
"i": "^0.3.7",
"install": "^0.13.0",
"npm": "^10.5.0",
"parcel": "^2.12.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"styled-components": "^6.1.8"
@ -54,7 +63,10 @@
"@parcel/packager-ts": "^2.12.0",
"@parcel/transformer-typescript-types": "^2.12.0",
"@types/dompurify": "^3.0.5",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"babel-loader": "^8.0.4",
"parcel": "^2.12.0",
"process": "^0.11.10",
"typescript": "^5.3.3"
},

View File

@ -1,12 +1,13 @@
"use client";
import { Fragment, useEffect, useRef, useState } from 'react'
import { PaperPlaneIcon, RocketIcon, ExclamationTriangleIcon, Cross2Icon } from '@radix-ui/react-icons';
import { MESSAGE_TYPE, Query, Status } from '../types/index';
import MessageIcon from '../assets/message.svg'
import { fetchAnswerStreaming } from '../requests/streamingApi';
import styled, { keyframes, createGlobalStyle } from 'styled-components';
import React from 'react'
import DOMPurify from 'dompurify';
import snarkdown from '@bpmn-io/snarkdown';
import { sanitize } from 'dompurify';
import styled, { keyframes, createGlobalStyle } from 'styled-components';
import { PaperPlaneIcon, RocketIcon, ExclamationTriangleIcon, Cross2Icon } from '@radix-ui/react-icons';
import MessageIcon from '../assets/message.svg';
import { MESSAGE_TYPE, Query, Status } from '../types/index';
import { fetchAnswerStreaming } from '../requests/streamingApi';
const GlobalStyles = createGlobalStyle`
.response pre {
padding: 8px;
@ -292,13 +293,13 @@ export const DocsGPTWidget = ({
heroDescription = 'This chatbot is built with DocsGPT and utilises GenAI, please review important information using sources.'
}) => {
const [prompt, setPrompt] = useState('');
const [status, setStatus] = useState<Status>('idle');
const [queries, setQueries] = useState<Query[]>([])
const [conversationId, setConversationId] = useState<string | null>(null)
const [open, setOpen] = useState<boolean>(false)
const [eventInterrupt, setEventInterrupt] = useState<boolean>(false); //click or scroll by user while autoScrolling
const endMessageRef = useRef<HTMLDivElement | null>(null);
const [prompt, setPrompt] = React.useState('');
const [status, setStatus] = React.useState<Status>('idle');
const [queries, setQueries] = React.useState<Query[]>([])
const [conversationId, setConversationId] = React.useState<string | null>(null)
const [open, setOpen] = React.useState<boolean>(false)
const [eventInterrupt, setEventInterrupt] = React.useState<boolean>(false); //click or scroll by user while autoScrolling
const endMessageRef = React.useRef<HTMLDivElement | null>(null);
const handleUserInterrupt = () => {
(status === 'loading') && setEventInterrupt(true);
}
@ -316,7 +317,7 @@ export const DocsGPTWidget = ({
lastChild && scrollToBottom(lastChild)
};
useEffect(() => {
React.useEffect(() => {
!eventInterrupt && scrollToBottom(endMessageRef.current);
}, [queries.length, queries[queries.length - 1]?.response]);
@ -396,7 +397,7 @@ export const DocsGPTWidget = ({
{
queries.length > 0 ? queries?.map((query, index) => {
return (
<Fragment key={index}>
<React.Fragment key={index}>
{
query.prompt && <MessageBubble type='QUESTION'>
<Message
@ -412,7 +413,7 @@ export const DocsGPTWidget = ({
type='ANSWER'
ref={(index === queries.length - 1) ? endMessageRef : null}
>
<div className="response" dangerouslySetInnerHTML={{ __html: sanitize(snarkdown(query.response)) }} />
<div className="response" dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(snarkdown(query.response)) }} />
</Message>
</MessageBubble>
: <div>
@ -436,7 +437,7 @@ export const DocsGPTWidget = ({
}
</div>
}
</Fragment>)
</React.Fragment>)
})
: <Hero title={heroTitle} description={heroDescription} />
}

View File

@ -9,5 +9,11 @@
<body>
<div id="app"></div>
<script type="module" src="main.tsx"></script>
<script type="module" src="../dist/main.js"></script>
<script type="module">
window.onload = function() {
renderDocsGPTWidget('app');
}
</script>
</body>
</html>

View File

@ -1,6 +1,11 @@
import { createRoot } from 'react-dom/client';
import App from './App.tsx';
import React from 'react';
const root = createRoot(document.getElementById('app') as HTMLElement);
import { createRoot } from 'react-dom/client';
import { DocsGPTWidget } from './components/DocsGPTWidget';
root.render(<App />);
const renderWidget = (elementId: string, props = {}) => {
const root = createRoot(document.getElementById(elementId) as HTMLElement);
root.render(<DocsGPTWidget {...props} />);
};
(window as any).renderDocsGPTWidget = renderWidget;
export { DocsGPTWidget };