2020-04-18 16:17:49 +07:00
{{define "base.html"}}
<!DOCTYPE html>
2025-02-05 12:47:06 +01:00
< html lang = "en" >
2020-04-18 16:17:49 +07:00
< head >
< meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< title > {{template "title" .}}< / title >
<!-- Tell the browser to be responsive to screen width -->
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
2023-02-16 17:09:24 +01:00
<!-- Favicon -->
< link rel = "icon" href = "{{.basePath}}/favicon" >
2020-04-18 16:17:49 +07:00
<!-- Font Awesome -->
2022-04-25 00:17:13 -07:00
< link rel = "stylesheet" href = "{{.basePath}}/static/plugins/fontawesome-free/css/all.min.css" >
2020-04-18 16:17:49 +07:00
<!-- iCheck for checkboxes and radio inputs -->
2022-04-25 00:17:13 -07:00
< link rel = "stylesheet" href = "{{.basePath}}/static/plugins/icheck-bootstrap/icheck-bootstrap.min.css" >
2020-04-18 16:17:49 +07:00
<!-- Select2 -->
2022-04-25 00:17:13 -07:00
< link rel = "stylesheet" href = "{{.basePath}}/static/plugins/select2/css/select2.min.css" >
2020-04-18 16:17:49 +07:00
<!-- Toastr -->
2022-04-25 00:17:13 -07:00
< link rel = "stylesheet" href = "{{.basePath}}/static/plugins/toastr/toastr.min.css" >
2020-04-19 00:44:51 +07:00
<!-- Jquery Tags Input -->
2022-04-25 00:17:13 -07:00
< link rel = "stylesheet" href = "{{.basePath}}/static/plugins/jquery-tags-input/dist/jquery.tagsinput.min.css" >
2020-04-18 16:17:49 +07:00
<!-- overlayScrollbars -->
2022-04-25 00:17:13 -07:00
< link rel = "stylesheet" href = "{{.basePath}}/static/dist/css/adminlte.min.css" >
2020-04-22 17:11:28 +07:00
<!-- START: On page css -->
{{template "top_css" .}}
<!-- END: On page css -->
2025-02-11 13:01:01 +01:00
< style >
2025-02-07 18:06:29 +01:00
/* Base Dark Mode Styles */
body, .content-wrapper {
background-color: #121212;
color: #e0e0e0;
}
.navbar, .main-sidebar, .sidebar {
background-color: #1e1e1e;
}
.nav-link, .navbar-nav .nav-item .nav-link {
color: #b0b0b0;
}
.navbar-light .navbar-nav .nav-link {
color: #b0b0b0;
}
.navbar-light .navbar-nav .nav-link:hover {
color: #ffffff;
}
.main-footer {
background-color: #1c1c1c;
color: #e0e0e0;
}
.sidebar-dark-primary .nav-link {
color: #e0e0e0;
}
.sidebar-dark-primary .nav-link:hover {
background-color: #444444;
}
/* Dark mode for buttons */
.btn-outline-primary {
border-color: #4e73df;
color: #4e73df;
}
.btn-outline-primary:hover {
background-color: #4e73df;
color: #ffffff;
}
.btn-outline-danger {
border-color: #e74a3b;
color: #e74a3b;
}
.btn-outline-danger:hover {
background-color: #e74a3b;
color: #ffffff;
}
/* Modify inputs and form elements */
input, select, textarea, .form-control, .form-control:disabled, div.tagsinput {
2025-02-11 13:01:01 +01:00
background-color: #333333 !important;
2025-02-11 08:28:07 +01:00
color: #e0e0e0 !important;
2025-02-11 13:01:01 +01:00
border: 1px solid #555 !important;
2025-02-07 18:06:29 +01:00
}
2025-02-12 10:04:20 +01:00
input::placeholder, select::placeholder, textarea::placeholder, #search-input::placeholder {
2025-02-07 18:06:29 +01:00
color: #b0b0b0;
}
2025-02-12 10:04:20 +01:00
.custom-select {
background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23dee2e6' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat;
}
2025-02-07 18:06:29 +01:00
input[type="checkbox"], input[type="radio"] {
background-color: #444;
}
2025-02-11 08:28:07 +01:00
.form-control:focus {
background-color: #555555;
border-color: #80bdff;
}
2025-02-11 14:48:05 +01:00
.table-success td {
border-color: #8fd19e;
}
.table-success > td, .table-success>th {
background-color: #00430f;
}
2025-02-11 08:28:07 +01:00
div.tagsinput span.tag {
border: 1px solid #22923c;
background: #181b16;
color: #35d85b;
}
div.tagsinput span.tag a {
color: #35d85b;
}
2025-02-11 14:48:05 +01:00
.modal-content, .card, table, .select2-dropdown {
2025-02-07 18:06:29 +01:00
background-color: #2a2a2a;
color: #e0e0e0;
}
.modal-header {
border-bottom: 1px solid #555;
}
.modal-footer {
border-top: 1px solid #555;
}
/* Dark mode for the sidebar active state */
.nav-sidebar .nav-link.active {
background-color: #444;
}
table th, table td {
color: #e0e0e0;
border: 1px solid #444;
}
2025-02-11 13:01:01 +01:00
< / style >
2020-04-18 16:17:49 +07:00
< / head >
< body class = "hold-transition sidebar-mini" >
<!-- Site wrapper -->
< div class = "wrapper" >
<!-- Navbar -->
< nav class = "main-header navbar navbar-expand navbar-white navbar-light" >
<!-- Left navbar links -->
< ul class = "navbar-nav" >
< li class = "nav-item" >
< a class = "nav-link" data-widget = "pushmenu" href = "#" role = "button" > < i class = "fas fa-bars" > < / i > < / a >
< / li >
< / ul >
<!-- SEARCH FORM -->
2023-02-16 18:17:10 +02:00
< form class = "form-inline ml-3" style = "display: none" id = "search-form" >
< div class = "input-group input-group-sm" >
< input class = "form-control form-control-navbar" placeholder = "Search"
aria-label="Search" id="search-input">
< div class = "input-group-append" >
< button class = "btn-navbar" type = "submit" disabled >
< i class = "fas fa-search" > < / i >
< / button >
< / div >
< / div >
2023-03-16 08:58:28 +01:00
< div class = "form-group form-group-sm" >
< select name = "status-selector" id = "status-selector" class = "custom-select form-control-navbar" style = "margin-left: 0.5em; height: 90%; font-size: 14px;" >
2023-12-27 13:08:55 +05:00
<!-- THIS SECTION IS OVERRIDDEN BY JS. SEE updateSearchList() function in clients.html BEFORE EDITING -->
2023-03-16 08:58:28 +01:00
< option value = "All" > All< / option >
< option value = "Enabled" > Enabled< / option >
< option value = "Disabled" > Disabled< / option >
< option value = "Connected" > Connected< / option >
< option value = "Disconnected" > Disconnected< / option >
2023-12-27 13:08:55 +05:00
<!-- THIS SECTION IS OVERRIDDEN BY JS. SEE updateSearchList() function in clients.html BEFORE EDITING -->
2023-03-16 08:58:28 +01:00
< / select >
< / div >
2023-02-16 18:17:10 +02:00
< / form >
2020-04-18 16:17:49 +07:00
2020-06-02 11:20:50 +07:00
<!-- Right navbar links -->
< div class = "navbar-nav ml-auto" >
< button style = "margin-left: 0.5em;" type = "button" class = "btn btn-outline-primary btn-sm" data-toggle = "modal"
2025-02-11 13:01:01 +01:00
data-target="#modal_new_client">< i class = "nav-icon fas fa-plus" > < / i > New Client< / button >
2023-03-15 22:15:41 +02:00
< button id = "apply-config-button" style = "margin-left: 0.5em; display: none;" type = "button" class = "btn btn-outline-danger btn-sm" data-toggle = "modal"
2025-02-11 13:01:01 +01:00
data-target="#modal_apply_config">< i class = "nav-icon fas fa-check" > < / i > Apply Config< / button >
2020-10-09 23:33:29 +02:00
{{if .baseData.CurrentUser}}
2022-04-25 00:17:13 -07:00
< button onclick = "location.href='{{.basePath}}/logout';" style = "margin-left: 0.5em;" type = "button"
2020-06-02 11:20:50 +07:00
class="btn btn-outline-danger btn-sm">< i class = "nav-icon fas fa-sign-out-alt" > < / i > Logout< / button >
2020-10-09 23:33:29 +02:00
{{end}}
2020-06-02 11:20:50 +07:00
< / div >
2020-04-18 16:17:49 +07:00
< / nav >
<!-- /.navbar -->
<!-- Main Sidebar Container -->
< aside class = "main-sidebar sidebar-dark-primary elevation-4" >
<!-- Brand Logo -->
2022-04-25 00:17:13 -07:00
< a href = "{{.basePath}}" class = "brand-link" >
2025-02-04 14:06:58 +01:00
< span class = "brand-text" > WIREGUARD MANAGER< / span >
2020-04-18 16:17:49 +07:00
< / a >
<!-- Sidebar -->
< div class = "sidebar" >
<!-- Sidebar user (optional) -->
< div class = "user-panel mt-3 pb-3 mb-3 d-flex" >
< div class = "image" >
2020-04-24 18:14:54 +07:00
< i class = "nav-icon fas fa-2x fa-user" > < / i >
2020-04-18 16:17:49 +07:00
< / div >
< div class = "info" >
2022-12-21 21:52:00 +01:00
{{if .baseData.CurrentUser}}
2025-02-07 18:06:29 +01:00
< a href = "{{.basePath}}/profile" class = "d-block" > My Account: {{.baseData.CurrentUser}}< / a >
2022-12-21 21:52:00 +01:00
{{else}}
2025-02-07 18:06:29 +01:00
< a href = "#" class = "d-block" > My Account< / a >
2022-12-21 21:52:00 +01:00
{{end}}
2020-04-18 16:17:49 +07:00
< / div >
< / div >
<!-- Sidebar Menu -->
< nav class = "mt-2" >
< ul class = "nav nav-pills nav-sidebar flex-column" data-widget = "treeview" role = "menu" data-accordion = "false" >
2022-03-20 13:53:09 +01:00
< li class = "nav-header" > MAIN< / li >
2020-04-18 16:17:49 +07:00
< li class = "nav-item" >
2022-04-26 20:36:39 +02:00
< a href = "{{.basePath}}/" class = "nav-link {{if eq .baseData.Active " " } } active { { end } } " >
2020-04-19 15:50:59 +07:00
< i class = "nav-icon fas fa-user-secret" > < / i >
2025-02-11 13:01:01 +01:00
< p > VPN Clients< / p >
2025-02-07 18:06:29 +01:00
< / a >
< / li >
< li class = "nav-item" >
< a href = "{{.basePath}}/status" class = "nav-link {{if eq .baseData.Active " status " } } active { { end } } " >
< i class = "nav-icon fas fa-signal" > < / i >
2025-02-11 13:01:01 +01:00
< p > VPN Connected< / p >
2020-04-18 16:17:49 +07:00
< / a >
< / li >
2023-03-15 22:13:53 +02:00
{{if .baseData.Admin}}
2025-02-07 18:06:29 +01:00
< li class = "nav-header" > SETTINGS< / li >
2020-04-18 16:17:49 +07:00
< li class = "nav-item" >
2022-04-25 00:17:13 -07:00
< a href = "{{.basePath}}/wg-server" class = "nav-link {{if eq .baseData.Active " wg-server " } } active { { end } } " >
2020-04-18 16:17:49 +07:00
< i class = "nav-icon fas fa-server" > < / i >
2025-02-11 13:01:01 +01:00
< p > WireGuard Server< / p >
2020-04-19 15:50:59 +07:00
< / a >
< / li >
< li class = "nav-item" >
2022-04-25 00:17:13 -07:00
< a href = "{{.basePath}}/global-settings" class = "nav-link {{if eq .baseData.Active " global-settings " } } active { { end } } " >
2020-04-19 15:50:59 +07:00
< i class = "nav-icon fas fa-cog" > < / i >
2025-02-11 13:01:01 +01:00
< p > Client Config Settings< / p >
2020-04-18 16:17:49 +07:00
< / a >
< / li >
2023-05-24 12:04:02 +02:00
{{if not .loginDisabled}}
2023-03-15 22:13:53 +02:00
< li class = "nav-item" >
< a href = "{{.basePath}}/users-settings" class = "nav-link {{if eq .baseData.Active " users-settings " } } active { { end } } " >
2025-02-11 13:01:01 +01:00
< i class = "nav-icon fas fa-cog" > < / i >
< p > WGM User Accounts< / p >
2023-03-15 22:13:53 +02:00
< / a >
< / li >
{{end}}
2023-05-24 12:04:02 +02:00
{{end}}
2020-04-18 16:17:49 +07:00
< / ul >
< / nav >
<!-- /.sidebar - menu -->
< / div >
<!-- /.sidebar -->
< / aside >
< div class = "modal fade" id = "modal_new_client" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
2025-02-04 12:57:06 +01:00
< h4 class = "modal-title" > New WireGuard Client< / h4 >
2020-04-18 16:17:49 +07:00
< button type = "button" class = "close" data-dismiss = "modal" aria-label = "Close" >
< span aria-hidden = "true" > × < / span >
< / button >
< / div >
< form name = "frm_new_client" id = "frm_new_client" >
< div class = "modal-body" >
2025-02-11 13:01:01 +01:00
<!-- Form fields for new client go here -->
2020-04-18 16:17:49 +07:00
< div class = "form-group" >
< label for = "client_name" class = "control-label" > Name< / label >
< input type = "text" class = "form-control" id = "client_name" name = "client_name" >
< / div >
< div class = "form-group" >
< label for = "client_email" class = "control-label" > Email< / label >
< input type = "text" class = "form-control" id = "client_email" name = "client_email" >
< / div >
2023-12-27 13:08:55 +05:00
< div class = "form-group" >
< label for = "subnet_ranges" class = "control-label" > Subnet range< / label >
2025-02-11 13:01:01 +01:00
< select id = "subnet_ranges" class = "select2" data-placeholder = "Select a subnet range" style = "width: 100%;" >
2023-12-27 13:08:55 +05:00
< / select >
< / div >
2020-04-18 16:17:49 +07:00
< div class = "form-group" >
< label for = "client_allocated_ips" class = "control-label" > IP Allocation< / label >
2020-04-21 00:26:49 +07:00
< input type = "text" data-role = "tagsinput" class = "form-control" id = "client_allocated_ips" >
2020-04-18 16:17:49 +07:00
< / div >
< div class = "form-group" >
2025-02-12 10:04:20 +01:00
< label for = "client_allowed_ips" class = "control-label" > Allowed IPs - What subnet traffic should go through WireGuard.
2025-02-11 13:01:01 +01:00
< i class = "fas fa-info-circle" data-toggle = "tooltip" data-original-title = "Specify a list of addresses that will get routed to the server. These addresses will be included in 'AllowedIPs' of client config" >
2022-03-20 13:53:09 +01:00
< / i >
< / label >
2025-02-11 13:01:01 +01:00
< input type = "text" data-role = "tagsinput" class = "form-control" id = "client_allowed_ips" value = "{{ StringsJoin .client_defaults.AllowedIPs " , " } } " >
2020-04-18 16:17:49 +07:00
< / div >
2025-02-12 10:04:20 +01:00
< div class = "form-group" style = "display:none;" >
2022-03-20 13:53:09 +01:00
< label for = "client_extra_allowed_ips" class = "control-label" > Extra Allowed IPs
2025-02-11 13:01:01 +01:00
< i class = "fas fa-info-circle" data-toggle = "tooltip" data-original-title = "Specify a list of addresses that will get routed to the client. These addresses will be included in 'AllowedIPs' of WG server config" >
2022-03-20 13:53:09 +01:00
< / i >
< / label >
2025-02-11 13:01:01 +01:00
< input type = "text" data-role = "tagsinput" class = "form-control" id = "client_extra_allowed_ips" value = "{{ StringsJoin .client_defaults.ExtraAllowedIPs " , " } } " >
2022-01-29 02:45:00 -05:00
< / div >
2025-02-12 10:04:20 +01:00
< div class = "form-group" style = "display:none;" >
2023-12-25 16:21:37 -03:00
< label for = "client_endpoint" class = "control-label" > Endpoint< / label >
< input type = "text" class = "form-control" id = "client_endpoint" name = "client_endpoint" >
< / div >
2021-08-05 19:58:01 +02:00
< div class = "form-group" >
< div class = "icheck-primary d-inline" >
2022-04-26 20:35:35 +02:00
< input type = "checkbox" id = "use_server_dns" { { if . client_defaults . UseServerDNS } } checked { { end } } >
2025-02-11 13:01:01 +01:00
< label for = "use_server_dns" > Use server DNS< / label >
2021-08-05 19:58:01 +02:00
< / div >
< / div >
2020-04-18 16:17:49 +07:00
< div class = "form-group" >
< div class = "icheck-primary d-inline" >
2022-04-26 20:35:35 +02:00
< input type = "checkbox" id = "enabled" { { if . client_defaults . EnableAfterCreation } } checked { { end } } >
2025-02-11 13:01:01 +01:00
< label for = "enabled" > Enable after creation< / label >
2020-04-18 16:17:49 +07:00
< / div >
< / div >
2022-03-13 19:33:37 +03:00
< details >
2025-02-11 13:01:01 +01:00
< summary >
< strong > Public and Preshared Keys< / strong >
< i class = "fas fa-info-circle" data-toggle = "tooltip" data-original-title = "If you don't want the server to generate and store the client's private key, you can manually specify its public and preshared key here. Note: QR code will not be generated" >
2022-03-20 13:53:09 +01:00
< / i >
< / summary >
2022-03-13 19:33:37 +03:00
< div class = "form-group" style = "margin-top: 1rem" >
2025-02-11 13:01:01 +01:00
< label for = "client_public_key" class = "control-label" > Public Key< / label >
2022-03-20 13:53:09 +01:00
< input type = "text" class = "form-control" id = "client_public_key" name = "client_public_key" placeholder = "Autogenerated" aria-invalid = "false" >
2022-03-13 19:33:37 +03:00
< / div >
< div class = "form-group" >
2025-02-11 13:01:01 +01:00
< label for = "client_preshared_key" class = "control-label" > Preshared Key< / label >
2022-12-13 21:35:13 +01:00
< input type = "text" class = "form-control" id = "client_preshared_key" name = "client_preshared_key" placeholder = "Autogenerated - enter "-" to skip generation" >
2022-03-13 19:33:37 +03:00
< / div >
< / details >
2023-12-29 13:22:12 +05:00
< details style = "margin-top: 0.5rem;" >
2025-02-11 13:01:01 +01:00
< summary > < strong > Additional configuration< / strong > < / summary >
2024-01-10 01:03:27 +05:00
< div class = "form-group" >
< label for = "additional_notes" class = "control-label" > Notes< / label >
< textarea class = "form-control" style = "min-height: 6rem;" id = "additional_notes" name = "additional_notes" placeholder = "Additional notes about this client" > < / textarea >
< / div >
2023-12-29 13:22:12 +05:00
< / details >
2020-04-18 16:17:49 +07:00
< / div >
< div class = "modal-footer justify-content-between" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Cancel< / button >
< button type = "submit" class = "btn btn-primary" > Submit< / button >
< / div >
< / form >
< / div >
<!-- /.modal - content -->
< / div >
<!-- /.modal - dialog -->
< / div >
<!-- /.modal -->
2020-04-23 09:29:44 +07:00
< div class = "modal fade" id = "modal_apply_config" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Apply Config< / h4 >
< button type = "button" class = "close" data-dismiss = "modal" aria-label = "Close" >
< span aria-hidden = "true" > × < / span >
< / button >
< / div >
< div class = "modal-body" >
< p > Do you want to write config file and restart WireGuard server?< / p >
< / div >
< div class = "modal-footer justify-content-between" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Cancel< / button >
< button type = "button" class = "btn btn-danger" id = "apply_config_confirm" > Apply< / button >
< / div >
< / div >
<!-- /.modal - content -->
< / div >
<!-- /.modal - dialog -->
< / div >
<!-- /.modal -->
2020-04-18 16:17:49 +07:00
<!-- Content Wrapper. Contains page content -->
< div class = "content-wrapper" >
<!-- Content Header (Page header) -->
< section class = "content-header" >
< div class = "container-fluid" >
< div class = "row mb-2" >
< div class = "col-sm-6" >
< h1 > {{template "page_title" .}}< / h1 >
< / div >
< / div >
< / div > <!-- /.container - fluid -->
< / section >
<!-- Main content -->
{{template "page_content" .}}
<!-- /.content -->
< / div >
<!-- /.content - wrapper -->
2025-02-05 12:47:06 +01:00
2020-04-18 16:17:49 +07:00
< footer class = "main-footer" >
< div class = "float-right d-none d-sm-block" >
2020-06-01 15:24:11 +07:00
< b > Version< / b > {{ .appVersion }}
2020-04-18 16:17:49 +07:00
< / div >
2025-02-11 13:01:01 +01:00
< strong > Copyright © < script > document . write ( new Date ( ) . getFullYear ( ) ) < / script > < a href = "https://github.com/swissmakers/wireguard-manager" > WireGuard Manager< / a > .< / strong > All rights reserved.
2020-04-18 16:17:49 +07:00
< / footer >
2025-02-05 12:47:06 +01:00
2020-04-18 16:17:49 +07:00
<!-- Control Sidebar -->
< aside class = "control-sidebar control-sidebar-dark" >
<!-- Control sidebar content goes here -->
< / aside >
<!-- /.control - sidebar -->
< / div >
<!-- ./wrapper -->
<!-- jQuery -->
2022-04-25 00:17:13 -07:00
< script src = "{{.basePath}}/static/plugins/jquery/jquery.min.js" > < / script >
2020-04-18 16:17:49 +07:00
<!-- Bootstrap 4 -->
2022-04-25 00:17:13 -07:00
< script src = "{{.basePath}}/static/plugins/bootstrap/js/bootstrap.bundle.min.js" > < / script >
2020-04-18 16:17:49 +07:00
<!-- Select2 -->
2022-04-25 00:17:13 -07:00
< script src = "{{.basePath}}/static/plugins/select2/js/select2.full.min.js" > < / script >
2020-04-18 16:17:49 +07:00
<!-- jquery - validation -->
2022-04-25 00:17:13 -07:00
< script src = "{{.basePath}}/static/plugins/jquery-validation/jquery.validate.min.js" > < / script >
2020-04-18 16:17:49 +07:00
<!-- Toastr -->
2022-04-25 00:17:13 -07:00
< script src = "{{.basePath}}/static/plugins/toastr/toastr.min.js" > < / script >
2020-04-19 00:44:51 +07:00
<!-- Jquery Tags Input -->
2022-04-25 00:17:13 -07:00
< script src = "{{.basePath}}/static/plugins/jquery-tags-input/dist/jquery.tagsinput.min.js" > < / script >
2020-04-18 16:17:49 +07:00
<!-- AdminLTE App -->
2022-04-25 00:17:13 -07:00
< script src = "{{.basePath}}/static/dist/js/adminlte.min.js" > < / script >
2020-06-02 11:20:50 +07:00
<!-- Custom js -->
2022-04-25 00:17:13 -07:00
< script src = "{{.basePath}}/static/custom/js/helper.js" > < / script >
2020-04-18 16:17:49 +07:00
< script >
2022-03-20 13:53:09 +01:00
// initialize all tooltips
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
2023-03-15 22:15:41 +02:00
$(document).ready(function () {
2023-12-27 13:08:55 +05:00
addGlobalStyle(`
.toast-top-right-fix {
top: 67px;
right: 12px;
}
`, 'toastrToastStyleFix')
toastr.options.closeDuration = 100;
toastr.options.positionClass = 'toast-top-right-fix';
2025-02-11 13:01:01 +01:00
// Initial call, and then poll every 5 seconds for config changes
updateApplyConfigVisibility();
setInterval(updateApplyConfigVisibility, 5000);
2025-03-04 10:56:12 +01:00
// Only poll for updates if the current page is the status page.
if (window.location.pathname === "{{.basePath}}/status") {
updateStatusTable();
setInterval(updateStatusTable, 5000);
}
2023-12-27 13:08:55 +05:00
});
function addGlobalStyle(css, id) {
if (!document.querySelector('#' + id)) {
2025-02-11 13:01:01 +01:00
let head = document.head;
if (!head) { return; }
let style = document.createElement('style');
style.type = 'text/css';
style.id = id;
style.innerHTML = css;
head.appendChild(style);
2023-12-27 13:08:55 +05:00
}
}
function updateApplyConfigVisibility() {
2025-02-11 13:01:01 +01:00
$.ajax({
cache: false,
method: 'GET',
url: '{{.basePath}}/test-hash',
dataType: 'json',
contentType: "application/json",
success: function(data) {
console.log("Config check response:", data);
// Check the 'success' property returned by the endpoint.
if (data.success) {
$("#apply-config-button").show();
} else {
$("#apply-config-button").hide();
}
},
error: function(jqXHR, exception) {
try {
const responseJson = JSON.parse(jqXHR.responseText);
2023-03-15 22:15:41 +02:00
toastr.error(responseJson['message']);
2025-02-11 13:01:01 +01:00
} catch (e) {
toastr.error("Error checking config changes.");
2023-03-15 22:15:41 +02:00
}
2025-02-11 13:01:01 +01:00
}
});
2023-12-27 13:08:55 +05:00
}
2025-02-11 13:01:01 +01:00
2023-03-15 22:15:41 +02:00
2025-02-11 13:01:01 +01:00
// populateClient function for render new client info on the client page.
2020-06-02 11:20:50 +07:00
function populateClient(client_id) {
$.ajax({
cache: false,
method: 'GET',
2022-04-25 00:17:13 -07:00
url: '{{.basePath}}/api/client/' + client_id,
2020-06-02 11:20:50 +07:00
dataType: 'json',
contentType: "application/json",
success: function (resp) {
renderClientList([resp]);
},
error: function (jqXHR, exception) {
2025-02-11 13:01:01 +01:00
try {
const responseJson = JSON.parse(jqXHR.responseText);
toastr.error(responseJson['message']);
} catch (e) {
toastr.error("Error loading client data.");
}
2020-06-02 11:20:50 +07:00
}
});
}
2025-02-11 13:01:01 +01:00
// submitNewClient function for new client form submission.
2020-04-18 16:17:49 +07:00
function submitNewClient() {
2020-05-29 14:22:29 +07:00
const name = $("#client_name").val();
const email = $("#client_email").val();
const allocated_ips = $("#client_allocated_ips").val().split(",");
const allowed_ips = $("#client_allowed_ips").val().split(",");
2023-12-25 16:21:37 -03:00
const endpoint = $("#client_endpoint").val();
2025-02-11 13:01:01 +01:00
const use_server_dns = $("#use_server_dns").is(':checked');
const enabled = $("#enabled").is(':checked');
2022-03-13 19:33:37 +03:00
const public_key = $("#client_public_key").val();
const preshared_key = $("#client_preshared_key").val();
2024-01-10 01:03:27 +05:00
const additional_notes = $("#additional_notes").val();
2020-04-18 16:17:49 +07:00
2025-02-11 13:01:01 +01:00
const data = {
"name": name,
"email": email,
"allocated_ips": allocated_ips,
"allowed_ips": allowed_ips,
"extra_allowed_ips": $("#client_extra_allowed_ips").val().split(","),
"endpoint": endpoint,
"use_server_dns": use_server_dns,
"enabled": enabled,
"public_key": public_key,
"preshared_key": preshared_key,
"additional_notes": additional_notes
};
2020-04-18 16:17:49 +07:00
$.ajax({
cache: false,
method: 'POST',
2022-04-25 00:17:13 -07:00
url: '{{.basePath}}/new-client',
2020-04-18 16:17:49 +07:00
dataType: 'json',
contentType: "application/json",
data: JSON.stringify(data),
2020-06-02 11:20:50 +07:00
success: function(resp) {
2020-05-29 11:27:23 +07:00
$("#modal_new_client").modal('hide');
2020-04-18 16:17:49 +07:00
toastr.success('Created new client successfully');
2025-02-11 13:01:01 +01:00
// Update the home page (clients page) after adding successfully.
2022-12-03 01:08:07 +03:00
if (window.location.pathname === "{{.basePath}}/") {
2020-06-02 11:20:50 +07:00
populateClient(resp.id);
2020-05-29 14:22:29 +07:00
}
2025-02-11 13:01:01 +01:00
updateApplyConfigVisibility();
2020-04-19 10:46:43 +07:00
},
error: function(jqXHR, exception) {
2025-02-11 13:01:01 +01:00
try {
const responseJson = JSON.parse(jqXHR.responseText);
toastr.error(responseJson['message']);
} catch (e) {
toastr.error("Error creating client.");
}
2020-04-18 16:17:49 +07:00
}
});
}
2020-04-21 00:26:49 +07:00
2025-02-11 13:01:01 +01:00
// updateIPAllocationSuggestion function for automatically filling
// the IP Allocation input with suggested IP addresses.
2023-12-27 13:08:55 +05:00
function updateIPAllocationSuggestion(forceDefault = false) {
let subnetRange = $("#subnet_ranges").select2('val');
if (forceDefault || !subnetRange || subnetRange.length === 0) {
2025-02-11 13:01:01 +01:00
subnetRange = '__default_any__';
2023-12-27 13:08:55 +05:00
}
2020-04-21 00:26:49 +07:00
$.ajax({
cache: false,
method: 'GET',
2023-12-27 13:08:55 +05:00
url: `{{.basePath}}/api/suggest-client-ips?sr=${subnetRange}`,
2020-04-21 00:26:49 +07:00
dataType: 'json',
contentType: "application/json",
success: function(data) {
2023-12-27 13:08:55 +05:00
const allocated_ips = $("#client_allocated_ips").val().split(",");
2025-02-11 13:01:01 +01:00
allocated_ips.forEach(function (item) {
$('#client_allocated_ips').removeTag(item);
});
data.forEach(function (item) {
2020-04-21 00:26:49 +07:00
$('#client_allocated_ips').addTag(item);
2025-02-11 13:01:01 +01:00
});
2020-04-21 00:26:49 +07:00
},
error: function(jqXHR, exception) {
2023-12-27 13:08:55 +05:00
const allocated_ips = $("#client_allocated_ips").val().split(",");
2025-02-11 13:01:01 +01:00
allocated_ips.forEach(function (item) {
$('#client_allocated_ips').removeTag(item);
});
try {
const responseJson = JSON.parse(jqXHR.responseText);
toastr.error(responseJson['message']);
} catch (e) {
toastr.error("Error suggesting IP allocation.");
}
2020-04-21 00:26:49 +07:00
}
});
}
2020-04-18 16:17:49 +07:00
< / script >
< script >
2025-02-11 13:01:01 +01:00
// Initialize Select2 Elements.
$(".select2").select2();
2020-04-18 16:17:49 +07:00
2025-02-11 13:01:01 +01:00
// IP Allocation tag input.
2020-05-29 11:27:23 +07:00
$("#client_allocated_ips").tagsInput({
2020-04-21 00:26:49 +07:00
'width': '100%',
'height': '75%',
'interactive': true,
'defaultText': 'Add More',
'removeWithBackspace': true,
'minChars': 0,
2023-12-28 12:37:26 +05:00
'minInputWidth': '100%',
2020-04-21 00:26:49 +07:00
'placeholderColor': '#666666'
});
2025-02-11 13:01:01 +01:00
// AllowedIPs tag input.
2020-05-29 11:27:23 +07:00
$("#client_allowed_ips").tagsInput({
2020-04-19 00:44:51 +07:00
'width': '100%',
'height': '75%',
'interactive': true,
'defaultText': 'Add More',
'removeWithBackspace': true,
'minChars': 0,
2023-12-28 12:37:26 +05:00
'minInputWidth': '100%',
2020-04-19 00:44:51 +07:00
'placeholderColor': '#666666'
});
2022-01-29 02:45:00 -05:00
$("#client_extra_allowed_ips").tagsInput({
'width': '100%',
'height': '75%',
'interactive': true,
'defaultText': 'Add More',
'removeWithBackspace': true,
'minChars': 0,
2023-12-28 12:37:26 +05:00
'minInputWidth': '100%',
2022-01-29 02:45:00 -05:00
'placeholderColor': '#666666'
});
2025-02-11 13:01:01 +01:00
// New client form validation.
2020-04-18 16:17:49 +07:00
$(document).ready(function () {
$.validator.setDefaults({
submitHandler: function () {
submitNewClient();
}
});
2020-05-29 11:27:23 +07:00
$("#frm_new_client").validate({
2020-04-18 16:17:49 +07:00
rules: {
client_name: {
required: true,
},
},
messages: {
client_name: {
2020-04-19 10:51:55 +07:00
required: "Please enter a name"
2020-04-18 16:17:49 +07:00
},
},
errorElement: 'span',
errorPlacement: function (error, element) {
error.addClass('invalid-feedback');
element.closest('.form-group').append(error);
},
2025-02-11 13:01:01 +01:00
highlight: function (element) {
2020-04-18 16:17:49 +07:00
$(element).addClass('is-invalid');
},
2025-02-11 13:01:01 +01:00
unhighlight: function (element) {
2020-04-18 16:17:49 +07:00
$(element).removeClass('is-invalid');
}
});
});
2020-04-21 00:26:49 +07:00
2025-03-04 10:56:12 +01:00
function updateSubnetRangesList(elementID, preselectedVal) {
$.getJSON("{{.basePath}}/api/subnet-ranges", null, function(data) {
$(`${elementID} option`).remove();
$(elementID).append(
$("< option > < / option > ")
.text("Any")
.val("__default_any__")
);
$.each(data, function(index, item) {
$(elementID).append(
$("< option > < / option > ")
.text(item)
.val(item)
);
if (item === preselectedVal) {
console.log(preselectedVal);
$(elementID).val(preselectedVal).trigger('change')
}
});
});
}
2025-02-11 13:01:01 +01:00
// New Client modal event.
2020-04-21 00:26:49 +07:00
$(document).ready(function () {
2025-02-11 13:01:01 +01:00
$("#modal_new_client").on('shown.bs.modal', function () {
2020-06-02 11:20:50 +07:00
$("#client_name").val("");
$("#client_email").val("");
2022-03-13 19:33:37 +03:00
$("#client_public_key").val("");
$("#client_preshared_key").val("");
2020-05-29 11:27:23 +07:00
$("#client_allocated_ips").importTags('');
2022-01-29 02:45:00 -05:00
$("#client_extra_allowed_ips").importTags('');
2023-12-29 13:22:12 +05:00
$("#client_endpoint").val('');
2024-01-10 01:03:27 +05:00
$("#additional_notes").val('');
2023-12-27 13:08:55 +05:00
updateSubnetRangesList("#subnet_ranges");
updateIPAllocationSuggestion(true);
2020-04-21 00:26:49 +07:00
});
});
2020-04-23 09:29:44 +07:00
2025-02-11 13:01:01 +01:00
// Handle subnet range select.
$('#subnet_ranges').on('select2:select', function () {
2023-12-27 13:08:55 +05:00
updateIPAllocationSuggestion();
});
2025-02-11 13:01:01 +01:00
// apply_config_confirm button event.
2020-04-23 09:29:44 +07:00
$(document).ready(function () {
2020-05-29 11:27:23 +07:00
$("#apply_config_confirm").click(function () {
2020-04-23 09:29:44 +07:00
$.ajax({
cache: false,
2022-07-14 08:36:47 +02:00
method: 'POST',
2022-04-25 00:17:13 -07:00
url: '{{.basePath}}/api/apply-wg-config',
2020-04-23 09:29:44 +07:00
dataType: 'json',
contentType: "application/json",
success: function(data) {
2025-02-11 13:01:01 +01:00
updateApplyConfigVisibility();
2020-05-29 11:27:23 +07:00
$("#modal_apply_config").modal('hide');
2020-04-23 09:29:44 +07:00
toastr.success('Applied config successfully');
},
2025-02-11 13:01:01 +01:00
error: function(jqXHR) {
try {
const responseJson = JSON.parse(jqXHR.responseText);
toastr.error(responseJson['message']);
} catch (e) {
toastr.error("Error applying config.");
}
2020-04-23 09:29:44 +07:00
}
});
});
});
2020-04-18 16:17:49 +07:00
< / script >
<!-- START: On page script -->
{{template "bottom_js" .}}
<!-- END: On page script -->
< / body >
< / html >
2021-08-28 15:10:30 +02:00
{{end}}