Mark Febrizio
commited on
Commit
•
4ea4f4c
1
Parent(s):
ec74423
Revert "Update app.py"
Browse filesThis reverts commit 164c6c162953c6283a1474194d75d0dff27abbed.
app.py
CHANGED
@@ -1,13 +1,10 @@
|
|
1 |
-
# ----- IMPORTS ----- #
|
2 |
-
|
3 |
-
|
4 |
import asyncio
|
5 |
from datetime import datetime, date, time
|
6 |
from pathlib import Path
|
7 |
|
8 |
from faicons import icon_svg
|
9 |
-
from pandas import DataFrame
|
10 |
-
from
|
11 |
|
12 |
from modules import (
|
13 |
DF,
|
@@ -23,33 +20,25 @@ from modules import (
|
|
23 |
pad_missing_dates,
|
24 |
plot_agency,
|
25 |
plot_tf,
|
26 |
-
plot_NA,
|
27 |
)
|
28 |
|
29 |
from shiny import reactive
|
30 |
from shiny.express import input, render, ui
|
31 |
|
32 |
-
# load css styles from external file
|
33 |
-
ui.include_css( Path(__file__).parent.joinpath("www") / "style.css")
|
34 |
-
|
35 |
-
|
36 |
-
# ----- CREATE OBJECTS ----- #
|
37 |
-
|
38 |
-
|
39 |
-
# this text appears in the browser tab
|
40 |
TITLE = "CRA Window Tracker - GW Regulatory Studies Center"
|
41 |
|
42 |
-
# page header above main content
|
43 |
HEADER = "Rules in the Congressional Review Act (CRA) Window"
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
"""
|
50 |
-
)
|
51 |
|
52 |
-
|
|
|
|
|
|
|
53 |
sidebar_logo = ui.HTML(
|
54 |
f"""
|
55 |
<div class="header">
|
@@ -60,48 +49,36 @@ sidebar_logo = ui.HTML(
|
|
60 |
"""
|
61 |
)
|
62 |
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
"""
|
69 |
-
|
70 |
-
|
71 |
-
# ----- APP LAYOUT ----- #
|
72 |
-
|
73 |
-
|
74 |
-
ui.tags.title(TITLE)
|
75 |
|
76 |
page_header
|
77 |
|
78 |
-
# sidebar settings
|
79 |
with ui.sidebar(open={"desktop": "open", "mobile": "closed"}):
|
80 |
sidebar_logo
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
ui.input_date("start_date", "Select start of window", value=WINDOW_OPEN_DATE, min=START_DATE, max=date.today())
|
85 |
-
"The estimated CRA window open date is May 23. See the notes for more information."
|
86 |
-
|
87 |
ui.input_select("menu_agency", "Select agencies", choices=["all"] + AGENCIES, selected="all", multiple=True)
|
88 |
|
89 |
-
ui.input_select("frequency", "Select frequency", choices=["daily", "
|
90 |
-
|
91 |
-
ui.input_select("menu_significant", "Select rule significance", choices=["all", "3f1-significant", "other-significant"], selected="all", multiple=True)
|
92 |
|
93 |
#ui.input_switch("switch", "Stack significant rules in plots", False)
|
94 |
|
95 |
-
# value boxes with summary data
|
96 |
with ui.layout_column_wrap():
|
97 |
-
with ui.value_box():
|
98 |
"All final rules"
|
99 |
@render.text
|
100 |
def count_rules():
|
101 |
return f"{filtered_df()['document_number'].count()}"
|
102 |
-
ui.input_action_button("filter_all", "
|
103 |
|
104 |
-
with ui.value_box():
|
105 |
"Section 3(f)(1) Significant rules *"
|
106 |
@render.text
|
107 |
def count_3f1_significant():
|
@@ -109,9 +86,9 @@ with ui.layout_column_wrap():
|
|
109 |
if GET_SIGNIFICANT:
|
110 |
output = f"{filtered_df()['3f1_significant'].sum()}"
|
111 |
return output
|
112 |
-
ui.input_action_button("filter_3f1", "
|
113 |
|
114 |
-
with ui.value_box():
|
115 |
"Other Significant rules *"
|
116 |
@render.text
|
117 |
def count_other_significant():
|
@@ -119,16 +96,14 @@ with ui.layout_column_wrap():
|
|
119 |
if GET_SIGNIFICANT:
|
120 |
output = f"{filtered_df()['other_significant'].sum()}"
|
121 |
return output
|
122 |
-
ui.input_action_button("filter_other", "
|
123 |
|
124 |
-
# documentation note on significance data
|
125 |
ui.markdown(
|
126 |
f"""
|
127 |
\* *Executive Order 12866 significance data last updated **{LAST_UPDATED}***.
|
128 |
"""
|
129 |
)
|
130 |
|
131 |
-
# main content
|
132 |
with ui.navset_card_underline(title=""):
|
133 |
|
134 |
with ui.nav_panel("Rules in detail"):
|
@@ -161,12 +136,14 @@ with ui.navset_card_underline(title=""):
|
|
161 |
count_gte_zero = sum(1 if g > 0 else 0 for g in values)
|
162 |
max_val = max(values, default=0)
|
163 |
if (max_val < 2) or (count_gte_zero < 2):
|
164 |
-
return
|
|
|
|
|
|
|
165 |
else:
|
166 |
return plot_tf(
|
167 |
grouped,
|
168 |
-
input.frequency()
|
169 |
-
rule_type=filter_value.get(),
|
170 |
)
|
171 |
|
172 |
with ui.card(full_screen=True):
|
@@ -203,14 +180,10 @@ with ui.navset_card_underline(title=""):
|
|
203 |
#if input.switch():
|
204 |
# pass
|
205 |
# # placeholder for stacked bar chart
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
grouped.head(10),
|
211 |
-
rule_type=filter_value.get(),
|
212 |
-
)
|
213 |
-
return plot
|
214 |
|
215 |
with ui.card(full_screen=True):
|
216 |
@render.data_frame
|
@@ -225,7 +198,6 @@ with ui.navset_card_underline(title=""):
|
|
225 |
]
|
226 |
return render.DataTable(grouped.loc[:, [c for c in cols if c in grouped.columns]])
|
227 |
|
228 |
-
# download data
|
229 |
with ui.accordion(open=False):
|
230 |
|
231 |
with ui.accordion_panel("Download Data"):
|
@@ -259,7 +231,6 @@ with ui.accordion(open=False):
|
|
259 |
await asyncio.sleep(0.25)
|
260 |
yield filtered_df().loc[:, output_cols].to_csv(index=False)
|
261 |
|
262 |
-
# notes
|
263 |
with ui.accordion(open=False):
|
264 |
|
265 |
with ui.accordion_panel("Notes"):
|
@@ -272,7 +243,6 @@ with ui.accordion(open=False):
|
|
272 |
"""
|
273 |
)
|
274 |
|
275 |
-
# footer citation
|
276 |
ui.markdown(
|
277 |
FOOTER
|
278 |
)
|
@@ -296,17 +266,6 @@ def filtered_df():
|
|
296 |
bool_agency = [True if sum(selected in agency for selected in input.menu_agency()) > 0 else False for agency in filt_df["parent_slug"]]
|
297 |
filt_df = filt_df.loc[bool_agency]
|
298 |
|
299 |
-
print(input.menu_significant())
|
300 |
-
# filter significance
|
301 |
-
bool_ = []
|
302 |
-
if (input.menu_significant() is not None) and ("all" not in input.menu_significant()):
|
303 |
-
if "3f1-significant" in input.menu_significant():
|
304 |
-
bool_.append((filt_df["3f1_significant"] == 1).to_numpy())
|
305 |
-
if "other-significant" in input.menu_significant():
|
306 |
-
bool_.append((filt_df["other_significant"] == 1).to_numpy())
|
307 |
-
filt_df = filt_df.loc[array(bool_).any(axis=0)]
|
308 |
-
|
309 |
-
# return filtered dataframe
|
310 |
return filt_df
|
311 |
|
312 |
|
|
|
|
|
|
|
|
|
1 |
import asyncio
|
2 |
from datetime import datetime, date, time
|
3 |
from pathlib import Path
|
4 |
|
5 |
from faicons import icon_svg
|
6 |
+
from pandas import DataFrame, to_datetime
|
7 |
+
from plotnine import ggplot, labs
|
8 |
|
9 |
from modules import (
|
10 |
DF,
|
|
|
20 |
pad_missing_dates,
|
21 |
plot_agency,
|
22 |
plot_tf,
|
|
|
23 |
)
|
24 |
|
25 |
from shiny import reactive
|
26 |
from shiny.express import input, render, ui
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
TITLE = "CRA Window Tracker - GW Regulatory Studies Center"
|
29 |
|
|
|
30 |
HEADER = "Rules in the Congressional Review Act (CRA) Window"
|
31 |
+
|
32 |
+
FOOTER = f"""
|
33 |
+
-----
|
34 |
+
|
35 |
+
© 2024 [GW Regulatory Studies Center](https://go.gwu.edu/regstudies). See our page on the [Congressional Review Act](https://regulatorystudies.columbian.gwu.edu/congressional-review-act) for more information.
|
36 |
"""
|
|
|
37 |
|
38 |
+
ui.include_css( Path(__file__).parent.joinpath("www") / "style.css")
|
39 |
+
|
40 |
+
ui.tags.title(TITLE)
|
41 |
+
|
42 |
sidebar_logo = ui.HTML(
|
43 |
f"""
|
44 |
<div class="header">
|
|
|
49 |
"""
|
50 |
)
|
51 |
|
52 |
+
page_header = ui.HTML(
|
53 |
+
f"""
|
54 |
+
<div class="header">
|
55 |
+
<span>{HEADER}</span>
|
56 |
+
</div>
|
57 |
"""
|
58 |
+
)
|
|
|
|
|
|
|
|
|
|
|
59 |
|
60 |
page_header
|
61 |
|
|
|
62 |
with ui.sidebar(open={"desktop": "open", "mobile": "closed"}):
|
63 |
sidebar_logo
|
64 |
|
65 |
+
ui.input_date("start_date", "Select start of window", value=WINDOW_OPEN_DATE, min=START_DATE, max=date.today())
|
66 |
+
|
|
|
|
|
|
|
67 |
ui.input_select("menu_agency", "Select agencies", choices=["all"] + AGENCIES, selected="all", multiple=True)
|
68 |
|
69 |
+
ui.input_select("frequency", "Select frequency", choices=["daily", "monthly", "weekly"], selected="daily")
|
|
|
|
|
70 |
|
71 |
#ui.input_switch("switch", "Stack significant rules in plots", False)
|
72 |
|
|
|
73 |
with ui.layout_column_wrap():
|
74 |
+
with ui.value_box(showcase=icon_svg("book")):
|
75 |
"All final rules"
|
76 |
@render.text
|
77 |
def count_rules():
|
78 |
return f"{filtered_df()['document_number'].count()}"
|
79 |
+
ui.input_action_button("filter_all", "View", ) #class_="btn-success")
|
80 |
|
81 |
+
with ui.value_box(showcase=icon_svg("book")):
|
82 |
"Section 3(f)(1) Significant rules *"
|
83 |
@render.text
|
84 |
def count_3f1_significant():
|
|
|
86 |
if GET_SIGNIFICANT:
|
87 |
output = f"{filtered_df()['3f1_significant'].sum()}"
|
88 |
return output
|
89 |
+
ui.input_action_button("filter_3f1", "View", ) #class_="btn-success")
|
90 |
|
91 |
+
with ui.value_box(showcase=icon_svg("book")):
|
92 |
"Other Significant rules *"
|
93 |
@render.text
|
94 |
def count_other_significant():
|
|
|
96 |
if GET_SIGNIFICANT:
|
97 |
output = f"{filtered_df()['other_significant'].sum()}"
|
98 |
return output
|
99 |
+
ui.input_action_button("filter_other", "View", )
|
100 |
|
|
|
101 |
ui.markdown(
|
102 |
f"""
|
103 |
\* *Executive Order 12866 significance data last updated **{LAST_UPDATED}***.
|
104 |
"""
|
105 |
)
|
106 |
|
|
|
107 |
with ui.navset_card_underline(title=""):
|
108 |
|
109 |
with ui.nav_panel("Rules in detail"):
|
|
|
136 |
count_gte_zero = sum(1 if g > 0 else 0 for g in values)
|
137 |
max_val = max(values, default=0)
|
138 |
if (max_val < 2) or (count_gte_zero < 2):
|
139 |
+
return (
|
140 |
+
ggplot()
|
141 |
+
+ labs(title="Not enough data available to visualize.")
|
142 |
+
)
|
143 |
else:
|
144 |
return plot_tf(
|
145 |
grouped,
|
146 |
+
input.frequency()
|
|
|
147 |
)
|
148 |
|
149 |
with ui.card(full_screen=True):
|
|
|
180 |
#if input.switch():
|
181 |
# pass
|
182 |
# # placeholder for stacked bar chart
|
183 |
+
plot = plot_agency(
|
184 |
+
grouped.head(10),
|
185 |
+
)
|
186 |
+
return plot
|
|
|
|
|
|
|
|
|
187 |
|
188 |
with ui.card(full_screen=True):
|
189 |
@render.data_frame
|
|
|
198 |
]
|
199 |
return render.DataTable(grouped.loc[:, [c for c in cols if c in grouped.columns]])
|
200 |
|
|
|
201 |
with ui.accordion(open=False):
|
202 |
|
203 |
with ui.accordion_panel("Download Data"):
|
|
|
231 |
await asyncio.sleep(0.25)
|
232 |
yield filtered_df().loc[:, output_cols].to_csv(index=False)
|
233 |
|
|
|
234 |
with ui.accordion(open=False):
|
235 |
|
236 |
with ui.accordion_panel("Notes"):
|
|
|
243 |
"""
|
244 |
)
|
245 |
|
|
|
246 |
ui.markdown(
|
247 |
FOOTER
|
248 |
)
|
|
|
266 |
bool_agency = [True if sum(selected in agency for selected in input.menu_agency()) > 0 else False for agency in filt_df["parent_slug"]]
|
267 |
filt_df = filt_df.loc[bool_agency]
|
268 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
return filt_df
|
270 |
|
271 |
|