new: [instance:home] Added statistics and highlight panel - WiP
parent
6a68290561
commit
14e0fa90b3
|
@ -19,7 +19,9 @@ class InstanceController extends AppController
|
|||
|
||||
public function home()
|
||||
{
|
||||
$this->set('md', file_get_contents(ROOT . '/README.md'));
|
||||
// $this->set('md', file_get_contents(ROOT . '/README.md'));
|
||||
$statistics = $this->Instance->getStatistics();
|
||||
$this->set('statistics', $statistics);
|
||||
}
|
||||
|
||||
public function status()
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Model\Table;
|
|||
|
||||
use App\Model\Table\AppTable;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Validation\Validator;
|
||||
use Migrations\Migrations;
|
||||
|
||||
|
@ -21,6 +22,47 @@ class InstanceTable extends AppTable
|
|||
return $validator;
|
||||
}
|
||||
|
||||
public function getStatistics($days=7): array
|
||||
{
|
||||
$models = ['Individuals', 'Organisations', 'Alignments', 'EncryptionKeys', 'SharingGroups', 'Users', 'Tags.Tags'];
|
||||
foreach ($models as $model) {
|
||||
$table = TableRegistry::getTableLocator()->get($model);
|
||||
$statistics[$model]['amount'] = $table->find()->all()->count();
|
||||
if ($table->behaviors()->has('Timestamp')) {
|
||||
$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;
|
||||
}
|
||||
|
||||
public function getMigrationStatus()
|
||||
{
|
||||
$migrations = new Migrations();
|
||||
|
|
|
@ -979,6 +979,7 @@ class BoostrapCard extends BootstrapGeneric
|
|||
'headerHTML' => '',
|
||||
'footerHTML' => '',
|
||||
'bodyHTML' => '',
|
||||
'class' => '',
|
||||
'headerClass' => '',
|
||||
'bodyClass' => '',
|
||||
'footerClass' => '',
|
||||
|
@ -1010,6 +1011,7 @@ class BoostrapCard extends BootstrapGeneric
|
|||
'card',
|
||||
!empty($this->options['variant']) ? "bg-{$this->options['variant']}" : '',
|
||||
!empty($this->options['variant']) ? $this->getTextClassForVariant($this->options['variant']) : '',
|
||||
h($this->options['class']),
|
||||
],
|
||||
], implode('', [$this->genHeader(), $this->genBody(), $this->genFooter()]));
|
||||
return $card;
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
<?php
|
||||
$Parsedown = new Parsedown();
|
||||
echo $Parsedown->text($md);
|
||||
// $Parsedown = new Parsedown();
|
||||
// echo $Parsedown->text($md);
|
||||
|
||||
?>
|
||||
|
||||
<div class="row">
|
||||
<?php foreach ($statistics as $modelName => $statistics): ?>
|
||||
<div class="col-sm-6 col-md-4 col-l-3 col-xl-2 mb-2">
|
||||
<?php
|
||||
$modelName = explode('.', $modelName);
|
||||
$modelName = $modelName[count($modelName)-1];
|
||||
echo $this->element('widgets/highlight-panel', [
|
||||
'title' => $modelName,
|
||||
'number' => $statistics['amount'],
|
||||
'variation' => $statistics['variation'] ?? '',
|
||||
'chartData' => $statistics['timeline'] ?? []
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</div>
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
$chartOptions = $chartOptions ?? [];
|
||||
$chartData = $chartData ?? [];
|
||||
$seed = mt_rand();
|
||||
$chartId = "chart-{$seed}";
|
||||
|
||||
// Transform the chart data into the expected format
|
||||
$data = [];
|
||||
foreach ($chartData as $i => $entry) {
|
||||
$data[] = $entry['count'];
|
||||
}
|
||||
?>
|
||||
|
||||
<div id="<?= $chartId ?>"></div>
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
|
||||
<script>
|
||||
(function() {
|
||||
const passedOptions = <?= json_encode($chartOptions) ?>;
|
||||
const defaultOptions = {
|
||||
chart: {
|
||||
id: '<?= $chartId ?>',
|
||||
type: 'bar',
|
||||
sparkline: {
|
||||
enabled: true
|
||||
},
|
||||
dropShadow: {
|
||||
enabled: true,
|
||||
top: 1,
|
||||
left: 1,
|
||||
blur: 2,
|
||||
opacity: 0.2,
|
||||
},
|
||||
animations: {
|
||||
enabled: false
|
||||
},
|
||||
},
|
||||
series: [{
|
||||
data: <?= json_encode($data) ?>,
|
||||
}],
|
||||
colors: ['var(--success)'],
|
||||
tooltip: {
|
||||
x: {
|
||||
show: false
|
||||
},
|
||||
y: {
|
||||
title: {
|
||||
formatter: function formatter(val) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
theme: '<?= !empty($darkMode) ? 'dark' : 'light' ?>'
|
||||
}
|
||||
}
|
||||
const chartOptions = Object.assign({}, defaultOptions, passedOptions)
|
||||
new ApexCharts(document.querySelector('#<?= $chartId ?>'), chartOptions).render();
|
||||
|
||||
// const chart = new ApexCharts(document.querySelector("#<?= $chartId ?>"), options);
|
||||
// chart.render();
|
||||
})()
|
||||
</script>
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
$variationIcon = '';
|
||||
$variationClass = '';
|
||||
if ($variation == 0) {
|
||||
$variationIcon = 'minus';
|
||||
} elseif ($variation > 0) {
|
||||
$variationIcon = 'arrow-up';
|
||||
$variationClass = 'text-success';
|
||||
} else {
|
||||
$variationIcon = 'arrow-down';
|
||||
$variationClass = 'text-danger';
|
||||
}
|
||||
|
||||
$variationHtml = sprintf('<div class="%s"><span class="%s mr-2"></span>%s</div>',
|
||||
$variationClass,
|
||||
$this->FontAwesome->getClass($variationIcon),
|
||||
!empty($variation) ? h($variation) : ''
|
||||
);
|
||||
|
||||
$leftContent = sprintf('<div class="">%s</div><h2 class="my-2">%s</h2>%s',
|
||||
h($title ?? ''),
|
||||
h($number ?? ''),
|
||||
$variationHtml
|
||||
);
|
||||
$rightContent = sprintf('<div class="">%s</div>', $this->element('charts/bar', [
|
||||
'chartData' => $chartData
|
||||
]));
|
||||
|
||||
$cardContent = sprintf('<div class="highlight-panel-container d-flex align-items-center justify-content-between"><div class="number-container">%s</div><div class="chart-container w-50">%s</div></div>', $leftContent, $rightContent);
|
||||
|
||||
echo $this->Bootstrap->card([
|
||||
'variant' => 'secondary',
|
||||
'bodyHTML' => $cardContent,
|
||||
'bodyClass' => 'p-3'
|
||||
]);
|
||||
|
||||
?>
|
Loading…
Reference in New Issue