Localization for routes and permissions, added compression for language/getEntries
This commit is contained in:
parent
12b8a0b386
commit
0e3d27fa10
@ -115,7 +115,8 @@ namespace Core\API\Language {
|
|||||||
public function __construct(Context $context, bool $externalCall = false) {
|
public function __construct(Context $context, bool $externalCall = false) {
|
||||||
parent::__construct($context, $externalCall, [
|
parent::__construct($context, $externalCall, [
|
||||||
"code" => new StringType("code", 5, true, NULL),
|
"code" => new StringType("code", 5, true, NULL),
|
||||||
"modules" => new ArrayType("modules", Parameter::TYPE_STRING, true, false)
|
"modules" => new ArrayType("modules", Parameter::TYPE_STRING, true, false),
|
||||||
|
"compression" => new StringType("compression", -1, true, NULL, ["gzip", "zlib"])
|
||||||
]);
|
]);
|
||||||
$this->loginRequired = false;
|
$this->loginRequired = false;
|
||||||
$this->csrfTokenRequired = false;
|
$this->csrfTokenRequired = false;
|
||||||
@ -156,7 +157,23 @@ namespace Core\API\Language {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->result["code"] = $code;
|
$this->result["code"] = $code;
|
||||||
$this->result["entries"] = $entries;
|
|
||||||
|
$compression = $this->getParam("compression");
|
||||||
|
if ($compression) {
|
||||||
|
switch ($compression) {
|
||||||
|
case "gzip":
|
||||||
|
$this->result["compressed"] = base64_encode(gzencode(json_encode($entries), 9));
|
||||||
|
break;
|
||||||
|
case "zlib":
|
||||||
|
$this->result["compressed"] = base64_encode(gzcompress(json_encode($entries), 9, ZLIB_ENCODING_DEFLATE));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
http_response_code(400);
|
||||||
|
return $this->createError("Invalid compression method: $compression");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->result["entries"] = $entries;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ return [
|
|||||||
"cancel" => "Abbrechen",
|
"cancel" => "Abbrechen",
|
||||||
"confirm" => "Bestätigen",
|
"confirm" => "Bestätigen",
|
||||||
"add" => "Hinzufügen",
|
"add" => "Hinzufügen",
|
||||||
|
"select" => "Auswählen",
|
||||||
"ok" => "OK",
|
"ok" => "OK",
|
||||||
"id" => "ID",
|
"id" => "ID",
|
||||||
"user" => "Benutzer",
|
"user" => "Benutzer",
|
||||||
|
20
Core/Localization/de_DE/permissions.php
Normal file
20
Core/Localization/de_DE/permissions.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
"title" => "Berechtigungen",
|
||||||
|
"title_short" => "ACL",
|
||||||
|
"query" => "Suchanfrage",
|
||||||
|
"add_permission" => "Berechtigung hinzufügen",
|
||||||
|
"permission" => "Berechtigung",
|
||||||
|
"everyone" => "Alle",
|
||||||
|
"method" => "Methode",
|
||||||
|
"description" => "Beschreibung",
|
||||||
|
|
||||||
|
# dialog
|
||||||
|
"delete_permission_confirm" => "Diese Berechtigung wirklich löschen?",
|
||||||
|
"edit_permission" => "Berechtigung bearbeiten",
|
||||||
|
"update_permission_error" => "Fehler beim Aktualisieren der Berechtigung",
|
||||||
|
"delete_permission_error" => "Fehler beim Löschen der Berechtigung",
|
||||||
|
"fetch_permission_error" => "Fehler beim Holen der Berechtigungen",
|
||||||
|
"fetch_group_error" => "Fehler beim Holen der Gruppen",
|
||||||
|
];
|
41
Core/Localization/de_DE/routes.php
Normal file
41
Core/Localization/de_DE/routes.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
"title" => "Routen",
|
||||||
|
"regenerating_cache" => "Lade Cache neu",
|
||||||
|
"regenerate_cache" => "Cache neuladen",
|
||||||
|
|
||||||
|
# table
|
||||||
|
"route" => "Route",
|
||||||
|
"type" => "Typ",
|
||||||
|
"target" => "Ziel",
|
||||||
|
"extra" => "Extra",
|
||||||
|
"active" => "Aktiv",
|
||||||
|
"exact" => "Exakt",
|
||||||
|
|
||||||
|
# form
|
||||||
|
"edit_route_title" => "Route bearbeiten",
|
||||||
|
"create_route_title" => "Neue Route erstellen",
|
||||||
|
"pattern" => "Pattern",
|
||||||
|
"arguments" => "Argumente",
|
||||||
|
"status_code" => "Status Code",
|
||||||
|
"json_ok" => "JSON ok!",
|
||||||
|
"json_err" => "Ungültiger JSON-string!",
|
||||||
|
"json_not_object" => "Das JSON muss ein Array oder Objekt sein!",
|
||||||
|
"validate_route" => "Route validieren",
|
||||||
|
"validate_route_placeholder" => "Einen Pfad eingeben um die Route zu testen",
|
||||||
|
|
||||||
|
# data
|
||||||
|
"type_dynamic" => "Dynamisch",
|
||||||
|
"type_static" => "Statisch",
|
||||||
|
"type_redirect_permanently" => "Dauerhaft weiterleiten",
|
||||||
|
"type_redirect_temporary" => "Temporär weiterleiten",
|
||||||
|
|
||||||
|
# dialogs
|
||||||
|
"fetch_routes_error" => "Fehler beim Holen der Routen",
|
||||||
|
"enable_route_error" => "Fehler beim Aktivieren der Route",
|
||||||
|
"disable_route_error" => "Fehler beim Deaktivieren der Route",
|
||||||
|
"remove_route_error" => "Fehler beim Entfernen der Route",
|
||||||
|
"regenerate_router_cache_error" => "Fehler beim Erzeugen des Router Caches",
|
||||||
|
"regenerate_router_cache_success" => "Router Cache erfolgreich erzeugt",
|
||||||
|
];
|
@ -30,6 +30,7 @@ return [
|
|||||||
"cancel" => "Cancel",
|
"cancel" => "Cancel",
|
||||||
"confirm" => "Confirm",
|
"confirm" => "Confirm",
|
||||||
"add" => "Add",
|
"add" => "Add",
|
||||||
|
"select" => "Select",
|
||||||
"close" => "Close",
|
"close" => "Close",
|
||||||
"ok" => "OK",
|
"ok" => "OK",
|
||||||
"id" => "ID",
|
"id" => "ID",
|
||||||
|
20
Core/Localization/en_US/permissions.php
Normal file
20
Core/Localization/en_US/permissions.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
"title" => "Permissions",
|
||||||
|
"title_short" => "ACL",
|
||||||
|
"query" => "Search query",
|
||||||
|
"add_permission" => "Add permission",
|
||||||
|
"permission" => "Permission",
|
||||||
|
"everyone" => "Everyone",
|
||||||
|
"method" => "Method",
|
||||||
|
"description" => "Description",
|
||||||
|
|
||||||
|
# dialog
|
||||||
|
"delete_permission_confirm" => "Do you really want to delete this permission?",
|
||||||
|
"edit_permission" => "Edit Permission",
|
||||||
|
"update_permission_error" => "Error updating permission",
|
||||||
|
"delete_permission_error" => "Error deleting permission",
|
||||||
|
"fetch_permission_error" => "Error fetching permissions",
|
||||||
|
"fetch_group_error" => "Error fetching groups",
|
||||||
|
];
|
41
Core/Localization/en_US/routes.php
Normal file
41
Core/Localization/en_US/routes.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
"title" => "Routes",
|
||||||
|
"regenerating_cache" => "Regenerating Cache",
|
||||||
|
"regenerate_cache" => "Regenerate Cache",
|
||||||
|
|
||||||
|
# table
|
||||||
|
"route" => "Route",
|
||||||
|
"type" => "Type",
|
||||||
|
"target" => "Target",
|
||||||
|
"extra" => "Extra",
|
||||||
|
"active" => "Active",
|
||||||
|
"exact" => "Exact",
|
||||||
|
|
||||||
|
# form
|
||||||
|
"edit_route_title" => "Edit Route",
|
||||||
|
"create_route_title" => "Create new Route",
|
||||||
|
"pattern" => "Pattern",
|
||||||
|
"arguments" => "Arguments",
|
||||||
|
"status_code" => "Status Code",
|
||||||
|
"json_ok" => "JSON ok!",
|
||||||
|
"json_err" => "Invalid JSON-string!",
|
||||||
|
"json_not_object" => "JSON must be Array or Object!",
|
||||||
|
"validate_route" => "Validate Route",
|
||||||
|
"validate_route_placeholder" => "Enter a path to test the route",
|
||||||
|
|
||||||
|
# data
|
||||||
|
"type_dynamic" => "Dynamic",
|
||||||
|
"type_static" => "Static",
|
||||||
|
"type_redirect_permanently" => "Redirect permanently",
|
||||||
|
"type_redirect_temporary" => "Redirect temporary",
|
||||||
|
|
||||||
|
# dialogs
|
||||||
|
"fetch_routes_error" => "Error fetching routes",
|
||||||
|
"enable_route_error" => "Error enabling route",
|
||||||
|
"disable_route_error" => "Error disabling route",
|
||||||
|
"remove_route_error" => "Error removing route",
|
||||||
|
"regenerate_router_cache_error" => "Error regenerating router cache",
|
||||||
|
"regenerate_router_cache_success" => "Router cache successfully regenerated",
|
||||||
|
];
|
@ -45,13 +45,13 @@ export default function AccessControlList(props) {
|
|||||||
setFetchACL(false);
|
setFetchACL(false);
|
||||||
props.api.fetchGroups().then(res => {
|
props.api.fetchGroups().then(res => {
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
props.showDialog(res.msg, "Error fetching groups");
|
props.showDialog(res.msg, L("permissions.fetch_group_error"));
|
||||||
navigate("/admin/dashboard");
|
navigate("/admin/dashboard");
|
||||||
} else {
|
} else {
|
||||||
setGroups(res.groups);
|
setGroups(res.groups);
|
||||||
props.api.fetchPermissions().then(res => {
|
props.api.fetchPermissions().then(res => {
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
props.showDialog(res.msg, "Error fetching permissions");
|
props.showDialog(res.msg, L("permissions.fetch_permission_error"));
|
||||||
navigate("/admin/dashboard");
|
navigate("/admin/dashboard");
|
||||||
} else {
|
} else {
|
||||||
setACL(res.permissions);
|
setACL(res.permissions);
|
||||||
@ -67,7 +67,7 @@ export default function AccessControlList(props) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
requestModules(props.api, ["general"], currentLocale).then(data => {
|
requestModules(props.api, ["general", "permissions"], currentLocale).then(data => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
props.showDialog("Error fetching translations: " + data.msg);
|
props.showDialog("Error fetching translations: " + data.msg);
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ export default function AccessControlList(props) {
|
|||||||
setACL(newACL);
|
setACL(newACL);
|
||||||
props.api.fetchUser();
|
props.api.fetchUser();
|
||||||
} else {
|
} else {
|
||||||
props.showDialog("Error updating permission: " + data.msg);
|
props.showDialog(data.msg, L("permissions.update_permission_error"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ export default function AccessControlList(props) {
|
|||||||
setACL(newACL);
|
setACL(newACL);
|
||||||
props.api.fetchUser();
|
props.api.fetchUser();
|
||||||
} else {
|
} else {
|
||||||
props.showDialog("Error deleting permission: " + data.msg);
|
props.showDialog(data.msg, L("permissions.delete_permission_error"));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [acl]);
|
}, [acl]);
|
||||||
@ -130,7 +130,7 @@ export default function AccessControlList(props) {
|
|||||||
setACL(newACL);
|
setACL(newACL);
|
||||||
props.api.fetchUser();
|
props.api.fetchUser();
|
||||||
} else {
|
} else {
|
||||||
props.showDialog("Error updating permission: " + data.msg);
|
props.showDialog(data.msg, L("permissions.update_permission_error"));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [acl]);
|
}, [acl]);
|
||||||
@ -162,11 +162,11 @@ export default function AccessControlList(props) {
|
|||||||
disabled={isRestricted(permission.method)}
|
disabled={isRestricted(permission.method)}
|
||||||
onClick={() => setDialogData({
|
onClick={() => setDialogData({
|
||||||
open: true,
|
open: true,
|
||||||
title: L("Edit permission"),
|
title: L("permissions.edit_permission"),
|
||||||
inputs: [
|
inputs: [
|
||||||
{ type: "label", value: L("general.method") + ":" },
|
{ type: "label", value: L("permissions.method") + ":" },
|
||||||
{ type: "text", name: "method", value: permission.method, disabled: true },
|
{ type: "text", name: "method", value: permission.method, disabled: true },
|
||||||
{ type: "label", value: L("general.description") + ":" },
|
{ type: "label", value: L("permissions.description") + ":" },
|
||||||
{ type: "text", name: "description", value: permission.description, maxLength: 128 }
|
{ type: "text", name: "description", value: permission.description, maxLength: 128 }
|
||||||
],
|
],
|
||||||
onOption: (option, inputData) => option === 0 && onUpdatePermission(inputData, permission.groups)
|
onOption: (option, inputData) => option === 0 && onUpdatePermission(inputData, permission.groups)
|
||||||
@ -177,8 +177,8 @@ export default function AccessControlList(props) {
|
|||||||
disabled={isRestricted(permission.method)}
|
disabled={isRestricted(permission.method)}
|
||||||
onClick={() => setDialogData({
|
onClick={() => setDialogData({
|
||||||
open: true,
|
open: true,
|
||||||
title: L("Do you really want to delete this permission?"),
|
title: L("permissions.delete_permission_confirm"),
|
||||||
message: "Method: " + permission.method,
|
message: L("permissions.method") + ": " + permission.method,
|
||||||
onOption: (option) => option === 0 && onDeletePermission(permission.method)
|
onOption: (option) => option === 0 && onDeletePermission(permission.method)
|
||||||
})} >
|
})} >
|
||||||
<Delete />
|
<Delete />
|
||||||
@ -212,12 +212,12 @@ export default function AccessControlList(props) {
|
|||||||
<div className={"container-fluid"}>
|
<div className={"container-fluid"}>
|
||||||
<div className={"row mb-2"}>
|
<div className={"row mb-2"}>
|
||||||
<div className={"col-sm-6"}>
|
<div className={"col-sm-6"}>
|
||||||
<h1 className={"m-0 text-dark"}>Access Control List</h1>
|
<h1 className={"m-0 text-dark"}>{L("permissions.title")}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className={"col-sm-6"}>
|
<div className={"col-sm-6"}>
|
||||||
<ol className={"breadcrumb float-sm-right"}>
|
<ol className={"breadcrumb float-sm-right"}>
|
||||||
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
||||||
<li className="breadcrumb-item active">ACL</li>
|
<li className="breadcrumb-item active">{L("permissions.title_short")}</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -226,10 +226,10 @@ export default function AccessControlList(props) {
|
|||||||
<div className={"row"}>
|
<div className={"row"}>
|
||||||
<div className={"col-6"}>
|
<div className={"col-6"}>
|
||||||
<div className={"form-group"}>
|
<div className={"form-group"}>
|
||||||
<label>{L("query")}</label>
|
<label>{L("permissions.query")}</label>
|
||||||
<TextField
|
<TextField
|
||||||
className={"form-control"}
|
className={"form-control"}
|
||||||
placeholder={L("search_query") + "…"}
|
placeholder={L("permissions.query") + "…"}
|
||||||
value={query}
|
value={query}
|
||||||
onChange={e => setQuery(e.target.value)}
|
onChange={e => setQuery(e.target.value)}
|
||||||
variant={"outlined"}
|
variant={"outlined"}
|
||||||
@ -245,7 +245,7 @@ export default function AccessControlList(props) {
|
|||||||
<Button variant={"outlined"} className={"m-1"} startIcon={<Add />} disabled={!props.api.hasGroup(USER_GROUP_ADMIN)}
|
<Button variant={"outlined"} className={"m-1"} startIcon={<Add />} disabled={!props.api.hasGroup(USER_GROUP_ADMIN)}
|
||||||
onClick={() => setDialogData({
|
onClick={() => setDialogData({
|
||||||
open: true,
|
open: true,
|
||||||
title: L("Add permission"),
|
title: L("permissions.add_permission"),
|
||||||
inputs: [
|
inputs: [
|
||||||
{ type: "label", value: L("general.method") + ":" },
|
{ type: "label", value: L("general.method") + ":" },
|
||||||
{ type: "text", name: "method", value: "", placeholder: L("general.method") },
|
{ type: "text", name: "method", value: "", placeholder: L("general.method") },
|
||||||
@ -263,8 +263,8 @@ export default function AccessControlList(props) {
|
|||||||
<Table stickyHeader size={"small"} className={"table-striped"}>
|
<Table stickyHeader size={"small"} className={"table-striped"}>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>{L("permission")}</TableCell>
|
<TableCell>{L("permissions.permission")}</TableCell>
|
||||||
<BorderedColumn align={"center"}><i>{L("everyone")}</i></BorderedColumn>
|
<BorderedColumn align={"center"}><i>{L("permissions.everyone")}</i></BorderedColumn>
|
||||||
{ groups.map(group => <TableCell key={"group-" + group.id} align={"center"}>
|
{ groups.map(group => <TableCell key={"group-" + group.id} align={"center"}>
|
||||||
{group.name}
|
{group.name}
|
||||||
</TableCell>) }
|
</TableCell>) }
|
||||||
|
@ -48,7 +48,7 @@ export default function RouteEditView(props) {
|
|||||||
const [isSaving, setSaving] = useState(false);
|
const [isSaving, setSaving] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
requestModules(props.api, ["general"], currentLocale).then(data => {
|
requestModules(props.api, ["general", "routes"], currentLocale).then(data => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
props.showDialog("Error fetching translations: " + data.msg);
|
props.showDialog("Error fetching translations: " + data.msg);
|
||||||
}
|
}
|
||||||
@ -122,15 +122,13 @@ export default function RouteEditView(props) {
|
|||||||
<div className={"container-fluid"}>
|
<div className={"container-fluid"}>
|
||||||
<ol className={"breadcrumb"}>
|
<ol className={"breadcrumb"}>
|
||||||
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
||||||
<li className="breadcrumb-item active"><Link to={"/admin/routes"}>Routes</Link></li>
|
<li className="breadcrumb-item active"><Link to={"/admin/routes"}>{L("routes.title")}</Link></li>
|
||||||
<li className="breadcrumb-item active">{isNewRoute ? "New" : "Edit"}</li>
|
<li className="breadcrumb-item active">{isNewRoute ? L("general.new") : L("general.edit")}</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
<div className={"content"}>
|
<div className={"content"}>
|
||||||
<div className={"container-fluid"}>
|
<div className={"container-fluid"}>
|
||||||
<h3>{L(isNewRoute ? "Create new Route" : "Edit Route")}</h3>
|
<h3>{L(isNewRoute ? "routes.create_route_title" : "routes.edit_route_title")}</h3>
|
||||||
<div className={"col-sm-12 col-lg-6"}>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<RouteForm route={route} setRoute={setRoute} />
|
<RouteForm route={route} setRoute={setRoute} />
|
||||||
@ -147,10 +145,10 @@ export default function RouteEditView(props) {
|
|||||||
</Button>
|
</Button>
|
||||||
</ButtonBar>
|
</ButtonBar>
|
||||||
<Box mt={3}>
|
<Box mt={3}>
|
||||||
<h5>{L("Validate Route")}</h5>
|
<h5>{L("routes.validate_route")}</h5>
|
||||||
<MonoSpaceTextField value={routeTest} onChange={e => setRouteTest(e.target.value)}
|
<MonoSpaceTextField value={routeTest} onChange={e => setRouteTest(e.target.value)}
|
||||||
variant={"outlined"} size={"small"} fullWidth={true}
|
variant={"outlined"} size={"small"} fullWidth={true}
|
||||||
placeholder={L("Enter a path to test the route…")} />
|
placeholder={L("routes.validate_route_placeholder") + "…"} />
|
||||||
<pre>
|
<pre>
|
||||||
Match: {JSON.stringify(routeTestResult)}
|
Match: {JSON.stringify(routeTestResult)}
|
||||||
</pre>
|
</pre>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Box, Checkbox, FormControl, FormControlLabel, FormGroup, Select, styled, TextField} from "@material-ui/core";
|
import {Checkbox, FormControl, FormControlLabel, Select, styled, TextField} from "@material-ui/core";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {useCallback, useContext, useEffect, useRef} from "react";
|
import {useCallback, useContext, useEffect, useRef} from "react";
|
||||||
import {LocaleContext} from "shared/locale";
|
import {LocaleContext} from "shared/locale";
|
||||||
@ -38,30 +38,30 @@ export default function RouteForm(props) {
|
|||||||
|
|
||||||
const elements = [
|
const elements = [
|
||||||
<RouteFormControl key={"form-control-pattern"} fullWidth={true}>
|
<RouteFormControl key={"form-control-pattern"} fullWidth={true}>
|
||||||
<label htmlFor={"route-pattern"}>{L("Pattern")}</label>
|
<label htmlFor={"route-pattern"}>{L("routes.pattern")}</label>
|
||||||
<TextField id={"route-pattern"} variant={"outlined"} size={"small"}
|
<TextField id={"route-pattern"} variant={"outlined"} size={"small"}
|
||||||
value={route.pattern}
|
value={route.pattern}
|
||||||
onChange={e => setRoute({...route, pattern: e.target.value})} />
|
onChange={e => setRoute({...route, pattern: e.target.value})} />
|
||||||
</RouteFormControl>,
|
</RouteFormControl>,
|
||||||
<FormGroup key={"form-control-exact"}>
|
<RouteFormControl key={"form-control-exact"}>
|
||||||
<FormControlLabel label={L("Exact")} control={<Checkbox
|
<FormControlLabel label={L("routes.exact")} control={<Checkbox
|
||||||
checked={route.exact}
|
checked={route.exact}
|
||||||
onChange={e => setRoute({...route, exact: e.target.checked})} />} />
|
onChange={e => setRoute({...route, exact: e.target.checked})} />} />
|
||||||
</FormGroup>,
|
</RouteFormControl>,
|
||||||
<FormGroup key={"form-control-active"}>
|
<RouteFormControl key={"form-control-active"}>
|
||||||
<FormControlLabel label={L("Active")} control={<Checkbox
|
<FormControlLabel label={L("routes.active")} control={<Checkbox
|
||||||
checked={route.active}
|
checked={route.active}
|
||||||
onChange={e => setRoute({...route, active: e.target.checked})} />} />
|
onChange={e => setRoute({...route, active: e.target.checked})} />} />
|
||||||
</FormGroup>,
|
</RouteFormControl>,
|
||||||
<RouteFormControl key={"form-control-type"} fullWidth={true} size={"small"}>
|
<RouteFormControl key={"form-control-type"} fullWidth={true} size={"small"}>
|
||||||
<label htmlFor={"route-type"}>{L("Type")}</label>
|
<label htmlFor={"route-type"}>{L("routes.type")}</label>
|
||||||
<Select value={route.type} variant={"outlined"} size={"small"} labelId={"route-type"}
|
<Select value={route.type} variant={"outlined"} size={"small"} labelId={"route-type"}
|
||||||
onChange={e => onChangeRouteType(e.target.value)} native>
|
onChange={e => onChangeRouteType(e.target.value)} native>
|
||||||
<option value={""}>Select…</option>
|
<option value={""}>{L("general.select")}…</option>
|
||||||
<option value={"dynamic"}>Dynamic</option>
|
<option value={"dynamic"}>{L("routes.type_dynamic")}</option>
|
||||||
<option value={"static"}>Static</option>
|
<option value={"static"}>{L("routes.type_static")}</option>
|
||||||
<option value={"redirect_permanently"}>Redirect Permanently</option>
|
<option value={"redirect_permanently"}>{L("routes.type_redirect_permanently")}</option>
|
||||||
<option value={"redirect_temporary"}>Redirect Temporary</option>
|
<option value={"redirect_temporary"}>{L("routes.type_redirect_temporary")}</option>
|
||||||
</Select>
|
</Select>
|
||||||
</RouteFormControl>,
|
</RouteFormControl>,
|
||||||
];
|
];
|
||||||
@ -77,7 +77,7 @@ export default function RouteForm(props) {
|
|||||||
if (route.type) {
|
if (route.type) {
|
||||||
elements.push(
|
elements.push(
|
||||||
<RouteFormControl key={"form-control-target"} fullWidth={true}>
|
<RouteFormControl key={"form-control-target"} fullWidth={true}>
|
||||||
<label htmlFor={"route-target"}>{L("Target")}</label>
|
<label htmlFor={"route-target"}>{L("routes.target")}</label>
|
||||||
<TextField id={"route-target"} variant={"outlined"} size={"small"}
|
<TextField id={"route-target"} variant={"outlined"} size={"small"}
|
||||||
value={route.target}
|
value={route.target}
|
||||||
onChange={e => setRoute({...route, target: e.target.value})}/>
|
onChange={e => setRoute({...route, target: e.target.value})}/>
|
||||||
@ -95,23 +95,22 @@ export default function RouteForm(props) {
|
|||||||
}
|
}
|
||||||
elements.push(
|
elements.push(
|
||||||
<RouteFormControl key={"form-control-extra"} fullWidth={true}>
|
<RouteFormControl key={"form-control-extra"} fullWidth={true}>
|
||||||
<label htmlFor={"route-extra"}>{L("Arguments")}</label>
|
<label htmlFor={"route-extra"}>{L("routes.arguments")}</label>
|
||||||
<textarea id={"route-extra"}
|
<textarea id={"route-extra"}
|
||||||
ref={extraRef}
|
ref={extraRef}
|
||||||
value={extraArgs ?? route.extra}
|
value={extraArgs ?? route.extra}
|
||||||
onChange={e => setRoute({...route, extra: minifyJson(e.target.value)})}/>
|
onChange={e => setRoute({...route, extra: minifyJson(e.target.value)})}/>
|
||||||
<i>{
|
<i>{
|
||||||
extraArgs === null ?
|
extraArgs === null ?
|
||||||
"Invalid JSON-string" :
|
L("routes.json_err") :
|
||||||
(type !== "object" ?
|
(type !== "object" ? L("routes.json_not_obj") : L("routes.json_ok"))
|
||||||
"JSON must be Array or Object" : "JSON ok!")
|
|
||||||
}</i>
|
}</i>
|
||||||
</RouteFormControl>
|
</RouteFormControl>
|
||||||
);
|
);
|
||||||
} else if (route.type === "static") {
|
} else if (route.type === "static") {
|
||||||
elements.push(
|
elements.push(
|
||||||
<RouteFormControl key={"form-control-extra"} fullWidth={true}>
|
<RouteFormControl key={"form-control-extra"} fullWidth={true}>
|
||||||
<label htmlFor={"route-extra"}>{L("Status Code")}</label>
|
<label htmlFor={"route-extra"}>{L("routes.status_code")}</label>
|
||||||
<TextField id={"route-extra"} variant={"outlined"} size={"small"}
|
<TextField id={"route-extra"} variant={"outlined"} size={"small"}
|
||||||
type={"number"} value={route.extra}
|
type={"number"} value={route.extra}
|
||||||
onChange={e => setRoute({...route, extra: parseInt(e.target.value) || 200})} />
|
onChange={e => setRoute({...route, extra: parseInt(e.target.value) || 200})} />
|
||||||
|
@ -42,7 +42,7 @@ export default function RouteListView(props) {
|
|||||||
setFetchRoutes(false);
|
setFetchRoutes(false);
|
||||||
props.api.fetchRoutes().then(res => {
|
props.api.fetchRoutes().then(res => {
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
props.showDialog(res.msg, "Error fetching routes");
|
props.showDialog(res.msg, L("routes.fetch_routes_error"));
|
||||||
navigate("/admin/dashboard");
|
navigate("/admin/dashboard");
|
||||||
} else {
|
} else {
|
||||||
setRoutes(res.routes);
|
setRoutes(res.routes);
|
||||||
@ -56,7 +56,7 @@ export default function RouteListView(props) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
requestModules(props.api, ["general"], currentLocale).then(data => {
|
requestModules(props.api, ["general", "routes"], currentLocale).then(data => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
props.showDialog("Error fetching translations: " + data.msg);
|
props.showDialog("Error fetching translations: " + data.msg);
|
||||||
}
|
}
|
||||||
@ -67,7 +67,7 @@ export default function RouteListView(props) {
|
|||||||
if (active) {
|
if (active) {
|
||||||
props.api.enableRoute(id).then(data => {
|
props.api.enableRoute(id).then(data => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
props.showDialog(data.msg, L("Error enabling route"));
|
props.showDialog(data.msg, L("routes.enable_route_error"));
|
||||||
} else {
|
} else {
|
||||||
setRoutes({...routes, [id]: { ...routes[id], active: true }});
|
setRoutes({...routes, [id]: { ...routes[id], active: true }});
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ export default function RouteListView(props) {
|
|||||||
} else {
|
} else {
|
||||||
props.api.disableRoute(id).then(data => {
|
props.api.disableRoute(id).then(data => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
props.showDialog(data.msg, L("Error enabling route"));
|
props.showDialog(data.msg, L("routes.disable_route_error"));
|
||||||
} else {
|
} else {
|
||||||
setRoutes({...routes, [id]: { ...routes[id], active: false }});
|
setRoutes({...routes, [id]: { ...routes[id], active: false }});
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ export default function RouteListView(props) {
|
|||||||
const onDeleteRoute = useCallback(id => {
|
const onDeleteRoute = useCallback(id => {
|
||||||
props.api.deleteRoute(id).then(data => {
|
props.api.deleteRoute(id).then(data => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
props.showDialog(data.msg, L("Error removing route"));
|
props.showDialog(data.msg, L("routes.remove_route_error"));
|
||||||
} else {
|
} else {
|
||||||
let newRoutes = { ...routes };
|
let newRoutes = { ...routes };
|
||||||
delete newRoutes[id];
|
delete newRoutes[id];
|
||||||
@ -100,13 +100,13 @@ export default function RouteListView(props) {
|
|||||||
setGeneratingCache(true);
|
setGeneratingCache(true);
|
||||||
props.api.regenerateRouterCache().then(data => {
|
props.api.regenerateRouterCache().then(data => {
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
props.showDialog(data.msg, L("Error regenerating router cache"));
|
props.showDialog(data.msg, L("routes.regenerate_router_cache_error"));
|
||||||
setGeneratingCache(false);
|
setGeneratingCache(false);
|
||||||
} else {
|
} else {
|
||||||
setDialogData({
|
setDialogData({
|
||||||
open: true,
|
open: true,
|
||||||
title: L("general.success"),
|
title: L("general.success"),
|
||||||
message: L("Router cache successfully regenerated"),
|
message: L("routes.regenerate_router_cache_success"),
|
||||||
onClose: () => setGeneratingCache(false)
|
onClose: () => setGeneratingCache(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -121,12 +121,12 @@ export default function RouteListView(props) {
|
|||||||
<div className={"container-fluid"}>
|
<div className={"container-fluid"}>
|
||||||
<div className={"row mb-2"}>
|
<div className={"row mb-2"}>
|
||||||
<div className={"col-sm-6"}>
|
<div className={"col-sm-6"}>
|
||||||
<h1 className={"m-0 text-dark"}>Routes</h1>
|
<h1 className={"m-0 text-dark"}>{L("routes.title")}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className={"col-sm-6"}>
|
<div className={"col-sm-6"}>
|
||||||
<ol className={"breadcrumb float-sm-right"}>
|
<ol className={"breadcrumb float-sm-right"}>
|
||||||
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
<li className={"breadcrumb-item"}><Link to={"/admin/dashboard"}>Home</Link></li>
|
||||||
<li className="breadcrumb-item active">Routes</li>
|
<li className="breadcrumb-item active">{L("routes.title")}</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -147,7 +147,7 @@ export default function RouteListView(props) {
|
|||||||
<Button variant={"outlined"} className={"m-1"} startIcon={<Cached />}
|
<Button variant={"outlined"} className={"m-1"} startIcon={<Cached />}
|
||||||
disabled={!props.api.hasPermission("routes/generateCache") || isGeneratingCache}
|
disabled={!props.api.hasPermission("routes/generateCache") || isGeneratingCache}
|
||||||
onClick={onRegenerateCache} >
|
onClick={onRegenerateCache} >
|
||||||
{isGeneratingCache ? L("regenerating_cache") + "…" : L("regenerate_cache")}
|
{isGeneratingCache ? L("routes.regenerating_cache") + "…" : L("routes.regenerate_cache")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -157,12 +157,12 @@ export default function RouteListView(props) {
|
|||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>{L("general.id")}</TableCell>
|
<TableCell>{L("general.id")}</TableCell>
|
||||||
<TableCell>{L("Route")}</TableCell>
|
<TableCell>{L("routes.route")}</TableCell>
|
||||||
<TableCell>{L("Type")}</TableCell>
|
<TableCell>{L("routes.type")}</TableCell>
|
||||||
<TableCell>{L("Target")}</TableCell>
|
<TableCell>{L("routes.target")}</TableCell>
|
||||||
<TableCell>{L("Extra")}</TableCell>
|
<TableCell>{L("routes.extra")}</TableCell>
|
||||||
<TableCell align={"center"}>{L("Active")}</TableCell>
|
<TableCell align={"center"}>{L("routes.active")}</TableCell>
|
||||||
<TableCell align={"center"}>{L("Exact")}</TableCell>
|
<TableCell align={"center"}>{L("routes.exact")}</TableCell>
|
||||||
<TableCell align={"center"}>{L("general.controls")}</TableCell>
|
<TableCell align={"center"}>{L("general.controls")}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"material-ui-color-picker": "^3.5.1",
|
"material-ui-color-picker": "^3.5.1",
|
||||||
"mini-css-extract-plugin": "^2.7.1",
|
"mini-css-extract-plugin": "^2.7.1",
|
||||||
|
"pako": "^2.1.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-chartjs-2": "^5.0.1",
|
"react-chartjs-2": "^5.0.1",
|
||||||
"react-collapse": "^5.1.1",
|
"react-collapse": "^5.1.1",
|
||||||
|
@ -308,12 +308,12 @@ export default class API {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLanguageEntries(modules, code=null, useCache=false) {
|
async getLanguageEntries(modules, code=null, compression=null) {
|
||||||
if (!Array.isArray(modules)) {
|
if (!Array.isArray(modules)) {
|
||||||
modules = [modules];
|
modules = [modules];
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.apiCall("language/getEntries", {code: code, modules: modules});
|
return this.apiCall("language/getEntries", {code: code, modules: modules, compression: compression});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ApiKeyAPI **/
|
/** ApiKeyAPI **/
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import React, {useReducer} from 'react';
|
import React, {useReducer} from 'react';
|
||||||
import {createContext, useCallback, useState} from "react";
|
import {createContext, useCallback, useState} from "react";
|
||||||
import { enUS as dateFnsEN, de as dateFnsDE } from 'date-fns/locale';
|
import { enUS as dateFnsEN, de as dateFnsDE } from 'date-fns/locale';
|
||||||
import {getCookie, getParameter} from "./util";
|
import {encodeText, getCookie, getParameter} from "./util";
|
||||||
|
import pako from "pako";
|
||||||
|
|
||||||
const LocaleContext = createContext(null);
|
const LocaleContext = createContext(null);
|
||||||
|
|
||||||
@ -109,7 +110,13 @@ function LocaleProvider(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (modules.length > 0) {
|
if (modules.length > 0) {
|
||||||
let data = await api.apiCall("language/getEntries", { code: code, modules: modules });
|
let compression = "zlib";
|
||||||
|
|
||||||
|
let data = await api.getLanguageEntries(modules, code, compression);
|
||||||
|
|
||||||
|
if (compression && data.success) {
|
||||||
|
data.entries = JSON.parse(pako.inflate(encodeText(atob(data.compressed)), { to: 'string' }));
|
||||||
|
}
|
||||||
|
|
||||||
if (useCache) {
|
if (useCache) {
|
||||||
if (data && data.success) {
|
if (data && data.success) {
|
||||||
|
@ -4858,11 +4858,6 @@ date-fns@^2.29.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.21.0"
|
"@babel/runtime" "^7.21.0"
|
||||||
|
|
||||||
dayjs@^1.11.10:
|
|
||||||
version "1.11.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0"
|
|
||||||
integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==
|
|
||||||
|
|
||||||
debug@2.6.9, debug@^2.6.0:
|
debug@2.6.9, debug@^2.6.0:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
@ -8392,6 +8387,11 @@ p-try@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||||
|
|
||||||
|
pako@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
|
||||||
|
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
|
||||||
|
|
||||||
param-case@^3.0.4:
|
param-case@^3.0.4:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
|
resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
|
||||||
|
Loading…
Reference in New Issue
Block a user