forked from React-Group/interstellar_ai
		
	Backend and CSS #17
					 12 changed files with 742 additions and 174 deletions
				
			
		
							
								
								
									
										16
									
								
								app/backend/database.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/backend/database.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | import axios from "axios"; | ||||||
|  | 
 | ||||||
|  | const sendToDatabase = (data: any) => { | ||||||
|  |     axios.post("http://localhost:5000/interstellar_ai/db", data) | ||||||
|  |         .then(response => { | ||||||
|  |             const status = response.data.status | ||||||
|  |             console.log(status); | ||||||
|  |             postMessage({ status }) | ||||||
|  |             console.log('message posted'); | ||||||
|  | 
 | ||||||
|  |         }) | ||||||
|  |         .catch(error => { | ||||||
|  |             console.log("Error calling Database:", error) | ||||||
|  |             postMessage({ status: 500 }) | ||||||
|  |         }) | ||||||
|  | } | ||||||
|  | @ -17,6 +17,11 @@ const Header: React.FC<HeaderProps> = ({ onViewChange, showDivs, toggleDivs, sho | ||||||
|     setMenuOpen(!menuOpen) |     setMenuOpen(!menuOpen) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   const buttonClicked = (page: "AI" | "Documentation" | "FAQ") => { | ||||||
|  |     onViewChange(page) | ||||||
|  |     toggleMenu() | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <header> |       <header> | ||||||
|  | @ -26,18 +31,20 @@ const Header: React.FC<HeaderProps> = ({ onViewChange, showDivs, toggleDivs, sho | ||||||
|           <span></span> |           <span></span> | ||||||
|         </div> |         </div> | ||||||
|         <nav className={`nav-links ${menuOpen ? "active":""}`}> |         <nav className={`nav-links ${menuOpen ? "active":""}`}> | ||||||
|             <button onClick={() => onViewChange('FAQ')} className="nav-btn">FAQ</button> |             <button onClick={() => buttonClicked("FAQ")} className="nav-btn">FAQ</button> | ||||||
|             <button onClick={() => onViewChange('Documentation')} className="nav-btn">Documentation</button> |             <button onClick={() => buttonClicked("Documentation")} className="nav-btn">Documentation</button> | ||||||
|             {showToggle && showHistoryModelsToggle && ( |             {showToggle && showHistoryModelsToggle && ( | ||||||
|               <button onClick={toggleDivs} className="nav-btn"> |               <button onClick={toggleDivs} className="nav-btn"> | ||||||
|                 {showDivs ? 'Hide History/Models' : 'Show History/Models'} |                 {showDivs ? 'Hide History/Models' : 'Show History/Models'} | ||||||
|               </button> |               </button> | ||||||
|             )} |             )} | ||||||
|           </nav> |           </nav> | ||||||
|           {/* <button onClick={() => onViewChange('AI')} className="header-button header-logo"> |         <button onClick={() => onViewChange('AI')} className="header-button header-logo"> | ||||||
|             <img src="/img/logo.png" alt="logo" className="header-logo" /> |           <p>1</p> | ||||||
|           </button> */} |         </button> | ||||||
|  |         <div className="login-button"> | ||||||
|           <Login />  |           <Login />  | ||||||
|  |         </div> | ||||||
|       </header> |       </header> | ||||||
|     </> |     </> | ||||||
|   ); |   ); | ||||||
|  |  | ||||||
|  | @ -53,11 +53,10 @@ const Login: React.FC = () => { | ||||||
|   return ( |   return ( | ||||||
|     <div> |     <div> | ||||||
|       {/* Login or Settings Button */} |       {/* Login or Settings Button */} | ||||||
|       <div className="login-button"> |        | ||||||
|       <button onClick={isLoggedIn ? toggleSettingsPopup : toggleLoginPopup}> |       <button onClick={isLoggedIn ? toggleSettingsPopup : toggleLoginPopup}> | ||||||
|         {isLoggedIn ? 'Settings' : 'Log In'} |         {isLoggedIn ? 'Settings' : 'Log In'} | ||||||
|       </button> |       </button> | ||||||
|       </div> |  | ||||||
| 
 | 
 | ||||||
|       {/* Conditional rendering of the Login Popup */} |       {/* Conditional rendering of the Login Popup */} | ||||||
|       {showLoginPopup && ( |       {showLoginPopup && ( | ||||||
|  |  | ||||||
|  | @ -1,34 +1,3 @@ | ||||||
| /* Container for the login layout */ |  | ||||||
| .login-container { |  | ||||||
|     display: grid; |  | ||||||
|     grid-template-columns: 1fr 3fr; /* 1fr for sidebar, 3fr for main content */ |  | ||||||
|     grid-auto-flow: column; |  | ||||||
|     overflow-x: hidden; |  | ||||||
|     height: 100%; /* Ensure it takes full height */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Button for login action */ |  | ||||||
| .login-button { |  | ||||||
|     position: absolute; |  | ||||||
|     top: 5px; |  | ||||||
|     right: 10px; |  | ||||||
|     z-index: 9999; /* Highest z-index for the login button */ |  | ||||||
|     margin: 1px; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .login-button button { |  | ||||||
|     padding: 10px 20px; |  | ||||||
|     background-color: var(--input-button-color); |  | ||||||
|     color: var(--text-color); |  | ||||||
|     border: none; |  | ||||||
|     border-radius: 5px; |  | ||||||
|     cursor: pointer; |  | ||||||
|     transition: background-color 0.3s; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .login-button button:hover { |  | ||||||
|     background-color: var(--input-button-hover-color); |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| /* Overlay for popup - full screen and centered */ | /* Overlay for popup - full screen and centered */ | ||||||
| .popup-overlay { | .popup-overlay { | ||||||
|  |  | ||||||
|  | @ -1,93 +1,29 @@ | ||||||
| header { | header{ | ||||||
|     background-color: var(--header-background-color); /* Use the new header background color */ |     position: absolute; | ||||||
|     color: var(--header-text-color); /* Use the new header text color */ |     padding: 0 20px; | ||||||
|     width: 100%; |  | ||||||
|     text-decoration: none; |  | ||||||
|     position: fixed; |  | ||||||
|     top: 0; |     top: 0; | ||||||
|     left: 0; |     left: 0; | ||||||
|     padding: 10px 20px; |     width: 100%; | ||||||
|     box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); |     height: 10vh; | ||||||
|     z-index: 1000; |  | ||||||
|     font-family: var(--font-family); |  | ||||||
|     display: flex; |     display: flex; | ||||||
|     justify-content: space-between; |     justify-content: space-between; | ||||||
|     align-items: center; |     align-items: center; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .nav-links{ |  | ||||||
|     display: flex; |  | ||||||
|     gap: 15px; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .nav-btn{ |  | ||||||
|     background: transparent; |  | ||||||
|     border: none; |  | ||||||
|     cursor: pointer; |  | ||||||
|     /* color */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .nav-btn:hover{ |  | ||||||
|     /* color */ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .hamburger{ | .hamburger{ | ||||||
|     display: none; |     display: none; | ||||||
|     flex-direction: column; | } | ||||||
|  | 
 | ||||||
|  | .login-button button{ | ||||||
|  |     padding: 10px 20px; | ||||||
|  |     background-color: var(--input-button-color); | ||||||
|  |     color: var(--text-color); | ||||||
|  |     border: none; | ||||||
|  |     border-radius: 5px; | ||||||
|     cursor: pointer; |     cursor: pointer; | ||||||
|  |     transition: background-color 0.3s; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .hamburger span{ | .login-button button:hover { | ||||||
|     width: 25px; |     background-color: var(--input-button-hover-color); | ||||||
|     height: 3px; |  | ||||||
|     background-color: var(--header-text-color); |  | ||||||
|     margin: 4px; |  | ||||||
|     transition: 0.3s; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .hamburger.open span:nth-child(1){ |  | ||||||
|     transform: rotate(45deg) translate(5px, 5px); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .hamburger.open span:nth-child(2){ |  | ||||||
|     opacity: 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .hamburger.open span:nth-child(3){ |  | ||||||
|     transform: rotate(-45deg) translate(5px, -5px); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .header-button{ |  | ||||||
|      |  | ||||||
| } |  | ||||||
| .header-button img{ |  | ||||||
|     height: 8vh; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| @media (max-width:768px) { |  | ||||||
|     .nav-links{ |  | ||||||
|         display: none; |  | ||||||
|         position: absolute; |  | ||||||
|         top: 60px; |  | ||||||
|         right: 0; |  | ||||||
|         /* background color */ |  | ||||||
|         width: 100%; |  | ||||||
|         flex-direction: column; |  | ||||||
|         align-items: flex-start; |  | ||||||
|         padding: 10px; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     .nav-links.active{ |  | ||||||
|         display: flex; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     .nav-btn{ |  | ||||||
|         width: 100%; |  | ||||||
|         text-align: center; |  | ||||||
|         padding: 10px; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     .hamburger{ |  | ||||||
|         display: flex; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  | @ -8,8 +8,6 @@ | ||||||
|    |    | ||||||
|   /* Header styles */ |   /* Header styles */ | ||||||
|   header { |   header { | ||||||
|     flex-direction: column; |  | ||||||
|     align-items: center; |  | ||||||
|     position: fixed; |     position: fixed; | ||||||
|     top: 0; |     top: 0; | ||||||
|     left: 0; |     left: 0; | ||||||
|  | @ -36,17 +34,6 @@ | ||||||
|     margin: 0; |     margin: 0; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   header li button { |  | ||||||
|     margin: 2px; |  | ||||||
|     margin-bottom: 0; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   header li img { |  | ||||||
|     height: 1.5em; |  | ||||||
|     vertical-align: middle; |  | ||||||
|     margin-top: 10px; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   /* Left panel styles */ |   /* Left panel styles */ | ||||||
|   .left-panel { |   .left-panel { | ||||||
|     display: hidden; /* Initially hidden */ |     display: hidden; /* Initially hidden */ | ||||||
|  | @ -120,6 +107,18 @@ | ||||||
|   .login-button button{ |   .login-button button{ | ||||||
|     margin: 20px 0; |     margin: 20px 0; | ||||||
|   }  |   }  | ||||||
|  | 
 | ||||||
|  |   .hamburger.open{ | ||||||
|  |     margin-top: 0.5vh; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   .nav-links{ | ||||||
|  |     position: fixed; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   .hamburger { | ||||||
|  |     display: flex; | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Responsive adjustments for the settings */ | /* Responsive adjustments for the settings */ | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ | ||||||
|     --conversation-background-color: #79832e; /* Background color for conversation container */ |     --conversation-background-color: #79832e; /* Background color for conversation container */ | ||||||
|     --doc-background-color: #ffffff; /* Background color for documents */ |     --doc-background-color: #ffffff; /* Background color for documents */ | ||||||
|     --close-button-color: red; |     --close-button-color: red; | ||||||
|  |     --burger-menu-background-color: #79832e;   | ||||||
|      |      | ||||||
|     /* FAQ Colors */ |     /* FAQ Colors */ | ||||||
|     --faq-background-color: #474D22; /* Background color for FAQ section */ |     --faq-background-color: #474D22; /* Background color for FAQ section */ | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								main.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								main.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | const { app, BrowserWindow } = require('electron'); | ||||||
|  | 
 | ||||||
|  | function createWindow() { | ||||||
|  |     const win = new BrowserWindow({ | ||||||
|  |         width: 800, | ||||||
|  |         height: 600, | ||||||
|  |         webPreferences: { | ||||||
|  |             nodeIntegration: true, | ||||||
|  |         }, | ||||||
|  | 	autoHideMenuBar: true, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     win.loadURL('http://localhost:3000'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | app.whenReady().then(createWindow); | ||||||
|  | 
 | ||||||
|  | app.on('window-all-closed', () => { | ||||||
|  |     if (process.platform !== 'darwin') { | ||||||
|  |         app.quit(); | ||||||
|  |     } | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | app.on('activate', () => { | ||||||
|  |     if (BrowserWindow.getAllWindows().length === 0) { | ||||||
|  |         createWindow(); | ||||||
|  |     } | ||||||
|  | }); | ||||||
							
								
								
									
										615
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										615
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -2,15 +2,18 @@ | ||||||
|   "name": "interstellar_ai", |   "name": "interstellar_ai", | ||||||
|   "version": "0.1.0", |   "version": "0.1.0", | ||||||
|   "private": true, |   "private": true, | ||||||
|  |   "main": "main.js", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "dev": "next dev", |     "dev": "next dev", | ||||||
|     "build": "next build", |     "build": "next build", | ||||||
|     "start": "next start", |     "start": "next start", | ||||||
|     "lint": "next lint" |     "lint": "next lint", | ||||||
|  |     "electron": "npx electron . & next dev" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@mistralai/mistralai": "^1.0.4", |     "@mistralai/mistralai": "^1.0.4", | ||||||
|     "axios": "^1.7.7", |     "axios": "^1.7.7", | ||||||
|  |     "electron": "^32.1.2", | ||||||
|     "fs": "^0.0.1-security", |     "fs": "^0.0.1-security", | ||||||
|     "next": "14.2.12", |     "next": "14.2.12", | ||||||
|     "ollama": "^0.5.9", |     "ollama": "^0.5.9", | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								py/db.py
									
										
									
									
									
								
							
							
						
						
									
										50
									
								
								py/db.py
									
										
									
									
									
								
							|  | @ -1,11 +1,21 @@ | ||||||
| import hashlib | import hashlib | ||||||
| import json | import json | ||||||
|  | import os | ||||||
|  | import pycouchdb | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DB: | class DB: | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         self.database = {} |         self.database = {} | ||||||
| 
 | 
 | ||||||
|  |     def ensure_username(self, data): | ||||||
|  |         if hasattr(data, 'username'): | ||||||
|  |             return data.get['username'] | ||||||
|  |         elif hasattr(data, 'email'): | ||||||
|  |             for index, entry in self.database: | ||||||
|  |                 if entry.get['email'] == data.get['email']: | ||||||
|  |                     return index | ||||||
|  | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def hash_password(password): |     def hash_password(password): | ||||||
|         salt = "your_secret_salt" |         salt = "your_secret_salt" | ||||||
|  | @ -15,12 +25,26 @@ class DB: | ||||||
|     def add_user(self, data): |     def add_user(self, data): | ||||||
|         username = data.get['username'] |         username = data.get['username'] | ||||||
|         password = data.get['password'] |         password = data.get['password'] | ||||||
|  |         email = data.get['email'] | ||||||
|         hashed_password = self.hash_password(password) |         hashed_password = self.hash_password(password) | ||||||
|         user_data = {"hashed_password": hashed_password} |         user_data = {"hashed_password": hashed_password, "email": email, "data": None} | ||||||
|  |         if username not in self.database: | ||||||
|             self.database[username] = user_data |             self.database[username] = user_data | ||||||
|  |             return True | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|  |     def delete_user(self, data): | ||||||
|  |         username = self.ensure_username(data) | ||||||
|  |         data = data.get['data'] | ||||||
|  |         if not self.check_credentials(data): | ||||||
|  |             return False | ||||||
|  | 
 | ||||||
|  |         del self.database[username] | ||||||
|  |         self.save_database() | ||||||
|  |         return True | ||||||
| 
 | 
 | ||||||
|     def change_data(self, data): |     def change_data(self, data): | ||||||
|         username = data.get['username'] |         username = self.ensure_username(data) | ||||||
|         data = data.get['data'] |         data = data.get['data'] | ||||||
|         if not self.check_credentials(data): |         if not self.check_credentials(data): | ||||||
|             return False |             return False | ||||||
|  | @ -30,7 +54,7 @@ class DB: | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
|     def update_password(self, data): |     def update_password(self, data): | ||||||
|         username = data.get['username'] |         username = self.ensure_username(data) | ||||||
|         new_password = data.get['new_password'] |         new_password = data.get['new_password'] | ||||||
|         if not self.check_credentials(data): |         if not self.check_credentials(data): | ||||||
|             return False |             return False | ||||||
|  | @ -41,7 +65,7 @@ class DB: | ||||||
|         return True |         return True | ||||||
| 
 | 
 | ||||||
|     def check_credentials(self, data): |     def check_credentials(self, data): | ||||||
|         username = data.get['username'] |         username = self.ensure_username(data) | ||||||
|         password = data.get['password'] |         password = data.get['password'] | ||||||
|         if username not in self.database: |         if username not in self.database: | ||||||
|             return False |             return False | ||||||
|  | @ -51,7 +75,7 @@ class DB: | ||||||
|         return stored_hashed_password == entered_hashed_password |         return stored_hashed_password == entered_hashed_password | ||||||
| 
 | 
 | ||||||
|     def get_data(self, data): |     def get_data(self, data): | ||||||
|         username = data.get['username'] |         username = self.ensure_username(data) | ||||||
|         if not self.check_credentials(data): |         if not self.check_credentials(data): | ||||||
|             return None |             return None | ||||||
| 
 | 
 | ||||||
|  | @ -59,10 +83,26 @@ class DB: | ||||||
|         return send_back |         return send_back | ||||||
| 
 | 
 | ||||||
|     def save_database(self): |     def save_database(self): | ||||||
|  |         if os.environ.get('PRODUCTION') == "YES": | ||||||
|  |             server = pycouchdb.Server("http://admin:admin@localhost:5984/") | ||||||
|  |             db = server.database("interstellar_ai") | ||||||
|  |             db.save(self.database) | ||||||
|  | 
 | ||||||
|  |         else: | ||||||
|             with open("database.json", 'w') as file: |             with open("database.json", 'w') as file: | ||||||
|                 json.dump(self.database, file) |                 json.dump(self.database, file) | ||||||
| 
 | 
 | ||||||
|     def load_database(self): |     def load_database(self): | ||||||
|  |         if os.environ.get('PRODUCTION') == "YES": | ||||||
|  |             server = pycouchdb.Server("http://admin:admin@localhost:5984/") | ||||||
|  |             db = server.database("interstellar_ai") | ||||||
|  |             if db: | ||||||
|  |                 self.database = db | ||||||
|  |             else: | ||||||
|  |                 server.create("interstellar_ai") | ||||||
|  |                 db = server.database("interstellar_ai") | ||||||
|  |                 db.save(self.database) | ||||||
|  |         else: | ||||||
|             try: |             try: | ||||||
|                 with open("database.json", 'r') as file: |                 with open("database.json", 'r') as file: | ||||||
|                     self.database = json.load(file) |                     self.database = json.load(file) | ||||||
|  |  | ||||||
|  | @ -10,3 +10,4 @@ PocketSphinx | ||||||
| google-cloud-speech | google-cloud-speech | ||||||
| google-generativeai | google-generativeai | ||||||
| python-weather | python-weather | ||||||
|  | pycouchdb | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue