forked from kevinowino869/mitrobill
getting ready for customizeable dashboard with widget
This commit is contained in:
@ -19,6 +19,7 @@ class Paginator
|
||||
$url .= '&' . http_build_query($search);
|
||||
}
|
||||
$url .= $append_url.'&p=';
|
||||
$url = Text::fixUrl($url);
|
||||
$totalReq = $query->count();
|
||||
$lastpage = ceil($totalReq / $per_page);
|
||||
$lpm1 = $lastpage - 1;
|
||||
|
@ -132,6 +132,14 @@ class Text
|
||||
}
|
||||
}
|
||||
|
||||
public static function fixUrl($url){
|
||||
//if url dont have ? then add it with replace first & to ?
|
||||
if(strpos($url, '?') === false && strpos($url, '&')!== false){
|
||||
return substr($url, 0, strpos($url, '&')). '?'. substr($url, strpos($url, '&')+1);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
// this will return & or ?
|
||||
public static function isQA(){
|
||||
global $config;
|
||||
|
50
system/autoload/Widget.php
Normal file
50
system/autoload/Widget.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* Validator class
|
||||
*/
|
||||
class Widget
|
||||
{
|
||||
|
||||
public static function rows($rows, $result){
|
||||
$result .= '<div class="row">';
|
||||
foreach($rows as $row){
|
||||
|
||||
}
|
||||
$result .= '</div>';
|
||||
}
|
||||
|
||||
public static function columns($cols, $result){
|
||||
$c = count($cols);
|
||||
switch($c){
|
||||
case 1:
|
||||
$result .= '<div class="col-md-12">';
|
||||
break;
|
||||
case 2:
|
||||
$result .= '<div class="col-md-6">';
|
||||
break;
|
||||
case 3:
|
||||
$result .= '<div class="col-md-4">';
|
||||
break;
|
||||
case 4:
|
||||
$result .= '<div class="col-md-4">';
|
||||
break;
|
||||
case 5:
|
||||
$result .= '<div class="col-md-4">';
|
||||
break;
|
||||
default:
|
||||
$result .= '<div class="col-md-1">';
|
||||
break;
|
||||
}
|
||||
|
||||
foreach($cols as $col){
|
||||
}
|
||||
$result .= '</div>';
|
||||
}
|
||||
}
|
185
system/controllers/dashboard_widget.php
Normal file
185
system/controllers/dashboard_widget.php
Normal file
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
|
||||
_admin();
|
||||
$ui->assign('_title', Lang::T('Dashboard'));
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if (isset($_GET['refresh'])) {
|
||||
$files = scandir($CACHE_PATH);
|
||||
foreach ($files as $file) {
|
||||
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
||||
if (is_file($CACHE_PATH . DIRECTORY_SEPARATOR . $file) && $ext == 'temp') {
|
||||
unlink($CACHE_PATH . DIRECTORY_SEPARATOR . $file);
|
||||
}
|
||||
}
|
||||
r2(getUrl('dashboard'), 's', 'Data Refreshed');
|
||||
}
|
||||
|
||||
|
||||
$reset_day = $config['reset_day'];
|
||||
if (empty($reset_day)) {
|
||||
$reset_day = 1;
|
||||
}
|
||||
//first day of month
|
||||
if (date("d") >= $reset_day) {
|
||||
$start_date = date('Y-m-' . $reset_day);
|
||||
} else {
|
||||
$start_date = date('Y-m-' . $reset_day, strtotime("-1 MONTH"));
|
||||
}
|
||||
|
||||
$current_date = date('Y-m-d');
|
||||
|
||||
$widgets = ORM::for_table('tbl_widgets')->selects("enabled", 1)->order_by_asc("orders")->findArray();
|
||||
$count = count($widgets);
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
try{
|
||||
require_once $WIDGET_PATH . DIRECTORY_SEPARATOR . $widgets[$i]['widget'].".php";
|
||||
$widgets[$i]['content'] = (new $widgets[$i]['widget'])->getWidget($widgets[$i]);;
|
||||
} catch (Throwable $e) {
|
||||
$widgets[$i]['content'] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
$ui->assign('widgets', $widgets);
|
||||
run_hook('view_dashboard'); #HOOK
|
||||
$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');
|
102
system/controllers/widgets.php
Normal file
102
system/controllers/widgets.php
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
||||
* by https://t.me/ibnux
|
||||
**/
|
||||
_admin();
|
||||
$ui->assign('_title', Lang::T('Widgets'));
|
||||
$ui->assign('_system_menu', 'settings');
|
||||
|
||||
$action = alphanumeric($routes['1']);
|
||||
$ui->assign('_admin', $admin);
|
||||
|
||||
if ($action == 'add') {
|
||||
$pos = alphanumeric($routes['2']);
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$orders = alphanumeric($_POST['orders']);
|
||||
$position = alphanumeric($_POST['position']);
|
||||
$enabled = alphanumeric($_POST['enabled']);
|
||||
$title = _post('title');
|
||||
$widget = _post('widget');
|
||||
$content = _post('content');
|
||||
$d = ORM::for_table('tbl_widgets')->create();
|
||||
$d->orders = $orders;
|
||||
$d->position = $position;
|
||||
$d->enabled = $enabled;
|
||||
$d->title = $title;
|
||||
$d->widget = $widget;
|
||||
$d->content = $content;
|
||||
$d->save();
|
||||
if ($d->id() > 0) {
|
||||
r2(getUrl('widgets'), 's', 'Widget Added Successfully');
|
||||
}
|
||||
}
|
||||
$files = scandir($WIDGET_PATH);
|
||||
$widgets = [];
|
||||
foreach ($files as $file) {
|
||||
if (strpos($file, '.php') !== false) {
|
||||
$name = ucwords(str_replace('.php', '', str_replace('_', ' ', $file)));
|
||||
$widgets[str_replace('.php', '', $file)] = $name;
|
||||
}
|
||||
}
|
||||
$widget['position'] = $pos;
|
||||
$ui->assign('do', 'add');
|
||||
$ui->assign('widgets', $widgets);
|
||||
$ui->assign('widget', $widget);
|
||||
$ui->display('admin/settings/widgets_add_edit.tpl');
|
||||
} else if ($action == 'edit') {
|
||||
// if request method post then save data
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$id = alphanumeric($_POST['id']);
|
||||
$orders = alphanumeric($_POST['orders']);
|
||||
$position = alphanumeric($_POST['position']);
|
||||
$enabled = alphanumeric($_POST['enabled']);
|
||||
$title = _post('title');
|
||||
$widget = _post('widget');
|
||||
$content = _post('content');
|
||||
|
||||
$d = ORM::for_table('tbl_widgets')->find_one($id);
|
||||
$d->orders = $orders;
|
||||
$d->position = $position;
|
||||
$d->enabled = $enabled;
|
||||
$d->title = $title;
|
||||
$d->widget = $widget;
|
||||
$d->content = $content;
|
||||
$d->save();
|
||||
r2(getUrl('widgets'), 's', 'Widget Saved Successfully');
|
||||
}
|
||||
$id = alphanumeric($routes['2']);
|
||||
$widget = ORM::for_table('tbl_widgets')->find_one($id);
|
||||
$files = scandir($WIDGET_PATH);
|
||||
$widgets = [];
|
||||
foreach ($files as $file) {
|
||||
if (strpos($file, '.php') !== false) {
|
||||
$name = ucwords(str_replace('.php', '', str_replace('_', ' ', $file)));
|
||||
$widgets[str_replace('.php', '', $file)] = $name;
|
||||
}
|
||||
}
|
||||
$ui->assign('do', 'edit');
|
||||
$ui->assign('widgets', $widgets);
|
||||
$ui->assign('widget', $widget);
|
||||
$ui->display('admin/settings/widgets_add_edit.tpl');
|
||||
} else if ($action == 'delete') {
|
||||
$id = alphanumeric($routes['2']);
|
||||
$d = ORM::for_table('tbl_widgets')->find_one($id);
|
||||
if ($d) {
|
||||
$d->delete();
|
||||
r2(getUrl('widgets'), 's', 'Widget Deleted Successfully');
|
||||
}
|
||||
r2(getUrl('widgets'), 'e', 'Widget Not Found');
|
||||
} else if (!empty($action) && file_exists("system/widget/$action.php") && !empty($routes['2'])) {
|
||||
require_once "system/widget/$action.php";
|
||||
try {
|
||||
(new $action)->run_command($routes['2']);
|
||||
} catch (Throwable $e) {
|
||||
//nothing to do
|
||||
}
|
||||
} else {
|
||||
$widgets = ORM::for_table('tbl_widgets')->selects("position", 1)->order_by_asc("orders")->find_many();
|
||||
$ui->assign('widgets', $widgets);
|
||||
$ui->display('admin/settings/widgets.tpl');
|
||||
}
|
@ -1027,5 +1027,12 @@
|
||||
"Back_to_Dashboard": "Back to Dashboard",
|
||||
"Continue_the_VPN_creation_process_": "Continue the VPN creation process?",
|
||||
"VPN": "VPN",
|
||||
"Go_Back": "Go Back"
|
||||
"Go_Back": "Go Back",
|
||||
"Widgets": "Widgets",
|
||||
"Order": "Order",
|
||||
"Position": "Position",
|
||||
"Widget": "Widget",
|
||||
"Contents": "Contents",
|
||||
"Please_enter_a_search_term_": "Please enter a search term.",
|
||||
"Customers_Expired__Today": "Customers Expired, Today"
|
||||
}
|
30
system/widgets/customer_expired.php
Normal file
30
system/widgets/customer_expired.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
|
||||
class customer_expired
|
||||
{
|
||||
|
||||
|
||||
public function getWidget()
|
||||
{
|
||||
global $ui, $current_date;
|
||||
|
||||
//user expire
|
||||
$query = ORM::for_table('tbl_user_recharges')
|
||||
->where_lte('expiration', $current_date)
|
||||
->order_by_desc('expiration');
|
||||
$expire = Paginator::findMany($query);
|
||||
|
||||
// Get the total count of expired records for pagination
|
||||
$totalCount = ORM::for_table('tbl_user_recharges')
|
||||
->where_lte('expiration', $current_date)
|
||||
->count();
|
||||
|
||||
// Pass the total count and current page to the paginator
|
||||
$paginator['total_count'] = $totalCount;
|
||||
|
||||
// Assign the pagination HTML to the template variable
|
||||
$ui->assign('expire', $expire);
|
||||
return $ui->fetch('widget/customer_expired.tpl');
|
||||
}
|
||||
}
|
22
system/widgets/html_php.php
Normal file
22
system/widgets/html_php.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
class html_php
|
||||
{
|
||||
|
||||
public function getWidget($data = null)
|
||||
{
|
||||
global $ui;
|
||||
$ui->assign('card_header', $data['title']);
|
||||
ob_start();
|
||||
try{
|
||||
eval('?>'. $data['content']);
|
||||
}catch(Exception $e){
|
||||
echo $e->getMessage();
|
||||
echo "<br>";
|
||||
echo $e->getTraceAsString();
|
||||
}
|
||||
$content = ob_get_clean();
|
||||
$ui->assign('card_body', $content);
|
||||
return $ui->fetch('widget/card_html.tpl');
|
||||
}
|
||||
}
|
18
system/widgets/template.md
Normal file
18
system/widgets/template.md
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```php
|
||||
class widget_name
|
||||
{
|
||||
|
||||
public static getWidget($data)
|
||||
{
|
||||
global $config, $ui;
|
||||
|
||||
return $ui->fetch('widget/template');
|
||||
}
|
||||
}
|
||||
```
|
56
system/widgets/top_widget.php
Normal file
56
system/widgets/top_widget.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
|
||||
class top_widget
|
||||
{
|
||||
public function getWidget()
|
||||
{
|
||||
global $config, $ui, $current_date, $start_date;
|
||||
|
||||
$iday = ORM::for_table('tbl_transactions')
|
||||
->where('recharged_on', $current_date)
|
||||
->where_not_equal('method', 'Customer - Balance')
|
||||
->where_not_equal('method', 'Recharge Balance - Administrator')
|
||||
->sum('price');
|
||||
|
||||
if ($iday == '') {
|
||||
$iday = '0.00';
|
||||
}
|
||||
$ui->assign('iday', $iday);
|
||||
|
||||
$imonth = ORM::for_table('tbl_transactions')
|
||||
->where_not_equal('method', 'Customer - Balance')
|
||||
->where_not_equal('method', 'Recharge Balance - Administrator')
|
||||
->where_gte('recharged_on', $start_date)
|
||||
->where_lte('recharged_on', $current_date)->sum('price');
|
||||
if ($imonth == '') {
|
||||
$imonth = '0.00';
|
||||
}
|
||||
$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();
|
||||
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/top_widget.tpl');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user