Skip to content

Commit 297d1e2

Browse files
committed
add client-side CSV export for monthly/daily tables
1 parent 05e0ca3 commit 297d1e2

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

css/dashboard.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ body.rtl .statify-chart * {
7979
width: 80%;
8080
}
8181

82+
.statify-table + a.button {
83+
margin: 1em 0 0 1em;
84+
}
85+
8286

8387
#statify_dashboard .postbox-title-action a,
8488
#statify_dashboard .settings-link a {

inc/class-statify.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ public static function add_js(): void {
269269
'statifyDashboard',
270270
array(
271271
'i18n' => array(
272-
'months' => array_map(
272+
'sitename' => sanitize_key( get_bloginfo( 'name' ) ),
273+
'months' => array_map(
273274
function ( $m ) {
274275
return date_i18n( 'M', strtotime( '0000-' . $m . '-01' ) );
275276
},

js/dashboard.js

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,15 @@
354354

355355
tbody.insertBefore(row, tbody.firstChild);
356356
}
357+
358+
addExportButton(table);
357359
}
358360

359361
/**
360362
* Render yearly table.
361363
*
362-
* @param {HTMLElement} table Root element.
363-
* @param {any} data Data from API.
364+
* @param {HTMLTableElement} table Root element.
365+
* @param {any} data Data from API.
364366
*/
365367
function renderDailyTable(table, data) {
366368
const rows = Array.from(table.querySelectorAll('tbody > tr'));
@@ -427,6 +429,8 @@
427429
for (const row of rows) {
428430
row.classList.remove('placeholder');
429431
}
432+
433+
addExportButton(table);
430434
}
431435

432436
/**
@@ -500,4 +504,43 @@
500504
'</p>';
501505
});
502506
}
507+
508+
/**
509+
* Add a CSV export button to a table.
510+
*
511+
* @param {HTMLTableElement} table Table to process
512+
*/
513+
function addExportButton(table) {
514+
const exportBtn = document.createElement('a');
515+
exportBtn.classList.add('button');
516+
exportBtn.role = 'button';
517+
518+
// Generate filename from table caption.
519+
exportBtn.download =
520+
statifyDashboard.i18n.sitename +
521+
'-' +
522+
table.caption.innerText.replaceAll(/\s+/g, '_') +
523+
'-export-' +
524+
new Date()
525+
.toISOString()
526+
.replace('T', '_')
527+
.replaceAll(':', '-')
528+
.substring(0, 16) +
529+
'.csv';
530+
531+
// Generate CSV on demand.
532+
exportBtn.innerText = wp.i18n.__('Export (CSV)', 'statify');
533+
exportBtn.addEventListener('click', () => {
534+
exportBtn.href =
535+
'data:text/csv;charset=utf-8,' +
536+
Array.from(table.rows)
537+
.map((row) =>
538+
Array.from(row.cells)
539+
.map((col) => col.innerText)
540+
.join(',')
541+
)
542+
.join('\r\n');
543+
});
544+
table.after(exportBtn);
545+
}
503546
}

views/view-dashboard.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ class="nav-tab<?php echo ( $selected_year === $y ) ? ' nav-tab-active' : ''; ?>"
9191
<section>
9292
<h3><?php esc_html_e( 'Monthly / Yearly Views', 'statify' ); ?></h3>
9393
<table id="statify-table-yearly" class="wp-list-table widefat striped statify-table">
94+
<caption class="screen-reader-text"><?php esc_html_e( 'Monthly Views', 'statify' ); ?></caption>
9495
<thead>
9596
<tr>
9697
<th scope="col"><?php esc_html_e( 'Year', 'statify' ); ?></th>
@@ -134,6 +135,15 @@ class="nav-tab<?php echo ( $selected_year === $y ) ? ' nav-tab-active' : ''; ?>"
134135
?>
135136
</h3>
136137
<table id="statify-table-daily" class="wp-list-table widefat striped statify-table">
138+
<caption class="screen-reader-text">
139+
<?php
140+
printf(
141+
/* translators: %s is replaced by a year number (e.g. 2023) */
142+
esc_html__( 'Daily Views %s', 'statify' ),
143+
esc_html( $selected_year )
144+
);
145+
?>
146+
</caption>
137147
<thead>
138148
<tr>
139149
<th><?php esc_html_e( 'Day', 'statify' ); ?></th>

0 commit comments

Comments
 (0)