mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'refactor/backups' into refactor/upload-api
This commit is contained in:
commit
5a6229d282
@ -1140,6 +1140,7 @@ class ServerInstance:
|
|||||||
was_server_running = None
|
was_server_running = None
|
||||||
logger.info(f"Starting server {self.name} (ID {self.server_id}) backup")
|
logger.info(f"Starting server {self.name} (ID {self.server_id}) backup")
|
||||||
server_users = PermissionsServers.get_server_user_list(self.server_id)
|
server_users = PermissionsServers.get_server_user_list(self.server_id)
|
||||||
|
# Alert the start of the backup to the authorized users.
|
||||||
for user in server_users:
|
for user in server_users:
|
||||||
WebSocketManager().broadcast_user(
|
WebSocketManager().broadcast_user(
|
||||||
user,
|
user,
|
||||||
@ -1149,34 +1150,37 @@ class ServerInstance:
|
|||||||
).format(self.name),
|
).format(self.name),
|
||||||
)
|
)
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
|
||||||
|
# Get the backup config
|
||||||
conf = HelpersManagement.get_backup_config(backup_id)
|
conf = HelpersManagement.get_backup_config(backup_id)
|
||||||
|
# Adjust the location to include the backup ID for destination.
|
||||||
backup_location = os.path.join(conf["backup_location"], conf["backup_id"])
|
backup_location = os.path.join(conf["backup_location"], conf["backup_id"])
|
||||||
|
|
||||||
|
# Check if the backup location even exists.
|
||||||
if not backup_location:
|
if not backup_location:
|
||||||
Console.critical("No backup path found. Canceling")
|
Console.critical("No backup path found. Canceling")
|
||||||
return None
|
return None
|
||||||
if conf["before"]:
|
if conf["before"]:
|
||||||
if self.check_running():
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Found running server and send command option. Sending command"
|
"Found running server and send command option. Sending command"
|
||||||
)
|
)
|
||||||
self.send_command(conf["before"])
|
self.send_command(conf["before"])
|
||||||
|
# Pause to let command run
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
if conf["shutdown"]:
|
if conf["shutdown"]:
|
||||||
if conf["before"]:
|
|
||||||
# pause to let people read message.
|
|
||||||
time.sleep(5)
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Found shutdown preference. Delaying"
|
"Found shutdown preference. Delaying"
|
||||||
+ "backup start. Shutting down server."
|
+ "backup start. Shutting down server."
|
||||||
)
|
)
|
||||||
if not update:
|
if not update:
|
||||||
|
was_server_running = False
|
||||||
if self.check_running():
|
if self.check_running():
|
||||||
self.stop_server()
|
self.stop_server()
|
||||||
was_server_running = True
|
was_server_running = True
|
||||||
else:
|
|
||||||
was_server_running = False
|
|
||||||
|
|
||||||
self.helper.ensure_dir_exists(backup_location)
|
self.helper.ensure_dir_exists(backup_location)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
backup_filename = (
|
backup_filename = (
|
||||||
f"{backup_location}/"
|
f"{backup_location}/"
|
||||||
@ -1402,41 +1406,10 @@ class ServerInstance:
|
|||||||
"string": message,
|
"string": message,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
backup_dir = os.path.join(
|
|
||||||
Helpers.get_os_understandable_path(self.settings["path"]),
|
|
||||||
"crafty_executable_backups",
|
|
||||||
)
|
|
||||||
# checks if backup directory already exists
|
|
||||||
if os.path.isdir(backup_dir):
|
|
||||||
backup_executable = os.path.join(backup_dir, self.settings["executable"])
|
|
||||||
else:
|
|
||||||
logger.info(
|
|
||||||
f"Executable backup directory not found for Server: {self.name}."
|
|
||||||
f" Creating one."
|
|
||||||
)
|
|
||||||
os.mkdir(backup_dir)
|
|
||||||
backup_executable = os.path.join(backup_dir, self.settings["executable"])
|
|
||||||
|
|
||||||
if len(os.listdir(backup_dir)) > 0:
|
|
||||||
# removes old backup
|
|
||||||
logger.info(f"Old backups found for server: {self.name}. Removing...")
|
|
||||||
for item in os.listdir(backup_dir):
|
|
||||||
os.remove(os.path.join(backup_dir, item))
|
|
||||||
logger.info(f"Old backups removed for server: {self.name}.")
|
|
||||||
else:
|
|
||||||
logger.info(f"No old backups found for server: {self.name}")
|
|
||||||
|
|
||||||
current_executable = os.path.join(
|
current_executable = os.path.join(
|
||||||
Helpers.get_os_understandable_path(self.settings["path"]),
|
Helpers.get_os_understandable_path(self.settings["path"]),
|
||||||
self.settings["executable"],
|
self.settings["executable"],
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
|
||||||
# copies to backup dir
|
|
||||||
FileHelpers.copy_file(current_executable, backup_executable)
|
|
||||||
except FileNotFoundError:
|
|
||||||
logger.error("Could not create backup of jarfile. File not found.")
|
|
||||||
|
|
||||||
backing_up = True
|
backing_up = True
|
||||||
# wait for backup
|
# wait for backup
|
||||||
while backing_up:
|
while backing_up:
|
||||||
|
@ -41,6 +41,8 @@ SUBPAGE_PERMS = {
|
|||||||
"webhooks": EnumPermissionsServer.CONFIG,
|
"webhooks": EnumPermissionsServer.CONFIG,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCHEDULE_AUTH_ERROR_URL = "/panel/error?error=Unauthorized access To Schedules"
|
||||||
|
|
||||||
|
|
||||||
class PanelHandler(BaseHandler):
|
class PanelHandler(BaseHandler):
|
||||||
def get_user_roles(self) -> t.Dict[str, list]:
|
def get_user_roles(self) -> t.Dict[str, list]:
|
||||||
@ -1147,7 +1149,7 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
if not EnumPermissionsServer.SCHEDULE in page_data["user_permissions"]:
|
if not EnumPermissionsServer.SCHEDULE in page_data["user_permissions"]:
|
||||||
if not superuser:
|
if not superuser:
|
||||||
self.redirect("/panel/error?error=Unauthorized access To Schedules")
|
self.redirect(SCHEDULE_AUTH_ERROR_URL)
|
||||||
return
|
return
|
||||||
|
|
||||||
template = "panel/server_schedule_edit.html"
|
template = "panel/server_schedule_edit.html"
|
||||||
@ -1245,7 +1247,7 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
if not EnumPermissionsServer.SCHEDULE in page_data["user_permissions"]:
|
if not EnumPermissionsServer.SCHEDULE in page_data["user_permissions"]:
|
||||||
if not superuser:
|
if not superuser:
|
||||||
self.redirect("/panel/error?error=Unauthorized access To Schedules")
|
self.redirect(SCHEDULE_AUTH_ERROR_URL)
|
||||||
return
|
return
|
||||||
|
|
||||||
template = "panel/server_schedule_edit.html"
|
template = "panel/server_schedule_edit.html"
|
||||||
@ -1315,9 +1317,9 @@ class PanelHandler(BaseHandler):
|
|||||||
exclusions.append(file.replace(server_info["path"] + "/", ""))
|
exclusions.append(file.replace(server_info["path"] + "/", ""))
|
||||||
page_data["exclusions"] = exclusions
|
page_data["exclusions"] = exclusions
|
||||||
|
|
||||||
if not EnumPermissionsServer.BACKUP in page_data["user_permissions"]:
|
if EnumPermissionsServer.BACKUP not in page_data["user_permissions"]:
|
||||||
if not superuser:
|
if not superuser:
|
||||||
self.redirect("/panel/error?error=Unauthorized access To Schedules")
|
self.redirect(SCHEDULE_AUTH_ERROR_URL)
|
||||||
return
|
return
|
||||||
template = "panel/server_backup_edit.html"
|
template = "panel/server_backup_edit.html"
|
||||||
|
|
||||||
@ -1374,9 +1376,9 @@ class PanelHandler(BaseHandler):
|
|||||||
)
|
)
|
||||||
page_data["exclusions"] = []
|
page_data["exclusions"] = []
|
||||||
|
|
||||||
if not EnumPermissionsServer.BACKUP in page_data["user_permissions"]:
|
if EnumPermissionsServer.BACKUP not in page_data["user_permissions"]:
|
||||||
if not superuser:
|
if not superuser:
|
||||||
self.redirect("/panel/error?error=Unauthorized access To Schedules")
|
self.redirect(SCHEDULE_AUTH_ERROR_URL)
|
||||||
return
|
return
|
||||||
template = "panel/server_backup_edit.html"
|
template = "panel/server_backup_edit.html"
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ BASIC_BACKUP_PATCH_SCHEMA = {
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"minProperties": 1,
|
"minProperties": 1,
|
||||||
}
|
}
|
||||||
|
ID_MISMATCH = "Server ID backup server ID different"
|
||||||
|
GENERAL_AUTH_ERROR = "Authorization Error"
|
||||||
|
|
||||||
|
|
||||||
class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
||||||
@ -69,7 +71,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "ID_MISMATCH",
|
"error": "ID_MISMATCH",
|
||||||
"error_data": "Server ID backup server ID different",
|
"error_data": ID_MISMATCH,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
server_permissions = self.controller.server_perms.get_permissions(mask)
|
server_permissions = self.controller.server_perms.get_permissions(mask)
|
||||||
@ -80,7 +82,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "NOT_AUTHORIZED",
|
"error": "NOT_AUTHORIZED",
|
||||||
"error_data": "Authorization Error",
|
"error_data": GENERAL_AUTH_ERROR,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.finish_json(200, backup_conf)
|
self.finish_json(200, backup_conf)
|
||||||
@ -94,7 +96,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "ID_MISMATCH",
|
"error": "ID_MISMATCH",
|
||||||
"error_data": "Server ID backup server ID different",
|
"error_data": ID_MISMATCH,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if not auth_data:
|
if not auth_data:
|
||||||
@ -113,7 +115,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "NOT_AUTHORIZED",
|
"error": "NOT_AUTHORIZED",
|
||||||
"error_data": "Authorization Error",
|
"error_data": GENERAL_AUTH_ERROR,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -155,7 +157,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "NOT_AUTHORIZED",
|
"error": "NOT_AUTHORIZED",
|
||||||
"error_data": "Authorization Error",
|
"error_data": GENERAL_AUTH_ERROR,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
backup_config = self.controller.management.get_backup_config(backup_id)
|
backup_config = self.controller.management.get_backup_config(backup_id)
|
||||||
@ -165,7 +167,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "ID_MISMATCH",
|
"error": "ID_MISMATCH",
|
||||||
"error_data": "Server ID backup server ID different",
|
"error_data": ID_MISMATCH,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -329,7 +331,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "NOT_AUTHORIZED",
|
"error": "NOT_AUTHORIZED",
|
||||||
"error_data": "Authorization Error",
|
"error_data": GENERAL_AUTH_ERROR,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if backup_conf["server_id"]["server_id"] != server_id:
|
if backup_conf["server_id"]["server_id"] != server_id:
|
||||||
@ -338,7 +340,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "ID_MISMATCH",
|
"error": "ID_MISMATCH",
|
||||||
"error_data": "Server ID backup server ID different",
|
"error_data": ID_MISMATCH,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
mask = self.controller.server_perms.get_lowest_api_perm_mask(
|
mask = self.controller.server_perms.get_lowest_api_perm_mask(
|
||||||
@ -355,7 +357,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "NOT_AUTHORIZED",
|
"error": "NOT_AUTHORIZED",
|
||||||
"error_data": "Authorization Error",
|
"error_data": GENERAL_AUTH_ERROR,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
self.controller.management.update_backup_config(backup_id, data)
|
self.controller.management.update_backup_config(backup_id, data)
|
||||||
@ -372,7 +374,7 @@ class ApiServersServerBackupsBackupFilesIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "ID_MISMATCH",
|
"error": "ID_MISMATCH",
|
||||||
"error_data": "Server ID backup server ID different",
|
"error_data": ID_MISMATCH,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if not auth_data:
|
if not auth_data:
|
||||||
@ -391,7 +393,7 @@ class ApiServersServerBackupsBackupFilesIndexHandler(BaseApiHandler):
|
|||||||
{
|
{
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"error": "NOT_AUTHORIZED",
|
"error": "NOT_AUTHORIZED",
|
||||||
"error_data": "Authorization Error",
|
"error_data": GENERAL_AUTH_ERROR,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -278,3 +278,7 @@ div.warnings div.wssError a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
|
|
||||||
|
.hidden-input {
|
||||||
|
margin-left: -40px;
|
||||||
|
}
|
@ -65,7 +65,7 @@
|
|||||||
{% if len(data['backups']) > 0 %}
|
{% if len(data['backups']) > 0 %}
|
||||||
<div class="d-none d-lg-block">
|
<div class="d-none d-lg-block">
|
||||||
<table class="table table-hover responsive-table" aria-label="backups list" id="backup_table"
|
<table class="table table-hover responsive-table" aria-label="backups list" id="backup_table"
|
||||||
width="100%" style="table-layout:fixed;">
|
style="table-layout:fixed;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="rounded">
|
<tr class="rounded">
|
||||||
<th scope="col" style="width: 15%; min-width: 10px;">{{ translate('serverBackups', 'name',
|
<th scope="col" style="width: 15%; min-width: 10px;">{{ translate('serverBackups', 'name',
|
||||||
@ -130,7 +130,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="d-block d-lg-none">
|
<div class="d-block d-lg-none">
|
||||||
<table aria-label="backups list" class="table table-hover responsive-table" id="backup_table_mini"
|
<table aria-label="backups list" class="table table-hover responsive-table" id="backup_table_mini"
|
||||||
width="100%" style="table-layout:fixed;">
|
style="table-layout:fixed;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="rounded">
|
<tr class="rounded">
|
||||||
<th style="width: 40%; min-width: 10px;">Name
|
<th style="width: 40%; min-width: 10px;">Name
|
||||||
|
@ -96,58 +96,61 @@
|
|||||||
placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}">
|
placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="compress" class="form-check-label ml-4 mb-4"></label>
|
<div class="custom-control custom-switch">
|
||||||
{% if data['backup_config']['compress'] %}
|
{% if data['backup_config']['compress'] %}
|
||||||
<input type="checkbox" class="form-check-input" id="compress" name="compress" checked=""
|
<input type="checkbox" class="custom-control-input" id="compress" name="compress" checked=""
|
||||||
value="True">{{ translate('serverBackups', 'compress', data['lang']) }}
|
value="True">
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="checkbox" class="form-check-input" id="compress" name="compress" value="True">{{
|
<input type="checkbox" class="custom-control-input" id="compress" name="compress" value="True">
|
||||||
translate('serverBackups', 'compress', data['lang']) }}
|
|
||||||
{% end %}
|
{% end %}
|
||||||
|
<label for="compress" class="custom-control-label">{{ translate('serverBackups', 'compress',
|
||||||
|
data['lang']) }}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="shutdown" class="form-check-label ml-4 mb-4"></label>
|
<div class="custom-control custom-switch">
|
||||||
{% if data['backup_config']['shutdown'] %}
|
{% if data['backup_config']['shutdown']%}
|
||||||
<input type="checkbox" class="form-check-input" id="shutdown" name="shutdown" checked=""
|
<input type="checkbox" class="custom-control-input" id="shutdown" name="shutdown" checked=""
|
||||||
value="True">{{ translate('serverBackups', 'shutdown', data['lang']) }}
|
value="True">
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="checkbox" class="form-check-input" id="shutdown" name="shutdown" value="True">{{
|
<input type="checkbox" class="custom-control-input" id="shutdown" name="shutdown" value="True">
|
||||||
translate('serverBackups', 'shutdown', data['lang']) }}
|
|
||||||
{% end %}
|
{% end %}
|
||||||
|
<label for="shutdown" class="custom-control-label">{{ translate('serverBackups', 'shutdown',
|
||||||
|
data['lang']) }}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="command-check" class="form-check-label ml-4 mb-4"></label>
|
<div class="custom-control custom-switch">
|
||||||
{% if data['backup_config']['before'] %}
|
{% if data['backup_config']['before'] %}
|
||||||
<input type="checkbox" class="form-check-input" id="before-check" name="before-check" checked>{{
|
<input type="checkbox" class="custom-control-input" id="before-check" name="before-check" checked>
|
||||||
translate('serverBackups', 'before', data['lang']) }}
|
<input type="text" class="form-control hidden-input" name="before" id="backup_before"
|
||||||
<br>
|
|
||||||
<input type="text" class="form-control" name="before" id="backup_before"
|
|
||||||
value="{{ data['backup_config']['before'] }}" placeholder="We enter the / for you"
|
value="{{ data['backup_config']['before'] }}" placeholder="We enter the / for you"
|
||||||
style="display: inline-block;">
|
style="display: inline-block;">
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="checkbox" class="form-check-input" id="before-check" name="before-check">{{
|
<input type="checkbox" class="custom-control-input" id="before-check" name="before-check">
|
||||||
translate('serverBackups', 'before', data['lang']) }}
|
<input type="text" class="form-control hidden-input" name="before" id="backup_before" value=""
|
||||||
<br>
|
|
||||||
<input type="text" class="form-control" name="before" id="backup_before" value=""
|
|
||||||
placeholder="We enter the / for you." style="display: none;">
|
placeholder="We enter the / for you." style="display: none;">
|
||||||
{% end %}
|
{% end %}
|
||||||
|
<label for="before-check" class="custom-control-label">{{
|
||||||
|
translate('serverBackups', 'before', data['lang']) }}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="command-check" class="form-check-label ml-4 mb-4"></label>
|
<div class="custom-control custom-switch">
|
||||||
{% if data['backup_config']['after'] %}
|
{% if data['backup_config']['after'] %}
|
||||||
<input type="checkbox" class="form-check-input" id="after-check" name="after-check" checked>{{
|
<input type="checkbox" class="custom-control-input" id="after-check" name="after-check" checked>
|
||||||
translate('serverBackups', 'after', data['lang']) }}
|
<input type="text" class="form-control hidden-input" name="after" id="backup_after"
|
||||||
<br>
|
|
||||||
<input type="text" class="form-control" name="after" id="backup_after"
|
|
||||||
value="{{ data['backup_config']['after'] }}" placeholder="We enter the / for you"
|
value="{{ data['backup_config']['after'] }}" placeholder="We enter the / for you"
|
||||||
style="display: inline-block;">
|
style="display: inline-block;">
|
||||||
{% else %}
|
|
||||||
<input type="checkbox" class="form-check-input" id="after-check" name="after-check">{{
|
|
||||||
translate('serverBackups', 'after', data['lang']) }}
|
|
||||||
<br>
|
<br>
|
||||||
<input type="text" class="form-control" name="after" id="backup_after" value=""
|
{% else %}
|
||||||
|
<input type="checkbox" class="custom-control-input" id="after-check" name="after-check">
|
||||||
|
<input type="text" class="form-control hidden-input" name="after" id="backup_after" value=""
|
||||||
placeholder="We enter the / for you." style="display: none;">
|
placeholder="We enter the / for you." style="display: none;">
|
||||||
{% end %}
|
{% end %}
|
||||||
|
<label for="after-check" class="custom-control-label">{{
|
||||||
|
translate('serverBackups', 'after', data['lang']) }}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="server">{{ translate('serverBackups', 'exclusionsTitle', data['lang']) }} <small> - {{
|
<label for="server">{{ translate('serverBackups', 'exclusionsTitle', data['lang']) }} <small> - {{
|
||||||
@ -157,9 +160,8 @@
|
|||||||
data-server_path="{{ data['server_stats']['server_id']['path']}}" type="button">{{
|
data-server_path="{{ data['server_stats']['server_id']['path']}}" type="button">{{
|
||||||
translate('serverBackups', 'clickExclude', data['lang']) }}</button>
|
translate('serverBackups', 'clickExclude', data['lang']) }}</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal fade" id="dir_select" tabindex="-1" role="dialog" aria-labelledby="dir_select"
|
<div class="modal fade" id="dir_select" tabindex="-1" aria-labelledby="dir_select" aria-hidden="true">
|
||||||
aria-hidden="true">
|
<div class="modal-dialog">
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="exampleModalLongTitle">{{ translate('serverBackups',
|
<h5 class="modal-title" id="exampleModalLongTitle">{{ translate('serverBackups',
|
||||||
@ -205,9 +207,9 @@
|
|||||||
<h4 class="card-title">{{ translate('serverBackups', 'currentBackups', data['lang']) }}</h4>
|
<h4 class="card-title">{{ translate('serverBackups', 'currentBackups', data['lang']) }}</h4>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="10%">{{ translate('serverBackups', 'options', data['lang']) }}</th>
|
<th>{{ translate('serverBackups', 'options', data['lang']) }}</th>
|
||||||
<th>{{ translate('serverBackups', 'path', data['lang']) }}</th>
|
<th>{{ translate('serverBackups', 'path', data['lang']) }}</th>
|
||||||
<th width="20%">{{ translate('serverBackups', 'size', data['lang']) }}</th>
|
<th>{{ translate('serverBackups', 'size', data['lang']) }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
Loading…
Reference in New Issue
Block a user