Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -5,10 +5,10 @@ import os
|
|
5 |
import base64
|
6 |
from io import StringIO
|
7 |
|
8 |
-
#
|
9 |
os.environ["PATH"] += os.pathsep + '/usr/bin/graphviz'
|
10 |
|
11 |
-
# Enhanced
|
12 |
st.markdown("""
|
13 |
<style>
|
14 |
.stApp {
|
@@ -26,9 +26,6 @@ st.markdown("""
|
|
26 |
border: none;
|
27 |
font-weight: 600;
|
28 |
transition: transform 0.3s;
|
29 |
-
}
|
30 |
-
.stButton>button:hover {
|
31 |
-
transform: scale(1.05);
|
32 |
box-shadow: 0 4px 12px rgba(76,175,80,0.3);
|
33 |
}
|
34 |
.stDownloadButton>button {
|
@@ -38,26 +35,41 @@ st.markdown("""
|
|
38 |
border-radius: 10px;
|
39 |
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
40 |
}
|
|
|
|
|
|
|
41 |
</style>
|
42 |
""", unsafe_allow_html=True)
|
43 |
|
44 |
def create_org_chart(df, title):
|
45 |
-
"""Create professional org chart with
|
46 |
dot = Digraph(comment=title)
|
47 |
dot.attr(rankdir='TB', labelloc='t', label=title,
|
48 |
fontsize='24', fontname='Arial', margin='0.5',
|
49 |
-
splines='ortho')
|
50 |
|
51 |
-
# Node styling
|
52 |
-
dot.attr('node',
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
|
58 |
-
# Edge styling for
|
59 |
-
dot.attr('edge',
|
60 |
-
|
|
|
|
|
|
|
61 |
|
62 |
# Process relationships
|
63 |
added_nodes = set()
|
@@ -66,65 +78,77 @@ def create_org_chart(df, title):
|
|
66 |
child = row['Child'].strip()
|
67 |
if parent and child:
|
68 |
if parent not in added_nodes:
|
69 |
-
dot.node(parent)
|
70 |
added_nodes.add(parent)
|
71 |
if child not in added_nodes:
|
72 |
-
dot.node(child)
|
73 |
added_nodes.add(child)
|
74 |
dot.edge(parent, child)
|
75 |
|
76 |
return dot
|
77 |
|
78 |
def main():
|
79 |
-
st.title("π’
|
80 |
|
81 |
with st.sidebar:
|
82 |
st.header("βοΈ Configuration")
|
83 |
chart_title = st.text_input("Chart Title", "Company Structure")
|
84 |
st.markdown("---")
|
85 |
-
st.markdown("### π CSV
|
86 |
-
st.write("1. Download template\n2. Edit in Excel/Sheets\n3. Upload your file")
|
87 |
|
88 |
-
# CSV template download
|
89 |
template = "Parent,Child\nCEO,CTO\nCEO,CFO\nCTO,Engineering Manager"
|
90 |
b64 = base64.b64encode(template.encode()).decode()
|
91 |
-
href = f'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
st.markdown(href, unsafe_allow_html=True)
|
93 |
|
94 |
-
uploaded_file = st.file_uploader("π€ Upload CSV File", type=["csv"]
|
95 |
-
help="Upload your organizational hierarchy CSV file")
|
96 |
|
97 |
if uploaded_file:
|
98 |
try:
|
99 |
df = pd.read_csv(uploaded_file)
|
100 |
if {'Parent', 'Child'}.issubset(df.columns):
|
101 |
-
with st.spinner("π
|
102 |
chart = create_org_chart(df, chart_title)
|
103 |
|
104 |
-
#
|
105 |
col1, col2 = st.columns([3, 1])
|
|
|
106 |
with col1:
|
107 |
st.graphviz_chart(chart, use_container_width=True)
|
108 |
|
109 |
-
# PDF Generation
|
110 |
with col2:
|
111 |
st.markdown("### π€ Export Options")
|
|
|
|
|
112 |
pdf_bytes = chart.pipe(format='pdf')
|
113 |
st.download_button(
|
114 |
label="π Download PDF",
|
115 |
data=pdf_bytes,
|
116 |
file_name=f"{chart_title.replace(' ', '_')}.pdf",
|
117 |
mime="application/pdf",
|
118 |
-
help="Download high-quality PDF version"
|
119 |
)
|
120 |
|
|
|
121 |
png_bytes = chart.pipe(format='png')
|
122 |
st.download_button(
|
123 |
label="πΌοΈ Download PNG",
|
124 |
data=png_bytes,
|
125 |
file_name=f"{chart_title.replace(' ', '_')}.png",
|
126 |
mime="image/png",
|
127 |
-
help="Download image version"
|
128 |
)
|
129 |
else:
|
130 |
st.error("β CSV must contain 'Parent' and 'Child' columns")
|
|
|
5 |
import base64
|
6 |
from io import StringIO
|
7 |
|
8 |
+
# Configure system path for Hugging Face Spaces
|
9 |
os.environ["PATH"] += os.pathsep + '/usr/bin/graphviz'
|
10 |
|
11 |
+
# Enhanced 3D styling CSS
|
12 |
st.markdown("""
|
13 |
<style>
|
14 |
.stApp {
|
|
|
26 |
border: none;
|
27 |
font-weight: 600;
|
28 |
transition: transform 0.3s;
|
|
|
|
|
|
|
29 |
box-shadow: 0 4px 12px rgba(76,175,80,0.3);
|
30 |
}
|
31 |
.stDownloadButton>button {
|
|
|
35 |
border-radius: 10px;
|
36 |
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
37 |
}
|
38 |
+
.node rect {
|
39 |
+
filter: drop-shadow(2px 2px 2px rgba(0,0,0,0.2));
|
40 |
+
}
|
41 |
</style>
|
42 |
""", unsafe_allow_html=True)
|
43 |
|
44 |
def create_org_chart(df, title):
|
45 |
+
"""Create professional org chart with 3D effects"""
|
46 |
dot = Digraph(comment=title)
|
47 |
dot.attr(rankdir='TB', labelloc='t', label=title,
|
48 |
fontsize='24', fontname='Arial', margin='0.5',
|
49 |
+
splines='ortho', bgcolor='transparent')
|
50 |
|
51 |
+
# 3D Node styling with gradient and shadow
|
52 |
+
dot.attr('node',
|
53 |
+
shape='box',
|
54 |
+
style='filled,rounded',
|
55 |
+
fillcolor='linear-gradient(45deg, #45a049 0%, #4CAF50 100%)',
|
56 |
+
gradientangle='270',
|
57 |
+
fontname='Arial',
|
58 |
+
fontcolor='white',
|
59 |
+
margin='0.4',
|
60 |
+
width='2',
|
61 |
+
height='0.9',
|
62 |
+
fixedsize='false',
|
63 |
+
fontsize='14',
|
64 |
+
penwidth='0',
|
65 |
+
color='#2c3e50')
|
66 |
|
67 |
+
# Edge styling for 3D effect
|
68 |
+
dot.attr('edge',
|
69 |
+
color='#666666',
|
70 |
+
arrowsize='0.8',
|
71 |
+
penwidth='1.5',
|
72 |
+
dir='forward')
|
73 |
|
74 |
# Process relationships
|
75 |
added_nodes = set()
|
|
|
78 |
child = row['Child'].strip()
|
79 |
if parent and child:
|
80 |
if parent not in added_nodes:
|
81 |
+
dot.node(parent, _attributes={'label': f'<<B>{parent}</B>>'})
|
82 |
added_nodes.add(parent)
|
83 |
if child not in added_nodes:
|
84 |
+
dot.node(child, _attributes={'label': f'<<B>{child}</B>>'})
|
85 |
added_nodes.add(child)
|
86 |
dot.edge(parent, child)
|
87 |
|
88 |
return dot
|
89 |
|
90 |
def main():
|
91 |
+
st.title("π’ 3D Organization Chart Generator")
|
92 |
|
93 |
with st.sidebar:
|
94 |
st.header("βοΈ Configuration")
|
95 |
chart_title = st.text_input("Chart Title", "Company Structure")
|
96 |
st.markdown("---")
|
97 |
+
st.markdown("### π CSV Template")
|
|
|
98 |
|
99 |
+
# CSV template download with 3D styling
|
100 |
template = "Parent,Child\nCEO,CTO\nCEO,CFO\nCTO,Engineering Manager"
|
101 |
b64 = base64.b64encode(template.encode()).decode()
|
102 |
+
href = f'''
|
103 |
+
<a href="data:file/csv;base64,{b64}" download="template.csv"
|
104 |
+
style="display: inline-block;
|
105 |
+
padding: 12px 24px;
|
106 |
+
border-radius: 8px;
|
107 |
+
background: linear-gradient(135deg, #4CAF50, #45a049);
|
108 |
+
color: white;
|
109 |
+
text-decoration: none;
|
110 |
+
font-weight: bold;
|
111 |
+
box-shadow: 0 4px 12px rgba(76,175,80,0.3);
|
112 |
+
transition: transform 0.3s;">
|
113 |
+
π₯ Download Template
|
114 |
+
</a>
|
115 |
+
'''
|
116 |
st.markdown(href, unsafe_allow_html=True)
|
117 |
|
118 |
+
uploaded_file = st.file_uploader("π€ Upload CSV File", type=["csv"])
|
|
|
119 |
|
120 |
if uploaded_file:
|
121 |
try:
|
122 |
df = pd.read_csv(uploaded_file)
|
123 |
if {'Parent', 'Child'}.issubset(df.columns):
|
124 |
+
with st.spinner("π Generating 3D visualization..."):
|
125 |
chart = create_org_chart(df, chart_title)
|
126 |
|
127 |
+
# Two-column layout
|
128 |
col1, col2 = st.columns([3, 1])
|
129 |
+
|
130 |
with col1:
|
131 |
st.graphviz_chart(chart, use_container_width=True)
|
132 |
|
|
|
133 |
with col2:
|
134 |
st.markdown("### π€ Export Options")
|
135 |
+
|
136 |
+
# PDF Export
|
137 |
pdf_bytes = chart.pipe(format='pdf')
|
138 |
st.download_button(
|
139 |
label="π Download PDF",
|
140 |
data=pdf_bytes,
|
141 |
file_name=f"{chart_title.replace(' ', '_')}.pdf",
|
142 |
mime="application/pdf",
|
|
|
143 |
)
|
144 |
|
145 |
+
# PNG Export
|
146 |
png_bytes = chart.pipe(format='png')
|
147 |
st.download_button(
|
148 |
label="πΌοΈ Download PNG",
|
149 |
data=png_bytes,
|
150 |
file_name=f"{chart_title.replace(' ', '_')}.png",
|
151 |
mime="image/png",
|
|
|
152 |
)
|
153 |
else:
|
154 |
st.error("β CSV must contain 'Parent' and 'Child' columns")
|