arif670 commited on
Commit
1cf083d
·
verified ·
1 Parent(s): e1e46ef

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -167
app.py CHANGED
@@ -1,185 +1,138 @@
1
  import streamlit as st
2
  import pandas as pd
3
- import plotly.graph_objects as go
4
- from io import StringIO
5
  import base64
 
6
 
7
  # Custom CSS for professional UI
8
  st.markdown("""
9
  <style>
10
  /* Main container */
11
  .stApp {
12
- background-color: #f5f5f5;
13
- font-family: 'Arial', sans-serif;
 
 
 
 
 
 
 
14
  }
15
 
16
  /* Sidebar */
17
  .stSidebar {
18
  background-color: #2c3e50;
19
- color: white;
20
- padding: 20px;
21
  }
22
 
23
  /* Buttons */
24
  .stButton>button {
25
  background-color: #4CAF50;
26
  color: white;
27
- border-radius: 8px;
28
- padding: 10px 24px;
29
  border: none;
30
  font-size: 16px;
31
- transition: background-color 0.3s;
32
  }
33
  .stButton>button:hover {
34
  background-color: #45a049;
 
35
  }
36
 
37
  /* File uploader */
38
  .stFileUploader>div>div>div>div {
39
- background-color: #f0f2f6;
40
- border-radius: 8px;
41
- padding: 12px;
 
 
 
 
 
 
 
 
42
  }
43
 
44
  /* Tabs */
45
  .stTabs [data-baseweb="tab-list"] {
46
- background-color: #2c3e50;
47
- border-radius: 8px;
48
  }
49
  .stTabs [data-baseweb="tab"] {
50
- color: white;
51
- padding: 10px 20px;
 
 
52
  }
53
  .stTabs [aria-selected="true"] {
54
  background-color: #4CAF50;
55
- border-radius: 8px;
56
- }
57
-
58
- /* Organization chart container */
59
- .org-chart-container {
60
- background-color: white;
61
- border-radius: 12px;
62
- padding: 20px;
63
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
64
  }
65
  </style>
66
  """, unsafe_allow_html=True)
67
 
68
- # Function to create organization chart
69
  def create_org_chart(df, title):
70
- positions = {}
71
- edge_x = []
72
- edge_y = []
73
- node_x = []
74
- node_y = []
75
- node_text = []
76
-
77
- # Create hierarchical positions
78
- levels = {}
79
- for _, row in df.iterrows():
80
- parent = row['Parent']
81
- child = row['Child']
82
- if parent not in levels:
83
- levels[parent] = 0
84
- if child not in levels:
85
- levels[child] = levels[parent] + 1
86
-
87
- # Assign coordinates
88
- max_level = max(levels.values())
89
- level_positions = {level: [] for level in range(max_level + 1)}
90
-
91
- for node, level in levels.items():
92
- level_positions[level].append(node)
93
-
94
- for level, nodes in level_positions.items():
95
- y_pos = max_level - level
96
- x_positions = [i - (len(nodes)-1)/2 for i in range(len(nodes))]
97
- for node, x_pos in zip(nodes, x_positions):
98
- positions[node] = (x_pos, y_pos)
99
-
100
- # Create edges
101
  for _, row in df.iterrows():
102
- parent = row['Parent']
103
- child = row['Child']
104
- x0, y0 = positions[parent]
105
- x1, y1 = positions[child]
106
- edge_x.extend([x0, x1, None])
107
- edge_y.extend([y0, y1, None])
108
-
109
- # Create nodes
110
- for node, (x, y) in positions.items():
111
- node_x.append(x)
112
- node_y.append(y)
113
- node_text.append(node)
114
-
115
- # Create 3D effect with rounded rectangles
116
- edge_trace = go.Scatter(
117
- x=edge_x, y=edge_y,
118
- line=dict(width=2, color='#888'),
119
- hoverinfo='none',
120
- mode='lines'
121
- )
122
-
123
- node_trace = go.Scatter(
124
- x=node_x, y=node_y,
125
- mode='markers+text',
126
- text=node_text,
127
- textposition="middle center",
128
- marker=dict(
129
- symbol='square',
130
- size=[120] * len(node_x), # Scalable size
131
- color='#4CAF50',
132
- line=dict(width=2, color='DarkSlateGrey'),
133
- opacity=0.8
134
- ),
135
- hoverinfo='text',
136
- textfont=dict(size=14, color='white'),
137
- texttemplate='<b>%{text}</b>', # Bold and wrapped text
138
- )
139
-
140
- fig = go.Figure(data=[edge_trace, node_trace],
141
- layout=go.Layout(
142
- title=f'<b>{title}</b><br>',
143
- titlefont_size=20,
144
- showlegend=False,
145
- hovermode='closest',
146
- margin=dict(b=20, l=5, r=5, t=40),
147
- xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
148
- yaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
149
- plot_bgcolor='white',
150
- paper_bgcolor='white'
151
- )
152
- )
153
-
154
- return fig
155
 
