awacke1 commited on
Commit
81e895d
Β·
verified Β·
1 Parent(s): 748e3e8

Update backup7.app.py

Browse files
Files changed (1) hide show
  1. backup7.app.py +454 -89
backup7.app.py CHANGED
@@ -12,29 +12,34 @@ 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
 
@@ -58,83 +63,432 @@ def push_to_github(local_path, repo, github_token):
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
 
67
- # New functions for dynamic sidebar
68
  def get_databases(client):
 
69
  return [db['id'] for db in client.list_databases()]
70
 
71
  def get_containers(database):
 
72
  return [container['id'] for container in database.list_containers()]
73
 
74
  def get_documents(container, limit=1000):
 
75
  query = "SELECT * FROM c"
76
  items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
77
  return items
78
 
79
 
80
- # Cosmos DB functions
81
- def insert_record(record):
82
  try:
83
- response = container.create_item(body=record)
84
- return True, response
85
  except exceptions.CosmosHttpResponseError as e:
86
- return False, f"HTTP error occurred: {str(e)}. Status code: {e.status_code}"
87
  except Exception as e:
88
- return False, f"An unexpected error occurred: {str(e)}"
89
 
90
- def call_stored_procedure(record):
91
  try:
92
- response = container.scripts.execute_stored_procedure(
93
- sproc="processPrompt",
94
- params=[record],
95
- partition_key=record['id']
96
- )
97
- return True, response
98
  except exceptions.CosmosHttpResponseError as e:
99
- error_message = f"HTTP error occurred: {str(e)}. Status code: {e.status_code}"
100
- return False, error_message
101
  except Exception as e:
102
- error_message = f"An unexpected error occurred: {str(e)}"
103
- return False, error_message
104
 
105
- def fetch_all_records():
106
  try:
107
- query = "SELECT * FROM c"
108
- items = list(container.query_items(query=query, enable_cross_partition_query=True))
109
- return pd.DataFrame(items)
 
110
  except exceptions.CosmosHttpResponseError as e:
111
- st.error(f"HTTP error occurred while fetching records: {str(e)}. Status code: {e.status_code}")
112
- return pd.DataFrame()
113
  except Exception as e:
114
- st.error(f"An unexpected error occurred while fetching records: {str(e)}")
115
- return pd.DataFrame()
116
 
117
- def update_record(updated_record):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  try:
119
  container.upsert_item(body=updated_record)
120
- return True, f"Record with id {updated_record['id']} successfully updated."
121
  except exceptions.CosmosHttpResponseError as e:
122
- return False, f"HTTP error occurred: {str(e)}. Status code: {e.status_code}"
123
  except Exception as e:
124
- return False, f"An unexpected error occurred: {traceback.format_exc()}"
125
 
126
- def delete_record(name, id):
127
  try:
128
  container.delete_item(item=id, partition_key=id)
129
- return True, f"Successfully deleted record with name: {name} and id: {id}"
130
  except exceptions.CosmosResourceNotFoundError:
131
- return False, f"Record with id {id} not found. It may have been already deleted."
132
  except exceptions.CosmosHttpResponseError as e:
133
- return False, f"HTTP error occurred: {str(e)}. Status code: {e.status_code}"
134
  except Exception as e:
135
- return False, f"An unexpected error occurred: {traceback.format_exc()}"
 
 
 
 
 
136
 
137
- # New function to archive current container
138
  def archive_current_container(database_name, container_name, client):
139
  try:
140
  base_dir = "./cosmos_archive_current_container"
@@ -159,14 +513,14 @@ def archive_current_container(database_name, container_name, client):
159
 
160
  return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
161
  except Exception as e:
162
- return f"An error occurred while archiving data: {str(e)}"
163
 
164
 
165
- # Modify the main app
166
  def main():
167
  st.title("🌟 Cosmos DB and GitHub Integration")
168
 
169
- # Initialize session state
170
  if 'logged_in' not in st.session_state:
171
  st.session_state.logged_in = False
172
  if 'selected_records' not in st.session_state:
@@ -178,27 +532,27 @@ def main():
178
  if 'selected_container' not in st.session_state:
179
  st.session_state.selected_container = None
180
 
181
- # Login section
182
  if not st.session_state.logged_in:
183
  st.subheader("πŸ” Login")
184
- #input_key = st.text_input("Enter your Cosmos DB key", type="password")
185
- input_key=Key
186
 
187
- # Cosmos DB configuration
188
  if st.button("πŸš€ Login"):
189
  if input_key:
190
  st.session_state.primary_key = input_key
191
  st.session_state.logged_in = True
192
  st.rerun()
193
  else:
194
- st.error("Invalid key. Please check your input.")
195
  else:
196
- # Initialize Cosmos DB client
197
  try:
198
  if st.session_state.client is None:
199
  st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
200
 
