awacke1 commited on
Commit
09ccae7
Β·
verified Β·
1 Parent(s): 9b2bf79

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +310 -0
app.py ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit.components.v1 import html
3
+ from pathlib import Path
4
+ import json
5
+ import time
6
+ from datetime import datetime
7
+ import re
8
+ import pandas as pd
9
+ import yaml
10
+ from io import StringIO
11
+ import openpyxl
12
+ import csv
13
+ import base64
14
+
15
+ # Supported file types and their handlers
16
+ FILE_TYPES = {
17
+ "md": "πŸ“ Markdown",
18
+ "txt": "πŸ“„ Text",
19
+ "json": "πŸ”§ JSON",
20
+ "csv": "πŸ“Š CSV",
21
+ "xlsx": "πŸ“— Excel",
22
+ "yaml": "βš™οΈ YAML",
23
+ "xml": "πŸ”— XML"
24
+ }
25
+
26
+ # Enhanced state initialization
27
+ if 'file_data' not in st.session_state:
28
+ st.session_state.file_data = {}
29
+ if 'file_types' not in st.session_state:
30
+ st.session_state.file_types = {}
31
+ if 'md_outline' not in st.session_state:
32
+ st.session_state.md_outline = {}
33
+ if 'rendered_content' not in st.session_state:
34
+ st.session_state.rendered_content = {}
35
+ if 'file_history' not in st.session_state:
36
+ st.session_state.file_history = []
37
+ if 'md_versions' not in st.session_state:
38
+ st.session_state.md_versions = {}
39
+ if 'md_files_history' not in st.session_state:
40
+ st.session_state.md_files_history = []
41
+
42
+ def get_binary_file_downloader_html(bin_file, file_label='File'):
43
+ """Generate a link allowing the data in a given file to be downloaded"""
44
+ b64 = base64.b64encode(bin_file.encode()).decode()
45
+ return f'<a href="data:text/plain;base64,{b64}" download="{file_label}">πŸ“₯ Download {file_label}</a>'
46
+
47
+ def encode_content(content):
48
+ """Encode content to base64"""
49
+ return base64.b64encode(content.encode()).decode()
50
+
51
+ def decode_content(encoded_content):
52
+ """Decode content from base64"""
53
+ return base64.b64decode(encoded_content.encode()).decode()
54
+
55
+ def add_to_history(filename, content, action="uploaded"):
56
+ """Add a file action to the history with timestamp"""
57
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
58
+ encoded_content = encode_content(content)
59
+ history_entry = {
60
+ "timestamp": timestamp,
61
+ "filename": filename,
62
+ "action": action,
63
+ "content": encoded_content
64
+ }
65
+ st.session_state.file_history.insert(0, history_entry)
66
+
67
+ # Store version if it's a markdown file
68
+ if filename.endswith('.md'):
69
+ if filename not in st.session_state.md_versions:
70
+ st.session_state.md_versions[filename] = []
71
+ st.session_state.md_versions[filename].append({
72
+ "timestamp": timestamp,
73
+ "content": encoded_content,
74
+ "action": action
75
+ })
76
+
77
+ # Add to MD files history if not already present
78
+ if filename not in [f["filename"] for f in st.session_state.md_files_history]:
79
+ st.session_state.md_files_history.append({
80
+ "filename": filename,
81
+ "timestamp": timestamp,
82
+ "content": encoded_content
83
+ })
84
+
85
+ def show_sidebar_history():
86
+ """Display markdown file history in the sidebar"""
87
+ st.sidebar.markdown("### πŸ“š Markdown Files History")
88
+
89
+ for md_file in st.session_state.md_files_history:
90
+ col1, col2, col3 = st.sidebar.columns([2, 1, 1])
91
+
92
+ with col1:
93
+ st.markdown(f"**{md_file['filename']}**")
94
+
95
+ with col2:
96
+ if st.button("πŸ“‚ Open", key=f"open_{md_file['filename']}"):
97
+ content = decode_content(md_file['content'])
98
+ st.session_state.file_data[md_file['filename']] = content
99
+ st.session_state.file_types[md_file['filename']] = "md"
100
+ st.session_state.md_outline[md_file['filename']] = parse_markdown_outline(content)
101
+ st.experimental_rerun()
102
+
103
+ with col3:
104
+ download_link = get_binary_file_downloader_html(
105
+ decode_content(md_file['content']),
106
+ md_file['filename']
107
+ )
108
+ st.markdown(download_link, unsafe_allow_html=True)
109
+
110
+ def show_file_history():
111
+ """Display the file history in a collapsible section"""
112
+ if st.session_state.file_history:
113
+ with st.expander("πŸ“‹ File History", expanded=False):
114
+ st.markdown("### Recent File Activities")
115
+ for entry in st.session_state.file_history:
116
+ col1, col2 = st.columns([2, 3])
117
+ with col1:
118
+ st.markdown(f"**{entry['timestamp']}**")
119
+ with col2:
120
+ st.markdown(f"{entry['action'].title()}: {entry['filename']}")
121
+
122
+ def show_markdown_versions(filename):
123
+ """Display previous versions of a markdown file"""
124
+ if filename in st.session_state.md_versions:
125
+ versions = st.session_state.md_versions[filename]
126
+ if len(versions) > 1:
127
+ st.markdown("### πŸ“š Previous Versions")
128
+ version_idx = st.selectbox(
129
+ "Select version to view",
130
+ range(len(versions)-1),
131
+ format_func=lambda x: f"Version {len(versions)-1-x} - {versions[x]['timestamp']}"
132
+ )
133
+
134
+ if version_idx is not None:
135
+ version = versions[version_idx]
136
+ decoded_content = decode_content(version['content'])
137
+ st.text_area(
138
+ "Content",
139
+ decoded_content,
140
+ height=200,
141
+ key=f"version_{filename}_{version_idx}",
142
+ disabled=True
143
+ )
144
+ if st.button(f"Restore to this version", key=f"restore_{filename}_{version_idx}"):
145
+ st.session_state.file_data[filename] = decoded_content
146
+ st.session_state.md_outline[filename] = parse_markdown_outline(decoded_content)
147
+ add_to_history(filename, decoded_content, "restored")
148
+ st.experimental_rerun()
149
+
150
+ def parse_markdown_outline(content):
151
+ """Generate an outline from markdown content"""
152
+ lines = content.split('\n')
153
+ outline = []
154
+ for line in lines:
155
+ if line.strip().startswith('#'):
156
+ level = len(line.split()[0])
157
+ title = line.strip('#').strip()
158
+ outline.append({
159
+ 'level': level,
160
+ 'title': title,
161
+ 'indent': ' ' * (level - 1)
162
+ })
163
+ return outline
164
+
165
+ def create_markdown_tabs(content, filename):
166
+ """Create tabs for markdown content viewing and editing"""
167
+ tab1, tab2, tab3 = st.tabs(["πŸ“ Editor", "πŸ‘€ Preview", "πŸ•’ History"])
168
+
169
+ with tab1:
170
+ edited_content = st.text_area(
171
+ "Edit your markdown",
172
+ content,
173
+ height=300,
174
+ key=f"edit_{filename}"
175
+ )
176
+
177
+ if edited_content != content:
178
+ st.session_state.file_data[filename] = edited_content
179
+ st.session_state.md_outline[filename] = parse_markdown_outline(edited_content)
180
+ add_to_history(filename, edited_content, "edited")
181
+ content = edited_content
182
+
183
+ with tab2:
184
+ st.markdown("### Preview")
185
+ st.markdown(content)
186
+
187
+ if filename in st.session_state.md_outline:
188
+ st.markdown("---")
189
+ st.markdown("### πŸ“‘ Document Outline")
190
+ for item in st.session_state.md_outline[filename]:
191
+ st.markdown(f"{item['indent']}β€’ {item['title']}")
192
+
193
+ with tab3:
194
+ show_markdown_versions(filename)
195
+
196
+ return content
197
+
198
+ def read_file_content(uploaded_file):
199
+ """Smart file reader with enhanced markdown handling"""
200
+ file_type = uploaded_file.name.split('.')[-1].lower()
201
+ try:
202
+ if file_type == 'md':
203
+ content = uploaded_file.getvalue().decode()
204
+ st.session_state.md_outline[uploaded_file.name] = parse_markdown_outline(content)
205
+ st.session_state.rendered_content[uploaded_file.name] = content
206
+ add_to_history(uploaded_file.name, content)
207
+ return content, "md"
208
+
209
+ elif file_type == 'csv':
210
+ df = pd.read_csv(uploaded_file)
211
+ return df.to_string(), "csv"
212
+
213
+ elif file_type == 'xlsx':
214
+ df = pd.read_excel(uploaded_file)
215
+ return df.to_string(), "xlsx"
216
+
217
+ elif file_type == 'json':
218
+ content = json.load(uploaded_file)
219
+ return json.dumps(content, indent=2), "json"
220
+
221
+ elif file_type == 'yaml':
222
+ content = yaml.safe_load(uploaded_file)
223
+ return yaml.dump(content), "yaml"
224
+
225
+ else: # Default text handling
226
+ return uploaded_file.getvalue().decode(), "txt"
227
+
228
+ except Exception as e:
229
+ st.error(f"🚨 Oops! Error reading {uploaded_file.name}: {str(e)}")
230
+ return None, None
231
+
232
+ def save_file_content(content, filename, file_type):
233
+ """Smart file saver with enhanced markdown handling"""
234
+ try:
235
+ if file_type == "md":
236
+ with open(filename, 'w') as f:
237
+ f.write(content)
238
+ st.session_state.rendered_content[filename] = content
239
+ add_to_history(filename, content, "saved")
240
+
241
+ elif file_type in ["csv", "xlsx"]:
242
+ df = pd.read_csv(StringIO(content)) if file_type == "csv" else pd.read_excel(StringIO(content))
243
+ if file_type == "csv":
244
+ df.to_csv(filename, index=False)
245
+ else:
246
+ df.to_excel(filename, index=False)
247
+
248
+ elif file_type == "json":
249
+ with open(filename, 'w') as f:
250
+ json.dump(json.loads(content), f, indent=2)
251
+
252
+ elif file_type == "yaml":
253
+ with open(filename, 'w') as f:
254
+ yaml.dump(yaml.safe_load(content), f)
255
+
256
+ else: # Default text handling
257
+ with open(filename, 'w') as f:
258
+ f.write(content)
259
+
260
+ return True
261
+ except Exception as e:
262
+ st.error(f"🚨 Error saving {filename}: {str(e)}")
263
+ return False
264
+
265
+ def main():
266
+ st.title("πŸ“šβœ¨ Super Smart File Handler with Markdown Magic! βœ¨πŸ“š")
267
+
268
+ # Show markdown history in sidebar
269
+ show_sidebar_history()
270
+
271
+ uploaded_file = st.file_uploader(
272
+ "πŸ“€ Upload your file!",
273
+ type=list(FILE_TYPES.keys()),
274
+ help="Supports: " + ", ".join([f"{v} (.{k})" for k, v in FILE_TYPES.items()])
275
+ )
276
+
277
+ # Show file history at the top
278
+ show_file_history()
279
+
280
+ if uploaded_file:
281
+ content, file_type = read_file_content(uploaded_file)
282
+ if content is not None:
283
+ st.session_state.file_data[uploaded_file.name] = content
284
+ st.session_state.file_types[uploaded_file.name] = file_type
285
+ st.success(f"πŸŽ‰ Loaded {FILE_TYPES.get(file_type, 'πŸ“„')} file: {uploaded_file.name}")
286
+
287
+ if st.session_state.file_data:
288
+ st.subheader("πŸ“‚ Your Files")
289
+ for filename, content in st.session_state.file_data.items():
290
+ file_type = st.session_state.file_types[filename]
291
+ with st.expander(f"{FILE_TYPES.get(file_type, 'πŸ“„')} {filename}"):
292
+ if file_type == "md":
293
+ content = create_markdown_tabs(content, filename)
294
+ else:
295
+ edited_content = st.text_area(
296
+ "Content",
297
+ content,
298
+ height=300,
299
+ key=f"edit_{filename}"
300
+ )
301
+ if edited_content != content:
302
+ st.session_state.file_data[filename] = edited_content
303
+ content = edited_content
304
+
305
+ if st.button(f"πŸ’Ύ Save {filename}"):
306
+ if save_file_content(content, filename, file_type):
307
+ st.success(f"✨ Saved {filename} successfully!")
308
+
309
+ if __name__ == "__main__":
310
+ main()