Update app.py
Browse files
app.py
CHANGED
@@ -6,7 +6,6 @@ import os
|
|
6 |
import xml.etree.ElementTree as ET
|
7 |
from typing import Dict, List
|
8 |
|
9 |
-
# Function to parse XML and build AGENCIES dictionary
|
10 |
def load_agencies_from_xml() -> Dict:
|
11 |
AGENCIES = {}
|
12 |
xml_files = [f for f in os.listdir('.') if f.endswith('.xml')]
|
@@ -27,20 +26,19 @@ def load_agencies_from_xml() -> Dict:
|
|
27 |
abbr = org.find("nc:OrganizationAbbreviationText", ns).text
|
28 |
fiscal_year = root.find(".//foia:DocumentFiscalYearDate", ns).text if root.find(".//foia:DocumentFiscalYearDate", ns) is not None else "N/A"
|
29 |
|
30 |
-
# Build minimal agency data (can be expanded with more XML data)
|
31 |
AGENCIES[name] = {
|
32 |
"name": name,
|
33 |
"summary": {
|
34 |
"name": name,
|
35 |
"description": f"FOIA data for {name} ({fiscal_year})",
|
36 |
"abbreviation": abbr,
|
37 |
-
"website": f"https://www.{abbr.lower()}.gov"
|
38 |
},
|
39 |
"website": f"https://www.{abbr.lower()}.gov",
|
40 |
-
"emails": [f"foia@{abbr.lower()}.gov"],
|
41 |
-
"address": {"address_lines": [], "street": "", "city": "", "state": "", "zip": ""},
|
42 |
-
"service_center": {"phone": ["N/A"]},
|
43 |
-
"request_form": f"https://www.{abbr.lower()}.gov/foia",
|
44 |
"request_time_stats": {
|
45 |
fiscal_year: {
|
46 |
"simple_median_days": float(root.find(".//foia:ProcessedResponseTimeSection/foia:ProcessedResponseTime/foia:SimpleResponseTime/foia:ResponseTimeMedianDaysValue", ns).text) if root.find(".//foia:ProcessedResponseTimeSection/foia:ProcessedResponseTime/foia:SimpleResponseTime/foia:ResponseTimeMedianDaysValue", ns) is not None else 0
|
@@ -93,12 +91,36 @@ class Agency:
|
|
93 |
def hasRequestForm(self) -> bool:
|
94 |
return bool(self.request_form)
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
def create_search_url_wikipedia(search_query):
|
97 |
base_url = "https://www.wikipedia.org/search-redirect.php?family=wikipedia&language=en&search="
|
98 |
return base_url + search_query.replace(' ', '+').replace('β', '%E2%80%93').replace('&', 'and')
|
99 |
|
100 |
def parse_foia_xml(filename: str) -> Dict:
|
101 |
-
"""Parse FOIA XML file and return key information"""
|
102 |
try:
|
103 |
tree = ET.parse(filename)
|
104 |
root = tree.getroot()
|
@@ -131,9 +153,18 @@ def list_and_display_xml_files():
|
|
131 |
return
|
132 |
|
133 |
for xml_file in xml_files:
|
134 |
-
file_name = xml_file[:-4]
|
135 |
data = parse_foia_xml(xml_file)
|
136 |
with st.expander(f"π {file_name} - {data['name']} ({data['abbr']})"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
st.write(f"π
Fiscal Year: {data['fiscal_year']}")
|
138 |
st.write(f"β³ Pending at Start: {data['pending_start']}")
|
139 |
st.write(f"π₯ Received: {data['received']}")
|
@@ -154,11 +185,16 @@ def search_foia_content(query: str, agency: str = None) -> Dict:
|
|
154 |
return results
|
155 |
|
156 |
def main():
|
157 |
-
# Load agencies from XML files
|
158 |
AGENCIES = load_agencies_from_xml()
|
159 |
|
160 |
st.title("Freedom of Information Act (FOIA) Explorer ππ")
|
161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
st.write("""
|
163 |
The Freedom of Information Act (FOIA) empowers individuals by granting access to previously unreleased information and documents controlled by the United States government. Championing transparency and accountability, FOIA serves as a foundation for democratic engagement and open government initiatives. πβ¨
|
164 |
Below is a list of datasets available under FOIA, alongside guessed Wikipedia URLs for more information. ππ
|
@@ -169,7 +205,6 @@ def main():
|
|
169 |
- [Data.Gov](https://catalog.data.gov/dataset?tags=foia)
|
170 |
""")
|
171 |
|
172 |
-
# FOIA Datasets with Emojis
|
173 |
datasets = [
|
174 |
("Provider Taxonomy", "π©Ί"),
|
175 |
("Consumer Complaint Database", "π"),
|
@@ -185,7 +220,6 @@ def main():
|
|
185 |
for dataset, emoji in datasets:
|
186 |
st.markdown(f"- {emoji} **{dataset}**: [Wikipedia]({create_search_url_wikipedia(dataset)})")
|
187 |
|
188 |
-
# Agency Browser
|
189 |
st.header("Agency Browser")
|
190 |
agency_names = sorted(list(AGENCIES.keys()))
|
191 |
selected_agency = st.selectbox("Select Agency", [""] + agency_names)
|
@@ -193,6 +227,12 @@ def main():
|
|
193 |
if selected_agency:
|
194 |
agency = Agency(AGENCIES[selected_agency])
|
195 |
st.subheader(f"{agency.name} Details")
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
st.write(f"Description: {agency.summary.get('description', 'N/A')}")
|
197 |
st.write(f"Abbreviation: {agency.summary.get('abbreviation', 'N/A')}")
|
198 |
if agency.website:
|
@@ -224,7 +264,6 @@ def main():
|
|
224 |
if "median" in key:
|
225 |
st.write(f"{key.replace('_median_days', '').title()}: {value} days")
|
226 |
|
227 |
-
# FOIA Document Search
|
228 |
st.subheader("Search FOIA Documents")
|
229 |
search_query = st.text_input("Enter search query")
|
230 |
if st.button("Search") and search_query:
|
@@ -234,7 +273,6 @@ def main():
|
|
234 |
for result in results["results"]:
|
235 |
st.write(f"- {result['title']} ({result['date']})")
|
236 |
|
237 |
-
# XML Files Display
|
238 |
st.header("FOIA XML Reports")
|
239 |
list_and_display_xml_files()
|
240 |
|
|
|
6 |
import xml.etree.ElementTree as ET
|
7 |
from typing import Dict, List
|
8 |
|
|
|
9 |
def load_agencies_from_xml() -> Dict:
|
10 |
AGENCIES = {}
|
11 |
xml_files = [f for f in os.listdir('.') if f.endswith('.xml')]
|
|
|
26 |
abbr = org.find("nc:OrganizationAbbreviationText", ns).text
|
27 |
fiscal_year = root.find(".//foia:DocumentFiscalYearDate", ns).text if root.find(".//foia:DocumentFiscalYearDate", ns) is not None else "N/A"
|
28 |
|
|
|
29 |
AGENCIES[name] = {
|
30 |
"name": name,
|
31 |
"summary": {
|
32 |
"name": name,
|
33 |
"description": f"FOIA data for {name} ({fiscal_year})",
|
34 |
"abbreviation": abbr,
|
35 |
+
"website": f"https://www.{abbr.lower()}.gov"
|
36 |
},
|
37 |
"website": f"https://www.{abbr.lower()}.gov",
|
38 |
+
"emails": [f"foia@{abbr.lower()}.gov"],
|
39 |
+
"address": {"address_lines": [], "street": "", "city": "", "state": "", "zip": ""},
|
40 |
+
"service_center": {"phone": ["N/A"]},
|
41 |
+
"request_form": f"https://www.{abbr.lower()}.gov/foia",
|
42 |
"request_time_stats": {
|
43 |
fiscal_year: {
|
44 |
"simple_median_days": float(root.find(".//foia:ProcessedResponseTimeSection/foia:ProcessedResponseTime/foia:SimpleResponseTime/foia:ResponseTimeMedianDaysValue", ns).text) if root.find(".//foia:ProcessedResponseTimeSection/foia:ProcessedResponseTime/foia:SimpleResponseTime/foia:ResponseTimeMedianDaysValue", ns) is not None else 0
|
|
|
91 |
def hasRequestForm(self) -> bool:
|
92 |
return bool(self.request_form)
|
93 |
|
94 |
+
AGENCY_LOGOS = {
|
95 |
+
"CFA": "https://upload.wikimedia.org/wikipedia/en/e/e8/U.S._Commission_of_Fine_Arts_logo.png",
|
96 |
+
"CEQ": "https://upload.wikimedia.org/wikipedia/commons/5/58/CEQ-Seal.png",
|
97 |
+
"DOJ": "https://upload.wikimedia.org/wikipedia/commons/f/f8/Seal_of_the_United_States_Department_of_Justice.svg",
|
98 |
+
"EPA": "https://upload.wikimedia.org/wikipedia/commons/7/78/Environmental_Protection_Agency_logo.svg",
|
99 |
+
"FTC": "https://upload.wikimedia.org/wikipedia/commons/5/5b/US-FederalTradeCommission-Seal.svg",
|
100 |
+
"ABMC": "https://upload.wikimedia.org/wikipedia/commons/2/2f/ABMC_seal.png",
|
101 |
+
"AFRH": "https://upload.wikimedia.org/wikipedia/commons/2/2e/Armed_Forces_Retirement_Home_logo.png",
|
102 |
+
"DHS": "https://upload.wikimedia.org/wikipedia/commons/5/52/Seal_of_the_United_States_Department_of_Homeland_Security.svg",
|
103 |
+
"DOC": "https://upload.wikimedia.org/wikipedia/commons/e/e0/Seal_of_the_United_States_Department_of_Commerce.svg",
|
104 |
+
"DOD": "https://upload.wikimedia.org/wikipedia/commons/e/e0/Seal_of_the_United_States_Department_of_Defense_%282004%29.svg",
|
105 |
+
"DOE": "https://upload.wikimedia.org/wikipedia/commons/e/e0/United_States_Department_of_Energy_Seal.svg",
|
106 |
+
"DOI": "https://upload.wikimedia.org/wikipedia/commons/e/e3/Seal_of_the_United_States_Department_of_the_Interior.svg",
|
107 |
+
"DOL": "https://upload.wikimedia.org/wikipedia/commons/4/47/Seal_of_the_United_States_Department_of_Labor.svg",
|
108 |
+
"DOS": "https://upload.wikimedia.org/wikipedia/commons/1/1b/Seal_of_the_United_States_Department_of_State.svg",
|
109 |
+
"DOT": "https://upload.wikimedia.org/wikipedia/commons/8/88/Seal_of_the_United_States_Department_of_Transportation.svg",
|
110 |
+
"HHS": "https://upload.wikimedia.org/wikipedia/commons/0/03/Seal_of_the_U.S._Department_of_Health_and_Human_Services.svg",
|
111 |
+
"HUD": "https://upload.wikimedia.org/wikipedia/commons/6/6e/Seal_of_the_United_States_Department_of_Housing_and_Urban_Development.svg",
|
112 |
+
"NASA": "https://upload.wikimedia.org/wikipedia/commons/e/e5/NASA_logo.svg",
|
113 |
+
"NRC": "https://upload.wikimedia.org/wikipedia/commons/8/85/U.S._Nuclear_Regulatory_Commission_seal.svg",
|
114 |
+
"SSA": "https://upload.wikimedia.org/wikipedia/commons/6/6e/Social_Security_Administration_logo_%282019%29.svg",
|
115 |
+
"USDA": "https://upload.wikimedia.org/wikipedia/commons/0/0f/Seal_of_the_United_States_Department_of_Agriculture.svg",
|
116 |
+
"VA": "https://upload.wikimedia.org/wikipedia/commons/8/87/Seal_of_the_U.S._Department_of_Veterans_Affairs.svg",
|
117 |
+
}
|
118 |
+
|
119 |
def create_search_url_wikipedia(search_query):
|
120 |
base_url = "https://www.wikipedia.org/search-redirect.php?family=wikipedia&language=en&search="
|
121 |
return base_url + search_query.replace(' ', '+').replace('β', '%E2%80%93').replace('&', 'and')
|
122 |
|
123 |
def parse_foia_xml(filename: str) -> Dict:
|
|
|
124 |
try:
|
125 |
tree = ET.parse(filename)
|
126 |
root = tree.getroot()
|
|
|
153 |
return
|
154 |
|
155 |
for xml_file in xml_files:
|
156 |
+
file_name = xml_file[:-4]
|
157 |
data = parse_foia_xml(xml_file)
|
158 |
with st.expander(f"π {file_name} - {data['name']} ({data['abbr']})"):
|
159 |
+
if data['abbr'] in AGENCY_LOGOS:
|
160 |
+
st.image(
|
161 |
+
AGENCY_LOGOS[data['abbr']],
|
162 |
+
caption=f"{data['name']} Seal",
|
163 |
+
width=100
|
164 |
+
)
|
165 |
+
else:
|
166 |
+
st.write("πΌοΈ No logo available for this agency yet.")
|
167 |
+
|
168 |
st.write(f"π
Fiscal Year: {data['fiscal_year']}")
|
169 |
st.write(f"β³ Pending at Start: {data['pending_start']}")
|
170 |
st.write(f"π₯ Received: {data['received']}")
|
|
|
185 |
return results
|
186 |
|
187 |
def main():
|
|
|
188 |
AGENCIES = load_agencies_from_xml()
|
189 |
|
190 |
st.title("Freedom of Information Act (FOIA) Explorer ππ")
|
191 |
|
192 |
+
st.image(
|
193 |
+
"https://upload.wikimedia.org/wikipedia/en/e/e8/U.S._Commission_of_Fine_Arts_logo.png",
|
194 |
+
caption="Logo of the United States Commission of Fine Arts - Representing U.S. Government Transparency",
|
195 |
+
width=200
|
196 |
+
)
|
197 |
+
|
198 |
st.write("""
|
199 |
The Freedom of Information Act (FOIA) empowers individuals by granting access to previously unreleased information and documents controlled by the United States government. Championing transparency and accountability, FOIA serves as a foundation for democratic engagement and open government initiatives. πβ¨
|
200 |
Below is a list of datasets available under FOIA, alongside guessed Wikipedia URLs for more information. ππ
|
|
|
205 |
- [Data.Gov](https://catalog.data.gov/dataset?tags=foia)
|
206 |
""")
|
207 |
|
|
|
208 |
datasets = [
|
209 |
("Provider Taxonomy", "π©Ί"),
|
210 |
("Consumer Complaint Database", "π"),
|
|
|
220 |
for dataset, emoji in datasets:
|
221 |
st.markdown(f"- {emoji} **{dataset}**: [Wikipedia]({create_search_url_wikipedia(dataset)})")
|
222 |
|
|
|
223 |
st.header("Agency Browser")
|
224 |
agency_names = sorted(list(AGENCIES.keys()))
|
225 |
selected_agency = st.selectbox("Select Agency", [""] + agency_names)
|
|
|
227 |
if selected_agency:
|
228 |
agency = Agency(AGENCIES[selected_agency])
|
229 |
st.subheader(f"{agency.name} Details")
|
230 |
+
if agency.summary.get('abbreviation') in AGENCY_LOGOS:
|
231 |
+
st.image(
|
232 |
+
AGENCY_LOGOS[agency.summary.get('abbreviation')],
|
233 |
+
caption=f"{agency.name} Seal",
|
234 |
+
width=100
|
235 |
+
)
|
236 |
st.write(f"Description: {agency.summary.get('description', 'N/A')}")
|
237 |
st.write(f"Abbreviation: {agency.summary.get('abbreviation', 'N/A')}")
|
238 |
if agency.website:
|
|
|
264 |
if "median" in key:
|
265 |
st.write(f"{key.replace('_median_days', '').title()}: {value} days")
|
266 |
|
|
|
267 |
st.subheader("Search FOIA Documents")
|
268 |
search_query = st.text_input("Enter search query")
|
269 |
if st.button("Search") and search_query:
|
|
|
273 |
for result in results["results"]:
|
274 |
st.write(f"- {result['title']} ({result['date']})")
|
275 |
|
|
|
276 |
st.header("FOIA XML Reports")
|
277 |
list_and_display_xml_files()
|
278 |
|