201
- # Sidebar for database, container, and document selection
202
  st.sidebar.title("πŸ—„οΈ Cosmos DB Navigator")
203
 
204
  databases = get_databases(st.session_state.client)
@@ -221,7 +575,7 @@ def main():
221
  if st.session_state.selected_container:
222
  container = database.get_container_client(st.session_state.selected_container)
223
 
224
- # Add Export button
225
  if st.button("πŸ“¦ Export Container Data"):
226
  download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
227
  if download_link.startswith('<a'):
@@ -240,78 +594,89 @@ def main():
240
  st.subheader(f"πŸ“„ Document Details: {selected_document}")
241
  selected_doc = next((doc for doc in documents if doc.get('id') == selected_document), None)
242
  if selected_doc:
243
- # Add Viewer/Editor selection
244
  view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Edit and Save', 'Clone Document', 'New Record']
245
  selected_view = st.selectbox("Select Viewer/Editor", view_options)
246
-
247
  if selected_view == 'Show as Markdown':
248
- # Show as Markdown
249
  items = get_documents(container)
250
  for item in items:
251
- st.markdown(f"### ID: {item.get('id', 'Unknown')}")
252
  content = item.get('content', '')
253
  if isinstance(content, dict) or isinstance(content, list):
254
  content = json.dumps(content, indent=2)
255
  st.markdown(content)
256
  elif selected_view == 'Show as Code Editor':
257
- # Show as Code Editor
258
  items = get_documents(container)
259
  for item in items:
 
260
  st.code(json.dumps(item, indent=2), language='python')
261
  elif selected_view == 'Show as Edit and Save':
262
- # Show as Edit and Save
263
- doc_str = st.text_area("Edit Document", value=json.dumps(selected_doc, indent=2), height=300)
264
- if st.button("πŸ’Ύ Save"):
 
 
 
 
 
265
  try:
266
  updated_doc = json.loads(doc_str)
267
- success, message = update_record(updated_doc)
 
268
  if success:
269
  st.success(message)
270
  else:
271
  st.error(message)
272
  except json.JSONDecodeError as e:
273
- st.error(f"Invalid JSON: {str(e)}")
274
  elif selected_view == 'Clone Document':
275
- # Clone Document
276
  if st.button("πŸ“„ Clone Document"):
277
  cloned_doc = selected_doc.copy()
278
- timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
279
- cloned_doc['id'] = f"{cloned_doc['id']}_clone_{timestamp}"
280
- success, message = insert_record(cloned_doc)
281
  if success:
282
- st.success(f"Document cloned with new id: {cloned_doc['id']}")
283
  else:
284
  st.error(message)
285
  elif selected_view == 'New Record':
286
- # New Record
287
- new_doc_str = st.text_area("New Document", value='{}', height=300)
 
 
288
  if st.button("βž• Create New Document"):
289
  try:
290
  new_doc = json.loads(new_doc_str)
291
- if 'id' not in new_doc:
292
- new_doc['id'] = f"new_doc_{datetime.now().strftime('%Y%m%d%H%M%S')}"
293
- success, message = insert_record(new_doc)
294
  if success:
295
- st.success(f"New document created with id: {new_doc['id']}")
296
  else:
297
  st.error(message)
298
  except json.JSONDecodeError as e:
299
- st.error(f"Invalid JSON: {str(e)}")
300
  else:
301
- st.sidebar.info("No documents found in this container.")
302
 
303
- # Main content area
304
  st.subheader(f"πŸ“Š Container: {st.session_state.selected_container}")
305
  if st.session_state.selected_container:
306
- df = pd.DataFrame(documents)
307
- st.dataframe(df)
 
 
 
308
 
309
- # GitHub section
310
  st.subheader("πŸ™ GitHub Operations")
311
  github_token = os.environ.get("GITHUB") # Read GitHub token from environment variable
312
  source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
313
  new_repo_name = st.text_input("New Repository Name (for cloning)", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
314
-
315
  col1, col2 = st.columns(2)
316
  with col1:
317
  if st.button("πŸ“₯ Clone Repository"):
@@ -322,16 +687,16 @@ def main():
322
  zip_filename = f"{new_repo_name}.zip"
323
  create_zip_file(local_path, zip_filename[:-4])
324
  st.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
325
- st.success("Repository cloned successfully!")
326
  except Exception as e:
327
- st.error(f"An error occurred: {str(e)}")
328
  finally:
329
  if os.path.exists(local_path):
330
  shutil.rmtree(local_path)
331
  if os.path.exists(zip_filename):
332
  os.remove(zip_filename)
333
  else:
334
- st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided.")
335
 
336
  with col2:
337
  if st.button("πŸ“€ Push to New Repository"):
@@ -342,21 +707,21 @@ def main():
342
  local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
343
  download_github_repo(source_repo, local_path)
344
  push_to_github(local_path, new_repo, github_token)
345
- st.success(f"Repository pushed successfully to {new_repo.html_url}")
346
  except Exception as e:
347
- st.error(f"An error occurred: {str(e)}")
348
  finally:
349
  if os.path.exists(local_path):
350
  shutil.rmtree(local_path)
351
  else:
352
- st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided.")
353
-
354
  except exceptions.CosmosHttpResponseError as e:
355
- st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)}. Status code: {e.status_code}")
356
  except Exception as e:
