Merge branch 'dev' into enhancement/add-storage-to-dash

This commit is contained in:
Zedifus 2023-02-17 00:00:00 +00:00
commit 5dea17a7cb
114 changed files with 17483 additions and 78878 deletions

View File

@ -3,16 +3,21 @@
### New features
- Add better feedback for uploads with a progress bar ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/546))
- Add ignored exit codes for crash detection ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/553))
- Allow users to change the directory where Crafty Stores Servers ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/539)) <br>
*(Only for non-docker, docker users should change host volume mount)*
### Bug fixes
- Fix exception related to page data on server start ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/544))
- Fix logical issue with uploading dynamic files ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/555))
- Fix backups failing by correctly using tz objects ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/556))
- Bump Cryptography/pyOpenSSL for CVE-2023-23931 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/554))
### Tweaks
- Cleanup authentication helpers ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/545))
- Optimize file upload progress WS ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/546))
- Truncate sidebar servers to a max of 10 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/552))
- Upgrade to FA 6. Add Translations ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/549))
### Lang
- Add additional translations to backups page strings ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/543))
- Add additional missing translations ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/549))
<br><br>
## --- [4.0.20] - 2023/01/29

View File

@ -195,3 +195,14 @@ class ManagementController:
def del_excluded_backup_dir(self, server_id: int, dir_to_del: str):
self.management_helper.del_excluded_backup_dir(server_id, dir_to_del)
# **********************************************************************************
# Crafty Methods
# **********************************************************************************
@staticmethod
def get_master_server_dir():
return HelpersManagement.get_master_server_dir()
@staticmethod
def set_master_server_dir(server_dir):
HelpersManagement.set_master_server_dir(server_dir)

View File

@ -102,6 +102,7 @@ class ServersController(metaclass=Singleton):
server_obj.server_id
)
server_instance.update_server_instance()
return ret
def get_history_stats(self, server_id, days):
@ -163,10 +164,9 @@ class ServersController(metaclass=Singleton):
return server["server_obj"]
logger.warning(f"Unable to find server object for server id {server_id}")
raise Exception(f"Unable to find server object for server id {server_id}")
raise ValueError(f"Unable to find server object for server id {server_id}")
def init_all_servers(self):
servers = self.get_all_defined_servers()
self.failed_servers = []
@ -227,7 +227,6 @@ class ServersController(metaclass=Singleton):
)
def check_server_loaded(self, server_id_to_check: int):
logger.info(f"Checking to see if we already registered {server_id_to_check}")
for server in self.servers_list:

View File

@ -19,7 +19,6 @@ class Server:
self.description = data.get("description")
# print(self.description)
if isinstance(self.description, dict):
# cat server
if "translate" in self.description:
self.description = self.description["translate"]
@ -124,7 +123,7 @@ def ping(ip, port):
try:
k = sock.recv(1)
if not k:
raise Exception()
raise ValueError()
except:
return 0
k = k[0]

View File

@ -104,7 +104,6 @@ class ServerJars:
logger.error(f"Unable to update serverjars.com cache file: {e}")
def refresh_cache(self):
cache_file = self.helper.serverjar_cache
cache_old = self.helper.is_file_older_than_x_days(cache_file)

View File

@ -211,7 +211,6 @@ class Stats:
@staticmethod
def get_world_size(server_path):
total_size = 0
total_size = Helpers.get_dir_size(server_path)
@ -221,7 +220,6 @@ class Stats:
return level_total_size
def get_server_players(self, server_id):
server = HelperServers.get_server_data_by_id(server_id)
logger.info(f"Getting players for server {server}")
@ -295,7 +293,6 @@ class Stats:
@staticmethod
def parse_server_raknet_ping(ping_obj: object):
try:
server_icon = base64.encodebytes(ping_obj["icon"])
except Exception as e:

View File

@ -15,6 +15,7 @@ from app.classes.shared.permission_helper import PermissionHelper
logger = logging.getLogger(__name__)
# **********************************************************************************
# User_Crafty Class
# **********************************************************************************

View File

@ -20,6 +20,7 @@ from app.classes.shared.main_models import DatabaseShortcuts
logger = logging.getLogger(__name__)
# **********************************************************************************
# Audit_Log Class
# **********************************************************************************
@ -46,6 +47,7 @@ class CraftySettings(BaseModel):
cookie_secret = CharField(default="")
login_photo = CharField(default="login_1.jpg")
login_opacity = IntegerField(default=100)
master_server_dir = CharField(default="")
class Meta:
table_name = "crafty_settings"
@ -271,6 +273,19 @@ class HelpersManagement:
CraftySettings.id == 1
).execute()
@staticmethod
def get_master_server_dir():
settings = CraftySettings.select(CraftySettings.master_server_dir).where(
CraftySettings.id == 1
)
return settings[0].master_server_dir
@staticmethod
def set_master_server_dir(server_dir):
CraftySettings.update({CraftySettings.master_server_dir: server_dir}).where(
CraftySettings.id == 1
).execute()
# **********************************************************************************
# Schedules Methods
# **********************************************************************************

View File

@ -15,6 +15,7 @@ from app.classes.shared.helpers import Helpers
logger = logging.getLogger(__name__)
# **********************************************************************************
# Roles Class
# **********************************************************************************

View File

@ -16,6 +16,7 @@ from app.classes.shared.permission_helper import PermissionHelper
logger = logging.getLogger(__name__)
# **********************************************************************************
# Role Servers Class
# **********************************************************************************

View File

@ -29,6 +29,7 @@ logger = logging.getLogger(__name__)
peewee_logger = logging.getLogger("peewee")
peewee_logger.setLevel(logging.INFO)
# **********************************************************************************
# Servers Stats Class
# **********************************************************************************

View File

