feat: Ghost error page for improved error display

This commit is contained in:
Maksim Eltyshev
2025-11-06 23:11:06 +01:00
parent 33a7a6ccb1
commit 22baf5ab12
42 changed files with 553 additions and 55 deletions
@@ -1,3 +1,8 @@
/*!
* Copyright (c) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
@@ -0,0 +1,134 @@
/*!
* Copyright (c) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
import React, { useCallback, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { Button, Icon } from 'semantic-ui-react';
import history from '../../../history';
import Paths from '../../../constants/Paths';
import styles from './GhostError.module.scss';
const GhostError = React.memo(({ message }) => {
const [t] = useTranslation();
const eyesRef = useRef(null);
const handleBackClick = useCallback(() => {
history.back();
}, []);
const handleHomeClick = useCallback(() => {
history.push(Paths.ROOT);
}, []);
useEffect(() => {
let pageX = document.documentElement.clientWidth;
let pageY = document.documentElement.clientHeight;
const handleMouseMove = (event) => {
if (!eyesRef.current) {
return;
}
// Vertical axis
const mouseY = event.pageY;
const yAxis = ((pageY / 2 - mouseY) / pageY) * -300;
// Horizontal axis
const mouseX = event.pageX / -pageX;
const xAxis = -mouseX * 100 - 100;
// Apply transform to eyes
eyesRef.current.style.transform = `translate(${xAxis}%, ${yAxis}%)`;
};
const handleResize = () => {
pageX = document.documentElement.clientWidth;
pageY = document.documentElement.clientHeight;
};
document.addEventListener('mousemove', handleMouseMove);
window.addEventListener('resize', handleResize);
return () => {
document.removeEventListener('mousemove', handleMouseMove);
window.removeEventListener('resize', handleResize);
};
}, []);
return (
<div className={styles.wrapper}>
<div className={styles.symbols}>
<div className={styles.symbol} />
<div className={styles.symbol} />
<div className={styles.symbol} />
<div className={styles.symbol} />
<div className={styles.symbol} />
<div className={styles.symbol} />
</div>
<div className={styles.ghost}>
<div ref={eyesRef} className={styles.eyes}>
<div className={styles.eyeLeft} />
<div className={styles.eyeRight} />
</div>
<div className={styles.bottom}>
<div />
<div />
<div />
<div />
<div />
</div>
</div>
<div className={styles.shadow} />
<div className={styles.message}>
<h1 className={styles.title}>
{t('common.whoops', {
context: 'title',
})}
</h1>
<div className={styles.text}>
{t(message, {
context: 'title',
})}
</div>
{window.history.length > 1 && (
<Button
basic
color="yellow"
size="large"
className={styles.button}
onClick={handleBackClick}
>
<Icon name="arrow left" />
{t('action.goBack')}
</Button>
)}
<Button
basic
color="olive"
size="large"
className={styles.button}
onClick={handleHomeClick}
>
<Icon name="home" />
{t('action.goHome')}
</Button>
</div>
</div>
);
});
GhostError.propTypes = {
message: PropTypes.string,
};
GhostError.defaultProps = {
message: 'common.pageNotFound',
};
export default GhostError;
@@ -0,0 +1,298 @@
/*!
* Copyright (c) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
:global(#app) {
.bottom {
display: flex;
left: 0;
position: absolute;
right: 0;
top: 100%;
div {
background-color: #fff;
border-radius: 100%;
flex-grow: 1;
height: 20px;
position: relative;
top: -10px;
&:nth-child(2n) {
background: transparent;
border-top: 15px solid #22252a;
top: -12px;
}
}
}
.button {
padding: 0.78571429em 1.5em 0.78571429em;
}
.eyeLeft {
background: #22252a;
border-radius: 50%;
height: 12px;
left: 10px;
position: absolute;
width: 12px;
}
.eyeRight {
background: #22252a;
border-radius: 50%;
height: 12px;
position: absolute;
right: 10px;
width: 12px;
}
.eyes {
height: 12px;
left: 50%;
position: absolute;
top: 45%;
transform: translateX(-50%);
width: 70px;
}
.ghost {
animation: upndown 3s ease-in-out infinite;
background: #fff;
border-radius: 100px 100px 0 0;
height: 100px;
margin: 0 auto 20px;
position: relative;
width: 100px;
z-index: 1;
}
.message {
max-width: 400px;
text-align: center;
z-index: 1;
}
.shadow {
animation: smallnbig 3s ease-in-out infinite;
background: #000;
border-radius: 50%;
height: 20px;
margin: 0 auto 30px;
width: 80px;
}
.symbol {
&:nth-child(1) {
animation: shine 4s ease-in-out 3s infinite;
left: 20px;
opacity: 0.3;
position: absolute;
top: 20px;
&:before,
&:after {
background: #6b808c;
border-radius: 3px;
content: "";
height: 3px;
position: absolute;
width: 8px;
}
&:before {
transform: rotate(45deg);
}
&:after {
transform: rotate(-45deg);
}
}
&:nth-child(2) {
animation: shine 4s ease-in-out 1.3s infinite;
border: 2px solid;
border-color: #6b808c;
border-radius: 50%;
height: 12px;
opacity: 0.3;
position: absolute;
right: 30px;
top: 40px;
width: 12px;
}
&:nth-child(3) {
animation: shine 3s ease-in-out 0.5s infinite;
bottom: 30px;
left: 30px;
opacity: 0.3;
position: absolute;
&:before,
&:after {
background: #6b808c;
border-radius: 3px;
content: "";
height: 3px;
position: absolute;
width: 8px;
}
&:before {
transform: rotate(90deg);
}
&:after {
transform: rotate(180deg);
}
}
&:nth-child(4) {
animation: shine 6s ease-in-out 1.6s infinite;
opacity: 0.3;
position: absolute;
right: 30px;
top: 10px;
&:before,
&:after {
background: #6b808c;
border-radius: 3px;
content: "";
height: 3px;
position: absolute;
width: 10px;
}
&:before {
transform: rotate(45deg);
}
&:after {
transform: rotate(-45deg);
}
}
&:nth-child(5) {
animation: shine 1.7s ease-in-out 7s infinite;
border: 2px solid;
border-color: #6b808c;
border-radius: 50%;
height: 8px;
opacity: 0.3;
position: absolute;
right: 5px;
top: 60px;
width: 8px;
}
&:nth-child(6) {
animation: shine 2s ease-in-out 6s infinite;
bottom: 10px;
opacity: 0.3;
position: absolute;
right: 10px;
&:before,
&:after {
background: #6b808c;
border-radius: 3px;
content: "";
height: 3px;
position: absolute;
width: 10px;
}
&:before {
transform: rotate(90deg);
}
&:after {
transform: rotate(180deg);
}
}
}
.symbols {
height: 200px;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 200px;
}
.text {
color: #6b808c;
font-size: 18px;
line-height: 1.4;
margin-bottom: 30px;
}
.title {
font-size: 32px;
letter-spacing: 0.5px;
}
.wrapper {
align-items: center;
color: #fff;
display: flex;
flex-direction: column;
height: 100%;
justify-content: center;
min-height: 60vh;
padding: 40px 20px;
position: relative;
width: 100%;
}
@keyframes shine {
0% {
opacity: 0.3;
}
25% {
opacity: 0.1;
}
50% {
opacity: 0.3;
}
100% {
opacity: 0.3;
}
}
@keyframes smallnbig {
0% {
width: 80px;
}
50% {
width: 90px;
}
100% {
width: 80px;
}
}
@keyframes upndown {
0% {
transform: translateY(5px);
}
50% {
transform: translateY(15px);
}
100% {
transform: translateY(5px);
}
}
}
@@ -0,0 +1,8 @@
/*!
* Copyright (c) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
import GhostError from './GhostError';
export default GhostError;
-21
View File
@@ -1,21 +0,0 @@
/*!
* Copyright (c) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
import React from 'react';
import { useTranslation } from 'react-i18next';
const NotFound = React.memo(() => {
const [t] = useTranslation();
return (
<h1>
{t('common.pageNotFound', {
context: 'title',
})}
</h1>
);
});
export default NotFound;
+2 -2
View File
@@ -15,7 +15,7 @@ import { ReduxRouter } from '../../lib/redux-router';
import Paths from '../../constants/Paths';
import Login from './Login';
import Core from './Core';
import NotFound from './NotFound';
import GhostError from './GhostError';
import 'react-datepicker/dist/react-datepicker.css';
import 'photoswipe/dist/photoswipe.css';
@@ -37,7 +37,7 @@ function Root({ store, history }) {
<Route path={Paths.PROJECTS} element={<Core />} />
<Route path={Paths.BOARDS} element={<Core />} />
<Route path={Paths.CARDS} element={<Core />} />
<Route path="*" element={<NotFound />} />
<Route path="*" element={<GhostError />} />
</Routes>
</ToasterProvider>
</ThemeProvider>
+4 -30
View File
@@ -13,6 +13,7 @@ import { useTransitioning } from '../../../lib/hooks';
import selectors from '../../../selectors';
import { BoardViews } from '../../../constants/Enums';
import Home from '../Home';
import GhostError from '../GhostError';
import Board from '../../boards/Board';
import styles from './Static.module.scss';
@@ -42,40 +43,13 @@ const Static = React.memo(() => {
contentNode = <Home />;
} else if (cardId === null) {
wrapperClassNames = [isFavoritesActive && styles.wrapperWithFavorites, styles.wrapperFlex];
contentNode = (
<div className={styles.message}>
<h1>
{t('common.cardNotFound', {
context: 'title',
})}
</h1>
</div>
);
contentNode = <GhostError message="common.cardNotFound" />;
} else if (board === null) {
wrapperClassNames = [isFavoritesActive && styles.wrapperWithFavorites, styles.wrapperFlex];
contentNode = (
<div className={styles.message}>
<h1>
{t('common.boardNotFound', {
context: 'title',
})}
</h1>
</div>
);
contentNode = <GhostError message="common.boardNotFound" />;
} else if (projectId === null) {
wrapperClassNames = [isFavoritesActive && styles.wrapperWithFavorites, styles.wrapperFlex];
contentNode = (
<div className={styles.message}>
<h1>
{t('common.projectNotFound', {
context: 'title',
})}
</h1>
</div>
);
contentNode = <GhostError message="common.projectNotFound" />;
} else if (board === undefined) {
wrapperClassNames = [
isFavoritesActive ? styles.wrapperProjectWithFavorites : styles.wrapperProject,
+3
View File
@@ -19,11 +19,14 @@ export default {
unknownError: 'خطأ غير معروف، يرجى المحاولة لاحقاً',
useSingleSignOn: 'استخدم تسجيل الدخول الموحد',
usernameAlreadyInUse: 'اسم المستخدم تم استخدامه بالفعل',
whoops_title: 'عفواً!',
},
action: {
cancelAndClose: 'إلغاء وإغلاق',
continue: 'متابعة',
goBack: 'العودة',
goHome: 'الذهاب للرئيسية',
logIn: 'تسجيل الدخول',
logInWithSso: 'تسجيل الدخول باستخدام SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Неизвестна грешка, опитайте отново по-късно',
useSingleSignOn: 'Използване на single sign-on',
usernameAlreadyInUse: 'Потребителското име вече се използва',
whoops_title: 'Опа!',
},
action: {
cancelAndClose: 'Отказ и затваряне',
continue: 'Продължи',
goBack: 'Назад',
goHome: 'Към началото',
logIn: 'Вход',
logInWithSso: 'Вход чрез SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Neznámá chyba, zkuste to později',
useSingleSignOn: 'Použít jednorázové přihlášení',
usernameAlreadyInUse: 'Uživatelské jméno se již používá',
whoops_title: 'Jejda!',
},
action: {
cancelAndClose: 'Zrušit a zavřít',
continue: 'Pokračovat',
goBack: 'Zpět',
goHome: 'Domů',
logIn: 'Přihlásit se',
logInWithSso: 'Přihlásit se pomocí SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Ukendt fejl - prøv igen',
useSingleSignOn: 'Anvend single sign-on',
usernameAlreadyInUse: 'Brugernavn allerede i brug',
whoops_title: 'Ups!',
},
action: {
cancelAndClose: 'Annuller og luk',
continue: 'Fortsæt',
goBack: 'Gå tilbage',
goHome: 'Gå hjem',
logIn: 'Log på',
logInWithSso: 'Log på med SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Unbekannter Fehler, bitte später erneut versuchen',
useSingleSignOn: 'Einmalige Anmeldung (SSO) verwenden',
usernameAlreadyInUse: 'Benutzername wird bereits verwendet',
whoops_title: 'Hoppla!',
},
action: {
cancelAndClose: 'Abbrechen und schließen',
continue: 'Fortfahren',
goBack: 'Zurück gehen',
goHome: 'Zur Startseite',
logIn: 'Einloggen',
logInWithSso: 'Einloggen mit SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Άγνωστο σφάλμα, δοκιμάστε ξανά αργότερα',
useSingleSignOn: 'Χρήση Single Sign-On',
usernameAlreadyInUse: 'Το όνομα χρήστη χρησιμοποιείται ήδη',
whoops_title: 'Ωχ!',
},
action: {
cancelAndClose: 'Ακύρωση και κλείσιμο',
continue: 'Συνέχεια',
goBack: 'Επιστροφή',
goHome: 'Αρχική σελίδα',
logIn: 'Σύνδεση',
logInWithSso: 'Σύνδεση με SSO',
},
+3
View File
@@ -19,11 +19,14 @@ export default {
unknownError: 'Unknown error, try again later',
useSingleSignOn: 'Use single sign-on',
usernameAlreadyInUse: 'Username already in use',
whoops_title: 'Whoops!',
},
action: {
cancelAndClose: 'Cancel and close',
continue: 'Continue',
goBack: 'Go back',
goHome: 'Go home',
logIn: 'Log in',
logInWithSso: 'Log in with SSO',
},
+3
View File
@@ -19,11 +19,14 @@ export default {
unknownError: 'Unknown error, try again later',
useSingleSignOn: 'Use single sign-on',
usernameAlreadyInUse: 'Username already in use',
whoops_title: 'Whoops!',
},
action: {
cancelAndClose: 'Cancel and close',
continue: 'Continue',
goBack: 'Go back',
goHome: 'Go home',
logIn: 'Log in',
logInWithSso: 'Log in with SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Error desconocido, inténtalo más tarde',
useSingleSignOn: 'Usar inicio de sesión único',
usernameAlreadyInUse: 'Nombre de usuario ya en uso',
whoops_title: '¡Ups!',
},
action: {
cancelAndClose: 'Cancelar y cerrar',
continue: 'Continuar',
goBack: 'Volver',
goHome: 'Ir al inicio',
logIn: 'Iniciar sesión',
logInWithSso: 'Iniciar sesión con SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Tundmatu viga, proovi hiljem uuesti',
useSingleSignOn: 'Kasuta ühekordset sisselogimist',
usernameAlreadyInUse: 'Kasutajanimi on juba kasutusel',
whoops_title: 'Ups!',
},
action: {
cancelAndClose: 'Tühista ja sulge',
continue: 'Jätka',
goBack: 'Tagasi',
goHome: 'Koju',
logIn: 'Logi sisse',
logInWithSso: 'Logi sisse SSO-ga',
},
+3
View File
@@ -19,11 +19,14 @@ export default {
unknownError: 'خطای ناشناخته، بعداً دوباره تلاش کنید',
useSingleSignOn: 'استفاده از ورود یکپارچه',
usernameAlreadyInUse: 'نام کاربری قبلا استفاده شده است',
whoops_title: 'اوه!',
},
action: {
cancelAndClose: 'لغو و بستن',
continue: 'ادامه',
goBack: 'بازگشت',
goHome: 'رفتن به خانه',
logIn: 'ورود',
logInWithSso: 'ورود با SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Tuntematon virhe, yritä myöhemmin uudelleen',
useSingleSignOn: 'Käytä kertakirjautumista',
usernameAlreadyInUse: 'Käyttäjänimi on jo käytössä',
whoops_title: 'Hups!',
},
action: {
cancelAndClose: 'Peruuta ja sulje',
continue: 'Jatka',
goBack: 'Takaisin',
goHome: 'Kotiin',
logIn: 'Kirjaudu sisään',
logInWithSso: 'Kirjaudu SSO:lla',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Erreur inconnue, réessayez plus tard',
useSingleSignOn: "Utiliser l'authentification unique",
usernameAlreadyInUse: "Nom d'utilisateur déjà utilisé",
whoops_title: 'Oups !',
},
action: {
cancelAndClose: 'Annuler et fermer',
continue: 'Continuer',
goBack: 'Retour',
goHome: "Aller à l'accueil",
logIn: 'Se connecter',
logInWithSso: "Se connecter avec l'authentification unique",
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Ismeretlen hiba, próbáld meg később újra',
useSingleSignOn: 'Egyszeri bejelentkezés használata',
usernameAlreadyInUse: 'A felhasználónév már használatban van',
whoops_title: 'Hoppá!',
},
action: {
cancelAndClose: 'Mégse és bezárás',
continue: 'Folytatás',
goBack: 'Vissza',
goHome: 'Kezdőlapra',
logIn: 'Belépés',
logInWithSso: 'Belépés SSO-val',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Kesalahan tidak diketahui, coba lagi nanti.',
useSingleSignOn: 'Gunakan single sign-on',
usernameAlreadyInUse: 'Username telah digunakan',
whoops_title: 'Ups!',
},
action: {
cancelAndClose: 'Batal dan tutup',
continue: 'Lanjutkan',
goBack: 'Kembali',
goHome: 'Ke beranda',
logIn: 'Masuk',
logInWithSso: 'Masuk dengan SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Errore sconosciuto, prova ancora',
useSingleSignOn: 'Accedi con SSO',
usernameAlreadyInUse: 'Username già in uso',
whoops_title: 'Ops!',
},
action: {
cancelAndClose: 'Annulla e chiudi',
continue: 'Continua',
goBack: 'Torna indietro',
goHome: 'Vai alla home',
logIn: 'Accedi',
logInWithSso: 'Accedi con SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: '不明なエラーです。後でもう一度試してください。',
useSingleSignOn: 'SSOを使用',
usernameAlreadyInUse: 'ユーザー名は既に使われています',
whoops_title: 'おっと!',
},
action: {
cancelAndClose: 'キャンセルして閉じる',
continue: '続行',
goBack: '戻る',
goHome: 'ホームへ',
logIn: 'ログイン',
logInWithSso: 'SSOでログイン',
},
+3
View File
@@ -19,11 +19,14 @@ export default {
unknownError: '알 수 없는 오류, 나중에 다시 시도하세요',
useSingleSignOn: 'Single Sign-On(SSO) 사용',
usernameAlreadyInUse: '이미 사용 중인 사용자 이름',
whoops_title: '앗!',
},
action: {
cancelAndClose: '취소 후 닫기',
continue: '계속',
goBack: '뒤로 가기',
goHome: '홈으로 가기',
logIn: '로그인',
logInWithSso: 'SSO로 로그인',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Onbekende fout, probeer het later opnieuw',
useSingleSignOn: 'Gebruik single sign-on',
usernameAlreadyInUse: 'Gebruikersnaam is al in gebruik',
whoops_title: 'Oeps!',
},
action: {
cancelAndClose: 'Annuleren en sluiten',
continue: 'Doorgaan',
goBack: 'Terug gaan',
goHome: 'Naar startpagina',
logIn: 'Inloggen',
logInWithSso: 'Inloggen met SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Nieznany błąd, spróbuj ponownie później',
useSingleSignOn: 'Użyj logowania SSO',
usernameAlreadyInUse: 'Nazwa użytkownika nie jest dostępna',
whoops_title: 'Ups!',
},
action: {
cancelAndClose: 'Anuluj i zamknij',
continue: 'Kontynuuj',
goBack: 'Wróć',
goHome: 'Idź do domu',
logIn: 'Zaloguj',
logInWithSso: 'Zaloguj z SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Erro desconhecido, tente novamente mais tarde',
useSingleSignOn: 'Usar login único',
usernameAlreadyInUse: 'Nome de usuário já está em uso',
whoops_title: 'Ops!',
},
action: {
cancelAndClose: 'Cancelar e fechar',
continue: 'Continuar',
goBack: 'Voltar',
goHome: 'Ir para início',
logIn: 'Entrar',
logInWithSso: 'Entrar com SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Erro desconhecido, tente novamente mais tarde',
useSingleSignOn: 'Utilizar início de sessão único',
usernameAlreadyInUse: 'Nome de utilizador já está em uso',
whoops_title: 'Ups!',
},
action: {
cancelAndClose: 'Cancelar e fechar',
continue: 'Continuar',
goBack: 'Voltar',
goHome: 'Ir para início',
logIn: 'Iniciar sessão',
logInWithSso: 'Iniciar sessão com SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Eroarea necunoscuta, mai incercați',
useSingleSignOn: 'Folosiți autentificarea unica',
usernameAlreadyInUse: 'Nume utilizator deja exista',
whoops_title: 'Ups!',
},
action: {
cancelAndClose: 'Anulează și închide',
continue: 'Continuă',
goBack: 'Înapoi',
goHome: 'Acasă',
logIn: 'Autentificarea',
logInWithSso: 'Autentificarea cu SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Что-то пошло не так, попробуйте позже',
useSingleSignOn: 'Используйте единый вход',
usernameAlreadyInUse: 'Имя пользователя уже занято',
whoops_title: 'Упс!',
},
action: {
cancelAndClose: 'Отменить и закрыть',
continue: 'Продолжить',
goBack: 'Назад',
goHome: 'На главную',
logIn: 'Войти',
logInWithSso: 'Войти с помощью единого входа',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Neznáma chyba, skúste to neskôr',
useSingleSignOn: 'Použiť jednotné prihlásenie',
usernameAlreadyInUse: 'Používateľské meno je zabrané',
whoops_title: 'Ups!',
},
action: {
cancelAndClose: 'Zrušiť a zavrieť',
continue: 'Pokračovať',
goBack: 'Ísť späť',
goHome: 'Ísť domov',
logIn: 'Prihlásiť sa',
logInWithSso: 'Prihlásiť sa cez SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Непозната грешка, покушајте поново касније',
useSingleSignOn: 'Користи универзалну пријаву',
usernameAlreadyInUse: 'Корисничко име је већ у употреби',
whoops_title: 'Упс!',
},
action: {
cancelAndClose: 'Откажи и затвори',
continue: 'Настави',
goBack: 'Назад',
goHome: 'Иди кући',
logIn: 'Пријава',
logInWithSso: 'Пријава са УП',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Nepoznata greška, pokušajte ponovo kasnije',
useSingleSignOn: 'Koristi univerzalnu prijavu',
usernameAlreadyInUse: 'Korisničko ime je već u upotrebi',
whoops_title: 'Ups!',
},
action: {
cancelAndClose: 'Otkaži i zatvori',
continue: 'Nastavi',
goBack: 'Nazad',
goHome: 'Idi kući',
logIn: 'Prijava',
logInWithSso: 'Prijava sa UP',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Okänt fel, försök igen senare',
useSingleSignOn: 'Använd enkel inloggning',
usernameAlreadyInUse: 'Användarnamnet används redan',
whoops_title: 'Hoppsan!',
},
action: {
cancelAndClose: 'Avbryt och stäng',
continue: 'Fortsätt',
goBack: 'Gå tillbaka',
goHome: 'Gå hem',
logIn: 'Logga in',
logInWithSso: 'Logga in med SSO',
},
+3
View File
@@ -19,11 +19,14 @@ export default {
unknownError: 'Bilinmeyen hata, daha sonra tekrar deneyin',
useSingleSignOn: 'Tek oturum açma kullan',
usernameAlreadyInUse: 'Kullanıcı adı zaten kullanımda',
whoops_title: 'Hata!',
},
action: {
cancelAndClose: 'İptal et ve kapat',
continue: 'Devam et',
goBack: 'Geri dön',
goHome: 'Ana sayfaya git',
logIn: 'Giriş yap',
logInWithSso: 'SSO ile giriş yap',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: 'Невідома помилка, спробуйте ще раз пізніше',
useSingleSignOn: 'Використовувати одночасний вхід',
usernameAlreadyInUse: "Ім'я користувача вже використовується",
whoops_title: 'Ой!',
},
action: {
cancelAndClose: 'Скасувати та закрити',
continue: 'Продовжити',
goBack: 'Назад',
goHome: 'На головну',
logIn: 'Увійти',
logInWithSso: 'Увійти за допомогою SSO',
},
+3
View File
@@ -20,11 +20,14 @@ export default {
unknownError: "Noma'lum xatolik, qaytadan urinib ko'ring",
useSingleSignOn: 'Yagona kirish tizimidan foydalaning',
usernameAlreadyInUse: 'Foydalanuvchi nomi allaqachon mavjud',
whoops_title: 'Voy!',
},
action: {
cancelAndClose: 'Bekor qilish va yopish',
continue: 'Davom etish',
goBack: 'Orqaga',
goHome: 'Bosh sahifaga',
logIn: 'Kirish',
logInWithSso: 'SSO orqali kirish',
},
+3
View File
@@ -19,11 +19,14 @@ export default {
unknownError: '未知错误,请稍后重试',
useSingleSignOn: '使用单点登录',
usernameAlreadyInUse: '用户名已被占用',
whoops_title: '哎呀!',
},
action: {
cancelAndClose: '取消并关闭',
continue: '继续',
goBack: '返回',
goHome: '回到首页',
logIn: '登录',
logInWithSso: '使用SSO登录',
},
+3
View File
@@ -19,11 +19,14 @@ export default {
unknownError: '未知錯誤,請稍後重試',
useSingleSignOn: '使用單一登入',
usernameAlreadyInUse: '使用者名稱已被佔用',
whoops_title: '哎呀!',
},
action: {
cancelAndClose: '取消並關閉',
continue: '繼續',
goBack: '返回',
goHome: '回到首頁',
logIn: '登入',
logInWithSso: '使用SSO登入',
},
+2 -2
View File
@@ -39,8 +39,8 @@ export default (state = initialState, { type, payload }) => {
const nextState = {
...state,
isContentFetching: false,
boardId: payload.currentBoardId,
cardId: payload.currentCardId,
boardId: payload.currentBoardId || null,
cardId: payload.currentCardId || null,
};
if (payload.currentCardId) {
+1
View File
@@ -47,6 +47,7 @@ export function* handleLocationChange() {
const pathsMatch = yield select(selectors.selectPathsMatch);
if (!pathsMatch) {
yield put(actions.handleLocationChange());
return;
}