Skip to content

Commit e1e63eb

Browse files
Merge branch 'main' of https://github.com/utin-francis-peter/DocsGPT into fix/issue#1023
2 parents 8279df4 + d86a06f commit e1e63eb

31 files changed

+852
-205
lines changed

application/api/user/routes.py

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
import requests
77
from pymongo import MongoClient
88
from bson.objectid import ObjectId
9+
from bson.binary import Binary, UuidRepresentation
910
from werkzeug.utils import secure_filename
10-
11+
from bson.dbref import DBRef
1112
from application.api.user.tasks import ingest, ingest_remote
1213

1314
from application.core.settings import settings
@@ -20,6 +21,8 @@
2021
prompts_collection = db["prompts"]
2122
feedback_collection = db["feedback"]
2223
api_key_collection = db["api_keys"]
24+
shared_conversations_collections = db["shared_conversations"]
25+
2326
user = Blueprint("user", __name__)
2427

2528
current_dir = os.path.dirname(
@@ -491,3 +494,73 @@ def delete_api_key():
491494
}
492495
)
493496
return {"status": "ok"}
497+
498+
499+
#route to share conversation
500+
##isPromptable should be passed through queries
501+
@user.route("/api/share",methods=["POST"])
502+
def share_conversation():
503+
try:
504+
data = request.get_json()
505+
user = "local"
506+
if(hasattr(data,"user")):
507+
user = data["user"]
508+
conversation_id = data["conversation_id"]
509+
isPromptable = request.args.get("isPromptable").lower() == "true"
510+
conversation = conversations_collection.find_one({"_id": ObjectId(conversation_id)})
511+
current_n_queries = len(conversation["queries"])
512+
pre_existing = shared_conversations_collections.find_one({
513+
"conversation_id":DBRef("conversations",ObjectId(conversation_id)),
514+
"isPromptable":isPromptable,
515+
"first_n_queries":current_n_queries
516+
})
517+
print("pre_existing",pre_existing)
518+
if(pre_existing is not None):
519+
explicit_binary = pre_existing["uuid"]
520+
return jsonify({"success":True, "identifier":str(explicit_binary.as_uuid())}),200
521+
else:
522+
explicit_binary = Binary.from_uuid(uuid.uuid4(), UuidRepresentation.STANDARD)
523+
shared_conversations_collections.insert_one({
524+
"uuid":explicit_binary,
525+
"conversation_id": {
526+
"$ref":"conversations",
527+
"$id":ObjectId(conversation_id)
528+
} ,
529+
"isPromptable":isPromptable,
530+
"first_n_queries":current_n_queries,
531+
"user":user
532+
})
533+
## Identifier as route parameter in frontend
534+
return jsonify({"success":True, "identifier":str(explicit_binary.as_uuid())}),201
535+
except Exception as err:
536+
return jsonify({"success":False,"error":str(err)}),400
537+
538+
#route to get publicly shared conversations
539+
@user.route("/api/shared_conversation/<string:identifier>",methods=["GET"])
540+
def get_publicly_shared_conversations(identifier : str):
541+
try:
542+
query_uuid = Binary.from_uuid(uuid.UUID(identifier), UuidRepresentation.STANDARD)
543+
shared = shared_conversations_collections.find_one({"uuid":query_uuid})
544+
conversation_queries=[]
545+
if shared and 'conversation_id' in shared and isinstance(shared['conversation_id'], DBRef):
546+
# Resolve the DBRef
547+
conversation_ref = shared['conversation_id']
548+
conversation = db.dereference(conversation_ref)
549+
if(conversation is None):
550+
return jsonify({"sucess":False,"error":"might have broken url or the conversation does not exist"}),404
551+
conversation_queries = conversation['queries'][:(shared["first_n_queries"])]
552+
for query in conversation_queries:
553+
query.pop("sources") ## avoid exposing sources
554+
else:
555+
return jsonify({"sucess":False,"error":"might have broken url or the conversation does not exist"}),404
556+
date = conversation["_id"].generation_time.isoformat()
557+
return jsonify({
558+
"success":True,
559+
"queries":conversation_queries,
560+
"title":conversation["name"],
561+
"timestamp":date
562+
}), 200
563+
except Exception as err:
564+
print (err)
565+
return jsonify({"success":False,"error":str(err)}),400
566+

application/vectorstore/base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ class EmbeddingsSingleton:
1414
@staticmethod
1515
def get_instance(embeddings_name, *args, **kwargs):
1616
if embeddings_name not in EmbeddingsSingleton._instances:
17-
EmbeddingsSingleton._instances[embeddings_name] = EmbeddingsSingleton._create_instance(embeddings_name, *args, **kwargs)
17+
EmbeddingsSingleton._instances[embeddings_name] = EmbeddingsSingleton._create_instance(
18+
embeddings_name, *args, **kwargs
19+
)
1820
return EmbeddingsSingleton._instances[embeddings_name]
1921

2022
@staticmethod

docs/package-lock.json