@ -15,6 +15,7 @@ from app.classes.models.base_model import BaseModel
logger = logging.getLogger(__name__)
# **********************************************************************************
# Servers Model
# **********************************************************************************

View File

@ -21,6 +21,7 @@ from app.classes.models.roles import Roles, HelperRoles
logger = logging.getLogger(__name__)
# **********************************************************************************
# Users Class
# **********************************************************************************
@ -58,6 +59,7 @@ PUBLIC_USER_ATTRS: t.Final = [
"lang", # maybe remove?
]
# **********************************************************************************
# API Keys Class
# **********************************************************************************

View File

@ -76,7 +76,7 @@ class Authentication:
output = self.check(token)
if output is None:
raise Exception("Invalid token")
raise ValueError("Invalid token")
return output
def check_bool(self, token) -> bool:

View File

@ -58,7 +58,6 @@ class MainPrompt(cmd.Cmd):
Console.info("Unknown migration command")
def do_set_passwd(self, line):
try:
username = str(line).lower()
# If no user is found it returns None

View File

@ -94,7 +94,7 @@ class Helpers:
try:
# Get tags from Gitlab, select the latest and parse the semver
response = get(
"https://gitlab.com/api/v4/projects/20430749/repository/tags"
"https://gitlab.com/api/v4/projects/20430749/repository/tags", timeout=1
)
if response.status_code == 200:
remote_version = pkg_version.parse(json.loads(response.text)[0]["name"])
@ -131,7 +131,7 @@ class Helpers:
try:
# Get minecraft server download page
# (hopefully the don't change the structure)
download_page = get(url, headers=headers)
download_page = get(url, headers=headers, timeout=1)
# Search for our string targets
win_download_url = re.search(target_win, download_page.text).group(0)
@ -281,7 +281,7 @@ class Helpers:
@staticmethod
def check_port(server_port):
try:
ip = get("https://api.ipify.org").content.decode("utf8")
ip = get("https://api.ipify.org", timeout=1).content.decode("utf8")
except:
ip = "google.com"
a_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -444,12 +444,20 @@ class Helpers:
return mounts
@staticmethod
def is_subdir(server_path, root_dir):
def is_subdir(self, server_path, root_dir):
server_path = os.path.realpath(server_path)
root_dir = os.path.realpath(root_dir)
relative = os.path.relpath(server_path, root_dir)
if self.is_os_windows():
try:
relative = os.path.relpath(server_path, root_dir)
except:
# Windows will crash out if two paths are on different
# Drives We can happily return false if this is the case.
# Since two different drives will not be relative to eachother.
return False
else:
relative = os.path.relpath(server_path, root_dir)
if relative.startswith(os.pardir):
return False
@ -605,7 +613,6 @@ class Helpers:
# open our file
with open(file_name, "r", encoding="utf-8") as f:
# seek
f.seek(0, 2)
@ -761,7 +768,7 @@ class Helpers:
use_ssl=True,
) # + "?d=404"
try:
if requests.head(url).status_code != 404:
if requests.head(url, timeout=1).status_code != 404:
profile_url = url
except Exception as e:
logger.debug(f"Could not pull resource from Gravatar with error {e}")
@ -770,7 +777,6 @@ class Helpers:
@staticmethod
def get_file_contents(path: str, lines=100):
contents = ""
if os.path.exists(path) and os.path.isfile(path):
@ -791,12 +797,10 @@ class Helpers:
return False
def create_session_file(self, ignore=False):
if ignore and os.path.exists(self.session_file):
os.remove(self.session_file)
if os.path.exists(self.session_file):
file_data = self.get_file_contents(self.session_file)
try:
data = json.loads(file_data)
@ -896,15 +900,16 @@ class Helpers:
try:
os.makedirs(path)
logger.debug(f"Created Directory : {path}")
return True
# directory already exists - non-blocking error
except FileExistsError:
pass
return True
except PermissionError as e:
logger.critical(f"Check generated exception due to permssion error: {e}")
return False
def create_self_signed_cert(self, cert_dir=None):
if cert_dir is None:
cert_dir = os.path.join(self.config_dir, "web", "certs")
@ -986,6 +991,15 @@ class Helpers:
def is_os_windows():
return os.name == "nt"
@staticmethod
def is_env_docker():
path = "/proc/self/cgroup"
return (
os.path.exists("/.dockerenv")
or os.path.isfile(path)
and any("docker" in line for line in open(path, encoding="utf-8"))
)
@staticmethod
def wtol_path(w_path):
l_path = w_path.replace("\\", "/")
@ -1035,9 +1049,9 @@ class Helpers:
if filename not in self.ignored_names:
output += f"""<li id="{dpath}li" class="tree-item"
data-path="{dpath}">
\n<div id="{dpath}" data-path="{dpath}" data-name="{filename}"
\n<div id="{dpath}" data-path="{dpath}" data-name="{filename}"
class="tree-caret tree-ctx-item tree-folder">
<span id="{dpath}span" class="files-tree-title" data-path="{dpath}"
<span id="{dpath}span" class="files-tree-title" data-path="{dpath}"
data-name="{filename}" onclick="getDirView(event)">
<i style="color: var(--info);" class="far fa-folder"></i>
<i style="color: var(--info);" class="far fa-folder-open"></i>
@ -1056,7 +1070,6 @@ class Helpers:
return output
def generate_dir(self, folder, output=""):
dir_list = []
unsorted_files = []
file_list = os.listdir(folder)
@ -1077,9 +1090,9 @@ class Helpers:
if filename not in self.ignored_names:
output += f"""<li id="{dpath}li" class="tree-item"
data-path="{dpath}">
\n<div id="{dpath}" data-path="{dpath}" data-name="{filename}"
\n<div id="{dpath}" data-path="{dpath}" data-name="{filename}"
class="tree-caret tree-ctx-item tree-folder">
<span id="{dpath}span" class="files-tree-title" data-path="{dpath}"
<span id="{dpath}span" class="files-tree-title" data-path="{dpath}"
data-name="{filename}" onclick="getDirView(event)">
<i style="color: var(--info);" class="far fa-folder"></i>
<i style="color: var(--info);" class="far fa-folder-open"></i>

