awacke1 commited on
Commit
403a411
·
verified ·
1 Parent(s): 2dba4ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +288 -143
app.py CHANGED
@@ -25,151 +25,105 @@ Key = os.environ.get("Key") # 🔑 Don't forget your key!
25
  # 🏠 Your local app URL (Change this to your app's URL)
26
  LOCAL_APP_URL = "https://huggingface.co/spaces/awacke1/AzureCosmosDBUI"
27
 
28
- # 🐙 GitHub configuration
29
- def download_github_repo(url, local_path):
30
- # 🚚 Let's download that GitHub repo!
31
- if os.path.exists(local_path):
32
- shutil.rmtree(local_path)
33
- Repo.clone_from(url, local_path)
34
-
35
- def create_zip_file(source_dir, output_filename):
36
- # 📦 Zipping up files like a pro!
37
- shutil.make_archive(output_filename, 'zip', source_dir)
38
-
39
- def create_repo(g, repo_name):
40
- # 🛠️ Creating a new GitHub repo. It's alive!
41
- user = g.get_user()
42
- return user.create_repo(repo_name)
43
-
44
- def push_to_github(local_path, repo, github_token):
45
- # 🚀 Pushing code to GitHub. Blast off!
46
- repo_url = f"https://{github_token}@github.com/{repo.full_name}.git"
47
- local_repo = Repo(local_path)
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
- # 🧭 Cosmos DB Functions
75
- def get_databases(client):
76
- # 📚 Fetching list of databases!
77
- return [db['id'] for db in client.list_databases()]
78
 
79
- def get_containers(database):
80
- # 📂 Listing containers within the selected database
81
- return [container['id'] for container in database.list_containers()]
82
-
83
- def get_documents(container, limit=None):
84
- # 📝 Fetching documents from Cosmos DB
85
- query = "SELECT * FROM c ORDER BY c._ts DESC"
86
- items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
87
- return items
88
 
 
89
  def insert_record(container, record):
90
- # 📥 Inserting a record into the Cosmos DB
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
- # 🛠️ Updating a record in the Cosmos DB
101
  try:
102
  container.upsert_item(body=updated_record)
 
103
  return True, f"Record with id {updated_record['id']} successfully updated. 🛠️"
104
  except exceptions.CosmosHttpResponseError as e:
 
105
  return False, f"HTTP error occurred: {str(e)} 🚨"
106
  except Exception as e:
 
107
  return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
108
 
109
  def delete_record(container, name, id):
110
- # 🗑️ Deleting a record in Cosmos DB
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
- def archive_current_container(database_name, container_name, client):
122
- # 📦 Archiving the container data from Cosmos DB
123
- try:
124
- base_dir = "./cosmos_archive_current_container"
125
- if os.path.exists(base_dir):
126
- shutil.rmtree(base_dir)
127
- os.makedirs(base_dir)
128
-
129
- db_client = client.get_database_client(database_name)
130
- container_client = db_client.get_container_client(container_name)
131
- items = list(container_client.read_all_items())
132
-
133
- container_dir = os.path.join(base_dir, container_name)
134
- os.makedirs(container_dir)
135
-
136
- for item in items:
137
- item_id = item.get('id', f"unknown_{datetime.now().strftime('%Y%m%d%H%M%S')}")
138
- with open(os.path.join(container_dir, f"{item_id}.json"), 'w') as f:
139
- json.dump(item, f, indent=2)
140
-
141
- archive_name = f"{container_name}_archive_{datetime.now().strftime('%Y%m%d%H%M%S')}"
142
- shutil.make_archive(archive_name, 'zip', base_dir)
143
-
144
- return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip")
145
- except Exception as e:
146
- return f"An error occurred while archiving data: {str(e)} 😢"
147
-
148
  # 🎲 Function to generate a unique UUID
149
  def generate_unique_id():
150
- # 🔮 Generate a unique ID for new records
151
  return str(uuid.uuid4())
152
 
