Merge branch 'dev' into bugfix/backup-migration-dupe

This commit is contained in:
Zedifus 2025-01-19 19:51:33 +00:00
commit d62ecef2dc
69 changed files with 33583 additions and 3217 deletions

View File

@ -5,9 +5,14 @@ TBD
### Refactor
- Refactor and standardize all JSON validator errors returning human readable translations ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/786))
- Improve docker-build CI/CD, supporting nightly builds ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/813))
- Standardize and centralize CSS throughout front end, Allows for easier management of themes ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/726))
### Bug fixes
- Bump requests to resolve yank for CVE-2024-35195 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/808))
- Better handle malformed mcping data ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/799))
- Resolves type issue when posting no keywords in the "keyword" field in config.json tab ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/819))
### Tweaks
- Dyamically change child action translation for backups ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/806))
- Remove EXIF image data on app Background Photos ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/805))
- Bump Docker base image `22.04` -> `24.04` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/812))
- Bump python pip `2.0.3` -> `24.3.1` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/812))
- Bump python setuptools `50.3.2` -> `75.6.0` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/812))

View File

@ -77,8 +77,8 @@ class Server:
class Players(list):
def __init__(self, data):
super().__init__(Player(x) for x in data.get("sample", []))
self.max = data["max"]
self.online = data["online"]
self.max = data.get("max", 0)
self.online = data.get("online", 0)
def report(self):
players = []
@ -93,8 +93,8 @@ class Players(list):
class Player:
def __init__(self, data):
self.id = data["id"]
self.name = data["name"]
self.id = data.get("id", "")
self.name = data("name", "Anonymous")
def __str__(self):
return self.name
@ -174,7 +174,7 @@ def ping(ip, port):
logger.debug(f"Server reports this data on ping: {data}")
try:
return Server(json.loads(data))
except KeyError:
except (KeyError, json.decoder.JSONDecodeError):
return {}
finally:
sock.close()

View File

