Reorganize repos

This commit is contained in:
2024-07-23 09:22:19 +02:00
parent 1a371c9349
commit b362c56b73
49 changed files with 0 additions and 0 deletions

View File

@ -0,0 +1,18 @@
<!-- Put your reusable template code into macros here -->
{% macro theme_icon(theme) %}
<div class="theme-icon">
{% if theme == "dark" %}
<svg xmlns="http://www.w3.org/2000/svg" class="theme-icon" fill="none" viewBox="0 0 24 24" stroke="yellow"
stroke-opacity="0.6">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
{% else %}
<svg xmlns="http://www.w3.org/2000/svg" class="theme-icon" fill="none" viewBox="0 0 18 24" stroke="grey"
stroke-opacity="0.6">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
</svg>
{% endif %}
</div>
{% endmacro %}

111
app/templates/base.html Normal file
View File

@ -0,0 +1,111 @@
{% import '_macros.html.j2' as mc -%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ config.APP_NAME }}</title>
<!-- meta -->
<meta name="description" content="">
<meta name="author" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
{% block meta %}{% endblock %}
<!-- styles -->
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/toggle-bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/toggle-bootstrap-dark.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/toggle-bootstrap-print.min.css') }}">
<!-- Century gothic font -->
<link rel="stylesheet" href="{{ url_for('static', filename='fonts/century-gothic.css') }}">
<!-- fontawesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
<link href="{{ url_for('static', filename='main.css') }}" rel="stylesheet" media="screen">
<!-- Datatables -->
<link href="{{ url_for('static', filename='datatables/datatables.min.css') }}" rel="stylesheet">
{% block links %}{% endblock %}
<link rel="icon" type="image/png" sizes="180x180" href="{{ url_for('static', filename='favicon/apple-touch-icon.png') }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon/favicon-32x32.png') }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon/favicon-16x16.png') }}">
<link rel="icon" type="image/png" sizes="192x192" href="{{ url_for('static', filename='favicon/android-chrome-192x192.png') }}">
<link rel="icon" type="image/png" sizes="512x512" href="{{ url_for('static', filename='favicon/android-chrome-512x512.png') }}">
<link rel="manifest" href="{{ url_for('static', filename='favicon/site.webmanifest') }}">
</head>
<body class="bootstrap bootstrap-dark">
<!-- Header -->
<header>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-themed">
<!-- Navbar Brand -->
<a class="navbar-brand" href="{{ url_for('main.index') }}">
<img src="{{ url_for('static', filename='/hsman.png') }}">
<!-- HSMAN -->
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.nodes') }}">nodes</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.users') }}">users</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('main.routes') }}">routes</a>
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item me-right">
<a href="{{url_for('main.logout') }}" id="themeSwitch">
<i class="fas fa-sign-out-alt"></i>
<!-- <i class="fas fa-plug-circle-xmark"></i> -->
</a>
</li>
</ul>
</div>
</nav>
</header>
{% if g.is_mobile %}
<div class="container-fluid">
{% else %}
<div class="container">
{% endif %}
<!-- Main Content -->
{% block content %}{% endblock %}
</div>
<!-- Footer-->
<footer class="footer text-center">
<div class="container">
<div class="row">
<!-- Copyrights -->
<div class="col-lg-12 text-center">
<p class="text-muted mb-0 py-2">
<!-- <img src="/static/hsman.png" height="20px"> -->
Headscale Manager |
ver. {{ config.APP_VERSION }} ({{ config.APP_SHA }})
</p>
</div>
</div>
</footer>
<!-- scripts -->
<script src="{{ url_for('static', filename='bootstrap/jquery-3.7.1.min.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap/popper-1.12.9.min.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='datatables/datatables.min.js') }}"></script>
<script src="{{ url_for('static', filename='main.js') }}" type="text/javascript"></script>
<script>
$(function () {
$('[data-toggle="tooltip"]').tooltip();
})
</script>
{% block scripts %}{% endblock %}
</body>
</html>

10
app/templates/error.html Normal file
View File

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block content %}
<div class="jumbotron my-4">
<div class="text-center">
<h1>{{ '%s - %s' % (error.code, error.name) }}</h1>
<p>{{ error.description }}.</p>
</div>
</div>
{% endblock %}

71
app/templates/index.html Normal file
View File