357
- st.error(f"An unexpected error occurred: {str(e)}")
358
 
359
- # Logout button
360
  if st.session_state.logged_in and st.sidebar.button("πŸšͺ Logout"):
361
  st.session_state.logged_in = False
362
  st.session_state.selected_records.clear()
 
12
  import base64
13
  import json
14
 
15
+ # πŸŽ‰ Welcome to our fun-filled Cosmos DB and GitHub Integration app!
16
  st.set_page_config(layout="wide")
17
 
18
+ # 🌌 Cosmos DB configuration
19
  ENDPOINT = "https://acae-afd.documents.azure.com:443/"
20
  SUBSCRIPTION_ID = "003fba60-5b3f-48f4-ab36-3ed11bc40816"
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
+ # πŸ™ GitHub configuration
26
  def download_github_repo(url, local_path):
27
+ # 🚚 Let's download that GitHub repo!
28
  if os.path.exists(local_path):
29
  shutil.rmtree(local_path)
30
  Repo.clone_from(url, local_path)
31
 
32
  def create_zip_file(source_dir, output_filename):
33
+ # πŸ“¦ Zipping up files like a pro!
34
  shutil.make_archive(output_filename, 'zip', source_dir)
35
 
36
  def create_repo(g, repo_name):
37
+ # πŸ› οΈ Creating a new GitHub repo. Magic!
38
  user = g.get_user()
39
  return user.create_repo(repo_name)
40
 
41
  def push_to_github(local_path, repo, github_token):
42
+ # πŸš€ Pushing code to GitHub. Hold on tight!
43
  repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
44
  local_repo = Repo(local_path)
45
 
 
63
  origin.push(refspec=f'{current_branch}:{current_branch}')
64
 
65
  def get_base64_download_link(file_path, file_name):
66
+ # πŸ§™β€β™‚οΈ Generating a magical download link!
67
  with open(file_path, "rb") as file:
68
  contents = file.read()
69
  base64_encoded = base64.b64encode(contents).decode()
70
+ return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">⬇️ Download {file_name}</a>'
71
 
72
 
73
+ # 🧭 New functions for dynamic sidebar navigation
74
  def get_databases(client):
75
+ # πŸ“š Fetching list of databases. So many options!
76
  return [db['id'] for db in client.list_databases()]
77
 
78
  def get_containers(database):
79
+ # πŸ“‚ Getting containers. Containers within containers!
80
  return [container['id'] for container in database.list_containers()]
81
 
82
  def get_documents(container, limit=1000):
83
+ # πŸ“ Retrieving documents. Shhh, don't tell anyone!
84
  query = "SELECT * FROM c"
85
  items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
86
  return items
87
 
88
 
89
+ # 🌟 Cosmos DB functions
90
+ def insert_record(container, record):
91
  try:
92
+ container.create_item(body=record)
93
+ return True, "Record inserted successfully! πŸŽ‰"
94
  except exceptions.CosmosHttpResponseError as e:
95
+ return False, f"HTTP error occurred: {str(e)} 🚨"
96
  except Exception as e:
97
+ return False, f"An unexpected error occurred: {str(e)} 😱"
98
 
99
+ def update_record(container, updated_record):
100
  try:
101
+ container.upsert_item(body=updated_record)
102
+ return True, f"Record with id {updated_record['id']} successfully updated. πŸ› οΈ"
 
 
 
 
103
  except exceptions.CosmosHttpResponseError as e:
104
+ return False, f"HTTP error occurred: {str(e)} 🚨"
 
105
  except Exception as e:
106
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
 
107
 
108
+ def delete_record(container, name, id):
109
  try:
110
+ container.delete_item(item=id, partition_key=id)
111
+ return True, f"Successfully deleted record with name: {name} and id: {id} πŸ—‘οΈ"
112
+ except exceptions.CosmosResourceNotFoundError:
113
+ return False, f"Record with id {id} not found. It may have been already deleted. πŸ•΅οΈβ€β™‚οΈ"
114
  except exceptions.CosmosHttpResponseError as e:
115
+ return False, f"HTTP error occurred: {str(e)} 🚨"
 
116
  except Exception as e:
117
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
 
118
 
