Profile page shows guests and lets you delete them. History page shows times in the appropriate format. IntlDatetime set up for each locale.

This commit is contained in:
Daniel Ledda
2020-05-25 22:54:15 +02:00
parent 0fe94c3066
commit 901cb04955
16 changed files with 287 additions and 97 deletions

View File

@@ -1,3 +1,8 @@
{ {
"presets": ["@babel/env", "@babel/preset-react"] "presets": [
"@babel/preset-typescript",
"@babel/env",
"@babel/preset-react"
],
"plugins": ["@babel/plugin-proposal-class-properties"]
} }

68
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "kadi-frontend", "name": "kadi-frontend",
"version": "0.1.0", "version": "1.0.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@@ -271,6 +271,20 @@
"semver": "^5.5.0" "semver": "^5.5.0"
} }
}, },
"@babel/helper-create-class-features-plugin": {
"version": "7.9.6",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.9.6.tgz",
"integrity": "sha512-6N9IeuyHvMBRyjNYOMJHrhwtu4WJMrYf8hVbEHD3pbbbmNOk1kmXSQs7bA4dYDUaIx4ZEzdnvo6NwC3WHd/Qow==",
"dev": true,
"requires": {
"@babel/helper-function-name": "^7.9.5",
"@babel/helper-member-expression-to-functions": "^7.8.3",
"@babel/helper-optimise-call-expression": "^7.8.3",
"@babel/helper-plugin-utils": "^7.8.3",
"@babel/helper-replace-supers": "^7.9.6",
"@babel/helper-split-export-declaration": "^7.8.3"
}
},
"@babel/helper-create-regexp-features-plugin": { "@babel/helper-create-regexp-features-plugin": {
"version": "7.8.8", "version": "7.8.8",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz",
@@ -547,6 +561,16 @@
"@babel/plugin-syntax-async-generators": "^7.8.0" "@babel/plugin-syntax-async-generators": "^7.8.0"
} }
}, },
"@babel/plugin-proposal-class-properties": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz",
"integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==",
"dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.8.3",
"@babel/helper-plugin-utils": "^7.8.3"
}
},
"@babel/plugin-proposal-dynamic-import": { "@babel/plugin-proposal-dynamic-import": {
"version": "7.8.3", "version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz",
@@ -718,6 +742,15 @@
"@babel/helper-plugin-utils": "^7.8.3" "@babel/helper-plugin-utils": "^7.8.3"
} }
}, },
"@babel/plugin-syntax-typescript": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz",
"integrity": "sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.3"
}
},
"@babel/plugin-transform-arrow-functions": { "@babel/plugin-transform-arrow-functions": {
"version": "7.8.3", "version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz",
@@ -1066,6 +1099,17 @@
"@babel/helper-plugin-utils": "^7.8.3" "@babel/helper-plugin-utils": "^7.8.3"
} }
}, },
"@babel/plugin-transform-typescript": {
"version": "7.9.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.6.tgz",
"integrity": "sha512-8OvsRdvpt3Iesf2qsAn+YdlwAJD7zJ+vhFZmDCa4b8dTp7MmHtKk5FF2mCsGxjZwuwsy/yIIay/nLmxST1ctVQ==",
"dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.9.6",
"@babel/helper-plugin-utils": "^7.8.3",
"@babel/plugin-syntax-typescript": "^7.8.3"
}
},
"@babel/plugin-transform-unicode-regex": { "@babel/plugin-transform-unicode-regex": {
"version": "7.8.3", "version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz",
@@ -1190,6 +1234,16 @@
"@babel/plugin-transform-react-jsx-source": "^7.9.0" "@babel/plugin-transform-react-jsx-source": "^7.9.0"
} }
}, },
"@babel/preset-typescript": {
"version": "7.9.0",
"resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz",
"integrity": "sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.3",
"@babel/plugin-transform-typescript": "^7.9.0"
}
},
"@babel/runtime": { "@babel/runtime": {
"version": "7.9.2", "version": "7.9.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
@@ -3053,9 +3107,9 @@
"dev": true "dev": true
}, },
"eventemitter3": { "eventemitter3": {
"version": "4.0.0", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
"integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==",
"dev": true "dev": true
}, },
"events": { "events": {
@@ -3834,9 +3888,9 @@
} }
}, },
"http-proxy": { "http-proxy": {
"version": "1.18.0", "version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"eventemitter3": "^4.0.0", "eventemitter3": "^4.0.0",

View File

@@ -6,33 +6,28 @@
"license": "ISC", "license": "ISC",
"author": "Daniel Ledda", "author": "Daniel Ledda",
"scripts": { "scripts": {
"build": "webpack --mode development", "build-dev": "webpack --mode development && npm postbuild",
"build": "webpack --mode production",
"postbuild": "rsync -avu --delete dist/ ../kadi_backend/static/frontend", "postbuild": "rsync -avu --delete dist/ ../kadi_backend/static/frontend",
"start": "webpack-dev-server --mode development", "start": "webpack-dev-server --mode development",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"dependencies": {
"axios": "^0.19.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.88.2"
},
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.8.4", "@babel/cli": "^7.8.4",
"@babel/core": "^7.9.6", "@babel/core": "^7.9.6",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/preset-env": "^7.9.6", "@babel/preset-env": "^7.9.6",
"@babel/preset-react": "^7.9.4", "@babel/preset-react": "^7.9.4",
"@babel/preset-typescript": "^7.9.0",
"@types/node": "^13.11.1", "@types/node": "^13.11.1",
"@types/react": "^16.9.34", "@types/react": "^16.9.34",
"@types/react-dom": "^16.9.7", "@types/react-dom": "^16.9.7",
"@types/react-router-dom": "^5.1.5", "@types/react-router-dom": "^5.1.5",
"ignore-loader": "^0.1.2",
"font-loader": "^0.1.2",
"babel-loader": "^8.1.0", "babel-loader": "^8.1.0",
"css-loader": "^3.5.3", "css-loader": "^3.5.3",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"font-loader": "^0.1.2",
"ignore-loader": "^0.1.2",
"react-hot-loader": "^4.12.21", "react-hot-loader": "^4.12.21",
"style-loader": "^1.2.1", "style-loader": "^1.2.1",
"ts-loader": "^7.0.3", "ts-loader": "^7.0.3",
@@ -42,5 +37,13 @@
"webpack": "^4.43.0", "webpack": "^4.43.0",
"webpack-cli": "^3.3.11", "webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0" "webpack-dev-server": "^3.11.0"
},
"dependencies": {
"axios": "^0.19.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^0.88.2"
} }
} }

