awacke1 commited on
Commit
695a85e
β€’
1 Parent(s): 5ee1015

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +357 -0
app.py ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from azure.cosmos import CosmosClient, PartitionKey, exceptions
3
+ import os
4
+ import pandas as pd
5
+ import traceback
6
+ import requests
7
+ import shutil
8
+ import zipfile
9
+ from github import Github
10
+ from git import Repo
11
+ from datetime import datetime
12
+ import base64
13
+ import json
14
+
15
+ st.set_page_config(layout="wide")
16
+
17
+ # Cosmos DB configuration
18
+ ENDPOINT = "https://acae-afd.documents.azure.com:443/"
19
+ SUBSCRIPTION_ID = "003fba60-5b3f-48f4-ab36-3ed11bc40816"
20
+ DATABASE_NAME = os.environ.get("COSMOS_DATABASE_NAME")
21
+ CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
22
+ Key = os.environ.get("Key")
23
+
24
+ # GitHub configuration
25
+ def download_github_repo(url, local_path):
26
+ if os.path.exists(local_path):
27
+ shutil.rmtree(local_path)
28
+ Repo.clone_from(url, local_path)
29
+
30
+ def create_zip_file(source_dir, output_filename):
31
+ shutil.make_archive(output_filename, 'zip', source_dir)
32
+
33
+ def create_repo(g, repo_name):
34
+ user = g.get_user()
35
+ return user.create_repo(repo_name)
36
+
37
+ def push_to_github(local_path, repo, github_token):
38
+ repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
39
+ local_repo = Repo(local_path)
40
+
41
+ if 'origin' in [remote.name for remote in local_repo.remotes]:
42
+ origin = local_repo.remote('origin')
43
+ origin.set_url(repo_url)
44
+ else:
45
+ origin = local_repo.create_remote('origin', repo_url)
46
+
47
+ if not local_repo.heads:
48
+ local_repo.git.checkout('-b', 'main')
49
+ current_branch = 'main'
50
+ else:
51
+ current_branch = local_repo.active_branch.name
52
+
53
+ local_repo.git.add(A=True)
54
+
55
+ if local_repo.is_dirty():
56
+ local_repo.git.commit('-m', 'Initial commit')
57
+
58
+ origin.push(refspec=f'{current_branch}:{current_branch}')
59
+
60
+ def get_base64_download_link(file_path, file_name):
61
+ with open(file_path, "rb") as file:
62
+ contents = file.read()
63
+ base64_encoded = base64.b64encode(contents).decode()
64
+ return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">Download {file_name}</a>'
65
+
66
+ # Cosmos DB functions
67
+ def insert_record(record):
68
+ try:
69
+ response = container.create_item(body=record)
70
+ return True, response
71
+ except exceptions.CosmosHttpResponseError as e:
72
+ return False, f"HTTP error occurred: {str(e)}. Status code: {e.status_code}"
73
+ except Exception as e:
74
+ return False, f"An unexpected error occurred: {str(e)}"
75
+
76
+ def call_stored_procedure(record):
77
+ try:
78
+ response = container.scripts.execute_stored_procedure(
79
+ sproc="processPrompt",
80
+ params=[record],
81
+ partition_key=record['id']
82
+ )
83
+ return True, response
84
+ except exceptions.CosmosHttpResponseError as e:
85
+ error_message = f"HTTP error occurred: {str(e)}. Status code: {e.status_code}"
86
+ return False, error_message
87
+ except Exception as e:
88
+ error_message = f"An unexpected error occurred: {str(e)}"
89
+ return False, error_message
90
+
91
+ def fetch_all_records():
92
+ try:
93
+ query = "SELECT * FROM c"
94
+ items = list(container.query_items(query=query, enable_cross_partition_query=True))
95
+ return pd.DataFrame(items)
96
+ except exceptions.CosmosHttpResponseError as e:
97
+ st.error(f"HTTP error occurred while fetching records: {str(e)}. Status code: {e.status_code}")
98
+ return pd.DataFrame()
99
+ except Exception as e:
100
+ st.error(f"An unexpected error occurred while fetching records: {str(e)}")
101
+ return pd.DataFrame()
102
+
103
+ def update_record(updated_record):
104
+ try:
105
+ container.upsert_item(body=updated_record)
106
+ return True, f"Record with id {updated_record['id']} successfully updated."
107
+ except exceptions.CosmosHttpResponseError as e:
108
+ return False, f"HTTP error occurred: {str(e)}. Status code: {e.status_code}"
109
+ except Exception as e:
110
+ return False, f"An unexpected error occurred: {traceback.format_exc()}"
111
+
112
+ def delete_record(name, id):
113
+ try:
114
+ container.delete_item(item=id, partition_key=id)
115
+ return True, f"Successfully deleted record with name: {name} and id: {id}"
116
+ except exceptions.CosmosResourceNotFoundError:
117
+ return False, f"Record with id {id} not found. It may have been already deleted."
118
+ except exceptions.CosmosHttpResponseError as e:
119
+ return False, f"HTTP error occurred: {str(e)}. Status code: {e.status_code}"
120
+ except Exception as e:
121
+ return False, f"An unexpected error occurred: {traceback.format_exc()}"
122
+
123
+ # New function to archive all databases and containers
124
+ def archive_all_data(client):
125
+ try:
126
+ base_dir = "./cosmos_archive"
127
+ if os.path.exists(base_dir):
128
+ shutil.rmtree(base_dir)
129
+ os.makedirs(base_dir)
130
+
131
+ for database in client.list_databases():
132
+ db_name = database['id']
133
+ db_dir = os.path.join(base_dir, db_name)
134
+ os.makedirs(db_dir)
135
+
136
+ db_client = client.get_database_client(db_name)
137
+ for container in db_client.list_containers():
138
+ container_name = container['id']
139
+ container_dir = os.path.join(db_dir, container_name)
140
+ os.makedirs(container_dir)
141
+
142
+ container_client = db_client.get_container_client(container_name)
143
+ items = list(container_client.read_all_items())
144
+
145
+ with open(os.path.join(container_dir, f"{container_name}.json"), 'w') as f:
146
+ json.dump(items, f, indent=2)
147
+
148
+ archive_name = f"cosmos_archive_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
149
+ shutil.make_archive(archive_name, 'zip', base_dir)
150
+
151
+ return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
152
+ except Exception as e:
153
+ return f"An error occurred while archiving data: {str(e)}"
154
+
155
+ # Streamlit app
156
+ st.title("🌟 Cosmos DB and GitHub Integration")
157
+
158
+ # Initialize session state
159
+ if 'logged_in' not in st.session_state:
160
+ st.session_state.logged_in = False
161
+ if 'selected_records' not in st.session_state:
162
+ st.session_state.selected_records = []
163
+
164
+ # Login section
165
+ if not st.session_state.logged_in:
166
+ st.subheader("πŸ” Login")
167
+ input_key = Key
168
+ if st.button("πŸš€ Login"):
169
+ if input_key:
170
+ st.session_state.primary_key = input_key
171
+ st.session_state.logged_in = True
172
+ st.rerun()
173
+ else:
174
+ st.error("Invalid key. Please check your environment variables.")
175
+ else:
176
+ # Initialize Cosmos DB client
177
+ try:
178
+ client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
179
+ database = client.get_database_client(DATABASE_NAME)
180
+ container = database.get_container_client(CONTAINER_NAME)
181
+ except exceptions.CosmosHttpResponseError as e:
182
+ st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)}. Status code: {e.status_code}")
183
+ st.stop()
184
+ except Exception as e:
185
+ st.error(f"An unexpected error occurred while connecting to Cosmos DB: {str(e)}")
186
+ st.stop()
187
+
188
+ # GitHub section
189
+ st.subheader("πŸ™ GitHub Operations")
190
+ github_token = os.environ.get("GITHUB_TOKEN") # Read GitHub token from environment variable
191
+ source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
192
+ new_repo_name = st.text_input("New Repository Name (for cloning)", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
193
+
194
+ col1, col2 = st.columns(2)
195
+ with col1:
196
+ if st.button("πŸ“₯ Clone Repository"):
197
+ if github_token and source_repo:
198
+ try:
199
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
200
+ download_github_repo(source_repo, local_path)
201
+ zip_filename = f"{new_repo_name}.zip"
202
+ create_zip_file(local_path, zip_filename[:-4])
203
+ st.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
204
+ st.success("Repository cloned successfully!")
205
+ except Exception as e:
206
+ st.error(f"An error occurred: {str(e)}")
207
+ finally:
208
+ if os.path.exists(local_path):
209
+ shutil.rmtree(local_path)
210
+ if os.path.exists(zip_filename):
211
+ os.remove(zip_filename)
212
+ else:
213
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided.")
214
+
215
+ with col2:
216
+ if st.button("πŸ“€ Push to New Repository"):
217
+ if github_token and source_repo:
218
+ try:
219
+ g = Github(github_token)
220
+ new_repo = create_repo(g, new_repo_name)
221
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
222
+ download_github_repo(source_repo, local_path)
223
+ push_to_github(local_path, new_repo, github_token)
224
+ st.success(f"Repository pushed successfully to {new_repo.html_url}")
225
+ except Exception as e:
226
+ st.error(f"An error occurred: {str(e)}")
227
+ finally:
228
+ if os.path.exists(local_path):
229
+ shutil.rmtree(local_path)
230
+ else:
231
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided.")
232
+
233
+ # Cosmos DB Operations
234
+ st.subheader("☁️ Cosmos DB Operations")
235
+
236
+ # Archive all data
237
+ if st.button("πŸ“¦ Archive All Cosmos DB Data"):
238
+ download_link = archive_all_data(client)
239
+ st.markdown(download_link, unsafe_allow_html=True)
240
+
241
+ # Fetch and display all records
242
+ st.subheader("πŸ“Š All Records")
243
+ df = fetch_all_records()
244
+
245
+ if df.empty:
246
+ st.write("No records found in the database.")
247
+ else:
248
+ st.write("Records:")
249
+ for index, row in df.iterrows():
250
+ col1, col2, col3 = st.columns([5, 1, 1])
251
+
252
+ with col1:
253
+ st.write(f"ID: {row['id']}, Name: {row['name']}, Document: {row['document']}, "
254
+ f"Evaluation Text: {row['evaluationText']}, Evaluation Score: {row['evaluationScore']}")
255
+
256
+ with col2:
257
+ key = f"select_{row['id']}"
258
+ if st.button(f"πŸ‘‰ Select", key=key):
259
+ st.session_state.selected_record = row.to_dict()
260
+
261
+ with col3:
262
+ if st.button(f"πŸ—‘οΈ Delete", key=f"delete_{row['id']}"):
263
+ success, message = delete_record(row['name'], row['id'])
264
+ if success:
265
+ st.success(message)
266
+ st.rerun()
267
+ else:
268
+ st.error(message)
269
+
270
+ # Display selected record for editing
271
+ if 'selected_record' in st.session_state and st.session_state.selected_record:
272
+ selected_record = st.session_state.selected_record
273
+
274
+ st.subheader(f"Editing Record - ID: {selected_record['id']}")
275
+
276
+ updated_name = st.text_input("Name", value=selected_record['name'])
277
+ updated_document = st.text_area("Document", value=selected_record['document'])
278
+ updated_evaluation_text = st.text_area("Evaluation Text", value=selected_record['evaluationText'])
279
+ updated_evaluation_score = st.text_input("Evaluation Score", value=str(selected_record['evaluationScore']))
280
+
281
+ if st.button("πŸ’Ύ Save Changes"):
282
+ updated_record = {
283
+ "id": selected_record['id'],
284
+ "name": updated_name,
285
+ "document": updated_document,
286
+ "evaluationText": updated_evaluation_text,
287
+ "evaluationScore": updated_evaluation_score
288
+ }
289
+
290
+ success, message = update_record(updated_record)
291
+ if success:
292
+ st.success(message)
293
+ st.session_state.selected_record = updated_record
294
+ else:
295
+ st.error(message)
296
+
297
+ # Input fields for new record
298
+ st.subheader("πŸ“ Enter New Record Details")
299
+ new_id = st.text_input("ID")
300
+ new_name = st.text_input("Name")
301
+ new_document = st.text_area("Document")
302
+ new_evaluation_text = st.text_area("Evaluation Text")
303
+ new_evaluation_score = st.text_input("Evaluation Score")
304
+
305
+ col1, col2 = st.columns(2)
306
+
307
+ with col1:
308
+ if st.button("πŸ’Ύ Insert Record"):
309
+ record = {
310
+ "id": new_id,
311
+ "name": new_name,
312
+ "document": new_document,
313
+ "evaluationText": new_evaluation_text,
314
+ "evaluationScore": new_evaluation_score
315
+ }
316
+
317
+ success, response = insert_record(record)
318
+ if success:
319
+ st.success("βœ… Record inserted successfully!")
320
+ st.json(response)
321
+ else:
322
+ st.error(f"❌ Failed to insert record: {response}")
323
+ st.rerun()
324
+
325
+ with col2:
326
+ if st.button("πŸ”§ Call Procedure"):
327
+ record = {
328
+ "id": new_id,
329
+ "name": new_name,
330
+ "document": new_document,
331
+ "evaluationText": new_evaluation_text,
332
+ "evaluationScore": new_evaluation_score
333
+ }
334
+
335
+ success, response = call_stored_procedure(record)
336
+ if success:
337
+ st.success("βœ… Stored procedure executed successfully!")
338
+ st.json(response)
339
+ else:
340
+ st.error(f"❌ Failed to execute stored procedure: {response}")
341
+
342
+ # Logout button
343
+ if st.button("πŸšͺ Logout"):
344
+ st.session_state.logged_in = False
345
+ st.session_state.selected_records.clear()
346
+ st.session_state.selected_record = None
347
+ st.rerun()
348
+
349
+ # Display connection info
350
+ st.sidebar.subheader("πŸ”— Connection Information")
351
+ st.sidebar.text(f"Endpoint: {ENDPOINT}")
352
+ st.sidebar.text(f"Subscription ID: {SUBSCRIPTION_ID}")
353
+ st.sidebar.text(f"Database: {DATABASE_NAME}")
354
+ st.sidebar.text(f"Container: {CONTAINER_NAME}")
355
+
356
+ #if __name__ == "__main__":
357
+ # st.write("Application is running")