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)
|
||||
}
|
||||
|
||||
const buttonClicked = (page: "AI" | "Documentation" | "FAQ") => {
|
||||
onViewChange(page)
|
||||
toggleMenu()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
|
@ -26,18 +31,20 @@ const Header: React.FC<HeaderProps> = ({ onViewChange, showDivs, toggleDivs, sho
|
|||
<span></span>
|
||||
</div>
|
||||
<nav className={`nav-links ${menuOpen ? "active":""}`}>
|
||||
<button onClick={() => onViewChange('FAQ')} className="nav-btn">FAQ</button>
|
||||
<button onClick={() => onViewChange('Documentation')} className="nav-btn">Documentation</button>
|
||||
<button onClick={() => buttonClicked("FAQ")} className="nav-btn">FAQ</button>
|
||||
<button onClick={() => buttonClicked("Documentation")} className="nav-btn">Documentation</button>
|
||||
{showToggle && showHistoryModelsToggle && (
|
||||
<button onClick={toggleDivs} className="nav-btn">
|
||||
{showDivs ? 'Hide History/Models' : 'Show History/Models'}
|
||||
</button>
|
||||
)}
|
||||
</nav>
|
||||
{/* <button onClick={() => onViewChange('AI')} className="header-button header-logo">
|
||||
<img src="/img/logo.png" alt="logo" className="header-logo" />
|
||||
</button> */}
|
||||
<Login />
|
||||
<button onClick={() => onViewChange('AI')} className="header-button header-logo">
|
||||
<p>1</p>
|
||||
</button>
|
||||
<div className="login-button">
|
||||
<Login />
|
||||
</div>
|
||||
</header>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -53,11 +53,10 @@ const Login: React.FC = () => {
|
|||
return (
|
||||
<div>
|
||||
{/* Login or Settings Button */}
|
||||
<div className="login-button">
|
||||
<button onClick={isLoggedIn ? toggleSettingsPopup : toggleLoginPopup}>
|
||||
{isLoggedIn ? 'Settings' : 'Log In'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button onClick={isLoggedIn ? toggleSettingsPopup : toggleLoginPopup}>
|
||||
{isLoggedIn ? 'Settings' : 'Log In'}
|
||||
</button>
|
||||
|
||||
{/* Conditional rendering of the Login Popup */}
|
||||
{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 */
|
||||
.popup-overlay {
|
||||
|
|
|
@ -1,93 +1,29 @@
|
|||
header {
|
||||
background-color: var(--header-background-color); /* Use the new header background color */
|
||||
color: var(--header-text-color); /* Use the new header text color */
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
position: fixed;
|
||||
header{
|
||||
position: absolute;
|
||||
padding: 0 20px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 10px 20px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1000;
|
||||
font-family: var(--font-family);
|
||||
width: 100%;
|
||||
height: 10vh;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-links{
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.nav-btn{
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
/* color */
|
||||
}
|
||||
|
||||
.nav-btn:hover{
|
||||
/* color */
|
||||
}
|
||||
|
||||
.hamburger{
|
||||
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;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.hamburger span{
|
||||
width: 25px;
|
||||
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;
|
||||
}
|
||||
.login-button button:hover {
|
||||
background-color: var(--input-button-hover-color);
|
||||
}
|
|
@ -8,8 +8,6 @@
|
|||
|
||||
/* Header styles */
|
||||
header {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -36,17 +34,6 @@
|
|||
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 {
|
||||
display: hidden; /* Initially hidden */
|
||||
|
@ -120,6 +107,18 @@
|
|||
.login-button button{
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.hamburger.open{
|
||||
margin-top: 0.5vh;
|
||||
}
|
||||
|
||||
.nav-links{
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.hamburger {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive adjustments for the settings */
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
--left-panel-background-color: #79832e; /* Background color for left panel */
|
||||
--conversation-background-color: #79832e; /* Background color for conversation container */
|
||||
--doc-background-color: #ffffff; /* Background color for documents */
|
||||
--close-button-color: red;
|
||||
--close-button-color: red;
|
||||
--burger-menu-background-color: #79832e;
|
||||
|
||||
/* FAQ Colors */
|
||||
--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",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
"lint": "next lint",
|
||||
"electron": "npx electron . & next dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mistralai/mistralai": "^1.0.4",
|
||||
"axios": "^1.7.7",
|
||||
"electron": "^32.1.2",
|
||||
"fs": "^0.0.1-security",
|
||||
"next": "14.2.12",
|
||||
"ollama": "^0.5.9",
|
||||
|
|
66
py/db.py
66
py/db.py
|
@ -1,11 +1,21 @@
|
|||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import pycouchdb
|
||||
|
||||
|
||||
class DB:
|
||||
def __init__(self):
|
||||
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
|
||||
def hash_password(password):
|
||||
salt = "your_secret_salt"
|
||||
|
@ -15,12 +25,26 @@ class DB:
|
|||
def add_user(self, data):
|
||||
username = data.get['username']
|
||||
password = data.get['password']
|
||||
email = data.get['email']
|
||||
hashed_password = self.hash_password(password)
|
||||
user_data = {"hashed_password": hashed_password}
|
||||
self.database[username] = user_data
|
||||
user_data = {"hashed_password": hashed_password, "email": email, "data": None}
|
||||
if username not in self.database:
|
||||
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):
|
||||
username = data.get['username']
|
||||
username = self.ensure_username(data)
|
||||
data = data.get['data']
|
||||
if not self.check_credentials(data):
|
||||
return False
|
||||
|
@ -30,7 +54,7 @@ class DB:
|
|||
return True
|
||||
|
||||
def update_password(self, data):
|
||||
username = data.get['username']
|
||||
username = self.ensure_username(data)
|
||||
new_password = data.get['new_password']
|
||||
if not self.check_credentials(data):
|
||||
return False
|
||||
|
@ -41,7 +65,7 @@ class DB:
|
|||
return True
|
||||
|
||||
def check_credentials(self, data):
|
||||
username = data.get['username']
|
||||
username = self.ensure_username(data)
|
||||
password = data.get['password']
|
||||
if username not in self.database:
|
||||
return False
|
||||
|
@ -51,7 +75,7 @@ class DB:
|
|||
return stored_hashed_password == entered_hashed_password
|
||||
|
||||
def get_data(self, data):
|
||||
username = data.get['username']
|
||||
username = self.ensure_username(data)
|
||||
if not self.check_credentials(data):
|
||||
return None
|
||||
|
||||
|
@ -59,12 +83,28 @@ class DB:
|
|||
return send_back
|
||||
|
||||
def save_database(self):
|
||||
with open("database.json", 'w') as file:
|
||||
json.dump(self.database, file)
|
||||
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:
|
||||
json.dump(self.database, file)
|
||||
|
||||
def load_database(self):
|
||||
try:
|
||||
with open("database.json", 'r') as file:
|
||||
self.database = json.load(file)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
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:
|
||||
with open("database.json", 'r') as file:
|
||||
self.database = json.load(file)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
|
|
@ -9,4 +9,5 @@ SpeechRecognition
|
|||
PocketSphinx
|
||||
google-cloud-speech
|
||||
google-generativeai
|
||||
python-weather
|
||||
python-weather
|
||||
pycouchdb
|
Loading…
Reference in a new issue