Spaces:
Runtime error
Runtime error
Commit ·
0082b84
1
Parent(s): 9bb8090
initial commit
Browse files- Dockerfile +21 -18
- Dockerfile.test +0 -28
- README +0 -1
- README.md +1 -3
- build_scripts/build.sh +28 -0
- docker-compose.dev.yml +1 -9
- docker-compose.prod.yml +1 -1
- nginx.conf +13 -17
- requirements.txt +182 -3
- web_app/backend/app/__init__.py +2 -8
- web_app/backend/app/answers_model.py +73 -8
- web_app/backend/app/{chatbot.py → chatbot_routes.py} +69 -19
- web_app/backend/app/data/.gitkeep +0 -0
- web_app/backend/app/data/{BER_Small.csv → BER/BER_Small.csv} +0 -0
- web_app/backend/app/data/chain.json +57 -0
- web_app/backend/app/data/dropped_features.txt +15 -0
- web_app/backend/app/data/energy_modelling.ipynb +0 -0
- web_app/backend/app/data/pinecone_tut.ipynb +0 -370
- web_app/backend/app/models.py +6 -6
- web_app/backend/app/pinecone_q.ipynb +0 -133
- web_app/backend/app/question_model.py +21 -4
- web_app/backend/requirements.txt +0 -102
- web_app/backend/run.py +1 -1
- web_app/frontend/package-lock.json +0 -0
- web_app/frontend/package.json +14 -4
- web_app/frontend/public/map1.json +0 -0
- web_app/frontend/src/App.jsx +2 -2
- web_app/frontend/src/AppRouter.jsx +7 -3
- web_app/frontend/src/components/ChatHistory.jsx +3 -3
- web_app/frontend/src/components/ChatInput.jsx +7 -5
- web_app/frontend/src/components/Map3D-old.jsx +137 -0
- web_app/frontend/src/components/Map3D.jsx +155 -0
- web_app/frontend/src/components/Navbar.jsx +15 -20
- web_app/frontend/src/components/StartCard.jsx +16 -13
- web_app/frontend/src/components/emailService.jsx +26 -0
- web_app/frontend/src/hooks/useChat.js +7 -9
- web_app/frontend/src/pages/AboutPage.jsx +13 -11
- web_app/frontend/src/pages/ChatBot.jsx +0 -76
- web_app/frontend/src/pages/ChatPage.jsx +169 -46
- web_app/frontend/src/pages/CityPage.jsx +112 -0
- web_app/frontend/src/pages/ContactPage.jsx +13 -11
- web_app/frontend/src/pages/DashboardPage-new.jsx +104 -0
- web_app/frontend/src/pages/DashboardPage-old.jsx +125 -0
- web_app/frontend/src/pages/DashboardPage.css +164 -0
- web_app/frontend/src/pages/LandingPage.jsx +3 -1
- web_app/frontend/src/pages/{DashboardPage.jsx → ReportsPage.jsx} +37 -36
- web_app/frontend/src/pages/ResourcesPage.jsx +105 -0
- web_app/frontend/src/pages/scrollbar.css +20 -0
- web_app/frontend/vite.config.js +11 -7
Dockerfile
CHANGED
|
@@ -1,37 +1,40 @@
|
|
| 1 |
-
#
|
| 2 |
# STAGE 1: Backend build
|
| 3 |
-
#
|
| 4 |
-
|
| 5 |
FROM python:3.9-slim-buster as backend
|
| 6 |
-
|
| 7 |
WORKDIR /app/backend
|
| 8 |
|
| 9 |
-
|
|
|
|
|
|
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
RUN
|
|
|
|
|
|
|
| 14 |
|
|
|
|
| 15 |
COPY web_app/backend/ .
|
| 16 |
|
| 17 |
CMD ["python", "run.py"]
|
| 18 |
|
| 19 |
-
#
|
| 20 |
# STAGE 2: Frontend build
|
| 21 |
-
#
|
| 22 |
-
|
| 23 |
FROM node:14-alpine as frontend
|
| 24 |
-
|
| 25 |
WORKDIR /app/frontend
|
| 26 |
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
RUN npm install
|
| 30 |
-
|
| 31 |
COPY web_app/frontend/ .
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
-
RUN
|
| 34 |
|
| 35 |
EXPOSE 3000
|
|
|
|
| 36 |
|
| 37 |
-
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
|
|
|
| 1 |
+
#------------------------
|
| 2 |
# STAGE 1: Backend build
|
| 3 |
+
#------------------------
|
|
|
|
| 4 |
FROM python:3.9-slim-buster as backend
|
|
|
|
| 5 |
WORKDIR /app/backend
|
| 6 |
|
| 7 |
+
# Copy necessary files
|
| 8 |
+
COPY requirements.txt .
|
| 9 |
+
COPY build_scripts/build.sh .
|
| 10 |
|
| 11 |
+
# Set environment variable, make the script executable and run it
|
| 12 |
+
ENV STAGE=backend
|
| 13 |
+
RUN chmod +x ./build.sh && \
|
| 14 |
+
./build.sh backend && \
|
| 15 |
+
rm -rf /var/lib/apt/lists/*
|
| 16 |
|
| 17 |
+
# Copy the rest of the backend app
|
| 18 |
COPY web_app/backend/ .
|
| 19 |
|
| 20 |
CMD ["python", "run.py"]
|
| 21 |
|
| 22 |
+
#-------------------------
|
| 23 |
# STAGE 2: Frontend build
|
| 24 |
+
#-------------------------
|
|
|
|
| 25 |
FROM node:14-alpine as frontend
|
|
|
|
| 26 |
WORKDIR /app/frontend
|
| 27 |
|
| 28 |
+
# Grouped copy for package-related files and the frontend app
|
| 29 |
+
COPY web_app/frontend/package*.json .
|
|
|
|
|
|
|
| 30 |
COPY web_app/frontend/ .
|
| 31 |
+
COPY build_scripts/build.sh .
|
| 32 |
+
|
| 33 |
+
# Set environment variables, make the script executable and run it
|
| 34 |
+
ENV STAGE=frontend
|
| 35 |
|
| 36 |
+
RUN chmod +x ./build.sh && ./build.sh frontend
|
| 37 |
|
| 38 |
EXPOSE 3000
|
| 39 |
+
CMD ["serve", "-s", "dist", "-l", "3000"]
|
| 40 |
|
|
|
Dockerfile.test
DELETED
|
@@ -1,28 +0,0 @@
|
|
| 1 |
-
# Use the official Python 3.9 image
|
| 2 |
-
FROM python:3.9
|
| 3 |
-
|
| 4 |
-
# Set the working directory to /code
|
| 5 |
-
WORKDIR /code
|
| 6 |
-
|
| 7 |
-
# Copy the current directory contents into the container at /code
|
| 8 |
-
COPY ./requirements.txt /code/requirements.txt
|
| 9 |
-
|
| 10 |
-
# Install requirements.txt
|
| 11 |
-
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
| 12 |
-
|
| 13 |
-
# Set up a new user named "user" with user ID 1000
|
| 14 |
-
RUN useradd -m -u 1000 user
|
| 15 |
-
# Switch to the "user" user
|
| 16 |
-
USER user
|
| 17 |
-
# Set home to the user's home directory
|
| 18 |
-
ENV HOME=/home/user \
|
| 19 |
-
PATH=/home/user/.local/bin:$PATH
|
| 20 |
-
|
| 21 |
-
# Set the working directory to the user's home directory
|
| 22 |
-
WORKDIR $HOME/app
|
| 23 |
-
|
| 24 |
-
# Copy the current directory contents into the container at $HOME/app setting the owner to the user
|
| 25 |
-
COPY --chown=user . $HOME/app
|
| 26 |
-
|
| 27 |
-
# Start the FastAPI app on port 7860, the default port expected by Spaces
|
| 28 |
-
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
# Hello
|
|
|
|
|
|
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: ⚡
|
| 4 |
colorFrom: yellow
|
| 5 |
colorTo: gray
|
|
@@ -8,5 +8,3 @@ pinned: false
|
|
| 8 |
license: cc-by-nc-2.0
|
| 9 |
app_port: 3000
|
| 10 |
---
|
| 11 |
-
|
| 12 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 1 |
---
|
| 2 |
+
title: web-app-temp
|
| 3 |
emoji: ⚡
|
| 4 |
colorFrom: yellow
|
| 5 |
colorTo: gray
|
|
|
|
| 8 |
license: cc-by-nc-2.0
|
| 9 |
app_port: 3000
|
| 10 |
---
|
|
|
|
|
|
build_scripts/build.sh
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/sh
|
| 2 |
+
set -e
|
| 3 |
+
|
| 4 |
+
# Check the STAGE environment variable
|
| 5 |
+
if [ "$STAGE" = "backend" ]; then
|
| 6 |
+
|
| 7 |
+
# Update and install dependencies
|
| 8 |
+
apt-get update && apt-get install -y --no-install-recommends gcc g++
|
| 9 |
+
|
| 10 |
+
# Install python dependencies
|
| 11 |
+
pip install --no-cache-dir -r requirements.txt
|
| 12 |
+
|
| 13 |
+
elif [ "$STAGE" = "frontend" ]; then
|
| 14 |
+
|
| 15 |
+
# Install dependencies
|
| 16 |
+
npm install
|
| 17 |
+
|
| 18 |
+
# Adjust permissions and build in a single command
|
| 19 |
+
chown -R node:node /app/frontend
|
| 20 |
+
npm run build
|
| 21 |
+
|
| 22 |
+
# Install serve
|
| 23 |
+
npm install -g serve
|
| 24 |
+
|
| 25 |
+
else
|
| 26 |
+
echo "Error: Invalid or no STAGE specified"
|
| 27 |
+
exit 1
|
| 28 |
+
fi
|
docker-compose.dev.yml
CHANGED
|
@@ -5,7 +5,7 @@ services:
|
|
| 5 |
context: .
|
| 6 |
target: backend
|
| 7 |
ports:
|
| 8 |
-
-
|
| 9 |
|
| 10 |
frontend:
|
| 11 |
image: node:alpine
|
|
@@ -23,14 +23,6 @@ services:
|
|
| 23 |
depends_on:
|
| 24 |
- backend
|
| 25 |
|
| 26 |
-
dl:
|
| 27 |
-
build:
|
| 28 |
-
context: .
|
| 29 |
-
dockerfile: Dockerfile
|
| 30 |
-
image: pytorch/pytorch:1.13.0-cuda11.6-cudnn8-runtime
|
| 31 |
-
tty: true
|
| 32 |
-
stdin_open: true
|
| 33 |
-
|
| 34 |
volumes:
|
| 35 |
postgres_data:
|
| 36 |
|
|
|
|
| 5 |
context: .
|
| 6 |
target: backend
|
| 7 |
ports:
|
| 8 |
+
- 5000:5000
|
| 9 |
|
| 10 |
frontend:
|
| 11 |
image: node:alpine
|
|
|
|
| 23 |
depends_on:
|
| 24 |
- backend
|
| 25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
volumes:
|
| 27 |
postgres_data:
|
| 28 |
|
docker-compose.prod.yml
CHANGED
|
@@ -5,7 +5,7 @@ services:
|
|
| 5 |
context: .
|
| 6 |
target: backend
|
| 7 |
ports:
|
| 8 |
-
-
|
| 9 |
environment:
|
| 10 |
- DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}
|
| 11 |
depends_on:
|
|
|
|
| 5 |
context: .
|
| 6 |
target: backend
|
| 7 |
ports:
|
| 8 |
+
- 5000:5000
|
| 9 |
environment:
|
| 10 |
- DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}
|
| 11 |
depends_on:
|
nginx.conf
CHANGED
|
@@ -1,30 +1,26 @@
|
|
| 1 |
-
|
| 2 |
-
events {
|
| 3 |
-
# The worker_connections directive specifies the maximum number of simultaneous connections
|
| 4 |
-
# that a single worker process can handle.
|
| 5 |
-
worker_connections 1024;
|
| 6 |
-
}
|
| 7 |
|
| 8 |
-
# The http block is where you define directives for handling HTTP requests.
|
| 9 |
http {
|
| 10 |
-
upstream frontend {
|
| 11 |
-
server frontend:3000;
|
| 12 |
-
}
|
| 13 |
-
|
| 14 |
upstream backend {
|
| 15 |
server backend:5000;
|
| 16 |
}
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
server {
|
| 19 |
-
listen
|
| 20 |
-
|
| 21 |
-
location / {
|
| 22 |
-
proxy_pass http://frontend;
|
| 23 |
-
}
|
| 24 |
|
| 25 |
location /api/ {
|
| 26 |
proxy_pass http://backend;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
}
|
| 28 |
}
|
| 29 |
}
|
| 30 |
-
|
|
|
|
| 1 |
+
events {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
|
|
|
| 3 |
http {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
upstream backend {
|
| 5 |
server backend:5000;
|
| 6 |
}
|
| 7 |
+
upstream frontend {
|
| 8 |
+
server frontend:3000;
|
| 9 |
+
}
|
| 10 |
|
| 11 |
server {
|
| 12 |
+
listen 8081;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
location /api/ {
|
| 15 |
proxy_pass http://backend;
|
| 16 |
+
proxy_set_header Host $host;
|
| 17 |
+
proxy_set_header X-Real-IP $remote_addr;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
location / {
|
| 21 |
+
proxy_pass http://frontend;
|
| 22 |
+
proxy_set_header Host $host;
|
| 23 |
+
proxy_set_header X-Real-IP $remote_addr;
|
| 24 |
}
|
| 25 |
}
|
| 26 |
}
|
|
|
requirements.txt
CHANGED
|
@@ -1,3 +1,182 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
aiohttp==3.8.5
|
| 2 |
+
aiosignal==1.3.1
|
| 3 |
+
anyio==3.7.1
|
| 4 |
+
appnope==0.1.3
|
| 5 |
+
argon2-cffi==21.3.0
|
| 6 |
+
argon2-cffi-bindings==21.2.0
|
| 7 |
+
arrow==1.2.3
|
| 8 |
+
astor==0.8.1
|
| 9 |
+
asttokens==2.2.1
|
| 10 |
+
async-lru==2.0.4
|
| 11 |
+
async-timeout==4.0.2
|
| 12 |
+
attrs==23.1.0
|
| 13 |
+
Babel==2.12.1
|
| 14 |
+
backcall==0.2.0
|
| 15 |
+
backoff==2.2.1
|
| 16 |
+
beautifulsoup4==4.12.2
|
| 17 |
+
bleach==6.0.0
|
| 18 |
+
blinker==1.6.2
|
| 19 |
+
cachetools==5.3.1
|
| 20 |
+
certifi==2023.7.22
|
| 21 |
+
cffi==1.15.1
|
| 22 |
+
charset-normalizer==3.2.0
|
| 23 |
+
chroma-hnswlib==0.7.1
|
| 24 |
+
chromadb==0.4.3
|
| 25 |
+
click==8.1.4
|
| 26 |
+
coloredlogs==15.0.1
|
| 27 |
+
comm==0.1.4
|
| 28 |
+
contourpy==1.1.0
|
| 29 |
+
cssselect==1.2.0
|
| 30 |
+
cssutils==2.7.1
|
| 31 |
+
cycler==0.11.0
|
| 32 |
+
dataclasses-json==0.5.13
|
| 33 |
+
debugpy==1.6.7
|
| 34 |
+
decorator==5.1.1
|
| 35 |
+
defusedxml==0.7.1
|
| 36 |
+
dnspython==2.4.1
|
| 37 |
+
docopt==0.6.2
|
| 38 |
+
executing==1.2.0
|
| 39 |
+
faiss-cpu==1.7.4
|
| 40 |
+
fastapi==0.99.1
|
| 41 |
+
fastjsonschema==2.18.0
|
| 42 |
+
Flask==2.3.2
|
| 43 |
+
Flask-Cors==4.0.0
|
| 44 |
+
Flask-SQLAlchemy==3.0.5
|
| 45 |
+
flatbuffers==23.5.26
|
| 46 |
+
fonttools==4.41.1
|
| 47 |
+
fpdf==1.7.2
|
| 48 |
+
fqdn==1.5.1
|
| 49 |
+
frozenlist==1.4.0
|
| 50 |
+
h11==0.14.0
|
| 51 |
+
httptools==0.6.0
|
| 52 |
+
humanfriendly==10.0
|
| 53 |
+
idna==3.4
|
| 54 |
+
importlib-resources==6.0.0
|
| 55 |
+
ipykernel==6.25.0
|
| 56 |
+
ipython==8.14.0
|
| 57 |
+
ipython-genutils==0.2.0
|
| 58 |
+
ipywidgets==8.1.0
|
| 59 |
+
isoduration==20.11.0
|
| 60 |
+
itsdangerous==2.1.2
|
| 61 |
+
jedi==0.18.2
|
| 62 |
+
Jinja2==3.1.2
|
| 63 |
+
joblib==1.3.1
|
| 64 |
+
json5==0.9.14
|
| 65 |
+
jsonpointer==2.4
|
| 66 |
+
jsonschema==4.18.6
|
| 67 |
+
jsonschema-specifications==2023.7.1
|
| 68 |
+
jupyter==1.0.0
|
| 69 |
+
jupyter-console==6.6.3
|
| 70 |
+
jupyter-events==0.7.0
|
| 71 |
+
jupyter-lsp==2.2.0
|
| 72 |
+
jupyter_client==8.3.0
|
| 73 |
+
jupyter_core==5.3.1
|
| 74 |
+
jupyter_server==2.7.0
|
| 75 |
+
jupyter_server_terminals==0.4.4
|
| 76 |
+
jupyterlab==4.0.4
|
| 77 |
+
jupyterlab-pygments==0.2.2
|
| 78 |
+
jupyterlab-widgets==3.0.8
|
| 79 |
+
jupyterlab_server==2.24.0
|
| 80 |
+
kiwisolver==1.4.4
|
| 81 |
+
langchain==0.0.247
|
| 82 |
+
langsmith==0.0.15
|
| 83 |
+
loguru==0.7.0
|
| 84 |
+
lxml==4.9.3
|
| 85 |
+
MarkupSafe==2.1.3
|
| 86 |
+
marshmallow==3.20.1
|
| 87 |
+
matplotlib==3.7.2
|
| 88 |
+
matplotlib-inline==0.1.6
|
| 89 |
+
mistune==3.0.1
|
| 90 |
+
monotonic==1.6
|
| 91 |
+
mpmath==1.3.0
|
| 92 |
+
multidict==6.0.4
|
| 93 |
+
mypy-extensions==1.0.0
|
| 94 |
+
nbclient==0.8.0
|
| 95 |
+
nbconvert==7.7.3
|
| 96 |
+
nbformat==5.9.2
|
| 97 |
+
nest-asyncio==1.5.7
|
| 98 |
+
notebook==7.0.2
|
| 99 |
+
notebook_shim==0.2.3
|
| 100 |
+
numexpr==2.8.4
|
| 101 |
+
numpy==1.25.1
|
| 102 |
+
onnxruntime==1.15.1
|
| 103 |
+
openai==0.27.8
|
| 104 |
+
openapi-schema-pydantic==1.2.4
|
| 105 |
+
overrides==7.3.1
|
| 106 |
+
packaging==23.1
|
| 107 |
+
pandas==1.5.3
|
| 108 |
+
pandasai==0.7.2
|
| 109 |
+
pandocfilters==1.5.0
|
| 110 |
+
parso==0.8.3
|
| 111 |
+
pexpect==4.8.0
|
| 112 |
+
pickleshare==0.7.5
|
| 113 |
+
Pillow==10.0.0
|
| 114 |
+
pinecone-client==2.2.2
|
| 115 |
+
pipreqs==0.4.13
|
| 116 |
+
platformdirs==3.10.0
|
| 117 |
+
plotly==5.15.0
|
| 118 |
+
posthog==3.0.1
|
| 119 |
+
premailer==3.10.0
|
| 120 |
+
prometheus-client==0.17.1
|
| 121 |
+
prompt-toolkit==3.0.39
|
| 122 |
+
protobuf==4.23.4
|
| 123 |
+
psutil==5.9.5
|
| 124 |
+
#psycopg2-binary==2.9.1
|
| 125 |
+
ptyprocess==0.7.0
|
| 126 |
+
pulsar-client==3.2.0
|
| 127 |
+
pure-eval==0.2.2
|
| 128 |
+
pycparser==2.21
|
| 129 |
+
pydantic==1.10.12
|
| 130 |
+
Pygments==2.15.1
|
| 131 |
+
pyparsing==3.0.9
|
| 132 |
+
PyPika==0.48.9
|
| 133 |
+
python-dateutil==2.8.2
|
| 134 |
+
python-dotenv==1.0.0
|
| 135 |
+
python-json-logger==2.0.7
|
| 136 |
+
pytz==2023.3
|
| 137 |
+
PyYAML==6.0.1
|
| 138 |
+
pyzmq==25.1.0
|
| 139 |
+
qtconsole==5.4.3
|
| 140 |
+
QtPy==2.3.1
|
| 141 |
+
referencing==0.30.2
|
| 142 |
+
regex==2023.6.3
|
| 143 |
+
requests==2.31.0
|
| 144 |
+
rfc3339-validator==0.1.4
|
| 145 |
+
rfc3986-validator==0.1.1
|
| 146 |
+
rpds-py==0.9.2
|
| 147 |
+
scikit-learn==1.3.0
|
| 148 |
+
scipy==1.11.1
|
| 149 |
+
Send2Trash==1.8.2
|
| 150 |
+
six==1.16.0
|
| 151 |
+
sniffio==1.3.0
|
| 152 |
+
soupsieve==2.4.1
|
| 153 |
+
SQLAlchemy==2.0.18
|
| 154 |
+
stack-data==0.6.2
|
| 155 |
+
starlette==0.27.0
|
| 156 |
+
sympy==1.12
|
| 157 |
+
tenacity==8.2.2
|
| 158 |
+
terminado==0.17.1
|
| 159 |
+
threadpoolctl==3.2.0
|
| 160 |
+
tiktoken==0.4.0
|
| 161 |
+
tinycss2==1.2.1
|
| 162 |
+
tokenizers==0.13.3
|
| 163 |
+
tornado==6.3.2
|
| 164 |
+
tqdm==4.65.0
|
| 165 |
+
traitlets==5.9.0
|
| 166 |
+
typing-inspect==0.9.0
|
| 167 |
+
typing_extensions==4.7.1
|
| 168 |
+
uri-template==1.3.0
|
| 169 |
+
urllib3==2.0.4
|
| 170 |
+
uvicorn==0.23.1
|
| 171 |
+
uvloop==0.17.0
|
| 172 |
+
watchfiles==0.19.0
|
| 173 |
+
wcwidth==0.2.6
|
| 174 |
+
webcolors==1.13
|
| 175 |
+
webencodings==0.5.1
|
| 176 |
+
websocket-client==1.6.1
|
| 177 |
+
websockets==11.0.3
|
| 178 |
+
Werkzeug==2.3.6
|
| 179 |
+
widgetsnbextension==4.0.8
|
| 180 |
+
yagmail==0.15.293
|
| 181 |
+
yarg==0.1.9
|
| 182 |
+
yarl==1.9.2
|
web_app/backend/app/__init__.py
CHANGED
|
@@ -2,11 +2,5 @@ from flask import Flask # Import the Flask module
|
|
| 2 |
from flask_cors import CORS # Import the CORS module
|
| 3 |
|
| 4 |
app = Flask(__name__) # Initialize a Flask web app
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
from app import chatbot, home, models # Import modules from the "app" package (assuming it's in the same directory)
|
| 8 |
-
|
| 9 |
-
# Use the app's context to perform actions related to the app
|
| 10 |
-
with app.app_context():
|
| 11 |
-
models.db.drop_all()
|
| 12 |
-
models.db.create_all()
|
|
|
|
| 2 |
from flask_cors import CORS # Import the CORS module
|
| 3 |
|
| 4 |
app = Flask(__name__) # Initialize a Flask web app
|
| 5 |
+
cors = CORS(app)
|
| 6 |
+
from app import chatbot_routes, home, models # Import modules from the "app" package (assuming it's in the same directory)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web_app/backend/app/answers_model.py
CHANGED
|
@@ -1,10 +1,75 @@
|
|
| 1 |
-
|
| 2 |
-
from
|
| 3 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
-
# Load
|
| 6 |
-
load_dotenv()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
-
# Initialize the OpenAI and PandasAI
|
| 9 |
-
llm = OpenAI(model = "gpt-3.5-turbo-16k", temperature = 0.0)
|
| 10 |
-
pandas_ai = PandasAI(llm, conversational = True)
|
|
|
|
| 1 |
+
import pinecone
|
| 2 |
+
from dotenv import load_dotenv, find_dotenv
|
| 3 |
+
from langchain.embeddings.openai import OpenAIEmbeddings
|
| 4 |
+
from langchain.memory import ConversationBufferMemory
|
| 5 |
+
from langchain.vectorstores import Pinecone
|
| 6 |
+
from langchain.chat_models import ChatOpenAI
|
| 7 |
+
from langchain.chains import RetrievalQA
|
| 8 |
+
from langchain import PromptTemplate
|
| 9 |
|
| 10 |
+
# Load environment variables
|
| 11 |
+
load_dotenv(find_dotenv())
|
| 12 |
+
|
| 13 |
+
# Setting up embeddings
|
| 14 |
+
embedder = OpenAIEmbeddings()
|
| 15 |
+
|
| 16 |
+
# Setting up the vectorstore
|
| 17 |
+
pinecone.init(environment="us-west4-gcp")
|
| 18 |
+
index = pinecone.Index('seai-website')
|
| 19 |
+
|
| 20 |
+
#Set up the retriever
|
| 21 |
+
vectorstore = Pinecone(index, embedder.embed_query, 'text')
|
| 22 |
+
|
| 23 |
+
# Setting up the llm
|
| 24 |
+
llm = ChatOpenAI(temperature=0.0)
|
| 25 |
+
|
| 26 |
+
# Setting up the prompt template
|
| 27 |
+
template = """
|
| 28 |
+
Use the following context (delimited by <ctx></ctx>) and the chat history (delimited by <hs></hs>) to answer the question:
|
| 29 |
+
------
|
| 30 |
+
<ctx>
|
| 31 |
+
{context}
|
| 32 |
+
</ctx>
|
| 33 |
+
------
|
| 34 |
+
<hs>
|
| 35 |
+
{history}
|
| 36 |
+
</hs>
|
| 37 |
+
------
|
| 38 |
+
{question}
|
| 39 |
+
Answer:
|
| 40 |
+
"""
|
| 41 |
+
prompt = PromptTemplate(
|
| 42 |
+
input_variables=["history", "context", "question"],
|
| 43 |
+
template=template,
|
| 44 |
+
)
|
| 45 |
+
|
| 46 |
+
# Setting up the memory
|
| 47 |
+
memory = ConversationBufferMemory(memory_key="history", input_key="question")
|
| 48 |
+
|
| 49 |
+
# Setting up the QA chain
|
| 50 |
+
qa = RetrievalQA.from_chain_type(
|
| 51 |
+
llm=ChatOpenAI(),
|
| 52 |
+
chain_type='stuff',
|
| 53 |
+
retriever=vectorstore.as_retriever(),
|
| 54 |
+
verbose=True,
|
| 55 |
+
chain_type_kwargs={
|
| 56 |
+
"verbose": True,
|
| 57 |
+
"prompt": prompt,
|
| 58 |
+
"memory": memory
|
| 59 |
+
}
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
def generate_question_response(query: str) -> str:
|
| 63 |
+
return qa.run(query)
|
| 64 |
+
|
| 65 |
+
if __name__ == "__main__":
|
| 66 |
+
# Sample query
|
| 67 |
+
test_query = "What is the capital of France?"
|
| 68 |
+
|
| 69 |
+
# Generate a response using the model
|
| 70 |
+
response = generate_question_response(test_query)
|
| 71 |
+
|
| 72 |
+
# Print the query and its response
|
| 73 |
+
print(f"Query: {test_query}")
|
| 74 |
+
print(f"Response: {response}")
|
| 75 |
|
|
|
|
|
|
|
|
|
web_app/backend/app/{chatbot.py → chatbot_routes.py}
RENAMED
|
@@ -1,40 +1,38 @@
|
|
| 1 |
from app import app
|
| 2 |
from flask import send_from_directory, jsonify, request
|
| 3 |
-
import pandas as pd
|
| 4 |
-
from pandasai import PandasAI
|
| 5 |
-
from pandasai.llm.openai import OpenAI
|
| 6 |
-
from os import environ
|
| 7 |
import os
|
| 8 |
-
from dotenv import load_dotenv
|
| 9 |
from app.question_model import generate_response
|
| 10 |
-
from app.answers_model import
|
| 11 |
-
|
| 12 |
-
|
| 13 |
|
| 14 |
# Load the environment variables
|
| 15 |
-
load_dotenv()
|
| 16 |
|
| 17 |
-
|
| 18 |
-
DATA_PATH = os.path.join(CURRENT_DIRECTORY, 'data', 'BER_Small.csv')
|
| 19 |
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
# Route to handle user prompt questions
|
| 23 |
@app.route('/sendText', methods=['POST'])
|
| 24 |
def handle_text():
|
| 25 |
try:
|
| 26 |
data = request.get_json()
|
| 27 |
-
print(data)
|
| 28 |
print(f'Received text: {data["text"]}')
|
| 29 |
|
| 30 |
-
#
|
| 31 |
-
output =
|
| 32 |
print(f'Output: {output}')
|
| 33 |
|
| 34 |
return jsonify(message='Received!', output=output), 200
|
| 35 |
except Exception as e:
|
| 36 |
-
|
| 37 |
-
return jsonify(message='Error occurred', error=str(e), type=str(type(e))), 500
|
| 38 |
|
| 39 |
# Route to handle suggested questions
|
| 40 |
@app.route('/sendQuestions', methods=['POST'])
|
|
@@ -58,5 +56,57 @@ def handle_questions():
|
|
| 58 |
|
| 59 |
return jsonify(message='Received!', output=output), 200
|
| 60 |
except Exception as e:
|
| 61 |
-
|
| 62 |
-
return jsonify(message='Error occurred', error=str(e), type=str(type(e))), 500
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from app import app
|
| 2 |
from flask import send_from_directory, jsonify, request
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import os
|
| 4 |
+
from dotenv import load_dotenv, find_dotenv
|
| 5 |
from app.question_model import generate_response
|
| 6 |
+
from app.answers_model import generate_question_response
|
| 7 |
+
from fpdf import FPDF
|
| 8 |
+
import yagmail
|
| 9 |
|
| 10 |
# Load the environment variables
|
| 11 |
+
load_dotenv(find_dotenv())
|
| 12 |
|
| 13 |
+
print(f"Loading .env from: {find_dotenv()}")
|
|
|
|
| 14 |
|
| 15 |
+
# Add a route to help with error handling
|
| 16 |
+
@app.errorhandler(500)
|
| 17 |
+
def internal_error(error):
|
| 18 |
+
app.logger.error("Server Error: %s", error)
|
| 19 |
+
return jsonify(message="Internal Server Error"), 500
|
| 20 |
|
| 21 |
# Route to handle user prompt questions
|
| 22 |
@app.route('/sendText', methods=['POST'])
|
| 23 |
def handle_text():
|
| 24 |
try:
|
| 25 |
data = request.get_json()
|
|
|
|
| 26 |
print(f'Received text: {data["text"]}')
|
| 27 |
|
| 28 |
+
# Use the new model to get the output
|
| 29 |
+
output = generate_question_response(data["text"])
|
| 30 |
print(f'Output: {output}')
|
| 31 |
|
| 32 |
return jsonify(message='Received!', output=output), 200
|
| 33 |
except Exception as e:
|
| 34 |
+
app.logger.error(f"Error occurred during sendText: {e}")
|
| 35 |
+
return jsonify(message='Error occurred during sendText', error=str(e), type=str(type(e))), 500
|
| 36 |
|
| 37 |
# Route to handle suggested questions
|
| 38 |
@app.route('/sendQuestions', methods=['POST'])
|
|
|
|
| 56 |
|
| 57 |
return jsonify(message='Received!', output=output), 200
|
| 58 |
except Exception as e:
|
| 59 |
+
app.logger.error(f"Error occurred during sendText: {e}")
|
| 60 |
+
return jsonify(message='Error occurred during sendText', error=str(e), type=str(type(e))), 500
|
| 61 |
+
|
| 62 |
+
@app.route('/exportChat', methods=['POST'])
|
| 63 |
+
def export_chat():
|
| 64 |
+
email = request.json.get('email')
|
| 65 |
+
chat_history = request.json.get('chatHistory')
|
| 66 |
+
|
| 67 |
+
# Convert chatHistory to PDF
|
| 68 |
+
pdf_file = create_pdf_from_chat_history(chat_history)
|
| 69 |
+
|
| 70 |
+
# Send the PDF to the email
|
| 71 |
+
send_pdf_to_email(email, pdf_file)
|
| 72 |
+
|
| 73 |
+
return jsonify({"message": f"Email sent to: {email}"}), 200
|
| 74 |
+
|
| 75 |
+
def create_pdf_from_chat_history(chat_history):
|
| 76 |
+
# Initialize the Python PDF library, FPDF
|
| 77 |
+
pdf = FPDF()
|
| 78 |
+
|
| 79 |
+
# Add a new page to the PDF
|
| 80 |
+
pdf.add_page()
|
| 81 |
+
|
| 82 |
+
# Set the font for the page (Arial, size 12)
|
| 83 |
+
pdf.set_font("Arial", size = 12)
|
| 84 |
+
|
| 85 |
+
# Loop through the chat history
|
| 86 |
+
for chat in chat_history:
|
| 87 |
+
# Add each question and answer to the PDF as a multiline text box
|
| 88 |
+
pdf.multi_cell(190, 10, f"Q: {chat['question']}\nA: {chat['response']}")
|
| 89 |
+
|
| 90 |
+
# Define the name of the generated PDF file
|
| 91 |
+
filename = "chat_history.pdf"
|
| 92 |
+
|
| 93 |
+
# Generate the PDF and save it to a file
|
| 94 |
+
pdf.output(name=filename, dest='F').encode("latin1")
|
| 95 |
+
|
| 96 |
+
# Return the filename for later usage
|
| 97 |
+
return filename
|
| 98 |
+
|
| 99 |
+
def send_pdf_to_email(email, pdf_file):
|
| 100 |
+
# Initialize yagmail client with email and password
|
| 101 |
+
yag = yagmail.SMTP(user="leo.defig", password="dummyPASSWORD123")
|
| 102 |
+
|
| 103 |
+
# Use yagmail to send an email with the PDF file as an attachment
|
| 104 |
+
yag.send(
|
| 105 |
+
to=email,
|
| 106 |
+
subject="Your Chat History",
|
| 107 |
+
contents="Please find attached the chat history.",
|
| 108 |
+
attachments=pdf_file,
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
# After sending the email, delete the PDF file from local storage
|
| 112 |
+
os.remove(pdf_file)
|
web_app/backend/app/data/.gitkeep
ADDED
|
File without changes
|
web_app/backend/app/data/{BER_Small.csv → BER/BER_Small.csv}
RENAMED
|
File without changes
|
web_app/backend/app/data/chain.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"memory": null,
|
| 3 |
+
"verbose": false,
|
| 4 |
+
"tags": null,
|
| 5 |
+
"metadata": null,
|
| 6 |
+
"prompt": {
|
| 7 |
+
"input_variables": [
|
| 8 |
+
"input"
|
| 9 |
+
],
|
| 10 |
+
"output_parser": null,
|
| 11 |
+
"partial_variables": {},
|
| 12 |
+
"messages": [
|
| 13 |
+
{
|
| 14 |
+
"content": "You are a world class algorithm for extracting information in structured formats.",
|
| 15 |
+
"additional_kwargs": {}
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"content": "Use the given format to extract information from the following input:",
|
| 19 |
+
"additional_kwargs": {},
|
| 20 |
+
"example": false
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"prompt": {
|
| 24 |
+
"input_variables": [
|
| 25 |
+
"input"
|
| 26 |
+
],
|
| 27 |
+
"output_parser": null,
|
| 28 |
+
"partial_variables": {},
|
| 29 |
+
"template": "{input}",
|
| 30 |
+
"template_format": "f-string",
|
| 31 |
+
"validate_template": true,
|
| 32 |
+
"_type": "prompt"
|
| 33 |
+
},
|
| 34 |
+
"additional_kwargs": {}
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"content": "Tips: Make sure to answer in the correct format",
|
| 38 |
+
"additional_kwargs": {},
|
| 39 |
+
"example": false
|
| 40 |
+
}
|
| 41 |
+
],
|
| 42 |
+
"_type": "chat"
|
| 43 |
+
},
|
| 44 |
+
"llm": {
|
| 45 |
+
"model_name": "gpt-3.5-turbo",
|
| 46 |
+
"model": "gpt-3.5-turbo",
|
| 47 |
+
"request_timeout": null,
|
| 48 |
+
"max_tokens": null,
|
| 49 |
+
"stream": false,
|
| 50 |
+
"n": 1,
|
| 51 |
+
"temperature": 0.0,
|
| 52 |
+
"_type": "openai-chat"
|
| 53 |
+
},
|
| 54 |
+
"output_key": "function",
|
| 55 |
+
"output_parser": {
|
| 56 |
+
"args_only": true,
|
| 57 |
+
"pydantic_schema":
|
web_app/backend/app/data/dropped_features.txt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"ThirdEnerProdDelivered","UvalueDoor","DeliveredEnergyPumpsFans","SecondFloorHeight",
|
| 2 |
+
"gsdHSSupplSystemEff","SecondPartLTotalContribution","FirstEnerProdC02EmissionFactor","FirstEnerProdDeliveredLow",
|
| 3 |
+
"LowEnergyLightingPercent","C02SupplementaryWater","FirstFloorArea","ZeroLossCollectorEff",
|
| 4 |
+
"FirstEnerConsumedDelivered","ThirdFloorHeight","InsulationThickness","ThirdWallUValue",
|
| 5 |
+
"SecondFloorArea","FanPowerManuDeclaredValue","CHPHeatEff","GroundFloorUValue",
|
| 6 |
+
"CollectorHeatLossCoEff","UValueFloor","WHMainSystemEff","PrimaryEnergySupplementaryWater",
|
| 7 |
+
"ThirdFloorArea","WHEffAdjFactor","UValueRoof","PermeabilityTestResult",
|
| 8 |
+
"TotalC02Emissions","FirstHeatGenPlantEff","ThirdPercentageHeat","prob_smarea_error_0corr",
|
| 9 |
+
"PercentageDraughtStripped","CHPUnitHeatFraction","SecondPercentageHeat","FirstFloorHeight",
|
| 10 |
+
"TotalPrimaryEnergyFact","DoorArea","HSSupplSystemEff","TempFactorUnadj",
|
| 11 |
+
"RenewEPren","SecondHeatGenPlantEff","CombiBoilerAddLoss","SolarStorageVolume",
|
| 12 |
+
"ThirdHeatGenPlantEff","HSEffAdjFactor","FirstWallUValue","HeatExchangerEff",
|
| 13 |
+
"ThirdPartLTotalContribution","DeliveredEnergySecondarySpace","AnnualSolarRadiation","FirstPercentageHeat",
|
| 14 |
+
"DeclaredLossFactor","WaterStorageVolume","RoomInRoofArea","FirstPartLTotalContribution",
|
| 15 |
+
"SecondWallUValue","SecondEnerProdDelivered","RER","ThermalBridgingFactor"
|
web_app/backend/app/data/energy_modelling.ipynb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
web_app/backend/app/data/pinecone_tut.ipynb
DELETED
|
@@ -1,370 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"cells": [
|
| 3 |
-
{
|
| 4 |
-
"cell_type": "code",
|
| 5 |
-
"execution_count": 13,
|
| 6 |
-
"metadata": {},
|
| 7 |
-
"outputs": [],
|
| 8 |
-
"source": [
|
| 9 |
-
"import pinecone \n",
|
| 10 |
-
"import pandas as pd\n",
|
| 11 |
-
"\n",
|
| 12 |
-
"api_key = \"22e9da2e-64bc-47c6-b4a2-d0d220210aff\"\n",
|
| 13 |
-
"pinecone.init(api_key=api_key, environment='us-west4-gcp')"
|
| 14 |
-
]
|
| 15 |
-
},
|
| 16 |
-
{
|
| 17 |
-
"cell_type": "code",
|
| 18 |
-
"execution_count": 10,
|
| 19 |
-
"metadata": {},
|
| 20 |
-
"outputs": [],
|
| 21 |
-
"source": [
|
| 22 |
-
"#Giving our index a name\n",
|
| 23 |
-
"index_name = \"lumin-question-data\"\n",
|
| 24 |
-
"\n",
|
| 25 |
-
"#Delete index if it already exists\n",
|
| 26 |
-
"if index_name in pinecone.list_indexes():\n",
|
| 27 |
-
" pinecone.delete_index(index_name)"
|
| 28 |
-
]
|
| 29 |
-
},
|
| 30 |
-
{
|
| 31 |
-
"cell_type": "code",
|
| 32 |
-
"execution_count": 11,
|
| 33 |
-
"metadata": {},
|
| 34 |
-
"outputs": [],
|
| 35 |
-
"source": [
|
| 36 |
-
"# Create Pinecone index\n",
|
| 37 |
-
"dimensions = 3\n",
|
| 38 |
-
"pinecone.create_index(name = index_name, dimension = dimensions, metric = 'cosine', shards = 1)"
|
| 39 |
-
]
|
| 40 |
-
},
|
| 41 |
-
{
|
| 42 |
-
"cell_type": "code",
|
| 43 |
-
"execution_count": 12,
|
| 44 |
-
"metadata": {},
|
| 45 |
-
"outputs": [],
|
| 46 |
-
"source": [
|
| 47 |
-
"index = pinecone.Index(index_name=index_name)"
|
| 48 |
-
]
|
| 49 |
-
},
|
| 50 |
-
{
|
| 51 |
-
"cell_type": "code",
|
| 52 |
-
"execution_count": 16,
|
| 53 |
-
"metadata": {},
|
| 54 |
-
"outputs": [
|
| 55 |
-
{
|
| 56 |
-
"data": {
|
| 57 |
-
"text/html": [
|
| 58 |
-
"<div>\n",
|
| 59 |
-
"<style scoped>\n",
|
| 60 |
-
" .dataframe tbody tr th:only-of-type {\n",
|
| 61 |
-
" vertical-align: middle;\n",
|
| 62 |
-
" }\n",
|
| 63 |
-
"\n",
|
| 64 |
-
" .dataframe tbody tr th {\n",
|
| 65 |
-
" vertical-align: top;\n",
|
| 66 |
-
" }\n",
|
| 67 |
-
"\n",
|
| 68 |
-
" .dataframe thead th {\n",
|
| 69 |
-
" text-align: right;\n",
|
| 70 |
-
" }\n",
|
| 71 |
-
"</style>\n",
|
| 72 |
-
"<table border=\"1\" class=\"dataframe\">\n",
|
| 73 |
-
" <thead>\n",
|
| 74 |
-
" <tr style=\"text-align: right;\">\n",
|
| 75 |
-
" <th></th>\n",
|
| 76 |
-
" <th>id</th>\n",
|
| 77 |
-
" <th>vector</th>\n",
|
| 78 |
-
" </tr>\n",
|
| 79 |
-
" </thead>\n",
|
| 80 |
-
" <tbody>\n",
|
| 81 |
-
" <tr>\n",
|
| 82 |
-
" <th>0</th>\n",
|
| 83 |
-
" <td>A</td>\n",
|
| 84 |
-
" <td>[0.1, 0.2, 0.3]</td>\n",
|
| 85 |
-
" </tr>\n",
|
| 86 |
-
" <tr>\n",
|
| 87 |
-
" <th>1</th>\n",
|
| 88 |
-
" <td>B</td>\n",
|
| 89 |
-
" <td>[0.2, 0.3, 0.4]</td>\n",
|
| 90 |
-
" </tr>\n",
|
| 91 |
-
" <tr>\n",
|
| 92 |
-
" <th>2</th>\n",
|
| 93 |
-
" <td>C</td>\n",
|
| 94 |
-
" <td>[0.3, 0.4, 0.5]</td>\n",
|
| 95 |
-
" </tr>\n",
|
| 96 |
-
" <tr>\n",
|
| 97 |
-
" <th>3</th>\n",
|
| 98 |
-
" <td>D</td>\n",
|
| 99 |
-
" <td>[0.4, 0.5, 0.6]</td>\n",
|
| 100 |
-
" </tr>\n",
|
| 101 |
-
" <tr>\n",
|
| 102 |
-
" <th>4</th>\n",
|
| 103 |
-
" <td>E</td>\n",
|
| 104 |
-
" <td>[0.5, 0.6, 0.7]</td>\n",
|
| 105 |
-
" </tr>\n",
|
| 106 |
-
" </tbody>\n",
|
| 107 |
-
"</table>\n",
|
| 108 |
-
"</div>"
|
| 109 |
-
],
|
| 110 |
-
"text/plain": [
|
| 111 |
-
" id vector\n",
|
| 112 |
-
"0 A [0.1, 0.2, 0.3]\n",
|
| 113 |
-
"1 B [0.2, 0.3, 0.4]\n",
|
| 114 |
-
"2 C [0.3, 0.4, 0.5]\n",
|
| 115 |
-
"3 D [0.4, 0.5, 0.6]\n",
|
| 116 |
-
"4 E [0.5, 0.6, 0.7]"
|
| 117 |
-
]
|
| 118 |
-
},
|
| 119 |
-
"execution_count": 16,
|
| 120 |
-
"metadata": {},
|
| 121 |
-
"output_type": "execute_result"
|
| 122 |
-
}
|
| 123 |
-
],
|
| 124 |
-
"source": [
|
| 125 |
-
"#Load the dataframe\n",
|
| 126 |
-
"df = pd.DataFrame(\n",
|
| 127 |
-
" data={\n",
|
| 128 |
-
" \"id\": [\"A\", \"B\", \"C\", \"D\", \"E\"],\n",
|
| 129 |
-
" \"vector\": [\n",
|
| 130 |
-
" [0.1, 0.2, 0.3],\n",
|
| 131 |
-
" [0.2, 0.3, 0.4],\n",
|
| 132 |
-
" [0.3, 0.4, 0.5],\n",
|
| 133 |
-
" [0.4, 0.5, 0.6],\n",
|
| 134 |
-
" [0.5, 0.6, 0.7]]\n",
|
| 135 |
-
" }\n",
|
| 136 |
-
")\n",
|
| 137 |
-
" \n",
|
| 138 |
-
"df"
|
| 139 |
-
]
|
| 140 |
-
},
|
| 141 |
-
{
|
| 142 |
-
"cell_type": "code",
|
| 143 |
-
"execution_count": 17,
|
| 144 |
-
"metadata": {},
|
| 145 |
-
"outputs": [
|
| 146 |
-
{
|
| 147 |
-
"data": {
|
| 148 |
-
"text/plain": [
|
| 149 |
-
"{'upserted_count': 5}"
|
| 150 |
-
]
|
| 151 |
-
},
|
| 152 |
-
"execution_count": 17,
|
| 153 |
-
"metadata": {},
|
| 154 |
-
"output_type": "execute_result"
|
| 155 |
-
}
|
| 156 |
-
],
|
| 157 |
-
"source": [
|
| 158 |
-
"index.upsert(vectors=zip(df['id'], df['vector']))"
|
| 159 |
-
]
|
| 160 |
-
},
|
| 161 |
-
{
|
| 162 |
-
"cell_type": "code",
|
| 163 |
-
"execution_count": 18,
|
| 164 |
-
"metadata": {},
|
| 165 |
-
"outputs": [
|
| 166 |
-
{
|
| 167 |
-
"data": {
|
| 168 |
-
"text/plain": [
|
| 169 |
-
"{'dimension': 3,\n",
|
| 170 |
-
" 'index_fullness': 0.0,\n",
|
| 171 |
-
" 'namespaces': {'': {'vector_count': 5}},\n",
|
| 172 |
-
" 'total_vector_count': 5}"
|
| 173 |
-
]
|
| 174 |
-
},
|
| 175 |
-
"execution_count": 18,
|
| 176 |
-
"metadata": {},
|
| 177 |
-
"output_type": "execute_result"
|
| 178 |
-
}
|
| 179 |
-
],
|
| 180 |
-
"source": [
|
| 181 |
-
"index.describe_index_stats()"
|
| 182 |
-
]
|
| 183 |
-
},
|
| 184 |
-
{
|
| 185 |
-
"cell_type": "code",
|
| 186 |
-
"execution_count": 19,
|
| 187 |
-
"metadata": {},
|
| 188 |
-
"outputs": [
|
| 189 |
-
{
|
| 190 |
-
"data": {
|
| 191 |
-
"text/plain": [
|
| 192 |
-
"{'results': [{'matches': [{'id': 'E',\n",
|
| 193 |
-
" 'score': 0.990867436,\n",
|
| 194 |
-
" 'values': [0.5, 0.6, 0.7]},\n",
|
| 195 |
-
" {'id': 'D',\n",
|
| 196 |
-
" 'score': 0.986927509,\n",
|
| 197 |
-
" 'values': [0.4, 0.5, 0.6]}],\n",
|
| 198 |
-
" 'namespace': ''}]}"
|
| 199 |
-
]
|
| 200 |
-
},
|
| 201 |
-
"execution_count": 19,
|
| 202 |
-
"metadata": {},
|
| 203 |
-
"output_type": "execute_result"
|
| 204 |
-
}
|
| 205 |
-
],
|
| 206 |
-
"source": [
|
| 207 |
-
"index.query(\n",
|
| 208 |
-
" queries=[[2,2,2]],\n",
|
| 209 |
-
" top_k=2,\n",
|
| 210 |
-
" include_values=True\n",
|
| 211 |
-
")"
|
| 212 |
-
]
|
| 213 |
-
},
|
| 214 |
-
{
|
| 215 |
-
"cell_type": "code",
|
| 216 |
-
"execution_count": 20,
|
| 217 |
-
"metadata": {},
|
| 218 |
-
"outputs": [
|
| 219 |
-
{
|
| 220 |
-
"data": {
|
| 221 |
-
"text/plain": [
|
| 222 |
-
"['lumin-question-data']"
|
| 223 |
-
]
|
| 224 |
-
},
|
| 225 |
-
"execution_count": 20,
|
| 226 |
-
"metadata": {},
|
| 227 |
-
"output_type": "execute_result"
|
| 228 |
-
}
|
| 229 |
-
],
|
| 230 |
-
"source": [
|
| 231 |
-
"pinecone.list_indexes()"
|
| 232 |
-
]
|
| 233 |
-
},
|
| 234 |
-
{
|
| 235 |
-
"cell_type": "code",
|
| 236 |
-
"execution_count": 22,
|
| 237 |
-
"metadata": {},
|
| 238 |
-
"outputs": [
|
| 239 |
-
{
|
| 240 |
-
"data": {
|
| 241 |
-
"text/plain": [
|
| 242 |
-
"IndexDescription(name='lumin-question-data', metric='cosine', replicas=1, dimension=3.0, shards=1, pods=1, pod_type='p1.x1', status={'ready': True, 'state': 'Ready'}, metadata_config=None, source_collection='')"
|
| 243 |
-
]
|
| 244 |
-
},
|
| 245 |
-
"execution_count": 22,
|
| 246 |
-
"metadata": {},
|
| 247 |
-
"output_type": "execute_result"
|
| 248 |
-
}
|
| 249 |
-
],
|
| 250 |
-
"source": [
|
| 251 |
-
"pinecone.describe_index(\"lumin-question-data\")"
|
| 252 |
-
]
|
| 253 |
-
},
|
| 254 |
-
{
|
| 255 |
-
"cell_type": "code",
|
| 256 |
-
"execution_count": 30,
|
| 257 |
-
"metadata": {},
|
| 258 |
-
"outputs": [],
|
| 259 |
-
"source": [
|
| 260 |
-
"import random \n",
|
| 261 |
-
"\n",
|
| 262 |
-
"ids = [\"a\", \"b\", \"c\", \"d\", \"e\"]\n",
|
| 263 |
-
"vecs = [[random.random() for _ in range(3)] for _ in range(len(ids))]"
|
| 264 |
-
]
|
| 265 |
-
},
|
| 266 |
-
{
|
| 267 |
-
"cell_type": "code",
|
| 268 |
-
"execution_count": 31,
|
| 269 |
-
"metadata": {},
|
| 270 |
-
"outputs": [
|
| 271 |
-
{
|
| 272 |
-
"data": {
|
| 273 |
-
"text/plain": [
|
| 274 |
-
"[[0.5582998198744755, 0.01804592916533032, 0.06927366246378208],\n",
|
| 275 |
-
" [0.19606955177481333, 0.9497032707066528, 0.08713643524214854],\n",
|
| 276 |
-
" [0.06740320859564719, 0.5796438198602569, 0.2521688997698266],\n",
|
| 277 |
-
" [0.08410319865807259, 0.0442919355259529, 0.6309807322716778],\n",
|
| 278 |
-
" [0.7629393424814093, 0.02832065828346908, 0.6747540161958138]]"
|
| 279 |
-
]
|
| 280 |
-
},
|
| 281 |
-
"execution_count": 31,
|
| 282 |
-
"metadata": {},
|
| 283 |
-
"output_type": "execute_result"
|
| 284 |
-
}
|
| 285 |
-
],
|
| 286 |
-
"source": [
|
| 287 |
-
"vecs"
|
| 288 |
-
]
|
| 289 |
-
},
|
| 290 |
-
{
|
| 291 |
-
"cell_type": "code",
|
| 292 |
-
"execution_count": 32,
|
| 293 |
-
"metadata": {},
|
| 294 |
-
"outputs": [],
|
| 295 |
-
"source": [
|
| 296 |
-
"index = pinecone.Index(\"lumin-question-data\")"
|
| 297 |
-
]
|
| 298 |
-
},
|
| 299 |
-
{
|
| 300 |
-
"cell_type": "code",
|
| 301 |
-
"execution_count": 33,
|
| 302 |
-
"metadata": {},
|
| 303 |
-
"outputs": [
|
| 304 |
-
{
|
| 305 |
-
"data": {
|
| 306 |
-
"text/plain": [
|
| 307 |
-
"{'upserted_count': 5}"
|
| 308 |
-
]
|
| 309 |
-
},
|
| 310 |
-
"execution_count": 33,
|
| 311 |
-
"metadata": {},
|
| 312 |
-
"output_type": "execute_result"
|
| 313 |
-
}
|
| 314 |
-
],
|
| 315 |
-
"source": [
|
| 316 |
-
"index.upsert(vectors=zip(ids, vecs))"
|
| 317 |
-
]
|
| 318 |
-
},
|
| 319 |
-
{
|
| 320 |
-
"cell_type": "code",
|
| 321 |
-
"execution_count": 36,
|
| 322 |
-
"metadata": {},
|
| 323 |
-
"outputs": [
|
| 324 |
-
{
|
| 325 |
-
"ename": "AttributeError",
|
| 326 |
-
"evalue": "'Index' object has no attribute 'delete_index'",
|
| 327 |
-
"output_type": "error",
|
| 328 |
-
"traceback": [
|
| 329 |
-
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
| 330 |
-
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
|
| 331 |
-
"Cell \u001b[0;32mIn[36], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m index\u001b[39m.\u001b[39;49mdelete_index(\u001b[39m\"\u001b[39m\u001b[39mlumin-question-data\u001b[39m\u001b[39m\"\u001b[39m)\n",
|
| 332 |
-
"\u001b[0;31mAttributeError\u001b[0m: 'Index' object has no attribute 'delete_index'"
|
| 333 |
-
]
|
| 334 |
-
}
|
| 335 |
-
],
|
| 336 |
-
"source": [
|
| 337 |
-
"index.delete_index(\"lumin-question-data\")"
|
| 338 |
-
]
|
| 339 |
-
},
|
| 340 |
-
{
|
| 341 |
-
"cell_type": "code",
|
| 342 |
-
"execution_count": null,
|
| 343 |
-
"metadata": {},
|
| 344 |
-
"outputs": [],
|
| 345 |
-
"source": []
|
| 346 |
-
}
|
| 347 |
-
],
|
| 348 |
-
"metadata": {
|
| 349 |
-
"kernelspec": {
|
| 350 |
-
"display_name": "Python 3",
|
| 351 |
-
"language": "python",
|
| 352 |
-
"name": "python3"
|
| 353 |
-
},
|
| 354 |
-
"language_info": {
|
| 355 |
-
"codemirror_mode": {
|
| 356 |
-
"name": "ipython",
|
| 357 |
-
"version": 3
|
| 358 |
-
},
|
| 359 |
-
"file_extension": ".py",
|
| 360 |
-
"mimetype": "text/x-python",
|
| 361 |
-
"name": "python",
|
| 362 |
-
"nbconvert_exporter": "python",
|
| 363 |
-
"pygments_lexer": "ipython3",
|
| 364 |
-
"version": "3.11.4"
|
| 365 |
-
},
|
| 366 |
-
"orig_nbformat": 4
|
| 367 |
-
},
|
| 368 |
-
"nbformat": 4,
|
| 369 |
-
"nbformat_minor": 2
|
| 370 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web_app/backend/app/models.py
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
-
from flask_sqlalchemy import SQLAlchemy
|
| 2 |
-
from app import app
|
| 3 |
|
| 4 |
#Connect to the database
|
| 5 |
-
app.config["SQLALCHEMY_DATABASE_URI"] = ("postgresql://luminlab:Lumin#adapt2023@194.29.101.181:5433/luminlab_db")
|
| 6 |
|
| 7 |
-
db = SQLAlchemy(app)
|
| 8 |
|
| 9 |
-
class User(db.Model):
|
| 10 |
__tablename__ = 'user'
|
| 11 |
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
| 12 |
first_name = db.Column(db.String(50), nullable=False)
|
|
@@ -29,4 +29,4 @@ class User(db.Model):
|
|
| 29 |
|
| 30 |
# create an application context
|
| 31 |
with app.app_context():
|
| 32 |
-
db.create_all()
|
|
|
|
| 1 |
+
#from flask_sqlalchemy import SQLAlchemy
|
| 2 |
+
#from app import app
|
| 3 |
|
| 4 |
#Connect to the database
|
| 5 |
+
#app.config["SQLALCHEMY_DATABASE_URI"] = ("postgresql://luminlab:Lumin#adapt2023@194.29.101.181:5433/luminlab_db")
|
| 6 |
|
| 7 |
+
#db = SQLAlchemy(app)
|
| 8 |
|
| 9 |
+
"""class User(db.Model):
|
| 10 |
__tablename__ = 'user'
|
| 11 |
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
| 12 |
first_name = db.Column(db.String(50), nullable=False)
|
|
|
|
| 29 |
|
| 30 |
# create an application context
|
| 31 |
with app.app_context():
|
| 32 |
+
db.create_all()"""
|
web_app/backend/app/pinecone_q.ipynb
DELETED
|
@@ -1,133 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"cells": [
|
| 3 |
-
{
|
| 4 |
-
"cell_type": "code",
|
| 5 |
-
"execution_count": 1,
|
| 6 |
-
"metadata": {},
|
| 7 |
-
"outputs": [
|
| 8 |
-
{
|
| 9 |
-
"name": "stderr",
|
| 10 |
-
"output_type": "stream",
|
| 11 |
-
"text": [
|
| 12 |
-
"/opt/homebrew/lib/python3.11/site-packages/pinecone/index.py:4: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
|
| 13 |
-
" from tqdm.autonotebook import tqdm\n"
|
| 14 |
-
]
|
| 15 |
-
},
|
| 16 |
-
{
|
| 17 |
-
"data": {
|
| 18 |
-
"text/plain": [
|
| 19 |
-
"True"
|
| 20 |
-
]
|
| 21 |
-
},
|
| 22 |
-
"execution_count": 1,
|
| 23 |
-
"metadata": {},
|
| 24 |
-
"output_type": "execute_result"
|
| 25 |
-
}
|
| 26 |
-
],
|
| 27 |
-
"source": [
|
| 28 |
-
"from langchain.document_loaders.csv_loader import CSVLoader\n",
|
| 29 |
-
"from langchain.vectorstores import FAISS\n",
|
| 30 |
-
"from langchain.embeddings.openai import OpenAIEmbeddings\n",
|
| 31 |
-
"from langchain.prompts import PromptTemplate\n",
|
| 32 |
-
"from langchain.chat_models import ChatOpenAI\n",
|
| 33 |
-
"from langchain.chains import LLMChain\n",
|
| 34 |
-
"from dotenv import load_dotenv\n",
|
| 35 |
-
"import pandas as pd\n",
|
| 36 |
-
"\n",
|
| 37 |
-
"import pinecone\n",
|
| 38 |
-
"\n",
|
| 39 |
-
"\n",
|
| 40 |
-
"\n",
|
| 41 |
-
"load_dotenv()"
|
| 42 |
-
]
|
| 43 |
-
},
|
| 44 |
-
{
|
| 45 |
-
"cell_type": "code",
|
| 46 |
-
"execution_count": 4,
|
| 47 |
-
"metadata": {},
|
| 48 |
-
"outputs": [],
|
| 49 |
-
"source": [
|
| 50 |
-
"#set the file path\n",
|
| 51 |
-
"file_path = \"/Users/leo/Programming/luminlab/web_app/backend/app/data/BER_Small.csv\"\n",
|
| 52 |
-
"df = pd.read_csv(file_path, encoding='ISO-8859-1', low_memory=False)\n",
|
| 53 |
-
"\n",
|
| 54 |
-
"#load the data\n",
|
| 55 |
-
"loader = CSVLoader(file_path=file_path)\n",
|
| 56 |
-
"documents = loader.load()\n",
|
| 57 |
-
"embeddings = OpenAIEmbeddings()\n",
|
| 58 |
-
"\n",
|
| 59 |
-
"#set up pinecone\n",
|
| 60 |
-
"api_key = \"22e9da2e-64bc-47c6-b4a2-d0d220210aff\"\n",
|
| 61 |
-
"pinecone.init(api_key=api_key, environment='us-west4-gcp')\n",
|
| 62 |
-
"index_name = \"lumin-answers\"\n",
|
| 63 |
-
"\n",
|
| 64 |
-
"\n",
|
| 65 |
-
"# Create Pinecone index\n",
|
| 66 |
-
"dimensions = df.shape[1]\n",
|
| 67 |
-
"\n",
|
| 68 |
-
"#Delete index if it already exists\n",
|
| 69 |
-
"if index_name in pinecone.list_indexes():\n",
|
| 70 |
-
" pinecone.delete_index(index_name)\n",
|
| 71 |
-
" \n",
|
| 72 |
-
"pinecone.create_index(name = index_name, dimension = dimensions, metric = 'cosine', shards = 1)\n",
|
| 73 |
-
"\n",
|
| 74 |
-
"#Init the index so that we can interact with it\n",
|
| 75 |
-
"index = pinecone.Index(index_name)"
|
| 76 |
-
]
|
| 77 |
-
},
|
| 78 |
-
{
|
| 79 |
-
"cell_type": "code",
|
| 80 |
-
"execution_count": 5,
|
| 81 |
-
"metadata": {},
|
| 82 |
-
"outputs": [
|
| 83 |
-
{
|
| 84 |
-
"data": {
|
| 85 |
-
"text/plain": [
|
| 86 |
-
"{'dimension': 212,\n",
|
| 87 |
-
" 'index_fullness': 0.0,\n",
|
| 88 |
-
" 'namespaces': {},\n",
|
| 89 |
-
" 'total_vector_count': 0}"
|
| 90 |
-
]
|
| 91 |
-
},
|
| 92 |
-
"execution_count": 5,
|
| 93 |
-
"metadata": {},
|
| 94 |
-
"output_type": "execute_result"
|
| 95 |
-
}
|
| 96 |
-
],
|
| 97 |
-
"source": [
|
| 98 |
-
"index.describe_index_stats()"
|
| 99 |
-
]
|
| 100 |
-
},
|
| 101 |
-
{
|
| 102 |
-
"cell_type": "code",
|
| 103 |
-
"execution_count": null,
|
| 104 |
-
"metadata": {},
|
| 105 |
-
"outputs": [],
|
| 106 |
-
"source": [
|
| 107 |
-
"index = "
|
| 108 |
-
]
|
| 109 |
-
}
|
| 110 |
-
],
|
| 111 |
-
"metadata": {
|
| 112 |
-
"kernelspec": {
|
| 113 |
-
"display_name": "Python 3",
|
| 114 |
-
"language": "python",
|
| 115 |
-
"name": "python3"
|
| 116 |
-
},
|
| 117 |
-
"language_info": {
|
| 118 |
-
"codemirror_mode": {
|
| 119 |
-
"name": "ipython",
|
| 120 |
-
"version": 3
|
| 121 |
-
},
|
| 122 |
-
"file_extension": ".py",
|
| 123 |
-
"mimetype": "text/x-python",
|
| 124 |
-
"name": "python",
|
| 125 |
-
"nbconvert_exporter": "python",
|
| 126 |
-
"pygments_lexer": "ipython3",
|
| 127 |
-
"version": "3.11.4"
|
| 128 |
-
},
|
| 129 |
-
"orig_nbformat": 4
|
| 130 |
-
},
|
| 131 |
-
"nbformat": 4,
|
| 132 |
-
"nbformat_minor": 2
|
| 133 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web_app/backend/app/question_model.py
CHANGED
|
@@ -4,10 +4,12 @@ from langchain.embeddings.openai import OpenAIEmbeddings
|
|
| 4 |
from langchain.prompts import PromptTemplate
|
| 5 |
from langchain.chat_models import ChatOpenAI
|
| 6 |
from langchain.chains import LLMChain
|
| 7 |
-
from dotenv import load_dotenv
|
| 8 |
import os
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
| 11 |
|
| 12 |
# Load the data
|
| 13 |
# Get the directory of the current file
|
|
@@ -49,7 +51,22 @@ llm = ChatOpenAI(temperature=0, model = "gpt-3.5-turbo-16k")
|
|
| 49 |
|
| 50 |
# Define a template for the prompts to the language model
|
| 51 |
template = """
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
"""
|
| 54 |
|
| 55 |
# Define the template for the prompt with the input variables and template
|
|
@@ -89,4 +106,4 @@ def generate_response(message):
|
|
| 89 |
# Convert follow-up questions into a string response
|
| 90 |
response = '\n'.join(follow_ups)
|
| 91 |
|
| 92 |
-
return response
|
|
|
|
| 4 |
from langchain.prompts import PromptTemplate
|
| 5 |
from langchain.chat_models import ChatOpenAI
|
| 6 |
from langchain.chains import LLMChain
|
| 7 |
+
from dotenv import load_dotenv, find_dotenv
|
| 8 |
import os
|
| 9 |
|
| 10 |
+
# Load the environment variables
|
| 11 |
+
load_dotenv(find_dotenv())
|
| 12 |
+
|
| 13 |
|
| 14 |
# Load the data
|
| 15 |
# Get the directory of the current file
|
|
|
|
| 51 |
|
| 52 |
# Define a template for the prompts to the language model
|
| 53 |
template = """
|
| 54 |
+
You are a extremely intelligent online assistant who's goal is to act as a
|
| 55 |
+
reccomendation system for the user. The user will ask you questions about the
|
| 56 |
+
retrofitting of their home in Ireland and you will provide them with the next two most
|
| 57 |
+
logical questions for them to ask. Your suggested questions should be similar to the
|
| 58 |
+
best practice examples that I will provide you with. The examples are structured as RootQuestion
|
| 59 |
+
being the original question asked by the user and FollowUp1 and FollowUp2 being the next two
|
| 60 |
+
questions that the user should ask.
|
| 61 |
+
|
| 62 |
+
Below is the question that you have received from the user:
|
| 63 |
+
{question}
|
| 64 |
+
|
| 65 |
+
Here is a list of the best practice examples that you should try to emulate:
|
| 66 |
+
{examples}
|
| 67 |
+
|
| 68 |
+
Please return the most logical next two questions for the user to ask.
|
| 69 |
+
Ensure that you only send back exactly two follow-up questions.
|
| 70 |
"""
|
| 71 |
|
| 72 |
# Define the template for the prompt with the input variables and template
|
|
|
|
| 106 |
# Convert follow-up questions into a string response
|
| 107 |
response = '\n'.join(follow_ups)
|
| 108 |
|
| 109 |
+
return response
|
web_app/backend/requirements.txt
DELETED
|
@@ -1,102 +0,0 @@
|
|
| 1 |
-
aiohttp==3.8.5
|
| 2 |
-
aiosignal==1.3.1
|
| 3 |
-
anyio==3.7.1
|
| 4 |
-
appnope==0.1.3
|
| 5 |
-
astor==0.8.1
|
| 6 |
-
asttokens==2.2.1
|
| 7 |
-
async-timeout==4.0.2
|
| 8 |
-
attrs==23.1.0
|
| 9 |
-
backcall==0.2.0
|
| 10 |
-
backoff==2.2.1
|
| 11 |
-
blinker==1.6.2
|
| 12 |
-
certifi==2023.7.22
|
| 13 |
-
charset-normalizer==3.2.0
|
| 14 |
-
chroma-hnswlib==0.7.1
|
| 15 |
-
chromadb==0.4.3
|
| 16 |
-
click==8.1.4
|
| 17 |
-
coloredlogs==15.0.1
|
| 18 |
-
contourpy==1.1.0
|
| 19 |
-
cycler==0.11.0
|
| 20 |
-
dataclasses-json==0.5.13
|
| 21 |
-
decorator==5.1.1
|
| 22 |
-
executing==1.2.0
|
| 23 |
-
faiss-cpu==1.7.4
|
| 24 |
-
fastapi==0.99.1
|
| 25 |
-
Flask==2.3.2
|
| 26 |
-
Flask-Cors==4.0.0
|
| 27 |
-
Flask-SQLAlchemy==3.0.5
|
| 28 |
-
flatbuffers==23.5.26
|
| 29 |
-
fonttools==4.41.1
|
| 30 |
-
frozenlist==1.4.0
|
| 31 |
-
h11==0.14.0
|
| 32 |
-
httptools==0.6.0
|
| 33 |
-
humanfriendly==10.0
|
| 34 |
-
idna==3.4
|
| 35 |
-
importlib-resources==6.0.0
|
| 36 |
-
ipython==8.14.0
|
| 37 |
-
itsdangerous==2.1.2
|
| 38 |
-
jedi==0.18.2
|
| 39 |
-
Jinja2==3.1.2
|
| 40 |
-
kiwisolver==1.4.4
|
| 41 |
-
langchain==0.0.247
|
| 42 |
-
langsmith==0.0.15
|
| 43 |
-
MarkupSafe==2.1.3
|
| 44 |
-
marshmallow==3.20.1
|
| 45 |
-
matplotlib==3.7.2
|
| 46 |
-
matplotlib-inline==0.1.6
|
| 47 |
-
monotonic==1.6
|
| 48 |
-
mpmath==1.3.0
|
| 49 |
-
multidict==6.0.4
|
| 50 |
-
mypy-extensions==1.0.0
|
| 51 |
-
numexpr==2.8.4
|
| 52 |
-
numpy==1.25.1
|
| 53 |
-
onnxruntime==1.15.1
|
| 54 |
-
openai==0.27.8
|
| 55 |
-
openapi-schema-pydantic==1.2.4
|
| 56 |
-
overrides==7.3.1
|
| 57 |
-
packaging==23.1
|
| 58 |
-
pandas==1.5.3
|
| 59 |
-
pandasai==0.7.2
|
| 60 |
-
parso==0.8.3
|
| 61 |
-
pexpect==4.8.0
|
| 62 |
-
pickleshare==0.7.5
|
| 63 |
-
Pillow==10.0.0
|
| 64 |
-
plotly==5.15.0
|
| 65 |
-
posthog==3.0.1
|
| 66 |
-
prompt-toolkit==3.0.39
|
| 67 |
-
protobuf==4.23.4
|
| 68 |
-
psycopg2-binary==2.9.1
|
| 69 |
-
ptyprocess==0.7.0
|
| 70 |
-
pulsar-client==3.2.0
|
| 71 |
-
pure-eval==0.2.2
|
| 72 |
-
pydantic==1.10.12
|
| 73 |
-
Pygments==2.15.1
|
| 74 |
-
pyparsing==3.0.9
|
| 75 |
-
PyPika==0.48.9
|
| 76 |
-
python-dateutil==2.8.2
|
| 77 |
-
python-dotenv==1.0.0
|
| 78 |
-
pytz==2023.3
|
| 79 |
-
PyYAML==6.0.1
|
| 80 |
-
regex==2023.6.3
|
| 81 |
-
requests==2.31.0
|
| 82 |
-
six==1.16.0
|
| 83 |
-
sniffio==1.3.0
|
| 84 |
-
SQLAlchemy==2.0.18
|
| 85 |
-
stack-data==0.6.2
|
| 86 |
-
starlette==0.27.0
|
| 87 |
-
sympy==1.12
|
| 88 |
-
tenacity==8.2.2
|
| 89 |
-
tiktoken==0.4.0
|
| 90 |
-
tokenizers==0.13.3
|
| 91 |
-
tqdm==4.65.0
|
| 92 |
-
traitlets==5.9.0
|
| 93 |
-
typing-inspect==0.9.0
|
| 94 |
-
typing_extensions==4.7.1
|
| 95 |
-
urllib3==2.0.4
|
| 96 |
-
uvicorn==0.23.1
|
| 97 |
-
uvloop==0.17.0
|
| 98 |
-
watchfiles==0.19.0
|
| 99 |
-
wcwidth==0.2.6
|
| 100 |
-
websockets==11.0.3
|
| 101 |
-
Werkzeug==2.3.6
|
| 102 |
-
yarl==1.9.2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web_app/backend/run.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
from app import app
|
| 2 |
|
| 3 |
if __name__ == "__main__":
|
| 4 |
-
app.run(host="0.0.0.0")
|
|
|
|
| 1 |
from app import app
|
| 2 |
|
| 3 |
if __name__ == "__main__":
|
| 4 |
+
app.run(host="0.0.0.0", port=5000, debug=True)
|
web_app/frontend/package-lock.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
web_app/frontend/package.json
CHANGED
|
@@ -7,17 +7,27 @@
|
|
| 7 |
"dev": "vite",
|
| 8 |
"build": "vite build",
|
| 9 |
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
| 10 |
-
"preview": "vite preview"
|
|
|
|
| 11 |
},
|
| 12 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
"@emotion/react": "^11.11.1",
|
| 14 |
"@emotion/styled": "^11.11.0",
|
| 15 |
"@mui/icons-material": "^5.14.1",
|
| 16 |
"@mui/material": "^5.14.1",
|
| 17 |
"axios": "^1.4.0",
|
| 18 |
-
"esbuild": "^0.18.
|
|
|
|
|
|
|
| 19 |
"react": "^18.2.0",
|
| 20 |
"react-dom": "^18.2.0",
|
|
|
|
| 21 |
"react-router-dom": "^6.14.2",
|
| 22 |
"react-transition-group": "^4.4.5",
|
| 23 |
"react-use": "^17.4.0"
|
|
@@ -25,11 +35,11 @@
|
|
| 25 |
"devDependencies": {
|
| 26 |
"@types/react": "^18.2.15",
|
| 27 |
"@types/react-dom": "^18.2.7",
|
| 28 |
-
"@vitejs/plugin-react": "^4.0.
|
| 29 |
"eslint": "^8.45.0",
|
| 30 |
"eslint-plugin-react": "^7.32.2",
|
| 31 |
"eslint-plugin-react-hooks": "^4.6.0",
|
| 32 |
"eslint-plugin-react-refresh": "^0.4.3",
|
| 33 |
-
"vite": "^4.4.
|
| 34 |
}
|
| 35 |
}
|
|
|
|
| 7 |
"dev": "vite",
|
| 8 |
"build": "vite build",
|
| 9 |
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
|
| 10 |
+
"preview": "vite preview",
|
| 11 |
+
"start": "npm run dev"
|
| 12 |
},
|
| 13 |
"dependencies": {
|
| 14 |
+
"@deck.gl/core": "^8.9.23",
|
| 15 |
+
"@deck.gl/extensions": "^8.9.23",
|
| 16 |
+
"@deck.gl/geo-layers": "^8.9.23",
|
| 17 |
+
"@deck.gl/layers": "^8.9.23",
|
| 18 |
+
"@deck.gl/mesh-layers": "^8.9.23",
|
| 19 |
+
"@deck.gl/react": "^8.9.23",
|
| 20 |
"@emotion/react": "^11.11.1",
|
| 21 |
"@emotion/styled": "^11.11.0",
|
| 22 |
"@mui/icons-material": "^5.14.1",
|
| 23 |
"@mui/material": "^5.14.1",
|
| 24 |
"axios": "^1.4.0",
|
| 25 |
+
"esbuild": "^0.18.18",
|
| 26 |
+
"mapbox-gl": "^2.15.0",
|
| 27 |
+
"maplibre-gl": "^3.2.1",
|
| 28 |
"react": "^18.2.0",
|
| 29 |
"react-dom": "^18.2.0",
|
| 30 |
+
"react-map-gl": "^7.1.3",
|
| 31 |
"react-router-dom": "^6.14.2",
|
| 32 |
"react-transition-group": "^4.4.5",
|
| 33 |
"react-use": "^17.4.0"
|
|
|
|
| 35 |
"devDependencies": {
|
| 36 |
"@types/react": "^18.2.15",
|
| 37 |
"@types/react-dom": "^18.2.7",
|
| 38 |
+
"@vitejs/plugin-react": "^4.0.4",
|
| 39 |
"eslint": "^8.45.0",
|
| 40 |
"eslint-plugin-react": "^7.32.2",
|
| 41 |
"eslint-plugin-react-hooks": "^4.6.0",
|
| 42 |
"eslint-plugin-react-refresh": "^0.4.3",
|
| 43 |
+
"vite": "^4.4.8"
|
| 44 |
}
|
| 45 |
}
|
web_app/frontend/public/map1.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
web_app/frontend/src/App.jsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
import React from 'react';
|
| 2 |
-
import Navbar from './components/Navbar';
|
| 3 |
// import Footer from './components/Footer';
|
| 4 |
import { Box } from '@mui/system';
|
| 5 |
|
| 6 |
const App = ({ children }) => {
|
| 7 |
return (
|
| 8 |
<>
|
| 9 |
-
<Navbar />
|
| 10 |
<Box flexGrow={1}>
|
| 11 |
{children}
|
| 12 |
</Box>
|
|
|
|
| 1 |
import React from 'react';
|
| 2 |
+
// import Navbar from './components/Navbar';
|
| 3 |
// import Footer from './components/Footer';
|
| 4 |
import { Box } from '@mui/system';
|
| 5 |
|
| 6 |
const App = ({ children }) => {
|
| 7 |
return (
|
| 8 |
<>
|
| 9 |
+
{/* <Navbar /> */}
|
| 10 |
<Box flexGrow={1}>
|
| 11 |
{children}
|
| 12 |
</Box>
|
web_app/frontend/src/AppRouter.jsx
CHANGED
|
@@ -2,22 +2,26 @@ import React from 'react';
|
|
| 2 |
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
|
| 3 |
import App from './App';
|
| 4 |
import LandingPage from './pages/LandingPage';
|
| 5 |
-
import ChatBot from './pages/ChatBot';
|
| 6 |
import AboutPage from './pages/AboutPage';
|
| 7 |
import ContactPage from './pages/ContactPage';
|
| 8 |
-
import DashboardPage from './pages/DashboardPage';
|
| 9 |
import ChatPage from './pages/ChatPage';
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
const AppRouter = () => (
|
| 12 |
<Router>
|
| 13 |
<App>
|
| 14 |
<Routes>
|
| 15 |
<Route path="/" element={<LandingPage />} />
|
| 16 |
-
<Route path="/chatbot" element={<ChatBot />} />
|
| 17 |
<Route path="/about" element={<AboutPage />} />
|
| 18 |
<Route path="/contact" element={<ContactPage />} />
|
| 19 |
<Route path="/dashboard" element={<DashboardPage />} />
|
| 20 |
<Route path="/dashboard/chat" element={<ChatPage />}/>
|
|
|
|
|
|
|
|
|
|
| 21 |
</Routes>
|
| 22 |
</App>
|
| 23 |
</Router>
|
|
|
|
| 2 |
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
|
| 3 |
import App from './App';
|
| 4 |
import LandingPage from './pages/LandingPage';
|
|
|
|
| 5 |
import AboutPage from './pages/AboutPage';
|
| 6 |
import ContactPage from './pages/ContactPage';
|
| 7 |
+
import DashboardPage from './pages/DashboardPage-old';
|
| 8 |
import ChatPage from './pages/ChatPage';
|
| 9 |
+
import ReportsPage from './pages/ReportsPage';
|
| 10 |
+
import CityPage from './pages/CityPage';
|
| 11 |
+
import ResourcesPage from './pages/ResourcesPage';
|
| 12 |
|
| 13 |
const AppRouter = () => (
|
| 14 |
<Router>
|
| 15 |
<App>
|
| 16 |
<Routes>
|
| 17 |
<Route path="/" element={<LandingPage />} />
|
|
|
|
| 18 |
<Route path="/about" element={<AboutPage />} />
|
| 19 |
<Route path="/contact" element={<ContactPage />} />
|
| 20 |
<Route path="/dashboard" element={<DashboardPage />} />
|
| 21 |
<Route path="/dashboard/chat" element={<ChatPage />}/>
|
| 22 |
+
<Route path="/dashboard/reports" element={<ReportsPage />}/>
|
| 23 |
+
<Route path="/dashboard/city" element={<CityPage />}/>
|
| 24 |
+
<Route path="/dashboard/resources" element={<ResourcesPage />}/>
|
| 25 |
</Routes>
|
| 26 |
</App>
|
| 27 |
</Router>
|
web_app/frontend/src/components/ChatHistory.jsx
CHANGED
|
@@ -27,10 +27,10 @@ const ChatHistory = ({ chatHistory, handleFollowUp }) => {
|
|
| 27 |
<Card
|
| 28 |
sx={{
|
| 29 |
my: 0,
|
| 30 |
-
mt: index === 0 ?
|
| 31 |
mx: 2,
|
| 32 |
-
width: '100%',
|
| 33 |
-
maxWidth: 'calc(100% - 48px)', // Calculated max-width to provide spacing on larger screens
|
| 34 |
}}
|
| 35 |
>
|
| 36 |
<CardContent>
|
|
|
|
| 27 |
<Card
|
| 28 |
sx={{
|
| 29 |
my: 0,
|
| 30 |
+
mt: index === 0 ? 1 : 2, // Conditional margin-top depending on the index
|
| 31 |
mx: 2,
|
| 32 |
+
// width: '100%',
|
| 33 |
+
// maxWidth: 'calc(100% - 48px)', // Calculated max-width to provide spacing on larger screens
|
| 34 |
}}
|
| 35 |
>
|
| 36 |
<CardContent>
|
web_app/frontend/src/components/ChatInput.jsx
CHANGED
|
@@ -17,17 +17,18 @@ const ChatInput = ({
|
|
| 17 |
component="form"
|
| 18 |
onSubmit={handleFormSubmit}
|
| 19 |
sx={{
|
| 20 |
-
position: '
|
| 21 |
bottom: 0,
|
| 22 |
left: 0,
|
| 23 |
right: 0,
|
| 24 |
-
backgroundColor: '#
|
| 25 |
borderTop: '1px solid #DDD',
|
| 26 |
py: 1,
|
| 27 |
px: 2,
|
| 28 |
display: 'flex',
|
| 29 |
justifyContent: 'space-between',
|
| 30 |
minHeight: 80,
|
|
|
|
| 31 |
}}
|
| 32 |
>
|
| 33 |
<TextField
|
|
@@ -40,11 +41,12 @@ const ChatInput = ({
|
|
| 40 |
rowsmax={2}
|
| 41 |
variant="outlined"
|
| 42 |
disabled={loading}
|
| 43 |
-
sx={{ flexGrow: 1, maxHeight: '80%', mr: 1, ml: -1, backgroundColor: '
|
|
|
|
| 44 |
/>
|
| 45 |
|
| 46 |
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
| 47 |
-
<Button type="submit" color="primary" variant="contained" disabled={loading} sx={{ height: '100%', mr: 1 }}>
|
| 48 |
{loading ? <CircularProgress size={24} /> : <PaperPlaneIcon />}
|
| 49 |
</Button>
|
| 50 |
|
|
@@ -56,7 +58,7 @@ const ChatInput = ({
|
|
| 56 |
height: '100%',
|
| 57 |
width: 50,
|
| 58 |
backgroundColor: grey[300],
|
| 59 |
-
borderRadius:
|
| 60 |
}}
|
| 61 |
>
|
| 62 |
<RefreshIcon />
|
|
|
|
| 17 |
component="form"
|
| 18 |
onSubmit={handleFormSubmit}
|
| 19 |
sx={{
|
| 20 |
+
position: 'flex',
|
| 21 |
bottom: 0,
|
| 22 |
left: 0,
|
| 23 |
right: 0,
|
| 24 |
+
backgroundColor: '#1D5B79',
|
| 25 |
borderTop: '1px solid #DDD',
|
| 26 |
py: 1,
|
| 27 |
px: 2,
|
| 28 |
display: 'flex',
|
| 29 |
justifyContent: 'space-between',
|
| 30 |
minHeight: 80,
|
| 31 |
+
borderRadius:'15px'
|
| 32 |
}}
|
| 33 |
>
|
| 34 |
<TextField
|
|
|
|
| 41 |
rowsmax={2}
|
| 42 |
variant="outlined"
|
| 43 |
disabled={loading}
|
| 44 |
+
sx={{ flexGrow: 1, maxHeight: '80%', mr: 1, ml: -1, backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
| 45 |
+
borderRadius:'15px'}}
|
| 46 |
/>
|
| 47 |
|
| 48 |
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
| 49 |
+
<Button type="submit" color="primary" variant="contained" disabled={loading} sx={{ backgroundColor:'#5499de' , height: '100%', mr: 1, borderRadius:'15px'}}>
|
| 50 |
{loading ? <CircularProgress size={24} /> : <PaperPlaneIcon />}
|
| 51 |
</Button>
|
| 52 |
|
|
|
|
| 58 |
height: '100%',
|
| 59 |
width: 50,
|
| 60 |
backgroundColor: grey[300],
|
| 61 |
+
borderRadius:'15px'
|
| 62 |
}}
|
| 63 |
>
|
| 64 |
<RefreshIcon />
|
web_app/frontend/src/components/Map3D-old.jsx
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, {useState, useEffect} from 'react';
|
| 2 |
+
import {createRoot} from 'react-dom/client';
|
| 3 |
+
import {Map} from 'react-map-gl';
|
| 4 |
+
import maplibregl from 'maplibre-gl';
|
| 5 |
+
import {AmbientLight, PointLight, LightingEffect} from '@deck.gl/core';
|
| 6 |
+
import DeckGL from '@deck.gl/react';
|
| 7 |
+
import {PolygonLayer} from '@deck.gl/layers';
|
| 8 |
+
import {TripsLayer} from '@deck.gl/geo-layers';
|
| 9 |
+
import { Box } from '@mui/system';
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
// Source data CSV, Attribution to CARTO, OpenStreetMap contributors to deck.gl trips-layer example
|
| 13 |
+
const DATA_URL = {
|
| 14 |
+
BUILDINGS:'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/buildings.json', // eslint-disable-line
|
| 15 |
+
TRIPS: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/trips-v7.json' // eslint-disable-line
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
const ambientLight = new AmbientLight({
|
| 19 |
+
color: [255, 255, 255],
|
| 20 |
+
intensity: 1.0
|
| 21 |
+
});
|
| 22 |
+
|
| 23 |
+
const pointLight = new PointLight({
|
| 24 |
+
color: [255, 255, 255],
|
| 25 |
+
intensity: 2.0,
|
| 26 |
+
position: [-74.05, 40.7, 8000]
|
| 27 |
+
});
|
| 28 |
+
|
| 29 |
+
const lightingEffect = new LightingEffect({ambientLight, pointLight});
|
| 30 |
+
|
| 31 |
+
const material = {
|
| 32 |
+
ambient: 0.1,
|
| 33 |
+
diffuse: 0.6,
|
| 34 |
+
shininess: 32,
|
| 35 |
+
specularColor: [60, 64, 70]
|
| 36 |
+
};
|
| 37 |
+
|
| 38 |
+
const DEFAULT_THEME = {
|
| 39 |
+
buildingColor: [74, 80, 87],
|
| 40 |
+
trailColor0: [253, 128, 93],
|
| 41 |
+
trailColor1: [23, 184, 190],
|
| 42 |
+
material,
|
| 43 |
+
effects: [lightingEffect]
|
| 44 |
+
};
|
| 45 |
+
|
| 46 |
+
const INITIAL_VIEW_STATE = {
|
| 47 |
+
longitude: -6.2760296,
|
| 48 |
+
latitude: 53.362321,
|
| 49 |
+
zoom: 13,
|
| 50 |
+
pitch: 45,
|
| 51 |
+
bearing: 0
|
| 52 |
+
};
|
| 53 |
+
|
| 54 |
+
const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json';
|
| 55 |
+
|
| 56 |
+
const landCover = [
|
| 57 |
+
[
|
| 58 |
+
[-74.0, 40.7],
|
| 59 |
+
[-74.02, 40.7],
|
| 60 |
+
[-74.02, 40.72],
|
| 61 |
+
[-74.0, 40.72]
|
| 62 |
+
]
|
| 63 |
+
];
|
| 64 |
+
|
| 65 |
+
export default function Map3D({
|
| 66 |
+
buildings = DATA_URL.BUILDINGS,
|
| 67 |
+
trips = DATA_URL.TRIPS,
|
| 68 |
+
trailLength = 180,
|
| 69 |
+
initialViewState = INITIAL_VIEW_STATE,
|
| 70 |
+
mapStyle = MAP_STYLE,
|
| 71 |
+
theme = DEFAULT_THEME,
|
| 72 |
+
loopLength = 1800,
|
| 73 |
+
animationSpeed = 1
|
| 74 |
+
}) {
|
| 75 |
+
const [time, setTime] = useState(0);
|
| 76 |
+
const [animation] = useState({});
|
| 77 |
+
|
| 78 |
+
const animate = () => {
|
| 79 |
+
setTime(t => (t + animationSpeed) % loopLength);
|
| 80 |
+
animation.id = window.requestAnimationFrame(animate);
|
| 81 |
+
};
|
| 82 |
+
|
| 83 |
+
useEffect(() => {
|
| 84 |
+
animation.id = window.requestAnimationFrame(animate);
|
| 85 |
+
return () => window.cancelAnimationFrame(animation.id);
|
| 86 |
+
}, [animation]);
|
| 87 |
+
|
| 88 |
+
const layers = [
|
| 89 |
+
new PolygonLayer({
|
| 90 |
+
id: 'ground',
|
| 91 |
+
data: landCover,
|
| 92 |
+
getPolygon: f => f,
|
| 93 |
+
stroked: false,
|
| 94 |
+
getFillColor: [0, 0, 0, 0]
|
| 95 |
+
}),
|
| 96 |
+
new TripsLayer({
|
| 97 |
+
id: 'trips',
|
| 98 |
+
data: trips,
|
| 99 |
+
getPath: d => d.path,
|
| 100 |
+
getTimestamps: d => d.timestamps,
|
| 101 |
+
getColor: d => (d.vendor === 0 ? theme.trailColor0 : theme.trailColor1),
|
| 102 |
+
opacity: 0.3,
|
| 103 |
+
widthMinPixels: 2,
|
| 104 |
+
rounded: true,
|
| 105 |
+
trailLength,
|
| 106 |
+
currentTime: time,
|
| 107 |
+
|
| 108 |
+
shadowEnabled: false
|
| 109 |
+
}),
|
| 110 |
+
new PolygonLayer({
|
| 111 |
+
id: 'buildings',
|
| 112 |
+
data: buildings,
|
| 113 |
+
extruded: true,
|
| 114 |
+
wireframe: false,
|
| 115 |
+
opacity: 0.5,
|
| 116 |
+
getPolygon: f => f.polygon,
|
| 117 |
+
getElevation: f => f.height,
|
| 118 |
+
getFillColor: theme.buildingColor,
|
| 119 |
+
material: theme.material
|
| 120 |
+
})
|
| 121 |
+
];
|
| 122 |
+
|
| 123 |
+
return (
|
| 124 |
+
<Box sx={{ width: '100%', height: '100%', position: 'relative', borderRadius: '15px', overflow: 'hidden'}}>
|
| 125 |
+
<DeckGL
|
| 126 |
+
style={{ width: '100%', height: '100%', position: 'absolute'}}
|
| 127 |
+
layers={layers}
|
| 128 |
+
effects={theme.effects}
|
| 129 |
+
initialViewState={initialViewState}
|
| 130 |
+
controller={true}
|
| 131 |
+
>
|
| 132 |
+
<Map reuseMaps mapLib={maplibregl} mapStyle={mapStyle} preventStyleDiffing={true} attributionControl={false} />
|
| 133 |
+
</DeckGL>
|
| 134 |
+
</Box>
|
| 135 |
+
);
|
| 136 |
+
}
|
| 137 |
+
|
web_app/frontend/src/components/Map3D.jsx
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, {useState, useEffect} from 'react';
|
| 2 |
+
import {createRoot} from 'react-dom/client';
|
| 3 |
+
import {Map} from 'react-map-gl';
|
| 4 |
+
import maplibregl from 'maplibre-gl';
|
| 5 |
+
import {AmbientLight, PointLight, LightingEffect} from '@deck.gl/core';
|
| 6 |
+
import DeckGL from '@deck.gl/react';
|
| 7 |
+
import {PolygonLayer} from '@deck.gl/layers';
|
| 8 |
+
import {TripsLayer} from '@deck.gl/geo-layers';
|
| 9 |
+
import { Box } from '@mui/system';
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
// Source data CSV, Attribution to CARTO, OpenStreetMap contributors to deck.gl trips-layer example
|
| 13 |
+
const DATA_URL = {
|
| 14 |
+
// BUILDINGS:'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/buildings.json', // eslint-disable-line
|
| 15 |
+
BUILDINGS: '/map1.json'
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
const ambientLight = new AmbientLight({
|
| 19 |
+
color: [255, 255, 255],
|
| 20 |
+
intensity: 6.0
|
| 21 |
+
});
|
| 22 |
+
|
| 23 |
+
const pointLight = new PointLight({
|
| 24 |
+
color: [255, 255, 255],
|
| 25 |
+
intensity: 1.0,
|
| 26 |
+
position: [-6.4741164,
|
| 27 |
+
53.4622087, 8000]
|
| 28 |
+
});
|
| 29 |
+
|
| 30 |
+
// const lightingEffect = new LightingEffect({ambientLight, pointLight});
|
| 31 |
+
const lightingEffect = new LightingEffect({ambientLight, pointLight});
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
const material = {
|
| 35 |
+
ambient: 0.1,
|
| 36 |
+
diffuse: 0.6,
|
| 37 |
+
shininess: 32,
|
| 38 |
+
specularColor: [60, 64, 70]
|
| 39 |
+
};
|
| 40 |
+
|
| 41 |
+
const DEFAULT_THEME = {
|
| 42 |
+
buildingColor: [51, 204, 255],
|
| 43 |
+
trailColor0: [253, 128, 93],
|
| 44 |
+
trailColor1: [23, 184, 190],
|
| 45 |
+
material,
|
| 46 |
+
effects: [lightingEffect]
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
const INITIAL_VIEW_STATE = {
|
| 50 |
+
longitude: -6.269218,
|
| 51 |
+
latitude: 53.342505,
|
| 52 |
+
zoom: 14.64,
|
| 53 |
+
pitch: 59.31,
|
| 54 |
+
bearing: 0
|
| 55 |
+
};
|
| 56 |
+
|
| 57 |
+
const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json';
|
| 58 |
+
|
| 59 |
+
const landCover = [
|
| 60 |
+
[
|
| 61 |
+
[-74.0, 40.7],
|
| 62 |
+
[-74.02, 40.7],
|
| 63 |
+
[-74.02, 40.72],
|
| 64 |
+
[-74.0, 40.72]
|
| 65 |
+
]
|
| 66 |
+
];
|
| 67 |
+
|
| 68 |
+
export default function Map3D({
|
| 69 |
+
buildings = DATA_URL.BUILDINGS,
|
| 70 |
+
initialViewState = INITIAL_VIEW_STATE,
|
| 71 |
+
mapStyle = MAP_STYLE,
|
| 72 |
+
theme = DEFAULT_THEME,
|
| 73 |
+
}) {
|
| 74 |
+
const [buildingData, setBuildingData] = useState(null);
|
| 75 |
+
const [viewState, setViewState] = useState(initialViewState); // Add this line to manage view state
|
| 76 |
+
|
| 77 |
+
useEffect(() => {
|
| 78 |
+
fetch(buildings)
|
| 79 |
+
.then((response) => response.json())
|
| 80 |
+
.then((json) => {
|
| 81 |
+
const allData = json.datasets[0].data.allData.map(([feature]) => feature);
|
| 82 |
+
setBuildingData(allData);
|
| 83 |
+
})
|
| 84 |
+
.catch((error) => {
|
| 85 |
+
console.error('Error fetching buildings data:', error);
|
| 86 |
+
});
|
| 87 |
+
}, [buildings]);
|
| 88 |
+
|
| 89 |
+
if (!buildingData) {
|
| 90 |
+
return <div>Loading...</div>;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
const layers = [
|
| 94 |
+
new PolygonLayer({
|
| 95 |
+
id: 'ground',
|
| 96 |
+
data: landCover,
|
| 97 |
+
getPolygon: f => f,
|
| 98 |
+
stroked: false,
|
| 99 |
+
getFillColor: [0, 0, 0, 0]
|
| 100 |
+
}),
|
| 101 |
+
new PolygonLayer({
|
| 102 |
+
id: 'buildings',
|
| 103 |
+
data: buildingData,
|
| 104 |
+
extruded: true,
|
| 105 |
+
wireframe: false,
|
| 106 |
+
opacity: 0.5,
|
| 107 |
+
getPolygon: (f) => f.geometry.coordinates[0][0],
|
| 108 |
+
getElevation: (f) => f.properties.Height_Met,
|
| 109 |
+
getFillColor: theme.buildingColor,
|
| 110 |
+
material: theme.material,
|
| 111 |
+
})
|
| 112 |
+
];
|
| 113 |
+
|
| 114 |
+
const onViewStateChange = ({ viewState }) => {
|
| 115 |
+
setViewState(viewState);
|
| 116 |
+
};
|
| 117 |
+
|
| 118 |
+
return (
|
| 119 |
+
<Box sx={{ width: '100%', height: '100%', position: 'relative', borderRadius: '15px', overflow: 'hidden'}}>
|
| 120 |
+
<DeckGL
|
| 121 |
+
style={{ width: '100%', height: '100%', position: 'absolute'}}
|
| 122 |
+
layers={layers}
|
| 123 |
+
effects={theme.effects}
|
| 124 |
+
initialViewState={initialViewState}
|
| 125 |
+
controller={true}
|
| 126 |
+
viewState={viewState}
|
| 127 |
+
onViewStateChange={onViewStateChange}
|
| 128 |
+
>
|
| 129 |
+
<Map reuseMaps mapLib={maplibregl} mapStyle={mapStyle} preventStyleDiffing={true} attributionControl={false} />
|
| 130 |
+
</DeckGL>
|
| 131 |
+
<div
|
| 132 |
+
style={{
|
| 133 |
+
position: 'absolute',
|
| 134 |
+
bottom: '10px',
|
| 135 |
+
right: '10px',
|
| 136 |
+
color: 'white',
|
| 137 |
+
background: 'rgba(0, 0, 0, 0.5)',
|
| 138 |
+
padding: '5px',
|
| 139 |
+
borderRadius: '5px',
|
| 140 |
+
}}
|
| 141 |
+
>
|
| 142 |
+
Longitude: {viewState.longitude.toFixed(6)}
|
| 143 |
+
<br />
|
| 144 |
+
Latitude: {viewState.latitude.toFixed(6)}
|
| 145 |
+
<br />
|
| 146 |
+
Zoom: {viewState.zoom.toFixed(2)}
|
| 147 |
+
<br />
|
| 148 |
+
Pitch: {viewState.pitch.toFixed(2)}
|
| 149 |
+
<br />
|
| 150 |
+
Bearing: {viewState.bearing.toFixed(2)}
|
| 151 |
+
</div>
|
| 152 |
+
</Box>
|
| 153 |
+
);
|
| 154 |
+
}
|
| 155 |
+
|
web_app/frontend/src/components/Navbar.jsx
CHANGED
|
@@ -5,8 +5,7 @@ import { Menu, Close } from '@mui/icons-material';
|
|
| 5 |
import { Link, useLocation } from 'react-router-dom';
|
| 6 |
import './Navbar.css'
|
| 7 |
|
| 8 |
-
|
| 9 |
-
const Navbar = () => {
|
| 10 |
const [open, setOpen] = useState(false);
|
| 11 |
const location = useLocation();
|
| 12 |
const [currentPage, setCurrentPage] = useState('');
|
|
@@ -22,24 +21,21 @@ const Navbar = () => {
|
|
| 22 |
};
|
| 23 |
|
| 24 |
return (
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
{/* Toolbar component to contain the navigation content */}
|
| 28 |
-
<Toolbar style={{ display: 'flex', justifyContent: 'space-between', margin: '10px', borderRadius: '15px', backgroundColor: 'rgba(255, 255, 255, 0.1)' }}>
|
| 29 |
-
{/* Link to the home page with a logo and text */}
|
| 30 |
<Link className="logo" to="/" style={{ textDecoration: 'none', padding: '10px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
| 31 |
-
<Typography style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold' }}>
|
| 32 |
LuminLab
|
| 33 |
</Typography>
|
| 34 |
-
<Divider orientation="vertical" flexItem sx={{ bgcolor:
|
| 35 |
-
<Typography style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold' }}>
|
| 36 |
{currentPage}
|
| 37 |
</Typography>
|
| 38 |
</Link>
|
| 39 |
|
| 40 |
<Box display={{ xs: 'block', sm: 'none' }}>
|
| 41 |
<IconButton
|
| 42 |
-
color=
|
| 43 |
onClick={handleToggle}
|
| 44 |
>
|
| 45 |
{open ? <Close /> : <Menu />}
|
|
@@ -58,29 +54,29 @@ const Navbar = () => {
|
|
| 58 |
marginTop: '76px',
|
| 59 |
marginRight: '10px',
|
| 60 |
marginLeft: '10px',
|
| 61 |
-
backgroundColor:
|
| 62 |
boxShadow: '1',
|
| 63 |
-
color:
|
| 64 |
}
|
| 65 |
}}
|
| 66 |
transitionDuration={200}
|
| 67 |
TransitionComponent={Fade}
|
| 68 |
>
|
| 69 |
-
<MenuItem onClick={() => setOpen(false)} component={Link} to="/about" style={{ fontWeight: 'bold'
|
| 70 |
-
<MenuItem onClick={() => setOpen(false)} component={Link} to="/contact" style={{ fontWeight: 'bold' }}>
|
| 71 |
<MenuItem onClick={() => setOpen(false)} component={Link} to="/dashboard" style={{ fontWeight: 'bold' }}>Dashboard</MenuItem>
|
| 72 |
{/* <MenuItem onClick={() => setOpen(false)} component={Link} to="/team" style={{ fontWeight: 'bold' }}>Team</MenuItem> */}
|
| 73 |
</Drawer>
|
| 74 |
</Box>
|
| 75 |
|
| 76 |
<Box display={{ sm: 'flex', xs: 'none' }}>
|
| 77 |
-
<Button className="nav-link" color="inherit" component={Link} to="/about" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px'}}>
|
| 78 |
About
|
| 79 |
</Button>
|
| 80 |
-
<Button className="nav-link" color="inherit" component={Link} to="/contact" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px'}}>
|
| 81 |
-
|
| 82 |
</Button>
|
| 83 |
-
<Button className="nav-link" color="inherit" component={Link} to="/dashboard" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px'}}>
|
| 84 |
Dashboard
|
| 85 |
</Button>
|
| 86 |
{/* <Button className="nav-link" color="inherit" component={Link} to="/team" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold'}}>
|
|
@@ -92,6 +88,5 @@ const Navbar = () => {
|
|
| 92 |
);
|
| 93 |
};
|
| 94 |
|
| 95 |
-
// Export the Navbar component as default
|
| 96 |
export default Navbar;
|
| 97 |
|
|
|
|
| 5 |
import { Link, useLocation } from 'react-router-dom';
|
| 6 |
import './Navbar.css'
|
| 7 |
|
| 8 |
+
const Navbar = ({bgColor = 'rgba(255, 255, 255, 0.1)', fontColor = 'white'}) => {
|
|
|
|
| 9 |
const [open, setOpen] = useState(false);
|
| 10 |
const location = useLocation();
|
| 11 |
const [currentPage, setCurrentPage] = useState('');
|
|
|
|
| 21 |
};
|
| 22 |
|
| 23 |
return (
|
| 24 |
+
<AppBar position="absolute" style={{ backgroundColor:'transparent', boxShadow: 'none' }}>
|
| 25 |
+
<Toolbar style={{ display: 'flex', justifyContent: 'space-between', margin: '10px', borderRadius: '15px', backgroundColor:bgColor }}>
|
|
|
|
|
|
|
|
|
|
| 26 |
<Link className="logo" to="/" style={{ textDecoration: 'none', padding: '10px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
| 27 |
+
<Typography style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', color: fontColor}}>
|
| 28 |
LuminLab
|
| 29 |
</Typography>
|
| 30 |
+
<Divider orientation="vertical" flexItem sx={{ bgcolor: fontColor, width: '1px', mx: 2 }}/>
|
| 31 |
+
<Typography style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', color: fontColor}}>
|
| 32 |
{currentPage}
|
| 33 |
</Typography>
|
| 34 |
</Link>
|
| 35 |
|
| 36 |
<Box display={{ xs: 'block', sm: 'none' }}>
|
| 37 |
<IconButton
|
| 38 |
+
color={fontColor}
|
| 39 |
onClick={handleToggle}
|
| 40 |
>
|
| 41 |
{open ? <Close /> : <Menu />}
|
|
|
|
| 54 |
marginTop: '76px',
|
| 55 |
marginRight: '10px',
|
| 56 |
marginLeft: '10px',
|
| 57 |
+
backgroundColor: bgColor,
|
| 58 |
boxShadow: '1',
|
| 59 |
+
color: fontColor
|
| 60 |
}
|
| 61 |
}}
|
| 62 |
transitionDuration={200}
|
| 63 |
TransitionComponent={Fade}
|
| 64 |
>
|
| 65 |
+
<MenuItem onClick={() => setOpen(false)} component={Link} to="/about" style={{ fontWeight: 'bold'}}>About</MenuItem>
|
| 66 |
+
<MenuItem onClick={() => setOpen(false)} component={Link} to="/contact" style={{ fontWeight: 'bold' }}>Client Communications</MenuItem>
|
| 67 |
<MenuItem onClick={() => setOpen(false)} component={Link} to="/dashboard" style={{ fontWeight: 'bold' }}>Dashboard</MenuItem>
|
| 68 |
{/* <MenuItem onClick={() => setOpen(false)} component={Link} to="/team" style={{ fontWeight: 'bold' }}>Team</MenuItem> */}
|
| 69 |
</Drawer>
|
| 70 |
</Box>
|
| 71 |
|
| 72 |
<Box display={{ sm: 'flex', xs: 'none' }}>
|
| 73 |
+
<Button className="nav-link" color="inherit" component={Link} to="/about" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px', color: fontColor}}>
|
| 74 |
About
|
| 75 |
</Button>
|
| 76 |
+
<Button className="nav-link" color="inherit" component={Link} to="/contact" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px', color: fontColor}}>
|
| 77 |
+
Client Communications
|
| 78 |
</Button>
|
| 79 |
+
<Button className="nav-link" color="inherit" component={Link} to="/dashboard" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold', marginRight: '15px', color: fontColor}}>
|
| 80 |
Dashboard
|
| 81 |
</Button>
|
| 82 |
{/* <Button className="nav-link" color="inherit" component={Link} to="/team" style={{ textTransform: 'none', fontSize: '16px', fontWeight: 'bold'}}>
|
|
|
|
| 88 |
);
|
| 89 |
};
|
| 90 |
|
|
|
|
| 91 |
export default Navbar;
|
| 92 |
|
web_app/frontend/src/components/StartCard.jsx
CHANGED
|
@@ -30,21 +30,24 @@ const StartCard = ({ inputText }) => {
|
|
| 30 |
<CardContent>
|
| 31 |
{/* Typography for the title */}
|
| 32 |
<Typography
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
| 44 |
>
|
| 45 |
-
|
| 46 |
</Typography>
|
| 47 |
-
|
| 48 |
</Card>
|
| 49 |
</Grid>
|
| 50 |
{/* Render the ButtonGrid component */}
|
|
|
|
| 30 |
<CardContent>
|
| 31 |
{/* Typography for the title */}
|
| 32 |
<Typography
|
| 33 |
+
variant="h6"
|
| 34 |
+
sx={{
|
| 35 |
+
textAlign: 'center',
|
| 36 |
+
// You can add or adjust font-related styles if necessary, for example:
|
| 37 |
+
// fontFamily: 'Your preferred font-family here',
|
| 38 |
+
// fontWeight: 'normal',
|
| 39 |
+
// fontSize: '1rem',
|
| 40 |
+
// color: 'black', // or any other color you prefer
|
| 41 |
+
pl: -100,
|
| 42 |
+
pr: 12,
|
| 43 |
+
pb: 0, // Remove bottom padding
|
| 44 |
+
mb: 0, // Remove bottom margin
|
| 45 |
+
mr: -10, // Adjust right margin
|
| 46 |
+
}}
|
| 47 |
>
|
| 48 |
+
Unsure Where to Start?
|
| 49 |
</Typography>
|
| 50 |
+
</CardContent>
|
| 51 |
</Card>
|
| 52 |
</Grid>
|
| 53 |
{/* Render the ButtonGrid component */}
|
web_app/frontend/src/components/emailService.jsx
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import axios from 'axios';
|
| 2 |
+
|
| 3 |
+
const handleSendEmail = async (email) => {
|
| 4 |
+
try {
|
| 5 |
+
// Fetch chatHistory from localStorage
|
| 6 |
+
const storedChatHistory = localStorage.getItem('chatHistory');
|
| 7 |
+
|
| 8 |
+
// If it doesn't exist or is empty, return
|
| 9 |
+
if (!storedChatHistory || storedChatHistory.length === 0) {
|
| 10 |
+
console.error("Chat history is empty.");
|
| 11 |
+
return;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const response = await axios.post('http://localhost:5000/exportChat', {
|
| 15 |
+
email: email,
|
| 16 |
+
chatHistory: JSON.parse(storedChatHistory) // Convert the stringified JSON to an object
|
| 17 |
+
});
|
| 18 |
+
|
| 19 |
+
console.log(response.data);
|
| 20 |
+
|
| 21 |
+
} catch (error) {
|
| 22 |
+
console.error("Error sending email:", error);
|
| 23 |
+
}
|
| 24 |
+
};
|
| 25 |
+
|
| 26 |
+
export default handleSendEmail;
|
web_app/frontend/src/hooks/useChat.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
| 1 |
import { useState } from 'react';
|
| 2 |
import axios from 'axios';
|
| 3 |
-
|
| 4 |
/**
|
| 5 |
* Custom hook for managing chat-related state and functionality.
|
| 6 |
* It handles input text, chat history, loading state, history navigation, and form submission.
|
|
@@ -24,8 +23,8 @@ export default function useChatHandler() {
|
|
| 24 |
setLoading(true);
|
| 25 |
let success = false;
|
| 26 |
try {
|
| 27 |
-
const sendTextResponse = await axios.post('http://
|
| 28 |
-
const sendQuestionsResponse = await axios.post('http://
|
| 29 |
|
| 30 |
const newChatItem = {
|
| 31 |
question: text,
|
|
@@ -60,18 +59,18 @@ export default function useChatHandler() {
|
|
| 60 |
setChatHistory([...chatHistory]);
|
| 61 |
|
| 62 |
try {
|
| 63 |
-
const response = await axios.post('http://
|
| 64 |
text: chatHistory[chatItemIndex].followUps[followUpIndex].text
|
| 65 |
});
|
| 66 |
|
| 67 |
-
//
|
| 68 |
chatHistory[chatItemIndex].followUps[followUpIndex].response = response.data.output;
|
| 69 |
chatHistory[chatItemIndex].followUps[followUpIndex].loading = false;
|
| 70 |
|
| 71 |
-
//
|
| 72 |
-
const sendQuestionsResponse = await axios.post('http://
|
| 73 |
|
| 74 |
-
//
|
| 75 |
const newFollowUps = sendQuestionsResponse.data.output.followUps.map(followUp => ({
|
| 76 |
text: followUp,
|
| 77 |
response: null,
|
|
@@ -152,4 +151,3 @@ export default function useChatHandler() {
|
|
| 152 |
};
|
| 153 |
|
| 154 |
}
|
| 155 |
-
|
|
|
|
| 1 |
import { useState } from 'react';
|
| 2 |
import axios from 'axios';
|
|
|
|
| 3 |
/**
|
| 4 |
* Custom hook for managing chat-related state and functionality.
|
| 5 |
* It handles input text, chat history, loading state, history navigation, and form submission.
|
|
|
|
| 23 |
setLoading(true);
|
| 24 |
let success = false;
|
| 25 |
try {
|
| 26 |
+
const sendTextResponse = await axios.post('http://127.0.0.1:5000/sendText', { text });
|
| 27 |
+
const sendQuestionsResponse = await axios.post('http://127.0.0.1:5000/sendQuestions', { text });
|
| 28 |
|
| 29 |
const newChatItem = {
|
| 30 |
question: text,
|
|
|
|
| 59 |
setChatHistory([...chatHistory]);
|
| 60 |
|
| 61 |
try {
|
| 62 |
+
const response = await axios.post('http://127.0.0.1:5000/sendText', {
|
| 63 |
text: chatHistory[chatItemIndex].followUps[followUpIndex].text
|
| 64 |
});
|
| 65 |
|
| 66 |
+
// Update the response and loading state
|
| 67 |
chatHistory[chatItemIndex].followUps[followUpIndex].response = response.data.output;
|
| 68 |
chatHistory[chatItemIndex].followUps[followUpIndex].loading = false;
|
| 69 |
|
| 70 |
+
// Get new follow-up questions based on the follow-up response.
|
| 71 |
+
const sendQuestionsResponse = await axios.post('http://127.0.0.1:5000/sendQuestions', { text: response.data.output });
|
| 72 |
|
| 73 |
+
// Add to FollowUp array
|
| 74 |
const newFollowUps = sendQuestionsResponse.data.output.followUps.map(followUp => ({
|
| 75 |
text: followUp,
|
| 76 |
response: null,
|
|
|
|
| 151 |
};
|
| 152 |
|
| 153 |
}
|
|
|
web_app/frontend/src/pages/AboutPage.jsx
CHANGED
|
@@ -2,23 +2,25 @@ import React from 'react';
|
|
| 2 |
import { Container, Typography, Button, Grid, styled, Paper} from '@mui/material';
|
| 3 |
import { Link } from 'react-router-dom';
|
| 4 |
import { Box } from '@mui/system';
|
|
|
|
| 5 |
import Footer from '../components/Footer';
|
| 6 |
|
| 7 |
const AboutPage = () => {
|
| 8 |
return (
|
| 9 |
<>
|
|
|
|
| 10 |
<Box
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
/>
|
| 23 |
<Box sx={{
|
| 24 |
position: 'absolute',
|
|
|
|
| 2 |
import { Container, Typography, Button, Grid, styled, Paper} from '@mui/material';
|
| 3 |
import { Link } from 'react-router-dom';
|
| 4 |
import { Box } from '@mui/system';
|
| 5 |
+
import Navbar from '../components/Navbar';
|
| 6 |
import Footer from '../components/Footer';
|
| 7 |
|
| 8 |
const AboutPage = () => {
|
| 9 |
return (
|
| 10 |
<>
|
| 11 |
+
<Navbar />
|
| 12 |
<Box
|
| 13 |
+
sx={{
|
| 14 |
+
position: 'absolute',
|
| 15 |
+
top: 0,
|
| 16 |
+
left: 0,
|
| 17 |
+
minHeight: '100vh',
|
| 18 |
+
width: '100%',
|
| 19 |
+
backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
|
| 20 |
+
backgroundRepeat: 'no-repeat',
|
| 21 |
+
backgroundSize: 'cover',
|
| 22 |
+
zIndex: -1
|
| 23 |
+
}}
|
| 24 |
/>
|
| 25 |
<Box sx={{
|
| 26 |
position: 'absolute',
|
web_app/frontend/src/pages/ChatBot.jsx
DELETED
|
@@ -1,76 +0,0 @@
|
|
| 1 |
-
// Import required dependencies and components
|
| 2 |
-
import React, { useState} from 'react';
|
| 3 |
-
import { Box } from '@mui/material';
|
| 4 |
-
import useChatHandler from '../hooks/useChat.js';
|
| 5 |
-
import ChatHistory from '../components/ChatHistory.jsx';
|
| 6 |
-
import ChatInput from '../components/ChatInput.jsx';
|
| 7 |
-
import StartCard from '../components/StartCard.jsx';
|
| 8 |
-
|
| 9 |
-
// The ChatBot component which manages and displays the chat feature
|
| 10 |
-
function ChatBot() {
|
| 11 |
-
// State to hold the current index in chat history navigation, initialized to -1
|
| 12 |
-
const [historyIndex, setHistoryIndex] = useState(-1);
|
| 13 |
-
// State to hold whether we are currently navigating through history, initialized to false
|
| 14 |
-
const [isHistoryNavigation, setIsHistoryNavigation] = useState(false);
|
| 15 |
-
|
| 16 |
-
// Hook to handle chat logic, returns various state and handler functions
|
| 17 |
-
const {
|
| 18 |
-
inputText,
|
| 19 |
-
handleInputChange,
|
| 20 |
-
chatHistory,
|
| 21 |
-
loading,
|
| 22 |
-
handleSubmit,
|
| 23 |
-
handleKeyDown,
|
| 24 |
-
clearChatHistory,
|
| 25 |
-
handleFollowUp, // include handleFollowUp here
|
| 26 |
-
} = useChatHandler();
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
// Function to submit a message, takes an event and prevents the page from refreshing
|
| 30 |
-
const handleFormSubmit = (e) => {
|
| 31 |
-
e.preventDefault();
|
| 32 |
-
handleSubmit(inputText); // Pass the current input text to the handleSubmit function
|
| 33 |
-
};
|
| 34 |
-
|
| 35 |
-
return (
|
| 36 |
-
<>
|
| 37 |
-
{/* Container for the gradient background */}
|
| 38 |
-
<Box
|
| 39 |
-
sx={{
|
| 40 |
-
position: 'absolute',
|
| 41 |
-
top: 0,
|
| 42 |
-
left: 0,
|
| 43 |
-
minHeight: '100vh',
|
| 44 |
-
width: '100%',
|
| 45 |
-
backgroundImage: 'linear-gradient(to bottom, #4568dc, #b06ab3)',
|
| 46 |
-
backgroundRepeat: 'no-repeat',
|
| 47 |
-
backgroundSize: 'cover',
|
| 48 |
-
zIndex: -1
|
| 49 |
-
}}
|
| 50 |
-
/>
|
| 51 |
-
|
| 52 |
-
{/* Container for the chat history */}
|
| 53 |
-
<Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '100vh', mt: 6 }}>
|
| 54 |
-
{/* Display the StartCard component only when the chat history is empty and the chat is not loading */}
|
| 55 |
-
{chatHistory.length === 0 && !loading && <StartCard inputText={inputText} />}
|
| 56 |
-
|
| 57 |
-
{/* Chat history component, displays past messages */}
|
| 58 |
-
<ChatHistory chatHistory={chatHistory} handleFollowUp={handleFollowUp} />
|
| 59 |
-
</Box>
|
| 60 |
-
|
| 61 |
-
{/* Chat input component, where users type and submit their messages */}
|
| 62 |
-
<ChatInput
|
| 63 |
-
inputText={inputText}
|
| 64 |
-
handleInputChange={handleInputChange}
|
| 65 |
-
handleKeyDown={handleKeyDown}
|
| 66 |
-
handleFormSubmit={handleFormSubmit}
|
| 67 |
-
loading={loading}
|
| 68 |
-
clearChatHistory={clearChatHistory}
|
| 69 |
-
/>
|
| 70 |
-
</>
|
| 71 |
-
);
|
| 72 |
-
}
|
| 73 |
-
|
| 74 |
-
// Export the ChatBot component
|
| 75 |
-
export default ChatBot;
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
web_app/frontend/src/pages/ChatPage.jsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
-
import React from 'react';
|
| 2 |
-
import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText } from '@mui/material';
|
| 3 |
import { Box } from '@mui/system';
|
| 4 |
import { Link, Outlet } from 'react-router-dom';
|
| 5 |
import ChatIcon from '@mui/icons-material/Chat';
|
|
@@ -7,6 +7,27 @@ import PieChartIcon from '@mui/icons-material/PieChart';
|
|
| 7 |
import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
|
| 8 |
import BookIcon from '@mui/icons-material/Book';
|
| 9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
const ChatPage = () => {
|
| 11 |
|
| 12 |
const services = [
|
|
@@ -16,74 +37,176 @@ const ChatPage = () => {
|
|
| 16 |
{ title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
|
| 17 |
];
|
| 18 |
|
| 19 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
return (
|
| 22 |
<>
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
|
|
|
| 47 |
<Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
|
| 48 |
<Grid item xs={3}>
|
| 49 |
-
<Box
|
| 50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
{menuOptions.map((option, index) => (
|
| 52 |
-
<ListItem button key={index}>
|
| 53 |
-
<
|
|
|
|
|
|
|
|
|
|
| 54 |
</ListItem>
|
| 55 |
))}
|
| 56 |
</List>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
<List
|
| 58 |
-
sx={{
|
| 59 |
textAlign: 'center',
|
| 60 |
backgroundColor:"white",
|
| 61 |
borderRadius:"15px",
|
| 62 |
}}
|
| 63 |
>
|
| 64 |
<ListItem button>
|
| 65 |
-
|
| 66 |
</ListItem>
|
| 67 |
</List>
|
| 68 |
-
|
| 69 |
-
|
| 70 |
</Box>
|
| 71 |
</Grid>
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
</Box>
|
| 81 |
</Grid>
|
| 82 |
</Grid>
|
| 83 |
</Box>
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
};
|
| 88 |
|
| 89 |
export default ChatPage;
|
|
|
|
| 1 |
+
import React, { useState } from 'react';
|
| 2 |
+
import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
|
| 3 |
import { Box } from '@mui/system';
|
| 4 |
import { Link, Outlet } from 'react-router-dom';
|
| 5 |
import ChatIcon from '@mui/icons-material/Chat';
|
|
|
|
| 7 |
import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
|
| 8 |
import BookIcon from '@mui/icons-material/Book';
|
| 9 |
|
| 10 |
+
import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
|
| 11 |
+
import SettingsIcon from '@mui/icons-material/Settings';
|
| 12 |
+
import PersonIcon from '@mui/icons-material/Person';
|
| 13 |
+
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
|
| 14 |
+
import SendIcon from '@mui/icons-material/Send';
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
import Navbar from '../components/Navbar';
|
| 18 |
+
|
| 19 |
+
import useChatHandler from '../hooks/useChat.js';
|
| 20 |
+
|
| 21 |
+
import ChatHistory from '../components/ChatHistory';
|
| 22 |
+
import ChatInput from '../components/ChatInput';
|
| 23 |
+
import StartCard from '../components/StartCard';
|
| 24 |
+
import handleSendEmail from '../components/emailService';
|
| 25 |
+
|
| 26 |
+
import './scrollbar.css';
|
| 27 |
+
|
| 28 |
+
import axios from 'axios';
|
| 29 |
+
|
| 30 |
+
|
| 31 |
const ChatPage = () => {
|
| 32 |
|
| 33 |
const services = [
|
|
|
|
| 37 |
{ title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
|
| 38 |
];
|
| 39 |
|
| 40 |
+
const handleSendEmail = async (email) => {
|
| 41 |
+
try {
|
| 42 |
+
const response = await axios.post('http://localhost:5000/exportChat', {
|
| 43 |
+
email: email
|
| 44 |
+
});
|
| 45 |
+
|
| 46 |
+
// You can handle the response here if needed.
|
| 47 |
+
console.log(response.data);
|
| 48 |
+
|
| 49 |
+
} catch (error) {
|
| 50 |
+
console.error("Error sending email:", error);
|
| 51 |
+
}
|
| 52 |
+
};
|
| 53 |
+
|
| 54 |
+
const menuOptions = [
|
| 55 |
+
{ title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
|
| 56 |
+
{ title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
|
| 57 |
+
{ title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 58 |
+
{ title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 59 |
+
];
|
| 60 |
+
|
| 61 |
+
const [historyIndex, setHistoryIndex] = useState(-1);
|
| 62 |
+
const [isHistoryNavigation, setIsHistoryNavigation] = useState(false);
|
| 63 |
|
| 64 |
+
const {
|
| 65 |
+
inputText,
|
| 66 |
+
handleInputChange,
|
| 67 |
+
chatHistory,
|
| 68 |
+
loading,
|
| 69 |
+
handleSubmit,
|
| 70 |
+
handleKeyDown,
|
| 71 |
+
clearChatHistory,
|
| 72 |
+
handleFollowUp,
|
| 73 |
+
} = useChatHandler();
|
| 74 |
+
|
| 75 |
+
const handleFormSubmit = (e) => {
|
| 76 |
+
e.preventDefault();
|
| 77 |
+
handleSubmit(inputText);
|
| 78 |
+
};
|
| 79 |
+
|
| 80 |
return (
|
| 81 |
<>
|
| 82 |
+
<Navbar />
|
| 83 |
+
<Box
|
| 84 |
+
sx={{
|
| 85 |
+
position: 'absolute',
|
| 86 |
+
top: 0,
|
| 87 |
+
left: 0,
|
| 88 |
+
minHeight: '100vh',
|
| 89 |
+
width: '100%',
|
| 90 |
+
backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
|
| 91 |
+
backgroundRepeat: 'no-repeat',
|
| 92 |
+
backgroundSize: 'cover',
|
| 93 |
+
zIndex: -1
|
| 94 |
+
}}
|
| 95 |
+
/>
|
| 96 |
+
<Box
|
| 97 |
+
sx={{
|
| 98 |
+
position: 'absolute',
|
| 99 |
+
top: '84px',
|
| 100 |
+
left: '10px',
|
| 101 |
+
right: '10px',
|
| 102 |
+
height: '85vh',
|
| 103 |
+
backgroundColor:'transparent',
|
| 104 |
+
borderRadius:'15px',
|
| 105 |
+
}}
|
| 106 |
+
>
|
| 107 |
<Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
|
| 108 |
<Grid item xs={3}>
|
| 109 |
+
<Box
|
| 110 |
+
sx={{
|
| 111 |
+
borderRadius: '15px',
|
| 112 |
+
p:2,
|
| 113 |
+
marginRight:'10px',
|
| 114 |
+
height:'calc(100%)',
|
| 115 |
+
backgroundColor: 'rgba(255, 255, 255, 0.7)',
|
| 116 |
+
boxSizing: 'border-box',
|
| 117 |
+
display: 'flex',
|
| 118 |
+
flexDirection: 'column',
|
| 119 |
+
justifyContent: 'space-between'
|
| 120 |
+
}}
|
| 121 |
+
>
|
| 122 |
+
<List sx={{backgroundColor:"white", borderRadius:"15px", mb: 2}}>
|
| 123 |
{menuOptions.map((option, index) => (
|
| 124 |
+
<ListItem button key={index} component={Link} to={option.link}>
|
| 125 |
+
<ListItemIcon>
|
| 126 |
+
{option.icon}
|
| 127 |
+
</ListItemIcon>
|
| 128 |
+
<ListItemText primary={option.title} />
|
| 129 |
</ListItem>
|
| 130 |
))}
|
| 131 |
</List>
|
| 132 |
+
<Box
|
| 133 |
+
sx={{
|
| 134 |
+
display: 'flex',
|
| 135 |
+
flexDirection: 'column',
|
| 136 |
+
alignItems: 'flex-start',
|
| 137 |
+
p:1,
|
| 138 |
+
backgroundColor:'white',
|
| 139 |
+
borderRadius: '15px',
|
| 140 |
+
marginBottom: 'auto' // Pushes items below it to the bottom
|
| 141 |
+
}}
|
| 142 |
+
>
|
| 143 |
+
<Typography variant="body2" sx={{fontWeight: 'bold', mb: 1, paddingLeft: '3px'}}>
|
| 144 |
+
Export chat as PDF
|
| 145 |
+
</Typography>
|
| 146 |
+
<Box sx={{width: '100%', display: 'flex', alignItems: 'center'}}>
|
| 147 |
+
<input
|
| 148 |
+
type="email"
|
| 149 |
+
placeholder="Enter your email"
|
| 150 |
+
style={{
|
| 151 |
+
flexGrow: 1,
|
| 152 |
+
padding: '8px 12px',
|
| 153 |
+
border: '1px solid #ccc',
|
| 154 |
+
borderRadius: '5px',
|
| 155 |
+
marginRight: '10px'
|
| 156 |
+
}}
|
| 157 |
+
/>
|
| 158 |
+
<IconButton color="primary" onClick={() => handleSendEmail(document.querySelector('input[type="email"]').value)}>
|
| 159 |
+
<SendIcon />
|
| 160 |
+
</IconButton>
|
| 161 |
+
</Box>
|
| 162 |
+
</Box>
|
| 163 |
<List
|
| 164 |
+
sx={{
|
| 165 |
textAlign: 'center',
|
| 166 |
backgroundColor:"white",
|
| 167 |
borderRadius:"15px",
|
| 168 |
}}
|
| 169 |
>
|
| 170 |
<ListItem button>
|
| 171 |
+
<ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
|
| 172 |
</ListItem>
|
| 173 |
</List>
|
|
|
|
|
|
|
| 174 |
</Box>
|
| 175 |
</Grid>
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
<Grid item container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
|
| 179 |
+
<Box sx={{
|
| 180 |
+
borderRadius: '15px',
|
| 181 |
+
p: 2,
|
| 182 |
+
marginLeft: '10px',
|
| 183 |
+
flexGrow: 1,
|
| 184 |
+
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
| 185 |
+
boxSizing: 'border-box',
|
| 186 |
+
display: 'flex', // Make this a flex container
|
| 187 |
+
flexDirection: 'column' // Column direction
|
| 188 |
+
}}>
|
| 189 |
+
<Box sx={{ flexGrow: 1, overflow: 'auto' }} className="custom-scrollbar">
|
| 190 |
+
{chatHistory.length === 0 && !loading && <StartCard inputText={inputText} />}
|
| 191 |
+
<ChatHistory chatHistory={chatHistory} handleFollowUp={handleFollowUp} />
|
| 192 |
+
</Box>
|
| 193 |
+
<Box sx={{ mt:'10px' }}>
|
| 194 |
+
<ChatInput
|
| 195 |
+
inputText={inputText}
|
| 196 |
+
handleInputChange={handleInputChange}
|
| 197 |
+
handleKeyDown={handleKeyDown}
|
| 198 |
+
handleFormSubmit={handleFormSubmit}
|
| 199 |
+
loading={loading}
|
| 200 |
+
clearChatHistory={clearChatHistory}
|
| 201 |
+
/>
|
| 202 |
+
</Box>
|
| 203 |
</Box>
|
| 204 |
</Grid>
|
| 205 |
</Grid>
|
| 206 |
</Box>
|
| 207 |
+
<Outlet />
|
| 208 |
+
</>
|
| 209 |
+
);
|
| 210 |
};
|
| 211 |
|
| 212 |
export default ChatPage;
|
web_app/frontend/src/pages/CityPage.jsx
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useEffect, useState } from 'react';
|
| 2 |
+
import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
|
| 3 |
+
import { Box } from '@mui/system';
|
| 4 |
+
import { Link, Outlet } from 'react-router-dom';
|
| 5 |
+
import ChatIcon from '@mui/icons-material/Chat';
|
| 6 |
+
import PieChartIcon from '@mui/icons-material/PieChart';
|
| 7 |
+
import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
|
| 8 |
+
import MapIcon from '@mui/icons-material/Map';
|
| 9 |
+
import BookIcon from '@mui/icons-material/Book';
|
| 10 |
+
|
| 11 |
+
import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
|
| 12 |
+
import SettingsIcon from '@mui/icons-material/Settings';
|
| 13 |
+
import PersonIcon from '@mui/icons-material/Person';
|
| 14 |
+
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
|
| 15 |
+
|
| 16 |
+
import Navbar from '../components/Navbar';
|
| 17 |
+
import Map3D from '../components/Map3D';
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
const CityPage = () => {
|
| 21 |
+
|
| 22 |
+
const services = [
|
| 23 |
+
{ title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
|
| 24 |
+
{ title: 'Statistics and Charts', link: '/dashboard/stats', icon: <PieChartIcon style={{ fontSize: 60 }} /> },
|
| 25 |
+
{ title: '3D Models', link: '/dashboard/3dmodels', icon: <ThreeDRotationIcon style={{ fontSize: 60 }} /> },
|
| 26 |
+
{ title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
|
| 27 |
+
];
|
| 28 |
+
|
| 29 |
+
const menuOptions = [
|
| 30 |
+
{ title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
|
| 31 |
+
{ title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
|
| 32 |
+
{ title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 33 |
+
{ title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 34 |
+
];
|
| 35 |
+
|
| 36 |
+
return (
|
| 37 |
+
<>
|
| 38 |
+
<Navbar />
|
| 39 |
+
<Box
|
| 40 |
+
sx={{
|
| 41 |
+
position: 'absolute',
|
| 42 |
+
top: 0,
|
| 43 |
+
left: 0,
|
| 44 |
+
minHeight: '100vh',
|
| 45 |
+
width: '100%',
|
| 46 |
+
backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
|
| 47 |
+
backgroundRepeat: 'no-repeat',
|
| 48 |
+
backgroundSize: 'cover',
|
| 49 |
+
zIndex: -1
|
| 50 |
+
}}
|
| 51 |
+
/>
|
| 52 |
+
<Box
|
| 53 |
+
sx={{
|
| 54 |
+
position: 'absolute',
|
| 55 |
+
top: '84px',
|
| 56 |
+
left: '10px',
|
| 57 |
+
right: '10px',
|
| 58 |
+
height: '85vh',
|
| 59 |
+
backgroundColor:'transparent',
|
| 60 |
+
borderRadius:'15px',
|
| 61 |
+
}}
|
| 62 |
+
>
|
| 63 |
+
<Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
|
| 64 |
+
<Grid item xs={3}>
|
| 65 |
+
<Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
|
| 66 |
+
<List sx={{backgroundColor:"white", borderRadius:"15px"}}>
|
| 67 |
+
{menuOptions.map((option, index) => (
|
| 68 |
+
<ListItem button key={index} component={Link} to={option.link}>
|
| 69 |
+
<ListItemIcon>
|
| 70 |
+
{option.icon}
|
| 71 |
+
</ListItemIcon>
|
| 72 |
+
<ListItemText primary={option.title} />
|
| 73 |
+
</ListItem>
|
| 74 |
+
))}
|
| 75 |
+
</List>
|
| 76 |
+
<List
|
| 77 |
+
sx={{
|
| 78 |
+
textAlign: 'center',
|
| 79 |
+
backgroundColor:"white",
|
| 80 |
+
borderRadius:"15px",
|
| 81 |
+
}}
|
| 82 |
+
>
|
| 83 |
+
<ListItem button>
|
| 84 |
+
<ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
|
| 85 |
+
</ListItem>
|
| 86 |
+
</List>
|
| 87 |
+
</Box>
|
| 88 |
+
</Grid>
|
| 89 |
+
<Grid item container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
|
| 90 |
+
<Box sx={{
|
| 91 |
+
borderRadius: '15px',
|
| 92 |
+
p: 2,
|
| 93 |
+
marginLeft: '10px',
|
| 94 |
+
flexGrow: 1,
|
| 95 |
+
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
| 96 |
+
boxSizing: 'border-box',
|
| 97 |
+
display: 'flex',
|
| 98 |
+
width: '100%',
|
| 99 |
+
height: '100%',
|
| 100 |
+
}}>
|
| 101 |
+
<Map3D />
|
| 102 |
+
</Box>
|
| 103 |
+
</Grid>
|
| 104 |
+
</Grid>
|
| 105 |
+
</Box>
|
| 106 |
+
<Outlet />
|
| 107 |
+
</>
|
| 108 |
+
);
|
| 109 |
+
|
| 110 |
+
}
|
| 111 |
+
export default CityPage;
|
| 112 |
+
|
web_app/frontend/src/pages/ContactPage.jsx
CHANGED
|
@@ -2,23 +2,25 @@ import React from 'react';
|
|
| 2 |
import { Container, Typography, Button } from '@mui/material';
|
| 3 |
import { Link } from 'react-router-dom';
|
| 4 |
import { Box } from '@mui/system';
|
|
|
|
| 5 |
import Footer from '../components/Footer';
|
| 6 |
|
| 7 |
const ContactPage = () => {
|
| 8 |
return (
|
| 9 |
<>
|
|
|
|
| 10 |
<Box
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
/>
|
| 23 |
<Box sx={{
|
| 24 |
position: 'absolute',
|
|
|
|
| 2 |
import { Container, Typography, Button } from '@mui/material';
|
| 3 |
import { Link } from 'react-router-dom';
|
| 4 |
import { Box } from '@mui/system';
|
| 5 |
+
import Navbar from '../components/Navbar';
|
| 6 |
import Footer from '../components/Footer';
|
| 7 |
|
| 8 |
const ContactPage = () => {
|
| 9 |
return (
|
| 10 |
<>
|
| 11 |
+
<Navbar />
|
| 12 |
<Box
|
| 13 |
+
sx={{
|
| 14 |
+
position: 'absolute',
|
| 15 |
+
top: 0,
|
| 16 |
+
left: 0,
|
| 17 |
+
minHeight: '100vh',
|
| 18 |
+
width: '100%',
|
| 19 |
+
backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
|
| 20 |
+
backgroundRepeat: 'no-repeat',
|
| 21 |
+
backgroundSize: 'cover',
|
| 22 |
+
zIndex: -1
|
| 23 |
+
}}
|
| 24 |
/>
|
| 25 |
<Box sx={{
|
| 26 |
position: 'absolute',
|
web_app/frontend/src/pages/DashboardPage-new.jsx
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useEffect, useState } from 'react';
|
| 2 |
+
import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText } from '@mui/material';
|
| 3 |
+
import { Box } from '@mui/system';
|
| 4 |
+
import { Link } from 'react-router-dom';
|
| 5 |
+
import ChatIcon from '@mui/icons-material/Chat';
|
| 6 |
+
import PieChartIcon from '@mui/icons-material/PieChart';
|
| 7 |
+
import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
|
| 8 |
+
import BookIcon from '@mui/icons-material/Book';
|
| 9 |
+
import './DashboardPage.css';
|
| 10 |
+
import Navbar from '../components/Navbar';
|
| 11 |
+
|
| 12 |
+
const DashboardPage = () => {
|
| 13 |
+
|
| 14 |
+
const services = [
|
| 15 |
+
{ title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon className="services-card-icon" /> },
|
| 16 |
+
{ title: 'Statistics and Charts', link: '/dashboard/stats', icon: <PieChartIcon className="services-card-icon" /> },
|
| 17 |
+
{ title: '3D Models', link: '/dashboard/3dmodels', icon: <ThreeDRotationIcon className="services-card-icon" /> },
|
| 18 |
+
{ title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon className="services-card-icon" /> },
|
| 19 |
+
];
|
| 20 |
+
|
| 21 |
+
const menuOptions = ["Settings", "Profile", "Sign out"];
|
| 22 |
+
|
| 23 |
+
const [colors, setColors] = useState({
|
| 24 |
+
bgColor: '',
|
| 25 |
+
fontColor: '',
|
| 26 |
+
});
|
| 27 |
+
|
| 28 |
+
useEffect(() => {
|
| 29 |
+
document.documentElement.classList.add('light-theme');
|
| 30 |
+
|
| 31 |
+
const updateColors = () => {
|
| 32 |
+
const computedStyle = getComputedStyle(document.documentElement);
|
| 33 |
+
const bgColor = computedStyle.getPropertyValue('--primary').trim();
|
| 34 |
+
const fontColor = computedStyle.getPropertyValue('--text').trim();
|
| 35 |
+
|
| 36 |
+
setColors({ bgColor, fontColor });
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
+
const toggleTheme = (event) => {
|
| 40 |
+
if (event.ctrlKey && event.key === 'q') {
|
| 41 |
+
document.documentElement.classList.toggle('light-theme');
|
| 42 |
+
document.documentElement.classList.toggle('dark-theme');
|
| 43 |
+
|
| 44 |
+
updateColors();
|
| 45 |
+
}
|
| 46 |
+
};
|
| 47 |
+
|
| 48 |
+
window.addEventListener('keydown', toggleTheme);
|
| 49 |
+
updateColors();
|
| 50 |
+
return () => {
|
| 51 |
+
window.removeEventListener('keydown', toggleTheme);
|
| 52 |
+
};
|
| 53 |
+
}, []);
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
return (
|
| 57 |
+
<>
|
| 58 |
+
<Navbar bgColor={colors.bgColor} fontColor={"#102317"}/>
|
| 59 |
+
<Box className="dashboard-background" />
|
| 60 |
+
<Box className="main-container">
|
| 61 |
+
<Grid container className="main-grid">
|
| 62 |
+
|
| 63 |
+
{/* Menu Grid */}
|
| 64 |
+
<Grid item xs={3} className="menu-grid">
|
| 65 |
+
<Box className="menu-box">
|
| 66 |
+
<List className="menu-list-1">
|
| 67 |
+
{menuOptions.map((option, index) => (
|
| 68 |
+
<ListItem button key={index}>
|
| 69 |
+
<ListItemText primary={option} />
|
| 70 |
+
</ListItem>
|
| 71 |
+
))}
|
| 72 |
+
</List>
|
| 73 |
+
<List className="menu-list-2">
|
| 74 |
+
<ListItem button>
|
| 75 |
+
<ListItemText primary={<Typography className="menu-list-item">Terms and Conditions</Typography>} />
|
| 76 |
+
</ListItem>
|
| 77 |
+
</List>
|
| 78 |
+
</Box>
|
| 79 |
+
</Grid>
|
| 80 |
+
|
| 81 |
+
<Grid item container spacing={0} className="services-grid" xs={9}>
|
| 82 |
+
{services.map((service, index) => (
|
| 83 |
+
<Grid item xs={6} className={"services-grid-item"} key={index}>
|
| 84 |
+
<Box className={`services-box services-box-${index}`}>
|
| 85 |
+
<Card className={"services-card"}>
|
| 86 |
+
<CardActionArea component={Link} to={service.link} className={"services-card-action-area"}>
|
| 87 |
+
<CardContent className="services-card-content">
|
| 88 |
+
{service.icon}
|
| 89 |
+
<Typography variant="body1" className="services-card-typography">{service.title}</Typography>
|
| 90 |
+
</CardContent>
|
| 91 |
+
</CardActionArea>
|
| 92 |
+
</Card>
|
| 93 |
+
</Box>
|
| 94 |
+
</Grid>
|
| 95 |
+
))}
|
| 96 |
+
</Grid>
|
| 97 |
+
</Grid>
|
| 98 |
+
</Box>
|
| 99 |
+
</>
|
| 100 |
+
);
|
| 101 |
+
|
| 102 |
+
};
|
| 103 |
+
export default DashboardPage;
|
| 104 |
+
|
web_app/frontend/src/pages/DashboardPage-old.jsx
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react';
|
| 2 |
+
import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
|
| 3 |
+
import { Box } from '@mui/system';
|
| 4 |
+
import { Link } from 'react-router-dom';
|
| 5 |
+
import ChatIcon from '@mui/icons-material/Chat';
|
| 6 |
+
import PieChartIcon from '@mui/icons-material/PieChart';
|
| 7 |
+
import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
|
| 8 |
+
import MapIcon from '@mui/icons-material/Map';
|
| 9 |
+
import BookIcon from '@mui/icons-material/Book';
|
| 10 |
+
|
| 11 |
+
import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
|
| 12 |
+
import SettingsIcon from '@mui/icons-material/Settings';
|
| 13 |
+
import PersonIcon from '@mui/icons-material/Person';
|
| 14 |
+
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
|
| 15 |
+
|
| 16 |
+
import Navbar from '../components/Navbar';
|
| 17 |
+
// import './DashboardPage.css';
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
const DashboardPage = () => {
|
| 21 |
+
|
| 22 |
+
const services = [
|
| 23 |
+
{ title: 'Chat Assistant', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
|
| 24 |
+
{ title: 'Reports and plans', link: '/dashboard/reports', icon: <PieChartIcon style={{ fontSize: 60 }} /> },
|
| 25 |
+
{ title: 'My city in 3D', link: '/dashboard/city', icon: <MapIcon style={{ fontSize: 60 }} /> },
|
| 26 |
+
{ title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
|
| 27 |
+
];
|
| 28 |
+
|
| 29 |
+
const menuOptions = [
|
| 30 |
+
{ title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
|
| 31 |
+
{ title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
|
| 32 |
+
{ title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 33 |
+
{ title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 34 |
+
];
|
| 35 |
+
|
| 36 |
+
return (
|
| 37 |
+
<>
|
| 38 |
+
<Navbar />
|
| 39 |
+
<Box
|
| 40 |
+
sx={{
|
| 41 |
+
position: 'absolute',
|
| 42 |
+
top: 0,
|
| 43 |
+
left: 0,
|
| 44 |
+
minHeight: '100vh',
|
| 45 |
+
width: '100%',
|
| 46 |
+
backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
|
| 47 |
+
backgroundRepeat: 'no-repeat',
|
| 48 |
+
backgroundSize: 'cover',
|
| 49 |
+
zIndex: -1
|
| 50 |
+
}}
|
| 51 |
+
/>
|
| 52 |
+
<Box
|
| 53 |
+
sx={{
|
| 54 |
+
position: 'absolute',
|
| 55 |
+
top: '84px',
|
| 56 |
+
left: '10px',
|
| 57 |
+
right: '10px',
|
| 58 |
+
height: '85vh',
|
| 59 |
+
backgroundColor:'transparent',
|
| 60 |
+
borderRadius:'15px',
|
| 61 |
+
}}
|
| 62 |
+
>
|
| 63 |
+
<Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
|
| 64 |
+
{/* Menu Grid */}
|
| 65 |
+
<Grid item xs={3}>
|
| 66 |
+
<Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
|
| 67 |
+
<List sx={{backgroundColor:"white", borderRadius:"15px"}}>
|
| 68 |
+
{menuOptions.map((option, index) => (
|
| 69 |
+
<ListItem button key={index} component={Link} to={option.link}>
|
| 70 |
+
<ListItemIcon>
|
| 71 |
+
{option.icon}
|
| 72 |
+
</ListItemIcon>
|
| 73 |
+
<ListItemText primary={option.title} />
|
| 74 |
+
</ListItem>
|
| 75 |
+
))}
|
| 76 |
+
</List>
|
| 77 |
+
<List
|
| 78 |
+
sx={{
|
| 79 |
+
textAlign: 'center',
|
| 80 |
+
backgroundColor:"white",
|
| 81 |
+
borderRadius:"15px",
|
| 82 |
+
}}
|
| 83 |
+
>
|
| 84 |
+
<ListItem button>
|
| 85 |
+
<ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
|
| 86 |
+
</ListItem>
|
| 87 |
+
</List>
|
| 88 |
+
</Box>
|
| 89 |
+
</Grid>
|
| 90 |
+
|
| 91 |
+
{/* Services Grid */}
|
| 92 |
+
<Grid item container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
|
| 93 |
+
{services.map((service, index) => (
|
| 94 |
+
<Grid item xs={6} sx={{display:'flex', flexDirection:'column'}} key={index}>
|
| 95 |
+
<Box sx={{
|
| 96 |
+
borderRadius: '15px',
|
| 97 |
+
p: 2,
|
| 98 |
+
marginLeft: '10px',
|
| 99 |
+
marginRight: (index % 2 !== 0) ? '0px' : '10px',
|
| 100 |
+
marginBottom: (index < 2) ? '10px' : '0px',
|
| 101 |
+
marginTop: (index >= 2) ? '10px' : '0px',
|
| 102 |
+
flexGrow: 1,
|
| 103 |
+
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
| 104 |
+
boxSizing: 'border-box'
|
| 105 |
+
}}>
|
| 106 |
+
<Card sx={{height: '100%', borderRadius: '15px'}}>
|
| 107 |
+
<CardActionArea component={Link} to={service.link} sx={{height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column'}}>
|
| 108 |
+
<CardContent sx={{textAlign: 'center'}}>
|
| 109 |
+
{service.icon}
|
| 110 |
+
<Typography variant="body1" sx={{mt: 1}}>{service.title}</Typography>
|
| 111 |
+
</CardContent>
|
| 112 |
+
</CardActionArea>
|
| 113 |
+
</Card>
|
| 114 |
+
</Box>
|
| 115 |
+
</Grid>
|
| 116 |
+
))}
|
| 117 |
+
</Grid>
|
| 118 |
+
</Grid>
|
| 119 |
+
</Box>
|
| 120 |
+
</>
|
| 121 |
+
);
|
| 122 |
+
};
|
| 123 |
+
|
| 124 |
+
export default DashboardPage;
|
| 125 |
+
|
web_app/frontend/src/pages/DashboardPage.css
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:root.dark-theme {
|
| 2 |
+
--text: #f4faf7;
|
| 3 |
+
--background: #102317;
|
| 4 |
+
--primary: #aae4c7;
|
| 5 |
+
--secondary: #060b0e;
|
| 6 |
+
--accent: #a1c2d7;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
:root.light-theme {
|
| 10 |
+
--text: #102317;
|
| 11 |
+
--background: #f4faf7;
|
| 12 |
+
--primary: #aae4c7;
|
| 13 |
+
--secondary: #c6dae6;
|
| 14 |
+
--accent: #437a9c;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
/* MAIN CONTAINER*/
|
| 18 |
+
|
| 19 |
+
.dashboard-background {
|
| 20 |
+
position: absolute;
|
| 21 |
+
top: 0;
|
| 22 |
+
left: 0;
|
| 23 |
+
min-height: 100vh;
|
| 24 |
+
width: 100%;
|
| 25 |
+
background-color: var(--background);
|
| 26 |
+
background-repeat: no-repeat;
|
| 27 |
+
background-size: cover;
|
| 28 |
+
z-index: -1;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
.main-container {
|
| 32 |
+
position: absolute;
|
| 33 |
+
top: 84px;
|
| 34 |
+
left: 10px;
|
| 35 |
+
right: 10px;
|
| 36 |
+
height: 85vh;
|
| 37 |
+
background-color: transparent;
|
| 38 |
+
border-radius: 15px;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
.main-grid {
|
| 42 |
+
background-color: transparent;
|
| 43 |
+
flex-grow: 1;
|
| 44 |
+
height: 100%;
|
| 45 |
+
border-radius: 15px;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
/* MENU */
|
| 50 |
+
|
| 51 |
+
/* .menu-grid {
|
| 52 |
+
} */
|
| 53 |
+
|
| 54 |
+
.menu-box {
|
| 55 |
+
border-radius: 15px;
|
| 56 |
+
padding: 10px;
|
| 57 |
+
margin-right: 10px;
|
| 58 |
+
height: calc(100%);
|
| 59 |
+
background-color: var(--accent);
|
| 60 |
+
box-sizing: border-box;
|
| 61 |
+
display: flex;
|
| 62 |
+
flex-direction: column;
|
| 63 |
+
justify-content: space-between;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
.menu-list-1 {
|
| 67 |
+
background-color: var(--secondary);
|
| 68 |
+
color: var(--text);
|
| 69 |
+
border-radius: 15px;
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
.menu-list-2 {
|
| 73 |
+
text-align: center;
|
| 74 |
+
background-color: var(--secondary);
|
| 75 |
+
color: var(--text);
|
| 76 |
+
border-radius: 15px;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
.menu-list-item {
|
| 80 |
+
font-size: 14px;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
/* SERVICE DASHBOARD */
|
| 84 |
+
|
| 85 |
+
.services-grid {
|
| 86 |
+
height: 100%;
|
| 87 |
+
box-sizing: border-box;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
.services-grid-item {
|
| 91 |
+
display: flex;
|
| 92 |
+
flex-direction: column;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
.services-box {
|
| 96 |
+
border-radius: 15px;
|
| 97 |
+
padding: 10px;
|
| 98 |
+
margin-left: 10px;
|
| 99 |
+
flex-grow: 1;
|
| 100 |
+
background-color: var(--accent);
|
| 101 |
+
box-sizing: border-box;
|
| 102 |
+
color: var(--secondary)
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
.services-card {
|
| 106 |
+
height: 100%;
|
| 107 |
+
border-radius: 15px !important;
|
| 108 |
+
background-color: var(--secondary) !important;
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
.services-card-action-area {
|
| 112 |
+
height: 100%;
|
| 113 |
+
display: flex;
|
| 114 |
+
align-items: center;
|
| 115 |
+
justify-content: center;
|
| 116 |
+
flex-direction: column;
|
| 117 |
+
background-color: 'blue' !important;
|
| 118 |
+
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
.services-card-content {
|
| 122 |
+
display: flex;
|
| 123 |
+
justify-content: center;
|
| 124 |
+
align-items: center;
|
| 125 |
+
flex-direction: column;
|
| 126 |
+
height: 90%;
|
| 127 |
+
background-color: 'blue' !important;
|
| 128 |
+
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
.services-card-typography {
|
| 132 |
+
margin-top: 1;
|
| 133 |
+
color: var(--text);
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
.services-card-icon {
|
| 137 |
+
font-size: 60px !important;
|
| 138 |
+
color: var(--text);
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
/* SERVICES GRID ITEMS */
|
| 142 |
+
.services-box-0 {
|
| 143 |
+
margin-right: 10px;
|
| 144 |
+
margin-bottom: 10px;
|
| 145 |
+
margin-top: 0px;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
.services-box-1 {
|
| 149 |
+
margin-right: 0px;
|
| 150 |
+
margin-bottom: 10px;
|
| 151 |
+
margin-top: 0px;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
.services-box-2 {
|
| 155 |
+
margin-right: 10px;
|
| 156 |
+
margin-bottom: 0px;
|
| 157 |
+
margin-top: 10px;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
.services-box-3 {
|
| 161 |
+
margin-right: 0px;
|
| 162 |
+
margin-bottom: 0px;
|
| 163 |
+
margin-top: 10px;
|
| 164 |
+
}
|
web_app/frontend/src/pages/LandingPage.jsx
CHANGED
|
@@ -3,10 +3,12 @@ import { Container, Typography, Button } from '@mui/material';
|
|
| 3 |
import { Link } from 'react-router-dom';
|
| 4 |
import { Box } from '@mui/system';
|
| 5 |
import Footer from '../components/Footer';
|
|
|
|
| 6 |
|
| 7 |
const LandingPage = () => {
|
| 8 |
return (
|
| 9 |
<>
|
|
|
|
| 10 |
<Box
|
| 11 |
sx={{
|
| 12 |
position: 'absolute',
|
|
@@ -31,7 +33,7 @@ const LandingPage = () => {
|
|
| 31 |
<Typography variant="h2" align="center" color="white" gutterBottom>
|
| 32 |
Building a sustainable Dublin
|
| 33 |
</Typography>
|
| 34 |
-
<Button variant="contained" color="primary" component={Link} to="/
|
| 35 |
<Typography style={{ textTransform: 'none', fontSize: '16px'}}>
|
| 36 |
Try it out
|
| 37 |
</Typography>
|
|
|
|
| 3 |
import { Link } from 'react-router-dom';
|
| 4 |
import { Box } from '@mui/system';
|
| 5 |
import Footer from '../components/Footer';
|
| 6 |
+
import Navbar from '../components/Navbar';
|
| 7 |
|
| 8 |
const LandingPage = () => {
|
| 9 |
return (
|
| 10 |
<>
|
| 11 |
+
<Navbar />
|
| 12 |
<Box
|
| 13 |
sx={{
|
| 14 |
position: 'absolute',
|
|
|
|
| 33 |
<Typography variant="h2" align="center" color="white" gutterBottom>
|
| 34 |
Building a sustainable Dublin
|
| 35 |
</Typography>
|
| 36 |
+
<Button variant="contained" color="primary" component={Link} to="/dashboard/chat" style={{ margin: '10px', borderRadius: '8px', backgroundColor: 'rgba(255, 255, 255, 0.2)' }}>
|
| 37 |
<Typography style={{ textTransform: 'none', fontSize: '16px'}}>
|
| 38 |
Try it out
|
| 39 |
</Typography>
|
web_app/frontend/src/pages/{DashboardPage.jsx → ReportsPage.jsx}
RENAMED
|
@@ -1,13 +1,21 @@
|
|
| 1 |
import React from 'react';
|
| 2 |
-
import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText } from '@mui/material';
|
| 3 |
import { Box } from '@mui/system';
|
| 4 |
-
import { Link } from 'react-router-dom';
|
| 5 |
import ChatIcon from '@mui/icons-material/Chat';
|
| 6 |
import PieChartIcon from '@mui/icons-material/PieChart';
|
| 7 |
import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
|
|
|
|
| 8 |
import BookIcon from '@mui/icons-material/Book';
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
const services = [
|
| 13 |
{ title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
|
|
@@ -16,10 +24,16 @@ const DashboardPage = () => {
|
|
| 16 |
{ title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
|
| 17 |
];
|
| 18 |
|
| 19 |
-
const menuOptions = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
return (
|
| 22 |
<>
|
|
|
|
| 23 |
<Box
|
| 24 |
sx={{
|
| 25 |
position: 'absolute',
|
|
@@ -27,7 +41,7 @@ const DashboardPage = () => {
|
|
| 27 |
left: 0,
|
| 28 |
minHeight: '100vh',
|
| 29 |
width: '100%',
|
| 30 |
-
backgroundImage: 'linear-gradient(to bottom, #
|
| 31 |
backgroundRepeat: 'no-repeat',
|
| 32 |
backgroundSize: 'cover',
|
| 33 |
zIndex: -1
|
|
@@ -45,17 +59,20 @@ const DashboardPage = () => {
|
|
| 45 |
}}
|
| 46 |
>
|
| 47 |
<Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
|
| 48 |
-
|
| 49 |
<Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
|
| 50 |
<List sx={{backgroundColor:"white", borderRadius:"15px"}}>
|
| 51 |
{menuOptions.map((option, index) => (
|
| 52 |
-
<ListItem button key={index}>
|
| 53 |
-
<
|
|
|
|
|
|
|
|
|
|
| 54 |
</ListItem>
|
| 55 |
))}
|
| 56 |
</List>
|
| 57 |
<List
|
| 58 |
-
sx={{
|
| 59 |
textAlign: 'center',
|
| 60 |
backgroundColor:"white",
|
| 61 |
borderRadius:"15px",
|
|
@@ -65,40 +82,24 @@ const DashboardPage = () => {
|
|
| 65 |
<ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
|
| 66 |
</ListItem>
|
| 67 |
</List>
|
| 68 |
-
|
| 69 |
-
|
| 70 |
</Box>
|
| 71 |
</Grid>
|
| 72 |
<Grid container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
flexGrow: 1,
|
| 83 |
-
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
| 84 |
-
boxSizing: 'border-box'
|
| 85 |
-
}}>
|
| 86 |
-
<Card sx={{height: '100%', borderRadius: '15px'}}>
|
| 87 |
-
<CardActionArea component={Link} to={service.link} sx={{height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column'}}>
|
| 88 |
-
<CardContent sx={{textAlign: 'center'}}>
|
| 89 |
-
{service.icon}
|
| 90 |
-
<Typography variant="body1" sx={{mt: 1}}>{service.title}</Typography>
|
| 91 |
-
</CardContent>
|
| 92 |
-
</CardActionArea>
|
| 93 |
-
</Card>
|
| 94 |
-
</Box>
|
| 95 |
-
</Grid>
|
| 96 |
-
))}
|
| 97 |
</Grid>
|
| 98 |
</Grid>
|
| 99 |
</Box>
|
|
|
|
| 100 |
</>
|
| 101 |
);
|
| 102 |
};
|
| 103 |
|
| 104 |
-
export default
|
|
|
|
| 1 |
import React from 'react';
|
| 2 |
+
import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
|
| 3 |
import { Box } from '@mui/system';
|
| 4 |
+
import { Link, Outlet } from 'react-router-dom';
|
| 5 |
import ChatIcon from '@mui/icons-material/Chat';
|
| 6 |
import PieChartIcon from '@mui/icons-material/PieChart';
|
| 7 |
import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
|
| 8 |
+
import MapIcon from '@mui/icons-material/Map';
|
| 9 |
import BookIcon from '@mui/icons-material/Book';
|
| 10 |
|
| 11 |
+
import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
|
| 12 |
+
import SettingsIcon from '@mui/icons-material/Settings';
|
| 13 |
+
import PersonIcon from '@mui/icons-material/Person';
|
| 14 |
+
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
|
| 15 |
+
|
| 16 |
+
import Navbar from '../components/Navbar';
|
| 17 |
+
|
| 18 |
+
const ReportsPage = () => {
|
| 19 |
|
| 20 |
const services = [
|
| 21 |
{ title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
|
|
|
|
| 24 |
{ title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
|
| 25 |
];
|
| 26 |
|
| 27 |
+
const menuOptions = [
|
| 28 |
+
{ title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
|
| 29 |
+
{ title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
|
| 30 |
+
{ title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 31 |
+
{ title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 32 |
+
];
|
| 33 |
|
| 34 |
return (
|
| 35 |
<>
|
| 36 |
+
<Navbar />
|
| 37 |
<Box
|
| 38 |
sx={{
|
| 39 |
position: 'absolute',
|
|
|
|
| 41 |
left: 0,
|
| 42 |
minHeight: '100vh',
|
| 43 |
width: '100%',
|
| 44 |
+
backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
|
| 45 |
backgroundRepeat: 'no-repeat',
|
| 46 |
backgroundSize: 'cover',
|
| 47 |
zIndex: -1
|
|
|
|
| 59 |
}}
|
| 60 |
>
|
| 61 |
<Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
|
| 62 |
+
<Grid item xs={3}>
|
| 63 |
<Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
|
| 64 |
<List sx={{backgroundColor:"white", borderRadius:"15px"}}>
|
| 65 |
{menuOptions.map((option, index) => (
|
| 66 |
+
<ListItem button key={index} component={Link} to={option.link}>
|
| 67 |
+
<ListItemIcon>
|
| 68 |
+
{option.icon}
|
| 69 |
+
</ListItemIcon>
|
| 70 |
+
<ListItemText primary={option.title} />
|
| 71 |
</ListItem>
|
| 72 |
))}
|
| 73 |
</List>
|
| 74 |
<List
|
| 75 |
+
sx={{
|
| 76 |
textAlign: 'center',
|
| 77 |
backgroundColor:"white",
|
| 78 |
borderRadius:"15px",
|
|
|
|
| 82 |
<ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
|
| 83 |
</ListItem>
|
| 84 |
</List>
|
|
|
|
|
|
|
| 85 |
</Box>
|
| 86 |
</Grid>
|
| 87 |
<Grid container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
|
| 88 |
+
<Box sx={{
|
| 89 |
+
borderRadius: '15px',
|
| 90 |
+
p: 2,
|
| 91 |
+
marginLeft: '10px',
|
| 92 |
+
flexGrow: 1,
|
| 93 |
+
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
| 94 |
+
boxSizing: 'border-box'
|
| 95 |
+
}}>
|
| 96 |
+
</Box>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
</Grid>
|
| 98 |
</Grid>
|
| 99 |
</Box>
|
| 100 |
+
<Outlet />
|
| 101 |
</>
|
| 102 |
);
|
| 103 |
};
|
| 104 |
|
| 105 |
+
export default ReportsPage;
|
web_app/frontend/src/pages/ResourcesPage.jsx
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react';
|
| 2 |
+
import { Typography, Grid, Card, CardContent, CardActionArea, IconButton, Tooltip, List, ListItem, ListItemText, ListItemIcon } from '@mui/material';
|
| 3 |
+
import { Box } from '@mui/system';
|
| 4 |
+
import { Link, Outlet } from 'react-router-dom';
|
| 5 |
+
import ChatIcon from '@mui/icons-material/Chat';
|
| 6 |
+
import PieChartIcon from '@mui/icons-material/PieChart';
|
| 7 |
+
import ThreeDRotationIcon from '@mui/icons-material/ThreeDRotation';
|
| 8 |
+
import MapIcon from '@mui/icons-material/Map';
|
| 9 |
+
import BookIcon from '@mui/icons-material/Book';
|
| 10 |
+
|
| 11 |
+
import GridViewSharpIcon from '@mui/icons-material/GridViewSharp';
|
| 12 |
+
import SettingsIcon from '@mui/icons-material/Settings';
|
| 13 |
+
import PersonIcon from '@mui/icons-material/Person';
|
| 14 |
+
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
|
| 15 |
+
|
| 16 |
+
import Navbar from '../components/Navbar';
|
| 17 |
+
|
| 18 |
+
const ResourcesPage = () => {
|
| 19 |
+
|
| 20 |
+
const services = [
|
| 21 |
+
{ title: 'ChatBot', link: '/dashboard/chat', icon: <ChatIcon style={{ fontSize: 60 }} /> },
|
| 22 |
+
{ title: 'Statistics and Charts', link: '/dashboard/stats', icon: <PieChartIcon style={{ fontSize: 60 }} /> },
|
| 23 |
+
{ title: '3D Models', link: '/dashboard/3dmodels', icon: <ThreeDRotationIcon style={{ fontSize: 60 }} /> },
|
| 24 |
+
{ title: 'Useful Resources', link: '/dashboard/resources', icon: <BookIcon style={{ fontSize: 60 }} /> },
|
| 25 |
+
];
|
| 26 |
+
|
| 27 |
+
const menuOptions = [
|
| 28 |
+
{ title: 'Dashboard', link: '/dashboard', icon: <GridViewSharpIcon style={{ fontSize:25, color: 'black'}} />},
|
| 29 |
+
{ title: 'Settings', link: '/dashboard/settings', icon: <SettingsIcon style={{ fontSize:25, color: 'black'}} /> },
|
| 30 |
+
{ title: 'Profile', link: '/dashboard/profile', icon: <PersonIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 31 |
+
{ title: 'Sign out', link: '/logout', icon: <ExitToAppIcon style={{ fontSize: 25, color: 'black' }} /> },
|
| 32 |
+
];
|
| 33 |
+
|
| 34 |
+
return (
|
| 35 |
+
<>
|
| 36 |
+
<Navbar />
|
| 37 |
+
<Box
|
| 38 |
+
sx={{
|
| 39 |
+
position: 'absolute',
|
| 40 |
+
top: 0,
|
| 41 |
+
left: 0,
|
| 42 |
+
minHeight: '100vh',
|
| 43 |
+
width: '100%',
|
| 44 |
+
backgroundImage: 'linear-gradient(to bottom, #1D5B79, #1D5B79)',
|
| 45 |
+
backgroundRepeat: 'no-repeat',
|
| 46 |
+
backgroundSize: 'cover',
|
| 47 |
+
zIndex: -1
|
| 48 |
+
}}
|
| 49 |
+
/>
|
| 50 |
+
<Box
|
| 51 |
+
sx={{
|
| 52 |
+
position: 'absolute',
|
| 53 |
+
top: '84px',
|
| 54 |
+
left: '10px',
|
| 55 |
+
right: '10px',
|
| 56 |
+
height: '85vh',
|
| 57 |
+
backgroundColor:'transparent',
|
| 58 |
+
borderRadius:'15px',
|
| 59 |
+
}}
|
| 60 |
+
>
|
| 61 |
+
<Grid container sx={{ backgroundColor: 'transparent', flexGrow: 1, height: '100%', borderRadius:'15px'}}>
|
| 62 |
+
<Grid item xs={3}>
|
| 63 |
+
<Box sx={{ borderRadius: '15px', p:2, marginRight:'10px', height:'calc(100%)', backgroundColor: 'rgba(255, 255, 255, 0.7)', boxSizing: 'border-box', display: 'flex', flexDirection: 'column', justifyContent: 'space-between'}}>
|
| 64 |
+
<List sx={{backgroundColor:"white", borderRadius:"15px"}}>
|
| 65 |
+
{menuOptions.map((option, index) => (
|
| 66 |
+
<ListItem button key={index} component={Link} to={option.link}>
|
| 67 |
+
<ListItemIcon>
|
| 68 |
+
{option.icon}
|
| 69 |
+
</ListItemIcon>
|
| 70 |
+
<ListItemText primary={option.title} />
|
| 71 |
+
</ListItem>
|
| 72 |
+
))}
|
| 73 |
+
</List>
|
| 74 |
+
<List
|
| 75 |
+
sx={{
|
| 76 |
+
textAlign: 'center',
|
| 77 |
+
backgroundColor:"white",
|
| 78 |
+
borderRadius:"15px",
|
| 79 |
+
}}
|
| 80 |
+
>
|
| 81 |
+
<ListItem button>
|
| 82 |
+
<ListItemText primary={<Typography sx={{ fontSize: '14px' }}>Terms and Conditions</Typography>} />
|
| 83 |
+
</ListItem>
|
| 84 |
+
</List>
|
| 85 |
+
</Box>
|
| 86 |
+
</Grid>
|
| 87 |
+
<Grid container spacing={0} sx={{height: '100%', boxSizing: 'border-box'}} xs={9}>
|
| 88 |
+
<Box sx={{
|
| 89 |
+
borderRadius: '15px',
|
| 90 |
+
p: 2,
|
| 91 |
+
marginLeft: '10px',
|
| 92 |
+
flexGrow: 1,
|
| 93 |
+
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
| 94 |
+
boxSizing: 'border-box'
|
| 95 |
+
}}>
|
| 96 |
+
</Box>
|
| 97 |
+
</Grid>
|
| 98 |
+
</Grid>
|
| 99 |
+
</Box>
|
| 100 |
+
<Outlet />
|
| 101 |
+
</>
|
| 102 |
+
);
|
| 103 |
+
};
|
| 104 |
+
|
| 105 |
+
export default ResourcesPage;
|
web_app/frontend/src/pages/scrollbar.css
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.custom-scrollbar {
|
| 2 |
+
height: 500px; /* Set your desired height */
|
| 3 |
+
overflow: auto;
|
| 4 |
+
}
|
| 5 |
+
|
| 6 |
+
.custom-scrollbar::-webkit-scrollbar {
|
| 7 |
+
width: 10px;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
.custom-scrollbar::-webkit-scrollbar-track {
|
| 11 |
+
background: #f1f1f1;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
.custom-scrollbar::-webkit-scrollbar-thumb {
|
| 15 |
+
background: #1D5B79;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
| 19 |
+
background: #1D5B79;
|
| 20 |
+
}
|
web_app/frontend/vite.config.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
| 1 |
-
import { defineConfig } from 'vite'
|
| 2 |
-
import react from '@vitejs/plugin-react'
|
| 3 |
|
| 4 |
-
// https://vitejs.dev/config/
|
| 5 |
export default defineConfig({
|
| 6 |
plugins: [react()],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
server: {
|
| 8 |
host: true,
|
| 9 |
port: 3000,
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
}
|
| 14 |
-
})
|
|
|
|
| 1 |
+
import { defineConfig } from 'vite';
|
| 2 |
+
import react from '@vitejs/plugin-react';
|
| 3 |
|
|
|
|
| 4 |
export default defineConfig({
|
| 5 |
plugins: [react()],
|
| 6 |
+
build: {
|
| 7 |
+
rollupOptions: {
|
| 8 |
+
external: ['@deck.gl/extensions']
|
| 9 |
+
}
|
| 10 |
+
},
|
| 11 |
server: {
|
| 12 |
host: true,
|
| 13 |
port: 3000,
|
| 14 |
+
watch: {
|
| 15 |
+
usePolling: true
|
| 16 |
+
}
|
| 17 |
}
|
| 18 |
+
});
|