153
- # 🔗 Helper function for hyperlink extraction
154
- def extract_hyperlinks(responses):
155
- # 🔗 Extracting hyperlinks from response
156
- hyperlinks = []
157
- for response in responses:
158
- parsed_response = json.loads(response)
159
- links = [value for key, value in parsed_response.items() if isinstance(value, str) and value.startswith("http")]
160
- hyperlinks.extend(links)
161
- return hyperlinks
162
-
163
- # 📋 Helper function to format text with line numbers
164
- def format_with_line_numbers(text):
165
- # 📋 Organizing lines with numbers
166
- lines = text.splitlines()
167
- formatted_text = '\n'.join(f"{i+1}: {line}" for i, line in enumerate(lines))
168
- return formatted_text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
 
170
  # 🎤 Function to process text input
171
  def process_text(text_input):
172
- # 🎤 Processing input for queries or searches
173
  if text_input:
174
  if 'messages' not in st.session_state:
175
  st.session_state.messages = []
@@ -182,22 +136,38 @@ def process_text(text_input):
182
  with st.chat_message("assistant"):
183
  search_glossary(text_input)
184
 
185
- # 🎈 Main function to drive the application
186
  def main():
187
- # 🎈 Let's kickstart the app with a fun introduction!
188
  st.title("🐙Git🌌Cosmos💫 - Azure Cosmos DB and Github Agent")
189
 
190
- # 🚦 Initialize session state for managing components
191
  if 'logged_in' not in st.session_state:
192
  st.session_state.logged_in = False
 
 
193
  if 'client' not in st.session_state:
194
  st.session_state.client = None
195
  if 'selected_database' not in st.session_state:
196
  st.session_state.selected_database = None
197
  if 'selected_container' not in st.session_state:
198
  st.session_state.selected_container = None
 
 
 
 
 
 
199
 
200
- # 🔐 Login management
 
 
 
 
 
 
 
 
 
 
201
  if Key:
202
  st.session_state.primary_key = Key
203
  st.session_state.logged_in = True
@@ -206,20 +176,20 @@ def main():
206
  return
207
 
208
  if st.session_state.logged_in:
 
209
  try:
210
- # 🌌 Initialize Cosmos DB client
211
  if st.session_state.client is None:
212
  st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
213
 
214
- # 🗄️ Sidebar for database and container selection
215
- st.sidebar.title("🗄️ Cosmos DB Navigator")
216
-
217
  databases = get_databases(st.session_state.client)
218
  selected_db = st.sidebar.selectbox("🗃️ Select Database", databases)
219
 
220
  if selected_db != st.session_state.selected_database:
221
  st.session_state.selected_database = selected_db
222
  st.session_state.selected_container = None
 
 
223
  st.rerun()
224
 
225
  if st.session_state.selected_database:
@@ -229,12 +199,14 @@ def main():
229
 
230
  if selected_container != st.session_state.selected_container:
231
  st.session_state.selected_container = selected_container
 
 
232
  st.rerun()
233
-
234
  if st.session_state.selected_container:
235
  container = database.get_container_client(st.session_state.selected_container)
236
-
237
- # 📦 Export container data
238
  if st.button("📦 Export Container Data"):
239
  download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
240
  if download_link.startswith('<a'):
@@ -242,57 +214,230 @@ def main():
242
  else:
243
  st.error(download_link)
244
 
245
- # 📝 Display documents
246
  documents = get_documents(container)
247
- st.subheader(f"📊 Container: {st.session_state.selected_container}")
248
- if documents:
249
- df = pd.DataFrame(documents)
250
- st.dataframe(df)
 
251
  else:
252
- st.info("No documents to display. 🧐")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
254
- # 🐙 GitHub operations
 
 
 
 
 
 
 
 
 
255
  st.subheader("🐙 GitHub Operations")
256
- github_token = os.environ.get("GITHUB") # GitHub token for authentication
257
  source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
