staticdash 0.2.2__py3-none-any.whl → 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -174,4 +174,15 @@ table.sortable th.sorted-asc::after {
174
174
 
175
175
  table.sortable th.sorted-desc::after {
176
176
  content: "\25BC";
177
+ }
178
+
179
+ .minipage-row {
180
+ display: flex;
181
+ gap: 20px;
182
+ margin-bottom: 20px;
183
+ }
184
+
185
+ .minipage {
186
+ box-sizing: border-box;
187
+ padding: 10px;
177
188
  }
staticdash/dashboard.py CHANGED
@@ -4,15 +4,12 @@ import uuid
4
4
  import pandas as pd
5
5
  import plotly.graph_objects as go
6
6
  from dominate import document
7
- from dominate.tags import div, h1, h2, h3, h4, p, a, script, link, table, thead, tr, th, tbody, td, span
7
+ from dominate.tags import div, h1, h2, h3, h4, p, a, script, link
8
8
  from dominate.util import raw as raw_util
9
9
 
10
- class Page:
11
- def __init__(self, slug, title):
12
- self.slug = slug
13
- self.title = title
10
+ class AbstractPage:
11
+ def __init__(self):
14
12
  self.elements = []
15
- self.add_header(title, level=1) # Add page title as level 1 header
16
13
 
17
14
  def add_header(self, text, level=1):
18
15
  if level not in (1, 2, 3, 4):
@@ -40,20 +37,25 @@ class Page:
40
37
  raise FileNotFoundError(f"File not found: {file_path}")
41
38
  self.elements.append(("download", (file_path, label)))
42
39
 
43
- def add(self, element):
44
- if isinstance(element, str):
45
- self.add_text(element)
46
- elif isinstance(element, go.Figure):
47
- self.add_plot(element)
48
- elif isinstance(element, pd.DataFrame):
49
- self.add_table(element)
50
- else:
51
- raise ValueError(f"Unsupported element type: {type(element)}")
40
+ def add_minipage(self, minipage):
41
+ self.elements.append(("minipage", minipage))
42
+
43
+ class Page(AbstractPage):
44
+ def __init__(self, slug, title):
45
+ super().__init__()
46
+ self.slug = slug
47
+ self.title = title
48
+ self.add_header(title, level=1)
52
49
 
53
50
  def render(self, index):
54
- section = div(id=f"page-{index}", cls="page-section")
51
+ section = div()
52
+ minipage_row = []
55
53
  for kind, content in self.elements:
56
- if kind == "header":
54
+ if kind == "minipage":
55
+ row_div = div(cls="minipage-row")
56
+ row_div += content.render(index)
57
+ section += row_div
58
+ elif kind == "header":
57
59
  text, level = content
58
60
  if level == 1:
59
61
  section += h1(text)
@@ -70,8 +72,65 @@ class Page:
70
72
  elif kind == "table":
71
73
  table_html, _ = content
72
74
  section += raw_util(table_html)
75
+ elif kind == "download":
76
+ file_path, label = content
77
+ btn = a(label or os.path.basename(file_path),
78
+ href=file_path,
79
+ cls="download-button",
80
+ download=True)
81
+ section += div(btn)
73
82
  return section
74
83
 
84
+ class MiniPage(AbstractPage):
85
+ def __init__(self, width=1.0):
86
+ super().__init__()
87
+ self.width = width
88
+
89
+ def render(self, index=None):
90
+ style = f"flex: 0 0 {self.width * 100}%; max-width: {self.width * 100}%;"
91
+ container = div(cls="minipage", style=style)
92
+ minipage_row = []
93
+ for kind, content in self.elements:
94
+ if kind == "minipage":
95
+ minipage_row.append(content)
96
+ else:
97
+ if minipage_row:
98
+ row_div = div(cls="minipage-row")
99
+ for mp in minipage_row:
100
+ row_div += mp.render(index)
101
+ container += row_div
102
+ minipage_row = []
103
+ if kind == "header":
104
+ text, level = content
105
+ if level == 1:
106
+ container += h1(text)
107
+ elif level == 2:
108
+ container += h2(text)
109
+ elif level == 3:
110
+ container += h3(text)
111
+ elif level == 4:
112
+ container += h4(text)
113
+ elif kind == "text":
114
+ container += p(content)
115
+ elif kind == "plot":
116
+ container += div(content, cls="plot-container")
117
+ elif kind == "table":
118
+ table_html, _ = content
119
+ container += raw_util(table_html)
120
+ elif kind == "download":
121
+ file_path, label = content
122
+ btn = a(label or os.path.basename(file_path),
123
+ href=file_path,
124
+ cls="download-button",
125
+ download=True)
126
+ container += div(btn)
127
+ if minipage_row:
128
+ row_div = div(cls="minipage-row")
129
+ for mp in minipage_row:
130
+ row_div += mp.render(index)
131
+ container += row_div
132
+ return container
133
+
75
134
  class Dashboard:
76
135
  def __init__(self, title="Dashboard"):
77
136
  self.title = title
@@ -96,10 +155,10 @@ class Dashboard:
96
155
  with doc.head:
97
156
  doc.head.add(link(rel="stylesheet", href="../assets/css/style.css"))
98
157
  doc.head.add(script(type="text/javascript", src="../assets/js/script.js"))
158
+ doc.head.add(script(src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"))
99
159
 
100
160
  with doc:
101
161
  with div(cls="page-section", id=f"page-{page.slug}"):
102
- # Remove h1(page.title) here, since it's already a header element
103
162
  for kind, content in page.elements:
104
163
  if kind == "header":
105
164
  text, level = content
@@ -126,6 +185,7 @@ class Dashboard:
126
185
  with index_doc.head:
127
186
  index_doc.head.add(link(rel="stylesheet", href="assets/css/style.css"))
128
187
  index_doc.head.add(script(type="text/javascript", src="assets/js/script.js"))
188
+ index_doc.head.add(script(src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"))
129
189
 
130
190
  with index_doc:
131
191
  with div(id="sidebar"):
@@ -136,39 +196,10 @@ class Dashboard:
136
196
  a("Produced by staticdash", href="https://pypi.org/project/staticdash/", target="_blank")
137
197
 
138
198
  with div(id="content"):
139
- for page in self.pages:
140
- with div(id=f"page-{page.slug}", cls="page-section", style="display:none;"):
141
- # Remove h2(page.title) here, since it's already a header element
142
- for kind, content in page.elements:
143
- if kind == "header":
144
- text, level = content
145
- if level == 1:
146
- h1(text)
147
- elif level == 2:
148
- h2(text)
149
- elif level == 3:
150
- h3(text)
151
- elif level == 4:
152
- h4(text)
153
- elif kind == "text":
154
- p(content)
155
- elif kind == "plot":
156
- div(content, cls="plot-container")
157
- elif kind == "table":
158
- table_html, _ = content
159
- div(raw_util(table_html))
160
- elif kind == "download":
161
- src_path, label = content
162
- file_uuid = f"{uuid.uuid4().hex}_{os.path.basename(src_path)}"
163
- dst_path = os.path.join(downloads_dir, file_uuid)
164
- shutil.copy2(src_path, dst_path)
165
- download_link = f"downloads/{file_uuid}"
166
- btn = a(label or os.path.basename(src_path),
167
- href=download_link,
168
- cls="download-button",
169
- download=True)
170
- div(btn)
171
- div(raw_util("<br>"))
199
+ for idx, page in enumerate(self.pages):
200
+ with div(id=f"page-{page.slug}", cls="page-section", style="display:none;") as section:
201
+ rendered = page.render(idx)
202
+ section += rendered # This is correct
172
203
 
173
204
  with open(os.path.join(output_dir, "index.html"), "w") as f:
174
205
  f.write(str(index_doc))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: staticdash
3
- Version: 0.2.2
3
+ Version: 0.3.1
4
4
  Summary: A lightweight static HTML dashboard generator with Plotly and pandas support.
5
5
  Author-email: Brian Day <brian.day1@gmail.com>
6
6
  License: CC0-1.0
@@ -0,0 +1,8 @@
1
+ staticdash/__init__.py,sha256=KqViaDkiQnhBI8-j3hr14umLDmPgddvdB_G1nJeC5Xs,38
2
+ staticdash/dashboard.py,sha256=OwQtURb0E5DNm4lyvAzy6WlAqfcFoXsmSIVDwrzuc2U,8212
3
+ staticdash/assets/css/style.css,sha256=z3bC-QjAb9f5E3HUkr6R81qQyAfKpMW48yjy11CYH-Q,2779
4
+ staticdash/assets/js/script.js,sha256=SMOyh7_E_BlvLYMEwYlvCnV7-GnMR-x8PtEiFbIIAsw,3089
5
+ staticdash-0.3.1.dist-info/METADATA,sha256=kXmv9eqBZU0MuQMPfAQGKkWZEaqzxtqRBQMig_3tysk,1776
6
+ staticdash-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ staticdash-0.3.1.dist-info/top_level.txt,sha256=3MzZU6SptkUkjcHV1cvPji0H4aRzPphLHnpStgGEcxM,11
8
+ staticdash-0.3.1.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- staticdash/__init__.py,sha256=KqViaDkiQnhBI8-j3hr14umLDmPgddvdB_G1nJeC5Xs,38
2
- staticdash/dashboard.py,sha256=trPzco0AZw4IAwZzgY__RsOjwg4UrD7etB-4Da1kHE0,7515
3
- staticdash/assets/css/style.css,sha256=kL6FAGxIwYrfNoo4oCzC-ygHmyOZDEjhjixpY0YGpss,2649
4
- staticdash/assets/js/script.js,sha256=SMOyh7_E_BlvLYMEwYlvCnV7-GnMR-x8PtEiFbIIAsw,3089
5
- staticdash-0.2.2.dist-info/METADATA,sha256=VDgodqPfaNsvqb-H8gqWWpixRKZie42xF3xG7jlz7rA,1776
6
- staticdash-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- staticdash-0.2.2.dist-info/top_level.txt,sha256=3MzZU6SptkUkjcHV1cvPji0H4aRzPphLHnpStgGEcxM,11
8
- staticdash-0.2.2.dist-info/RECORD,,