Put all user information (including locale) into a user context. Language can be changed, all pages access the user context now. Translated some stuff.

This commit is contained in:
Daniel Ledda
2020-05-24 11:37:04 +02:00
parent 7cb8a03c24
commit 0fe94c3066
21 changed files with 196 additions and 137 deletions

View File

@@ -7,7 +7,7 @@
"author": "Daniel Ledda",
"scripts": {
"build": "webpack --mode development",
"postbuild": "rsync -avu --delete dist/ ../kadi_backend/dist/frontend/static",
"postbuild": "rsync -avu --delete dist/ ../kadi_backend/static/frontend",
"start": "webpack-dev-server --mode development",
"test": "echo \"Error: no test specified\" && exit 1"
},

View File

@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="favicon.ico" />
<link rel="icon" href="static/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
@@ -17,6 +17,6 @@
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<script src="../dist/bundle.js"></script>
<script src="static/bundle.js"></script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,25 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@@ -9,18 +9,16 @@ import HomePage from "./Components/HomePage";
import {SERVER_BASE_NAME} from "./index";
import axios from "axios";
import UserContext, {IUserContext} from "./Contexts/UserContext";
import LocaleContext, {ILocaleContext} from "./Contexts/LocaleContext";
interface AppState {
userContext: IUserContext;
localeContext: ILocaleContext;
}
interface AppProps {}
class App extends React.Component<AppProps, AppState> {
private readonly updateUserContext: (username: string, loggedIn: boolean) => void;
private readonly changeLang: (lang: SupportedLang) => void;
private readonly changeLang: (lang: SupportedLang, submit?: boolean) => void;
constructor(props: AppProps) {
super(props);
@@ -28,16 +26,25 @@ class App extends React.Component<AppProps, AppState> {
this.setState({userContext: {
username: username,
loggedIn: loggedIn,
updateUserContext: this.updateUserContext
updateUserContext: this.updateUserContext,
currentLang: this.state.userContext.currentLang,
strings: this.state.userContext.strings,
changeLang: this.state.userContext.changeLang,
}});
};
this.changeLang = (lang: SupportedLang) => {
this.setState({localeContext: {
this.changeLang = (lang: SupportedLang, submit=true) => {
this.setState({userContext: {
strings: IntlStrings[lang],
currentLang: lang,
changeLang: this.changeLang
changeLang: this.changeLang,
username: this.state.userContext.username,
loggedIn: this.state.userContext.loggedIn,
updateUserContext: this.state.userContext.updateUserContext,
}});
if (submit) {
this.submitLanguagePreference(lang);
}
};
this.state = {
@@ -45,32 +52,40 @@ class App extends React.Component<AppProps, AppState> {
username: "",
loggedIn: false,
updateUserContext: this.updateUserContext,
},
localeContext: {
currentLang: SupportedLang.gb,
strings: IntlStrings[SupportedLang.gb],
changeLang: this.changeLang,
}
};
}
componentDidMount(): void {
this.getDefaultVals();
}
getDefaultVals(): void {
axios.get("/api/user", {baseURL: SERVER_BASE_NAME})
.then((res) => {
const data = res.data as any;
if (data.loggedIn) {
this.updateUserContext(data.username, true);
}
else {
this.updateUserContext("", false);
this.updateUserContext(data.username, data.loggedIn);
this.changeLang(data.lang, false);
}
})
.catch(err => console.log(err));
}
submitLanguagePreference(lang: SupportedLang) {
axios.post(SERVER_BASE_NAME + "/api/changeLang",
{lang: lang},
{headers: {"Content-Type": "application/json"}}
);
};
render(): ReactNode {
return (
<UserContext.Provider value={this.state.userContext}>
<LocaleContext.Provider value={this.state.localeContext}>
<Router basename={SERVER_BASE_NAME}>
<Route exact={true} path={"/"}>
<KadiPage activePage={PageId.home}>
@@ -90,7 +105,6 @@ class App extends React.Component<AppProps, AppState> {
/>
</Route>
</Router>
</LocaleContext.Provider>
</UserContext.Provider>
);
}

View File

@@ -1,6 +1,6 @@
import React, {ReactElement} from "react";
import KadiPage from "../Components/KadiPage";
import {Header} from "semantic-ui-react";
import UserContext from "../Contexts/UserContext";
interface FriendsPageProps {}
@@ -16,12 +16,14 @@ class FriendsPage extends React.Component<FriendsPageProps, FriendsPageState> {
}
render(): ReactElement {
const Locale = this.context.strings;
return (
<Header>
My Friends
{Locale.friendsPage.title}
</Header>
);
}
}
FriendsPage.contextType = UserContext;
export default FriendsPage;

View File

@@ -2,6 +2,7 @@ import React, {ReactElement} from "react";
import {Header, List, ListItem} from "semantic-ui-react";
import axios from "axios";
import {SERVER_BASE_NAME} from "../index";
import UserContext from "../Contexts/UserContext";
interface HistoryPageProps {
}
@@ -22,10 +23,11 @@ class HistoryPage extends React.Component<HistoryPageProps, HistoryPageState> {
}
componentDidMount(): void {
axios.get(SERVER_BASE_NAME + "/api/games/")
axios.get(SERVER_BASE_NAME + "/api/games")
.then(response => this.setState({gameListings: response.data.games}))
.catch(error => this.handleError(error))
.finally(() => this.setState({ loadingGames: false }));
console.log(this.state.gameListings);
}
handleError = (error: any) => void {
@@ -33,11 +35,19 @@ class HistoryPage extends React.Component<HistoryPageProps, HistoryPageState> {
};
render(): ReactElement {
const Locale = this.context.strings;
return (
<>
<Header size={"huge"}>
History
{Locale.historyPage.title}
</Header>
{
this.state.loadingGames ? (
<p>
Loading games...
</p>
) :
(
<List bulleted={true}>
{
this.state.gameListings.map(listing => {
@@ -45,9 +55,12 @@ class HistoryPage extends React.Component<HistoryPageProps, HistoryPageState> {
})
}
</List>
)
}
</>
);
}
}
HistoryPage.contextType = UserContext;
export default HistoryPage;

View File

@@ -1,6 +1,6 @@
import React, {ReactElement} from "react";
import KadiPage from "../Components/KadiPage";
import {Header} from "semantic-ui-react";
import UserContext from "../Contexts/UserContext";
interface HomePageProps {}
@@ -16,12 +16,14 @@ class HomePage extends React.Component<HomePageProps, HomePageState> {
}
render(): ReactElement {
const Locale = this.context.strings;
return (
<Header>
Home
{Locale.homePage.title}
</Header>
);
}
}
HomePage.contextType = UserContext;
export default HomePage;

View File

@@ -4,6 +4,7 @@ import "../static/css/site.css";
import KadiSidebarNav from "../Components/KadiSidebarNav";
import MainPageContent from "../Components/MainPageContent";
import {PageId} from "../enums";
import UserContext from "../Contexts/UserContext";
interface KadiPageProps {
activePage: PageId;
@@ -32,5 +33,6 @@ class KadiPage extends React.Component<KadiPageProps, KadiPageState> {
);
}
}
KadiPage.contextType = UserContext;
export default KadiPage;

View File

@@ -1,7 +1,7 @@
import {Header, HeaderContent, Icon, Image, Menu, Segment, Sidebar, SidebarPusher} from "semantic-ui-react";
import {Header, HeaderContent, Icon, Image, Menu} from "semantic-ui-react";
import logo from "../static/images/kadi.png";
import React from "react";
import LocaleContext from "../Contexts/LocaleContext";
import UserContext from "../Contexts/UserContext";
import {Link} from "react-router-dom";
import {PageId} from "../enums";
import {SERVER_BASE_NAME} from "../index";
@@ -11,7 +11,7 @@ interface KadiSidebarNavProps {
}
const KadiSidebarNav: React.FunctionComponent<KadiSidebarNavProps> = (props) => {
const Locale = React.useContext(LocaleContext).strings;
const Locale = React.useContext(UserContext).strings;
const {activeItem} = props;
return (
<Menu
@@ -40,7 +40,7 @@ const KadiSidebarNav: React.FunctionComponent<KadiSidebarNavProps> = (props) =>
<Icon name={"game"} />
{Locale.menu.playTab}
</Menu.Item>
<Link to={"/" + PageId.profile}>
<Link to={PageId.profile}>
<Menu.Item
as={"a"}
icon={true}
@@ -50,7 +50,7 @@ const KadiSidebarNav: React.FunctionComponent<KadiSidebarNavProps> = (props) =>
{Locale.menu.profileTab}
</Menu.Item>
</Link>
<Link to={"/" + PageId.stats}>
<Link to={PageId.stats}>
<Menu.Item
as={"a"}
icon={true}
@@ -60,7 +60,7 @@ const KadiSidebarNav: React.FunctionComponent<KadiSidebarNavProps> = (props) =>
{Locale.menu.statsTab}
</Menu.Item>
</Link>
<Link to={"/" + PageId.rulesets}>
<Link to={PageId.rulesets}>
<Menu.Item
as={"a"}
icon={true}
@@ -70,7 +70,7 @@ const KadiSidebarNav: React.FunctionComponent<KadiSidebarNavProps> = (props) =>
{Locale.menu.rulesetsTab}
</Menu.Item>
</Link>
<Link to={"/" + PageId.friends}>
<Link to={PageId.friends}>
<Menu.Item
as={"a"}
icon={true}
@@ -80,7 +80,7 @@ const KadiSidebarNav: React.FunctionComponent<KadiSidebarNavProps> = (props) =>
{Locale.menu.friendsTab}
</Menu.Item>
</Link>
<Link to={"/" + PageId.history}>
<Link to={PageId.history}>
<Menu.Item
as={"a"}
icon={true}

View File

@@ -1,7 +1,6 @@
import React, {ReactElement, SyntheticEvent} from "react";
import {Dropdown, DropdownItemProps, DropdownProps, Flag, Icon, Menu} from "semantic-ui-react";
import React, {ReactElement} from "react";
import {Dropdown, DropdownItemProps, Flag, Icon, Menu} from "semantic-ui-react";
import {SERVER_BASE_NAME} from "../index";
import LocaleContext from "../Contexts/LocaleContext";
import {LanguageNames} from "../static/strings";
import {IUserContext} from "../Contexts/UserContext";
import {SupportedLang} from "../enums";
@@ -11,7 +10,6 @@ interface KadiTopMenuBarProps {
}
interface KadiTopMenuBarState {
currentLangSelection: SupportedLang;
}
class KadiTopMenuBar extends React.Component<KadiTopMenuBarProps, KadiTopMenuBarState> {
@@ -21,7 +19,6 @@ class KadiTopMenuBar extends React.Component<KadiTopMenuBarProps, KadiTopMenuBar
super(props);
this.state = {
currentLangSelection: SupportedLang.gb,
};
this.changeLanguageGlobally = () => {};
@@ -33,19 +30,8 @@ class KadiTopMenuBar extends React.Component<KadiTopMenuBarProps, KadiTopMenuBar
}
}
componentDidMount(): void {
this.changeLanguageGlobally = this.context.changeLang;
}
handleLanguageChange: (e: SyntheticEvent, data: DropdownProps) => void = (event, data) => {
const lang = data.value as SupportedLang;
this.setState({currentLangSelection: lang});
this.changeLanguageGlobally(lang);
};
render(): ReactElement {
const {loggedIn, username} = this.props.user;
const Locale = this.context.strings;
const {loggedIn, username, strings: Locale, currentLang, changeLang} = this.props.user;
return (
<Menu
@@ -72,12 +58,12 @@ class KadiTopMenuBar extends React.Component<KadiTopMenuBarProps, KadiTopMenuBar
<Dropdown
trigger={(
<span>
<Flag name={this.state.currentLangSelection} />
{LanguageNames[this.state.currentLangSelection]}
<Flag name={currentLang} />
{LanguageNames[currentLang]}
</span>
)}
options={this.languageDropdowns}
onChange={this.handleLanguageChange}
onChange={(e, d) => changeLang(d.value as SupportedLang)}
/>
</Menu.Item>
</Menu.Menu>
@@ -85,6 +71,5 @@ class KadiTopMenuBar extends React.Component<KadiTopMenuBarProps, KadiTopMenuBar
);
}
}
KadiTopMenuBar.contextType = LocaleContext;
export default KadiTopMenuBar;

View File

@@ -1,6 +1,6 @@
import React, {ReactElement} from "react";
import KadiPage from "../Components/KadiPage";
import {Header} from "semantic-ui-react";
import UserContext from "../Contexts/UserContext";
interface ProfilePageProps {}
@@ -16,12 +16,14 @@ class ProfilePage extends React.Component<ProfilePageProps, ProfilePageState> {
}
render(): ReactElement {
const Locale = this.context.strings;
return (
<Header>
My Profile
<Header size={"huge"}>
{Locale.profilePage.title}
</Header>
);
}
}
ProfilePage.contextType = UserContext;
export default ProfilePage;

View File

@@ -1,6 +1,6 @@
import React, {ReactElement} from "react";
import KadiPage from "../Components/KadiPage";
import {Header} from "semantic-ui-react";
import UserContext from "../Contexts/UserContext";
interface RulesetsPageProps {}
@@ -16,12 +16,14 @@ class RulesetsPage extends React.Component<RulesetsPageProps, RulesetsPageState>
}
render(): ReactElement {
const Locale = this.context.strings;
return (
<Header>
My Rulesets
{Locale.rulesetsPage.title}
</Header>
);
}
}
RulesetsPage.contextType = UserContext;
export default RulesetsPage;

View File

@@ -1,7 +1,6 @@
import React, {ReactNode} from "react";
import {BrowserRouter as Router, Link, Route} from "react-router-dom";
import {Header} from "semantic-ui-react";
import KadiPage from "../Components/KadiPage";
import UserContext from "../Contexts/UserContext";
interface StatsPageProps {}
@@ -17,12 +16,14 @@ class StatsPage extends React.Component<StatsPageProps, StatsPageState> {
}
render(): ReactNode {
const Locale = this.context.strings;
return (
<Header>
My Stats
{Locale.statsPage.title}
</Header>
);
}
}
StatsPage.contextType = UserContext;
export default StatsPage;

