Skip to content

Commit 19e86f1

Browse files
authored
Flip angle of bar chart text in mobile layout (#331)
To make it easier to read
1 parent e60cda0 commit 19e86f1

File tree

1 file changed

+72
-32
lines changed

1 file changed

+72
-32
lines changed

report/surveyhero/render.py

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -72,60 +72,88 @@ def normalize_arg(key, value) -> Tuple[str, Any]:
7272
if isinstance(chart, PlotlyRenderer):
7373
figure = chart.render_fn(**args)
7474
chart_type = figure.layout.meta
75-
element = BeautifulSoup(figure.to_html(full_html=False, include_plotlyjs=None, div_id=chart_id, config=dict(
76-
modeBarButtonsToRemove=["zoom", "pan", "lasso2d", "select", "autoScale", "toImage"],
77-
displaylogo=False
78-
)), features="html.parser").div
75+
element = BeautifulSoup(
76+
figure.to_html(
77+
full_html=False,
78+
include_plotlyjs=None,
79+
div_id=chart_id,
80+
config=dict(
81+
modeBarButtonsToRemove=[
82+
"zoom",
83+
"pan",
84+
"lasso2d",
85+
"select",
86+
"autoScale",
87+
"toImage",
88+
],
89+
displaylogo=False,
90+
),
91+
),
92+
features="html.parser",
93+
).div
7994
div = element.find("div")
8095
div["class"] = chart_type
81-
div.append(BeautifulSoup(f"""<noscript>
96+
div.append(
97+
BeautifulSoup(
98+
f"""<noscript>
8299
<img src="{make_rel_path(image_dir=image_dir, path=png_path)}" height="{height}" alt="{chart_id}" />
83-
</noscript>""", "html.parser"))
100+
</noscript>""",
101+
"html.parser",
102+
)
103+
)
84104

85105
links = [
86-
(make_rel_path(image_dir=image_dir, path=png_path), "Download chart as PNG", "PNG"),
87-
(make_rel_path(image_dir=image_dir, path=svg_path), "Download chart as SVG", "SVG"),
106+
(
107+
make_rel_path(image_dir=image_dir, path=png_path),
108+
"Download chart as PNG",
109+
"PNG",
110+
),
111+
(
112+
make_rel_path(image_dir=image_dir, path=svg_path),
113+
"Download chart as SVG",
114+
"SVG",
115+
),
88116
]
89117

90118
wordcloud_id = f"{chart_id}-wordcloud"
91119
wordcloud = report.get_chart(wordcloud_id)
92120
if wordcloud is not None:
93-
wc_png_path = render_png(image_dir=image_dir, renderer=wordcloud, chart_id=wordcloud_id)
121+
wc_png_path = render_png(
122+
image_dir=image_dir, renderer=wordcloud, chart_id=wordcloud_id
123+
)
94124
links.append(
95-
(make_rel_path(image_dir=image_dir, path=wc_png_path), "Download open answers as wordcloud PNG",
96-
"Wordcloud of open answers")
125+
(
126+
make_rel_path(image_dir=image_dir, path=wc_png_path),
127+
"Download open answers as wordcloud PNG",
128+
"Wordcloud of open answers",
129+
)
97130
)
98131

99-
links = [f"""<span>[<a href="{link}" target="_href_" title="{title}">{label}</a>]</span>"""
100-
for (link, title, label) in links]
132+
links = [
133+
f"""<span>[<a href="{link}" target="_href_" title="{title}">{label}</a>]</span>"""
134+
for (link, title, label) in links
135+
]
101136
tag = f"""<!-- Chart {chart_id} start -->
102137
<div>
103138
{div}
104139
<div style="display: flex; margin-bottom: 10px;">
105-
{'&nbsp;'.join(links)}
140+
{"&nbsp;".join(links)}
106141
</div>
107142
</div>
108143
<!-- Chart {chart_id} end -->"""
109144

110145
script = element.find("script")
111146
assert script is not None
112147

113-
return RenderedChart(
114-
script=script.text.strip(),
115-
tag=tag,
116-
to_replace=fullmatch
117-
)
148+
return RenderedChart(script=script.text.strip(), tag=tag, to_replace=fullmatch)
118149
elif isinstance(chart, PngRenderer):
119150
assert False
120151
else:
121152
assert False
122153

123154

124155
def render_blog_post(
125-
template: Path,
126-
blog_root: Path,
127-
resource_dir: str,
128-
report: ChartReport
156+
template: Path, blog_root: Path, resource_dir: str, report: ChartReport
129157
):
130158
"""
131159
Render a Rust Blog post containing special placeholders that will render as SurveyHero charts from the given `report`.
@@ -150,7 +178,9 @@ def render_blog_post(
150178
image_dir.mkdir(parents=True, exist_ok=True)
151179
script_dir = blog_root / "static" / "scripts" / resource_dir
152180
script_dir.mkdir(parents=True, exist_ok=True)
153-
print(f"Generating blog post to {output_path}, image directory {image_dir}, scripts directory {script_dir}")
181+
print(
182+
f"Generating blog post to {output_path}, image directory {image_dir}, scripts directory {script_dir}"
183+
)
154184

155185
with open(template) as f:
156186
document = f.read()
@@ -193,7 +223,7 @@ def render_blog_post(
193223
layout.autosize = false;
194224
layout.width = "100%";
195225
Plotly.relayout(chart, layout);
196-
Plotly.restyle(chart, {textangle: -90});
226+
Plotly.restyle(chart, {textangle: 90});
197227
}
198228
var matrix_charts = document.getElementsByClassName("matrix-chart");
199229
for (var i = 0; i < matrix_charts.length; i++) {
@@ -216,16 +246,20 @@ def render_blog_post(
216246

217247
plotly_script_path = script_dir.parent / "plotly-basic-2.29.0.min.js"
218248
if not os.path.isfile(plotly_script_path):
219-
urllib.request.urlretrieve("https://cdn.plot.ly/plotly-basic-2.29.0.min.js", plotly_script_path)
249+
urllib.request.urlretrieve(
250+
"https://cdn.plot.ly/plotly-basic-2.29.0.min.js", plotly_script_path
251+
)
220252

221253
scripts = [
222254
'<script charset="utf-8" src="../../../scripts/plotly-basic-2.29.0.min.js"></script>',
223-
f'<script src="../../../scripts/{script_path.relative_to(script_dir.parent)}"></script>'
255+
f'<script src="../../../scripts/{script_path.relative_to(script_dir.parent)}"></script>',
224256
]
225257

226258
script_marker = "<!-- scripts -->"
227259
if script_marker not in document:
228-
raise Exception(f"Please add `{script_marker}` to the (end of the) Markdown document")
260+
raise Exception(
261+
f"Please add `{script_marker}` to the (end of the) Markdown document"
262+
)
229263
script_str = "<!-- Chart scripts -->\n\n" + "\n\n".join(scripts)
230264
document = document.replace(script_marker, script_str)
231265

@@ -248,7 +282,9 @@ def render_pdf_page(args) -> Tuple[str, str, Union[str, bytes]]:
248282
return (name, "png", png_bytes)
249283

250284

251-
def render_report_to_pdf(report: ChartReport, output: Path, title: str, include_labels=False):
285+
def render_report_to_pdf(
286+
report: ChartReport, output: Path, title: str, include_labels=False
287+
):
252288
"""
253289
Renders a PDF report containing all charts from the given `report` into the `output` path.
254290
"""
@@ -266,12 +302,16 @@ def render_report_to_pdf(report: ChartReport, output: Path, title: str, include_
266302

267303
args = [(report, name) for name in report.charts.keys()]
268304
with mp.Pool() as pool:
269-
for (name, format, result) in tqdm.tqdm(pool.imap(render_pdf_page, args), total=len(args)):
305+
for name, format, result in tqdm.tqdm(
306+
pool.imap(render_pdf_page, args), total=len(args)
307+
):
270308
slide = slides.new_slide()
271309

272310
if name.endswith("-wordcloud"):
273-
slide.box(y=150).text("Wordcloud of open answers for the previous chart:",
274-
style=elsie.TextStyle(size=20))
311+
slide.box(y=150).text(
312+
"Wordcloud of open answers for the previous chart:",
313+
style=elsie.TextStyle(size=20),
314+
)
275315

276316
box = slide.box(width="95%")
277317
if format == "png":

0 commit comments

Comments
 (0)