awacke1 commited on
Commit
ff78816
1 Parent(s): bbf0aa1

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +613 -0
app.py ADDED
@@ -0,0 +1,613 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from azure.cosmos import CosmosClient, exceptions
3
+ import os
4
+ import pandas as pd
5
+ import json
6
+ from datetime import datetime
7
+ import shutil
8
+ from github import Github
9
+ from git import Repo
10
+ import base64
11
+ from dotenv import load_dotenv
12
+
13
+ load_dotenv()
14
+
15
+ # Cosmos DB configuration
16
+ ENDPOINT = os.getenv("ENDPOINT")
17
+ PRIMARY_KEY = os.getenv("PRIMARY_KEY")
18
+
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
+
38
+ if 'origin' in [remote.name for remote in local_repo.remotes]:
39
+ origin = local_repo.remote('origin')
40
+ origin.set_url(repo_url)
41
+ else:
42
+ origin = local_repo.create_remote('origin', repo_url)
43
+
44
+ local_repo.git.add(A=True)
45
+ if local_repo.is_dirty():
46
+ local_repo.git.commit('-m', 'Initial commit')
47
+
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']
60
+ structure[db_name] = []
61
+ db_client = client.get_database_client(db_name)
62
+ for container in db_client.list_containers():
63
+ structure[db_name].append(container['id'])
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):
120
+ shutil.rmtree(base_dir)
121
+ os.makedirs(base_dir)
122
+
123
+ for database in client.list_databases():
124
+ db_name = database['id']
125
+ db_dir = os.path.join(base_dir, db_name)
126
+ os.makedirs(db_dir)
127
+
128
+ db_client = client.get_database_client(db_name)
129
+ for container in db_client.list_containers():
130
+ container_name = container['id']
131
+ container_dir = os.path.join(db_dir, container_name)
132
+ os.makedirs(container_dir)
133
+
134
+ container_client = db_client.get_container_client(container_name)
135
+ items = list(container_client.read_all_items())
136
+
137
+ with open(os.path.join(container_dir, f"{container_name}.json"), 'w') as f:
138
+ json.dump(items, f, indent=2)
139
+
140
+ archive_name = f"cosmos_archive_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
141
+ shutil.make_archive(archive_name, 'zip', base_dir)
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
224
+ st.experimental_rerun()
225
+
226
+ return selected_db, selected_container, selected_item, app_mode
227
+ else:
228
+ # For tutorial mode
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')}"
235
+ download_github_repo(source_repo, local_path)
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:
272
+ st.session_state.logged_in = False
273
+ if 'action' not in st.session_state:
274
+ st.session_state.action = None
275
+ if 'selected_item' not in st.session_state:
276
+ st.session_state.selected_item = None
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:
291
+ client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
292
+ # Fetch database structure
293
+ structure = fetch_db_structure(client)
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)
301
+ elif st.session_state.action == "edit":
302
+ edit_item(client, selected_db, selected_container, st.session_state.selected_item)
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("""
356
+ git clone https://github.com/yourusername/cosmosdb-streamlit-app.git
357
+ cd cosmosdb-streamlit-app
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("""
381
+ pip install -r requirements.txt
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("""
411
+ ENDPOINT=https://your-cosmos-db-account.documents.azure.com:443/
412
+ PRIMARY_KEY=your_cosmos_db_primary_key
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("""
448
+ import streamlit as st
449
+ from azure.cosmos import CosmosClient, exceptions
450
+ import os
451
+ import json
452
+ from datetime import datetime
453
+ import shutil
454
+ from github import Github
455
+ from git import Repo
456
+ import base64
457
+ from dotenv import load_dotenv
458
+
459
+ load_dotenv()
460
+ """, language='python')
461
+
462
+ st.markdown("""
463
+ ### Configuring Cosmos DB and GitHub
464
+
465
+ """)
466
+ st.code("""
467
+ # Cosmos DB configuration
468
+ ENDPOINT = os.getenv("ENDPOINT")
469
+ PRIMARY_KEY = os.getenv("PRIMARY_KEY")
470
+
471
+ # GitHub configuration
472
+ GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
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):
482
+ # Function implementation
483
+
484
+ def create_repo(github_token, repo_name):
485
+ # Function implementation
486
+
487
+ def push_to_github(local_path, repo, github_token):
488
+ # Function implementation
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):
496
+ # Function implementation
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):
506
+ # Function implementation
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):
516
+ # Function implementation
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):
524
+ # Function implementation
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):
532
+ # Function implementation
533
+ """, language='python')
534
+
535
+ st.markdown("""
536
+ ### Archiving Data
537
+
538
+ """)
539
+ st.code("""
540
+ def archive_all_data(client):
541
+ # Function implementation
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):
551
+ # Function implementation
552
+ """, language='python')
553
+
554
+ st.markdown("""
555
+ **Main Function**
556
+ """)
557
+ st.code("""
558
+ def main():
559
+ # Function implementation
560
+
561
+ if __name__ == "__main__":
562
+ main()
563
+ """, language='python')
564
+
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__":
613
+ main()