View File

@@ -1,19 +0,0 @@
import {SupportedLang} from "../enums";
import React from "react";
import {IntlStrings} from "../static/strings";
export interface ILocaleContext {
currentLang: SupportedLang;
strings: any;
changeLang: (lang: SupportedLang) => void;
}
export const localeDefaultVal: ILocaleContext = {
currentLang: SupportedLang.gb,
strings: IntlStrings[SupportedLang.gb as SupportedLang],
changeLang: () => {},
};
const LocaleContext = React.createContext(localeDefaultVal);
export default LocaleContext;

View File

@@ -1,15 +1,23 @@
import React from "react";
import {SupportedLang} from "../enums";
import {IntlStrings} from "../static/strings";
export interface IUserContext {
username: string;
loggedIn: boolean;
updateUserContext: (username: string, loggedIn: boolean) => void;
currentLang: SupportedLang;
strings: any;
changeLang: (lang: SupportedLang, submit?: boolean) => void;
}
const userDefaultVal = {
loggedIn: false,
username: "",
updateUserContext: () => {},
currentLang: SupportedLang.gb,
strings: IntlStrings[SupportedLang.gb as SupportedLang],
changeLang: () => {},
} as IUserContext;
const UserContext = React.createContext(userDefaultVal);

View File

@@ -481,7 +481,8 @@
y="30.678488"
ry="50.39043" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
id="path2986-9-6-9-0"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
cy="170.66669"
@@ -503,13 +504,15 @@
id="rect58-5-2-5-0"
style="fill:url(#linearGradient2955-9-2-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:9.59501;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="252.17938"
cy="596.60443"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-1-1);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-54-0-3" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="88.967949"
cy="426.58774"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-8-0);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
@@ -531,31 +534,36 @@
id="rect58-5-2-5-4"
style="fill:url(#linearGradient2955-9-2-9);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:9.59501;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="853.33337"
cy="170.66669"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-1);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-29" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="771.63464"
cy="256.07895"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-9-8);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-3-8-22" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="934.84607"
cy="255.27113"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-1-7);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-54-0-2" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="771.63464"
cy="85.254402"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-8-4);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-3-84-5" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="934.84607"
cy="84.446587"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-4-8);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
@@ -577,25 +585,29 @@
id="rect58-5-2-5-6"
style="fill:url(#linearGradient2955-9-2-8);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:9.59501;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="430.30133"
cy="597.41235"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-9-2);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-3-8-4" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="593.5127"
cy="596.60443"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-1-5);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-54-0-35" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="430.30133"
cy="426.58774"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-8-49);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-3-84-7" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="593.5127"
cy="425.77991"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-4-9);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
@@ -617,19 +629,22 @@
y="713.34515"
ry="50.39043" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
id="path2986-9-6-9-0-39-0"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-2-8);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
cy="853.33337"
cx="170.66666" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
id="path2986-9-6-9-0-54-0-3-6"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-1-1-1);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
cy="937.93781"
cx="252.17938" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
id="path2986-9-6-9-0-3-84-8-1"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-8-0-4);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
cy="767.92108"
@@ -651,37 +666,43 @@
y="713.34515"
ry="50.39043" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="771.63464"
cy="853.33337"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-6-1);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-3-3-4" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
cx="934.84607"
cy="852.52551"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-41-9);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
id="path2986-9-6-9-0-54-3-7" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
id="path2986-9-6-9-0-3-8-8-8"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-9-88-7);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
cy="938.74567"
cx="771.63464" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
id="path2986-9-6-9-0-54-0-0-5"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-1-9-8);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
cy="937.93781"
cx="934.84607" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
id="path2986-9-6-9-0-3-84-76-2"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-64-8-88-5);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
cy="767.92108"
cx="771.63464" />
<ellipse
r="29.836327"
rx="29.836327"
ry="29.836327"
id="path2986-9-6-9-0-54-7-8-6"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#radialGradient3042-3-1-6-0-4-86-3);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:4.448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000000;stop-opacity:1"
cy="767.11328"

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -39,6 +39,24 @@ export const IntlStrings = {
logoutButton: "Logout",
userWelcome: "Hi, ",
},
homePage: {
title: "Home",
},
profilePage: {
title: "Profile",
},
statsPage: {
title: "Stats",
},
rulesetsPage: {
title: "Rulesets",
},
friendsPage: {
title: "Friends",
},
historyPage: {
title: "History",
},
},
de: {
menu: {
@@ -52,6 +70,24 @@ export const IntlStrings = {
logoutButton: "Abmelden",
userWelcome: "Hallo, ",
},
homePage: {
title: "Startseite",
},
profilePage: {
title: "Profil",
},
statsPage: {
title: "Statistiken",
},
rulesetsPage: {
title: "Regelwerke",
},
friendsPage: {
title: "Freunde",
},
historyPage: {
title: "Spielverlauf",
},
},
it: {
menu: {
@@ -65,5 +101,23 @@ export const IntlStrings = {
logoutButton: "Esci",
userWelcome: "Ciao, ",
},
homePage: {
title: "Home",
},
profilePage: {
title: "Profilo",
},
statsPage: {
title: "Statistiche",
},
rulesetsPage: {
title: "Regolamenti",
},
friendsPage: {
title: "Amici",
},
historyPage: {
title: "Storia",
},
},
} as const;

View File

@@ -38,7 +38,7 @@ module.exports = {
resolve: { extensions: [".tsx", ".ts", ".js", "*"] },
output: {
path: path.resolve(__dirname, "dist/"),
publicPath: "/kadi/static/",
publicPath: "/kadi/static/frontend/",
filename: "bundle.js"
},
devServer: {