View File

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

View File

@@ -1,8 +1,8 @@
import React, {ReactNode} from "react"; import React, {ReactNode} from "react";
import {BrowserRouter as Router, Link, Route} from "react-router-dom"; import {BrowserRouter as Router, Route} from "react-router-dom";
import {Redirect, Switch} from "react-router"; import {Redirect} from "react-router";
import {IntlStrings} from "./static/strings"; import {IntlStrings} from "./static/strings";
import {PageId, SupportedLang} from "./enums"; import {PageId, SupportedLang, supportedLangToIntlDTF} from "./enums";
import {pageComponentFromId} from "./pageListings"; import {pageComponentFromId} from "./pageListings";
import KadiPage from "./Components/KadiPage"; import KadiPage from "./Components/KadiPage";
import HomePage from "./Components/HomePage"; import HomePage from "./Components/HomePage";
@@ -27,6 +27,7 @@ class App extends React.Component<AppProps, AppState> {
username: username, username: username,
loggedIn: loggedIn, loggedIn: loggedIn,
updateUserContext: this.updateUserContext, updateUserContext: this.updateUserContext,
dateTimeFormatter: this.state.userContext.dateTimeFormatter,
currentLang: this.state.userContext.currentLang, currentLang: this.state.userContext.currentLang,
strings: this.state.userContext.strings, strings: this.state.userContext.strings,
changeLang: this.state.userContext.changeLang, changeLang: this.state.userContext.changeLang,
@@ -35,6 +36,7 @@ class App extends React.Component<AppProps, AppState> {
this.changeLang = (lang: SupportedLang, submit=true) => { this.changeLang = (lang: SupportedLang, submit=true) => {
this.setState({userContext: { this.setState({userContext: {
dateTimeFormatter: supportedLangToIntlDTF[lang],
strings: IntlStrings[lang], strings: IntlStrings[lang],
currentLang: lang, currentLang: lang,
changeLang: this.changeLang, changeLang: this.changeLang,
@@ -52,6 +54,7 @@ class App extends React.Component<AppProps, AppState> {
username: "", username: "",
loggedIn: false, loggedIn: false,
updateUserContext: this.updateUserContext, updateUserContext: this.updateUserContext,
dateTimeFormatter: supportedLangToIntlDTF[SupportedLang.gb],
currentLang: SupportedLang.gb, currentLang: SupportedLang.gb,
strings: IntlStrings[SupportedLang.gb], strings: IntlStrings[SupportedLang.gb],
changeLang: this.changeLang, changeLang: this.changeLang,
@@ -76,7 +79,7 @@ class App extends React.Component<AppProps, AppState> {
} }
submitLanguagePreference(lang: SupportedLang) { submitLanguagePreference(lang: SupportedLang) {
axios.post(SERVER_BASE_NAME + "/api/changeLang", axios.put(SERVER_BASE_NAME + "/api/lang",
{lang: lang}, {lang: lang},
{headers: {"Content-Type": "application/json"}} {headers: {"Content-Type": "application/json"}}
); );

View File

@@ -0,0 +1,31 @@
import {List, ListItem} from "semantic-ui-react";
import React from "react";
import UserContext from "../Contexts/UserContext";
interface GamesListProps {
loading: boolean;
gamesList: any[];
}
const GamesList: React.FunctionComponent<GamesListProps> = (props) => {
const {loading, gamesList} = props;
const Uctx = React.useContext(UserContext);
const listItems = gamesList.map(listing =>
<ListItem key={listing.createdAt}>
Game played on: {Uctx.dateTimeFormatter.format(new Date(listing.createdAt))}
</ListItem>
);
return (
<>
{loading ? (
<p>{Uctx.strings.historyPage.loading}</p>
) : (
<List bulleted={true}>
{listItems}
</List>
)}
</>
);
};
export default GamesList;

View File

@@ -0,0 +1,39 @@
import {Header, List, ListItem} from "semantic-ui-react";
import React from "react";
import UserContext from "../Contexts/UserContext";
import {Guest} from "./ProfilePage";
import HeaderSubHeader from "semantic-ui-react/dist/commonjs/elements/Header/HeaderSubheader";
import {SERVER_BASE_NAME} from "../index";
interface GuestListProps {
loading: boolean;
guestList: Guest[];
deleteGuest: (id: string) => any;
}
const GuestList: React.FunctionComponent<GuestListProps> = (props) => {
const {loading, guestList, deleteGuest} = props;
const Uctx = React.useContext(UserContext);
const listItems = guestList.map(guest =>
<ListItem key={guest.id}>
{guest.nick} - <a onClick={() => deleteGuest(guest.id)}>{Uctx.strings.general.deleteCommand}</a>
</ListItem>
);
return (
<>
<Header size={"medium"}>
{Uctx.strings.profilePage.guestsHeader}
</Header>
{loading ? (
<p>{Uctx.strings.profilePage.loadingGuests}</p>
) : (
<List bulleted={true}>
{listItems}
</List>
)}
</>
);
};
export default GuestList;

View File

@@ -3,6 +3,7 @@ import {Header, List, ListItem} from "semantic-ui-react";
import axios from "axios"; import axios from "axios";
import {SERVER_BASE_NAME} from "../index"; import {SERVER_BASE_NAME} from "../index";
import UserContext from "../Contexts/UserContext"; import UserContext from "../Contexts/UserContext";
import GamesList from "./GamesList";
interface HistoryPageProps { interface HistoryPageProps {
} }
@@ -27,11 +28,9 @@ class HistoryPage extends React.Component<HistoryPageProps, HistoryPageState> {
.then(response => this.setState({gameListings: response.data.games})) .then(response => this.setState({gameListings: response.data.games}))
.catch(error => this.handleError(error)) .catch(error => this.handleError(error))
.finally(() => this.setState({ loadingGames: false })); .finally(() => this.setState({ loadingGames: false }));
console.log(this.state.gameListings);
} }
handleError = (error: any) => void { handleError = (error: any) => void {
}; };
render(): ReactElement { render(): ReactElement {
@@ -41,22 +40,10 @@ class HistoryPage extends React.Component<HistoryPageProps, HistoryPageState> {
<Header size={"huge"}> <Header size={"huge"}>
{Locale.historyPage.title} {Locale.historyPage.title}
</Header> </Header>
{ <GamesList
this.state.loadingGames ? ( loading={this.state.loadingGames}
<p> gamesList={this.state.gameListings}
Loading games... />
</p>
) :
(
<List bulleted={true}>
{
this.state.gameListings.map(listing => {
return <ListItem key={listing.createdAt}>Game played on: {listing.createdAt}</ListItem>;
})
}
</List>
)
}
</> </>
); );
} }

View File

@@ -1,10 +1,20 @@
import React, {ReactElement} from "react"; import React, {ReactElement} from "react";
import {Header} from "semantic-ui-react"; import {Header} from "semantic-ui-react";
import UserContext from "../Contexts/UserContext"; import UserContext from "../Contexts/UserContext";
import axios from "axios";
import {SERVER_BASE_NAME} from "../index";
import GuestList from "./GuestList";
interface ProfilePageProps {} interface ProfilePageProps {}
interface ProfilePageState { interface ProfilePageState {
loadingGuests: boolean;
guests: Guest[];
}
export interface Guest {
id: string;
nick: string;
} }
class ProfilePage extends React.Component<ProfilePageProps, ProfilePageState> { class ProfilePage extends React.Component<ProfilePageProps, ProfilePageState> {
@@ -12,15 +22,48 @@ class ProfilePage extends React.Component<ProfilePageProps, ProfilePageState> {
super(props); super(props);
this.state = { this.state = {
loadingGuests: false,
guests: [],
}; };
} }
componentDidMount(): void {
this.loadGuests();
}
loadGuests(): void {
this.setState({loadingGuests: true}, () => {
axios.get(SERVER_BASE_NAME + "/api/guests")
.then(response => this.setState({guests: response.data.guests}))
.catch(error => this.handleError(error))
.finally(() => this.setState({ loadingGuests: false }));
});
}
deleteGuest(id: string): void {
console.log("delete with url", SERVER_BASE_NAME + "/api/guest/" + id);
axios.delete(SERVER_BASE_NAME + "/api/guest/" + id)
.then(response => this.loadGuests())
.catch(error => this.handleError(error))
}
handleError(error: any): void {
console.log(error);
}
render(): ReactElement { render(): ReactElement {
const Locale = this.context.strings; const Locale = this.context.strings;
return ( return (
<>
<Header size={"huge"}> <Header size={"huge"}>
{Locale.profilePage.title} {Locale.profilePage.title}
</Header> </Header>
<GuestList
deleteGuest={(id) => this.deleteGuest(id)}
loading={this.state.loadingGuests}
guestList={this.state.guests}
/>
</>
); );
} }
} }

View File

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

View File

@@ -12,3 +12,9 @@ export enum PageId {
home = "home", home = "home",
history = "history", history = "history",
} }
export const supportedLangToIntlDTF: Record<SupportedLang, Intl.DateTimeFormat> = {
gb: Intl.DateTimeFormat('en-AU'),
de: Intl.DateTimeFormat('de-DE'),
it: Intl.DateTimeFormat('it-IT'),
};

0
src/filetypes.d.ts vendored Executable file → Normal file
View File

View File

@@ -3,8 +3,7 @@ import ReactDOM from "react-dom";
import "semantic-ui-css/semantic.min.css"; import "semantic-ui-css/semantic.min.css";
import App from "./App"; import App from "./App";
import * as serviceWorker from "./serviceWorker"; import * as serviceWorker from "./serviceWorker";
export {homepage as SERVER_BASE_NAME} from "../package.json";
export const SERVER_BASE_NAME = "/kadi";
ReactDOM.render(( ReactDOM.render((
<React.StrictMode> <React.StrictMode>

View File

@@ -28,6 +28,9 @@ export const LanguageNames: Record<SupportedLang, string> = {
export const IntlStrings = { export const IntlStrings = {
gb: { gb: {
general: {
deleteCommand: "Delete",
},
menu: { menu: {
profileTab: "Profile", profileTab: "Profile",
statsTab: "Stats", statsTab: "Stats",
@@ -44,6 +47,8 @@ export const IntlStrings = {
}, },
profilePage: { profilePage: {
title: "Profile", title: "Profile",
guestsHeader: "Guests",
loadingGuests: "Loading guests..."
}, },
statsPage: { statsPage: {
title: "Stats", title: "Stats",
@@ -56,9 +61,13 @@ export const IntlStrings = {
}, },
historyPage: { historyPage: {
title: "History", title: "History",
loading: "Loading games...",
}, },
}, },
de: { de: {
general: {
deleteCommand: "Löschen",
},
menu: { menu: {
profileTab: "Profil", profileTab: "Profil",
statsTab: "Statistiken", statsTab: "Statistiken",
@@ -75,6 +84,8 @@ export const IntlStrings = {
}, },
profilePage: { profilePage: {
title: "Profil", title: "Profil",
guestsHeader: "Gäste",
loadingGuests: "Gäste werden geladen...",
}, },
statsPage: { statsPage: {
title: "Statistiken", title: "Statistiken",
@@ -87,9 +98,13 @@ export const IntlStrings = {
}, },
historyPage: { historyPage: {
title: "Spielverlauf", title: "Spielverlauf",
loading: "Spielverlauf wird geladen...",
}, },
}, },
it: { it: {
general: {
deleteCommand: "Cancella",
},
menu: { menu: {
profileTab: "Profilo", profileTab: "Profilo",
statsTab: "Statistiche", statsTab: "Statistiche",
@@ -106,6 +121,8 @@ export const IntlStrings = {
}, },
profilePage: { profilePage: {
title: "Profilo", title: "Profilo",
guestsHeader: "===TRANSLATE ME===",
loadingGuests: "===TRANSLATE ME===",
}, },
statsPage: { statsPage: {
title: "Statistiche", title: "Statistiche",
@@ -118,6 +135,7 @@ export const IntlStrings = {
}, },
historyPage: { historyPage: {
title: "Storia", title: "Storia",
loading: "Caricando storia giochi..."
}, },
}, },
} as const; } as const;

View File

@@ -25,7 +25,7 @@
], ],
"linterOptions": { "linterOptions": {
"exclude": [ "exclude": [
"build/**/*.js", "dist/**/*.js",
"config/**/*.js", "config/**/*.js",
"node_modules/**/*.ts" "node_modules/**/*.ts"
] ]

View File

@@ -1,20 +1,19 @@
const path = require("path"); const path = require("path");
const webpack = require("webpack"); const webpack = require("webpack");
const SERVER_ROOT = require("./package.json").homepage;
module.exports = { module.exports = {
entry: "./src/index.tsx", entry: "./src/index.tsx",
mode: "development", mode: "production",
module: { module: {
rules: [ rules: [
{ {
test: /\.tsx?$/, test: /\.tsx?$/,
exclude: /(node_modules|bower_components|\.d\.ts$)/, exclude: /(node_modules|bower_components|\.d\.ts$)/,
use: [ use: [
{ "react-hot-loader/webpack",
loader: "babel-loader", "babel-loader",
options: { presets: ["@babel/env"] },
},
{ loader: "ts-loader" },
], ],
}, },
{ {
@@ -38,13 +37,14 @@ module.exports = {
resolve: { extensions: [".tsx", ".ts", ".js", "*"] }, resolve: { extensions: [".tsx", ".ts", ".js", "*"] },
output: { output: {
path: path.resolve(__dirname, "dist/"), path: path.resolve(__dirname, "dist/"),
publicPath: "/kadi/static/frontend/", publicPath: SERVER_ROOT + "/static/frontend/",
filename: "bundle.js" filename: "bundle.js"
}, },
devServer: { devServer: {
contentBase: path.join(__dirname, "public/"), contentBase: path.join(__dirname, "public/"),
contentBasePublicPath: SERVER_ROOT + "/",
port: 3000, port: 3000,
publicPath: "http://localhost:3000/dist/", publicPath: "http://localhost:3000" + SERVER_ROOT + "/static/frontend/",
hotOnly: true hotOnly: true
}, },
plugins: [new webpack.HotModuleReplacementPlugin()] plugins: [new webpack.HotModuleReplacementPlugin()]