chg: [instance:home] Added support of both `modified` and `created` in stat panels
parent
24e5a94662
commit
509b203591
|
@ -21,7 +21,6 @@ class InstanceController extends AppController
|
||||||
|
|
||||||
public function home()
|
public function home()
|
||||||
{
|
{
|
||||||
// $this->set('md', file_get_contents(ROOT . '/README.md'));
|
|
||||||
$statistics = $this->Instance->getStatistics();
|
$statistics = $this->Instance->getStatistics();
|
||||||
$this->set('statistics', $statistics);
|
$this->set('statistics', $statistics);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,47 +25,64 @@ class InstanceTable extends AppTable
|
||||||
return $validator;
|
return $validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStatistics($days=30): array
|
public function getStatistics(int $days=30): array
|
||||||
{
|
{
|
||||||
$models = ['Individuals', 'Organisations', 'Alignments', 'EncryptionKeys', 'SharingGroups', 'Users', 'Broods', 'Tags.Tags'];
|
$models = ['Individuals', 'Organisations', 'Alignments', 'EncryptionKeys', 'SharingGroups', 'Users', 'Broods', 'Tags.Tags'];
|
||||||
foreach ($models as $model) {
|
foreach ($models as $model) {
|
||||||
$table = TableRegistry::getTableLocator()->get($model);
|
$table = TableRegistry::getTableLocator()->get($model);
|
||||||
$statistics[$model]['amount'] = $table->find()->all()->count();
|
$statistics[$model]['created'] = $this->getActivityStatistic($table, $days, 'created');
|
||||||
if ($table->behaviors()->has('Timestamp')) {
|
$statistics[$model]['modified'] = $this->getActivityStatistic($table, $days, 'modified');
|
||||||
$query = $table->find();
|
|
||||||
$query->select([
|
|
||||||
'count' => $query->func()->count('id'),
|
|
||||||
'date' => 'DATE(modified)',
|
|
||||||
])
|
|
||||||
->where(['modified >' => new \DateTime("-{$days} days")])
|
|
||||||
->group(['date'])
|
|
||||||
->order(['date']);
|
|
||||||
$data = $query->toArray();
|
|
||||||
$interval = new \DateInterval('P1D');
|
|
||||||
$period = new \DatePeriod(new \DateTime("-{$days} days"), $interval, new \DateTime());
|
|
||||||
$timeline = [];
|
|
||||||
foreach ($period as $date) {
|
|
||||||
$timeline[$date->format("Y-m-d")] = [
|
|
||||||
'time' => $date->format("Y-m-d"),
|
|
||||||
'count' => 0
|
|
||||||
];
|
|
||||||
}
|
|
||||||
foreach ($data as $entry) {
|
|
||||||
$timeline[$entry->date]['count'] = $entry->count;
|
|
||||||
}
|
|
||||||
$statistics[$model]['timeline'] = array_values($timeline);
|
|
||||||
|
|
||||||
$startCount = $table->find()->where(['modified <' => new \DateTime("-{$days} days")])->all()->count();
|
|
||||||
$endCount = $statistics[$model]['amount'];
|
|
||||||
$statistics[$model]['variation'] = $endCount - $startCount;
|
|
||||||
} else {
|
|
||||||
$statistics[$model]['timeline'] = [];
|
|
||||||
$statistics[$model]['variation'] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return $statistics;
|
return $statistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getActivityStatistic(Object $table, int $days=30, string $field='modified', bool $includeTimeline=true): array
|
||||||
|
{
|
||||||
|
$statistics = [];
|
||||||
|
$statistics['amount'] = $table->find()->all()->count();
|
||||||
|
if ($table->behaviors()->has('Timestamp') && $includeTimeline) {
|
||||||
|
$statistics['timeline'] = $this->buildTimeline($table, $days, $field);
|
||||||
|
$statistics['variation'] = $table->find()->where(["{$field} >" => new \DateTime("-{$days} days")])->all()->count(); - $statistics['amount'];
|
||||||
|
} else {
|
||||||
|
$statistics['timeline'] = [];
|
||||||
|
$statistics['variation'] = 0;
|
||||||
|
}
|
||||||
|
return $statistics;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildTimeline(Object $table, int $days=30, string $field='modified'): array
|
||||||
|
{
|
||||||
|
$timeline = [];
|
||||||
|
$authorizedFields = ['modified', 'created'];
|
||||||
|
if ($table->behaviors()->has('Timestamp')) {
|
||||||
|
if (!in_array($field, $authorizedFields)) {
|
||||||
|
throw new MethodNotAllowedException(__('Cannot construct timeline for field `{0}`', $field));
|
||||||
|
}
|
||||||
|
$query = $table->find();
|
||||||
|
$query->select([
|
||||||
|
'count' => $query->func()->count('id'),
|
||||||
|
'date' => "DATE({$field})",
|
||||||
|
])
|
||||||
|
->where(["{$field} >" => new \DateTime("-{$days} days")])
|
||||||
|
->group(['date'])
|
||||||
|
->order(['date']);
|
||||||
|
$data = $query->toArray();
|
||||||
|
$interval = new \DateInterval('P1D');
|
||||||
|
$period = new \DatePeriod(new \DateTime("-{$days} days"), $interval, new \DateTime());
|
||||||
|
foreach ($period as $date) {
|
||||||
|
$timeline[$date->format("Y-m-d")] = [
|
||||||
|
'time' => $date->format("Y-m-d"),
|
||||||
|
'count' => 0
|
||||||
|
];
|
||||||
|
}
|
||||||
|
foreach ($data as $entry) {
|
||||||
|
$timeline[$entry->date]['count'] = $entry->count;
|
||||||
|
}
|
||||||
|
$timeline = array_values($timeline);
|
||||||
|
}
|
||||||
|
return $timeline;
|
||||||
|
}
|
||||||
|
|
||||||
public function searchAll($value, $limit=5, $model=null)
|
public function searchAll($value, $limit=5, $model=null)
|
||||||
{
|
{
|
||||||
$results = [];
|
$results = [];
|
||||||
|
|
|
@ -32,7 +32,7 @@ $bookmarks = !empty($loggedUser->user_settings_by_name['ui.bookmarks']['value'])
|
||||||
<?= __('Activity') ?>
|
<?= __('Activity') ?>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<?php foreach ($statistics as $modelName => $statistics) : ?>
|
<?php foreach ($statistics as $modelName => $statisticForModel) : ?>
|
||||||
<div class="col-sm-6 col-md-5 col-l-4 col-xl-3 mb-3">
|
<div class="col-sm-6 col-md-5 col-l-4 col-xl-3 mb-3">
|
||||||
<?php
|
<?php
|
||||||
$exploded = explode('.', $modelName);
|
$exploded = explode('.', $modelName);
|
||||||
|
@ -47,9 +47,9 @@ $bookmarks = !empty($loggedUser->user_settings_by_name['ui.bookmarks']['value'])
|
||||||
);
|
);
|
||||||
echo $this->element('widgets/highlight-panel', [
|
echo $this->element('widgets/highlight-panel', [
|
||||||
'titleHtml' => $panelTitle,
|
'titleHtml' => $panelTitle,
|
||||||
'number' => $statistics['amount'],
|
'number' => $statisticForModel['created']['amount'],
|
||||||
'variation' => $statistics['variation'] ?? '',
|
'variation' => $statisticForModel['created']['variation'] ?? '',
|
||||||
'chartData' => $statistics['timeline'] ?? []
|
'timeline' => $statisticForModel ?? []
|
||||||
]);
|
]);
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
$chartOptions = $chartOptions ?? [];
|
$chartOptions = $chartOptions ?? [];
|
||||||
$chartData = $chartData ?? [];
|
|
||||||
$seed = mt_rand();
|
$seed = mt_rand();
|
||||||
$chartId = "chart-{$seed}";
|
$chartId = "chart-{$seed}";
|
||||||
|
|
||||||
// Transform the chart data into the expected format
|
$chartData = $chartData ?? [];
|
||||||
$data = [];
|
$chartSeries = [];
|
||||||
foreach ($chartData as $i => $entry) {
|
if (!empty($series)) {
|
||||||
$data[] = $entry['count'];
|
$chartSeries = $series;
|
||||||
|
} else {
|
||||||
|
// Transform the chart data into the expected format
|
||||||
|
$data = [];
|
||||||
|
foreach ($chartData as $i => $entry) {
|
||||||
|
$data[] = $entry['count'];
|
||||||
|
}
|
||||||
|
$chartSeries = [
|
||||||
|
['data' => $data]
|
||||||
|
];
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
@ -20,7 +28,7 @@ foreach ($chartData as $i => $entry) {
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
chart: {
|
chart: {
|
||||||
id: '<?= $chartId ?>',
|
id: '<?= $chartId ?>',
|
||||||
type: 'bar',
|
type: 'line',
|
||||||
sparkline: {
|
sparkline: {
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
|
@ -35,10 +43,7 @@ foreach ($chartData as $i => $entry) {
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
series: [{
|
series: <?= json_encode($chartSeries) ?>,
|
||||||
data: <?= json_encode($data) ?>,
|
|
||||||
}],
|
|
||||||
colors: ['var(--bs-light)'],
|
|
||||||
tooltip: {
|
tooltip: {
|
||||||
x: {
|
x: {
|
||||||
show: false
|
show: false
|
||||||
|
@ -46,11 +51,11 @@ foreach ($chartData as $i => $entry) {
|
||||||
y: {
|
y: {
|
||||||
title: {
|
title: {
|
||||||
formatter: function formatter(val) {
|
formatter: function formatter(val) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
theme: '<?= !empty($darkMode) ? 'dark' : 'light' ?>'
|
theme: 'dark'
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const chartOptions = Object.assign({}, defaultOptions, passedOptions)
|
const chartOptions = Object.assign({}, defaultOptions, passedOptions)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
// debug($timeline);
|
||||||
|
// $chartData = $timeline['modified']['timeline'];
|
||||||
$variationIcon = '';
|
$variationIcon = '';
|
||||||
$variationClass = '';
|
$variationClass = '';
|
||||||
if ($variation == 0) {
|
if ($variation == 0) {
|
||||||
|
@ -11,6 +13,22 @@ if ($variation == 0) {
|
||||||
$variationClass = 'bg-danger';
|
$variationClass = 'bg-danger';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$series = [];
|
||||||
|
if (!empty($timeline['created']['timeline'])) {
|
||||||
|
$series[0]['name'] = __('Created');
|
||||||
|
$series[0]['type'] = 'column';
|
||||||
|
foreach ($timeline['created']['timeline'] as $entry) {
|
||||||
|
$series[0]['data'][] = $entry['count'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($timeline['modified']['timeline'])) {
|
||||||
|
$series[1]['name'] = __('Modified');
|
||||||
|
$series[1]['type'] = 'line';
|
||||||
|
foreach ($timeline['modified']['timeline'] as $entry) {
|
||||||
|
$series[1]['data'][] = $entry['count'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$variationHtml = sprintf(
|
$variationHtml = sprintf(
|
||||||
'<div class="badge %s fw-bold"><span class="%s me-2 align-middle"></span>%s</div>',
|
'<div class="badge %s fw-bold"><span class="%s me-2 align-middle"></span>%s</div>',
|
||||||
$variationClass,
|
$variationClass,
|
||||||
|
@ -25,9 +43,12 @@ $leftContent = sprintf('<div class="">%s</div><h2 class="my-2">%s</h2>%s',
|
||||||
$variationHtml
|
$variationHtml
|
||||||
);
|
);
|
||||||
$rightContent = sprintf('<div class="">%s</div>', $this->element('charts/bar', [
|
$rightContent = sprintf('<div class="">%s</div>', $this->element('charts/bar', [
|
||||||
'chartData' => $chartData,
|
'series' => $series,
|
||||||
'chartOptions' => [
|
'chartOptions' => [
|
||||||
|
// 'colors' => ['var(--bs-light)', 'var(--bs-primary)'],
|
||||||
|
'stroke' => [
|
||||||
|
'width' => [0, 2]
|
||||||
|
],
|
||||||
]
|
]
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue