powerdns-admin/powerdnsadmin/templates/dashboard.html
Matt Scott 4f83879e95 Added Jinja filter for handle formatting of zone type labels to enforce modern social standards.
Removed text label of dashboard domain list action menu to reduce size.

Continuing work on re-design and clean-up of dashboard view.
2023-02-19 09:48:43 -05:00

438 lines
22 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
<small>Info</small>
</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">
<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.pdns_stats') }}">
<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">
<div class="card-header">
<h3 class="card-title">Recent History</h3>
</div>
<!-- /.card-header -->
<div class="card-body table-responsive p-0">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>User</th>
<th>Log Message</th>
<th>Timestamp</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for history in histories %}
<tr class="odd">
<td>{{ history.history.created_by }}</td>
<td>{{ history.history.msg }}</td>
<td>{{ history.history.created_on | format_datetime_local }}</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"
{% 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>&nbsp;Info
</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">
<div class="card-header">
<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">
Hosted Domains <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">Hosted
Domains <b>{{ custom_boxes.boxes[boxId][0] }}</b></a>
</li>
{% endfor %}
</ul>
</div>
</div>
<!-- /.card-header -->
<div class="card-body p-0">
<div class="tab-content">
{% for boxId in custom_boxes.order %}
<div class="tab-pane fade show" id='tab_{{ boxId }}'>
<div class="card-header">
<h3 class="card-title">Hosted Domains
<b>{{ custom_boxes.boxes[boxId][0] }}</b></h3>
{% if show_bg_domain_button %}
<button type="button"
class="btn btn-primary refresh-bg-button float-right">
<i class="fa-solid fa-sync"></i>
&nbsp;Sync Domains
</button>
{% endif %}
</div>
<!-- /.card-header -->
<div class="card-body table-responsive p-0 pt-2">
<table id='tbl_domain_list_{{ boxId }}'
class="table table-striped table-hover records table-sm">
<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 type="text/css">
table.records thead th, table.records tbody td { text-align: center; vertical-align: middle; }
table.records tbody td:first-of-type { text-align: left; }
table.records thead th:last-of-type { width: 50px; }
div.table-responsive > div.dataTables_wrapper > div.row:first-of-type { margin: 0 0.5em 0 0.5em; }
div.table-responsive > div.dataTables_wrapper > div.row:last-of-type { margin: 0.4em 0.5em 0.4em 0.5em; }
div.table-responsive > div.dataTables_wrapper table.dataTable { margin: 0!important; }
</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]}
{% if current_user.role.name not in ['Administrator', 'Operator'] %},{
"visible": false,
"targets": [-2]
}{% endif %}
],
"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">&times;</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">&times;</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">&times;</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">&times;</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 %}