Merge branch 'dev' into 'feature/upload-import'

# Conflicts:
#   app/frontend/templates/server/wizard.html
This commit is contained in:
Andrew 2022-10-02 19:10:05 +00:00
commit 5f8c0dab4c
24 changed files with 43976 additions and 22533 deletions

View File

@ -1,9 +1,11 @@
# Changelog # Changelog
## --- [4.0.15] - 2022/TBD ## --- [4.0.15] - 2022/10/02
### New features ### New features
TBD - Base Theme Switching (Dark, Light, Default) 🤩🎨 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/471))
### Bug fixes ### Bug fixes
TBD - Fix traceback on basic schedule with "days" interval ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/469))
- Fix bad method call with API stdin ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/470))<br>
*(Thank you ['IWant2Tryhard'](https://github.com/MyNameTsThad) for catching that 🐛)*
### Tweaks ### Tweaks
TBD TBD
### Lang ### Lang

View File

@ -241,6 +241,7 @@ class UsersController:
email="default@example.com", email="default@example.com",
enabled: bool = True, enabled: bool = True,
superuser: bool = False, superuser: bool = False,
theme="default",
): ):
return self.users_helper.add_user( return self.users_helper.add_user(
username, username,
@ -249,6 +250,7 @@ class UsersController:
email=email, email=email,
enabled=enabled, enabled=enabled,
superuser=superuser, superuser=superuser,
theme=theme,
) )
@staticmethod @staticmethod

View File

@ -43,6 +43,7 @@ class Users(BaseModel):
hints = BooleanField(default=True) hints = BooleanField(default=True)
manager = IntegerField(default=None, null=True) manager = IntegerField(default=None, null=True)
pfp = CharField(default="/static/assets/images/faces-clipart/pic-3.png") pfp = CharField(default="/static/assets/images/faces-clipart/pic-3.png")
theme = CharField(default="default")
class Meta: class Meta:
table_name = "users" table_name = "users"
@ -210,6 +211,7 @@ class HelperUsers:
email: t.Optional[str] = None, email: t.Optional[str] = None,
enabled: bool = True, enabled: bool = True,
superuser: bool = False, superuser: bool = False,
theme: str = "default",
) -> str: ) -> str:
if password is not None: if password is not None:
pw_enc = self.helper.encode_pass(password) pw_enc = self.helper.encode_pass(password)
@ -225,6 +227,7 @@ class HelperUsers:
Users.superuser: superuser, Users.superuser: superuser,
Users.created: Helpers.get_time_as_string(), Users.created: Helpers.get_time_as_string(),
Users.manager: manager, Users.manager: manager,
Users.theme: theme,
} }
).execute() ).execute()
return user_id return user_id

View File

@ -399,6 +399,10 @@ class Helpers:
) )
return False return False
@staticmethod
def get_themes():
return ["default", "dark", "light", "ronald"]
@staticmethod @staticmethod
def get_local_ip(): def get_local_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

View File

