Localization & stuff

This commit is contained in:
Roman 2022-11-30 16:42:24 +01:00
parent 25ef07b0b7
commit 1ba27e4f40
54 changed files with 856 additions and 494 deletions

@ -2,7 +2,6 @@
namespace Core\API { namespace Core\API {
use Core\Driver\SQL\Condition\Compare;
use Core\Objects\Context; use Core\Objects\Context;
abstract class ApiKeyAPI extends Request { abstract class ApiKeyAPI extends Request {

@ -2,7 +2,6 @@
namespace Core\API { namespace Core\API {
use Core\Driver\SQL\Condition\Compare;
use Core\Objects\Context; use Core\Objects\Context;
abstract class GroupsAPI extends Request { abstract class GroupsAPI extends Request {

@ -14,6 +14,7 @@ namespace Core\API {
namespace Core\API\Language { namespace Core\API\Language {
use Core\API\LanguageAPI; use Core\API\LanguageAPI;
use Core\API\Parameter\ArrayType;
use Core\API\Parameter\Parameter; use Core\API\Parameter\Parameter;
use Core\API\Parameter\StringType; use Core\API\Parameter\StringType;
use Core\Driver\SQL\Condition\Compare; use Core\Driver\SQL\Condition\Compare;
@ -105,7 +106,58 @@ namespace Core\API\Language {
} }
$this->context->setLanguage($this->language); $this->context->setLanguage($this->language);
$this->result["language"] = $this->language->jsonSerialize();
return $this->success; return $this->success;
} }
} }
class GetEntries extends LanguageAPI {
public function __construct(Context $context, bool $externalCall = false) {
parent::__construct($context, $externalCall, [
"code" => new StringType("code", 5, true, NULL),
"modules" => new ArrayType("modules", Parameter::TYPE_STRING, true, false)
]);
$this->loginRequired = false;
$this->csrfTokenRequired = false;
}
protected function _execute(): bool {
$code = $this->getParam("code");
if ($code === null) {
$code = $this->context->getLanguage()->getCode();
}
if (!preg_match(Language::LANG_CODE_PATTERN, $code)) {
return $this->createError("Invalid lang code format: $code");
}
$entries = [];
$modulePaths = [];
$requestedModules = $this->getParam("modules");
foreach ($requestedModules as $module) {
if (!preg_match(Language::LANG_MODULE_PATTERN, $module)) {
return $this->createError("Invalid module name: $module");
}
$moduleFound = false;
foreach (["Site", "Core"] as $baseDir) {
$filePath = realpath(implode("/", [$baseDir, "Localization", $code, "$module.php"]));
if ($filePath && is_file($filePath)) {
$moduleFound = true;
$moduleEntries = @include_once $filePath;
$entries[$module] = $moduleEntries;
break;
}
}
if (!$moduleFound) {
return $this->createError("Module not found: $module");
}
}
$this->result["code"] = $code;
$this->result["entries"] = $entries;
return true;
}
}
} }

@ -48,9 +48,7 @@ namespace Core\API\Mail {
use Core\API\Parameter\StringType; use Core\API\Parameter\StringType;
use Core\Objects\DatabaseEntity\MailQueueItem; use Core\Objects\DatabaseEntity\MailQueueItem;
use DateTimeInterface; use DateTimeInterface;
use Core\Driver\SQL\Column\Column;
use Core\Driver\SQL\Condition\Compare; use Core\Driver\SQL\Condition\Compare;
use Core\Driver\SQL\Condition\CondIn;
use Core\External\PHPMailer\Exception; use Core\External\PHPMailer\Exception;
use Core\External\PHPMailer\PHPMailer; use Core\External\PHPMailer\PHPMailer;
use Core\Objects\Context; use Core\Objects\Context;

@ -28,7 +28,6 @@ namespace Core\API\Permission {
use Core\API\Parameter\StringType; use Core\API\Parameter\StringType;
use Core\API\PermissionAPI; use Core\API\PermissionAPI;
use Core\Driver\SQL\Column\Column; use Core\Driver\SQL\Column\Column;
use Core\Driver\SQL\Condition\Compare;
use Core\Driver\SQL\Condition\CondIn; use Core\Driver\SQL\Condition\CondIn;
use Core\Driver\SQL\Condition\CondLike; use Core\Driver\SQL\Condition\CondLike;
use Core\Driver\SQL\Condition\CondNot; use Core\Driver\SQL\Condition\CondNot;

@ -6,7 +6,6 @@ use DateTime;
use Core\Driver\SQL\Condition\Compare; use Core\Driver\SQL\Condition\Compare;
use Core\Driver\SQL\Condition\CondBool; use Core\Driver\SQL\Condition\CondBool;
use Core\Objects\Context; use Core\Objects\Context;
use Core\Objects\DatabaseEntity\User;
class Stats extends Request { class Stats extends Request {

@ -297,8 +297,8 @@ namespace Core\API\User {
$this->result["users"][$userId] = $serialized; $this->result["users"][$userId] = $serialized;
} }
$this->result["pageCount"] = intval(ceil($this->userCount / $count)); $this->result["pageCount"] = intval(ceil($userCount / $count));
$this->result["totalCount"] = $this->userCount; $this->result["totalCount"] = $userCount;
} else { } else {
return $this->createError("Error fetching users: " . $sql->getLastError()); return $this->createError("Error fetching users: " . $sql->getLastError());
} }
@ -1580,4 +1580,33 @@ namespace Core\API\User {
return $this->success; return $this->success;
} }
} }
class CheckToken extends UserAPI {
private ?UserToken $userToken;
public function __construct($user, $externalCall = false) {
parent::__construct($user, $externalCall, array(
'token' => new StringType('token', 36),
));
$this->userToken = null;
}
public function getToken(): ?UserToken {
return $this->userToken;
}
public function _execute(): bool {
$token = $this->getParam('token');
$userToken = $this->checkToken($token);
if ($userToken === false) {
return false;
}
$this->userToken = $userToken;
$this->result["token"] = $userToken->jsonSerialize();
return $this->success;
}
}
} }

