PyObservability 1.2.0__py3-none-any.whl → 1.3.0__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.
@@ -224,14 +224,63 @@
224
224
  }
225
225
 
226
226
  function setData(arr, columns) {
227
- if (JSON.stringify(state.data) === JSON.stringify(arr)) {
228
- return; // do not re-render if data didn't change
229
- }
230
227
  headEl.innerHTML = "<tr>" + columns.map(c => `<th>${c}</th>`).join("") + "</tr>";
231
- state.data = arr.map(row => {
232
- return "<tr>" + columns.map(c => `<td>${row[c] ?? ""}</td>`).join("") + "</tr>";
228
+ state.dataRaw = arr.slice();
229
+ state.columns = columns;
230
+ // Sorting logic
231
+ Array.from(headEl.querySelectorAll("th")).forEach((th, idx) => {
232
+ th.style.cursor = "pointer";
233
+ th.onclick = (e) => {
234
+ // Prevent sort if reset button was clicked
235
+ if (e.target.classList.contains("sort-reset")) return;
236
+ const col = columns[idx];
237
+ if (state.sortCol === col) {
238
+ state.sortAsc = !state.sortAsc;
239
+ } else {
240
+ state.sortCol = col;
241
+ state.sortAsc = true;
242
+ }
243
+ sortAndRender();
244
+ };
233
245
  });
234
- render();
246
+
247
+ function sortAndRender() {
248
+ // Rebuild all headers with correct HTML
249
+ headEl.querySelectorAll("th").forEach((th, idx) => {
250
+ const col = state.columns[idx];
251
+ if (state.sortCol === col) {
252
+ th.innerHTML = `${col} <span style="font-size:0.9em">${state.sortAsc ? "▲" : "▼"}</span>&nbsp;<span class="sort-reset" style="cursor:pointer;font-size:0.9em;color:#888;margin-left:8px;" title="Reset sort">⨯</span>`;
253
+ th.querySelector(".sort-reset").onclick = (e) => {
254
+ e.stopPropagation();
255
+ state.sortCol = null;
256
+ state.sortAsc = true;
257
+ state.dataRaw = arr.slice();
258
+ sortAndRender();
259
+ };
260
+ } else {
261
+ th.innerHTML = col;
262
+ }
263
+ });
264
+ if (state.sortCol) {
265
+ state.dataRaw.sort((a, b) => {
266
+ let va = a[state.sortCol], vb = b[state.sortCol];
267
+ let na = parseFloat(va), nb = parseFloat(vb);
268
+ if (!isNaN(na) && !isNaN(nb)) {
269
+ return state.sortAsc ? na - nb : nb - na;
270
+ }
271
+ va = (va ?? "").toString().toLowerCase();
272
+ vb = (vb ?? "").toString().toLowerCase();
273
+ if (va < vb) return state.sortAsc ? -1 : 1;
274
+ if (va > vb) return state.sortAsc ? 1 : -1;
275
+ return 0;
276
+ });
277
+ }
278
+ state.data = state.dataRaw.map(row =>
279
+ "<tr>" + state.columns.map(c => `<td>${row[c] ?? ""}</td>`).join("") + "</tr>"
280
+ );
281
+ render();
282
+ }
283
+ sortAndRender();
235
284
  }
236
285
 
237
286
  return {setData};
@@ -1 +1 @@
1
- __version__ = "1.2.0"
1
+ __version__ = "1.3.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyObservability
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: Lightweight OS-agnostic observability UI for PyNinja
5
5
  Author-email: Vignesh Rao <svignesh1793@gmail.com>
6
6
  License: MIT License
@@ -64,8 +64,6 @@ Dynamic: license-file
64
64
  **Deployments**
65
65
 
66
66
  [![pypi][label-actions-pypi]][gha_pypi]
67
- [![notes][label-actions-notes]][gha_notes]
68
- [![release][label-actions-release]][gha_release]
69
67
  [![docker][label-actions-docker]][gha_docker]
70
68
 
71
69
  [![Pypi][label-pypi]][pypi]
@@ -158,15 +156,11 @@ Licensed under the [MIT License][license]
158
156
  [label-pypi]: https://img.shields.io/pypi/v/PyObservability
159
157
  [label-pypi-format]: https://img.shields.io/pypi/format/PyObservability
160
158
  [label-pypi-status]: https://img.shields.io/pypi/status/PyObservability
161
- [label-actions-notes]: https://github.com/thevickypedia/PyObservability/actions/workflows/notes.yml/badge.svg
162
- [label-actions-release]: https://github.com/thevickypedia/PyObservability/actions/workflows/release.yml/badge.svg
163
159
  [label-actions-docker]: https://github.com/thevickypedia/PyObservability/actions/workflows/docker.yml/badge.svg
164
160
 
165
161
  [3.11]: https://docs.python.org/3/whatsnew/3.11.html
166
162
  [virtual environment]: https://docs.python.org/3/tutorial/venv.html
167
163
  [gha_pypi]: https://github.com/thevickypedia/PyObservability/actions/workflows/python-publish.yml
168
- [gha_notes]: https://github.com/thevickypedia/PyObservability/actions/workflows/notes.yml
169
- [gha_release]: https://github.com/thevickypedia/PyObservability/actions/workflows/release.yml
170
164
  [gha_docker]: https://github.com/thevickypedia/PyObservability/actions/workflows/docker.yml
171
165
  [pypi]: https://pypi.org/project/PyObservability
172
166
  [pypi-files]: https://pypi.org/project/PyObservability/#files
@@ -2,15 +2,15 @@ pyobservability/__init__.py,sha256=yVBLyTohBiBKp0Otyl04IggPh8mhg3Er25u6eFyxMto,2
2
2
  pyobservability/main.py,sha256=6Ozyxi-XVq9ojkrTEjw9oYWJaW49JJZ-ezBNzEM951Y,4503
3
3
  pyobservability/monitor.py,sha256=Y38zDJFPDbQqz_2jQcNmJBnRpeobC_SV2uhN-13e9RU,7591
4
4
  pyobservability/transport.py,sha256=zHLAodX20bKkPOuacKjzv1Dqj3JbNAB75o1ABwzum0U,2534
5
- pyobservability/version.py,sha256=MpAT5hgNoHnTtG1XRD_GV_A7QrHVU6vJjGSw_8qMGA4,22
5
+ pyobservability/version.py,sha256=F5mW07pSyGrqDNY2Ehr-UpDzpBtN-FsYU0QGZWf6PJE,22
6
6
  pyobservability/config/enums.py,sha256=EhvD9kB5EMW3ARxr5KmISmf-rP3D4IKqOIjw6Tb8SB8,294
7
7
  pyobservability/config/settings.py,sha256=l1xtD8teYS5ozXWm6JqpyyrcQsu95Syjs02xsd0m6MI,5886
8
- pyobservability/static/app.js,sha256=lb0IjLle-FibG_ee0VN6qAe5LGJuSurgXVhHXCQL6WI,24281
8
+ pyobservability/static/app.js,sha256=ngeSsp8mCkF6XqZpXhwqv-EtNI8NmrMYxNgQtaKB4WE,26675
9
9
  pyobservability/static/styles.css,sha256=4-VCDhzv_FnrvUffETTHkNnyGOFDUJU0qz2eLHCz_QI,5569
10
10
  pyobservability/templates/index.html,sha256=OvFDydHMquBtFr_2cy3iXP0I-pax6_RKBJinVVEIzQY,7193
11
- pyobservability-1.2.0.dist-info/licenses/LICENSE,sha256=_sOIKJWdD2o1WwwDIwYB2qTP2nlSWqT5Tyg9jr1Xa4w,1070
12
- pyobservability-1.2.0.dist-info/METADATA,sha256=WEEJiWj1F32ixoMA7n8Cc-3bOQpeGn_p586qh9PjfEk,7037
13
- pyobservability-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
- pyobservability-1.2.0.dist-info/entry_points.txt,sha256=DSGIr_VA8Tb3FYa2iNUYpf55eAvuFCAoInNS4ngXaME,57
15
- pyobservability-1.2.0.dist-info/top_level.txt,sha256=p20T0EmihDYW1uMintRXr7X9bg3XWYKyoSbBHOVC1xI,16
16
- pyobservability-1.2.0.dist-info/RECORD,,
11
+ pyobservability-1.3.0.dist-info/licenses/LICENSE,sha256=_sOIKJWdD2o1WwwDIwYB2qTP2nlSWqT5Tyg9jr1Xa4w,1070
12
+ pyobservability-1.3.0.dist-info/METADATA,sha256=FJSF4L10qUjlQMYDKxJmuHrRkWmSLmOConJB5MKufOY,6537
13
+ pyobservability-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
14
+ pyobservability-1.3.0.dist-info/entry_points.txt,sha256=DSGIr_VA8Tb3FYa2iNUYpf55eAvuFCAoInNS4ngXaME,57
15
+ pyobservability-1.3.0.dist-info/top_level.txt,sha256=p20T0EmihDYW1uMintRXr7X9bg3XWYKyoSbBHOVC1xI,16
16
+ pyobservability-1.3.0.dist-info/RECORD,,