View File

@ -226,7 +226,6 @@ class ImportHelpers:
download_thread.start()
def download_threaded_bedrock_server(self, path, new_id):
# downloads zip from remote url
try:
bedrock_url = Helpers.get_latest_bedrock_url()

View File

@ -10,7 +10,6 @@ class Install:
)
def do_install(self):
# are we in a venv?
if not self.is_venv():
print("Crafty Requires a venv to install")

View File

@ -6,6 +6,7 @@ import platform
import shutil
import time
import logging
import threading
from peewee import DoesNotExist
# TZLocal is set as a hidden import on win pipeline
@ -347,7 +348,7 @@ class Controller:
elif root_create_data["create_type"] == "import_zip":
# TODO: Copy files from the zip file to the new server directory
server_file = create_data["jarfile"]
raise Exception("Not yet implemented")
raise NotImplementedError("Not yet implemented")
_create_server_properties_if_needed(
create_data["server_properties_port"],
)
@ -379,7 +380,7 @@ class Controller:
logger.error(f"Server import failed with error: {ex}")
elif root_create_data["create_type"] == "import_zip":
# TODO: Copy files from the zip file to the new server directory
raise Exception("Not yet implemented")
raise NotImplementedError("Not yet implemented")
_create_server_properties_if_needed(0, True)
@ -401,7 +402,7 @@ class Controller:
logger.error(f"Server import failed with error: {ex}")
elif root_create_data["create_type"] == "import_zip":
# TODO: Copy files from the zip file to the new server directory
raise Exception("Not yet implemented")
raise NotImplementedError("Not yet implemented")
_create_server_properties_if_needed(0, True)
@ -941,7 +942,6 @@ class Controller:
def remove_server(self, server_id, files):
counter = 0
for server in self.servers.servers_list:
# if this is the droid... im mean server we are looking for...
if str(server["server_id"]) == str(server_id):
server_data = self.servers.get_server_data(server_id)
@ -1003,3 +1003,122 @@ class Controller:
@staticmethod
def clear_support_status():
HelperUsers.clear_support_status()
def set_master_server_dir(self, server_dir):
# This method should only be used on a first run basis if the server dir is ""
self.helper.servers_dir = server_dir
HelpersManagement.set_master_server_dir(server_dir)
def update_master_server_dir(self, server_dir, user_id):
move_thread = threading.Thread(
name="dir_move",
target=self.t_update_master_server_dir,
daemon=True,
args=(
server_dir,
user_id,
),
)
move_thread.start()
def t_update_master_server_dir(self, server_dir, user_id):
server_dir = self.helper.wtol_path(server_dir)
self.helper.websocket_helper.broadcast_page(
"/panel/panel_config", "move_status", "Checking dir"
)
current_master = self.helper.wtol_path(
HelpersManagement.get_master_server_dir()
)
if current_master == server_dir:
logger.info(
"Admin tried to change server dir to current server dir. Canceling..."
)
self.helper.websocket_helper.broadcast_page(
"/panel/panel_config",
"move_status",
"done",
)
return
if self.helper.is_subdir(server_dir, current_master):
logger.info(
"Admin tried to change server dir to be inside a sub directory of the"
" current server dir. This will result in a copy loop."
)
self.helper.websocket_helper.broadcast_page(
"/panel/panel_config",
"move_status",
"done",
)
return
self.helper.websocket_helper.broadcast_page(
"/panel/panel_config", "move_status", "Checking permissions"
)
if not self.helper.ensure_dir_exists(os.path.join(server_dir, "servers")):
self.helper.websocket_helper.broadcast_user(
user_id,
"send_start_error",
{
"error": "Crafty failed to move server dir. "
"It seems Crafty lacks permission to write to "
"the new directory."
},
)
return
# set the cached serve dir
self.helper.servers_dir = server_dir
# set DB server dir
HelpersManagement.set_master_server_dir(server_dir)
servers = self.servers.get_all_defined_servers()
# move the servers
for server in servers:
server_path = server.get("path")
new_server_path = os.path.join(
server_dir, "servers", server.get("server_uuid")
)
if os.path.isdir(server_path):
self.helper.websocket_helper.broadcast_page(
"/panel/panel_config",
"move_status",
f"Moving {server.get('server_name')}",
)
try:
self.file_helper.move_dir(
server_path,
new_server_path,
)
except FileExistsError as e:
logger.error(f"Failed to move server with error: {e}")
server_obj = self.servers.get_server_obj(server.get("server_id"))
# reset executable path
if current_master in server["executable"]:
server_obj.executable = str(server["executable"]).replace(
current_master, server_dir
)
# reset run command path
if current_master in server["execution_command"]:
server_obj.execution_command = str(server["execution_command"]).replace(
current_master, server_dir
)
# reset log path
if current_master in server["log_path"]:
server_obj.log_path = str(server["log_path"]).replace(
current_master, server_dir
)
server_obj.path = new_server_path
failed = False
for s in self.servers.failed_servers:
if int(s["server_id"]) == int(server.get("server_id")):
failed = True
if not failed:
self.servers.update_server(server_obj)
else:
self.servers.update_unloaded_server(server_obj)
self.servers.init_all_servers()
self.helper.websocket_helper.broadcast_page(
"/panel/panel_config",
"move_status",
"done",
)

View File

