codewithRiz commited on
Commit
f693e67
·
1 Parent(s): a40a2dc

Initial commit

Browse files
Files changed (4) hide show
  1. .gitignore +3 -1
  2. .gradio/certificate.pem +31 -0
  3. app.py +177 -0
  4. requirements.txt +1 -0
.gitignore CHANGED
@@ -1 +1,3 @@
1
- .pt
 
 
 
1
+ .pt
2
+ .env
3
+
.gradio/certificate.pem ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
31
+ -----END CERTIFICATE-----
app.py ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from huggingface_hub import list_bucket_tree, download_bucket_files
3
+ from datetime import datetime
4
+ import pandas as pd
5
+ import json
6
+ import os
7
+ from dotenv import load_dotenv
8
+
9
+ # ---------- LOAD ENV ----------
10
+ load_dotenv()
11
+ BUCKET_NAME = os.getenv("BUCKET_NAME")
12
+
13
+ PAGE_SIZE = 5
14
+
15
+
16
+ # ---------- LOAD DATA FROM BUCKET ----------
17
+ def extract_customer_data():
18
+ try:
19
+ tree = list_bucket_tree(BUCKET_NAME, recursive=True)
20
+
21
+ json_files = [
22
+ item.path for item in tree
23
+ if item.path.endswith("cameras.json")
24
+ ]
25
+
26
+ if not json_files:
27
+ return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"])
28
+
29
+ files_map = [(f, f"C:/tmp/{f.replace('/', '_')}") for f in json_files]
30
+
31
+ download_bucket_files(BUCKET_NAME, files=files_map)
32
+
33
+ rows = []
34
+
35
+ for remote_path, local_path in files_map:
36
+ parts = remote_path.split("/")
37
+ customer_id = parts[1] if len(parts) > 1 else "unknown"
38
+
39
+ try:
40
+ with open(local_path, "r", encoding="utf-8") as f:
41
+ data = json.load(f)
42
+
43
+ for item in data:
44
+ rows.append({
45
+ "customer_id": customer_id,
46
+ "customer_name": item.get("customer_name"),
47
+ "customer_email": item.get("customer_email")
48
+ })
49
+
50
+ except Exception as e:
51
+ print(f"File error {remote_path}: {e}")
52
+
53
+ df = pd.DataFrame(rows)
54
+
55
+ # ---------- REMOVE DUPLICATES ----------
56
+ if not df.empty:
57
+ df = df.drop_duplicates(
58
+ subset=["customer_id", "customer_name", "customer_email"]
59
+ )
60
+
61
+ return df
62
+
63
+ except Exception as e:
64
+ print("ERROR:", e)
65
+ return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"])
66
+
67
+
68
+ # ---------- FILTER ----------
69
+ def apply_search(df, email_query):
70
+ if df is None or not isinstance(df, pd.DataFrame):
71
+ return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"])
72
+
73
+ if email_query:
74
+ df = df[df["customer_email"].astype(str).str.contains(email_query, case=False, na=False)]
75
+
76
+ return df
77
+
78
+
79
+ # ---------- PAGINATION ----------
80
+ def build_view(df, page, email_query):
81
+ filtered = apply_search(df, email_query)
82
+
83
+ total_pages = max(1, (len(filtered) - 1) // PAGE_SIZE + 1)
84
+ page = max(0, min(page, total_pages - 1))
85
+
86
+ start = page * PAGE_SIZE
87
+ end = start + PAGE_SIZE
88
+
89
+ paged = filtered.iloc[start:end]
90
+
91
+ status = f"Page {page+1} / {total_pages} | Total Results: {len(filtered)}"
92
+
93
+ return paged, page, status
94
+
95
+
96
+ # ---------- ACTIONS ----------
97
+ def search(df, email_query):
98
+ page = 0
99
+ table, page, status = build_view(df, page, email_query)
100
+ return table, page, status, df
101
+
102
+
103
+ def next_page(df, page, email_query):
104
+ page = page + 1
105
+ table, page, status = build_view(df, page, email_query)
106
+ return table, page, status, df
107
+
108
+
109
+ def prev_page(df, page, email_query):
110
+ page = page - 1
111
+ table, page, status = build_view(df, page, email_query)
112
+ return table, page, status, df
113
+
114
+
115
+ def refresh_data(email_query):
116
+ df = extract_customer_data()
117
+ page = 0
118
+ table, page, status = build_view(df, page, email_query)
119
+ return table, page, status, df
120
+
121
+
122
+ # ---------- INITIAL DATA ----------
123
+ df_global = extract_customer_data()
124
+
125
+
126
+ # ---------- UI ----------
127
+ with gr.Blocks() as app:
128
+ gr.Markdown("# 🛰 Buck Tracker Customer Dashboard")
129
+
130
+ state_df = gr.State(df_global)
131
+ state_page = gr.State(0)
132
+
133
+ search_box = gr.Textbox(
134
+ label="🔍 Search Customer Email",
135
+ placeholder="Enter email to search..."
136
+ )
137
+
138
+ table = gr.Dataframe(
139
+ value=build_view(df_global, 0, "")[0],
140
+ interactive=False,
141
+ label="Customer Data"
142
+ )
143
+
144
+ status = gr.Textbox(interactive=False)
145
+
146
+ with gr.Row():
147
+ refresh_btn = gr.Button("🔄 Refresh Bucket Data", variant="primary")
148
+ prev_btn = gr.Button("⬅️ Previous")
149
+ next_btn = gr.Button("Next ➡️")
150
+
151
+ # ---------- EVENTS ----------
152
+
153
+ search_box.change(
154
+ fn=search,
155
+ inputs=[state_df, search_box],
156
+ outputs=[table, state_page, status, state_df]
157
+ )
158
+
159
+ refresh_btn.click(
160
+ fn=refresh_data,
161
+ inputs=[search_box],
162
+ outputs=[table, state_page, status, state_df]
163
+ )
164
+
165
+ next_btn.click(
166
+ fn=next_page,
167
+ inputs=[state_df, state_page, search_box],
168
+ outputs=[table, state_page, status, state_df]
169
+ )
170
+
171
+ prev_btn.click(
172
+ fn=prev_page,
173
+ inputs=[state_df, state_page, search_box],
174
+ outputs=[table, state_page, status, state_df]
175
+ )
176
+
177
+ app.launch()
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gradio