258
- new_repo_name = st.text_input("New Repository Name", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
259
 
260
  col1, col2 = st.columns(2)
261
  with col1:
262
  if st.button("📥 Clone Repository"):
263
  if github_token and source_repo:
264
- local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
265
- download_github_repo(source_repo, local_path)
266
- zip_filename = f"{new_repo_name}.zip"
267
- create_zip_file(local_path, zip_filename[:-4])
268
- st.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
269
- st.success("Repository cloned successfully! 🎉")
270
- shutil.rmtree(local_path)
 
 
 
 
 
 
 
271
  else:
272
- st.error("Please provide GitHub token and source repo URL.")
273
-
274
  with col2:
275
  if st.button("📤 Push to New Repository"):
276
  if github_token and source_repo:
277
- g = Github(github_token)
278
- new_repo = create_repo(g, new_repo_name)
279
- local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
280
- download_github_repo(source_repo, local_path)
281
- push_to_github(local_path, new_repo, github_token)
282
- st.success(f"Repository pushed successfully to {new_repo.html_url} 🚀")
283
- shutil.rmtree(local_path)
 
 
 
 
 
284
  else:
285
- st.error("Please provide GitHub token and source repo URL.")
286
 
287
  except exceptions.CosmosHttpResponseError as e:
288
  st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
289
  except Exception as e:
290
  st.error(f"An unexpected error occurred: {str(e)} 😱")
291
 
292
- # 🚪 Logout option
293
  if st.session_state.logged_in and st.sidebar.button("🚪 Logout"):
294
  st.session_state.logged_in = False
 
295
  st.session_state.client = None
 
 
 
 
296
  st.rerun()
297
 
298
  if __name__ == "__main__":
 
25
  # 🏠 Your local app URL (Change this to your app's URL)
26
  LOCAL_APP_URL = "https://huggingface.co/spaces/awacke1/AzureCosmosDBUI"
27
 
28
+ # 📝 Initialize logging system
29
+ if 'logs' not in st.session_state:
30
+ st.session_state.logs = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ def log_event(message):
33
+ """Adds a log entry to the log session state."""
34
+ timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
35
+ st.session_state.logs.append(f"[{timestamp}] {message}")
 
 
36
 
37
+ # 🏠 Add logs to sidebar
38
+ st.sidebar.title("📝 Log Viewer")
39
+ st.sidebar.write("\n".join(st.session_state.logs))
 
40
 
41
+ # 🤖 OpenAI configuration
42
+ # openai.api_key = os.environ.get("OPENAI_API_KEY")
43
+ # MODEL = "gpt-3.5-turbo" # Replace with your desired model
 
 
 
 
 
 
44
 
45
+ # 🌟 Cosmos DB functions
46
  def insert_record(container, record):
 
47
  try:
48
  container.create_item(body=record)
49
+ log_event("Record inserted successfully!")
50
  return True, "Record inserted successfully! 🎉"
51
  except exceptions.CosmosHttpResponseError as e:
52
+ log_event(f"HTTP error occurred: {str(e)} 🚨")
53
  return False, f"HTTP error occurred: {str(e)} 🚨"
54
  except Exception as e:
55
+ log_event(f"An unexpected error occurred: {str(e)} 😱")
56
  return False, f"An unexpected error occurred: {str(e)} 😱"
57
 
58
  def update_record(container, updated_record):
 
59
  try:
60
  container.upsert_item(body=updated_record)
61
+ log_event(f"Record with id {updated_record['id']} successfully updated.")
62
  return True, f"Record with id {updated_record['id']} successfully updated. 🛠️"
63
  except exceptions.CosmosHttpResponseError as e:
64
+ log_event(f"HTTP error occurred: {str(e)} 🚨")
65
  return False, f"HTTP error occurred: {str(e)} 🚨"
66
  except Exception as e:
67
+ log_event(f"An unexpected error occurred: {traceback.format_exc()} 😱")
68
  return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
69
 
70
  def delete_record(container, name, id):
 
71
  try:
72
  container.delete_item(item=id, partition_key=id)
73
+ log_event(f"Successfully deleted record with name: {name} and id: {id}")
74
  return True, f"Successfully deleted record with name: {name} and id: {id} 🗑️"
75
  except exceptions.CosmosResourceNotFoundError:
76
+ log_event(f"Record with id {id} not found. It may have been already deleted.")
77
  return False, f"Record with id {id} not found. It may have been already deleted. 🕵️‍♂️"
78
  except exceptions.CosmosHttpResponseError as e:
79
+ log_event(f"HTTP error occurred: {str(e)} 🚨")
80
  return False, f"HTTP error occurred: {str(e)} 🚨"
81
  except Exception as e:
82
+ log_event(f"An unexpected error occurred: {traceback.format_exc()} 😱")
83
  return False, f"An unexpected error occurred: {traceback.format_exc()} 😱"
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  # 🎲 Function to generate a unique UUID
86
  def generate_unique_id():
 
87
  return str(uuid.uuid4())
88
 
89
+ def get_databases(client):
90
+ return [db['id'] for db in client.list_databases()]
91
+
92
+ def get_containers(database):
93
+ return [container['id'] for container in database.list_containers()]
94
+
95
+ def get_documents(container, limit=None):
96
+ query = "SELECT * FROM c ORDER BY c._ts DESC"
97
+ items = list(container.query_items(query=query, enable_cross_partition_query=True, max_item_count=limit))
98
+ return items
99
+
100
+ def save_to_cosmos_db(container, query, response1, response2):
101
+ try:
102
+ if container:
103
+ record = {
104
+ "id": generate_unique_id(),
105
+ "query": query,
106
+ "response1": response1,
107
+ "response2": response2
108
+ }
109
+ try:
110
+ container.create_item(body=record)
111
+ st.success(f"Record saved successfully with ID: {record['id']}")
112
+ log_event(f"Record saved to Cosmos DB with ID: {record['id']}")
113
+ # Refresh the documents display
114
+ st.session_state.documents = get_documents(container)
115
+ except exceptions.CosmosHttpResponseError as e:
116
+ st.error(f"Error saving record to Cosmos DB: {e}")
117
+ log_event(f"Error saving record to Cosmos DB: {e}")
118
+ else:
119
+ st.error("Cosmos DB container is not initialized.")
120
+ log_event("Error: Cosmos DB container is not initialized.")
121
+ except Exception as e:
122
+ st.error(f"An unexpected error occurred: {str(e)}")
123
+ log_event(f"An unexpected error occurred while saving to Cosmos DB: {str(e)}")
124
 
125
  # 🎤 Function to process text input
126
  def process_text(text_input):
 
127
  if text_input:
128
  if 'messages' not in st.session_state:
129
  st.session_state.messages = []
 
136
  with st.chat_message("assistant"):
137
  search_glossary(text_input)
138
 
139
+ # 🎈 Main function
140
  def main():
 
141
  st.title("🐙Git🌌Cosmos💫 - Azure Cosmos DB and Github Agent")
142
 
 
143
  if 'logged_in' not in st.session_state:
144
  st.session_state.logged_in = False
145
+ if 'selected_records' not in st.session_state:
146
+ st.session_state.selected_records = []
147
  if 'client' not in st.session_state:
148
  st.session_state.client = None
149
  if 'selected_database' not in st.session_state:
150
  st.session_state.selected_database = None
151
  if 'selected_container' not in st.session_state:
152
  st.session_state.selected_container = None
153
+ if 'selected_document_id' not in st.session_state:
154
+ st.session_state.selected_document_id = None
155
+ if 'current_index' not in st.session_state:
156
+ st.session_state.current_index = 0
157
+ if 'cloned_doc' not in st.session_state:
158
+ st.session_state.cloned_doc = None
159
 
160
+ # ⚙️ Check query parameters for any action
161
+ try:
162
+ query_params = st.query_params
163
+ query = query_params.get('q') or query_params.get('query') or ''
164
+ if query:
165
+ process_text(query)
166
+ st.stop()
167
+ except Exception as e:
168
+ st.markdown(' ')
169
+
170
+ # 🔐 Automatic Login
171
  if Key:
172
  st.session_state.primary_key = Key
173
  st.session_state.logged_in = True
 
176
  return
177
 
178
  if st.session_state.logged_in:
179
+ # 🌌 Initialize Cosmos DB client
180
  try:
 
181
  if st.session_state.client is None:
182
  st.session_state.client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key)