@ -878,6 +878,7 @@ class PanelHandler(BaseHandler):
page_data["user"]["roles"] = set() page_data["user"]["roles"] = set()
page_data["user"]["hints"] = True page_data["user"]["hints"] = True
page_data["superuser"] = superuser page_data["superuser"] = superuser
page_data["themes"] = self.helper.get_themes()
if EnumPermissionsCrafty.USER_CONFIG not in exec_user_crafty_permissions: if EnumPermissionsCrafty.USER_CONFIG not in exec_user_crafty_permissions:
self.redirect( self.redirect(
@ -1092,6 +1093,7 @@ class PanelHandler(BaseHandler):
page_data["exec_user"] = exec_user["user_id"] page_data["exec_user"] = exec_user["user_id"]
page_data["servers_all"] = self.controller.servers.get_all_defined_servers() page_data["servers_all"] = self.controller.servers.get_all_defined_servers()
page_data["superuser"] = superuser page_data["superuser"] = superuser
page_data["themes"] = self.helper.get_themes()
if page_data["user"]["manager"] is not None: if page_data["user"]["manager"] is not None:
page_data["manager"] = self.controller.users.get_user_by_id( page_data["manager"] = self.controller.users.get_user_by_id(
page_data["user"]["manager"] page_data["user"]["manager"]
@ -1700,7 +1702,7 @@ class PanelHandler(BaseHandler):
# only check for time if it's number of days # only check for time if it's number of days
if interval_type == "days": if interval_type == "days":
sch_time = bleach.clean(self.get_argument("time", None)) sch_time = bleach.clean(self.get_argument("time", None))
if interval > 30: if int(interval) > 30:
self.redirect( self.redirect(
"/panel/error?error=Invalid argument." "/panel/error?error=Invalid argument."
" Days must be 30 or fewer." " Days must be 30 or fewer."
@ -1868,7 +1870,7 @@ class PanelHandler(BaseHandler):
# only check for time if it's number of days # only check for time if it's number of days
if interval_type == "days": if interval_type == "days":
sch_time = bleach.clean(self.get_argument("time", None)) sch_time = bleach.clean(self.get_argument("time", None))
if interval > 30: if int(interval) > 30:
self.redirect( self.redirect(
"/panel/error?error=Invalid argument." "/panel/error?error=Invalid argument."
" Days must be 30 or fewer." " Days must be 30 or fewer."
@ -2011,6 +2013,7 @@ class PanelHandler(BaseHandler):
user_id = bleach.clean(self.get_argument("id", None)) user_id = bleach.clean(self.get_argument("id", None))
user = self.controller.users.get_user_by_id(user_id) user = self.controller.users.get_user_by_id(user_id)
username = bleach.clean(self.get_argument("username", None).lower()) username = bleach.clean(self.get_argument("username", None).lower())
theme = bleach.clean(self.get_argument("theme", "default"))
if ( if (
username != self.controller.users.get_user_by_id(user_id)["username"] username != self.controller.users.get_user_by_id(user_id)["username"]
and username in self.controller.users.get_all_usernames() and username in self.controller.users.get_all_usernames()
@ -2077,6 +2080,7 @@ class PanelHandler(BaseHandler):
"email": email, "email": email,
"lang": lang, "lang": lang,
"hints": hints, "hints": hints,
"theme": theme,
} }
self.controller.users.update_user(user_id, user_data=user_data) self.controller.users.update_user(user_id, user_data=user_data)
@ -2113,6 +2117,7 @@ class PanelHandler(BaseHandler):
"lang": lang, "lang": lang,
"superuser": superuser, "superuser": superuser,
"hints": hints, "hints": hints,
"theme": theme,
} }
user_crafty_data = { user_crafty_data = {
"permissions_mask": permissions_mask, "permissions_mask": permissions_mask,
@ -2224,6 +2229,7 @@ class PanelHandler(BaseHandler):
password1 = bleach.clean(self.get_argument("password1", None)) password1 = bleach.clean(self.get_argument("password1", None))
email = bleach.clean(self.get_argument("email", "default@example.com")) email = bleach.clean(self.get_argument("email", "default@example.com"))
enabled = int(float(self.get_argument("enabled", "0"))) enabled = int(float(self.get_argument("enabled", "0")))
theme = bleach.clean(self.get_argument("theme"), "default")
hints = True hints = True
lang = bleach.clean( lang = bleach.clean(
self.get_argument("lang", self.helper.get_setting("language")) self.get_argument("lang", self.helper.get_setting("language"))
@ -2279,6 +2285,7 @@ class PanelHandler(BaseHandler):
email=email, email=email,
enabled=enabled, enabled=enabled,
superuser=new_superuser, superuser=new_superuser,
theme=theme,
) )
user_data = {"roles": roles, "lang": lang, "hints": True} user_data = {"roles": roles, "lang": lang, "hints": True}
user_crafty_data = { user_crafty_data = {

View File

@ -26,7 +26,7 @@ class ApiServersServerStdinHandler(BaseApiHandler):
# if the user doesn't have Commands permission, return an error # if the user doesn't have Commands permission, return an error
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
svr = self.controller.get_server_obj_optional(server_id) svr = self.controller.servers.get_server_obj_optional(server_id)
if svr is None: if svr is None:
# It's in auth_data[0] but not as a Server object # It's in auth_data[0] but not as a Server object
logger.critical( logger.critical(

View File

@ -105,6 +105,7 @@ class ApiUsersIndexHandler(BaseApiHandler):
permissions = data.get("permissions", None) permissions = data.get("permissions", None)
roles = data.get("roles", None) roles = data.get("roles", None)
hints = data.get("hints", True) hints = data.get("hints", True)
theme = data.get("theme", "default")
if username.lower() in ["system", ""]: if username.lower() in ["system", ""]:
return self.finish_json( return self.finish_json(
@ -155,6 +156,7 @@ class ApiUsersIndexHandler(BaseApiHandler):
email, email,
enabled, enabled,
new_superuser, new_superuser,
theme,
) )
self.controller.users.update_user( self.controller.users.update_user(
user_id, user_id,

View File

@ -1,11 +1,11 @@
.select-css option { .select-css option {
background-color: #1C1E2F; background-color: var(--deep-bg);
color: white color: var(--base-text)
} }
.select-css option:checked { .select-css option:checked {
background-color: #1C1E2F; background-color: var(--deep-bg);
color: white color: var(--base-text)
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -3,68 +3,122 @@
* License - https://fontawesome.com/license (Commercial License) * License - https://fontawesome.com/license (Commercial License)
*/ */
svg:not(:root).svg-inline--fa { svg:not(:root).svg-inline--fa {
overflow: visible; } overflow: visible;
}
.svg-inline--fa { .svg-inline--fa {
display: inline-block; display: inline-block;
font-size: inherit; font-size: inherit;
height: 1em; height: 1em;
overflow: visible; overflow: visible;
vertical-align: -.125em; } vertical-align: -.125em;
}
.svg-inline--fa.fa-lg { .svg-inline--fa.fa-lg {
vertical-align: -.225em; } vertical-align: -.225em;
}
.svg-inline--fa.fa-w-1 { .svg-inline--fa.fa-w-1 {
width: 0.0625em; } width: 0.0625em;
}
.svg-inline--fa.fa-w-2 { .svg-inline--fa.fa-w-2 {
width: 0.125em; } width: 0.125em;
}
.svg-inline--fa.fa-w-3 { .svg-inline--fa.fa-w-3 {
width: 0.1875em; } width: 0.1875em;
}
.svg-inline--fa.fa-w-4 { .svg-inline--fa.fa-w-4 {
width: 0.25em; } width: 0.25em;
}
.svg-inline--fa.fa-w-5 { .svg-inline--fa.fa-w-5 {
width: 0.3125em; } width: 0.3125em;
}
.svg-inline--fa.fa-w-6 { .svg-inline--fa.fa-w-6 {
width: 0.375em; } width: 0.375em;
}
.svg-inline--fa.fa-w-7 { .svg-inline--fa.fa-w-7 {
width: 0.4375em; } width: 0.4375em;
}
.svg-inline--fa.fa-w-8 { .svg-inline--fa.fa-w-8 {
width: 0.5em; } width: 0.5em;
}
.svg-inline--fa.fa-w-9 { .svg-inline--fa.fa-w-9 {
width: 0.5625em; } width: 0.5625em;
}
.svg-inline--fa.fa-w-10 { .svg-inline--fa.fa-w-10 {
width: 0.625em; } width: 0.625em;
}
.svg-inline--fa.fa-w-11 { .svg-inline--fa.fa-w-11 {
width: 0.6875em; } width: 0.6875em;
}
.svg-inline--fa.fa-w-12 { .svg-inline--fa.fa-w-12 {
width: 0.75em; } width: 0.75em;
}
.svg-inline--fa.fa-w-13 { .svg-inline--fa.fa-w-13 {
width: 0.8125em; } width: 0.8125em;
}
.svg-inline--fa.fa-w-14 { .svg-inline--fa.fa-w-14 {
width: 0.875em; } width: 0.875em;
}
.svg-inline--fa.fa-w-15 { .svg-inline--fa.fa-w-15 {
width: 0.9375em; } width: 0.9375em;
}
.svg-inline--fa.fa-w-16 { .svg-inline--fa.fa-w-16 {
width: 1em; } width: 1em;
}
.svg-inline--fa.fa-w-17 { .svg-inline--fa.fa-w-17 {
width: 1.0625em; } width: 1.0625em;
}
.svg-inline--fa.fa-w-18 { .svg-inline--fa.fa-w-18 {
width: 1.125em; } width: 1.125em;
}
.svg-inline--fa.fa-w-19 { .svg-inline--fa.fa-w-19 {
width: 1.1875em; } width: 1.1875em;
}
.svg-inline--fa.fa-w-20 { .svg-inline--fa.fa-w-20 {
width: 1.25em; } width: 1.25em;
}
.svg-inline--fa.fa-pull-left { .svg-inline--fa.fa-pull-left {
margin-right: .3em; margin-right: .3em;
width: auto; } width: auto;
}
.svg-inline--fa.fa-pull-right { .svg-inline--fa.fa-pull-right {
margin-left: .3em; margin-left: .3em;
width: auto; } width: auto;
}
.svg-inline--fa.fa-border { .svg-inline--fa.fa-border {
height: 1.5em; } height: 1.5em;
}
.svg-inline--fa.fa-li { .svg-inline--fa.fa-li {
width: 2em; } width: 2em;
}
.svg-inline--fa.fa-fw { .svg-inline--fa.fa-fw {
width: 1.25em; } width: 1.25em;
}
.fa-layers svg.svg-inline--fa { .fa-layers svg.svg-inline--fa {
bottom: 0; bottom: 0;
@ -72,7 +126,8 @@ svg:not(:root).svg-inline--fa {
margin: auto; margin: auto;
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; } top: 0;
}
.fa-layers { .fa-layers {
display: inline-block; display: inline-block;
@ -80,15 +135,20 @@ svg:not(:root).svg-inline--fa {
position: relative; position: relative;
text-align: center; text-align: center;
vertical-align: -.125em; vertical-align: -.125em;
width: 1em; } width: 1em;
}
.fa-layers svg.svg-inline--fa { .fa-layers svg.svg-inline--fa {
-webkit-transform-origin: center center; -webkit-transform-origin: center center;
transform-origin: center center; } transform-origin: center center;
}
.fa-layers-text, .fa-layers-counter { .fa-layers-text,
.fa-layers-counter {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
text-align: center; } text-align: center;
}
.fa-layers-text { .fa-layers-text {
left: 50%; left: 50%;
@ -96,14 +156,15 @@ svg:not(:root).svg-inline--fa {
-webkit-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
-webkit-transform-origin: center center; -webkit-transform-origin: center center;
transform-origin: center center; } transform-origin: center center;
}
.fa-layers-counter { .fa-layers-counter {
background-color: #ff253a; background-color: #ff253a;
border-radius: 1em; border-radius: 1em;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
color: #fff; var(--base-text);
height: 1.5em; height: 1.5em;
line-height: 1; line-height: 1;
max-width: 5em; max-width: 5em;
@ -116,7 +177,8 @@ svg:not(:root).svg-inline--fa {
-webkit-transform: scale(0.25); -webkit-transform: scale(0.25);
transform: scale(0.25); transform: scale(0.25);
-webkit-transform-origin: top right; -webkit-transform-origin: top right;
transform-origin: top right; } transform-origin: top right;
}
.fa-layers-bottom-right { .fa-layers-bottom-right {
bottom: 0; bottom: 0;
@ -125,7 +187,8 @@ svg:not(:root).svg-inline--fa {
-webkit-transform: scale(0.25); -webkit-transform: scale(0.25);
transform: scale(0.25); transform: scale(0.25);
-webkit-transform-origin: bottom right; -webkit-transform-origin: bottom right;
transform-origin: bottom right; } transform-origin: bottom right;
}
.fa-layers-bottom-left { .fa-layers-bottom-left {
bottom: 0; bottom: 0;
@ -135,7 +198,8 @@ svg:not(:root).svg-inline--fa {
-webkit-transform: scale(0.25); -webkit-transform: scale(0.25);
transform: scale(0.25); transform: scale(0.25);
-webkit-transform-origin: bottom left; -webkit-transform-origin: bottom left;
transform-origin: bottom left; } transform-origin: bottom left;
}
.fa-layers-top-right { .fa-layers-top-right {
right: 0; right: 0;
@ -143,7 +207,8 @@ svg:not(:root).svg-inline--fa {
-webkit-transform: scale(0.25); -webkit-transform: scale(0.25);
transform: scale(0.25); transform: scale(0.25);
-webkit-transform-origin: top right; -webkit-transform-origin: top right;
transform-origin: top right; } transform-origin: top right;
}
.fa-layers-top-left { .fa-layers-top-left {
left: 0; left: 0;
@ -152,145 +217,186 @@ svg:not(:root).svg-inline--fa {
-webkit-transform: scale(0.25); -webkit-transform: scale(0.25);
transform: scale(0.25); transform: scale(0.25);
-webkit-transform-origin: top left; -webkit-transform-origin: top left;
transform-origin: top left; } transform-origin: top left;
}
.fa-lg { .fa-lg {
font-size: 1.33333em; font-size: 1.33333em;
line-height: 0.75em; line-height: 0.75em;
vertical-align: -.0667em; } vertical-align: -.0667em;
}
.fa-xs { .fa-xs {
font-size: .75em; } font-size: .75em;
}
.fa-sm { .fa-sm {
font-size: .875em; } font-size: .875em;
}
.fa-1x { .fa-1x {
font-size: 1em; } font-size: 1em;
}
.fa-2x { .fa-2x {
font-size: 2em; } font-size: 2em;
}
.fa-3x { .fa-3x {
font-size: 3em; } font-size: 3em;
}
.fa-4x { .fa-4x {
font-size: 4em; } font-size: 4em;
}
.fa-5x { .fa-5x {
font-size: 5em; } font-size: 5em;
}
.fa-6x { .fa-6x {
font-size: 6em; } font-size: 6em;
}
.fa-7x { .fa-7x {
font-size: 7em; } font-size: 7em;
}
.fa-8x { .fa-8x {
font-size: 8em; } font-size: 8em;
}
.fa-9x { .fa-9x {
font-size: 9em; } font-size: 9em;
}
.fa-10x { .fa-10x {
font-size: 10em; } font-size: 10em;
}
.fa-fw { .fa-fw {
text-align: center; text-align: center;
width: 1.25em; } width: 1.25em;
}
.fa-ul { .fa-ul {
list-style-type: none; list-style-type: none;
margin-left: 2.5em; margin-left: 2.5em;
padding-left: 0; } padding-left: 0;
}
.fa-ul>li { .fa-ul>li {
position: relative; } position: relative;
}
.fa-li { .fa-li {
left: -2em; left: -2em;
position: absolute; position: absolute;
text-align: center; text-align: center;
width: 2em; width: 2em;
line-height: inherit; } line-height: inherit;
}
.fa-border { .fa-border {
border: solid 0.08em #eee; border: solid 0.08em #eee;
border-radius: .1em; border-radius: .1em;
padding: .2em .25em .15em; } padding: .2em .25em .15em;
}
.fa-pull-left { .fa-pull-left {
float: left; } float: left;
}
.fa-pull-right { .fa-pull-right {
float: right; } float: right;
}
.fa.fa-pull-left, .fa.fa-pull-left,
.fas.fa-pull-left, .fas.fa-pull-left,
.far.fa-pull-left, .far.fa-pull-left,
.fal.fa-pull-left, .fal.fa-pull-left,
.fab.fa-pull-left { .fab.fa-pull-left {
margin-right: .3em; } margin-right: .3em;
}
.fa.fa-pull-right, .fa.fa-pull-right,
.fas.fa-pull-right, .fas.fa-pull-right,
.far.fa-pull-right, .far.fa-pull-right,
.fal.fa-pull-right, .fal.fa-pull-right,
.fab.fa-pull-right { .fab.fa-pull-right {
margin-left: .3em; } margin-left: .3em;
}
.fa-spin { .fa-spin {
-webkit-animation: fa-spin 2s infinite linear; -webkit-animation: fa-spin 2s infinite linear;
animation: fa-spin 2s infinite linear; } animation: fa-spin 2s infinite linear;
}
.fa-pulse { .fa-pulse {
-webkit-animation: fa-spin 1s infinite steps(8); -webkit-animation: fa-spin 1s infinite steps(8);
animation: fa-spin 1s infinite steps(8); } animation: fa-spin 1s infinite steps(8);
}
@-webkit-keyframes fa-spin { @-webkit-keyframes fa-spin {
0% { 0% {
-webkit-transform: rotate(0deg); -webkit-transform: rotate(0deg);
transform: rotate(0deg); } transform: rotate(0deg);
}
100% { 100% {
-webkit-transform: rotate(360deg); -webkit-transform: rotate(360deg);
transform: rotate(360deg); } } transform: rotate(360deg);
}
}
@keyframes fa-spin { @keyframes fa-spin {
0% { 0% {
-webkit-transform: rotate(0deg); -webkit-transform: rotate(0deg);
transform: rotate(0deg); } transform: rotate(0deg);
}
100% { 100% {
-webkit-transform: rotate(360deg); -webkit-transform: rotate(360deg);
transform: rotate(360deg); } } transform: rotate(360deg);
}
}
.fa-rotate-90 { .fa-rotate-90 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
-webkit-transform: rotate(90deg); -webkit-transform: rotate(90deg);
transform: rotate(90deg); } transform: rotate(90deg);
}
.fa-rotate-180 { .fa-rotate-180 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
-webkit-transform: rotate(180deg); -webkit-transform: rotate(180deg);
transform: rotate(180deg); } transform: rotate(180deg);
}
.fa-rotate-270 { .fa-rotate-270 {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
-webkit-transform: rotate(270deg); -webkit-transform: rotate(270deg);
transform: rotate(270deg); } transform: rotate(270deg);
}
.fa-flip-horizontal { .fa-flip-horizontal {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
-webkit-transform: scale(-1, 1); -webkit-transform: scale(-1, 1);
transform: scale(-1, 1); } transform: scale(-1, 1);
}
.fa-flip-vertical { .fa-flip-vertical {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
-webkit-transform: scale(1, -1); -webkit-transform: scale(1, -1);
transform: scale(1, -1); } transform: scale(1, -1);
}
.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical { .fa-flip-both,
.fa-flip-horizontal.fa-flip-vertical {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
-webkit-transform: scale(-1, -1); -webkit-transform: scale(-1, -1);
transform: scale(-1, -1); } transform: scale(-1, -1);
}
:root .fa-rotate-90, :root .fa-rotate-90,
:root .fa-rotate-180, :root .fa-rotate-180,
@ -299,13 +405,15 @@ svg:not(:root).svg-inline--fa {
:root .fa-flip-vertical, :root .fa-flip-vertical,
:root .fa-flip-both { :root .fa-flip-both {
-webkit-filter: none; -webkit-filter: none;
filter: none; } filter: none;
}
.fa-stack { .fa-stack {
display: inline-block; display: inline-block;
height: 2em; height: 2em;
position: relative; position: relative;
width: 2.5em; } width: 2.5em;
}
.fa-stack-1x, .fa-stack-1x,
.fa-stack-2x { .fa-stack-2x {
@ -314,18 +422,22 @@ svg:not(:root).svg-inline--fa {
margin: auto; margin: auto;
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; } top: 0;
}
.svg-inline--fa.fa-stack-1x { .svg-inline--fa.fa-stack-1x {
height: 1em; height: 1em;
width: 1.25em; } width: 1.25em;
}
.svg-inline--fa.fa-stack-2x { .svg-inline--fa.fa-stack-2x {
height: 2em; height: 2em;
width: 2.5em; } width: 2.5em;
}
.fa-inverse { .fa-inverse {
color: #fff; } var(--base-text);
}
.sr-only { .sr-only {
border: 0; border: 0;
@ -335,37 +447,46 @@ svg:not(:root).svg-inline--fa {
overflow: hidden; overflow: hidden;
padding: 0; padding: 0;
position: absolute; position: absolute;
width: 1px; } width: 1px;
}
.sr-only-focusable:active, .sr-only-focusable:focus { .sr-only-focusable:active,
.sr-only-focusable:focus {
clip: auto; clip: auto;
height: auto; height: auto;
margin: 0; margin: 0;
overflow: visible; overflow: visible;
position: static; position: static;
width: auto; } width: auto;
}
.svg-inline--fa .fa-primary { .svg-inline--fa .fa-primary {
fill: var(--fa-primary-color, currentColor); fill: var(--fa-primary-color, currentColor);
opacity: 1; opacity: 1;
opacity: var(--fa-primary-opacity, 1); } opacity: var(--fa-primary-opacity, 1);
}
.svg-inline--fa .fa-secondary { .svg-inline--fa .fa-secondary {
fill: var(--fa-secondary-color, currentColor); fill: var(--fa-secondary-color, currentColor);
opacity: 0.4; opacity: 0.4;
opacity: var(--fa-secondary-opacity, 0.4); } opacity: var(--fa-secondary-opacity, 0.4);
}
.svg-inline--fa.fa-swap-opacity .fa-primary { .svg-inline--fa.fa-swap-opacity .fa-primary {
opacity: 0.4; opacity: 0.4;
opacity: var(--fa-secondary-opacity, 0.4); } opacity: var(--fa-secondary-opacity, 0.4);
}
.svg-inline--fa.fa-swap-opacity .fa-secondary { .svg-inline--fa.fa-swap-opacity .fa-secondary {
opacity: 1; opacity: 1;
opacity: var(--fa-primary-opacity, 1); } opacity: var(--fa-primary-opacity, 1);
}
.svg-inline--fa mask .fa-primary, .svg-inline--fa mask .fa-primary,
.svg-inline--fa mask .fa-secondary { .svg-inline--fa mask .fa-secondary {
fill: black; } fill: black;
}
.fad.fa-inverse { .fad.fa-inverse {
color: #fff; } var(--base-text);
}

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ data['lang_page'] }}"> <html lang="{{ data['lang_page'] }}" class="{{data['user_data'].get('theme', 'default')}}">
<head> <head>
<!-- Required meta tags --> <!-- Required meta tags -->
@ -54,7 +54,7 @@
</head> </head>
<body class="dark-theme"> <body>
<div class="container-scroller"> <div class="container-scroller">
<!-- partial:partials/_navbar.html --> <!-- partial:partials/_navbar.html -->
<nav class="navbar default-layout col-lg-12 col-12 p-0 fixed-top d-flex flex-row"> <nav class="navbar default-layout col-lg-12 col-12 p-0 fixed-top d-flex flex-row">
@ -127,7 +127,7 @@
width: 180px; width: 180px;
margin-left: 10px; margin-left: 10px;
margin-right: 10px; margin-right: 10px;
background: #282a40; background: var(--card-banner-bg);
transition: right 0.75s, opacity 0.75s, top 0.75s; transition: right 0.75s, opacity 0.75s, top 0.75s;
right: -6rem; right: -6rem;
opacity: 0.1; opacity: 0.1;

View File

@ -152,13 +152,13 @@
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
border-bottom: var(--table-border-width) solid #383e5d; border-bottom: var(--table-border-width) solid var(--outline);
transition: border-bottom-color 500ms; transition: border-bottom-color 500ms;
padding-bottom: 5px; padding-bottom: 5px;
user-select: none; user-select: none;
} }
table.rotate-table > tbody td { table.rotate-table > tbody td {
border-right: var(--table-border-width) solid #383e5d; border-right: var(--table-border-width) solid var(--outline);
/* make sure this is at least as wide as sqrt(2) * height of the tallest letter in your font or the headers will overlap each other*/ /* make sure this is at least as wide as sqrt(2) * height of the tallest letter in your font or the headers will overlap each other*/
min-width: 30px; min-width: 30px;
padding-top: 2px; padding-top: 2px;

View File

@ -121,6 +121,19 @@ data['lang']) }}{% end %}
{% end %} {% end %}
</select> </select>
</div> </div>
<div class="form-group">
<label class="form-label" for="theme">{{ translate('userConfig', 'userTheme', data['lang'])
}}</label>
<select class="form-select form-control form-control-lg select-css" id="language"
name="theme" form="user_form">
<option value="{{data['user'].get('theme', 'default')}}">{{data['user'].get('theme', 'default')}}</option>
{% for theme in data['themes'] %}
{% if theme != data['user'].get('theme', 'default') %}
<option value="{{theme}}">{{theme}}</option>
{% end %}
{% end %}
</select>
</div>
{% if data['superuser'] %} {% if data['superuser'] %}
<div class="form-group"> <div class="form-group">
<label class="form-label" for="manager">{{ translate('userConfig', 'selectManager', <label class="form-label" for="manager">{{ translate('userConfig', 'selectManager',

View File

@ -42,7 +42,6 @@
<div class="col-md-6 col-sm-12"> <div class="col-md-6 col-sm-12">
<style> <style>
.playerItem { .playerItem {
background: #1c1e2f;
padding: 1rem; padding: 1rem;
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;

View File

@ -42,7 +42,7 @@
<div class="col-md-12"> <div class="col-md-12">
<div class="input-group"> <div class="input-group">
<div id="virt_console" class="" <div id="virt_console" class=""
style="font-size: .8em; padding: 5px 10px; border: 1px solid #383e5d; background-color:#2a2c44;height:500px; overflow: scroll;"> style="font-size: .8em; padding: 5px 10px; border: 1px solid var(--outline); background-color:var(--card-banner-bg);height:500px; overflow: scroll;">
</div> </div>
</div> </div>
<br /> <br />

View File

@ -14,7 +14,8 @@
<div class="col-12"> <div class="col-12">
<div class="page-header"> <div class="page-header">
<h4 class="page-title"> <h4 class="page-title">
{{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{ data['server_stats']['server_id']['server_name'] }} {{ translate('serverDetails', 'serverDetails', data['lang']) }} - {{
data['server_stats']['server_id']['server_name'] }}
<br /> <br />
<small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small> <small>UUID: {{ data['server_stats']['server_id']['server_uuid'] }}</small>
</h4> </h4>
@ -40,16 +41,21 @@
</span> </span>
<div class="col-md-12"> <div class="col-md-12">
<button id="to-bottom" style="visibility: hidden; float: right;" class="btn btn-outline-success">{{ translate('serverDetails', 'reset', data['lang']) }}</button> <button id="to-bottom" style="visibility: hidden; float: right;" class="btn btn-outline-success">{{
translate('serverDetails', 'reset', data['lang']) }}</button>
<br /> <br />
<br /> <br />
<div class="input-group"> <div class="input-group">
<div id="virt_console" class="" style="width: 100%; font-size: .8em; padding: 5px 10px; border: 1px solid #383e5d; background-color:#2a2c44;height:500px; overflow: scroll;"></div> <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>
</div> </div>
<br /> <br />
<div style="gap: 0.5rem;" class="input-group flex-wrap"> <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=""> <input style="min-width: 10rem;" type="text" class="form-control" id="server_command"
name="server_command" placeholder="{{ translate('serverTerm', 'commandInput', data['lang']) }}"
autofocus="">
<span class="input-group-btn ml-5"> <span class="input-group-btn ml-5">
<button id="submit" class="btn btn-sm btn-info" type="button">{{ translate('serverTerm', 'sendCommand', <button id="submit" class="btn btn-sm btn-info" type="button">{{ translate('serverTerm', 'sendCommand',
data['lang']) }}</button> data['lang']) }}</button>
@ -57,30 +63,60 @@
</div> </div>
{% if data['permissions']['Commands'] in data['user_permissions'] %} {% if data['permissions']['Commands'] in data['user_permissions'] %}
{% if data['server_stats']['updating']%} {% if 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"> <div id="update_control_buttons"
<button onclick="" id="start-btn" style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1 disabled"><i class="mt-4 flex-wrap d-flex justify-content-between justify-content-md-center align-items-center px-5 px-md-0"
class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'updating', data['lang']) }}</button> style="visibility: visible">
<button onclick="" id="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button> <button onclick="" id="start-btn" style="max-width: 7rem;"
<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> class="btn btn-warning m-1 flex-grow-1 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',
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>
</div> </div>
{% elif data['waiting_start'] %} {% 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"> <div id="control_buttons"
<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', 'starting', data['lang']) }}</button> 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="restart-btn" style="max-width: 7rem;" class="btn btn-outline-primary m-1 flex-grow-1 disabled">{% raw translate('serverTerm', 'restart', data['lang']) %}</button> style="visibility: visible">
<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> <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',
'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',
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>
</div> </div>
{% elif data['importing'] %} {% 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"> <div id="control_buttons"
<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> {{ translate('serverTerm', 'importing', 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> {{
translate('serverTerm', 'importing',
data['lang']) }}</button> 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', data['lang']) %}</button> <button onclick="" id="restart-btn" style="max-width: 7rem;"
<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> class="btn btn-outline-primary m-1 flex-grow-1 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>
</div> </div>
{% else %} {% 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"> <div id="control_buttons"
<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> 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, '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> style="visibility: visible">
<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, '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="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>
</div> </div>
{% end %} {% end %}
{% end %} {% end %}

View File

@ -8,7 +8,7 @@
{% block content %} {% block content %}
<!-- View for Large screen --> <!-- View for Large screen -->
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="content-wrapper col-md login-modal d-none d-sm-block" style="background-color: #222437;"> <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%;'> <img src="/static/assets/images/logo_long.png" style='width: 25%; margin-left: 38%;'>
<hr /> <hr />
<div class="table-responsive"> <div class="table-responsive">
@ -40,7 +40,8 @@
</td> </td>
<td id="server_motd_{{ server['stats']['server_id']['server_id'] }}"> <td id="server_motd_{{ server['stats']['server_id']['server_id'] }}">
{% if server['stats']['desc'] != 'False' %} {% if server['stats']['desc'] != 'False' %}
<img src="/static/assets/images/pack.png" alt="icon" style="-webkit-filter:grayscale(100%); filter:grayscale(100%)" /> <img src="/static/assets/images/pack.png" alt="icon"
style="-webkit-filter:grayscale(100%); filter:grayscale(100%)" />
<span id="input_motd_{{ server['stats']['server_id']['server_id'] }}" class="input_motd">{{ <span id="input_motd_{{ server['stats']['server_id']['server_id'] }}" class="input_motd">{{
server['stats']['desc'] }}</span> <br /> server['stats']['desc'] }}</span> <br />
{% end %} {% end %}
@ -94,7 +95,8 @@
<h2 class="mb-0 container overflow-hidden"> <h2 class="mb-0 container overflow-hidden">
<div class="row"> <div class="row">
<div class="col-8 mx-0 px-0"> <div class="col-8 mx-0 px-0">
<a id="m_server_name_{{ server['stats']['server_id']['server_id'] }}" class="btn btn-link d-flex justify-content-center" type="button" data-toggle="collapse" <a id="m_server_name_{{ server['stats']['server_id']['server_id'] }}"
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" data-target="#collapse-{{server['server_data']['server_id']}}" aria-expanded="false"
aria-controls="collapse-{{server['server_data']['server_id']}}"> aria-controls="collapse-{{server['server_data']['server_id']}}">
<i class="fas fa-server"></i> <i class="fas fa-server"></i>
@ -102,13 +104,16 @@
</a> </a>
</div> </div>
<div class="col-4 mx-0 px-0"> <div class="col-4 mx-0 px-0">
<a id="m_server_online_status_{{ server['stats']['server_id']['server_id'] }}" class="btn btn-link d-flex justify-content-center" type="button"> <a id="m_server_online_status_{{ server['stats']['server_id']['server_id'] }}"
class="btn btn-link d-flex justify-content-center" type="button">
{% if server['stats']['running'] %} {% if server['stats']['running'] %}
<div id="m_server_players_{{ server['stats']['server_id']['server_id'] }}"> <div id="m_server_players_{{ server['stats']['server_id']['server_id'] }}">
<span class="text-success"><i class="fas fa-signal"></i> {{ server['stats']['online'] }} / {{ server['stats']['max'] }}</span> <span class="text-success"><i class="fas fa-signal"></i> {{ server['stats']['online'] }} / {{
server['stats']['max'] }}</span>
</div> </div>
{% else %} {% else %}
<span class="text-danger"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline', data['lang']) }}</span> <span class="text-danger"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline',
data['lang']) }}</span>
{% end %} {% end %}
</a> </a>
</div> </div>
@ -122,7 +127,8 @@
{% if server['stats']['int_ping_results'] != 'False' %} {% if server['stats']['int_ping_results'] != 'False' %}
<div id="m_server_motd_{{ server['stats']['server_id']['server_id'] }}" class="media"> <div id="m_server_motd_{{ server['stats']['server_id']['server_id'] }}" class="media">
{% if server['stats']['desc'] != 'False' %} {% if server['stats']['desc'] != 'False' %}
<img src="/static/assets/images/pack.png" class="w-25 mr-3" alt="icon" style="-webkit-filter:grayscale(100%); filter:grayscale(100%);" /> <img src="/static/assets/images/pack.png" class="w-25 mr-3" alt="icon"
style="-webkit-filter:grayscale(100%); filter:grayscale(100%);" />
{% end %} {% end %}
<div class="media-body"> <div class="media-body">
{% if server['stats']['desc'] != 'False' %} {% if server['stats']['desc'] != 'False' %}
@ -143,7 +149,8 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<div id="m_server_motd_{{ server['stats']['server_id']['server_id'] }}"> <div id="m_server_motd_{{ server['stats']['server_id']['server_id'] }}">
<span class="text-warning"><i class="fas fa-exclamation-triangle"></i> Crafty can't get infos from this Server </span> <span class="text-warning"><i class="fas fa-exclamation-triangle"></i> Crafty can't get infos from
this Server </span>
</div> </div>
<div id="m_server_version_{{ server['stats']['server_id']['server_id'] }}"></div> <div id="m_server_version_{{ server['stats']['server_id']['server_id'] }}"></div>
</div> </div>

View File

@ -487,7 +487,7 @@
z-index: 200; z-index: 200;
margin-top: 4px; margin-top: 4px;
position: absolute; position: absolute;
background-color: #2a2c44; background-color: var(--card-banner-bg);
} }
.menu-option { .menu-option {

View File

@ -598,6 +598,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<style> <style>
.refresh-class:hover { .refresh-class:hover {
cursor: grab; cursor: grab;
@ -613,6 +614,113 @@
padding: 2px 10px; 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>
{% end %}
{% block js%}
<script>
document.getElementById("root_files_button").addEventListener("click", function () {
if (document.forms["zip"]["server_path"].value != "") {
if (document.getElementById('root_files_button').classList.contains('clicked')) {
document.getElementById('main-tree-div').innerHTML = '<input type="radio" 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><i class="far fa-folder-open"></i>{{ translate("serverFiles", "files", data["lang"]) }}</span></input>'
} else {
document.getElementById('root_files_button').classList.add('clicked')
}
path = document.forms["zip"]["server_path"].value;
console.log(document.forms["zip"]["server_path"].value)
var token = getCookie("_xsrf");
var dialog = bootbox.dialog({
message: '<p class="text-center mb-0"><i class="fa fa-spin fa-cog"></i> Please wait while we gather your files...</p>',
closeButton: false
});
$.ajax({
type: "POST",
headers: { 'X-XSRFToken': token },
url: '/ajax/unzip_server?id=-1&path=' + path,
});
} else {
bootbox.alert("You must input a path before selecting this button");
}
.scroll {
max-height: 12em;
overflow-y: auto;
}
.menu-btn {
font-size: 0.9em;
padding: 2px 10px;
}
.menu { .menu {
padding-top: 10px; padding-top: 10px;
z-index: 200; z-index: 200;

View File

@ -0,0 +1,16 @@
# Generated by database migrator
import peewee
def migrate(migrator, database, **kwargs):
migrator.add_columns("users", theme=peewee.CharField(default="default"))
"""
Write your migrations here.
"""
def rollback(migrator, database, **kwargs):
migrator.drop_columns("users", ["theme"])
"""
Write your rollback migrations here.
"""

View File

@ -566,6 +566,7 @@
"roleName": "Role Name", "roleName": "Role Name",
"super": "Super User", "super": "Super User",
"userLang": "User Language", "userLang": "User Language",
"userTheme": "UI Theme",
"userName": "User Name", "userName": "User Name",
"userNameDesc": "What do you want to call this user?", "userNameDesc": "What do you want to call this user?",
"userRoles": "User Roles", "userRoles": "User Roles",