aboutsummaryrefslogtreecommitdiff
path: root/app/views/stats
diff options
context:
space:
mode:
authorGravatar maTh <1645099+math-GH@users.noreply.github.com> 2025-01-21 23:45:22 +0100
committerGravatar GitHub <noreply@github.com> 2025-01-21 23:45:22 +0100
commitafb6f788fa9c90817c9bd21e91993f4ddb462621 (patch)
tree0408f1f354c15aa13e09b94c2f924c43c3afbfc8 /app/views/stats
parentf2c820dccd18eea9213a27d0401569b0f6e9a402 (diff)
Improve stats page layout (#7243)
* New stats box layout * repartition: table overview improved with links and icons * Show selected feed name in title * i18n string: overview * fix * fix * fix * delete unused stat in frss * Update app/i18n/fr/admin.php --------- Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Diffstat (limited to 'app/views/stats')
-rw-r--r--app/views/stats/index.phtml146
-rw-r--r--app/views/stats/repartition.phtml132
2 files changed, 149 insertions, 129 deletions
diff --git a/app/views/stats/index.phtml b/app/views/stats/index.phtml
index f3fc3e986..88c4f0a3c 100644
--- a/app/views/stats/index.phtml
+++ b/app/views/stats/index.phtml
@@ -6,77 +6,77 @@
<main class="post">
<h1><?= _t('admin.stats.main') ?></h1>
- <div class="stat-grid">
- <div class="stat half">
- <h2><?= _t('admin.stats.entry_repartition') ?></h2>
- <div class="table-wrapper scrollbar-thin">
- <table>
- <thead>
- <tr>
- <th> </th>
- <th><?= _t('admin.stats.main_stream') ?></th>
- <th><?= _t('admin.stats.all_feeds') ?></th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <th><?= _t('admin.stats.status_total') ?></th>
- <td class="numeric"><?= format_number($this->repartitions['main_stream']['total'] ?? -1) ?></td>
- <td class="numeric"><?= format_number($this->repartitions['all_feeds']['total'] ?? -1) ?></td>
- </tr>
- <tr>
- <th><?= _t('admin.stats.status_read') ?></th>
- <td class="numeric"><?= format_number($this->repartitions['main_stream']['count_reads'] ?? -1) ?></td>
- <td class="numeric"><?= format_number($this->repartitions['all_feeds']['count_reads'] ?? -1) ?></td>
- </tr>
- <tr>
- <th><?= _t('admin.stats.status_unread') ?></th>
- <td class="numeric"><?= format_number($this->repartitions['main_stream']['count_unreads'] ?? -1) ?></td>
- <td class="numeric"><?= format_number($this->repartitions['all_feeds']['count_unreads'] ?? -1) ?></td>
- </tr>
- <tr>
- <th><?= _t('admin.stats.status_favorites') ?></th>
- <td class="numeric"><?= format_number($this->repartitions['main_stream']['count_favorites'] ?? -1) ?></td>
- <td class="numeric"><?= format_number($this->repartitions['all_feeds']['count_favorites'] ?? -1) ?></td>
- </tr>
- </tbody>
- </table>
- </div>
+ <div class="box">
+ <div class="box-title"><h2><?= _t('admin.stats.entry_repartition') ?></h2></div>
+ <div class="box-content scrollbar-thin">
+ <table>
+ <thead>
+ <tr>
+ <th> </th>
+ <th><?= _t('admin.stats.main_stream') ?></th>
+ <th><?= _t('admin.stats.all_feeds') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th><?= _t('admin.stats.status_total') ?></th>
+ <td class="numeric"><?= format_number($this->repartitions['main_stream']['total'] ?? -1) ?></td>
+ <td class="numeric"><?= format_number($this->repartitions['all_feeds']['total'] ?? -1) ?></td>
+ </tr>
+ <tr>
+ <th><?= _t('admin.stats.status_read') ?></th>
+ <td class="numeric"><?= format_number($this->repartitions['main_stream']['count_reads'] ?? -1) ?></td>
+ <td class="numeric"><?= format_number($this->repartitions['all_feeds']['count_reads'] ?? -1) ?></td>
+ </tr>
+ <tr>
+ <th><?= _t('admin.stats.status_unread') ?></th>
+ <td class="numeric"><?= format_number($this->repartitions['main_stream']['count_unreads'] ?? -1) ?></td>
+ <td class="numeric"><?= format_number($this->repartitions['all_feeds']['count_unreads'] ?? -1) ?></td>
+ </tr>
+ <tr>
+ <th><?= _t('admin.stats.status_favorites') ?></th>
+ <td class="numeric"><?= format_number($this->repartitions['main_stream']['count_favorites'] ?? -1) ?></td>
+ <td class="numeric"><?= format_number($this->repartitions['all_feeds']['count_favorites'] ?? -1) ?></td>
+ </tr>
+ </tbody>
+ </table>
</div>
+ </div>
+
- <div class="stat half">
- <h2><?= _t('admin.stats.top_feed') ?></h2>
- <div class="table-wrapper scrollbar-thin">
- <table>
- <thead>
+ <div class="box double-height">
+ <div class="box-title"><h2><?= _t('admin.stats.top_feed') ?></h2></div>
+ <div class="box-content scrollbar-thin">
+ <table>
+ <thead>
+ <tr>
+ <th><?= _t('admin.stats.feed') ?></th>
+ <th><?= _t('admin.stats.category') ?></th>
+ <th><?= _t('admin.stats.entry_count') ?></th>
+ <th><?= _t('admin.stats.percent_of_total') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($this->topFeed as $feed): ?>
<tr>
- <th><?= _t('admin.stats.feed') ?></th>
- <th><?= _t('admin.stats.category') ?></th>
- <th><?= _t('admin.stats.entry_count') ?></th>
- <th><?= _t('admin.stats.percent_of_total') ?></th>
+ <td><a href="<?= _url('stats', 'repartition', 'id', $feed['id']) ?>"><?= $feed['name'] ?></a></td>
+ <td><?= $feed['category'] ?></td>
+ <td class="numeric"><?= format_number($feed['count']) ?></td>
+ <td class="numeric"><?php
+ if (!empty($this->repartitions['all_feeds']['total'])) {
+ echo format_number($feed['count'] / $this->repartitions['all_feeds']['total'] * 100, 1);
+ }
+ ?></td>
</tr>
- </thead>
- <tbody>
- <?php foreach ($this->topFeed as $feed): ?>
- <tr>
- <td><a href="<?= _url('stats', 'repartition', 'id', $feed['id']) ?>"><?= $feed['name'] ?></a></td>
- <td><?= $feed['category'] ?></td>
- <td class="numeric"><?= format_number($feed['count']) ?></td>
- <td class="numeric"><?php
- if (!empty($this->repartitions['all_feeds']['total'])) {
- echo format_number($feed['count'] / $this->repartitions['all_feeds']['total'] * 100, 1);
- }
- ?></td>
- </tr>
- <?php endforeach; ?>
- </tbody>
- </table>
- </div>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
</div>
-
- <div class="stat">
- <h2><?= _t('admin.stats.entry_per_day') ?></h2>
- <div>
+ </div>
+ <br />
+ <div class="box double-width double-height">
+ <div class="box-title"><h2><?= _t('admin.stats.entry_per_day') ?></h2></div>
+ <div class="box-content scrollbar-thin">
<canvas id="statsEntriesPerDay"></canvas>
<script class="jsonData-stats" type="application/json">
<?= json_encode([
@@ -140,10 +140,10 @@ $entryLabels = array_keys($entryData);
$entryColors = array_map(fn($label) => $colorMap[$label], $entryLabels);
$entryValues = array_values($entryData);
?>
-
- <div class="stat half">
- <h2><?= _t('admin.stats.feed_per_category') ?></h2>
- <div>
+<br id="stats_per_category" />
+ <div class="box double-height" id="feed_per_category">
+ <div class="box-title"><h2><?= _t('admin.stats.feed_per_category') ?></h2><a href="#feed_per_category" class="btn target-hidden">+</a><a href="#stats_per_category" class="btn target-visible">-</a></div>
+ <div class="box-content scrollbar-thin">
<canvas id="statsFeedsPerCategory"></canvas>
<script class="jsonData-stats" type="application/json">
<?= json_encode([
@@ -157,9 +157,9 @@ $entryValues = array_values($entryData);
</div>
</div>
- <div class="stat half">
- <h2><?= _t('admin.stats.entry_per_category') ?></h2>
- <div>
+ <div class="box double-height" id="entry_per_category">
+ <div class="box-title"><h2><?= _t('admin.stats.entry_per_category') ?></h2><a href="#entry_per_category" class="btn target-hidden">+</a><a href="#stats_per_category" class="btn target-visible">-</a></div>
+ <div class="box-content scrollbar-thin">
<canvas id="statsEntriesPerCategory"></canvas>
<script class="jsonData-stats" type="application/json">
<?= json_encode([
diff --git a/app/views/stats/repartition.phtml b/app/views/stats/repartition.phtml
index e212e79bf..59cae9e1a 100644
--- a/app/views/stats/repartition.phtml
+++ b/app/views/stats/repartition.phtml
@@ -2,9 +2,11 @@
declare(strict_types=1);
/** @var FreshRSS_ViewStats $this */
$this->partial('aside_subscription');
+ $feedname = _t('admin.stats.all_feeds');
?>
-<main class="post ">
- <h1><?= _t('admin.stats.repartition') ?></h1>
+
+<nav class="nav_menu">
+ <a class="btn toggle_aside" href="#aside_feed"><?= _i('category') ?></a>
<select id="feed_select" class="select-change">
<option data-url="<?= _url('stats', 'repartition') ?>"><?= _t('admin.stats.all_feeds') ?></option>
@@ -16,6 +18,7 @@
if ($this->feed !== null && $feed->id() == $this->feed->id()) {
echo '<option value="', $feed->id(), '" selected="selected" data-url="',
_url('stats', 'repartition', 'id', $feed->id()), '">', $feed->name(), '</option>';
+ $feedname = $feed->name();
} else {
echo '<option value="', $feed->id(), '" data-url="',
_url('stats', 'repartition', 'id', $feed->id()), '">', $feed->name(), '</option>';
@@ -31,74 +34,91 @@
<?= _i('configure') ?> <?= _t('gen.action.manage') ?>
</a>
<?php }?>
+</nav>
+
+<main class="post">
+ <h1><?= _t('admin.stats.repartition', $feedname) ?></h1>
- <div class="stat-grid">
- <div class="stat table-wrapper scrollbar-thin">
+ <div class="box double-width">
+ <div class="box-title"><h2><?= _t('admin.stats.overview') ?></h2></div>
+ <div class="box-content scrollbar-thin">
<table>
<tr>
<th><?= _t('admin.stats.status_total') ?></th>
- <th><?= _t('admin.stats.status_read') ?></th>
- <th><?= _t('admin.stats.status_unread') ?></th>
- <th><?= _t('admin.stats.status_favorites') ?></th>
+ <th><?= _i('read') ?> <?= _t('admin.stats.status_read') ?></th>
+ <th><?= _i('unread') ?> <?= _t('admin.stats.status_unread') ?></th>
+ <th><?= _i('starred') ?> <?= _t('admin.stats.status_favorites') ?></th>
</tr>
<tr>
- <td class="numeric"><?= $this->repartition['total'] ?? -1 ?></td>
- <td class="numeric"><?= $this->repartition['count_reads'] ?? -1 ?></td>
- <td class="numeric"><?= $this->repartition['count_unreads'] ?? -1 ?></td>
- <td class="numeric"><?= $this->repartition['count_favorites'] ?? -1 ?></td>
+ <?php
+ $feedID = $this->feed !== null ? $this->feed->id() : 0;
+ if ($feedID === 0) { ?>
+ <td class="numeric"><?= $this->repartition['total'] ?? -1 ?></td>
+ <td class="numeric"><?= $this->repartition['count_reads'] ?? -1 ?></td>
+ <td class="numeric"><?= $this->repartition['count_unreads'] ?? -1 ?></td>
+ <td class="numeric"><a href="<?= _url('index', 'index', 'get', 's') ?>" title="<?= _t('gen.action.filter') ?>"><?= $this->repartition['count_favorites'] ?? -1 ?></a></td>
+ <?php
+ } else {
+ ?>
+ <td class="numeric"><a href="<?= _url('index', 'index', 'get', 'f_' . $feedID, 'state', FreshRSS_Entry::STATE_ALL) ?>" title="<?= _t('gen.action.filter') ?>"><?= $this->repartition['total'] ?? -1 ?></a></td>
+ <td class="numeric"><a href="<?= _url('index', 'index', 'get', 'f_' . $feedID, 'state', FreshRSS_Entry::STATE_READ) ?>" title="<?= _t('gen.action.filter') ?>"><?= $this->repartition['count_reads'] ?? -1 ?></a></td>
+ <td class="numeric"><a href="<?= _url('index', 'index', 'get', 'f_' . $feedID, 'state', FreshRSS_Entry::STATE_NOT_READ) ?>" title="<?= _t('gen.action.filter') ?>"><?= $this->repartition['count_unreads'] ?? -1 ?></a></td>
+ <td class="numeric"><a href="<?= _url('index', 'index', 'get', 'f_' . $feedID, 'state', FreshRSS_Entry::STATE_FAVORITE) ?>" title="<?= _t('gen.action.filter') ?>"><?= $this->repartition['count_favorites'] ?? -1 ?></a></td>
+ <?php } ?>
</tr>
</table>
</div>
+ </div>
- <div class="stat">
- <h2><?= _t('admin.stats.entry_per_hour', $this->averageHour) ?></h2>
- <div>
- <canvas id="statsEntriesPerHour"></canvas>
- <script class="jsonData-stats" type="application/json">
- <?php
- echo json_encode([
- 'canvasID' => 'statsEntriesPerHour',
- 'charttype' => 'bar',
- 'data' => $this->repartitionHour,
- 'label' => _t('admin.stats.entry_count'),
- 'xAxisLabels' => $this->hours24Labels
- ], JSON_UNESCAPED_UNICODE);
- ?></script>
- </div>
+ <div class="box double-width double-height">
+ <div class="box-title"><h2><?= _t('admin.stats.entry_per_hour', $this->averageHour) ?></h2></div>
+ <div class="box-content scrollbar-thin">
+ <canvas id="statsEntriesPerHour"></canvas>
+ <script class="jsonData-stats" type="application/json">
+ <?php
+ echo json_encode([
+ 'canvasID' => 'statsEntriesPerHour',
+ 'charttype' => 'bar',
+ 'data' => $this->repartitionHour,
+ 'label' => _t('admin.stats.entry_count'),
+ 'xAxisLabels' => $this->hours24Labels
+ ], JSON_UNESCAPED_UNICODE);
+ ?></script>
</div>
+ </div>
- <div class="stat half">
- <h2><?= _t('admin.stats.entry_per_day_of_week', $this->averageDayOfWeek) ?></h2>
- <div>
- <canvas id="statsEntriesPerDayOfWeek"></canvas>
- <script class="jsonData-stats" type="application/json">
- <?php
- echo json_encode([
- 'canvasID' => 'statsEntriesPerDayOfWeek',
- 'charttype' => 'bar',
- 'data' => $this->repartitionDayOfWeek,
- 'label' => _t('admin.stats.entry_count'),
- 'xAxisLabels' => $this->days,
- ], JSON_UNESCAPED_UNICODE);
- ?></script>
- </div>
+ <br />
+ <div class="box">
+ <div class="box-title"><h2><?= _t('admin.stats.entry_per_day_of_week', $this->averageDayOfWeek) ?></h2></div>
+ <div class="box-content scrollbar-thin">
+ <canvas id="statsEntriesPerDayOfWeek"></canvas>
+ <script class="jsonData-stats" type="application/json">
+ <?php
+ echo json_encode([
+ 'canvasID' => 'statsEntriesPerDayOfWeek',
+ 'charttype' => 'bar',
+ 'data' => $this->repartitionDayOfWeek,
+ 'label' => _t('admin.stats.entry_count'),
+ 'xAxisLabels' => $this->days,
+ ], JSON_UNESCAPED_UNICODE);
+ ?></script>
</div>
+ </div>
- <div class="stat half">
- <h2><?= _t('admin.stats.entry_per_month', $this->averageMonth) ?></h2>
- <div>
- <canvas id="statsEntriesPerMonth"></canvas>
- <script class="jsonData-stats" type="application/json">
- <?php
- echo json_encode([
- 'canvasID' => 'statsEntriesPerMonth',
- 'charttype' => 'bar',
- 'data' => $this->repartitionMonth,
- 'label' => _t('admin.stats.entry_count'),
- 'xAxisLabels' => $this->months,
- ], JSON_UNESCAPED_UNICODE);
- ?></script>
- </div>
+ <div class="box">
+ <div class="box-title"><h2><?= _t('admin.stats.entry_per_month', $this->averageMonth) ?></h2></div>
+ <div class="box-content scrollbar-thin">
+ <canvas id="statsEntriesPerMonth"></canvas>
+ <script class="jsonData-stats" type="application/json">
+ <?php
+ echo json_encode([
+ 'canvasID' => 'statsEntriesPerMonth',
+ 'charttype' => 'bar',
+ 'data' => $this->repartitionMonth,
+ 'label' => _t('admin.stats.entry_count'),
+ 'xAxisLabels' => $this->months,
+ ], JSON_UNESCAPED_UNICODE);
+ ?></script>
</div>
</div>
</main>