@ -85,6 +85,8 @@ class Helpers:
self.crafty_starting = False
self.minimum_password_length = 8
self.theme_list = self.load_themes()
@staticmethod
def auto_installer_fix(ex):
logger.critical(f"Import Error: Unable to load {ex.name} module", exc_info=True)
@ -595,9 +597,20 @@ class Helpers:
)
return False
@staticmethod
def get_themes():
return ["default", "dark", "light", "ronald"]
def load_themes(self):
theme_list = []
themes_path = os.path.join(self.webroot, "static", "assets", "css", "themes")
theme_files = [
file
for file in os.listdir(themes_path)
if os.path.isfile(os.path.join(themes_path, file))
]
for theme in theme_files:
theme_list.append(theme.split(".css")[0])
return theme_list
def get_themes(self):
return self.theme_list
@staticmethod
def get_local_ip():
@ -1198,8 +1211,8 @@ class Helpers:
\n<div id="{dpath}" data-path="{dpath}" data-name="{filename}" class="tree-caret tree-ctx-item tree-folder">
<input type="radio" name="root_path" value="{dpath}">
<span id="{dpath}span" class="files-tree-title" data-path="{dpath}" data-name="{filename}" onclick="getDirView(event)">
<i style="color: var(--info);" class="far fa-folder"></i>
<i style="color: var(--info);" class="far fa-folder-open"></i>
<i class="text-info far fa-folder"></i>
<i class="text-info far fa-folder-open"></i>
{filename}
</span>
</input></div><li>
@ -1220,8 +1233,8 @@ class Helpers:
\n<div id="{dpath}" data-path="{dpath}" data-name="{filename}" class="tree-caret tree-ctx-item tree-folder">
<input type="radio" name="root_path" value="{dpath}">
<span id="{dpath}span" class="files-tree-title" data-path="{dpath}" data-name="{filename}" onclick="getDirView(event)">
<i style="color: var(--info);" class="far fa-folder"></i>
<i style="color: var(--info);" class="far fa-folder-open"></i>
<i class="text-info far fa-folder"></i>
<i class="text-info far fa-folder-open"></i>
{filename}
</span>
</input></div><li>"""

View File

@ -23,9 +23,9 @@ class Translation:
def translate(self, page, word, language, error=True):
fallback_language = "en_EN"
translated_word = self.translate_inner(page, word, language)
translated_word = self.translate_inner(page, word, language, error)
if translated_word is None:
translated_word = self.translate_inner(page, word, fallback_language)
translated_word = self.translate_inner(page, word, fallback_language, error)
if translated_word:
if isinstance(translated_word, dict):
@ -41,7 +41,7 @@ class Translation:
return "Error while getting translation"
return word
def translate_inner(self, page, word, language) -> t.Union[t.Any, None]:
def translate_inner(self, page, word, language, error) -> t.Union[t.Any, None]:
language_file = self.get_language_file(language)
try:
if not self.cached_translation:
@ -59,6 +59,7 @@ class Translation:
try:
translated_page = data[page]
except KeyError:
if error:
logger.error(
f"Translation File Error: page {page} "
f"does not exist for lang {language}"
@ -73,6 +74,7 @@ class Translation:
translated_word = translated_page[word]
return translated_word
except KeyError:
if error:
logger.error(
f"Translation File Error: word {word} does not exist on page "
f"{page} for lang {language}"
@ -84,6 +86,7 @@ class Translation:
return None
except Exception as e:
if error:
logger.critical(
f"Translation File Error: Unable to read {language_file} due to {e}"
)

View File

@ -43,6 +43,8 @@ SUBPAGE_PERMS = {
SCHEDULE_AUTH_ERROR_URL = "/panel/error?error=Unauthorized access To Schedules"
HUMANIZED_INDEX_FILE = "humanized_index.json"
class PanelHandler(BaseHandler):
def get_user_roles(self) -> t.Dict[str, list]:
@ -359,6 +361,7 @@ class PanelHandler(BaseHandler):
else None
),
"superuser": superuser,
"themes": self.helper.get_themes(),
}
try:
page_data["hosts_data"]["disk_json"] = json.loads(
@ -879,7 +882,7 @@ class PanelHandler(BaseHandler):
os.path.join(self.helper.root_dir, "app", "translations")
)
):
if file == "humanized_index.json":
if file == HUMANIZED_INDEX_FILE:
continue
if file.endswith(".json"):
if file.split(".")[0] not in self.helper.get_setting(
@ -977,7 +980,7 @@ class PanelHandler(BaseHandler):
for file in sorted(
os.listdir(os.path.join(self.helper.root_dir, "app", "translations"))
):
if file == "humanized_index.json":
if file == HUMANIZED_INDEX_FILE:
continue
if file.endswith(".json"):
if file.split(".")[0] not in self.helper.get_setting(
@ -1436,7 +1439,7 @@ class PanelHandler(BaseHandler):
for file in sorted(
os.listdir(os.path.join(self.helper.root_dir, "app", "translations"))
):
if file == "humanized_index.json":
if file == HUMANIZED_INDEX_FILE:
continue
if file.endswith(".json"):
if file.split(".")[0] not in self.helper.get_setting(

View File

@ -45,6 +45,7 @@ class PublicHandler(BaseHandler):
"query": "",
"background": self.controller.cached_login,
"login_opacity": self.controller.management.get_login_opacity(),
"themes": self.helper.get_themes(),
}
if self.request.query:

View File

@ -1,6 +1,7 @@
import os
import logging
import shutil
from PIL import Image
from app.classes.models.server_permissions import EnumPermissionsServer
from app.classes.shared.helpers import Helpers
from app.classes.web.base_api_handler import BaseApiHandler
@ -295,6 +296,21 @@ class ApiFilesUploadHandler(BaseApiHandler):
with open(chunk_file, "rb") as infile:
outfile.write(infile.read())
os.remove(chunk_file)
if upload_type == "background":
# Strip EXIF data
image_path = os.path.join(file_path)
logger.debug("Stripping exif data from image")
image = Image.open(image_path)
# Get current raw pixel data from image
image_data = list(image.getdata())
# Create new image
image_no_exif = Image.new(image.mode, image.size)
# Restore pixel data
image_no_exif.putdata(image_data)
image_no_exif.save(image_path)
logger.info(
f"File upload completed. Filename: {self.filename}"
f" Path: {file_path} Type: {u_type}"

View File

@ -130,6 +130,7 @@ class ServerHandler(BaseHandler):
else None
),
"superuser": superuser,
"themes": self.helper.get_themes(),
}
if superuser:

View File

@ -12,6 +12,7 @@ class StatusHandler(BaseHandler):
"lang": self.helper.get_setting("language"),
"lang_page": self.helper.get_lang_page(self.helper.get_setting("language")),
"servers": self.controller.servers.get_all_servers_stats(),
"themes": self.helper.get_themes(),
}
running = 0
for srv in page_data["servers"]:

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,8 @@
height: 1.5rem;
width: 3rem;
border-radius: 1.5rem;
color: #6b7381;
background: #bdc1c8;
color: var(--gray);
background: var(--select-bg);
}
.btn-toggle:focus,
@ -52,7 +52,7 @@
width: 1.125rem;
height: 1.125rem;
border-radius: 1.125rem;
background: #fff;
background: var(--white);
transition: left 0.25s;
}
@ -76,7 +76,7 @@
.btn-toggle.btn-sm:before,
.btn-toggle.btn-sm:after {
line-height: -0.5rem;
color: #fff;
color: var(--white);
letter-spacing: 0.75px;
left: 0.4125rem;
width: 2.325rem;
@ -106,11 +106,11 @@
.btn-toggle:before,
.btn-toggle:after {
color: #6b7381;
color: var(--gray);
}
.btn-toggle.active {
background-color: #29b5a8;
background-color: var(--success);
}
.btn-toggle.btn-lg {
@ -162,7 +162,7 @@
width: 1.875rem;
height: 1.875rem;
border-radius: 1.875rem;
background: #fff;
background: var(--white);
transition: left 0.25s;
}
@ -186,7 +186,7 @@
.btn-toggle.btn-lg.btn-sm:before,
.btn-toggle.btn-lg.btn-sm:after {
line-height: 0.5rem;
color: #fff;
color: var(--white);
letter-spacing: 0.75px;
left: 0.6875rem;
width: 3.875rem;
@ -423,7 +423,7 @@
.btn-toggle.btn-info:before,
.btn-toggle.btn-info:after {
color: #6b7381;
color: var(--gray);
}
.btn-toggle.btn-info.active {
@ -431,17 +431,17 @@
}
.btn-toggle.btn-secondary {
color: #6b7381;
background: #bdc1c8;
color: var(--gray);
background: var(--select-bg);
}
.btn-toggle.btn-secondary:before,
.btn-toggle.btn-secondary:after {
color: #6b7381;
color: var(--gray);
}
.btn-toggle.btn-secondary.active {
background-color: #ff8300;
background-color: var(--warning);
}
/**************************************************************/

View File

@ -1,3 +1,97 @@
/**************************************************************/
/* CSS From base.html */
/**************************************************************/
body:not(.sidebar-icon-only) .navbar-toggler .mdi-chevron-double-right {
display: none;
}
body.sidebar-icon-only .navbar-toggler .mdi-chevron-double-left {
display: none;
}
/**************************************************************/
/**************************************************************/
/* CSS as bootstrap extensions */
/**************************************************************/
.overflow-x-auto {
overflow-x: auto;
}
.overflow-y-auto {
overflow-y: auto;
}
.overflow-scroll {
overflow: scroll;
}
.text-none {
text-transform: none;
}
.vw-40 {
width: 40vw !important;
}
.vh-40 {
height: 40vh !important;
}
.mw-25 {
max-width: 25% !important;
}
.mw-50 {
max-width: 50% !important;
}
.mw-75 {
max-width: 75% !important;
}
.mw-80 {
max-width: 80% !important;
}
.mh-25 {
max-height: 25% !important;
}
.mh-50 {
max-height: 50% !important;
}
.mh-75 {
max-height: 75% !important;
}
.mh-80 {
max-height: 80% !important;
}
/**************************************************************/
/**************************************************************/
/* CSS for MainMenu in partials/_sidebar.html */
/**************************************************************/
@media screen and (max-width: 991px) {
.sidebar-offcanvas {
-webkit-transition: all 0.25s cubic-bezier(.22, .61, .36, 1);
transition: all 0.25s cubic-bezier(.22, .61, .36, 1);
box-shadow: 0px 8px 17px 2px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12), 0px 5px 5px -3px rgba(0, 0, 0, 0.2);
}
}
li.nav-item.nav-category {
margin-top: 10px;
}
/**************************************************************/
/**************************************************************/
/* CSS For ? */
/**************************************************************/
.select-css option {
background-color: var(--deep-bg);
color: var(--base-text)
@ -93,11 +187,11 @@ td::-webkit-scrollbar {
}
.mc-log-error {
color: #af463f;
color: var(--danger);
}
.mc-log-fatal {
color: #da0f00;
color: var(--red);
}
.mc-log-keyword {
@ -118,16 +212,6 @@ body {
/* Firefox */
}
/* Webkit */
/* Didn't really work out
::-webkit-scrollbar { background-color: #202538; }
::-webkit-scrollbar-button { background-color: #1D212F; }
::-webkit-scrollbar-thumb { background-color: #777A86; }
::-webkit-scrollbar-thumb:hover { background-color: #646773; }
::-webkit-scrollbar-track { background-color: #202538; }
::-webkit-scrollbar-corner { background-color: #202538; }*/
.actions_serverlist>a>i {
cursor: pointer;
}
@ -151,7 +235,52 @@ body {
}
/**************************************************************/
/* CSS for Froms Displays */
/**************************************************************/
/* CSS for Dashboard */
/**************************************************************/
#desc_id {
-ms-overflow-style: none;
/* for Internet Explorer, Edge */
scrollbar-width: none;
/* for Firefox */
overflow-y: scroll;
}
#desc_id::-webkit-scrollbar {
display: none;
/* for Chrome, Safari, and Opera */
}
.gray {
color: var(--gray) !important;
}
.disk-usage {
height: 20px;
width: 100%;
background-color: rgb(139, 139, 139) !important
}
.disk-usage>.progress-bar {
color: black;
height: 100%;
}
.server-desc {
overflow-wrap: break-word !important;
max-width: 85px !important;
overflow: scroll;
}
.server-alert {
color: var(--red) !important;
}
/**************************************************************/
/**************************************************************/
/* CSS for Forms Displays */
/**************************************************************/
div>.input-group>.custom-file-input {
position: relative !important;
@ -196,6 +325,7 @@ div>.input-group>.form-control {
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
overflow: scroll;
}
.no-scroll::-webkit-scrollbar {
@ -219,7 +349,11 @@ div>.input-group>.form-control {
}
.custom-switch .custom-control-label::after {
top: calc(-0.125rem + 1px);
top: calc(-0.175rem);
}
.custom-radio .custom-control-label::after {
top: calc(-0.175rem);
}
a.btn-primary {
@ -235,7 +369,11 @@ button.btn-primary {
/**************************************************************/
/* CSS for Tables Displays */
/**************************************************************/
td>ul {
table.table {
overflow: scroll;
}
div td>ul {
margin: auto;
}
@ -268,6 +406,12 @@ div.warnings div.wssError a:hover {
color: var(--white-smoke);
}
noscript.noscript-warning {
padding: 20px;
background-color: rgb(247, 151, 15);
/* TODO change background color */
}
/**************************************************************/
/**************************************************************/
@ -278,6 +422,99 @@ div.warnings div.wssError a:hover {
}
/**************************************************************/
/**************************************************************/
/* CSS for Annoucements Displays */
/**************************************************************/
.annoucement-item>p {
float: right;
}
.annoucement-title {
color: var(--info);
}
.annoucement-item:hover>a .annoucement-title {
color: var(--purple);
}
div.support_progress {
height: 15px;
width: 100%;
}
/**************************************************************/
/**************************************************************/
/* CSS for API Keys Displays */
/**************************************************************/
.api-key {
white-space: pre-wrap;
color: white;
word-break: break-all;
background: grey;
border-radius: 5px;
}
/**************************************************************/
/**************************************************************/
/* CSS for Virtual Console Displays */
/**************************************************************/
.virt_console {
width: 100%;
font-size: .8em;
padding: 5px 10px;
border: 1px solid var(--outline);
background-color: var(--card-banner-bg);
height: 500px;
overflow: scroll;
}
/**************************************************************/
/**************************************************************/
/* CSS for Lists Displays */
/**************************************************************/
ul>li.list-group-item {
background-color: var(--card-banner-bg);
}
ul>li.list-group-item i {
margin: 0;
}
/**************************************************************/
/**************************************************************/
/* CSS for Card Displays */
/**************************************************************/
.card .card-header.header-sm {
padding: 1rem 1.81rem;
height: auto;
}
/**************************************************************/
/**************************************************************/
/* CSS for ? */
/**************************************************************/
div.form-group.reset-secret {
background: rgba(243, 21, 6, 0.3);
outline: 1px solid red;
padding: 10px;
}
.bg-dropdown {
background-color: var(--dropdown-bg);
}
.hidden-input {
margin-left: -40px;
}
/**************************************************************/

View File

@ -11,222 +11,6 @@
*/
@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500,700");
root,
:root.default {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: black;
--select-bg: #dee0f4;
--ram-bg: #323550;
--base-text: #b9c0d3;
--outline: #383e5d;
--card-banner-bg: #282a40;
--deep-bg: #1C1E2F;
--dropdown-bg: #222437;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #2196f3;
--secondary: #dde4eb;
--success: #19d895;
--info: #8862e0;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
:root.anti-lockout {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: rgb(215, 82, 0);
--select-bg: #b8772c;
--ram-bg: #4d4d4e;
--base-text: white;
--outline: #c73929;
--card-banner-bg: #de7c26;
--deep-bg: #912f2f;
--dropdown-bg: #c83b3b;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #dbc900;
--secondary: #dde4eb;
--success: #adff84;
--info: #dbc900;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
:root.light {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: white;
--select-bg: #dee0f4;
--ram-bg: #4d4d4e;
--base-text: black;
--outline: #383e5d;
--card-banner-bg: #e0e0e0;
--deep-bg: #F5F5F5;
--dropdown-bg: #d8d8d8;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #2196f3;
--secondary: #dde4eb;
--success: #449c4b;
--info: #8862e0;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
:root.dark {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: black;
--select-bg: #dee0f4;
--ram-bg: #3d3d3d;
--base-text: #b9c0d3;
--outline: #3f3f3f;
--card-banner-bg: #212221;
--deep-bg: #0d0d0d;
--dropdown-bg: #171717;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #2196f3;
--secondary: #dde4eb;
--success: #19d895;
--info: #8862e0;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
:root.ronald {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: white;
--select-bg: #dee0f4;
--card-banner-bg: white;
--deep-bg: yellow;
--dropdown-bg: red;
--ram-bg: #4d4d4e;
--base-text: black;
--outline: #383e5d;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #2196f3;
--secondary: #dde4eb;
--success: #19d895;
--info: #8862e0;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
*,
*::before,
*::after {

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,42 @@
:root.anti-lockout {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: rgb(215, 82, 0);
--select-bg: #b8772c;
--ram-bg: #4d4d4e;
--base-text: white;
--outline: #c73929;
--card-banner-bg: #de7c26;
--deep-bg: #912f2f;
--dropdown-bg: #c83b3b;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #dbc900;
--secondary: #dde4eb;
--success: #adff84;
--info: #dbc900;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

View File

@ -0,0 +1,33 @@
:root {
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: var(--red);
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: var(--teal);
--cyan: var(--cyan);
--white: var(--white);
--white-smoke: var(--white-smoke);
--gray: var(--gray);
--gray-dark: #292b2c;
--gray-light: #8ba2b5;
--gray-lightest: var(--gray-lightest);
--primary: var(--primary);
--secondary: var(--secondary);
--success: var(--success);
--info: var(--info);
--warning: var(--warning);
--danger: var(--danger);
--light: var(--light);
--dark: var(--dark);
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

View File

@ -0,0 +1,39 @@
/* Remove default bullets */
.tree-view,
.tree-nested {
list-style-type: none;
margin: 0;
padding: 0;
margin-left: 10px;
}
/* Style the items */
.tree-item,
.files-tree-title {
cursor: pointer;
user-select: none;
/* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder {
display: inline-block;
}
.tree-caret .fa-folder-open {
display: none;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down .fa-folder {
display: none;
}
.tree-caret-down .fa-folder-open {
display: inline-block;
}
/* Hide the nested list */
.tree-nested {
display: none;
}

View File

@ -0,0 +1,143 @@
/* Overlay (right click menu) */
.overlay {
display: none;
flex-direction: column;
background-color: var(--base-bg);
border-radius: 10px;
box-shadow: 0 10px 20px rgb(64 64 64 / 5%);
padding: 10px 0;
z-index: 10000;
overflow: scroll;
/* IE and Edge */
-ms-overflow-style: none;
/* Firefox */
scrollbar-width: none;
}
.overlay::-webkit-scrollbar {
display: none;
}
/* Position the content inside the overlay */
.overlay-content {
display: flex;
flex-direction: column;
background-color: var(--base-bg);
border-radius: 10px;
box-shadow: 0 10px 20px rgb(64 64 64 / 5%);
padding: 10px 0;
}
.overlay-title {
color: var(--info);
text-align: center;
padding: 3px;
}
/* The navigation links inside the overlay */
.overlay a {
font: inherit;
border: 0;
padding: 10px 30px 10px 15px;
width: 100%;
display: flex;
align-items: center;
position: relative;
text-decoration: unset;
color: var(--black);
font-weight: 500;
transition: 0.5s linear;
-webkit-transition: 0.5s linear;
-moz-transition: 0.5s linear;
-ms-transition: 0.5s linear;
-o-transition: 0.5s linear;
}
/* When you mouse over the navigation links, change their color */
.overlay a:hover,
.overlay a:focus {
background: var(--ram-bg);
color: var(--info);
}
/* Position the close button (top right corner) */
.overlay .closebtn .closebtn:hover {
background-color: var(--red);
color: var(--red);
z-index: 10000;
}
/* When the height of the screen is less than 450 pixels, change the font-size of the links and position the close button again, so they don't overlap */
@media screen and (max-height: 450px) {
.overlay a {
font-size: 20px;
}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 35px;
}
}
.tree-file:hover {
cursor: pointer;
}
/* Remove default bullets */
.tree-view,
.tree-nested {
list-style-type: none;
margin: 0;
padding: 0;
margin-left: 10px;
}
/* Style the items */
.tree-item,
.files-tree-title {
cursor: pointer;
user-select: none;
/* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder {
display: inline-block;
}
.tree-caret .fa-folder-open {
display: none;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down .fa-folder {
display: none;
}
.tree-caret-down .fa-folder-open {
display: inline-block;
}
/* Hide the nested list */
.tree-nested {
display: none;
}
html,
body,
body>.container-scroller {
overflow: initial;
}
.editorManager {
top: 63px;
position: sticky;
}
span.separator {
width: 90%;
border-bottom: 2px solid var(--black);
margin: 0 auto;
}

View File

@ -0,0 +1,36 @@
/**************************************************************/
/* CSS for Page Footer */
/**************************************************************/
a:hover {
text-decoration: none;
}
.blink-text {
color: var(--base-text);
font-weight: bold;
font-size: 2rem;
animation: blinkingText 2s infinite;
}
@keyframes blinkingText {
0% {
color: var(--base-text);
}
50% {
color: var(--red);
}
100% {
color: var(--base-text);
}
}
#kofiframe {
border: none;
width: 100%;
padding: 4px;
background: var(--deep-bg);
}
/**************************************************************/

View File

@ -0,0 +1,44 @@
/**************************************************************/
/* CSS for the login page */
/**************************************************************/
.login-modal {
border-radius: 0.4rem !important;
box-shadow: 0 8px 12px 0 hsla(0, 0%, 0%, 0.2) !important;
}
.login-text-input {
border: none !important;
background-color: hsl(234, 30%, 45%);
color: var(--white) !important;
}
.login-text-input:hover,
.login-text-input:focus {
background-color: hsl(234, 30%, 39%) !important;
}
.login-input {
border-radius: 0.4rem !important;
box-shadow: 0 8px 12px 0 hsla(0, 0%, 0%, 0.2);
transition: all 0.3s ease-in-out;
}
.login-input:hover,
.login-input:focus {
box-shadow: 0 12px 16px 0 hsla(0, 0%, 0%, 0.4);
}
#error-field {
color: var(--red);
text-align: center;
margin-bottom: 2rem;
}
.loginError {
color: var(--red);
text-align: center;
margin-bottom: 2rem;
}
/**************************************************************/

View File

@ -0,0 +1,59 @@
/**************************************************************/
/* CSS for Notifications */
/**************************************************************/
.notifications {
position: fixed;
width: 200px;
top: 70px;
right: 0px;
}
.notification {
position: relative;
margin-right: 1rem;
background: var(--card-banner-bg);
-webkit-transition: right 0.75s, opacity 0.75s, top 0.75s;
-moz-transition: right 0.75s, opacity 0.75s, top 0.75s;
-o-transition: right 0.75s, opacity 0.75s, top 0.75s;
transition: right 0.75s, opacity 0.75s, top 0.75s;
right: -20rem;
opacity: 0.1;
}
.toast-header {
background-color: var(--card-banner-bg);
color: var(--base-text);
}
.toast-body {
background-color: var(--dropdown-bg);
color: var(--base-text);
}
.notification img {
max-height: 20px;
}
.notification strong {
line-height: 20px;
}
.notification.active {
right: 0rem;
opacity: 1;
}
.notification.remove {
right: 0rem;
opacity: 0.1;
top: -2rem;
}
.notification span {
line-height: 20px;
font-size: 15px;
user-select: none;
cursor: pointer;
}
/**************************************************************/

View File

@ -0,0 +1,38 @@
#virt_console::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
#virt_console {
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;
white-space: pre-wrap;
width: 100%;
font-size: .8em;
padding: 5px 10px;
border: 1px solid var(--outline);
background-color: var(--card-banner-bg);
height: 500px;
overflow: scroll;
}
#to-bottom {
visibility: hidden;
float: right;
}
.term-btn {
max-width: 12rem;
white-space: nowrap;
}
div.server_command {
gap: 0.5rem;
}
input.server_command {
min-width: 10rem;
}

View File

@ -0,0 +1,108 @@
.api-alert {
position: absolute;
top: -5px;
left: 0;
font-size: 50px !important;
color: var(--white);
background: var(--blue);
/* rgb(0, 170, 170);*/
width: 100%;
height: 100%;
z-index: 100;
opacity: .95;
}
.api-alert p {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
text-align: center;
font-size: 20px;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
color: var(--white) !important;
}
.api-alert p>i,
.api-alert p>a {
color: var(--red);
}
button>i.refresh-class {
margin: 0px;
}
.refresh-class:hover {
cursor: grab;
}
.scroll {
max-height: 12em;
overflow-y: auto;
}
#overlay {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 100;
}
/* Remove default bullets */
.tree-view,
.tree-nested {
list-style-type: none;
margin: 0;
padding: 0;
margin-left: 10px;
}
/* Style the items */
.tree-item,
.files-tree-title {
cursor: pointer;
user-select: none;
/* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder {
display: inline-block;
}
.tree-caret .fa-folder-open {
display: none;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down .fa-folder {
display: none;
}
.tree-caret-down .fa-folder-open {
display: inline-block;
}
/* Hide the nested list */
.tree-nested {
display: none;
}
#op_logo {
position: relative;
top: 50%;
transform: translateY(-50%);
}
div>.input-group>.custom-file-input {
position: relative !important;
-webkit-box-flex: 1 !important;
-ms-flex: 1 1 auto !important;
flex: 1 1 auto !important;
width: 1% !important;
margin-bottom: 0 !important;
border: 1px solid var(--outline);
}

View File

@ -0,0 +1,43 @@
:root.dark {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: black;
--select-bg: #dee0f4;
--ram-bg: #3d3d3d;
--base-bg: #303030;
--base-text: #b9c0d3;
--outline: #3f3f3f;
--card-banner-bg: #212221;
--deep-bg: #0d0d0d;
--dropdown-bg: #171717;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #2196f3;
--secondary: #dde4eb;
--success: #19d895;
--info: #8862e0;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

View File

@ -0,0 +1,45 @@
root,
:root.default {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: black;
--base-bg: #dee0f4;
--select-bg: #dee0f4;
--ram-bg: #323550;
--base-text: #b9c0d3;
--outline: #383e5d;
--card-banner-bg: #282a40;
--deep-bg: #1C1E2F;
--dropdown-bg: #222437;
/*END THEME VARIATION*/
--black: black;
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #2196f3;
--secondary: #dde4eb;
--success: #19d895;
--info: #8862e0;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

View File

@ -0,0 +1,43 @@
:root.light {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: white;
--select-bg: #dee0f4;
--base-bg: #e6e6e6;
--ram-bg: #4d4d4e;
--base-text: black;
--outline: #383e5d;
--card-banner-bg: #e0e0e0;
--deep-bg: #F5F5F5;
--dropdown-bg: #d8d8d8;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #2196f3;
--secondary: #dde4eb;
--success: #449c4b;
--info: #8862e0;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

View File

@ -0,0 +1,42 @@
:root.ronald {
/*CHANGE THESE FOR THEMES*/
--tooltip-bg: white;
--select-bg: #dee0f4;
--card-banner-bg: white;
--deep-bg: yellow;
--dropdown-bg: red;
--ram-bg: #4d4d4e;
--base-text: black;
--outline: #383e5d;
/*END THEME VARIATION*/
--blue: #00aeef;
--indigo: #6610f2;
--purple: #ab8ce4;
--pink: #E91E63;
--red: #ff0017;
--orange: #fb9678;
--yellow: #ffd500;
--green: #3bd949;
--teal: #58d8a3;
--cyan: #57c7d4;
--white: #ffffff;
--white-smoke: #f3f5f6;
--gray: #6c757d;
--gray-light: #8ba2b5;
--gray-lightest: #f7f7f9;
--primary: #2196f3;
--secondary: #dde4eb;
--success: #19d895;
--info: #8862e0;
--warning: #ffaf00;
--danger: #ff6258;
--light: #fbfbfb;
--dark: #252C46;
--breakpoint-xs: 0;
--breakpoint-sm: 576px;
--breakpoint-md: 768px;
--breakpoint-lg: 992px;
--breakpoint-xl: 1200px;
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}

View File

@ -87,8 +87,8 @@ function process_tree_response(response, unzip) {
<div id="${dpath}" data-path="${dpath}" data-name="${filename}" class="tree-caret tree-ctx-item tree-folder">
<input type="radio" class="root-input" name="root_path" value="${dpath}">
<span id="${dpath}span" class="files-tree-title" data-path="${dpath}" data-name="${filename}" onclick="getDirView(event)">
<i style="color: var(--info);" class="far fa-folder"></i>
<i style="color: var(--info);" class="far fa-folder-open"></i>
<i class="far fa-folder text-info"></i>
<i class="far fa-folder-open text-info"></i>
${filename}
</span>
</input></div><li>`

View File

@ -137,7 +137,7 @@ async function uploadFile(type, file = null, path = null, file_num = 0, _onProgr
// All promises resolved successfully
$("#upload_input").html(`<div class="card-header header-sm d-flex justify-content-between align-items-center" style="width: 100%;"><input value="${file.name}" type="text" id="file-uploaded" disabled></input> 🔒</div>`);
if (type === "import") {
document.getElementById("lower_half").style.visibility = "visible";
document.getElementById("lower_half").classList.remove("d-none");
document.getElementById("lower_half").hidden = false;
} else if (type === "background") {
setTimeout(function () {

View File

@ -17,8 +17,14 @@
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Sarabun" media="screen">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.22/fh-3.1.7/r-2.2.6/sc-2.0.3/sp-1.2.2/datatables.min.css" />
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">
<link rel="stylesheet" href="/static/assets/css/internal/root.css">
<link rel="stylesheet" href="/static/assets/css/internal/anti-lockout.css">
<link rel="stylesheet" href="/static/assets/css/themes/default.css">
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<link rel="stylesheet" href="/static/assets/css/crafty-toggle-btn.css">
<link rel="stylesheet" href="/static/assets/css/partial/crafty-notification.css">
<link rel="manifest" href="/static/assets/crafty.webmanifest">
<meta name="mobile-web-app-capable" content="yes">
@ -37,12 +43,15 @@
<!-- End Plugin css for this page-->
<!-- Layout styles -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
{% for theme in data['themes'] %}
<link rel="stylesheet" href="/static/assets/css/themes/{{ theme }}.css">
{% end %}
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- End Layout styles -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- Alpine.js - The modern jQuery alternative -->
<script defer src="../static/assets/vendors/js/cdn.min.js"></script>
@ -69,21 +78,12 @@
<img src="/static/assets/images/logo_small.svg" alt="logo" /> </a>
</div>
<div class="navbar-menu-wrapper d-flex align-items-center">
<style>
body:not(.sidebar-icon-only) .navbar-toggler .mdi-chevron-double-right {
display: none;
}
body.sidebar-icon-only .navbar-toggler .mdi-chevron-double-left {
display: none;
}
</style>
<button class="navbar-toggler navbar-toggler align-self-center" type="button" data-toggle="minimize">
<span class="mdi mdi-chevron-double-left"></span>
<span class="mdi mdi-chevron-double-right"></span>
</button>
&nbsp;&nbsp;&nbsp;
<span class="badge-pill badge-outline-primary" id="server-name-nav" style="display: none;"></span>
<span class="badge-pill badge-outline-primary d-none" id="server-name-nav"></span>
{% include notify.html %}
@ -100,7 +100,7 @@
<div class="main-panel">
<div class="warnings">
<noscript class="noscript-warning" style="padding: 20px; background-color: rgb(247, 151, 15);">
<noscript class="noscript-warning">
<div>{% raw translate('base', 'doesNotWorkWithoutJavascript', data['lang']) %}</div>
</noscript>
</div>
@ -117,65 +117,6 @@
<!-- page-body-wrapper ends -->
</div>
<style>
.notifications {
position: fixed;
width: 200px;
top: 70px;
right: 0px;
}
.notification {
position: relative;
margin-right: 1rem;
background: var(--card-banner-bg);
-webkit-transition: right 0.75s, opacity 0.75s, top 0.75s;
-moz-transition: right 0.75s, opacity 0.75s, top 0.75s;
-o-transition: right 0.75s, opacity 0.75s, top 0.75s;
transition: right 0.75s, opacity 0.75s, top 0.75s;
right: -20rem;
opacity: 0.1;
}
.toast-header {
background-color: var(--card-banner-bg);
color: var(--base-text);
}
.toast-body {
background-color: var(--dropdown-bg);
color: var(--base-text);
}
.notification img {
max-height: 20px;
}
.notification strong {
line-height: 20px;
}
.notification.active {
right: 0rem;
opacity: 1;
}
.notification.remove {
right: 0rem;
opacity: 0.1;
top: -2rem;
}
.notification span {
line-height: 20px;
font-size: 15px;
user-select: none;
cursor: pointer;
}
</style>
<div class="notifications"></div>
<script src="/static/assets/vendors/js/vendor.bundle.base.js"></script>
@ -256,9 +197,9 @@
const sendWssError = () => wsOpen || warn(
'WebSockets are required for Crafty to work. This websocket connection has been closed. Are you using a reverse proxy?',
link='https://docs.craftycontrol.com/pages/getting-started/proxies/',
link_msg="See our documentation for details",
className='wssError'
link = 'https://docs.craftycontrol.com/pages/getting-started/proxies/',
link_msg = "See our documentation for details",
className = 'wssError'
)
function startWebSocket() {
@ -460,7 +401,7 @@
}
function warn(message, link = null, link_msg=null, className = null, bg_color="#f7970f") {
function warn(message, link = null, link_msg = null, className = null, bg_color = "#f7970f") {
var closeEl = document.createElement('span');
var strongEL = document.createElement('strong');
var msgEl = document.createElement('div');
@ -581,13 +522,13 @@
$(document).ready(function () {
console.log('%c[Crafty Controller] %cReady for JS!', 'font-weight: 900; color: #800080;', 'font-weight: 900; color: #eee;');
if ($(document.documentElement).data("username") === "anti-lockout-user"){
if ($(document.documentElement).data("username") === "anti-lockout-user") {
warn(
'⚠You are in a recovery account. Access is limited!',
link='/logout',
link_msg="Click here to log out after you change your password. ⚠️",
className='anti-lockout',
bg_color='#6887dc'
link = '/logout',
link_msg = "Click here to log out after you change your password. ⚠️",
className = 'anti-lockout',
bg_color = '#6887dc'
)
}
$('#support_logs').click(function () {

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="default">
<head>
<!-- Required meta tags -->
@ -13,6 +13,7 @@
<link rel="stylesheet" href="/static/assets/vendors/typicons/typicons.css">
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">
<link rel="stylesheet" href="/static/assets/vendors/fontawesome6/css/all.css">
<link rel="stylesheet" href="/static/assest/css/internal/root.css">
<link rel="stylesheet" href="/static/assest/css/crafty.css">
<link rel="manifest" href="/static/assets/crafty.webmanifest">
@ -24,14 +25,22 @@
<!-- endinject -->
<!-- Plugin css for this page -->
<!-- End Plugin css for this page -->
<!-- Layout styles -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
<link rel="stylesheet" href="/static/assets/css/internal/root.css">
<link rel="stylesheet" href="/static/assets/css/internal/anti-lockout.css">
{% for theme in data['themes'] %}
<link rel="stylesheet" href="/static/assets/css/themes/{{ theme }}.css">
{% end %}
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- End Layout styles -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
</head>
<body class="dark-theme">
<body>
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">

View File

@ -1,5 +1,5 @@
<!-- partial:partials/_footer.html -->
<footer class="footer">
<footer class="footer">
<div class="container-fluid ">
<span class="text-muted d-block text-center text-sm-left d-sm-inline-block">{{ translate('footer', 'copyright', data['lang']) }} © 2021 - <span x-data x-text="new Date().getFullYear()"></span> <a href="https://craftycontrol.com/" target="_blank">Crafty Controller</a>. {{ translate('footer', 'allRightsReserved', data['lang']) }}.</span>
<span class="float-none float-sm-right d-block mt-1 mt-sm-0">&nbsp;&nbsp;{{ translate('footer', 'version', data['lang']) }}: {{ data['version_data'] }}</span>
@ -7,21 +7,6 @@
<span class="float-none float-sm-right d-block mt-1 mt-sm-0"><a target="_blank" class="blink-text" href="https://gitlab.com/crafty-controller/crafty-4/-/releases">Update Available!</a></span>
{% end %}
</div>
<style>
a:hover {
text-decoration: none;
}
.blink-text{
color: #000;
font-weight: bold;
font-size: 2rem;
animation: blinkingText 2s infinite;
}
@keyframes blinkingText{
0% { color: grey;}
50% { color: red;}
100% { color: grey;}
}
</style>
</footer>
<link rel="stylesheet" href="/static/assets/css/partial/crafty-footer.css">
</footer>
<!-- partial -->

View File

@ -1,14 +1,6 @@
<!-- partial -->
<!-- partial:partials/_sidebar.html -->
<style>
@media screen and (max-width: 991px) {
.sidebar-offcanvas {
-webkit-transition: all 0.25s cubic-bezier(.22, .61, .36, 1);
transition: all 0.25s cubic-bezier(.22, .61, .36, 1);
box-shadow: 0px 8px 17px 2px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12), 0px 5px 5px -3px rgba(0, 0, 0, 0.2);
}
}
</style>
<script>
function debounce(func, wait, immediate) {
var timeout;
@ -71,8 +63,7 @@
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="collapse" href="#page-layouts" aria-expanded="false"
aria-controls="page-layouts">
<a class="nav-link" data-toggle="collapse" href="#page-layouts" aria-expanded="false" aria-controls="page-layouts">
<i class="fas fa-server"></i> &nbsp;
<span class="menu-title">{{ translate('sidebar', 'servers', data['lang']) }}</span>
<i class="menu-arrow"></i>

View File

@ -6,8 +6,8 @@
text-danger
{% end %}
"></i><span id="notif-count" class="badge badge-notify"></span> </a>
<div class="dropdown-menu dropdown-menu-right navbar-dropdown notif-div" style="width: 40vw; max-height: 80vh;" aria-labelledby="notifDropdown">
<ul style="padding-top: 10px;" id="announcements">
<div class="p-0 dropdown-menu dropdown-menu-right navbar-dropdown notif-div vw-40 max-vh-80" aria-labelledby="notifDropdown">
<ul class="p-3" id="announcements">
</ul>
</div>
</li>
@ -38,7 +38,7 @@
<span class="dropdown-item" id="support_progress"><i class="dropdown-item-icon mdi mdi-download-outline text-primary"></i>{{ translate('notify', 'supportLogs',
data['lang']) }}<br><br></span>
<span class="dropdown-item" id="support_progress">
<div class="support_progress" style="height: 15px; width: 100%;">
<div class="support_progress">
<div class="progress-bar progress-bar-striped progress-bar-animated" id="logs_progress_bar" role="progressbar" style="width:0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
</div>
</span>
@ -96,7 +96,7 @@
console.log(data);
let text = "";
for (let value of data) {
text += `<li class="card-header header-sm justify-content-between align-items-center" id="${value.id}"><p style="float: right;"><i data-id="${value.id}"class="clear-button fa-regular fa-x"></i></p><a style="color: var(--purple);" href=${value.link} target="_blank"><h6>${value.title}</h6><small><p>${value.date}</p></small><p>${value.desc}</p></li></a>`
text += `<li class="card-header header-sm justify-content-between align-items-center annoucement-item" id="${value.id}"><p><i data-id="${value.id}" class="clear-button fa-regular fa-x"></i></p><a href=${value.link} target="_blank"><h6 class="annoucement-title">${value.title}</h6><small><p>${value.date}</p></small><p>${value.desc}</p></li></a>`
}
if (data.length > 0) {
localStorage.setItem("notif-count", data.length);
@ -104,8 +104,7 @@
$("#notif-count").html(data.length);
$("#announcements").html(text);
} else {
$("#announcements").html(`<p style='margin-top: 15px;' class='text-center'><i class="fa fa-bell-slash" aria-hidden="true"></i>
</p>`);
$("#announcements").html(`<li><p class='my-3 text-center'><i class="fa fa-bell-slash" aria-hidden="true"></i></p></li>`);
$("#notif-count").hide()
}
$(".clear-button").on("click", function (event) {
@ -119,8 +118,7 @@
localStorage.setItem("notif-count", notif_count);
$("#notif-count").html(notif_count);
} else {
$("#announcements").html(`<p style='margin-top: 15px;' class='text-center'><i class="fa fa-bell-slash" aria-hidden="true"></i>
</p>`)
$("#announcements").html(`<li><p class='my-3 text-center'><i class="fa fa-bell-slash" aria-hidden="true"></i></p></li>`)
$("#notif-count").html("");
}
@ -136,7 +134,7 @@
});
let responseData = await res.json();
console.log(responseData);
setTimeout(function() {
setTimeout(function () {
getAnnouncements();
}, 1800000); //Wait 30 minutes in miliseconds
console.log("Registered annoucement fetch event in 30 minutes.")

View File

@ -25,15 +25,13 @@
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fas fa-history"></i> &nbsp;Audit Logs</h4>
{% if data['user_data']['hints'] %}
<span class="too_small" title="{{ translate('dashboard', 'cannotSeeOnMobile', data['lang']) }}" ,
data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}" ,
data-placement="top"></span>
<span class="too_small" title="{{ translate('dashboard', 'cannotSeeOnMobile', data['lang']) }}" , data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}" , data-placement="top"></span>
{% end %}
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover" id="audit_table" style="overflow: scroll;" width="100%">
<table class="table table-hover w-100" id="audit_table">
<thead>
<tr class="rounded">
<th>Time</th>
@ -46,8 +44,7 @@
<tbody>
<tr>
<td colspan="5" id="image-div" class="text-center"> <!-- Center image within table -->
<img class="img-center" id="logo-animate" src="../static/assets/images/crafty-logo-square-1024.png"
alt="Crafty Logo, Crafty is loading" width="20%"><br><br>{{ translate('datatables',
<img class="img-center" id="logo-animate" src="../static/assets/images/crafty-logo-square-1024.png" alt="Crafty Logo, Crafty is loading" width="20%"><br><br>{{ translate('datatables',
'loadingRecords', data['lang'])}}
</td>
</tr>
@ -59,16 +56,6 @@
</div>
</div>
</div>
<style>
.popover-body {
color: white !important;
;
}
</style>
</div>
<!-- content-wrapper ends -->

View File

@ -6,8 +6,7 @@
{% block title %}Crafty Controller - {{ translate('panelConfig', 'pageTitle', data['lang']) }}{% end %}
{% block content %}
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.10/css/bootstrap-select.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.10/css/bootstrap-select.min.css">
<div class="content-wrapper">
@ -50,17 +49,16 @@
</div>
<!-- Page Title Header Ends-->
<form id="config-form" class="forms-sample" method="post" action="/panel/config_json">
<form id="config-form" method="post" action="/panel/config_json">
{% for item in data['config-json'].items() %}
{% if item[0] == "reset_secrets_on_next_boot" %}
<div class="form-group" style="background: rgba(243, 21, 6, 0.3); outline: 1px solid red; padding: 10px;">
<div class="form-group reset-secret">
{% else %}
<div class="form-group">
{% end %}
<label class="form" for="{{item[0]}}">{{item[0]}}
<small class="text-muted ml-1">
</small> </label><br />
<label class="form" for="{{item[0]}}">
{{item[0]}}
</label>
{% if item[0] == 'language' %}
<select name="{{item[0]}}" class="form-control">
{% for lang in data['availables_languages'] %}
@ -73,11 +71,9 @@
</select>
{% elif item[0] == 'disabled_language_files' %}
<div class="input-group">
<button type="button" class="btn btn-outline-default custom-picker"
onclick="$('option', $('#lang_select')).each(function(element) {$(this).removeAttr('selected').prop('selected', false); $('.selectpicker').selectpicker('refresh')});">{{
<button type="button" class="btn btn-outline-default custom-picker" onclick="$('option', $('#lang_select')).each(function(element) {$(this).removeAttr('selected').prop('selected', false); $('.selectpicker').selectpicker('refresh')});">{{
translate('panelConfig', 'enableLang', data['lang']) }}</button>
<select id="lang_select" class="form-control selectpicker show-tick custom-picker"
data-icon-base="fas" data-tick-icon="fa-check" multiple data-style="custom-picker">
<select id="lang_select" class="form-control selectpicker show-tick custom-picker" data-icon-base="fas" data-tick-icon="fa-check" multiple data-style="custom-picker">
{% for lang in data['all_languages'] %}
{% if lang in item[1] %}
<option selected>{{lang}}</option>
@ -86,17 +82,13 @@
{% end %}
{% end %}
</select>
<textarea id="disabled_lang" name="{{item[0]}}" class="form-control list hidden"
rows="{{ len(data['all_languages']) }}" value="{{','.join(item[1])}}"
hidden>{{','.join(item[1])}}</textarea>
<textarea id="disabled_lang" name="{{item[0]}}" class="form-control list hidden" rows="{{ len(data['all_languages']) }}" value="{{','.join(item[1])}}" hidden>{{','.join(item[1])}}</textarea>
</div>
{% elif item[0] == 'monitored_mounts'%}
<div class="input-group">
<button type="button" class="btn btn-outline-default custom-picker"
onclick="$('option', $('#mount_select')).each(function(element) {$(this).removeAttr('selected').prop('selected', false); $('.selectpicker').selectpicker('refresh')});">{{
<button type="button" class="btn btn-outline-default custom-picker" onclick="$('option', $('#mount_select')).each(function(element) {$(this).removeAttr('selected').prop('selected', false); $('.selectpicker').selectpicker('refresh')});">{{
translate('panelConfig', 'noMounts', data['lang']) }}</button>
<select id="mount_select" class="form-control selectpicker show-tick" data-icon-base="fas"
data-tick-icon="fa-check" multiple data-style="custom-picker">
<select id="mount_select" class="form-control selectpicker show-tick" data-icon-base="fas" data-tick-icon="fa-check" multiple data-style="custom-picker">
{% for mount in data['all_partitions'] %}
{% if mount in item[1] %}
<option selected>{{mount}}</option>
@ -105,33 +97,40 @@
{% end %}
{% end %}
</select>
<textarea id="monitored_mounts" name="{{item[0]}}" class="form-control list hidden"
rows="{{ len(data['all_partitions']) }}" value="{{','.join(item[1])}}"
hidden>{{','.join(item[1])}}</textarea>
<textarea id="monitored_mounts" name="{{item[0]}}" class="form-control list hidden" rows="{{ len(data['all_partitions']) }}" value="{{','.join(item[1])}}" hidden>{{','.join(item[1])}}</textarea>
</div>
{% elif isinstance(item[1], list) %}
<textarea id="{{item[0]}}" value="{{','.join(item[1])}}" type="text" name="{{item[0]}}"
class="form-control list">{{','.join(item[1])}}</textarea>
<textarea id="{{item[0]}}" value="{{','.join(item[1])}}" type="text" name="{{item[0]}}" class="form-control list">{{','.join(item[1])}}</textarea>
{% elif isinstance(item[1], bool) %}
<div style="margin-left: 30px;">
{% if item[1] == True %}
<input type="radio" class="form-check-input" name="{{item[0]}}" id="True" value="True" checked>
 <label for="True">True</label><br>
<input type="radio" class="form-check-input" name="{{item[0]}}" id="False" value="False">
 <label for="False">False</label>
{% else %}
<input type="radio" class="form-check-input" name="{{item[0]}}" id="True" value="True">
 <label for="True">True</label><br>
<input type="radio" class="form-check-input" name="{{item[0]}}" id="False" value="False" checked>
 <label for="False">False</label>
{% end %}
<div class="custom-control custom-radio">
<input class="custom-control-input" type="radio" name="{{item[0]}}" id="{{item[0]}}_True" value="True" checked>
<label class="custom-control-label" for="{{item[0]}}_True">
True
</label>
</div>
<div class="custom-control custom-radio">
<input class="custom-control-input" type="radio" name="{{item[0]}}" id="{{item[0]}}_False" value="False">
<label class="custom-control-label" for="{{item[0]}}_False">False</label>
</div>
{% elif isinstance(item[1], int) %}
<input type="number" class="form-control" name="{{item[0]}}" id="{{item[0]}}" value="{{ item[1] }}"
step="1" min="0" required>
{% else %}
<input type="text" class="form-control" name="{{item[0]}}" id="{{item[0]}}" value="{{ item[1] }}"
step="2" min="0" required>
<div class="custom-control custom-radio">
<input class="custom-control-input" type="radio" name="{{item[0]}}" id="{{item[0]}}_True" value="True">
<label class="custom-control-label" for="{{item[0]}}_True">True</label>
</div>
<div class="custom-control custom-radio">
<input class="custom-control-input" type="radio" name="{{item[0]}}" id="{{item[0]}}_False" value="False" checked>
<label class="custom-control-label" for="{{item[0]}}_False">
False
</label>
</div>
{% end %}
{% elif isinstance(item[1], int) %}
<input type="number" class="form-control" name="{{item[0]}}" id="{{item[0]}}" value="{{ item[1] }}" step="1" min="0" required>
{% else %}
<input type="text" class="form-control" name="{{item[0]}}" id="{{item[0]}}" value="{{ item[1] }}" step="2" min="0" required>
{% end %}
</div>
{% end %}
@ -141,28 +140,7 @@
</div>
</div>
</div>
</div>
<style>
.dropdown-menu.inner {
display: inline-block !important;
}
.popover-body {
color: white !important;
;
}
input[type="radio"] {
-ms-transform: scale(1.5);
/* IE 9 */
-webkit-transform: scale(1.5);
/* Chrome, Safari, Opera */
transform: scale(1.5);
}
</style>
<!-- content-wrapper ends -->
{% end %}
@ -170,7 +148,7 @@
{% block js %}
<script>
function replacer(key, value) {
if (key == "disabled_language_files" || key == "monitored_mounts") {
if (key == "disabled_language_files" || key == "monitored_mounts" || key == "keywords") {
if (value == 0) {
return []
} else {
@ -199,6 +177,7 @@
formDataObject.disabled_language_files = $('#lang_select').val();
formDataObject.monitored_mounts = $('#mount_select').val();
formDataObject.keywords = $('#keywords').val().split(",");
$('#config-form input[type="radio"]:checked').each(function () {
if ($(this).val() == 'True') {
formDataObject[this.name] = true;
@ -206,12 +185,10 @@
formDataObject[this.name] = false;
}
});
console.log(formDataObject);
// Format the plain form data as JSON
let formDataJsonString = JSON.stringify(formDataObject, replacer);
console.log(formDataJsonString);
let res = await fetch(`/api/v2/crafty/config/`, {
method: 'PATCH',
headers: {

View File

@ -22,7 +22,7 @@
<div class="row">
<div class="col-md-4 grid-margin">
<div class="col-md-6 col-lg-4 grid-margin">
<div class="card">
<div class="card-body">
@ -37,13 +37,11 @@
</ul>
<br />
<div class="text-center">
<a href='https://ko-fi.com/C0C1AIIZS' target='_blank'><img style='border:0px;width:100%;'
src='../static/assets/images/kofi_cross.png' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
<a href='https://ko-fi.com/C0C1AIIZS' target='_blank'><img class="w-100" src='../static/assets/images/kofi_cross.png' alt='Buy Me a Coffee at ko-fi.com' /></a>
</div>
<br>
<div class="text-center">
<a href="https://www.patreon.com/bePatron?u=27882946"
data-patreon-widget-type="become-patron-button">Become a Patron!</a>
<a href="https://www.patreon.com/bePatron?u=27882946" data-patreon-widget-type="become-patron-button">Become a Patron!</a>
<script async src="https://c6.patreon.com/becomePatronButton.bundle.js"></script>
</div>
</div>
@ -51,7 +49,7 @@
</div>
</div>
</div>
<div class="col-md-4 grid-margin">
<div class="col-md-6 col-lg-4 grid-margin">
<div class="card">
<div class="card-body">
@ -63,17 +61,14 @@
</p>
<br />
<div class="text-center">
<iframe id='kofiframe'
src='https://ko-fi.com/arcadiatech/?hidefeed=true&widget=true&embed=true&preview=true'
style='border:none;width:100%;padding:4px;background:#1d1d2f;' height='650'
title='arcadiatech'></iframe>
<iframe id='kofiframe' src='https://ko-fi.com/arcadiatech/?hidefeed=true&widget=true&embed=true&preview=true' class="w-100 border-0" height='650' title='arcadiatech'></iframe>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4 grid-margin">
<div class="col-md-6 col-lg-4 grid-margin">
<div class="card">
<div class="card-body">

View File

@ -23,69 +23,56 @@
<!-- Page Title Header Ends-->
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fa-solid fa-code-merge"></i> &nbsp;{{ translate('credits', 'developmentTeam',
data['lang'])
}}</h4>
<div class="card-header header-sm">
<h4><i class="fa-solid fa-code-merge"></i> &nbsp;{{ translate('credits', 'developmentTeam', data['lang'])}}</h4>
</div>
<div class="card-body">
<div class="row">
{% for person in data['staff']['development'] %}
<div class="col-lg-6 mb-5">
<div class="card rounded shadow-none">
<div class="row">
<div class="col-md-4" style="max-width: fit-content;">
<div class="user-avatar mb-auto">
<div class="col-12 col-lg-6">
<div class="row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
<div class="col-12 col-sm-auto col-lg-12 col-xl-auto px-4 pb-2 pt-4 px-lg-4 pb-lg-2 pt-lg-4 py-sm-4 pr-sm-2 pl-sm-4 py-xl-4 pr-xl-2 pl-xl-4">
<div class="user-avatar pl-2 pb-2">
{% if person['pic'] %}
<img src="{{ person['pic'] }}" alt="profile image" class="profile-img img-lg rounded-circle">
{% else %}
<div alt="profil image" class="profile-img img-lg rounded-circle">
<img src="/static/assets/images/credits/user-circle-solid.svg" alt="profile image"
class="profile-img img-lg rounded-circle">
<img src="/static/assets/images/credits/user-circle-solid.svg" alt="profile image" class="profile-img img-lg rounded-circle">
</div>
{% end %}
</div>
<div class="wrapper">
<div class="wrapper d-flex align-items-center">
<h4 class="mb-0 font-weight-medium">{{ person['name'] }}</h4>
<div class="align-items-center">
<h4 class="font-weight-medium">{{ person['name'] }}</h4>
</div>
<div class="wrapper d-flex align-items-center font-weight-medium text-muted">
<div class="align-items-center font-weight-medium text-muted">
{% if person['loc'] %}
<i class="mdi mdi-map-marker-outline mr-2"></i>
<p class="mb-0 text-muted">{{ person['loc'] }}</p>
<p class="text-muted mb-2"><i class="mdi mdi-map-marker-outline"></i> {{ person['loc'] }}</p>
{% end %}
</div>
</div>
</div>
<div class="col-md-8">
<div class="wrapper d-flex align-items-start">
<div class="col px-4 pt-2 pb-4 px-lg-4 pt-lg-2 pb-lg-4 py-sm-4 pl-sm-2 pr-sm-4 py-xl-4 pl-xl-2 pr-xl-4 d-flex flex-column position-static">
<div name="tags" class="my-2 align-items-start">
{% if person['tags'][0] %}
<span class="btn btn-sm btn-info mr-2">{{ person['tags'][0] }}</span>
<span class="btn btn-sm btn-info m-1">{{ person['tags'][0] }}</span>
{% end %}
{% if person['tags'][1] %}
{% if type(person['tags'][1]) is list %}
<a href="{{ person['tags'][1][1] }}" class="btn btn-sm btn-primary mr-2">{{ person['tags'][1][0]
<a href="{{ person['tags'][1][1] }}" class="btn btn-sm btn-primary m-1">{{ person['tags'][1][0]
}}</a>
{% else %}
<span class="btn btn-sm btn-primary mr-2">{{ person['tags'][1] }}</span>
<span class="btn btn-sm btn-primary m-1">{{ person['tags'][1] }}</span>
{% end %}
{% end %}
{% if person['tags'][2] %}
{% if type(person['tags'][2]) is list %}
<a href="{{ person['tags'][2][1] }}" class="btn btn-sm btn-inverse-success mr-2">{{
<a href="{{ person['tags'][2][1] }}" class="btn btn-sm btn-inverse-success m-1">{{
person['tags'][2][0] }}</a>
{% else %}
<span class="btn btn-sm btn-inverse-success mr-2">{{ person['tags'][2] }}</span>
<span class="btn btn-sm btn-inverse-success m-1">{{ person['tags'][2] }}</span>
{% end %}
{% end %}
</div>
<div class="wrapper align-items-start pt-3">
<div name="blurb" class="m-2 align-items-start">
{% if person['title'] %}
<h5><strong>Crafty's {{ person['title'] }}</strong></h5>
{% end %}
@ -93,8 +80,6 @@
</div>
</div>
</div>
</div>
</div>
{% end %}
</div>
@ -104,160 +89,133 @@
<br />
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fa fa-book"></i> &nbsp;{{ translate('credits', 'supportTeam', data['lang'])
}}</h4>
<div class="card-header header-sm">
<h4><i class="fa fa-book"></i> &nbsp;{{ translate('credits', 'supportTeam', data['lang']) }}</h4>
</div>
<div class="card-body">
<div class="row">
{% for person in data['staff']['support'] %}
<div class="col-lg-6 mb-5">
<div class="card rounded shadow-none">
<div class="row">
<div class="col-md-4" style="max-width: fit-content;">
<div class="user-avatar mb-auto">
<div class="col-12 col-lg-6">
<div class="row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
<div class="col-12 col-sm-auto col-lg-12 col-xl-auto px-4 pb-2 pt-4 px-lg-4 pb-lg-2 pt-lg-4 py-sm-4 pr-sm-2 pl-sm-4 py-xl-4 pr-xl-2 pl-xl-4">
<div class="user-avatar pl-2 pb-2">
{% if person['pic'] %}
<img src="{{ person['pic'] }}" alt="profile image" class="profile-img img-lg rounded-circle">
{% else %}
<div alt="profil image" class="profile-img img-lg rounded-circle">
<img src="/static/assets/images/credits/user-circle-solid.svg" alt="profile image"
class="profile-img img-lg rounded-circle">
<img src="/static/assets/images/credits/user-circle-solid.svg" alt="profile image" class="profile-img img-lg rounded-circle">
</div>
{% end %}
</div>
<div class="wrapper">
<div class="wrapper d-flex align-items-center">
<h4 class="mb-0 font-weight-medium">{{ person['name'] }}</h4>
<div class="align-items-center">
<h4 class="font-weight-medium">{{ person['name'] }}</h4>
</div>
<div class="wrapper d-flex align-items-center font-weight-medium text-muted">
<div class="align-items-center font-weight-medium text-muted">
{% if person['loc'] %}
<i class="mdi mdi-map-marker-outline mr-2"></i>
<p class="mb-0 text-muted">{{ person['loc'] }}</p>
<p class="text-muted mb-2"><i class="mdi mdi-map-marker-outline"></i> {{ person['loc'] }}</p>
{% end %}
</div>
</div>
</div>
<div class="col-md-8">
<div class="wrapper d-flex align-items-start">
<div class="col px-4 pt-2 pb-4 px-lg-4 pt-lg-2 pb-lg-4 py-sm-4 pl-sm-2 pr-sm-4 py-xl-4 pl-xl-2 pr-xl-4 d-flex flex-column position-static">
<div name="tags" class="my-2 align-items-start">
{% if person['tags'][0] %}
<span class="btn btn-sm btn-info mr-2">{{ person['tags'][0] }}</span>
<span class="btn btn-sm btn-info m-1">{{ person['tags'][0] }}</span>
{% end %}
{% if person['tags'][1] %}
{% if type(person['tags'][1]) is list %}
<a href="{{ person['tags'][1][1] }}" class="btn btn-sm btn-primary mr-2">{{ person['tags'][1][0]
<a href="{{ person['tags'][1][1] }}" class="btn btn-sm btn-primary m-1">{{ person['tags'][1][0]
}}</a>
{% else %}
<span class="btn btn-sm btn-primary mr-2">{{ person['tags'][1] }}</span>
<span class="btn btn-sm btn-primary m-1">{{ person['tags'][1] }}</span>
{% end %}
{% end %}
{% if person['tags'][2] %}
{% if type(person['tags'][2]) is list %}
<a href="{{ person['tags'][2][1] }}" class="btn btn-sm btn-inverse-success mr-2">{{
<a href="{{ person['tags'][2][1] }}" class="btn btn-sm btn-inverse-success m-1">{{
person['tags'][2][0] }}</a>
{% else %}
<span class="btn btn-sm btn-inverse-success mr-2">{{ person['tags'][2] }}</span>
<span class="btn btn-sm btn-inverse-success m-1">{{ person['tags'][2] }}</span>
{% end %}
{% end %}
</div>
<div class="wrapper align-items-start pt-3">
<div name="blurb" class="m-2 align-items-start">
{% if person['title'] %}
<h5><strong>{{ person['title'] }}</strong></h5>
<h5><strong>Crafty's {{ person['title'] }}</strong></h5>
{% end %}
<p>{{ person['blurb'] }}</p>
</div>
</div>
</div>
</div>
</div>
{% end %}
</div>
</div> <!-- end user row-->
</div> <!-- end of user row -->
</div>
<br />
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fa-solid fa-thumbtack"></i> &nbsp;{{ translate('credits', 'retiredStaff',
data['lang'])
}}</h4>
<div class="card-header header-sm">
<h4><i class="fa-solid fa-thumbtack"></i> &nbsp;{{ translate('credits', 'retiredStaff', data['lang']) }}</h4>
</div>
<div class="card-body">
<div class="row">
{% for person in data['staff']['retired'] %}
<div class="col-lg-6 mb-5">
<div class="card rounded shadow-none">
<div class="row">
<div class="col-md-4" style="max-width: fit-content;">
<div class="card-img-top user-avatar mb-auto">
<div class="col-12 col-lg-6">
<div class="row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
<div class="col-12 col-sm-auto col-lg-12 col-xl-auto px-4 pb-2 pt-4 px-lg-4 pb-lg-2 pt-lg-4 py-sm-4 pr-sm-2 pl-sm-4 py-xl-4 pr-xl-2 pl-xl-4">
<div class="user-avatar pl-2 pb-2">
{% if person['pic'] %}
<img src="{{ person['pic'] }}" alt="profile image" class="profile-img img-lg rounded-circle">
{% else %}
<div alt="profil image" class="profile-img img-lg rounded-circle">
<img src="/static/assets/images/credits/user-circle-solid.svg" alt="profile image">
<img src="/static/assets/images/credits/user-circle-solid.svg" alt="profile image" class="profile-img img-lg rounded-circle">
</div>
{% end %}
</div>
<div class="wrapper">
<div class="wrapper d-flex align-items-center">
<h4 class="mb-0 font-weight-medium">{{ person['name'] }}</h4>
<div class="align-items-center">
<h4 class="font-weight-medium">{{ person['name'] }}</h4>
</div>
<div class="wrapper d-flex align-items-center font-weight-medium text-muted">
<div class="align-items-center font-weight-medium text-muted">
{% if person['loc'] %}
<i class="mdi mdi-map-marker-outline mr-2"></i>
<p class="mb-0 text-muted">{{ person['loc'] }}</p>
<p class="text-muted mb-2"><i class="mdi mdi-map-marker-outline"></i> {{ person['loc'] }}</p>
{% end %}
</div>
</div>
</div>
<div class="col-md-8">
<div class="wrapper d-flex align-items-start">
<div class="col px-4 pt-2 pb-4 px-lg-4 pt-lg-2 pb-lg-4 py-sm-4 pl-sm-2 pr-sm-4 py-xl-4 pl-xl-2 pr-xl-4 d-flex flex-column position-static">
<div name="tags" class="my-2 align-items-start">
{% if person['tags'][0] %}
<span class="btn btn-sm btn-info mr-2">{{ person['tags'][0] }}</span>
<span class="btn btn-sm btn-info m-1">{{ person['tags'][0] }}</span>
{% end %}
{% if person['tags'][1] %}
{% if type(person['tags'][1]) is list %}
<a href="{{ person['tags'][1][1] }}" class="btn btn-sm btn-primary mr-2">{{ person['tags'][1][0]
<a href="{{ person['tags'][1][1] }}" class="btn btn-sm btn-primary m-1">{{ person['tags'][1][0]
}}</a>
{% else %}
<span class="btn btn-sm btn-primary mr-2">{{ person['tags'][1] }}</span>
<span class="btn btn-sm btn-primary m-1">{{ person['tags'][1] }}</span>
{% end %}
{% end %}
{% if person['tags'][2] %}
{% if type(person['tags'][2]) is list %}
<a href="{{ person['tags'][2][1] }}" class="btn btn-sm btn-inverse-success mr-2">{{
<a href="{{ person['tags'][2][1] }}" class="btn btn-sm btn-inverse-success m-1">{{
person['tags'][2][0] }}</a>
{% else %}
<span class="btn btn-sm btn-inverse-success mr-2">{{ person['tags'][2] }}</span>
<span class="btn btn-sm btn-inverse-success m-1">{{ person['tags'][2] }}</span>
{% end %}
{% end %}
</div>
<div class="wrapper align-items-start pt-3">
<div name="blurb" class="m-2 align-items-start">
{% if person['title'] %}
<h5><strong>{{ person['title'] }}</strong></h5>
<h5><strong>Crafty's {{ person['title'] }}</strong></h5>
{% end %}
<p>{{ person['blurb'] }}</p>
</div>
</div>
</div>
</div>
</div>
{% end %}
</div> <!-- end user row-->
</div>
</div> <!-- end of user row -->
</div>
<br />
@ -274,7 +232,7 @@
<div class="card-body">
<p class="card-description"> {{ translate('credits', 'hugeDesc', data['lang']) }}
<code>{{ translate('credits', 'thankYou', data['lang']) }}</code>&nbsp; {{ translate('credits',
'patreonDesc', data['lang']) }} | <span style="color: #9365B8">{{ translate('credits', 'patreonUpdate',
'patreonDesc', data['lang']) }} | <span class="text-info">{{ translate('credits', 'patreonUpdate',
data['lang']) }} {{ data["lastUpdate"] }}</span>
</p>
<table class="table table-hover">
@ -341,14 +299,14 @@
{% for person in data['translations'] %}
<tr>
<td>{{ person }}</td>
<td class="pb-0">
<td class="">
<div class="row">
{% for language in data['translations'][person] %}
{% if language['status'] %}
<span class="btn btn-sm btn-inverse-success mr-2" style="margin-bottom: 12px;">{{ language['name']
<span class="btn btn-sm btn-inverse-success m-1">{{ language['name']
}}</span>
{% else %}
<span class="btn btn-sm btn-inverse-secondary mr-2" style="margin-bottom: 12px;">{{ language['name']
<span class="btn btn-sm btn-inverse-secondary m-1">{{ language['name']
}}</span>
{% end %}
{% end %}

View File

@ -62,14 +62,12 @@
<div class="form-group">
<div id="upload_input" class="input-group">
<div class="custom-file">
<input type="file" class="custom-file-input" id="file" name="file" multiple="false"
required>
<input type="file" class="custom-file-input" id="file" name="file" multiple="false" required>
<label id="fileLabel" class="custom-file-label" for="file">{{ translate('customLogin',
'labelLoginImage', data['lang']) }}</label>
</div>
<div class="input-group-append">
<button type="button" class="btn btn-info upload-button" id="upload-button"
onclick="uploadFile('background')" disabled>UPLOAD</button>
<button type="button" class="btn btn-info upload-button" id="upload-button" onclick="uploadFile('background')" disabled>UPLOAD</button>
</div>
</div>
</div>
@ -84,8 +82,7 @@
<div class="form-group row">
<label for="photo" class="col-sm-6 col-form-label">Selected Background Image</label>
<div class="col-sm-6">
<select class="form-select form-control form-control-lg select-css form-control-plaintext"
id="photo" name="photo" form="photo_form" onchange="updateBackgroundPreview()">
<select class="form-select form-control form-control-lg select-css form-control-plaintext" id="photo" name="photo" form="photo_form" onchange="updateBackgroundPreview()">
{% for image in data["backgrounds"] %}
<option value="{{image}}">{{image}}</option>
{% end %}
@ -94,9 +91,7 @@
</div>
<div id="photo_loading" class="form-group" hidden>
<div class="progress">
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar"
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%">&nbsp;<i
class="fa-solid fa-spinner"></i></div>
<div class="progress-bar progress-bar-striped progress-bar-animated w-100" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100">&nbsp;<i class="fa-solid fa-spinner"></i></div>
</div>
</div>
<div class="form-group row">
@ -104,13 +99,11 @@
data['lang']) }}</label>
<label class="col-sm-1" id="opacityValue">{{ data['login_opacity'] }}%</label>
<div class="range col-sm-8">
<input type="range" class="form-control-range" id="modal_opacity" name="modal_opacity"
onchange="previewOpacity()" min="0" max="100" value="{{ data['login_opacity'] }}">
<input type="range" class="form-control-range" id="modal_opacity" name="modal_opacity" onchange="previewOpacity()" min="0" max="100" value="{{ data['login_opacity'] }}">
</div>
</div>
<div id="login_preview" style="position: relative;">
<img id="bg-preview" src="../../static/assets/images/auth/{{ data['background'] }}"
class="img-fluid" alt="Responsive image">
<div id="login_preview" class="position-relative">
<img id="bg-preview" src="../../static/assets/images/auth/{{ data['background'] }}" class="img-fluid" alt="Responsive image">
<div id="login-form-preview">
<div id="login-form-background" class="auto-form-wrapper login-modal">
<div class="text-center auto-form-logo">
@ -174,20 +167,17 @@
</style>
<div id="login_form_data">
<input type="hidden" name="_xsrf"
value="2|1d603267|809fb6bd82f677d440e484dde7c3a310|1671726040" disabled>
<input type="hidden" name="_xsrf" value="2|1d603267|809fb6bd82f677d440e484dde7c3a310|1671726040" disabled>
<div class="form-group">
<label class="label">Username</label>
<div class="input-group">
<input type="text" class="form-control login-text-input login-input"
placeholder="Username" name="username" id="username" required="true" disabled>
<input type="text" class="form-control login-text-input login-input" placeholder="Username" name="username" id="username" required="true" disabled>
</div>
</div>
<div class="form-group">
<label class="label">Password</label>
<div class="input-group">
<input type="password" class="form-control login-text-input login-input"
placeholder="Password" name="password" id="password" required="true" disabled>
<input type="password" class="form-control login-text-input login-input" placeholder="Password" name="password" id="password" required="true" disabled>
</div>
</div>
<div class="form-group">
@ -195,20 +185,14 @@
In</button>
</div>
<fieldset style="color: red; text-align: center;">
<span></span>
</fieldset>
<div class="form-group d-flex justify-content-between">
<div class="form-check form-check-flat mt-0">
&nbsp;
</div>
<a href="#" class="text-small forgot-password" disabled>Forgot Password</a>
<a href="#" class="text-small forgot-password">Forgot Password</a>
</div>
<div class="text-block text-center my-3">
<span class="text-small font-weight-semibold"><a
href="https://craftycontrol.com/">Crafty Control
4.0.20</a> </span>
<span class="text-small font-weight-semibold"><a href="#">Crafty Control {{ data['version_data'] }}</a> </span>
</div>
</div>
</div>
@ -242,11 +226,6 @@
.img-fluid {
margin-bottom: 1rem;
}
.popover-body {
color: white !important;
;
}
</style>
<!-- content-wrapper ends -->

View File

@ -15,7 +15,7 @@
<div class="page-header">
<h4 class="page-title">{{ translate('dashboard', 'dashboard', data['lang']) }}
{% if data['server_stats']['running'] != 0 %}
<span id="sync" style="margin-left: 5px;"><i class="fas fa-sync fa-spin"></i></span>
<span id="sync" class="ml-5"><i class="fas fa-sync fa-spin"></i></span>
</h4>
{% end %}
</div>
@ -58,11 +58,13 @@
</div>
<div class="wrapper my-auto ml-auto ml-lg-4">
<p id="cpu_data" class="mb-0 text-success" data-toggle="tooltip" data-placement="top" data-html="true" title="{% raw translate('dashboard', 'cpuCores', data['lang']) %}: {{ data.get('hosts_data').get('cpu_cores') }} <br /> {% raw translate('dashboard', 'cpuCurFreq', data['lang']) %}: {{ data.get('hosts_data').get('cpu_cur_freq') }} <br /> {% raw translate('dashboard', 'cpuMaxFreq', data['lang']) %}: {{ data.get('hosts_data').get('cpu_max_freq') }}">
<p id="cpu_data" class="mb-0 text-success" data-toggle="tooltip" data-placement="top" data-html="true"
title="{% raw translate('dashboard', 'cpuCores', data['lang']) %}: {{ data.get('hosts_data').get('cpu_cores') }} <br /> {% raw translate('dashboard', 'cpuCurFreq', data['lang']) %}: {{ data.get('hosts_data').get('cpu_cur_freq') }} <br /> {% raw translate('dashboard', 'cpuMaxFreq', data['lang']) %}: {{ data.get('hosts_data').get('cpu_max_freq') }}">
{{ translate('dashboard', 'cpuUsage', data['lang']) }}: <span id="cpu_usage">{{
data.get('hosts_data').get('cpu_usage') }}</span>
</p>
<p id="mem_usage" class="mb-0 text-danger" data-toggle="tooltip" data-placement="top" title="{{ translate('dashboard', 'memUsage', data['lang']) }}: {{ data.get('hosts_data').get('mem_usage') }}">
<p id="mem_usage" class="mb-0 text-danger" data-toggle="tooltip" data-placement="top"
title="{{ translate('dashboard', 'memUsage', data['lang']) }}: {{ data.get('hosts_data').get('mem_usage') }}">
{{ translate('dashboard', 'memUsage', data['lang']) }}: <span id="mem_percent">{{
data.get('hosts_data').get('mem_percent') }}%</span>
</p>
@ -101,7 +103,7 @@
{% if len(data['hosts_data']['disk_json']) > 0 %}
<div class="col-12 mt-4">
<div class="d-flex">
<div class="wrapper" style="width: 100%;">
<div class="wrapper w-100">
{% if len(data["monitored"]) > 0 %}
<h5 class="mb-1 font-weight-medium text-primary">{{ translate('dashboard', 'storage',
data['lang']) }}
@ -112,9 +114,11 @@
{% for item in data['hosts_data']['disk_json'] %}
{% if item["mount"] in data["monitored"] %}
<div id="{{item['device']}}" class="col-xl-3 col-lg-3 col-md-4 col-12">
<h4 class="mb-0 font-weight-semibold d-inline-block text-truncate storage-heading" id="title_{{item['device']}}" data-toggle="tooltip" data-placement="bottom" title="{{item['mount']}}" style="max-width: 100%;"><i class="fas fa-hdd"></i>
<h4 class="mb-0 w-100 font-weight-semibold d-inline-block text-truncate storage-heading"
id="title_{{item['device']}}" data-toggle="tooltip" data-placement="bottom"
title="{{item['mount']}}"><i class="fas fa-hdd"></i>
{{item["mount"]}}</h4>
<div class="progress d-inline-block" style="height: 20px; width: 100%; background-color: rgb(139, 139, 139) !important;">
<div class="progress d-inline-block disk-usage">
<div class="progress-bar
{% if item['percent_used'] <= 58 %}
bg-success
@ -123,7 +127,9 @@
{% else %}
bg-danger
{% end %}
" role="progressbar" style="color: black; height: 100%; width: {{item['percent_used']}}%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">{{item["used"]}} /
" role="progressbar" style="width: {{item['percent_used']}}%"
aria-valuenow="{{item['percent_used']}}" aria-valuemin="0" aria-valuemax="100">
{{item["used"]}} /
{{item["total"]}}
</div>
</div>
@ -150,7 +156,9 @@
data['lang']) }}</h4>
{% if len(data['servers']) > 0 %}
{% if data['user_data']['hints'] %}
<span class="too_small" title="{{ translate('dashboard', 'cannotSeeOnMobile', data['lang']) }}" , data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}" , data-placement="top"></span>
<span class="too_small" title="{{ translate('dashboard', 'cannotSeeOnMobile', data['lang']) }}" ,
data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}" ,
data-placement="top"></span>
{% end %}
{% end %}
<div><a class="nav-link" href="/server/step1"><i class="fas fa-plus-circle"></i> &nbsp; {{
@ -159,7 +167,7 @@
<div class="card-body">
{% if len(data['servers']) == 0 and len(data['failed_servers']) == 0 %}
<div style="text-align: center; color: grey;">
<div class="text-align-center">
<h1>{{ translate('dashboard', 'welcome', data['lang']) }}</h1>
<br>
<h7>{{ translate('dashboard', 'no-servers', data['lang']) }} {{ translate('dashboard', 'newServer',
@ -188,7 +196,8 @@
<td draggable="false">
<i class="fas fa-server"></i>
{% if server['alert'] %}
<a style="color: red !important;" draggable="false" href="/panel/server_detail?id={{server['server_data']['server_id']}}">
<a class="server-alert" draggable="false"
href="/panel/server_detail?id={{server['server_data']['server_id']}}">
{{ server['server_data']['server_name'] }}&nbsp; <i class="fas fa-exclamation-triangle"></i>
</a>
{% else %}
@ -197,16 +206,17 @@
</a>
{% end %}
</td>
<td draggable="false" id="controls{{server['server_data']['server_id']}}" class="actions_serverlist">
{% if server['user_command_permission'] %}
{% if server['stats']['importing'] and server['stats']['running'] %}
<!-- WHAT HAPPENED HERE -->
<a data-id="{{server['server_data']['server_id']}}" class=""><i class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'installing',
<a data-id="{{server['server_data']['server_id']}}" class=""><i
class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'installing',
data['lang']) }}</i></a>
{% elif server['stats']['updating']%}
<!-- WHAT HAPPENED HERE -->
<a data-id="{{server['server_data']['server_id']}}" class=""><i class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'updating',
<a data-id="{{server['server_data']['server_id']}}" class=""><i
class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'updating',
data['lang']) }}</i></a>
{% elif server['stats']['waiting_start']%}
<!-- WHAT HAPPENED HERE -->
@ -218,33 +228,39 @@
{{ translate('serverTerm', 'importing',
data['lang']) }}</a>
{% elif server['stats']['running'] %}
<a data-id="{{server['server_data']['server_id']}}" class="stop_button" data-toggle="tooltip" title="{{ translate('dashboard', 'stop' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}" class="stop_button" data-toggle="tooltip"
title="{{ translate('dashboard', 'stop' , data['lang']) }}">
<i class="fas fa-stop"></i>
</a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="restart_button" data-toggle="tooltip" title="{{ translate('dashboard', 'restart' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}" class="restart_button" data-toggle="tooltip"
title="{{ translate('dashboard', 'restart' , data['lang']) }}">
<i class="fas fa-sync"></i>
</a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip"
title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<i class="fas fa-skull"></i>
</a> &nbsp;
{% else %}
<a data-id="{{server['server_data']['server_id']}}" class="play_button" data-toggle="tooltip" title="{{ translate('dashboard', 'start' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}" class="play_button" data-toggle="tooltip"
title="{{ translate('dashboard', 'start' , data['lang']) }}">
<i class="fas fa-play"></i>
</a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="clone_button" data-toggle="tooltip" title="{{ translate('dashboard', 'clone' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}" class="clone_button" data-toggle="tooltip"
title="{{ translate('dashboard', 'clone' , data['lang']) }}">
<i class="fas fa-clone"></i>
</a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip"
title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<i class="fas fa-skull"></i>
</a> &nbsp;
{% end %}
{% end %}
</td>
<td draggable="false" id="server_cpu_{{server['server_data']['server_id']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top" title="{{server['stats']['cpu']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top"
title="{{server['stats']['cpu']}}">
<div class="progress-bar
{% if server['stats']['cpu'] <= 33 %}
bg-success
@ -253,13 +269,14 @@
{% else %}
bg-danger
{% end %}
" role="progressbar" style="width: {{server['stats']['cpu']}}%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
" role="progressbar" style="width: {{server['stats']['cpu']}}%"
aria-valuenow="{{server['stats']['cpu']}}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
{{server['stats']['cpu']}}%
</td>
<td draggable="false" id="server_mem_{{server['server_data']['server_id']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top" title="{{server['stats']['mem']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top"
title="{{server['stats']['mem']}}">
<div class="progress-bar
{% if server['stats']['mem_percent'] <= 33 %}
bg-success
@ -268,7 +285,8 @@
{% else %}
bg-danger
{% end %}
" role="progressbar" style="width: {{server['stats']['mem_percent']}}%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
" role="progressbar" style="width: {{server['stats']['mem_percent']}}%"
aria-valuenow="{{server['stats']['mem_percent']}}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
{{server['stats']['mem_percent']}}% -
@ -284,22 +302,16 @@
<td draggable="false" id="server_desc_{{server['server_data']['server_id']}}">
{% if server['stats']['int_ping_results'] %}
{{ server['stats']['online'] }} / {{ server['stats']['max'] }} {{ translate('dashboard', 'max',
data['lang']) }} <br />
{% if server['stats']['desc'] != 'False' %}
<div id="desc_id" style="overflow-wrap: break-word !important; max-width: 85px !important; overflow: scroll;">{{ translate('serverStats', 'loadingMotd', data['lang']) }}</div> <br />
data['lang']) }}
{% end %}
{% if server['stats']['version'] != 'False' %}
{{ server['stats']['version'] }}
{% end %}
{% end %}
<span class="server-player-totals" id="server_players_{{server['server_data']['server_id']}}"
data-serverId="{{server['server_data']['server_id']}}"
data-players="{{ server['stats']['online']}}" data-max="{{ server['stats']['max'] }}"
data-count="{{server['server_data']['count_players']}}"></span>
</td>
<td draggable="false">
<span class="port" data-toggle="tooltip" title="{{
<div id="server_running_status_{{server['server_data']['server_id']}}" data-toggle="tooltip" title="{{
server['server_data']['server_port'] }}">
<div id="server_running_status_{{server['server_data']['server_id']}}">
{% if server['stats']['running'] %}
<span class="text-success"><i class="fas fa-signal"></i> {{ translate('dashboard', 'online',
data['lang']) }}</span>
@ -311,17 +323,14 @@
<span class="text-warning"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline',
data['lang']) }}</span>
{% end %}
<br />
<br />
</td>
<span class="server-player-totals" id="server_players_{{server['server_data']['server_id']}}" data-serverId="{{server['server_data']['server_id']}}" data-players="{{ server['stats']['online']}}" data-max="{{ server['stats']['max'] }}" data-count="{{server['server_data']['count_players']}}"></span>
</tr>
{% end %}
</div>
</span>
{% for server in data['failed_servers'] %}
<tr id="{{server['server_id']}}" draggable="false">
<td class="text-warning"><i class="fas fa-server"></i>&nbsp;<a class="text-warning" href="/panel/server_detail?id={{server['server_id']}}&subpage=config">{{server['server_name']}}</a>
<td class="text-warning"><i class="fas fa-server"></i>&nbsp;<a class="text-warning"
href="/panel/server_detail?id={{server['server_id']}}&subpage=config">{{server['server_name']}}</a>
</td>
<td></td>
<td></td>
@ -346,22 +355,28 @@
<div class="row">
<div class="col-10 col-lg-3 mx-0 px-0">
{% if server['alert'] %}
<a style="color: red !important" class="btn btn-link d-flex justify-content-start" type="button" href="/panel/server_detail?id={{server['server_data']['server_id']}}">
<i class="fas fa-server"></i> {{ server['server_data']['server_name'] }}&nbsp; <i class="fas fa-exclamation-triangle"></i>
<a class="btn btn-link d-flex justify-content-start server-alert" type="button"
href="/panel/server_detail?id={{server['server_data']['server_id']}}">
<i class="fas fa-server"></i> {{ server['server_data']['server_name'] }}&nbsp; <i
class="fas fa-exclamation-triangle"></i>
</a>
{% else %}
<a class="btn btn-link d-flex justify-content-start" type="button" href="/panel/server_detail?id={{server['server_data']['server_id']}}">
<a class="btn btn-link d-flex justify-content-start" type="button"
href="/panel/server_detail?id={{server['server_data']['server_id']}}">
<i class="fas fa-server"></i> {{ server['server_data']['server_name'] }}
</a>
{% end %}
</div>
<div class="col-2 col-lg-3 mx-0 px-0">
<a class="btn btn-link d-flex justify-content-center" type="button" data-toggle="collapse" data-target="#collapse-{{server['server_data']['server_id']}}" aria-expanded="false" aria-controls="collapse-{{server['server_data']['server_id']}}">
<a class="btn btn-link d-flex justify-content-center" type="button" data-toggle="collapse"
data-target="#collapse-{{server['server_data']['server_id']}}" aria-expanded="false"
aria-controls="collapse-{{server['server_data']['server_id']}}">
<i class="fas fa-chart-bar"></i>
</a>
</div>
<div class="col-4 col-lg-3 mx-0 px-0">
<a id="m_server_running_status_{{server['server_data']['server_id']}}" class="btn btn-link d-flex justify-content-start" type="button">
<a id="m_server_running_status_{{server['server_data']['server_id']}}"
class="btn btn-link d-flex justify-content-start" type="button">
{% if server['stats']['running'] %}
<span class="text-success"><i class="fas fa-signal"></i> {{ translate('dashboard', 'online',
data['lang']) }}</span>
@ -382,17 +397,23 @@
{% if server['stats']['running'] %}
<div class="row">
<div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" class="btn btn-link stop_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'stop' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}"
class="btn btn-link stop_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'stop' , data['lang']) }}">
<i class="fas fa-stop"></i>
</a>
</div>
<div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" class="btn btn-link restart_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'restart' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}"
class="btn btn-link restart_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'restart' , data['lang']) }}">
<i class="fas fa-sync"></i>
</a>
</div>
<div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" class="btn btn-link kill_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}"
class="btn btn-link kill_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<i class="fas fa-skull"></i>
</a>
</div>
@ -418,24 +439,31 @@
{% elif server['stats']['importing']%}
<div class="row">
<div class="col-12 px-0">
<a data-id="{{server['server_data']['server_id']}}" class="btn btn-link"><i class="fa fa-spinner fa-spin"></i>
<a data-id="{{server['server_data']['server_id']}}" class="btn btn-link"><i
class="fa fa-spinner fa-spin"></i>
{{ translate('serverTerm', 'importing', data['lang']) }}</a>
</div>
</div>
{% else %}
<div class="row">
<div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" class="btn play_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'start' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}"
class="btn play_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'start' , data['lang']) }}">
<i class="fas fa-play"></i>
</a>
</div>
<div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" class="btn clone_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'clone' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}"
class="btn clone_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'clone' , data['lang']) }}">
<i class="fas fa-clone"></i>
</a>
</div>
<div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" class="btn kill_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<a data-id="{{server['server_data']['server_id']}}"
class="btn kill_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<i class="fas fa-skull"></i></a>
</div>
</div>
@ -447,13 +475,15 @@
</h2>
</div>
<div id="collapse-{{server['server_data']['server_id']}}" class="collapse" aria-labelledby="heading-{{server['server_data']['server_id']}}" data-parent="#accordionServers">
<div id="collapse-{{server['server_data']['server_id']}}" class="collapse"
aria-labelledby="heading-{{server['server_data']['server_id']}}" data-parent="#accordionServers">
<div class="card-body">
<div class="row">
<div class="col-6">
<h6>{{ translate('dashboard', 'cpuUsage', data['lang']) }}</h6>
<div id="m_server_cpu_{{server['server_data']['server_id']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top" title="{{server['stats']['cpu']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top"
title="{{server['stats']['cpu']}}">
<div class="progress-bar
{% if server['stats']['cpu'] <= 33 %}
bg-success
@ -462,7 +492,8 @@
{% else %}
bg-danger
{% end %}
" role="progressbar" style="width: {{server['stats']['cpu']}}%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
" role="progressbar" style="width: {{server['stats']['cpu']}}%"
aria-valuenow="{{server['stats']['cpu']}}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
{{server['stats']['cpu']}}%
</div>
@ -470,7 +501,8 @@
<div class="col-6">
<h6>{{ translate('dashboard', 'memUsage', data['lang']) }}</h6>
<div draggable="false" id="m_server_mem_{{server['server_data']['server_id']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top" title="{{server['stats']['mem']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top"
title="{{server['stats']['mem']}}">
<div class="progress-bar
{% if server['stats']['mem_percent'] <= 33 %}
bg-success
@ -479,7 +511,9 @@
{% else %}
bg-danger
{% end %}
" role="progressbar" style="width: {{server['stats']['mem_percent']}}%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
" role="progressbar" style="width: {{server['stats']['mem_percent']}}%"
aria-valuenow="{{server['stats']['mem_percent']}}" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
{{server['stats']['mem_percent']}}% -
@ -499,22 +533,12 @@
{{ server['stats']['world_size'] }}
</div>
</div>
<div class="col-6" style="width: auto;">
<div class="col-6">
<h6>{{ translate('dashboard', 'players', data['lang']) }}</h6>
<div draggable="false" id="m_server_desc_{{server['server_data']['server_id']}}">
{% if server['stats']['int_ping_results'] %}
{{ server['stats']['online'] }} / {{ server['stats']['max'] }} {{ translate('dashboard',
'max',
data['lang']) }} <br />
{% if server['stats']['desc'] != 'False' %}
<div id="desc_id" style="overflow-wrap: break-word !important; max-width: 85px !important; overflow: scroll;">
{{ server['stats']['desc'] }}</div> <br />
{% end %}
{% if server['stats']['version'] != 'False' %}
{{ server['stats']['version'] }}
{% end %}
{{ server['stats']['online'] }} / {{ server['stats']['max'] }} {{ translate('dashboard', 'max',
data['lang']) }}
{% end %}
</div>
</div>
@ -535,30 +559,6 @@
</div>
<!-- content-wrapper ends -->
<div id="mobile"></div>
<style>
.popover-body {
color: white !important;
;
}
#desc_id {
-ms-overflow-style: none;
/* for Internet Explorer, Edge */
scrollbar-width: none;
/* for Firefox */
overflow-y: scroll;
}
#desc_id::-webkit-scrollbar {
display: none;
/* for Chrome, Safari, and Opera */
}
.gray {
color: gray !important;
}
</style>
{% end %}
@ -609,12 +609,12 @@
});
let responseData = await res.json();
if (responseData.status === "ok") {
if (command === "clone_server"){
if (command === "clone_server") {
window.location.reload()
}
console.log("Command received successfully")
} else {
setTimeout(function(){
setTimeout(function () {
$('.modal').modal('hide');
bootbox.alert({
title: responseData.error,
@ -726,8 +726,8 @@
if (server.int_ping_results) {
/* Update Players */
if (server.players) {
server_desc.innerHTML = server.online + ` / ` + server.max + ` {{ translate('dashboard', 'max', data['lang']) }}<br />`
m_server_desc.innerHTML = server.online + ` / ` + server.max + ` {{ translate('dashboard', 'max', data['lang']) }}<br />`
server_desc.innerHTML = server.online + ` / ` + server.max + ` {{ translate('dashboard', 'max', data['lang']) }}`
m_server_desc.innerHTML = server.online + ` / ` + server.max + ` {{ translate('dashboard', 'max', data['lang']) }}`
server_players.setAttribute('data-players', server.online);
server_players.setAttribute('data-max', server.max);
@ -756,22 +756,8 @@
server_infos = "";
m_server_infos = "";
server_infos = server.online + " / " + server.max + " {{ translate('dashboard', 'max', data['lang']) }}<br />"
}
/* Update Motd */
let motd = "";
if (server.desc) {
m_motd = `<span id="m_input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span>`;
motd = `<span id="input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span>`;
m_server_infos = server_infos + '<div id="desc_id" style="word-wrap: break-word; overflow: auto;">' + motd + '</div>' + "<br />";
server_infos = server_infos + '<div id="desc_id" style="word-wrap: break-word; max-width: 85px !important; overflow: auto;">' + motd + '</div>' + "<br />";
}
/* Version */
if (server.version) {
server_infos = server_infos + server.version
m_server_infos = m_server_infos + server.version
server_infos = server.online + " / " + server.max + " {{ translate('dashboard', 'max', data['lang']) }}"
m_server_infos = server.online + " / " + server.max + " {{ translate('dashboard', 'max', data['lang']) }}"
}
server_desc.innerHTML = server_infos;
m_server_desc.innerHTML = m_server_infos;
@ -880,8 +866,8 @@
for (i = 0; i < hostStats.disk_usage.length; i++) {
if (hostStats.mounts.includes(hostStats.disk_usage[i].mount)) {
storage_html += `<div id="host_storage" class="col-xl-3 col-lg-3 col-md-4 col-12">
<h4 class="mb-0 font-weight-semibold d-inline-block text-truncate storage-heading" id="title_host_storage" data-toggle="tooltip" data-placement="bottom" title="${hostStats.disk_usage[i].mount}" style="max-width: 100%;"><i class="fas fa-hdd"></i> ${hostStats.disk_usage[i].mount}</h4>
<div class="progress" style="display: inline-block; height: 20px; width: 100%; background-color: rgb(139, 139, 139) !important;">
<h4 class="mb-0 font-weight-semibold d-inline-block text-truncate storage-heading mw-100" id="title_host_storage" data-toggle="tooltip" data-placement="bottom" title="${hostStats.disk_usage[i].mount}"><i class="fas fa-hdd"></i> ${hostStats.disk_usage[i].mount}</h4>
<div class="progress d-inline-block disk-usage">
<div class="progress-bar`;
if (hostStats.disk_usage[i].percent_used <= 58) {
storage_html += ` bg-success`;
@ -890,7 +876,7 @@
} else {
storage_html += ` bg-danger`;
}
storage_html += `" role="progressbar" style="color: black; height: 100%; width: ${hostStats.disk_usage[i].percent_used}%;"
storage_html += `" role="progressbar" style="width: ${hostStats.disk_usage[i].percent_used}%;"
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">${hostStats.disk_usage[i].used} / ${hostStats.disk_usage[i].total}
</div>
</div>

View File

@ -1,6 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<html lang="en" class="default">
<head>
<!-- Required meta tags -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
@ -22,32 +23,35 @@
<!-- Plugin css for this page -->
<!-- End Plugin css for this page -->
<!-- Layout styles -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css" />
<link rel="stylesheet" href="/static/assest/css/internal/root.css">
<link rel="stylesheet" href="/static/assets/css/themes/default.css">
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- End Layout styles -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg" />
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
</head>
<style>
</head>
<style>
.auth.auth-bg-1 {
background: url("../../static/assets/images/auth/{% raw data['background'] %}"),
url("/static/assets/images/auth/login_1.jpg");
background-size: cover;
}
</style>
</style>
<body class="dark-theme">
<body>
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one" >
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">
<div class="row w-100">
<div class="col-lg-4 mx-auto">
<div class="auto-form-wrapper">
<div class="text-center">
<img alt="Crafty Logo" src="/static/assets/images/logo_long.svg" /><br /><br />
<div class="col-sm-12 grid-margin stretch-card">
<div class="card card-statistics social-card google-card card-colored" >
<div class="card card-statistics social-card google-card card-colored">
<div class="card-body">
<h4 class="platform-name mb-3 mt-4 font-weight-semibold user-name" >
<h4 class="platform-name mb-3 mt-4 font-weight-semibold user-name">
{{ translate('accessDenied', 'accessDenied', data['lang']) }}
</h4>
<h5 class="headline font-weight-medium">
@ -56,7 +60,7 @@
<p class="mb-2 comment font-weight-light">
{{ translate('accessDenied', 'contactAdmin',
data['lang']) }}<br /><br />
<a class="d-inline font-weight-medium" href="https://discord.gg/9VJPhCE" > {{ translate('accessDenied', 'contact', data['lang']) }}</a>
<a class="d-inline font-weight-medium" href="https://discord.gg/9VJPhCE"> {{ translate('accessDenied', 'contact', data['lang']) }}</a>
</p>
</div>
</div>
@ -99,5 +103,6 @@
}
});
</script>
</body>
</body>
</html>

View File

@ -7,22 +7,16 @@
{% block content %}
<div class="content-wrapper">
<div class="card-header justify-content-between align-items-center" style="border: none;">
<div id="image-div" style="width: 100%;">
<img class="img-center" id="logo-animate" src="../static/assets/images/crafty-logo-square-1024.png"
alt="Crafty Logo, Crafty is loading" width="20%" style="clear: both;">
<div class="card-header justify-content-between align-items-center border-0">
<div id="image-div" class="w-100">
<img class="img-center clearfix" id="logo-animate" src="../static/assets/images/crafty-logo-square-1024.png" alt="Crafty Logo, Crafty is loading" width="20%">
</div>
<br>
</br>
<div id="text-div" style="width: 100%; text-align: center;">
<h2 id="status" style="display: block;" data-init="{{ translate('startup', 'serverInit', data['lang']) }}"
data-server="{{ translate('startup', 'server', data['lang']) }}"
data-internet="{{ translate('startup', 'internet', data['lang']) }}"
data-tasks="{{ translate('startup', 'tasks', data['lang']) }}"
data-internals="{{ translate('startup', 'internals', data['lang']) }}"
data-almost="{{ translate('startup', 'almost', data['lang']) }}"
data-cache="{{ translate('startup', 'cache', data['lang'])}}">
{{ translate('startup', 'starting', data['lang']) }}</h2>
<div id="text-div" class="w-100 text-center">
<h2 id="status" class="d-block" data-init="{{ translate('startup', 'serverInit', data['lang']) }}" data-server="{{ translate('startup', 'server', data['lang']) }}" data-internet="{{ translate('startup', 'internet', data['lang']) }}" data-tasks="{{ translate('startup', 'tasks', data['lang']) }}" data-internals="{{ translate('startup', 'internals', data['lang']) }}" data-almost="{{ translate('startup', 'almost', data['lang']) }}" data-cache="{{ translate('startup', 'cache', data['lang'])}}">
{{ translate('startup', 'starting', data['lang']) }}
</h2>
</div>
</div>

View File

@ -24,7 +24,7 @@
<div class="row">
<div class="col-md-12 grid-margin">
<div class="card">
<div class="card-body">
<div class="card-body pt-0">
{% if data['superuser'] %}
@ -79,7 +79,8 @@
<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><i class="fas fa-user"></i><span id="user_{{user.user_id}}">{{ user.username }}</span>
</td>
<td>
{% if user.enabled %}
<span class="text-success">
@ -106,9 +107,18 @@
{% 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><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 %}
@ -141,9 +151,18 @@
{% 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><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 %}
@ -283,18 +302,15 @@
.clickable {
color: var(--primary);
}
.clickable:hover {
cursor: pointer;
}
.custom-picker {
border: 1px solid var(--outline);
}
.popover-body {
color: white !important;
;
}
.loading:after {
overflow: hidden;
display: inline-block;
@ -341,7 +357,7 @@
return password1;
}
}
$(".edit_password").on("click", async function(){
$(".edit_password").on("click", async function () {
const token = getCookie("_xsrf");
let user_id = $(this).data('id');
bootbox.confirm(`<form class="form" id='infos' action=''>\
@ -353,10 +369,10 @@
<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){
</form>`, async function (result) {
if (result) {
password = validateForm();
if (!password){
if (!password) {
return;
}
let res = await fetch(`/api/v2/users/${user_id}`, {
@ -364,7 +380,7 @@
headers: {
'X-XSRFToken': token
},
body: JSON.stringify({"password": password}),
body: JSON.stringify({ "password": password }),
});
let responseData = await res.json();
if (responseData.status === "ok") {
@ -372,19 +388,19 @@
} else {
bootbox.alert({
title: responseData.error,
title: responseData.status,
message: responseData.error_data
});
}
}
});
});
$(document).on("submit", ".bootbox form", function(e) {
$(document).on("submit", ".bootbox form", function (e) {
e.preventDefault();
$(".bootbox .btn-primary").click();
});
});
$(".edit_user").on("click", function(){
$(".edit_user").on("click", function () {
const token = getCookie("_xsrf");
let username = $(this).data('name');
let user_id = $(this).data('id');
@ -393,15 +409,15 @@
<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){
</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}),
body: JSON.stringify({ "username": new_username }),
});
let responseData = await res.json();
if (responseData.status === "ok") {
@ -415,7 +431,8 @@
});
}
}
});
}
)
});
if (webSocket) {
webSocket.on('move_status', function (message) {

View File

@ -31,13 +31,11 @@
<div class="card-body pt-0">
<ul class="nav nav-tabs col-md-12 tab-simple-styled " role="tablist">
<li class="nav-item">
<a class="nav-link" href="/panel/edit_user?id={{ data['user']['user_id'] }}&subpage=config"
role="tab" aria-selected="false">
<a class="nav-link" href="/panel/edit_user?id={{ data['user']['user_id'] }}&subpage=config" role="tab" aria-selected="false">
<i class="fas fa-cogs"></i>{{ translate('apiKeys', 'config', data['lang']) }}</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/panel/edit_user_apikeys?id={{ data['user']['user_id'] }}"
role="tab" aria-selected="true">
<a class="nav-link active" href="/panel/edit_user_apikeys?id={{ data['user']['user_id'] }}" role="tab" aria-selected="true">
<i class="fas fa-key"></i>{{ translate('apiKeys', 'apiKeys', data['lang']) }}</a>
</li>
</ul>
@ -86,13 +84,9 @@
apikey.server_permissions }}
{{ translate('apiKeys', 'crafty', data['lang']) }} {{
apikey.crafty_permissions }}</td>
<td><button class="btn btn-danger delete-api-key"
data-key-id="{{ apikey.token_id }}"
data-key-name="{{ apikey.name }}">{{translate('panelConfig',
<td><button class="btn btn-danger delete-api-key" data-key-id="{{ apikey.token_id }}" data-key-name="{{ apikey.name }}">{{translate('panelConfig',
'delete', data['lang'])}}</button>
<button class="btn btn-outline-primary get-a-token"
data-key-id="{{ apikey.token_id }}"
data-key-name="{{ apikey.name }}">{{translate('apiKeys',
<button class="btn btn-outline-primary get-a-token" data-key-id="{{ apikey.token_id }}" data-key-name="{{ apikey.name }}">{{translate('apiKeys',
'getToken', data['lang'])}}</button>
</td>
</tr>
@ -118,8 +112,7 @@
<label class="form-label" for="username">{{ translate('apiKeys', 'name',
data['lang']) }}<small class="text-muted ml-1"> - {{
translate('apiKeys', 'nameDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="name" id="name"
placeholder="API Key">
<input type="text" class="form-control" name="name" id="name" placeholder="API Key">
</div>
<table class="table table-hover mb-3">
@ -136,9 +129,7 @@
}}</label>
</td>
<td>
<input type="checkbox" class="server_perm"
id="permission_{{ permission.name }}"
name="permission_{{ permission.name }}" value="1">
<input type="checkbox" class="server_perm" id="permission_{{ permission.name }}" name="permission_{{ permission.name }}" value="1">
</td>
</tr>
{% end %}
@ -149,13 +140,9 @@
</td>
<td>
{% if permission in data['user_crafty_permissions'] %}
<input type="checkbox" class="crafty_perm"
id="permission_{{ permission.name }}"
name="permission_{{ permission.name }}" value="1">
<input type="checkbox" class="crafty_perm" id="permission_{{ permission.name }}" name="permission_{{ permission.name }}" value="1">
{% else %}
<input type="checkbox" class="crafty_perm"
id="permission_{{ permission.name }}"
name="permission_{{ permission.name }}" value="1" disabled>
<input type="checkbox" class="crafty_perm" id="permission_{{ permission.name }}" name="permission_{{ permission.name }}" value="1" disabled>
{% end %}
</td>
</tr>
@ -306,7 +293,7 @@
if (responseData.status === "ok") {
bootbox.alert({
title: `API token for ${keyName}`,
message: `Here is an API token for ${keyName}:\n<pre style="white-space: pre-wrap;color:white;word-break:break-all;background: grey;border-radius: 5px;">${responseData.data}</pre>`
message: `Here is an API token for ${keyName}:\n<pre class="api-key">${responseData.data}</pre>`
});
} else {

View File

@ -1,4 +1,4 @@
<ul class="nav nav-tabs col-md-12 tab-simple-styled" role="tablist" style="margin-top: 0;">
<ul class="nav nav-tabs col-md-12 tab-simple-styled" role="tablist">
<li class="nav-item term-nav-item">
<a class="nav-link {% if data['active_link'] == 'panel_config' %}active{% end %}" href="/panel/panel_config" role="tab" aria-selected="false">
<i class="fas fa-wrench"></i>{{ translate('panelConfig', 'pageTitle', data['lang']) }}</a>

View File

@ -3,7 +3,7 @@
<div class="card">
<div class="card-body pt-3 pb-3">
<div class="row">
<div class="col-sm-4 mr-2">
<div class="col-sm-4">
{% if data['server_stats']['running'] %}
<b>{{ translate('serverStats', 'serverStatus', data['lang']) }}:</b> <span id="status" class="text-success">{{ translate('serverStats', 'online', data['lang']) }}</span><br />
<b>{{ translate('serverStats', 'serverStarted', data['lang']) }}:</b> <span id="started">{{ data['server_stats']['started'] }}</span><br />
@ -21,7 +21,7 @@
<b>{{ translate('serverStats', 'serverTimeZone', data['lang']) }}:</b> <span class="text-info">{{ data['serverTZ'] }}</span>
</div>
<div class="col-sm-3 mr-2">
<div class="col-sm-3">
<b>{{ translate('serverStats', 'cpuUsage', data['lang']) }}:</b> <span id="cpu">{{ data['server_stats']['cpu'] }}%</span> <br />
<b>{{ translate('serverStats', 'memUsage', data['lang']) }}:</b> <span id="mem">{{ data['server_stats']['mem'] }}</span> <br />
{% if data['server_stats']['int_ping_results'] %}
@ -31,14 +31,14 @@
{% end %}
</div>
<div class="col-sm-3 mr-2">
<div class="col-sm-5">
{% if data['server_stats']['version'] != 'False' %}
<b>{{ translate('serverStats', 'version', data['lang']) }}:</b> <span id="version">{{ data['server_stats']['version'] }}</span><br />
<b>{{ translate('serverStats', 'description', data['lang']) }}:</b> <span id="input_motd" style="max-width: 10px; max-height: 10px" class="input_motd">{{ translate('serverStats', 'loadingMotd', data['lang']) }}</span>
<b>{{ translate('serverStats', 'description', data['lang']) }}:</b> <span id="input_motd" class="input_motd">{{ translate('serverStats', 'loadingMotd', data['lang']) }}</span>
<br />
{% else %}
<b>{{ translate('serverStats', 'version', data['lang']) }}:</b> <span id="version">{{ translate('serverStats', 'unableToConnect', data['lang']) }}</span> <br />
<b>{{ translate('serverStats', 'description', data['lang']) }}:</b> <span style="max-width: 10px; max-height: 10px" id="input_motd" class="input_motd">{{ translate('serverStats', 'unableToConnect', data['lang']) }}</span> <br />
<b>{{ translate('serverStats', 'description', data['lang']) }}:</b> <span id="input_motd" class="input_motd">{{ translate('serverStats', 'unableToConnect', data['lang']) }}</span> <br />
{% end %}
<b>Server Type: <span class="text-info">{{data['server_stats']['server_type']}}</span></b>
@ -211,17 +211,24 @@
let text = ""
let players = server.players_cache;
for (let i = 0; i < players.length; i++) {
text += `<tr id="playerItem-${players[i]["name"]}" class="playerItem--" style="text-align: center;">`;
text += `<td class="no-scroll" style="overflow: scroll;"><strong>${players[i]["name"]}</strong></td>`;
text += `<tr id="playerItem-${players[i]["name"]}" class="playerItem-- text-center">`;
text += `<td class="no-scroll col-5"><strong>${players[i]["name"]}</strong></td>`;
if (players[i]["status"] === "Online") {
text += `<td><span class="text-success"><i class="fas fa-signal"></i> ${players[i]['status']}</span></td>`
text += `<td class="col-4"><span class="text-success"><i class="fas fa-signal"></i> ${players[i]['status']}</span></td>`
} else {
text += `<td><span class="text-warning"><i class="fa-regular fa-circle-xmark"></i><span class="offline-status">&nbsp;${players[i]['status']}</span><span class="conn-break"> Last connection :<br> ${players[i]['last_seen']}</span></td>`
text += `<td class="col-4"><span class="text-warning"><i class="fa-regular fa-circle-xmark"></i><span class="offline-status">&nbsp;${players[i]['status']}</span><span class="conn-break"> Last connection :<br> ${players[i]['last_seen']}</span></td>`
}
if (server["running"]) {
text += `<td><button onclick="send_command_to_server('ban ${players[i]['name']}')" type="button" class="btn btn-danger controls">Ban</button><br class="mobile-break"><button onclick="send_command_to_server('kick ${players[i]['name']}')" type="button" class="btn btn-outline-danger controls">Kick</button><br><button onclick="send_command_to_server('op ${players[i]['name']}')" type="button" class="btn btn-warning controls">OP</button><br class="mobile-break"><button onclick="send_command_to_server('deop ${players[i]['name']}')" type="button" class="btn btn-outline-warning controls">De-OP</button></td>`
text += `<td class="col-3">
<div class="row">
<div class="col"><button onclick="send_command_to_server('ban ${players[i]['name']}')" type="button" class="btn btn-danger">Ban</button></div>
<div class="col"><button onclick="send_command_to_server('kick ${players[i]['name']}')" type="button" class="btn btn-outline-danger">Kick</button></div>
<div class="col"><button onclick="send_command_to_server('op ${players[i]['name']}')" type="button" class="btn btn-warning">OP</button></div>
<div class="col"><button onclick="send_command_to_server('deop ${players[i]['name']}')" type="button" class="btn btn-outline-warning">De-OP</button></div>
</div>
</td>`
} else {
text += `<td><span> Unavailable<br> (Server Offline)</span></td>`
text += `<td><div><span> Unavailable<br> (Server Offline)</span></div></td>`
}
}

View File

@ -16,7 +16,7 @@
{% end %}
{% if data['permissions']['Backup'] in data['user_permissions'] %}
{% if data['backup_failed'] %}
<a style="color: red !important;" class="dropdown-item {% if data['active_link'] == 'backup' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=backup" role="tab" aria-selected="false"><i class="fas fa-save"></i> {{ translate('serverDetails', 'backup', data['lang']) }}&nbsp; <i class="fas fa-exclamation-triangle"> </i></a>
<a class="dropdown-item text-danger {% if data['active_link'] == 'backup' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=backup" role="tab" aria-selected="false"><i class="fas fa-save"></i> {{ translate('serverDetails', 'backup', data['lang']) }}&nbsp; <i class="fas fa-exclamation-triangle"> </i></a>
{% else %}
<a class="dropdown-item {% if data['active_link'] == 'backup' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=backup" role="tab" aria-selected="false"><i class="fas fa-save"></i> {{ translate('serverDetails', 'backup', data['lang']) }}</a>
{% end %}

View File

@ -21,7 +21,7 @@
{% if data['permissions']['Backup'] in data['user_permissions'] %}
{% if data['backup_failed'] %}
<li class="nav-item term-nav-item">
<a style="color: red !important;" class="nav-link {% if data['active_link'] == 'backup' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=backup" role="tab" aria-selected="false">
<a class="nav-link text-danger {% if data['active_link'] == 'backup' %}active{% end %}" href="/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=backup" role="tab" aria-selected="false">
<i class="fas fa-save"></i>{{ translate('serverDetails', 'backup', data['lang']) }}&nbsp; <i class="fas fa-exclamation-triangle"> </i></a>
</li>
{% else %}

View File

@ -1,33 +1,33 @@
<div class="col-xl-6 col-lg-12 col-md-12 col-sm-12">
<h2>{{ translate('serverPlayerManagement', 'players', data['lang']) }}:</h2>
<table class="table table-sm-responsive">
<div class="table-responsive ">
<table class="table no-scroll">
<thead class="thead">
<tr>
<th scope="col">Player</th>
<th scope="col">Status</th>
<th scope="col">Actions</th>
<th scope="col-5">Player</th>
<th scope="col-4">Status</th>
<th scope="col-3">Actions</th>
</tr>
</thead>
<tbody id="player-body">
{% for player in data['cached_players'] %}
<tr id="playerItem-{{ player['name'] }}" class="playerItem--" style="text-align: center;">
<td class="no-scroll" style="overflow: scroll;">
<tr id="playerItem-{{ player['name'] }}" class="playerItem-- text-center">
<td class=" no-scroll">
<strong> {{ player['name'] }}</strong>
</td>
{% if player['status'] == 'Online' %}
<td class="no-scroll" style="overflow: scroll;"><span class="text-success"><i class="fas fa-signal"></i> {{ player['status'] }}</span></td>
<td class="no-scroll col-5"><span class="text-success"><i class="fas fa-signal"></i> {{ player['status'] }}</span></td>
{% elif player['status'] == 'Offline' %}
<td class="no-scroll" style="overflow: scroll;"><span class="text-warning"><i class="fa-regular fa-circle-xmark"></i><span class="offline-status">&nbsp;{{ player['status'] }}</span><span class="conn-break"> Last connection :<br> {{ player['last_seen'] }}</span></span></td>
<td class="no-scroll col-4"><span class="text-warning"><i class="fa-regular fa-circle-xmark"></i><span class="d-md-none ">&nbsp;{{ player['status'] }}</span><span class="d-none d-md-inline"> Last connection :<br> {{ player['last_seen'] }}</span></span></td>
{% end %}
<td class="buttons" style="text-align: center;">
<td class="no-scroll col-3">
{% if data['server_stats']['running'] %}
<button onclick="send_command_to_server(`ban {{ player['name'] }}`)" type="button" class="btn btn-danger controls">Ban</button>
<br class="mobile-break"/>
<button onclick="send_command_to_server(`kick {{ player['name'] }}`)" type="button" class="btn btn-outline-danger controls">Kick</button>
<br>
<button onclick="send_command_to_server(`op {{ player['name'] }}`)" type="button" class="btn btn-warning controls">OP</button>
<br class="mobile-break"/>
<button onclick="send_command_to_server(`deop {{ player['name'] }}`)" type="button" class="btn btn-outline-warning controls">De-OP</button>
<div class="row">
<div class="col"><button onclick="send_command_to_server(`ban {{ player['name'] }}`)" type="button" class="btn btn-danger">Ban</button></div>
<div class="col"><button onclick="send_command_to_server(`kick {{ player['name'] }}`)" type="button" class="btn btn-outline-danger">Kick</button></div>
<div class="col"><button onclick="send_command_to_server(`op {{ player['name'] }}`)" type="button" class="btn btn-warning">OP</button></div>
<div class="col"><button onclick="send_command_to_server(`deop {{ player['name'] }}`)" type="button" class="btn btn-outline-warning">De-OP</button></div>
</div>
{% else %}
<span> Unavailable <br>(Server Offline)</span>
{% end %}
@ -36,24 +36,12 @@
{% end %}
</tbody>
</table>
</div>
</div>
<style>
@media (min-width: 600px) {
.mobile-break { display: none;}
.offline-status {
display: none;
}
}
@media screen and (max-width: 600px) {
.conn-break { display: none; }
}
button.controls {
width: 70px;
}
</style>
<div class="col-xl-6 col-lg-12 col-md-12 col-sm-12 no-scroll" width="100%">
<div class="col-xl-6 col-lg-12 no-scroll">
<h2>{{ translate('serverPlayerManagement', 'bannedPlayers', data['lang']) }}:</h2>
<table class="table table-sm-responsive d-none d-lg-block no-scroll" style="width: 100%;">
<div class="d-none d-lg-block table-responsive">
<table class="table no-scroll w-100">
<thead class="thead">
<tr>
<th scope="col">Player</th>
@ -75,7 +63,9 @@
{% end %}
</tbody>
</table>
<table class="table table-sm-responsive d-block d-lg-none" style="width: 100%;">
</div>
<div class="d-block d-lg-none table-responsive">
<table class="table no-scroll">
<thead class="thead ">
<tr>
<th scope="col">Player</th>
@ -93,4 +83,5 @@
{% end %}
</tbody>
</table>
</div>
</div>

View File

@ -40,31 +40,26 @@
{% include "parts/m_server_controls_list.html %}
</span>
<div class="row">
<div class="col-md-12 col-sm-12" style="overflow-x:auto;">
<div class="col-md-12 col-sm-12 overflow-x-auto">
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fa-regular fa-bell"></i> {{ translate('serverBackups', 'backups',
data['lang']) }} </h4>
{% if data['user_data']['hints'] %}
<span class="too_small" title="{{ translate('serverSchedules', 'cannotSee', data['lang']) }}" ,
data-content="{{ translate('serverSchedules', 'cannotSeeOnMobile', data['lang']) }}" ,
data-placement="bottom"></span>
<span class="too_small" title="{{ translate('serverSchedules', 'cannotSee', data['lang']) }}" , data-content="{{ translate('serverSchedules', 'cannotSeeOnMobile', data['lang']) }}" , data-placement="bottom"></span>
{% end %}
<div><a class="btn btn-info"
href="/panel/add_backup?id={{ data['server_stats']['server_id']['server_id'] }}"><i
class="fas fa-plus-circle"></i> {{ translate('serverBackups', 'newBackup', data['lang']) }}</a>
<div><a class="btn btn-info" href="/panel/add_backup?id={{ data['server_stats']['server_id']['server_id'] }}"><i class="fas fa-plus-circle"></i> {{ translate('serverBackups', 'newBackup', data['lang']) }}</a>
</div>
</div>
<div class="card-body">
{% if len(data['backups']) == 0 %}
<div style="text-align: center; color: grey;">
<div class="text-align-center text-secondary">
<h7>{{ translate('serverBackups', 'no-backup', data['lang']) }}.</h7>
</div>
{% end %}
{% if len(data['backups']) > 0 %}
<div class="d-none d-lg-block">
<table class="table table-hover responsive-table" aria-label="backups list" id="backup_table"
style="table-layout:fixed;">
<table class="table table-hover responsive-table" aria-label="backups list" id="backup_table" style="table-layout:fixed;">
<thead>
<tr class="rounded">
<th scope="col" style="width: 15%; min-width: 10px;">{{ translate('serverBackups', 'name',
@ -87,28 +82,22 @@
<br>
{% if backup.default %}
<span class="badge-pill badge-outline-warning">{{ translate('serverBackups', 'default',
data['lang']) }}</span><small><button class="badge-pill badge-outline-info backup-explain"
data-explain="{{ translate('serverBackups', 'defaultExplain', data['lang'])}}"><i
class="fa-solid fa-question"></i></button></small>
data['lang']) }}</span><small><button class="badge-pill badge-outline-info backup-explain" data-explain="{{ translate('serverBackups', 'defaultExplain', data['lang'])}}"><i class="fa-solid fa-question"></i></button></small>
{% end %}
</td>
<td>
<div id="{{backup.backup_id}}_status">
<button class="btn btn-outline-success backup-status" data-status="{{ backup.status }}"
data-Standby="{{ translate('serverBackups', 'standby', data['lang'])}}"
data-Failed="{{ translate('serverBackups', 'failed', data['lang'])}}"></button>
<button class="btn btn-outline-success backup-status" data-status="{{ backup.status }}" data-Standby="{{ translate('serverBackups', 'standby', data['lang'])}}" data-Failed="{{ translate('serverBackups', 'failed', data['lang'])}}"></button>
</div>
</td>
<td id="{{backup.backup_location}}" class="type">
<p style="overflow: scroll;" class="no-scroll">{{backup.backup_location}}</p>
<p class="no-scroll">{{backup.backup_location}}</p>
</td>
<td id="{{backup.max_backups}}" class="trigger" style="overflow: scroll; max-width: 30px;">
<td id="{{backup.max_backups}}" class="trigger overflow-scroll" style="max-width: 30px;">
<p>{{backup.max_backups}}</p>
</td>
<td id="backup_edit" class="action">
<button
onclick="window.location.href=`/panel/edit_backup?id={{ data['server_stats']['server_id']['server_id'] }}&backup_id={{backup.backup_id}}`"
class="btn btn-info">
<button onclick="window.location.href=`/panel/edit_backup?id={{ data['server_stats']['server_id']['server_id'] }}&backup_id={{backup.backup_id}}`" class="btn btn-info">
<i class="fas fa-pencil-alt"></i>
</button>
{% if not backup.default %}
@ -116,9 +105,7 @@
<i class="fas fa-trash" aria-hidden="true"></i>
</button>
{% end %}
<button data-backup={{ backup.backup_id }} data-toggle="tooltip"
title="{{ translate('serverBackups', 'run', data['lang']) }}"
class="btn btn-outline-warning run-backup backup_now_button">
<button data-backup={{ backup.backup_id }} data-toggle="tooltip" title="{{ translate('serverBackups', 'run', data['lang']) }}" class="btn btn-outline-warning run-backup backup_now_button">
<i class="fa-solid fa-forward"></i>
</button>
</td>
@ -128,8 +115,7 @@
</table>
</div>
<div class="d-block d-lg-none">
<table aria-label="backups list" class="table table-hover responsive-table" id="backup_table_mini"
style="table-layout:fixed;">
<table aria-label="backups list" class="table table-hover responsive-table" id="backup_table_mini" style="table-layout:fixed;">
<thead>
<tr class="rounded">
<th style="width: 40%; min-width: 10px;">Name
@ -145,22 +131,16 @@
<p>{{backup.backup_name}}</p>
<br>
<div id="{{backup.backup_id}}_status">
<button class="btn btn-outline-success backup-status" data-status="{{ backup.status }}"
data-Standby="{{ translate('serverBackups', 'standby', data['lang'])}}"
data-Failed="{{ translate('serverBackups', 'failed', data['lang'])}}"></button>
<button class="btn btn-outline-success backup-status" data-status="{{ backup.status }}" data-Standby="{{ translate('serverBackups', 'standby', data['lang'])}}" data-Failed="{{ translate('serverBackups', 'failed', data['lang'])}}"></button>
</div>
<br>
{% if backup.default %}
<span class="badge-pill badge-outline-warning">{{ translate('serverBackups', 'default',
data['lang']) }}</span><small><button class="badge-pill badge-outline-info backup-explain"
data-explain="{{ translate('serverBackups', 'defaultExplain', data['lang'])}}"><i
class="fa-solid fa-question"></i></button></small>
data['lang']) }}</span><small><button class="badge-pill badge-outline-info backup-explain" data-explain="{{ translate('serverBackups', 'defaultExplain', data['lang'])}}"><i class="fa-solid fa-question"></i></button></small>
{% end %}
</td>
<td id="backup_edit" class="action">
<button
onclick="window.location.href=`/panel/edit_backup?id={{ data['server_stats']['server_id']['server_id'] }}&backup_id={{backup.backup_id}}`"
class="btn btn-info">
<button onclick="window.location.href=`/panel/edit_backup?id={{ data['server_stats']['server_id']['server_id'] }}&backup_id={{backup.backup_id}}`" class="btn btn-info">
<i class="fas fa-pencil-alt"></i>
</button>
{% if not backup.default %}
@ -168,9 +148,7 @@
<i class="fas fa-trash" aria-hidden="true"></i>
</button>
{% end %}
<button data-backup={{ backup.backup_id }} data-toggle="tooltip"
title="{{ translate('serverBackups', 'run', data['lang']) }}"
class="btn btn-outline-warning test-socket backup_now_button">
<button data-backup={{ backup.backup_id }} data-toggle="tooltip" title="{{ translate('serverBackups', 'run', data['lang']) }}" class="btn btn-outline-warning test-socket backup_now_button">
<i class="fa-solid fa-forward"></i>
</button>
</td>
@ -193,47 +171,7 @@
</div>
<style>
/* Remove default bullets */
.tree-view,
.tree-nested {
list-style-type: none;
margin: 0;
padding: 0;
margin-left: 10px;
}
/* Style the items */
.tree-item,
.files-tree-title {
cursor: pointer;
user-select: none;
/* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder {
display: inline-block;
}
.tree-caret .fa-folder-open {
display: none;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down .fa-folder {
display: none;
}
.tree-caret-down .fa-folder-open {
display: inline-block;
}
/* Hide the nested list */
.tree-nested {
display: none;
}
</style>
<link rel="stylesheet" href="/static/assets/css/partial/crafty-backup.css">
<!-- content-wrapper ends -->
{% end %}
@ -510,8 +448,8 @@
\n<div id="${dpath}" data-path="${dpath}" data-name="${filename}" class="tree-caret tree-ctx-item tree-folder">
<input type="checkbox" class="checkBoxClass excluded" value="${dpath}" ${checked}>
<span id="${dpath}span" class="files-tree-title" data-path="${dpath}" data-name="${filename}" onclick="getDirView(event)">
<i style="color: var(--info);" class="far fa-folder"></i>
<i style="color: var(--info);" class="far fa-folder-open"></i>
<i class="text-info far fa-folder"></i>
<i class="text-info far fa-folder-open"></i>
<strong>${filename}</strong>
</span>
</input></div><li>`

View File

@ -43,12 +43,10 @@
<div class="col-md-6 col-sm-12">
<br>
<br>
<div id="{{data['backup_config'].get('backup_id', None)}}_status" class="progress"
style="height: 15px; display: none;">
<div id="{{data['backup_config'].get('backup_id', None)}}_status" class="progress" style="height: 15px; display: none;">
</div>
{% if data['backing_up'] %}
<p>Backing up <i class="fas fa-spin fa-spinner"></i> <span
id="total_files">{{data['server_stats']['world_size']}}</span></p>
<p>Backing up <i class="fas fa-spin fa-spinner"></i> <span id="total_files">{{data['server_stats']['world_size']}}</span></p>
{% end %}
<br>
@ -63,43 +61,32 @@
<label for="backup_name">{{ translate('serverBackups', 'name', data['lang']) }}
{% if data["backup_config"].get("default", None) %}
&nbsp;&nbsp; <span class="badge-pill badge-outline-warning">{{ translate('serverBackups', 'default',
data['lang']) }}</span><small><button class="badge-pill badge-outline-info backup-explain"
data-explain="{{ translate('serverBackups', 'defaultExplain', data['lang'])}}"><i
class="fa-solid fa-question"></i></button></small>
data['lang']) }}</span><small><button class="badge-pill badge-outline-info backup-explain" data-explain="{{ translate('serverBackups', 'defaultExplain', data['lang'])}}"><i class="fa-solid fa-question"></i></button></small>
{% end %}
</label>
{% if data["backup_config"].get("backup_id", None) %}
<input type="text" class="form-control" name="backup_name" id="backup_name"
value="{{ data['backup_config']['backup_name'] }}">
<input type="text" class="form-control" name="backup_name" id="backup_name" value="{{ data['backup_config']['backup_name'] }}">
{% else %}
<input type="text" class="form-control" name="backup_name" id="backup_name"
placeholder="{{ translate('serverBackups', 'myBackup', data['lang']) }}">
<input type="text" class="form-control" name="backup_name" id="backup_name" placeholder="{{ translate('serverBackups', 'myBackup', data['lang']) }}">
{% end %}
<br>
<br>
{% if data['super_user'] %}
<label for="server_name">{{ translate('serverBackups', 'storageLocation', data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverBackups', 'storageLocationDesc', data['lang'])
<label for="server_name">{{ translate('serverBackups', 'storageLocation', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverBackups', 'storageLocationDesc', data['lang'])
}}</small> </label>
<input type="text" class="form-control" name="backup_location" id="backup_location"
value="{{ data['backup_config']['backup_location'] }}"
placeholder="{{ translate('serverBackups', 'storageLocation', data['lang']) }}">
<input type="text" class="form-control" name="backup_location" id="backup_location" value="{{ data['backup_config']['backup_location'] }}" placeholder="{{ translate('serverBackups', 'storageLocation', data['lang']) }}">
{% end %}
</div>
<div class="form-group">
<label for="server_path">{{ translate('serverBackups', 'maxBackups', data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverBackups', 'maxBackupsDesc', data['lang'])
<label for="server_path">{{ translate('serverBackups', 'maxBackups', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverBackups', 'maxBackupsDesc', data['lang'])
}}</small> </label>
<input type="text" class="form-control" name="max_backups" id="max_backups"
value="{{ data['backup_config']['max_backups'] }}"
placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}">
<input type="text" class="form-control" name="max_backups" id="max_backups" value="{{ data['backup_config']['max_backups'] }}" placeholder="{{ translate('serverBackups', 'maxBackups', data['lang']) }}">
</div>
<div class="form-group">
<div class="custom-control custom-switch">
{% if data['backup_config']['compress'] %}
<input type="checkbox" class="custom-control-input" id="compress" name="compress" checked=""
value="True">
<input type="checkbox" class="custom-control-input" id="compress" name="compress" checked="" value="True">
{% else %}
<input type="checkbox" class="custom-control-input" id="compress" name="compress" value="True">
{% end %}
@ -110,8 +97,7 @@
<div class="form-group">
<div class="custom-control custom-switch">
{% if data['backup_config']['shutdown']%}
<input type="checkbox" class="custom-control-input" id="shutdown" name="shutdown" checked=""
value="True">
<input type="checkbox" class="custom-control-input" id="shutdown" name="shutdown" checked="" value="True">
{% else %}
<input type="checkbox" class="custom-control-input" id="shutdown" name="shutdown" value="True">
{% end %}
@ -123,13 +109,10 @@
<div class="custom-control custom-switch">
{% if data['backup_config']['before'] %}
<input type="checkbox" class="custom-control-input" id="before-check" name="before-check" checked>
<input type="text" class="form-control hidden-input" name="before" id="backup_before"
value="{{ data['backup_config']['before'] }}" placeholder="We enter the / for you"
style="display: inline-block;">
<input type="text" class="form-control hidden-input d-inline-block" name="before" id="backup_before" value="{{ data['backup_config']['before'] }}" placeholder="We enter the / for you">
{% else %}
<input type="checkbox" class="custom-control-input" id="before-check" name="before-check">
<input type="text" class="form-control hidden-input" name="before" id="backup_before" value=""
placeholder="We enter the / for you." style="display: none;">
<input type="text" class="form-control hidden-input" name="before" id="backup_before" value="" placeholder="We enter the / for you." style="display: none;">
{% end %}
<label for="before-check" class="custom-control-label">{{
translate('serverBackups', 'before', data['lang']) }}</label>
@ -139,14 +122,11 @@
<div class="custom-control custom-switch">
{% if data['backup_config']['after'] %}
<input type="checkbox" class="custom-control-input" id="after-check" name="after-check" checked>
<input type="text" class="form-control hidden-input" name="after" id="backup_after"
value="{{ data['backup_config']['after'] }}" placeholder="We enter the / for you"
style="display: inline-block;">
<input type="text" class="form-control hidden-input d-inline-block" name="after" id="backup_after" value="{{ data['backup_config']['after'] }}" placeholder="We enter the / for you">
<br>
{% 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;">
<input type="text" class="form-control hidden-input" name="after" id="backup_after" value="" placeholder="We enter the / for you." style="display: none;">
{% end %}
<label for="after-check" class="custom-control-label">{{
translate('serverBackups', 'after', data['lang']) }}</label>
@ -156,8 +136,7 @@
<label for="server">{{ translate('serverBackups', 'exclusionsTitle', data['lang']) }} <small> - {{
translate('serverBackups', 'excludedChoose', data['lang']) }}</small></label>
<br>
<button class="btn btn-primary mr-2" id="root_files_button"
data-server_path="{{ data['server_stats']['server_id']['path']}}" type="button">{{
<button class="btn btn-primary mr-2" id="root_files_button" data-server_path="{{ data['server_stats']['server_id']['path']}}" type="button">{{
translate('serverBackups', 'clickExclude', data['lang']) }}</button>
</div>
<div class="modal fade" id="dir_select" tabindex="-1" aria-labelledby="dir_select" aria-hidden="true">
@ -171,8 +150,7 @@
</button>
</div>
<div class="modal-body">
<div class="tree-ctx-item" id="main-tree-div" data-path=""
style="overflow: scroll; max-height:75%;">
<div class="tree-ctx-item overflow-scroll mh-75" id="main-tree-div" data-path="">
<input type="checkbox" id="main-tree-input" name="root_path" value="" disabled>
<span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path="">
<i class="far fa-folder"></i>
@ -183,10 +161,8 @@
</div>
</div>
<div class="modal-footer">
<button type="button" id="modal-cancel" class="btn btn-secondary" data-dismiss="modal"><i
class="fa-solid fa-xmark"></i></button>
<button type="button" id="modal-okay" data-dismiss="modal" class="btn btn-primary"><i
class="fa-solid fa-thumbs-up"></i></button>
<button type="button" id="modal-cancel" class="btn btn-secondary" data-dismiss="modal"><i class="fa-solid fa-xmark"></i></button>
<button type="button" id="modal-okay" data-dismiss="modal" class="btn btn-primary"><i class="fa-solid fa-thumbs-up"></i></button>
</div>
</div>
</div>
@ -216,16 +192,13 @@
{% for backup in data['backup_list'] %}
<tr>
<td>
<a href="/panel/download_backup?file={{ backup['path'] }}&id={{ data['server_stats']['server_id']['server_id'] }}&backup_id={{ data['backup_config']['backup_id']}}"
class="btn btn-primary">
<a href="/panel/download_backup?file={{ backup['path'] }}&id={{ data['server_stats']['server_id']['server_id'] }}&backup_id={{ data['backup_config']['backup_id']}}" class="btn btn-primary">
<i class="fas fa-download" aria-hidden="true"></i>
{{ translate('serverBackups', 'download', data['lang']) }}
</a>
<br>
<br>
<button data-file="{{ backup['path'] }}"
data-backup_location="{{ data['backup_config']['backup_location'] }}"
class="btn btn-danger del_button">
<button data-file="{{ backup['path'] }}" data-backup_location="{{ data['backup_config']['backup_location'] }}" class="btn btn-danger del_button">
<i class="fas fa-trash" aria-hidden="true"></i>
{{ translate('serverBackups', 'delete', data['lang']) }}
</button>
@ -269,47 +242,7 @@
</div>
<style>
/* Remove default bullets */
.tree-view,
.tree-nested {
list-style-type: none;
margin: 0;
padding: 0;
margin-left: 10px;
}
/* Style the items */
.tree-item,
.files-tree-title {
cursor: pointer;
user-select: none;
/* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder {
display: inline-block;
}
.tree-caret .fa-folder-open {
display: none;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down .fa-folder {
display: none;
}
.tree-caret-down .fa-folder-open {
display: inline-block;
}
/* Hide the nested list */
.tree-nested {
display: none;
}
</style>
<link rel="stylesheet" href="/static/assets/css/partial/crafty-backup.css">
<!-- content-wrapper ends -->
{% end %}
@ -701,8 +634,8 @@
\n<div id="${dpath}" data-path="${dpath}" data-name="${filename}" class="tree-caret tree-ctx-item tree-folder">
<input type="checkbox" class="checkBoxClass excluded" value="${dpath}" ${checked}>
<span id="${dpath}span" class="files-tree-title" data-path="${dpath}" data-name="${filename}" onclick="getDirView(event)">
<i style="color: var(--info);" class="far fa-folder"></i>
<i style="color: var(--info);" class="far fa-folder-open"></i>
<i class="text-info far fa-folder"></i>
<i class="text-info far fa-folder-open"></i>
<strong>${filename}</strong>
</span>
</input></div><li>`

View File

@ -56,7 +56,7 @@
<label for="server_path">{{ translate('serverConfig', 'serverPath', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverConfig', 'serverPathDesc', data['lang']) }}</small>
</label>
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<span style="color: gray; font-size: .9vw;">{{ data['server_stats']['server_id']['path'] }}</span>
<span class="text-secondary" style="font-size: .9vw;">{{ data['server_stats']['server_id']['path'] }}</span>
🔒
</div>
@ -100,7 +100,7 @@
{% else %}
<label for="execution_command">{{ translate('serverConfig', 'serverExecutionCommand', data['lang']) }}
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<span style="color: gray; font-size: .9vw;">{{ data['server_stats']['server_id']['execution_command'] }}</span> 🔒
<span class="text-secondary" style="font-size: .9vw;">{{ data['server_stats']['server_id']['execution_command'] }}</span> 🔒
</div>
<br>
{% end %}

File diff suppressed because it is too large Load Diff

View File

@ -41,8 +41,7 @@
<div class="col-md-12">
<div class="input-group">
<div id="virt_console" class=""
style="width: 100%; font-size: .8em; padding: 5px 10px; border: 1px solid var(--outline); background-color:var(--card-banner-bg);height:500px; overflow: scroll;">
<div id="virt_console" class="virt_console">
</div>
</div>
<br />
@ -51,12 +50,9 @@
<br />
<br />
<h4>{{ translate('serverDetails', 'filterList', data['lang']) }}</h4>
<ul id="ignored-words" style="list-style: None;"></ul>
<ul id="ignored-words" class="list-group"></ul>
<br />
</div>
</div>
</div>
</div>
@ -148,8 +144,8 @@
// Display filtered word
words.push(word);
$("#ignored-words").append(
`<li id=${safe_word.replaceAll(" ", "-")}>` +
"<div class='card-header header-sm d-flex justify-content-between align-items-center'>" +
`<li id=${safe_word.replaceAll(" ", "-")} class="list-group-item">` +
"<div class='text-sm d-flex justify-content-between align-items-center'>" +
`${word}&nbsp;<button class='btn btn-danger' onclick='deleteWord("${word}")' >` +
"<i class='fas fa-trash'></i></button></div></li>"
);
@ -163,8 +159,8 @@
let safe_word = sanitize(word);
$("#ignored-words").append(
`<li id=${safe_word.replaceAll(" ", "-")}>` +
"<div class='card-header header-sm d-flex justify-content-between align-items-center'>" +
`<li id=${safe_word.replaceAll(" ", "-")} class="list-group-item">` +
"<div class='text-sm d-flex justify-content-between align-items-center'>" +
`${word}&nbsp;<button class='btn btn-danger' onclick='deleteWord("${word}")' >` +
"<i class='fas fa-trash'></i></button></div></li>"
);

View File

@ -48,12 +48,10 @@
</select>
</div>
</div>
<button style="float: right; visibility: hidden;" class="btn btn-outline-success reset-button"
id="reset-button"><i class="fas fa-undo"></i>&nbsp;{{ translate('serverMetrics', 'resetZoom', data['lang'])
<button class="btn btn-outline-success reset-button float-right d-none" id="reset-button" hidden><i class="fas fa-undo"></i>&nbsp;{{ translate('serverMetrics', 'resetZoom', data['lang'])
}}</button>
{% if data['user_data']['hints'] %}
<span data-html="true" class="hints text-center" title="<i class='fa fa-info-circle'></i> " ,
data-content="{{
<span data-html="true" class="hints text-center" title="<i class='fa fa-info-circle'></i> " , data-content="{{
translate('serverMetrics', 'zoomHint1' , data['lang'])}} <br> <br> {{ translate('serverMetrics', 'zoomHint2', data['lang'])}}" , data-placement="top"></span>
{% end %}
<div class="chart-wrapper">
@ -72,11 +70,6 @@
.chart-wrapper {
height: 65vh;
}
.popover-body {
color: white !important;
;
}
</style>
<script type="text/javascript">
const serverId = new URLSearchParams(document.location.search).get('id')
@ -135,7 +128,8 @@
zoom: {
onZoom({ hist_chart }) {
console.log("zooming");
document.getElementById("reset-button").style.visibility = "visible";
document.getElementById("reset-button").classList.remove("d-none");
document.getElementById("reset-button").classList.add("d-block");
zoomed = true;
},
wheel: {
@ -232,7 +226,8 @@
console.log("resetting zoom");
zoomed = false;
hist_chart.resetZoom();
document.getElementById("reset-button").style.visibility = "hidden";
document.getElementById("reset-button").classList.add("d-none");
document.getElementById("reset-button").classList.remove("d-block");
});
});
</script>

View File

@ -37,24 +37,19 @@
<div class="row">
<div class="col-md-8 col-sm-8">
{% if data['new_schedule'] == True %}
<form class="forms-sample" method="post" id="new_schedule_form"
action="/panel/new_schedule?id={{ data['server_stats']['server_id']['server_id'] }}">
<form class="forms-sample" method="post" id="new_schedule_form" action="/panel/new_schedule?id={{ data['server_stats']['server_id']['server_id'] }}">
{% else %}
<form class="forms-sample" method="post" id="schedule_form"
action="/panel/edit_schedule?id={{ data['server_stats']['server_id']['server_id'] }}&sch_id={{ data['schedule']['schedule_id'] }}">
<form class="forms-sample" method="post" id="schedule_form" action="/panel/edit_schedule?id={{ data['server_stats']['server_id']['server_id'] }}&sch_id={{ data['schedule']['schedule_id'] }}">
{% end %}
<div class="form-group">
<label for="name">{{ translate('serverSchedules', 'name' , data['lang']) }}</label>
<input type="input" class="form-control" name="name" id="name_input"
value="{{ data['schedule']['name']}}" maxlength="30" placeholder="Name" required>
<input type="input" class="form-control" name="name" id="name_input" value="{{ data['schedule']['name']}}" maxlength="30" placeholder="Name" required>
</div>
<div class="form-group">
<label for="difficulty">{{ translate('serverScheduleConfig', 'select' , data['lang']) }}<small
class="text-muted ml-1"></small> </label><br>
<select id="difficulty" name="difficulty" onchange="basicAdvanced(this);"
class="form-control form-control-lg select-css" value="{{ data['schedule']['difficulty'] }}">
<label for="difficulty">{{ translate('serverScheduleConfig', 'select' , data['lang']) }}<small class="text-muted ml-1"></small> </label><br>
<select id="difficulty" name="difficulty" onchange="basicAdvanced(this);" class="form-control form-control-lg select-css" value="{{ data['schedule']['difficulty'] }}">
<option id="basic" value="basic">{{ translate('serverScheduleConfig', 'basic' , data['lang']) }}
</option>
<option id="advanced" value="advanced">{{ translate('serverScheduleConfig', 'cron' , data['lang'])
@ -64,10 +59,8 @@
</select>
</div>
<div class="form-group">
<label for="server_name">{{ translate('serverSchedules', 'action' , data['lang']) }}<small
class="text-muted ml-1"></small> </label><br>
<select id="action" name="action" onchange="yesnoCheck(this);"
class="form-control form-control-lg select-css" value="{{ data['schedule']['action'] }}">
<label for="server_name">{{ translate('serverSchedules', 'action' , data['lang']) }}<small class="text-muted ml-1"></small> </label><br>
<select id="action" name="action" onchange="yesnoCheck(this);" class="form-control form-control-lg select-css" value="{{ data['schedule']['action'] }}">
<option id="start" value="start">{{ translate('serverScheduleConfig', 'start' , data['lang']) }}
</option>
<option id="restart" value="restart">{{ translate('serverScheduleConfig', 'restart' ,
@ -79,9 +72,9 @@
<option id="command" value="command">{{ translate('serverScheduleConfig', 'custom' , data['lang'])
}}</option>
</select>
<div id="ifBackup" style="display: none;">
<div id="ifBackup" class="d-none">
<br>
<label for="action_id">{{ translate('serverSchedules', 'actionId' , data['lang']) }}<small
<label id="action_id_label" for="action_id" data-backup-translate="{{ translate('serverSchedules', 'backupPol', data['lang']) }}" data-action-translate="{{ translate('serverSchedules', 'actionId', data['lang']) }}"><small
class="text-muted ml-1"></small> </label><br>
<select id="action_id" name="action_id"
class="form-control form-control-lg select-css" value="{{ data['schedule']['action_id'] }}">
@ -100,16 +93,12 @@
</div>
<div id="ifBasic">
<div class="form-group">
<label for="server_path">{{ translate('serverScheduleConfig', 'interval' , data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'interval-explain' ,
<label for="server_path">{{ translate('serverScheduleConfig', 'interval' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'interval-explain' ,
data['lang']) }}</small> </label>
<input type="number" class="form-control" name="interval" id="interval"
value="{{ data['schedule']['interval'] }}" placeholder="Interval" required min="1">
<input type="number" class="form-control" name="interval" id="interval" value="{{ data['schedule']['interval'] }}" placeholder="Interval" required min="1">
<br>
<br>
<select id="interval_type" onchange="ifDays(this);" name="interval_type"
class="form-control form-control-lg select-css"
value="{{ data['schedule']['interval_type'] }}">
<select id="interval_type" onchange="ifDays(this);" name="interval_type" class="form-control form-control-lg select-css" value="{{ data['schedule']['interval_type'] }}">
<option id="days" value="days">{{ translate('serverScheduleConfig', 'days' , data['lang']) }}
</option>
<option id="hours" value="hours">{{ translate('serverScheduleConfig', 'hours' , data['lang']) }}
@ -118,48 +107,38 @@
data['lang']) }}</option>
</select>
</div>
<div id="ifDays" style="display: block;">
<div id="ifDays" class="d-block">
<div class="form-group">
<label for="time">{{ translate('serverScheduleConfig', 'time' , data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'time-explain' ,
<label for="time">{{ translate('serverScheduleConfig', 'time' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'time-explain' ,
data['lang']) }}</small> </label>
<input type="time" class="form-control" name="start_time" id="time"
value="{{ data['schedule']['time'] }}" placeholder="Time" required>
<input type="time" class="form-control" name="start_time" id="time" value="{{ data['schedule']['time'] }}" placeholder="Time" required>
</div>
</div>
</div>
<div id="ifYes" style="display: none;">
<div id="ifYes" class="d-none">
<div class="form-group">
<label for="command">{{ translate('serverScheduleConfig', 'command' , data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'command-explain' ,
<label for="command">{{ translate('serverScheduleConfig', 'command' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'command-explain' ,
data['lang']) }}</small> </label>
<input type="input" class="form-control" name="command" id="command_input"
value="{{ data['schedule']['command'] }}" placeholder="Command" required>
<input type="input" class="form-control" name="command" id="command_input" value="{{ data['schedule']['command'] }}" placeholder="Command" required>
</div>
</div>
<div id="ifAdvanced" style="display: none;">
<div id="ifAdvanced" class="d-none">
<div class="form-group">
<label for="cron">{{ translate('serverScheduleConfig', 'cron' , data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'cron-explain' , data['lang'])
<label for="cron">{{ translate('serverScheduleConfig', 'cron' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'cron-explain' , data['lang'])
}}</small> </label>
<input type="input" class="form-control" name="cron_string" id="cron"
value="{{ data['schedule']['cron_string'] }}" placeholder="* * * * *">
<input type="input" class="form-control" name="cron_string" id="cron" value="{{ data['schedule']['cron_string'] }}" placeholder="* * * * *">
</div>
</div>
<div id="ifReaction" style="display: none;">
<div id="ifReaction" class="d-none">
<div class="form-group">
<label for="delay">{{ translate('serverScheduleConfig', 'offset' , data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'offset-explain' ,
<label for="delay">{{ translate('serverScheduleConfig', 'offset' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'offset-explain' ,
data['lang']) }}</small> </label>
<input type="number" class="form-control" name="delay" id="delay"
value="{{ data['schedule']['delay']}}">
<input type="number" class="form-control" name="delay" id="delay" value="{{ data['schedule']['delay']}}">
<br>
<br>
<label for="parent">{{ translate('serverScheduleConfig', 'parent' , data['lang']) }} <small
class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'parent-explain' ,
<label for="parent">{{ translate('serverScheduleConfig', 'parent' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'parent-explain' ,
data['lang']) }}</small> </label>
<select id="parent" name="parent" class="form-control form-control-lg select-css"
value="{{ data['schedule']['action'] }}">
<select id="parent" name="parent" class="form-control form-control-lg select-css" value="{{ data['schedule']['action'] }}">
{% if data['parent'] %}
<option id="{{data['parent']['schedule_id']}}" value="{{data['parent']['schedule_id']}}">
{{data['parent']['name']}} | {{data['parent']['command']}} | {{data['parent']['interval']}}
@ -196,8 +175,7 @@
<div class="form-check-flat">
<label for="enabled" class="form-check-label ml-4 mb-4">
<input type="checkbox" class="form-check-input" id="enabled" name="enabled" checked=""
value="1">{{ translate('serverScheduleConfig', 'enabled' , data['lang']) }}
<input type="checkbox" class="form-check-input" id="enabled" name="enabled" checked="" value="1">{{ translate('serverScheduleConfig', 'enabled' , data['lang']) }}
</label>
</div>
@ -210,19 +188,17 @@
</div>
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-save"></i> {{
translate('serverConfig', 'save', data['lang']) }}</button>
<button type="reset"
onclick="location.href=`/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=schedules`"
class="btn btn-light"><i class="fas fa-times"></i> {{ translate('serverConfig', 'cancel',
<button type="reset" onclick="location.href=`/panel/server_detail?id={{ data['server_stats']['server_id']['server_id'] }}&subpage=schedules`" class="btn btn-light"><i class="fas fa-times"></i> {{ translate('serverConfig', 'cancel',
data['lang']) }}</button>
</form>
</div>
<div class="col-sm-4 grid-margin">
<h4>{{ translate('serverScheduleConfig', 'children' , data['lang']) }}</h4>
<ul>
<ul class="list-group">
{% for schedule in data['schedule']['children'] %}
<li style="overflow: auto;"><a
href="/panel/edit_schedule?id={{schedule.server_id}}&sch_id={{schedule.schedule_id}}">{{schedule.name}}
| {{schedule.schedule_id}}</a></li>
<li class="list-group-item">
<a href="/panel/edit_schedule?id={{schedule.server_id}}&sch_id={{schedule.schedule_id}}">{{schedule.name}} | {{schedule.schedule_id}}</a>
</li>
{% end %}
</ul>
</div>
@ -255,17 +231,17 @@
return value
}
console.log(key)
if (key === "interval" && value === ""){
if (key === "interval" && value === "") {
return 0;
}
if (key === "command" && typeof(value === "integer")){
if (key === "command" && typeof (value === "integer")) {
return value.toString();
}else {
} else {
return (isNaN(value) ? value : +value);
}
} else if (value === "" && key == "start_time"){
} else if (value === "" && key == "start_time") {
return "00:00";
}else {
} else {
return value;
}
}
@ -286,13 +262,13 @@
//We need to make sure these are sent regardless of whether or not they're checked
formDataObject.enabled = $("#enabled").prop('checked');
formDataObject.one_time = $("#one_time").prop('checked');
if ($("#difficulty").val() == "reaction"){
if ($("#difficulty").val() == "reaction") {
formDataObject.interval_type = "reaction";
}
if ($("#action").val() != "command"){
if ($("#action").val() != "command") {
formDataObject.command = formDataObject.action + "_server";
}
if (formDataObject.cron_string != ""){
if (formDataObject.cron_string != "") {
formDataObject.interval_type = '';
}
console.log(formDataObject);
@ -300,7 +276,7 @@
let formDataJsonString = JSON.stringify(formDataObject, replacer);
let data = JSON.parse(formDataJsonString)
if (data["action"] === "backup" && !data["action_id"]){
if (data["action"] === "backup" && !data["action_id"]) {
return bootbox.alert("Validation Failed")
}
@ -336,13 +312,13 @@
//We need to make sure these are sent regardless of whether or not they're checked
formDataObject.enabled = $("#enabled").prop('checked');
formDataObject.one_time = $("#one_time").prop('checked');
if ($("#difficulty").val() == "reaction"){
if ($("#difficulty").val() == "reaction") {
formDataObject.interval_type = "reaction";
}
if ($("#action").val() != "command"){
if ($("#action").val() != "command") {
formDataObject.command = formDataObject.action + "_server";
}
if (formDataObject.cron_string != ""){
if (formDataObject.cron_string != "") {
formDataObject.interval_type = '';
}
console.log(formDataObject);
@ -375,57 +351,79 @@
function yesnoCheck() {
if (document.getElementById('action').value == "command") {
document.getElementById("ifYes").style.display = "block";
document.getElementById("ifYes").classList.add("d-block");
document.getElementById("ifYes").classList.remove("d-none");
document.getElementById("command_input").required = true;
} else {
document.getElementById("ifYes").style.display = "none";
document.getElementById("ifYes").classList.add("d-none");
document.getElementById("ifYes").classList.remove("d-block");
document.getElementById("command_input").required = false;
}
if (document.getElementById('action').value == "backup"){
document.getElementById("ifBackup").style.display = "block";
if (document.getElementById('action').value == "backup") {
document.getElementById("ifBackup").classList.add("d-block");
document.getElementById("ifBackup").classList.remove("d-none");
document.getElementById("action_id").required = true;
$("#action_id_label").html($("#action_id_label").attr("data-backup-translate"));
} else {
document.getElementById("ifBackup").style.display = "none";
document.getElementById("ifBackup").classList.remove("d-block");
document.getElementById("ifBackup").classList.add("d-none");
document.getElementById("action_id").required = false;
$("#action_id").val(null);
$("#action_id_label").html($("#action_id_label").attr("data-action-translate"));
}
}
function basicAdvanced() {
if (document.getElementById('difficulty').value == "advanced") {
document.getElementById("ifAdvanced").style.display = "block";
document.getElementById("ifReaction").style.display = "none";
document.getElementById("ifBasic").style.display = "none";
document.getElementById("ifAdvanced").classList.add("d-block");
document.getElementById("ifReaction").classList.add("d-none");
document.getElementById("ifBasic").classList.add("d-none");
document.getElementById("ifAdvanced").classList.remove("d-none");
document.getElementById("ifReaction").classList.remove("d-block");
document.getElementById("ifBasic").classList.remove("d-block");
document.getElementById("delay").required = false;
document.getElementById("parent").required = false;
document.getElementById("interval").required = false;
document.getElementById("time").required = false;
document.getElementById("ifDays").classList.add("d-none");
document.getElementById("ifDays").classList.remove("d-block");
} else if (document.getElementById('difficulty').value == "reaction") {
document.getElementById("ifReaction").style.display = "block";
document.getElementById("ifBasic").style.display = "none";
document.getElementById("ifAdvanced").style.display = "none";
document.getElementById("ifReaction").classList.add("d-block");
document.getElementById("ifBasic").classList.add("d-none");
document.getElementById("ifAdvanced").classList.add("d-none");
document.getElementById("ifReaction").classList.remove("d-none");
document.getElementById("ifBasic").classList.remove("d-block");
document.getElementById("ifAdvanced").classList.remove("d-block");
document.getElementById("delay").required = true;
document.getElementById("parent").required = true;
document.getElementById("interval").required = false;
document.getElementById("time").required = false;
document.getElementById("ifDays").classList.add("d-none");
document.getElementById("ifDays").classList.remove("d-block");
$("#cron").val("");
}
else {
document.getElementById("ifAdvanced").style.display = "none";
document.getElementById("ifReaction").style.display = "none";
document.getElementById("ifBasic").style.display = "block";
document.getElementById("ifAdvanced").classList.add("d-none");
document.getElementById("ifReaction").classList.add("d-none");
document.getElementById("ifAdvanced").classList.remove("d-block");
document.getElementById("ifReaction").classList.remove("d-block");
document.getElementById("ifBasic").classList.add("d-block");
document.getElementById("ifBasic").classList.remove("d-none");
document.getElementById("delay").required = false;
document.getElementById("parent").required = false;
document.getElementById("interval").required = true;
document.getElementById("time").required = true;
ifDays();
$("#cron").val("");
}
}
function ifDays() {
if (document.getElementById('interval_type').value == "days") {
document.getElementById("ifDays").style.display = "block";
document.getElementById("ifDays").classList.add("d-block");
document.getElementById("ifDays").classList.remove("d-none");
document.getElementById("time").required = true;
} else {
document.getElementById("ifDays").style.display = "none";
document.getElementById("ifDays").classList.add("d-none");
document.getElementById("ifDays").classList.remove("d-block");
document.getElementById("time").required = false;
}
}

View File

@ -41,7 +41,7 @@
</span>
<div class="row">
<div class="col-md-12 col-sm-12" style="overflow-x:auto;">
<div class="col-md-12 col-sm-12 overflow-x-auto">
<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-calendar"></i> {{ translate('serverSchedules',
@ -53,13 +53,13 @@
</div>
<div class="card-body">
{% if len(data['schedules']) == 0 %}
<div style="text-align: center; color: grey;">
<div class="text-align-center text-secondary">
<h7>{{ translate('serverSchedules', 'no-schedule', data['lang']) }} <strong>{{ translate('serverSchedules', 'newSchedule',data['lang']) }}</strong>.</h7>
</div>
{% end %}
{% if len(data['schedules']) > 0 %}
<div class="d-none d-lg-block">
<table class="table table-hover table-responsive" id="schedule_table" style="table-layout:fixed;" aria-describedby="Schedule List">
<table class="table table-hover table-responsive no-scroll" id="schedule_table" style="table-layout:fixed;" aria-describedby="Schedule List">
<thead>
<tr class="rounded">
<th style="width: 5%; min-width: 64px;">{{ translate('serverSchedules', 'enabled',
@ -92,8 +92,8 @@
<td id="{{schedule.action}}">
<p>{{schedule.action}}</p>
</td>
<td id="{{schedule.command}}" style="overflow: scroll; max-width: 30px;">
<p style="overflow: scroll;" class="no-scroll">{{schedule.command}}</p>
<td id="{{schedule.command}}" class="overflow-scroll" style="max-width: 30px;">
<p class="no-scroll">{{schedule.command}}</p>
</td>
<td id="{{schedule.interval}}">
{% if schedule.interval_type != '' and schedule.interval_type != 'reaction' %}
@ -142,8 +142,8 @@
<td id="{{schedule.action}}" class="action">
<p>{{schedule.action}}</p>
</td>
<td id="{{schedule.command}}" class="action" style="overflow: scroll; max-width: 30px;">
<p style="overflow: scroll;">{{schedule.command}}</p>
<td id="{{schedule.command}}" class="action overflow-scroll" style="max-width: 30px;">
<p class="overflow-scroll;">{{schedule.command}}</p>
</td>
<td id="{{schedule.enabled}}" class="enabled">
<button type="button" class="btn btn-sm btn-info btn-toggle schedule-custom-toggle" id="schedule{{schedule.id}}" name="schedule{{schedule.id}}" data-schedule-id="{{schedule.schedule_id}}" data-schedule-enabled="{{ 'true' if schedule.enabled else 'false' }}" data-toggle="button" aria-pressed="true" autocomplete="off">
@ -163,43 +163,42 @@
</button>
</div>
<div class="modal-body">
<ul style="list-style: none;">
<li id="{{schedule.schedule_id}}" class="id" style="border-top: .1em solid gray;">
<ul class="list-group">
<li id="{{schedule.schedule_id}}" class="id list-group-item">
<h4>{{ translate('serverSchedules', 'name', data['lang']) }}</h4>
<p>{{schedule.schedule_id}}</p>
<p class="mb-0">{{schedule.schedule_id}}</p>
</li>
<li id="{{schedule.action}}" class="action" style="border-top: .1em solid gray;">
<li id="{{schedule.action}}" class="action list-group-item">
<h4>{{ translate('serverSchedules', 'action', data['lang']) }}</h4>
<p>{{schedule.action}}</p>
<p class="mb-0">{{schedule.action}}</p>
</li>
<li id="{{schedule.command}}" class="action" style="border-top: .1em solid gray;">
<li id="{{schedule.command}}" class="action list-group-item">
<h4>{{ translate('serverSchedules', 'command', data['lang']) }}</h4>
<p>{{schedule.command}}</p>
<p class="mb-0">{{schedule.command}}</p>
</li>
<li id="{{schedule.interval}}" class="action" style="border-top: .1em solid gray;">
<li id="{{schedule.interval}}" class="action list-group-item">
{% if schedule.interval != '' %}
<h4>{{ translate('serverSchedules', 'interval', data['lang']) }}</h4>
<p>{{ translate('serverSchedules', 'every', data['lang']) }} {{schedule.interval}}
<p class="mb-0">{{ translate('serverSchedules', 'every', data['lang']) }} {{schedule.interval}}
{{schedule.interval_type}}</p>
{% elif schedule.interval_type == 'reaction' %}
<h4>{{ translate('serverSchedules', 'interval', data['lang']) }}</h4>
<p>{{schedule.interval_type}}<br><br>{{ translate('serverSchedules', 'child',
<p class="mb-0">{{schedule.interval_type}}<br><br>{{ translate('serverSchedules', 'child',
data['lang']) }}: {{ schedule.parent }}</p>
{% else %}
<h4>{{ translate('serverSchedules', 'interval', data['lang']) }}</h4>
<p>{{ translate('serverSchedules', 'cron', data['lang']) }}: {{schedule.cron_string}}
</p>
<p class="mb-0">{{ translate('serverSchedules', 'cron', data['lang']) }}: {{schedule.cron_string}}</p>
{% end %}
</li>
<li id="{{schedule.start_time}}" class="action" style="border-top: .1em solid gray;">
<li id="{{schedule.start_time}}" class="action list-group-item">
<h4>{{ translate('serverSchedules', 'nextRun', data['lang']) }}</h4>
{% if schedule.next_run %}
<p>{{schedule.next_run}}</p>
<p class="mb-0">{{schedule.next_run}}</p>
{% else %}
<p>zzzzzzz</p>
<p class="mb-0">zzzzzzz</p>
{% end %}
</li>
<li id="{{schedule.enabled}}" class="action" style="border-top: .1em solid gray; border-bottom: .1em solid gray">
<li id="{{schedule.enabled}}" class="action list-group-item">
<h4>{{ translate('serverSchedules', 'enabled', data['lang']) }}</h4>
<input type="checkbox" class="schedule-enabled-toggle" data-schedule-id="{{schedule.schedule_id}}" data-schedule-enabled="{{ 'true' if schedule.enabled else 'false' }}">
</li>
@ -235,11 +234,6 @@
</div>
</div>
<style>
.popover-body {
color: white !important;
;
}
.toggle-handle {
background-color: white !important;
}

View File

@ -41,96 +41,66 @@
</span>
<div class="col-md-12">
<button id="to-bottom" style="visibility: hidden; float: right;" class="btn btn-outline-success" hidden>{{
translate('serverDetails', 'reset', data['lang']) }}</button>
<button id="to-bottom" class="btn btn-outline-success" hidden>
{{ translate('serverDetails', 'reset', data['lang']) }}
</button>
<div class="input-group">
<div id="virt_console" class=""
style="width: 100%; font-size: .8em; padding: 5px 10px; border: 1px solid var(--outline); background-color:var(--card-banner-bg);height:500px; overflow: scroll;">
<div id="virt_console">
</div>
</div>
<br />
<div style="gap: 0.5rem;" class="input-group flex-wrap">
<input style="min-width: 10rem;" type="text" class="form-control" id="server_command"
name="server_command" placeholder="{{ translate('serverTerm', 'commandInput', data['lang']) }}"
autofocus="">
<div class="input-group flex-wrap server_command">
<input type="text" class="form-control server_command" id="server_command" name="server_command" placeholder="{{ translate('serverTerm', 'commandInput', data['lang']) }}" autofocus="">
<span class="input-group-btn ml-5">
<button id="submit" class="btn btn-sm btn-info" type="button">{{ translate('serverTerm', 'sendCommand',
data['lang']) }}</button>
<button id="submit" class="btn btn-sm btn-info" type="button">{{ translate('serverTerm', 'sendCommand', data['lang']) }}</button>
</span>
</div>
{% if data['permissions']['Commands'] in data['user_permissions'] %}
{% if data['importing'] and data['server_stats']['running']%}
<div id="update_control_buttons"
class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0"
style="visibility: visible">
<button onclick="" id="start-btn" style="max-width: 7rem;"
class="btn btn-warning m-1 flex-grow-1 disabled"><i
class="fa fa-spinner fa-spin"></i>&nbsp;{{translate('serverTerm', 'installing', data['lang'])
<div id="update_control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0">
<button onclick="" id="start-btn" class="btn btn-warning m-1 flex-grow-1 term-btn disabled"><i class="fa fa-spinner fa-spin"></i>&nbsp;{{translate('serverTerm', 'installing', data['lang'])
}}</button>
<button onclick="" id="restart-btn" style="max-width: 7rem;"
class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart',
<button onclick="" id="restart-btn" class="btn btn-outline-primary m-1 flex-grow-1 term-btn disabled">{% raw translate('serverTerm', 'restart',
data['lang']) %}</button>
<button onclick="" id="stop-btn" style="max-width: 7rem;"
class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang'])
<button onclick="" id="stop-btn" class="btn btn-danger m-1 flex-grow-1 term-btn disabled">{{ translate('serverTerm', 'stop', data['lang'])
}}</button>
</div>
{% elif data['server_stats']['updating']%}
<div id="update_control_buttons"
class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0"
style="visibility: visible">
<button onclick="" id="start-btn" style="max-width: 7rem;"
class="btn btn-warning m-1 flex-grow-1 disabled"><i class="fa fa-spinner fa-spin"></i>&nbsp;{{
<div id="update_control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0">
<button onclick="" id="start-btn" class="btn btn-warning m-1 flex-grow-1 term-btn disabled"><i class="fa fa-spinner fa-spin"></i>&nbsp;{{
translate('serverTerm', 'updating', data['lang']) }}</button>
<button onclick="" id="restart-btn" style="max-width: 7rem;"
class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart',
<button onclick="" id="restart-btn" class="btn btn-outline-primary m-1 flex-grow-1 term-btn disabled">{% raw translate('serverTerm', 'restart',
data['lang']) %}</button>
<button onclick="" id="stop-btn" style="max-width: 7rem;"
class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang'])
<button onclick="" id="stop-btn" class="btn btn-danger m-1 flex-grow-1 term-btn disabled">{{ translate('serverTerm', 'stop', data['lang'])
}}</button>
</div>
{% elif data['waiting_start'] %}
<div id="control_buttons"
class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0"
style="visibility: visible">
<button onclick="" id="start-btn" style="max-width: 7rem; white-space: nowrap;"
class="btn btn-secondary m-1 flex-grow-1 disabled" data-toggle="tooltip"
title="{{ translate('serverTerm', 'delay-explained', data['lang'])}}">{{ translate('serverTerm',
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0">
<button onclick="" id="start-btn" class="btn btn-secondary m-1 flex-grow-1 term-btn disabled" data-toggle="tooltip" title="{{ translate('serverTerm', 'delay-explained', data['lang'])}}">{{ translate('serverTerm',
'starting', data['lang']) }}</button>
<button onclick="" id="restart-btn" style="max-width: 7rem;"
class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart',
<button onclick="" id="restart-btn" class="btn btn-outline-primary m-1 flex-grow-1 term-btn disabled">{% raw translate('serverTerm', 'restart',
data['lang']) %}</button>
<button onclick="" id="stop-btn" style="max-width: 7rem;"
class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang'])
<button onclick="" id="stop-btn" class="btn btn-danger m-1 flex-grow-1 term-btn disabled">{{ translate('serverTerm', 'stop', data['lang'])
}}</button>
</div>
{% elif data['importing'] %}
<div id="control_buttons"
class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0"
style="visibility: visible">
<button onclick="" id="start-btn" style="max-width: 12rem; white-space: nowrap;"
class="btn btn-secondary m-1 flex-grow-1 disabled"><i class="fa fa-spinner fa-spin"></i> {{
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0">
<button onclick="" id="start-btn" class="btn btn-secondary m-1 flex-grow-1 term-btn disabled"><i class="fa fa-spinner fa-spin"></i> {{
translate('serverTerm', 'importing',
data['lang']) }}</button>
<button onclick="" id="restart-btn" style="max-width: 7rem;"
class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart',
<button onclick="" id="restart-btn" class="btn btn-outline-primary m-1 flex-grow-1 term-btn disabled">{% raw translate('serverTerm', 'restart',
data['lang']) %}</button>
<button onclick="" id="stop-btn" style="max-width: 7rem;"
class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate('serverTerm', 'stop', data['lang'])
<button onclick="" id="stop-btn" class="btn btn-danger m-1 flex-grow-1 term-btn disabled">{{ translate('serverTerm', 'stop', data['lang'])
}}</button>
</div>
{% else %}
<div id="control_buttons"
class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0"
style="visibility: visible">
<button onclick="send_command(serverId, 'start_server');" id="start-btn" style="max-width: 7rem;"
class="btn btn-primary m-1 flex-grow-1">{{ translate('serverTerm', 'start', data['lang']) }}</button>
<button onclick="send_command(serverId, 'restart_server');" id="restart-btn" style="max-width: 7rem;"
class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate('serverTerm', 'restart', data['lang'])
<div id="control_buttons" class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0">
<button onclick="send_command(serverId, 'start_server');" id="start-btn" class="btn btn-primary m-1 flex-grow-1 term-btn">{{ translate('serverTerm', 'start', data['lang']) }}</button>
<button onclick="send_command(serverId, 'restart_server');" id="restart-btn" class="btn btn-outline-primary m-1 flex-grow-1 term-btn">{% raw translate('serverTerm', 'restart', data['lang'])
%}</button>
<button onclick="send_command(serverId, 'stop_server');" id="stop-btn" style="max-width: 7rem;"
class="btn btn-danger m-1 flex-grow-1">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
<button onclick="send_command(serverId, 'stop_server');" id="stop-btn" class="btn btn-danger m-1 flex-grow-1 term-btn">{{ translate('serverTerm', 'stop', data['lang']) }}</button>
</div>
{% end %}
{% end %}
@ -140,21 +110,7 @@
</div>
</div>
</div>
<style>
#virt_console::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
#virt_console {
-ms-overflow-style: none;
/* IE and Edge */
scrollbar-width: none;
/* Firefox */
font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;
white-space: pre-wrap;
}
</style>
<link rel="stylesheet" href="/static/assets/css/partial/crafty-terminal.css">
<!-- content-wrapper ends -->
{% end %}
@ -200,12 +156,12 @@
if (updateButton.isUpdating) {
if (updateButton.server_id == serverId) {
console.log(updateButton.isUpdating)
document.getElementById('control_buttons').innerHTML = '<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "updating", data["lang"]) }}</button><button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data["lang"]) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data["lang"]) }}</button>';
document.getElementById('control_buttons').innerHTML = '<button onclick="" id="start-btn" class="btn btn-primary m-1 flex-grow-1 term-btn">{{ translate("serverTerm", "updating", data["lang"]) }}</button><button onclick="" id="restart-btn" class="btn btn-outline-primary m-1 flex-grow-1 term-btn">{% raw translate("serverTerm", "restart", data["lang"]) %}</button><button onclick="" id="stop-btn" class="btn btn-danger m-1 flex-grow-1 term-btn disabled">{{ translate("serverTerm", "stop", data["lang"]) }}</button>';
}
}
else if (updateButton.server_id == serverId) {
window.location.reload()
document.getElementById('update_control_buttons').innerHTML = '<button onclick="send_command(serverId, "start_server");" id="start-btn" style="max-width: 7rem;" class="btn btn-primary m-1 flex-grow-1">{{ translate("serverTerm", "start", data["lang"]) }}</button><button onclick="send_command(serverId, "restart_server");" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1">{% raw translate("serverTerm", "restart", data["lang"]) %}</button><button onclick="" id="stop-btn" style="max-width: 7rem;" class="btn btn-danger m-1 flex-grow-1 disabled">{{ translate("serverTerm", "stop", data["lang"]) }}</button>';
document.getElementById('update_control_buttons').innerHTML = '<button onclick="send_command(serverId, "start_server");" id="start-btn" class="btn btn-primary m-1 flex-grow-1 term-btn">{{ translate("serverTerm", "start", data["lang"]) }}</button><button onclick="send_command(serverId, "restart_server");" id="restart-btn" class="btn btn-outline-primary m-1 flex-grow-1 term-btn">{% raw translate("serverTerm", "restart", data["lang"]) %}</button><button onclick="" id="stop-btn" class="btn btn-danger m-1 flex-grow-1 term-btn disabled">{{ translate("serverTerm", "stop", data["lang"]) }}</button>';
}
});
}

View File

@ -41,7 +41,7 @@
</span>
<div class="row">
<div class="col-md-12 col-sm-12" style="overflow-x:auto;">
<div class="col-md-12 col-sm-12 overflow-x-auto">
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
<h4 class="card-title"><i class="fa-regular fa-bell"></i> {{ translate('webhooks', 'webhooks', data['lang']) }} </h4>
@ -52,7 +52,7 @@
</div>
<div class="card-body">
{% if len(data['webhooks']) == 0 %}
<div style="text-align: center; color: grey;">
<div class="text-center text-secondary">
<h7>{{ translate('webhooks', 'no-webhook', data['lang']) }} <strong>{{ translate('webhooks', 'newWebhook',data['lang']) }}</strong>.</h7>
</div>
{% end %}
@ -82,7 +82,7 @@
<td id="{{webhook.webhook_type}}" class="type">
<p>{{webhook.webhook_type}}</p>
</td>
<td id="{{webhook.trigger}}" class="trigger" style="overflow: scroll; max-width: 30px;">
<td id="{{webhook.trigger}}" class="trigger overflow-scroll" style="max-width: 30px;">
<ul>
{% for trigger in webhook.trigger.split(",") %}
{% if trigger in data["triggers"] %}
@ -157,11 +157,6 @@
</div>
</div>
<style>
.popover-body {
color: white !important;
;
}
.toggle-handle {
background-color: white !important;
}

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="default">
<head>
<!-- Required meta tags -->
@ -24,7 +24,10 @@
<!-- Plugin css for this page -->
<!-- End Plugin css for this page -->
<!-- Layout styles -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
<link rel="stylesheet" href="/static/assest/css/internal/root.css">
<link rel="stylesheet" href="/static/assets/css/themes/default.css">
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- End Layout styles -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
@ -37,7 +40,7 @@
}
</style>
<body class="dark-theme">
<body">
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">
@ -84,6 +87,6 @@
<script src="/static/assets/js/shared/settings.js"></script>
<script src="/static/assets/js/shared/todolist.js"></script>
<!-- endinject -->
</body>
</body>
</html>

View File

@ -1,6 +1,5 @@
<!DOCTYPE html>
<html lang="{{ data.get('lang_page', 'en') }}" class="{{data['user_data'].get('theme', 'default')}}"
data-username="{{data['user_data'].get('username', None)}}">
<html lang="{{ data.get('lang_page', 'en') }}" class="{{data['user_data'].get('theme', 'default')}}" data-username="{{data['user_data'].get('username', None)}}">
<head>
<!-- Required meta tags -->
@ -25,7 +24,10 @@
<!-- Plugin css for this page -->
<!-- End Plugin css for this page -->
<!-- Layout styles -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
<link rel="stylesheet" href="/static/assest/css/internal/root.css">
<link rel="stylesheet" href="/static/assets/css/themes/default.css">
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- End Layout styles -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
@ -38,7 +40,7 @@
}
</style>
<body class="dark-theme">
<body>
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="default">
<head>
<!-- Required meta tags -->
@ -23,7 +23,11 @@
<!-- Plugin css for this page -->
<!-- End Plugin css for this page -->
<!-- Layout styles -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
<link rel="stylesheet" href="/static/assest/css/internal/root.css">
<link rel="stylesheet" href="/static/assets/css/themes/default.css">
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<link rel="stylesheet" href="/static/assets/css/partial/crafty-login_page.css">
<!-- End Layout styles -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
@ -37,7 +41,7 @@
}
</style>
<body class="dark-theme">
<body>
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">
@ -49,64 +53,31 @@
<div class="text-center auto-form-logo">
<img src="/static/assets/images/logo_long.svg">
</div>
<style>
.login-modal {
border-radius: 0.4rem !important;
box-shadow: 0 8px 12px 0 hsla(0, 0%, 0%, 0.2) !important;
}
.login-text-input {
border: none !important;
background-color: hsl(234, 30%, 45%);
color: var(--white) !important;
}
.login-text-input:hover,
.login-text-input:focus {
background-color: hsl(234, 30%, 39%) !important;
}
.login-input {
border-radius: 0.4rem !important;
box-shadow: 0 8px 12px 0 hsla(0, 0%, 0%, 0.2);
transition: all 0.3s ease-in-out;
}
.login-input:hover,
.login-input:focus {
box-shadow: 0 12px 16px 0 hsla(0, 0%, 0%, 0.4);
}
</style>
<form id="login-form" data-query="{{ data.get('query', None) }}">
{% raw xsrf_form_html() %}
<div class="form-group">
<label class="label">{{ translate('login', 'username', data['lang']) }}</label>
<div class="input-group">
<input type="text" class="form-control login-text-input login-input"
placeholder="{{ translate('login', 'username', data['lang']) }}" name="username" id="username"
required="true">
<input type="text" class="form-control login-text-input login-input" placeholder="{{ translate('login', 'username', data['lang']) }}" name="username" id="username" required="true">
</div>
</div>
<div class="form-group">
<label class="label">{{ translate('login', 'password', data['lang']) }}</label>
<div class="input-group">
<input type="password" class="form-control login-text-input login-input"
placeholder="{{ translate('login', 'password', data['lang']) }}" name="password" id="password"
required="true">
<input type="password" class="form-control login-text-input login-input" placeholder="{{ translate('login', 'password', data['lang']) }}" name="password" id="password" required="true">
</div>
</div>
<div class="form-group">
<button class="login-input btn btn-primary submit-btn btn-block">{{ translate('login', 'login',
data['lang']) }}</button>
</div>
<fieldset id="error-field" style="color: red; text-align: center;">
<fieldset id="error-field" class="loginError">
</fieldset>
<div class="form-group d-flex justify-content-between">
<div class="form-check form-check-flat mt-0">
&nbsp;
</div>
<button onclick="resetPass()" id="#resetPass" form=""
class="btn btn-outline-primary btn-sm forgot-password ">{{ translate('login', 'forgotPassword',
<button onclick="resetPass()" id="#resetPass" form="" class="btn btn-outline-primary btn-sm forgot-password ">{{ translate('login', 'forgotPassword',
data['lang']) }}</button>
</div>

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="default">
<head>
<!-- Required meta tags -->
@ -24,7 +24,10 @@
<!-- Plugin css for this page -->
<!-- End Plugin css for this page -->
<!-- Layout styles -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
<link rel="stylesheet" href="/static/assest/css/internal/root.css">
<link rel="stylesheet" href="/static/assets/css/themes/default.css">
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- End Layout styles -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
@ -37,7 +40,7 @@
}
</style>
<body class="dark-theme">
<body>
<div class="container-scroller">
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">

View File

@ -3,20 +3,24 @@
{% block meta %}
{% end %}
{% block title %}Crafty Controller - {{ translate('dashboard', 'dashboard', data['lang']) }}{% end %}
{% block title %}Crafty Controller - Status{% end %}
{% block content %}
<!-- View for Large screen -->
<style>
.auth.auth-bg-1 {
background: url("../../static/assets/images/auth/{% raw data['background'] %}"),
background: url("/static/assets/images/auth/{% raw data['background'] %}"),
url("/static/assets/images/auth/login_1.jpg");
background-size: cover;
}
</style>
<div class="row justify-content-center">
<div class="content-wrapper col-md login-modal d-none d-sm-block" style="background-color: var(--dropdown-bg);">
<img src="/static/assets/images/logo_long.png" style='width: 25%; margin-left: 38%;'>
<div class="content-wrapper col-md login-modal d-none d-sm-block bg-dropdown">
<div class="row text-center">
<div class="col-12">
<img src="/static/assets/images/logo_long.png" class="w-25" alt="Crafty Logo">
</div>
</div>
<hr />
<div class="table-responsive">
<table class="table table-hover">
@ -32,7 +36,7 @@
<tbody>
{% for server in data['servers'] %}
{% if server['server_data']['show_status'] %}
<tr>
<tr class="h-">
<td id="server_name_{{ server['stats']['server_id']['server_id'] }}">
<i class="fas fa-server"></i>
{{ server['server_data']['server_name'] }}
@ -85,13 +89,12 @@
</tbody>
</table>
</div>
<hr />
</div>
</div>
<!-- View for Small screen -->
<div class="row justify-content-center align-items-sm-center">
<div class="content-wrapper login-modal d-sm-none d-block" style="background-color: var(--dropdown-bg);">
<img src="/static/assets/images/logo_long.png" style='width: 100%;'>
<div class="content-wrapper login-modal d-sm-none d-block bg-dropdown">
<img src="/static/assets/images/logo_long.png" class="w-100" alt="Crafty Logo">
<hr />
<div class="accordion" id="accordionServers">
{% for server in data['servers'] %}
@ -207,10 +210,10 @@
m_motd = `<img class="w-25 mr-3" src="/static/assets/images/pack.png" alt="icon" /> `;
}
desc_motd = `<span id="input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span> <br />`;
m_motd = m_motd + `<div class="media-body"><span id="m_input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span></div>`;
var desc_motd = `<span id="input_motd_` + server.id + `" class="input_motd align-middle">` + server.desc + `</span> <br />`;
m_motd = m_motd + `<div class="media-body"><span id="m_input_motd_` + server.id + `" class="input_motd align-middle">` + server.desc + `</span></div>`;
motd = `<div class="row"><div class="col-auto">` + img_motd + `</div><div class="col-auto">` + desc_motd + `</div></div>`;
motd = `<div class="row"><div class="col-auto">` + img_motd + `</div><div class="col-auto text-left align-items-center align-content-center">` + desc_motd + `</div></div>`;
server_motd.innerHTML = motd;
m_server_motd.innerHTML = m_motd;
}

View File

@ -25,7 +25,9 @@
<!-- Plugin css for this page -->
<!-- End Plugin css for this page -->
<!-- Layout styles -->
<link rel="stylesheet" href="/static/assets/css/dark/style.css" />
<link rel="stylesheet" href="/static/assets/css/themes/default.css">
<link rel="stylesheet" href="/static/assets/css/base-style.css">
<link rel="stylesheet" href="/static/assets/css/crafty.css">
<!-- End Layout styles -->
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg" />
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
@ -36,7 +38,7 @@
<div class="container-fluid page-body-wrapper full-page-wrapper">
<div class="content-wrapper d-flex align-items-sm-center auth auth-bg-1 theme-one">
<div class="mx-auto">
<div class="auto-form-wrapper">{% block content %} {% end %}</div>
<div class="auto-form-wrapper h-100">{% block content %} {% end %}</div>
</div>
</div>
<!-- content-wrapper ends -->

View File

@ -29,54 +29,21 @@
<fieldset>
{% else %}
<fieldset disabled="disabled">
<style>
.api-alert {
position: absolute;
top: -5px;
left: 0;
font-size: 50px !important;
color: #fff;
background: rgb(127, 133, 133);
opacity: .4;
width: 100%;
height: 100%;
z-index: 100;
}
.api-alert p {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
text-align: center;
font-size: 20px;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
</style>
{% end %}
<div class="form-group">
<label for="server_name">{{ translate('serverWizard', 'serverName', data['lang']) }}</label>
<input type="text" class="form-control" id="server_name" name="name"
placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
<input type="text" class="form-control" id="server_name" name="name" placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
</div>
<div class="form-group">
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang'])
}}
<small style="text-transform: none;"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small>
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang']) }}
<small class="text-none"> - {{ translate('serverWizard', 'autoCreate', data['lang']) }}</small>
</p>
<select data-container="body"
data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}"
data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}"
class="selectpicker form-control form-control-lg select-css roles_select"
data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles"
multiple>
<select data-container="body" data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}" data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}" class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles" multiple>
{% for r in data['roles'] %}
<option class="roles" type="checkbox" value="{{ r['role_id'] }}">
&nbsp; {{ r['role_name'].capitalize()
}}
&nbsp; {{ r['role_name'].capitalize() }}
</option>
{% end %}
</select>
@ -88,18 +55,14 @@
}}</button>
</fieldset>
{% if not data["server_api"] and data["online"] %}
<div class="api-alert" style="position: absolute; top: -5px; z-index: 100; opacity: .99;">
<p style="color: white !important;"><i class="fas fa-exclamation-triangle"
style="color: red;"></i>&nbsp;{{ translate('error', 'bedrockError', data['lang']) }}<a
style="color: red;" ; href="https://status.craftycontrol.com/status/craftycontrol" target="_blank"
rel="noopener noreferrer">&nbsp;{{ translate('error', 'craftyStatus', data['lang']) }}</a>
<div class="api-alert">
<p><i class="fas fa-exclamation-triangle"></i>&nbsp;{{ translate('error', 'bedrockError', data['lang']) }}<a href="https://status.craftycontrol.com/status/craftycontrol" target="_blank" rel="noopener noreferrer">&nbsp;{{ translate('error', 'craftyStatus', data['lang']) }}</a>
&nbsp;{{ translate('error', 'serverJars2', data['lang']) }}</p>
</div>
{% end %}
{% if not data["online"] %}
<div class="api-alert" style="position: absolute; top: -5px; z-index: 100; opacity: .99;">
<p style="color: white !important;"><i class="fas fa-exclamation-triangle"
style="color: red;"></i>&nbsp;{{ translate('error', 'noInternet', data['lang']) }}</p>
<div class="api-alert">
<p><i class="fas fa-exclamation-triangle"></i>&nbsp;{{ translate('error', 'noInternet', data['lang']) }}</p>
</div>
{% end %}
</div>
@ -116,43 +79,34 @@
<form method="post" id="import-jar" class="server-wizard">
<div class="form-group">
<label for="server_name">{{ translate('serverWizard', 'serverName', data['lang']) }}</label>
<input type="text" class="form-control" id="server_name" name="name" value=""
placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
<input type="text" class="form-control" id="server_name" name="name" value="" placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="server">{{ translate('serverWizard', 'serverPath', data['lang']) }} <small>{{
translate('serverWizard', 'absoluteServerPath', data['lang']) }}</small></label>
<input type="text" class="form-control" id="server_path" name="server_path" placeholder="/var/opt/server"
required>
<input type="text" class="form-control" id="server_path" name="server_path" placeholder="/var/opt/server" required>
</div>
<div class="form-group">
<label for="server_jar">{{ translate('serverWizard', 'serverJar', data['lang']) }}</label>
<input type="text" class="form-control" id="server_jar" name="server_jar" value=""
placeholder="bedrock_server" required>
<input type="text" class="form-control" id="server_jar" name="server_jar" value="" placeholder="bedrock_server" required>
</div>
<br />
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small
style="text-transform: none;"> - {{ translate('serverWizard', 'quickSettingsDescription',
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small class="text-none"> - {{ translate('serverWizard', 'quickSettingsDescription',
data['lang']) }}</small></h4>
<hr>
<div class="form-group">
<label for="port2">{{ translate('serverWizard', 'serverPort', data['lang']) }}
<small></small></label>
<input type="number" class="form-control" id="port2" name="port" value="19132" step="1" min="1"
max="65535" required>
<input type="number" class="form-control" id="port2" name="port" value="19132" step="1" min="1" max="65535" required>
</div>
<div class="form-group">
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang'])
}}
<small style="text-transform: none;"> - {{ translate('serverWizard', 'autoCreate',
<small class="text-none"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small>
</p>
<select data-container="body"
data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}"
data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}"
class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control"
data-style="form-control" data-live-search="true" name="server_roles" multiple>
<select data-container="body" data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}" data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}" class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles" multiple>
{% for r in data['roles'] %}
<option class="roles" type="checkbox" value="{{ r['role_id'] }}">
&nbsp; {{ r['role_name'].capitalize()
@ -180,15 +134,13 @@
<div class="form-group">
<label for="server_name">{{ translate('serverWizard', 'serverName', data['lang']) }}</label>
<input type="text" class="form-control" id="server_name" name="name" value=""
placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
<input type="text" class="form-control" id="server_name" name="name" value="" placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="server">{{ translate('serverWizard', 'zipPath', data['lang']) }} <small>{{
translate('serverWizard', 'absoluteZipPath', data['lang']) }}</small></label>
<input type="text" class="form-control" id="zip_server_path" name="server_path"
placeholder="/var/opt/server.zip" required>
<input type="text" class="form-control" id="zip_server_path" name="server_path" placeholder="/var/opt/server.zip" required>
</div>
<div class="form-group">
@ -200,32 +152,25 @@
</div>
<div class="form-group">
<label for="server_jar">{{ translate('serverWizard', 'serverJar', data['lang']) }}</label>
<input type="text" class="form-control" id="server_jar" name="server_jar" value=""
placeholder="bedrock_server" required>
<input type="text" class="form-control" id="server_jar" name="server_jar" value="" placeholder="bedrock_server" required>
</div>
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small
style="text-transform: none;"> - {{ translate('serverWizard', 'quickSettingsDescription', data['lang'])
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small class="text-none"> - {{ translate('serverWizard', 'quickSettingsDescription', data['lang'])
}}</small>
</h4>
<hr>
<div class="form-group">
<label for="port3">{{ translate('serverWizard', 'serverPort', data['lang']) }}
<small></small></label>
<input type="number" class="form-control" id="port3" name="port" value="19132" step="1" min="1"
max="65535" required>
<input type="number" class="form-control" id="port3" name="port" value="19132" step="1" min="1" max="65535" required>
</div>
<div class="form-group">
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang'])
}}
<small style="text-transform: none;"> - {{ translate('serverWizard', 'autoCreate',
<small class="text-none"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small>
</p>
<select data-container="body"
data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}"
data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}"
class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control"
data-style="form-control" data-live-search="true" name="server_roles" multiple>
<select data-container="body" data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}" data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}" class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles" multiple>
{% for r in data['roles'] %}
<option class="roles" type="checkbox" value="{{ r['role_id'] }}">
&nbsp; {{ r['role_name'].capitalize()
@ -234,8 +179,7 @@
{% end %}
</select>
</div>
<div class="modal fade" id="dir_select" tabindex="-1" role="dialog" aria-labelledby="dir_select"
aria-hidden="true">
<div class="modal fade" id="dir_select" tabindex="-1" role="dialog" aria-labelledby="dir_select" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
@ -246,8 +190,7 @@
</button>
</div>
<div class="modal-body">
<div class="tree-ctx-item" id="main-tree-div" data-path=""
style="overflow: scroll; max-height:75%;">
<div class="tree-ctx-item overflow-scroll mh-75" id="main-tree-div" data-path="">
<input type="radio" class="root-input" id="main-tree-input" name="root_path" value="" checked>
<span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path="">
<i class="far fa-folder"></i>
@ -266,8 +209,7 @@
</div>
</div>
</div>
<button id="zip_submit" type="submit" title="You must select server root dir first" disabled
class="btn btn-primary mr-2">{{ translate('serverWizard', 'importServerButton', data['lang'])
<button id="zip_submit" type="submit" title="You must select server root dir first" disabled class="btn btn-primary mr-2">{{ translate('serverWizard', 'importServerButton', data['lang'])
}}</button>
<button type="button" class="btn btn-danger mr-2 tree-reset">{{ translate('serverWizard', 'resetForm',
data['lang'])
@ -288,8 +230,7 @@
<div class="form-group">
<label for="server_name">{{ translate('serverWizard', 'serverName', data['lang']) }}</label>
<input type="text" class="form-control" id="server_name" name="name" value=""
placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
<input type="text" class="form-control" id="server_name" name="name" value="" placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
</div>
<div class="form-group">
@ -301,13 +242,12 @@
'labelZipFile', data['lang']) }}</label>
</div>
<div class="input-group-append">
<button type="button" class="btn btn-info upload-button" id="upload-button"
onclick="uploadFile('import')" disabled>{{ translate('serverWizard',
<button type="button" class="btn btn-info upload-button" id="upload-button" onclick="uploadFile('import')" disabled>{{ translate('serverWizard',
'uploadButton', data['lang']) }}</button>
</div>
</div>
</div>
<div id="lower_half" style="visibility: hidden;">
<div id="lower_half" class="d-none" hidden>
<div class="form-group">
<label for="server">{{ translate('serverWizard', 'selectRoot', data['lang']) }} <small>{{
translate('serverWizard', 'explainRoot', data['lang']) }}</small></label>
@ -319,34 +259,26 @@
<div class="form-group">
<label for="server_jar">{{ translate('serverWizard', 'serverJar', data['lang']) }}</label>
<input type="text" class="form-control" id="server_jar" name="server_jar" value=""
placeholder="paper.jar" required>
<input type="text" class="form-control" id="server_jar" name="server_jar" value="" placeholder="paper.jar" required>
</div>
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small
style="text-transform: none;"> - {{ translate('serverWizard', 'quickSettingsDescription',
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small class="text-none"> - {{ translate('serverWizard', 'quickSettingsDescription',
data['lang']) }}</small></h4>
<hr>
<div class="form-group">
<label for="port3">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port4" name="port" value="19132" step="1" min="1"
max="65535" required>
<input type="number" class="form-control" id="port4" name="port" value="19132" step="1" min="1" max="65535" required>
</div>
<div class="form-group">
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang'])
}}
<small style="text-transform: none;"> - {{ translate('serverWizard', 'autoCreate',
<small class="text-none"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small>
</p>
<select data-container="body"
data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}"
data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}"
class="selectpicker form-control form-control-lg select-css roles_select"
data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles"
multiple>
<select data-container="body" data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}" data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}" class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles" multiple>
{% for r in data['roles'] %}
<option class="roles" type="checkbox" value="{{ r['role_id'] }}">
&nbsp; {{ r['role_name'].capitalize()
@ -355,8 +287,7 @@
{% end %}
</select>
</div>
<div class="modal fade" id="dir_upload_select" tabindex="-1" role="dialog" aria-labelledby="dir_select"
aria-hidden="true">
<div class="modal fade" id="dir_upload_select" tabindex="-1" role="dialog" aria-labelledby="dir_select" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
@ -367,10 +298,8 @@
</button>
</div>
<div class="modal-body">
<div class="tree-ctx-item" id="main-tree-div-upload" data-path=""
style="overflow: scroll; max-height:75%;">
<input type="radio" class="root-input" id="main-tree-input-upload" name="root_path" value=""
checked>
<div class="tree-ctx-item overflow-scroll mh-75" id="main-tree-div-upload" data-path="">
<input type="radio" class="root-input" id="main-tree-input-upload" name="root_path" value="" checked>
<span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path="">
<i class="far fa-folder"></i>
<i class="far fa-folder-open"></i>
@ -388,8 +317,7 @@
</div>
</div>
</div>
<button id="upload_submit" type="submit" title="You must select server root dir first" disabled
class="btn btn-primary mr-2">{{ translate('serverWizard', 'importServerButton', data['lang'])
<button id="upload_submit" type="submit" title="You must select server root dir first" disabled class="btn btn-primary mr-2">{{ translate('serverWizard', 'importServerButton', data['lang'])
}}</button>
<button type="button" class="btn btn-danger mr-2 tree-reset">{{ translate('serverWizard', 'resetForm',
data['lang'])
@ -401,96 +329,7 @@
</div>
</div>
</div>
<style>
div>.input-group>.custom-file-input {
position: relative !important;
-webkit-box-flex: 1 !important;
-ms-flex: 1 1 auto !important;
flex: 1 1 auto !important;
width: 1% !important;
margin-bottom: 0 !important;
border: 1px solid var(--outline);
}
.scroll {
max-height: 12em;
overflow-y: auto;
}
.menu-btn {
font-size: 0.9em;
padding: 2px 10px;
}
.menu {
padding-top: 10px;
z-index: 200;
margin-top: 4px;
position: absolute;
background-color: var(--card-banner-bg);
}
.menu-option {
padding: 6px 20px 6px;
color: white;
}
#overlay {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 100;
}
#op_logo {
position: relative;
top: 50%;
transform: translateY(-50%);
}
</style>
<style>
/* Remove default bullets */
.tree-view,
.tree-nested {
list-style-type: none;
margin: 0;
padding: 0;
margin-left: 10px;
}
/* Style the items */
.tree-item,
.files-tree-title {
cursor: pointer;
user-select: none;
/* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder {
display: inline-block;
}
.tree-caret .fa-folder-open {
display: none;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down .fa-folder {
display: none;
}
.tree-caret-down .fa-folder-open {
display: inline-block;
}
/* Hide the nested list */
.tree-nested {
display: none;
}
</style>
<link rel="stylesheet" href="/static/assets/css/partial/crafty-wizard.css">
{% end %}

View File

@ -31,35 +31,6 @@
<fieldset>
{% else %}
<fieldset disabled="disabled">
<style>
#creation_wizard {
-webkit-filter: grayscale(1);
}
.api-alert {
position: absolute;
top: -5px;
left: 0;
font-size: 50px !important;
color: #fff;
background: rgb(0, 170, 170);
opacity: .4;
width: 100%;
height: 100%;
z-index: 100;
}
.api-alert p {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
text-align: center;
font-size: 20px;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
</style>
{% end %}
{% raw xsrf_form_html() %}
<div class="row">
@ -68,8 +39,7 @@
<div class="form-group">
<label for="server_jar">{{ translate('serverWizard', 'serverType', data['lang']) }}</label>
<div class="input-group">
<select required class="form-control form-control-lg select-css" id="server_jar" name="type"
onchange="serverJarChange(this)">
<select required class="form-control form-control-lg select-css" id="server_jar" name="type" onchange="serverJarChange(this)">
<option value="">{{ translate('serverWizard', 'selectServer', data['lang']) }}</option>
{% for s in data['server_types'] %}
{% if data['server_types'][s].get("enabled", False) %}
@ -80,8 +50,7 @@
</select>
{% if data['super_user'] %}
<div class="input-group-append">
<button class="btn custom-picker" type="button" onclick="refreshCache()"><i id="refresh-cache"
class="refresh-class fas fa-sync"></i></button>
<button class="btn custom-picker" type="button" onclick="refreshCache()"><i id="refresh-cache" class="refresh-class fas fa-sync"></i></button>
</div>
{% end %}
</div>
@ -91,8 +60,7 @@
<div class="col-sm-12">
<div class="form-group">
<label for="server_type">{{ translate('serverWizard', 'serverSelect', data['lang']) }}</label>
<select required class="form-control form-control-lg select-css" id="server_type" name="type"
onchange="serverTypeChange(this)">
<select required class="form-control form-control-lg select-css" id="server_type" name="type" onchange="serverTypeChange(this)">
<option value="">{{ translate('serverWizard', 'selectServer', data['lang']) }}</option>
</select>
</div>
@ -106,22 +74,17 @@
</select>
</div>
</div>
<span data-html="true" class="version-hint text-center"
data-content="⚠️ {{ translate('serverWizard', 'unsupported', data['lang']) }} ⚠️" ,
data-placement="right"></span>
<span data-html="true" class="version-hint text-center" data-content="⚠️ {{ translate('serverWizard', 'unsupported', data['lang']) }} ⚠️" , data-placement="right"></span>
<div class="col-sm-12">
<div class="form-group">
<label for="server_name">{{ translate('serverWizard', 'serverName', data['lang']) }}</label>
<input type="text" class="form-control" id="server_name" name="name"
placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
<input type="text" class="form-control" id="server_name" name="name" placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
</div>
</div>
</div>
<br />
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small
style="text-transform: none;"> - {{ translate('serverWizard', 'quickSettingsDescription',
data['lang']) }}</small></h4>
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small class="text-none"> - {{ translate('serverWizard', 'quickSettingsDescription', data['lang']) }}</small></h4>
<hr>
<div class="row">
@ -129,8 +92,7 @@
<div class="form-group">
<label for="min_memory1">{{ translate('serverWizard', 'minMem', data['lang']) }} <small> - {{
translate('serverWizard', 'sizeInGB', data['lang']) }}</small></label>
<input type="number" class="form-control" id="min_memory1" name="mem_min" value="1" step="0.5"
min="0.5" required>
<input type="number" class="form-control" id="min_memory1" name="mem_min" value="1" step="0.5" min="0.5" required>
</div>
</div>
@ -138,8 +100,7 @@
<div class="form-group">
<label for="max_memory1">{{ translate('serverWizard', 'maxMem', data['lang']) }} <small> - {{
translate('serverWizard', 'sizeInGB', data['lang']) }}</small></label>
<input type="number" class="form-control" id="max_memory1" name="mem_max" value="2" step="0.5"
min="0.5" required>
<input type="number" class="form-control" id="max_memory1" name="mem_max" value="2" step="0.5" min="0.5" required>
</div>
</div>
@ -147,23 +108,16 @@
<div class="form-group">
<label for="port1">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port1" name="port" value="25565" step="1" min="1"
max="65535 " required>
<input type="number" class="form-control" id="port1" name="port" value="25565" step="1" min="1" max="65535 " required>
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang'])
<label for="Role-1"> {{ translate('serverWizard', 'addRole', data['lang'])
}}
<small style="text-transform: none;"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small>
</p>
<select data-container="body"
data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}"
data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}"
class="selectpicker form-control form-control-lg select-css roles_select"
data-styleBase="form-control" data-style="form-control" data-live-search="true"
name="server_roles" multiple>
<small class="text-none"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small></label>
<select data-container="body" data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}" data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}" class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles" multiple>
{% for r in data['roles'] %}
<option class="roles" type="checkbox" value="{{ r['role_id'] }}">
&nbsp; {{ r['role_name'].capitalize()
@ -173,7 +127,6 @@
</select>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary mr-2">{{ translate('serverWizard', 'buildServer',
data['lang']) }}</button>
@ -183,10 +136,9 @@
</div>
</fieldset>
{% if not data["server_api"] and data["online"] %}
<div class="api-alert" style="position: absolute; top: -5px; z-index: 100; opacity: .99;">
<p style="color: white !important;"><i class="fas fa-exclamation-triangle" style="color: red;"></i>&nbsp;{{
translate('error', 'bigBucket1', data['lang']) }}<a style="color: red;" ;
href="https://status.craftycontrol.com/status/craftycontrol" target="_blank" rel="noopener">&nbsp;{{
<div class="api-alert">
<p><i class="fas fa-exclamation-triangle"></i>&nbsp;{{
translate('error', 'bigBucket1', data['lang']) }}<a href="https://status.craftycontrol.com/status/craftycontrol" target="_blank" rel="noopener">&nbsp;{{
translate('error',
'craftyStatus', data['lang']) }}</a>
&nbsp;{{ translate('error', 'bigBucket2', data['lang']) }}</br></br><small>{{ translate('error', 'selfHost',
@ -194,9 +146,8 @@
</div>
{% end %}
{% if not data["online"] %}
<div class="api-alert" style="position: absolute; top: -5px; z-index: 100; opacity: .99;">
<p style="color: white !important;"><i class="fas fa-exclamation-triangle" style="color: red;"></i>&nbsp;{{
translate('error', 'noInternet', data['lang']) }}</p>
<div class="api-alert">
<p><i class="fas fa-exclamation-triangle"></i>&nbsp;{{ translate('error', 'noInternet', data['lang']) }}</p>
</div>
{% end %}
</div>
@ -220,8 +171,7 @@
<div class="col-sm-12">
<div class="form-group">
<label for="server_name">{{ translate('serverWizard', 'serverName', data['lang']) }}</label>
<input type="text" class="form-control" id="server_name" name="name" value=""
placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
<input type="text" class="form-control" id="server_name" name="name" value="" placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
</div>
</div>
@ -229,16 +179,14 @@
<div class="form-group">
<label for="server">{{ translate('serverWizard', 'serverPath', data['lang']) }} <small>{{
translate('serverWizard', 'absoluteServerPath', data['lang']) }}</small></label>
<input type="text" class="form-control" id="server_path" name="server_path"
placeholder="/var/opt/server" required>
<input type="text" class="form-control" id="server_path" name="server_path" placeholder="/var/opt/server" required>
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<label for="server_jar">{{ translate('serverWizard', 'serverJar', data['lang']) }}</label>
<input type="text" class="form-control" id="server_jar" name="server_jar" value=""
placeholder="paper.jar" required>
<input type="text" class="form-control" id="server_jar" name="server_jar" value="" placeholder="paper.jar" required>
</div>
</div>
@ -246,8 +194,7 @@
</div>
<br />
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small
style="text-transform: none;"> - {{ translate('serverWizard', 'quickSettingsDescription',
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small class="text-none"> - {{ translate('serverWizard', 'quickSettingsDescription',
data['lang']) }}</small></h4>
<hr>
<div class="row">
@ -256,8 +203,7 @@
<div class="form-group">
<label for="min_memory2">{{ translate('serverWizard', 'minMem', data['lang']) }} <small> - {{
translate('serverWizard', 'sizeInGB', data['lang']) }}</small></label>
<input type="number" class="form-control" id="min_memory2" name="mem_min" value="1" step="0.5"
min="0.5" required>
<input type="number" class="form-control" id="min_memory2" name="mem_min" value="1" step="0.5" min="0.5" required>
</div>
</div>
@ -265,8 +211,7 @@
<div class="form-group">
<label for="max_memory2">{{ translate('serverWizard', 'maxMem', data['lang']) }} <small> - {{
translate('serverWizard', 'sizeInGB', data['lang']) }}</small></label>
<input type="number" class="form-control" id="max_memory2" name="mem_max" value="2" step="0.5"
min="0.5" required>
<input type="number" class="form-control" id="max_memory2" name="mem_max" value="2" step="0.5" min="0.5" required>
</div>
</div>
@ -274,23 +219,16 @@
<div class="form-group">
<label for="port2">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port2" name="port" value="25565" step="1" min="1"
max="65535" required>
<input type="number" class="form-control" id="port2" name="port" value="25565" step="1" min="1" max="65535" required>
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang'])
<label for="Role-2"> {{ translate('serverWizard', 'addRole', data['lang'])
}}
<small style="text-transform: none;"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small>
</p>
<select data-container="body"
data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}"
data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}"
class="selectpicker form-control form-control-lg select-css roles_select"
data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles"
multiple>
<small class="text-none"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small></label>
<select data-container="body" data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}" data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}" class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles" multiple>
{% for r in data['roles'] %}
<option class="roles" type="checkbox" value="{{ r['role_id'] }}">
&nbsp; {{ r['role_name'].capitalize()
@ -330,8 +268,7 @@
<div class="col-sm-12">
<div class="form-group">
<label for="server_name">{{ translate('serverWizard', 'serverName', data['lang']) }}</label>
<input type="text" class="form-control" id="server_name" name="name" value=""
placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
<input type="text" class="form-control" id="server_name" name="name" value="" placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
</div>
</div>
@ -339,8 +276,7 @@
<div class="form-group">
<label for="server">{{ translate('serverWizard', 'zipPath', data['lang']) }} <small>{{
translate('serverWizard', 'absoluteZipPath', data['lang']) }}</small></label>
<input type="text" class="form-control" id="zip_server_path" name="server_path"
placeholder="/var/opt/server.zip" required>
<input type="text" class="form-control" id="zip_server_path" name="server_path" placeholder="/var/opt/server.zip" required>
</div>
</div>
@ -358,8 +294,7 @@
<div class="col-sm-12">
<div class="form-group">
<label for="server_jar">{{ translate('serverWizard', 'serverJar', data['lang']) }}</label>
<input type="text" class="form-control" id="server_jar" name="server_jar" value=""
placeholder="paper.jar" required>
<input type="text" class="form-control" id="server_jar" name="server_jar" value="" placeholder="paper.jar" required>
</div>
</div>
</div>
@ -368,8 +303,7 @@
<div class="col-sm-12">
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small
style="text-transform: none;"> - {{ translate('serverWizard', 'quickSettingsDescription',
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small class="text-none"> - {{ translate('serverWizard', 'quickSettingsDescription',
data['lang']) }}</small></h4>
<hr>
<div class="row">
@ -377,8 +311,7 @@
<div class="form-group">
<label for="min_memory3">{{ translate('serverWizard', 'minMem', data['lang']) }} <small> - {{
translate('serverWizard', 'sizeInGB', data['lang']) }}</small></label>
<input type="number" class="form-control" id="min_memory3" name="mem_min" value="1" step="0.5"
min="0.5" required>
<input type="number" class="form-control" id="min_memory3" name="mem_min" value="1" step="0.5" min="0.5" required>
</div>
</div>
@ -386,8 +319,7 @@
<div class="form-group">
<label for="max_memory3">{{ translate('serverWizard', 'maxMem', data['lang']) }} <small> - {{
translate('serverWizard', 'sizeInGB', data['lang']) }}</small></label>
<input type="number" class="form-control" id="max_memory3" name="mem_max" value="2" step="0.5"
min="0.5" required>
<input type="number" class="form-control" id="max_memory3" name="mem_max" value="2" step="0.5" min="0.5" required>
</div>
</div>
@ -395,24 +327,17 @@
<div class="form-group">
<label for="port3">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port3" name="port" value="25565" step="1" min="1"
max="65535" required>
<input type="number" class="form-control" id="port3" name="port" value="25565" step="1" min="1" max="65535" required>
</div>
</div>
<div class="col-sm-12">
<div class="form-group">
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang'])
<label for="Role-3"> {{ translate('serverWizard', 'addRole', data['lang'])
}}
<small style="text-transform: none;"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small>
</p>
<select data-container="body"
data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}"
data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}"
class="selectpicker form-control form-control-lg select-css roles_select"
data-styleBase="form-control" data-style="form-control" data-live-search="true"
name="server_roles" multiple>
<small class="text-none"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small></label>
<select data-container="body" data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}" data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}" class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles" multiple>
{% for r in data['roles'] %}
<option class="roles" type="checkbox" value="{{ r['role_id'] }}">
&nbsp; {{ r['role_name'].capitalize()
@ -422,8 +347,7 @@
</select>
</div>
</div>
<div class="modal fade" id="dir_select" tabindex="-1" role="dialog" aria-labelledby="dir_select"
aria-hidden="true">
<div class="modal fade" id="dir_select" tabindex="-1" role="dialog" aria-labelledby="dir_select" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
@ -434,8 +358,7 @@
</button>
</div>
<div class="modal-body">
<div class="tree-ctx-item" id="main-tree-div" data-path=""
style="overflow: scroll; max-height:75%;">
<div class="tree-ctx-item overflow-scroll mh-75" id="main-tree-div" data-path="">
<input type="radio" class="root-input" id="main-tree-input" name="root_path" value="" checked>
<span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path="">
<i class="far fa-folder"></i>
@ -455,8 +378,7 @@
</div>
</div>
</div>
<button id="zip_submit" type="submit" title="You must select server root dir first" disabled
class="btn btn-primary mr-2">{{ translate('serverWizard', 'importServerButton', data['lang'])
<button id="zip_submit" type="submit" title="You must select server root dir first" disabled class="btn btn-primary mr-2">{{ translate('serverWizard', 'importServerButton', data['lang'])
}}</button>
<button type="button" class="btn btn-danger mr-2 tree-reset">{{ translate('serverWizard', 'resetForm',
data['lang'])
@ -482,8 +404,7 @@
<div class="form-group">
<label for="server_name">{{ translate('serverWizard', 'serverName', data['lang']) }}</label>
<input type="text" class="form-control" id="server_name" name="name" value=""
placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
<input type="text" class="form-control" id="server_name" name="name" value="" placeholder="{{ translate('serverWizard', 'myNewServer', data['lang']) }}" required>
</div>
<div class="form-group">
<label for="server">{{ translate('serverWizard', 'serverUpload', data['lang']) }}</label>
@ -494,14 +415,13 @@
'labelZipFile', data['lang']) }}</label>
</div>
<div class="input-group-append">
<button type="button" class="btn btn-info upload-button" id="upload-button"
onclick="uploadFile('import')" disabled>{{ translate('serverWizard',
<button type="button" class="btn btn-info upload-button" id="upload-button" onclick="uploadFile('import')" disabled>{{ translate('serverWizard',
'uploadButton', data['lang']) }}</button>
</div>
</div>
</div>
<div id="lower_half" style="visibility: hidden;" hidden>
<div id="lower_half" class="d-none" hidden>
<div class="form-group">
<label for="server">{{ translate('serverWizard', 'selectRoot', data['lang']) }} <small>{{
translate('serverWizard', 'explainRoot', data['lang']) }}</small></label>
@ -512,48 +432,37 @@
<div class="form-group">
<label for="server_jar">{{ translate('serverWizard', 'serverJar', data['lang']) }}</label>
<input type="text" class="form-control" id="server_jar" name="server_jar" value=""
placeholder="paper.jar" required>
<input type="text" class="form-control" id="server_jar" name="server_jar" value="" placeholder="paper.jar" required>
</div>
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small
style="text-transform: none;"> - {{ translate('serverWizard', 'quickSettingsDescription',
<h4 class="card-title">{{ translate('serverWizard', 'quickSettings', data['lang']) }} <small class="text-none"> - {{ translate('serverWizard', 'quickSettingsDescription',
data['lang']) }}</small></h4>
<hr>
<div class="form-group">
<label for="min_memory3">{{ translate('serverWizard', 'minMem', data['lang']) }} <small> - {{
translate('serverWizard', 'sizeInGB', data['lang']) }}</small></label>
<input type="number" class="form-control" id="min_memory3" name="mem_min" value="1" step="0.5" min="0.5"
required>
<input type="number" class="form-control" id="min_memory3" name="mem_min" value="1" step="0.5" min="0.5" required>
</div>
<div class="form-group">
<label for="max_memory3">{{ translate('serverWizard', 'maxMem', data['lang']) }} <small> - {{
translate('serverWizard', 'sizeInGB', data['lang']) }}</small></label>
<input type="number" class="form-control" id="max_memory3" name="mem_max" value="2" step="0.5" min="0.5"
required>
<input type="number" class="form-control" id="max_memory3" name="mem_max" value="2" step="0.5" min="0.5" required>
</div>
<div class="form-group">
<label for="port3">{{ translate('serverWizard', 'serverPort', data['lang']) }} <small> - {{
translate('serverWizard', 'defaultPort', data['lang']) }}</small></label>
<input type="number" class="form-control" id="port3" name="port" value="25565" step="1" min="1"
max="65535" required>
<input type="number" class="form-control" id="port3" name="port" value="25565" step="1" min="1" max="65535" required>
</div>
<div class="form-group">
<p class="mb-0 p-0" aria-expanded="true">{{ translate('serverWizard', 'addRole', data['lang'])
<label for="Role-3"> {{ translate('serverWizard', 'addRole', data['lang'])
}}
<small style="text-transform: none;"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small>
</p>
<select data-container="body"
data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}"
data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}"
class="selectpicker form-control form-control-lg select-css roles_select"
data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles"
multiple>
<small class="text-none"> - {{ translate('serverWizard', 'autoCreate',
data['lang']) }}</small></label>
<select data-container="body" data-none-selected-text="{{ translate('serverWizard', 'noneRoles', data['lang']) }}" data-none-results-text="{{ translate('serverWizard', 'noRole', data['lang']) }} {0}" class="selectpicker form-control form-control-lg select-css roles_select" data-styleBase="form-control" data-style="form-control" data-live-search="true" name="server_roles" multiple>
{% for r in data['roles'] %}
<option class="roles" type="checkbox" value="{{ r['role_id'] }}">
&nbsp; {{ r['role_name'].capitalize()
@ -562,8 +471,7 @@
{% end %}
</select>
</div>
<div class="modal fade" id="dir_upload_select" tabindex="-1" role="dialog" aria-labelledby="dir_select"
aria-hidden="true">
<div class="modal fade" id="dir_upload_select" tabindex="-1" role="dialog" aria-labelledby="dir_select" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
@ -574,10 +482,8 @@
</button>
</div>
<div class="modal-body">
<div class="tree-ctx-item" id="main-tree-div-upload" data-path=""
style="overflow: scroll; max-height:75%;">
<input type="radio" class="root-input" id="main-tree-input-upload" name="root_path" value=""
checked>
<div class="tree-ctx-item overflow-scroll mh-75" id="main-tree-div-upload" data-path="">
<input type="radio" class="root-input" id="main-tree-input-upload" name="root_path" value="" checked>
<span id="main-tree" class="files-tree-title tree-caret-down root-dir" data-path="">
<i class="far fa-folder"></i>
<i class="far fa-folder-open"></i>
@ -596,8 +502,7 @@
</div>
</div>
</div>
<button id="upload_submit" type="submit" title="You must select server root dir first" disabled
class="btn btn-primary mr-2">{{ translate('serverWizard', 'importServerButton', data['lang'])
<button id="upload_submit" type="submit" title="You must select server root dir first" disabled class="btn btn-primary mr-2">{{ translate('serverWizard', 'importServerButton', data['lang'])
}}</button>
<button type="button" class="btn btn-danger mr-2 tree-reset">{{ translate('serverWizard', 'resetForm',
data['lang'])
@ -609,177 +514,7 @@
</div>
</div>
</div>
<style>
button>i.refresh-class {
margin: 0px;
}
</style>
<style>
.refresh-class:hover {
cursor: grab;
}
.scroll {
max-height: 12em;
overflow-y: auto;
}
.menu-btn {
font-size: 0.9em;
padding: 2px 10px;
}
.menu {
padding-top: 10px;
z-index: 200;
margin-top: 4px;
position: absolute;
background-color: var(--card-banner-bg);
}
.menu-option {
padding: 6px 20px 6px;
color: white;
}
#overlay {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
z-index: 100;
}
</style>
<style>
/* Remove default bullets */
.tree-view,
.tree-nested {
list-style-type: none;
margin: 0;
padding: 0;
margin-left: 10px;
}
/* Style the items */
.tree-item,
.files-tree-title {
cursor: pointer;
user-select: none;
/* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder {
display: inline-block;
}
.tree-caret .fa-folder-open {
display: none;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down .fa-folder {
display: none;
}
.tree-caret-down .fa-folder-open {
display: inline-block;
}
/* Hide the nested list */
.tree-nested {
display: none;
}
#op_logo {
position: relative;
top: 50%;
transform: translateY(-50%);
}
</style>
<style>
.scroll {
max - height: 12em;
overflow - y: auto;
}
.menu - btn {
font - size: 0.9em;
padding: 2px 10px;
}
.menu {
padding - top: 10px;
z - index: 200;
margin - top: 4px;
position: absolute;
background - color: #2a2c44;
}
.menu - option {
padding: 6px 20px 6px;
color: white;
}
#overlay {
position: absolute;
top: 0px;
left: 0px;
width: 100 %;
height: 100 %;
z - index: 100;
}
</style>
<style>
/* Remove default bullets */
.tree-view,
.tree-nested {
list - style - type: none;
margin: 0;
padding: 0;
margin-left: 10px;
}
/* Style the items */
.tree-item,
.files-tree-title {
cursor: pointer;
user-select: none;
/* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.tree-caret .fa-folder {
display: inline-block;
}
.tree-caret .fa-folder-open {
display: none;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.tree-caret-down .fa-folder {
display: none;
}
.tree-caret-down .fa-folder-open {
display: inline-block;
}
/* Hide the nested list */
.tree-nested {
display: none;
}
#op_logo {
position: relative;
top: 50%;
transform: translateY(-50%);
}
</style>
</style>
<link rel="stylesheet" href="/static/assets/css/partial/crafty-wizard.css">
{% end %}

View File

@ -508,7 +508,8 @@
},
"serverSchedules": {
"action": "Action",
"actionId": "Select Action Child",
"actionId": "Action Child",
"backupPol": "Backup Policy",
"areYouSure": "Delete Scheduled Task?",
"cancel": "Cancel",
"cannotSee": "Not seeing everything?",

View File

@ -20,3 +20,4 @@ tzlocal==5.1
jsonschema==4.19.1
orjson==3.9.15
prometheus-client==0.17.1
pillow==10.4.0