@ -0,0 +1,71 @@
{% extends "base.html" %}
{% block content %}
<h3>Welcome, {{ session.userinfo.name }}</h3>
<hr>
<h4>authentication info</h4>
<div class="row data">
<div class="col col-2">
<strong>email</strong>
</div>
<div class="col col-6">
{{ session.userinfo.email }}
<!-- {{ session.userinfo.email_verified | fancyBool | safe }} -->
</div>
</div>
<div class="row data">
<div class="col col-2">
<strong>username</strong>
</div>
<div class="col col-6">
{{ session.userinfo.preferred_username }}
</div>
</div>
<div class="row data">
<div class="col col-2">
<strong>groups</strong>
</div>
<div class="col col-6">
<i class="fas fa-angle-right"></i>
{{ session.userinfo.groups[0]}}
</div>
</div>
{% for group in session.userinfo.groups[1:] |sort %}
<div class="row data">
<div class="col col-2">
&nbsp;
</div>
<div class="col col-6">
<i class="fas fa-angle-right"></i> {{ group }}
</div>
</div>
{% endfor %}
<hr>
<h4>your devices</h4>
<div class="row strong">
<div class="col col-2"><strong></strong></div>
<div class="col col-2"><strong>registered</strong></div>
<div class="col col-2"><strong>last event</strong></div>
<div class="col col-2"><strong>online</strong></div>
</div>
{% for node in userNodeList %}
<div class="row data">
<div class="col col-2">
{{ node.givenName}}
</div>
<div class="col col-2">
<span data-toggle="tooltip" data-placement="right" title="{{ node.createdAt | fmt_datetime }}">
{{node.createdAt | htime_dt }}
</span>
</div>
<div class="col col-2">
<span data-toggle="tooltip" data-placement="right" title="{{ node.lastSeen | fmt_datetime }}">
{{node.lastSeen | htime_dt }}
</span>
</div>
<div class="col col-2">
{{node.online | fancyBool | safe }}
</div>
</div>
{% endfor %}
{% endblock %}

209
app/templates/node.html Normal file
View File

@ -0,0 +1,209 @@
{% extends "base.html" %}
{% block content %}
<h3>
<span id="givenName">
{{node.givenName}}
</span>
<a href="#" data-toggle="modal" data-target="#renameModal">
<span data-toggle="tooltip"
data-placement="right"
title="rename node">
<i class="fas fa-edit h6"></i>
</span>
</a>
</h3>
<hr>
<p></p>
<div class="row">
<div class="col col-3 float-left">
<strong>status</strong>
</div>
<div class="col col-8 float-left">
{% if node.online %}
<span class="badge badge-pill badge-success">online</span>
{% else %}
<span class="badge badge-pill badge-danger">offline</span>
{% endif %}
</div>
</div>
<div class="row">
<div class="col col-3 float-left">
<strong>registered</strong>
</div>
<div class="col col-8 float-left">
<span data-toggle="tooltip" data-placement="right" title="{{ node.createdAt | fmt_datetime }}">
{{ node.createdAt | htime_dt }}
</span>
</div>
</div>
<div class="row">
<div class="col col-3 float-left">
<strong>expire</strong>
</div>
<div class="col col-8 float-left">
<span data-toggle="tooltip" data-placement="right" title="{{ node.expiry | fmt_datetime }}">
{{ node.expiry | htime_dt }}
</span>
{% if node.expireDate and not node.expired %}
<a href="{{ url_for('rest.expireNode', nodeId=node.id) }}">
<span data-toggle="tooltip" data-placement="right" title="expire/disconnect node">
<i class="fas fa-plug"></i>
</span>
</a>
{% endif %}
</div>
</div>
<div class="row">
<div class="col col-3 float-left">
<strong>owner</strong>
</div>
<div class="col col-8 float-left">
<a href='{{ url_for("main.user", userName=node.user.name) }}' class="plain">{{ node.user.name }}</a>
</div>
</div>
<p></p>
<!-- ADDRESSES -->
<h5>addresses</h5>
{% for ip in node.ipAddresses %}
<div class="row data">
<div class="col col-3">
{{ ip }}
</div>
</div>
{% endfor %}
<p></p>
<!-- TAGS -->
<h5>tags</h5>
<div class="row data">
<div class="col col-3 float-left">
<strong>
announced
</strong>
</div>
<div class="col col-6 float-left">
{% if node.validTags %}
{% for tag in node.validTags %}
<span class="badge badge-pill badge-warning">
{{ tag }}
</span>
{% endfor %}
{% else %}
None
{% endif %}
</div>
</div>
<div class="row data">
<div class="col col-3 float-left">
<strong>forced</strong>
</div>
<div class="col col-6 float-left">
{% if node.forced %}
{% for tag in node.forcedTags %}
<h3><span class="badge badge-pill badge-primary">
{{ tag }}
</span></h3>
{% endfor %}
{% else %}
None
{% endif %}
</div>
</div>
<!-- KEYS -->
<p></p>
<h5>keys</h5>
<div class="row data">
<div class="col col-3 float-left">
<strong>machineKey</strong>
</div>
<div class="col col-8 float-left">
<code>{{ node.machineKey }}</code>
</div>
</div>
<div class="row data">
<div class="col col-3 float-left">
<strong>nodeKey</strong>
</div>
<div class="col col-8 float-left">
<code>{{ node.nodeKey }}</code>
</div>
</div>
<div class="row data">
<div class="col col-3 float-left">
<strong>discoKey</strong>
</div>
<div class="col col-8 float-left">
<code>{{ node.discoKey }}</code>
</div>
</div>
<p></p>
<!-- ROUTES -->
<h5>routes
{% if isExitNode %}
<span class="small badge-pill badge-primary">Exit Node</span>
{% endif %}
</h5>
{% if routes %}
<div class="row">
<div class="col col-3 float-left">
<strong>prefix</strong>
</div>
<div class="col col-3 float-left">
<strong>enabled</strong>
</div>
<div class="col col-3 float-left">
<strong>primary</strong>
</div>
</div>
{% for route in routes | sort(attribute='prefix') %}
<div class="row data">
<div class="col col-3 float-left">
{{ route.prefix }}
</div>
<div class="col col-3 float-left">
{{ route.enabled | fancyBool | safe }}
</div>
<div class="col col-3 float-left">
{{ route.isPrimary | fancyBool | safe }}
</div>
</div>
{% endfor %}
{% else %}
<div class="row">
<div class="col col-9 text-center">
<h3>No routes announced</h3>
</div>
</div>
{% endif %}
<!-- rename modal -->
<!-- Modal -->
<div class="modal fade" id="renameModal" tabindex="-1" role="dialog" aria-labelledby="renameModal" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="renameModalLabel">Rename node</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<input type="text" name="newName" id="newName" value="{{ node.givenName}}">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onClick="renameNode(id={{node.id}})">Save changes</button>
</div>
</div>
</div>
</div>
{% endblock %}

