diff options
| author | 2025-01-21 23:45:22 +0100 | |
|---|---|---|
| committer | 2025-01-21 23:45:22 +0100 | |
| commit | afb6f788fa9c90817c9bd21e91993f4ddb462621 (patch) | |
| tree | 0408f1f354c15aa13e09b94c2f924c43c3afbfc8 /app/views/stats | |
| parent | f2c820dccd18eea9213a27d0401569b0f6e9a402 (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.phtml | 146 | ||||
| -rw-r--r-- | app/views/stats/repartition.phtml | 132 |
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> |
