awacke1 commited on
Commit
34bc3b5
Β·
verified Β·
1 Parent(s): 24201c9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +520 -0
app.py ADDED
@@ -0,0 +1,520 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from azure.cosmos import CosmosClient, exceptions
3
+ import os
4
+ import pandas as pd
5
+ import traceback
6
+ import shutil
7
+ from github import Github
8
+ from git import Repo
9
+ from datetime import datetime
10
+ import base64
11
+ import json
12
+ import uuid # 🎲 For generating unique IDs
13
+ from urllib.parse import quote # πŸ”— For encoding URLs
14
+ from gradio_client import Client # 🌐 For connecting to Gradio apps
15
+
16
+ # πŸŽ‰ Welcome to our fun-filled Cosmos DB and GitHub Integration app!
17
+ st.set_page_config(layout="wide")
18
+
19
+ # 🌌 Cosmos DB configuration
20
+ ENDPOINT = "https://acae-afd.documents.azure.com:443/"
21
+ DATABASE_NAME = os.environ.get("COSMOS_DATABASE_NAME")
22
+ CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
23
+ Key = os.environ.get("Key") # πŸ”‘ Don't forget your key!
24
+
25
+ # 🏠 Your local app URL (Change this to your app's URL)
26
+ LOCAL_APP_URL = "http://localhost:8501"
27
+
28
+ # πŸ™ GitHub configuration
29
+ def download_github_repo(url, local_path):
30
+ # 🚚 Let's download that GitHub repo!
31
+ if os.path.exists(local_path):
32
+ shutil.rmtree(local_path)
33
+ Repo.clone_from(url, local_path)
34
+
35
+ def create_zip_file(source_dir, output_filename):
36
+ # πŸ“¦ Zipping up files like a pro!
37
+ shutil.make_archive(output_filename, 'zip', source_dir)
38
+
39
+ def create_repo(g, repo_name):
40
+ # πŸ› οΈ Creating a new GitHub repo. Magic!
41
+ user = g.get_user()
42
+ return user.create_repo(repo_name)
43
+
44
+ def push_to_github(local_path, repo, github_token):
45
+ # πŸš€ Pushing code to GitHub. Hold on tight!
46
+ repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
47
+ local_repo = Repo(local_path)
48
+
49
+ if 'origin' in [remote.name for remote in local_repo.remotes]:
50
+ origin = local_repo.remote('origin')
51
+ origin.set_url(repo_url)
52
+ else:
53
+ origin = local_repo.create_remote('origin', repo_url)
54
+
55
+ if not local_repo.heads:
56
+ local_repo.git.checkout('-b', 'main')
57
+ current_branch = 'main'
58
+ else:
59
+ current_branch = local_repo.active_branch.name
60
+
61
+ local_repo.git.add(A=True)
62
+
63
+ if local_repo.is_dirty():
64
+ local_repo.git.commit('-m', 'Initial commit')
65
+
66
+ origin.push(refspec=f'{current_branch}:{current_branch}')
67
+
68
+ def get_base64_download_link(file_path, file_name):
69
+ # πŸ§™β€β™‚οΈ Generating a magical download link!
70
+ with open(file_path, "rb") as file:
71
+ contents = file.read()
72
+ base64_encoded = base64.b64encode(contents).decode()
73
+ return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">⬇️ Download {file_name}</a>'
74
+
75
+
76
+ # 🧭 New functions for dynamic sidebar navigation
77
+ def get_databases(client):
78
+ # πŸ“š Fetching list of databases. So many options!
79
+ return [db['id'] for db in client.list_databases()]
80
+
81
+ def get_containers(database):
82
+ # πŸ“‚ Getting containers. Containers within containers!
83
+ return [container['id'] for container in database.list_containers()]
84
+
85
+ def get_documents(container, limit=None):
86
+ # πŸ“ Retrieving documents. Shhh, don't tell anyone!
87
+ query = "SELECT * FROM c ORDER BY c._ts DESC"
88
+ items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
89
+ return items
90
+
91
+
92
+ # 🌟 Cosmos DB functions
93
+ def insert_record(container, record):
94
+ try:
95
+ container.create_item(body=record)
96
+ return True, "Record inserted successfully! πŸŽ‰"
97
+ except exceptions.CosmosHttpResponseError as e:
98
+ return False, f"HTTP error occurred: {str(e)} 🚨"
99
+ except Exception as e:
100
+ return False, f"An unexpected error occurred: {str(e)} 😱"
101
+
102
+ def update_record(container, updated_record):
103
+ try:
104
+ container.upsert_item(body=updated_record)
105
+ return True, f"Record with id {updated_record['id']} successfully updated. πŸ› οΈ"
106
+ except exceptions.CosmosHttpResponseError as e:
107
+ return False, f"HTTP error occurred: {str(e)} 🚨"
108
+ except Exception as e:
109
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
110
+
111
+ def delete_record(container, name, id):
112
+ try:
113
+ container.delete_item(item=id, partition_key=id)
114
+ return True, f"Successfully deleted record with name: {name} and id: {id} πŸ—‘οΈ"
115
+ except exceptions.CosmosResourceNotFoundError:
116
+ return False, f"Record with id {id} not found. It may have been already deleted. πŸ•΅οΈβ€β™‚οΈ"
117
+ except exceptions.CosmosHttpResponseError as e:
118
+ return False, f"HTTP error occurred: {str(e)} 🚨"
119
+ except Exception as e:
120
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
121
+
122
+ # 🎲 Function to generate a unique UUID
123
+ def generate_unique_id():
124
+ # πŸ§™β€β™‚οΈ Generating a unique UUID!
125
+ return str(uuid.uuid4())
126
+
127
+ # πŸ“¦ Function to archive current container
128
+ def archive_current_container(database_name, container_name, client):
129
+ try:
130
+ base_dir = "./cosmos_archive_current_container"
131
+ if os.path.exists(base_dir):
132
+ shutil.rmtree(base_dir)
133
+ os.makedirs(base_dir)
134
+
135
+ db_client = client.get_database_client(database_name)
136
+ container_client = db_client.get_container_client(container_name)
137
+ items = list(container_client.read_all_items())
138
+
139
+ container_dir = os.path.join(base_dir, container_name)
140
+ os.makedirs(container_dir)
141
+
142
+ for item in items:
143
+ item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
144
+ with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
145
+ json.dump(item, f, indent=2)
146
+
147
+ archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
148
+ shutil.make_archive(archive_name, 'zip', base_dir)
149
+
150
+ return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
151
+ except Exception as e:
152
+ return f"An error occurred while archiving data: {str(e)} 😒"
153
+
154
+ # πŸ” Search Glossary function
155
+ def search_glossary(query):
156
+ # πŸ•΅οΈβ€β™‚οΈ Searching the glossary for: query
157
+ all_results = ""
158
+ st.markdown(f"- {query}")
159
+
160
+ # πŸ” Run 1 - ArXiv RAG researcher expert ~-<>-~ Paper Summary & Ask LLM
161
+ client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
162
+ response2 = client.predict(
163
+ query, # str in 'parameter_13' Textbox component
164
+ "google/gemma-7b-it", # LLM Model Dropdown component
165
+ True, # Stream output Checkbox component
166
+ api_name="/ask_llm"
167
+ )
168
+ st.write('πŸ” Run of Multi-Agent System Paper Summary Spec is Complete')
169
+ st.markdown(response2)
170
+
171
+ # ArXiv searcher ~-<>-~ Paper References - Update with RAG
172
+ client = Client("awacke1/Arxiv-Paper-Search-And-QA-RAG-Pattern")
173
+ response1 = client.predict(
174
+ query,
175
+ 10,
176
+ "Semantic Search - up to 10 Mar 2024", # Search Source Dropdown component
177
+ "mistralai/Mixtral-8x7B-Instruct-v0.1", # LLM Model Dropdown component
178
+ api_name="/update_with_rag_md"
179
+ )
180
+ st.write('πŸ” Run of Multi-Agent System Paper References is Complete')
181
+ responseall = response2 + response1[0] + response1[1]
182
+ st.markdown(responseall)
183
+ return responseall
184
+
185
+ # 🎈 Let's modify the main app to be more fun!
186
+ def main():
187
+ st.title("πŸ™Git🌌CosmosπŸ’« - Azure Cosmos DB and Github Agent")
188
+
189
+ # 🚦 Initialize session state
190
+ if 'logged_in' not in st.session_state:
191
+ st.session_state.logged_in = False
192
+ if 'selected_records' not in st.session_state:
193
+ st.session_state.selected_records = []
194
+ if 'client' not in st.session_state:
195
+ st.session_state.client = None
196
+ if 'selected_database' not in st.session_state:
197
+ st.session_state.selected_database = None
198
+ if 'selected_container' not in st.session_state:
199
+ st.session_state.selected_container = None
200
+ if 'selected_document_id' not in st.session_state:
201
+ st.session_state.selected_document_id = None
202
+ if 'current_index' not in st.session_state:
203
+ st.session_state.current_index = 0
204
+ if 'cloned_doc' not in st.session_state:
205
+ st.session_state.cloned_doc = None
206
+
207
+ # πŸ” Check for query parameters
208
+ query_params = st.experimental_get_query_params()
209
+ if 'q' in query_params:
210
+ query = query_params['q'][0] # Get the first value of 'q'
211
+ # πŸ•΅οΈβ€β™‚οΈ We have a query! Let's search the glossary!
212
+ search_glossary(query)
213
+ st.stop() # Stop further execution
214
+
215
+ # πŸ” Automatic Login
216
+ if Key:
217
+ st.session_state.primary_key = Key
218
+ st.session_state.logged_in = True
219
+ else:
220
+ st.error("Cosmos DB Key is not set in environment variables. πŸ”‘βŒ")
221
+ return # Can't proceed without a key
222
+
223
+ if st.session_state.logged_in:
224
+ # 🌌 Initialize Cosmos DB client
225
+ try:
226
+ if st.session_state.client is None:
227
+ st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
228
+
229
+ # πŸ—„οΈ Sidebar for database, container, and document selection
230
+ st.sidebar.title("πŸ™Git🌌CosmosπŸ’«πŸ—„οΈNavigator")
231
+
232
+ databases = get_databases(st.session_state.client)
233
+ selected_db = st.sidebar.selectbox("πŸ—ƒοΈ Select Database", databases)
234
+
235
+ if selected_db != st.session_state.selected_database:
236
+ st.session_state.selected_database = selected_db
237
+ st.session_state.selected_container = None
238
+ st.session_state.selected_document_id = None
239
+ st.session_state.current_index = 0
240
+ st.rerun()
241
+
242
+ if st.session_state.selected_database:
243
+ database = st.session_state.client.get_database_client(st.session_state.selected_database)
244
+ containers = get_containers(database)
245
+ selected_container = st.sidebar.selectbox("πŸ“ Select Container", containers)
246
+
247
+ if selected_container != st.session_state.selected_container:
248
+ st.session_state.selected_container = selected_container
249
+ st.session_state.selected_document_id = None
250
+ st.session_state.current_index = 0
251
+ st.rerun()
252
+
253
+ if st.session_state.selected_container:
254
+ container = database.get_container_client(st.session_state.selected_container)
255
+
256
+ # πŸ“¦ Add Export button
257
+ if st.button("πŸ“¦ Export Container Data"):
258
+ download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
259
+ if download_link.startswith('<a'):
260
+ st.markdown(download_link, unsafe_allow_html=True)
261
+ else:
262
+ st.error(download_link)
263
+
264
+ # Fetch documents
265
+ documents = get_documents(container)
266
+ total_docs = len(documents)
267
+
268
+ if total_docs > 5:
269
+ documents_to_display = documents[:5]
270
+ st.info("Showing top 5 most recent documents.")
271
+ else:
272
+ documents_to_display = documents
273
+ st.info(f"Showing all {len(documents_to_display)} documents.")
274
+
275
+ if documents_to_display:
276
+ # 🎨 Add Viewer/Editor selection
277
+ view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Edit and Save', 'Clone Document', 'New Record']
278
+ selected_view = st.selectbox("Select Viewer/Editor", view_options, index=2)
279
+
280
+ if selected_view == 'Show as Markdown':
281
+ # πŸ–ŒοΈ Show each record as Markdown with navigation
282
+ total_docs = len(documents)
283
+ doc = documents[st.session_state.current_index]
284
+ st.markdown(f"#### Document ID: {doc.get('id', '')}")
285
+
286
+ # πŸ•΅οΈβ€β™‚οΈ Let's extract values from the JSON that have at least one space
287
+ values_with_space = []
288
+ def extract_values(obj):
289
+ if isinstance(obj, dict):
290
+ for k, v in obj.items():
291
+ extract_values(v)
292
+ elif isinstance(obj, list):
293
+ for item in obj:
294
+ extract_values(item)
295
+ elif isinstance(obj, str):
296
+ if ' ' in obj:
297
+ values_with_space.append(obj)
298
+
299
+ extract_values(doc)
300
+
301
+ # πŸ”— Let's create a list of links for these values
302
+ search_urls = {
303
+ "πŸš€πŸŒŒArXiv": lambda k: f"/?q={quote(k)}",
304
+ "πŸƒAnalyst": lambda k: f"/?q={quote(k)}-{quote('PromptPrefix')}",
305
+ "πŸ“šPyCoder": lambda k: f"/?q={quote(k)}-{quote('PromptPrefix2')}",
306
+ "πŸ”¬JSCoder": lambda k: f"/?q={quote(k)}-{quote('PromptPrefix3')}",
307
+ "🏠": lambda k: f"{LOCAL_APP_URL}/?q={quote(k)}",
308
+ "πŸ“–": lambda k: f"https://en.wikipedia.org/wiki/{quote(k)}",
309
+ "πŸ”": lambda k: f"https://www.google.com/search?q={quote(k)}",
310
+ "▢️": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
311
+ "πŸ”Ž": lambda k: f"https://www.bing.com/search?q={quote(k)}",
312
+ "πŸŽ₯": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
313
+ "🐦": lambda k: f"https://twitter.com/search?q={quote(k)}",
314
+ }
315
+
316
+ st.markdown("#### πŸ”— Links for Extracted Texts")
317
+ for term in values_with_space:
318
+ links_md = ' '.join([f"[{emoji}]({url(term)})" for emoji, url in search_urls.items()])
319
+ st.markdown(f"**{term}** <small>{links_md}</small>", unsafe_allow_html=True)
320
+
321
+ # Show the document content as markdown
322
+ content = json.dumps(doc, indent=2)
323
+ st.markdown(f"```json\n{content}\n```")
324
+
325
+ # Navigation buttons
326
+ col_prev, col_next = st.columns([1, 1])
327
+ with col_prev:
328
+ if st.button("⬅️ Previous", key='prev_markdown'):
329
+ if st.session_state.current_index > 0:
330
+ st.session_state.current_index -= 1
331
+ st.rerun()
332
+ with col_next:
333
+ if st.button("➑️ Next", key='next_markdown'):
334
+ if st.session_state.current_index < total_docs - 1:
335
+ st.session_state.current_index += 1
336
+ st.rerun()
337
+
338
+ elif selected_view == 'Show as Code Editor':
339
+ # πŸ’» Show each record in a code editor with navigation
340
+ total_docs = len(documents)
341
+ doc = documents[st.session_state.current_index]
342
+ st.markdown(f"#### Document ID: {doc.get('id', '')}")
343
+ doc_str = st.text_area("Edit Document", value=json.dumps(doc, indent=2), height=300, key=f'code_editor_{st.session_state.current_index}')
344
+ col_prev, col_next = st.columns([1, 1])
345
+ with col_prev:
346
+ if st.button("⬅️ Previous", key='prev_code'):
347
+ if st.session_state.current_index > 0:
348
+ st.session_state.current_index -= 1
349
+ st.rerun()
350
+ with col_next:
351
+ if st.button("➑️ Next", key='next_code'):
352
+ if st.session_state.current_index < total_docs - 1:
353
+ st.session_state.current_index += 1
354
+ st.rerun()
355
+ if st.button("πŸ’Ύ Save Changes", key=f'save_button_{st.session_state.current_index}'):
356
+ try:
357
+ updated_doc = json.loads(doc_str)
358
+ success, message = update_record(container, updated_doc)
359
+ if success:
360
+ st.success(f"Document {updated_doc['id']} saved successfully.")
361
+ st.session_state.selected_document_id = updated_doc['id']
362
+ st.rerun()
363
+ else:
364
+ st.error(message)
365
+ except json.JSONDecodeError as e:
366
+ st.error(f"Invalid JSON: {str(e)} 🚫")
367
+ elif selected_view == 'Show as Edit and Save':
368
+ # ✏️ Show as Edit and Save in columns
369
+ st.markdown("#### Edit the document fields below:")
370
+
371
+ # Create columns for each document
372
+ num_cols = len(documents_to_display)
373
+ cols = st.columns(num_cols)
374
+
375
+ for idx, (col, doc) in enumerate(zip(cols, documents_to_display)):
376
+ with col:
377
+ st.markdown(f"##### Document ID: {doc.get('id', '')}")
378
+ editable_id = st.text_input("ID", value=doc.get('id', ''), key=f'edit_id_{idx}')
379
+ # Remove 'id' from the document for editing other fields
380
+ editable_doc = doc.copy()
381
+ editable_doc.pop('id', None)
382
+ doc_str = st.text_area("Document Content (in JSON format)", value=json.dumps(editable_doc, indent=2), height=300, key=f'doc_str_{idx}')
383
+ if st.button("πŸ’Ύ Save Changes", key=f'save_button_{idx}'):
384
+ try:
385
+ updated_doc = json.loads(doc_str)
386
+ updated_doc['id'] = editable_id # Include the possibly edited ID
387
+ success, message = update_record(container, updated_doc)
388
+ if success:
389
+ st.success(f"Document {updated_doc['id']} saved successfully.")
390
+ st.session_state.selected_document_id = updated_doc['id']
391
+ st.rerun()
392
+ else:
393
+ st.error(message)
394
+ except json.JSONDecodeError as e:
395
+ st.error(f"Invalid JSON: {str(e)} 🚫")
396
+ elif selected_view == 'Clone Document':
397
+ # 🧬 Clone Document per record
398
+ st.markdown("#### Clone a document:")
399
+ for idx, doc in enumerate(documents_to_display):
400
+ st.markdown(f"##### Document ID: {doc.get('id', '')}")
401
+ if st.button("πŸ“„ Clone Document", key=f'clone_button_{idx}'):
402
+ cloned_doc = doc.copy()
403
+ # Generate a unique ID
404
+ cloned_doc['id'] = generate_unique_id()
405
+ st.session_state.cloned_doc = cloned_doc
406
+ st.session_state.cloned_doc_str = json.dumps(cloned_doc, indent=2)
407
+ st.session_state.clone_mode = True
408
+ st.rerun()
409
+ if st.session_state.get('clone_mode', False):
410
+ st.markdown("#### Edit Cloned Document:")
411
+ cloned_doc_str = st.text_area("Cloned Document Content (in JSON format)", value=st.session_state.cloned_doc_str, height=300)
412
+ if st.button("πŸ’Ύ Save Cloned Document"):
413
+ try:
414
+ new_doc = json.loads(cloned_doc_str)
415
+ success, message = insert_record(container, new_doc)
416
+ if success:
417
+ st.success(f"Cloned document saved with id: {new_doc['id']} πŸŽ‰")
418
+ st.session_state.selected_document_id = new_doc['id']
419
+ st.session_state.clone_mode = False
420
+ st.session_state.cloned_doc = None
421
+ st.session_state.cloned_doc_str = ''
422
+ st.rerun()
423
+ else:
424
+ st.error(message)
425
+ except json.JSONDecodeError as e:
426
+ st.error(f"Invalid JSON: {str(e)} 🚫")
427
+ elif selected_view == 'New Record':
428
+ # πŸ†• New Record
429
+ st.markdown("#### Create a new document:")
430
+ new_id = st.text_input("ID", value=generate_unique_id(), key='new_id')
431
+ new_doc_str = st.text_area("Document Content (in JSON format)", value='{}', height=300)
432
+ if st.button("βž• Create New Document"):
433
+ try:
434
+ new_doc = json.loads(new_doc_str)
435
+ new_doc['id'] = new_id # Use the provided ID
436
+ success, message = insert_record(container, new_doc)
437
+ if success:
438
+ st.success(f"New document created with id: {new_doc['id']} πŸŽ‰")
439
+ st.session_state.selected_document_id = new_doc['id']
440
+ # Switch to 'Show as Edit and Save' mode
441
+ st.rerun()
442
+ else:
443
+ st.error(message)
444
+ except json.JSONDecodeError as e:
445
+ st.error(f"Invalid JSON: {str(e)} 🚫")
446
+ else:
447
+ st.sidebar.info("No documents found in this container. πŸ“­")
448
+
449
+ # πŸŽ‰ Main content area
450
+ st.subheader(f"πŸ“Š Container: {st.session_state.selected_container}")
451
+ if st.session_state.selected_container:
452
+ if documents_to_display:
453
+ df = pd.DataFrame(documents_to_display)
454
+ st.dataframe(df)
455
+ else:
456
+ st.info("No documents to display. 🧐")
457
+
458
+ # πŸ™ GitHub section
459
+ st.subheader("πŸ™ GitHub Operations")
460
+ github_token = os.environ.get("GITHUB") # Read GitHub token from environment variable
461
+ source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
462
+ new_repo_name = st.text_input("New Repository Name (for cloning)", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
463
+
464
+ col1, col2 = st.columns(2)
465
+ with col1:
466
+ if st.button("πŸ“₯ Clone Repository"):
467
+ if github_token and source_repo:
468
+ try:
469
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
470
+ download_github_repo(source_repo, local_path)
471
+ zip_filename = f"{new_repo_name}.zip"
472
+ create_zip_file(local_path, zip_filename[:-4])
473
+ st.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
474
+ st.success("Repository cloned successfully! πŸŽ‰")
475
+ except Exception as e:
476
+ st.error(f"An error occurred: {str(e)} 😒")
477
+ finally:
478
+ if os.path.exists(local_path):
479
+ shutil.rmtree(local_path)
480
+ if os.path.exists(zip_filename):
481
+ os.remove(zip_filename)
482
+ else:
483
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
484
+
485
+ with col2:
486
+ if st.button("πŸ“€ Push to New Repository"):
487
+ if github_token and source_repo:
488
+ try:
489
+ g = Github(github_token)
490
+ new_repo = create_repo(g, new_repo_name)
491
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
492
+ download_github_repo(source_repo, local_path)
493
+ push_to_github(local_path, new_repo, github_token)
494
+ st.success(f"Repository pushed successfully to {new_repo.html_url} πŸš€")
495
+ except Exception as e:
496
+ st.error(f"An error occurred: {str(e)} 😒")
497
+ finally:
498
+ if os.path.exists(local_path):
499
+ shutil.rmtree(local_path)
500
+ else:
501
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
502
+
503
+ except exceptions.CosmosHttpResponseError as e:
504
+ st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
505
+ except Exception as e:
506
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
507
+
508
+ # πŸšͺ Logout button
509
+ if st.session_state.logged_in and st.sidebar.button("πŸšͺ Logout"):
510
+ st.session_state.logged_in = False
511
+ st.session_state.selected_records.clear()
512
+ st.session_state.client = None
513
+ st.session_state.selected_database = None
514
+ st.session_state.selected_container = None
515
+ st.session_state.selected_document_id = None
516
+ st.session_state.current_index = 0
517
+ st.rerun()
518
+
519
+ if __name__ == "__main__":
520
+ main()