Lines changed: 20 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/web-widget/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package-lock.json

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"@reduxjs/toolkit": "^1.9.2",
2323
"@vercel/analytics": "^0.1.10",
2424
"i18next": "^23.11.5",
25+
"i18next-browser-languagedetector": "^8.0.0",
26+
"prop-types": "^15.8.1",
2527
"react": "^18.2.0",
2628
"react-copy-to-clipboard": "^5.1.0",
2729
"react-dom": "^18.2.0",

frontend/src/App.tsx

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Routes, Route } from 'react-router-dom';
2+
import { useEffect } from 'react';
23
import Navigation from './Navigation';
34
import Conversation from './conversation/Conversation';
45
import About from './About';
@@ -8,29 +9,53 @@ import { useMediaQuery } from './hooks';
89
import { useState } from 'react';
910
import Setting from './settings';
1011
import './locale/i18n';
11-
12+
import { Outlet } from 'react-router-dom';
13+
import SharedConversation from './conversation/SharedConversation';
14+
import { useDarkTheme } from './hooks';
1215
inject();
1316

14-
export default function App() {
17+
function MainLayout() {
1518
const { isMobile } = useMediaQuery();
1619
const [navOpen, setNavOpen] = useState(!isMobile);
1720
return (
18-
<div className="min-h-full min-w-full dark:bg-raisin-black">
21+
<div className="dark:bg-raisin-black">
1922
<Navigation navOpen={navOpen} setNavOpen={setNavOpen} />
2023
<div
21-
className={`transition-all duration-200 ${
24+
className={`min-h-screen ${
2225
!isMobile
2326
? `ml-0 ${!navOpen ? 'md:mx-auto lg:mx-auto' : 'md:ml-72'}`
2427
: 'ml-0 md:ml-16'
2528
}`}
2629
>
27-
<Routes>
28-
<Route path="/" element={<Conversation />} />
29-
<Route path="/about" element={<About />} />
30-
<Route path="*" element={<PageNotFound />} />
31-
<Route path="/settings" element={<Setting />} />
32-
</Routes>
30+
<Outlet />
3331
</div>
3432
</div>
3533
);
3634
}
35+
36+
export default function App() {
37+
const [isDarkTheme] = useDarkTheme();
38+
useEffect(() => {
39+
localStorage.setItem('selectedTheme', isDarkTheme ? 'Dark' : 'Light');
40+
if (isDarkTheme) {
41+
document
42+
.getElementById('root')
43+
?.classList.add('dark', 'dark:bg-raisin-black');
44+
} else {
45+
document.getElementById('root')?.classList.remove('dark');
46+
}
47+
}, [isDarkTheme]);
48+
return (
49+
<>
50+
<Routes>
51+
<Route element={<MainLayout />}>
52+
<Route index element={<Conversation />} />
53+
<Route path="/about" element={<About />} />
54+
<Route path="/settings" element={<Setting />} />
55+
</Route>
56+
<Route path="/share/:identifier" element={<SharedConversation />} />
57+
<Route path="/*" element={<PageNotFound />} />
58+
</Routes>
59+
</>
60+
);
61+
}

frontend/src/Hero.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default function Hero({
1919
}>;
2020
return (
2121
<div
22-
className={`mt-14 mb-4 flex w-full flex-col justify-end text-black-1000 dark:text-bright-gray sm:w-full lg:mt-6`}
22+
className={`mt-16 mb-4 flex w-full flex-col justify-end text-black-1000 dark:text-bright-gray sm:w-full lg:mt-6`}
2323
>
2424
<div className="flex h-full w-full flex-col items-center justify-center">
2525
<div className="flex items-center">

frontend/src/PageNotFound.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { Link } from 'react-router-dom';
22

33
export default function PageNotFound() {
44
return (
5-
<div className="mx-5 grid min-h-screen md:mx-36">
6-
<p className="mx-auto my-auto mt-20 flex w-full max-w-6xl flex-col place-items-center gap-6 rounded-3xl bg-gray-100 p-6 text-jet lg:p-10 xl:p-16">
5+
<div className="grid min-h-screen dark:bg-raisin-black">
6+
<p className="mx-auto my-auto mt-20 flex w-full max-w-6xl flex-col place-items-center gap-6 rounded-3xl bg-gray-100 p-6 text-jet dark:bg-outer-space dark:text-gray-100 lg:p-10 xl:p-16">
77
<h1>404</h1>
88
<p>The page you are looking for does not exist.</p>
9-
<button className="pointer-cursor mr-4 flex cursor-pointer items-center justify-center rounded-full bg-blue-1000 py-2 px-4 text-white hover:bg-blue-3000">
9+
<button className="pointer-cursor mr-4 flex cursor-pointer items-center justify-center rounded-full bg-blue-1000 py-2 px-4 text-white transition-colors duration-100 hover:bg-blue-3000">
1010
<Link to="/">Go Back Home</Link>
1111
</button>
1212
</p>

frontend/src/assets/red-trash.svg

Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)