Backend and CSS #17

Merged
sageTheDm merged 9 commits from React-Group/interstellar_ai:main into main 2024-09-25 11:39:00 +02:00
12 changed files with 742 additions and 174 deletions

16
app/backend/database.ts Normal file
View 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 })
})
}

View file

@ -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>
<Login /> <div className="login-button">
<Login />
</div>
</header> </header>
</> </>
); );

View file

@ -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 && (

View file

@ -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 {

View file

@ -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;
}
} }

View file

@ -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 */

View file

@ -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
View 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

File diff suppressed because it is too large Load diff

View file

@ -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",

View file

@ -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}
self.database[username] = user_data 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): 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,12 +83,28 @@ class DB:
return send_back return send_back
def save_database(self): def save_database(self):
with open("database.json", 'w') as file: if os.environ.get('PRODUCTION') == "YES":
json.dump(self.database, file) 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): def load_database(self):
try: if os.environ.get('PRODUCTION') == "YES":
with open("database.json", 'r') as file: server = pycouchdb.Server("http://admin:admin@localhost:5984/")
self.database = json.load(file) db = server.database("interstellar_ai")
except FileNotFoundError: if db:
pass 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

View file

@ -10,3 +10,4 @@ PocketSphinx
google-cloud-speech google-cloud-speech
google-generativeai google-generativeai
python-weather python-weather
pycouchdb