awacke1 commited on
Commit
4358a38
โ€ข
1 Parent(s): ff78816

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +205 -189
app.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import streamlit as st
2
  from azure.cosmos import CosmosClient, exceptions
3
  import os
@@ -10,6 +11,7 @@ from git import Repo
10
  import base64
11
  from dotenv import load_dotenv
12
 
 
13
  load_dotenv()
14
 
15
  # Cosmos DB configuration
@@ -19,19 +21,28 @@ PRIMARY_KEY = os.getenv("PRIMARY_KEY")
19
  # GitHub configuration
20
  GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
21
 
22
- # Helper Functions
23
 
24
  def download_github_repo(url, local_path):
 
 
 
25
  if os.path.exists(local_path):
26
  shutil.rmtree(local_path)
27
  Repo.clone_from(url, local_path)
28
 
29
  def create_repo(github_token, repo_name):
 
 
 
30
  g = Github(github_token)
31
  user = g.get_user()
32
  return user.create_repo(repo_name)
33
 
34
  def push_to_github(local_path, repo, github_token):
 
 
 
35
  repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
36
  local_repo = Repo(local_path)
37
 
@@ -48,12 +59,18 @@ def push_to_github(local_path, repo, github_token):
48
  origin.push(refspec=f"{local_repo.active_branch.name}:{local_repo.active_branch.name}")
49
 
50
  def get_base64_download_link(file_path, file_name):
 
 
 
51
  with open(file_path, "rb") as file:
52
  contents = file.read()
53
  base64_encoded = base64.b64encode(contents).decode()
54
- return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">Download {file_name}</a>'
55
 
56
  def fetch_db_structure(client):
 
 
 
57
  structure = {}
58
  for database in client.list_databases():
59
  db_name = database['id']
@@ -64,56 +81,71 @@ def fetch_db_structure(client):
64
  return structure
65
 
66
  def fetch_items(client, db_name, container_name):
 
 
 
67
  container = client.get_database_client(db_name).get_container_client(container_name)
68
  items = list(container.read_all_items())
69
  return items
70
 
71
  def create_item(client, db_name, container_name):
72
- st.subheader("Create New Item")
73
- item_id = st.text_input("Item ID")
74
- item_data = st.text_area("Item Data (in JSON format)")
 
 
 
75
 
76
- if st.button("Save New Item"):
77
  try:
78
  container = client.get_database_client(db_name).get_container_client(container_name)
79
  json_data = json.loads(item_data)
80
  json_data['id'] = item_id
81
  container.create_item(body=json_data)
82
- st.success("New item created successfully!")
83
  st.json(json_data)
84
  st.experimental_rerun()
85
  except Exception as e:
86
- st.error(f"Error creating item: {str(e)}")
87
 
88
  def edit_item(client, db_name, container_name, item_id):
 
 
 
89
  container = client.get_database_client(db_name).get_container_client(container_name)
90
  item = container.read_item(item=item_id, partition_key=item_id)
91
 
92
- st.subheader(f"Editing Item: {item_id}")
93
- edited_item = st.text_area("Edit Item Data (in JSON format)", value=json.dumps(item, indent=2))
94
 
95
- if st.button("Save Changes"):
96
  try:
97
  json_data = json.loads(edited_item)
98
  container.upsert_item(body=json_data)
99
- st.success("Item updated successfully!")
100
  st.json(json_data)
101
  st.experimental_rerun()
102
  except Exception as e:
103
- st.error(f"Error updating item: {str(e)}")
104
 
105
  def delete_item(client, db_name, container_name, item_id):
106
- st.subheader(f"Delete Item: {item_id}")
107
- if st.button("Confirm Delete"):
 
 
 
108
  try:
109
  container = client.get_database_client(db_name).get_container_client(container_name)
110
  container.delete_item(item=item_id, partition_key=item_id)
111
- st.success(f"Item {item_id} deleted successfully!")
112
  st.experimental_rerun()
113
  except Exception as e:
114
- st.error(f"Error deleting item: {str(e)}")
115
 
116
  def archive_all_data(client):
 
 
 
117
  try:
118
  base_dir = "./cosmos_archive"
119
  if os.path.exists(base_dir):
@@ -142,82 +174,79 @@ def archive_all_data(client):
142
 
143
  return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
144
  except Exception as e:
145
- st.error(f"An error occurred while archiving data: {str(e)}")
146
 
147
  def download_all_code():
 
 
 
148
  try:
149
  base_dir = "."
150
  exclude_dirs = ['.git', '__pycache__', 'cosmos_archive']
151
  exclude_files = ['.env', '.gitignore', 'cosmos_archive.zip']
152
 
153
- def zipdir(path, ziph):
154
- for root, dirs, files in os.walk(path):
155
- dirs[:] = [d for d in dirs if d not in exclude_dirs]
156
- for file in files:
157
- if file not in exclude_files and not file.endswith('.zip'):
158
- ziph.write(os.path.join(root, file),
159
- os.path.relpath(os.path.join(root, file),
160
- os.path.join(base_dir, '..')))
161
-
162
  zip_filename = f"CosmosDBAICode_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip"
163
  shutil.make_archive(zip_filename[:-4], 'zip', base_dir)
164
  return get_base64_download_link(zip_filename, zip_filename)
