default widgets

This commit is contained in:
iBNu Maksum 2025-02-17 13:54:18 +07:00
parent 69a7d842e0
commit 4bb5361d4b
No known key found for this signature in database
GPG Key ID: 7FC82848810579E5
15 changed files with 338 additions and 235 deletions

View File

@ -33,13 +33,19 @@ if (date("d") >= $reset_day) {
} }
$current_date = date('Y-m-d'); $current_date = date('Y-m-d');
$ui->assign('start_date', $start_date);
$ui->assign('current_date', $current_date);
$widgets = ORM::for_table('tbl_widgets')->selects("enabled", 1)->order_by_asc("orders")->findArray(); $widgets = ORM::for_table('tbl_widgets')->selects("enabled", 1)->order_by_asc("orders")->findArray();
$count = count($widgets); $count = count($widgets);
for ($i = 0; $i < $count; $i++) { for ($i = 0; $i < $count; $i++) {
try{ try{
require_once $WIDGET_PATH . DIRECTORY_SEPARATOR . $widgets[$i]['widget'].".php"; if(file_exists($WIDGET_PATH . DIRECTORY_SEPARATOR . $widgets[$i]['widget'].".php")){
$widgets[$i]['content'] = (new $widgets[$i]['widget'])->getWidget($widgets[$i]);; require_once $WIDGET_PATH . DIRECTORY_SEPARATOR . $widgets[$i]['widget'].".php";
$widgets[$i]['content'] = (new $widgets[$i]['widget'])->getWidget($widgets[$i]);
}else{
$widgets[$i]['content'] = "Widget not found";
}
} catch (Throwable $e) { } catch (Throwable $e) {
$widgets[$i]['content'] = $e->getMessage(); $widgets[$i]['content'] = $e->getMessage();
} }
@ -48,138 +54,3 @@ for ($i = 0; $i < $count; $i++) {
$ui->assign('widgets', $widgets); $ui->assign('widgets', $widgets);
run_hook('view_dashboard'); #HOOK run_hook('view_dashboard'); #HOOK
$ui->display('admin/dashboard_widget.tpl'); $ui->display('admin/dashboard_widget.tpl');
die();
//activity log
$dlog = ORM::for_table('tbl_logs')->limit(5)->order_by_desc('id')->find_many();
$ui->assign('dlog', $dlog);
$log = ORM::for_table('tbl_logs')->count();
$ui->assign('log', $log);
if ($config['hide_vs'] != 'yes') {
$cacheStocksfile = $CACHE_PATH . File::pathFixer('/VoucherStocks.temp');
$cachePlanfile = $CACHE_PATH . File::pathFixer('/VoucherPlans.temp');
//Cache for 5 minutes
if (file_exists($cacheStocksfile) && time() - filemtime($cacheStocksfile) < 600) {
$stocks = json_decode(file_get_contents($cacheStocksfile), true);
$plans = json_decode(file_get_contents($cachePlanfile), true);
} else {
// Count stock
$tmp = $v = ORM::for_table('tbl_plans')->select('id')->select('name_plan')->find_many();
$plans = array();
$stocks = array("used" => 0, "unused" => 0);
$n = 0;
foreach ($tmp as $plan) {
$unused = ORM::for_table('tbl_voucher')
->where('id_plan', $plan['id'])
->where('status', 0)->count();
$used = ORM::for_table('tbl_voucher')
->where('id_plan', $plan['id'])
->where('status', 1)->count();
if ($unused > 0 || $used > 0) {
$plans[$n]['name_plan'] = $plan['name_plan'];
$plans[$n]['unused'] = $unused;
$plans[$n]['used'] = $used;
$stocks["unused"] += $unused;
$stocks["used"] += $used;
$n++;
}
}
file_put_contents($cacheStocksfile, json_encode($stocks));
file_put_contents($cachePlanfile, json_encode($plans));
}
}
$cacheMRfile = File::pathFixer('/monthlyRegistered.temp');
//Cache for 1 hour
if (file_exists($cacheMRfile) && time() - filemtime($cacheMRfile) < 3600) {
$monthlyRegistered = json_decode(file_get_contents($cacheMRfile), true);
} else {
//Monthly Registered Customers
$result = ORM::for_table('tbl_customers')
->select_expr('MONTH(created_at)', 'month')
->select_expr('COUNT(*)', 'count')
->where_raw('YEAR(created_at) = YEAR(NOW())')
->group_by_expr('MONTH(created_at)')
->find_many();
$monthlyRegistered = [];
foreach ($result as $row) {
$monthlyRegistered[] = [
'date' => $row->month,
'count' => $row->count
];
}
file_put_contents($cacheMRfile, json_encode($monthlyRegistered));
}
$cacheMSfile = $CACHE_PATH . File::pathFixer('/monthlySales.temp');
//Cache for 12 hours
if (file_exists($cacheMSfile) && time() - filemtime($cacheMSfile) < 43200) {
$monthlySales = json_decode(file_get_contents($cacheMSfile), true);
} else {
// Query to retrieve monthly data
$results = ORM::for_table('tbl_transactions')
->select_expr('MONTH(recharged_on)', 'month')
->select_expr('SUM(price)', 'total')
->where_raw("YEAR(recharged_on) = YEAR(CURRENT_DATE())") // Filter by the current year
->where_not_equal('method', 'Customer - Balance')
->where_not_equal('method', 'Recharge Balance - Administrator')
->group_by_expr('MONTH(recharged_on)')
->find_many();
// Create an array to hold the monthly sales data
$monthlySales = array();
// Iterate over the results and populate the array
foreach ($results as $result) {
$month = $result->month;
$totalSales = $result->total;
$monthlySales[$month] = array(
'month' => $month,
'totalSales' => $totalSales
);
}
// Fill in missing months with zero sales
for ($month = 1; $month <= 12; $month++) {
if (!isset($monthlySales[$month])) {
$monthlySales[$month] = array(
'month' => $month,
'totalSales' => 0
);
}
}
// Sort the array by month
ksort($monthlySales);
// Reindex the array
$monthlySales = array_values($monthlySales);
file_put_contents($cacheMSfile, json_encode($monthlySales));
}
if ($config['router_check']) {
$routeroffs = ORM::for_table('tbl_routers')->selects(['id', 'name', 'last_seen'])->where('status', 'Offline')->where('enabled', '1')->order_by_desc('name')->find_array();
$ui->assign('routeroffs', $routeroffs);
}
$timestampFile = "$UPLOAD_PATH/cron_last_run.txt";
if (file_exists($timestampFile)) {
$lastRunTime = file_get_contents($timestampFile);
$ui->assign('run_date', date('Y-m-d h:i:s A', $lastRunTime));
}
// Assign the monthly sales data to Smarty
$ui->assign('start_date', $start_date);
$ui->assign('current_date', $current_date);
$ui->assign('monthlySales', $monthlySales);
$ui->assign('xfooter', '');
$ui->assign('monthlyRegistered', $monthlyRegistered);
$ui->assign('stocks', $stocks);
$ui->assign('plans', $plans);
run_hook('view_dashboard'); #HOOK
$ui->display('admin/dashboard.tpl');

View File

@ -0,0 +1,15 @@
<?php
class activity_log
{
public function getWidget()
{
global $config, $ui, $current_date, $start_date;
$dlog = ORM::for_table('tbl_logs')->limit(5)->order_by_desc('id')->findArray();
$ui->assign('dlog', $dlog);
// $log = ORM::for_table('tbl_logs')->count();
// $ui->assign('log', $log);
return $ui->fetch('widget/activity_log.tpl');
}
}

View File

@ -0,0 +1,17 @@
<?php
class cron_monitor
{
public function getWidget()
{
global $UPLOAD_PATH,$ui;
$timestampFile = "$UPLOAD_PATH/cron_last_run.txt";
if (file_exists($timestampFile)) {
$lastRunTime = file_get_contents($timestampFile);
$ui->assign('run_date', date('Y-m-d h:i:s A', $lastRunTime));
}
return $ui->fetch('widget/cron_monitor.tpl');
}
}

View File

@ -0,0 +1,17 @@
<?php
class default_info_row
{
public function getWidget()
{
global $config,$ui;
if ($config['enable_balance'] == 'yes'){
$cb = ORM::for_table('tbl_customers')->whereGte('balance', 0)->sum('balance');
$ui->assign('cb', $cb);
}
return $ui->fetch('widget/default_info_row.tpl');
}
}

View File

@ -0,0 +1,28 @@
<?php
class graph_customers_insight
{
public function getWidget()
{
global $CACHE_PATH,$ui;
$u_act = ORM::for_table('tbl_user_recharges')->where('status', 'on')->count();
if (empty($u_act)) {
$u_act = '0';
}
$ui->assign('u_act', $u_act);
$u_all = ORM::for_table('tbl_user_recharges')->count();
if (empty($u_all)) {
$u_all = '0';
}
$ui->assign('u_all', $u_all);
$c_all = ORM::for_table('tbl_customers')->count();
if (empty($c_all)) {
$c_all = '0';
}
$ui->assign('c_all', $c_all);
return $ui->fetch('widget/graph_customers_insight.tpl');
}
}

View File

@ -0,0 +1,34 @@
<?php
class graph_monthly_registered_customers
{
public function getWidget()
{
global $CACHE_PATH,$ui;
$cacheMRfile = File::pathFixer('/monthlyRegistered.temp');
//Cache for 1 hour
if (file_exists($cacheMRfile) && time() - filemtime($cacheMRfile) < 3600) {
$monthlyRegistered = json_decode(file_get_contents($cacheMRfile), true);
} else {
//Monthly Registered Customers
$result = ORM::for_table('tbl_customers')
->select_expr('MONTH(created_at)', 'month')
->select_expr('COUNT(*)', 'count')
->where_raw('YEAR(created_at) = YEAR(NOW())')
->group_by_expr('MONTH(created_at)')
->find_many();
$monthlyRegistered = [];
foreach ($result as $row) {
$monthlyRegistered[] = [
'date' => $row->month,
'count' => $row->count
];
}
file_put_contents($cacheMRfile, json_encode($monthlyRegistered));
}
$ui->assign('monthlyRegistered', $monthlyRegistered);
return $ui->fetch('widget/graph_monthly_registered_customers.tpl');
}
}

View File

@ -0,0 +1,60 @@
<?php
class graph_monthly_sales
{
public function getWidget()
{
global $CACHE_PATH, $ui;
$cacheMSfile = $CACHE_PATH . File::pathFixer('/monthlySales.temp');
//Cache for 12 hours
if (file_exists($cacheMSfile) && time() - filemtime($cacheMSfile) < 43200) {
$monthlySales = json_decode(file_get_contents($cacheMSfile), true);
} else {
// Query to retrieve monthly data
$results = ORM::for_table('tbl_transactions')
->select_expr('MONTH(recharged_on)', 'month')
->select_expr('SUM(price)', 'total')
->where_raw("YEAR(recharged_on) = YEAR(CURRENT_DATE())") // Filter by the current year
->where_not_equal('method', 'Customer - Balance')
->where_not_equal('method', 'Recharge Balance - Administrator')
->group_by_expr('MONTH(recharged_on)')
->find_many();
// Create an array to hold the monthly sales data
$monthlySales = array();
// Iterate over the results and populate the array
foreach ($results as $result) {
$month = $result->month;
$totalSales = $result->total;
$monthlySales[$month] = array(
'month' => $month,
'totalSales' => $totalSales
);
}
// Fill in missing months with zero sales
for ($month = 1; $month <= 12; $month++) {
if (!isset($monthlySales[$month])) {
$monthlySales[$month] = array(
'month' => $month,
'totalSales' => 0
);
}
}
// Sort the array by month
ksort($monthlySales);
// Reindex the array
$monthlySales = array_values($monthlySales);
file_put_contents($cacheMSfile, json_encode($monthlySales));
}
$ui->assign('monthlySales', $monthlySales);
return $ui->fetch('widget/graph_monthly_sales.tpl');
}
}

View File

@ -0,0 +1,11 @@
<?php
class html_only
{
public function getWidget($data = null)
{
global $ui;
return $data['content'];
}
}

View File

@ -0,0 +1,16 @@
<?php
class mikrotik_cron_monitor
{
public function getWidget()
{
global $config,$ui;
if ($config['router_check']) {
$routeroffs = ORM::for_table('tbl_routers')->selects(['id', 'name', 'last_seen'])->where('status', 'Offline')->where('enabled', '1')->order_by_desc('name')->find_array();
$ui->assign('routeroffs', $routeroffs);
}
return $ui->fetch('widget/mikrotik_cron_monitor.tpl');
}
}

View File

@ -5,7 +5,7 @@ class top_widget
{ {
public function getWidget() public function getWidget()
{ {
global $config, $ui, $current_date, $start_date; global $ui, $current_date, $start_date;
$iday = ORM::for_table('tbl_transactions') $iday = ORM::for_table('tbl_transactions')
->where('recharged_on', $current_date) ->where('recharged_on', $current_date)
@ -28,11 +28,6 @@ class top_widget
} }
$ui->assign('imonth', $imonth); $ui->assign('imonth', $imonth);
if ($config['enable_balance'] == 'yes') {
$cb = ORM::for_table('tbl_customers')->whereGte('balance', 0)->sum('balance');
$ui->assign('cb', $cb);
}
$u_act = ORM::for_table('tbl_user_recharges')->where('status', 'on')->count(); $u_act = ORM::for_table('tbl_user_recharges')->where('status', 'on')->count();
if (empty($u_act)) { if (empty($u_act)) {
$u_act = '0'; $u_act = '0';

View File

@ -0,0 +1,43 @@
<?php
class voucher_stocks
{
public function getWidget()
{
global $CACHE_PATH,$ui;
$cacheStocksfile = $CACHE_PATH . File::pathFixer('/VoucherStocks.temp');
$cachePlanfile = $CACHE_PATH . File::pathFixer('/VoucherPlans.temp');
//Cache for 5 minutes
if (file_exists($cacheStocksfile) && time() - filemtime($cacheStocksfile) < 600) {
$stocks = json_decode(file_get_contents($cacheStocksfile), true);
$plans = json_decode(file_get_contents($cachePlanfile), true);
} else {
// Count stock
$tmp = $v = ORM::for_table('tbl_plans')->select('id')->select('name_plan')->find_many();
$plans = array();
$stocks = array("used" => 0, "unused" => 0);
$n = 0;
foreach ($tmp as $plan) {
$unused = ORM::for_table('tbl_voucher')
->where('id_plan', $plan['id'])
->where('status', 0)->count();
$used = ORM::for_table('tbl_voucher')
->where('id_plan', $plan['id'])
->where('status', 1)->count();
if ($unused > 0 || $used > 0) {
$plans[$n]['name_plan'] = $plan['name_plan'];
$plans[$n]['unused'] = $unused;
$plans[$n]['used'] = $used;
$stocks["unused"] += $unused;
$stocks["used"] += $used;
$n++;
}
}
file_put_contents($cacheStocksfile, json_encode($stocks));
file_put_contents($cachePlanfile, json_encode($plans));
}
$ui->assign('stocks', $stocks);
$ui->assign('plans', $plans);
return $ui->fetch('widget/voucher_stocks.tpl');
}
}

View File

@ -2,11 +2,11 @@
<div class="panel-heading"><a href="{Text::url('logs')}">{Lang::T('Activity Log')}</a></div> <div class="panel-heading"><a href="{Text::url('logs')}">{Lang::T('Activity Log')}</a></div>
<div class="panel-body"> <div class="panel-body">
<ul class="list-unstyled"> <ul class="list-unstyled">
{foreach $dlog as $dlogs} {foreach $dlog as $dl}
<li class="primary"> <li class="primary">
<span class="point"></span> <span class="point"></span>
<span class="time small text-muted">{Lang::timeElapsed($dlogs['date'],true)}</span> <span class="time small text-muted">{Lang::timeElapsed($dl['date'],true)}</span>
<p>{$dlogs['description']}</p> <p>{$dl['description']}</p>
</li> </li>
{/foreach} {/foreach}
</ul> </ul>

View File

@ -7,53 +7,51 @@
<script type="text/javascript"> <script type="text/javascript">
{if $_c['hide_aui'] != 'yes'} {literal}
{literal} document.addEventListener("DOMContentLoaded", function() {
document.addEventListener("DOMContentLoaded", function() { // Get the data from PHP and assign it to JavaScript variables
// Get the data from PHP and assign it to JavaScript variables var u_act = '{/literal}{$u_act}{literal}';
var u_act = '{/literal}{$u_act}{literal}'; var c_all = '{/literal}{$c_all}{literal}';
var c_all = '{/literal}{$c_all}{literal}'; var u_all = '{/literal}{$u_all}{literal}';
var u_all = '{/literal}{$u_all}{literal}'; //lets calculate the inactive users as reported
//lets calculate the inactive users as reported var expired = u_all - u_act;
var expired = u_all - u_act; var inactive = c_all - u_all;
var inactive = c_all - u_all; if (inactive < 0) {
if (inactive < 0) { inactive = 0;
inactive = 0; }
} // Create the chart data
// Create the chart data var data = {
var data = { labels: ['Active Users', 'Expired Users', 'Inactive Users'],
labels: ['Active Users', 'Expired Users', 'Inactive Users'], datasets: [{
datasets: [{ label: 'User Recharges',
label: 'User Recharges', data: [parseInt(u_act), parseInt(expired), parseInt(inactive)],
data: [parseInt(u_act), parseInt(expired), parseInt(inactive)], backgroundColor: ['rgba(4, 191, 13)', 'rgba(191, 35, 4)', 'rgba(0, 0, 255, 0.5'],
backgroundColor: ['rgba(4, 191, 13)', 'rgba(191, 35, 4)', 'rgba(0, 0, 255, 0.5'], borderColor: ['rgba(0, 255, 0, 1)', 'rgba(255, 99, 132, 1)', 'rgba(0, 0, 255, 0.7'],
borderColor: ['rgba(0, 255, 0, 1)', 'rgba(255, 99, 132, 1)', 'rgba(0, 0, 255, 0.7'], borderWidth: 1
borderWidth: 1 }]
}] };
};
// Create chart options // Create chart options
var options = { var options = {
responsive: true, responsive: true,
aspectRatio: 1, aspectRatio: 1,
plugins: { plugins: {
legend: { legend: {
position: 'bottom', position: 'bottom',
labels: { labels: {
boxWidth: 15 boxWidth: 15
}
} }
} }
}; }
};
// Get the canvas element and create the chart // Get the canvas element and create the chart
var ctx = document.getElementById('userRechargesChart').getContext('2d'); var ctx = document.getElementById('userRechargesChart').getContext('2d');
var chart = new Chart(ctx, { var chart = new Chart(ctx, {
type: 'pie', type: 'pie',
data: data, data: data,
options: options options: options
});
}); });
{/literal} });
{/if} {/literal}
</script> </script>

View File

@ -18,56 +18,54 @@
<script type="text/javascript"> <script type="text/javascript">
{if $_c['hide_mrc'] != 'yes'} {literal}
{literal} document.addEventListener("DOMContentLoaded", function() {
document.addEventListener("DOMContentLoaded", function() { var counts = JSON.parse('{/literal}{$monthlyRegistered|json_encode}{literal}');
var counts = JSON.parse('{/literal}{$monthlyRegistered|json_encode}{literal}');
var monthNames = [ var monthNames = [
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
]; ];
var labels = []; var labels = [];
var data = []; var data = [];
for (var i = 1; i <= 12; i++) { for (var i = 1; i <= 12; i++) {
var month = counts.find(count => count.date === i); var month = counts.find(count => count.date === i);
labels.push(month ? monthNames[i - 1] : monthNames[i - 1].substring(0, 3)); labels.push(month ? monthNames[i - 1] : monthNames[i - 1].substring(0, 3));
data.push(month ? month.count : 0); data.push(month ? month.count : 0);
} }
var ctx = document.getElementById('chart').getContext('2d'); var ctx = document.getElementById('chart').getContext('2d');
var chart = new Chart(ctx, { var chart = new Chart(ctx, {
type: 'bar', type: 'bar',
data: { data: {
labels: labels, labels: labels,
datasets: [{ datasets: [{
label: 'Registered Members', label: 'Registered Members',
data: data, data: data,
backgroundColor: 'rgba(0, 0, 255, 0.5)', backgroundColor: 'rgba(0, 0, 255, 0.5)',
borderColor: 'rgba(0, 0, 255, 0.7)', borderColor: 'rgba(0, 0, 255, 0.7)',
borderWidth: 1 borderWidth: 1
}] }]
}, },
options: { options: {
responsive: true, responsive: true,
scales: { scales: {
x: { x: {
grid: { grid: {
display: false display: false
} }
}, },
y: { y: {
beginAtZero: true, beginAtZero: true,
grid: { grid: {
color: 'rgba(0, 0, 0, 0.1)' color: 'rgba(0, 0, 0, 0.1)'
}
} }
} }
} }
}); }
}); });
{/literal} });
{/if} {/literal}
</script> </script>