@ -9,7 +9,6 @@ use Core\Objects\DatabaseEntity\Language;
use Core\Objects\DatabaseEntity\Route; use Core\Objects\DatabaseEntity\Route;
use Core\Objects\Router\DocumentRoute; use Core\Objects\Router\DocumentRoute;
use Core\Objects\Router\StaticFileRoute; use Core\Objects\Router\StaticFileRoute;
use Core\Objects\Router\StaticRoute;
use PHPUnit\Util\Exception; use PHPUnit\Util\Exception;
class CreateDatabase extends DatabaseScript { class CreateDatabase extends DatabaseScript {
@ -21,7 +20,7 @@ class CreateDatabase extends DatabaseScript {
$queries[] = Language::getHandler($sql)->getInsertQuery([ $queries[] = Language::getHandler($sql)->getInsertQuery([
new Language(Language::AMERICAN_ENGLISH, "en_US", 'American English'), new Language(Language::AMERICAN_ENGLISH, "en_US", 'American English'),
new Language(Language::AMERICAN_ENGLISH, "de_DE", 'Deutsch Standard'), new Language(Language::GERMAN_STANDARD, "de_DE", 'Deutsch Standard'),
]); ]);
$queries[] = Group::getHandler($sql)->getInsertQuery([ $queries[] = Group::getHandler($sql)->getInsertQuery([

@ -4,12 +4,14 @@
namespace Core\Documents; namespace Core\Documents;
use Core\Elements\TemplateDocument; use Core\Elements\TemplateDocument;
use Core\Objects\DatabaseEntity\UserToken;
use Core\Objects\Router\Router; use Core\Objects\Router\Router;
class Account extends TemplateDocument { class Account extends TemplateDocument {
public function __construct(Router $router, string $templateName) { public function __construct(Router $router, string $templateName) {
parent::__construct($router, $templateName); parent::__construct($router, $templateName);
$this->languageModules = ["general", "account"];
$this->title = "Account"; $this->title = "Account";
$this->searchable = false; $this->searchable = false;
$this->enableCSP(); $this->enableCSP();
@ -21,47 +23,67 @@ class Account extends TemplateDocument {
} }
protected function loadParameters() { protected function loadParameters() {
$settings = $this->getSettings();
$templateName = $this->getTemplateName();
$language = $this->getContext()->getLanguage();
$this->parameters["view"] = ["success" => true]; $this->parameters["view"] = ["success" => true];
if ($this->getTemplateName() === "account/reset_password.twig") { switch ($templateName) {
if (isset($_GET["token"]) && is_string($_GET["token"]) && !empty($_GET["token"])) {
$this->parameters["view"]["token"] = $_GET["token"]; case "account/reset_password.twig": {
$req = new \Core\API\User\CheckToken($this->getContext()); if (isset($_GET["token"]) && is_string($_GET["token"]) && !empty($_GET["token"])) {
$this->parameters["view"]["success"] = $req->execute(array("token" => $_GET["token"])); $this->parameters["view"]["token"] = $_GET["token"];
if ($this->parameters["view"]["success"]) { $req = new \Core\API\User\CheckToken($this->getContext());
if (strcmp($req->getResult()["token"]["type"], "password_reset") !== 0) { $this->parameters["view"]["success"] = $req->execute(array("token" => $_GET["token"]));
$this->createError("The given token has a wrong type."); if ($this->parameters["view"]["success"]) {
} if (strcmp($req->getToken()->getType(), UserToken::TYPE_PASSWORD_RESET) !== 0) {
} else { $this->createError("The given token has a wrong type.");
$this->createError("Error requesting password reset: " . $req->getLastError()); }
}
}
} else if ($this->getTemplateName() === "account/register.twig") {
$settings = $this->getSettings();
if ($this->getUser()) {
$this->createError("You are already logged in.");
} else if (!$settings->isRegistrationAllowed()) {
$this->createError("Registration is not enabled on this website.");
}
} else if ($this->getTemplateName() === "account/login.twig" && $this->getUser()) {
header("Location: /admin");
exit();
} else if ($this->getTemplateName() === "account/accept_invite.twig") {
if (isset($_GET["token"]) && is_string($_GET["token"]) && !empty($_GET["token"])) {
$this->parameters["view"]["token"] = $_GET["token"];
$req = new \Core\API\User\CheckToken($this->getContext());
$this->parameters["view"]["success"] = $req->execute(array("token" => $_GET["token"]));
if ($this->parameters["view"]["success"]) {
if (strcmp($req->getResult()["token"]["type"], "invite") !== 0) {
$this->createError("The given token has a wrong type.");
} else { } else {
$this->parameters["view"]["invited_user"] = $req->getResult()["user"]; $this->createError("Error requesting password reset: " . $req->getLastError());
}
}
break;
}
case "account/register.twig": {
if ($this->getUser()) {
$this->createError("You are already logged in.");
} else if (!$settings->isRegistrationAllowed()) {
$this->createError("Registration is not enabled on this website.");
}
break;
}
case "account/login.twig": {
if ($this->getUser()) {
header("Location: /admin");
exit();
}
break;
}
case "account/accept_invite.twig": {
if (isset($_GET["token"]) && is_string($_GET["token"]) && !empty($_GET["token"])) {
$this->parameters["view"]["token"] = $_GET["token"];
$req = new \Core\API\User\CheckToken($this->getContext());
$this->parameters["view"]["success"] = $req->execute(array("token" => $_GET["token"]));
if ($this->parameters["view"]["success"]) {
if (strcmp($req->getToken()->getType(), UserToken::TYPE_INVITE) !== 0) {
$this->createError("The given token has a wrong type.");
} else {
$this->parameters["view"]["invited_user"] = $req->getToken()->getUser()->jsonSerialize();
}
} else {
$this->createError("Error confirming e-mail address: " . $req->getLastError());
} }
} else { } else {
$this->createError("Error confirming e-mail address: " . $req->getLastError()); $this->createError("The link you visited is no longer valid");
} }
} else { break;
$this->createError("The link you visited is no longer valid");
} }
default:
break;
} }
} }
} }

@ -5,6 +5,7 @@ namespace Core\Documents;
use Core\Elements\EmptyHead; use Core\Elements\EmptyHead;
use Core\Elements\HtmlDocument; use Core\Elements\HtmlDocument;
use Core\Elements\SimpleBody; use Core\Elements\SimpleBody;
use Core\Objects\DatabaseEntity\Group;
use Core\Objects\Router\Router; use Core\Objects\Router\Router;
class Info extends HtmlDocument { class Info extends HtmlDocument {
@ -16,7 +17,7 @@ class Info extends HtmlDocument {
class InfoBody extends SimpleBody { class InfoBody extends SimpleBody {
protected function getContent(): string { protected function getContent(): string {
$user = $this->getDocument()->getUser(); $user = $this->getContext()->getUser();
if ($user && $user->hasGroup(Group::ADMIN)) { if ($user && $user->hasGroup(Group::ADMIN)) {
phpinfo(); phpinfo();
return ""; return "";

@ -2,7 +2,6 @@
namespace Core\Driver\SQL\Column; namespace Core\Driver\SQL\Column;
use Core\Driver\SQL\Column\Column;
class NumericColumn extends Column { class NumericColumn extends Column {

@ -2,8 +2,6 @@
namespace Core\Driver\SQL\Expression; namespace Core\Driver\SQL\Expression;
use Core\Driver\SQL\SQL;
class DateAdd extends Expression { class DateAdd extends Expression {
private Expression $lhs; private Expression $lhs;

@ -2,8 +2,6 @@
namespace Core\Driver\SQL\Expression; namespace Core\Driver\SQL\Expression;
use Core\Driver\SQL\SQL;
class DateSub extends Expression { class DateSub extends Expression {
private Expression $lhs; private Expression $lhs;

@ -2,8 +2,6 @@
namespace Core\Driver\SQL\Expression; namespace Core\Driver\SQL\Expression;
use Core\Driver\SQL\SQL;
abstract class Expression { abstract class Expression {
} }

@ -5,7 +5,6 @@ namespace Core\Driver\SQL\Query;
use Core\Driver\SQL\Column\Column; use Core\Driver\SQL\Column\Column;
use Core\Driver\SQL\Column\EnumColumn; use Core\Driver\SQL\Column\EnumColumn;
use Core\Driver\SQL\Constraint\Constraint; use Core\Driver\SQL\Constraint\Constraint;
use Core\Driver\SQL\Constraint\ForeignKey;
use Core\Driver\SQL\Constraint\PrimaryKey; use Core\Driver\SQL\Constraint\PrimaryKey;
use Core\Driver\SQL\PostgreSQL; use Core\Driver\SQL\PostgreSQL;
use Core\Driver\SQL\SQL; use Core\Driver\SQL\SQL;

@ -2,7 +2,6 @@
namespace Core\Driver\SQL\Query; namespace Core\Driver\SQL\Query;
use Core\API\User\Create;
use Core\Driver\SQL\SQL; use Core\Driver\SQL\SQL;
class CreateTrigger extends Query { class CreateTrigger extends Query {

@ -2,7 +2,6 @@
namespace Core\Driver\SQL\Query; namespace Core\Driver\SQL\Query;
use Core\Driver\SQL\Condition\CondOr;
use Core\Driver\SQL\SQL; use Core\Driver\SQL\SQL;
class Delete extends ConditionalQuery { class Delete extends ConditionalQuery {

@ -6,7 +6,6 @@ use Core\Configuration\Settings;
use Core\Driver\Logger\Logger; use Core\Driver\Logger\Logger;
use Core\Driver\SQL\SQL; use Core\Driver\SQL\SQL;
use Core\Objects\Context; use Core\Objects\Context;
use Core\Objects\lang\LanguageModule;
use Core\Objects\Router\DocumentRoute; use Core\Objects\Router\DocumentRoute;
use Core\Objects\Router\Router; use Core\Objects\Router\Router;
use Core\Objects\DatabaseEntity\User; use Core\Objects\DatabaseEntity\User;
@ -24,6 +23,7 @@ abstract class Document {
private array $cspWhitelist; private array $cspWhitelist;
private string $domain; private string $domain;
protected bool $searchable; protected bool $searchable;
protected array $languageModules;
public function __construct(Router $router) { public function __construct(Router $router) {
$this->router = $router; $this->router = $router;
@ -34,6 +34,7 @@ abstract class Document {
$this->domain = $this->getSettings()->getBaseUrl(); $this->domain = $this->getSettings()->getBaseUrl();
$this->logger = new Logger("Document", $this->getSQL()); $this->logger = new Logger("Document", $this->getSQL());
$this->searchable = false; $this->searchable = false;
$this->languageModules = [];
} }
public abstract function getTitle(): string; public abstract function getTitle(): string;
@ -88,11 +89,6 @@ abstract class Document {
} }
} }
public function loadLanguageModule(LanguageModule|string $module) {
$language = $this->getContext()->getLanguage();
$language->loadModule($module);
}
public function sendHeaders() { public function sendHeaders() {
if ($this->cspEnabled) { if ($this->cspEnabled) {
$cspWhiteList = implode(" ", $this->cspWhitelist); $cspWhiteList = implode(" ", $this->cspWhitelist);
@ -126,8 +122,12 @@ abstract class Document {
} }
} }
$language = $this->getContext()->getLanguage();
foreach ($this->languageModules as $module) {
$language->loadModule($module);
}
$code = $this->getCode($params); $code = $this->getCode($params);
$this->sendHeaders(); $this->sendHeaders();
return $code; return $code;
} }

@ -94,6 +94,12 @@ class TemplateDocument extends Document {
"csp" => [ "csp" => [
"nonce" => $this->getCSPNonce(), "nonce" => $this->getCSPNonce(),
"enabled" => $this->isCSPEnabled() "enabled" => $this->isCSPEnabled()
],
"language" => [
"code" => $language->getCode(),
"shortCode" => $language->getShortCode(),
"name" => $language->getName(),
"entries" => $language->getEntries()
] ]
] ]
], $params); ], $params);

@ -2,6 +2,8 @@
namespace Core\Elements; namespace Core\Elements;
use Core\Objects\Context;
abstract class View extends StaticView { abstract class View extends StaticView {
private Document $document; private Document $document;
@ -18,9 +20,10 @@ abstract class View extends StaticView {
public function getTitle(): string { return $this->title; } public function getTitle(): string { return $this->title; }
public function getDocument(): Document { return $this->document; } public function getDocument(): Document { return $this->document; }
public function getContext(): Context { return $this->document->getContext(); }
public function getSiteName(): string { public function getSiteName(): string {
return $this->getDocument()->getSettings()->getSiteName(); return $this->getContext()->getSettings()->getSiteName();
} }
protected function load(string $viewClass) : string { protected function load(string $viewClass) : string {
@ -38,23 +41,13 @@ abstract class View extends StaticView {
return ""; return "";
} }
private function loadLanguageModules() {
$lang = $this->document->getContext()->getLanguage();
foreach ($this->langModules as $langModule) {
$lang->loadModule($langModule);
}
}
// Virtual Methods // Virtual Methods
public function loadView() { } public function loadView() { }
public function getCode(): string { public function getCode(): string {
// Load translations
$this->loadLanguageModules();
// Load metadata + head (title, scripts, includes, ...) // Load metadata + head (title, scripts, includes, ...)
if($this->loadView) { if ($this->loadView) {
$this->loadView(); $this->loadView();
} }

@ -0,0 +1,19 @@
<?php
return [
"title" => "Einloggen",
"description" => "Loggen Sie sich in Ihren Account ein",
"form_title" => "Bitte geben Sie ihre Daten ein",
"username" => "Benutzername",
"username_or_email" => "Benutzername oder E-Mail",
"password" => "Passwort",
"remember_me" => "Eingeloggt bleiben",
"signing_in" => "Einloggen",
"sign_in" => "Einloggen",
"forgot_password" => "Passwort vergessen?",
"passwords_do_not_match" => "Die Passwörter stimmen nicht überein",
"register_text" => "Noch keinen Account? Jetzt registrieren",
"6_digit_code" => "6-stelliger Code",
"2fa_title" => "Es werden weitere Informationen zum Einloggen benötigt",
"2fa_text" => "Stecke dein 2FA-Gerät ein. Möglicherweise wird noch eine Interaktion benötigt, z.B. durch Eingabe einer PIN oder durch Berühren des Geräts",
];

@ -0,0 +1,11 @@
<?php
return [
"something_went_wrong" => "Etwas ist schief gelaufen",
"retry" => "Erneut versuchen",
"Go back" => "Zurück",
"submitting" => "Übermittle",
"submit" => "Absenden",
"language" => "Sprache",
"loading" => "Laden",
];

@ -0,0 +1,19 @@
<?php
return [
"title" => "Sign In",
"description" => "Sign In into your account",
"form_title" => "Please fill with your details",
"username" => "Username",
"username_or_email" => "Username or E-Mail",
"password" => "Password",
"remember_me" => "Remember Me",
"signing_in" => "Signing in",
"sign_in" => "Sign In",
"forgot_password" => "Forgot password?",
"register_text" => "Don't have an account? Sign Up",
"passwords_do_not_match" => "Your passwords did not match",
"6_digit_code" => "6-Digit Code",
"2fa_title" => "Additional information is required for logging in",
"2fa_text" => "Plugin your 2FA-Device. Interaction might be required, e.g. typing in a PIN or touching it."
];

@ -0,0 +1,11 @@
<?php
return [
"something_went_wrong" => "Something went wrong",
"retry" => "Retry",
"go_back" => "Go Back",
"submitting" => "Submitting",
"submit" => "Submit",
"language" => "Language",
"loading" => "Loading",
];

@ -2,6 +2,7 @@
namespace Core\Objects; namespace Core\Objects;
use Core\Objects\DatabaseEntity\Language;
use Twig\Extension\AbstractExtension; use Twig\Extension\AbstractExtension;
use Twig\TwigFunction; use Twig\TwigFunction;
@ -9,10 +10,16 @@ class CustomTwigFunctions extends AbstractExtension {
public function getFunctions(): array { public function getFunctions(): array {
return [ return [
new TwigFunction('L', array($this, 'translate')), new TwigFunction('L', array($this, 'translate')),
new TwigFunction('LoadLanguageModule', array($this, 'loadLanguageModule')),
]; ];
} }
public function translate(string $key): string { public function translate(string $key): string {
return L($key); return L($key);
} }
public function loadLanguageModule(string $module): void {
$language = Language::getInstance();
$language->loadModule($module);
}
} }

@ -2,7 +2,6 @@
namespace Core\Objects\DatabaseEntity\Controller; namespace Core\Objects\DatabaseEntity\Controller;
use Core\Driver\SQL\Condition\Compare;
use Core\Driver\SQL\Condition\Condition; use Core\Driver\SQL\Condition\Condition;
use Core\Driver\SQL\SQL; use Core\Driver\SQL\SQL;

@ -3,8 +3,6 @@
namespace Core\Objects\DatabaseEntity\Controller; namespace Core\Objects\DatabaseEntity\Controller;
use Core\Driver\Logger\Logger; use Core\Driver\Logger\Logger;
use Core\Driver\SQL\Condition\Condition;
use Core\Driver\SQL\Join;
use Core\Driver\SQL\Query\Select; use Core\Driver\SQL\Query\Select;
use Core\Driver\SQL\SQL; use Core\Driver\SQL\SQL;

@ -4,7 +4,6 @@ namespace Core\Objects\DatabaseEntity {
use Core\Objects\DatabaseEntity\Attribute\MaxLength; use Core\Objects\DatabaseEntity\Attribute\MaxLength;
use Core\Objects\DatabaseEntity\Attribute\Transient; use Core\Objects\DatabaseEntity\Attribute\Transient;
use Core\Objects\lang\LanguageModule;
use Core\Objects\DatabaseEntity\Controller\DatabaseEntity; use Core\Objects\DatabaseEntity\Controller\DatabaseEntity;
// TODO: language from cookie? // TODO: language from cookie?
@ -14,11 +13,11 @@ namespace Core\Objects\DatabaseEntity {
const GERMAN_STANDARD = 2; const GERMAN_STANDARD = 2;
const LANG_CODE_PATTERN = "/^[a-zA-Z]{2}_[a-zA-Z]{2}$/"; const LANG_CODE_PATTERN = "/^[a-zA-Z]{2}_[a-zA-Z]{2}$/";
const LANG_MODULE_PATTERN = "/[a-zA-Z0-9_-]/";
#[MaxLength(5)] private string $code; #[MaxLength(5)] private string $code;
#[MaxLength(32)] private string $name; #[MaxLength(32)] private string $name;
#[Transient] private array $modules = [];
#[Transient] protected array $entries = []; #[Transient] protected array $entries = [];
public function __construct(int $id, string $code, string $name) { public function __construct(int $id, string $code, string $name) {
@ -39,22 +38,6 @@ namespace Core\Objects\DatabaseEntity {
return $this->name; return $this->name;
} }
public function loadModule(LanguageModule|string $module) {
if (!is_object($module)) {
$module = new $module();
}
if (!in_array($module, $this->modules)) {
$moduleEntries = $module->getEntries($this->code);
$this->entries = array_merge($this->entries, $moduleEntries);
$this->modules[] = $module;
}
}
public function translate(string $key): string {
return $this->entries[$key] ?? $key;
}
public function sendCookie(string $domain) { public function sendCookie(string $domain) {
setcookie('lang', $this->code, 0, "/", $domain, false, false); setcookie('lang', $this->code, 0, "/", $domain, false, false);
} }
@ -73,6 +56,11 @@ namespace Core\Objects\DatabaseEntity {
$LANGUAGE = $this; $LANGUAGE = $this;
} }
public static function getInstance(): Language {
global $LANGUAGE;
return $LANGUAGE;
}
public static function DEFAULT_LANGUAGE(bool $fromCookie = true): Language { public static function DEFAULT_LANGUAGE(bool $fromCookie = true): Language {
if ($fromCookie && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { if ($fromCookie && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE']; $acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
@ -94,16 +82,70 @@ namespace Core\Objects\DatabaseEntity {
return new Language(1, "en_US", "American English"); return new Language(1, "en_US", "American English");
} }
public function getEntries(): array { public function getEntries(?string $module = null): ?array {
return $this->entries; if (!$module) {
return $this->entries;
} else {
return $this->entries[$module] ?? null;
}
}
public function translate(string $key): string {
if (preg_match("/(\w+)\.(\w+)/", $key, $matches)) {
$module = $matches[1];
$moduleKey = $matches[2];
if ($this->hasModule($module) && array_key_exists($moduleKey, $this->entries[$module])) {
return $this->entries[$module][$moduleKey];
}
}
return "[$key]";
}
public function addModule(string $module, array $entries) {
if ($this->hasModule($module)) {
$this->entries[$module] = array_merge($this->entries[$module], $entries);
} else {
$this->entries[$module] = $entries;
}
}
public function loadModule(string $module, bool $forceReload=false): bool {
if ($this->hasModule($module) && !$forceReload) {
return true;
}
if (!preg_match(self::LANG_MODULE_PATTERN, $module)) {
return false;
}
if (!preg_match(self::LANG_CODE_PATTERN, $this->code)) {
return false;
}
foreach (["Site", "Core"] as $baseDir) {
$filePath = realpath(implode("/", [$baseDir, "Localization", $this->code, "$module.php"]));
if ($filePath && is_file($filePath)) {
$moduleEntries = @include_once $filePath;
$this->addModule($module, $moduleEntries);
return true;
}
}
return false;
}
public function hasModule(string $module): bool {
return array_key_exists($module, $this->entries);
} }
} }
} }
namespace { namespace {
function L($key) { function L(string $key): string {
if (!array_key_exists('LANGUAGE', $GLOBALS)) if (!array_key_exists('LANGUAGE', $GLOBALS)) {
return $key; return "[$key]";
}
global $LANGUAGE; global $LANGUAGE;
return $LANGUAGE->translate($key); return $LANGUAGE->translate($key);

@ -1,8 +0,0 @@
<?php
namespace Core\Objects\lang;
abstract class LanguageModule {
public abstract function getEntries(string $langCode);
}

@ -8,10 +8,13 @@
<script src="/js/bootstrap.bundle.min.js" nonce="{{ site.csp.nonce }}"></script> <script src="/js/bootstrap.bundle.min.js" nonce="{{ site.csp.nonce }}"></script>
<link rel="stylesheet" href="/css/fontawesome.min.css" nonce="{{ site.csp.nonce }}"> <link rel="stylesheet" href="/css/fontawesome.min.css" nonce="{{ site.csp.nonce }}">
<link rel="stylesheet" href="/css/account.css" nonce="{{ site.csp.nonce }}"> <link rel="stylesheet" href="/css/account.css" nonce="{{ site.csp.nonce }}">
<title>Account - {{ view_title }}</title> <title>Account - {{ L(view_title) }}</title>
{% if site.recaptcha.enabled %} {% if site.recaptcha.enabled %}
<script src="https://www.google.com/recaptcha/api.js?render={{ site.recaptcha.key }}" nonce="{{ site.csp.nonce }}"></script> <script src="https://www.google.com/recaptcha/api.js?render={{ site.recaptcha.key }}" nonce="{{ site.csp.nonce }}"></script>
{% endif %} {% endif %}
<script nonce="{{ site.csp.nonce }}">
window.languageEntries = {{ site.language.entries|json_encode()|raw }};
</script>
{% endblock %} {% endblock %}
{% block body %} {% block body %}
@ -20,8 +23,8 @@
<div class="col-md-3 py-5 bg-primary text-white text-center" style='border-top-left-radius:.4em;border-bottom-left-radius:.4em;margin-left: auto'> <div class="col-md-3 py-5 bg-primary text-white text-center" style='border-top-left-radius:.4em;border-bottom-left-radius:.4em;margin-left: auto'>
<div class="card-body"> <div class="card-body">
<i class="fas fa-{{ view_icon }} fa-3x"></i> <i class="fas fa-{{ view_icon }} fa-3x"></i>
<h2 class="py-3">{{ view_title }}</h2> <h2 class="py-3">{{ L(view_title) }}</h2>
<p>{{ view_description }}</p> <p>{{ L(view_description) }}</p>
</div> </div>
</div> </div>
<div class="col-md-5 pt-5 pb-2 border border-info" style='border-top-right-radius:.4em;border-bottom-right-radius:.4em;margin-right:auto'> <div class="col-md-5 pt-5 pb-2 border border-info" style='border-top-right-radius:.4em;border-bottom-right-radius:.4em;margin-right:auto'>

@ -1,32 +1,36 @@
{% extends "account/account_base.twig" %} {% extends "account/account_base.twig" %}
{% set view_title = 'Sign In' %} {% set view_title = 'account.title' %}
{% set view_icon = 'user-lock' %} {% set view_icon = 'user-lock' %}
{% set view_description = 'Sign In into your account' %} {% set view_description = 'account.description' %}
{% block view_content %} {% block view_content %}
<h4 class="pb-4">Please fill with your details</h4> <h4 class="pb-4">{{ L("account.form_title") }}</h4>
<form> <form>
<div class="input-group"> <div class="input-group">
<div class="input-group-append"> <div class="input-group-append">
<span class="input-group-text"><i class="fas fa-hashtag"></i></span> <span class="input-group-text"><i class="fas fa-hashtag"></i></span>
</div> </div>
<input id="username" autocomplete='username' name="username" placeholder="Username or E-Mail" class="form-control" type="text" maxlength="32"> <input id="username" autocomplete='username' name="username"
placeholder="{{ L("account.username_or_email") }}" class="form-control" type="text" maxlength="32">
</div> </div>
<div class="input-group mt-3"> <div class="input-group mt-3">
<div class="input-group-append"> <div class="input-group-append">
<span class="input-group-text"><i class="fas fa-key"></i></span> <span class="input-group-text"><i class="fas fa-key"></i></span>
</div> </div>
<input type="password" autocomplete='password' name='password' id='password' class="form-control" placeholder="Password"> <input type="password" autocomplete='password' name='password' id='password' class="form-control"
placeholder={{ L("account.password") }}>
</div> </div>
<div class="ml-2" style="line-height: 38px;"> <div class="ml-2" style="line-height: 38px;">
<a href="/resetPassword">Forgot Password?</a> <a href="/resetPassword">{{ L("account.forgot_password") }}</a>
</div> </div>
<div class="input-group mt-3 mb-4"> <div class="input-group mt-3 mb-4">
<button type="button" class="btn btn-primary" id='btnLogin'>Sign In</button> <button type="button" class="btn btn-primary" id='btnLogin'>{{ L("account.sign_in") }}</button>
{% if site.registrationEnabled %} {% if site.registrationEnabled %}
<div class="ml-2" style="line-height: 38px;">Don't have an account yet? <a href="/register">Click here</a> to register.</div> <div class="ml-2" style="line-height: 38px;">
<a href="/register">{{ L("account.register_text") }}</a>
</div>
{% endif %} {% endif %}
</div> </div>
</form> </form>

@ -9,4 +9,5 @@
<noscript>You need Javascript enabled to run this app</noscript> <noscript>You need Javascript enabled to run this app</noscript>
<div class="wrapper" type="module" id="admin-panel"></div> <div class="wrapper" type="module" id="admin-panel"></div>
<script src="/js/admin-panel/index.js" nonce="{{ site.csp.nonce }}"></script> <script src="/js/admin-panel/index.js" nonce="{{ site.csp.nonce }}"></script>
<link rel="stylesheet" href="/js/admin-panel/index.css" nonce="{{ site.csp.nonce }}"></link>
{% endblock %} {% endblock %}

@ -1,17 +0,0 @@
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};

@ -1,9 +1,5 @@
$(document).ready(function () { $(document).ready(function () {
function isRecaptchaEnabled() {
return (typeof grecaptcha !== 'undefined');
}
function showAlert(type, msg, raw=false) { function showAlert(type, msg, raw=false) {
let alert = $("#alertMessage"); let alert = $("#alertMessage");
if (raw) { if (raw) {
@ -46,12 +42,12 @@ $(document).ready(function () {
hideAlert(); hideAlert();
btn.prop("disabled", true); btn.prop("disabled", true);
btn.html("Logging in… <i class=\"fa fa-spin fa-circle-notch\"></i>"); btn.html(L("account.signing_in") + "… <i class=\"fa fa-spin fa-circle-notch\"></i>");
jsCore.apiCall("/user/login", {"username": username, "password": password, "stayLoggedIn": stayLoggedIn }, function(res) { jsCore.apiCall("/user/login", {"username": username, "password": password, "stayLoggedIn": stayLoggedIn }, function(res) {
if (res.success) { if (res.success) {
document.location.reload(); document.location.reload();
} else { } else {
btn.html("Login"); btn.text(L("account.sign_in"));
btn.prop("disabled", false); btn.prop("disabled", false);
$("#password").val(""); $("#password").val("");
createdDiv.hide(); createdDiv.hide();
@ -77,10 +73,10 @@ $(document).ready(function () {
if (username === '' || email === '' || password === '' || confirmPassword === '') { if (username === '' || email === '' || password === '' || confirmPassword === '') {
showAlert("danger", "Please fill out every field."); showAlert("danger", "Please fill out every field.");
} else if(password !== confirmPassword) { } else if(password !== confirmPassword) {
showAlert("danger", "Your passwords did not match."); showAlert("danger", L("register.passwords_do_not_match"));
} else { } else {
let params = { username: username, email: email, password: password, confirmPassword: confirmPassword }; let params = { username: username, email: email, password: password, confirmPassword: confirmPassword };
if (isRecaptchaEnabled()) { if (jsCore.isRecaptchaEnabled()) {
let siteKey = $("#siteKey").val().trim(); let siteKey = $("#siteKey").val().trim();
grecaptcha.ready(function() { grecaptcha.ready(function() {
grecaptcha.execute(siteKey, {action: 'register'}).then(function(captcha) { grecaptcha.execute(siteKey, {action: 'register'}).then(function(captcha) {
@ -138,7 +134,7 @@ $(document).ready(function () {
let email = $("#email").val(); let email = $("#email").val();
let params = { email: email }; let params = { email: email };
if (isRecaptchaEnabled()) { if (jsCore.isRecaptchaEnabled()) {
let siteKey = $("#siteKey").val().trim(); let siteKey = $("#siteKey").val().trim();
grecaptcha.ready(function() { grecaptcha.ready(function() {
grecaptcha.execute(siteKey, {action: 'resetPassword'}).then(function(captcha) { grecaptcha.execute(siteKey, {action: 'resetPassword'}).then(function(captcha) {
@ -196,7 +192,7 @@ $(document).ready(function () {
let btn = $(this); let btn = $(this);
let email = $("#email").val(); let email = $("#email").val();
let params = { email: email }; let params = { email: email };
if (isRecaptchaEnabled()) { if (jsCore.isRecaptchaEnabled()) {
let siteKey = $("#siteKey").val().trim(); let siteKey = $("#siteKey").val().trim();
grecaptcha.ready(function() { grecaptcha.ready(function() {
grecaptcha.execute(siteKey, {action: 'resendConfirmation'}).then(function(captcha) { grecaptcha.execute(siteKey, {action: 'resendConfirmation'}).then(function(captcha) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -150,7 +150,25 @@ let Core = function () {
return this.getJsonDateTime(date).split(' ')[1]; return this.getJsonDateTime(date).split(' ')[1];
}; };
this.isRecaptchaEnabled = function () {
return (typeof grecaptcha !== 'undefined');
}
this.__construct(); this.__construct();
}; };
let jsCore = new Core(); let jsCore = new Core();
function L(key) {
let entries = window.languageEntries || {};
let [module, variable] = key.split(".");
if (module && variable && entries.hasOwnProperty(module)) {
let translation = entries[module][variable];
if (translation) {
return translation;
}
}
return "[" + key + "]";
}

@ -2,10 +2,11 @@
"name": "admin-panel", "name": "admin-panel",
"version": "1.0.0", "version": "1.0.0",
"dependencies": { "dependencies": {
"shared": "link:../shared" "shared": "link:../shared",
"react": "^18.2.0"
}, },
"scripts": { "scripts": {
"debug": "react-app-rewired start" "dev": "react-app-rewired start"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",

@ -3,7 +3,7 @@ import './res/adminlte.min.css';
import './res/index.css'; import './res/index.css';
import API from "shared/api"; import API from "shared/api";
import Icon from "shared/elements/icon"; import Icon from "shared/elements/icon";
import {BrowserRouter, Route, Routes} from "react-router-dom"; import {BrowserRouter, Routes} from "react-router-dom";
import Dialog from "./elements/dialog"; import Dialog from "./elements/dialog";
import Footer from "./elements/footer"; import Footer from "./elements/footer";
import Header from "./elements/header"; import Header from "./elements/header";
@ -11,12 +11,14 @@ import Sidebar from "./elements/sidebar";
import LoginForm from "./views/login"; import LoginForm from "./views/login";
import {Alert} from "@material-ui/lab"; import {Alert} from "@material-ui/lab";
import {Button} from "@material-ui/core"; import {Button} from "@material-ui/core";
import {Locale} from "shared/locale";
export default class AdminDashboard extends React.Component { export default class AdminDashboard extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.api = new API(); this.api = new API();
this.locale = Locale.getInstance();
this.state = { this.state = {
loaded: false, loaded: false,
dialog: { onClose: () => this.hideDialog() }, dialog: { onClose: () => this.hideDialog() },
@ -39,13 +41,19 @@ export default class AdminDashboard extends React.Component {
onInit() { onInit() {
this.setState({ ...this.state, loaded: false, error: null }); this.setState({ ...this.state, loaded: false, error: null });
this.api.info().then(data => { this.api.getLanguageEntries("general").then(data => {
if (data.success) { if (data.success) {
this.setState({...this.state, info: data.info }) this.api.info().then(data => {
this.api.fetchUser().then(data => {
if (data.success) { if (data.success) {
setInterval(this.onUpdate.bind(this), 60*1000); this.setState({...this.state, info: data.info })
this.setState({...this.state, loaded: true}); this.api.fetchUser().then(data => {
if (data.success) {
setInterval(this.onUpdate.bind(this), 60*1000);
this.setState({...this.state, loaded: true});
} else {
this.setState({ ...this.state, error: data.msg })
}
});
} else { } else {
this.setState({ ...this.state, error: data.msg }) this.setState({ ...this.state, error: data.msg })
} }
@ -73,7 +81,6 @@ export default class AdminDashboard extends React.Component {
callback(res); callback(res);
}) })
} else { } else {
this.setState({ ...this.state, error: res.msg });
callback(res); callback(res);
} }
}); });
@ -96,7 +103,6 @@ export default class AdminDashboard extends React.Component {
callback(res); callback(res);
}) })
} else { } else {
this.setState({ ...this.state, error: res.msg });
callback(res); callback(res);
} }
}); });
@ -111,7 +117,6 @@ export default class AdminDashboard extends React.Component {
callback(res); callback(res);
}) })
} else { } else {
this.setState({ ...this.state, error: res.msg });
callback(res); callback(res);
} }
}); });
@ -136,6 +141,7 @@ export default class AdminDashboard extends React.Component {
showDialog: this.showDialog.bind(this), showDialog: this.showDialog.bind(this),
api: this.api, api: this.api,
info: this.state.info, info: this.state.info,
locale: this.locale,
onUpdateLocale: this.onUpdateLocale.bind(this), onUpdateLocale: this.onUpdateLocale.bind(this),
onLogout: this.onLogout.bind(this), onLogout: this.onLogout.bind(this),
onLogin: this.onLogin.bind(this), onLogin: this.onLogin.bind(this),

@ -1,5 +1,5 @@
import React, {useState} from 'react'; import React, {useState} from 'react';
import {initLocale, L} from "shared/locale/locale"; import {L} from "shared/locale";
import {Box} from "@material-ui/core"; import {Box} from "@material-ui/core";
import {makeStyles} from "@material-ui/core/styles"; import {makeStyles} from "@material-ui/core/styles";
@ -20,8 +20,9 @@ export default function LanguageSelection(props) {
const onSetLanguage = (code) => { const onSetLanguage = (code) => {
api.setLanguageByCode(code).then((res) => { api.setLanguageByCode(code).then((res) => {
if (res.success) { if (res.success) {
initLocale(code);
props.onUpdateLocale(); props.onUpdateLocale();
} else {
alert(res.msg);
} }
}); });
}; };
@ -42,6 +43,6 @@ export default function LanguageSelection(props) {
} }
return <Box mt={1}> return <Box mt={1}>
{L("Language") + ": "} { flags } {L("general.language") + ": "} { flags }
</Box> </Box>
} }

@ -1,8 +1,6 @@
import ReactDOM from "react-dom"; import React from "react";
import {createRoot} from "react-dom/client";
import AdminDashboard from "./App"; import AdminDashboard from "./App";
const root = createRoot(document.getElementById('admin-panel'));
ReactDOM.render( root.render(<AdminDashboard />);
<AdminDashboard />,
document.getElementById('admin-panel')
);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -13,10 +13,11 @@ import {makeStyles} from '@material-ui/core/styles';
import {Alert} from '@material-ui/lab'; import {Alert} from '@material-ui/lab';
import React, {useCallback, useEffect, useState} from "react"; import React, {useCallback, useEffect, useState} from "react";
import {Navigate} from "react-router-dom"; import {Navigate} from "react-router-dom";
import {L} from "shared/locale/locale"; import {L} from "shared/locale";
import ReplayIcon from '@material-ui/icons/Replay'; import ReplayIcon from '@material-ui/icons/Replay';
import LanguageSelection from "../elements/language-selection"; import LanguageSelection from "../elements/language-selection";
import {decodeText, encodeText, getParameter, removeParameter} from "shared/util"; import {decodeText, encodeText, getParameter, removeParameter} from "shared/util";
import Icon from "shared/elements/icon";
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
paper: { paper: {
@ -79,13 +80,29 @@ export default function LoginForm(props) {
let [tfaCode, set2FACode] = useState(""); let [tfaCode, set2FACode] = useState("");
let [tfaState, set2FAState] = useState(0); // 0: not sent, 1: sent, 2: retry let [tfaState, set2FAState] = useState(0); // 0: not sent, 1: sent, 2: retry
let [tfaError, set2FAError] = useState(""); let [tfaError, set2FAError] = useState("");
let [error, setError] = useState("");
let [loaded, setLoaded] = useState(0);
const getNextUrl = () => { const getNextUrl = () => {
return getParameter("next") || "/admin"; return getParameter("next") || "/admin";
} }
const onUpdateLocale = useCallback(() => {
api.getLanguageEntries(["general", "account"]).then(data => {
setLoaded(loaded + 1);
if (!data.success) {
alert(data.msg);
}
});
}, [loaded]);
useEffect(() => {
onUpdateLocale();
}, []);
const onLogin = useCallback(() => { const onLogin = useCallback(() => {
if (!isLoggingIn) { if (!isLoggingIn) {
setError("");
setLoggingIn(true); setLoggingIn(true);
removeParameter("success"); removeParameter("success");
props.onLogin(username, password, rememberMe, (res) => { props.onLogin(username, password, rememberMe, (res) => {
@ -94,6 +111,7 @@ export default function LoginForm(props) {
setPassword(""); setPassword("");
if (!res.success) { if (!res.success) {
setEmailConfirmed(res.emailConfirmed); setEmailConfirmed(res.emailConfirmed);
setError(res.msg);
} }
}); });
} }
@ -162,24 +180,24 @@ export default function LoginForm(props) {
// 2FA // 2FA
if (api.loggedIn && api.user["2fa"]) { if (api.loggedIn && api.user["2fa"]) {
return <> return <>
<div>Additional information is required for logging in: {api.user["2fa"].type}</div> <div>{L("account.2fa_title")}: {api.user["2fa"].type}</div>
{ api.user["2fa"].type === "totp" ? { api.user["2fa"].type === "totp" ?
<TextField <TextField
variant="outlined" margin="normal" variant="outlined" margin="normal"
id="code" label={L("6-Digit Code")} name="code" id="code" label={L("account.6_digit_code")} name="code"
autoComplete="code" autoComplete="code"
required fullWidth autoFocus required fullWidth autoFocus
value={tfaCode} onChange={(e) => set2FACode(e.target.value)} value={tfaCode} onChange={(e) => set2FACode(e.target.value)}
/> : <> /> : <>
Plugin your 2FA-Device. Interaction might be required, e.g. typing in a PIN or touching it. {L("account.2fa_text")}
<Box mt={2} textAlign={"center"}> <Box mt={2} textAlign={"center"}>
{tfaState !== 2 {tfaState !== 2
? <CircularProgress/> ? <CircularProgress/>
: <div className={classes.error2FA}> : <div className={classes.error2FA}>
<div>{L("Something went wrong:")}<br />{tfaError}</div> <div>{L("general.something_went_wrong")}:<br />{tfaError}</div>
<Button onClick={() => set2FAState(0)} <Button onClick={() => set2FAState(0)}
variant={"outlined"} color={"secondary"} size={"small"}> variant={"outlined"} color={"secondary"} size={"small"}>
<ReplayIcon />&nbsp;{L("Retry")} <ReplayIcon />&nbsp;{L("general.retry")}
</Button> </Button>
</div> </div>
} }
@ -187,7 +205,7 @@ export default function LoginForm(props) {
</> </>
} }
{ {
props.error ? <Alert severity="error">{props.error}</Alert> : <></> error ? <Alert severity="error">{error}</Alert> : <></>
} }
<Grid container spacing={2} className={classes.buttons2FA}> <Grid container spacing={2} className={classes.buttons2FA}>
<Grid item xs={6}> <Grid item xs={6}>
@ -196,7 +214,7 @@ export default function LoginForm(props) {
color="inherit" size={"medium"} color="inherit" size={"medium"}
disabled={isLoggingIn} disabled={isLoggingIn}
onClick={onCancel2FA}> onClick={onCancel2FA}>
{L("Go back")} {L("general.go_back")}
</Button> </Button>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
@ -206,8 +224,8 @@ export default function LoginForm(props) {
disabled={isLoggingIn || api.user["2fa"].type !== "totp"} disabled={isLoggingIn || api.user["2fa"].type !== "totp"}
onClick={onSubmit2FA}> onClick={onSubmit2FA}>
{isLoggingIn ? {isLoggingIn ?
<>{L("Submitting…")} <CircularProgress size={15}/></> : <>{L("general.submitting")} <CircularProgress size={15}/></> :
L("Submit") L("general.submit")
} }
</Button> </Button>
</Grid> </Grid>
@ -218,35 +236,35 @@ export default function LoginForm(props) {
return <> return <>
<TextField <TextField
variant="outlined" margin="normal" variant="outlined" margin="normal"
id="username" label={L("Username")} name="username" id="username" label={L("account.username")} name="username"
autoComplete="username" disabled={isLoggingIn} autoComplete="username" disabled={isLoggingIn}
required fullWidth autoFocus required fullWidth autoFocus
value={username} onChange={(e) => setUsername(e.target.value)} value={username} onChange={(e) => setUsername(e.target.value)}
/> />
<TextField <TextField
variant="outlined" margin="normal" variant="outlined" margin="normal"
name="password" label={L("Password")} type="password" id="password" name="password" label={L("account.password")} type="password" id="password"
autoComplete="current-password" autoComplete="current-password"
required fullWidth disabled={isLoggingIn} required fullWidth disabled={isLoggingIn}
value={password} onChange={(e) => setPassword(e.target.value)} value={password} onChange={(e) => setPassword(e.target.value)}
/> />
<FormControlLabel <FormControlLabel
control={<Checkbox value="remember" color="primary"/>} control={<Checkbox value="remember" color="primary"/>}
label={L("Remember me")} label={L("account.remember_me")}
checked={rememberMe} onClick={(e) => setRememberMe(!rememberMe)} checked={rememberMe} onClick={(e) => setRememberMe(!rememberMe)}
/> />
{ {
props.error ? error
<Alert severity="error"> ? <Alert severity="error">
{props.error} {error}
{emailConfirmed === false {emailConfirmed === false
? <> <Link href={"/resendConfirmation"}>Click here</Link> to resend the confirmation email.</> ? <> <Link href={"/resendConfirmation"}>Click here</Link> to resend the confirmation email.</>
: <></> : <></>
} }
</Alert> : </Alert>
successMessage : (successMessage
? <Alert severity="success">{successMessage}</Alert> ? <Alert severity="success">{successMessage}</Alert>
: <></> : <></>)
} }
<Button <Button
type={"submit"} fullWidth variant={"contained"} type={"submit"} fullWidth variant={"contained"}
@ -255,20 +273,20 @@ export default function LoginForm(props) {
disabled={isLoggingIn} disabled={isLoggingIn}
onClick={onLogin}> onClick={onLogin}>
{isLoggingIn ? {isLoggingIn ?
<>{L("Signing in")} <CircularProgress size={15}/></> : <>{L("account.signing_in")} <CircularProgress size={15}/></> :
L("Sign In") L("account.sign_in")
} }
</Button> </Button>
<Grid container> <Grid container>
<Grid item xs> <Grid item xs>
<Link href="/resetPassword" variant="body2"> <Link href="/resetPassword" variant="body2">
{L("Forgot password?")} {L("account.forgot_password")}
</Link> </Link>
</Grid> </Grid>
{ props.info.registrationAllowed ? { props.info.registrationAllowed ?
<Grid item> <Grid item>
<Link href="/register" variant="body2"> <Link href="/register" variant="body2">
{L("Don't have an account? Sign Up")} {L("account.register_text")}
</Link> </Link>
</Grid> : <></> </Grid> : <></>
} }
@ -276,6 +294,10 @@ export default function LoginForm(props) {
</> </>
} }
if (loaded === 0) {
return <b>{L("general.loading")} <Icon icon={"spinner"}/></b>
}
let successMessage = getParameter("success"); let successMessage = getParameter("success");
return <Container maxWidth={"xs"} className={classes.container}> return <Container maxWidth={"xs"} className={classes.container}>
<div className={classes.paper}> <div className={classes.paper}>
@ -287,7 +309,7 @@ export default function LoginForm(props) {
</div> </div>
<form className={classes.form} onSubmit={(e) => e.preventDefault()}> <form className={classes.form} onSubmit={(e) => e.preventDefault()}>
{ createForm() } { createForm() }
<LanguageSelection api={api} locale={props.locale} onUpdateLocale={props.onUpdateLocale}/> <LanguageSelection api={api} onUpdateLocale={onUpdateLocale} />
</form> </form>
</div> </div>
</Container> </Container>

@ -13,14 +13,15 @@
"admin-panel" "admin-panel"
], ],
"scripts": { "scripts": {
"build": "npx parcel build", "build": "parcel build",
"deploy": "cp -r dist/* ../js/", "deploy": "cp -r dist/* ../js/",
"clean": "rm -rfd .parcel-cache dist/*" "clean": "rm -rfd .parcel-cache dist/*"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@babel/core": "^7.20.2", "@babel/core": "^7.20.5",
"@babel/plugin-transform-react-jsx": "^7.19.0",
"customize-cra": "^1.0.0", "customize-cra": "^1.0.0",
"parcel": "^2.8.0", "parcel": "^2.8.0",
"react-app-rewired": "^2.2.1", "react-app-rewired": "^2.2.1",
@ -40,5 +41,17 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router-dom": "^6.4.3" "react-router-dom": "^6.4.3"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
} }
} }

@ -1,3 +1,5 @@
import {Locale} from "./locale";
export default class API { export default class API {
constructor() { constructor() {
this.loggedIn = false; this.loggedIn = false;
@ -136,11 +138,69 @@ export default class API {
return this.apiCall("language/get"); return this.apiCall("language/get");
} }
async setLanguage(params) {
let res = await this.apiCall("language/set", params);
if (res.success) {
Locale.getInstance().setLocale(res.language.code);
}
return res;
}
async setLanguageByCode(code) { async setLanguageByCode(code) {
return this.apiCall("language/set", { code: code }); return this.setLanguage({ code: code });
} }
async setLanguageByName(name) { async setLanguageByName(name) {
return this.apiCall("language/set", { name: name }); return this.setLanguage({ name: name });
}
async getLanguageEntries(modules, code=null, useCache=true) {
if (!Array.isArray(modules)) {
modules = [modules];
}
let locale = Locale.getInstance();
if (code === null) {
code = locale.currentLocale;
if (code === null && this.loggedIn) {
code = this.user.language.code;
}
}
if (code === null) {
return { success: false, msg: "No locale selected currently" };
}
let languageEntries = {};
if (useCache) {
// remove cached modules from request array
for (const module of [...modules]) {
let moduleEntries = locale.getModule(code, module);
if (moduleEntries) {
modules.splice(modules.indexOf(module), 1);
languageEntries = {...languageEntries, [module]: moduleEntries};
}
}
}
if (modules.length > 0) {
let data = await this.apiCall("language/getEntries", { code: code, modules: modules });
if (useCache) {
if (data && data.success) {
// insert into cache
for (const [module, entries] of Object.entries(data.entries)) {
locale.loadModule(code, module, entries);
}
data.entries = {...data.entries, ...languageEntries};
data.cached = false;
}
}
return data;
} else {
return { success: true, msg: "", entries: languageEntries, code: code, cached: true };
}
} }
}; };

67
react/shared/locale.js Normal file

@ -0,0 +1,67 @@
// application-wide global variables // translation cache
class Locale {
constructor() {
this.entries = {};
this.currentLocale = "en_US";
}
translate(key) {
if (this.currentLocale) {
if (this.entries.hasOwnProperty(this.currentLocale)) {
let [module, variable] = key.split(".");
if (module && variable && this.entries[this.currentLocale].hasOwnProperty(module)) {
let translation = this.entries[this.currentLocale][module][variable];
if (translation) {
return translation;
}
}
}
}
return "[" + key + "]";
}
setLocale(code) {
this.currentLocale = code;
if (!this.entries.hasOwnProperty(code)) {
this.entries[code] = {};
}
}
loadModule(code, module, newEntries) {
if (!this.entries.hasOwnProperty(code)) {
this.entries[code] = {};
}
if (this.entries[code].hasOwnProperty(module)) {
this.entries[code][module] = {...this.entries[code][module], ...newEntries};
} else {
this.entries[code][module] = newEntries;
}
}
hasModule(code, module) {
return this.entries.hasOwnProperty(code) && !!this.entries[code][module];
}
getModule(code, module) {
if (this.hasModule(code, module)) {
return this.entries[code][module];
} else {
return null;
}
}
static getInstance() {
return INSTANCE;
}
}
let INSTANCE = new Locale();
function L(key) {
return Locale.getInstance().translate(key);
}
export { L, Locale };

@ -1,14 +0,0 @@
import React from "react";
import { enUS as dateFnsEN } from "date-fns/locale/index.js";
export default class LocaleEnglish {
constructor() {
this.code = "en_US";
this.name = "American English";
this.entries = {};
}
toDateFns() {
return dateFnsEN;
}
};

@ -1,14 +0,0 @@
import React from "react";
import { de as dateFnsDE } from "date-fns/locale/index.js";
export default class LocaleGerman {
constructor() {
this.code = "de_DE";
this.name = "Deutsch Standard";
this.entries = {};
}
toDateFns() {
return dateFnsDE;
}
}

@ -1,35 +0,0 @@
import LocaleGerman from "./german";
import LocaleEnglish from "./english";
let INSTANCE = new LocaleEnglish();
function initLocale(code) {
if (!INSTANCE || INSTANCE.code !== code) {
const constructors = {
"de_DE": LocaleGerman,
"en_US": LocaleEnglish,
}
if (constructors.hasOwnProperty(code)) {
INSTANCE = new (constructors[code])();
} else {
INSTANCE = { code: code, entries: { } };
}
}
return INSTANCE;
}
function translate(key) {
return (INSTANCE.entries[key] || key);
}
function useLanguageModule(module) {
if (module[INSTANCE.code]) {
for (const [key, value] of Object.entries(module[INSTANCE.code])) {
INSTANCE.entries[key] = value;
}
}
}
export { translate as L, initLocale, useLanguageModule, INSTANCE as currentLocale };

@ -27,25 +27,25 @@
"@babel/highlight" "^7.18.6" "@babel/highlight" "^7.18.6"
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1":
version "7.20.1" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.5.tgz#86f172690b093373a933223b4745deeb6049e733"
integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== integrity sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==
"@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.20.2", "@babel/core@^7.7.2", "@babel/core@^7.8.0": "@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.20.5", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
version "7.20.2" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.2.tgz#8dc9b1620a673f92d3624bd926dc49a52cf25b92" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.5.tgz#45e2114dc6cd4ab167f81daf7820e8fa1250d113"
integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g== integrity sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==
dependencies: dependencies:
"@ampproject/remapping" "^2.1.0" "@ampproject/remapping" "^2.1.0"
"@babel/code-frame" "^7.18.6" "@babel/code-frame" "^7.18.6"
"@babel/generator" "^7.20.2" "@babel/generator" "^7.20.5"
"@babel/helper-compilation-targets" "^7.20.0" "@babel/helper-compilation-targets" "^7.20.0"
"@babel/helper-module-transforms" "^7.20.2" "@babel/helper-module-transforms" "^7.20.2"
"@babel/helpers" "^7.20.1" "@babel/helpers" "^7.20.5"
"@babel/parser" "^7.20.2" "@babel/parser" "^7.20.5"
"@babel/template" "^7.18.10" "@babel/template" "^7.18.10"
"@babel/traverse" "^7.20.1" "@babel/traverse" "^7.20.5"
"@babel/types" "^7.20.2" "@babel/types" "^7.20.5"
convert-source-map "^1.7.0" convert-source-map "^1.7.0"
debug "^4.1.0" debug "^4.1.0"
gensync "^1.0.0-beta.2" gensync "^1.0.0-beta.2"
@ -61,12 +61,12 @@
eslint-visitor-keys "^2.1.0" eslint-visitor-keys "^2.1.0"
semver "^6.3.0" semver "^6.3.0"
"@babel/generator@^7.20.1", "@babel/generator@^7.20.2", "@babel/generator@^7.7.2": "@babel/generator@^7.20.5", "@babel/generator@^7.7.2":
version "7.20.4" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.5.tgz#cb25abee3178adf58d6814b68517c62bdbfdda95"
integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA== integrity sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==
dependencies: dependencies:
"@babel/types" "^7.20.2" "@babel/types" "^7.20.5"
"@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/gen-mapping" "^0.3.2"
jsesc "^2.5.1" jsesc "^2.5.1"
@ -95,10 +95,10 @@
browserslist "^4.21.3" browserslist "^4.21.3"
semver "^6.3.0" semver "^6.3.0"
"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.2": "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.2", "@babel/helper-create-class-features-plugin@^7.20.5":
version "7.20.2" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz#3c08a5b5417c7f07b5cf3dfb6dc79cbec682e8c2" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.5.tgz#327154eedfb12e977baa4ecc72e5806720a85a06"
integrity sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA== integrity sha512-3RCdA/EmEaikrhayahwToF0fpweU/8o2p8vhc1c/1kftHOdTKuC65kik/TLc+qfbS8JKw4qqJbne4ovICDhmww==
dependencies: dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-annotate-as-pure" "^7.18.6"
"@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-environment-visitor" "^7.18.9"
@ -108,13 +108,13 @@
"@babel/helper-replace-supers" "^7.19.1" "@babel/helper-replace-supers" "^7.19.1"
"@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6"
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5":
version "7.19.0" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz#5ea79b59962a09ec2acf20a963a01ab4d076ccca"
integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== integrity sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w==
dependencies: dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-annotate-as-pure" "^7.18.6"
regexpu-core "^5.1.0" regexpu-core "^5.2.1"
"@babel/helper-define-polyfill-provider@^0.3.3": "@babel/helper-define-polyfill-provider@^0.3.3":
version "0.3.3" version "0.3.3"
@ -253,23 +253,23 @@
integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==
"@babel/helper-wrap-function@^7.18.9": "@babel/helper-wrap-function@^7.18.9":
version "7.19.0" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3"
integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==
dependencies: dependencies:
"@babel/helper-function-name" "^7.19.0" "@babel/helper-function-name" "^7.19.0"
"@babel/template" "^7.18.10" "@babel/template" "^7.18.10"
"@babel/traverse" "^7.19.0" "@babel/traverse" "^7.20.5"
"@babel/types" "^7.19.0" "@babel/types" "^7.20.5"
"@babel/helpers@^7.20.1": "@babel/helpers@^7.20.5":
version "7.20.1" version "7.20.6"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.6.tgz#e64778046b70e04779dfbdf924e7ebb45992c763"
integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg== integrity sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==
dependencies: dependencies:
"@babel/template" "^7.18.10" "@babel/template" "^7.18.10"
"@babel/traverse" "^7.20.1" "@babel/traverse" "^7.20.5"
"@babel/types" "^7.20.0" "@babel/types" "^7.20.5"
"@babel/highlight@^7.18.6": "@babel/highlight@^7.18.6":
version "7.18.6" version "7.18.6"
@ -280,10 +280,10 @@
chalk "^2.0.0" chalk "^2.0.0"
js-tokens "^4.0.0" js-tokens "^4.0.0"
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2": "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.20.5":
version "7.20.3" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8"
integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg== integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
version "7.18.6" version "7.18.6"
@ -329,11 +329,11 @@
"@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-class-static-block" "^7.14.5"
"@babel/plugin-proposal-decorators@^7.16.4": "@babel/plugin-proposal-decorators@^7.16.4":
version "7.20.2" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.20.2.tgz#1c6c32b2a44b154ebeec2bb534f9eaebdb541fb6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.20.5.tgz#28ba1a0e5044664a512967a19407d7fc26925394"
integrity sha512-nkBH96IBmgKnbHQ5gXFrcmez+Z9S2EIDKDQGp005ROqBigc88Tky4rzCnlP/lnlj245dCEQl4/YyV0V1kYh5dw== integrity sha512-Lac7PpRJXcC3s9cKsBfl+uc+DYXU5FD06BrTFunQO6QIQT+DwyzDPURAowI3bcvD1dZF/ank1Z5rstUJn3Hn4Q==
dependencies: dependencies:
"@babel/helper-create-class-features-plugin" "^7.20.2" "@babel/helper-create-class-features-plugin" "^7.20.5"
"@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-plugin-utils" "^7.20.2"
"@babel/helper-replace-supers" "^7.19.1" "@babel/helper-replace-supers" "^7.19.1"
"@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6"
@ -424,13 +424,13 @@
"@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-proposal-private-property-in-object@^7.18.6": "@babel/plugin-proposal-private-property-in-object@^7.18.6":
version "7.18.6" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz#309c7668f2263f1c711aa399b5a9a6291eef6135"
integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== integrity sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ==
dependencies: dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-annotate-as-pure" "^7.18.6"
"@babel/helper-create-class-features-plugin" "^7.18.6" "@babel/helper-create-class-features-plugin" "^7.20.5"
"@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": "@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
@ -612,9 +612,9 @@
"@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-transform-block-scoping@^7.20.2": "@babel/plugin-transform-block-scoping@^7.20.2":
version "7.20.2" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.2.tgz#f59b1767e6385c663fd0bce655db6ca9c8b236ed" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.5.tgz#401215f9dc13dc5262940e2e527c9536b3d7f237"
integrity sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ== integrity sha512-WvpEIW9Cbj9ApF3yJCjIEEf1EiNJLtXagOrL5LNWEZOo3jv8pmPoYTSNJQvqej8OavVlgOoOPw6/htGZro6IkA==
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-plugin-utils" "^7.20.2"
@ -744,12 +744,12 @@
"@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": "@babel/plugin-transform-named-capturing-groups-regex@^7.19.1":
version "7.19.1" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8"
integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==
dependencies: dependencies:
"@babel/helper-create-regexp-features-plugin" "^7.19.0" "@babel/helper-create-regexp-features-plugin" "^7.20.5"
"@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-transform-new-target@^7.18.6": "@babel/plugin-transform-new-target@^7.18.6":
version "7.18.6" version "7.18.6"
@ -767,9 +767,9 @@
"@babel/helper-replace-supers" "^7.18.6" "@babel/helper-replace-supers" "^7.18.6"
"@babel/plugin-transform-parameters@^7.20.1": "@babel/plugin-transform-parameters@^7.20.1":
version "7.20.3" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.3.tgz#7b3468d70c3c5b62e46be0a47b6045d8590fb748" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.5.tgz#f8f9186c681d10c3de7620c916156d893c8a019e"
integrity sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA== integrity sha512-h7plkOmcndIUWXZFLgpbrh2+fXAi47zcUX7IrOQuZdLD0I0KvjJ6cvo3BEcAOsDOcZhVKGJqv07mkSqK0y2isQ==
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-plugin-utils" "^7.20.2"
@ -801,7 +801,7 @@
dependencies: dependencies:
"@babel/plugin-transform-react-jsx" "^7.18.6" "@babel/plugin-transform-react-jsx" "^7.18.6"
"@babel/plugin-transform-react-jsx@^7.18.6": "@babel/plugin-transform-react-jsx@^7.18.6", "@babel/plugin-transform-react-jsx@^7.19.0":
version "7.19.0" version "7.19.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9"
integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==
@ -821,12 +821,12 @@
"@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-transform-regenerator@^7.18.6": "@babel/plugin-transform-regenerator@^7.18.6":
version "7.18.6" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz#57cda588c7ffb7f4f8483cc83bdcea02a907f04d"
integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== integrity sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-plugin-utils" "^7.20.2"
regenerator-transform "^0.15.0" regenerator-transform "^0.15.1"
"@babel/plugin-transform-reserved-words@^7.18.6": "@babel/plugin-transform-reserved-words@^7.18.6":
version "7.18.6" version "7.18.6"
@ -1021,19 +1021,19 @@
"@babel/plugin-transform-typescript" "^7.18.6" "@babel/plugin-transform-typescript" "^7.18.6"
"@babel/runtime-corejs3@^7.10.2": "@babel/runtime-corejs3@^7.10.2":
version "7.20.1" version "7.20.6"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.20.1.tgz#d0775a49bb5fba77e42cbb7276c9955c7b05af8d" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.20.6.tgz#63dae945963539ab0ad578efbf3eff271e7067ae"
integrity sha512-CGulbEDcg/ND1Im7fUNRZdGXmX2MTWVVZacQi/6DiKE5HNwZ3aVTm5PV4lO8HHz0B2h8WQyvKKjbX5XgTtydsg== integrity sha512-tqeujPiuEfcH067mx+7otTQWROVMKHXEaOQcAeNV5dDdbPWvPcFA8/W9LXw2NfjNmOetqLl03dfnG2WALPlsRQ==
dependencies: dependencies:
core-js-pure "^3.25.1" core-js-pure "^3.25.1"
regenerator-runtime "^0.13.10" regenerator-runtime "^0.13.11"
"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
version "7.20.1" version "7.20.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3"
integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg== integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==
dependencies: dependencies:
regenerator-runtime "^0.13.10" regenerator-runtime "^0.13.11"
"@babel/template@^7.18.10", "@babel/template@^7.3.3": "@babel/template@^7.18.10", "@babel/template@^7.3.3":
version "7.18.10" version "7.18.10"
@ -1044,26 +1044,26 @@
"@babel/parser" "^7.18.10" "@babel/parser" "^7.18.10"
"@babel/types" "^7.18.10" "@babel/types" "^7.18.10"
"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.7.2": "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.20.5", "@babel/traverse@^7.7.2":
version "7.20.1" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.5.tgz#78eb244bea8270fdda1ef9af22a5d5e5b7e57133"
integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== integrity sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==
dependencies: dependencies:
"@babel/code-frame" "^7.18.6" "@babel/code-frame" "^7.18.6"
"@babel/generator" "^7.20.1" "@babel/generator" "^7.20.5"
"@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-environment-visitor" "^7.18.9"
"@babel/helper-function-name" "^7.19.0" "@babel/helper-function-name" "^7.19.0"
"@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-hoist-variables" "^7.18.6"
"@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6"
"@babel/parser" "^7.20.1" "@babel/parser" "^7.20.5"
"@babel/types" "^7.20.0" "@babel/types" "^7.20.5"
debug "^4.1.0" debug "^4.1.0"
globals "^11.1.0" globals "^11.1.0"
"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": "@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
version "7.20.2" version "7.20.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.2.tgz#67ac09266606190f496322dbaff360fdaa5e7842" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.5.tgz#e206ae370b5393d94dfd1d04cd687cace53efa84"
integrity sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog== integrity sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==
dependencies: dependencies:
"@babel/helper-string-parser" "^7.19.4" "@babel/helper-string-parser" "^7.19.4"
"@babel/helper-validator-identifier" "^7.19.1" "@babel/helper-validator-identifier" "^7.19.1"
@ -2255,9 +2255,9 @@
nullthrows "^1.1.1" nullthrows "^1.1.1"
"@pmmmwh/react-refresh-webpack-plugin@^0.5.3": "@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
version "0.5.9" version "0.5.10"
resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.9.tgz#35aae6624a6270ca7ad755800b7eec417fa6f830" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz#2eba163b8e7dbabb4ce3609ab5e32ab63dda3ef8"
integrity sha512-7QV4cqUwhkDIHpMAZ9mestSJ2DMIotVTbOUwbiudhjCRTAWWKIaBecELiEM2LT3AHFeOAaHIcFu4dbXjX+9GBA== integrity sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==
dependencies: dependencies:
ansi-html-community "^0.0.8" ansi-html-community "^0.0.8"
common-path-prefix "^3.0.0" common-path-prefix "^3.0.0"
@ -2265,7 +2265,7 @@
error-stack-parser "^2.0.6" error-stack-parser "^2.0.6"
find-up "^5.0.0" find-up "^5.0.0"
html-entities "^2.1.0" html-entities "^2.1.0"
loader-utils "^2.0.3" loader-utils "^2.0.4"
schema-utils "^3.0.0" schema-utils "^3.0.0"
source-map "^0.7.3" source-map "^0.7.3"
@ -2322,9 +2322,9 @@
integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==
"@sinonjs/commons@^1.7.0": "@sinonjs/commons@^1.7.0":
version "1.8.5" version "1.8.6"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.5.tgz#e280c94c95f206dcfd5aca00a43f2156b758c764" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9"
integrity sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA== integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==
dependencies: dependencies:
type-detect "4.0.8" type-detect "4.0.8"
@ -2492,9 +2492,9 @@
"@babel/types" "^7.0.0" "@babel/types" "^7.0.0"
"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": "@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6":
version "7.18.2" version "7.18.3"
resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.2.tgz#235bf339d17185bdec25e024ca19cce257cc7309" resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.3.tgz#dfc508a85781e5698d5b33443416b6268c4b3e8d"
integrity sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg== integrity sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==
dependencies: dependencies:
"@babel/types" "^7.3.0" "@babel/types" "^7.3.0"
@ -2756,20 +2756,20 @@
"@types/yargs-parser" "*" "@types/yargs-parser" "*"
"@types/yargs@^17.0.8": "@types/yargs@^17.0.8":
version "17.0.14" version "17.0.15"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.14.tgz#0943473052c24bd8cf2d1de25f1a710259327237" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.15.tgz#5b62c89fb049e2fc8378394a2861a593055f0866"
integrity sha512-9Pj7abXoW1RSTcZaL2Hk6G2XyLMlp5ECdVC/Zf2p/KBjC3srijLGgRAXOBjtFrJoIrvxdTKyKDA14bEcbxBaWw== integrity sha512-ZHc4W2dnEQPfhn06TBEdWaiUHEZAocYaiVMfwOipY5jcJt/251wVrKCBWBetGZWO5CF8tdb7L3DmdxVlZ2BOIg==
dependencies: dependencies:
"@types/yargs-parser" "*" "@types/yargs-parser" "*"
"@typescript-eslint/eslint-plugin@^5.5.0": "@typescript-eslint/eslint-plugin@^5.5.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.44.0.tgz#105788f299050c917eb85c4d9fd04b089e3740de" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.45.0.tgz#ffa505cf961d4844d38cfa19dcec4973a6039e41"
integrity sha512-j5ULd7FmmekcyWeArx+i8x7sdRHzAtXTkmDPthE4amxZOWKFK7bomoJ4r7PJ8K7PoMzD16U8MmuZFAonr1ERvw== integrity sha512-CXXHNlf0oL+Yg021cxgOdMHNTXD17rHkq7iW6RFHoybdFgQBjU3yIXhhcPpGwr1CjZlo6ET8C6tzX5juQoXeGA==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.44.0" "@typescript-eslint/scope-manager" "5.45.0"
"@typescript-eslint/type-utils" "5.44.0" "@typescript-eslint/type-utils" "5.45.0"
"@typescript-eslint/utils" "5.44.0" "@typescript-eslint/utils" "5.45.0"
debug "^4.3.4" debug "^4.3.4"
ignore "^5.2.0" ignore "^5.2.0"
natural-compare-lite "^1.4.0" natural-compare-lite "^1.4.0"
@ -2778,78 +2778,78 @@
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/experimental-utils@^5.0.0": "@typescript-eslint/experimental-utils@^5.0.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.44.0.tgz#51ee9699532270ce3c95e2dee4313d18c24fad56" resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.45.0.tgz#b59fea61a855cb2b1fdbd0fb45934a844f4bf870"
integrity sha512-j8GLemAySe8oUCgILdUaT66pemdWSYcwUYG2Pb71O119hCdvkU+4q8sUTbnDg8NhlZEzSWG2N1v4IxT1kEZrGg== integrity sha512-DnRQg5+3uHHt/gaifTjwg9OKbg9/TWehfJzYHQIDJboPEbF897BKDE/qoqMhW7nf0jWRV1mwVXTaUvtB1/9Gwg==
dependencies: dependencies:
"@typescript-eslint/utils" "5.44.0" "@typescript-eslint/utils" "5.45.0"
"@typescript-eslint/parser@^5.5.0": "@typescript-eslint/parser@^5.5.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.44.0.tgz#99e2c710a2252191e7a79113264f438338b846ad" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.45.0.tgz#b18a5f6b3cf1c2b3e399e9d2df4be40d6b0ddd0e"
integrity sha512-H7LCqbZnKqkkgQHaKLGC6KUjt3pjJDx8ETDqmwncyb6PuoigYajyAwBGz08VU/l86dZWZgI4zm5k2VaKqayYyA== integrity sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.44.0" "@typescript-eslint/scope-manager" "5.45.0"
"@typescript-eslint/types" "5.44.0" "@typescript-eslint/types" "5.45.0"
"@typescript-eslint/typescript-estree" "5.44.0" "@typescript-eslint/typescript-estree" "5.45.0"
debug "^4.3.4" debug "^4.3.4"
"@typescript-eslint/scope-manager@5.44.0": "@typescript-eslint/scope-manager@5.45.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.44.0.tgz#988c3f34b45b3474eb9ff0674c18309dedfc3e04" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.45.0.tgz#7a4ac1bfa9544bff3f620ab85947945938319a96"
integrity sha512-2pKml57KusI0LAhgLKae9kwWeITZ7IsZs77YxyNyIVOwQ1kToyXRaJLl+uDEXzMN5hnobKUOo2gKntK9H1YL8g== integrity sha512-noDMjr87Arp/PuVrtvN3dXiJstQR1+XlQ4R1EvzG+NMgXi8CuMCXpb8JqNtFHKceVSQ985BZhfRdowJzbv4yKw==
dependencies: dependencies:
"@typescript-eslint/types" "5.44.0" "@typescript-eslint/types" "5.45.0"
"@typescript-eslint/visitor-keys" "5.44.0" "@typescript-eslint/visitor-keys" "5.45.0"
"@typescript-eslint/type-utils@5.44.0": "@typescript-eslint/type-utils@5.45.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.44.0.tgz#bc5a6e8a0269850714a870c9268c038150dfb3c7" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.45.0.tgz#aefbc954c40878fcebeabfb77d20d84a3da3a8b2"
integrity sha512-A1u0Yo5wZxkXPQ7/noGkRhV4J9opcymcr31XQtOzcc5nO/IHN2E2TPMECKWYpM3e6olWEM63fq/BaL1wEYnt/w== integrity sha512-DY7BXVFSIGRGFZ574hTEyLPRiQIvI/9oGcN8t1A7f6zIs6ftbrU0nhyV26ZW//6f85avkwrLag424n+fkuoJ1Q==
dependencies: dependencies:
"@typescript-eslint/typescript-estree" "5.44.0" "@typescript-eslint/typescript-estree" "5.45.0"
"@typescript-eslint/utils" "5.44.0" "@typescript-eslint/utils" "5.45.0"
debug "^4.3.4" debug "^4.3.4"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/types@5.44.0": "@typescript-eslint/types@5.45.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.44.0.tgz#f3f0b89aaff78f097a2927fe5688c07e786a0241" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.45.0.tgz#794760b9037ee4154c09549ef5a96599621109c5"
integrity sha512-Tp+zDnHmGk4qKR1l+Y1rBvpjpm5tGXX339eAlRBDg+kgZkz9Bw+pqi4dyseOZMsGuSH69fYfPJCBKBrbPCxYFQ== integrity sha512-QQij+u/vgskA66azc9dCmx+rev79PzX8uDHpsqSjEFtfF2gBUTRCpvYMh2gw2ghkJabNkPlSUCimsyBEQZd1DA==
"@typescript-eslint/typescript-estree@5.44.0": "@typescript-eslint/typescript-estree@5.45.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.44.0.tgz#0461b386203e8d383bb1268b1ed1da9bc905b045" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.0.tgz#f70a0d646d7f38c0dfd6936a5e171a77f1e5291d"
integrity sha512-M6Jr+RM7M5zeRj2maSfsZK2660HKAJawv4Ud0xT+yauyvgrsHu276VtXlKDFnEmhG+nVEd0fYZNXGoAgxwDWJw== integrity sha512-maRhLGSzqUpFcZgXxg1qc/+H0bT36lHK4APhp0AEUVrpSwXiRAomm/JGjSG+kNUio5kAa3uekCYu/47cnGn5EQ==
dependencies: dependencies:
"@typescript-eslint/types" "5.44.0" "@typescript-eslint/types" "5.45.0"
"@typescript-eslint/visitor-keys" "5.44.0" "@typescript-eslint/visitor-keys" "5.45.0"
debug "^4.3.4" debug "^4.3.4"
globby "^11.1.0" globby "^11.1.0"
is-glob "^4.0.3" is-glob "^4.0.3"
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/utils@5.44.0", "@typescript-eslint/utils@^5.13.0": "@typescript-eslint/utils@5.45.0", "@typescript-eslint/utils@^5.13.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.44.0.tgz#d733da4d79d6c30f1a68b531cdda1e0c1f00d52d" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.45.0.tgz#9cca2996eee1b8615485a6918a5c763629c7acf5"
integrity sha512-fMzA8LLQ189gaBjS0MZszw5HBdZgVwxVFShCO3QN+ws3GlPkcy9YuS3U4wkT6su0w+Byjq3mS3uamy9HE4Yfjw== integrity sha512-OUg2JvsVI1oIee/SwiejTot2OxwU8a7UfTFMOdlhD2y+Hl6memUSL4s98bpUTo8EpVEr0lmwlU7JSu/p2QpSvA==
dependencies: dependencies:
"@types/json-schema" "^7.0.9" "@types/json-schema" "^7.0.9"
"@types/semver" "^7.3.12" "@types/semver" "^7.3.12"
"@typescript-eslint/scope-manager" "5.44.0" "@typescript-eslint/scope-manager" "5.45.0"
"@typescript-eslint/types" "5.44.0" "@typescript-eslint/types" "5.45.0"
"@typescript-eslint/typescript-estree" "5.44.0" "@typescript-eslint/typescript-estree" "5.45.0"
eslint-scope "^5.1.1" eslint-scope "^5.1.1"
eslint-utils "^3.0.0" eslint-utils "^3.0.0"
semver "^7.3.7" semver "^7.3.7"
"@typescript-eslint/visitor-keys@5.44.0": "@typescript-eslint/visitor-keys@5.45.0":
version "5.44.0" version "5.45.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.44.0.tgz#10740dc28902bb903d12ee3a005cc3a70207d433" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.0.tgz#e0d160e9e7fdb7f8da697a5b78e7a14a22a70528"
integrity sha512-a48tLG8/4m62gPFbJ27FxwCOqPKxsb8KC3HkmYoq2As/4YyjQl1jDbRr1s63+g4FS/iIehjmN3L5UjmKva1HzQ== integrity sha512-jc6Eccbn2RtQPr1s7th6jJWQHBHI6GBVQkCHoJFQ5UreaKm59Vxw+ynQUPPY2u2Amquc+7tmEoC2G52ApsGNNg==
dependencies: dependencies:
"@typescript-eslint/types" "5.44.0" "@typescript-eslint/types" "5.45.0"
eslint-visitor-keys "^3.3.0" eslint-visitor-keys "^3.3.0"
"@webassemblyjs/ast@1.11.1": "@webassemblyjs/ast@1.11.1":
@ -3613,9 +3613,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0" lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426: caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426:
version "1.0.30001434" version "1.0.30001435"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz#ec1ec1cfb0a93a34a0600d37903853030520a4e5" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001435.tgz#502c93dbd2f493bee73a408fe98e98fb1dad10b2"
integrity sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA== integrity sha512-kdCkUTjR+v4YAJelyiDTqiu82BDr4W4CP5sgTA0ZBmqn30XfS2ZghPLMowik9TPhS+psWJiUNxsqLyurDbmutA==
case-sensitive-paths-webpack-plugin@^2.4.0: case-sensitive-paths-webpack-plugin@^2.4.0:
version "2.4.0" version "2.4.0"
@ -3675,9 +3675,9 @@ chrome-trace-event@^1.0.2:
integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
ci-info@^3.2.0: ci-info@^3.2.0:
version "3.6.2" version "3.7.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.6.2.tgz#362ea15378f1c39378ba786affbc1c9ef015ecfd" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.0.tgz#6d01b3696c59915b6ce057e4aa4adfc2fa25f5ef"
integrity sha512-lVZdhvbEudris15CLytp2u6Y0p5EKfztae9Fqa189MfNmln9F33XuH69v5fvNfiRN5/0eAUz2yJL3mo+nhaRKg== integrity sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==
cjs-module-lexer@^1.0.0: cjs-module-lexer@^1.0.0:
version "1.2.2" version "1.2.2"
@ -4031,9 +4031,9 @@ css-what@^6.0.1:
integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
cssdb@^7.1.0: cssdb@^7.1.0:
version "7.1.0" version "7.2.0"
resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-7.1.0.tgz#574f97235a83eb753a29f0b1f2cbacac0d628bb8" resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-7.2.0.tgz#f44bd4abc430f0ff7f4c64b8a1fb857a753f77a8"
integrity sha512-Sd99PrFgx28ez4GHu8yoQIufc/70h9oYowDf4EjeIKi8mac9whxRjhM3IaMr6EllP6KKKWtJrMfN6C7T9tIWvQ== integrity sha512-JYlIsE7eKHSi0UNuCyo96YuIDFqvhGgHw4Ck6lsN+DP0Tp8M64UTDT2trGbkMDqnCoEjks7CkS0XcjU0rkvBdg==
cssesc@^3.0.0: cssesc@^3.0.0:
version "3.0.0" version "3.0.0"
@ -5562,9 +5562,9 @@ identity-obj-proxy@^3.0.0:
harmony-reflect "^1.4.6" harmony-reflect "^1.4.6"
ignore@^5.2.0: ignore@^5.2.0:
version "5.2.0" version "5.2.1"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c"
integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==
immer@^9.0.7: immer@^9.0.7:
version "9.0.16" version "9.0.16"
@ -6611,61 +6611,61 @@ levn@~0.3.0:
prelude-ls "~1.1.2" prelude-ls "~1.1.2"
type-check "~0.3.2" type-check "~0.3.2"
lightningcss-darwin-arm64@1.16.1: lightningcss-darwin-arm64@1.17.0:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.16.1.tgz#f67287c500b96bc5d21e6d04de0e2607ff2784ff" resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.17.0.tgz#c30e5f0c7419a3c88bb645fd1aa69573166c160b"
integrity sha512-/J898YSAiGVqdybHdIF3Ao0Hbh2vyVVj5YNm3NznVzTSvkOi3qQCAtO97sfmNz+bSRHXga7ZPLm+89PpOM5gAg== integrity sha512-k8/9PaFUZ7ISS5XGDo3RLRUoj1Yf0yNvjYsU4n8TqjE7kCZY0eJaYb6PFvFba1RQ2i3EX5SFiW9nxrEctU+o1A==
lightningcss-darwin-x64@1.16.1: lightningcss-darwin-x64@1.17.0:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.16.1.tgz#2dc89dd4e1eb3c39ca4abbeca769a276c206b038" resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.17.0.tgz#4ec0f17ff0234fd574a347f235af549beecefabe"
integrity sha512-vyKCNPRNRqke+5i078V+N0GLfMVLEaNcqIcv28hA/vUNRGk/90EDkDB9EndGay0MoPIrC2y0qE3Y74b/OyedqQ== integrity sha512-tkY6IsflCzU63/QlM5L+ygIRMnnJdx2l7ay7dphEhMw1I2Rf3vQli8N/Lj3MSxFe5srJwxv2leDM9VzVhKFm3Q==
lightningcss-linux-arm-gnueabihf@1.16.1: lightningcss-linux-arm-gnueabihf@1.17.0:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.16.1.tgz#9edacb0d9bd18fa1830a9d9f9ba00bdc9f8dabc9" resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.17.0.tgz#3d84b9ca8651dd1223ea7aec9ec4b5c889a57e25"
integrity sha512-0AJC52l40VbrzkMJz6qRvlqVVGykkR2MgRS4bLjVC2ab0H0I/n4p6uPZXGvNIt5gw1PedeND/hq+BghNdgfuPQ== integrity sha512-bvACFOvKv3Ls8d5OPG0sCCKV44/cr2UMDceWc4qXHQ3cKoeyduuqitYF9Ez6U7OmyI5B2MEXB8ttyRdr1oL/pg==
lightningcss-linux-arm64-gnu@1.16.1: lightningcss-linux-arm64-gnu@1.17.0:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.16.1.tgz#b6986324d21de3813b84432b51c3e7b019dd2224" resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.17.0.tgz#c36bca7226e1857ce21adac393051429401fc6cc"
integrity sha512-NqxYXsRvI3/Fb9AQLXKrYsU0Q61LqKz5It+Es9gidsfcw1lamny4lmlUgO3quisivkaLCxEkogaizcU6QeZeWQ== integrity sha512-tLX4TtLg5h8RQjZuB8qXJ9bi2i16e70E+hKXCAV84KgjcAkjcBq1f9xuo5NNg7/+gyLvzdpUEOtmMd5FK5dMqQ==
lightningcss-linux-arm64-musl@1.16.1: lightningcss-linux-arm64-musl@1.17.0:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.16.1.tgz#d13a01ed19a72c99b4ef9c5b9d8ee0dcdc4bf3ed" resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.17.0.tgz#cd88f0c0d994c13d5eb95126a95165b9cc30cc90"
integrity sha512-VUPQ4dmB9yDQxpJF8/imtwNcbIPzlL6ArLHSUInOGxipDk1lOAklhUjbKUvlL3HVlDwD3WHCxggAY01WpFcjiA== integrity sha512-HtXlBG7mKDBGqqxKzyFb4m7BeJhO2jc+KGwcNz/3BJcQLGDbUyInVHC2kwIDtlVQi5Ugn7Hg+Q/kSOyYdnuQ3A==
lightningcss-linux-x64-gnu@1.16.1: lightningcss-linux-x64-gnu@1.17.0:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.16.1.tgz#6c888ef4faac53333d6d2241da463c405b19ec79" resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.17.0.tgz#2f5afbd4f8f727d209f8013584f21611d4d521d0"
integrity sha512-A40Jjnbellnvh4YF+kt047GLnUU59iLN2LFRCyWQG+QqQZeXOCzXfTQ6EJB4yvHB1mQvWOVdAzVrtEmRw3Vh8g== integrity sha512-xANXvOqArvnYjEGKZkjmeAvX1nchcdMZ3mYU7XbEzs9mPWbP4fyJ2AWmClslX3PyW2i1lRXsN9lFP515shsBEw==
lightningcss-linux-x64-musl@1.16.1: lightningcss-linux-x64-musl@1.17.0:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.16.1.tgz#20b51081679dd6b7271ce11df825dc536a0c617c" resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.17.0.tgz#08607fb1827c719fa3a28d98aeeec92ccb4d64dc"
integrity sha512-VZf76GxW+8mk238tpw0u9R66gBi/m0YB0TvD54oeGiOqvTZ/mabkBkbsuXTSWcKYj8DSrLW+A42qu+6PLRsIgA== integrity sha512-F4mZ9uPMD35wegJvyVOvfSuX+Xuu6N0kqNsw5o0cX0SVLEbYXh5xhXXgr/V1aS4VPGqqMR+HoSJV5FJ/g3DvEA==
lightningcss-win32-x64-msvc@1.16.1: lightningcss-win32-x64-msvc@1.17.0:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.16.1.tgz#7546b4dca78314b1d2701ed220cb6e50b8c6b5ca" resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.17.0.tgz#b8c5cf0e349715319c9064978bff43947f541eb0"
integrity sha512-Djy+UzlTtJMayVJU3eFuUW5Gdo+zVTNPJhlYw25tNC9HAoMCkIdSDDrGsWEdEyibEV7xwB8ySTmLuxilfhBtgg== integrity sha512-PbG+MTGVmIM0oEPUEBECnnYH4E+wlABWf98n0O7BJhoX4jcakbqn6v1LdIT6ogE/5T4i9HAlnr7k/J9M5u4qww==
lightningcss@^1.16.1: lightningcss@^1.16.1:
version "1.16.1" version "1.17.0"
resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.16.1.tgz#b5a16632b6824d023af2fb7d35b1c6fc42608bc6" resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.17.0.tgz#32fec5f10def6bd32a608ae302d0266ba7d90332"
integrity sha512-zU8OTaps3VAodmI2MopfqqOQQ4A9L/2Eo7xoTH/4fNkecy6ftfiGwbbRMTQqtIqJjRg3f927e+lnyBBPhucY1Q== integrity sha512-flO6jocjeV0MUDkYCtg1+jwLqAlqrV/t3n7rUrJ6/tcntm5zfBXsewwOj7PSSv9iTNqFKJX8zIkx/M1W2AG3kw==
dependencies: dependencies:
detect-libc "^1.0.3" detect-libc "^1.0.3"
optionalDependencies: optionalDependencies:
lightningcss-darwin-arm64 "1.16.1" lightningcss-darwin-arm64 "1.17.0"
lightningcss-darwin-x64 "1.16.1" lightningcss-darwin-x64 "1.17.0"
lightningcss-linux-arm-gnueabihf "1.16.1" lightningcss-linux-arm-gnueabihf "1.17.0"
lightningcss-linux-arm64-gnu "1.16.1" lightningcss-linux-arm64-gnu "1.17.0"
lightningcss-linux-arm64-musl "1.16.1" lightningcss-linux-arm64-musl "1.17.0"
lightningcss-linux-x64-gnu "1.16.1" lightningcss-linux-x64-gnu "1.17.0"
lightningcss-linux-x64-musl "1.16.1" lightningcss-linux-x64-musl "1.17.0"
lightningcss-win32-x64-msvc "1.16.1" lightningcss-win32-x64-msvc "1.17.0"
lilconfig@^2.0.3, lilconfig@^2.0.5, lilconfig@^2.0.6: lilconfig@^2.0.3, lilconfig@^2.0.5, lilconfig@^2.0.6:
version "2.0.6" version "2.0.6"
@ -6700,7 +6700,7 @@ loader-runner@^4.2.0:
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
loader-utils@^2.0.0, loader-utils@^2.0.3: loader-utils@^2.0.0, loader-utils@^2.0.4:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c"
integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==
@ -6886,9 +6886,9 @@ mimic-fn@^2.1.0:
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mini-css-extract-plugin@^2.4.5: mini-css-extract-plugin@^2.4.5:
version "2.7.0" version "2.7.1"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz#d7d9ba0c5b596d155e36e2b174082fc7f010dd64" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.1.tgz#ec924df783cff32ce6183fceb653028f70128643"
integrity sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw== integrity sha512-viOoaUFy+Z2w43VsGPbtfwFrr0tKwDctK9dUofG5MBViYhD1noGFUzzDIVw0KPwCGUP+c7zqLxm+acuQs7zLzw==
dependencies: dependencies:
schema-utils "^4.0.0" schema-utils "^4.0.0"
@ -6905,9 +6905,9 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
minimatch@^5.0.1: minimatch@^5.0.1:
version "5.1.0" version "5.1.1"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.1.tgz#6c9dffcf9927ff2a31e74b5af11adf8b9604b022"
integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg== integrity sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==
dependencies: dependencies:
brace-expansion "^2.0.1" brace-expansion "^2.0.1"
@ -6953,9 +6953,9 @@ msgpackr-extract@^2.2.0:
"@msgpackr-extract/msgpackr-extract-win32-x64" "2.2.0" "@msgpackr-extract/msgpackr-extract-win32-x64" "2.2.0"
msgpackr@^1.5.4: msgpackr@^1.5.4:
version "1.8.0" version "1.8.1"
resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.8.0.tgz#6cf213e88f04c5a358c61085a42a4dbe5542de44" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.8.1.tgz#2298aed8a14f83e99df77d344cbda3e436f29b5b"
integrity sha512-1Cos3r86XACdjLVY4CN8r72Cgs5lUzxSON6yb81sNZP9vC9nnBrEbu1/ldBhuR9BKejtoYV5C9UhmYUvZFJSNQ== integrity sha512-05fT4J8ZqjYlR4QcRDIhLCYKUOHXk7C/xa62GzMKj74l3up9k2QZ3LgFc6qWdsPHl91QA2WLWqWc8b8t7GLNNw==
optionalDependencies: optionalDependencies:
msgpackr-extract "^2.2.0" msgpackr-extract "^2.2.0"
@ -8380,12 +8380,12 @@ regenerate@^1.4.2:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
regenerator-runtime@^0.13.10, regenerator-runtime@^0.13.7, regenerator-runtime@^0.13.9: regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.7, regenerator-runtime@^0.13.9:
version "0.13.11" version "0.13.11"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
regenerator-transform@^0.15.0: regenerator-transform@^0.15.1:
version "0.15.1" version "0.15.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56"
integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==
@ -8411,7 +8411,7 @@ regexpp@^3.2.0:
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
regexpu-core@^5.1.0: regexpu-core@^5.2.1:
version "5.2.2" version "5.2.2"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc"
integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==
@ -9201,9 +9201,9 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.5:
terser "^5.14.1" terser "^5.14.1"
terser@^5.0.0, terser@^5.10.0, terser@^5.14.1, terser@^5.2.0: terser@^5.0.0, terser@^5.10.0, terser@^5.14.1, terser@^5.2.0:
version "5.15.1" version "5.16.0"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.1.tgz#8561af6e0fd6d839669c73b92bdd5777d870ed6c" resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.0.tgz#29362c6f5506e71545c73b069ccd199bb28f7f54"
integrity sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw== integrity sha512-KjTV81QKStSfwbNiwlBXfcgMcOloyuRdb62/iLFPGBcVNF4EXjhdYBhYHmbJpiBrVxZhDvltE11j+LBQUxEEJg==
dependencies: dependencies:
"@jridgewell/source-map" "^0.3.2" "@jridgewell/source-map" "^0.3.2"
acorn "^8.5.0" acorn "^8.5.0"