Update app.py
Browse files
app.py
CHANGED
|
@@ -71,11 +71,20 @@ st.markdown("""
|
|
| 71 |
transform: translateY(-2px) rotateX(15deg);
|
| 72 |
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
|
| 73 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
</style>
|
| 75 |
""", unsafe_allow_html=True)
|
| 76 |
|
| 77 |
import firebase_admin
|
| 78 |
-
from firebase_admin import credentials, firestore, auth
|
| 79 |
import pandas as pd
|
| 80 |
import plotly.express as px
|
| 81 |
from datetime import datetime, timedelta
|
|
@@ -87,11 +96,40 @@ if not firebase_admin._apps:
|
|
| 87 |
firebase_admin.initialize_app(cred)
|
| 88 |
db = firestore.client()
|
| 89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
# Authentication Functions
|
| 91 |
def register_user(email, password):
|
| 92 |
try:
|
| 93 |
user = auth.create_user(email=email, password=password)
|
| 94 |
-
db.collection("users").document(user.uid).set({
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
st.success("Registration successful! Please sign in.")
|
| 96 |
except Exception as e:
|
| 97 |
st.error(f"Error: {e}")
|
|
@@ -99,10 +137,10 @@ def register_user(email, password):
|
|
| 99 |
def authenticate_user(email, password):
|
| 100 |
try:
|
| 101 |
user = auth.get_user_by_email(email)
|
| 102 |
-
return user
|
| 103 |
except Exception as e:
|
| 104 |
st.error(f"Authentication error: {str(e)}")
|
| 105 |
-
return
|
| 106 |
|
| 107 |
# Main Application Logic
|
| 108 |
def main():
|
|
@@ -110,6 +148,7 @@ def main():
|
|
| 110 |
if "authenticated" not in st.session_state:
|
| 111 |
st.session_state.authenticated = False
|
| 112 |
st.session_state.email = ""
|
|
|
|
| 113 |
st.session_state.first_login = True
|
| 114 |
st.session_state.user_uid = ""
|
| 115 |
|
|
@@ -135,12 +174,15 @@ def main():
|
|
| 135 |
password = st.text_input("Password", type="password")
|
| 136 |
if st.form_submit_button("Login"):
|
| 137 |
try:
|
| 138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
st.session_state.authenticated = True
|
| 140 |
-
st.session_state.email = email
|
| 141 |
-
# Get user UID for password updates
|
| 142 |
-
user = auth.get_user_by_email(email)
|
| 143 |
st.session_state.user_uid = user.uid
|
|
|
|
| 144 |
st.rerun()
|
| 145 |
else:
|
| 146 |
st.error("Invalid credentials")
|
|
@@ -199,15 +241,23 @@ def main():
|
|
| 199 |
st.session_state.first_login = False
|
| 200 |
|
| 201 |
# Sidebar Navigation
|
| 202 |
-
|
| 203 |
-
menu = st.sidebar.radio("Navigation", [
|
| 204 |
"π Dashboard",
|
| 205 |
"π Task Entry",
|
| 206 |
"π View Tasks",
|
| 207 |
"βοΈ Edit Tasks",
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
|
| 212 |
# Dashboard View
|
| 213 |
if menu == "π Dashboard":
|
|
@@ -289,7 +339,7 @@ def main():
|
|
| 289 |
except Exception as e:
|
| 290 |
st.error(f"Error saving task: {str(e)}")
|
| 291 |
|
| 292 |
-
# View Tasks
|
| 293 |
elif menu == "π View Tasks":
|
| 294 |
st.title("π Task Explorer")
|
| 295 |
tasks = get_tasks()
|
|
@@ -366,8 +416,12 @@ def main():
|
|
| 366 |
else:
|
| 367 |
st.info("No tasks available for editing")
|
| 368 |
|
| 369 |
-
# Project Management
|
| 370 |
elif menu == "ποΈ Projects":
|
|
|
|
|
|
|
|
|
|
|
|
|
| 371 |
st.title("ποΈ Project Management")
|
| 372 |
try:
|
| 373 |
projects_ref = db.collection("projects")
|
|
|
|
| 71 |
transform: translateY(-2px) rotateX(15deg);
|
| 72 |
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
|
| 73 |
}
|
| 74 |
+
|
| 75 |
+
/* Admin badge */
|
| 76 |
+
.admin-badge {
|
| 77 |
+
background: #4a148c;
|
| 78 |
+
color: white !important;
|
| 79 |
+
padding: 2px 8px;
|
| 80 |
+
border-radius: 12px;
|
| 81 |
+
font-size: 0.8em;
|
| 82 |
+
}
|
| 83 |
</style>
|
| 84 |
""", unsafe_allow_html=True)
|
| 85 |
|
| 86 |
import firebase_admin
|
| 87 |
+
from firebase_admin import credentials, firestore, auth, exceptions
|
| 88 |
import pandas as pd
|
| 89 |
import plotly.express as px
|
| 90 |
from datetime import datetime, timedelta
|
|
|
|
| 96 |
firebase_admin.initialize_app(cred)
|
| 97 |
db = firestore.client()
|
| 98 |
|
| 99 |
+
# Create default admin user if not exists
|
| 100 |
+
def create_default_admin():
|
| 101 |
+
try:
|
| 102 |
+
admin_email = "admin@example.com"
|
| 103 |
+
try:
|
| 104 |
+
admin_user = auth.get_user_by_email(admin_email)
|
| 105 |
+
except auth.UserNotFoundError:
|
| 106 |
+
admin_user = auth.create_user(
|
| 107 |
+
email=admin_email,
|
| 108 |
+
password="Temp@2025",
|
| 109 |
+
display_name="Admin"
|
| 110 |
+
)
|
| 111 |
+
auth.set_custom_user_claims(admin_user.uid, {'admin': True})
|
| 112 |
+
db.collection("users").document(admin_user.uid).set({
|
| 113 |
+
"email": admin_email,
|
| 114 |
+
"is_admin": True,
|
| 115 |
+
"created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 116 |
+
})
|
| 117 |
+
except Exception as e:
|
| 118 |
+
print(f"Error creating admin user: {str(e)}")
|
| 119 |
+
except Exception as e:
|
| 120 |
+
print(f"Error in admin setup: {str(e)}")
|
| 121 |
+
|
| 122 |
+
create_default_admin()
|
| 123 |
+
|
| 124 |
# Authentication Functions
|
| 125 |
def register_user(email, password):
|
| 126 |
try:
|
| 127 |
user = auth.create_user(email=email, password=password)
|
| 128 |
+
db.collection("users").document(user.uid).set({
|
| 129 |
+
"email": email,
|
| 130 |
+
"is_admin": False,
|
| 131 |
+
"created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 132 |
+
})
|
| 133 |
st.success("Registration successful! Please sign in.")
|
| 134 |
except Exception as e:
|
| 135 |
st.error(f"Error: {e}")
|
|
|
|
| 137 |
def authenticate_user(email, password):
|
| 138 |
try:
|
| 139 |
user = auth.get_user_by_email(email)
|
| 140 |
+
return user
|
| 141 |
except Exception as e:
|
| 142 |
st.error(f"Authentication error: {str(e)}")
|
| 143 |
+
return None
|
| 144 |
|
| 145 |
# Main Application Logic
|
| 146 |
def main():
|
|
|
|
| 148 |
if "authenticated" not in st.session_state:
|
| 149 |
st.session_state.authenticated = False
|
| 150 |
st.session_state.email = ""
|
| 151 |
+
st.session_state.is_admin = False
|
| 152 |
st.session_state.first_login = True
|
| 153 |
st.session_state.user_uid = ""
|
| 154 |
|
|
|
|
| 174 |
password = st.text_input("Password", type="password")
|
| 175 |
if st.form_submit_button("Login"):
|
| 176 |
try:
|
| 177 |
+
user = authenticate_user(email, password)
|
| 178 |
+
if user:
|
| 179 |
+
custom_claims = user.custom_claims or {}
|
| 180 |
+
user_doc = db.collection("users").document(user.uid).get().to_dict()
|
| 181 |
+
|
| 182 |
st.session_state.authenticated = True
|
| 183 |
+
st.session_state.email = user.email
|
|
|
|
|
|
|
| 184 |
st.session_state.user_uid = user.uid
|
| 185 |
+
st.session_state.is_admin = custom_claims.get('admin', False) or user_doc.get('is_admin', False)
|
| 186 |
st.rerun()
|
| 187 |
else:
|
| 188 |
st.error("Invalid credentials")
|
|
|
|
| 241 |
st.session_state.first_login = False
|
| 242 |
|
| 243 |
# Sidebar Navigation
|
| 244 |
+
menu_items = [
|
|
|
|
| 245 |
"π Dashboard",
|
| 246 |
"π Task Entry",
|
| 247 |
"π View Tasks",
|
| 248 |
"βοΈ Edit Tasks",
|
| 249 |
+
]
|
| 250 |
+
|
| 251 |
+
if st.session_state.is_admin:
|
| 252 |
+
menu_items += ["ποΈ Projects"]
|
| 253 |
+
|
| 254 |
+
menu_items += ["βοΈ Settings"]
|
| 255 |
+
|
| 256 |
+
st.sidebar.title(f"Welcome, {st.session_state.email}")
|
| 257 |
+
if st.session_state.is_admin:
|
| 258 |
+
st.sidebar.markdown('<span class="admin-badge">ADMIN</span>', unsafe_allow_html=True)
|
| 259 |
+
|
| 260 |
+
menu = st.sidebar.radio("Navigation", menu_items, label_visibility="collapsed")
|
| 261 |
|
| 262 |
# Dashboard View
|
| 263 |
if menu == "π Dashboard":
|
|
|
|
| 339 |
except Exception as e:
|
| 340 |
st.error(f"Error saving task: {str(e)}")
|
| 341 |
|
| 342 |
+
# View Tasks
|
| 343 |
elif menu == "π View Tasks":
|
| 344 |
st.title("π Task Explorer")
|
| 345 |
tasks = get_tasks()
|
|
|
|
| 416 |
else:
|
| 417 |
st.info("No tasks available for editing")
|
| 418 |
|
| 419 |
+
# Project Management (Admin Only)
|
| 420 |
elif menu == "ποΈ Projects":
|
| 421 |
+
if not st.session_state.is_admin:
|
| 422 |
+
st.error("β You don't have permission to access this section")
|
| 423 |
+
return
|
| 424 |
+
|
| 425 |
st.title("ποΈ Project Management")
|
| 426 |
try:
|
| 427 |
projects_ref = db.collection("projects")
|