156
- # Function to download CSV template
157
  def download_csv_template():
 
158
  csv_template = "Parent,Child\nCEO,CTO\nCEO,CFO\nCTO,Engineering Manager\nCFO,Accounting Manager"
159
  b64 = base64.b64encode(csv_template.encode()).decode()
160
- href = f'<a href="data:file/csv;base64,{b64}" download="org_chart_template.csv">Download CSV Template</a>'
 
 
161
  st.markdown(href, unsafe_allow_html=True)
162
 
163
- # Main function
164
  def main():
165
- st.title("Professional Organization Chart Generator")
166
-
167
- # Tabs for better organization
168
- tab1, tab2 = st.tabs(["Data Input", "Organization Chart"])
169
 
 
 
 
 
 
 
 
 
170
  with tab1:
171
- st.header("Data Input")
172
- st.markdown("### Upload or Edit Your Organizational Data")
173
-
174
- # Download CSV template
175
- st.markdown("**Step 1:** Download the CSV template to input your data.")
176
  download_csv_template()
177
 
178
- # File upload
179
- st.markdown("**Step 2:** Upload your CSV file or edit the default data below.")
180
- uploaded_file = st.file_uploader("Upload CSV File", type=["csv"])
181
 
182
- # Input data
183
  if uploaded_file:
184
  df = pd.read_csv(uploaded_file)
185
  else:
@@ -190,49 +143,30 @@ CTO,Engineering Manager
190
  CFO,Accounting Manager"""
191
  df = pd.read_csv(StringIO(default_data))
192
 
193
- # Editable data table
194
- st.markdown("**Step 3:** Edit your data below if needed.")
195
- edited_df = st.data_editor(df, num_rows="dynamic")
196
-
197
- # Save edited data
198
- if st.button("Save Data"):
199
- edited_df.to_csv("edited_data.csv", index=False)
200
- st.success("Data saved successfully!")
201
-
202
  with tab2:
203
- st.header("Organization Chart")
204
- st.markdown("### Visualize Your Organizational Structure")
205
-
206
- # Chart title
207
- chart_title = st.text_input("Enter Chart Title", "Organization Chart")
208
-
209
- # Generate chart
210
- if st.button("Generate Organization Chart"):
211
  if not edited_df.empty:
212
- fig = create_org_chart(edited_df, chart_title)
213
- st.plotly_chart(fig, use_container_width=True)
214
-
215
- # PDF download options
216
- st.markdown("### Download Options")
217
- col1, col2 = st.columns(2)
218
- with col1:
219
- orientation = st.selectbox("PDF Orientation", ["Portrait", "Landscape"])
220
- with col2:
221
- paper_size = st.selectbox("Paper Size", ["A4", "Letter", "Legal"])
222
-
223
- # Convert to PDF
224
- if st.button("Download as PDF"):
225
- img_bytes = fig.to_image(format="pdf",
226
- width=800 if orientation == "Portrait" else 1200,
227
- height=1200 if orientation == "Portrait" else 800)
228
- st.download_button(
229
- label="Download PDF",
230
- data=img_bytes,
231
- file_name="org_chart.pdf",
232
- mime="application/pdf"
233
- )
234
  else:
235
- st.warning("Please enter some organizational data first.")
236
 
237
  if __name__ == "__main__":
238
- main()
 
1
  import streamlit as st
2
  import pandas as pd
3
+ from graphviz import Digraph
 
4
  import base64
5
+ from io import StringIO
6
 
7
  # Custom CSS for professional UI
8
  st.markdown("""
9
  <style>
10
  /* Main container */
11
  .stApp {
12
+ background-color: #f9f9f9;
13
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
14
+ }
15
+
16
+ /* Titles */
17
+ h1 {
18
+ color: #2c3e50;
19
+ border-bottom: 3px solid #4CAF50;
20
+ padding-bottom: 10px;
21
  }
22
 
23
  /* Sidebar */
24
  .stSidebar {
25
  background-color: #2c3e50;
26
+ color: white !important;
 
27
  }
28
 
29
  /* Buttons */
30
  .stButton>button {
31
  background-color: #4CAF50;
32
  color: white;
33
+ border-radius: 25px;
34
+ padding: 12px 28px;
35
  border: none;
36
  font-size: 16px;
37
+ transition: all 0.3s;
38
  }
39
  .stButton>button:hover {
40
  background-color: #45a049;
41
+ transform: scale(1.05);
42
  }
43
 
44
  /* File uploader */
45
  .stFileUploader>div>div>div>div {
46
+ background-color: #ffffff;
47
+ border-radius: 10px;
48
+ padding: 15px;
49
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
50
+ }
51
+
52
+ /* Data editor */
53
+ .stDataEditor {
54
+ background-color: white;
55
+ border-radius: 10px;
56
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
57
  }