119
+ # πŸ•’ Function to generate a unique ID based on timestamp
120
+ def generate_timestamp_id():
121
+ # ⏰ Time waits for no one, but IDs can!
122
+ return datetime.now().strftime('%Y%m%d%H%M%S%f')
123
+
124
+ # πŸ“¦ Function to archive current container
125
+ def archive_current_container(database_name, container_name, client):
126
+ try:
127
+ base_dir = "./cosmos_archive_current_container"
128
+ if os.path.exists(base_dir):
129
+ shutil.rmtree(base_dir)
130
+ os.makedirs(base_dir)
131
+
132
+ db_client = client.get_database_client(database_name)
133
+ container_client = db_client.get_container_client(container_name)
134
+ items = list(container_client.read_all_items())
135
+
136
+ container_dir = os.path.join(base_dir, container_name)
137
+ os.makedirs(container_dir)
138
+
139
+ for item in items:
140
+ item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
141
+ with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
142
+ json.dump(item, f, indent=2)
143
+
144
+ archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
145
+ shutil.make_archive(archive_name, 'zip', base_dir)
146
+
147
+ return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
148
+ except Exception as e:
149
+ return f"An error occurred while archiving data: {str(e)} 😒"
150
+
151
+
152
+ # 🎈 Let's modify the main app to be more fun!
153
+ def main():
154
+ st.title("🌟 Cosmos DB and GitHub Integration")
155
+
156
+ # 🚦 Initialize session state
157
+ if 'logged_in' not in st.session_state:
158
+ st.session_state.logged_in = False
159
+ if 'selected_records' not in st.session_state:
160
+ st.session_state.selected_records = []
161
+ if 'client' not in st.session_state:
162
+ st.session_state.client = None
163
+ if 'selected_database' not in st.session_state:
164
+ st.session_state.selected_database = None
165
+ if 'selected_container' not in st.session_state:
166
+ st.session_state.selected_container = None
167
+
168
+ # πŸ” Login section
169
+ if not st.session_state.logged_in:
170
+ st.subheader("πŸ” Login")
171
+ # Let's be sneaky and use the Key from environment variables! πŸ•΅οΈβ€β™‚οΈ
172
+ input_key = Key
173
+
174
+ # πŸš€ Time to blast off!
175
+ if st.button("πŸš€ Login"):
176
+ if input_key:
177
+ st.session_state.primary_key = input_key
178
+ st.session_state.logged_in = True
179
+ st.rerun()
180
+ else:
181
+ st.error("Invalid key. Please check your input. πŸ”‘βŒ")
182
+ else:
183
+ # 🌌 Initialize Cosmos DB client
184
+ try:
185
+ if st.session_state.client is None:
186
+ st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
187
+
188
+ # πŸ—„οΈ Sidebar for database, container, and document selection
189
+ st.sidebar.title("πŸ—„οΈ Cosmos DB Navigator")
190
+
191
+ databases = get_databases(st.session_state.client)
192
+ selected_db = st.sidebar.selectbox("πŸ—ƒοΈ Select Database", databases)
193
+
194
+ if selected_db != st.session_state.selected_database:
195
+ st.session_state.selected_database = selected_db
196
+ st.session_state.selected_container = None
197
+ st.rerun()
198
+
199
+ if st.session_state.selected_database:
200
+ database = st.session_state.client.get_database_client(st.session_state.selected_database)
201
+ containers = get_containers(database)
202
+ selected_container = st.sidebar.selectbox("πŸ“ Select Container", containers)
203
+
204
+ if selected_container != st.session_state.selected_container:
205
+ st.session_state.selected_container = selected_container
206
+ st.rerun()
207
+
208
+ if st.session_state.selected_container:
209
+ container = database.get_container_client(st.session_state.selected_container)
210
+
211
+ # πŸ“¦ Add Export button
212
+ if st.button("πŸ“¦ Export Container Data"):
213
+ download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
214
+ if download_link.startswith('<a'):
215
+ st.markdown(download_link, unsafe_allow_html=True)
216
+ else:
217
+ st.error(download_link)
218
+
219
+ limit_to_1000 = st.sidebar.checkbox("πŸ”’ Limit to top 1000 documents", value=True)
220
+ documents = get_documents(container, limit=1000 if limit_to_1000 else None)
221
+
222
+ if documents:
223
+ document_ids = [doc.get('id', 'Unknown') for doc in documents]
224
+ selected_document = st.sidebar.selectbox("πŸ“„ Select Document", document_ids)
225
+
226
+ if selected_document:
227
+ st.subheader(f"πŸ“„ Document Details: {selected_document}")
228
+ selected_doc = next((doc for doc in documents if doc.get('id') == selected_document), None)
229
+ if selected_doc:
230
+ # 🎨 Add Viewer/Editor selection
231
+ view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Edit and Save', 'Clone Document', 'New Record']
232
+ selected_view = st.selectbox("Select Viewer/Editor", view_options)
233
+
234
+ if selected_view == 'Show as Markdown':
235
+ # πŸ–ŒοΈ Show as Markdown
236
+ items = get_documents(container)
237
+ for item in items:
238
+ st.markdown(f"### **πŸ†” ID: {item.get('id', 'Unknown')}**")
239
+ content = item.get('content', '')
240
+ if isinstance(content, dict) or isinstance(content, list):
241
+ content = json.dumps(content, indent=2)
242
+ st.markdown(content)
243
+ elif selected_view == 'Show as Code Editor':
244
+ # πŸ’» Show as Code Editor
245
+ items = get_documents(container)
246
+ for item in items:
247
+ st.markdown(f"### **πŸ†” ID: {item.get('id', 'Unknown')}**")
248
+ st.code(json.dumps(item, indent=2), language='python')
249
+ elif selected_view == 'Show as Edit and Save':
250
+ # ✏️ Show as Edit and Save
251
+ st.markdown("#### Edit the document fields below:")
252
+ editable_id = st.text_input("ID", value=selected_doc.get('id', ''), key='edit_id')
253
+ # Remove 'id' from the document for editing other fields
254
+ editable_doc = selected_doc.copy()
255
+ editable_doc.pop('id', None)
256
+ doc_str = st.text_area("Document Content (in JSON format)", value=json.dumps(editable_doc, indent=2), height=300)
257
+ if st.button("πŸ’Ύ Save Changes"):
258
+ try:
259
+ updated_doc = json.loads(doc_str)
260
+ updated_doc['id'] = editable_id # Include the possibly edited ID
261
+ success, message = update_record(container, updated_doc)
262
+ if success:
263
+ st.success(message)
264
+ else:
265
+ st.error(message)
266
+ except json.JSONDecodeError as e:
267
+ st.error(f"Invalid JSON: {str(e)} 🚫")
268
+ elif selected_view == 'Clone Document':
269
+ # 🧬 Clone Document
270
+ if st.button("πŸ“„ Clone Document"):
271
+ cloned_doc = selected_doc.copy()
272
+ # Generate a unique ID based on timestamp
273
+ cloned_doc['id'] = generate_timestamp_id()
274
+ success, message = insert_record(container, cloned_doc)
275
+ if success:
276
+ st.success(f"Document cloned with new id: {cloned_doc['id']} πŸŽ‰")
277
+ else:
278
+ st.error(message)
279
+ elif selected_view == 'New Record':
280
+ # πŸ†• New Record
281
+ st.markdown("#### Create a new document:")
282
+ new_id = st.text_input("ID", value=generate_timestamp_id(), key='new_id')
283
+ new_doc_str = st.text_area("Document Content (in JSON format)", value='{}', height=300)
284
+ if st.button("βž• Create New Document"):
285
+ try:
286
+ new_doc = json.loads(new_doc_str)
287
+ new_doc['id'] = new_id # Use the provided ID
288
+ success, message = insert_record(container, new_doc)
289
+ if success:
290
+ st.success(f"New document created with id: {new_doc['id']} πŸŽ‰")
291
+ else:
292
+ st.error(message)
293
+ except json.JSONDecodeError as e:
294
+ st.error(f"Invalid JSON: {str(e)} 🚫")
295
+ else:
296
+ st.sidebar.info("No documents found in this container. πŸ“­")
297
+
298
+ # πŸŽ‰ Main content area
299
+ st.subheader(f"πŸ“Š Container: {st.session_state.selected_container}")
300
+ if st.session_state.selected_container:
301
+ if documents:
302
+ df = pd.DataFrame(documents)
303
+ st.dataframe(df)
304
+ else:
305
+ st.info("No documents to display. 🧐")
306
+
307
+ # πŸ™ GitHub section
308
+ st.subheader("πŸ™ GitHub Operations")
309
+ github_token = os.environ.get("GITHUB") # Read GitHub token from environment variable
310
+ source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
311
+ new_repo_name = st.text_input("New Repository Name (for cloning)", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
312
+
313
+ col1, col2 = st.columns(2)
314
+ with col1:
315
+ if st.button("πŸ“₯ Clone Repository"):
316
+ if github_token and source_repo:
317
+ try:
318
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
319
+ download_github_repo(source_repo, local_path)
320
+ zip_filename = f"{new_repo_name}.zip"
321
+ create_zip_file(local_path, zip_filename[:-4])
322
+ st.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
323
+ st.success("Repository cloned successfully! πŸŽ‰")
324
+ except Exception as e:
325
+ st.error(f"An error occurred: {str(e)} 😒")
326
+ finally:
327
+ if os.path.exists(local_path):
328
+ shutil.rmtree(local_path)
329
+ if os.path.exists(zip_filename):
330
+ os.remove(zip_filename)
331
+ else:
332
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
333
+
334
+ with col2:
335
+ if st.button("πŸ“€ Push to New Repository"):
336
+ if github_token and source_repo:
337
+ try:
338
+ g = Github(github_token)
339
+ new_repo = create_repo(g, new_repo_name)
340
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
341
+ download_github_repo(source_repo, local_path)
342
+ push_to_github(local_path, new_repo, github_token)
343
+ st.success(f"Repository pushed successfully to {new_repo.html_url} πŸš€")
344
+ except Exception as e:
345
+ st.error(f"An error occurred: {str(e)} 😒")
346
+ finally:
347
+ if os.path.exists(local_path):
348
+ shutil.rmtree(local_path)
349
+ else:
350
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
351
+
352
+ except exceptions.CosmosHttpResponseError as e:
353
+ st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
354
+ except Exception as e:
355
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
356
+
357
+ # πŸšͺ Logout button
358
+ if st.session_state.logged_in and st.sidebar.button("πŸšͺ Logout"):
359
+ st.session_state.logged_in = False
360
+ st.session_state.selected_records.clear()
361
+ st.session_state.client = None
362
+ st.session_state.selected_database = None
363
+ st.session_state.selected_container = None
364
+ st.rerun()
365
+
366
+ if __name__ == "__main__":
367
+ main()
368
+ import streamlit as st
369
+ from azure.cosmos import CosmosClient, PartitionKey, exceptions
370
+ import os
371
+ import pandas as pd
372
+ import traceback
373
+ import requests
374
+ import shutil
375
+ import zipfile
376
+ from github import Github
377
+ from git import Repo
378
+ from datetime import datetime
379
+ import base64
380
+ import json
381
+
382
+ # πŸŽ‰ Welcome to our fun-filled Cosmos DB and GitHub Integration app!
383
+ st.set_page_config(layout="wide")
384
+
385
+ # 🌌 Cosmos DB configuration
386
+ ENDPOINT = "https://acae-afd.documents.azure.com:443/"
387
+ SUBSCRIPTION_ID = "003fba60-5b3f-48f4-ab36-3ed11bc40816"
388
+ DATABASE_NAME = os.environ.get("COSMOS_DATABASE_NAME")
389
+ CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
390
+ Key = os.environ.get("Key") # πŸ”‘ Don't forget your key!
391
+
392
+ # πŸ™ GitHub configuration
393
+ def download_github_repo(url, local_path):
394
+ # 🚚 Let's download that GitHub repo!
395
+ if os.path.exists(local_path):
396
+ shutil.rmtree(local_path)
397
+ Repo.clone_from(url, local_path)
398
+
399
+ def create_zip_file(source_dir, output_filename):
400
+ # πŸ“¦ Zipping up files like a pro!
401
+ shutil.make_archive(output_filename, 'zip', source_dir)
402
+
403
+ def create_repo(g, repo_name):
404
+ # πŸ› οΈ Creating a new GitHub repo. Magic!
405
+ user = g.get_user()
406
+ return user.create_repo(repo_name)
407
+
408
+ def push_to_github(local_path, repo, github_token):
409
+ # πŸš€ Pushing code to GitHub. Hold on tight!
410
+ repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
411
+ local_repo = Repo(local_path)
412
+
413
+ if 'origin' in [remote.name for remote in local_repo.remotes]:
414
+ origin = local_repo.remote('origin')
415
+ origin.set_url(repo_url)
416
+ else:
417
+ origin = local_repo.create_remote('origin', repo_url)
418
+
419
+ if not local_repo.heads:
420
+ local_repo.git.checkout('-b', 'main')
421
+ current_branch = 'main'
422
+ else:
423
+ current_branch = local_repo.active_branch.name
424
+
425
+ local_repo.git.add(A=True)
426
+
427
+ if local_repo.is_dirty():
428
+ local_repo.git.commit('-m', 'Initial commit')
429
+
430
+ origin.push(refspec=f'{current_branch}:{current_branch}')
431
+
432
+ def get_base64_download_link(file_path, file_name):
433
+ # πŸ§™β€β™‚οΈ Generating a magical download link!
434
+ with open(file_path, "rb") as file:
435
+ contents = file.read()
436
+ base64_encoded = base64.b64encode(contents).decode()
437
+ return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">⬇️ Download {file_name}</a>'
438
+
439
+
440
+ # 🧭 New functions for dynamic sidebar navigation
441
+ def get_databases(client):
442
+ # πŸ“š Fetching list of databases. So many options!
443
+ return [db['id'] for db in client.list_databases()]
444
+
445
+ def get_containers(database):
446
+ # πŸ“‚ Getting containers. Containers within containers!
447
+ return [container['id'] for container in database.list_containers()]
448
+
449
+ def get_documents(container, limit=1000):
450
+ # πŸ“ Retrieving documents. Shhh, don't tell anyone!
451
+ query = "SELECT * FROM c"
452
+ items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
453
+ return items
454
+
455
+
456
+ # 🌟 Cosmos DB functions
457
+ def insert_record(container, record):
458
+ try:
459
+ container.create_item(body=record)
460
+ return True, "Record inserted successfully! πŸŽ‰"
461
+ except exceptions.CosmosHttpResponseError as e:
462
+ return False, f"HTTP error occurred: {str(e)} 🚨"
463
+ except Exception as e:
464
+ return False, f"An unexpected error occurred: {str(e)} 😱"
465
+
466
+ def update_record(container, updated_record):
467
  try:
468
  container.upsert_item(body=updated_record)
469
+ return True, f"Record with id {updated_record['id']} successfully updated. πŸ› οΈ"
470
  except exceptions.CosmosHttpResponseError as e:
471
+ return False, f"HTTP error occurred: {str(e)} 🚨"
472
  except Exception as e:
473
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
474
 
475
+ def delete_record(container, name, id):
476
  try:
477
  container.delete_item(item=id, partition_key=id)
478
+ return True, f"Successfully deleted record with name: {name} and id: {id} πŸ—‘οΈ"
479
  except exceptions.CosmosResourceNotFoundError:
480
+ return False, f"Record with id {id} not found. It may have been already deleted. πŸ•΅οΈβ€β™‚οΈ"
481
  except exceptions.CosmosHttpResponseError as e:
482
+ return False, f"HTTP error occurred: {str(e)} 🚨"
483
  except Exception as e:
484
+ return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
485
+
486
+ # πŸ•’ Function to generate a unique ID based on timestamp
487
+ def generate_timestamp_id():
488
+ # ⏰ Time waits for no one, but IDs can!
489
+ return datetime.now().strftime('%Y%m%d%H%M%S%f')
490
 
491
+ # πŸ“¦ Function to archive current container
492
  def archive_current_container(database_name, container_name, client):
493
  try:
494
  base_dir = "./cosmos_archive_current_container"
 
513
 
514
  return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
515
  except Exception as e:
516
+ return f"An error occurred while archiving data: {str(e)} 😒"
517
 
518
 
519
+ # 🎈 Let's modify the main app to be more fun!
520
  def main():
521
  st.title("🌟 Cosmos DB and GitHub Integration")
522
 
523
+ # 🚦 Initialize session state
524
  if 'logged_in' not in st.session_state:
525
  st.session_state.logged_in = False
526
  if 'selected_records' not in st.session_state:
 
532
  if 'selected_container' not in st.session_state:
533
  st.session_state.selected_container = None
534
 
535
+ # πŸ” Login section
536
  if not st.session_state.logged_in:
537
  st.subheader("πŸ” Login")
538
+ # Let's be sneaky and use the Key from environment variables! πŸ•΅οΈβ€β™‚οΈ
539
+ input_key = Key
540
 
541
+ # πŸš€ Time to blast off!
542
  if st.button("πŸš€ Login"):
543
  if input_key:
544
  st.session_state.primary_key = input_key
545
  st.session_state.logged_in = True
546
  st.rerun()
547
  else:
548
+ st.error("Invalid key. Please check your input. πŸ”‘βŒ")
549
  else:
550
+ # 🌌 Initialize Cosmos DB client
551
  try:
552
  if st.session_state.client is None:
553
  st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
554
 
555
+ # πŸ—„οΈ Sidebar for database, container, and document selection
556
  st.sidebar.title("πŸ—„οΈ Cosmos DB Navigator")
557
 
558
  databases = get_databases(st.session_state.client)
 
575
  if st.session_state.selected_container:
576
  container = database.get_container_client(st.session_state.selected_container)
577
 
578
+ # πŸ“¦ Add Export button
579
  if st.button("πŸ“¦ Export Container Data"):
580
  download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
581
  if download_link.startswith('<a'):
 
594
  st.subheader(f"πŸ“„ Document Details: {selected_document}")
595
  selected_doc = next((doc for doc in documents if doc.get('id') == selected_document), None)
596
  if selected_doc:
597
+ # 🎨 Add Viewer/Editor selection
598
  view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Edit and Save', 'Clone Document', 'New Record']
599
  selected_view = st.selectbox("Select Viewer/Editor", view_options)
600
+
601
  if selected_view == 'Show as Markdown':
602
+ # πŸ–ŒοΈ Show as Markdown
603
  items = get_documents(container)
604
  for item in items:
605
+ st.markdown(f"### **πŸ†” ID: {item.get('id', 'Unknown')}**")
606
  content = item.get('content', '')
607
  if isinstance(content, dict) or isinstance(content, list):
608
  content = json.dumps(content, indent=2)
609
  st.markdown(content)
610
  elif selected_view == 'Show as Code Editor':
611
+ # πŸ’» Show as Code Editor
612
  items = get_documents(container)
613
  for item in items:
614
+ st.markdown(f"### **πŸ†” ID: {item.get('id', 'Unknown')}**")
615
  st.code(json.dumps(item, indent=2), language='python')
616
  elif selected_view == 'Show as Edit and Save':
617
+ # ✏️ Show as Edit and Save
618
+ st.markdown("#### Edit the document fields below:")
619
+ editable_id = st.text_input("ID", value=selected_doc.get('id', ''), key='edit_id')
620
+ # Remove 'id' from the document for editing other fields
621
+ editable_doc = selected_doc.copy()
622
+ editable_doc.pop('id', None)
623
+ doc_str = st.text_area("Document Content (in JSON format)", value=json.dumps(editable_doc, indent=2), height=300)
624
+ if st.button("πŸ’Ύ Save Changes"):
625
  try:
626
  updated_doc = json.loads(doc_str)
627
+ updated_doc['id'] = editable_id # Include the possibly edited ID
628
+ success, message = update_record(container, updated_doc)
629
  if success:
630
  st.success(message)
631
  else:
632
  st.error(message)
633
  except json.JSONDecodeError as e:
634
+ st.error(f"Invalid JSON: {str(e)} 🚫")
635
  elif selected_view == 'Clone Document':
636
+ # 🧬 Clone Document
637
  if st.button("πŸ“„ Clone Document"):
638
  cloned_doc = selected_doc.copy()
639
+ # Generate a unique ID based on timestamp
640
+ cloned_doc['id'] = generate_timestamp_id()
641
+ success, message = insert_record(container, cloned_doc)
642
  if success:
643
+ st.success(f"Document cloned with new id: {cloned_doc['id']} πŸŽ‰")
644
  else:
645
  st.error(message)
646
  elif selected_view == 'New Record':
647
+ # πŸ†• New Record
648
+ st.markdown("#### Create a new document:")
649
+ new_id = st.text_input("ID", value=generate_timestamp_id(), key='new_id')
650
+ new_doc_str = st.text_area("Document Content (in JSON format)", value='{}', height=300)
651
  if st.button("βž• Create New Document"):
652
  try:
653
  new_doc = json.loads(new_doc_str)
654
+ new_doc['id'] = new_id # Use the provided ID
655
+ success, message = insert_record(container, new_doc)
 
656
  if success:
657
+ st.success(f"New document created with id: {new_doc['id']} πŸŽ‰")
658
  else:
659
  st.error(message)
660
  except json.JSONDecodeError as e:
661
+ st.error(f"Invalid JSON: {str(e)} 🚫")
662
  else:
663
+ st.sidebar.info("No documents found in this container. πŸ“­")
664
 
665
+ # πŸŽ‰ Main content area
666
  st.subheader(f"πŸ“Š Container: {st.session_state.selected_container}")
667
  if st.session_state.selected_container:
668
+ if documents:
669
+ df = pd.DataFrame(documents)
670
+ st.dataframe(df)
671
+ else:
672
+ st.info("No documents to display. 🧐")
673
 
674
+ # πŸ™ GitHub section
675
  st.subheader("πŸ™ GitHub Operations")
676
  github_token = os.environ.get("GITHUB") # Read GitHub token from environment variable
677
  source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
678
  new_repo_name = st.text_input("New Repository Name (for cloning)", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
679
+
680
  col1, col2 = st.columns(2)
681
  with col1:
682
  if st.button("πŸ“₯ Clone Repository"):
 
687
  zip_filename = f"{new_repo_name}.zip"
688
  create_zip_file(local_path, zip_filename[:-4])
689
  st.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
690
+ st.success("Repository cloned successfully! πŸŽ‰")
691
  except Exception as e:
692
+ st.error(f"An error occurred: {str(e)} 😒")
693
  finally:
694
  if os.path.exists(local_path):
695
  shutil.rmtree(local_path)
696
  if os.path.exists(zip_filename):
697
  os.remove(zip_filename)
698
  else:
699
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
700
 
701
  with col2:
702
  if st.button("πŸ“€ Push to New Repository"):
 
707
  local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
708
  download_github_repo(source_repo, local_path)
709
  push_to_github(local_path, new_repo, github_token)
710
+ st.success(f"Repository pushed successfully to {new_repo.html_url} πŸš€")
711
  except Exception as e:
712
+ st.error(f"An error occurred: {str(e)} 😒")
713
  finally:
714
  if os.path.exists(local_path):
715
  shutil.rmtree(local_path)
716
  else:
717
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. πŸ”‘β“")
718
+
719
  except exceptions.CosmosHttpResponseError as e:
720
+ st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
721
  except Exception as e:
722
+ st.error(f"An unexpected error occurred: {str(e)} 😱")
723
 
724
+ # πŸšͺ Logout button
725
  if st.session_state.logged_in and st.sidebar.button("πŸšͺ Logout"):
726
  st.session_state.logged_in = False
727
  st.session_state.selected_records.clear()