183
 
184
+ st.sidebar.title("🐙Git🌌Cosmos💫🗄️Navigator")
 
 
185
  databases = get_databases(st.session_state.client)
186
  selected_db = st.sidebar.selectbox("🗃️ Select Database", databases)
187
 
188
  if selected_db != st.session_state.selected_database:
189
  st.session_state.selected_database = selected_db
190
  st.session_state.selected_container = None
191
+ st.session_state.selected_document_id = None
192
+ st.session_state.current_index = 0
193
  st.rerun()
194
 
195
  if st.session_state.selected_database:
 
199
 
200
  if selected_container != st.session_state.selected_container:
201
  st.session_state.selected_container = selected_container
202
+ st.session_state.selected_document_id = None
203
+ st.session_state.current_index = 0
204
  st.rerun()
205
+
206
  if st.session_state.selected_container:
207
  container = database.get_container_client(st.session_state.selected_container)
208
+
209
+ # 📦 Add Export button
210
  if st.button("📦 Export Container Data"):
211
  download_link = archive_current_container(st.session_state.selected_database, st.session_state.selected_container, st.session_state.client)
212
  if download_link.startswith('<a'):
 
214
  else:
215
  st.error(download_link)
216
 
217
+ # Fetch documents
218
  documents = get_documents(container)