98
app/templates/nodes.html Normal file
View File

@ -0,0 +1,98 @@
{% extends "base.html" %}
{% block content %}
<h3>nodes</h3>
<hr>
<p></p>
<table id="nodes" class="display" style="width:100%">
<thead>
<tr>
<th>name</th>
<th>user</th>
<th>expire</th>
<th>last event</th>
<th>addresses</th>
<th>online</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for node in nodes %}
<tr>
<td>
<a class="plain" href="{{ url_for('main.node', nodeId=node.id)}}">
<span data-toggle="tooltip" data-placement="right" title="{{ node.ipAddresses | join('\n') }}">
{{node.givenName}}
</span>
</a>
</td>
<td>
<a class="plain" href="{{ url_for('main.user', userName=node.user.name)}}">
{{node.user.name}}
</a>
</td>
<td>
<span data-toggle="tooltip" data-placement="right"
title="{{ node.expiry | fmt_datetime }}"
class="{% if node.expired %}expired{% endif %}">
{{node.expireDate | htime_dt | safe}}
</span>
</td>
<td data-order="{{ node.lastSeen | fmt_datetime }}">
<span data-toggle="tooltip" data-placement="right" title="{{ node.lastSeen | fmt_datetime }}">
{{node.lastSeen | htime_dt }}
</span>
</td>
<td>
{{ node.ipAddresses | join(', ') }}
</td>
<td data-filter="{{ node.online | fancyOnline }}">
{{node.online | fancyBool | safe}}
</td>
<td class="no-sort">
{% if node.expireDate and not node.expired %}
<span data-toggle="tooltip" data-placement="right" title="expire/disconnect">
<a class="nodeco" href="{{ url_for('rest.expireNodeList', nodeId=node.id) }}">
<i class="fas fa-plug"></i>
</a>
</span>
{% else %}
<i class="fas fa-plug disabled"></i>
{% endif %}
<span data-toggle="tooltip" data-placement="right" title="delete">
<a class="nodeco" href="{{ url_for('rest.deleteNode', nodeId=node.id) }}">
<i class="fas fa-trash"></i>
</a>
</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
{% block scripts %}
<script>
$(function () {
new DataTable('#nodes', {
paging: true,
lengthMenu: [15, 30, 50, 100, { label: 'All', value: -1 }],
pageLength: 30,
fixedHeader: false,
select: false,
keys: false,
aoColumnDefs: [
{ 'bSortable': false, 'aTargets': [ -1 ] }
],
columnDefs: [
{
target: 4,
visible: false,
searchable: true
}
]
});
})
</script>
{% endblock %}