58
 
59
  /* Tabs */
60
  .stTabs [data-baseweb="tab-list"] {
61
+ gap: 10px;
 
62
  }
63
  .stTabs [data-baseweb="tab"] {
64
+ background-color: #e8f5e9;
65
+ border-radius: 8px;
66
+ padding: 12px 24px;
67
+ transition: all 0.3s;
68
  }
69
  .stTabs [aria-selected="true"] {
70
  background-color: #4CAF50;
71
+ color: white !important;
 
 
 
 
 
 
 
 
72
  }
73
  </style>
74
  """, unsafe_allow_html=True)
75
 
 
76
  def create_org_chart(df, title):
77
+ """Create professional organization chart with Graphviz"""
78
+ dot = Digraph(comment=title)
79
+ dot.attr(rankdir='TB', labelloc='t', label=title, fontsize='24', fontname='Arial')
80
+ dot.attr('node', shape='box', style='filled',
81
+ fillcolor='linear-gradient(#4CAF50, #45a049)', fontname='Arial',
82
+ fontcolor='white', margin='0.3', width='2', height='0.8',
83
+ fixedsize='false', color='#2c3e50', fontsize='14')
84
+ dot.attr('edge', color='#666666', arrowsize='0.8')
85
+
86
+ # Track all nodes and relationships
87
+ nodes = set()
88
+ edges = set()
89
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  for _, row in df.iterrows():
91
+ parent = row['Parent'].strip()
92
+ child = row['Child'].strip()
93
+
94
+ if parent and child:
95
+ nodes.add(parent)
96
+ nodes.add(child)
97
+ edges.add((parent, child))
98
+
99
+ # Add nodes first to maintain order
100
+ for node in nodes:
101
+ dot.node(node, node)
102
+
103
+ # Add edges
104
+ for edge in edges:
105
+ dot.edge(edge[0], edge[1])
106
+
107
+ return dot
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
 
109
  def download_csv_template():
110
+ """Generate CSV template download link"""
111
  csv_template = "Parent,Child\nCEO,CTO\nCEO,CFO\nCTO,Engineering Manager\nCFO,Accounting Manager"
112
  b64 = base64.b64encode(csv_template.encode()).decode()
113
+ href = f'<a href="data:file/csv;base64,{b64}" download="org_chart_template.csv" style="\
114
+ background-color: #4CAF50; color: white; padding: 12px 24px; \
115
+ border-radius: 25px; text-decoration: none;">Download CSV Template</a>'
116
  st.markdown(href, unsafe_allow_html=True)
117
 
 
118
  def main():
119
+ st.title("🏢 Professional Organization Chart Generator")
 
 
 
120
 
121
+ with st.sidebar:
122
+ st.header("Configuration")
123
+ chart_title = st.text_input("Chart Title", "Company Organization Chart")
124
+ orientation = st.selectbox("PDF Orientation", ["Portrait", "Landscape"])
125
+ paper_size = st.select_slider("Paper Size", options=["A3", "A4", "Letter", "Legal"])
126
+
127
+ tab1, tab2 = st.tabs(["📥 Data Input", "📊 Organization Chart"])
128
+
129
  with tab1:
130
+ st.subheader("1. Prepare Your Data")
 
 
 
 
131
  download_csv_template()
132
 
133
+ uploaded_file = st.file_uploader("Upload CSV File", type=["csv"],
134
+ help="Upload your organizational data in CSV format")
 
135
 
 
136
  if uploaded_file:
137
  df = pd.read_csv(uploaded_file)
138
  else:
 
143
  CFO,Accounting Manager"""
144
  df = pd.read_csv(StringIO(default_data))
145
 
146
+ edited_df = st.data_editor(df, num_rows="dynamic", use_container_width=True)
147
+
 
 
 
 
 
 
 
148
  with tab2:
149
+ if st.button("Generate Organization Chart", type="primary"):
 
 
 
 
 
 
 
150
  if not edited_df.empty:
151
+ with st.spinner("Generating professional chart..."):
152
+ try:
153
+ # Create and display chart
154
+ chart = create_org_chart(edited_df, chart_title)
155
+ st.graphviz_chart(chart, use_container_width=True)
156
+
157
+ # PDF Generation
158
+ pdf_bytes = chart.pipe(format='pdf')
159
+ st.download_button(
160
+ label="📥 Download PDF",
161
+ data=pdf_bytes,
162
+ file_name=f"{chart_title.replace(' ', '_')}.pdf",
163
+ mime="application/pdf",
164
+ help=f"Download {orientation} PDF ({paper_size} size)"
165
+ )
166
+ except Exception as e:
167
+ st.error(f"Error generating chart: {str(e)}")
 
 
 
 
 
168
  else:
169
+ st.warning("Please input organizational data first!")
170
 
171
  if __name__ == "__main__":
172
+ main()