219
+ total_docs = len(documents)
220
+
221
+ if total_docs > 5:
222
+ documents_to_display = documents[:5]
223
+ st.info("Showing top 5 most recent documents.")
224
  else:
225
+ documents_to_display = documents
226
+ st.info(f"Showing all {len(documents_to_display)} documents.")
227
+
228
+ if documents_to_display:
229
+ # 🎨 Add Viewer/Editor selection
230
+ view_options = ['Show as Markdown', 'Show as Code Editor', 'Show as Edit and Save', 'Clone Document', 'New Record']
231
+ selected_view = st.selectbox("Select Viewer/Editor", view_options, index=2)
232
+
233
+ if selected_view == 'Show as Markdown':
234
+ doc = documents[st.session_state.current_index]
235
+ st.markdown(f"#### Document ID: {doc.get('id', '')}")
236
+ content = json.dumps(doc, indent=2)
237
+ st.markdown(f"```json\n{content}\n```")
238
+
239
+ col_prev, col_next = st.columns([1, 1])
240
+ with col_prev:
241
+ if st.button("⬅️ Previous", key='prev_markdown'):
242
+ if st.session_state.current_index > 0:
243
+ st.session_state.current_index -= 1
244
+ st.rerun()
245
+ with col_next:
246
+ if st.button("➡️ Next", key='next_markdown'):
247
+ if st.session_state.current_index < total_docs - 1:
248
+ st.session_state.current_index += 1
249
+ st.rerun()
250
+
251
+ elif selected_view == 'Show as Code Editor':
252
+ doc = documents[st.session_state.current_index]
253
+ st.markdown(f"#### Document ID: {doc.get('id', '')}")
254
+ doc_str = st.text_area("Edit Document", value=json.dumps(doc, indent=2), height=300, key=f'code_editor_{st.session_state.current_index}')
255
+
256
+ col_prev, col_next = st.columns([1, 1])
257
+ with col_prev:
258
+ if st.button("⬅️ Previous", key='prev_code'):
259
+ if st.session_state.current_index > 0:
260
+ st.session_state.current_index -= 1
261
+ st.rerun()
262
+ with col_next:
263
+ if st.button("➡️ Next", key='next_code'):
264
+ if st.session_state.current_index < total_docs - 1:
265
+ st.session_state.current_index += 1
266
+ st.rerun()
267
+
268
+ if st.button("💾 Save Changes", key=f'save_button_{st.session_state.current_index}'):
269
+ try:
270
+ updated_doc = json.loads(doc_str)
271
+ success, message = update_record(container, updated_doc)
272
+ if success:
273
+ st.success(f"Document {updated_doc['id']} saved successfully.")
274
+ st.session_state.selected_document_id = updated_doc['id']
275
+ st.rerun()
276
+ else:
277
+ st.error(message)
278
+ except json.JSONDecodeError as e:
279
+ st.error(f"Invalid JSON: {str(e)} 🚫")
280
+
281
+ elif selected_view == 'Show as Edit and Save':
282
+ st.markdown("#### Edit the document fields below:")
283
+ num_cols = len(documents_to_display)
284
+ cols = st.columns(num_cols)
285
+
286
+ for idx, (col, doc) in enumerate(zip(cols, documents_to_display)):
287
+ with col:
288
+ st.markdown(f"##### Document ID: {doc.get('id', '')}")
289
+ editable_id = st.text_input("ID", value=doc.get('id', ''), key=f'edit_id_{idx}')
290
+ editable_doc = doc.copy()
291
+ editable_doc.pop('id', None)
292
+ doc_str = st.text_area("Document Content (in JSON format)", value=json.dumps(editable_doc, indent=2), height=300, key=f'doc_str_{idx}')
293
+
294
+ col_save, col_ai = st.columns(2)
295
+ with col_save:
296
+ if st.button("💾 Save Changes", key=f'save_button_{idx}'):
297
+ try:
298
+ updated_doc = json.loads(doc_str)
299
+ updated_doc['id'] = editable_id
300
+ success, message = update_record(container, updated_doc)
301
+ if success:
302
+ st.success(f"Document {updated_doc['id']} saved successfully.")
303
+ st.session_state.selected_document_id = updated_doc['id']
304
+ st.rerun()
305
+ else:
306
+ st.error(message)
307
+ except json.JSONDecodeError as e:
308
+ st.error(f"Invalid JSON: {str(e)} 🚫")
309
+ with col_ai:
310
+ if st.button("🤖 Run With AI", key=f'run_with_ai_button_{idx}'):
311
+ search_glossary(json.dumps(editable_doc, indent=2))
312
+
313
+ elif selected_view == 'Clone Document':
314
+ st.markdown("#### Clone a document:")
315
+ for idx, doc in enumerate(documents_to_display):
316
+ st.markdown(f"##### Document ID: {doc.get('id', '')}")
317
+ if st.button("📄 Clone Document", key=f'clone_button_{idx}'):
318
+ cloned_doc = doc.copy()
319
+ cloned_doc['id'] = generate_unique_id()
320
+ st.session_state.cloned_doc = cloned_doc
321
+ st.session_state.cloned_doc_str = json.dumps(cloned_doc, indent=2)
322
+ st.session_state.clone_mode = True
323
+ st.rerun()
324
+
325
+ if st.session_state.get('clone_mode', False):
326
+ st.markdown("#### Edit Cloned Document:")
327
+ cloned_doc_str = st.text_area("Cloned Document Content (in JSON format)", value=st.session_state.cloned_doc_str, height=300)
328
+ if st.button("💾 Save Cloned Document"):
329
+ try:
330
+ new_doc = json.loads(cloned_doc_str)
331
+ success, message = insert_record(container, new_doc)
332
+ if success:
333
+ st.success(f"Cloned document saved with id: {new_doc['id']} 🎉")
334
+ st.session_state.selected_document_id = new_doc['id']
335
+ st.session_state.clone_mode = False
336
+ st.session_state.cloned_doc = None
337
+ st.session_state.cloned_doc_str = ''
338
+ st.rerun()
339
+ else:
340
+ st.error(message)
341
+ except json.JSONDecodeError as e:
342
+ st.error(f"Invalid JSON: {str(e)} 🚫")
343
+
344
+ elif selected_view == 'New Record':
345
+ st.markdown("#### Create a new document:")
346
+ if st.button("🤖 Insert Auto-Generated Record"):
347
+ success, message = insert_auto_generated_record(container)
348
+ if success:
349
+ st.success(message)
350
+ st.rerun()
351
+ else:
352
+ st.error(message)
353
+ else:
354
+ new_id = st.text_input("ID", value=generate_unique_id(), key='new_id')
355
+ new_doc_str = st.text_area("Document Content (in JSON format)", value='{}', height=300)
356
+ if st.button("➕ Create New Document"):
357
+ try:
358
+ new_doc = json.loads(new_doc_str)
359
+ new_doc['id'] = new_id
360
+ success, message = insert_record(container, new_doc)
361
+ if success:
362
+ st.success(f"New document created with id: {new_doc['id']} 🎉")
363
+ st.session_state.selected_document_id = new_doc['id']
364
+ st.rerun()
365
+ else:
366
+ st.error(message)
367
+ except json.JSONDecodeError as e:
368
+ st.error(f"Invalid JSON: {str(e)} 🚫")
369
+
370
+ else:
371
+ st.sidebar.info("No documents found in this container. 📭")
372
 