93
app/templates/routes.html Normal file
View File

@ -0,0 +1,93 @@
{% extends "base.html" %}
{% block content %}
<h5>
Routing table
<small class="text-muted">
click on the icon in <em>enabled</em> column to toggle route status
</small>
</h5>
<hr>
<p></p>
<div class="row">
<div class="col col-12">
<h5>Exit nodes</h5>
</div>
</div>
{% for exitNode in exitNodes %}
<div class="row data">
<div class="col col-12">
<span data-toggle="tooltip" data-placement="right" title="{{ exitNode.ipAddresses | join('\n') }}">
&nbsp; {{ exitNode.givenName }}
</span>
</div>
</div>
{% endfor %}
<p></p>
{% for prefix, rts in routes.items() %}
<div class="row">
<div class="col col-4 float-left">
<strong>prefix</strong>
</div>
<div class="col col-4 float-left">
<strong>gateway</strong>
</div>
<div class="col col-2 float-left">
<strong>enabled</strong>
</div>
<div class="col col-2 float-left">
<strong>active</strong>
</div>
</div>
<div class="row data">
<div class="col col-4 float-left">
{{ prefix}}
</div>
<div class="col col-4 float-left">
<a class="plain route primary" href="{{ url_for('main.node', nodeId=rts[0].node.id) }}">
<span data-toggle="tooltip" data-placement="right"
title="{{ rts[0].node.ipAddresses | join('\n') }}">
{{ rts[0].node.givenName}}
</span>
</a>
</div>
<div class="col col-2 float-left">
<a class="routeToggle" href="{{ url_for('rest.routeToggle', routeId=rts[0].id) }}">
{{ rts[0].enabled | fancyBool | safe}}
</a>
</div>
<div class="col col-2 float-left">
{{ rts[0].isPrimary | fancyBool | safe}}
</div>
</div>
{% for rt in rts[1:] %}
<div class="row data">
<div class="col col-4 float-left" style="border: 1px red;">
<span>&nbsp;</span>
</div>
<div class="col col-4">
<a class="plain route {{rt.enabled}}" href="{{ url_for('main.node', nodeId=rt.node.id) }}">
<span data-toggle="tooltip" data-placement="right"
title="{{ rt.node.ipAddresses | join('\n') }}">
{{ rt.node.givenName}}
</span>
</a>
</div>
<div class="col col-2 float-left">
<a class="routeToggle" href="{{ url_for('rest.routeToggle', routeId=rt.id) }}">
{{ rt.enabled | fancyBool | safe}}
</a>
</div>
<div class="col col-2 float-left">
{{ rt.isPrimary | fancyBool | safe}}
</div>
</div>
{% endfor %}
<p></p>
{% endfor %}
{% endblock %}

208
app/templates/user.html Normal file
View File

