mirror of
https://github.com/cwinfo/powerdns-admin.git
synced 2024-11-08 22:50:26 +00:00
432 lines
21 KiB
HTML
Executable File
432 lines
21 KiB
HTML
Executable File
{% extends "base.html" %}
|
|
{% set active_page = "dashboard" %}
|
|
{% block title %}<title>Dashboard - {{ SITE_NAME }}</title>{% endblock %}
|
|
|
|
{% block dashboard_stat %}
|
|
<div class="content-header">
|
|
<div class="container-fluid">
|
|
<div class="row mb-2">
|
|
<div class="col-sm-6">
|
|
<h1 class="m-0 text-dark">
|
|
Dashboard
|
|
</h1>
|
|
</div>
|
|
<div class="col-sm-6">
|
|
<ol class="breadcrumb float-sm-right">
|
|
<li class="breadcrumb-item"><a href="{{ url_for('dashboard.dashboard') }}">Dashboard</a></li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% import 'applied_change_macro.html' as applied_change_macro %}
|
|
|
|
{% block content %}
|
|
<section class="content">
|
|
<div class="container-fluid">
|
|
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<div class="card card-outline card-secondary shadow">
|
|
<div class="card-header">
|
|
<h3 class="card-title">Statistics</h3>
|
|
</div>
|
|
<!-- /.card-header -->
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-6 col-sm-3">
|
|
<div class="small-box bg-info">
|
|
<div class="inner">
|
|
<h3>{{ domain_count }}</h3>
|
|
<p>{% if domain_count > 1 %}Domains{% else %}Domain{% endif %}</p>
|
|
</div>
|
|
<div class="icon">
|
|
<i class="fa-solid fa-book"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6 col-sm-3">
|
|
<a href="{{ url_for('admin.history') }}">
|
|
<div class="small-box bg-green">
|
|
<div class="inner">
|
|
<h3>{{ history_number }}</h3>
|
|
<p>{% if history_number > 1 %}Histories{% else %}
|
|
History{% endif %}</p>
|
|
</div>
|
|
<div class="icon">
|
|
<i class="fa-solid fa-calendar"></i>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
{% if current_user.role.name in ['Administrator', 'Operator'] %}
|
|
<div class="col-6 col-sm-3">
|
|
<a href="{{ url_for('admin.manage_user') }}">
|
|
<div class="small-box bg-green">
|
|
<div class="inner">
|
|
<h3>{{ user_num }}</h3>
|
|
<p>{% if user_num > 1 %}Users{% else %}User{% endif %}</p>
|
|
</div>
|
|
<div class="icon">
|
|
<i class="fa-solid fa-users"></i>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
<div class="col-6 col-sm-3">
|
|
<a href="{{ url_for('admin.server_statistics') }}">
|
|
<div class="small-box bg-green">
|
|
<div class="inner">
|
|
<h3><span
|
|
style="font-size: 18px">{{ uptime|display_second_to_time }}</span>
|
|
</h3>
|
|
<p>Uptime</p>
|
|
</div>
|
|
<div class="icon">
|
|
<i class="fa-solid fa-clock"></i>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<!-- /.row -->
|
|
</div>
|
|
<!-- /.card-body -->
|
|
</div>
|
|
<!-- /.card -->
|
|
</div>
|
|
<!-- /.col -->
|
|
</div>
|
|
<!-- /.row -->
|
|
|
|
{% if current_user.role.name in ['Administrator', 'Operator'] or SETTING.get('allow_user_view_history') %}
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card card-outline card-secondary shadow">
|
|
<div class="card-header">
|
|
<h3 class="card-title">Recent History</h3>
|
|
</div>
|
|
<!-- /.card-header -->
|
|
<div class="card-body table-responsive records p-0">
|
|
<table class="table table-striped table-hover table-sm records">
|
|
<thead>
|
|
<tr>
|
|
<th>Log Message</th>
|
|
<th>Timestamp</th>
|
|
<th>User</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for history in histories %}
|
|
<tr class="odd">
|
|
<td>{{ history.history.msg }}</td>
|
|
<td>{{ history.history.created_on | format_datetime_local }}</td>
|
|
<td>{{ history.history.created_by }}</td>
|
|
<td>
|
|
<div id="history-info-div-{{ loop.index0 }}" style="display: none;">
|
|
{{ history.detailed_msg | safe }}
|
|
{% if history.change_set %}
|
|
<div class="content">
|
|
<div id="change_index_definition"></div>
|
|
{% call applied_change_macro.applied_change_template(history.change_set) %}
|
|
{% endcall %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<button type="button" class="btn btn-sm btn-primary history-info-button"
|
|
title="View Additional Information"
|
|
{% if history.detailed_msg == "" and history.change_set is none %}
|
|
style="visibility: hidden;"
|
|
{% endif %} value="{{ loop.index0 }}">
|
|
<i class="fa-solid fa-info-circle"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<!-- /.card-body -->
|
|
</div>
|
|
<!-- /.card -->
|
|
</div>
|
|
<!-- /.col -->
|
|
</div>
|
|
<!-- /.row -->
|
|
{% endif %}
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card card-outline card-primary shadow">
|
|
<div class="card-header">
|
|
<h3 class="card-title mb-2">
|
|
Zones
|
|
{% if show_bg_domain_button %}
|
|
<button type="button" title="Synchronize Zones"
|
|
class="btn btn-tool refresh-bg-button">
|
|
<i class="fa-solid fa-sync"></i>
|
|
</button>
|
|
{% endif %}
|
|
</h3>
|
|
<div class="card-tools">
|
|
<div class="nav-tabs-custom">
|
|
<ul class="nav nav-tabs card-header-tabs" id="custom-content-below-tab"
|
|
role="tablist">
|
|
<li class="nav-item">
|
|
<a class="nav-link active" href="#tab_{{ custom_boxes.order[0] }}"
|
|
data-toggle="pill" role="tab">
|
|
Zones <b>{{ custom_boxes.boxes[custom_boxes.order[0]][0] }}</b>
|
|
</a>
|
|
</li>
|
|
{% for boxId in custom_boxes.order[1:] %}
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="#tab_{{ boxId }}" data-toggle="pill"
|
|
role="tab">
|
|
Zones <b>{{ custom_boxes.boxes[boxId][0] }}</b>
|
|
</a>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- /.card-header -->
|
|
<div class="card-body p-0">
|
|
<div class="tab-content">
|
|
{% for boxId in custom_boxes.order %}
|
|
<div class="tab-pane show" id='tab_{{ boxId }}'>
|
|
<div class="card-body table-responsive records p-0 pt-2">
|
|
<table id='tbl_domain_list_{{ boxId }}'
|
|
class="table table-striped table-hover table-sm records">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>DNSSEC</th>
|
|
<th>Type</th>
|
|
<th>Serial</th>
|
|
<th>Primary</th>
|
|
<th>Account</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<!-- /.card-body -->
|
|
</div>
|
|
<!-- /.tab-pane -->
|
|
{% endfor %}
|
|
</div>
|
|
<!-- /.tab-content -->
|
|
</div>
|
|
<!-- /.card-body -->
|
|
</div>
|
|
<!-- /.card -->
|
|
</div>
|
|
<!-- /.col -->
|
|
</div>
|
|
<!-- /.row -->
|
|
</div>
|
|
<!-- /.container-fluid -->
|
|
</section>
|
|
{% endblock %}
|
|
|
|
{% block head_styles %}
|
|
<style>
|
|
/* Page Specific Overrides */
|
|
table.records tbody td:first-of-type { text-align: left; }
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block extrascripts %}
|
|
<script>
|
|
//SYBPATCH START//
|
|
function setUpDomainList(id, url) {
|
|
$(id).DataTable({
|
|
"paging": true,
|
|
"lengthChange": true,
|
|
language: {
|
|
searchPlaceholder: "Use ^ and $ for start and end",
|
|
},
|
|
"searching": true,
|
|
"ordering": true,
|
|
"columnDefs": [
|
|
{"orderable": false, "targets": [-1]}
|
|
],
|
|
"processing": true,
|
|
"serverSide": true,
|
|
"ajax": url,
|
|
"info": false,
|
|
"autoWidth": false,
|
|
{% if SETTING.get('default_domain_table_size')|string in ['10','25','50','100'] %}
|
|
"lengthMenu": [[10, 25, 50, 100, -1],
|
|
[10, 25, 50, 100, "All"]],
|
|
{% else %}
|
|
"lengthMenu": [[10, 25, 50, 100, {{ SETTING.get('default_domain_table_size') }}, -1],
|
|
[10, 25, 50, 100, {{ SETTING.get('default_domain_table_size') }}, "All"]],
|
|
{% endif %}
|
|
"pageLength": {{ SETTING.get('default_domain_table_size') }}
|
|
});
|
|
}
|
|
|
|
$('#tab_{{custom_boxes.order[0]}}').addClass("active");
|
|
{% for boxId in custom_boxes.order %}
|
|
setUpDomainList("#tbl_domain_list_{{boxId}}", "{{url_for('dashboard.domains_custom',boxId=boxId)}}");
|
|
{% endfor %}
|
|
//SYBPATCH END//
|
|
|
|
$(document.body).on('click', '.history-info-button', function () {
|
|
var modal = $("#modal_history_info");
|
|
var history_id = $(this).val();
|
|
var info = $("#history-info-div-" + history_id).html();
|
|
$('#modal-info-content').html(info);
|
|
modal.modal('show');
|
|
});
|
|
|
|
$(document.body).on('click', '.refresh-bg-button', function () {
|
|
var modal = $("#modal_bg_reload");
|
|
modal.modal('show');
|
|
reload_domains($SCRIPT_ROOT + '/dashboard/domains-updater');
|
|
});
|
|
|
|
$(document.body).on("click", ".button_template", function (e) {
|
|
var modal = $("#modal_template");
|
|
var domain = $(this).prop('id');
|
|
var form = " <label for=\"template_name\">Template name</label> \
|
|
<input type=\"text\" class=\"form-control\" name=\"template_name\" id=\"template_name\" placeholder=\"Enter a valid template name (required)\"> \
|
|
<label for=\"template_description\">Template description</label> \
|
|
<input type=\"text\" class=\"form-control\" name=\"template_description\" id=\"template_description\" placeholder=\"Enter a template description (optional)\"> \
|
|
<input id=\"domain\" name=\"domain\" type=\"hidden\" value=\"" + domain + "\"> \
|
|
";
|
|
modal.find('.modal-body p').html(form);
|
|
modal.find('#button_save').click(function () {
|
|
var data = {'_csrf_token': '{{ csrf_token() }}'};
|
|
data['name'] = modal.find('#template_name').val();
|
|
data['description'] = modal.find('#template_description').val();
|
|
data['domain'] = modal.find('#domain').val();
|
|
applyChanges(data, "{{ url_for('admin.create_template_from_zone') }}", true);
|
|
modal.modal('hide');
|
|
})
|
|
modal.find('#button_close').click(function () {
|
|
modal.modal('hide');
|
|
})
|
|
|
|
modal.modal('show');
|
|
});
|
|
|
|
{% if current_user.role.name in ['Administrator', 'Operator'] or not SETTING.get('dnssec_admins_only') %}
|
|
$(document.body).on("click", ".button_dnssec", function () {
|
|
var domain = $(this).prop('id');
|
|
getdnssec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec', domain);
|
|
});
|
|
|
|
$(document.body).on("click", ".button_dnssec_enable", function () {
|
|
var domain = $(this).prop('id');
|
|
enable_dns_sec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec/enable', '{{ csrf_token() }}');
|
|
});
|
|
|
|
$(document.body).on("click", ".button_dnssec_disable", function () {
|
|
var domain = $(this).prop('id');
|
|
enable_dns_sec($SCRIPT_ROOT + '/domain/' + domain + '/dnssec/disable', '{{ csrf_token() }}');
|
|
});
|
|
{% endif %}
|
|
</script>
|
|
{% endblock %}
|
|
|
|
{% block modals %}
|
|
<div class="modal fade" id="modal_history_info">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">History Details</h4>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="modal-info-content">
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary float-right" data-dismiss="modal">
|
|
Close
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal fade modal-primary" id="modal_template">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Clone to template</h4>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary float-right" id="button_close" data-dismiss="modal">
|
|
Close
|
|
</button>
|
|
<button type="button" class="btn btn-primary float-right" id="button_save">
|
|
Save
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal fade" id="modal_dnssec_info">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">DNSSEC</h4>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p></p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary float-right" data-dismiss="modal">
|
|
Close
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal fade" id="modal_bg_reload">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">Sync Domains from backend</h4>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="modal_bg_reload_content">
|
|
<i class="fa fa-refresh fa-spin"></i> Update in progress ..
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary float-right" data-dismiss="modal">
|
|
Close
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|