165
  except Exception as e:
166
- st.error(f"An error occurred while creating the code archive: {str(e)}")
167
 
168
  def render_sidebar(client, structure):
169
- st.sidebar.title("๐Ÿ“ Cosmos DB Manager")
170
-
171
- # Navigation
172
- app_mode = st.sidebar.radio("Navigate", ["App", "Tutorial"])
173
-
174
- if app_mode == "App":
175
- # Database and Container selection
176
- selected_db = st.sidebar.selectbox("Select Database", list(structure.keys()))
177
- selected_container = st.sidebar.selectbox("Select Container", structure[selected_db])
 
 
 
178
 
179
- # Fetch items for the selected container
180
  items = fetch_items(client, selected_db, selected_container)
181
 
182
- # Item selection
183
  item_ids = [item['id'] for item in items]
184
- selected_item = st.sidebar.selectbox("Select Item", ["Create New Item"] + item_ids)
185
 
186
- # Action buttons
187
  if selected_item != "Create New Item":
188
- if st.sidebar.button("Edit Item"):
189
  st.session_state.action = "edit"
190
  st.session_state.selected_item = selected_item
191
- if st.sidebar.button("Delete Item"):
192
  st.session_state.action = "delete"
193
  st.session_state.selected_item = selected_item
194
  else:
195
- if st.sidebar.button("Create New Item"):
196
  st.session_state.action = "create"
197
 
198
- # GitHub Operations
199
  st.sidebar.subheader("๐Ÿ™ GitHub Operations")
