shikharyashmaurya commited on
Commit
aa7ea9c
1 Parent(s): 72fa6ca

Upload revision-app-streamlit3.py

Browse files
Files changed (1) hide show
  1. revision-app-streamlit3.py +226 -0
revision-app-streamlit3.py ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import json
3
+ import os
4
+ import networkx as nx
5
+ import matplotlib.pyplot as plt
6
+ import textwrap
7
+ from io import BytesIO
8
+
9
+ FILENAME = "nested_dictionary.json"
10
+
11
+ class RevisionApp:
12
+ def __init__(self):
13
+ self.load_data()
14
+ self.create_ui()
15
+
16
+ def load_data(self):
17
+ if 'data' not in st.session_state:
18
+ if os.path.exists(FILENAME):
19
+ with open(FILENAME, 'r') as file:
20
+ st.session_state.data = json.load(file)
21
+ else:
22
+ st.session_state.data = {}
23
+
24
+ def save_data(self):
25
+ with open(FILENAME, 'w') as file:
26
+ json.dump(st.session_state.data, file, indent=2)
27
+
28
+ def create_ui(self):
29
+ st.title("Concept Revision App")
30
+ st.write('''Demo app don't have functionality like unlimited tree view expand, touch,expand,export map.
31
+ No session history - after session your input information will be lost
32
+ .For full functionality see -
33
+ https://github.com/shikharyashmaurya/Revision-App''')
34
+
35
+ # Sidebar for navigation
36
+ page = st.sidebar.selectbox("Choose a page", ["Tree View", "Mind Map", "Search"])
37
+
38
+ if page == "Tree View":
39
+ self.show_tree_view()
40
+ elif page == "Mind Map":
41
+ self.show_mind_map()
42
+ elif page == "Search":
43
+ self.show_search()
44
+
45
+ def show_tree_view(self):
46
+ st.header("Tree View")
47
+
48
+ # Input for new concept
49
+ new_key = st.text_input("Enter a new concept:")
50
+ if st.button("Add Concept"):
51
+ if new_key and new_key not in st.session_state.data:
52
+ st.session_state.data[new_key] = {'next': [], 'text': []}
53
+ self.save_data()
54
+ st.success(f"Added new concept: {new_key}")
55
+ st.experimental_rerun()
56
+
57
+ # Display concepts
58
+ selected_concept = st.selectbox("Select a concept to view details:",
59
+ options=[""] + list(st.session_state.data.keys()))
60
+
61
+ if selected_concept:
62
+ self.show_concept_details(selected_concept)
63
+
64
+ def show_concept_details(self, key):
65
+ st.subheader(f"Concept: {key}")
66
+
67
+ # Display related concepts
68
+ st.write("Related Concepts:")
69
+ for next_item in st.session_state.data[key]['next']:
70
+ if st.button(f"Go to {next_item}", key=f"goto_{next_item}"):
71
+ self.show_concept_details(next_item)
72
+ return
73
+
74
+ # Add related concept
75
+ new_related = st.text_input(f"Add related concept to {key}:", key=f"related_{key}")
76
+ if st.button(f"Add related to {key}", key=f"add_related_{key}"):
77
+ if new_related and new_related not in st.session_state.data[key]['next']:
78
+ if new_related not in st.session_state.data:
79
+ st.session_state.data[new_related] = {'next': [], 'text': []}
80
+ st.session_state.data[key]['next'].append(new_related)
81
+ self.save_data()
82
+ st.success(f"Added {new_related} as related to {key}")
83
+ st.experimental_rerun()
84
+
85
+ # Display information
86
+ st.write("Information:")
87
+ for i, text_item in enumerate(st.session_state.data[key]['text']):
88
+ st.text_area(f"Info {i+1}", value=text_item, key=f"info_{key}_{i}", height=100, disabled=True)
89
+
90
+ # Add information
91
+ new_info = st.text_area(f"Add information to {key}:", key=f"new_info_{key}")
92
+ if st.button(f"Add info to {key}", key=f"add_info_{key}"):
93
+ if new_info:
94
+ st.session_state.data[key]['text'].append(new_info)
95
+ self.save_data()
96
+ st.success(f"Added new information to {key}")
97
+ st.experimental_rerun()
98
+
99
+ def show_mind_map(self):
100
+ st.header("Mind Map")
101
+
102
+ G = nx.Graph()
103
+ for key, value in st.session_state.data.items():
104
+ G.add_node(key)
105
+ for next_item in value['next']:
106
+ if next_item in st.session_state.data:
107
+ G.add_edge(key, next_item)
108
+
109
+ pos = self.custom_tree_layout(G)
110
+
111
+ plt.figure(figsize=(12, 8))
112
+ nx.draw(G, pos, with_labels=False, node_color='lightblue', node_size=3000, alpha=0.8)
113
+
114
+ for node, (x, y) in pos.items():
115
+ lines = textwrap.wrap(node, width=10)
116
+ plt.annotate('\n'.join(lines), (x, y), horizontalalignment='center', verticalalignment='center')
117
+
118
+ plt.axis('off')
119
+
120
+ # Save plot to a buffer
121
+ buf = BytesIO()
122
+ plt.savefig(buf, format="png")
123
+ buf.seek(0)
124
+
125
+ # Display the image
126
+ st.image(buf, caption='Mind Map', use_column_width=True)
127
+
128
+ def show_search(self):
129
+ st.header("Search")
130
+
131
+ query = st.text_input("Enter search term:")
132
+ if st.button("Search"):
133
+ results = self.search_data(query)
134
+ if results:
135
+ for key in results:
136
+ with st.expander(f"Concept: {key}"):
137
+ st.write("Related Concepts:")
138
+ for related in st.session_state.data[key]['next']:
139
+ st.write(f"- {related}")
140
+ st.write("Information:")
141
+ for info in st.session_state.data[key]['text']:
142
+ st.write(f"- {info}")
143
+ else:
144
+ st.write("No results found.")
145
+
146
+ def search_data(self, query):
147
+ query = query.lower()
148
+ results = set()
149
+ for key, value in st.session_state.data.items():
150
+ if query in key.lower():
151
+ results.add(key)
152
+ for next_item in value['next']:
153
+ if query in next_item.lower():
154
+ results.add(key)
155
+ for text_item in value['text']:
156
+ if query in text_item.lower():
157
+ results.add(key)
158
+ return list(results)
159
+
160
+ # def custom_tree_layout(self, G):
161
+ # # ... (custom_tree_layout method remains unchanged)
162
+ # pass
163
+
164
+ def custom_tree_layout(self, G):
165
+ if not G.nodes():
166
+ return {}
167
+
168
+ def bfs_tree(root):
169
+ tree = nx.bfs_tree(G, root)
170
+ return tree
171
+
172
+ def assign_positions(tree, root):
173
+ pos = {}
174
+ level_width = {}
175
+ max_depth = 0
176
+
177
+ def dfs(node, depth, order):
178
+ nonlocal max_depth
179
+ max_depth = max(max_depth, depth)
180
+ if depth not in level_width:
181
+ level_width[depth] = 0
182
+ level_width[depth] += 1
183
+ children = list(tree.successors(node))
184
+ if not children:
185
+ pos[node] = (order, -depth)
186
+ return order + 1
187
+
188
+ start = order
189
+ for child in children:
190
+ order = dfs(child, depth + 1, order)
191
+ pos[node] = (start + (order - start - 1) / 2, -depth)
192
+ return order
193
+
194
+ dfs(root, 0, 0)
195
+
196
+ # Normalize positions
197
+ max_width = max(level_width.values()) if level_width else 1
198
+ for node in pos:
199
+ x, y = pos[node]
200
+ pos[node] = (x / max_width, y / max_depth if max_depth != 0 else 0)
201
+
202
+ return pos
203
+
204
+ # Handle disconnected components
205
+ components = list(nx.connected_components(G))
206
+ if not components:
207
+ return {}
208
+
209
+ pos = {}
210
+ y_offset = 0
211
+ for component in components:
212
+ subgraph = G.subgraph(component)
213
+ root = max(subgraph.nodes(), key=lambda n: subgraph.degree(n))
214
+ tree = bfs_tree(root)
215
+ component_pos = assign_positions(tree, root)
216
+
217
+ # Adjust y-positions for each component
218
+ for node, (x, y) in component_pos.items():
219
+ pos[node] = (x, y + y_offset)
220
+
221
+ y_offset -= 1.5 # Increase vertical separation between components
222
+
223
+ return pos
224
+
225
+ if __name__ == "__main__":
226
+ app = RevisionApp()