mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2025-01-20 02:05:30 +01:00
Merge branch 'dev' into enhancement/mobile-app
This commit is contained in:
commit
3f4e9ac0c2
30
CHANGELOG.md
30
CHANGELOG.md
@ -1,14 +1,38 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
## --- [4.0.10] - 2022/TBD
|
||||||
## --- [4.0.8] - 2022/TBD
|
|
||||||
### New features
|
### New features
|
||||||
TBD
|
TBD
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
TBD
|
||||||
|
### Tweaks
|
||||||
|
TBD
|
||||||
|
### Lang
|
||||||
|
TBD
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
## --- [4.0.9] - 2022/08/06
|
||||||
|
### Bug fixes
|
||||||
|
- Fix Schedules Traceback Bug ([Merge Request |](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/419) [Commit |](https://gitlab.com/crafty-controller/crafty-4/-/commit/f69d79b7023d6c26fccb5caeae9e47b40ebe5af2) [Commit](https://gitlab.com/crafty-controller/crafty-4/-/commit/ad318296dc93beb5533fcd13066440df9f9e799a))
|
||||||
|
- Fix handling of missing servers ([Merge Request🎉](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/420))
|
||||||
|
- Fix offline credits panel stack ([Commit](https://gitlab.com/crafty-controller/crafty-4/-/commit/247678e6c6af5e7d5dbfcf3bfdcec49fc5980e55))
|
||||||
|
### Tweaks
|
||||||
|
- credits-v2| Translator status ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/421))
|
||||||
|
- Use Names in Schedules ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/419))
|
||||||
|
### Lang
|
||||||
|
- Make Schedules panel translatable ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/419))
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
## --- [4.0.8] - 2022/08/05
|
||||||
|
### New features
|
||||||
|
- Add Crafty Version Check and notification ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/411))
|
||||||
|
### Bug fixes
|
||||||
- Fix SU status not sticking on user creation ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/410))
|
- Fix SU status not sticking on user creation ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/410))
|
||||||
- Handle Missing Java From Win Registry ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/413))
|
- Handle Missing Java From Win Registry ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/413))
|
||||||
- Disable restart while server is backing up ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/414))
|
- Disable restart while server is backing up ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/414))
|
||||||
|
- Fix server creation with serverjars API ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/415))
|
||||||
|
- Fix API Key delete confirmations ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/416))
|
||||||
### Tweaks
|
### Tweaks
|
||||||
TBD
|
- Add next run to schedule info ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/417))
|
||||||
### Lang
|
### Lang
|
||||||
- Updated `es_ES` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/412))
|
- Updated `es_ES` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/412))
|
||||||
- Added `pl_PL` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/412))
|
- Added `pl_PL` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/412))
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
|
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
|
||||||
[![Supported Python Versions](https://shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10%20-blue)](https://www.python.org)
|
[![Supported Python Versions](https://shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10%20-blue)](https://www.python.org)
|
||||||
[![Version(temp-hardcoded)](https://img.shields.io/badge/release-v4.0.8--beta-orange)](https://gitlab.com/crafty-controller/crafty-4/-/releases)
|
[![Version(temp-hardcoded)](https://img.shields.io/badge/release-v4.0.10--beta-orange)](https://gitlab.com/crafty-controller/crafty-4/-/releases)
|
||||||
[![Code Quality(temp-hardcoded)](https://img.shields.io/badge/code%20quality-10-brightgreen)](https://gitlab.com/crafty-controller/crafty-4)
|
[![Code Quality(temp-hardcoded)](https://img.shields.io/badge/code%20quality-10-brightgreen)](https://gitlab.com/crafty-controller/crafty-4)
|
||||||
[![Build Status](https://gitlab.com/crafty-controller/crafty-4/badges/master/pipeline.svg)](https://gitlab.com/crafty-controller/crafty-4/-/commits/master)
|
[![Build Status](https://gitlab.com/crafty-controller/crafty-4/badges/master/pipeline.svg)](https://gitlab.com/crafty-controller/crafty-4/-/commits/master)
|
||||||
|
|
||||||
# Crafty Controller 4.0.8-beta
|
# Crafty Controller 4.0.10-beta
|
||||||
> Python based Control Panel for your Minecraft Server
|
> Python based Control Panel for your Minecraft Server
|
||||||
|
|
||||||
## What is Crafty Controller?
|
## What is Crafty Controller?
|
||||||
|
@ -76,7 +76,7 @@ class ManagementController:
|
|||||||
interval_type,
|
interval_type,
|
||||||
start_time,
|
start_time,
|
||||||
command,
|
command,
|
||||||
comment=None,
|
name,
|
||||||
enabled=True,
|
enabled=True,
|
||||||
):
|
):
|
||||||
return HelpersManagement.create_scheduled_task(
|
return HelpersManagement.create_scheduled_task(
|
||||||
@ -86,7 +86,7 @@ class ManagementController:
|
|||||||
interval_type,
|
interval_type,
|
||||||
start_time,
|
start_time,
|
||||||
command,
|
command,
|
||||||
comment,
|
name,
|
||||||
enabled,
|
enabled,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -102,6 +102,11 @@ class ServersController(metaclass=Singleton):
|
|||||||
server_instance.update_server_instance()
|
server_instance.update_server_instance()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_unloaded_server(server_obj):
|
||||||
|
ret = HelperServers.update_server(server_obj)
|
||||||
|
return ret
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def set_download(server_id):
|
def set_download(server_id):
|
||||||
srv = ServersController().get_server_instance_by_id(server_id)
|
srv = ServersController().get_server_instance_by_id(server_id)
|
||||||
@ -146,6 +151,7 @@ class ServersController(metaclass=Singleton):
|
|||||||
def init_all_servers(self):
|
def init_all_servers(self):
|
||||||
|
|
||||||
servers = self.get_all_defined_servers()
|
servers = self.get_all_defined_servers()
|
||||||
|
self.failed_servers = []
|
||||||
|
|
||||||
for server in servers:
|
for server in servers:
|
||||||
server_id = server.get("server_id")
|
server_id = server.get("server_id")
|
||||||
@ -169,6 +175,8 @@ class ServersController(metaclass=Singleton):
|
|||||||
f"{server['server_name']} at path {server['path']}. "
|
f"{server['server_name']} at path {server['path']}. "
|
||||||
f"Skipping this server"
|
f"Skipping this server"
|
||||||
)
|
)
|
||||||
|
if server not in self.failed_servers:
|
||||||
|
self.failed_servers.append(server)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
temp_server_dict = {
|
temp_server_dict = {
|
||||||
|
@ -51,7 +51,7 @@ class ServerJars:
|
|||||||
|
|
||||||
def get_serverjar_data(self):
|
def get_serverjar_data(self):
|
||||||
data = self._read_cache()
|
data = self._read_cache()
|
||||||
return data.get("servers")
|
return data.get("types")
|
||||||
|
|
||||||
def _check_api_alive(self):
|
def _check_api_alive(self):
|
||||||
logger.info("Checking serverjars.com API status")
|
logger.info("Checking serverjars.com API status")
|
||||||
@ -70,6 +70,39 @@ class ServerJars:
|
|||||||
logger.error("unable to contact serverjars.com api")
|
logger.error("unable to contact serverjars.com api")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def manual_refresh_cache(self):
|
||||||
|
cache_file = self.helper.serverjar_cache
|
||||||
|
|
||||||
|
# debug override
|
||||||
|
# cache_old = True
|
||||||
|
|
||||||
|
# if the API is down... we bomb out
|
||||||
|
if not self._check_api_alive():
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.info("Manual Refresh requested.")
|
||||||
|
now = datetime.now()
|
||||||
|
data = {
|
||||||
|
"last_refreshed": now.strftime("%m/%d/%Y, %H:%M:%S"),
|
||||||
|
"types": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
jar_types = self._get_server_type_list()
|
||||||
|
data["types"].update(jar_types)
|
||||||
|
for s in data["types"]:
|
||||||
|
data["types"].update({s: dict.fromkeys(data["types"].get(s), {})})
|
||||||
|
for j in data["types"].get(s):
|
||||||
|
versions = self._get_jar_details(j, s)
|
||||||
|
data["types"][s].update({j: versions})
|
||||||
|
# save our cache
|
||||||
|
try:
|
||||||
|
with open(cache_file, "w", encoding="utf-8") as f:
|
||||||
|
f.write(json.dumps(data, indent=4))
|
||||||
|
logger.info("Cache file refreshed")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Unable to update serverjars.com cache file: {e}")
|
||||||
|
|
||||||
def refresh_cache(self):
|
def refresh_cache(self):
|
||||||
|
|
||||||
cache_file = self.helper.serverjar_cache
|
cache_file = self.helper.serverjar_cache
|
||||||
@ -88,22 +121,18 @@ class ServerJars:
|
|||||||
if cache_old:
|
if cache_old:
|
||||||
logger.info("Cache file is over 1 day old, refreshing")
|
logger.info("Cache file is over 1 day old, refreshing")
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
data = {"last_refreshed": now.strftime("%m/%d/%Y, %H:%M:%S"), "servers": {}}
|
data = {
|
||||||
|
"last_refreshed": now.strftime("%m/%d/%Y, %H:%M:%S"),
|
||||||
|
"types": {},
|
||||||
|
}
|
||||||
|
|
||||||
jar_types = self._get_server_type_list()
|
jar_types = self._get_server_type_list()
|
||||||
|
data["types"].update(jar_types)
|
||||||
# for each jar type
|
for s in data["types"]:
|
||||||
for j in jar_types:
|
data["types"].update({s: dict.fromkeys(data["types"].get(s), {})})
|
||||||
|
for j in data["types"].get(s):
|
||||||
# for each server
|
versions = self._get_jar_details(j, s)
|
||||||
for s in jar_types.get(j):
|
data["types"][s].update({j: versions})
|
||||||
# jar versions for this server
|
|
||||||
versions = self._get_jar_details(s)
|
|
||||||
|
|
||||||
# add these versions (a list) to the dict with
|
|
||||||
# a key of the server type
|
|
||||||
data["servers"].update({s: versions})
|
|
||||||
|
|
||||||
# save our cache
|
# save our cache
|
||||||
try:
|
try:
|
||||||
with open(cache_file, "w", encoding="utf-8") as f:
|
with open(cache_file, "w", encoding="utf-8") as f:
|
||||||
@ -113,8 +142,8 @@ class ServerJars:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Unable to update serverjars.com cache file: {e}")
|
logger.error(f"Unable to update serverjars.com cache file: {e}")
|
||||||
|
|
||||||
def _get_jar_details(self, jar_type="servers"):
|
def _get_jar_details(self, server_type, jar_type="servers"):
|
||||||
url = f"/api/fetchAll/{jar_type}"
|
url = f"/api/fetchAll/{jar_type}/{server_type}"
|
||||||
response = self._get_api_result(url)
|
response = self._get_api_result(url)
|
||||||
temp = []
|
temp = []
|
||||||
for v in response:
|
for v in response:
|
||||||
@ -127,19 +156,19 @@ class ServerJars:
|
|||||||
response = self._get_api_result(url)
|
response = self._get_api_result(url)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def download_jar(self, server, version, path, server_id):
|
def download_jar(self, jar, server, version, path, server_id):
|
||||||
update_thread = threading.Thread(
|
update_thread = threading.Thread(
|
||||||
name=f"server_download-{server_id}-{server}-{version}",
|
name=f"server_download-{server_id}-{server}-{version}",
|
||||||
target=self.a_download_jar,
|
target=self.a_download_jar,
|
||||||
daemon=True,
|
daemon=True,
|
||||||
args=(server, version, path, server_id),
|
args=(jar, server, version, path, server_id),
|
||||||
)
|
)
|
||||||
update_thread.start()
|
update_thread.start()
|
||||||
|
|
||||||
def a_download_jar(self, server, version, path, server_id):
|
def a_download_jar(self, jar, server, version, path, server_id):
|
||||||
# delaying download for server register to finish
|
# delaying download for server register to finish
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
fetch_url = f"{self.base_url}/api/fetchJar/{server}/{version}"
|
fetch_url = f"{self.base_url}/api/fetchJar/{jar}/{server}/{version}"
|
||||||
server_users = PermissionsServers.get_server_user_list(server_id)
|
server_users = PermissionsServers.get_server_user_list(server_id)
|
||||||
|
|
||||||
# We need to make sure the server is registered before
|
# We need to make sure the server is registered before
|
||||||
|
@ -110,11 +110,12 @@ class Schedules(BaseModel):
|
|||||||
interval_type = CharField()
|
interval_type = CharField()
|
||||||
start_time = CharField(null=True)
|
start_time = CharField(null=True)
|
||||||
command = CharField(null=True)
|
command = CharField(null=True)
|
||||||
comment = CharField()
|
name = CharField()
|
||||||
one_time = BooleanField(default=False)
|
one_time = BooleanField(default=False)
|
||||||
cron_string = CharField(default="")
|
cron_string = CharField(default="")
|
||||||
parent = IntegerField(null=True)
|
parent = IntegerField(null=True)
|
||||||
delay = IntegerField(default=0)
|
delay = IntegerField(default=0)
|
||||||
|
next_run = CharField(default="")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
table_name = "schedules"
|
table_name = "schedules"
|
||||||
@ -264,7 +265,7 @@ class HelpersManagement:
|
|||||||
interval_type,
|
interval_type,
|
||||||
start_time,
|
start_time,
|
||||||
command,
|
command,
|
||||||
comment=None,
|
name,
|
||||||
enabled=True,
|
enabled=True,
|
||||||
one_time=False,
|
one_time=False,
|
||||||
cron_string="* * * * *",
|
cron_string="* * * * *",
|
||||||
@ -280,11 +281,12 @@ class HelpersManagement:
|
|||||||
Schedules.interval_type: interval_type,
|
Schedules.interval_type: interval_type,
|
||||||
Schedules.start_time: start_time,
|
Schedules.start_time: start_time,
|
||||||
Schedules.command: command,
|
Schedules.command: command,
|
||||||
Schedules.comment: comment,
|
Schedules.name: name,
|
||||||
Schedules.one_time: one_time,
|
Schedules.one_time: one_time,
|
||||||
Schedules.cron_string: cron_string,
|
Schedules.cron_string: cron_string,
|
||||||
Schedules.parent: parent,
|
Schedules.parent: parent,
|
||||||
Schedules.delay: delay,
|
Schedules.delay: delay,
|
||||||
|
Schedules.next_run: "",
|
||||||
}
|
}
|
||||||
).execute()
|
).execute()
|
||||||
return sch_id
|
return sch_id
|
||||||
|
@ -20,6 +20,7 @@ import itertools
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from socket import gethostname
|
from socket import gethostname
|
||||||
from contextlib import redirect_stderr, suppress
|
from contextlib import redirect_stderr, suppress
|
||||||
|
from packaging import version as pkg_version
|
||||||
|
|
||||||
from app.classes.shared.null_writer import NullWriter
|
from app.classes.shared.null_writer import NullWriter
|
||||||
from app.classes.shared.console import Console
|
from app.classes.shared.console import Console
|
||||||
@ -75,6 +76,7 @@ class Helpers:
|
|||||||
|
|
||||||
self.websocket_helper = WebSocketHelper(self)
|
self.websocket_helper = WebSocketHelper(self)
|
||||||
self.translation = Translation(self)
|
self.translation = Translation(self)
|
||||||
|
self.update_available = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def auto_installer_fix(ex):
|
def auto_installer_fix(ex):
|
||||||
@ -82,6 +84,29 @@ class Helpers:
|
|||||||
print(f"Import Error: Unable to load {ex.name} module")
|
print(f"Import Error: Unable to load {ex.name} module")
|
||||||
installer.do_install()
|
installer.do_install()
|
||||||
|
|
||||||
|
def check_remote_version(self):
|
||||||
|
"""
|
||||||
|
Check if the remote version is newer than the local version
|
||||||
|
Returning remote version if it is newer, otherwise False.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Get tags from Gitlab, select the latest and parse the semver
|
||||||
|
response = get(
|
||||||
|
"https://gitlab.com/api/v4/projects/20430749/repository/tags"
|
||||||
|
)
|
||||||
|
if response.status_code == 200:
|
||||||
|
remote_version = pkg_version.parse(json.loads(response.text)[0]["name"])
|
||||||
|
|
||||||
|
# Get local version data from the file and parse the semver
|
||||||
|
local_version = pkg_version.parse(self.get_version_string())
|
||||||
|
|
||||||
|
if remote_version > local_version:
|
||||||
|
return remote_version
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Unable to check for new crafty version! \n{e}")
|
||||||
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def find_java_installs():
|
def find_java_installs():
|
||||||
# If we're windows return oracle java versions,
|
# If we're windows return oracle java versions,
|
||||||
|
@ -422,6 +422,7 @@ class Controller:
|
|||||||
|
|
||||||
def create_jar_server(
|
def create_jar_server(
|
||||||
self,
|
self,
|
||||||
|
jar: str,
|
||||||
server: str,
|
server: str,
|
||||||
version: str,
|
version: str,
|
||||||
name: str,
|
name: str,
|
||||||
@ -493,7 +494,7 @@ class Controller:
|
|||||||
|
|
||||||
# download the jar
|
# download the jar
|
||||||
self.server_jars.download_jar(
|
self.server_jars.download_jar(
|
||||||
server, version, os.path.join(server_dir, server_file), new_id
|
jar, server, version, os.path.join(server_dir, server_file), new_id
|
||||||
)
|
)
|
||||||
|
|
||||||
return new_id
|
return new_id
|
||||||
@ -933,6 +934,14 @@ class Controller:
|
|||||||
|
|
||||||
counter += 1
|
counter += 1
|
||||||
|
|
||||||
|
def remove_unloaded_server(self, server_id):
|
||||||
|
try:
|
||||||
|
HelpersManagement.delete_scheduled_task_by_server(server_id)
|
||||||
|
except DoesNotExist:
|
||||||
|
logger.info("No scheduled jobs exist. Continuing.")
|
||||||
|
# remove the server from the DB
|
||||||
|
self.servers.remove_server(server_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def clear_unexecuted_commands():
|
def clear_unexecuted_commands():
|
||||||
HelpersManagement.clear_unexecuted_commands()
|
HelpersManagement.clear_unexecuted_commands()
|
||||||
|
@ -3,7 +3,7 @@ import time
|
|||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from tzlocal import get_localzone
|
from tzlocal import get_localzone
|
||||||
from tzlocal.utils import ZoneInfoNotFoundError
|
from tzlocal.utils import ZoneInfoNotFoundError
|
||||||
@ -192,6 +192,15 @@ class TasksManager:
|
|||||||
def scheduler_thread(self):
|
def scheduler_thread(self):
|
||||||
schedules = HelpersManagement.get_schedules_enabled()
|
schedules = HelpersManagement.get_schedules_enabled()
|
||||||
self.scheduler.add_listener(self.schedule_watcher, mask=EVENT_JOB_EXECUTED)
|
self.scheduler.add_listener(self.schedule_watcher, mask=EVENT_JOB_EXECUTED)
|
||||||
|
self.scheduler.start()
|
||||||
|
self.check_for_updates()
|
||||||
|
self.scheduler.add_job(
|
||||||
|
self.check_for_updates,
|
||||||
|
"interval",
|
||||||
|
hours=12,
|
||||||
|
id="update_watcher",
|
||||||
|
start_date=datetime.now(),
|
||||||
|
)
|
||||||
# self.scheduler.add_job(
|
# self.scheduler.add_job(
|
||||||
# self.scheduler.print_jobs, "interval", seconds=10, id="-1"
|
# self.scheduler.print_jobs, "interval", seconds=10, id="-1"
|
||||||
# )
|
# )
|
||||||
@ -199,9 +208,10 @@ class TasksManager:
|
|||||||
# load schedules from DB
|
# load schedules from DB
|
||||||
for schedule in schedules:
|
for schedule in schedules:
|
||||||
if schedule.interval != "reaction":
|
if schedule.interval != "reaction":
|
||||||
|
new_job = "error"
|
||||||
if schedule.cron_string != "":
|
if schedule.cron_string != "":
|
||||||
try:
|
try:
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
CronTrigger.from_crontab(
|
CronTrigger.from_crontab(
|
||||||
schedule.cron_string, timezone=str(self.tz)
|
schedule.cron_string, timezone=str(self.tz)
|
||||||
@ -215,6 +225,7 @@ class TasksManager:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
new_job = "error"
|
||||||
Console.error(f"Failed to schedule task with error: {e}.")
|
Console.error(f"Failed to schedule task with error: {e}.")
|
||||||
Console.warning("Removing failed task from DB.")
|
Console.warning("Removing failed task from DB.")
|
||||||
logger.error(f"Failed to schedule task with error: {e}.")
|
logger.error(f"Failed to schedule task with error: {e}.")
|
||||||
@ -225,7 +236,7 @@ class TasksManager:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if schedule.interval_type == "hours":
|
if schedule.interval_type == "hours":
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
minute=0,
|
minute=0,
|
||||||
@ -239,7 +250,7 @@ class TasksManager:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
elif schedule.interval_type == "minutes":
|
elif schedule.interval_type == "minutes":
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
minute="*/" + str(schedule.interval),
|
minute="*/" + str(schedule.interval),
|
||||||
@ -253,7 +264,7 @@ class TasksManager:
|
|||||||
)
|
)
|
||||||
elif schedule.interval_type == "days":
|
elif schedule.interval_type == "days":
|
||||||
curr_time = schedule.start_time.split(":")
|
curr_time = schedule.start_time.split(":")
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
day="*/" + str(schedule.interval),
|
day="*/" + str(schedule.interval),
|
||||||
@ -267,7 +278,18 @@ class TasksManager:
|
|||||||
schedule.command,
|
schedule.command,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
self.scheduler.start()
|
if new_job != "error":
|
||||||
|
task = self.controller.management.get_scheduled_task_model(
|
||||||
|
int(new_job.id)
|
||||||
|
)
|
||||||
|
self.controller.management.update_scheduled_task(
|
||||||
|
task.schedule_id,
|
||||||
|
{
|
||||||
|
"next_run": str(
|
||||||
|
new_job.next_run_time.strftime("%m/%d/%Y, %H:%M:%S")
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
jobs = self.scheduler.get_jobs()
|
jobs = self.scheduler.get_jobs()
|
||||||
logger.info("Loaded schedules. Current enabled schedules: ")
|
logger.info("Loaded schedules. Current enabled schedules: ")
|
||||||
for item in jobs:
|
for item in jobs:
|
||||||
@ -281,7 +303,7 @@ class TasksManager:
|
|||||||
job_data["interval_type"],
|
job_data["interval_type"],
|
||||||
job_data["start_time"],
|
job_data["start_time"],
|
||||||
job_data["command"],
|
job_data["command"],
|
||||||
"None",
|
job_data["name"],
|
||||||
job_data["enabled"],
|
job_data["enabled"],
|
||||||
job_data["one_time"],
|
job_data["one_time"],
|
||||||
job_data["cron_string"],
|
job_data["cron_string"],
|
||||||
@ -296,9 +318,10 @@ class TasksManager:
|
|||||||
|
|
||||||
# Check to see if it's enabled and is not a chain reaction.
|
# Check to see if it's enabled and is not a chain reaction.
|
||||||
if job_data["enabled"] and job_data["interval_type"] != "reaction":
|
if job_data["enabled"] and job_data["interval_type"] != "reaction":
|
||||||
|
new_job = "error"
|
||||||
if job_data["cron_string"] != "":
|
if job_data["cron_string"] != "":
|
||||||
try:
|
try:
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
CronTrigger.from_crontab(
|
CronTrigger.from_crontab(
|
||||||
job_data["cron_string"], timezone=str(self.tz)
|
job_data["cron_string"], timezone=str(self.tz)
|
||||||
@ -312,6 +335,7 @@ class TasksManager:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
new_job = "error"
|
||||||
Console.error(f"Failed to schedule task with error: {e}.")
|
Console.error(f"Failed to schedule task with error: {e}.")
|
||||||
Console.warning("Removing failed task from DB.")
|
Console.warning("Removing failed task from DB.")
|
||||||
logger.error(f"Failed to schedule task with error: {e}.")
|
logger.error(f"Failed to schedule task with error: {e}.")
|
||||||
@ -320,7 +344,7 @@ class TasksManager:
|
|||||||
self.controller.management_helper.delete_scheduled_task(sch_id)
|
self.controller.management_helper.delete_scheduled_task(sch_id)
|
||||||
else:
|
else:
|
||||||
if job_data["interval_type"] == "hours":
|
if job_data["interval_type"] == "hours":
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
minute=0,
|
minute=0,
|
||||||
@ -334,7 +358,7 @@ class TasksManager:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
elif job_data["interval_type"] == "minutes":
|
elif job_data["interval_type"] == "minutes":
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
minute="*/" + str(job_data["interval"]),
|
minute="*/" + str(job_data["interval"]),
|
||||||
@ -348,7 +372,7 @@ class TasksManager:
|
|||||||
)
|
)
|
||||||
elif job_data["interval_type"] == "days":
|
elif job_data["interval_type"] == "days":
|
||||||
curr_time = job_data["start_time"].split(":")
|
curr_time = job_data["start_time"].split(":")
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
day="*/" + str(job_data["interval"]),
|
day="*/" + str(job_data["interval"]),
|
||||||
@ -364,6 +388,14 @@ class TasksManager:
|
|||||||
)
|
)
|
||||||
logger.info("Added job. Current enabled schedules: ")
|
logger.info("Added job. Current enabled schedules: ")
|
||||||
jobs = self.scheduler.get_jobs()
|
jobs = self.scheduler.get_jobs()
|
||||||
|
if new_job != "error":
|
||||||
|
task = self.controller.management.get_scheduled_task_model(
|
||||||
|
int(new_job.id)
|
||||||
|
)
|
||||||
|
self.controller.management.update_scheduled_task(
|
||||||
|
task.schedule_id,
|
||||||
|
{"next_run": new_job.next_run_time.strftime("%m/%d/%Y, %H:%M:%S")},
|
||||||
|
)
|
||||||
for item in jobs:
|
for item in jobs:
|
||||||
logger.info(f"JOB: {item}")
|
logger.info(f"JOB: {item}")
|
||||||
|
|
||||||
@ -416,9 +448,10 @@ class TasksManager:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if job_data["enabled"] and job_data["interval"] != "reaction":
|
if job_data["enabled"] and job_data["interval"] != "reaction":
|
||||||
|
new_job = "error"
|
||||||
if job_data["cron_string"] != "":
|
if job_data["cron_string"] != "":
|
||||||
try:
|
try:
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
CronTrigger.from_crontab(
|
CronTrigger.from_crontab(
|
||||||
job_data["cron_string"], timezone=str(self.tz)
|
job_data["cron_string"], timezone=str(self.tz)
|
||||||
@ -432,12 +465,13 @@ class TasksManager:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
new_job = "error"
|
||||||
Console.error(f"Failed to schedule task with error: {e}.")
|
Console.error(f"Failed to schedule task with error: {e}.")
|
||||||
Console.info("Removing failed task from DB.")
|
Console.info("Removing failed task from DB.")
|
||||||
self.controller.management_helper.delete_scheduled_task(sch_id)
|
self.controller.management_helper.delete_scheduled_task(sch_id)
|
||||||
else:
|
else:
|
||||||
if job_data["interval_type"] == "hours":
|
if job_data["interval_type"] == "hours":
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
minute=0,
|
minute=0,
|
||||||
@ -451,7 +485,7 @@ class TasksManager:
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
elif job_data["interval_type"] == "minutes":
|
elif job_data["interval_type"] == "minutes":
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
minute="*/" + str(job_data["interval"]),
|
minute="*/" + str(job_data["interval"]),
|
||||||
@ -465,7 +499,7 @@ class TasksManager:
|
|||||||
)
|
)
|
||||||
elif job_data["interval_type"] == "days":
|
elif job_data["interval_type"] == "days":
|
||||||
curr_time = job_data["start_time"].split(":")
|
curr_time = job_data["start_time"].split(":")
|
||||||
self.scheduler.add_job(
|
new_job = self.scheduler.add_job(
|
||||||
HelpersManagement.add_command,
|
HelpersManagement.add_command,
|
||||||
"cron",
|
"cron",
|
||||||
day="*/" + str(job_data["interval"]),
|
day="*/" + str(job_data["interval"]),
|
||||||
@ -479,6 +513,14 @@ class TasksManager:
|
|||||||
job_data["command"],
|
job_data["command"],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
if new_job != "error":
|
||||||
|
task = self.controller.management.get_scheduled_task_model(
|
||||||
|
int(new_job.id)
|
||||||
|
)
|
||||||
|
self.controller.management.update_scheduled_task(
|
||||||
|
task.schedule_id,
|
||||||
|
{"next_run": new_job.next_run_time.strftime("%m/%d/%Y, %H:%M:%S")},
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self.scheduler.get_job(str(sch_id))
|
self.scheduler.get_job(str(sch_id))
|
||||||
@ -506,6 +548,15 @@ class TasksManager:
|
|||||||
if task.one_time:
|
if task.one_time:
|
||||||
self.remove_job(task.schedule_id)
|
self.remove_job(task.schedule_id)
|
||||||
logger.info("one time task detected. Deleting...")
|
logger.info("one time task detected. Deleting...")
|
||||||
|
else:
|
||||||
|
self.controller.management.update_scheduled_task(
|
||||||
|
task.schedule_id,
|
||||||
|
{
|
||||||
|
"next_run": self.scheduler.get_job(
|
||||||
|
event.job_id
|
||||||
|
).next_run_time.strftime("%m/%d/%Y, %H:%M:%S")
|
||||||
|
},
|
||||||
|
)
|
||||||
# check for any child tasks for this. It's kind of backward,
|
# check for any child tasks for this. It's kind of backward,
|
||||||
# but this makes DB management a lot easier. One to one
|
# but this makes DB management a lot easier. One to one
|
||||||
# instead of one to many.
|
# instead of one to many.
|
||||||
@ -606,6 +657,16 @@ class TasksManager:
|
|||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
def check_for_updates(self):
|
||||||
|
logger.info("Checking for Crafty updates...")
|
||||||
|
self.helper.update_available = self.helper.check_remote_version()
|
||||||
|
if self.helper.update_available:
|
||||||
|
logger.info(f"Found new version {self.helper.update_available}")
|
||||||
|
else:
|
||||||
|
logger.info(
|
||||||
|
"No updates found! You are on the most up to date Crafty version."
|
||||||
|
)
|
||||||
|
|
||||||
def log_watcher(self):
|
def log_watcher(self):
|
||||||
self.controller.servers.check_for_old_logs()
|
self.controller.servers.check_for_old_logs()
|
||||||
self.scheduler.add_job(
|
self.scheduler.add_job(
|
||||||
|
@ -454,6 +454,14 @@ class AjaxHandler(BaseHandler):
|
|||||||
self.helper.backup_select(path, exec_user["user_id"])
|
self.helper.backup_select(path, exec_user["user_id"])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
elif page == "jar_cache":
|
||||||
|
if not superuser:
|
||||||
|
self.redirect("/panel/error?error=Not a super user")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.controller.server_jars.manual_refresh_cache()
|
||||||
|
return
|
||||||
|
|
||||||
@tornado.web.authenticated
|
@tornado.web.authenticated
|
||||||
def delete(self, page):
|
def delete(self, page):
|
||||||
api_key, _, exec_user = self.current_user
|
api_key, _, exec_user = self.current_user
|
||||||
@ -565,9 +573,39 @@ class AjaxHandler(BaseHandler):
|
|||||||
self.get_remote_ip(),
|
self.get_remote_ip(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for server in self.controller.servers.failed_servers:
|
||||||
|
if server["server_id"] == int(server_id):
|
||||||
|
return
|
||||||
self.tasks_manager.remove_all_server_tasks(server_id)
|
self.tasks_manager.remove_all_server_tasks(server_id)
|
||||||
self.controller.remove_server(server_id, True)
|
self.controller.remove_server(server_id, True)
|
||||||
|
|
||||||
|
elif page == "delete_unloaded_server":
|
||||||
|
if not permissions["Config"] in user_perms:
|
||||||
|
if not superuser:
|
||||||
|
self.redirect("/panel/error?error=Unauthorized access to Config")
|
||||||
|
return
|
||||||
|
server_id = self.get_argument("id", None)
|
||||||
|
logger.info(
|
||||||
|
f"Removing server and all associated files for server: "
|
||||||
|
f"{self.controller.servers.get_server_friendly_name(server_id)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
server_data = self.controller.servers.get_server_data_by_id(server_id)
|
||||||
|
server_name = server_data["server_name"]
|
||||||
|
|
||||||
|
self.controller.management.add_to_audit_log(
|
||||||
|
exec_user["user_id"],
|
||||||
|
f"Deleted server {server_id} named {server_name}",
|
||||||
|
server_id,
|
||||||
|
self.get_remote_ip(),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.tasks_manager.remove_all_server_tasks(server_id)
|
||||||
|
for item in self.controller.servers.failed_servers[:]:
|
||||||
|
if item["server_id"] == int(server_id):
|
||||||
|
self.controller.servers.failed_servers.remove(item)
|
||||||
|
self.controller.remove_unloaded_server(server_id)
|
||||||
|
|
||||||
def check_server_id(self, server_id, page_name):
|
def check_server_id(self, server_id, page_name):
|
||||||
if server_id is None:
|
if server_id is None:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
@ -157,6 +157,10 @@ class PanelHandler(BaseHandler):
|
|||||||
if server_id is None:
|
if server_id is None:
|
||||||
self.redirect("/panel/error?error=Invalid Server ID")
|
self.redirect("/panel/error?error=Invalid Server ID")
|
||||||
return None
|
return None
|
||||||
|
for server in self.controller.servers.failed_servers:
|
||||||
|
if int(server_id) == server["server_id"]:
|
||||||
|
self.failed_server = True
|
||||||
|
return server_id
|
||||||
# Does this server exist?
|
# Does this server exist?
|
||||||
if not self.controller.servers.server_id_exists(server_id):
|
if not self.controller.servers.server_id_exists(server_id):
|
||||||
self.redirect("/panel/error?error=Invalid Server ID")
|
self.redirect("/panel/error?error=Invalid Server ID")
|
||||||
@ -207,6 +211,7 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
@tornado.web.authenticated
|
@tornado.web.authenticated
|
||||||
async def get(self, page):
|
async def get(self, page):
|
||||||
|
self.failed_server = False
|
||||||
error = self.get_argument("error", "WTF Error!")
|
error = self.get_argument("error", "WTF Error!")
|
||||||
|
|
||||||
template = "panel/denied.html"
|
template = "panel/denied.html"
|
||||||
@ -284,9 +289,10 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
page_data: t.Dict[str, t.Any] = {
|
page_data: t.Dict[str, t.Any] = {
|
||||||
# todo: make this actually pull and compare version data
|
# todo: make this actually pull and compare version data
|
||||||
"update_available": False,
|
"update_available": self.helper.update_available,
|
||||||
"serverTZ": tz,
|
"serverTZ": tz,
|
||||||
"version_data": self.helper.get_version_string(),
|
"version_data": self.helper.get_version_string(),
|
||||||
|
"failed_servers": self.controller.servers.failed_servers,
|
||||||
"user_data": exec_user,
|
"user_data": exec_user,
|
||||||
"user_role": exec_user_role,
|
"user_role": exec_user_role,
|
||||||
"user_crafty_permissions": exec_user_crafty_permissions,
|
"user_crafty_permissions": exec_user_crafty_permissions,
|
||||||
@ -368,7 +374,7 @@ class PanelHandler(BaseHandler):
|
|||||||
) as credits_default_local:
|
) as credits_default_local:
|
||||||
try:
|
try:
|
||||||
remote = requests.get(
|
remote = requests.get(
|
||||||
"https://craftycontrol.com/credits", allow_redirects=True
|
"https://craftycontrol.com/credits-v2", allow_redirects=True
|
||||||
)
|
)
|
||||||
credits_dict: dict = remote.json()
|
credits_dict: dict = remote.json()
|
||||||
if not credits_dict["staff"]:
|
if not credits_dict["staff"]:
|
||||||
@ -503,8 +509,10 @@ class PanelHandler(BaseHandler):
|
|||||||
server_id = self.check_server_id()
|
server_id = self.check_server_id()
|
||||||
if server_id is None:
|
if server_id is None:
|
||||||
return
|
return
|
||||||
|
if not self.failed_server:
|
||||||
server_obj = self.controller.servers.get_server_instance_by_id(server_id)
|
server_obj = self.controller.servers.get_server_instance_by_id(
|
||||||
|
server_id
|
||||||
|
)
|
||||||
page_data["backup_failed"] = server_obj.last_backup_status()
|
page_data["backup_failed"] = server_obj.last_backup_status()
|
||||||
server_obj = None
|
server_obj = None
|
||||||
|
|
||||||
@ -517,18 +525,57 @@ class PanelHandler(BaseHandler):
|
|||||||
"admin_controls",
|
"admin_controls",
|
||||||
"schedules",
|
"schedules",
|
||||||
]
|
]
|
||||||
|
if not self.failed_server:
|
||||||
server = self.controller.servers.get_server_instance_by_id(server_id)
|
server = self.controller.servers.get_server_instance_by_id(server_id)
|
||||||
# server_data isn't needed since the server_stats also pulls server data
|
# server_data isn't needed since the server_stats also pulls server data
|
||||||
page_data["server_data"] = self.controller.servers.get_server_data_by_id(
|
page_data["server_data"] = self.controller.servers.get_server_data_by_id(
|
||||||
server_id
|
server_id
|
||||||
)
|
)
|
||||||
page_data["server_stats"] = self.controller.servers.get_server_stats_by_id(
|
if not self.failed_server:
|
||||||
|
page_data[
|
||||||
|
"server_stats"
|
||||||
|
] = self.controller.servers.get_server_stats_by_id(server_id)
|
||||||
|
else:
|
||||||
|
server_temp_obj = self.controller.servers.get_server_data_by_id(
|
||||||
server_id
|
server_id
|
||||||
)
|
)
|
||||||
|
page_data["server_stats"] = {
|
||||||
|
"server_id": {
|
||||||
|
"server_id": server_id,
|
||||||
|
"server_name": server_temp_obj["server_name"],
|
||||||
|
"server_uuid": server_temp_obj["server_uuid"],
|
||||||
|
"path": server_temp_obj["path"],
|
||||||
|
"log_path": server_temp_obj["log_path"],
|
||||||
|
"executable": server_temp_obj["executable"],
|
||||||
|
"execution_command": server_temp_obj["execution_command"],
|
||||||
|
"stop_command": server_temp_obj["stop_command"],
|
||||||
|
"executable_update_url": server_temp_obj[
|
||||||
|
"executable_update_url"
|
||||||
|
],
|
||||||
|
"auto_start_delay": server_temp_obj["auto_start_delay"],
|
||||||
|
"server_ip": server_temp_obj["server_ip"],
|
||||||
|
"server_port": server_temp_obj["server_port"],
|
||||||
|
"logs_delete_after": server_temp_obj["logs_delete_after"],
|
||||||
|
"auto_start": server_temp_obj["auto_start"],
|
||||||
|
"crash_detection": server_temp_obj["crash_detection"],
|
||||||
|
"show_status": server_temp_obj["show_status"],
|
||||||
|
},
|
||||||
|
"running": False,
|
||||||
|
"crashed": False,
|
||||||
|
"server_type": "N/A",
|
||||||
|
"cpu": "N/A",
|
||||||
|
"mem": "N/A",
|
||||||
|
"int_ping_results": [],
|
||||||
|
"version": "N/A",
|
||||||
|
"desc": "N/A",
|
||||||
|
"started": "False",
|
||||||
|
}
|
||||||
|
if not self.failed_server:
|
||||||
page_data["downloading"] = self.controller.servers.get_download_status(
|
page_data["downloading"] = self.controller.servers.get_download_status(
|
||||||
server_id
|
server_id
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
page_data["downloading"] = False
|
||||||
page_data["server_id"] = server_id
|
page_data["server_id"] = server_id
|
||||||
try:
|
try:
|
||||||
page_data["waiting_start"] = self.controller.servers.get_waiting_start(
|
page_data["waiting_start"] = self.controller.servers.get_waiting_start(
|
||||||
@ -537,7 +584,10 @@ class PanelHandler(BaseHandler):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to get server waiting to start: {e}")
|
logger.error(f"Failed to get server waiting to start: {e}")
|
||||||
page_data["waiting_start"] = False
|
page_data["waiting_start"] = False
|
||||||
|
if not self.failed_server:
|
||||||
page_data["get_players"] = server.get_server_players()
|
page_data["get_players"] = server.get_server_players()
|
||||||
|
else:
|
||||||
|
page_data["get_players"] = []
|
||||||
page_data["active_link"] = subpage
|
page_data["active_link"] = subpage
|
||||||
page_data["permissions"] = {
|
page_data["permissions"] = {
|
||||||
"Commands": EnumPermissionsServer.COMMANDS,
|
"Commands": EnumPermissionsServer.COMMANDS,
|
||||||
@ -554,9 +604,11 @@ class PanelHandler(BaseHandler):
|
|||||||
] = self.controller.server_perms.get_user_id_permissions_list(
|
] = self.controller.server_perms.get_user_id_permissions_list(
|
||||||
exec_user["user_id"], server_id
|
exec_user["user_id"], server_id
|
||||||
)
|
)
|
||||||
page_data["server_stats"]["crashed"] = self.controller.servers.is_crashed(
|
if not self.failed_server:
|
||||||
server_id
|
page_data["server_stats"][
|
||||||
)
|
"crashed"
|
||||||
|
] = self.controller.servers.is_crashed(server_id)
|
||||||
|
if not self.failed_server:
|
||||||
page_data["server_stats"][
|
page_data["server_stats"][
|
||||||
"server_type"
|
"server_type"
|
||||||
] = self.controller.servers.get_server_type_by_id(server_id)
|
] = self.controller.servers.get_server_type_by_id(server_id)
|
||||||
@ -639,6 +691,7 @@ class PanelHandler(BaseHandler):
|
|||||||
return
|
return
|
||||||
page_data["java_versions"] = Helpers.find_java_installs()
|
page_data["java_versions"] = Helpers.find_java_installs()
|
||||||
server_obj: Servers = self.controller.servers.get_server_obj(server_id)
|
server_obj: Servers = self.controller.servers.get_server_obj(server_id)
|
||||||
|
page_data["failed"] = self.failed_server
|
||||||
page_java = []
|
page_java = []
|
||||||
page_data["java_versions"].append("java")
|
page_data["java_versions"].append("java")
|
||||||
for version in page_data["java_versions"]:
|
for version in page_data["java_versions"]:
|
||||||
@ -901,6 +954,7 @@ class PanelHandler(BaseHandler):
|
|||||||
page_data["new_schedule"] = True
|
page_data["new_schedule"] = True
|
||||||
page_data["schedule"] = {}
|
page_data["schedule"] = {}
|
||||||
page_data["schedule"]["children"] = []
|
page_data["schedule"]["children"] = []
|
||||||
|
page_data["schedule"]["name"] = ""
|
||||||
page_data["schedule"]["server_id"] = server_id
|
page_data["schedule"]["server_id"] = server_id
|
||||||
page_data["schedule"]["schedule_id"] = ""
|
page_data["schedule"]["schedule_id"] = ""
|
||||||
page_data["schedule"]["action"] = ""
|
page_data["schedule"]["action"] = ""
|
||||||
@ -968,6 +1022,10 @@ class PanelHandler(BaseHandler):
|
|||||||
page_data["schedule"]["server_id"] = server_id
|
page_data["schedule"]["server_id"] = server_id
|
||||||
page_data["schedule"]["schedule_id"] = schedule.schedule_id
|
page_data["schedule"]["schedule_id"] = schedule.schedule_id
|
||||||
page_data["schedule"]["action"] = schedule.action
|
page_data["schedule"]["action"] = schedule.action
|
||||||
|
if schedule.name:
|
||||||
|
page_data["schedule"]["name"] = schedule.name
|
||||||
|
else:
|
||||||
|
page_data["schedule"]["name"] = ""
|
||||||
page_data["schedule"][
|
page_data["schedule"][
|
||||||
"children"
|
"children"
|
||||||
] = self.controller.management.get_child_schedules(sch_id)
|
] = self.controller.management.get_child_schedules(sch_id)
|
||||||
@ -1466,7 +1524,15 @@ class PanelHandler(BaseHandler):
|
|||||||
server_obj.auto_start = auto_start
|
server_obj.auto_start = auto_start
|
||||||
server_obj.crash_detection = crash_detection
|
server_obj.crash_detection = crash_detection
|
||||||
server_obj.logs_delete_after = logs_delete_after
|
server_obj.logs_delete_after = logs_delete_after
|
||||||
|
failed = False
|
||||||
|
for servers in self.controller.servers.failed_servers:
|
||||||
|
if servers["server_id"] == int(server_id):
|
||||||
|
failed = True
|
||||||
|
if not failed:
|
||||||
self.controller.servers.update_server(server_obj)
|
self.controller.servers.update_server(server_obj)
|
||||||
|
else:
|
||||||
|
self.controller.servers.update_unloaded_server(server_obj)
|
||||||
|
self.controller.servers.init_all_servers()
|
||||||
self.controller.servers.crash_detection(server_obj)
|
self.controller.servers.crash_detection(server_obj)
|
||||||
|
|
||||||
self.controller.servers.refresh_server_settings(server_id)
|
self.controller.servers.refresh_server_settings(server_id)
|
||||||
@ -1557,6 +1623,7 @@ class PanelHandler(BaseHandler):
|
|||||||
difficulty = bleach.clean(self.get_argument("difficulty", None))
|
difficulty = bleach.clean(self.get_argument("difficulty", None))
|
||||||
server_obj = self.controller.servers.get_server_obj(server_id)
|
server_obj = self.controller.servers.get_server_obj(server_id)
|
||||||
enabled = bleach.clean(self.get_argument("enabled", "0"))
|
enabled = bleach.clean(self.get_argument("enabled", "0"))
|
||||||
|
name = bleach.clean(self.get_argument("name", ""))
|
||||||
if difficulty == "basic":
|
if difficulty == "basic":
|
||||||
action = bleach.clean(self.get_argument("action", None))
|
action = bleach.clean(self.get_argument("action", None))
|
||||||
interval = bleach.clean(self.get_argument("interval", None))
|
interval = bleach.clean(self.get_argument("interval", None))
|
||||||
@ -1621,6 +1688,7 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
if interval_type == "days":
|
if interval_type == "days":
|
||||||
job_data = {
|
job_data = {
|
||||||
|
"name": name,
|
||||||
"server_id": server_id,
|
"server_id": server_id,
|
||||||
"action": action,
|
"action": action,
|
||||||
"interval_type": interval_type,
|
"interval_type": interval_type,
|
||||||
@ -1635,6 +1703,7 @@ class PanelHandler(BaseHandler):
|
|||||||
}
|
}
|
||||||
elif difficulty == "reaction":
|
elif difficulty == "reaction":
|
||||||
job_data = {
|
job_data = {
|
||||||
|
"name": name,
|
||||||
"server_id": server_id,
|
"server_id": server_id,
|
||||||
"action": action,
|
"action": action,
|
||||||
"interval_type": interval_type,
|
"interval_type": interval_type,
|
||||||
@ -1650,6 +1719,7 @@ class PanelHandler(BaseHandler):
|
|||||||
}
|
}
|
||||||
elif difficulty == "advanced":
|
elif difficulty == "advanced":
|
||||||
job_data = {
|
job_data = {
|
||||||
|
"name": name,
|
||||||
"server_id": server_id,
|
"server_id": server_id,
|
||||||
"action": action,
|
"action": action,
|
||||||
"interval_type": "",
|
"interval_type": "",
|
||||||
@ -1665,6 +1735,7 @@ class PanelHandler(BaseHandler):
|
|||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
job_data = {
|
job_data = {
|
||||||
|
"name": name,
|
||||||
"server_id": server_id,
|
"server_id": server_id,
|
||||||
"action": action,
|
"action": action,
|
||||||
"interval_type": interval_type,
|
"interval_type": interval_type,
|
||||||
@ -1714,6 +1785,7 @@ class PanelHandler(BaseHandler):
|
|||||||
difficulty = bleach.clean(self.get_argument("difficulty", None))
|
difficulty = bleach.clean(self.get_argument("difficulty", None))
|
||||||
server_obj = self.controller.servers.get_server_obj(server_id)
|
server_obj = self.controller.servers.get_server_obj(server_id)
|
||||||
enabled = bleach.clean(self.get_argument("enabled", "0"))
|
enabled = bleach.clean(self.get_argument("enabled", "0"))
|
||||||
|
name = bleach.clean(self.get_argument("name", ""))
|
||||||
if difficulty == "basic":
|
if difficulty == "basic":
|
||||||
action = bleach.clean(self.get_argument("action", None))
|
action = bleach.clean(self.get_argument("action", None))
|
||||||
interval = bleach.clean(self.get_argument("interval", None))
|
interval = bleach.clean(self.get_argument("interval", None))
|
||||||
@ -1777,6 +1849,7 @@ class PanelHandler(BaseHandler):
|
|||||||
|
|
||||||
if interval_type == "days":
|
if interval_type == "days":
|
||||||
job_data = {
|
job_data = {
|
||||||
|
"name": name,
|
||||||
"server_id": server_id,
|
"server_id": server_id,
|
||||||
"action": action,
|
"action": action,
|
||||||
"interval_type": interval_type,
|
"interval_type": interval_type,
|
||||||
@ -1791,6 +1864,7 @@ class PanelHandler(BaseHandler):
|
|||||||
}
|
}
|
||||||
elif difficulty == "advanced":
|
elif difficulty == "advanced":
|
||||||
job_data = {
|
job_data = {
|
||||||
|
"name": name,
|
||||||
"server_id": server_id,
|
"server_id": server_id,
|
||||||
"action": action,
|
"action": action,
|
||||||
"interval_type": "",
|
"interval_type": "",
|
||||||
@ -1806,6 +1880,7 @@ class PanelHandler(BaseHandler):
|
|||||||
}
|
}
|
||||||
elif difficulty == "reaction":
|
elif difficulty == "reaction":
|
||||||
job_data = {
|
job_data = {
|
||||||
|
"name": name,
|
||||||
"server_id": server_id,
|
"server_id": server_id,
|
||||||
"action": action,
|
"action": action,
|
||||||
"interval_type": interval_type,
|
"interval_type": interval_type,
|
||||||
@ -1821,6 +1896,7 @@ class PanelHandler(BaseHandler):
|
|||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
job_data = {
|
job_data = {
|
||||||
|
"name": name,
|
||||||
"server_id": server_id,
|
"server_id": server_id,
|
||||||
"action": action,
|
"action": action,
|
||||||
"interval_type": interval_type,
|
"interval_type": interval_type,
|
||||||
|
@ -92,10 +92,12 @@ class ServerHandler(BaseHandler):
|
|||||||
template = "public/404.html"
|
template = "public/404.html"
|
||||||
|
|
||||||
page_data = {
|
page_data = {
|
||||||
|
"update_available": self.helper.update_available,
|
||||||
"version_data": self.helper.get_version_string(),
|
"version_data": self.helper.get_version_string(),
|
||||||
"user_data": exec_user,
|
"user_data": exec_user,
|
||||||
"user_role": exec_user_role,
|
"user_role": exec_user_role,
|
||||||
"roles": list_roles,
|
"roles": list_roles,
|
||||||
|
"super_user": exec_user["superuser"],
|
||||||
"user_crafty_permissions": exec_user_crafty_permissions,
|
"user_crafty_permissions": exec_user_crafty_permissions,
|
||||||
"crafty_permissions": {
|
"crafty_permissions": {
|
||||||
"Server_Creation": EnumPermissionsCrafty.SERVER_CREATION,
|
"Server_Creation": EnumPermissionsCrafty.SERVER_CREATION,
|
||||||
@ -386,14 +388,20 @@ class ServerHandler(BaseHandler):
|
|||||||
# deletes temp dir
|
# deletes temp dir
|
||||||
FileHelpers.del_dirs(zip_path)
|
FileHelpers.del_dirs(zip_path)
|
||||||
else:
|
else:
|
||||||
if len(server_parts) != 2:
|
if len(server_parts) != 3:
|
||||||
self.redirect("/panel/error?error=Invalid server data")
|
self.redirect("/panel/error?error=Invalid server data")
|
||||||
return
|
return
|
||||||
server_type, server_version = server_parts
|
jar_type, server_type, server_version = server_parts
|
||||||
# TODO: add server type check here and call the correct server
|
# TODO: add server type check here and call the correct server
|
||||||
# add functions if not a jar
|
# add functions if not a jar
|
||||||
new_server_id = self.controller.create_jar_server(
|
new_server_id = self.controller.create_jar_server(
|
||||||
server_type, server_version, server_name, min_mem, max_mem, port
|
jar_type,
|
||||||
|
server_type,
|
||||||
|
server_version,
|
||||||
|
server_name,
|
||||||
|
min_mem,
|
||||||
|
max_mem,
|
||||||
|
port,
|
||||||
)
|
)
|
||||||
self.controller.management.add_to_audit_log(
|
self.controller.management.add_to_audit_log(
|
||||||
exec_user["user_id"],
|
exec_user["user_id"],
|
||||||
|
@ -5,7 +5,14 @@
|
|||||||
"name": "Pita Bread",
|
"name": "Pita Bread",
|
||||||
"title": "CEO",
|
"title": "CEO",
|
||||||
"loc": "Midwest, USA",
|
"loc": "Midwest, USA",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/craftbreadth" ], "Crafty Leadership" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/craftbreadth"
|
||||||
|
],
|
||||||
|
"Crafty Leadership"
|
||||||
|
],
|
||||||
"blurb": "Baked goods enthusiast who dabbles in Linux and sets up networks for fun. Can be found writing long-winded emails, debugging strange wifi issues, or taking care of his extensive houseplant collection.",
|
"blurb": "Baked goods enthusiast who dabbles in Linux and sets up networks for fun. Can be found writing long-winded emails, debugging strange wifi issues, or taking care of his extensive houseplant collection.",
|
||||||
"pic": "/static/assets/images/credits/pita.png"
|
"pic": "/static/assets/images/credits/pita.png"
|
||||||
},
|
},
|
||||||
@ -13,7 +20,14 @@
|
|||||||
"name": "Xithical",
|
"name": "Xithical",
|
||||||
"title": "CFO/COO",
|
"title": "CFO/COO",
|
||||||
"loc": "Midwest, USA",
|
"loc": "Midwest, USA",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/xithical" ], "Crafty Leadership" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/xithical"
|
||||||
|
],
|
||||||
|
"Crafty Leadership"
|
||||||
|
],
|
||||||
"blurb": "Having sold his soul to the IT administration gods many eons ago, you can usually find him working, going home to do work, or continuing to work in the support Discord.",
|
"blurb": "Having sold his soul to the IT administration gods many eons ago, you can usually find him working, going home to do work, or continuing to work in the support Discord.",
|
||||||
"pic": "/static/assets/images/credits/xithical.png"
|
"pic": "/static/assets/images/credits/xithical.png"
|
||||||
},
|
},
|
||||||
@ -21,7 +35,14 @@
|
|||||||
"name": "Phil Tarrant",
|
"name": "Phil Tarrant",
|
||||||
"title": "Creator",
|
"title": "Creator",
|
||||||
"loc": "Southeast, USA",
|
"loc": "Southeast, USA",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/Ptarrant1" ], "Crafty Advisor" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/Ptarrant1"
|
||||||
|
],
|
||||||
|
"Crafty Advisor"
|
||||||
|
],
|
||||||
"blurb": "For best results, apply a thin layer of Phillip to code, cyber security, and parenthood for maximum effectiveness. Phillip often spends too much time with his chickens.",
|
"blurb": "For best results, apply a thin layer of Phillip to code, cyber security, and parenthood for maximum effectiveness. Phillip often spends too much time with his chickens.",
|
||||||
"pic": "/static/assets/images/credits/ptarrant.png"
|
"pic": "/static/assets/images/credits/ptarrant.png"
|
||||||
},
|
},
|
||||||
@ -29,23 +50,59 @@
|
|||||||
"name": "macgeek",
|
"name": "macgeek",
|
||||||
"title": "Lead Software Engineer",
|
"title": "Lead Software Engineer",
|
||||||
"loc": "Midwest, USA",
|
"loc": "Midwest, USA",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/computergeek125" ], "Crafty Advisor" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/computergeek125"
|
||||||
|
],
|
||||||
|
"Crafty Advisor"
|
||||||
|
],
|
||||||
"blurb": "Sysadmin for work and sysadmin for fun (avid homelabber). He enjoys a good tech tangent and gaming.",
|
"blurb": "Sysadmin for work and sysadmin for fun (avid homelabber). He enjoys a good tech tangent and gaming.",
|
||||||
"pic": "/static/assets/images/credits/macgeek.png"
|
"pic": "/static/assets/images/credits/macgeek.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "parzivaldewey",
|
"name": "pretzeldewey 🥨",
|
||||||
"title": "Support Manager",
|
"title": "Support Manager & Software Engineer",
|
||||||
"loc": "East Coast, USA",
|
"loc": "East Coast, USA",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/amcmanu3" ], "Support Manager" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/amcmanu3"
|
||||||
|
],
|
||||||
|
"Crafty Advisor"
|
||||||
|
],
|
||||||
"blurb": "His interests include Linux, gaming, and helping others. When he's able to unplug he enjoys biking, hiking, and playing soccer.",
|
"blurb": "His interests include Linux, gaming, and helping others. When he's able to unplug he enjoys biking, hiking, and playing soccer.",
|
||||||
"pic": "/static/assets/images/credits/parzivaldewey.png"
|
"pic": "/static/assets/images/credits/parzivaldewey.png"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Zedifus",
|
||||||
|
"title": "DevOps Manager",
|
||||||
|
"loc": "Scotland, UK",
|
||||||
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/Zedifus"
|
||||||
|
],
|
||||||
|
"Crafty Advisor"
|
||||||
|
],
|
||||||
|
"blurb": "A Streamer, who is currently working in the insurance industry, self-teaching software development & DevOps, with the hopes of a career change! Enjoys playing games and has a sassy cat called Eve.",
|
||||||
|
"pic": "/static/assets/images/credits/zedifus.jpg"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Silversthorn",
|
"name": "Silversthorn",
|
||||||
"title": "Software Engineer",
|
"title": "Software Engineer",
|
||||||
"loc": "Provence, FR",
|
"loc": "Provence, FR",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/Silversthorn" ], null ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/Silversthorn"
|
||||||
|
],
|
||||||
|
null
|
||||||
|
],
|
||||||
"blurb": "Developer at work and at home, testing his own code is a pain, so his coding precept is \"Testing is Doubting\"",
|
"blurb": "Developer at work and at home, testing his own code is a pain, so his coding precept is \"Testing is Doubting\"",
|
||||||
"pic": "/static/assets/images/credits/silversthorn.png"
|
"pic": "/static/assets/images/credits/silversthorn.png"
|
||||||
},
|
},
|
||||||
@ -53,17 +110,16 @@
|
|||||||
"name": "ThatOneLukas",
|
"name": "ThatOneLukas",
|
||||||
"title": "Software Engineer",
|
"title": "Software Engineer",
|
||||||
"loc": "Helsinki, FI",
|
"loc": "Helsinki, FI",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/LukasDoesDev" ], null ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/LukasDoesDev"
|
||||||
|
],
|
||||||
|
null
|
||||||
|
],
|
||||||
"blurb": "Arch Linux enthusiast who likes 80s/90s music, Rust (The programming language) and light distros like Arch Linux btw. Dislikes C, C++, Go, and Microsoft. Also doesn't like Finnish weather that freezes molten snow to (deadly) ice.",
|
"blurb": "Arch Linux enthusiast who likes 80s/90s music, Rust (The programming language) and light distros like Arch Linux btw. Dislikes C, C++, Go, and Microsoft. Also doesn't like Finnish weather that freezes molten snow to (deadly) ice.",
|
||||||
"pic": "/static/assets/images/credits/lukas.png"
|
"pic": "/static/assets/images/credits/lukas.png"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Zedifus",
|
|
||||||
"title": "DevOps Engineer",
|
|
||||||
"loc": "Scotland, UK",
|
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/Zedifus" ], "DevOps" ],
|
|
||||||
"blurb": "A Streamer, who is currently working in the insurance industry, self-teaching software development & DevOps, with the hopes of a career change! Enjoys playing games and has a sassy cat called Eve.",
|
|
||||||
"pic": "/static/assets/images/credits/zedifus.jpg"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"support": [
|
"support": [
|
||||||
@ -71,7 +127,11 @@
|
|||||||
"name": "iSilverfyre",
|
"name": "iSilverfyre",
|
||||||
"title": "Community Manager",
|
"title": "Community Manager",
|
||||||
"loc": "South Central, US",
|
"loc": "South Central, US",
|
||||||
"tags": [ "Staff", null, "Wiki" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
null,
|
||||||
|
"Wiki"
|
||||||
|
],
|
||||||
"blurb": "Silver enjoys helping others with their computer needs, writing documentation, and loving her cat.",
|
"blurb": "Silver enjoys helping others with their computer needs, writing documentation, and loving her cat.",
|
||||||
"pic": "/static/assets/images/credits/isilverfyre.png"
|
"pic": "/static/assets/images/credits/isilverfyre.png"
|
||||||
},
|
},
|
||||||
@ -79,17 +139,28 @@
|
|||||||
"name": "Quentin",
|
"name": "Quentin",
|
||||||
"title": "Document Curator",
|
"title": "Document Curator",
|
||||||
"loc": null,
|
"loc": null,
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/qub3d" ], "Wiki" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/qub3d"
|
||||||
|
],
|
||||||
|
"Wiki"
|
||||||
|
],
|
||||||
"blurb": "Hosts Minecraft servers for his weird friends, works for an IoT company as his dayjob. The 's' in IoT stands for 'secure'.",
|
"blurb": "Hosts Minecraft servers for his weird friends, works for an IoT company as his dayjob. The 's' in IoT stands for 'secure'.",
|
||||||
"pic": "/static/assets/images/credits/qub3d.png"
|
"pic": "/static/assets/images/credits/qub3d.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "DarthLeo",
|
"name": "Kornster",
|
||||||
"title": "Support Engineer",
|
"title": null,
|
||||||
"loc": "East Coast, US",
|
"loc": "Victoria, Australia",
|
||||||
"tags": [ "Staff", null, "Discord" ],
|
"tags": [
|
||||||
"blurb": "Just a simple gamer.",
|
"Discord Mod",
|
||||||
"pic": "/static/assets/images/credits/darthLeo.png"
|
null,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"blurb": "Day to day I am a Network Administrator, dealing with a range of vendors and products. Outside of work my hobbies are handyman things, such as carpentry and motor mechanics having grown up around them. My home-lab consists of Linux distros ranging from Debian, Ubuntu & Centos having self taught myself Linux for the last 12+ years.",
|
||||||
|
"pic": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"retired": [
|
"retired": [
|
||||||
@ -97,7 +168,14 @@
|
|||||||
"name": "Kev Dagoat",
|
"name": "Kev Dagoat",
|
||||||
"title": "Head of Development",
|
"title": "Head of Development",
|
||||||
"loc": "East Coast, AU",
|
"loc": "East Coast, AU",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/kevdagoat" ], "HOD" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/kevdagoat"
|
||||||
|
],
|
||||||
|
"HOD"
|
||||||
|
],
|
||||||
"blurb": "His interests include Linux, programming, and goats of course. He enjoys building APIs, K8s, and geeking over video cards.",
|
"blurb": "His interests include Linux, programming, and goats of course. He enjoys building APIs, K8s, and geeking over video cards.",
|
||||||
"pic": "/static/assets/images/credits/kevdagoat.jpeg"
|
"pic": "/static/assets/images/credits/kevdagoat.jpeg"
|
||||||
},
|
},
|
||||||
@ -105,7 +183,11 @@
|
|||||||
"name": "Manu",
|
"name": "Manu",
|
||||||
"title": null,
|
"title": null,
|
||||||
"loc": "Eastern, CA",
|
"loc": "Eastern, CA",
|
||||||
"tags": [ "Staff", "Developer", "Project Manager" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
"Developer",
|
||||||
|
"Project Manager"
|
||||||
|
],
|
||||||
"blurb": "His interests include learning, Linux, and programming. He enjoys speaking French, doing 6 things at once, and testing software.",
|
"blurb": "His interests include learning, Linux, and programming. He enjoys speaking French, doing 6 things at once, and testing software.",
|
||||||
"pic": "/static/assets/images/credits/manu.png"
|
"pic": "/static/assets/images/credits/manu.png"
|
||||||
},
|
},
|
||||||
@ -113,7 +195,11 @@
|
|||||||
"name": "UltraBlack",
|
"name": "UltraBlack",
|
||||||
"title": null,
|
"title": null,
|
||||||
"loc": "Bavaria, DE",
|
"loc": "Bavaria, DE",
|
||||||
"tags": [ "Staff", null, "Idea Manager" ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
null,
|
||||||
|
"Idea Manager"
|
||||||
|
],
|
||||||
"blurb": "Hi, my name is Tim, and I'm a huge fan of linux. I'm often gaming and occasionally coding.",
|
"blurb": "Hi, my name is Tim, and I'm a huge fan of linux. I'm often gaming and occasionally coding.",
|
||||||
"pic": "/static/assets/images/credits/ultrablack.png"
|
"pic": "/static/assets/images/credits/ultrablack.png"
|
||||||
},
|
},
|
||||||
@ -121,19 +207,32 @@
|
|||||||
"name": "MC Gaming",
|
"name": "MC Gaming",
|
||||||
"title": null,
|
"title": null,
|
||||||
"loc": "Central, UK",
|
"loc": "Central, UK",
|
||||||
"tags": [ "Staff", [ "Developer", "https://gitlab.com/MCgamin1738" ], null ],
|
"tags": [
|
||||||
|
"Staff",
|
||||||
|
[
|
||||||
|
"Developer",
|
||||||
|
"https://gitlab.com/MCgamin1738"
|
||||||
|
],
|
||||||
|
null
|
||||||
|
],
|
||||||
"blurb": "His interests include learning, Linux, and programming. He loves pentesting apps and gaming.",
|
"blurb": "His interests include learning, Linux, and programming. He loves pentesting apps and gaming.",
|
||||||
"pic": "/static/assets/images/credits/mcgaming.png"
|
"pic": "/static/assets/images/credits/mcgaming.png"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"translations": {
|
"translations": {
|
||||||
"Data Unavailable": ["🌎🪣🔗👎😭"]
|
"Data Unavailable": [
|
||||||
|
{
|
||||||
|
"name": "🌎🪣🔗👎😭",
|
||||||
|
"status": false
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"patrons": [
|
"patrons": [
|
||||||
{
|
{
|
||||||
"name": "Data Unavailable 🌎🪣🔗👎😭",
|
"name": "Data Unavailable 🌎🪣🔗👎😭",
|
||||||
"level": ""
|
"level": "",
|
||||||
|
"source": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lastUpdate": 0
|
"lastUpdate": 0
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"major": 4,
|
"major": 4,
|
||||||
"minor": 0,
|
"minor": 0,
|
||||||
"sub": 8,
|
"sub": 10,
|
||||||
"meta": "beta"
|
"meta": "beta"
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,27 @@
|
|||||||
<!-- partial:partials/_footer.html -->
|
<!-- partial:partials/_footer.html -->
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="container-fluid ">
|
<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="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"> {{ translate('footer', 'version', data['lang']) }}: {{ data['version_data'] }}</span>
|
||||||
<span class="float-none float-sm-right d-block mt-1 mt-sm-0 text-center">{{ translate('footer', 'version', data['lang']) }}: {{ data['version_data'] }}
|
{% if data['update_available'] %}
|
||||||
</span>
|
<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>
|
</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>
|
</footer>
|
||||||
<!-- partial -->
|
<!-- partial -->
|
||||||
|
@ -342,7 +342,11 @@
|
|||||||
<td class="pb-0">
|
<td class="pb-0">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for language in data['translations'][person] %}
|
{% for language in data['translations'][person] %}
|
||||||
<span class="btn btn-sm btn-inverse-success mr-2" style="margin-bottom: 12px;">{{ language }}</span>
|
{% if language['status'] %}
|
||||||
|
<span class="btn btn-sm btn-inverse-success mr-2" style="margin-bottom: 12px;">{{ language['name'] }}</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="btn btn-sm btn-inverse-secondary mr-2" style="margin-bottom: 12px;">{{ language['name'] }}</span>
|
||||||
|
{% end %}
|
||||||
{% end %}
|
{% end %}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
@ -125,7 +125,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|
||||||
{% if len(data['servers']) == 0%}
|
{% if len(data['servers']) == 0 and len(data['failed_servers']) == 0 %}
|
||||||
<div style="text-align: center; color: grey;">
|
<div style="text-align: center; color: grey;">
|
||||||
<h1>{{ translate('dashboard', 'welcome', data['lang']) }}</h1>
|
<h1>{{ translate('dashboard', 'welcome', data['lang']) }}</h1>
|
||||||
<br>
|
<br>
|
||||||
@ -134,7 +134,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% end %}
|
{% end %}
|
||||||
{% if len(data['servers']) > 0 %}
|
{% if len(data['servers']) > 0 or len(data['failed_servers']) > 0 %}
|
||||||
<!-- View for Large screen -->
|
<!-- View for Large screen -->
|
||||||
<div class="table-responsive d-none d-sm-block">
|
<div class="table-responsive d-none d-sm-block">
|
||||||
<table id="servers_table" class="table table-hover">
|
<table id="servers_table" class="table table-hover">
|
||||||
@ -290,6 +290,19 @@
|
|||||||
data-players="{{ server['stats']['online']}}" data-max="{{ server['stats']['max'] }}"></span>
|
data-players="{{ server['stats']['online']}}" data-max="{{ server['stats']['max'] }}"></span>
|
||||||
</tr>
|
</tr>
|
||||||
{% end %}
|
{% end %}
|
||||||
|
{% for server in data['failed_servers'] %}
|
||||||
|
<tr id="{{server['server_id']}}" draggable="false">
|
||||||
|
<td class="text-warning"><i class="fas fa-server"></i> <a class="text-warning"
|
||||||
|
href="/panel/server_detail?id={{server['server_id']}}&subpage=config">{{server['server_name']}}</a>
|
||||||
|
</td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td><i class="fas fa-cloud"></i> Unloaded</td>
|
||||||
|
</tr>
|
||||||
|
{% end %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,14 +32,12 @@
|
|||||||
<ul class="nav nav-tabs col-md-12 tab-simple-styled " role="tablist">
|
<ul class="nav nav-tabs col-md-12 tab-simple-styled " role="tablist">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/panel/edit_user?id={{ data['user']['user_id'] }}&subpage=config"
|
<a class="nav-link" href="/panel/edit_user?id={{ data['user']['user_id'] }}&subpage=config"
|
||||||
role="tab"
|
role="tab" aria-selected="false">
|
||||||
aria-selected="false">
|
|
||||||
<i class="fas fa-cogs"></i>{{ translate('apiKeys', 'config', data['lang']) }}</a>
|
<i class="fas fa-cogs"></i>{{ translate('apiKeys', 'config', data['lang']) }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link active" href="/panel/edit_user_apikeys?id={{ data['user']['user_id'] }}"
|
<a class="nav-link active" href="/panel/edit_user_apikeys?id={{ data['user']['user_id'] }}"
|
||||||
role="tab"
|
role="tab" aria-selected="true">
|
||||||
aria-selected="true">
|
|
||||||
<i class="fas fa-key"></i>{{ translate('apiKeys', 'apiKeys', data['lang']) }}</a>
|
<i class="fas fa-key"></i>{{ translate('apiKeys', 'apiKeys', data['lang']) }}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -48,7 +46,8 @@
|
|||||||
<div class="col-md-7 col-sm-12">
|
<div class="col-md-7 col-sm-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header header-sm d-flex justify-content-between align-items-center">
|
<div class="card-header header-sm d-flex justify-content-between align-items-center">
|
||||||
<h4 class="card-title"><i class="fas fa-key"></i>{{ translate('apiKeys', 'apiKeys', data['lang']) }}</h4>
|
<h4 class="card-title"><i class="fas fa-key"></i>{{ translate('apiKeys', 'apiKeys',
|
||||||
|
data['lang']) }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -73,27 +72,30 @@
|
|||||||
<td>
|
<td>
|
||||||
{% if apikey.superuser %}
|
{% if apikey.superuser %}
|
||||||
<span class="text-success">
|
<span class="text-success">
|
||||||
<i class="fas fa-check-square"></i> {{ translate('apiKeys', 'yes', data['lang']) }}
|
<i class="fas fa-check-square"></i> {{
|
||||||
|
translate('apiKeys', 'yes', data['lang']) }}
|
||||||
</span>
|
</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="text-danger">
|
<span class="text-danger">
|
||||||
<i class="far fa-times-square"></i> {{ translate('apiKeys', 'no', data['lang']) }}
|
<i class="far fa-times-square"></i> {{
|
||||||
|
translate('apiKeys', 'no', data['lang']) }}
|
||||||
</span>
|
</span>
|
||||||
{% end %}
|
{% end %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ translate('apiKeys', 'server', data['lang']) }} {{ apikey.server_permissions }}
|
<td>{{ translate('apiKeys', 'server', data['lang']) }} {{
|
||||||
{{ translate('apiKeys', 'crafty', data['lang']) }} {{ apikey.crafty_permissions }}</td>
|
apikey.server_permissions }}
|
||||||
|
{{ translate('apiKeys', 'crafty', data['lang']) }} {{
|
||||||
|
apikey.crafty_permissions }}</td>
|
||||||
<td>
|
<td>
|
||||||
<button
|
<button class="btn btn-danger delete-api-key"
|
||||||
class="btn btn-danger delete-api-key"
|
|
||||||
data-key-id="{{ apikey.token_id }}"
|
data-key-id="{{ apikey.token_id }}"
|
||||||
data-key-name="{{ apikey.name }}"
|
data-key-name="{{ apikey.name }}">{{
|
||||||
>{{ translate('panelConfig', 'delete', data['lang']) }}</button>
|
translate('panelConfig', 'delete', data['lang'])
|
||||||
<button
|
}}</button>
|
||||||
class="btn btn-outline-primary get-a-token"
|
<button class="btn btn-outline-primary get-a-token"
|
||||||
data-key-id="{{ apikey.token_id }}"
|
data-key-id="{{ apikey.token_id }}"
|
||||||
data-key-name="{{ apikey.name }}"
|
data-key-name="{{ apikey.name }}">{{
|
||||||
>{{ translate('apiKeys', 'getToken', data['lang']) }}
|
translate('apiKeys', 'getToken', data['lang']) }}
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -109,7 +111,8 @@
|
|||||||
<div class="col-md-5 col-sm-12">
|
<div class="col-md-5 col-sm-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header header-sm d-flex justify-content-between align-items-center">
|
<div class="card-header header-sm d-flex justify-content-between align-items-center">
|
||||||
<h4 class="card-title"><i class="fas fa-plus"></i> {{ translate('apiKeys', 'createNew', data['lang']) }}</h4>
|
<h4 class="card-title"><i class="fas fa-plus"></i> {{ translate('apiKeys',
|
||||||
|
'createNew', data['lang']) }}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form id="user_form" class="forms-sample" method="post"
|
<form id="user_form" class="forms-sample" method="post"
|
||||||
@ -118,8 +121,9 @@
|
|||||||
<input type="hidden" name="id" value="{{ data['user']['user_id'] }}">
|
<input type="hidden" name="id" value="{{ data['user']['user_id'] }}">
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="username">{{ translate('apiKeys', 'name', data['lang']) }}<small
|
<label class="form-label" for="username">{{ translate('apiKeys', 'name',
|
||||||
class="text-muted ml-1"> - {{ translate('apiKeys', 'nameDesc', data['lang']) }}</small> </label>
|
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"
|
<input type="text" class="form-control" name="name" id="name"
|
||||||
placeholder="API Key">
|
placeholder="API Key">
|
||||||
</div>
|
</div>
|
||||||
@ -134,8 +138,8 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for permission in data['server_permissions_all'] %}
|
{% for permission in data['server_permissions_all'] %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><label
|
<td><label for="permission_{{ permission.name }}">{{ permission.name
|
||||||
for="permission_{{ permission.name }}">{{ permission.name }}</label>
|
}}</label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" class=""
|
<input type="checkbox" class=""
|
||||||
@ -146,8 +150,8 @@
|
|||||||
{% end %}
|
{% end %}
|
||||||
{% for permission in data['crafty_permissions_all'] %}
|
{% for permission in data['crafty_permissions_all'] %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><label
|
<td><label for="permission_{{ permission.name }}">{{ permission.name
|
||||||
for="permission_{{ permission.name }}">{{ permission.name }}</label>
|
}}</label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="checkbox" class=""
|
<input type="checkbox" class=""
|
||||||
@ -161,16 +165,15 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<label for="superuser">Superuser</label>
|
<label for="superuser">Superuser</label>
|
||||||
<input type="checkbox" class="" id="superuser"
|
<input type="checkbox" class="" id="superuser" name="superuser" value="1">
|
||||||
name="superuser" value="1">
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-plus"></i>
|
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-plus"></i>
|
||||||
Create
|
Create
|
||||||
</button>
|
</button>
|
||||||
<button type="reset" class="btn btn-light"><i
|
<button type="reset" class="btn btn-light"><i class="fas fa-undo-alt"></i> {{
|
||||||
class="fas fa-undo-alt"></i> {{ translate('panelConfig', 'cancel', data['lang']) }}
|
translate('panelConfig', 'cancel', data['lang']) }}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -216,6 +219,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
callback: function (result) {
|
callback: function (result) {
|
||||||
|
if (result) {
|
||||||
var token = getCookie("_xsrf")
|
var token = getCookie("_xsrf")
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "DELETE",
|
type: "DELETE",
|
||||||
@ -226,6 +230,7 @@
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
$('.get-a-token').click(function () {
|
$('.get-a-token').click(function () {
|
||||||
|
@ -32,12 +32,14 @@
|
|||||||
<div class="col-sm-12 grid-margin">
|
<div class="col-sm-12 grid-margin">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body pt-0">
|
<div class="card-body pt-0">
|
||||||
|
{% if not data['failed'] %}
|
||||||
<span class="d-none d-sm-block">
|
<span class="d-none d-sm-block">
|
||||||
{% include "parts/server_controls_list.html %}
|
{% include "parts/server_controls_list.html %}
|
||||||
</span>
|
</span>
|
||||||
<span class="d-block d-sm-none">
|
<span class="d-block d-sm-none">
|
||||||
{% include "parts/m_server_controls_list.html %}
|
{% include "parts/m_server_controls_list.html %}
|
||||||
</span>
|
</span>
|
||||||
|
{% end %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 col-sm-12">
|
<div class="col-md-6 col-sm-12">
|
||||||
@ -117,7 +119,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="stop_command">{{ translate('serverConfig', 'serverStopCommand', data['lang']) }} <small
|
<label for="stop_command">{{ translate('serverConfig', 'serverStopCommand', data['lang']) }} <small
|
||||||
class="text-muted ml-1"> - {{ translate('serverConfig', 'serverStopCommandDesc', data['lang'])
|
class="text-muted ml-1"> - {{ translate('serverConfig', 'serverStopCommandDesc', data['lang'])
|
||||||
@ -176,32 +177,38 @@
|
|||||||
<div class="form-check-flat">
|
<div class="form-check-flat">
|
||||||
<label for="auto_start" class="form-check-label ml-4 mb-4">
|
<label for="auto_start" class="form-check-label ml-4 mb-4">
|
||||||
{% if data['server_stats']['server_id']['auto_start'] %}
|
{% if data['server_stats']['server_id']['auto_start'] %}
|
||||||
<input type="checkbox" class="form-check-input" id="auto_start" name="auto_start" checked="" data-toggle="toggle"
|
<input type="checkbox" class="form-check-input" id="auto_start" name="auto_start" checked=""
|
||||||
value="1"> {{ translate('serverConfig', 'serverAutoStart', data['lang']) }}
|
data-toggle="toggle" value="1"> {{ translate('serverConfig', 'serverAutoStart',
|
||||||
|
data['lang']) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="checkbox" class="form-check-input" id="auto_start" name="auto_start" value="1" data-toggle="toggle"> {{
|
<input type="checkbox" class="form-check-input" id="auto_start" name="auto_start" value="1"
|
||||||
|
data-toggle="toggle"> {{
|
||||||
translate('serverConfig', 'serverAutoStart', data['lang']) }}
|
translate('serverConfig', 'serverAutoStart', data['lang']) }}
|
||||||
{% end %}
|
{% end %}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="crash_detection" class="form-check-label ml-4 mb-4">
|
<label for="crash_detection" class="form-check-label ml-4 mb-4">
|
||||||
{% if data['server_stats']['server_id']['crash_detection'] %}
|
{% if data['server_stats']['server_id']['crash_detection'] %}
|
||||||
<input type="checkbox" class="form-check-input" id="crash_detection" name="crash_detection" data-toggle="toggle"
|
<input type="checkbox" class="form-check-input" id="crash_detection" name="crash_detection"
|
||||||
checked="" value="1"> {{ translate('serverConfig', 'serverCrashDetection', data['lang']) }}
|
data-toggle="toggle" checked="" value="1"> {{ translate('serverConfig',
|
||||||
|
'serverCrashDetection', data['lang']) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="checkbox" class="form-check-input" id="crash_detection" name="crash_detection" data-toggle="toggle"
|
<input type="checkbox" class="form-check-input" id="crash_detection" name="crash_detection"
|
||||||
value="1"> {{ translate('serverConfig', 'serverCrashDetection', data['lang']) }}
|
data-toggle="toggle" value="1"> {{ translate('serverConfig', 'serverCrashDetection',
|
||||||
|
data['lang']) }}
|
||||||
{% end %}
|
{% end %}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
{% if data['super_user'] %}
|
{% if data['super_user'] %}
|
||||||
<label for="show_status" class="form-check-label ml-4 mb-4">
|
<label for="show_status" class="form-check-label ml-4 mb-4">
|
||||||
{% if data['server_stats']['server_id']['show_status'] %}
|
{% if data['server_stats']['server_id']['show_status'] %}
|
||||||
<input type="checkbox" class="form-check-input" id="show_status" name="show_status" data-toggle="toggle"
|
<input type="checkbox" class="form-check-input" id="show_status" name="show_status"
|
||||||
checked="" value="1"> {{ translate('serverConfig', 'showStatus', data['lang']) }}
|
data-toggle="toggle" checked="" value="1"> {{ translate('serverConfig', 'showStatus',
|
||||||
|
data['lang']) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="checkbox" class="form-check-input" id="show_status" name="show_status" data-toggle="toggle"
|
<input type="checkbox" class="form-check-input" id="show_status" name="show_status"
|
||||||
value="1"> {{ translate('serverConfig', 'showStatus', data['lang']) }}
|
data-toggle="toggle" value="1"> {{ translate('serverConfig', 'showStatus',
|
||||||
|
data['lang']) }}
|
||||||
{% end %}
|
{% end %}
|
||||||
</label>
|
</label>
|
||||||
{% end %}
|
{% end %}
|
||||||
@ -235,11 +242,18 @@
|
|||||||
}}</a><br />
|
}}</a><br />
|
||||||
<small>{{ translate('serverConfig', 'stopBeforeDeleting', data['lang']) }}</small>
|
<small>{{ translate('serverConfig', 'stopBeforeDeleting', data['lang']) }}</small>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
{% if not data['failed'] %}
|
||||||
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
<button onclick="send_command(serverId, 'update_executable');" id="update_executable"
|
||||||
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1">{{ translate('serverConfig',
|
style="max-width: 7rem;" class="btn btn-warning m-1 flex-grow-1">{{ translate('serverConfig',
|
||||||
'update', data['lang']) }}</button>
|
'update', data['lang']) }}</button>
|
||||||
|
{% end %}
|
||||||
|
{% if not data['failed'] %}
|
||||||
<button onclick="deleteConfirm()" class="btn btn-sm btn-danger">{{ translate('serverConfig',
|
<button onclick="deleteConfirm()" class="btn btn-sm btn-danger">{{ translate('serverConfig',
|
||||||
'deleteServer', data['lang']) }}</button>
|
'deleteServer', data['lang']) }}</button>
|
||||||
|
{% else %}
|
||||||
|
<button onclick="deleteUnloadedConfirm()" class="btn btn-sm btn-danger">{{ translate('serverConfig',
|
||||||
|
'deleteServer', data['lang']) }}</button>
|
||||||
|
{% end %}
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -430,6 +444,54 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function deleteUnloadedConfirm() {
|
||||||
|
path = "{{data['server_stats']['server_id']['path']}}";
|
||||||
|
name = "{{data['server_stats']['server_id']['server_name']}}";
|
||||||
|
bootbox.confirm({
|
||||||
|
size: "",
|
||||||
|
title: "{% raw translate('serverConfig', 'deleteServerQuestion', data['lang']) %}",
|
||||||
|
closeButton: false,
|
||||||
|
message: "{% raw translate('serverConfig', 'deleteServerQuestionMessage', data['lang']) %}",
|
||||||
|
buttons: {
|
||||||
|
confirm: {
|
||||||
|
label: "{{ translate('serverConfig', 'yesDelete', data['lang']) }}",
|
||||||
|
className: 'btn-danger',
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
label: "{{ translate('serverConfig', 'noDelete', data['lang']) }}",
|
||||||
|
className: 'btn-link',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callback: function (result) {
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var token = getCookie("_xsrf")
|
||||||
|
setTimeout(function () { window.location = '/panel/dashboard'; }, 5000);
|
||||||
|
bootbox.dialog({
|
||||||
|
backdrop: true,
|
||||||
|
title: '{% raw translate("serverConfig", "sendingDelete", data['lang']) %}',
|
||||||
|
message: '<div align="center"><i class="fas fa-spin fa-spinner"></i> {% raw translate("serverConfig", "bePatientDelete", data['lang']) %} </div>',
|
||||||
|
closeButton: false
|
||||||
|
})
|
||||||
|
$.ajax({
|
||||||
|
type: "DELETE",
|
||||||
|
headers: { 'X-XSRFToken': token },
|
||||||
|
url: '/ajax/delete_unloaded_server?id=' + serverId,
|
||||||
|
data: {
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
console.log("got response:");
|
||||||
|
console.log(data);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -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>
|
||||||
@ -36,77 +37,122 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8 col-sm-8">
|
<div class="col-md-8 col-sm-8">
|
||||||
{% if data['new_schedule'] == True %}
|
{% if data['new_schedule'] == True %}
|
||||||
<form class="forms-sample" method="post" action="/panel/new_schedule?id={{ data['server_stats']['server_id']['server_id'] }}">
|
<form class="forms-sample" method="post"
|
||||||
|
action="/panel/new_schedule?id={{ data['server_stats']['server_id']['server_id'] }}">
|
||||||
{% else %}
|
{% else %}
|
||||||
<form class="forms-sample" method="post" action="/panel/edit_schedule?id={{ data['server_stats']['server_id']['server_id'] }}&sch_id={{ data['schedule']['schedule_id'] }}">
|
<form class="forms-sample" method="post"
|
||||||
|
action="/panel/edit_schedule?id={{ data['server_stats']['server_id']['server_id'] }}&sch_id={{ data['schedule']['schedule_id'] }}">
|
||||||
{% end %}
|
{% end %}
|
||||||
{% raw xsrf_form_html() %}
|
{% raw xsrf_form_html() %}
|
||||||
<input type="hidden" name="id" value="{{ data['server_stats']['server_id']['server_id'] }}">
|
<input type="hidden" name="id" value="{{ data['server_stats']['server_id']['server_id'] }}">
|
||||||
<input type="hidden" name="subpage" value="config">
|
<input type="hidden" name="subpage" value="config">
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="difficulty">Basic / Cron / Chain-Reaction Select<small class="text-muted ml-1"></small> </label><br>
|
<label for="name">{{ translate('serverSchedules', 'name' , data['lang']) }}</label>
|
||||||
<select id="difficulty" name="difficulty" onchange="basicAdvanced(this);" class="form-control form-control-lg select-css" value="{{ data['schedule']['difficulty'] }}">
|
<input type="input" class="form-control" name="name" id="name_input"
|
||||||
<option id="basic" value="basic">{{ translate('serverScheduleConfig', 'basic' , data['lang']) }}</option>
|
value="{{ data['schedule']['name']}}" maxlength="30" placeholder="Name" required>
|
||||||
<option id="advanced" value="advanced">{{ translate('serverScheduleConfig', 'cron' , data['lang']) }}</option>
|
</div>
|
||||||
<option id="reaction" value="reaction">{{ translate('serverScheduleConfig', 'reaction' , data['lang']) }}</option>
|
|
||||||
|
<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'] }}">
|
||||||
|
<option id="basic" value="basic">{{ translate('serverScheduleConfig', 'basic' , data['lang']) }}
|
||||||
|
</option>
|
||||||
|
<option id="advanced" value="advanced">{{ translate('serverScheduleConfig', 'cron' , data['lang'])
|
||||||
|
}}</option>
|
||||||
|
<option id="reaction" value="reaction">{{ translate('serverScheduleConfig', 'reaction' ,
|
||||||
|
data['lang']) }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="server_name">Action<small class="text-muted ml-1"></small> </label><br>
|
<label for="server_name">{{ translate('serverSchedules', 'action' , data['lang']) }}<small
|
||||||
<select id="action" name="action" onchange="yesnoCheck(this);" class="form-control form-control-lg select-css" value="{{ data['schedule']['action'] }}">
|
class="text-muted ml-1"></small> </label><br>
|
||||||
<option id="start" value="start">{{ translate('serverScheduleConfig', 'start' , data['lang']) }}</option>
|
<select id="action" name="action" onchange="yesnoCheck(this);"
|
||||||
<option id="restart" value="restart">{{ translate('serverScheduleConfig', 'restart' , data['lang']) }}</option>
|
class="form-control form-control-lg select-css" value="{{ data['schedule']['action'] }}">
|
||||||
<option id="stop" value="stop">{{ translate('serverScheduleConfig', 'stop' , data['lang']) }}</option>
|
<option id="start" value="start">{{ translate('serverScheduleConfig', 'start' , data['lang']) }}
|
||||||
<option id="backup" value="backup">{{ translate('serverScheduleConfig', 'backup' , data['lang']) }}</option>
|
</option>
|
||||||
<option id="command" value="command">{{ translate('serverScheduleConfig', 'custom' , data['lang']) }}</option>
|
<option id="restart" value="restart">{{ translate('serverScheduleConfig', 'restart' ,
|
||||||
|
data['lang']) }}</option>
|
||||||
|
<option id="stop" value="stop">{{ translate('serverScheduleConfig', 'stop' , data['lang']) }}
|
||||||
|
</option>
|
||||||
|
<option id="backup" value="backup">{{ translate('serverScheduleConfig', 'backup' , data['lang'])
|
||||||
|
}}</option>
|
||||||
|
<option id="command" value="command">{{ translate('serverScheduleConfig', 'custom' , data['lang'])
|
||||||
|
}}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="ifBasic">
|
<div id="ifBasic">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="server_path">{{ translate('serverScheduleConfig', 'interval' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'interval-explain' , data['lang']) }}</small> </label>
|
<label for="server_path">{{ translate('serverScheduleConfig', 'interval' , data['lang']) }} <small
|
||||||
<input type="number" class="form-control" name="interval" id="interval" value="{{ data['schedule']['interval'] }}" placeholder="Interval" required>
|
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>
|
||||||
<br>
|
<br>
|
||||||
<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"
|
||||||
<option id = "days" value="days">{{ translate('serverScheduleConfig', 'days' , data['lang']) }}</option>
|
class="form-control form-control-lg select-css"
|
||||||
<option id = "hours" value="hours">{{ translate('serverScheduleConfig', 'hours' , data['lang']) }}</option>
|
value="{{ data['schedule']['interval_type'] }}">
|
||||||
<option id = "minutes" value="minutes">{{ translate('serverScheduleConfig', 'minutes' , data['lang']) }}</option>
|
<option id="days" value="days">{{ translate('serverScheduleConfig', 'days' , data['lang']) }}
|
||||||
|
</option>
|
||||||
|
<option id="hours" value="hours">{{ translate('serverScheduleConfig', 'hours' , data['lang']) }}
|
||||||
|
</option>
|
||||||
|
<option id="minutes" value="minutes">{{ translate('serverScheduleConfig', 'minutes' ,
|
||||||
|
data['lang']) }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div id="ifDays" style="display: block;">
|
<div id="ifDays" style="display: block;">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="time">{{ translate('serverScheduleConfig', 'time' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'time-explain' , data['lang']) }}</small> </label>
|
<label for="time">{{ translate('serverScheduleConfig', 'time' , data['lang']) }} <small
|
||||||
<input type="time" class="form-control" name="time" id="time" value="{{ data['schedule']['time'] }}" placeholder="Time" required>
|
class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'time-explain' ,
|
||||||
|
data['lang']) }}</small> </label>
|
||||||
|
<input type="time" class="form-control" name="time" id="time"
|
||||||
|
value="{{ data['schedule']['time'] }}" placeholder="Time" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="ifYes" style="display: none;">
|
<div id="ifYes" style="display: none;">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="command">{{ translate('serverScheduleConfig', 'command' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'command-explain' , data['lang']) }}</small> </label>
|
<label for="command">{{ translate('serverScheduleConfig', 'command' , data['lang']) }} <small
|
||||||
<input type="input" class="form-control" name="command" id="command_input" value="{{ data['schedule']['command'] }}" placeholder="Command" required>
|
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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="ifAdvanced" style="display: none;">
|
<div id="ifAdvanced" style="display: none;">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="cron">{{ translate('serverScheduleConfig', 'cron' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'cron-explain' , data['lang']) }}</small> </label>
|
<label for="cron">{{ translate('serverScheduleConfig', 'cron' , data['lang']) }} <small
|
||||||
<input type="input" class="form-control" name="cron" id="cron" value="{{ data['schedule']['cron_string'] }}" placeholder="* * * * *">
|
class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'cron-explain' , data['lang'])
|
||||||
|
}}</small> </label>
|
||||||
|
<input type="input" class="form-control" name="cron" id="cron"
|
||||||
|
value="{{ data['schedule']['cron_string'] }}" placeholder="* * * * *">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="ifReaction" style="display: none;">
|
<div id="ifReaction" style="display: none;">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="delay">{{ translate('serverScheduleConfig', 'offset' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'offset-explain' , data['lang']) }}</small> </label>
|
<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="0">
|
<input type="number" class="form-control" name="delay" id="delay" value="0">
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<label for="parent">{{ translate('serverScheduleConfig', 'parent' , data['lang']) }} <small class="text-muted ml-1"> - {{ translate('serverScheduleConfig', 'parent-explain' , data['lang']) }}</small> </label>
|
<label for="parent">{{ translate('serverScheduleConfig', 'parent' , data['lang']) }} <small
|
||||||
<select id="parent" name="parent" class="form-control form-control-lg select-css" value="{{ data['schedule']['action'] }}">
|
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'] }}">
|
||||||
{% for schedule in data['schedules'] %}
|
{% for schedule in data['schedules'] %}
|
||||||
{% if schedule.schedule_id != data['schedule']['schedule_id'] %}
|
{% if schedule.schedule_id != data['schedule']['schedule_id'] %}
|
||||||
{% if schedule.interval != '' %}
|
{% if schedule.interval != '' %}
|
||||||
<option id="{{schedule.schedule_id}}" value="{{schedule.schedule_id}}">ID: {{schedule.schedule_id}} | {{schedule.command}} | {{schedule.interval}} {{ schedule.interval_type}}</option>
|
<option id="{{schedule.schedule_id}}" value="{{schedule.schedule_id}}">
|
||||||
|
{{schedule.name}} | {{schedule.command}} | {{schedule.interval}} {{
|
||||||
|
schedule.interval_type}}</option>
|
||||||
{% else %}
|
{% else %}
|
||||||
<option id="{{schedule.schedule_id}}" value="{{schedule.schedule_id}}">ID: {{schedule.schedule_id}} {{schedule.command}} {{schedule.cron_string}}</option>
|
<option id="{{schedule.schedule_id}}" value="{{schedule.schedule_id}}">
|
||||||
|
{{schedule.name}} | {{schedule.command}} | {{schedule.cron_string}}</option>
|
||||||
{% end %}
|
{% end %}
|
||||||
{% end %}
|
{% end %}
|
||||||
{% end %}
|
{% end %}
|
||||||
@ -116,25 +162,33 @@
|
|||||||
|
|
||||||
<div class="form-check-flat">
|
<div class="form-check-flat">
|
||||||
<label for="enabled" class="form-check-label ml-4 mb-4">
|
<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>
|
</label>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check-flat">
|
<div class="form-check-flat">
|
||||||
<label for="one_time" class="form-check-label ml-4 mb-4">
|
<label for="one_time" class="form-check-label ml-4 mb-4">
|
||||||
<input type="checkbox" class="form-check-input" id="one_time" name="one_time" value="1">{{ translate('serverScheduleConfig', 'one-time' , data['lang']) }}
|
<input type="checkbox" class="form-check-input" id="one_time" name="one_time" value="1">{{
|
||||||
|
translate('serverScheduleConfig', 'one-time' , data['lang']) }}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-save"></i> {{ translate('serverConfig', 'save', data['lang']) }}</button>
|
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-save"></i> {{
|
||||||
<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>
|
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',
|
||||||
|
data['lang']) }}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 grid-margin">
|
<div class="col-sm-4 grid-margin">
|
||||||
<h4>{{ translate('serverScheduleConfig', 'children' , data['lang']) }}</h4>
|
<h4>{{ translate('serverScheduleConfig', 'children' , data['lang']) }}</h4>
|
||||||
<ul>
|
<ul>
|
||||||
{% for schedule in data['schedule']['children'] %}
|
{% 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.schedule_id}} | {{schedule.command}}</a></li>
|
<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>
|
||||||
{% end %}
|
{% end %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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>
|
||||||
@ -43,7 +44,8 @@
|
|||||||
<div class="col-md-12 col-sm-12" style="overflow-x:auto;">
|
<div class="col-md-12 col-sm-12" style="overflow-x:auto;">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header header-sm d-flex justify-content-between align-items-center">
|
<div class="card-header header-sm d-flex justify-content-between align-items-center">
|
||||||
<h4 class="card-title"><i class="fas fa-calendar"></i> Scheduled Tasks</h4>
|
<h4 class="card-title"><i class="fas fa-calendar"></i> {{ translate('serverSchedules',
|
||||||
|
'scheduledTasks', data['lang']) }} </h4>
|
||||||
{% if data['user_data']['hints'] %}
|
{% if data['user_data']['hints'] %}
|
||||||
<span class="too_small" title="{{ translate('serverSchedules', 'cannotSee', data['lang']) }}" ,
|
<span class="too_small" title="{{ translate('serverSchedules', 'cannotSee', data['lang']) }}" ,
|
||||||
data-content="{{ translate('serverSchedules', 'cannotSeeOnMobile', data['lang']) }}" ,
|
data-content="{{ translate('serverSchedules', 'cannotSeeOnMobile', data['lang']) }}" ,
|
||||||
@ -51,27 +53,35 @@
|
|||||||
{% end %}
|
{% end %}
|
||||||
<div><button
|
<div><button
|
||||||
onclick="location.href=`/panel/add_schedule?id={{ data['server_stats']['server_id']['server_id'] }}`"
|
onclick="location.href=`/panel/add_schedule?id={{ data['server_stats']['server_id']['server_id'] }}`"
|
||||||
class="btn btn-info">Create New Schedule <i class="fas fa-pencil-alt"></i></button></div>
|
class="btn btn-info">{{ translate('serverSchedules', 'create', data['lang']) }}<i
|
||||||
|
class="fas fa-pencil-alt"></i></button></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-hover d-none d-lg-block responsive-table" id="schedule_table" width="100%"
|
<table class="table table-hover d-none d-lg-block responsive-table" id="schedule_table" width="100%"
|
||||||
style="table-layout:fixed;">
|
style="table-layout:fixed;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="rounded">
|
<tr class="rounded">
|
||||||
<th style="width: 2%; min-width: 10px;">ID</th>
|
<th style="width: 2%; min-width: 10px;">{{ translate('serverSchedules', 'name', data['lang']) }}
|
||||||
<th style="width: 23%; min-width: 50px;">Action</th>
|
</th>
|
||||||
<th style="width: 40%; min-width: 50px;">Command</th>
|
<th style="width: 23%; min-width: 50px;">{{ translate('serverSchedules', 'action', data['lang'])
|
||||||
<th style="width: 10%; min-width: 50px;">Interval</th>
|
}}</th>
|
||||||
<th style="width: 10%; min-width: 50px;">Start Time</th>
|
<th style="width: 40%; min-width: 50px;">{{ translate('serverSchedules', 'command',
|
||||||
<th style="width: 10%; min-width: 50px;">Enabled</th>
|
data['lang']) }}</th>
|
||||||
<th style="width: 10%; min-width: 50px;">Edit</th>
|
<th style="width: 10%; min-width: 50px;">{{ translate('serverSchedules', 'interval',
|
||||||
|
data['lang']) }}</th>
|
||||||
|
<th style="width: 10%; min-width: 50px;">{{ translate('serverSchedules', 'nextRun',
|
||||||
|
data['lang']) }}</th>
|
||||||
|
<th style="width: 10%; min-width: 50px;">{{ translate('serverSchedules', 'enabled',
|
||||||
|
data['lang']) }}</th>
|
||||||
|
<th style="width: 10%; min-width: 50px;">{{ translate('serverSchedules', 'edit', data['lang'])
|
||||||
|
}}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for schedule in data['schedules'] %}
|
{% for schedule in data['schedules'] %}
|
||||||
<tr>
|
<tr>
|
||||||
<td id="{{schedule.schedule_id}}" class="id">
|
<td id="{{schedule.schedule_id}}" class="id">
|
||||||
<p>{{schedule.schedule_id}}</p>
|
<p>{{schedule.name}}</p>
|
||||||
</td>
|
</td>
|
||||||
<td id="{{schedule.action}}" class="action">
|
<td id="{{schedule.action}}" class="action">
|
||||||
<p>{{schedule.action}}</p>
|
<p>{{schedule.action}}</p>
|
||||||
@ -81,23 +91,28 @@
|
|||||||
</td>
|
</td>
|
||||||
<td id="{{schedule.interval}}" class="action">
|
<td id="{{schedule.interval}}" class="action">
|
||||||
{% if schedule.interval != '' %}
|
{% if schedule.interval != '' %}
|
||||||
<p>Every</p>
|
<p>{{ translate('serverSchedules', 'every', data['lang']) }}</p>
|
||||||
<p>{{schedule.interval}} {{schedule.interval_type}}</p>
|
<p>{{schedule.interval}} {{schedule.interval_type}}</p>
|
||||||
{% elif schedule.interval_type == 'reaction' %}
|
{% elif schedule.interval_type == 'reaction' %}
|
||||||
<p>{{schedule.interval_type}}<br><br>child of ID: {{ schedule.parent }}</p>
|
<p>{{schedule.interval_type}}<br><br>{{ translate('serverSchedules', 'child', data['lang'])}}:
|
||||||
|
{{ schedule.parent }}</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>Cron String:</p>
|
<p>Cron String:</p>
|
||||||
<p>{{schedule.cron_string}}</p>
|
<p>{{schedule.cron_string}}</p>
|
||||||
{% end %}
|
{% end %}
|
||||||
</td>
|
</td>
|
||||||
<td id="{{schedule.start_time}}" class="action">
|
<td id="{{schedule.start_time}}" class="action">
|
||||||
<p>{{schedule.start_time}}</p>
|
<p>{{schedule.next_run}}</p>
|
||||||
</td>
|
</td>
|
||||||
<td id="{{schedule.enabled}}" class="action">
|
<td id="{{schedule.enabled}}" class="action">
|
||||||
<input style="width: 10px !important;" type="checkbox" class="schedule-enabled-toggle" data-schedule-id="{{schedule.schedule_id}}" data-schedule-enabled="{{ 'true' if schedule.enabled else 'false' }}">
|
<input style="width: 10px !important;" type="checkbox" class="schedule-enabled-toggle"
|
||||||
|
data-schedule-id="{{schedule.schedule_id}}"
|
||||||
|
data-schedule-enabled="{{ 'true' if schedule.enabled else 'false' }}">
|
||||||
</td>
|
</td>
|
||||||
<td id="{{schedule.action}}" class="action">
|
<td id="{{schedule.action}}" class="action">
|
||||||
<button onclick="window.location.href='/panel/edit_schedule?id={{ data['server_stats']['server_id']['server_id'] }}&sch_id={{schedule.schedule_id}}'" class="btn btn-info">
|
<button
|
||||||
|
onclick="window.location.href='/panel/edit_schedule?id={{ data['server_stats']['server_id']['server_id'] }}&sch_id={{schedule.schedule_id}}'"
|
||||||
|
class="btn btn-info">
|
||||||
<i class="fas fa-pencil-alt"></i>
|
<i class="fas fa-pencil-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
<br>
|
<br>
|
||||||
@ -111,12 +126,16 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<hr />
|
<hr />
|
||||||
<table class="table table-hover d-block d-lg-none" id="mini_schedule_table" width="100%" style="table-layout:fixed;">
|
<table class="table table-hover d-block d-lg-none" id="mini_schedule_table" width="100%"
|
||||||
|
style="table-layout:fixed;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="rounded">
|
<tr class="rounded">
|
||||||
<th style="width: 25%; min-width: 50px;">Action</th>
|
<th style="width: 25%; min-width: 50px;">{{ translate('serverSchedules', 'action', data['lang'])
|
||||||
<th style="max-width: 40%; min-width: 50px;">Command</th>
|
}}</th>
|
||||||
<th style="width: 10%; min-width: 50px;">Enabled</th>
|
<th style="max-width: 40%; min-width: 50px;">{{ translate('serverSchedules', 'command',
|
||||||
|
data['lang']) }}</th>
|
||||||
|
<th style="width: 10%; min-width: 50px;">{{ translate('serverSchedules', 'enabled',
|
||||||
|
data['lang']) }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -131,21 +150,23 @@
|
|||||||
<td id="{{schedule.enabled}}" class="action">
|
<td id="{{schedule.enabled}}" class="action">
|
||||||
{% if schedule.enabled %}
|
{% if schedule.enabled %}
|
||||||
<span class="text-success">
|
<span class="text-success">
|
||||||
<i class="fas fa-check-square"></i> Yes
|
<i class="fas fa-check-square"></i> {{ translate('serverSchedules', 'yes', data['lang']) }}
|
||||||
</span>
|
</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="text-danger">
|
<span class="text-danger">
|
||||||
<i class="far fa-times-square"></i> No
|
<i class="far fa-times-square"></i> {{ translate('serverSchedules', 'no', data['lang']) }}
|
||||||
</span>
|
</span>
|
||||||
{% end %}
|
{% end %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
<div class="modal fade" id="task_details_{{schedule.schedule_id}}" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
<div class="modal fade" id="task_details_{{schedule.schedule_id}}" tabindex="-1" role="dialog"
|
||||||
|
aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="exampleModalLabel">Task Details</h5>
|
<h5 class="modal-title" id="exampleModalLabel">{{ translate('serverSchedules', 'details',
|
||||||
|
data['lang']) }}</h5>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
@ -153,47 +174,62 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<ul style="list-style: none;">
|
<ul style="list-style: none;">
|
||||||
<li id="{{schedule.schedule_id}}" class="id" style="border-top: .1em solid gray;">
|
<li id="{{schedule.schedule_id}}" class="id" style="border-top: .1em solid gray;">
|
||||||
<h4>ID</h4>
|
<h4>{{ translate('serverSchedules', 'name', data['lang']) }}</h4>
|
||||||
<p>{{schedule.schedule_id}}</p>
|
<p>{{schedule.schedule_id}}</p>
|
||||||
</li>
|
</li>
|
||||||
<li id="{{schedule.action}}" class="action" style="border-top: .1em solid gray;">
|
<li id="{{schedule.action}}" class="action" style="border-top: .1em solid gray;">
|
||||||
<h4>Action</h4>
|
<h4>{{ translate('serverSchedules', 'action', data['lang']) }}</h4>
|
||||||
<p>{{schedule.action}}</p>
|
<p>{{schedule.action}}</p>
|
||||||
</li>
|
</li>
|
||||||
<li id="{{schedule.command}}" class="action" style="border-top: .1em solid gray;">
|
<li id="{{schedule.command}}" class="action" style="border-top: .1em solid gray;">
|
||||||
<h4>Command</h4>
|
<h4>{{ translate('serverSchedules', 'command', data['lang']) }}</h4>
|
||||||
<p>{{schedule.command}}</p>
|
<p>{{schedule.command}}</p>
|
||||||
</li>
|
</li>
|
||||||
<li id="{{schedule.interval}}" class="action" style="border-top: .1em solid gray;">
|
<li id="{{schedule.interval}}" class="action" style="border-top: .1em solid gray;">
|
||||||
{% if schedule.interval != '' %}
|
{% if schedule.interval != '' %}
|
||||||
<h4>Interval</h4>
|
<h4>{{ translate('serverSchedules', 'interval', data['lang']) }}</h4>
|
||||||
<p>Every {{schedule.interval}} {{schedule.interval_type}}</p>
|
<p>{{ translate('serverSchedules', 'every', data['lang']) }} {{schedule.interval}}
|
||||||
|
{{schedule.interval_type}}</p>
|
||||||
{% elif schedule.interval_type == 'reaction' %}
|
{% elif schedule.interval_type == 'reaction' %}
|
||||||
<h4>Interval</h4>
|
<h4>{{ translate('serverSchedules', 'interval', data['lang']) }}</h4>
|
||||||
<p>{{schedule.interval_type}}<br><br>child of ID: {{ schedule.parent }}</p>
|
<p>{{schedule.interval_type}}<br><br>{{ translate('serverSchedules', 'child',
|
||||||
|
data['lang']) }}: {{ schedule.parent }}</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h4>Interval</h4>
|
<h4>{{ translate('serverSchedules', 'interval', data['lang']) }}</h4>
|
||||||
<p>Cron String: {{schedule.cron_string}}</p>
|
<p>{{ translate('serverSchedules', 'cron', data['lang']) }}: {{schedule.cron_string}}
|
||||||
|
</p>
|
||||||
{% end %}
|
{% end %}
|
||||||
</li>
|
</li>
|
||||||
<li id="{{schedule.start_time}}" class="action" style="border-top: .1em solid gray;">
|
<li id="{{schedule.start_time}}" class="action" style="border-top: .1em solid gray;">
|
||||||
<h4>Start Time</h4>
|
<h4>{{ translate('serverSchedules', 'nextRun', data['lang']) }}</h4>
|
||||||
<p>{{schedule.start_time}}</p>
|
{% if schedule.next_run %}
|
||||||
|
<p>{{schedule.next_run}}</p>
|
||||||
|
{% else %}
|
||||||
|
<p>zzzzzzz</p>
|
||||||
|
{% end %}
|
||||||
</li>
|
</li>
|
||||||
<li id="{{schedule.enabled}}" class="action" style="border-top: .1em solid gray; border-bottom: .1em solid gray">
|
<li id="{{schedule.enabled}}" class="action"
|
||||||
<h4>Enabled</h4>
|
style="border-top: .1em solid gray; border-bottom: .1em solid gray">
|
||||||
<input type="checkbox" class="schedule-enabled-toggle" data-schedule-id="{{schedule.schedule_id}}" data-schedule-enabled="{{ 'true' if schedule.enabled else 'false' }}">
|
<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>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button onclick="window.location.href='/panel/edit_schedule?id={{ data['server_stats']['server_id']['server_id'] }}&sch_id={{schedule.schedule_id}}'" class="btn btn-info">
|
<button
|
||||||
<i class="fas fa-pencil-alt"></i> Edit
|
onclick="window.location.href='/panel/edit_schedule?id={{ data['server_stats']['server_id']['server_id'] }}&sch_id={{schedule.schedule_id}}'"
|
||||||
|
class="btn btn-info">
|
||||||
|
<i class="fas fa-pencil-alt"></i> {{ translate('serverSchedules', 'edit', data['lang'])
|
||||||
|
}}
|
||||||
</button>
|
</button>
|
||||||
<button data-sch={{ schedule.schedule_id }} class="btn btn-danger del_button">
|
<button data-sch={{ schedule.schedule_id }} class="btn btn-danger del_button">
|
||||||
<i class="fas fa-trash" aria-hidden="true"></i> Delete
|
<i class="fas fa-trash" aria-hidden="true"></i> {{ translate('serverSchedules',
|
||||||
|
'delete', data['lang']) }}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{
|
||||||
|
translate('serverSchedules', 'close', data['lang']) }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -215,12 +251,15 @@
|
|||||||
color: white !important;
|
color: white !important;
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-handle {
|
.toggle-handle {
|
||||||
background-color: white !important;
|
background-color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-on {
|
.toggle-on {
|
||||||
color: black !important;
|
color: black !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle {
|
.toggle {
|
||||||
height: 0px !important;
|
height: 0px !important;
|
||||||
}
|
}
|
||||||
@ -288,7 +327,7 @@
|
|||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
console.log('ready for JS!')
|
console.log('ready for JS!')
|
||||||
$('#schedule_table').DataTable({
|
$('#schedule_table').DataTable({
|
||||||
'order': [4, 'desc']
|
'order': [4, 'asc'],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -296,7 +335,7 @@
|
|||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
console.log('ready for JS!')
|
console.log('ready for JS!')
|
||||||
$('#mini_schedule_table').DataTable({
|
$('#mini_schedule_table').DataTable({
|
||||||
'order': [2, 'desc']
|
'order': [2, 'asc']
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
document.getElementById('mini_schedule_table_wrapper').hidden = true;
|
document.getElementById('mini_schedule_table_wrapper').hidden = true;
|
||||||
|
@ -32,14 +32,33 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="server_type">{{ translate('serverWizard', 'serverType', data['lang']) }}</label>
|
<label for="server_jar">{{ translate('serverWizard', 'serverType', data['lang'])
|
||||||
<select required class="form-control form-control-lg select-css" id="server_type" name="server_type"
|
}}</label>
|
||||||
onchange="serverTypeChange(this)">
|
{% if data['super_user'] %}
|
||||||
<option value="">{{ translate('serverWizard', 'selectType', data['lang']) }}</option>
|
<select style="width: 90%;" required class="form-control form-control-lg select-css" id="server_jar"
|
||||||
|
name="server_jar" onchange="serverJarChange(this)">
|
||||||
|
{% else %}
|
||||||
|
<select required class="form-control form-control-lg select-css" id="server_jar" name="server_jar"
|
||||||
|
onchange="serverJarChange(this)">
|
||||||
|
{% end %}
|
||||||
|
<option value="None">{{ translate('serverWizard', 'selectType', data['lang']) }}</option>
|
||||||
{% for s in data['server_types'] %}
|
{% for s in data['server_types'] %}
|
||||||
<option value="{{ s }}">{{ s.capitalize() }}</option>
|
<option value="{{ s }}">{{ s.capitalize() }}</option>
|
||||||
{% end %}
|
{% end %}
|
||||||
</select>
|
</select>
|
||||||
|
{% if data['super_user'] %}
|
||||||
|
<i onclick="refreshCache()" id="refresh-cache" class="refresh-class fas fa-sync"></i>
|
||||||
|
{% end %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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="server_type"
|
||||||
|
onchange="serverTypeChange(this)">
|
||||||
|
<option value="">{{ translate('serverWizard', 'selectServer', data['lang']) }}</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -414,6 +433,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
|
.refresh-class:hover {
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
.scroll {
|
.scroll {
|
||||||
max-height: 12em;
|
max-height: 12em;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@ -673,6 +696,25 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refreshCache() {
|
||||||
|
var token = getCookie("_xsrf")
|
||||||
|
document.getElementById("refresh-cache").classList.add("fa-spin")
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
headers: { 'X-XSRFToken': token },
|
||||||
|
url: '/ajax/jar_cache',
|
||||||
|
success: function () {
|
||||||
|
document.getElementById("refresh-cache").classList.remove("fa-sync");
|
||||||
|
document.getElementById("refresh-cache").classList.remove("fa-spin");
|
||||||
|
document.getElementById("refresh-cache").classList.add("fa-check");
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
location.reload();
|
||||||
|
}, 2000);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var text = '{% raw data["js_server_types"] %}';
|
var text = '{% raw data["js_server_types"] %}';
|
||||||
@ -682,11 +724,21 @@
|
|||||||
*/
|
*/
|
||||||
function serverTypeChange(selectObj) {
|
function serverTypeChange(selectObj) {
|
||||||
// get the index of the selected option
|
// get the index of the selected option
|
||||||
var idx = selectObj.selectedIndex;
|
var idx = document.getElementById('server_type').selectedIndex;
|
||||||
// get the value of the selected option
|
// get the value of the selected option
|
||||||
var which = selectObj.options[idx].value;
|
var cSelect = document.getElementById("server");
|
||||||
|
try {
|
||||||
|
var which = document.getElementById('server_type').options[idx].value;
|
||||||
|
} catch {
|
||||||
|
while (cSelect.options.length > 0) {
|
||||||
|
cSelect.remove(0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let server_type = which.split('|')[0];
|
||||||
|
let server = which.split('|')[1];
|
||||||
// use the selected option value to retrieve the list of items from the serverTypesLists array
|
// use the selected option value to retrieve the list of items from the serverTypesLists array
|
||||||
cList = serverTypesLists[which];
|
let cList = serverTypesLists[server_type];
|
||||||
// get the country select element via its known id
|
// get the country select element via its known id
|
||||||
var cSelect = document.getElementById("server");
|
var cSelect = document.getElementById("server");
|
||||||
// remove the current options from the country select
|
// remove the current options from the country select
|
||||||
@ -696,7 +748,7 @@
|
|||||||
}
|
}
|
||||||
var newOption;
|
var newOption;
|
||||||
// create new options ordered by ascending
|
// create new options ordered by ascending
|
||||||
cList.forEach(type => {
|
cList[server].forEach(type => {
|
||||||
newOption = document.createElement("option");
|
newOption = document.createElement("option");
|
||||||
newOption.value = which + "|" + type; // assumes option string and value are the same
|
newOption.value = which + "|" + type; // assumes option string and value are the same
|
||||||
newOption.text = type;
|
newOption.text = type;
|
||||||
@ -709,5 +761,47 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function serverJarChange(selectObj) {
|
||||||
|
let type_select = document.getElementById('server_jar')
|
||||||
|
let tidx = type_select.selectedIndex;
|
||||||
|
let val = type_select.options[tidx].value;
|
||||||
|
if (val == 'None') {
|
||||||
|
var jcSelect = document.getElementById("server_type");
|
||||||
|
while (jcSelect.options.length > 0) {
|
||||||
|
jcSelect.remove(0);
|
||||||
|
}
|
||||||
|
serverTypeChange(selectObj);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// get the index of the selected option
|
||||||
|
var jidx = selectObj.selectedIndex;
|
||||||
|
// get the value of the selected option
|
||||||
|
var jwhich = selectObj.options[jidx].value;
|
||||||
|
// use the selected option value to retrieve the list of items from the serverTypesLists array
|
||||||
|
jcList = Object.keys(serverTypesLists[jwhich]);
|
||||||
|
// get the country select element via its known id
|
||||||
|
var jcSelect = document.getElementById("server_type");
|
||||||
|
// remove the current options from the country select
|
||||||
|
var jlen = jcSelect.options.length;
|
||||||
|
while (jcSelect.options.length > 0) {
|
||||||
|
jcSelect.remove(0);
|
||||||
|
}
|
||||||
|
var jnewOption;
|
||||||
|
// create new options ordered by ascending
|
||||||
|
jcList.forEach(type => {
|
||||||
|
jnewOption = document.createElement("option");
|
||||||
|
jnewOption.value = jwhich + "|" + type; // assumes option string and value are the same
|
||||||
|
jnewOption.text = type;
|
||||||
|
// add the new option
|
||||||
|
try {
|
||||||
|
jcSelect.add(jnewOption); // this will fail in DOM browsers but is needed for IE
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
jcSelect.appendChild(jnewOption);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
serverTypeChange(selectObj);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% end %}
|
{% end %}
|
16
app/migrations/20220804_schedule_next_run.py
Normal file
16
app/migrations/20220804_schedule_next_run.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Generated by database migrator
|
||||||
|
import peewee
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(migrator, database, **kwargs):
|
||||||
|
migrator.add_columns("schedules", next_run=peewee.CharField(default=""))
|
||||||
|
"""
|
||||||
|
Write your migrations here.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def rollback(migrator, database, **kwargs):
|
||||||
|
migrator.drop_columns("schedules", ["next_run"])
|
||||||
|
"""
|
||||||
|
Write your rollback migrations here.
|
||||||
|
"""
|
17
app/migrations/20220805_schedule_rename_comment.py
Normal file
17
app/migrations/20220805_schedule_rename_comment.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Generated by database migrator
|
||||||
|
import peewee
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(migrator, database, **kwargs):
|
||||||
|
migrator.rename_column("schedules", "comment", "name")
|
||||||
|
|
||||||
|
"""
|
||||||
|
Write your migrations here.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def rollback(migrator, database, **kwargs):
|
||||||
|
migrator.rename_column("schedules", "name", "comment")
|
||||||
|
"""
|
||||||
|
Write your rollback migrations here.
|
||||||
|
"""
|
@ -48,7 +48,7 @@
|
|||||||
"subscriptionLevel": "Level",
|
"subscriptionLevel": "Level",
|
||||||
"supportTeam": "Support and Documentation Team",
|
"supportTeam": "Support and Documentation Team",
|
||||||
"thankYou": "THANK YOU",
|
"thankYou": "THANK YOU",
|
||||||
"translationDesc": "to our community who translate!",
|
"translationDesc": "to our community who translate! [ Active = 🟢 Inactive/Retired = ⚪ ]",
|
||||||
"translationName": "Name",
|
"translationName": "Name",
|
||||||
"translationTitle": "Language Translation",
|
"translationTitle": "Language Translation",
|
||||||
"translator": "Translators"
|
"translator": "Translators"
|
||||||
@ -392,6 +392,7 @@
|
|||||||
},
|
},
|
||||||
"serverScheduleConfig": {
|
"serverScheduleConfig": {
|
||||||
"backup": "Backup Server",
|
"backup": "Backup Server",
|
||||||
|
"select": "Basic / Cron / Chain Reaction Select",
|
||||||
"basic": "Basic",
|
"basic": "Basic",
|
||||||
"children": "Linked Child Tasks: ",
|
"children": "Linked Child Tasks: ",
|
||||||
"command": "Command",
|
"command": "Command",
|
||||||
@ -418,7 +419,24 @@
|
|||||||
"time-explain": "What time do you want your schedule to execute?"
|
"time-explain": "What time do you want your schedule to execute?"
|
||||||
},
|
},
|
||||||
"serverSchedules": {
|
"serverSchedules": {
|
||||||
|
"scheduledTasks": "Scheduled Tasks",
|
||||||
|
"create": "Create New Schedule",
|
||||||
|
"name": "Name",
|
||||||
|
"action": "Action",
|
||||||
|
"command": "Command",
|
||||||
|
"interval": "Interval",
|
||||||
|
"nextRun": "Next Run",
|
||||||
|
"enabled": "Enabled",
|
||||||
|
"edit": "Edit",
|
||||||
|
"every": "Every",
|
||||||
|
"yes": "Yes",
|
||||||
|
"no": "No",
|
||||||
|
"cron": "Crong String",
|
||||||
|
"details": "Schedule Details",
|
||||||
|
"child": "Child of schedule with ID ",
|
||||||
"areYouSure": "Delete Scheduled Task?",
|
"areYouSure": "Delete Scheduled Task?",
|
||||||
|
"close": "Close",
|
||||||
|
"delete": "Delete",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"cannotSee": "Not seeing everything?",
|
"cannotSee": "Not seeing everything?",
|
||||||
"cannotSeeOnMobile": "Try clicking on a scheduled task for full details.",
|
"cannotSeeOnMobile": "Try clicking on a scheduled task for full details.",
|
||||||
@ -480,7 +498,8 @@
|
|||||||
"save": "Save",
|
"save": "Save",
|
||||||
"selectRole": "Select Role(s)",
|
"selectRole": "Select Role(s)",
|
||||||
"selectRoot": "Select Archive Root Dir",
|
"selectRoot": "Select Archive Root Dir",
|
||||||
"selectType": "Select a Type",
|
"selectType": "Server Type (Vanilla, Servers, Modded, etc.)",
|
||||||
|
"selectServer": "Select a Server",
|
||||||
"selectVersion": "Select a Version",
|
"selectVersion": "Select a Version",
|
||||||
"selectZipDir": "Select the directory in the archive you want us to unzip files from",
|
"selectZipDir": "Select the directory in the archive you want us to unzip files from",
|
||||||
"serverJar": "Server Executable File",
|
"serverJar": "Server Executable File",
|
||||||
@ -488,6 +507,7 @@
|
|||||||
"serverPath": "Server Path",
|
"serverPath": "Server Path",
|
||||||
"serverPort": "Server Port",
|
"serverPort": "Server Port",
|
||||||
"serverType": "Server Type",
|
"serverType": "Server Type",
|
||||||
|
"serverSelect": "Server Select",
|
||||||
"serverVersion": "Server Version",
|
"serverVersion": "Server Version",
|
||||||
"sizeInGB": "Size in GB",
|
"sizeInGB": "Size in GB",
|
||||||
"zipPath": "Server Path"
|
"zipPath": "Server Path"
|
||||||
|
16
main.py
16
main.py
@ -7,8 +7,9 @@ import argparse
|
|||||||
import logging.config
|
import logging.config
|
||||||
import signal
|
import signal
|
||||||
import peewee
|
import peewee
|
||||||
from app.classes.shared.file_helpers import FileHelpers
|
from packaging import version as pkg_version
|
||||||
|
|
||||||
|
from app.classes.shared.file_helpers import FileHelpers
|
||||||
from app.classes.shared.import3 import Import3
|
from app.classes.shared.import3 import Import3
|
||||||
from app.classes.shared.console import Console
|
from app.classes.shared.console import Console
|
||||||
from app.classes.shared.helpers import Helpers
|
from app.classes.shared.helpers import Helpers
|
||||||
@ -225,6 +226,19 @@ if __name__ == "__main__":
|
|||||||
controller_setup_thread.join()
|
controller_setup_thread.join()
|
||||||
|
|
||||||
Console.info("Crafty has fully started and is now ready for use!")
|
Console.info("Crafty has fully started and is now ready for use!")
|
||||||
|
|
||||||
|
# Check if new version available
|
||||||
|
remote_ver = helper.check_remote_version()
|
||||||
|
if remote_ver:
|
||||||
|
notice = f"""
|
||||||
|
A new version of Crafty is available!
|
||||||
|
{'/' * 37}
|
||||||
|
New version available: {remote_ver}
|
||||||
|
Current version: {pkg_version.parse(helper.get_version_string())}
|
||||||
|
{'/' * 37}
|
||||||
|
"""
|
||||||
|
Console.yellow(notice)
|
||||||
|
|
||||||
crafty_prompt.prompt = f"Crafty Controller v{helper.get_version_string()} > "
|
crafty_prompt.prompt = f"Crafty Controller v{helper.get_version_string()} > "
|
||||||
try:
|
try:
|
||||||
logger.info("Removing old temp dirs")
|
logger.info("Removing old temp dirs")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user