crafty-4/app/frontend/templates/panel/panel_config.html
2023-10-08 22:30:40 -04:00

498 lines
20 KiB
HTML

{% extends ../base.html %}
{% block meta %}
{% end %}
{% block title %}Crafty Controller - {{ translate('panelConfig', 'pageTitle', data['lang']) }}{% end %}
{% block content %}
<div class="content-wrapper">
<!-- Page Title Header Starts-->
<div class="row page-title-header">
<div class="col-12">
<div class="page-header">
<h4 class="page-title">
{{ translate('panelConfig', 'title', data['lang']) }}
<br />
</h4>
</div>
</div>
</div>
<!-- Page Title Header Ends-->
<div class="row">
<div class="col-md-12 grid-margin">
<div class="card">
<div class="card-body">
{% if data['superuser'] %}
<span class="d-none d-sm-block">
{% include "parts/crafty_config_list.html %}
</span>
<span class="d-block d-sm-none">
{% include "parts/m_crafty_config_list.html %}
</span>
{% end %}
<!-- Page Title Header Starts-->
<div class="row page-title-header">
<div class="col-12">
<div class="page-header">
<!-- TODO: Translate the following -->
<h4 class="page-title">{{ translate('panelConfig', 'pageTitle', data['lang']) }}</h4>
</div>
</div>
</div>
<!-- Page Title Header Ends-->
<div class="row">
<div class="col-md-12 col-lg-12 grid-margin stretch-card">
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-users"></i> {{ translate('panelConfig', 'users', data['lang'])
}}</h4>
{% if data['user_data']['hints'] %}
<span class="too_small" title="{{ translate('dashboard', 'cannotSee', data['lang']) }}" ,
data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}" ,
data-placement="top"></span>
{% end %}
<!-- TODO: Translate the following -->
<div><a class="nav-link" href="/panel/add_user"><i class="fas fa-plus-circle"></i> &nbsp; {{
translate('panelConfig', 'newUser', data['lang']) }}</a></div>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<!-- TODO: Translate the following -->
<tr class="rounded">
<th>{{ translate('panelConfig', 'user', data['lang']) }}</th>
<th>{{ translate('panelConfig', 'enabled', data['lang']) }}</th>
<th>{{ translate('panelConfig', 'allowedServers', data['lang']) }}</th>
<th>{{ translate('panelConfig', 'assignedRoles', data['lang']) }}</th>
<th>{{ translate('panelConfig', 'edit', data['lang']) }}</th>
</tr>
</thead>
<tbody>
{% for user in data['users'] %}
<tr>
<td><i class="fas fa-user"></i><span id="user_{{user.user_id}}">{{ user.username }}</span></td>
<td>
{% if user.enabled %}
<span class="text-success">
<i class="fas fa-check-square"></i> Yes
</span>
{% else %}
<span class="text-danger">
<i class="far fa-times-square"></i> No
</span>
{% end %}
</td>
<td id="server_list_{{user.user_id}}">
<ul id="{{user.user_id}}">
{% for item in data['auth-servers'][user.user_id] %}
<li>{{item}}</li>
{% end %}
</ul>
</td>
<td id="role_list_{{user.user_id}}">
<ul>
{% for item in data['user-roles'][user.user_id] %}
<li data-toggle="tooltip" title="{{ item }}">{{item}}</li>
{% end %}
</ul>
</td>
<td><span data-translate="{{translate('userConfig', 'userName', data['lang'])}}" data-toggle="tooltip" title="{{ translate('userConfig', 'userName', data['lang'])}}" id="username_{{user.user_id}}" class="edit_user clickable" data-name="{{user.username}}" data-id="{{user.user_id}}"><i class="fa-solid fa-user"></i></span>
&nbsp;&nbsp;<span data-translate1="{{translate('userConfig', 'password', data['lang'])}}" data-translate2="{{translate('userConfig', 'repeat', data['lang'])}}" data-toggle="tooltip" title="{{ translate('userConfig', 'password', data['lang'])}}" class="edit_password clickable" data-id="{{user.user_id}}"><i class="fa-solid fa-lock"></i></span>
&nbsp;&nbsp;<a data-toggle="tooltip" title="{{ translate('userConfig', 'pageTitle', data['lang'])}}" href="/panel/edit_user?id={{user.user_id}}"><i class="fas fa-pencil-alt"></i></a>
</td>
</tr>
{% end %}
{% for user in data['managed_users'] %}
<tr>
<td><i class="fas fa-user"></i> {{ user.username }}</td>
<td>
{% if user.enabled %}
<span class="text-success">
<i class="fas fa-check-square"></i> Yes
</span>
{% else %}
<span class="text-danger">
<i class="far fa-times-square"></i> No
</span>
{% end %}
</td>
<td id="server_list_{{user.user_id}}">
<ul id="{{user.user_id}}">
{% for item in data['auth-servers'][user.user_id] %}
<li>{{item}}</li>
{% end %}
</ul>
</td>
<td id="role_list_{{user.user_id}}">
<ul>
{% for item in data['user-roles'][user.user_id] %}
<li data-toggle="tooltip" title="{{ item }}">{{item}}</li>
{% end %}
</ul>
</td>
<td><span data-translate="{{translate('userConfig', 'userName', data['lang'])}}" data-toggle="tooltip" title="{{ translate('userConfig', 'userName', data['lang'])}}" id="username_{{user.user_id}}" class="edit_user clickable" data-name="{{user.username}}" data-id="{{user.user_id}}"><i class="fa-solid fa-user"></i></span>
&nbsp;&nbsp;<span data-translate1="{{translate('userConfig', 'password', data['lang'])}}" data-translate2="{{translate('userConfig', 'repeat', data['lang'])}}" data-toggle="tooltip" title="{{ translate('userConfig', 'password', data['lang'])}}" class="edit_password clickable" data-id="{{user.user_id}}"><i class="fa-solid fa-lock"></i></span>
&nbsp;&nbsp;<a data-toggle="tooltip" title="{{ translate('userConfig', 'pageTitle', data['lang'])}}" href="/panel/edit_user?id={{user.user_id}}"><i class="fas fa-pencil-alt"></i></a>
</td>
</tr>
{% end %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-lg-12 grid-margin stretch-card">
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-user-tag"></i> {{ translate('panelConfig', 'roles',
data['lang']) }}</h4>
{% if data['user_data']['hints'] %}
<span class="too_small2" title="{{ translate('dashboard', 'cannotSee', data['lang']) }}" ,
data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}" ,
data-placement="top"></span>
{% end %}
<div><a class="nav-link" href="/panel/add_role"><i class="fas fa-plus-circle"></i> &nbsp; {{
translate('panelConfig', 'newRole', data['lang']) }}</a></div>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<!-- TODO: Translate the following -->
<tr class="rounded">
<th>{{ translate('panelConfig', 'role', data['lang']) }}</th>
<th>{{ translate('panelConfig', 'allowedServers', data['lang']) }}</th>
<th>{{ translate('panelConfig', 'roleUsers', data['lang']) }}</th>
<th>{{ translate('panelConfig', 'edit', data['lang']) }}</th>
</tr>
</thead>
<tbody>
{% for role in data['roles'] %}
<tr>
<td>{{ role.role_name }}</td>
<td id="role_list_{{role.role_id}}">
<ul id="{{role.role_id}}">
{% for item in data['role-servers'][role.role_id] %}
<li>{{item}}</li>
{% end %}
</ul>
</td>
<td>
<ul>
{% for user in data['users'] %}
{% for ruser in data['user-roles'][user.user_id] %}
{% if ruser == role.role_name %}
<li>{{ user.username }}</li>
{% end %}
{% end %}
{% end %}
</ul>
</td>
<td><a href="/panel/edit_role?id={{role.role_id}}"><i class="fas fa-pencil-alt"></i></a></td>
</tr>
{% end %}
{% if not data['superuser'] %}
{% for role in data['managed_roles'] %}
{% if role.role_id not in data['assigned_roles'] %}
<tr>
<td>{{ role.role_name }}</td>
<td id="role_list_{{role.role_id}}">
<ul id="{{role.role_id}}">
{% for item in data['role-servers'][role.role_id] %}
<li>{{item}}</li>
{% end %}
</ul>
</td>
<td>
<ul>
{% for user in data['users'] %}
{% for ruser in data['user-roles'][user.user_id] %}
{% if ruser == role.role_name %}
<li>{{ user.username }}</li>
{% end %}
{% end %}
{% end %}
</ul>
</td>
<td><a href="/panel/edit_role?id={{role.role_id}}"><i class="fas fa-pencil-alt"></i></a></td>
</tr>
{% end %}
{% end %}
{% end %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% if data['superuser'] and not data["docker"] %}
<div class="row">
<div class="col-md-12 col-lg-12 grid-margin stretch-card">
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-user-tag"></i> {{ translate('panelConfig', 'adminControls',
data['lang']) }}</h4>
</div>
<br>
<form id="server-path">
<div class="form-group">
<label for="global_server_path">{{ translate('panelConfig', 'globalServer',
data['lang']) }}<small class="text-muted ml-1"> - {{ translate('panelConfig', 'globalExplain',
data['lang']) }}</small></label>
<div class="input-group">
<input type="text" id="global_server_path" class="form-control" name="global_server_path"
placeholder="/var/opt/servers" value="{{data['servers_dir']}}" directory>
<div class="input-group-append">
<span type="button" class="btn btn-outline-default custom-picker">/servers/</span>
</div>
</div>
</div>
<button class="btn btn-success" type="submit">Submit</button>&nbsp;<span id="submit-status"></span>
<br>
<span id="submit-list"></span>
</form>
</div>
</div>
</div>
{% end %}
</div>
</div>
</div>
</div>
</div>
<style>
.clickable {
color: #007bff;
}
.clickable:hover {
cursor: pointer;
}
.custom-picker {
border: 1px solid var(--outline);
}
.popover-body {
color: white !important;
;
}
.loading:after {
overflow: hidden;
display: inline-block;
vertical-align: bottom;
-webkit-animation: ellipsis steps(4, end) 900ms infinite;
animation: ellipsis steps(4, end) 900ms infinite;
content: "\2026";
/* ascii code for the ellipsis character */
width: 0px;
}
@keyframes ellipsis {
to {
width: 1.25em;
}
}
@-webkit-keyframes ellipsis {
to {
width: 1.25em;
}
}
</style>
<!-- content-wrapper ends -->
{% end %}
{% block js %}
<script>
function validateForm() {
let password0 = document.getElementById("password0").value;
let password1 = document.getElementById("password1").value;
if (password0 != password1) {
$('.passwords-match').popover('show');
$('.popover-body').click(function () {
$('.passwords-match').popover("hide");
});
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
$("#password0").css("outline", "1px solid red");
$("#password1").css("outline", "1px solid red");
return false;
} else {
return password1;
}
}
$(".edit_password").on("click", async function(){
const token = getCookie("_xsrf");
let user_id = $(this).data('id');
bootbox.confirm(`<form class="form" id='infos' action=''>\
<div class="form-group">
<label for="new_password">${$(this).data("translate1")}</label>
<input class="form-control" type='password' id="password0" name='new_password' /></br>\
</div>
<div class="form-group">
<label for="confirm_password">${$(this).data("translate2")}</label>
<input class="form-control" type='password' id="password1" name='confirm_password' />\
</div>
</form>`, async function(result) {
if(result){
password = validateForm();
if (!password){
return;
}
let res = await fetch(`/api/v2/users/${user_id}`, {
method: 'PATCH',
headers: {
'X-XSRFToken': token
},
body: JSON.stringify({"password": password}),
});
let responseData = await res.json();
if (responseData.status === "ok") {
console.log(responseData.data)
} else {
bootbox.alert({
title: responseData.status,
message: responseData.error
});
}
}
});
});
$(document).on("submit", ".bootbox form", function(e) {
e.preventDefault();
$(".bootbox .btn-primary").click();
});
$(".edit_user").on("click", function(){
const token = getCookie("_xsrf");
let username = $(this).data('name');
let user_id = $(this).data('id');
bootbox.confirm(`<form class="form" id='infos' action=''>\
<div class="form-group">
<label for="username">${$(this).data("translate")}</label>
<input class="form-control" type='text' name='username' id="username_field" value=${username} /><br/>\
</div>
</form>`, async function(result) {
if(result){
let new_username = $("#username_field").val();
let res = await fetch(`/api/v2/users/${user_id}`, {
method: 'PATCH',
headers: {
'X-XSRFToken': token
},
body: JSON.stringify({"username": new_username}),
});
let responseData = await res.json();
if (responseData.status === "ok") {
$(`#user_${user_id}`).html(` ${new_username}`)
$(`#username_${user_id}`).data('name', new_username);
} else {
bootbox.alert({
title: responseData.status,
message: responseData.error
});
}
}
});
});
if (webSocket) {
webSocket.on('move_status', function (message) {
if (message === "done") {
$("#submit-list").removeClass("loading");
$("#submit-list").html("");
$("#submit-status").html('<i class="fa fa-check"></i>');
} else {
$("#submit-status").html('<i class="fa fa-spinner fa-spin"></i>');
$("#submit-list").html(message);
$("#submit-list").addClass("loading");
}
});
}
$("#server-path").submit(async function (e) {
const token = getCookie("_xsrf")
e.preventDefault();
$("#submit-status").html('<i class="fa fa-spinner fa-spin"></i>');
let path = $("#global_server_path").val();
let res = await fetch(`/api/v2/crafty/config/servers_dir`, {
method: 'PATCH',
headers: {
'X-XSRFToken': token
},
body: JSON.stringify({ "new_dir": path }),
});
let responseData = await res.json();
if (responseData.status === "ok") {
return
} else {
bootbox.alert({
title: responseData.status,
message: responseData.error
});
}
});
$(document).ready(function () {
$('[data-toggle="popover"]').popover();
if ($(window).width() < 1000) {
$('.too_small').popover("show");
$('.too_small2').popover("show");
}
});
$(window).ready(function () {
$('body').click(function () {
$('.too_small').popover("hide");
$('.too_small2').popover("hide");
});
});
$(window).resize(function () {
// This will execute whenever the window is resized
if ($(window).width() < 1000) {
$('.too_small').popover("show");
}
else {
$('.too_small').popover("hide");
} // New width
if ($(window).width() < 1000) {
$('.too_small2').popover("show");
}
else {
$('.too_small2').popover("hide");
} // New width
});
$('#file').change(function () {
console.log("File changed");
if ($('#file').val()) {
$('#upload-button').prop("disabled", false);
console.log("File changed good");
}
});
</script>
{% end %}