200
- source_repo = st.sidebar.text_input("Source Repo URL")
201
- new_repo_name = st.sidebar.text_input("New Repo Name", value=f"Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
202
 
203
- if st.sidebar.button("Clone Repository"):
204
  clone_github_repo(source_repo, new_repo_name)
205
 
206
- if st.sidebar.button("Push to New Repository"):
207
  push_to_new_repo(source_repo, new_repo_name)
208
 
209
- # Archive data button
210
- if st.sidebar.button("Archive All Data"):
211
  download_link = archive_all_data(client)
212
  st.sidebar.markdown(download_link, unsafe_allow_html=True)
213
 
214
- # Download All Code button
215
- if st.sidebar.button("Download All Code"):
216
  download_link = download_all_code()
217
  st.sidebar.markdown(download_link, unsafe_allow_html=True)
218
 
219
- # Logout button
220
- if st.sidebar.button("Logout"):
221
  st.session_state.logged_in = False
222
  st.session_state.action = None
223
  st.session_state.selected_item = None
@@ -229,6 +258,9 @@ def render_sidebar(client, structure):
229
  return None, None, None, app_mode
230
 
231
  def clone_github_repo(source_repo, new_repo_name):
 
 
 
232
  if GITHUB_TOKEN and source_repo:
233
  try:
234
  local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
@@ -236,36 +268,42 @@ def clone_github_repo(source_repo, new_repo_name):
236
  zip_filename = f"{new_repo_name}.zip"
237
  shutil.make_archive(zip_filename[:-4], 'zip', local_path)
238
  st.sidebar.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
239
- st.sidebar.success("Repository cloned successfully!")
240
  except Exception as e:
241
- st.sidebar.error(f"An error occurred: {str(e)}")
242
  finally:
243
  if os.path.exists(local_path):
244
  shutil.rmtree(local_path)
245
  if os.path.exists(zip_filename):
246
  os.remove(zip_filename)
247
  else:
248
- st.sidebar.error("Please ensure GitHub token is set in environment variables and source repository URL is provided.")
249
 
250
  def push_to_new_repo(source_repo, new_repo_name):
 
 
 
251
  if GITHUB_TOKEN and source_repo:
252
  try:
253
  new_repo = create_repo(GITHUB_TOKEN, new_repo_name)
254
  local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
255
  download_github_repo(source_repo, local_path)
256
  push_to_github(local_path, new_repo, GITHUB_TOKEN)
257
- st.sidebar.success(f"Repository pushed successfully to {new_repo.html_url}")
258
  except Exception as e:
259
- st.sidebar.error(f"An error occurred: {str(e)}")
260
  finally:
261
  if os.path.exists(local_path):
262
  shutil.rmtree(local_path)
263
  else:
264
- st.sidebar.error("Please ensure GitHub token is set in environment variables and source repository URL is provided.")
265
 
266
  def main():
 
 
 
267
  st.set_page_config(layout="wide")
268
- st.title("๐ŸŒŸ Cosmos DB and GitHub Integration App with Tutorial")
269
 
270
  # Initialize session state
271
  if 'logged_in' not in st.session_state:
@@ -277,14 +315,14 @@ def main():
277
 
278
  # Login section
279
  if not st.session_state.logged_in:
280
- st.subheader("Login")
281
- if st.button("Login"):
282
  if PRIMARY_KEY:
283
  st.session_state.primary_key = PRIMARY_KEY
284
  st.session_state.logged_in = True
285
  st.experimental_rerun()
286
  else:
287
- st.error("Invalid key. Please check your environment variables.")
288
  else:
289
  # Initialize Cosmos DB client
290
  try:
@@ -294,7 +332,7 @@ def main():
294
  # Render sidebar and get selections
295
  selected_db, selected_container, selected_item, app_mode = render_sidebar(client, structure)
296
 
297
- if app_mode == "App":
298
  # Main area
299
  if st.session_state.action == "create":
300
  create_item(client, selected_db, selected_container)
@@ -303,53 +341,50 @@ def main():
303
  elif st.session_state.action == "delete":
304
  delete_item(client, selected_db, selected_container, st.session_state.selected_item)
305
  else:
306
- st.write("Select an action from the sidebar to get started.")
307
- elif app_mode == "Tutorial":
308
  display_tutorial()
309
  except exceptions.CosmosHttpResponseError as e:
310
- st.error(f"Failed to connect to Cosmos DB: {str(e)}")
311
  except Exception as e:
312
- st.error(f"An unexpected error occurred: {str(e)}")
313
 
314
  def display_tutorial():
315
- st.header("๐Ÿ“– In-App Tutorial")
 
 
 
316
 
317
  st.markdown("""
318
- ## Introduction
319
-
320
- In this tutorial, we'll build a web application using **Streamlit** that allows users to perform CRUD (Create, Read, Update, Delete) operations on Azure Cosmos DB. Additionally, we'll integrate GitHub functionalities to clone repositories, push changes, and archive data.
321
-
322
- ### What You'll Learn
323
-
324
- - How to connect to Azure Cosmos DB using Python.
325
- - Performing CRUD operations on Cosmos DB containers.
326
- - Integrating GitHub functionalities within the application.
327
- - Building an interactive user interface with Streamlit.
328
-
329
- ### Use Cases
330
-
331
- - **Database Administration**: Simplify database management tasks for administrators.
332
- - **Educational Tools**: Teach students about NoSQL databases and version control.
333
- - **Data Archiving**: Easily archive and download database contents.
334
-
335
  ---
 
 
 
 
336
 
337
- ## Prerequisites
338
-
339
- Before we start, ensure you have the following:
340
-
341
- - An **Azure Cosmos DB** account.
342
- - A **GitHub** account and a personal access token with the necessary permissions.
343
- - Python 3.7 or higher installed on your system.
344
- - Basic knowledge of Python and Streamlit.
345
-
346
  ---
 
 
 
 
347
 
348
- ## Setting Up the Environment
349
-
350
- ### 1. Clone the Repository
351
-
352
- Use the following command to clone the repository:
353
 
354
  """)
355
  st.code("""
@@ -358,23 +393,23 @@ def display_tutorial():
358
  """, language='bash')
359
 
360
  st.markdown("""
361
- ### 2. Create a Virtual Environment
362
 
363
- Create and activate a virtual environment to manage dependencies.
364
 
365
  """)
366
  st.code("""
367
  python -m venv venv
368
  # On Windows
369
  venv\\Scripts\\activate
370
- # On Unix or MacOS
371
  source venv/bin/activate
372
  """, language='bash')
373
 
374
  st.markdown("""
375
- ### 3. Install Dependencies
376
 
377
- Install the required Python packages using `requirements.txt`.
378
 
379
  """)
380
  st.code("""
@@ -382,29 +417,9 @@ def display_tutorial():
382
  """, language='bash')
383
 
384
  st.markdown("""
385
- Contents of `requirements.txt`:
386
 
387
- """)
388
- st.code("""
389
- streamlit
390
- azure-cosmos
391
- PyGithub
392
- GitPython
393
- python-dotenv
394
- """, language='text')
395
-
396
- st.markdown("""
397
- ### 4. Set Up Environment Variables
398
-
399
- Create a `.env` file to store your sensitive information.
400
-
401
- """)
402
- st.code("""
403
- touch .env
404
- """, language='bash')
405
-
406
- st.markdown("""
407
- Add the following variables to your `.env` file:
408
 
409
  """)
410
  st.code("""
@@ -413,35 +428,31 @@ def display_tutorial():
413
  GITHUB_TOKEN=your_github_personal_access_token
414
  """, language='text')
415
 
416
- st.warning("**Note:** Never commit your `.env` file to version control.")
417
 
418
  st.markdown("---")
419
 
420
  st.markdown("""
421
- ## Application Architecture
422
-
423
- ### Overview
424
-
425
- Our application consists of several key components:
426
-
427
- - **Cosmos DB Operations**: Functions to connect and interact with Azure Cosmos DB.
428
- - **GitHub Integration**: Functions to clone repositories, create new ones, and push changes.
429
- - **Streamlit Interface**: The front-end of our app that users will interact with.
430
 
431
- ### Data Flow
432
 
433
- 1. **User Interaction**: Users perform actions via the Streamlit sidebar and main interface.
434
- 2. **Database Operations**: The app connects to Cosmos DB to perform CRUD operations based on user input.
435
- 3. **GitHub Actions**: Users can clone repositories or push local changes to GitHub.
436
- 4. **Archiving Data**: The app can archive database contents into a downloadable ZIP file.
 
437
 
 
 
 
 
 
438
  ---
 
 
439
 
440
- ## Implementing the Application
441
-
442
- Below are code snippets for key parts of the application.
443
-
444
- ### Importing Libraries
445
 
446
  """)
447
  st.code("""
@@ -460,7 +471,7 @@ def display_tutorial():
460
  """, language='python')
461
 
462
  st.markdown("""
463
- ### Configuring Cosmos DB and GitHub
464
 
465
  """)
466
  st.code("""
@@ -473,9 +484,12 @@ def display_tutorial():
473
  """, language='python')
474
 
475
  st.markdown("""
476
- ### Helper Functions
 
 
 
 
477
 
478
- **GitHub Operations**
479
  """)
480
  st.code("""
481
  def download_github_repo(url, local_path):
@@ -489,7 +503,8 @@ def display_tutorial():
489
  """, language='python')
490
 
491
  st.markdown("""
492
- **Base64 Download Link**
 
493
  """)
494
  st.code("""
495
  def get_base64_download_link(file_path, file_name):
@@ -497,9 +512,10 @@ def display_tutorial():
497
  """, language='python')
498
 
499
  st.markdown("""
500
- ### Cosmos DB Operations
 
 
501
 
502
- **Fetching Database Structure**
503
  """)
504
  st.code("""
505
  def fetch_db_structure(client):
@@ -507,9 +523,10 @@ def display_tutorial():
507
  """, language='python')
508
 
509
  st.markdown("""
510
- **CRUD Operations**
 
 
511
 
512
- *Create Item*
513
  """)
514
  st.code("""
515
  def create_item(client, db_name, container_name):
@@ -517,7 +534,8 @@ def display_tutorial():
517
  """, language='python')
518
 
519
  st.markdown("""
520
- *Edit Item*
 
521
  """)
522
  st.code("""
523
  def edit_item(client, db_name, container_name, item_id):
@@ -525,7 +543,8 @@ def display_tutorial():
525
  """, language='python')
526
 
527
  st.markdown("""
528
- *Delete Item*
 
529
  """)
530
  st.code("""
531
  def delete_item(client, db_name, container_name, item_id):
@@ -533,7 +552,7 @@ def display_tutorial():
533
  """, language='python')
534
 
535
  st.markdown("""
536
- ### Archiving Data
537
 
538
  """)
539
  st.code("""
@@ -542,9 +561,10 @@ def display_tutorial():
542
  """, language='python')
543
 
544
  st.markdown("""
545
- ### Streamlit Interface
 
 
546
 
547
- **Rendering the Sidebar**
548
  """)
549
  st.code("""
550
  def render_sidebar(client, structure):
@@ -552,7 +572,8 @@ def display_tutorial():
552
  """, language='python')
553
 
554
  st.markdown("""
555
- **Main Function**
 
556
  """)
557
  st.code("""
558
  def main():
@@ -565,48 +586,43 @@ def display_tutorial():
565
  st.markdown("---")
566
 
567
  st.markdown("""
568
- ## Running the Application
569
 
570
- ### Start the Streamlit App
571
-
572
- Run the following command in your terminal:
573
 
574
  """)
575
  st.code("""
576
- streamlit run app.py
577
  """, language='bash')
578
 
579
  st.markdown("""
580
- ### Login
581
-
582
- - Navigate to `http://localhost:8501` in your web browser.
583
- - Click on the **Login** button. If your `PRIMARY_KEY` is correctly set in the `.env` file, you should be logged in.
584
 
585
- ### Using the App
 
 
 
586
 
587
- - **Database Selection**: Use the sidebar to select a database and container.
588
  - **Item Operations**:
589
- - **Create New Item**: Input the item ID and JSON data to create a new item.
590
- - **Edit Item**: Modify the JSON data of an existing item.
591
- - **Delete Item**: Remove an item from the container.
592
  - **GitHub Operations**:
593
- - **Clone Repository**: Enter the source repository URL and clone it locally.
594
- - **Push to New Repository**: Create a new repository and push local changes.
595
- - **Archive Data**: Click **Archive All Data** to download a ZIP file of your databases.
596
- - **Download All Code**: Click **Download All Code** to download the app's source code.
597
 
598
  ---
 
 
599
 
600
- ## Summary
601
-
602
- In this tutorial, we've built a comprehensive application that integrates Azure Cosmos DB and GitHub functionalities using Streamlit. This app allows users to manage their Cosmos DB databases through a graphical interface, perform GitHub operations, and archive data easily.
603
-
604
- ### Next Steps
605
 
606
- - **Enhance Security**: Implement authentication mechanisms for multiple users.
607
- - **Extend Functionality**: Add support for other database operations like indexing.
608
- - **User Interface Improvements**: Make the app more user-friendly with better error handling and feedback.
609
 
 
610
  """)
611
 
612
  if __name__ == "__main__":
 
1
+ # CosmicApp.py
2
  import streamlit as st
3
  from azure.cosmos import CosmosClient, exceptions
4
  import os
 
11
  import base64
12
  from dotenv import load_dotenv
13
 
14
+ # Load environment variables
15
  load_dotenv()
16
 
17
  # Cosmos DB configuration
 
21
  # GitHub configuration
22
  GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
23
 
24
+ # ๐ŸŒŸ Helper Functions Galore ๐ŸŒŸ
25
 
26
  def download_github_repo(url, local_path):
27
+ """
28
+ ๐ŸŒ€ Clone a GitHub repo faster than a swirling vortex!
29
+ """
30
  if os.path.exists(local_path):
31
  shutil.rmtree(local_path)
32
  Repo.clone_from(url, local_path)
33
 
34
  def create_repo(github_token, repo_name):
35
+ """
36
+ ๐Ÿฃ Hatch a new GitHub repo like a pro!
37
+ """
38
  g = Github(github_token)
39
  user = g.get_user()
40
  return user.create_repo(repo_name)
41
 
42
  def push_to_github(local_path, repo, github_token):
43
+ """
44
+ ๐Ÿš€ Push your changes to GitHub at warp speed!
45
+ """
46
  repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
47
  local_repo = Repo(local_path)
48
 
 
59
  origin.push(refspec=f"{local_repo.active_branch.name}:{local_repo.active_branch.name}")
60
 
61
  def get_base64_download_link(file_path, file_name):
62
+ """
63
+ ๐Ÿ”— Get a base64 download link for instant gratification!
64
+ """
65
  with open(file_path, "rb") as file:
66
  contents = file.read()
67
  base64_encoded = base64.b64encode(contents).decode()
68
+ return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">๐Ÿ›ธ Download {file_name} ๐Ÿ›ธ</a>'
69
 
70
  def fetch_db_structure(client):
71
+ """
72
+ ๐Ÿ“‚ Fetch the cosmic database structureโ€”no telescope needed!
73
+ """
74
  structure = {}
75
  for database in client.list_databases():
76
  db_name = database['id']
 
81
  return structure
82
 
83
  def fetch_items(client, db_name, container_name):
84
+ """
85
+ ๐Ÿ›ฐ๏ธ Fetch items from a containerโ€”beep boop!
86
+ """
87
  container = client.get_database_client(db_name).get_container_client(container_name)
88
  items = list(container.read_all_items())
89
  return items
90
 
91
  def create_item(client, db_name, container_name):
92
+ """
93
+ ๐ŸŒฑ Create a new cosmic itemโ€”let it grow!
94
+ """
95
+ st.subheader("๐ŸŒฑ Create New Item")
96
+ item_id = st.text_input("๐Ÿ†” Item ID")
97
+ item_data = st.text_area("๐Ÿ“ Item Data (in JSON format)")
98
 
99
+ if st.button("๐Ÿ’พ Save New Item"):
100
  try:
101
  container = client.get_database_client(db_name).get_container_client(container_name)
102
  json_data = json.loads(item_data)
103
  json_data['id'] = item_id
104
  container.create_item(body=json_data)
105
+ st.success("๐ŸŽ‰ New item created successfully!")
106
  st.json(json_data)
107
  st.experimental_rerun()
108
  except Exception as e:
109
+ st.error(f"๐Ÿšจ Error creating item: {str(e)}")
110
 
111
  def edit_item(client, db_name, container_name, item_id):
112
+ """
113
+ โœ๏ธ Edit an existing itemโ€”because change is the only constant!
114
+ """
115
  container = client.get_database_client(db_name).get_container_client(container_name)
116
  item = container.read_item(item=item_id, partition_key=item_id)
117
 
118
+ st.subheader(f"โœ๏ธ Editing Item: {item_id}")
119
+ edited_item = st.text_area("๐Ÿ“ Edit Item Data (in JSON format)", value=json.dumps(item, indent=2))
120
 
121
+ if st.button("๐Ÿ’พ Save Changes"):
122
  try:
123
  json_data = json.loads(edited_item)
124
  container.upsert_item(body=json_data)
125
+ st.success("โœจ Item updated successfully!")
126
  st.json(json_data)
127
  st.experimental_rerun()
128
  except Exception as e:
129
+ st.error(f"๐Ÿšจ Error updating item: {str(e)}")
130
 
131
  def delete_item(client, db_name, container_name, item_id):
132
+ """
133
+ ๐Ÿ—‘๏ธ Delete an itemโ€”because sometimes less is more!
134
+ """
135
+ st.subheader(f"๐Ÿ—‘๏ธ Delete Item: {item_id}")
136
+ if st.button("โš ๏ธ Confirm Delete"):
137
  try:
138
  container = client.get_database_client(db_name).get_container_client(container_name)
139
  container.delete_item(item=item_id, partition_key=item_id)
140
+ st.success(f"๐Ÿ”ฅ Item {item_id} deleted successfully!")
141
  st.experimental_rerun()
142
  except Exception as e:
143
+ st.error(f"๐Ÿšจ Error deleting item: {str(e)}")
144
 
145
  def archive_all_data(client):
146
+ """
147
+ ๐Ÿ“ฆ Archive all your dataโ€”pack it up, pack it in!
148
+ """
149
  try:
150
  base_dir = "./cosmos_archive"
151
  if os.path.exists(base_dir):
 
174
 
175
  return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
176
  except Exception as e:
177
+ st.error(f"๐Ÿšจ An error occurred while archiving data: {str(e)}")
178
 
179
  def download_all_code():
180
+ """
181
+ ๐Ÿ’พ Download all the codeโ€”because sharing is caring!
182
+ """
183
  try:
184
  base_dir = "."
185
  exclude_dirs = ['.git', '__pycache__', 'cosmos_archive']
186
  exclude_files = ['.env', '.gitignore', 'cosmos_archive.zip']
187
 
 
 
 
 
 
 
 
 
 
188
  zip_filename = f"CosmosDBAICode_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip"
189
  shutil.make_archive(zip_filename[:-4], 'zip', base_dir)
190
  return get_base64_download_link(zip_filename, zip_filename)
191
  except Exception as e:
192
+ st.error(f"๐Ÿšจ An error occurred while creating the code archive: {str(e)}")
193
 
194
  def render_sidebar(client, structure):
195
+ """
196
+ ๐ŸŽ›๏ธ Render the cosmic sidebarโ€”control your destiny!
197
+ """
198
+ st.sidebar.title("๐ŸŒŒ Cosmic Control Panel")
199
+
200
+ # ๐Ÿšฆ Navigation
201
+ app_mode = st.sidebar.radio("๐Ÿš€ Choose Your Adventure", ["App Mode ๐ŸŒŸ", "Tutorial Mode ๐Ÿ“–"])
202
+
203
+ if app_mode == "App Mode ๐ŸŒŸ":
204
+ # ๐Ÿ—„๏ธ Database and Container selection
205
+ selected_db = st.sidebar.selectbox("๐Ÿ—„๏ธ Select Database", list(structure.keys()))
206
+ selected_container = st.sidebar.selectbox("๐Ÿ“ฆ Select Container", structure[selected_db])
207
 
208
+ # ๐Ÿ“ Fetch items for the selected container
209
  items = fetch_items(client, selected_db, selected_container)
210
 
211
+ # ๐Ÿ“„ Item selection
212
  item_ids = [item['id'] for item in items]
213
+ selected_item = st.sidebar.selectbox("๐Ÿ“„ Select Item", ["Create New Item"] + item_ids)
214
 
215
+ # ๐ŸŽฌ Action buttons
216
  if selected_item != "Create New Item":
217
+ if st.sidebar.button("โœ๏ธ Edit Item"):
218
  st.session_state.action = "edit"
219
  st.session_state.selected_item = selected_item
220
+ if st.sidebar.button("๐Ÿ—‘๏ธ Delete Item"):
221
  st.session_state.action = "delete"
222
  st.session_state.selected_item = selected_item
223
  else:
224
+ if st.sidebar.button("๐ŸŒฑ Create New Item"):
225
  st.session_state.action = "create"
226
 
227
+ # ๐Ÿ™ GitHub Operations
228
  st.sidebar.subheader("๐Ÿ™ GitHub Operations")
229
+ source_repo = st.sidebar.text_input("๐Ÿ”— Source Repo URL")
230
+ new_repo_name = st.sidebar.text_input("๐Ÿ†• New Repo Name", value=f"Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
231
 
232
+ if st.sidebar.button("๐Ÿ“ฅ Clone Repository"):
233
  clone_github_repo(source_repo, new_repo_name)
234
 
235
+ if st.sidebar.button("๐Ÿ“ค Push to New Repository"):
236
  push_to_new_repo(source_repo, new_repo_name)
237
 
238
+ # ๐Ÿ“ฆ Archive data button
239
+ if st.sidebar.button("๐Ÿ“ฆ Archive All Data"):
240
  download_link = archive_all_data(client)
241
  st.sidebar.markdown(download_link, unsafe_allow_html=True)
242
 
243
+ # ๐Ÿ’พ Download All Code button
244
+ if st.sidebar.button("๐Ÿ’พ Download All Code"):
245
  download_link = download_all_code()
246
  st.sidebar.markdown(download_link, unsafe_allow_html=True)
247
 
248
+ # ๐Ÿšช Logout button
249
+ if st.sidebar.button("๐Ÿšช Logout"):
250
  st.session_state.logged_in = False
251
  st.session_state.action = None
252
  st.session_state.selected_item = None
 
258
  return None, None, None, app_mode
259
 
260
  def clone_github_repo(source_repo, new_repo_name):
261
+ """
262
+ ๐Ÿ“ฅ Clone a GitHub repoโ€”it's like magic!
263
+ """
264
  if GITHUB_TOKEN and source_repo:
265
  try:
266
  local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
 
268
  zip_filename = f"{new_repo_name}.zip"
269
  shutil.make_archive(zip_filename[:-4], 'zip', local_path)
270
  st.sidebar.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
271
+ st.sidebar.success("๐ŸŽ‰ Repository cloned successfully!")
272
  except Exception as e:
273
+ st.sidebar.error(f"๐Ÿšจ An error occurred: {str(e)}")
274
  finally:
275
  if os.path.exists(local_path):
276
  shutil.rmtree(local_path)
277
  if os.path.exists(zip_filename):
278
  os.remove(zip_filename)
279
  else:
280
+ st.sidebar.error("๐Ÿšจ Please ensure GitHub token is set and source repository URL is provided.")
281
 
282
  def push_to_new_repo(source_repo, new_repo_name):
283
+ """
284
+ ๐Ÿ“ค Push to a new GitHub repoโ€”reach for the stars!
285
+ """
286
  if GITHUB_TOKEN and source_repo:
287
  try:
288
  new_repo = create_repo(GITHUB_TOKEN, new_repo_name)
289
  local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
290
  download_github_repo(source_repo, local_path)
291
  push_to_github(local_path, new_repo, GITHUB_TOKEN)
292
+ st.sidebar.success(f"๐Ÿš€ Repository pushed successfully to {new_repo.html_url}")
293
  except Exception as e:
294
+ st.sidebar.error(f"๐Ÿšจ An error occurred: {str(e)}")
295
  finally:
296
  if os.path.exists(local_path):
297
  shutil.rmtree(local_path)
298
  else:
299
+ st.sidebar.error("๐Ÿšจ Please ensure GitHub token is set and source repository URL is provided.")
300
 
301
  def main():
302
+ """
303
+ ๐Ÿ›ธ Main functionโ€”where all the magic happens!
304
+ """
305
  st.set_page_config(layout="wide")
306
+ st.title("๐Ÿš€ Cosmos DB & GitHub Integration App with Streamlit ๐ŸŽ‰")
307
 
308
  # Initialize session state
309
  if 'logged_in' not in st.session_state:
 
315
 
316
  # Login section
317
  if not st.session_state.logged_in:
318
+ st.subheader("๐Ÿ” Login to Your Cosmic Account")
319
+ if st.button("๐Ÿš€ Launch"):
320
  if PRIMARY_KEY:
321
  st.session_state.primary_key = PRIMARY_KEY
322
  st.session_state.logged_in = True
323
  st.experimental_rerun()
324
  else:
325
+ st.error("๐Ÿšจ Invalid key. Please check your environment variables.")
326
  else:
327
  # Initialize Cosmos DB client
328
  try:
 
332
  # Render sidebar and get selections
333
  selected_db, selected_container, selected_item, app_mode = render_sidebar(client, structure)
334
 
335
+ if app_mode == "App Mode ๐ŸŒŸ":
336
  # Main area
337
  if st.session_state.action == "create":
338
  create_item(client, selected_db, selected_container)
 
341
  elif st.session_state.action == "delete":
342
  delete_item(client, selected_db, selected_container, st.session_state.selected_item)
343
  else:
344
+ st.write("๐ŸŒŸ Select an action from the sidebar to get started.")
345
+ elif app_mode == "Tutorial Mode ๐Ÿ“–":
346
  display_tutorial()
347
  except exceptions.CosmosHttpResponseError as e:
348
+ st.error(f"๐Ÿšจ Failed to connect to Cosmos DB: {str(e)}")
349
  except Exception as e:
350
+ st.error(f"๐Ÿšจ An unexpected error occurred: {str(e)}")
351
 
352
  def display_tutorial():
353
+ """
354
+ ๐Ÿ“– Display the in-app tutorialโ€”knowledge is power!
355
+ """
356
+ st.header("๐Ÿ“– Welcome to the Cosmic Tutorial!")
357
 
358
  st.markdown("""
359
+ ### ๐Ÿš€ Introduction
360
+
361
+ **Greetings, Earthling!** ๐Ÿ‘ฝ Ready to embark on a cosmic journey through the universe of Azure Cosmos DB and GitHub? Buckle up! This tutorial is not just informativeโ€”it's a blast! ๐ŸŽ†
362
+
363
+ **What You'll Learn:**
364
+
365
+ - ๐ŸŒŒ Connecting to **Azure Cosmos DB** using Pythonโ€”no rocket science degree required!
366
+ - ๐Ÿ› ๏ธ Performing **CRUD operations** on Cosmos DB containersโ€”because you can!
367
+ - ๐Ÿ™ Integrating **GitHub functionalities** within the appโ€”unleash the octopus!
368
+ - ๐ŸŽจ Building an interactive UI with **Streamlit**โ€”your canvas awaits!
369
+
 
 
 
 
 
 
370
  ---
371
+
372
+ ### ๐ŸŒŸ Prerequisites
373
+
374
+ Before we launch into space, make sure you've got:
375
 
376
+ - ๐Ÿ›ฐ๏ธ An **Azure Cosmos DB** accountโ€”your mission control.
377
+ - ๐Ÿ™ A **GitHub** account with a personal access tokenโ€”tentacles not included.
378
+ - ๐Ÿ **Python 3.7+** installedโ€”because snakes are cool.
379
+ - ๐Ÿง  Basic knowledge of Python and Streamlitโ€”you've got this!
380
+
 
 
 
 
381
  ---
382
+
383
+ ### ๐Ÿ› ๏ธ Setting Up the Environment
384
+
385
+ **1. Clone the Repository**
386
 
387
+ Open your terminal and run:
 
 
 
 
388
 
389
  """)
390
  st.code("""
 
393
  """, language='bash')
394
 
395
  st.markdown("""
396
+ **2. Create a Virtual Environment**
397
 
398
+ Let's keep things tidy:
399
 
400
  """)
401
  st.code("""
402
  python -m venv venv
403
  # On Windows
404
  venv\\Scripts\\activate
405
+ # On macOS/Linux
406
  source venv/bin/activate
407
  """, language='bash')
408
 
409
  st.markdown("""
410
+ **3. Install Dependencies**
411
 
412
+ Time to get those packages:
413
 
414
  """)
415
  st.code("""
 
417
  """, language='bash')
418
 
419
  st.markdown("""
420
+ **4. Set Up Environment Variables**
421
 
422
+ Create a `.env` file and add:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
423
 
424
  """)
425
  st.code("""
 
428
  GITHUB_TOKEN=your_github_personal_access_token
429
  """, language='text')
430
 
431
+ st.warning("โš ๏ธ **Note:** Keep your `.env` file secretโ€”just like your secret stash of cookies! ๏ฟฝ๏ฟฝ")
432
 
433
  st.markdown("---")
434
 
435
  st.markdown("""
436
+ ### ๐Ÿ”ง Application Architecture
 
 
 
 
 
 
 
 
437
 
438
+ **Components:**
439
 
440
+ - ๐Ÿ—„๏ธ **Cosmos DB Operations**: Functions to connect and interact with Azure Cosmos DB.
441
+ - ๐Ÿ™ **GitHub Integration**: Clone, create, and push repositories like a boss.
442
+ - ๐ŸŽจ **Streamlit Interface**: The front-end that brings it all together.
443
+
444
+ **Data Flow:**
445
 
446
+ 1. ๐ŸŽ›๏ธ **User Interaction**: Users make choices in the app.
447
+ 2. ๐Ÿ—„๏ธ **Database Operations**: App performs actions on Cosmos DB.
448
+ 3. ๐Ÿ™ **GitHub Actions**: Clone and push repositories.
449
+ 4. ๐Ÿ“ฆ **Archiving Data**: Archive and download database contents.
450
+
451
  ---
452
+
453
+ ### ๐Ÿงฉ Implementing the Application
454
 
455
+ **Importing Libraries**
 
 
 
 
456
 
457
  """)
458
  st.code("""
 
471
  """, language='python')
472
 
473
  st.markdown("""
474
+ **Configuring Cosmos DB and GitHub**
475
 
476
  """)
477
  st.code("""
 
484
  """, language='python')
485
 
486
  st.markdown("""
487
+ **Helper Functions**
488
+
489
+ Here's where the magic happens! โœจ
490
+
491
+ *GitHub Operations*
492
 
 
493
  """)
494
  st.code("""
495
  def download_github_repo(url, local_path):
 
503
  """, language='python')
504
 
505
  st.markdown("""
506
+ *Base64 Download Link*
507
+
508
  """)
509
  st.code("""
510
  def get_base64_download_link(file_path, file_name):
 
512
  """, language='python')
513
 
514
  st.markdown("""
515
+ **Cosmos DB Operations**
516
+
517
+ *Fetching Database Structure*
518
 
 
519
  """)
520
  st.code("""
521
  def fetch_db_structure(client):
 
523
  """, language='python')
524
 
525
  st.markdown("""
526
+ *CRUD Operations*
527
+
528
+ **Create Item**
529
 
 
530
  """)
531
  st.code("""
532
  def create_item(client, db_name, container_name):
 
534
  """, language='python')
535
 
536
  st.markdown("""
537
+ **Edit Item**
538
+
539
  """)
540
  st.code("""
541
  def edit_item(client, db_name, container_name, item_id):
 
543
  """, language='python')
544
 
545
  st.markdown("""
546
+ **Delete Item**
547
+
548
  """)
549
  st.code("""
550
  def delete_item(client, db_name, container_name, item_id):
 
552
  """, language='python')
553
 
554
  st.markdown("""
555
+ **Archiving Data**
556
 
557
  """)
558
  st.code("""
 
561
  """, language='python')
562
 
563
  st.markdown("""
564
+ **Streamlit Interface**
565
+
566
+ *Rendering the Sidebar*
567
 
 
568
  """)
569
  st.code("""
570
  def render_sidebar(client, structure):
 
572
  """, language='python')
573
 
574
  st.markdown("""
575
+ *Main Function*
576
+
577
  """)
578
  st.code("""
579
  def main():
 
586
  st.markdown("---")
587
 
588
  st.markdown("""
589
+ ### ๐Ÿš€ Running the Application
590
 
591
+ **Start the Streamlit App**
 
 
592
 
593
  """)
594
  st.code("""
595
+ streamlit run CosmicApp.py
596
  """, language='bash')
597
 
598
  st.markdown("""
599
+ **Login**
 
 
 
600
 
601
+ - Open your browser and go to `http://localhost:8501`.
602
+ - Click **Launch** to enter the app.
603
+
604
+ **Using the App**
605
 
606
+ - **Database Selection**: Choose your database and container from the sidebar.
607
  - **Item Operations**:
608
+ - ๐ŸŒฑ **Create New Item**
609
+ - โœ๏ธ **Edit Item**
610
+ - ๐Ÿ—‘๏ธ **Delete Item**
611
  - **GitHub Operations**:
612
+ - ๐Ÿ“ฅ **Clone Repository**
613
+ - ๐Ÿ“ค **Push to New Repository**
614
+ - **Archive Data**: Click **๐Ÿ“ฆ Archive All Data** to download a ZIP file.
615
+ - **Download Code**: Click **๐Ÿ’พ Download All Code** to get the app's source code.
616
 
617
  ---
618
+
619
+ ### ๐ŸŒ  Conclusion
620
 
621
+ You've reached the end of our cosmic tutorial! ๐Ÿš€ We hope you had a stellar time learning and exploring the universe of Cosmos DB and GitHub integration.
 
 
 
 
622
 
623
+ **Keep Reaching for the Stars!** ๐ŸŒŸ
 
 
624
 
625
+ ---
626
  """)
627
 
628
  if __name__ == "__main__":