373
+ # 🎉 Main content area
374
+ st.subheader(f"📊 Container: {st.session_state.selected_container}")
375
+ if st.session_state.selected_container:
376
+ if documents_to_display:
377
+ df = pd.DataFrame(documents_to_display)
378
+ st.dataframe(df)
379
+ else:
380
+ st.info("No documents to display. 🧐")
381
+
382
+ # 🐙 GitHub section
383
  st.subheader("🐙 GitHub Operations")
384
+ github_token = os.environ.get("GITHUB") # Read GitHub token from environment variable
385
  source_repo = st.text_input("Source GitHub Repository URL", value="https://github.com/AaronCWacker/AIExamples-8-24-Streamlit")
386
+ new_repo_name = st.text_input("New Repository Name (for cloning)", value=f"AIExample-Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}")
387
 
388
  col1, col2 = st.columns(2)
389
  with col1:
390
  if st.button("📥 Clone Repository"):
391
  if github_token and source_repo:
392
+ try:
393
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
394
+ download_github_repo(source_repo, local_path)
395
+ zip_filename = f"{new_repo_name}.zip"
396
+ create_zip_file(local_path, zip_filename[:-4])
397
+ st.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True)
398
+ st.success("Repository cloned successfully! 🎉")
399
+ except Exception as e:
400
+ st.error(f"An error occurred: {str(e)} 😢")
401
+ finally:
402
+ if os.path.exists(local_path):
403
+ shutil.rmtree(local_path)
404
+ if os.path.exists(zip_filename):
405
+ os.remove(zip_filename)
406
  else:
