route bugfix, localization
This commit is contained in:
		
							parent
							
								
									e4e2511d1c
								
							
						
					
					
						commit
						8a09fc1f2d
					
				| @ -1259,7 +1259,7 @@ namespace Core\API\User { | |||||||
|       $settings = $this->context->getSettings(); |       $settings = $this->context->getSettings(); | ||||||
|       $baseUrl = htmlspecialchars($settings->getBaseUrl()); |       $baseUrl = htmlspecialchars($settings->getBaseUrl()); | ||||||
|       $token = htmlspecialchars(urlencode($token)); |       $token = htmlspecialchars(urlencode($token)); | ||||||
|       $url = "$baseUrl/settings?confirmGPG&token=$token"; // TODO: fix this url
 |       $url = "$baseUrl/confirmGPG?token=$token"; | ||||||
|       $mailBody = "Hello $name,<br><br>" . |       $mailBody = "Hello $name,<br><br>" . | ||||||
|         "you imported a GPG public key for end-to-end encrypted mail communication. " . |         "you imported a GPG public key for end-to-end encrypted mail communication. " . | ||||||
|         "To confirm the key and verify, you own the corresponding private key, please click on the following link. " . |         "To confirm the key and verify, you own the corresponding private key, please click on the following link. " . | ||||||
|  | |||||||
| @ -8,6 +8,9 @@ return [ | |||||||
|   "accept_invite_description" => "Schließen Sie die Registrierung ab indem Sie ein Passwort wählen", |   "accept_invite_description" => "Schließen Sie die Registrierung ab indem Sie ein Passwort wählen", | ||||||
|   "confirm_email_title" => "E-Mail Adresse bestätigen", |   "confirm_email_title" => "E-Mail Adresse bestätigen", | ||||||
|   "confirm_email_description" => "Schließen Sie die Registrierung ab indem Sie Ihre E-Mail Adresse bestätigen", |   "confirm_email_description" => "Schließen Sie die Registrierung ab indem Sie Ihre E-Mail Adresse bestätigen", | ||||||
|  |   "confirm_gpg_title" => "GPG-Schlüssel bestätigen", | ||||||
|  |   "confirm_gpg_error" => "Fehler beim Bestätigen des GPG-Schlüssels", | ||||||
|  |   "confirm_gpg_success" => "GPG-Schlüssel erfolgreich bestätigt", | ||||||
|   "registration_title" => "Registration", |   "registration_title" => "Registration", | ||||||
|   "registration_description" => "Erstelle einen neuen Account", |   "registration_description" => "Erstelle einen neuen Account", | ||||||
|   "resend_confirm_email_title" => "Bestätigungsmail erneut senden", |   "resend_confirm_email_title" => "Bestätigungsmail erneut senden", | ||||||
| @ -43,7 +46,15 @@ return [ | |||||||
|   "confirm_success" => "Ihre E-Mail Adresse wurde erfolgreich bestätigt, Sie können sich jetzt einloggen", |   "confirm_success" => "Ihre E-Mail Adresse wurde erfolgreich bestätigt, Sie können sich jetzt einloggen", | ||||||
|   "confirm_error" => "Fehler beim Bestätigen der E-Mail Adresse", |   "confirm_error" => "Fehler beim Bestätigen der E-Mail Adresse", | ||||||
|   "gpg_key" => "GPG-Schlüssel", |   "gpg_key" => "GPG-Schlüssel", | ||||||
|  |   "no_gpg_key_added" => "Kein GPG-Schlüssel hinzugefügt", | ||||||
|  |   "download_gpg_key" => "GPG-Schlüssel herunterladen", | ||||||
|   "2fa_token" => "Zwei-Faktor Authentifizierung (2FA)", |   "2fa_token" => "Zwei-Faktor Authentifizierung (2FA)", | ||||||
|   "profile_picture_of" => "Profilbild von", |   "profile_picture_of" => "Profilbild von", | ||||||
|  |   "profile_of" => "Profil von", | ||||||
|   "language" => "Sprache", |   "language" => "Sprache", | ||||||
|  |   "profile" => "Benutzerprofil", | ||||||
|  |   "loading_profile" => "Lade Benutzerprofil", | ||||||
|  |   "error_profile_get" => "Fehler beim Laden des Benutzerprofils", | ||||||
|  |   "registered_at" => "Registriert am", | ||||||
|  |   "last_online" => "Zuletzt online", | ||||||
| ]; | ]; | ||||||
| @ -6,10 +6,12 @@ return [ | |||||||
|   "retry" => "Erneut versuchen", |   "retry" => "Erneut versuchen", | ||||||
|   "go_back" => "Zurück", |   "go_back" => "Zurück", | ||||||
|   "save" => "Speichern", |   "save" => "Speichern", | ||||||
|  |   "save_only" => "Nur Speichern", | ||||||
|   "saving" => "Speichere", |   "saving" => "Speichere", | ||||||
|   "unsaved_changes" => "Du hast nicht gespeicherte Änderungen", |   "unsaved_changes" => "Du hast nicht gespeicherte Änderungen", | ||||||
|   "new" => "Neu", |   "new" => "Neu", | ||||||
|   "edit" => "Bearbeiten", |   "edit" => "Bearbeiten", | ||||||
|  |   "apply" => "Übernehmen", | ||||||
|   "submitting" => "Übermittle", |   "submitting" => "Übermittle", | ||||||
|   "submit" => "Absenden", |   "submit" => "Absenden", | ||||||
|   "request" => "Anfordern", |   "request" => "Anfordern", | ||||||
|  | |||||||
| @ -8,6 +8,9 @@ return [ | |||||||
|   "accept_invite_description" => "Complete your account registration by choosing a password", |   "accept_invite_description" => "Complete your account registration by choosing a password", | ||||||
|   "confirm_email_title" => "Confirm Email", |   "confirm_email_title" => "Confirm Email", | ||||||
|   "confirm_email_description" => "Complete your registration by confirming the e-mail address", |   "confirm_email_description" => "Complete your registration by confirming the e-mail address", | ||||||
|  |   "confirm_gpg_title" => "Confirm GPG Key", | ||||||
|  |   "confirm_gpg_error" => "Error confirming GPG Key", | ||||||
|  |   "confirm_gpg_success" => "Successfully confirmed GPG Key", | ||||||
|   "registration_title" => "Registration", |   "registration_title" => "Registration", | ||||||
|   "registration_description" => "Create a new account", |   "registration_description" => "Create a new account", | ||||||
|   "resend_confirm_email_title" => "Resend Confirm Email", |   "resend_confirm_email_title" => "Resend Confirm Email", | ||||||
| @ -43,7 +46,15 @@ return [ | |||||||
|   "confirm_success" => "Your e-mail address was successfully confirmed, you may now log in", |   "confirm_success" => "Your e-mail address was successfully confirmed, you may now log in", | ||||||
|   "confirm_error" => "Error confirming e-mail address", |   "confirm_error" => "Error confirming e-mail address", | ||||||
|   "gpg_key" => "GPG Key", |   "gpg_key" => "GPG Key", | ||||||
|  |   "no_gpg_key_added" => "No GPG key added", | ||||||
|  |   "download_gpg_key" => "Download GPG Key", | ||||||
|   "2fa_token" => "Two-Factor Authentication (2FA)", |   "2fa_token" => "Two-Factor Authentication (2FA)", | ||||||
|   "profile_picture_of" => "Profile Picture of", |   "profile_picture_of" => "Profile Picture of", | ||||||
|  |   "profile_of" => "Profile of", | ||||||
|   "language" => "Language", |   "language" => "Language", | ||||||
|  |   "profile" => "User Profile", | ||||||
|  |   "loading_profile" => "Loading Profile", | ||||||
|  |   "error_profile_get" => "Error retrieving user profile", | ||||||
|  |   "registered_at" => "Registered At", | ||||||
|  |   "last_online" => "Last Online", | ||||||
| ]; | ]; | ||||||
| @ -24,6 +24,7 @@ return [ | |||||||
|   "edit" => "Edit", |   "edit" => "Edit", | ||||||
|   "submitting" => "Submitting", |   "submitting" => "Submitting", | ||||||
|   "submit" => "Submit", |   "submit" => "Submit", | ||||||
|  |   "apply" => "Apply", | ||||||
|   "request" => "Request", |   "request" => "Request", | ||||||
|   "cancel" => "Cancel", |   "cancel" => "Cancel", | ||||||
|   "confirm" => "Confirm", |   "confirm" => "Confirm", | ||||||
| @ -36,6 +37,7 @@ return [ | |||||||
|   "retry" => "Retry", |   "retry" => "Retry", | ||||||
|   "go_back" => "Go Back", |   "go_back" => "Go Back", | ||||||
|   "save" => "Save", |   "save" => "Save", | ||||||
|  |   "save_only" => "Save Only", | ||||||
|   "saving" => "Saving", |   "saving" => "Saving", | ||||||
|   "delete" => "Delete", |   "delete" => "Delete", | ||||||
|   "info" => "Info", |   "info" => "Info", | ||||||
|  | |||||||
| @ -105,6 +105,7 @@ class DatabaseEntityQuery extends Select { | |||||||
|     return $this; |     return $this; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   // TODO: fix cycle detection + rather use deterministic aliases instead of t1, t2, t3...?
 | ||||||
|   private function fetchRelation(string $propertyName, string $tableName, DatabaseEntityHandler $src, DatabaseEntityHandler $relationHandler, |   private function fetchRelation(string $propertyName, string $tableName, DatabaseEntityHandler $src, DatabaseEntityHandler $relationHandler, | ||||||
|                                  bool $recursive = false, string $relationColumnPrefix = "", array &$visited = []) { |                                  bool $recursive = false, string $relationColumnPrefix = "", array &$visited = []) { | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -81,7 +81,7 @@ namespace Core\Objects\DatabaseEntity { | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       return new Language(1, "en_US", "American English"); |       return self::getPredefinedValues()[0]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public function getEntries(?string $module = null): ?array { |     public function getEntries(?string $module = null): ?array { | ||||||
| @ -101,7 +101,7 @@ namespace Core\Objects\DatabaseEntity { | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       return "[$key]"; |       return $key ? "[$key]" : ""; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public function addModule(string $module, array $entries) { |     public function addModule(string $module, array $entries) { | ||||||
| @ -143,8 +143,8 @@ namespace Core\Objects\DatabaseEntity { | |||||||
| 
 | 
 | ||||||
|     public static function getPredefinedValues(): array { |     public static function getPredefinedValues(): array { | ||||||
|       return [ |       return [ | ||||||
|         new Language(Language::AMERICAN_ENGLISH, "en_US", 'American English'), |         new Language(Language::AMERICAN_ENGLISH, "en_US", 'English (US)'), | ||||||
|         new Language(Language::GERMAN_STANDARD, "de_DE", 'Deutsch Standard'), |         new Language(Language::GERMAN_STANDARD, "de_DE", 'Deutsch (Standard)'), | ||||||
|       ]; |       ]; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @ -153,7 +153,7 @@ namespace Core\Objects\DatabaseEntity { | |||||||
| namespace { | namespace { | ||||||
|   function L(string $key): string { |   function L(string $key): string { | ||||||
|     if (!array_key_exists('LANGUAGE', $GLOBALS)) { |     if (!array_key_exists('LANGUAGE', $GLOBALS)) { | ||||||
|       return "[$key]"; |       return $key ? "[$key]" : ""; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     global $LANGUAGE; |     global $LANGUAGE; | ||||||
|  | |||||||
| @ -107,15 +107,23 @@ abstract class Route extends DatabaseEntity { | |||||||
|     return "new $className($args)"; |     return "new $className($args)"; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   private static function getParts(string $url): array { | ||||||
|  |     if ($url === "/" || $url === "") { | ||||||
|  |       return []; | ||||||
|  |     } else { | ||||||
|  |       return explode("/", $url); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   public function match(string $url) { |   public function match(string $url) { | ||||||
| 
 | 
 | ||||||
|     # /test/{abc}/{param:?}/{xyz:int}/{aaa:int?}
 |     # /test/{abc}/{param:?}/{xyz:int}/{aaa:int?}
 | ||||||
|     $patternParts = explode("/", Router::cleanURL($this->pattern, false)); |     $patternParts = self::getParts(Router::cleanURL($this->pattern, false)); | ||||||
|     $countPattern = count($patternParts); |     $countPattern = count($patternParts); | ||||||
|     $patternOffset = 0; |     $patternOffset = 0; | ||||||
| 
 | 
 | ||||||
|     # /test/param/optional/123
 |     # /test/param/optional/123
 | ||||||
|     $urlParts = explode("/", Router::cleanURL($url)); |     $urlParts = self::getParts(Router::cleanURL($url)); | ||||||
|     $countUrl = count($urlParts); |     $countUrl = count($urlParts); | ||||||
|     $urlOffset = 0; |     $urlOffset = 0; | ||||||
| 
 | 
 | ||||||
| @ -235,6 +243,7 @@ abstract class Route extends DatabaseEntity { | |||||||
|       new DocumentRoute("/admin", false, \Core\Documents\Admin::class), |       new DocumentRoute("/admin", false, \Core\Documents\Admin::class), | ||||||
|       new DocumentRoute("/register", true, \Core\Documents\Account::class, "account/register.twig"), |       new DocumentRoute("/register", true, \Core\Documents\Account::class, "account/register.twig"), | ||||||
|       new DocumentRoute("/confirmEmail", true, \Core\Documents\Account::class, "account/confirm_email.twig"), |       new DocumentRoute("/confirmEmail", true, \Core\Documents\Account::class, "account/confirm_email.twig"), | ||||||
|  |       new DocumentRoute("/confirmGPG", true, \Core\Documents\Account::class, "account/confirm_gpg.twig"), | ||||||
|       new DocumentRoute("/acceptInvite", true, \Core\Documents\Account::class, "account/accept_invite.twig"), |       new DocumentRoute("/acceptInvite", true, \Core\Documents\Account::class, "account/accept_invite.twig"), | ||||||
|       new DocumentRoute("/resetPassword", true, \Core\Documents\Account::class, "account/reset_password.twig"), |       new DocumentRoute("/resetPassword", true, \Core\Documents\Account::class, "account/reset_password.twig"), | ||||||
|       new DocumentRoute("/login", true, \Core\Documents\Account::class, "account/login.twig"), |       new DocumentRoute("/login", true, \Core\Documents\Account::class, "account/login.twig"), | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								Core/Templates/account/confirm_gpg.twig
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										36
									
								
								Core/Templates/account/confirm_gpg.twig
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | {% extends "account/account_base.twig" %} | ||||||
|  | 
 | ||||||
|  | {% set view_title = 'account.confirm_gpg_title' %} | ||||||
|  | {% set view_icon = 'user-check' %} | ||||||
|  | {% set view_description = '' %} | ||||||
|  | 
 | ||||||
|  | {% block view_content %} | ||||||
|  |     <noscript> | ||||||
|  |         <div class="alert alert-danger">{{ L('general.noscript') }}</div> | ||||||
|  |     </noscript> | ||||||
|  |     <div class="alert alert-info" id="confirm-status"> | ||||||
|  |         {{ L('account.confirming_gpg') }}… <i class="fas fa-spinner fa-spin"></i> | ||||||
|  |     </div> | ||||||
|  |     <script nonce="{{ site.csp.nonce }}"> | ||||||
|  |         $(document).ready(function() { | ||||||
|  |             let token = jsCore.getParameter("token"); | ||||||
|  |             let confirmStatus = $("#confirm-status"); | ||||||
|  |             if (token) { | ||||||
|  |                 jsCore.apiCall("/user/confirmGPG", { token: token, csrfToken: '{{ user.session.csrfToken }}' }, (res) => { | ||||||
|  |                     confirmStatus.removeClass("alert-info"); | ||||||
|  |                     if (!res.success) { | ||||||
|  |                         confirmStatus.addClass("alert-danger"); | ||||||
|  |                         confirmStatus.text("{{ L('account.confirm_gpg_error') }}: " + res.msg); | ||||||
|  |                     } else { | ||||||
|  |                         confirmStatus.addClass("alert-success"); | ||||||
|  |                         confirmStatus.text("{{ L('account.confirm_gpg_success') }}"); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             } else { | ||||||
|  |                 confirmStatus.removeClass("alert-info"); | ||||||
|  |                 confirmStatus.addClass("alert-danger"); | ||||||
|  |                 confirmStatus.text("{{ L('account.invalid_link') }}"); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     </script> | ||||||
|  | {% endblock %} | ||||||
							
								
								
									
										8
									
								
								cli.php
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										8
									
								
								cli.php
									
									
									
									
									
								
							| @ -480,6 +480,12 @@ function onRoutes(array $argv) { | |||||||
| 
 | 
 | ||||||
|       printTable($head, $tableRows); |       printTable($head, $tableRows); | ||||||
|     } |     } | ||||||
|  |   } else if ($action === "generate_cache") { | ||||||
|  |     $req = new \Core\API\Routes\GenerateCache($context); | ||||||
|  |     $success = $req->execute(); | ||||||
|  |     if (!$success) { | ||||||
|  |       _exit("Error generating cache: " . $req->getLastError()); | ||||||
|  |     } | ||||||
|   } else if ($action === "add") { |   } else if ($action === "add") { | ||||||
|     if (count($argv) < 7) { |     if (count($argv) < 7) { | ||||||
|       _exit("Usage: cli.php routes add <pattern> <type> <target> <exact> [extra]"); |       _exit("Usage: cli.php routes add <pattern> <type> <target> <exact> [extra]"); | ||||||
| @ -543,7 +549,7 @@ function onRoutes(array $argv) { | |||||||
|       _exit("Route updated successfully"); |       _exit("Route updated successfully"); | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     _exit("Usage: cli.php routes <list|enable|disable|add|remove|modify> [options...]"); |     _exit("Usage: cli.php routes <list|enable|disable|add|remove|modify|generate_cache> [options...]"); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ server { | |||||||
| 	error_log  /var/log/nginx/error.log; | 	error_log  /var/log/nginx/error.log; | ||||||
| 	access_log /var/log/nginx/access.log; | 	access_log /var/log/nginx/access.log; | ||||||
| 	root /application; | 	root /application; | ||||||
|  | 	client_max_body_size 1G; | ||||||
| 
 | 
 | ||||||
|     # rewrite error codes |     # rewrite error codes | ||||||
|     error_page   400          /index.php?error=400; |     error_page   400          /index.php?error=400; | ||||||
|  | |||||||
| @ -101,8 +101,8 @@ let Core = function () { | |||||||
|       var param = split[i]; |       var param = split[i]; | ||||||
|       var index = param.indexOf('='); |       var index = param.indexOf('='); | ||||||
|       if (index !== -1) { |       if (index !== -1) { | ||||||
|         var key = param.substr(0, index); |         var key = param.substring(0, index); | ||||||
|         var val = param.substr(index + 1); |         var val = param.substring(index + 1); | ||||||
|         this.parameters[key] = val; |         this.parameters[key] = val; | ||||||
|       } else |       } else | ||||||
|         this.parameters[param] = ''; |         this.parameters[param] = ''; | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ export default class API { | |||||||
|         this.loggedIn = false; |         this.loggedIn = false; | ||||||
|         this.user = null; |         this.user = null; | ||||||
|         this.session = null; |         this.session = null; | ||||||
|         this.language = { id: 1, code: "en_US", shortCode: "en", name: "American English" }; |         this.language = { id: 1, code: "en_US", shortCode: "en", name: "English (US)" }; | ||||||
|         this.permissions = []; |         this.permissions = []; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ | |||||||
| 
 | 
 | ||||||
| .data-table th { | .data-table th { | ||||||
|     background-color: #bbb; |     background-color: #bbb; | ||||||
|  |     white-space: nowrap; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .data-table th > svg { | .data-table th > svg { | ||||||
| @ -34,3 +35,13 @@ | |||||||
|     padding-top: 5px; |     padding-top: 5px; | ||||||
|     padding-bottom: 5px; |     padding-bottom: 5px; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .data-table-buttons { | ||||||
|  |     white-space: nowrap; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .data-table-buttons > svg { | ||||||
|  |     margin-left: 4px; | ||||||
|  |     margin-right: 4px; | ||||||
|  |     cursor: pointer; | ||||||
|  | } | ||||||
| @ -293,7 +293,6 @@ export class ControlsColumn extends DataColumn { | |||||||
|                 ...buttonProps, |                 ...buttonProps, | ||||||
|                 key: "button-" + index, |                 key: "button-" + index, | ||||||
|                 onClick: (e) => { e.stopPropagation(); button.onClick(entry, index); }, |                 onClick: (e) => { e.stopPropagation(); button.onClick(entry, index); }, | ||||||
|                 className: "data-table-clickable", |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (button.hasOwnProperty("disabled")) { |             if (button.hasOwnProperty("disabled")) { | ||||||
| @ -309,8 +308,8 @@ export class ControlsColumn extends DataColumn { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return <> |         return <Box className={"data-table-buttons"}> | ||||||
|             {buttonElements} |             {buttonElements} | ||||||
|         </> |         </Box> | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -7,7 +7,8 @@ export default function useAsyncSearch(callback, minLength = 1) { | |||||||
|     const [results, setResults] = useState(null); |     const [results, setResults] = useState(null); | ||||||
| 
 | 
 | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|         if (!searchString || searchString.length < minLength) { |         console.log("searchString:", searchString); | ||||||
|  |         if (minLength > 0 && (!searchString || searchString.length < minLength)) { | ||||||
|             setResults([]); |             setResults([]); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| import {format, parse} from "date-fns"; | import {format, parse, formatDistance as formatDistanceDateFns } from "date-fns"; | ||||||
| import {API_DATE_FORMAT, API_DATETIME_FORMAT} from "./constants"; | import {API_DATE_FORMAT, API_DATETIME_FORMAT} from "./constants"; | ||||||
| 
 | 
 | ||||||
| function createDownload(name, data) { | function createDownload(name, data) { | ||||||
| @ -58,33 +58,36 @@ const getBaseUrl = () => { | |||||||
|     return window.location.protocol + "//" + window.location.host; |     return window.location.protocol + "//" + window.location.host; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const formatDate = (L, apiDate) => { | const toDate = (apiDate, apiFormat = API_DATETIME_FORMAT) => { | ||||||
|     if (!(apiDate instanceof Date)) { |     if (apiDate === null) { | ||||||
|  |         return ""; | ||||||
|  |     } else if (!(apiDate instanceof Date)) { | ||||||
|         if (!isNaN(apiDate)) { |         if (!isNaN(apiDate)) { | ||||||
|             apiDate = new Date(apiDate * 1000); |             apiDate = new Date(apiDate * 1000); | ||||||
|         } else { |         } else { | ||||||
|             apiDate = parse(apiDate, API_DATE_FORMAT, new Date()); |             apiDate = parse(apiDate, apiFormat, new Date()); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return format(apiDate, L("general.datefns_date_format", "YYY/MM/dd")); |     return apiDate; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const formatDate = (L, apiDate) => { | ||||||
|  |     return format(toDate(apiDate), L("general.datefns_date_format", "YYY/MM/dd")); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const formatDateTime = (L, apiDate, precise=false) => { | const formatDateTime = (L, apiDate, precise=false) => { | ||||||
|     if (!(apiDate instanceof Date)) { |     let dateFormat = precise ? | ||||||
|         if (!isNaN(apiDate)) { |         L("general.datefns_datetime_format_precise", "YYY/MM/dd HH:mm:ss") : | ||||||
|             apiDate = new Date(apiDate * 1000); |         L("general.datefns_datetime_format", "YYY/MM/dd HH:mm"); | ||||||
|         } else { |     return format(toDate(apiDate), dateFormat); | ||||||
|             apiDate = parse(apiDate, API_DATETIME_FORMAT, new Date()); |  | ||||||
|         } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     let dateFormat = precise ? | function formatDistance(dateFns, apiDate) { | ||||||
|         L("general.datefns_date_time_format_precise", "YYY/MM/dd HH:mm:ss") : |     return formatDistanceDateFns(toDate(apiDate), new Date(), { addSuffix: true, locale: dateFns }); | ||||||
|         L("general.datefns_date_time_format", "YYY/MM/dd HH:mm"); |  | ||||||
|     return format(apiDate, dateFormat); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| const upperFirstChars = (str) => { | const upperFirstChars = (str) => { | ||||||
|     return str.split(" ") |     return str.split(" ") | ||||||
|         .map(block => block.charAt(0).toUpperCase() + block.substring(1)) |         .map(block => block.charAt(0).toUpperCase() + block.substring(1)) | ||||||
| @ -97,5 +100,7 @@ const isInt = (value) => { | |||||||
|         !isNaN(parseInt(value, 10)); |         !isNaN(parseInt(value, 10)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export { humanReadableSize, removeParameter, getParameter, encodeText, decodeText, getBaseUrl, | export { humanReadableSize, removeParameter, getParameter, | ||||||
|     formatDate, formatDateTime, upperFirstChars, isInt, createDownload }; |     encodeText, decodeText, getBaseUrl, | ||||||
|  |     formatDate, formatDateTime, formatDistance, | ||||||
|  |     upperFirstChars, isInt, createDownload }; | ||||||
| @ -15,7 +15,6 @@ import React, {useCallback, useContext, useEffect, useState} from "react"; | |||||||
| 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"; |  | ||||||
| import {LocaleContext} from "shared/locale"; | import {LocaleContext} from "shared/locale"; | ||||||
| 
 | 
 | ||||||
| const useStyles = makeStyles((theme) => ({ | const useStyles = makeStyles((theme) => ({ | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user