Herc commited on
Commit
72042de
·
verified ·
1 Parent(s): f80e0c4

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -0
app.py ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import random
4
+ from datetime import datetime, timedelta
5
+
6
+ st.set_page_config(layout="wide")
7
+
8
+
9
+ # Helper function to generate a random date within the last year
10
+ def random_date():
11
+ start_date = datetime.now() - timedelta(days=365)
12
+ random_days = random.randint(0, 365)
13
+ return (start_date + timedelta(days=random_days)).strftime("%Y-%m-%d")
14
+
15
+ # Function to load and cache the product catalog
16
+ @st.cache_data
17
+ def load_catalog():
18
+ # Generate approval attributes
19
+ cyber_approved = [random.choice([True, False]) for _ in range(50)]
20
+ accessibility_approved = [random.choice([True, False]) for _ in range(50)]
21
+ privacy_approved = [random.choice([True, False]) for _ in range(50)]
22
+
23
+ review_statuses = []
24
+ not_approved_reasons = []
25
+ for cyber, accessibility, privacy in zip(cyber_approved, accessibility_approved, privacy_approved):
26
+ if cyber and accessibility and privacy: # All approvals are True
27
+ review_statuses.append("Approved")
28
+ not_approved_reasons.append(None)
29
+ elif not cyber and not accessibility and not privacy: # All approvals are False
30
+ review_statuses.append("Not Approved")
31
+ not_approved_reasons.append(random.choice(["Security Concern", "Licensing Issue", "Privacy Issue", "Compliance Requirement"]))
32
+ else: # Mixed approvals
33
+ review_statuses.append("Under Review")
34
+ not_approved_reasons.append(None)
35
+
36
+ products = {
37
+ "Product Name": [
38
+ "Notepad++", "WinRAR", "7-Zip", "CCleaner", "TeamViewer",
39
+ "FileZilla", "PuTTY", "WinSCP", "Everything", "Greenshot",
40
+ "Visual Studio Code", "JetBrains IntelliJ IDEA", "Sublime Text", "Atom", "Eclipse",
41
+ "PyCharm", "NetBeans", "Xcode", "Android Studio", "GitLab",
42
+ "Norton Antivirus", "McAfee Total Protection", "Kaspersky Internet Security", "Bitdefender Antivirus Plus", "Avast Free Antivirus",
43
+ "Sophos Home", "Trend Micro Antivirus+", "ESET NOD32 Antivirus", "F-Secure SAFE", "Malwarebytes",
44
+ "Microsoft Office 365", "Google Workspace", "Slack", "Trello", "Asana",
45
+ "Zoom", "Evernote", "Notion", "Dropbox", "Adobe Acrobat Reader",
46
+ "Adobe Photoshop", "Adobe Illustrator", "Adobe Premiere Pro", "Final Cut Pro", "Sketch",
47
+ "Blender", "Autodesk Maya", "CorelDRAW", "GIMP", "Inkscape"
48
+ ],
49
+ "Category": [
50
+ "Utility Tools", "Utility Tools", "Utility Tools", "Utility Tools", "Utility Tools",
51
+ "Utility Tools", "Utility Tools", "Utility Tools", "Utility Tools", "Utility Tools",
52
+ "Development Tools", "Development Tools", "Development Tools", "Development Tools", "Development Tools",
53
+ "Development Tools", "Development Tools", "Development Tools", "Development Tools", "Development Tools",
54
+ "Security Software", "Security Software", "Security Software", "Security Software", "Security Software",
55
+ "Security Software", "Security Software", "Security Software", "Security Software", "Security Software",
56
+ "Productivity Software", "Productivity Software", "Productivity Software", "Productivity Software", "Productivity Software",
57
+ "Productivity Software", "Productivity Software", "Productivity Software", "Productivity Software", "Productivity Software",
58
+ "Creative Software", "Creative Software", "Creative Software", "Creative Software", "Creative Software",
59
+ "Creative Software", "Creative Software", "Creative Software", "Creative Software", "Creative Software"
60
+ ],
61
+ "Cyber Approved": cyber_approved,
62
+ "Accessibility Approved": accessibility_approved,
63
+ "Privacy Approved": privacy_approved,
64
+ "Review Date": [random_date() for _ in range(50)],
65
+ "Review Status": review_statuses,
66
+ "Not Approved Reason": not_approved_reasons
67
+ }
68
+ return pd.DataFrame(products)
69
+
70
+ # Function to filter the catalog based on multiple attributes with AND logic
71
+ @st.cache_data
72
+ def filter_catalog(catalog, search_query=None, selected_category=None, cyber_approved=None, accessibility_approved=None, privacy_approved=None,review_status=None):
73
+ filtered = catalog
74
+ if search_query:
75
+ filtered = filtered[filtered.apply(lambda row: search_query.lower() in str(row).lower(), axis=1)]
76
+ if selected_category and selected_category != 'All':
77
+ filtered = filtered[filtered["Category"] == selected_category]
78
+ if cyber_approved:
79
+ filtered = filtered[filtered["Cyber Approved"] == True]
80
+ if accessibility_approved:
81
+ filtered = filtered[filtered["Accessibility Approved"] == True]
82
+ if privacy_approved:
83
+ filtered = filtered[filtered["Privacy Approved"] == True]
84
+ if review_status and review_status != 'All':
85
+ filtered = filtered[filtered["Review Status"] == review_status]
86
+ return filtered
87
+
88
+ catalog = load_catalog()
89
+
90
+
91
+ st.markdown("""
92
+ <style>
93
+ .custom-header {
94
+ font-size: 24px;
95
+ font-weight: bold;
96
+ color: #4f8bf9;
97
+ margin-bottom: 10px;
98
+ }
99
+ .custom-text {
100
+ font-size: 16px;
101
+ margin-bottom: 20px;
102
+ }
103
+ .custom-button {
104
+ margin: 5px;
105
+ }
106
+ .stButton>button {
107
+ border: 2px solid #4f8bf9;
108
+ border-radius: 20px;
109
+ color: #4f8bf9;
110
+ }
111
+ .status-true {
112
+ color: green;
113
+ }
114
+ .stDataFrame {
115
+ font-size: 14px;
116
+ }
117
+ </style>
118
+ """, unsafe_allow_html=True)
119
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+ # Streamlit app layout
127
+ st.markdown('<p class="custom-header">Enterprise Software Product Catalog</p>', unsafe_allow_html=True)
128
+ st.markdown('<p class="custom-text">This is the source of truth for app approval statuses within the enterprise.</p>', unsafe_allow_html=True)
129
+
130
+
131
+
132
+ # Sidebar for Advanced Search and Filtering
133
+ with st.sidebar:
134
+ st.markdown('<p class="custom-header">Advanced Search Options</p>', unsafe_allow_html=True)
135
+ search_query = st.text_input("Search by Any Attribute", key='search_query')
136
+ selected_category = st.selectbox("Select Category", ['All'] + list(catalog["Category"].unique()), key='search_category')
137
+ cyber_approved = st.checkbox("Cyber Approved", key='cyber_approved')
138
+ accessibility_approved = st.checkbox("Accessibility Approved", key='accessibility_approved')
139
+ privacy_approved = st.checkbox("Privacy Approved", key='privacy_approved')
140
+ review_status_options = ['All', 'Approved', 'Under Review', 'Not Approved']
141
+ review_status = st.selectbox("Select Review Status", options=review_status_options, key='review_status')
142
+
143
+
144
+ # Apply the enhanced filter based on user input
145
+ filtered_catalog = filter_catalog(catalog, search_query, selected_category, cyber_approved, accessibility_approved, privacy_approved, review_status)
146
+
147
+
148
+
149
+ # Display the filtered product catalog
150
+ st.markdown('<p class="custom-header">Product Catalog</p>', unsafe_allow_html=True)
151
+ st.dataframe(filtered_catalog.style.applymap(lambda x: "background-color: #ffffff"))
152
+
153
+ for index, row in filtered_catalog.iterrows():
154
+ with st.expander(f"{row['Product Name']}"):
155
+ st.markdown(f"""
156
+ <div>
157
+ <p><b>Category:</b> {row['Category']}</p>
158
+ <p><b>Cyber Approved:</b> <span class='{"status-true" if row["Cyber Approved"] else ""}'>{'Yes' if row['Cyber Approved'] else 'No'}</span></p>
159
+ <p><b>Accessibility Approved:</b> <span class='{"status-true" if row["Accessibility Approved"] else ""}'>{'Yes' if row['Accessibility Approved'] else 'No'}</span></p>
160
+ <p><b>Privacy Approved:</b> <span class='{"status-true" if row["Privacy Approved"] else ""}'>{'Yes' if row['Privacy Approved'] else 'No'}</span></p>
161
+ <p><b>Review Date:</b> {row['Review Date']}</p>
162
+ <p><b>Review Status:</b> {row['Review Status']}</p>
163
+ {'<p><b>Not Approved Reason:</b> '+row['Not Approved Reason']+'</p>' if row['Review Status'] == 'Not Approved' else ''}
164
+ </div>
165
+ """, unsafe_allow_html=True)
166
+