Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -8,14 +8,47 @@ from reportlab.pdfgen import canvas
|
|
| 8 |
|
| 9 |
REQUIRED_COLUMNS = ['DeviceID', 'Lab', 'Type', 'Timestamp', 'Status', 'UsageCount']
|
| 10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
# ----------------------------
|
| 12 |
# Load Logs Safely
|
| 13 |
# ----------------------------
|
| 14 |
def load_logs(file_obj):
|
| 15 |
try:
|
| 16 |
if file_obj is not None:
|
| 17 |
-
|
| 18 |
-
|
|
|
|
| 19 |
if not all(col in df.columns for col in REQUIRED_COLUMNS):
|
| 20 |
raise ValueError(f"CSV must contain columns: {', '.join(REQUIRED_COLUMNS)}")
|
| 21 |
df['Timestamp'] = pd.to_datetime(df['Timestamp'], errors='coerce')
|
|
@@ -51,7 +84,6 @@ def filter_df(df, selected_lab, selected_type):
|
|
| 51 |
# ----------------------------
|
| 52 |
def summarize_logs(df):
|
| 53 |
if df.empty:
|
| 54 |
-
# Return empty DataFrame with expected columns for plotting
|
| 55 |
return pd.DataFrame(columns=['OK', 'DOWN'])
|
| 56 |
summary = df.groupby(['Lab', 'Type'])['Status'].value_counts().unstack().fillna(0)
|
| 57 |
return summary
|
|
@@ -122,7 +154,6 @@ def update_dropdown_options(file_obj):
|
|
| 122 |
df = load_logs(file_obj)
|
| 123 |
labs = sorted(df['Lab'].dropna().unique().tolist())
|
| 124 |
types = sorted(df['Type'].dropna().unique().tolist())
|
| 125 |
-
# Add "All" option for no filtering
|
| 126 |
labs = ["All"] + labs
|
| 127 |
types = ["All"] + types
|
| 128 |
return labs, types, gr.update(visible=True)
|
|
@@ -136,7 +167,7 @@ def dashboard(file_obj, selected_lab, selected_type):
|
|
| 136 |
try:
|
| 137 |
df = load_logs(file_obj)
|
| 138 |
fig = generate_chart(df, selected_lab, selected_type)
|
| 139 |
-
return fig, gr.update(visible=False)
|
| 140 |
except Exception as e:
|
| 141 |
return None, gr.update(value=f"❌ Error: {e}", visible=True)
|
| 142 |
|
|
|
|
| 8 |
|
| 9 |
REQUIRED_COLUMNS = ['DeviceID', 'Lab', 'Type', 'Timestamp', 'Status', 'UsageCount']
|
| 10 |
|
| 11 |
+
# ----------------------------
|
| 12 |
+
# Helper to extract file content correctly for HF Spaces and local
|
| 13 |
+
# ----------------------------
|
| 14 |
+
def get_file_content(file_obj):
|
| 15 |
+
if file_obj is None:
|
| 16 |
+
return None
|
| 17 |
+
|
| 18 |
+
if hasattr(file_obj, "read"):
|
| 19 |
+
content = file_obj.read()
|
| 20 |
+
if isinstance(content, bytes):
|
| 21 |
+
return content
|
| 22 |
+
else:
|
| 23 |
+
return content.encode('utf-8')
|
| 24 |
+
|
| 25 |
+
if isinstance(file_obj, dict) and 'data' in file_obj:
|
| 26 |
+
data = file_obj['data']
|
| 27 |
+
if isinstance(data, str):
|
| 28 |
+
import base64
|
| 29 |
+
if data.startswith("data:"):
|
| 30 |
+
data = data.split(",")[1]
|
| 31 |
+
return base64.b64decode(data)
|
| 32 |
+
elif isinstance(data, bytes):
|
| 33 |
+
return data
|
| 34 |
+
else:
|
| 35 |
+
raise ValueError("Unexpected data format in file upload dict")
|
| 36 |
+
|
| 37 |
+
if isinstance(file_obj, str):
|
| 38 |
+
with open(file_obj, "rb") as f:
|
| 39 |
+
return f.read()
|
| 40 |
+
|
| 41 |
+
raise ValueError("Unsupported file object format")
|
| 42 |
+
|
| 43 |
# ----------------------------
|
| 44 |
# Load Logs Safely
|
| 45 |
# ----------------------------
|
| 46 |
def load_logs(file_obj):
|
| 47 |
try:
|
| 48 |
if file_obj is not None:
|
| 49 |
+
content_bytes = get_file_content(file_obj)
|
| 50 |
+
content_str = content_bytes.decode('utf-8')
|
| 51 |
+
df = pd.read_csv(io.StringIO(content_str))
|
| 52 |
if not all(col in df.columns for col in REQUIRED_COLUMNS):
|
| 53 |
raise ValueError(f"CSV must contain columns: {', '.join(REQUIRED_COLUMNS)}")
|
| 54 |
df['Timestamp'] = pd.to_datetime(df['Timestamp'], errors='coerce')
|
|
|
|
| 84 |
# ----------------------------
|
| 85 |
def summarize_logs(df):
|
| 86 |
if df.empty:
|
|
|
|
| 87 |
return pd.DataFrame(columns=['OK', 'DOWN'])
|
| 88 |
summary = df.groupby(['Lab', 'Type'])['Status'].value_counts().unstack().fillna(0)
|
| 89 |
return summary
|
|
|
|
| 154 |
df = load_logs(file_obj)
|
| 155 |
labs = sorted(df['Lab'].dropna().unique().tolist())
|
| 156 |
types = sorted(df['Type'].dropna().unique().tolist())
|
|
|
|
| 157 |
labs = ["All"] + labs
|
| 158 |
types = ["All"] + types
|
| 159 |
return labs, types, gr.update(visible=True)
|
|
|
|
| 167 |
try:
|
| 168 |
df = load_logs(file_obj)
|
| 169 |
fig = generate_chart(df, selected_lab, selected_type)
|
| 170 |
+
return fig, gr.update(visible=False)
|
| 171 |
except Exception as e:
|
| 172 |
return None, gr.update(value=f"❌ Error: {e}", visible=True)
|
| 173 |
|