From 40f452cff8a7a8d19cb4e429a08231a83be2c943 Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Thu, 5 Sep 2024 13:46:07 +0100
Subject: [PATCH 01/28] just little bold
---
ui/ui/user-ui/header.tpl | 401 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 400 insertions(+), 1 deletion(-)
diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl
index f57da6bc..e52c1b69 100644
--- a/ui/ui/user-ui/header.tpl
+++ b/ui/ui/user-ui/header.tpl
@@ -178,7 +178,7 @@
}
.content .row [class*=col-] .box {
- -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
box-shadow: 4px 4px 30px rgba(221, 224, 255, .54);
-moz-box-shadow: 0 1px 1px rgba(0, 0, 0, .1);
-ms-box-shadow: 0 1px 1px rgba(0, 0, 0, .1);
@@ -215,16 +215,19 @@
background: transparent;
background-color: transparent;
}
+
.box.box-solid.box-primary>.box-header {
color: inherit;
background-color: transparent;
border-color: transparent;
}
+
.box.box-solid.box-info>.box-header {
color: inherit;
background-color: transparent;
border-color: transparent;
}
+
.box.box-solid.box-danger>.box-header {
color: inherit;
background-color: transparent;
@@ -246,6 +249,21 @@
box-shadow: 0px 4px 30px rgba(221, 224, 255, .54);
}
+ .modern-skin-dark .main-sidebar .sidebar .sidebar-menu li>a {
+ font-weight: bold;
+ }
+
+ .content-header>h1 {
+ font-weight: bold;
+ }
+
+ .box-header>.fa,
+ .box-header>.glyphicon,
+ .box-header>.ion,
+ .box-header .box-title {
+ font-weight: bold;
+ }
+
/* New Customize Interface End Here */
::-moz-selection {
@@ -306,6 +324,387 @@
margin: 0;
padding: 10px;
}
+
+
+
+
+ .toggle-container {
+ position: absolute;
+ top: 17px;
+ right: 15px;
+ cursor: pointer;
+ }
+
+ .toggle-container .toggle-icon {
+ font-size: 25px;
+ color: rgb(100 116 139);
+ transition: color 0.5s ease;
+ }
+
+ @media (max-width: 600px) {
+ .toggle-container {
+ top: 15px;
+ right: 200px;
+ }
+
+ .toggle-container .toggle-icon {
+ font-size: 20px;
+ color: rgb(100 116 139);
+ transition: color 0.5s ease;
+ }
+ }
+
+
+ /* dark mode styles start here */
+ .dark-mode {
+ background-color: #1a202c;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .main-header .logo,
+ .dark-mode .main-header .navbar,
+ .dark-mode .main-sidebar,
+ .dark-mode .main-sidebar .sidebar,
+ .dark-mode .sidebar-menu li>a {
+ background-color: #0e1219;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .sidebar-menu li:hover,
+ .dark-mode .sidebar-menu li:focus {
+ color: #10d435;
+ }
+
+ .dark-mode .main-sidebar .sidebar .sidebar-menu li.active a {
+ background-color: #2e298e;
+ }
+
+ .dark-mode .content,
+ .dark-mode .content-header,
+ .dark-mode .content-wrapper,
+ .dark-mode .right-side {
+ background-color: #0e1219;
+ }
+
+ .dark-mode .main-footer {
+ background-color: #1a202c;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .panel,
+ .dark-mode .box {
+ background-color: #2d3748;
+ border-color: #4a5568;
+ box-shadow: none;
+ }
+
+ .dark-mode .panel-heading,
+ .dark-mode .box-header {
+ background-color: transparent;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .box-footer,
+ .dark-mode .panel-footer {
+ background-color: #2d3748;
+ }
+
+ .dark-mode .search-container {
+ background-color: #2d3748;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .searchTerm {
+ background-color: #4a5568;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .cancelButton {
+ background-color: #e53e3e;
+ }
+
+ .dark-mode .notification-top-bar {
+ background-color: #742a2a;
+ }
+
+ .dark-mode .bs-callout {
+ background-color: #2d3748;
+ border-color: #4a5568;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .bs-callout h4 {
+ color: #cbd5e0;
+ }
+
+ .dark-mode .bg-gray {
+ background-color: inherit !important;
+ }
+
+ .dark-mode .breadcrumb {
+ padding: 8px 15px;
+ margin-bottom: 20px;
+ list-style: none;
+ background-color: rgba(221, 224, 255, .54);
+ border-radius: 4px;
+ }
+
+ .dark-mode .pagination>.disabled>span,
+ .dark-mode .pagination>.disabled>span:hover,
+ .dark-mode .pagination>.disabled>span:focus,
+ .dark-mode .pagination>.disabled>a,
+ .dark-mode .pagination>.disabled>a:hover,
+ .dark-mode .pagination>.disabled>a:focus {
+ color: inherit;
+ background-color: rgba(221, 224, 255, .54);
+ border-color: rgba(221, 224, 255, .54);
+ cursor: not-allowed;
+ }
+
+ .dark-mode .pagination>.active>a,
+ .dark-mode .pagination>.active>a:hover,
+ .dark-mode .pagination>.active>a:focus,
+ .dark-mode .pagination>.active>span,
+ .dark-mode .pagination>.active>span:hover,
+ .dark-mode .pagination>.active>span:focus {
+ z-index: 2;
+ color: #fff;
+ background-color: #435ebe;
+ border-color: rgba(221, 224, 255, .54);
+ box-shadow: 0 2px 5px rgba(67, 94, 190, .3);
+ cursor: default;
+ }
+
+ .dark-mode .pagination>li>a {
+ background: inherit;
+ color: inherit;
+ border: 1px solid;
+ border-color: rgba(221, 224, 255, .54);
+ }
+
+ .dark-mode .table {
+ background-color: inherit;
+ color: #ddd;
+ border-color: #444;
+ }
+
+ .dark-mode .table th,
+ .dark-mode .table td {
+ background-color: inherit;
+ border-color: inherit;
+ color: #ddd;
+ }
+
+ .dark-mode .table th {
+ background-color: inherit;
+ font-weight: bold;
+ }
+
+ .dark-mode .table-striped tbody tr:nth-of-type(odd) {
+ background-color: inherit;
+ }
+
+ .dark-mode .table-bordered {
+ border: 1px solid #444;
+ }
+
+ .dark-mode .table-hover tbody tr:hover {
+ background-color: #555;
+ color: #fff;
+ }
+
+ .dark-mode .table-condensed th,
+ .dark-mode .table-condensed td {
+ padding: 8px;
+ }
+
+ .dark-mode .panel>.table:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ }
+
+ .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child,
+ .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ }
+
+ .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,
+ .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,
+ .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,
+ .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child {
+ border-bottom-right-radius: 21px;
+ }
+
+ .dark-mode .help-block {
+ display: block;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: inherit;
+ }
+
+ .dark-mode .text-muted {
+ color: rgba(221, 224, 255, .54);
+ }
+
+ .dark-mode .form-control {
+ display: block;
+ width: 100%;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.428571429;
+ color: inherit;
+ background-color: transparent;
+ background-image: none;
+ border: 1px solid;
+ border-color: rgba(221, 224, 255, .54);
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ }
+
+ .dark-mode .main-footer {
+ border-top: 1px solid transparent;
+ }
+
+ .dark-mode .box.box-solid.box-primary>.box-header {
+ color: #fff;
+ background-color: inherit;
+ border-color: rgba(221, 224, 255, .54);
+ border-top-left-radius: 45px;
+ border-top-right-radius: 45px;
+ }
+
+ .dark-mode .box-body {
+ border-radius: 0px;
+ padding: 10px;
+ }
+
+ .dark-mode .box-header {
+ display: block;
+ padding: 10px;
+ position: relative;
+ border-color: transparent;
+ border-radius: 0px;
+ }
+
+ .dark-mode .nav-stacked>li>a {
+ color: inherit;
+ }
+
+ .dark-mode .list-group-item {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ margin-bottom: -1px;
+ background-color: transparent;
+ border: 1px solid rgba(221, 224, 255, .54);
+ }
+
+ .dark-mode .panel-footer {
+ padding: 10px 15px;
+ border-top: 1px rgba(221, 224, 255, .54);
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+ }
+
+
+ .dark-mode .content .row [class*=col-] .box {
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+ box-shadow: 4px 4px 30px rgba(221, 224, 255, .54);
+ -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, .1);
+ -ms-box-shadow: 0 1px 1px rgba(0, 0, 0, .1);
+ -webkit-border-radius: 1px !important;
+ -moz-border-radius: 1px !important;
+ -ms-border-radius: 1px !important;
+ border-radius: 15px !important;
+ border-color: inherit;
+ background-color: inherit;
+ }
+
+ /* Dark Mode - Input Fields */
+ .dark-mode input:not(#filterNavigateMenu),
+ .dark-mode textarea:not(#filterNavigateMenu),
+ .dark-mode select:not(#filterNavigateMenu),
+ .dark-mode .select2-selection:not(#filterNavigateMenu) {
+ color: inherit;
+ transition: all .5s ease-in-out;
+ }
+
+ .dark-mode input:focus:not(#filterNavigateMenu),
+ .dark-mode textarea:focus:not(#filterNavigateMenu),
+ .dark-mode select:focus:not(#filterNavigateMenu),
+ .dark-mode .select2-selection:focus:not(#filterNavigateMenu) {
+ color: #1f201f;
+ outline: none;
+ }
+
+ .dark-mode .input-group .form-control {
+ position: relative;
+ z-index: 2;
+ float: left;
+ width: 100%;
+ margin-bottom: 0;
+ color: inherit;
+ border-color: rgba(221, 224, 255, .54);
+ background-color: inherit;
+ }
+
+ .dark-mode .input-group .input-group-addon {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ color: inherit;
+ border-bottom-left-radius: 0;
+ border-color: rgba(221, 224, 255, .54);
+ background-color: transparent;
+ }
+
+ .dark-mode .input-group .form-control:last-child,
+ .dark-mode .input-group-addon:last-child,
+ .dark-mode .input-group-btn:last-child>.btn,
+ .dark-mode .input-group-btn:last-child>.btn-group>.btn,
+ .dark-mode .input-group-btn:last-child>.dropdown-toggle,
+ .dark-mode .input-group-btn:first-child>.btn:not(:first-child),
+ .dark-mode .input-group-btn:first-child>.btn-group:not(:first-child)>.btn {
+ color: inherit;
+ }
+
+ .dark-mode input:not(#filterNavigateMenu),
+ textarea:not(#filterNavigateMenu),
+ optgroup:not(#filterNavigateMenu),
+ select:not(#filterNavigateMenu),
+ .dark-mode .select2-selection:not(#filterNavigateMenu) {
+ -moz-transition: all .5s ease-in-out;
+ -o-transition: all .5s ease-in-out;
+ -webkit-transition: all .5s ease-in-out;
+ transition: all .5s ease-in-out;
+ }
+
+ .dark-mode .modern-skin-dark .main-sidebar .sidebar .sidebar-menu li>a {
+ font-weight: bold;
+ }
+
+ .dark-mode .content-header>h1 {
+ font-weight: bold;
+ }
+
+ .dark-mode .box-header>.fa,
+ .dark-mode .box-header>.glyphicon,
+ .dark-mode .box-header>.ion,
+ .dark-mode .box-header .box-title {
+ font-weight: bold;
+ }
{if isset($xheader)}
From 93d53cc6d832e20201f23cddb374bf19f1f6d24d Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Thu, 5 Sep 2024 13:59:19 +0100
Subject: [PATCH 02/28] We added bold to sidebar, we want your opinion if it
looks good or we should remove it
---
ui/ui/sections/header.tpl | 476 +++++++++++++++++++++++++++++++++++++-
1 file changed, 474 insertions(+), 2 deletions(-)
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index 26270036..843109d9 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -171,7 +171,7 @@
-webkit-border-radius: 1px !important;
-moz-border-radius: 1px !important;
-ms-border-radius: 1px !important;
- border-radius: 25px !important;
+ border-radius: 15px !important;
border-color: rgba(221, 224, 255, .54);
}
@@ -180,11 +180,13 @@
background-color: transparent;
border-color: transparent;
}
+
.box.box-solid.box-info>.box-header {
color: inherit;
background-color: transparent;
border-color: transparent;
}
+
.box.box-solid.box-danger>.box-header {
color: inherit;
background-color: transparent;
@@ -211,6 +213,7 @@
border-top: 1px solid transparent;
padding: 10px;
background-color: inherit;
+ border-radius: 15px;
}
.panel-footer {
@@ -232,6 +235,26 @@
box-shadow: 0px 4px 30px rgba(221, 224, 255, .54);
}
+ .panel-success>.panel-heading {
+ color: #3c763d;
+ background-color: transparent;
+ border-color: #d6e9c6;
+ }
+
+ .content-header>h1 {
+ font-weight: bold;
+ }
+
+ .box-header>.fa,
+ .box-header>.glyphicon,
+ .box-header>.ion,
+ .box-header .box-title {
+ font-weight: bold;
+ }
+
+ .modern-skin-dark .main-sidebar .sidebar .sidebar-menu li>a {
+ font-weight: bold;
+ }
/* Search Bar Start Here */
.wrap {
@@ -303,6 +326,13 @@
overflow-y: auto;
}
+ .panel-heading {
+ padding: 10px 15px;
+ border-bottom: 0px solid transparent;
+ border-top-right-radius: 21px;
+ border-top-left-radius: 21px;
+ }
+
/* Search Bar End Here */
/* New Customize Interface End Here */
@@ -332,7 +362,6 @@
th:first-child,
td:first-child {
position: sticky;
- left: 0px;
background-color: #f9f9f9;
}
@@ -534,6 +563,449 @@
-ms-transform: translateX(26px);
transform: translateX(26px);
}
+
+ /* dark mode styles start here */
+
+ .dark-mode {
+ background-color: #1a202c;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .main-header .logo,
+ .dark-mode .main-header .navbar,
+ .dark-mode .main-sidebar,
+ .dark-mode .main-sidebar .sidebar,
+ .dark-mode .sidebar-menu li>a {
+ background-color: #1a202c;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .sidebar-menu li:hover,
+ .dark-mode .sidebar-menu li:focus {
+ color: #10d435;
+ }
+
+ .dark-mode .main-sidebar .sidebar .sidebar-menu li.active a {
+ background-color: #2e298e;
+ }
+
+ .dark-mode .content,
+ .dark-mode .content-header,
+ .dark-mode .content-wrapper,
+ .dark-mode .right-side {
+ background-color: #2d3748;
+ }
+
+ .dark-mode .main-footer {
+ background-color: #1a202c;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .panel,
+ .dark-mode .box {
+ background-color: #2d3748;
+ border-color: #4a5568;
+ box-shadow: none;
+ }
+
+ .dark-mode .panel-heading,
+ .dark-mode .box-header {
+ background-color: transparent;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .box-footer,
+ .dark-mode .panel-footer {
+ background-color: #2d3748;
+ }
+
+ .dark-mode .search-container {
+ background-color: #2d3748;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .searchTerm {
+ background-color: #4a5568;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .cancelButton {
+ background-color: #e53e3e;
+ }
+
+ .dark-mode .notification-top-bar {
+ background-color: #742a2a;
+ }
+
+ .dark-mode .bs-callout {
+ background-color: #2d3748;
+ border-color: #4a5568;
+ color: #cbd5e0;
+ }
+
+ .dark-mode .bs-callout h4 {
+ color: #cbd5e0;
+ }
+
+ .dark-mode .bg-gray {
+ background-color: inherit !important;
+ }
+
+ .toggle-container {
+ position: absolute;
+ top: 17px;
+ right: 15px;
+ cursor: pointer;
+ }
+
+ .toggle-container .toggle-icon {
+ font-size: 25px;
+ color: rgb(100 116 139);
+ transition: color 0.5s ease;
+ }
+
+ @media (max-width: 600px) {
+ .toggle-container {
+ top: 15px;
+ right: 60px;
+ }
+
+ .toggle-container .toggle-icon {
+ font-size: 20px;
+ color: rgb(100 116 139);
+ transition: color 0.5s ease;
+ }
+ }
+
+ .dark-mode .toggle-container .toggle-icon {
+ color: #ffdd57;
+ }
+
+ .dark-mode th:first-child,
+ .dark-mode td:first-child {
+ background-color: #4a4949;
+ }
+
+ .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,
+ .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,
+ .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,
+ .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child {
+ background-color: #4a4949;
+ border-bottom-left-radius: 21px;
+ }
+
+ .dark-mode .table>thead>tr>td.danger,
+ .dark-mode .table>thead>tr>th.danger,
+ .dark-mode .table>thead>tr.danger>td,
+ .dark-mode .table>thead>tr.danger>th,
+ .dark-mode .table>tbody>tr>td.danger,
+ .dark-mode .table>tbody>tr>th.danger,
+ .dark-mode .table>tbody>tr.danger>td,
+ .dark-mode .table>tbody>tr.danger>th,
+ .dark-mode .table>tfoot>tr>td.danger,
+ .dark-mode .table>tfoot>tr>th.danger,
+ .dark-mode .table>tfoot>tr.danger>td,
+ .dark-mode .table>tfoot>tr.danger>th {
+ background-color: #694760;
+ }
+
+ .dark-mode .panel-heading {
+ padding: 10px 15px;
+ border-bottom: 1px solid transparent;
+ border-top-right-radius: 21px;
+ border-top-left-radius: 21px;
+ }
+
+ .dark-mode .table-bordered>thead>tr>th,
+ .dark-mode .table-bordered>thead>tr>td,
+ .dark-mode .table-bordered>tbody>tr>th,
+ .dark-mode .table-bordered>tbody>tr>td,
+ .dark-mode .table-bordered>tfoot>tr>th,
+ .dark-mode .table-bordered>tfoot>tr>td {
+ border: 1px solid;
+ border-color: rgba(221, 224, 255, .54);
+ }
+
+ /* Dark Mode - Input Fields */
+ .dark-mode input:not(#filterNavigateMenu),
+ .dark-mode textarea:not(#filterNavigateMenu),
+ .dark-mode select:not(#filterNavigateMenu),
+ .dark-mode .select2-selection:not(#filterNavigateMenu) {
+ color: inherit;
+ transition: all .5s ease-in-out;
+ }
+
+ .dark-mode input:focus:not(#filterNavigateMenu),
+ .dark-mode textarea:focus:not(#filterNavigateMenu),
+ .dark-mode select:focus:not(#filterNavigateMenu),
+ .dark-mode .select2-selection:focus:not(#filterNavigateMenu) {
+ color: #1f201f;
+ outline: none;
+ }
+
+ .dark-mode .nav-stacked>li>a {
+ color: inherit;
+ }
+
+ .dark-mode .input-group .form-control {
+ position: relative;
+ z-index: 2;
+ float: left;
+ width: 100%;
+ margin-bottom: 0;
+ color: inherit;
+ border-color: rgba(221, 224, 255, .54);
+ background-color: inherit;
+ }
+
+ .dark-mode .input-group .input-group-addon {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ color: inherit;
+ border-bottom-left-radius: 0;
+ border-color: rgba(221, 224, 255, .54);
+ background-color: transparent;
+ }
+
+ .dark-mode .input-group .form-control:last-child,
+ .dark-mode .input-group-addon:last-child,
+ .dark-mode .input-group-btn:last-child>.btn,
+ .dark-mode .input-group-btn:last-child>.btn-group>.btn,
+ .dark-mode .input-group-btn:last-child>.dropdown-toggle,
+ .dark-mode .input-group-btn:first-child>.btn:not(:first-child),
+ .dark-mode .input-group-btn:first-child>.btn-group:not(:first-child)>.btn {
+ color: inherit;
+ }
+
+ .dark-mode input:not(#filterNavigateMenu),
+ textarea:not(#filterNavigateMenu),
+ optgroup:not(#filterNavigateMenu),
+ select:not(#filterNavigateMenu),
+ .dark-mode .select2-selection:not(#filterNavigateMenu) {
+ -moz-transition: all .5s ease-in-out;
+ -o-transition: all .5s ease-in-out;
+ -webkit-transition: all .5s ease-in-out;
+ transition: all .5s ease-in-out;
+ }
+
+ .dark-mode .form-control {
+ display: block;
+ width: 100%;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.428571429;
+ color: inherit;
+ background-color: transparent;
+ background-image: none;
+ border: 1px solid;
+ border-color: rgba(221, 224, 255, .54);
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ }
+
+ .dark-mode .help-block {
+ display: block;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: inherit;
+ }
+
+ .dark-mode .text-muted {
+ color: rgba(221, 224, 255, .54);
+ }
+
+ .dark-mode .breadcrumb {
+ padding: 8px 15px;
+ margin-bottom: 20px;
+ list-style: none;
+ background-color: rgba(221, 224, 255, .54);
+ border-radius: 4px;
+ }
+
+ .dark-mode .pagination>.disabled>span,
+ .dark-mode .pagination>.disabled>span:hover,
+ .dark-mode .pagination>.disabled>span:focus,
+ .dark-mode .pagination>.disabled>a,
+ .dark-mode .pagination>.disabled>a:hover,
+ .dark-mode .pagination>.disabled>a:focus {
+ color: inherit;
+ background-color: rgba(221, 224, 255, .54);
+ border-color: rgba(221, 224, 255, .54);
+ cursor: not-allowed;
+ }
+
+ .dark-mode .pagination>.active>a,
+ .dark-mode .pagination>.active>a:hover,
+ .dark-mode .pagination>.active>a:focus,
+ .dark-mode .pagination>.active>span,
+ .dark-mode .pagination>.active>span:hover,
+ .dark-mode .pagination>.active>span:focus {
+ z-index: 2;
+ color: #fff;
+ background-color: #435ebe;
+ border-color: rgba(221, 224, 255, .54);
+ box-shadow: 0 2px 5px rgba(67, 94, 190, .3);
+ cursor: default;
+ }
+
+ .dark-mode .pagination>li>a {
+ background: inherit;
+ color: inherit;
+ border: 1px solid;
+ border-color: rgba(221, 224, 255, .54);
+ }
+
+ .dark-mode .table {
+ background-color: #2a2a2a;
+ color: #ddd;
+ border-color: #444;
+ }
+
+ .dark-mode .table th,
+ .dark-mode .table td {
+ background-color: #333;
+ border-color: #444;
+ color: #ddd;
+ }
+
+ .dark-mode .table th {
+ background-color: #444;
+ font-weight: bold;
+ }
+
+ .dark-mode .table-striped tbody tr:nth-of-type(odd) {
+ background-color: #3a3a3a;
+ }
+
+ .dark-mode .table-bordered {
+ border: 1px solid #444;
+ }
+
+ .dark-mode .table-hover tbody tr:hover {
+ background-color: #555;
+ color: #fff;
+ }
+
+ .dark-mode .table-condensed th,
+ .dark-mode .table-condensed td {
+ padding: 8px;
+ }
+
+ .dark-mode .panel>.table:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ }
+
+ .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child,
+ .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ }
+
+ .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,
+ .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,
+ .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,
+ .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,
+ .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child {
+ border-bottom-right-radius: 21px;
+ }
+
+ /* Dark Mode - Select2 Dropdown start here */
+ .dark-mode .select2-container--bootstrap .select2-results__option--highlighted[aria-selected] {
+ background-color: rgb(96, 89, 89);
+ color: #ffffff;
+ }
+
+ .dark-mode .select2-container--bootstrap .select2-results__option {
+ padding: 6px 12px;
+ background-color: rgb(96, 89, 89);
+ color: #f8f9fa;
+ }
+
+ .dark-mode .select2-results__option[aria-selected] {
+ cursor: pointer;
+ background-color: inherit;
+ color: #ffffff;
+ }
+
+ .dark-mode .select2-results__option {
+ padding: 6px 12px;
+ user-select: none;
+ -webkit-user-select: none;
+ background-color: #343a40;
+ color: #f8f9fa;
+ }
+
+ .dark-mode .select2-dropdown {
+ background-color: #343a40;
+ border-color: #454d55;
+ }
+
+ .dark-mode .select2-selection--single {
+ background-color: #495057;
+ color: #ffffff;
+ border-color: #454d55;
+ }
+
+ .dark-mode .select2-selection__rendered {
+ color: #ffffff;
+ }
+
+ .dark-mode .select2-selection__arrow b {
+ border-color: #ffffff transparent transparent transparent;
+ }
+
+ .dark-mode .select2-container--bootstrap .select2-selection--single .select2-selection__rendered {
+ color: inherit;
+ padding: 0;
+ }
+
+ .dark-mode .main-footer {
+ border-top: 1px solid transparent;
+ }
+
+ .dark-mode .list-group-item {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ margin-bottom: -1px;
+ background-color: transparent;
+ border: 1px solid rgba(221, 224, 255, .54);
+ }
+
+ .dark-mode .modern-skin-dark .main-sidebar .sidebar .sidebar-menu li>a {
+ font-weight: bold;
+ }
+
+ .dark-mode .content-header>h1 {
+ font-weight: bold;
+ }
+
+ .dark-mode .box-header>.fa,
+ .dark-mode .box-header>.glyphicon,
+ .dark-mode .box-header>.ion,
+ .dark-mode .box-header .box-title {
+ font-weight: bold;
+ }
+
+ /* Dark Mode - Select2 Dropdown ends here */
+
+ /* dark mode styles start ends here */
{if isset($xheader)}
{$xheader}
From 4f74aa0bff1908eac7303e73bd9314724a76b08c Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Thu, 5 Sep 2024 14:14:50 +0100
Subject: [PATCH 03/28] Please if you dont like the bold feature kindly report
it
---
ui/ui/sections/header.tpl | 12 ++++++++++++
ui/ui/user-ui/header.tpl | 12 ++++++++++++
2 files changed, 24 insertions(+)
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index 843109d9..d056aabc 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -256,6 +256,10 @@
font-weight: bold;
}
+ .main-header .logo .logo-lg {
+ font-weight: bold;
+ }
+
/* Search Bar Start Here */
.wrap {
width: 30%;
@@ -1003,6 +1007,14 @@
font-weight: bold;
}
+ .dark-mode .content-header>h2 {
+ font-weight: bold;
+ }
+
+ .dark-mode .main-header .logo .logo-lg {
+ font-weight: bold;
+ }
+
/* Dark Mode - Select2 Dropdown ends here */
/* dark mode styles start ends here */
diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl
index e52c1b69..09841709 100644
--- a/ui/ui/user-ui/header.tpl
+++ b/ui/ui/user-ui/header.tpl
@@ -264,6 +264,10 @@
font-weight: bold;
}
+ .main-header .logo .logo-lg {
+ font-weight: bold;
+ }
+
/* New Customize Interface End Here */
::-moz-selection {
@@ -705,6 +709,14 @@
.dark-mode .box-header .box-title {
font-weight: bold;
}
+
+ .dark-mode .content-header>h2 {
+ font-weight: bold;
+ }
+
+ .dark-mode .main-header .logo .logo-lg {
+ font-weight: bold;
+ }
{if isset($xheader)}
From c255a7be4972fcd47a30cee9593093bdf90dfd61 Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Thu, 5 Sep 2024 15:47:28 +0100
Subject: [PATCH 04/28] fix modal in dark mode
---
ui/ui/sections/header.tpl | 19 +++++++++++++++++++
ui/ui/user-ui/header.tpl | 20 ++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index d056aabc..0ea33f58 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -1015,6 +1015,25 @@
font-weight: bold;
}
+ .dark-mode .modal-content {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 15px;
+ border-bottom-left-radius: 15px;
+ -webkit-box-shadow: 0 2px 3px rgba(0, 0, 0, .125);
+ box-shadow: 0 2px 3px rgba(0, 0, 0, .125);
+ border: 0;
+ background: #1a202c;
+ }
+
+ .dark-mode .modal-header {
+ padding: 15px;
+ border-bottom: 1px solid rgba(221, 224, 255, .54);
+ min-height: 16.428571429px;
+ background-color: #1a202c;
+ color: inherit;
+ }
+
/* Dark Mode - Select2 Dropdown ends here */
/* dark mode styles start ends here */
diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl
index 09841709..f88820aa 100644
--- a/ui/ui/user-ui/header.tpl
+++ b/ui/ui/user-ui/header.tpl
@@ -717,6 +717,26 @@
.dark-mode .main-header .logo .logo-lg {
font-weight: bold;
}
+
+
+ .dark-mode .modal-content {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 15px;
+ border-bottom-left-radius: 15px;
+ -webkit-box-shadow: 0 2px 3px rgba(0, 0, 0, .125);
+ box-shadow: 0 2px 3px rgba(0, 0, 0, .125);
+ border: 0;
+ background: #1a202c;
+ }
+
+ .dark-mode .modal-header {
+ padding: 15px;
+ border-bottom: 1px solid rgba(221, 224, 255, .54);
+ min-height: 16.428571429px;
+ background-color: #1a202c;
+ color: inherit;
+ }
{if isset($xheader)}
From 299fd90949450257a8632a868f6c939f658963a0 Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Thu, 5 Sep 2024 16:13:14 +0100
Subject: [PATCH 05/28] fix dark mode drop-down menu
---
ui/ui/sections/header.tpl | 11 +++++++++++
ui/ui/user-ui/header.tpl | 22 ++++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index 0ea33f58..2588a37f 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -1034,6 +1034,17 @@
color: inherit;
}
+ .dark-mode .navbar-nav>.notifications-menu>.dropdown-menu>li.footer>a,
+ .dark-mode .navbar-nav>.messages-menu>.dropdown-menu>li.footer>a,
+ .dark-mode .navbar-nav>.tasks-menu>.dropdown-menu>li.footer>a {
+ background: #1a202c !important;
+ color: inherit !important;
+ }
+
+ .dark-mode .navbar-nav>.user-menu>.dropdown-menu>.user-footer {
+ background-color: #1a202c;
+ }
+
/* Dark Mode - Select2 Dropdown ends here */
/* dark mode styles start ends here */
diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl
index f88820aa..37b9e1ee 100644
--- a/ui/ui/user-ui/header.tpl
+++ b/ui/ui/user-ui/header.tpl
@@ -737,6 +737,28 @@
background-color: #1a202c;
color: inherit;
}
+
+
+ .dark-mode .navbar-nav>.notifications-menu>.dropdown-menu>li .menu>li>a,
+ .dark-mode .navbar-nav>.messages-menu>.dropdown-menu>li .menu>li>a,
+ .dark-mode .navbar-nav>.tasks-menu>.dropdown-menu>li .menu>li>a {
+ display: block;
+ white-space: nowrap;
+ border-bottom: 1px solid rgba(221, 224, 255, .54);
+ background: #1a202c;
+ color: inherit;
+ }
+
+ .dark-mode .navbar-nav>.notifications-menu>.dropdown-menu>li.footer>a,
+ .dark-mode .navbar-nav>.messages-menu>.dropdown-menu>li.footer>a,
+ .dark-mode .navbar-nav>.tasks-menu>.dropdown-menu>li.footer>a {
+ background: #1a202c !important;
+ color: inherit !important;
+ }
+
+ .dark-mode .navbar-nav>.user-menu>.dropdown-menu>.user-footer {
+ background-color: #1a202c;
+ }
{if isset($xheader)}
From 9e63d7ce20e9da98c7a957f8092347204e78572f Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Fri, 6 Sep 2024 11:36:30 +0100
Subject: [PATCH 06/28] add margin to the table list
---
ui/ui/reports.tpl | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/ui/ui/reports.tpl b/ui/ui/reports.tpl
index 21a39b9f..7303afb1 100644
--- a/ui/ui/reports.tpl
+++ b/ui/ui/reports.tpl
@@ -80,8 +80,9 @@
-
-
+
-
-
From 3aead7a98ab7a53fd8f93d99215e0dea58152ea1 Mon Sep 17 00:00:00 2001
From: Ibnu Maksum
Date: Mon, 9 Sep 2024 13:23:26 +0700
Subject: [PATCH 11/28] Fix toggle dark mode
---
ui/ui/user-ui/header.tpl | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl
index a2be9f04..4298c03a 100644
--- a/ui/ui/user-ui/header.tpl
+++ b/ui/ui/user-ui/header.tpl
@@ -333,9 +333,6 @@
.toggle-container {
- position: absolute;
- top: 17px;
- right: 15px;
cursor: pointer;
}
@@ -346,10 +343,6 @@
}
@media (max-width: 600px) {
- .toggle-container {
- top: 15px;
- right: 200px;
- }
.toggle-container .toggle-icon {
font-size: 20px;
@@ -781,13 +774,13 @@
-
+
@@ -72,7 +72,7 @@
@@ -81,7 +81,7 @@
@@ -104,38 +104,40 @@
-
-
-
- |
- {Lang::T('Internet Package')} |
- {Lang::T('Limit')} |
- |
-
- {Lang::T('Expired')} |
- |
-
-
- {Lang::T('Name')} |
- {Lang::T('Type')} |
- Bandwidth |
- {Lang::T('Category')} |
- {Lang::T('Price')} |
- {Lang::T('Validity')} |
- {Lang::T('Time')} |
- {Lang::T('Data')} |
- {Lang::T('Location')} |
- {Lang::T('Device')} |
- {Lang::T('Internet Package')} |
- {Lang::T('Date')} |
- {Lang::T('ID')} |
- {Lang::T('Manage')} |
-
-
-
- {foreach $d as $ds}
+
+
+
+
+ |
+ {Lang::T('Internet Package')} |
+
+ {Lang::T('Limit')} |
+ |
+
+ {Lang::T('Expired')} |
+ |
+
+
+ {Lang::T('Name')} |
+ {Lang::T('Type')} |
+ Bandwidth |
+ {Lang::T('Category')} |
+ {Lang::T('Price')} |
+ {Lang::T('Validity')} |
+ {Lang::T('Time')} |
+ {Lang::T('Data')} |
+ {Lang::T('Location')} |
+ {Lang::T('Device')} |
+ {Lang::T('Internet Package')} |
+ {Lang::T('Date')} |
+ {Lang::T('ID')} |
+ {Lang::T('Manage')} |
+
+
+
+ {foreach $d as $ds}
+ }class="warning" title="Postpaid" {/if}>
{$ds['name_plan']} |
{if $ds['prepaid'] == no}Postpaid{else}Prepaid{/if} {$ds['plan_type']} |
{$ds['name_bw']} |
@@ -146,11 +148,11 @@
{$ds['data_limit']} {$ds['data_unit']} |
{if $ds['is_radius']}
- RADIUS
+ RADIUS
{else}
- {if $ds['routers']!=''}
- {$ds['routers']}
- {/if}
+ {if $ds['routers']!=''}
+ {$ds['routers']}
+ {/if}
{/if}
|
{$ds['device']} |
@@ -163,13 +165,14 @@
{Lang::T('Edit')}
+ onclick="return confirm('{Lang::T('Delete')}?')"
+ class="btn btn-danger btn-xs">
- {/foreach}
-
-
+ {/foreach}
+
+
+
-{include file="sections/footer.tpl"}
+{include file="sections/footer.tpl"}
\ No newline at end of file
diff --git a/ui/ui/plan.tpl b/ui/ui/plan.tpl
index 4cf71280..3cca5861 100644
--- a/ui/ui/plan.tpl
+++ b/ui/ui/plan.tpl
@@ -5,19 +5,19 @@
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
-
- {*
*}
+
+ {*
*}
{/if}
-{Lang::T('Active Customers')}
+ {Lang::T('Active Customers')}
@@ -70,33 +70,34 @@
-
-
-
- {Lang::T('Username')} |
- {Lang::T('Plan Name')} |
- {Lang::T('Type')} |
- {Lang::T('Created On')} |
- {Lang::T('Expires On')} |
- {Lang::T('Method')} |
- {Lang::T('Location')} |
- {Lang::T('Manage')} |
-
-
-
- {foreach $d as $ds}
-
+
+
+
{include file="pagination.tpl"}
@@ -131,10 +133,10 @@
var res = prompt("Extend for many days?", "3");
if (res) {
if (confirm("Extend for " + res + " days?")) {
- window.location.href = "{$_url}plan/extend/"+idP+"/"+res+"&stoken={App::getToken()}";
+ window.location.href = "{$_url}plan/extend/" + idP + "/" + res + "&stoken={App::getToken()}";
}
}
}
-{include file="sections/footer.tpl"}
+{include file="sections/footer.tpl"}
\ No newline at end of file
diff --git a/ui/ui/pppoe.tpl b/ui/ui/pppoe.tpl
index 3c17d6b1..9dfc8711 100644
--- a/ui/ui/pppoe.tpl
+++ b/ui/ui/pppoe.tpl
@@ -35,8 +35,8 @@
@@ -44,9 +44,9 @@
@@ -54,8 +54,8 @@
@@ -63,8 +63,8 @@
@@ -72,7 +72,7 @@
@@ -81,7 +81,7 @@
@@ -104,36 +104,38 @@
-
-
-
- |
- {Lang::T('Internet Plan')} |
- |
-
- {Lang::T('Expired')} |
- |
-
-
- {Lang::T('Name')} |
- {Lang::T('Type')} |
- {Lang::T('Bandwidth')} |
- {Lang::T('Price')} |
- {Lang::T('Validity')} |
- {Lang::T('IP Pool')} |
- {Lang::T('Internet Plan')} |
- {Lang::T('Date')} |
- {Lang::T('Location')} |
- {Lang::T('Device')} |
- {Lang::T('Manage')} |
- ID |
-
-
-
- {foreach $d as $ds}
-
+
+
+
+
+ |
+ {Lang::T('Internet Plan')} |
+ |
+
+ {Lang::T('Expired')} |
+ |
+
+
+ {Lang::T('Name')} |
+ {Lang::T('Type')} |
+ {Lang::T('Bandwidth')} |
+ {Lang::T('Price')} |
+ {Lang::T('Validity')} |
+ {Lang::T('IP Pool')} |
+ {Lang::T('Internet Plan')} |
+ {Lang::T('Date')} |
+ {Lang::T('Location')} |
+ {Lang::T('Device')} |
+ {Lang::T('Manage')} |
+ ID |
+
+
+
+ {foreach $d as $ds}
+
{$ds['name_plan']} |
- {$ds['plan_type']} {if $ds['prepaid'] != 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if} |
+ {$ds['plan_type']} {if $ds['prepaid'] !=
+ 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if} |
{$ds['name_bw']} |
{Lang::moneyFormat($ds['price'])} |
{$ds['validity']} {$ds['validity_unit']} |
@@ -144,11 +146,11 @@
{if $ds['prepaid'] == no}{$ds['expired_date']}{/if} |
{if $ds['is_radius']}
- RADIUS
+ RADIUS
{else}
- {if $ds['routers']!=''}
- {$ds['routers']}
- {/if}
+ {if $ds['routers']!=''}
+ {$ds['routers']}
+ {/if}
{/if}
|
{$ds['device']} |
@@ -161,9 +163,10 @@
{$ds['id']} |
- {/foreach}
-
-
+ {/foreach}
+
+
+
-{include file="sections/footer.tpl"}
+{include file="sections/footer.tpl"}
\ No newline at end of file
diff --git a/ui/ui/voucher.tpl b/ui/ui/voucher.tpl
index 6f357b48..abf652f0 100644
--- a/ui/ui/voucher.tpl
+++ b/ui/ui/voucher.tpl
@@ -17,11 +17,12 @@
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
-
+
{/if}
@@ -41,8 +42,8 @@
@@ -50,7 +51,7 @@
@@ -65,7 +66,7 @@
@@ -76,8 +77,8 @@
class="fa fa-search">
@@ -85,24 +86,25 @@
-
-
-
- ID |
- {Lang::T('Type')} |
- {Lang::T('Routers')} |
- {Lang::T('Plan Name')} |
- {Lang::T('Code Voucher')} |
- {Lang::T('Status Voucher')} |
- {Lang::T('Customer')} |
- {Lang::T('Used Date')} |
- {Lang::T('Generated By')} |
- {Lang::T('Manage')} |
-
-
-
- {foreach $d as $ds}
-
+
+
+
+
+ ID |
+ {Lang::T('Type')} |
+ {Lang::T('Routers')} |
+ {Lang::T('Plan Name')} |
+ {Lang::T('Code Voucher')} |
+ {Lang::T('Status Voucher')} |
+ {Lang::T('Customer')} |
+ {Lang::T('Used Date')} |
+ {Lang::T('Generated By')} |
+ {Lang::T('Manage')} |
+
+
+
+ {foreach $d as $ds}
+
{$ds['id']} |
{$ds['type']} |
{$ds['routers']} |
@@ -112,33 +114,35 @@
onmouseenter="this.style.backgroundColor = 'white';">
{$ds['code']}
{if $ds['status'] eq '0'} {else}
+ {else}
{/if} |
{if $ds['user'] eq '0'} -
{else}{$ds['user']}
{/if} |
{if $ds['used_date']}{Lang::dateTimeFormat($ds['used_date'])}{/if} |
{if $ds['generated_by']}
- {$admins[$ds['generated_by']]}
+ {$admins[$ds['generated_by']]}
{else} -
{/if}
|
{if $ds['status'] neq '1'}
- {Lang::T('View')}
+ {Lang::T('View')}
{/if}
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
-
+
{/if}
|
- {/foreach}
-
-
+ {/foreach}
+
+
+
{include file="pagination.tpl"}
-{include file="sections/footer.tpl"}
+{include file="sections/footer.tpl"}
\ No newline at end of file
From 723e99ebedc231e502707621ec169cd1da57aa57 Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Wed, 11 Sep 2024 14:19:13 +0100
Subject: [PATCH 16/28] fix panel headers in css, add cron job monitor to check
if cron is running, has run, or not setup
---
system/controllers/dashboard.php | 6 +++
system/cron.php | 69 ++++++++++++++++++--------------
ui/ui/dashboard.tpl | 17 ++++++++
ui/ui/sections/header.tpl | 30 ++++++++++++--
4 files changed, 87 insertions(+), 35 deletions(-)
diff --git a/system/controllers/dashboard.php b/system/controllers/dashboard.php
index 4d1c9849..9f1185b0 100644
--- a/system/controllers/dashboard.php
+++ b/system/controllers/dashboard.php
@@ -214,6 +214,12 @@ if ($config['router_check']) {
$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);
diff --git a/system/cron.php b/system/cron.php
index e4e6719c..81d9f423 100644
--- a/system/cron.php
+++ b/system/cron.php
@@ -1,6 +1,27 @@
where('enabled', '1')->find_many();
if (!$routers) {
echo "No active routers found in the database.\n";
@@ -186,14 +187,20 @@ if ($config['router_check']) {
Message::SendEmail($adminEmail, $subject, $message);
sendTelegram($message);
}
-
- if (defined('PHP_SAPI') && PHP_SAPI === 'cli') {
- echo "Cronjob finished\n";
- } else {
- echo "";
- }
-
- flock($lock, LOCK_UN);
- fclose($lock);
- unlink($lockFile);
+ echo "Router monitoring finished\n";
}
+
+
+if (defined('PHP_SAPI') && PHP_SAPI === 'cli') {
+ echo "Cronjob finished\n";
+} else {
+ echo "";
+}
+
+flock($lock, LOCK_UN);
+fclose($lock);
+unlink($lockFile);
+
+$timestampFile = "$UPLOAD_PATH/cron_last_run.txt";
+file_put_contents($timestampFile, time());
+
diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl
index eb6788da..7a998ba8 100644
--- a/ui/ui/dashboard.tpl
+++ b/ui/ui/dashboard.tpl
@@ -194,6 +194,23 @@
{/if}
+ {if $run_date}
+ {if $current_time - $run_time > 3600}
+
+
{Lang::T('Cron has not run for over 1 hour. Please
+ check your setup.')}
+
+ {else}
+
+
{Lang::T('Cron Job last ran on')}: {$run_date}
+
+ {/if}
+ {else}
+
+
{Lang::T('Cron appear not been setup, please check
+ your cron setup.')}
+
+ {/if}
{if $_c['hide_pg'] != 'yes'}
{Lang::T('Payment Gateway')}: {str_replace(',',', ',$_c['payment_gateway'])}
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index bba3dbce..34b7f1e9 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -148,12 +148,26 @@
color: inherit;
background-color: transparent;
border-color: transparent;
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
}
- .panel-primary>.panel-heading {
- color: inherit;
- background-color: transparent;
- border-color: transparent;
+ .panel-success>.panel-heading {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ }
+
+ .panel-warning>.panel-heading {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ }
+
+ .panel-danger>.panel-heading {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #ebccd1;
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
}
.panel-heading {
@@ -656,6 +670,9 @@
}
.toggle-container {
+ position: absolute;
+ top: 17px;
+ right: 15px;
cursor: pointer;
}
@@ -666,6 +683,11 @@
}
@media (max-width: 600px) {
+ .toggle-container {
+ top: 15px;
+ right: 60px;
+ }
+
.toggle-container .toggle-icon {
font-size: 20px;
color: rgb(100 116 139);
From 05b681df47fb12f84725091f3831b0199a96a545 Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Wed, 11 Sep 2024 14:38:54 +0100
Subject: [PATCH 17/28] change current_time to current_date
---
ui/ui/dashboard.tpl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl
index 7a998ba8..78955672 100644
--- a/ui/ui/dashboard.tpl
+++ b/ui/ui/dashboard.tpl
@@ -195,7 +195,7 @@
{/if}
{if $run_date}
- {if $current_time - $run_time > 3600}
+ {if $current_date - $run_time > 3600}
{Lang::T('Cron has not run for over 1 hour. Please
check your setup.')}
From fe532a62386a5b588d65cb8fdd1b5d9097153fac Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Wed, 11 Sep 2024 16:52:34 +0100
Subject: [PATCH 18/28] change the time calculation logic
---
ui/ui/dashboard.tpl | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl
index 78955672..f0432982 100644
--- a/ui/ui/dashboard.tpl
+++ b/ui/ui/dashboard.tpl
@@ -195,7 +195,9 @@
{/if}
{if $run_date}
- {if $current_date - $run_time > 3600}
+ {assign var="current_time" value=$smarty.now}
+ {assign var="run_time" value=strtotime($run_date)}
+ {if $current_time - $run_time > 3600}
{Lang::T('Cron has not run for over 1 hour. Please
check your setup.')}
From 68de3a71b930f55c0713197c745263e088601b0b Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Thu, 12 Sep 2024 11:39:45 +0100
Subject: [PATCH 19/28] if admin session time error, it logout admin out
whether admin are online or not, once time reach it logout you out
---
system/autoload/Admin.php | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/system/autoload/Admin.php b/system/autoload/Admin.php
index 66052cda..18d016c6 100644
--- a/system/autoload/Admin.php
+++ b/system/autoload/Admin.php
@@ -13,25 +13,27 @@ class Admin
{
global $db_pass, $config;
$enable_session_timeout = $config['enable_session_timeout'];
- if ($enable_session_timeout) {
- $timeout = 60;
- if ($config['session_timeout_duration']) {
- $timeout = intval($config['session_timeout_duration']);
+ $session_timeout_duration = $config['session_timeout_duration'] ? intval($config['session_timeout_duration'] * 60) : intval(60 * 60); // Convert minutes to seconds
+
+ // Check if the session is active and valid
+ if (isset($_SESSION['aid']) && isset($_SESSION['aid_expiration'])) {
+ if ($_SESSION['aid_expiration'] > time()) {
+ if ($enable_session_timeout) {
+ $_SESSION['aid_expiration'] = time() + $session_timeout_duration;
+ }
+ return $_SESSION['aid'];
+ }
+ // Session expired, log out the user
+ elseif ($enable_session_timeout && $_SESSION['aid_expiration'] <= time()) {
+ self::removeCookie();
+ session_destroy();
+ _alert(Lang::T('Session has expired. Please log in again.'), 'danger', "admin");
+ return 0;
}
- $session_timeout_duration = $timeout * 60; // Convert minutes to seconds
}
- if (isset($_SESSION['aid']) && isset($_SESSION['aid_expiration']) && $_SESSION['aid_expiration'] > time()) {
- return $_SESSION['aid'];
- } elseif ($enable_session_timeout && isset($_SESSION['aid']) && isset($_SESSION['aid_expiration']) && $_SESSION['aid_expiration'] <= time()) {
- self::removeCookie();
- session_destroy();
- _alert(Lang::T('Session has expired. Please log in again.'), 'danger', "admin");
- return 0;
- }
- // Check if cookie is set and valid
+ // Check if the cookie is set and valid
elseif (isset($_COOKIE['aid'])) {
- // id.time.sha1
$tmp = explode('.', $_COOKIE['aid']);
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_pass) == $tmp[2]) {
if (time() - $tmp[1] < 86400 * 7) {
From 095e8937a29c6279b86e6ea5fcf5c0b94c0e1943 Mon Sep 17 00:00:00 2001
From: agamsatria
Date: Fri, 13 Sep 2024 00:43:46 +0700
Subject: [PATCH 20/28] Paket vpn tunnel remot
---
system/controllers/home.php | 10 +-
system/controllers/order.php | 7 +
system/controllers/pool.php | 126 +++++++++++
system/controllers/services.php | 374 ++++++++++++++++++++++++++++++++
system/controllers/settings.php | 10 +
system/updates.json | 6 +
ui/ui/app-localisation.tpl | 8 +
ui/ui/customers-add.tpl | 1 +
ui/ui/customers-edit.tpl | 1 +
ui/ui/plan.tpl | 10 +-
ui/ui/port-add.tpl | 51 +++++
ui/ui/port-edit.tpl | 49 +++++
ui/ui/port.tpl | 76 +++++++
ui/ui/recharge.tpl | 1 +
ui/ui/scripts/custom.js | 23 +-
ui/ui/sections/header.tpl | 4 +
ui/ui/user-ui/dashboard.tpl | 25 ++-
ui/ui/user-ui/orderPlan.tpl | 104 +++++++++
ui/ui/vpn-add.tpl | 188 ++++++++++++++++
ui/ui/vpn-edit.tpl | 255 ++++++++++++++++++++++
ui/ui/vpn.tpl | 179 +++++++++++++++
21 files changed, 1502 insertions(+), 6 deletions(-)
create mode 100644 ui/ui/port-add.tpl
create mode 100644 ui/ui/port-edit.tpl
create mode 100644 ui/ui/port.tpl
create mode 100644 ui/ui/vpn-add.tpl
create mode 100644 ui/ui/vpn-edit.tpl
create mode 100644 ui/ui/vpn.tpl
diff --git a/system/controllers/home.php b/system/controllers/home.php
index a71d340e..20e1d1b6 100644
--- a/system/controllers/home.php
+++ b/system/controllers/home.php
@@ -317,7 +317,15 @@ if (!empty($_SESSION['nux-mac']) && !empty($_SESSION['nux-ip'] && !empty($_SESSI
}
}
}
-
+
+$tcf = ORM::for_table('tbl_customers_fields')
+ ->where('customer_id', $user['id'])
+ ->find_many();
+$vpn = ORM::for_table('tbl_port_pool')
+ ->find_one();
+$ui->assign('cf', $tcf);
+$ui->assign('vpn', $vpn);
+
$ui->assign('unpaid', ORM::for_table('tbl_payment_gateway')
->where('username', $user['username'])
->where('status', 1)
diff --git a/system/controllers/order.php b/system/controllers/order.php
index 0d4b2a3c..988db104 100644
--- a/system/controllers/order.php
+++ b/system/controllers/order.php
@@ -113,12 +113,19 @@ switch ($action) {
->where('type', 'Hotspot')
->where('prepaid', 'yes')
->find_many();
+ $plans_vpn = ORM::for_table('tbl_plans')
+ ->where('plan_type', $account_type)
+ ->where('enabled', '1')->where('is_radius', 0)
+ ->where('type', 'VPN')
+ ->where('prepaid', 'yes')
+ ->find_many();
}
$ui->assign('routers', $routers);
$ui->assign('radius_pppoe', $radius_pppoe);
$ui->assign('radius_hotspot', $radius_hotspot);
$ui->assign('plans_pppoe', $plans_pppoe);
$ui->assign('plans_hotspot', $plans_hotspot);
+ $ui->assign('plans_vpn', $plans_vpn);
run_hook('customer_view_order_plan'); #HOOK
$ui->display('user-ui/orderPlan.tpl');
break;
diff --git a/system/controllers/pool.php b/system/controllers/pool.php
index 5528e751..ba599f22 100644
--- a/system/controllers/pool.php
+++ b/system/controllers/pool.php
@@ -147,6 +147,132 @@ switch ($action) {
} else {
r2(U . 'pool/edit/' . $id, 'e', $msg);
}
+
+ case 'port':
+ $ui->assign('xfooter', '');
+
+ $name = _post('name');
+ if ($name != '') {
+ $query = ORM::for_table('tbl_port_pool')->where_like('pool_name', '%' . $name . '%')->order_by_desc('id');
+ $d = Paginator::findMany($query, ['name' => $name]);
+ } else {
+ $query = ORM::for_table('tbl_port_pool')->order_by_desc('id');
+ $d = Paginator::findMany($query);
+ }
+
+ $ui->assign('d', $d);
+ run_hook('view_port'); #HOOK
+ $ui->display('port.tpl');
+ break;
+
+ case 'add-port':
+ $r = ORM::for_table('tbl_routers')->find_many();
+ $ui->assign('r', $r);
+ run_hook('view_add_port'); #HOOK
+ $ui->display('port-add.tpl');
+ break;
+
+ case 'edit-port':
+ $id = $routes['2'];
+ $d = ORM::for_table('tbl_port_pool')->find_one($id);
+ if ($d) {
+ $ui->assign('d', $d);
+ run_hook('view_edit_port'); #HOOK
+ $ui->display('port-edit.tpl');
+ } else {
+ r2(U . 'pool/port', 'e', Lang::T('Account Not Found'));
+ }
+ break;
+
+ case 'delete-port':
+ $id = $routes['2'];
+ run_hook('delete_port'); #HOOK
+ $d = ORM::for_table('tbl_port_pool')->find_one($id);
+ if ($d) {
+ $d->delete();
+
+ r2(U . 'pool/port', 's', Lang::T('Data Deleted Successfully'));
+ }
+ break;
+
+ case 'sync':
+ $pools = ORM::for_table('tbl_port_pool')->find_many();
+ $log = '';
+ foreach ($pools as $pool) {
+ if ($pool['routers'] != 'radius') {
+ (new MikrotikPppoe())->update_pool($pool, $pool);
+ $log .= 'DONE: ' . $pool['port_name'] . ': ' . $pool['range_port'] . '
';
+ }
+ }
+ r2(U . 'pool/list', 's', $log);
+ break;
+ case 'add-port-post':
+ $name = _post('name');
+ $port_range = _post('port_range');
+ $public_ip = _post('public_ip');
+ $routers = _post('routers');
+ run_hook('add_pool'); #HOOK
+ $msg = '';
+ if (Validator::Length($name, 30, 2) == false) {
+ $msg .= 'Name should be between 3 to 30 characters' . '
';
+ }
+ if ($port_range == '' or $routers == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+
+ $d = ORM::for_table('tbl_port_pool')->where('routers', $routers)->find_one();
+ if ($d) {
+ $msg .= Lang::T('Routers already have ports, each router can only have 1 port range!') . '
';
+ }
+ if ($msg == '') {
+ $b = ORM::for_table('tbl_port_pool')->create();
+ $b->public_ip = $public_ip;
+ $b->port_name = $name;
+ $b->range_port = $port_range;
+ $b->routers = $routers;
+ $b->save();
+ r2(U . 'pool/port', 's', Lang::T('Data Created Successfully'));
+ } else {
+ r2(U . 'pool/add-port', 'e', $msg);
+ }
+ break;
+
+
+ case 'edit-port-post':
+ $name = _post('name');
+ $public_ip = _post('public_ip');
+ $range_port = _post('range_port');
+ $routers = _post('routers');
+ run_hook('edit_port'); #HOOK
+ $msg = '';
+ $msg = '';
+ if (Validator::Length($name, 30, 2) == false) {
+ $msg .= 'Name should be between 3 to 30 characters' . '
';
+ }
+ if ($range_port == '' or $routers == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+
+ $id = _post('id');
+ $d = ORM::for_table('tbl_port_pool')->find_one($id);
+ $old = ORM::for_table('tbl_port_pool')->find_one($id);
+ if (!$d) {
+ $msg .= Lang::T('Data Not Found') . '
';
+ }
+
+ if ($msg == '') {
+ $d->port_name = $name;
+ $d->public_ip = $public_ip;
+ $d->range_port = $range_port;
+ $d->routers = $routers;
+ $d->save();
+
+
+
+ r2(U . 'pool/port', 's', Lang::T('Data Updated Successfully'));
+ } else {
+ r2(U . 'pool/edit-port/' . $id, 'e', $msg);
+ }
break;
default:
diff --git a/system/controllers/services.php b/system/controllers/services.php
index aaa69635..9bc32e5e 100644
--- a/system/controllers/services.php
+++ b/system/controllers/services.php
@@ -901,6 +901,380 @@ switch ($action) {
r2(U . 'services/balance-add', 'e', $msg);
}
break;
+ case 'vpn':
+ $ui->assign('_title', Lang::T('VPN Plans'));
+ $ui->assign('xfooter', '');
+
+ $name = _post('name');
+ $name = _req('name');
+ $type1 = _req('type1');
+ $type2 = _req('type2');
+ $type3 = _req('type3');
+ $bandwidth = _req('bandwidth');
+ $valid = _req('valid');
+ $device = _req('device');
+ $status = _req('status');
+ $router = _req('router');
+ $ui->assign('type1', $type1);
+ $ui->assign('type2', $type2);
+ $ui->assign('type3', $type3);
+ $ui->assign('bandwidth', $bandwidth);
+ $ui->assign('valid', $valid);
+ $ui->assign('device', $device);
+ $ui->assign('status', $status);
+ $ui->assign('router', $router);
+
+ $append_url = "&type1=" . urlencode($type1)
+ . "&type2=" . urlencode($type2)
+ . "&type3=" . urlencode($type3)
+ . "&bandwidth=" . urlencode($bandwidth)
+ . "&valid=" . urlencode($valid)
+ . "&device=" . urlencode($device)
+ . "&status=" . urlencode($status)
+ . "&router=" . urlencode($router);
+
+ $bws = ORM::for_table('tbl_plans')->distinct()->select("id_bw")->where('tbl_plans.type', 'VPN')->findArray();
+ $ids = array_column($bws, 'id_bw');
+ if(count($ids)){
+ $ui->assign('bws', ORM::for_table('tbl_bandwidth')->select("id")->select('name_bw')->where_id_in($ids)->findArray());
+ }else{
+ $ui->assign('bws', []);
+ }
+ $ui->assign('type2s', ORM::for_table('tbl_plans')->getEnum("plan_type"));
+ $ui->assign('type3s', ORM::for_table('tbl_plans')->getEnum("typebp"));
+ $ui->assign('valids', ORM::for_table('tbl_plans')->getEnum("validity_unit"));
+ $ui->assign('routers', array_column(ORM::for_table('tbl_plans')->distinct()->select("routers")->whereNotEqual('routers', '')->findArray(), 'routers'));
+ $devices = [];
+ $files = scandir($DEVICE_PATH);
+ foreach ($files as $file) {
+ $ext = pathinfo($file, PATHINFO_EXTENSION);
+ if ($ext == 'php') {
+ $devices[] = pathinfo($file, PATHINFO_FILENAME);
+ }
+ }
+ $ui->assign('devices', $devices);
+ $query = ORM::for_table('tbl_bandwidth')
+ ->left_outer_join('tbl_plans', array('tbl_bandwidth.id', '=', 'tbl_plans.id_bw'))
+ ->where('tbl_plans.type', 'VPN');
+ if (!empty($type1)) {
+ $query->where('tbl_plans.prepaid', $type1);
+ }
+ if (!empty($type2)) {
+ $query->where('tbl_plans.plan_type', $type2);
+ }
+ if (!empty($type3)) {
+ $query->where('tbl_plans.typebp', $type3);
+ }
+ if (!empty($bandwidth)) {
+ $query->where('tbl_plans.id_bw', $bandwidth);
+ }
+ if (!empty($valid)) {
+ $query->where('tbl_plans.validity_unit', $valid);
+ }
+ if (!empty($router)) {
+ if ($router == 'radius') {
+ $query->where('tbl_plans.is_radius', '1');
+ } else {
+ $query->where('tbl_plans.routers', $router);
+ }
+ }
+ if (!empty($device)) {
+ $query->where('tbl_plans.device', $device);
+ }
+ if (in_array($status, ['0', '1'])) {
+ $query->where('tbl_plans.enabled', $status);
+ }
+ if ($name != '') {
+ $query->where_like('tbl_plans.name_plan', '%' . $name . '%');
+ }
+ $d = Paginator::findMany($query, ['name' => $name], 20, $append_url);
+
+ $ui->assign('d', $d);
+ run_hook('view_list_vpn'); #HOOK
+ $ui->display('vpn.tpl');
+ break;
+
+ case 'vpn-add':
+ $ui->assign('_title', Lang::T('VPN Plans'));
+ $d = ORM::for_table('tbl_bandwidth')->find_many();
+ $ui->assign('d', $d);
+ $r = ORM::for_table('tbl_routers')->find_many();
+ $ui->assign('r', $r);
+ $devices = [];
+ $files = scandir($DEVICE_PATH);
+ foreach ($files as $file) {
+ $ext = pathinfo($file, PATHINFO_EXTENSION);
+ if ($ext == 'php') {
+ $devices[] = pathinfo($file, PATHINFO_FILENAME);
+ }
+ }
+ $ui->assign('devices', $devices);
+ run_hook('view_add_vpn'); #HOOK
+ $ui->display('vpn-add.tpl');
+ break;
+
+ case 'vpn-edit':
+ $ui->assign('_title', Lang::T('VPN Plans'));
+ $id = $routes['2'];
+ $d = ORM::for_table('tbl_plans')->find_one($id);
+ if ($d) {
+ if (empty($d['device'])) {
+ if ($d['is_radius']) {
+ $d->device = 'Radius';
+ } else {
+ $d->device = 'MikrotikVpn';
+ }
+ $d->save();
+ }
+ $ui->assign('d', $d);
+ $p = ORM::for_table('tbl_pool')->where('routers', ($d['is_radius']) ? 'radius' : $d['routers'])->find_many();
+ $ui->assign('p', $p);
+ $b = ORM::for_table('tbl_bandwidth')->find_many();
+ $ui->assign('b', $b);
+ $r = [];
+ if ($d['is_radius']) {
+ $r = ORM::for_table('tbl_routers')->find_many();
+ }
+ $ui->assign('r', $r);
+ $devices = [];
+ $files = scandir($DEVICE_PATH);
+ foreach ($files as $file) {
+ $ext = pathinfo($file, PATHINFO_EXTENSION);
+ if ($ext == 'php') {
+ $devices[] = pathinfo($file, PATHINFO_FILENAME);
+ }
+ }
+ $ui->assign('devices', $devices);
+ //select expired plan
+ if ($d['is_radius']) {
+ $exps = ORM::for_table('tbl_plans')->selects('id', 'name_plan')->where('type', 'VPN')->where("is_radius", 1)->findArray();
+ } else {
+ $exps = ORM::for_table('tbl_plans')->selects('id', 'name_plan')->where('type', 'VPN')->where("routers", $d['routers'])->findArray();
+ }
+ $ui->assign('exps', $exps);
+ run_hook('view_edit_vpn'); #HOOK
+ $ui->display('vpn-edit.tpl');
+ } else {
+ r2(U . 'services/vpn', 'e', Lang::T('Account Not Found'));
+ }
+ break;
+
+ case 'vpn-delete':
+ $id = $routes['2'];
+
+ $d = ORM::for_table('tbl_plans')->find_one($id);
+ if ($d) {
+ run_hook('delete_vpn'); #HOOK
+
+ $dvc = Package::getDevice($d);
+ if ($_app_stage != 'demo') {
+ if (file_exists($dvc)) {
+ require_once $dvc;
+ (new $d['device'])->remove_plan($d);
+ } else {
+ new Exception(Lang::T("Devices Not Found"));
+ }
+ }
+ $d->delete();
+
+ r2(U . 'services/vpn', 's', Lang::T('Data Deleted Successfully'));
+ }
+ break;
+
+ case 'vpn-add-post':
+ $name = _post('name_plan');
+ $plan_type = _post('plan_type');
+ $radius = _post('radius');
+ $id_bw = _post('id_bw');
+ $price = _post('price');
+ $validity = _post('validity');
+ $validity_unit = _post('validity_unit');
+ $routers = _post('routers');
+ $device = _post('device');
+ $pool = _post('pool_name');
+ $enabled = _post('enabled');
+ $prepaid = _post('prepaid');
+ $expired_date = _post('expired_date');
+
+
+ $msg = '';
+ if (Validator::UnsignedNumber($validity) == false) {
+ $msg .= 'The validity must be a number' . '
';
+ }
+ if (Validator::UnsignedNumber($price) == false) {
+ $msg .= 'The price must be a number' . '
';
+ }
+ if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+ if (empty($radius)) {
+ if ($routers == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+ }
+
+ $d = ORM::for_table('tbl_plans')->where('name_plan', $name)->find_one();
+ if ($d) {
+ $msg .= Lang::T('Name Plan Already Exist') . '
';
+ }
+ run_hook('add_vpn'); #HOOK
+ if ($msg == '') {
+ $b = ORM::for_table('tbl_bandwidth')->where('id', $id_bw)->find_one();
+ if ($b['rate_down_unit'] == 'Kbps') {
+ $unitdown = 'K';
+ $raddown = '000';
+ } else {
+ $unitdown = 'M';
+ $raddown = '000000';
+ }
+ if ($b['rate_up_unit'] == 'Kbps') {
+ $unitup = 'K';
+ $radup = '000';
+ } else {
+ $unitup = 'M';
+ $radup = '000000';
+ }
+ $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
+ $radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
+ $rate = trim($rate . " " . $b['burst']);
+ $d = ORM::for_table('tbl_plans')->create();
+ $d->type = 'VPN';
+ $d->name_plan = $name;
+ $d->id_bw = $id_bw;
+ $d->price = $price;
+ $d->plan_type = $plan_type;
+ $d->validity = $validity;
+ $d->validity_unit = $validity_unit;
+ $d->pool = $pool;
+ if (!empty($radius)) {
+ $d->is_radius = 1;
+ $d->routers = '';
+ } else {
+ $d->is_radius = 0;
+ $d->routers = $routers;
+ }
+ if ($prepaid == 'no') {
+ if ($expired_date > 28 && $expired_date < 1) {
+ $expired_date = 20;
+ }
+ $d->expired_date = $expired_date;
+ } else {
+ $d->expired_date = 0;
+ }
+ $d->enabled = $enabled;
+ $d->prepaid = $prepaid;
+ $d->device = $device;
+ $d->save();
+
+ $dvc = Package::getDevice($d);
+ if ($_app_stage != 'demo') {
+ if (file_exists($dvc)) {
+ require_once $dvc;
+ (new $d['device'])->add_plan($d);
+ } else {
+ new Exception(Lang::T("Devices Not Found"));
+ }
+ }
+ r2(U . 'services/vpn', 's', Lang::T('Data Created Successfully'));
+ } else {
+ r2(U . 'services/vpn-add', 'e', $msg);
+ }
+ break;
+
+ case 'edit-vpn-post':
+ $id = _post('id');
+ $plan_type = _post('plan_type');
+ $name = _post('name_plan');
+ $id_bw = _post('id_bw');
+ $price = _post('price');
+ $validity = _post('validity');
+ $validity_unit = _post('validity_unit');
+ $routers = _post('routers');
+ $device = _post('device');
+ $pool = _post('pool_name');
+ $plan_expired = _post('plan_expired');
+ $enabled = _post('enabled');
+ $prepaid = _post('prepaid');
+ $expired_date = _post('expired_date');
+ $on_login = _post('on_login');
+ $on_logout = _post('on_logout');
+
+ $msg = '';
+ if (Validator::UnsignedNumber($validity) == false) {
+ $msg .= 'The validity must be a number' . '
';
+ }
+ if (Validator::UnsignedNumber($price) == false) {
+ $msg .= 'The price must be a number' . '
';
+ }
+ if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') {
+ $msg .= Lang::T('All field is required') . '
';
+ }
+
+ $d = ORM::for_table('tbl_plans')->where('id', $id)->find_one();
+ $old = ORM::for_table('tbl_plans')->where('id', $id)->find_one();
+ if ($d) {
+ } else {
+ $msg .= Lang::T('Data Not Found') . '
';
+ }
+ run_hook('edit_vpn'); #HOOK
+ if ($msg == '') {
+ $b = ORM::for_table('tbl_bandwidth')->where('id', $id_bw)->find_one();
+ if ($b['rate_down_unit'] == 'Kbps') {
+ $unitdown = 'K';
+ $raddown = '000';
+ } else {
+ $unitdown = 'M';
+ $raddown = '000000';
+ }
+ if ($b['rate_up_unit'] == 'Kbps') {
+ $unitup = 'K';
+ $radup = '000';
+ } else {
+ $unitup = 'M';
+ $radup = '000000';
+ }
+ $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
+ $radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
+ $rate = trim($rate . " " . $b['burst']);
+
+ $d->name_plan = $name;
+ $d->id_bw = $id_bw;
+ $d->price = $price;
+ $d->plan_type = $plan_type;
+ $d->validity = $validity;
+ $d->validity_unit = $validity_unit;
+ $d->routers = $routers;
+ $d->pool = $pool;
+ $d->plan_expired = $plan_expired;
+ $d->enabled = $enabled;
+ $d->prepaid = $prepaid;
+ $d->device = $device;
+ $d->on_login = $on_login;
+ $d->on_logout = $on_logout;
+ if ($prepaid == 'no') {
+ if ($expired_date > 28 && $expired_date < 1) {
+ $expired_date = 20;
+ }
+ $d->expired_date = $expired_date;
+ } else {
+ $d->expired_date = 0;
+ }
+ $d->save();
+
+ $dvc = Package::getDevice($d);
+ if ($_app_stage != 'demo') {
+ if (file_exists($dvc)) {
+ require_once $dvc;
+ (new $d['device'])->update_plan($old, $d);
+ } else {
+ new Exception(Lang::T("Devices Not Found"));
+ }
+ }
+ r2(U . 'services/vpn', 's', Lang::T('Data Updated Successfully'));
+ } else {
+ r2(U . 'services/vpn-edit/' . $id, 'e', $msg);
+ }
+ break;
default:
$ui->display('a404.tpl');
}
diff --git a/system/controllers/settings.php b/system/controllers/settings.php
index 33e4abe9..96cb497b 100644
--- a/system/controllers/settings.php
+++ b/system/controllers/settings.php
@@ -295,6 +295,16 @@ switch ($action) {
$d->value = _post('pppoe_plan');
$d->save();
}
+ $d = ORM::for_table('tbl_appconfig')->where('setting', 'vpn_plan')->find_one();
+ if ($d) {
+ $d->value = _post('vpn_plan');
+ $d->save();
+ } else {
+ $d = ORM::for_table('tbl_appconfig')->create();
+ $d->setting = 'vpn_plan';
+ $d->value = _post('vpn_plan');
+ $d->save();
+ }
$currency_code = $_POST['currency_code'];
$d = ORM::for_table('tbl_appconfig')->where('setting', 'currency_code')->find_one();
diff --git a/system/updates.json b/system/updates.json
index bce2f4ef..8d66fc0c 100644
--- a/system/updates.json
+++ b/system/updates.json
@@ -155,5 +155,11 @@
"2024.8.28" : [
"ALTER TABLE `tbl_routers` ADD `status` ENUM('Online', 'Offline') DEFAULT 'Online' AFTER `coordinates`;",
"ALTER TABLE `tbl_routers` ADD `last_seen` DATETIME AFTER `status`;"
+ ],
+ "2024.9.13" : [
+ "ALTER TABLE `tbl_plans` CHANGE `type` `type` ENUM('Hotspot','PPPOE','VPN','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;",
+ "ALTER TABLE `tbl_customers` CHANGE `service_type` `service_type` ENUM('Hotspot','PPPoE','VPN','Others') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'Others' COMMENT 'For selecting user type';",
+ "ALTER TABLE `tbl_transactions` CHANGE `type` `type` ENUM('Hotspot','PPPOE','VPN','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;",
+ "CREATE TABLE IF NOT EXISTS `tbl_port_pool` ( `id` int(10) NOT NULL AUTO_INCREMENT , `public_ip` varchar(40) NOT NULL, `port_name` varchar(40) NOT NULL, `range_port` varchar(40) NOT NULL, `routers` varchar(40) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;"
]
}
\ No newline at end of file
diff --git a/ui/ui/app-localisation.tpl b/ui/ui/app-localisation.tpl
index 936c3abb..571d5588 100644
--- a/ui/ui/app-localisation.tpl
+++ b/ui/ui/app-localisation.tpl
@@ -128,6 +128,14 @@
{Lang::T('Change title in user Plan order')}
+
diff --git a/ui/ui/plan.tpl b/ui/ui/plan.tpl
index 3cca5861..32111f4a 100644
--- a/ui/ui/plan.tpl
+++ b/ui/ui/plan.tpl
@@ -95,9 +95,13 @@
{/if}
{if $ds['type'] == 'Hotspot'}
- {$ds['namebp']} |
- {else}
- {$ds['namebp']} |
+ {$ds['namebp']} |
+ {/if}
+ {if $ds['type'] == 'PPPOE'}
+ {$ds['namebp']} |
+ {/if}
+ {if $ds['type'] == 'VPN'}
+ {$ds['namebp']} |
{/if}
{$ds['type']} |
{Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])} |
diff --git a/ui/ui/port-add.tpl b/ui/ui/port-add.tpl
new file mode 100644
index 00000000..b689a896
--- /dev/null
+++ b/ui/ui/port-add.tpl
@@ -0,0 +1,51 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
{Lang::T('Add Port Pool')}
+
+
+
+
+
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/port-edit.tpl b/ui/ui/port-edit.tpl
new file mode 100644
index 00000000..46413314
--- /dev/null
+++ b/ui/ui/port-edit.tpl
@@ -0,0 +1,49 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
{Lang::T('Edit Port')}
+
+
+
+
+
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/port.tpl b/ui/ui/port.tpl
new file mode 100644
index 00000000..77fd2661
--- /dev/null
+++ b/ui/ui/port.tpl
@@ -0,0 +1,76 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
+
+ {Lang::T('Port Pool')} - VPN Tunnels
+
+
+
+
+
+
+
+ {Lang::T('Port Name')} |
+ {Lang::T('Public IP')} |
+ {Lang::T('Range Port')} |
+ {Lang::T('Routers')} |
+ {Lang::T('Manage')} |
+ ID |
+
+
+
+ {foreach $d as $ds}
+
+ {$ds['port_name']} |
+ {$ds['public_ip']} |
+ {$ds['range_port']} |
+ {$ds['routers']} |
+
+ {Lang::T('Edit')}
+
+ |
+ {$ds['id']} |
+
+ {/foreach}
+
+
+
+ {include file="pagination.tpl"}
+
+
{Lang::T('Create expired Internet Plan')}
+
{Lang::T('When customer expired, you can move it to Expired Internet Plan')}
+
+
+
+
+
+
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/recharge.tpl b/ui/ui/recharge.tpl
index b896ab50..96370d58 100644
--- a/ui/ui/recharge.tpl
+++ b/ui/ui/recharge.tpl
@@ -22,6 +22,7 @@
+
@@ -215,6 +219,25 @@
{$_bill['plan_type']}
+ {if $_bill['type'] == 'VPN' && $_bill['routers'] == $vpn['routers']}
+
+ {Lang::T('Public IP')} |
+ {$vpn['public_ip']} / {$vpn['port_name']} |
+
+
+ {Lang::T('Private IP')} |
+ {$_user['pppoe_ip']} |
+
+ {foreach $cf as $tcf}
+
+ {if $tcf['field_name'] == 'Winbox' or $tcf['field_name'] == 'Api' or $tcf['field_name'] == 'Web'}
+ {$tcf['field_name']} - Port |
+ {$tcf['field_value']} |
+
+ {/if}
+ {/foreach}
+ {/if}
+
{if $nux_ip neq ''}
{Lang::T('Current IP')} |
diff --git a/ui/ui/user-ui/orderPlan.tpl b/ui/ui/user-ui/orderPlan.tpl
index f79ed4dd..9db514ff 100644
--- a/ui/ui/user-ui/orderPlan.tpl
+++ b/ui/ui/user-ui/orderPlan.tpl
@@ -226,6 +226,7 @@
{/if}
{foreach $routers as $router}
{if Validator::isRouterHasPlan($plans_hotspot, $router['name']) || Validator::isRouterHasPlan($plans_pppoe,
+ $router['name']) || Validator::isRouterHasPlan($plans_vpn,
$router['name'])}
@@ -338,9 +339,62 @@
{/if}
{/foreach}
+ {/if}
+ {if $_user['service_type'] == 'VPN' && Validator::countRouterPlan($plans_vpn,$router['name'])>0}
+
+
+ {foreach $plans_vpn as $plan}
+ {if $router['name'] eq $plan['routers']}
+
+
+
+
+
+
+
+
+ {Lang::T('Type')} |
+ {$plan['type']} |
+
+
+ {Lang::T('Price')} |
+ {Lang::moneyFormat($plan['price'])} |
+
+
+ {Lang::T('Validity')} |
+ {$plan['validity']} {$plan['validity_unit']} |
+
+
+
+
+
+
+
+ {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' &&
+ $_user['balance']>=$plan['price']}
+
{Lang::T('Buy for friend')}
+ {/if}
+
+
+
+ {/if}
+ {/foreach}
+
{/if}
{if $_user['service_type'] == 'Others' || $_user['service_type'] == '' &&
(Validator::countRouterPlan($plans_hotspot, $router['name'])>0 || Validator::countRouterPlan($plans_pppoe,
+ $router['name'])>0 || Validator::countRouterPlan($plans_vpn,
$router['name'])>0)}
@@ -443,6 +497,56 @@
{/if}
{/foreach}
+
+
+ {foreach $plans_vpn as $plan}
+ {if $router['name'] eq $plan['routers']}
+
+
+
+
+
+
+
+
+ {Lang::T('Type')} |
+ {$plan['type']} |
+
+
+ {Lang::T('Price')} |
+ {Lang::moneyFormat($plan['price'])} |
+
+
+ {Lang::T('Validity')} |
+ {$plan['validity']} {$plan['validity_unit']} |
+
+
+
+
+
+
+
+ {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' &&
+ $_user['balance']>=$plan['price']}
+
{Lang::T('Buy for friend')}
+ {/if}
+
+
+
+ {/if}
+ {/foreach}
+
{/if}
{/if}
diff --git a/ui/ui/vpn-add.tpl b/ui/ui/vpn-add.tpl
new file mode 100644
index 00000000..ae26a8ac
--- /dev/null
+++ b/ui/ui/vpn-add.tpl
@@ -0,0 +1,188 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
{Lang::T('Add Service Plan')}
+
+
+
+
+
+{if $_c['radius_enable']}
+ {literal}
+
+ {/literal}
+{/if}
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/vpn-edit.tpl b/ui/ui/vpn-edit.tpl
new file mode 100644
index 00000000..53428605
--- /dev/null
+++ b/ui/ui/vpn-edit.tpl
@@ -0,0 +1,255 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{include file="sections/footer.tpl"}
diff --git a/ui/ui/vpn.tpl b/ui/ui/vpn.tpl
new file mode 100644
index 00000000..6047e446
--- /dev/null
+++ b/ui/ui/vpn.tpl
@@ -0,0 +1,179 @@
+{include file="sections/header.tpl"}
+
+
+
+
+
+
{Lang::T('VPN Package')}
+
+
+
+
+
+
+ |
+ {Lang::T('Internet Plan')} |
+ |
+
+ {Lang::T('Expired')} |
+ |
+
+
+ {Lang::T('Name')} |
+ {Lang::T('Type')} |
+ {Lang::T('Bandwidth')} |
+ {Lang::T('Price')} |
+ {Lang::T('Validity')} |
+ {Lang::T('IP Pool')} |
+ {Lang::T('Internet Plan')} |
+ {Lang::T('Date')} |
+ {Lang::T('Location')} |
+ {Lang::T('Device')} |
+ {Lang::T('Manage')} |
+ ID |
+
+
+
+ {foreach $d as $ds}
+
+ {$ds['name_plan']} |
+ {$ds['plan_type']} {if $ds['prepaid'] != 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if} |
+ {$ds['name_bw']} |
+ {Lang::moneyFormat($ds['price'])} |
+ {$ds['validity']} {$ds['validity_unit']} |
+ {$ds['pool']} |
+ {if $ds['plan_expired']}{Lang::T('Yes')}{else}{Lang::T('No')}
+ {/if} |
+ {if $ds['prepaid'] == no}{$ds['expired_date']}{/if} |
+
+ {if $ds['is_radius']}
+ RADIUS
+ {else}
+ {if $ds['routers']!=''}
+ {$ds['routers']}
+ {/if}
+ {/if}
+ |
+ {$ds['device']} |
+
+ {Lang::T('Edit')}
+
+ |
+ {$ds['id']} |
+
+ {/foreach}
+
+
+
+
+
+
+
+
+{include file="sections/footer.tpl"}
From f5d9649f97e512751dbcb1eec8c1c40925c31fde Mon Sep 17 00:00:00 2001
From: AGSTR <144728914+agstrxyz@users.noreply.github.com>
Date: Fri, 13 Sep 2024 00:46:40 +0700
Subject: [PATCH 21/28] Add files via upload
---
system/devices/MikrotikVpn.php | 504 +++++++++++++++++++++++++++++++++
1 file changed, 504 insertions(+)
create mode 100644 system/devices/MikrotikVpn.php
diff --git a/system/devices/MikrotikVpn.php b/system/devices/MikrotikVpn.php
new file mode 100644
index 00000000..6edeed2c
--- /dev/null
+++ b/system/devices/MikrotikVpn.php
@@ -0,0 +1,504 @@
+ 'Mikrotik Vpn',
+ 'description' => 'To handle connection between PHPNuxBill with Mikrotik VPN',
+ 'author' => 'agstr',
+ 'url' => [
+ 'Github' => 'https://github.com/agstrxyz',
+ 'Telegram' => 'https://t.me/agstrxyz',
+ 'Youtube' => 'https://www.youtube.com/@agstrxyz',
+ 'Donate' => 'https://paypal.me/ibnux'
+ ]
+ ];
+ }
+
+ function add_customer($customer, $plan)
+ {
+ global $isChangePlan;
+ $mikrotik = $this->info($plan['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+ $cid = self::getIdByCustomer($customer, $client);
+ if (empty($cid)) {
+ $this->addVpnUser($client, $plan, $customer);
+ }else{
+ $setRequest = new RouterOS\Request('/ppp/secret/set');
+ $setRequest->setArgument('numbers', $cid);
+ if (!empty($customer['pppoe_password'])) {
+ $setRequest->setArgument('password', $customer['pppoe_password']);
+ } else {
+ $setRequest->setArgument('password', $customer['password']);
+ }
+ if (!empty($customer['pppoe_username'])) {
+ $setRequest->setArgument('name', $customer['pppoe_username']);
+ } else {
+ $setRequest->setArgument('name', $customer['username']);
+ }
+ if (!empty($customer['pppoe_ip'])) {
+ $setRequest->setArgument('remote-address', $customer['pppoe_ip']);
+ }else{
+ $setRequest->setArgument('remote-address', '0.0.0.0');
+ }
+ $setRequest->setArgument('profile', $plan['name_plan']);
+ $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id'])));
+ $client->sendSync($setRequest);
+ if(isset($isChangePlan) && $isChangePlan){
+ $this->removeVpnActive($client, $customer['username']);
+ if (!empty($customer['pppoe_username'])) {
+ $this->removeVpnActive($client, $customer['pppoe_username']);
+ }
+ }
+ }
+ }
+
+ function remove_customer($customer, $plan)
+ {
+ $mikrotik = $this->info($plan['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+ if (!empty($plan['plan_expired'])) {
+ $p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']);
+ if($p){
+ $this->add_customer($customer, $p);
+ $this->removeVpnActive($client, $customer['username']);
+ if (!empty($customer['pppoe_username'])) {
+ $this->removeVpnActive($client, $customer['pppoe_username']);
+ }
+ return;
+ }
+ }
+ $this->removeVpnUser($client, $customer['username'], $customer['id']);
+ if (!empty($customer['pppoe_username'])) {
+ $this->removeVpnUser($client, $customer['pppoe_username'], $customer['id']);
+ }
+ $this->removeVpnActive($client, $customer['username']);
+ if (!empty($customer['pppoe_username'])) {
+ $this->removeVpnActive($client, $customer['pppoe_username']);
+ }
+ }
+
+ public function change_username($plan, $from, $to)
+ {
+ $mikrotik = $this->info($plan['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+ $printRequest = new RouterOS\Request('/ppp/secret/print');
+ $printRequest->setQuery(RouterOS\Query::where('name', $from));
+ $cid = $client->sendSync($printRequest)->getProperty('.id');
+ if (!empty($cid)) {
+ $setRequest = new RouterOS\Request('/ppp/secret/set');
+ $setRequest->setArgument('numbers', $cid);
+ $setRequest->setArgument('name', $to);
+ $client->sendSync($setRequest);
+ $this->removeVpnActive($client, $from);
+ }
+ }
+
+ function add_plan($plan)
+ {
+ $mikrotik = $this->info($plan['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+
+
+ $bw = ORM::for_table("tbl_bandwidth")->find_one($plan['id_bw']);
+ if ($bw['rate_down_unit'] == 'Kbps') {
+ $unitdown = 'K';
+ } else {
+ $unitdown = 'M';
+ }
+ if ($bw['rate_up_unit'] == 'Kbps') {
+ $unitup = 'K';
+ } else {
+ $unitup = 'M';
+ }
+ $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown;
+ if(!empty(trim($bw['burst']))){
+ $rate .= ' '.$bw['burst'];
+ }
+ $pool = ORM::for_table("tbl_pool")->where("pool_name", $plan['pool'])->find_one();
+ $addRequest = new RouterOS\Request('/ppp/profile/add');
+ $client->sendSync(
+ $addRequest
+ ->setArgument('name', $plan['name_plan'])
+ ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name'])
+ ->setArgument('remote-address', $pool['pool_name'])
+ ->setArgument('rate-limit', $rate)
+ );
+ }
+
+
+ function getIdByCustomer($customer, $client){
+ $printRequest = new RouterOS\Request('/ppp/secret/print');
+ $printRequest->setQuery(RouterOS\Query::where('name', $customer['username']));
+ $id = $client->sendSync($printRequest)->getProperty('.id');
+ if(empty($id)){
+ if (!empty($customer['pppoe_username'])) {
+ $printRequest = new RouterOS\Request('/ppp/secret/print');
+ $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username']));
+ $id = $client->sendSync($printRequest)->getProperty('.id');
+ }
+ }
+ return $id;
+ }
+
+ function update_plan($old_name, $new_plan)
+ {
+ $mikrotik = $this->info($new_plan['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+
+ $printRequest = new RouterOS\Request(
+ '/ppp profile print .proplist=.id',
+ RouterOS\Query::where('name', $old_name['name_plan'])
+ );
+ $profileID = $client->sendSync($printRequest)->getProperty('.id');
+ if (empty($profileID)) {
+ $this->add_plan($new_plan);
+ } else {
+ $bw = ORM::for_table("tbl_bandwidth")->find_one($new_plan['id_bw']);
+ if ($bw['rate_down_unit'] == 'Kbps') {
+ $unitdown = 'K';
+ } else {
+ $unitdown = 'M';
+ }
+ if ($bw['rate_up_unit'] == 'Kbps') {
+ $unitup = 'K';
+ } else {
+ $unitup = 'M';
+ }
+ $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown;
+ if(!empty(trim($bw['burst']))){
+ $rate .= ' '.$bw['burst'];
+ }
+ $pool = ORM::for_table("tbl_pool")->where("pool_name", $new_plan['pool'])->find_one();
+ $setRequest = new RouterOS\Request('/ppp/profile/set');
+ $client->sendSync(
+ $setRequest
+ ->setArgument('numbers', $profileID)
+ ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name'])
+ ->setArgument('remote-address', $pool['pool_name'])
+ ->setArgument('rate-limit', $rate)
+ ->setArgument('on-up', $new_plan['on_login'])
+ ->setArgument('on-down', $new_plan['on_logout'])
+ );
+ }
+ }
+
+ function remove_plan($plan)
+ {
+ $mikrotik = $this->info($plan['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+ $printRequest = new RouterOS\Request(
+ '/ppp profile print .proplist=.id',
+ RouterOS\Query::where('name', $plan['name_plan'])
+ );
+ $profileID = $client->sendSync($printRequest)->getProperty('.id');
+
+ $removeRequest = new RouterOS\Request('/ppp/profile/remove');
+ $client->sendSync(
+ $removeRequest
+ ->setArgument('numbers', $profileID)
+ );
+ }
+
+ function add_pool($pool){
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $mikrotik = $this->info($pool['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+ $addRequest = new RouterOS\Request('/ip/pool/add');
+ $client->sendSync(
+ $addRequest
+ ->setArgument('name', $pool['pool_name'])
+ ->setArgument('ranges', $pool['range_ip'])
+ );
+ }
+
+ function update_pool($old_pool, $new_pool){
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $mikrotik = $this->info($new_pool['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+ $printRequest = new RouterOS\Request(
+ '/ip pool print .proplist=.id',
+ RouterOS\Query::where('name', $old_pool['pool_name'])
+ );
+ $poolID = $client->sendSync($printRequest)->getProperty('.id');
+ if (empty($poolID)) {
+ $this->add_pool($new_pool);
+ } else {
+ $setRequest = new RouterOS\Request('/ip/pool/set');
+ $client->sendSync(
+ $setRequest
+ ->setArgument('numbers', $poolID)
+ ->setArgument('name', $new_pool['pool_name'])
+ ->setArgument('ranges', $new_pool['range_ip'])
+ );
+ }
+ }
+
+ function remove_pool($pool){
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $mikrotik = $this->info($pool['routers']);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+ $printRequest = new RouterOS\Request(
+ '/ip pool print .proplist=.id',
+ RouterOS\Query::where('name', $pool['pool_name'])
+ );
+ $poolID = $client->sendSync($printRequest)->getProperty('.id');
+ $removeRequest = new RouterOS\Request('/ip/pool/remove');
+ $client->sendSync(
+ $removeRequest
+ ->setArgument('numbers', $poolID)
+ );
+ }
+
+
+ function online_customer($customer, $router_name)
+ {
+ $mikrotik = $this->info($router_name);
+ $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
+ $printRequest = new RouterOS\Request(
+ '/ppp active print',
+ RouterOS\Query::where('user', $customer['username'])
+ );
+ return $client->sendSync($printRequest)->getProperty('.id');
+ }
+
+ function info($name)
+ {
+ return ORM::for_table('tbl_routers')->where('name', $name)->find_one();
+ }
+
+ function getClient($ip, $user, $pass)
+ {
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $iport = explode(":", $ip);
+ return new RouterOS\Client($iport[0], $user, $pass, ($iport[1]) ? $iport[1] : null);
+ }
+
+ function removeVpnUser($client, $username, $cstid)
+ {
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $printRequest = new RouterOS\Request('/ppp/secret/print');
+ //$printRequest->setArgument('.proplist', '.id');
+ $printRequest->setQuery(RouterOS\Query::where('name', $username));
+ $id = $client->sendSync($printRequest)->getProperty('.id');
+ $removeRequest = new RouterOS\Request('/ppp/secret/remove');
+ $removeRequest->setArgument('numbers', $id);
+ $client->sendSync($removeRequest);
+ $this->rmNat($client, $cstid);
+ }
+
+ function addVpnUser($client, $plan, $customer)
+ {
+ $setRequest = new RouterOS\Request('/ppp/secret/add');
+ $setRequest->setArgument('service', 'any');
+ $setRequest->setArgument('profile', $plan['name_plan']);
+ $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id'])));
+ if (!empty($customer['pppoe_password'])) {
+ $setRequest->setArgument('password', $customer['pppoe_password']);
+ } else {
+ $setRequest->setArgument('password', $customer['password']);
+ }
+ if (!empty($customer['pppoe_username'])) {
+ $setRequest->setArgument('name', $customer['pppoe_username']);
+ } else {
+ $setRequest->setArgument('name', $customer['username']);
+ }
+ if (!empty($customer['pppoe_ip'])) {
+ $ips = $customer['pppoe_ip'];
+ $setRequest->setArgument('remote-address', $customer['pppoe_ip']);
+ } else {
+ $ips = $this->checkIpAddr($plan['pool'], $customer['id']);
+ $setRequest->setArgument('remote-address', $ips);
+
+ }
+ $this->addNat($client, $plan, $customer, $ips);
+ $client->sendSync($setRequest);
+ $customer->service_type = 'VPN';
+ $customer->pppoe_ip = $ips;
+ $customer->save();
+ }
+
+ function removeVpnActive($client, $username)
+ {
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $onlineRequest = new RouterOS\Request('/ppp/active/print');
+ $onlineRequest->setArgument('.proplist', '.id');
+ $onlineRequest->setQuery(RouterOS\Query::where('name', $username));
+ $id = $client->sendSync($onlineRequest)->getProperty('.id');
+
+ $removeRequest = new RouterOS\Request('/ppp/active/remove');
+ $removeRequest->setArgument('numbers', $id);
+ $client->sendSync($removeRequest);
+ }
+
+
+ function addIpToAddressList($client, $ip, $listName, $comment = '')
+ {
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $addRequest = new RouterOS\Request('/ip/firewall/address-list/add');
+ $client->sendSync(
+ $addRequest
+ ->setArgument('address', $ip)
+ ->setArgument('comment', $comment)
+ ->setArgument('list', $listName)
+ );
+
+ }
+
+ function removeIpFromAddressList($client, $ip)
+ {
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $printRequest = new RouterOS\Request(
+ '/ip firewall address-list print .proplist=.id',
+ RouterOS\Query::where('address', $ip)
+ );
+ $id = $client->sendSync($printRequest)->getProperty('.id');
+ $removeRequest = new RouterOS\Request('/ip/firewall/address-list/remove');
+ $client->sendSync(
+ $removeRequest
+ ->setArgument('numbers', $id)
+ );
+ }
+
+ function addNat($client, $plan, $cust, $ips)
+ {
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $this->checkPort($cust['id'], 'Winbox', $plan['routers']);
+ $this->checkPort($cust['id'], 'Api', $plan['routers']);
+ $this->checkPort($cust['id'], 'Web', $plan['routers']);
+ $tcf = ORM::for_table('tbl_customers_fields')
+ ->where('customer_id', $cust['id'])
+ ->find_many();
+
+ foreach ($tcf as $cf) {
+ $dst = $cf['field_value'];
+ $cmnt = $cf['field_name'];
+ if ($cmnt == 'Winbox') {
+ $tp = '8291'; }
+ if ($cmnt == 'Web') {
+ $tp = '80'; }
+ if ($cmnt == 'Api') {
+ $tp = '8728'; }
+ if ($cmnt == 'Winbox' || $cmnt == 'Web' || $cmnt == 'Api') {
+ $addRequest = new RouterOS\Request('/ip/firewall/nat/add');
+ $client->sendSync(
+ $addRequest
+ ->setArgument('chain', 'dstnat')
+ ->setArgument('protocol', 'tcp')
+ ->setArgument('dst-port', $dst)
+ ->setArgument('action', 'dst-nat')
+ ->setArgument('to-addresses', $ips)
+ ->setArgument('to-ports', $tp)
+ ->setArgument('address', $ip)
+ ->setArgument('comment', $cmnt.' || '.$cust['username'])
+ );
+ }
+ }
+ }
+
+ function rmNat($client, $cstid)
+ {
+ global $_app_stage;
+ if ($_app_stage == 'demo') {
+ return null;
+ }
+ $tcf = ORM::for_table('tbl_customers_fields')
+ ->where('customer_id', $cstid)
+ ->find_many();
+ $cst = ORM::for_table('tbl_customers')->find_one($cstid);
+ $printRequest = new RouterOS\Request('/ip/firewall/nat/print');
+ $printRequest->setQuery(RouterOS\Query::where('to-addresses', $cst['pppoe_ip']));
+ $nats = $client->sendSync($printRequest);
+ foreach ($nats as $nat) {
+ $id = $client->sendSync($printRequest)->getProperty('.id');
+ $removeRequest = new RouterOS\Request('/ip/firewall/nat/remove');
+ $removeRequest->setArgument('numbers', $id);
+ $client->sendSync($removeRequest);
+ }
+ }
+
+
+ function checkPort($id, $portn, $router)
+ {
+ $tcf = ORM::for_table('tbl_customers_fields')
+ ->where('customer_id', $id)
+ ->where('field_name', $portn)
+ ->find_one();
+ $ports = ORM::for_table('tbl_port_pool')
+ ->where('routers', $router)
+ ->find_one();
+ $port = explode('-',$ports['range_port']);
+ if (empty($tcf) && !empty($ports)) {
+ repeat:
+ $portr = rand($port['0'], $port['1']);
+ if (ORM::for_table('tbl_customers_fields')->where('field_value', $portr)->find_one()) {
+ if($portr == $port['1'])
+ {
+ return;
+ }
+ goto repeat;
+ }
+ $cf = ORM::for_table('tbl_customers_fields')->create();
+ $cf->customer_id = $id;
+ $cf->field_name = $portn;
+ $cf->field_value = $portr;
+ $cf->save();
+ }
+ }
+
+ function checkIpAddr($pname, $id) {
+ $c = ORM::for_table('tbl_customers')->find_one($id);
+ $ipp = ORM::for_table('tbl_pool')
+ ->where('pool_name', $pname)
+ ->find_one();
+ $ip_r = explode('-',$ipp['range_ip']);
+ $ip_1 = explode('.',$ip_r['0']);
+ $ip_2 = explode('.',$ip_r['1']);
+ repeat:
+ $ipt = rand($ip_1['3'], $ip_2['3']);
+ $ips = $ip_1['0'].'.'.$ip_1['1'].'.'.$ip_1['2'].'.'.$ipt;
+ if (empty($c['pppoe_ip'])) {
+ if (ORM::for_table('tbl_customers')->where('pppoe_ip' ,$ips)->find_one()) {
+ if ($ip_2['3'] == $ipt)
+ {
+ return;
+ }
+ goto repeat;
+ }
+ return $ips;
+ }
+ }
+
+}
From 82569239e2a1d43e355d06ed7f01a5eb8838554a Mon Sep 17 00:00:00 2001
From: Ibnu Maksum
Date: Fri, 13 Sep 2024 14:46:14 +0700
Subject: [PATCH 22/28] update changelog
---
CHANGELOG.md | 7 +++++++
version.json | 2 +-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21df89e6..8f9e0862 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,13 @@
# CHANGELOG
+## 2024.9.13
+
+- Add Selling Mikrotik VPN By @agstrxyz
+- Theme Redesign by @Focuslinkstech
+- Fix That and this
+
+
## 2024.8.28
- add Router Status Offline/Online by @Focuslinkstech
diff --git a/version.json b/version.json
index 1bd146b2..13f748ef 100644
--- a/version.json
+++ b/version.json
@@ -1,3 +1,3 @@
{
- "version": "2024.9.6"
+ "version": "2024.9.13"
}
\ No newline at end of file
From c2916da21541812a277b24c1772c95a9cf6d4f35 Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Fri, 13 Sep 2024 09:33:59 +0100
Subject: [PATCH 23/28] fix dark button
---
ui/ui/sections/header.tpl | 3 ---
1 file changed, 3 deletions(-)
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index bb5f8525..a86d1409 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -670,9 +670,6 @@
}
.toggle-container {
- position: absolute;
- top: 17px;
- right: 15px;
cursor: pointer;
}
From a31286d7812f34fa12a99e21899476f3065be8d1 Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Fri, 13 Sep 2024 09:47:43 +0100
Subject: [PATCH 24/28] fix toggle switch button mobile view
---
ui/ui/sections/header.tpl | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index a86d1409..862dbe4d 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -679,19 +679,6 @@
transition: color 0.5s ease;
}
- @media (max-width: 600px) {
- .toggle-container {
- top: 15px;
- right: 60px;
- }
-
- .toggle-container .toggle-icon {
- font-size: 20px;
- color: rgb(100 116 139);
- transition: color 0.5s ease;
- }
- }
-
.dark-mode .toggle-container .toggle-icon {
color: #ffdd57;
}
From 985ddda41f9c5cc07cd6e18d9563be475634da70 Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Fri, 13 Sep 2024 09:55:58 +0100
Subject: [PATCH 25/28] fix panel warning bottom radius
---
ui/ui/dashboard.tpl | 2 +-
ui/ui/sections/header.tpl | 5 -----
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl
index f0432982..b47f0796 100644
--- a/ui/ui/dashboard.tpl
+++ b/ui/ui/dashboard.tpl
@@ -198,7 +198,7 @@
{assign var="current_time" value=$smarty.now}
{assign var="run_time" value=strtotime($run_date)}
{if $current_time - $run_time > 3600}
-
+
{Lang::T('Cron has not run for over 1 hour. Please
check your setup.')}
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index 862dbe4d..a075a25a 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -157,11 +157,6 @@
border-bottom-left-radius: 21px;
}
- .panel-warning>.panel-heading {
- border-bottom-right-radius: 21px;
- border-bottom-left-radius: 21px;
- }
-
.panel-danger>.panel-heading {
color: #a94442;
background-color: #f2dede;
From 3c6ef3bcf34fac4a861036cdb55e8f9b5606057b Mon Sep 17 00:00:00 2001
From: AGSTR <144728914+agstrxyz@users.noreply.github.com>
Date: Fri, 13 Sep 2024 16:31:03 +0700
Subject: [PATCH 26/28] Update MikrotikVpn.php
---
system/devices/MikrotikVpn.php | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/system/devices/MikrotikVpn.php b/system/devices/MikrotikVpn.php
index 6edeed2c..a8f41fec 100644
--- a/system/devices/MikrotikVpn.php
+++ b/system/devices/MikrotikVpn.php
@@ -400,8 +400,10 @@ class MikrotikVpn
$this->checkPort($cust['id'], 'Web', $plan['routers']);
$tcf = ORM::for_table('tbl_customers_fields')
->where('customer_id', $cust['id'])
- ->find_many();
-
+ ->find_many();
+ $ip = ORM::for_table('tbl_port_pool')
+ ->where('routers', $plan['routers'])
+ ->find_one();
foreach ($tcf as $cf) {
$dst = $cf['field_value'];
$cmnt = $cf['field_name'];
@@ -421,7 +423,7 @@ class MikrotikVpn
->setArgument('action', 'dst-nat')
->setArgument('to-addresses', $ips)
->setArgument('to-ports', $tp)
- ->setArgument('address', $ip)
+ ->setArgument('dst-address', $ip['public_ip'])
->setArgument('comment', $cmnt.' || '.$cust['username'])
);
}
@@ -434,9 +436,7 @@ class MikrotikVpn
if ($_app_stage == 'demo') {
return null;
}
- $tcf = ORM::for_table('tbl_customers_fields')
- ->where('customer_id', $cstid)
- ->find_many();
+
$cst = ORM::for_table('tbl_customers')->find_one($cstid);
$printRequest = new RouterOS\Request('/ip/firewall/nat/print');
$printRequest->setQuery(RouterOS\Query::where('to-addresses', $cst['pppoe_ip']));
From f81f3df700196ea2b022dd7f9c7bb578cb5a26ec Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Fri, 13 Sep 2024 10:43:42 +0100
Subject: [PATCH 27/28] add mailer error reporting
---
system/autoload/Message.php | 3 +++
1 file changed, 3 insertions(+)
diff --git a/system/autoload/Message.php b/system/autoload/Message.php
index 988c98e0..cdc04525 100644
--- a/system/autoload/Message.php
+++ b/system/autoload/Message.php
@@ -154,6 +154,9 @@ class Message
$mail->Body = $body;
}
$mail->send();
+ if (!$mail->send()) {
+ _log(Lang::T("Email not sent, Mailer Error: ") . $mail->ErrorInfo);
+ }
//
}
From f738c9b120b324c447f5fa4bf0db30481577c58a Mon Sep 17 00:00:00 2001
From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com>
Date: Fri, 13 Sep 2024 12:03:18 +0100
Subject: [PATCH 28/28] add seperate css for cron monitor
---
ui/ui/dashboard.tpl | 6 +++---
ui/ui/sections/header.tpl | 24 ++++++++++++++++++++++++
2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl
index b47f0796..79db90d3 100644
--- a/ui/ui/dashboard.tpl
+++ b/ui/ui/dashboard.tpl
@@ -198,17 +198,17 @@
{assign var="current_time" value=$smarty.now}
{assign var="run_time" value=strtotime($run_date)}
{if $current_time - $run_time > 3600}
-
+
{Lang::T('Cron has not run for over 1 hour. Please
check your setup.')}
{else}
-
+
{Lang::T('Cron Job last ran on')}: {$run_date}
{/if}
{else}
-
+
{Lang::T('Cron appear not been setup, please check
your cron setup.')}
diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl
index a075a25a..89c354d6 100644
--- a/ui/ui/sections/header.tpl
+++ b/ui/ui/sections/header.tpl
@@ -157,6 +157,30 @@
border-bottom-left-radius: 21px;
}
+ .panel-cron-success>.panel-heading {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ color: #fff;
+ background-color: #169210;
+ border-color: #25e01c;
+
+ }
+
+ .panel-cron-warning>.panel-heading {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ color: #350808;
+ background-color: #efeb0a;
+ border-color: #efeb0a;
+ }
+ .panel-cron-danger>.panel-heading {
+ border-bottom-right-radius: 21px;
+ border-bottom-left-radius: 21px;
+ color: #fff;
+ background-color: #e61212;
+ border-color: #df1335;
+ }
+
.panel-danger>.panel-heading {
color: #a94442;
background-color: #f2dede;