awacke1 commited on
Commit
bdabcd9
ยท
verified ยท
1 Parent(s): 658d7a2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +309 -0
app.py ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from azure.cosmos import CosmosClient, exceptions
3
+ import os
4
+ import pandas as pd
5
+ import traceback
6
+ import shutil
7
+ from github import Github
8
+ from git import Repo
9
+ from datetime import datetime
10
+ import base64
11
+ import json
12
+ import uuid # ๐ŸŽฒ For generating unique IDs
13
+ from urllib.parse import quote # ๐Ÿ”— For encoding URLs
14
+
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
+ DATABASE_NAME = os.environ.get("COSMOS_DATABASE_NAME")
21
+ CONTAINER_NAME = os.environ.get("COSMOS_CONTAINER_NAME")
22
+ Key = os.environ.get("Key") # ๐Ÿ”‘ Don't forget your key!
23
+
24
+ # ๐Ÿ  Your local app URL (Change this to your app's URL)
25
+ LOCAL_APP_URL = "http://localhost:8501"
26
+
27
+ # ๐Ÿ™ GitHub configuration
28
+ def download_github_repo(url, local_path):
29
+ # ๐Ÿšš Let's download that GitHub repo!
30
+ if os.path.exists(local_path):
31
+ shutil.rmtree(local_path)
32
+ Repo.clone_from(url, local_path)
33
+
34
+ def create_zip_file(source_dir, output_filename):
35
+ # ๐Ÿ“ฆ Zipping up files like a pro!
36
+ shutil.make_archive(output_filename, 'zip', source_dir)
37
+
38
+ def create_repo(g, repo_name):
39
+ # ๐Ÿ› ๏ธ Creating a new GitHub repo. Magic!
40
+ user = g.get_user()
41
+ return user.create_repo(repo_name)
42
+
43
+ def push_to_github(local_path, repo, github_token):
44
+ # ๐Ÿš€ Pushing code to GitHub. Hold on tight!
45
+ repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
46
+ local_repo = Repo(local_path)
47
+
48
+ if 'origin' in [remote.name for remote in local_repo.remotes]:
49
+ origin = local_repo.remote('origin')
50
+ origin.set_url(repo_url)
51
+ else:
52
+ origin = local_repo.create_remote('origin', repo_url)
53
+
54
+ if not local_repo.heads:
55
+ local_repo.git.checkout('-b', 'main')
56
+ current_branch = 'main'
57
+ else:
58
+ current_branch = local_repo.active_branch.name
59
+
60
+ local_repo.git.add(A=True)
61
+
62
+ if local_repo.is_dirty():
63
+ local_repo.git.commit('-m', 'Initial commit')
64
+
65
+ origin.push(refspec=f'{current_branch}:{current_branch}')
66
+
67
+ def get_base64_download_link(file_path, file_name):
68
+ # ๐Ÿง™โ€โ™‚๏ธ Generating a magical download link!
69
+ with open(file_path, "rb") as file:
70
+ contents = file.read()
71
+ base64_encoded = base64.b64encode(contents).decode()
72
+ return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">โฌ‡๏ธ Download {file_name}</a>'
73
+
74
+
75
+ # ๐Ÿงญ New functions for dynamic sidebar navigation
76
+ def get_databases(client):
77
+ # ๐Ÿ“š Fetching list of databases. So many options!
78
+ return [db['id'] for db in client.list_databases()]
79
+
80
+ def get_containers(database):
81
+ # ๐Ÿ“‚ Getting containers. Containers within containers!
82
+ return [container['id'] for container in database.list_containers()]
83
+
84
+ def get_documents(container, limit=None):
85
+ # ๐Ÿ“ Retrieving documents. Shhh, don't tell anyone!
86
+ query = "SELECT * FROM c ORDER BY c._ts DESC"
87
+ items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
88
+ return items
89
+
90
+
91
+ # ๐ŸŒŸ Cosmos DB functions
92
+ def insert_record(container, record):
93
+ try:
94
+ container.create_item(body=record)
95
+ return True, "Record inserted successfully! ๐ŸŽ‰"
96
+ except exceptions.CosmosHttpResponseError as e:
97
+ return False, f"HTTP error occurred: {str(e)} ๐Ÿšจ"
98
+ except Exception as e:
99
+ return False, f"An unexpected error occurred: {str(e)} ๐Ÿ˜ฑ"
100
+
101
+ def update_record(container, updated_record):
102
+ try:
103
+ container.upsert_item(body=updated_record)
104
+ return True, f"Record with id {updated_record['id']} successfully updated. ๐Ÿ› ๏ธ"
105
+ except exceptions.CosmosHttpResponseError as e:
106
+ return False, f"HTTP error occurred: {str(e)} ๐Ÿšจ"
107
+ except Exception as e:
108
+ return False, f"An unexpected error occurred: {traceback.format_exc()} ๐Ÿ˜ฑ"
109
+
110
+ def delete_record(container, name, id):
111
+ try:
112
+ container.delete_item(item=id, partition_key=id)
113
+ return True, f"Successfully deleted record with name: {name} and id: {id} ๐Ÿ—‘๏ธ"
114
+ except exceptions.CosmosResourceNotFoundError:
115
+ return False, f"Record with id {id} not found. It may have been already deleted. ๐Ÿ•ต๏ธโ€โ™‚๏ธ"
116
+ except exceptions.CosmosHttpResponseError as e:
117
+ return False, f"HTTP error occurred: {str(e)} ๐Ÿšจ"
118
+ except Exception as e:
119
+ return False, f"An unexpected error occurred: {traceback.format_exc()} ๐Ÿ˜ฑ"
120
+
121
+ # ๐ŸŽฒ Function to generate a unique UUID
122
+ def generate_unique_id():
123
+ # ๐Ÿง™โ€โ™‚๏ธ Generating a unique UUID!
124
+ return str(uuid.uuid4())
125
+
126
+ # ๐Ÿ“ฆ Function to archive current container
127
+ def archive_current_container(database_name, container_name, client):
128
+ try:
129
+ base_dir = "./cosmos_archive_current_container"
130
+ if os.path.exists(base_dir):
131
+ shutil.rmtree(base_dir)
132
+ os.makedirs(base_dir)
133
+
134
+ db_client = client.get_database_client(database_name)
135
+ container_client = db_client.get_container_client(container_name)
136
+ items = list(container_client.read_all_items())
137
+
138
+ container_dir = os.path.join(base_dir, container_name)
139
+ os.makedirs(container_dir)
140
+
141
+ for item in items:
142
+ item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
143
+ with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
144
+ json.dump(item, f, indent=2)
145
+
146
+ archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
147
+ shutil.make_archive(archive_name, 'zip', base_dir)
148
+
149
+ return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
150
+ except Exception as e:
151
+ return f"An error occurred while archiving data: {str(e)} ๐Ÿ˜ข"
152
+
153
+
154
+ # ๐ŸŽˆ Let's modify the main app to be more fun!
155
+ def main():
156
+ st.title("๐Ÿ™Git๐ŸŒŒCosmos๐Ÿ’ซ - Azure Cosmos DB and Github Agent")
157
+
158
+ # ๐Ÿšฆ Initialize session state
159
+ if 'logged_in' not in st.session_state:
160
+ st.session_state.logged_in = False
161
+ if 'selected_records' not in st.session_state:
162
+ st.session_state.selected_records = []
163
+ if 'client' not in st.session_state:
164
+ st.session_state.client = None
165
+ if 'selected_database' not in st.session_state:
166
+ st.session_state.selected_database = None
167
+ if 'selected_container' not in st.session_state:
168
+ st.session_state.selected_container = None
169
+ if 'selected_document_id' not in st.session_state:
170
+ st.session_state.selected_document_id = None
171
+ if 'current_index' not in st.session_state:
172
+ st.session_state.current_index = 0
173
+ if 'cloned_doc' not in st.session_state:
174
+ st.session_state.cloned_doc = None
175
+
176
+ # ๐Ÿ” Automatic Login
177
+ if Key:
178
+ st.session_state.primary_key = Key
179
+ st.session_state.logged_in = True
180
+ else:
181
+ st.error("Cosmos DB Key is not set in environment variables. ๐Ÿ”‘โŒ")
182
+ return # Can't proceed without a key
183
+
184
+ if st.session_state.logged_in:
185
+ # ๐ŸŒŒ Initialize Cosmos DB client
186
+ try:
187
+ if st.session_state.client is None:
188
+ st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
189
+
190
+ # ๐Ÿ—„๏ธ Sidebar for database, container, and document selection
191
+ st.sidebar.title("๐Ÿ™Git๐ŸŒŒCosmos๐Ÿ’ซ๐Ÿ—„๏ธNavigator")
192
+
193
+ databases = get_databases(st.session_state.client)
194
+ selected_db = st.sidebar.selectbox("๐Ÿ—ƒ๏ธ Select Database", databases)
195
+
196
+ if selected_db != st.session_state.selected_database:
197
+ st.session_state.selected_database = selected_db
198
+ st.session_state.selected_container = None
199
+ st.session_state.selected_document_id = None
200
+ st.session_state.current_index = 0
201
+ st.rerun()
202
+
203
+ if st.session_state.selected_database:
204
+ database = st.session_state.client.get_database_client(st.session_state.selected_database)
205
+ containers = get_containers(database)
206
+ selected_container = st.sidebar.selectbox("๐Ÿ“ Select Container", containers)
207
+
208
+ if selected_container != st.session_state.selected_container:
209
+ st.session_state.selected_container = selected_container
210
+ st.session_state.selected_document_id = None
211
+ st.session_state.current_index = 0
212
+ st.rerun()
213
+
214
+ if st.session_state.selected_container:
215
+ container = database.get_container_client(st.session_state.selected_container)
216
+
217
+ # ๐Ÿ“ฆ Add Export button
218
+ if st.button("๐Ÿ“ฆ Export Container Data"):
219
+ download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
220
+ if download_link.startswith('<a'):
221
+ st.markdown(download_link, unsafe_allow_html=True)
222
+ else:
223
+ st.error(download_link)
224
+
225
+ # Fetch documents
226
+ documents = get_documents(container)
227
+ total_docs = len(documents)
228
+
229
+ if total_docs > 5:
230
+ documents_to_display = documents[:5]
231
+ st.info("Showing top 5 most recent documents.")
232
+ else:
233
+ documents_to_display = documents
234
+ st.info(f"Showing all {len(documents_to_display)} documents.")
235
+
236
+ if documents_to_display:
237
+ # ๐ŸŽจ Add Viewer/Editor selection
238
+ view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Edit and Save', 'Clone Document', 'New Record']
239
+ selected_view = st.selectbox("Select Viewer/Editor", view_options, index=2)
240
+
241
+ if selected_view == 'Show as Markdown':
242
+ # ๐Ÿ–Œ๏ธ Show each record as Markdown with navigation
243
+ total_docs = len(documents)
244
+ doc = documents[st.session_state.current_index]
245
+ st.markdown(f"#### Document ID: {doc.get('id', '')}")
246
+
247
+ # ๐Ÿ•ต๏ธโ€โ™‚๏ธ Let's extract values from the JSON that have at least one space
248
+ values_with_space = []
249
+ def extract_values(obj):
250
+ if isinstance(obj, dict):
251
+ for k, v in obj.items():
252
+ extract_values(v)
253
+ elif isinstance(obj, list):
254
+ for item in obj:
255
+ extract_values(item)
256
+ elif isinstance(obj, str):
257
+ if ' ' in obj:
258
+ values_with_space.append(obj)
259
+
260
+ extract_values(doc)
261
+
262
+ # ๐Ÿ”— Let's create a list of links for these values
263
+ search_urls = {
264
+ "๐Ÿš€๐ŸŒŒArXiv": lambda k: f"/?q={quote(k)}",
265
+ "๐ŸƒAnalyst": lambda k: f"/?q={quote(k)}-{quote('PromptPrefix')}",
266
+ "๐Ÿ“šPyCoder": lambda k: f"/?q={quote(k)}-{quote('PromptPrefix2')}",
267
+ "๐Ÿ”ฌJSCoder": lambda k: f"/?q={quote(k)}-{quote('PromptPrefix3')}",
268
+ "๐Ÿ ": lambda k: f"{LOCAL_APP_URL}/?q={quote(k)}",
269
+ "๐Ÿ“–": lambda k: f"https://en.wikipedia.org/wiki/{quote(k)}",
270
+ "๐Ÿ”": lambda k: f"https://www.google.com/search?q={quote(k)}",
271
+ "โ–ถ๏ธ": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
272
+ "๐Ÿ”Ž": lambda k: f"https://www.bing.com/search?q={quote(k)}",
273
+ "๐ŸŽฅ": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
274
+ "๐Ÿฆ": lambda k: f"https://twitter.com/search?q={quote(k)}",
275
+ }
276
+
277
+ st.markdown("#### ๐Ÿ”— Links for Extracted Texts")
278
+ for term in values_with_space:
279
+ links_md = ' '.join([f"[{emoji}]({url(term)})" for emoji, url in search_urls.items()])
280
+ st.markdown(f"**{term}** <small>{links_md}</small>", unsafe_allow_html=True)
281
+
282
+ # Show the document content as markdown
283
+ content = json.dumps(doc, indent=2)
284
+ st.markdown(f"```json\n{content}\n```")
285
+
286
+ # Navigation buttons
287
+ col_prev, col_next = st.columns([1, 1])
288
+ with col_prev:
289
+ if st.button("โฌ…๏ธ Previous", key='prev_markdown'):
290
+ if st.session_state.current_index > 0:
291
+ st.session_state.current_index -= 1
292
+ st.rerun()
293
+ with col_next:
294
+ if st.button("โžก๏ธ Next", key='next_markdown'):
295
+ if st.session_state.current_index < total_docs - 1:
296
+ st.session_state.current_index += 1
297
+ st.rerun()
298
+
299
+ elif selected_view == 'Show as Code Editor':
300
+ # ๐Ÿ’ป Show each record in a code editor with navigation
301
+ total_docs = len(documents)
302
+ doc = documents[st.session_state.current_index]
303
+ st.markdown(f"#### Document ID: {doc.get('id', '')}")
304
+ doc_str = st.text_area("Edit Document", value=json.dumps(doc, indent=2), height=300, key=f'code_editor_{st.session_state.current_index}')
305
+ col_prev, col_next = st.columns([1, 1])
306
+ with col_prev:
307
+ if st.button("โฌ…๏ธ Previous", key='prev_code'):
308
+ if st.session_state.current_index > 0:
309
+