@ -0,0 +1,208 @@
{% extends "base.html" %}
{% block content %}
<h3>{{ user.name }}</h3>
<hr>
<p></p>
<div class="row">
<div class="col col-3">
<strong>registered</strong>
</div>
<div class="col col-8">
<span data-toggle="tooltip"
data-placement="right"
title="{{ user.createdAt | fmt_datetime }}">
{{ user.createdAt | htime_dt }}
</span>
</div>
</div>
<p></p>
<!-- NODES -->
<h5>nodes</h5>
<table id="nodes" class="display" style="width:80%">
<thead>
<tr>
<th>&nbsp;</th>
<th>last connect</th>
<th>online</th>
</tr>
</thead>
<tbody>
{% for node in userNodeList %}
<tr>
<td>
<a href="{{ url_for('main.node', nodeId=node.id) }}" class="plain">
{{ node.givenName }}
</a>
</td>
<td>
<span data-toggle="tooltip"
data-placement="right"
title="{{ node.lastSeen | fmt_datetime }}">
{{node.lastSeen | htime_dt }}
</span>
</td>
<td>
{{node.online | fancyBool | safe}}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<p></p>
<!-- PRE AUTH KEYS -->
<h5>
pre auth keys
&nbsp;
<button class="btn btn-outline-primary btn-sm" data-toggle="modal" data-target="#createPKA">create</button>
</h5>
{% if preauthKeys %}
<table id="paks" class="display" style="width:80%">
<thead>
<tr>
<th>
<div class="form-check form-check-inline">
<label class="form-check-label small" for="showExpired">
show expired&nbsp;
</label>
<input type="checkbox" class="form-check-input form-control-sm" id="showExpired">
</div>
</th>
<th>created</th>
<th>expiration</th>
<th>attributes</th>
<!-- <th>&nbsp;</th> -->
</tr>
</thead>
<tbody>
{% for key in preauthKeys %}
<tr class="pka{% if key.expired %} pka-expired pka-hide{% endif %}">
<td>
<span data-toggle="tooltip"
data-placement="right"
value="{{ key.key}}"
title="click to copy full value"
class="pak_copy">{{ key.key[:5] }}&hellip;{{ key.key[-5:] }}</span>
</td>
<td>
<span data-toggle="tooltip"
data-placement="right"
title="{{ key.createdAt | fmt_datetime }}">
{{key.createdAt | htime_dt }}
</span>
</td>
<td>
<span data-toggle="tooltip"
data-placement="right"
title="{{ key.expiration | fmt_datetime }}">
{{key.expiration | htime_dt }}
</span>
</td>
<td>
{% if key.ephemeral %}
<span class="badge badge-pill badge-primary">ephemereal</span>
{% endif %}
{% if key.reusable %}
<span class="badge badge-pill badge-primary">reusable</span>
{% endif %}
{% if key.used %}
<span class="badge badge-pill badge-primary">used</span>
{% endif %}
</td>
<!-- <td>
<span data-toggle="tooltip" data-placement="right" title="expire">
<a class="nodeco" href="/user/{{user.name}}/expire/{{key.key}}">
<i class="fas fa-trash"></i>
</a>
</span>
</td> -->
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="row">
<div class="col col-9 text-center">
<h3>No preauth keys</h3>
</div>
</div>
{% endif %}
<!-- new key modal -->
<div class="modal fade" id="createPKA" tabindex="-1" role="dialog" aria-labelledby="createPKA" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="renameModalLabel">create new pre auth key</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-check form-check-inline">
<input class="form-check-input" type="datetime-local" name="expiration" id="expiration" value="{{ defaultExpiry}}">
<label class="form-check-label" for="ephemereal">expiration</label>
</div>
<p></p>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="reusable" id="reusable">
<label class="form-check-label" for="reusable">reusable</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="ephemereal" id="ephemereal">
<label class="form-check-label" for="ephemereal">ephemereal</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onClick="createPKA(user='{{ user.name }}')">Save changes</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
$(function () {
$('.pak_copy').on('click', function() {
copyToClipboard(this)
})
$('#showExpired').on('change', function() {
toggleExpired(this)
})
new DataTable('#nodes', {
scrollY: 130,
scrollCollapse: true,
paging: false,
// lengthMenu: [5, 10, 30, 50, { label: 'All', value: -1 }],
// pageLength: 10,
fixedHeader: {
header: true,
footer: false
},
info: false,
searching: false,
select: false,
keys: false,
});
new DataTable('#paks', {
scrollY: 230,
scrollCollapse: true,
paging: false,
// lengthMenu: [5, 10, 30, 50, { label: 'All', value: -1 }],
// pageLength: 10,
fixedHeader: {
header: true,
footer: false
},
info: false,
searching: false,
select: false,
keys: false,
});
})
</script>
{% endblock %}

62
app/templates/users.html Normal file
View File

@ -0,0 +1,62 @@
{% extends "base.html" %}
{% block content %}
<h3>users</h3>
<hr>
<p></p>
<table id="users" class="display" style="width:100%">
<thead>
<tr>
<th>name</th>
<th>registered on</th>
<th>online</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>
<a class="plain" href="{{ url_for('main.user', userName=user.name)}}">
{{user.name}}
</a>
</td>
<td data-order="{{ user.createdAt }}">
<span data-toggle="tooltip" data-placement="right" title="{{ user.createdAt | fmt_datetime }}">
{{user.createdAt | htime_dt }}
</span>
</td>
<td data-filter="{{ online[user.name] | fancyOnline }}">
{{online[user.name] | fancyBool | safe }}
</td>
<td class="no-sort">
<span data-toggle="tooltip" data-placement="right" title="delete">
<a class="nodeco" href="/user/{{user.name}}/delete">
<i class="fas fa-trash"></i>
</a>
</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
{% block scripts %}
<script>
$(function () {
new DataTable('#users', {
paging: true,
lengthMenu: [15, 30, 50, 100, { label: 'All', value: -1 }],
pageLength: 30,
fixedHeader: false,
select: false,
keys: false,
aoColumnDefs: [
{ 'bSortable': false, 'aTargets': [ -1 ] }
],
});
})
</script>
{% endblock %}