407
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. 🔑❓")
408
+
409
  with col2:
410
  if st.button("📤 Push to New Repository"):
411
  if github_token and source_repo:
412
+ try:
413
+ g = Github(github_token)
414
+ new_repo = create_repo(g, new_repo_name)
415
+ local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d%H%M%S')}"
416
+ download_github_repo(source_repo, local_path)
417
+ push_to_github(local_path, new_repo, github_token)
418
+ st.success(f"Repository pushed successfully to {new_repo.html_url} 🚀")
419
+ except Exception as e:
420
+ st.error(f"An error occurred: {str(e)} 😢")
421
+ finally:
422
+ if os.path.exists(local_path):
423
+ shutil.rmtree(local_path)
424
  else:
425
+ st.error("Please ensure GitHub token is set in environment variables and source repository URL is provided. 🔑❓")
426
 
427
  except exceptions.CosmosHttpResponseError as e:
428
  st.error(f"Failed to connect to Cosmos DB. HTTP error: {str(e)} 🚨")
429
  except Exception as e:
430
  st.error(f"An unexpected error occurred: {str(e)} 😱")
431
 
432
+ # 🚪 Logout button
433
  if st.session_state.logged_in and st.sidebar.button("🚪 Logout"):
434
  st.session_state.logged_in = False
435
+ st.session_state.selected_records.clear()
436
  st.session_state.client = None
437
+ st.session_state.selected_database = None
438
+ st.session_state.selected_container = None
439
+ st.session_state.selected_document_id = None
440
+ st.session_state.current_index = 0
441
  st.rerun()
442
 
443
  if __name__ == "__main__":