@ -158,6 +158,8 @@ class ServerInstance:
self.jar_update_url = server_data.executable_update_url
self.name = server_data.server_name
self.server_object = server_data
self.stats_helper.select_database()
self.reload_server_settings()
def reload_server_settings(self):
server_data = HelperServers.get_server_data_by_id(self.server_id)
@ -590,7 +592,6 @@ class ServerInstance:
# We need to grab the exact forge version number.
# We know we can find it here in the run.sh/bat script.
try:
# Getting the forge version from the executable command
version = re.findall(
r"forge-([0-9\.]+)((?:)|(?:-([0-9\.]+)-[a-zA-Z]+)).jar",
@ -850,7 +851,6 @@ class ServerInstance:
return True
def crash_detected(self, name):
# clear the old scheduled watcher task
self.server_scheduler.remove_job(f"c_{self.server_id}")
# remove the stats polling job since server is stopped
@ -912,7 +912,6 @@ class ServerInstance:
return self.process.pid if self.process is not None else None
def detect_crash(self):
logger.info(f"Detecting possible crash for server: {self.name} ")
running = self.check_running()
@ -935,7 +934,6 @@ class ServerInstance:
self.stats_helper.sever_crashed()
# if we haven't tried to restart more 3 or more times
if self.restart_count <= 3:
# start the server if needed
server_restarted = self.crash_detected(self.name)
@ -1461,7 +1459,6 @@ class ServerInstance:
Console.critical("Can't broadcast server status to websocket")
def get_servers_stats(self):
server_stats = {}
logger.info("Getting Stats for Server " + self.name + " ...")
@ -1548,7 +1545,6 @@ class ServerInstance:
return server_stats
def get_server_players(self):
server = HelperServers.get_server_data_by_id(self.server_id)
logger.info(f"Getting players for server {server}")
@ -1569,7 +1565,6 @@ class ServerInstance:
return []
def get_raw_server_stats(self, server_id):
try:
server = HelperServers.get_server_obj(server_id)
except:
@ -1718,7 +1713,6 @@ class ServerInstance:
return server_stats
def record_server_stats(self):
server_stats = self.get_servers_stats()
self.stats_helper.insert_server_stats(server_stats)

View File

@ -673,7 +673,6 @@ class TasksManager:
host_stats = HelpersManagement.get_latest_hosts_stats()
while True:
if host_stats.get(
"cpu_usage"
) != HelpersManagement.get_latest_hosts_stats().get(

View File

@ -575,6 +575,31 @@ class AjaxHandler(BaseHandler):
self.controller.server_jars.manual_refresh_cache()
return
elif page == "update_server_dir":
for server in self.controller.servers.get_all_servers_stats():
if server["stats"]["running"]:
self.helper.websocket_helper.broadcast_user(
exec_user["user_id"],
"send_start_error",
{
"error": "You must stop all servers before "
"starting a storage migration."
},
)
return
if not superuser:
self.redirect("/panel/error?error=Not a super user")
return
if self.helper.is_env_docker():
self.redirect(
"/panel/error?error=This feature is not"
" supported on docker environments"
)
return
new_dir = urllib.parse.unquote(self.get_argument("server_dir"))
self.controller.update_master_server_dir(new_dir, exec_user["user_id"])
return
@tornado.web.authenticated
def delete(self, page):
api_key, _, exec_user = self.current_user

View File

@ -6,7 +6,6 @@ logger = logging.getLogger(__name__)
class DefaultHandler(BaseHandler):
# Override prepare() instead of get() to cover all possible HTTP methods.
def prepare(self, page=None): # pylint: disable=arguments-differ
if page is not None:

View File

@ -290,6 +290,7 @@ class PanelHandler(BaseHandler):
page_data: t.Dict[str, t.Any] = {
# todo: make this actually pull and compare version data
"update_available": self.helper.update_available,
"docker": self.helper.is_env_docker(),
"background": self.controller.cached_login,
"login_opacity": self.controller.management.get_login_opacity(),
"serverTZ": tz,
@ -847,6 +848,9 @@ class PanelHandler(BaseHandler):
page_data["auth-servers"] = auth_servers
page_data["role-servers"] = auth_role_servers
page_data["user-roles"] = user_roles
page_data[
"servers_dir"
] = self.controller.management.get_master_server_dir()
page_data["users"] = self.controller.users.user_query(exec_user["user_id"])
page_data["roles"] = self.controller.users.user_role_query(

View File

@ -10,7 +10,6 @@ logger = logging.getLogger(__name__)
class PublicHandler(BaseHandler):
def set_current_user(self, user_id: str = None):
expire_days = self.helper.get_setting("cookie_expire")
# if helper comes back with false
@ -29,7 +28,6 @@ class PublicHandler(BaseHandler):
# self.clear_cookie("user_data")
def get(self, page=None):
error = bleach.clean(self.get_argument("error", "Invalid Login!"))
error_msg = bleach.clean(self.get_argument("error_msg", ""))
@ -81,7 +79,6 @@ class PublicHandler(BaseHandler):
)
def post(self, page=None):
error = bleach.clean(self.get_argument("error", "Invalid Login!"))
error_msg = bleach.clean(self.get_argument("error_msg", ""))
@ -96,7 +93,6 @@ class PublicHandler(BaseHandler):
page_data["query"] = self.request.query
if page == "login":
next_page = "/login"
if self.request.query:
next_page = "/login?" + self.request.query

View File

@ -26,7 +26,6 @@ login_schema = {
class ApiAuthLoginHandler(BaseApiHandler):
def post(self):
try:
data = json.loads(self.request.body)
except json.decoder.JSONDecodeError as e:

View File

@ -631,7 +631,6 @@ class ApiServersIndexHandler(BaseApiHandler):
self.finish_json(200, {"status": "ok", "data": auth_data[0]})
def post(self):
auth_data = self.authenticate_user()
if not auth_data:
return

View File

@ -552,7 +552,6 @@ class ServerHandler(BaseHandler):
self.get_remote_ip(),
)
else:
new_server_id = self.controller.create_bedrock_server(
server_name,
exec_user["user_id"],

View File

@ -59,7 +59,6 @@ class Webserver:
@staticmethod
def log_function(handler):
info = {
"Status_Code": handler.get_status(),
"Method": handler.request.method,
@ -103,7 +102,6 @@ class Webserver:
logger.debug("Applied asyncio patch")
def run_tornado(self):
# let's verify we have an SSL cert
self.helper.create_self_signed_cert()

View File

@ -18,7 +18,6 @@ logger = logging.getLogger(__name__)
@tornado.web.stream_request_body
class UploadHandler(BaseHandler):
# noinspection PyAttributeOutsideInit
def initialize(
self,
@ -173,7 +172,6 @@ class UploadHandler(BaseHandler):
if not self.request.headers.get("X-Content-Type", None).startswith(
"image/"
):
return self.finish_json(
415,
{

View File

@ -79,7 +79,6 @@ class SocketHandler(tornado.websocket.WebSocketHandler):
# pylint: disable=arguments-renamed
@staticmethod
def on_message(raw_message):
logger.debug(f"Got message from WebSocket connection {raw_message}")
message = json.loads(raw_message)
logger.debug(f"Event Type: {message['event']}, Data: {message['data']}")

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,15 +0,0 @@
/*!
* Font Awesome Pro 5.14.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license (Commercial License)
*/
@font-face {
font-family: 'Font Awesome 5 Brands';
font-style: normal;
font-weight: 400;
font-display: block;
src: url("../webfonts/fa-brands-400.eot");
src: url("../webfonts/fa-brands-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.woff") format("woff"), url("../webfonts/fa-brands-400.ttf") format("truetype"), url("../webfonts/fa-brands-400.svg#fontawesome") format("svg"); }
.fab {
font-family: 'Font Awesome 5 Brands';
font-weight: 400; }

View File

@ -1,5 +0,0 @@
/*!
* Font Awesome Pro 5.14.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license (Commercial License)
*/
@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands";font-weight:400}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,15 +0,0 @@
/*!
* Font Awesome Pro 5.14.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license (Commercial License)
*/
@font-face {
font-family: 'Font Awesome 5 Pro';
font-style: normal;
font-weight: 300;
font-display: block;
src: url("../webfonts/fa-light-300.eot");
src: url("../webfonts/fa-light-300.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-light-300.woff2") format("woff2"), url("../webfonts/fa-light-300.woff") format("woff"), url("../webfonts/fa-light-300.ttf") format("truetype"), url("../webfonts/fa-light-300.svg#fontawesome") format("svg"); }
.fal {
font-family: 'Font Awesome 5 Pro';
font-weight: 300; }

View File

@ -1,5 +0,0 @@
/*!
* Font Awesome Pro 5.14.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license (Commercial License)
*/
@font-face{font-family:"Font Awesome 5 Pro";font-style:normal;font-weight:300;font-display:block;src:url(../webfonts/fa-light-300.eot);src:url(../webfonts/fa-light-300.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-light-300.woff2) format("woff2"),url(../webfonts/fa-light-300.woff) format("woff"),url(../webfonts/fa-light-300.ttf) format("truetype"),url(../webfonts/fa-light-300.svg#fontawesome) format("svg")}.fal{font-family:"Font Awesome 5 Pro";font-weight:300}

View File

@ -1,15 +0,0 @@
/*!
* Font Awesome Pro 5.14.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license (Commercial License)
*/
@font-face {
font-family: 'Font Awesome 5 Pro';
font-style: normal;
font-weight: 400;
font-display: block;
src: url("../webfonts/fa-regular-400.eot");
src: url("../webfonts/fa-regular-400.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.woff") format("woff"), url("../webfonts/fa-regular-400.ttf") format("truetype"), url("../webfonts/fa-regular-400.svg#fontawesome") format("svg"); }
.far {
font-family: 'Font Awesome 5 Pro';
font-weight: 400; }

View File

@ -1,5 +0,0 @@
/*!
* Font Awesome Pro 5.14.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license (Commercial License)
*/
@font-face{font-family:"Font Awesome 5 Pro";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:"Font Awesome 5 Pro";font-weight:400}

View File

@ -1,16 +0,0 @@
/*!
* Font Awesome Pro 5.14.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license (Commercial License)
*/
@font-face {
font-family: 'Font Awesome 5 Pro';
font-style: normal;
font-weight: 900;
font-display: block;
src: url("../webfonts/fa-solid-900.eot");
src: url("../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.woff") format("woff"), url("../webfonts/fa-solid-900.ttf") format("truetype"), url("../webfonts/fa-solid-900.svg#fontawesome") format("svg"); }
.fa,
.fas {
font-family: 'Font Awesome 5 Pro';
font-weight: 900; }

View File

@ -1,5 +0,0 @@
/*!
* Font Awesome Pro 5.14.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license (Commercial License)
*/
@font-face{font-family:"Font Awesome 5 Pro";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Pro";font-weight:900}

View File

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 713 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 2.5 MiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 2.3 MiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 2.1 MiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 1.7 MiB

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
:root, :host {
--fa-style-family-classic: 'Font Awesome 6 Free';
--fa-font-regular: normal 400 1em/1 'Font Awesome 6 Free'; }
@font-face {
font-family: 'Font Awesome 6 Free';
font-style: normal;
font-weight: 400;
font-display: block;
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }
.far,
.fa-regular {
font-weight: 400; }

View File

@ -0,0 +1,6 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}.fa-regular,.far{font-weight:400}

View File

@ -0,0 +1,19 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
:root, :host {
--fa-style-family-classic: 'Font Awesome 6 Free';
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; }
@font-face {
font-family: 'Font Awesome 6 Free';
font-style: normal;
font-weight: 900;
font-display: block;
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
.fas,
.fa-solid {
font-weight: 900; }

View File

@ -0,0 +1,6 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}

View File

@ -0,0 +1,635 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
:root, :host {
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Solid';
--fa-font-regular: normal 400 1em/1 'Font Awesome 6 Regular';
--fa-font-light: normal 300 1em/1 'Font Awesome 6 Light';
--fa-font-thin: normal 100 1em/1 'Font Awesome 6 Thin';
--fa-font-duotone: normal 900 1em/1 'Font Awesome 6 Duotone';
--fa-font-sharp-solid: normal 900 1em/1 'Font Awesome 6 Sharp';
--fa-font-brands: normal 400 1em/1 'Font Awesome 6 Brands'; }
svg:not(:root).svg-inline--fa, svg:not(:host).svg-inline--fa {
overflow: visible;
box-sizing: content-box; }
.svg-inline--fa {
display: var(--fa-display, inline-block);
height: 1em;
overflow: visible;
vertical-align: -.125em; }
.svg-inline--fa.fa-2xs {
vertical-align: 0.1em; }
.svg-inline--fa.fa-xs {
vertical-align: 0em; }
.svg-inline--fa.fa-sm {
vertical-align: -0.07143em; }
.svg-inline--fa.fa-lg {
vertical-align: -0.2em; }
.svg-inline--fa.fa-xl {
vertical-align: -0.25em; }
.svg-inline--fa.fa-2xl {
vertical-align: -0.3125em; }
.svg-inline--fa.fa-pull-left {
margin-right: var(--fa-pull-margin, 0.3em);
width: auto; }
.svg-inline--fa.fa-pull-right {
margin-left: var(--fa-pull-margin, 0.3em);
width: auto; }
.svg-inline--fa.fa-li {
width: var(--fa-li-width, 2em);
top: 0.25em; }
.svg-inline--fa.fa-fw {
width: var(--fa-fw-width, 1.25em); }
.fa-layers svg.svg-inline--fa {
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0; }
.fa-layers-text, .fa-layers-counter {
display: inline-block;
position: absolute;
text-align: center; }
.fa-layers {
display: inline-block;
height: 1em;
position: relative;
text-align: center;
vertical-align: -.125em;
width: 1em; }
.fa-layers svg.svg-inline--fa {
-webkit-transform-origin: center center;
transform-origin: center center; }
.fa-layers-text {
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
-webkit-transform-origin: center center;
transform-origin: center center; }
.fa-layers-counter {
background-color: var(--fa-counter-background-color, #ff253a);
border-radius: var(--fa-counter-border-radius, 1em);
box-sizing: border-box;
color: var(--fa-inverse, #fff);
line-height: var(--fa-counter-line-height, 1);
max-width: var(--fa-counter-max-width, 5em);
min-width: var(--fa-counter-min-width, 1.5em);
overflow: hidden;
padding: var(--fa-counter-padding, 0.25em 0.5em);
right: var(--fa-right, 0);
text-overflow: ellipsis;
top: var(--fa-top, 0);
-webkit-transform: scale(var(--fa-counter-scale, 0.25));
transform: scale(var(--fa-counter-scale, 0.25));
-webkit-transform-origin: top right;
transform-origin: top right; }
.fa-layers-bottom-right {
bottom: var(--fa-bottom, 0);
right: var(--fa-right, 0);
top: auto;
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: bottom right;
transform-origin: bottom right; }
.fa-layers-bottom-left {
bottom: var(--fa-bottom, 0);
left: var(--fa-left, 0);
right: auto;
top: auto;
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: bottom left;
transform-origin: bottom left; }
.fa-layers-top-right {
top: var(--fa-top, 0);
right: var(--fa-right, 0);
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: top right;
transform-origin: top right; }
.fa-layers-top-left {
left: var(--fa-left, 0);
right: auto;
top: var(--fa-top, 0);
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
transform: scale(var(--fa-layers-scale, 0.25));
-webkit-transform-origin: top left;
transform-origin: top left; }
.fa-1x {
font-size: 1em; }
.fa-2x {
font-size: 2em; }
.fa-3x {
font-size: 3em; }
.fa-4x {
font-size: 4em; }
.fa-5x {
font-size: 5em; }
.fa-6x {
font-size: 6em; }
.fa-7x {
font-size: 7em; }
.fa-8x {
font-size: 8em; }
.fa-9x {
font-size: 9em; }
.fa-10x {
font-size: 10em; }
.fa-2xs {
font-size: 0.625em;
line-height: 0.1em;
vertical-align: 0.225em; }
.fa-xs {
font-size: 0.75em;
line-height: 0.08333em;
vertical-align: 0.125em; }
.fa-sm {
font-size: 0.875em;
line-height: 0.07143em;
vertical-align: 0.05357em; }
.fa-lg {
font-size: 1.25em;
line-height: 0.05em;
vertical-align: -0.075em; }
.fa-xl {
font-size: 1.5em;
line-height: 0.04167em;
vertical-align: -0.125em; }
.fa-2xl {
font-size: 2em;
line-height: 0.03125em;
vertical-align: -0.1875em; }
.fa-fw {
text-align: center;
width: 1.25em; }
.fa-ul {
list-style-type: none;
margin-left: var(--fa-li-margin, 2.5em);
padding-left: 0; }
.fa-ul > li {
position: relative; }
.fa-li {
left: calc(var(--fa-li-width, 2em) * -1);
position: absolute;
text-align: center;
width: var(--fa-li-width, 2em);
line-height: inherit; }
.fa-border {
border-color: var(--fa-border-color, #eee);
border-radius: var(--fa-border-radius, 0.1em);
border-style: var(--fa-border-style, solid);
border-width: var(--fa-border-width, 0.08em);
padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); }
.fa-pull-left {
float: left;
margin-right: var(--fa-pull-margin, 0.3em); }
.fa-pull-right {
float: right;
margin-left: var(--fa-pull-margin, 0.3em); }
.fa-beat {
-webkit-animation-name: fa-beat;
animation-name: fa-beat;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
animation-timing-function: var(--fa-animation-timing, ease-in-out); }
.fa-bounce {
-webkit-animation-name: fa-bounce;
animation-name: fa-bounce;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); }
.fa-fade {
-webkit-animation-name: fa-fade;
animation-name: fa-fade;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); }
.fa-beat-fade {
-webkit-animation-name: fa-beat-fade;
animation-name: fa-beat-fade;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); }
.fa-flip {
-webkit-animation-name: fa-flip;
animation-name: fa-flip;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
animation-timing-function: var(--fa-animation-timing, ease-in-out); }
.fa-shake {
-webkit-animation-name: fa-shake;
animation-name: fa-shake;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
animation-timing-function: var(--fa-animation-timing, linear); }
.fa-spin {
-webkit-animation-name: fa-spin;
animation-name: fa-spin;
-webkit-animation-delay: var(--fa-animation-delay, 0s);
animation-delay: var(--fa-animation-delay, 0s);
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 2s);
animation-duration: var(--fa-animation-duration, 2s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
animation-timing-function: var(--fa-animation-timing, linear); }
.fa-spin-reverse {
--fa-animation-direction: reverse; }
.fa-pulse,
.fa-spin-pulse {
-webkit-animation-name: fa-spin;
animation-name: fa-spin;
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
animation-timing-function: var(--fa-animation-timing, steps(8)); }
@media (prefers-reduced-motion: reduce) {
.fa-beat,
.fa-bounce,
.fa-fade,
.fa-beat-fade,
.fa-flip,
.fa-pulse,
.fa-shake,
.fa-spin,
.fa-spin-pulse {
-webkit-animation-delay: -1ms;
animation-delay: -1ms;
-webkit-animation-duration: 1ms;
animation-duration: 1ms;
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
transition-delay: 0s;
transition-duration: 0s; } }
@-webkit-keyframes fa-beat {
0%, 90% {
-webkit-transform: scale(1);
transform: scale(1); }
45% {
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
transform: scale(var(--fa-beat-scale, 1.25)); } }
@keyframes fa-beat {
0%, 90% {
-webkit-transform: scale(1);
transform: scale(1); }
45% {
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
transform: scale(var(--fa-beat-scale, 1.25)); } }
@-webkit-keyframes fa-bounce {
0% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0); }
10% {
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); }
30% {
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); }
50% {
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); }
57% {
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); }
64% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0); }
100% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0); } }
@keyframes fa-bounce {
0% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0); }
10% {
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); }
30% {
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); }
50% {
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); }
57% {
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); }
64% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0); }
100% {
-webkit-transform: scale(1, 1) translateY(0);
transform: scale(1, 1) translateY(0); } }
@-webkit-keyframes fa-fade {
50% {
opacity: var(--fa-fade-opacity, 0.4); } }
@keyframes fa-fade {
50% {
opacity: var(--fa-fade-opacity, 0.4); } }
@-webkit-keyframes fa-beat-fade {
0%, 100% {
opacity: var(--fa-beat-fade-opacity, 0.4);
-webkit-transform: scale(1);
transform: scale(1); }
50% {
opacity: 1;
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
transform: scale(var(--fa-beat-fade-scale, 1.125)); } }
@keyframes fa-beat-fade {
0%, 100% {
opacity: var(--fa-beat-fade-opacity, 0.4);
-webkit-transform: scale(1);
transform: scale(1); }
50% {
opacity: 1;
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
transform: scale(var(--fa-beat-fade-scale, 1.125)); } }
@-webkit-keyframes fa-flip {
50% {
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } }
@keyframes fa-flip {
50% {
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } }
@-webkit-keyframes fa-shake {
0% {
-webkit-transform: rotate(-15deg);
transform: rotate(-15deg); }
4% {
-webkit-transform: rotate(15deg);
transform: rotate(15deg); }
8%, 24% {
-webkit-transform: rotate(-18deg);
transform: rotate(-18deg); }
12%, 28% {
-webkit-transform: rotate(18deg);
transform: rotate(18deg); }
16% {
-webkit-transform: rotate(-22deg);
transform: rotate(-22deg); }
20% {
-webkit-transform: rotate(22deg);
transform: rotate(22deg); }
32% {
-webkit-transform: rotate(-12deg);
transform: rotate(-12deg); }
36% {
-webkit-transform: rotate(12deg);
transform: rotate(12deg); }
40%, 100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg); } }
@keyframes fa-shake {
0% {
-webkit-transform: rotate(-15deg);
transform: rotate(-15deg); }
4% {
-webkit-transform: rotate(15deg);
transform: rotate(15deg); }
8%, 24% {
-webkit-transform: rotate(-18deg);
transform: rotate(-18deg); }
12%, 28% {
-webkit-transform: rotate(18deg);
transform: rotate(18deg); }
16% {
-webkit-transform: rotate(-22deg);
transform: rotate(-22deg); }
20% {
-webkit-transform: rotate(22deg);
transform: rotate(22deg); }
32% {
-webkit-transform: rotate(-12deg);
transform: rotate(-12deg); }
36% {
-webkit-transform: rotate(12deg);
transform: rotate(12deg); }
40%, 100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg); } }
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg); }
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg); } }
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg); }
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg); } }
.fa-rotate-90 {
-webkit-transform: rotate(90deg);
transform: rotate(90deg); }
.fa-rotate-180 {
-webkit-transform: rotate(180deg);
transform: rotate(180deg); }
.fa-rotate-270 {
-webkit-transform: rotate(270deg);
transform: rotate(270deg); }
.fa-flip-horizontal {
-webkit-transform: scale(-1, 1);
transform: scale(-1, 1); }
.fa-flip-vertical {
-webkit-transform: scale(1, -1);
transform: scale(1, -1); }
.fa-flip-both,
.fa-flip-horizontal.fa-flip-vertical {
-webkit-transform: scale(-1, -1);
transform: scale(-1, -1); }
.fa-rotate-by {
-webkit-transform: rotate(var(--fa-rotate-angle, none));
transform: rotate(var(--fa-rotate-angle, none)); }
.fa-stack {
display: inline-block;
vertical-align: middle;
height: 2em;
position: relative;
width: 2.5em; }
.fa-stack-1x,
.fa-stack-2x {
bottom: 0;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
z-index: var(--fa-stack-z-index, auto); }
.svg-inline--fa.fa-stack-1x {
height: 1em;
width: 1.25em; }
.svg-inline--fa.fa-stack-2x {
height: 2em;
width: 2.5em; }
.fa-inverse {
color: var(--fa-inverse, #fff); }
.sr-only,
.fa-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0; }
.sr-only-focusable:not(:focus),
.fa-sr-only-focusable:not(:focus) {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0; }
.svg-inline--fa .fa-primary {
fill: var(--fa-primary-color, currentColor);
opacity: var(--fa-primary-opacity, 1); }
.svg-inline--fa .fa-secondary {
fill: var(--fa-secondary-color, currentColor);
opacity: var(--fa-secondary-opacity, 0.4); }
.svg-inline--fa.fa-swap-opacity .fa-primary {
opacity: var(--fa-secondary-opacity, 0.4); }
.svg-inline--fa.fa-swap-opacity .fa-secondary {
opacity: var(--fa-primary-opacity, 1); }
.svg-inline--fa mask .fa-primary,
.svg-inline--fa mask .fa-secondary {
fill: black; }
.fad.fa-inverse,
.fa-duotone.fa-inverse {
color: var(--fa-inverse, #fff); }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,26 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
@font-face {
font-family: 'FontAwesome';
font-display: block;
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
@font-face {
font-family: 'FontAwesome';
font-display: block;
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
@font-face {
font-family: 'FontAwesome';
font-display: block;
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype");
unicode-range: U+F003,U+F006,U+F014,U+F016-F017,U+F01A-F01B,U+F01D,U+F022,U+F03E,U+F044,U+F046,U+F05C-F05D,U+F06E,U+F070,U+F087-F088,U+F08A,U+F094,U+F096-F097,U+F09D,U+F0A0,U+F0A2,U+F0A4-F0A7,U+F0C5,U+F0C7,U+F0E5-F0E6,U+F0EB,U+F0F6-F0F8,U+F10C,U+F114-F115,U+F118-F11A,U+F11C-F11D,U+F133,U+F147,U+F14E,U+F150-F152,U+F185-F186,U+F18E,U+F190-F192,U+F196,U+F1C1-F1C9,U+F1D9,U+F1DB,U+F1E3,U+F1EA,U+F1F7,U+F1F9,U+F20A,U+F247-F248,U+F24A,U+F24D,U+F255-F25B,U+F25D,U+F271-F274,U+F278,U+F27B,U+F28C,U+F28E,U+F29C,U+F2B5,U+F2B7,U+F2BA,U+F2BC,U+F2BE,U+F2C0-F2C1,U+F2C3,U+F2D0,U+F2D2,U+F2D4,U+F2DC; }
@font-face {
font-family: 'FontAwesome';
font-display: block;
src: url("../webfonts/fa-v4compatibility.woff2") format("woff2"), url("../webfonts/fa-v4compatibility.ttf") format("truetype");
unicode-range: U+F041,U+F047,U+F065-F066,U+F07D-F07E,U+F080,U+F08B,U+F08E,U+F090,U+F09A,U+F0AC,U+F0AE,U+F0B2,U+F0D0,U+F0D6,U+F0E4,U+F0EC,U+F10A-F10B,U+F123,U+F13E,U+F148-F149,U+F14C,U+F156,U+F15E,U+F160-F161,U+F163,U+F175-F178,U+F195,U+F1F8,U+F219,U+F27A; }

View File

@ -0,0 +1,6 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,22 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
@font-face {
font-family: 'Font Awesome 5 Brands';
font-display: block;
font-weight: 400;
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
@font-face {
font-family: 'Font Awesome 5 Free';
font-display: block;
font-weight: 900;
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
@font-face {
font-family: 'Font Awesome 5 Free';
font-display: block;
font-weight: 400;
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }

View File

@ -0,0 +1,6 @@
/*!
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2022 Fonticons, Inc.
*/
@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}

View File

@ -13,7 +13,7 @@
<link rel="stylesheet" href="/static/assets/vendors/flag-icon-css/css/flag-icon.min.css">
<link rel="stylesheet" href="/static/assets/vendors/ti-icons/css/themify-icons.css">
<link rel="stylesheet" href="/static/assets/vendors/typicons/typicons.css">
<link rel="stylesheet" href="/static/assets/vendors/fontawesome5/css/all.css">
<link rel="stylesheet" href="/static/assets/vendors/fontawesome6/css/all.css">
<link rel="stylesheet" type="text/css"
href="https://cdn.datatables.net/v/bs4/dt-1.10.22/fh-3.1.7/r-2.2.6/sc-2.0.3/sp-1.2.2/datatables.min.css" />
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">

Some files were not shown because too many files have changed in this diff Show More