change how we render layouts
This commit is contained in:
parent
ea71ef5e0b
commit
3e87c42e0b
|
@ -4,25 +4,44 @@ import { heights } from '@theme/toolbar';
|
|||
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
export interface Props extends React.HTMLProps<HTMLElement> {
|
||||
export interface Props extends React.HTMLAttributes<HTMLOrSVGElement> {
|
||||
footer?: boolean;
|
||||
component?: keyof JSX.IntrinsicElements;
|
||||
minHeight?: boolean;
|
||||
}
|
||||
|
||||
interface MakeStylesProps {
|
||||
footer?: boolean;
|
||||
}
|
||||
|
||||
function Content({ className, footer = false, ...props }: Props) {
|
||||
function Content({
|
||||
className,
|
||||
footer = false,
|
||||
component: Wrapper = 'main',
|
||||
minHeight = true,
|
||||
...props
|
||||
}: Props) {
|
||||
const classes = useStyles({ footer });
|
||||
return <main className={clsx(classes.main, className)} {...props} />;
|
||||
return (
|
||||
<Wrapper
|
||||
className={clsx(
|
||||
{ [classes.minHeight]: minHeight },
|
||||
classes.padding,
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => {
|
||||
return {
|
||||
main: ({ footer }: MakeStylesProps) => {
|
||||
padding: {
|
||||
padding: theme.spacing(3, 0),
|
||||
},
|
||||
minHeight: ({ footer }: MakeStylesProps) => {
|
||||
const multiplier = footer ? 2 : 1;
|
||||
return {
|
||||
padding: theme.spacing(3, 0),
|
||||
minHeight: `calc(100vh - ${heights.tabletDesktop * multiplier}px)`,
|
||||
[`${theme.breakpoints.down('xs')} and (orientation: landscape)`]: {
|
||||
minHeight: `calc(100vh - ${heights.mobileLandscape * multiplier}px)`,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import React from 'react';
|
||||
import { StringParam, useQueryParam, withDefault } from 'use-query-params';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { TWHELP, NAME } from '@config/app';
|
||||
import * as ROUTES from '@config/routes';
|
||||
import * as NAMESPACES from '@config/namespaces';
|
||||
|
@ -21,20 +23,14 @@ import VersionSelector from '@common/VersionSelector/VersionSelector';
|
|||
import SearchInput from './SearchInput';
|
||||
|
||||
export interface Props {
|
||||
showLinkToHomePage?: boolean;
|
||||
hideVersionSelectorOnMobile?: boolean;
|
||||
defaultQ?: string;
|
||||
appBarProps?: AppBarProps;
|
||||
}
|
||||
|
||||
export default function Header({
|
||||
showLinkToHomePage = true,
|
||||
hideVersionSelectorOnMobile = false,
|
||||
defaultQ = '',
|
||||
appBarProps = {},
|
||||
}: Props) {
|
||||
export default function Header({ appBarProps = {} }: Props) {
|
||||
const { t } = useTranslation(NAMESPACES.COMMON);
|
||||
const location = useLocation();
|
||||
const classes = useStyles();
|
||||
const [q] = useQueryParam('q', withDefault(StringParam, ''));
|
||||
|
||||
const versionSelector = (
|
||||
<div>
|
||||
|
@ -46,9 +42,11 @@ export default function Header({
|
|||
<Container>
|
||||
<Toolbar disableGutters className={classes.toolbar}>
|
||||
<form className={classes.form}>
|
||||
<SearchInput defaultQ={defaultQ} />
|
||||
<SearchInput
|
||||
defaultQ={location.pathname === ROUTES.SEARCH_PAGE ? q : ''}
|
||||
/>
|
||||
</form>
|
||||
{showLinkToHomePage && (
|
||||
{location.pathname !== ROUTES.INDEX_PAGE && (
|
||||
<Link to={ROUTES.INDEX_PAGE}>
|
||||
<Hidden xsDown implementation="css">
|
||||
<Button startIcon={<InputIcon />}>
|
||||
|
@ -62,7 +60,7 @@ export default function Header({
|
|||
</Hidden>
|
||||
</Link>
|
||||
)}
|
||||
{hideVersionSelectorOnMobile ? (
|
||||
{location.pathname !== ROUTES.INDEX_PAGE ? (
|
||||
<Hidden xsDown implementation="css">
|
||||
{versionSelector}
|
||||
</Hidden>
|
||||
|
|
|
@ -7,6 +7,7 @@ import ScrollToTop from '@common/ScrollToTop/ScrollToTop';
|
|||
|
||||
import VersionProvider from '../libs/VersionContext/Provider';
|
||||
import DateUtilsProvider from '../libs/date/DateUtilsProvider';
|
||||
import MainLayout from '../common/MainLayout/MainLayout';
|
||||
import IndexPage from './IndexPage/IndexPage';
|
||||
import NotFoundPage from './NotFoundPage/NotFoundPage';
|
||||
import SearchPage from './SearchPage/SearchPage';
|
||||
|
@ -18,11 +19,17 @@ function App() {
|
|||
<VersionProvider>
|
||||
<DateUtilsProvider>
|
||||
<Switch>
|
||||
<Route path={ROUTES.INDEX_PAGE} exact>
|
||||
<IndexPage />
|
||||
</Route>
|
||||
<Route path={ROUTES.SEARCH_PAGE} exact>
|
||||
<SearchPage />
|
||||
<Route path={[ROUTES.INDEX_PAGE, ROUTES.SEARCH_PAGE]} exact>
|
||||
<MainLayout>
|
||||
<Switch>
|
||||
<Route path={ROUTES.INDEX_PAGE} exact>
|
||||
<IndexPage />
|
||||
</Route>
|
||||
<Route path={ROUTES.SEARCH_PAGE} exact>
|
||||
<SearchPage />
|
||||
</Route>
|
||||
</Switch>
|
||||
</MainLayout>
|
||||
</Route>
|
||||
<Route path={ROUTES.SERVER_PAGE.INDEX_PAGE}>
|
||||
<ServerPage />
|
||||
|
|
|
@ -4,7 +4,6 @@ import useTitle from '@libs/useTitle';
|
|||
import { INDEX_PAGE } from '@config/namespaces';
|
||||
|
||||
import { Container, Box } from '@material-ui/core';
|
||||
import MainLayout from '@common/MainLayout/MainLayout';
|
||||
import DevNote from '@common/DevNote/DevNote';
|
||||
import ServerSelection from './components/ServerSelection/ServerSelection';
|
||||
|
||||
|
@ -12,18 +11,11 @@ export default function IndexPage() {
|
|||
const { t } = useTranslation(INDEX_PAGE);
|
||||
useTitle(t('title'));
|
||||
return (
|
||||
<MainLayout
|
||||
headerProps={{
|
||||
showLinkToHomePage: false,
|
||||
hideVersionSelectorOnMobile: false,
|
||||
}}
|
||||
>
|
||||
<Container>
|
||||
<Box mb={3}>
|
||||
<DevNote />
|
||||
</Box>
|
||||
<ServerSelection />
|
||||
</Container>
|
||||
</MainLayout>
|
||||
<Container>
|
||||
<Box mb={3}>
|
||||
<DevNote />
|
||||
</Box>
|
||||
<ServerSelection />
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useRef } from 'react';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import formatNumber from '@utils/formatNumber';
|
||||
import * as ROUTES from '@config/routes';
|
||||
import * as NAMESPACES from '@config/namespaces';
|
||||
|
@ -31,7 +31,7 @@ export interface Props {
|
|||
|
||||
function GridItem({ t, server, hideTooltip = true }: Props) {
|
||||
const classes = useStyles();
|
||||
const [expanded, setExpanded] = React.useState<boolean>(false);
|
||||
const [expanded, setExpanded] = useState<boolean>(false);
|
||||
const accordion = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const handleClick = (e: React.ChangeEvent<{}>, expanded: boolean) => {
|
||||
|
|
|
@ -14,7 +14,6 @@ import { SEARCH_PAGE } from '@config/namespaces';
|
|||
import { MODES, LIMIT } from './constants';
|
||||
|
||||
import { Container, Paper } from '@material-ui/core';
|
||||
import MainLayout from '@common/MainLayout/MainLayout';
|
||||
import ModeSelector from '@common/ModeSelector/ModeSelector';
|
||||
import PlayerTable from './components/PlayerTable/PlayerTable';
|
||||
import TribeTable from './components/TribeTable/TribeTable';
|
||||
|
@ -55,39 +54,35 @@ function SearchPage() {
|
|||
};
|
||||
|
||||
return (
|
||||
<MainLayout
|
||||
headerProps={{ hideVersionSelectorOnMobile: true, defaultQ: query.q }}
|
||||
>
|
||||
<Container>
|
||||
<Paper>
|
||||
<ModeSelector
|
||||
buttonProps={{ size: 'medium' }}
|
||||
onSelect={m => setQuery({ mode: m.name, page: 0, limit: LIMIT })}
|
||||
modes={[
|
||||
{
|
||||
name: 'player',
|
||||
label: t('modes.player'),
|
||||
get selected() {
|
||||
return this.name === query.mode;
|
||||
},
|
||||
<Container>
|
||||
<Paper>
|
||||
<ModeSelector
|
||||
buttonProps={{ size: 'medium' }}
|
||||
onSelect={m => setQuery({ mode: m.name, page: 0, limit: LIMIT })}
|
||||
modes={[
|
||||
{
|
||||
name: 'player',
|
||||
label: t('modes.player'),
|
||||
get selected() {
|
||||
return this.name === query.mode;
|
||||
},
|
||||
{
|
||||
name: 'tribe',
|
||||
label: t('modes.tribe'),
|
||||
get selected() {
|
||||
return this.name === query.mode;
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'tribe',
|
||||
label: t('modes.tribe'),
|
||||
get selected() {
|
||||
return this.name === query.mode;
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{query.mode === MODES.TRIBE ? (
|
||||
<TribeTable {...tableProps} />
|
||||
) : (
|
||||
<PlayerTable {...tableProps} />
|
||||
)}
|
||||
</Paper>
|
||||
</Container>
|
||||
</MainLayout>
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{query.mode === MODES.TRIBE ? (
|
||||
<TribeTable {...tableProps} />
|
||||
) : (
|
||||
<PlayerTable {...tableProps} />
|
||||
)}
|
||||
</Paper>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import { SERVER_PAGE } from '@config/routes';
|
|||
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import ServerProvider from './libs/ServerContext/Provider';
|
||||
import PageLayout from './common/PageLayout/PageLayout';
|
||||
import IndexPage from './features/IndexPage/IndexPage';
|
||||
import PlayerPage from './features/PlayerPage/PlayerPage';
|
||||
import TribePage from './features/TribePage/TribePage';
|
||||
|
@ -16,35 +17,37 @@ import NotFoundPage from './features/NotFoundPage/NotFoundPage';
|
|||
function ServerPage() {
|
||||
return (
|
||||
<ServerProvider>
|
||||
<Switch>
|
||||
<Route exact path={SERVER_PAGE.INDEX_PAGE}>
|
||||
<IndexPage />
|
||||
</Route>
|
||||
<Route path={SERVER_PAGE.PLAYER_PAGE.INDEX_PAGE}>
|
||||
<PlayerPage />
|
||||
</Route>
|
||||
<Route path={SERVER_PAGE.TRIBE_PAGE.INDEX_PAGE}>
|
||||
<TribePage />
|
||||
</Route>
|
||||
<Route exact path={SERVER_PAGE.VILLAGE_PAGE.INDEX_PAGE}>
|
||||
<VillagePage />
|
||||
</Route>
|
||||
<Route path={SERVER_PAGE.RANKING_PAGE.BASE}>
|
||||
<RankingPage />
|
||||
</Route>
|
||||
<Route path={SERVER_PAGE.MAP_PAGE}>
|
||||
<MapPage />
|
||||
</Route>
|
||||
<Route exact path={SERVER_PAGE.ENNOBLEMENTS_PAGE}>
|
||||
<EnnoblementsPage />
|
||||
</Route>
|
||||
<Route exact path={SERVER_PAGE.WAR_STATS_PAGE}>
|
||||
<WarStatsPage />
|
||||
</Route>
|
||||
<Route path="*">
|
||||
<NotFoundPage />
|
||||
</Route>
|
||||
</Switch>
|
||||
<PageLayout>
|
||||
<Switch>
|
||||
<Route exact path={SERVER_PAGE.INDEX_PAGE}>
|
||||
<IndexPage />
|
||||
</Route>
|
||||
<Route path={SERVER_PAGE.PLAYER_PAGE.INDEX_PAGE}>
|
||||
<PlayerPage />
|
||||
</Route>
|
||||
<Route path={SERVER_PAGE.TRIBE_PAGE.INDEX_PAGE}>
|
||||
<TribePage />
|
||||
</Route>
|
||||
<Route exact path={SERVER_PAGE.VILLAGE_PAGE.INDEX_PAGE}>
|
||||
<VillagePage />
|
||||
</Route>
|
||||
<Route path={SERVER_PAGE.RANKING_PAGE.BASE}>
|
||||
<RankingPage />
|
||||
</Route>
|
||||
<Route path={SERVER_PAGE.MAP_PAGE}>
|
||||
<MapPage />
|
||||
</Route>
|
||||
<Route exact path={SERVER_PAGE.ENNOBLEMENTS_PAGE}>
|
||||
<EnnoblementsPage />
|
||||
</Route>
|
||||
<Route exact path={SERVER_PAGE.WAR_STATS_PAGE}>
|
||||
<WarStatsPage />
|
||||
</Route>
|
||||
<Route path="*">
|
||||
<NotFoundPage />
|
||||
</Route>
|
||||
</Switch>
|
||||
</PageLayout>
|
||||
</ServerProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,23 +7,15 @@ import { DRAWER_WIDTH } from './components/Sidebar/contants';
|
|||
import { makeStyles, useTheme } from '@material-ui/core/styles';
|
||||
import { useMediaQuery, Toolbar } from '@material-ui/core';
|
||||
|
||||
import Content, { Props as ContentProps } from '@common/Content/Content';
|
||||
import Content from '@common/Content/Content';
|
||||
import Sidebar from './components/Sidebar/Sidebar';
|
||||
import TopBar from './components/TopBar/TopBar';
|
||||
|
||||
export interface Props {
|
||||
children?: React.ReactNode;
|
||||
noPadding?: boolean;
|
||||
contentClassName?: string;
|
||||
contentStyle?: ContentProps['style'];
|
||||
}
|
||||
|
||||
function PageLayout({
|
||||
children,
|
||||
noPadding,
|
||||
contentClassName,
|
||||
contentStyle,
|
||||
}: Props) {
|
||||
function PageLayout({ children }: Props) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const classes = useStyles();
|
||||
const theme = useTheme();
|
||||
|
@ -56,14 +48,7 @@ function PageLayout({
|
|||
t={t}
|
||||
onOpen={openSidebar}
|
||||
/>
|
||||
<Content
|
||||
className={clsx(classes.content, contentClassName, {
|
||||
'no-padding': noPadding,
|
||||
})}
|
||||
style={contentStyle}
|
||||
>
|
||||
{children}
|
||||
</Content>
|
||||
<Content className={classes.content}>{children}</Content>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -81,10 +66,7 @@ const useStyles = makeStyles(theme => ({
|
|||
},
|
||||
content: {
|
||||
height: '100%',
|
||||
padding: theme.spacing(3, 0),
|
||||
'&.no-padding': {
|
||||
padding: '0 0',
|
||||
},
|
||||
padding: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ const Sidebar = ({ t, className, open, variant, onClose, onOpen }: Props) => {
|
|||
name: t('pageLayout.sidebar.routes.rankings.name'),
|
||||
Icon: <GradeIcon color="inherit" />,
|
||||
to: ROUTES.SERVER_PAGE.RANKING_PAGE.BASE,
|
||||
isExpandable: true,
|
||||
nested: [
|
||||
{
|
||||
name: t('pageLayout.sidebar.routes.rankings.player.index'),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment, useState } from 'react';
|
||||
import React, { Fragment, useState, memo } from 'react';
|
||||
import { useLocation, matchPath } from 'react-router-dom';
|
||||
import { Route } from './types';
|
||||
|
||||
|
@ -26,7 +26,7 @@ function ListItem({ route, nestedLevel }: Props) {
|
|||
const isActive =
|
||||
!!route.to && !!matchPath(pathname, { path: route.to, exact: route.exact });
|
||||
const [open, setOpen] = useState(
|
||||
(hasNested && isActive) || !route.isExpandable
|
||||
(hasNested && !route.isExpandable) || isActive
|
||||
);
|
||||
|
||||
const getItem = () => {
|
||||
|
@ -97,4 +97,4 @@ const useStyles = makeStyles(theme => ({
|
|||
},
|
||||
}));
|
||||
|
||||
export default ListItem;
|
||||
export default memo(ListItem);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Route } from './types';
|
||||
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { List } from '@material-ui/core';
|
||||
import ListItem from './ListItem';
|
||||
|
||||
|
@ -9,15 +8,9 @@ export interface Props {
|
|||
routes: Route[];
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {},
|
||||
}));
|
||||
|
||||
const Nav = ({ routes }: Props) => {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<List className={classes.root}>
|
||||
<List>
|
||||
{routes.map(route => (
|
||||
<ListItem nestedLevel={1} route={route} key={route.name} />
|
||||
))}
|
||||
|
|
|
@ -6,7 +6,7 @@ import useServer from '@features/ServerPage/libs/ServerContext/useServer';
|
|||
import { SERVER_PAGE } from '@config/namespaces';
|
||||
|
||||
import { Container, Paper } from '@material-ui/core';
|
||||
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Content from '@common/Content/Content';
|
||||
import ModeSelector from '@common/ModeSelector/ModeSelector';
|
||||
import LiveEnnoblements from './components/LiveEnnoblements/LiveEnnoblements';
|
||||
import LatestSavedEnnoblements from './components/LatestSavedEnnoblements/LatestSavedEnnoblements';
|
||||
|
@ -22,7 +22,7 @@ function EnnoblementsPage() {
|
|||
);
|
||||
|
||||
return (
|
||||
<ServerPageLayout>
|
||||
<Content component="div" minHeight={false}>
|
||||
<Container>
|
||||
<Paper>
|
||||
<ModeSelector
|
||||
|
@ -53,7 +53,7 @@ function EnnoblementsPage() {
|
|||
)}
|
||||
</Paper>
|
||||
</Container>
|
||||
</ServerPageLayout>
|
||||
</Content>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import useServer from '../../libs/ServerContext/useServer';
|
|||
import { SERVER_PAGE } from '@config/namespaces';
|
||||
|
||||
import { Container, Grid, Hidden } from '@material-ui/core';
|
||||
import PageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Content from '@common/Content/Content';
|
||||
import PlayerStatistics from './components/PlayerStatistics/PlayerStatistics';
|
||||
import TribeStatistics from './components/TribeStatistics/TribeStatistics';
|
||||
import Top5Players from './components/Top5Players/Top5Players';
|
||||
|
@ -23,7 +23,7 @@ function IndexPage() {
|
|||
useTitle(t('title', { key }));
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
<Content component="div" minHeight={false}>
|
||||
<Container>
|
||||
<Grid container spacing={2}>
|
||||
<Grid
|
||||
|
@ -72,7 +72,7 @@ function IndexPage() {
|
|||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
</PageLayout>
|
||||
</Content>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import {
|
|||
Checkbox,
|
||||
FormControlLabel,
|
||||
} from '@material-ui/core';
|
||||
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Content from '@common/Content/Content';
|
||||
import ColorInput from '@common/Form/ColorInput';
|
||||
import Spinner from '@common/Spinner/Spinner';
|
||||
import Map from './components/Map/Map';
|
||||
|
@ -188,275 +188,272 @@ function MapPage() {
|
|||
return blacklist.some(id2 => id === id2);
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Spinner
|
||||
containerProps={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
minHeight: 'inherit',
|
||||
paddingY: 5,
|
||||
}}
|
||||
description={t('loading')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ServerPageLayout>
|
||||
{loading && (
|
||||
<Spinner
|
||||
containerProps={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
textAlign: 'center',
|
||||
minHeight: 'inherit',
|
||||
paddingY: 5,
|
||||
}}
|
||||
description={t('loading')}
|
||||
/>
|
||||
)}
|
||||
{!loading && (
|
||||
<Container>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Grid container spacing={2}>
|
||||
<Card>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h3"
|
||||
align="center"
|
||||
gutterBottom
|
||||
>
|
||||
{t('sections.settings')}
|
||||
</Typography>
|
||||
<div className={classes.formGroup}>
|
||||
<TextField
|
||||
label={t('inputLabels.zoomLevel')}
|
||||
type="number"
|
||||
name="scale"
|
||||
value={query.scale}
|
||||
onChange={createSettingsChangeHandler('scale')}
|
||||
<Content component="div" minHeight={false}>
|
||||
<Container>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Grid container spacing={2}>
|
||||
<Card>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h3"
|
||||
align="center"
|
||||
gutterBottom
|
||||
>
|
||||
{t('sections.settings')}
|
||||
</Typography>
|
||||
<div className={classes.formGroup}>
|
||||
<TextField
|
||||
label={t('inputLabels.zoomLevel')}
|
||||
type="number"
|
||||
name="scale"
|
||||
value={query.scale}
|
||||
onChange={createSettingsChangeHandler('scale')}
|
||||
fullWidth
|
||||
variant="standard"
|
||||
inputProps={{
|
||||
min: 1,
|
||||
max: 5,
|
||||
step: '.1',
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
label={t('inputLabels.centerX')}
|
||||
type="number"
|
||||
name="centerX"
|
||||
value={query.centerX}
|
||||
onChange={createSettingsChangeHandler('centerX')}
|
||||
fullWidth
|
||||
variant="standard"
|
||||
inputProps={{
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: '1',
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
label={t('inputLabels.centerY')}
|
||||
type="number"
|
||||
name="centerY"
|
||||
value={query.centerY}
|
||||
onChange={createSettingsChangeHandler('centerY')}
|
||||
fullWidth
|
||||
variant="standard"
|
||||
inputProps={{
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: '1',
|
||||
}}
|
||||
/>
|
||||
{[
|
||||
{
|
||||
name: 'backgroundColor',
|
||||
color: query.backgroundColor,
|
||||
onChange: createSettingsChangeHandler('backgroundColor'),
|
||||
},
|
||||
{
|
||||
name: 'playerVillageColor',
|
||||
color: query.playerVillageColor,
|
||||
onChange: createSettingsChangeHandler('playerVillageColor'),
|
||||
},
|
||||
{
|
||||
name: 'barbarianVillageColor',
|
||||
color: query.barbarianVillageColor,
|
||||
onChange: createSettingsChangeHandler(
|
||||
'barbarianVillageColor'
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'gridLineColor',
|
||||
color: query.gridLineColor,
|
||||
onChange: createSettingsChangeHandler('gridLineColor'),
|
||||
},
|
||||
{
|
||||
name: 'continentNumberColor',
|
||||
color: query.continentNumberColor,
|
||||
onChange: createSettingsChangeHandler(
|
||||
'continentNumberColor'
|
||||
),
|
||||
},
|
||||
].map(({ color, name, onChange }) => (
|
||||
<ColorInput
|
||||
key={name}
|
||||
color={color}
|
||||
onChange={onChange}
|
||||
fullWidth
|
||||
variant="standard"
|
||||
inputProps={{
|
||||
min: 1,
|
||||
max: 5,
|
||||
step: '.1',
|
||||
}}
|
||||
name={name}
|
||||
label={t('inputLabels.' + name)}
|
||||
/>
|
||||
<TextField
|
||||
label={t('inputLabels.centerX')}
|
||||
type="number"
|
||||
name="centerX"
|
||||
value={query.centerX}
|
||||
onChange={createSettingsChangeHandler('centerX')}
|
||||
fullWidth
|
||||
variant="standard"
|
||||
inputProps={{
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: '1',
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
label={t('inputLabels.centerY')}
|
||||
type="number"
|
||||
name="centerY"
|
||||
value={query.centerY}
|
||||
onChange={createSettingsChangeHandler('centerY')}
|
||||
fullWidth
|
||||
variant="standard"
|
||||
inputProps={{
|
||||
min: 0,
|
||||
max: 1000,
|
||||
step: '1',
|
||||
}}
|
||||
/>
|
||||
{[
|
||||
{
|
||||
name: 'backgroundColor',
|
||||
color: query.backgroundColor,
|
||||
onChange: createSettingsChangeHandler('backgroundColor'),
|
||||
},
|
||||
{
|
||||
name: 'playerVillageColor',
|
||||
color: query.playerVillageColor,
|
||||
onChange: createSettingsChangeHandler(
|
||||
'playerVillageColor'
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'barbarianVillageColor',
|
||||
color: query.barbarianVillageColor,
|
||||
onChange: createSettingsChangeHandler(
|
||||
'barbarianVillageColor'
|
||||
),
|
||||
},
|
||||
{
|
||||
name: 'gridLineColor',
|
||||
color: query.gridLineColor,
|
||||
onChange: createSettingsChangeHandler('gridLineColor'),
|
||||
},
|
||||
{
|
||||
name: 'continentNumberColor',
|
||||
color: query.continentNumberColor,
|
||||
onChange: createSettingsChangeHandler(
|
||||
'continentNumberColor'
|
||||
),
|
||||
},
|
||||
].map(({ color, name, onChange }) => (
|
||||
<ColorInput
|
||||
))}
|
||||
{[
|
||||
{
|
||||
name: 'markersOnly',
|
||||
checked: query.markersOnly,
|
||||
onChange: createSettingsChangeHandler('markersOnly'),
|
||||
},
|
||||
{
|
||||
name: 'showBarbarian',
|
||||
checked: query.showBarbarian,
|
||||
onChange: createSettingsChangeHandler('showBarbarian'),
|
||||
},
|
||||
{
|
||||
name: 'largerMarkers',
|
||||
checked: query.largerMarkers,
|
||||
onChange: createSettingsChangeHandler('largerMarkers'),
|
||||
},
|
||||
{
|
||||
name: 'showGrid',
|
||||
checked: query.showGrid,
|
||||
onChange: createSettingsChangeHandler('showGrid'),
|
||||
},
|
||||
{
|
||||
name: 'showContinentNumbers',
|
||||
checked: query.showContinentNumbers,
|
||||
onChange: createSettingsChangeHandler(
|
||||
'showContinentNumbers'
|
||||
),
|
||||
},
|
||||
].map(({ name, checked, onChange }) => {
|
||||
return (
|
||||
<FormControlLabel
|
||||
key={name}
|
||||
color={color}
|
||||
onChange={onChange}
|
||||
fullWidth
|
||||
variant="standard"
|
||||
name={name}
|
||||
label={t('inputLabels.' + name)}
|
||||
control={
|
||||
<Checkbox
|
||||
name={name}
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
{[
|
||||
{
|
||||
name: 'markersOnly',
|
||||
checked: query.markersOnly,
|
||||
onChange: createSettingsChangeHandler('markersOnly'),
|
||||
},
|
||||
{
|
||||
name: 'showBarbarian',
|
||||
checked: query.showBarbarian,
|
||||
onChange: createSettingsChangeHandler('showBarbarian'),
|
||||
},
|
||||
{
|
||||
name: 'largerMarkers',
|
||||
checked: query.largerMarkers,
|
||||
onChange: createSettingsChangeHandler('largerMarkers'),
|
||||
},
|
||||
{
|
||||
name: 'showGrid',
|
||||
checked: query.showGrid,
|
||||
onChange: createSettingsChangeHandler('showGrid'),
|
||||
},
|
||||
{
|
||||
name: 'showContinentNumbers',
|
||||
checked: query.showContinentNumbers,
|
||||
onChange: createSettingsChangeHandler(
|
||||
'showContinentNumbers'
|
||||
),
|
||||
},
|
||||
].map(({ name, checked, onChange }) => {
|
||||
return (
|
||||
<FormControlLabel
|
||||
key={name}
|
||||
label={t('inputLabels.' + name)}
|
||||
control={
|
||||
<Checkbox
|
||||
name={name}
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h3"
|
||||
align="center"
|
||||
gutterBottom
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h3"
|
||||
align="center"
|
||||
gutterBottom
|
||||
>
|
||||
{t('sections.tribeMarkers')}
|
||||
</Typography>
|
||||
<div className={classes.formGroup}>
|
||||
{tribeMarkers.map(marker => {
|
||||
return (
|
||||
<MarkerField
|
||||
key={marker.id}
|
||||
onDelete={createDeleteTribeMarkerHandler(marker.id)}
|
||||
onChange={createUpdateTribeMarkerItemHandler(marker.id)}
|
||||
onChangeColor={createUpdateTribeMarkerColorHandler(
|
||||
marker.id
|
||||
)}
|
||||
loadingText={t('loading')}
|
||||
noOptionsText={t('noOptions')}
|
||||
loadSuggestions={searchTribes}
|
||||
getOptionLabel={tribeGetOptionLabel}
|
||||
getOptionSelected={getOptionSelected}
|
||||
getOptionDisabled={opt =>
|
||||
isDisabled(opt.id, selectedTribeIDs)
|
||||
}
|
||||
color={marker.color}
|
||||
value={marker.item}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
color="secondary"
|
||||
onClick={handleAddTribeMarker}
|
||||
disabled={tribeMarkers.length >= 25}
|
||||
>
|
||||
{t('sections.tribeMarkers')}
|
||||
</Typography>
|
||||
<div className={classes.formGroup}>
|
||||
{tribeMarkers.map(marker => {
|
||||
return (
|
||||
<MarkerField
|
||||
key={marker.id}
|
||||
onDelete={createDeleteTribeMarkerHandler(marker.id)}
|
||||
onChange={createUpdateTribeMarkerItemHandler(marker.id)}
|
||||
onChangeColor={createUpdateTribeMarkerColorHandler(
|
||||
marker.id
|
||||
)}
|
||||
loadingText={t('loading')}
|
||||
noOptionsText={t('noOptions')}
|
||||
loadSuggestions={searchTribes}
|
||||
getOptionLabel={tribeGetOptionLabel}
|
||||
getOptionSelected={getOptionSelected}
|
||||
getOptionDisabled={opt =>
|
||||
isDisabled(opt.id, selectedTribeIDs)
|
||||
}
|
||||
color={marker.color}
|
||||
value={marker.item}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
color="secondary"
|
||||
onClick={handleAddTribeMarker}
|
||||
disabled={tribeMarkers.length >= 25}
|
||||
>
|
||||
{t('buttons.addMarker')}
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h3"
|
||||
align="center"
|
||||
gutterBottom
|
||||
{t('buttons.addMarker')}
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h3"
|
||||
align="center"
|
||||
gutterBottom
|
||||
>
|
||||
{t('sections.playerMarkers')}
|
||||
</Typography>
|
||||
<div className={classes.formGroup}>
|
||||
{playerMarkers.map(marker => {
|
||||
return (
|
||||
<MarkerField
|
||||
key={marker.id}
|
||||
onDelete={createDeletePlayerMarkerHandler(marker.id)}
|
||||
onChange={createUpdatePlayerMarkerItemHandler(marker.id)}
|
||||
onChangeColor={createUpdatePlayerMarkerColorHandler(
|
||||
marker.id
|
||||
)}
|
||||
noOptionsText={t('noOptions')}
|
||||
loadSuggestions={searchPlayers}
|
||||
getOptionLabel={playerGetOptionLabel}
|
||||
getOptionSelected={getOptionSelected}
|
||||
getOptionDisabled={opt =>
|
||||
isDisabled(opt.id, selectedPlayerIDs)
|
||||
}
|
||||
color={marker.color}
|
||||
value={marker.item}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
color="secondary"
|
||||
onClick={handleAddPlayerMarker}
|
||||
disabled={playerMarkers.length >= 25}
|
||||
>
|
||||
{t('sections.playerMarkers')}
|
||||
</Typography>
|
||||
<div className={classes.formGroup}>
|
||||
{playerMarkers.map(marker => {
|
||||
return (
|
||||
<MarkerField
|
||||
key={marker.id}
|
||||
onDelete={createDeletePlayerMarkerHandler(marker.id)}
|
||||
onChange={createUpdatePlayerMarkerItemHandler(
|
||||
marker.id
|
||||
)}
|
||||
onChangeColor={createUpdatePlayerMarkerColorHandler(
|
||||
marker.id
|
||||
)}
|
||||
noOptionsText={t('noOptions')}
|
||||
loadSuggestions={searchPlayers}
|
||||
getOptionLabel={playerGetOptionLabel}
|
||||
getOptionSelected={getOptionSelected}
|
||||
getOptionDisabled={opt =>
|
||||
isDisabled(opt.id, selectedPlayerIDs)
|
||||
}
|
||||
color={marker.color}
|
||||
value={marker.item}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
color="secondary"
|
||||
onClick={handleAddPlayerMarker}
|
||||
disabled={playerMarkers.length >= 25}
|
||||
>
|
||||
{t('buttons.addMarker')}
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<Grid item xs={12}>
|
||||
<Typography align="center" component="div">
|
||||
<Button
|
||||
type="submit"
|
||||
size="large"
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
>
|
||||
{t('buttons.generateMap')}
|
||||
</Button>
|
||||
</Typography>
|
||||
</Grid>
|
||||
{mapURL && (
|
||||
<Grid item xs={12}>
|
||||
<Map src={mapURL} alt={key} t={t} />
|
||||
</Grid>
|
||||
)}
|
||||
{t('buttons.addMarker')}
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
<Grid item xs={12}>
|
||||
<Typography align="center" component="div">
|
||||
<Button
|
||||
type="submit"
|
||||
size="large"
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
>
|
||||
{t('buttons.generateMap')}
|
||||
</Button>
|
||||
</Typography>
|
||||
</Grid>
|
||||
</form>
|
||||
</Container>
|
||||
)}
|
||||
</ServerPageLayout>
|
||||
{mapURL && (
|
||||
<Grid item xs={12}>
|
||||
<Map src={mapURL} alt={key} t={t} />
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</form>
|
||||
</Container>
|
||||
</Content>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,10 @@ import { NOT_FOUND_PAGE } from '@config/namespaces';
|
|||
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { Typography } from '@material-ui/core';
|
||||
import PageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Content from '@common/Content/Content';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
container: {
|
||||
padding: theme.spacing(3, 0),
|
||||
width: '100%',
|
||||
minHeight: 'inherit',
|
||||
display: 'flex',
|
||||
|
@ -24,40 +23,20 @@ const useStyles = makeStyles(theme => ({
|
|||
export interface Props {
|
||||
title?: string;
|
||||
description?: string;
|
||||
wrapIntoServerPageLayout?: boolean;
|
||||
}
|
||||
|
||||
function NotFoundPage({
|
||||
title,
|
||||
description,
|
||||
wrapIntoServerPageLayout = true,
|
||||
}: Props) {
|
||||
function NotFoundPage({ title, description }: Props) {
|
||||
const classes = useStyles();
|
||||
const { t } = useTranslation(NOT_FOUND_PAGE);
|
||||
useTitle(t('title'));
|
||||
|
||||
const jsx = (
|
||||
<div className={classes.container}>
|
||||
return (
|
||||
<Content component="div" className={classes.container}>
|
||||
<div>
|
||||
<Typography variant="h1">{title ? title : t('title')}</Typography>
|
||||
{description && <Typography variant="h4">{description}</Typography>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (!wrapIntoServerPageLayout) {
|
||||
return jsx;
|
||||
}
|
||||
|
||||
return (
|
||||
<PageLayout noPadding>
|
||||
<div className={classes.container}>
|
||||
<div>
|
||||
<Typography variant="h1">{title ? title : t('title')}</Typography>
|
||||
{description && <Typography variant="h4">{description}</Typography>}
|
||||
</div>
|
||||
</div>
|
||||
</PageLayout>
|
||||
</Content>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ function PlayerPage() {
|
|||
<EnnoblementsPage />
|
||||
</Route>
|
||||
<Route path="*">
|
||||
<NotFoundPage wrapIntoServerPageLayout={false} />
|
||||
<NotFoundPage />
|
||||
</Route>
|
||||
</Switch>
|
||||
</PageLayout>
|
||||
|
|
|
@ -11,9 +11,9 @@ import * as ROUTES from '@config/routes';
|
|||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
import { Chip, Toolbar, Typography, Tabs, ChipProps } from '@material-ui/core';
|
||||
import Content from '@common/Content/Content';
|
||||
import Link from '@common/Link/Link';
|
||||
import TabLink from '@common/Link/TabLink';
|
||||
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
|
||||
import background1 from './backgrounds/bg-1-dark.png';
|
||||
import background2 from './backgrounds/bg-2-dark.jpg';
|
||||
|
@ -37,7 +37,7 @@ function PageLayout({ children }: Props) {
|
|||
size: 'small',
|
||||
};
|
||||
return (
|
||||
<ServerPageLayout noPadding>
|
||||
<div>
|
||||
<header className={clsx(classes.header, 'bg-' + bg)}>
|
||||
<Toolbar className={classes.toolbar}>
|
||||
<div style={{ width: '100%' }}>
|
||||
|
@ -124,8 +124,10 @@ function PageLayout({ children }: Props) {
|
|||
})}
|
||||
</Tabs>
|
||||
</header>
|
||||
<div className={classes.content}>{children}</div>
|
||||
</ServerPageLayout>
|
||||
<Content component="div" minHeight={false}>
|
||||
{children}
|
||||
</Content>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -181,13 +183,6 @@ const useStyles = makeStyles(theme => ({
|
|||
margin: theme.spacing(0.5),
|
||||
},
|
||||
},
|
||||
content: {
|
||||
height: '100%',
|
||||
padding: theme.spacing(3, 0),
|
||||
'&.no-padding': {
|
||||
padding: '0 0',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export default PageLayout;
|
||||
|
|
|
@ -10,7 +10,6 @@ import { PlayerQueryVariables } from '@libs/graphql/types';
|
|||
import { Params, PlayerQueryResult } from './types';
|
||||
|
||||
import NotFoundPage from '@features/ServerPage/features/NotFoundPage/NotFoundPage';
|
||||
import PageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Spinner from '@common/Spinner/Spinner';
|
||||
|
||||
export interface Props {
|
||||
|
@ -41,17 +40,15 @@ function Provider({ children }: Props) {
|
|||
alignItems: 'center',
|
||||
};
|
||||
return (
|
||||
<PageLayout noPadding contentStyle={centerFlex as React.CSSProperties}>
|
||||
<Spinner
|
||||
containerProps={{
|
||||
...centerFlex,
|
||||
textAlign: 'center',
|
||||
height: '100%',
|
||||
paddingY: 5,
|
||||
}}
|
||||
description={t('playerPageContextProvider.loadingPlayer')}
|
||||
/>
|
||||
</PageLayout>
|
||||
<Spinner
|
||||
containerProps={{
|
||||
...centerFlex,
|
||||
textAlign: 'center',
|
||||
minHeight: 'inherit',
|
||||
paddingY: 5,
|
||||
}}
|
||||
description={t('playerPageContextProvider.loadingPlayer')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ function RankingPage() {
|
|||
<TribePage />
|
||||
</Route>
|
||||
<Route path="*">
|
||||
<NotFoundPage wrapIntoServerPageLayout={false} />
|
||||
<NotFoundPage />
|
||||
</Route>
|
||||
</Switch>
|
||||
</PageLayout>
|
||||
|
|
|
@ -8,7 +8,7 @@ import { makeStyles } from '@material-ui/core/styles';
|
|||
|
||||
import { Tabs } from '@material-ui/core';
|
||||
import TabLink from '@common/Link/TabLink';
|
||||
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Content from '@common/Content/Content';
|
||||
|
||||
import background from './backgrounds/bg-1-dark.png';
|
||||
|
||||
|
@ -22,7 +22,7 @@ function PageLayout({ children }: Props) {
|
|||
const { t } = useTranslation(NAMESPACES.SERVER_PAGE.RANKING_PAGE.COMMON);
|
||||
const { currentTab, tabs } = useTabs(t);
|
||||
return (
|
||||
<ServerPageLayout noPadding>
|
||||
<div>
|
||||
<header className={classes.header}>
|
||||
<Tabs variant="scrollable" value={currentTab}>
|
||||
{tabs.map(({ to, label }) => {
|
||||
|
@ -40,8 +40,10 @@ function PageLayout({ children }: Props) {
|
|||
})}
|
||||
</Tabs>
|
||||
</header>
|
||||
<div className={classes.content}>{children}</div>
|
||||
</ServerPageLayout>
|
||||
<Content minHeight={false} component="div">
|
||||
{children}
|
||||
</Content>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -61,15 +63,6 @@ const useStyles = makeStyles(theme => ({
|
|||
minHeight: theme.spacing(10),
|
||||
},
|
||||
},
|
||||
content: {
|
||||
padding: theme.spacing(3, 0),
|
||||
'&.no-padding': {
|
||||
padding: '0 0',
|
||||
},
|
||||
},
|
||||
tabs: {
|
||||
overflowX: 'auto',
|
||||
},
|
||||
}));
|
||||
|
||||
export default PageLayout;
|
||||
|
|
|
@ -24,7 +24,7 @@ function PlayerPage() {
|
|||
<ArchivePage />
|
||||
</Route>
|
||||
<Route path="*">
|
||||
<NotFoundPage wrapIntoServerPageLayout={false} />
|
||||
<NotFoundPage />
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
|
|
|
@ -24,7 +24,7 @@ function TribePage() {
|
|||
<ArchivePage />
|
||||
</Route>
|
||||
<Route path="*">
|
||||
<NotFoundPage wrapIntoServerPageLayout={false} />
|
||||
<NotFoundPage />
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
|
|
|
@ -32,7 +32,7 @@ function TribePage() {
|
|||
<EnnoblementsPage />
|
||||
</Route>
|
||||
<Route path="*">
|
||||
<NotFoundPage wrapIntoServerPageLayout={false} />
|
||||
<NotFoundPage />
|
||||
</Route>
|
||||
</Switch>
|
||||
</PageLayout>
|
||||
|
|
|
@ -10,8 +10,8 @@ import * as NAMESPACES from '@config/namespaces';
|
|||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
import { Chip, Toolbar, Typography, Tabs, ChipProps } from '@material-ui/core';
|
||||
import Content from '@common/Content/Content';
|
||||
import TabLink from '@common/Link/TabLink';
|
||||
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
|
||||
import background1 from './backgrounds/bg-1-dark.jpg';
|
||||
import background2 from './backgrounds/bg-2-dark.jpg';
|
||||
|
@ -35,7 +35,7 @@ function PageLayout({ children }: Props) {
|
|||
size: 'small',
|
||||
};
|
||||
return (
|
||||
<ServerPageLayout noPadding>
|
||||
<div>
|
||||
<header className={clsx(classes.header, 'bg-' + bg)}>
|
||||
<Toolbar className={classes.toolbar}>
|
||||
<div style={{ width: '100%' }}>
|
||||
|
@ -105,8 +105,10 @@ function PageLayout({ children }: Props) {
|
|||
})}
|
||||
</Tabs>
|
||||
</header>
|
||||
<div className={classes.content}>{children}</div>
|
||||
</ServerPageLayout>
|
||||
<Content minHeight={false} component="div">
|
||||
{children}
|
||||
</Content>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -161,13 +163,6 @@ const useStyles = makeStyles(theme => ({
|
|||
margin: theme.spacing(0.5),
|
||||
},
|
||||
},
|
||||
content: {
|
||||
height: '100%',
|
||||
padding: theme.spacing(3, 0),
|
||||
'&.no-padding': {
|
||||
padding: '0 0',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export default PageLayout;
|
||||
|
|
|
@ -10,7 +10,6 @@ import { TribeQueryVariables } from '@libs/graphql/types';
|
|||
import { Params, TribeQueryResult } from './types';
|
||||
|
||||
import NotFoundPage from '@features/ServerPage/features/NotFoundPage/NotFoundPage';
|
||||
import PageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Spinner from '@common/Spinner/Spinner';
|
||||
|
||||
export interface Props {
|
||||
|
@ -41,17 +40,16 @@ function Provider({ children }: Props) {
|
|||
alignItems: 'center',
|
||||
};
|
||||
return (
|
||||
<PageLayout noPadding contentStyle={centerFlex as React.CSSProperties}>
|
||||
<Spinner
|
||||
containerProps={{
|
||||
...centerFlex,
|
||||
textAlign: 'center',
|
||||
height: '100%',
|
||||
paddingY: 5,
|
||||
}}
|
||||
description={t('tribePageContextProvider.loadingTribe')}
|
||||
/>
|
||||
</PageLayout>
|
||||
<Spinner
|
||||
containerProps={{
|
||||
...centerFlex,
|
||||
textAlign: 'center',
|
||||
minHeight: 'inherit',
|
||||
height: '100%',
|
||||
paddingY: 5,
|
||||
}}
|
||||
description={t('tribePageContextProvider.loadingTribe')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import { SERVER_PAGE } from '@config/namespaces';
|
|||
|
||||
import { Container } from '@material-ui/core';
|
||||
import NotFoundPage from '@features/ServerPage/features/NotFoundPage/NotFoundPage';
|
||||
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Spinner from '@common/Spinner/Spinner';
|
||||
import PageLayout from './components/PageLayout/PageLayout';
|
||||
import Ennoblements from './components/Ennoblements/Ennoblements';
|
||||
|
@ -28,20 +27,15 @@ function VillagePage() {
|
|||
alignItems: 'center',
|
||||
};
|
||||
return (
|
||||
<ServerPageLayout
|
||||
noPadding
|
||||
contentStyle={centerFlex as React.CSSProperties}
|
||||
>
|
||||
<Spinner
|
||||
containerProps={{
|
||||
...centerFlex,
|
||||
textAlign: 'center',
|
||||
height: '100%',
|
||||
paddingY: 5,
|
||||
}}
|
||||
description={t('loadingVillage')}
|
||||
/>
|
||||
</ServerPageLayout>
|
||||
<Spinner
|
||||
containerProps={{
|
||||
...centerFlex,
|
||||
textAlign: 'center',
|
||||
minHeight: 'inherit',
|
||||
paddingY: 5,
|
||||
}}
|
||||
description={t('loadingVillage')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Village } from '../../types';
|
|||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
import { Toolbar, Typography } from '@material-ui/core';
|
||||
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Content from '@common/Content/Content';
|
||||
import PlayerProfileLink from '@features/ServerPage/common/PlayerProfileLink/PlayerProfileLink';
|
||||
|
||||
import background from './backgrounds/bg-1-dark.jpg';
|
||||
|
@ -21,7 +21,7 @@ export interface Props {
|
|||
function PageLayout({ children, village, server, t }: Props) {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<ServerPageLayout noPadding>
|
||||
<div>
|
||||
<header className={classes.header}>
|
||||
<Toolbar className={classes.toolbar}>
|
||||
<div>
|
||||
|
@ -40,8 +40,10 @@ function PageLayout({ children, village, server, t }: Props) {
|
|||
</div>
|
||||
</Toolbar>
|
||||
</header>
|
||||
<div className={classes.content}>{children}</div>
|
||||
</ServerPageLayout>
|
||||
<Content minHeight={false} component="div">
|
||||
{children}
|
||||
</Content>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -68,13 +70,6 @@ const useStyles = makeStyles(theme => ({
|
|||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
},
|
||||
content: {
|
||||
height: '100%',
|
||||
padding: theme.spacing(3, 0),
|
||||
'&.no-padding': {
|
||||
padding: '0 0',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export default PageLayout;
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
Button,
|
||||
} from '@material-ui/core';
|
||||
import DateTimePicker from '@common/Picker/DateTimePicker';
|
||||
import ServerPageLayout from '@features/ServerPage/common/PageLayout/PageLayout';
|
||||
import Content from '@common/Content/Content';
|
||||
import Spinner from '@common/Spinner/Spinner';
|
||||
import Card from './components/Card/Card';
|
||||
import OneSide from './components/OneSide/OneSide';
|
||||
|
@ -205,127 +205,127 @@ function WarStatsPage() {
|
|||
setIsSubmitting(false);
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Spinner
|
||||
containerProps={{
|
||||
minHeight: 'inherit',
|
||||
textAlign: 'center',
|
||||
paddingY: 5,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
description={t('loading')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ServerPageLayout>
|
||||
{loading && (
|
||||
<Spinner
|
||||
containerProps={{
|
||||
minHeight: 'inherit',
|
||||
textAlign: 'center',
|
||||
paddingY: 5,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
description={t('loading')}
|
||||
/>
|
||||
)}
|
||||
{!loading && (
|
||||
<Container>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Grid container spacing={2}>
|
||||
<Card>
|
||||
<Typography variant="h4" align="center" gutterBottom>
|
||||
{t('sections.settings')}
|
||||
</Typography>
|
||||
<div className={classes.formGroup}>
|
||||
{[
|
||||
{
|
||||
name: 'ennobledAtGTE',
|
||||
val: query.ennobledAtGTE,
|
||||
maxDate: query.ennobledAtLTE,
|
||||
},
|
||||
{
|
||||
name: 'ennobledAtLTE',
|
||||
val: query.ennobledAtLTE,
|
||||
minDate: query.ennobledAtGTE,
|
||||
},
|
||||
].map(({ name, val, maxDate, minDate }) => {
|
||||
return (
|
||||
<DateTimePicker
|
||||
key={name}
|
||||
maxDate={maxDate}
|
||||
minDate={minDate}
|
||||
disableFuture
|
||||
disabled={isSubmitting}
|
||||
TextFieldComponent={props => {
|
||||
return (
|
||||
<TextField
|
||||
{...props}
|
||||
helperText=""
|
||||
fullWidth
|
||||
variant="standard"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
label={t('inputLabels.' + name)}
|
||||
value={val}
|
||||
onChange={d => {
|
||||
setQuery({ [name]: d ? d : undefined });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<OneSide
|
||||
title={t('sections.sideOne')}
|
||||
players={sideOnePlayers}
|
||||
tribes={sideOneTribes}
|
||||
onChangePlayers={sideOneHandleChangePlayers}
|
||||
onChangeTribes={sideOneHandleChangeTribes}
|
||||
server={server.key}
|
||||
tribeIDNEQ={selectedTribesIDs}
|
||||
playerIDNEQ={selectedPlayersIDs}
|
||||
className={classes.formGroup}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</Card>
|
||||
<Card>
|
||||
<OneSide
|
||||
title={t('sections.sideTwo')}
|
||||
players={sideTwoPlayers}
|
||||
tribes={sideTwoTribes}
|
||||
onChangePlayers={sideTwoHandleChangePlayers}
|
||||
onChangeTribes={sideTwoHandleChangeTribes}
|
||||
server={server.key}
|
||||
tribeIDNEQ={selectedTribesIDs}
|
||||
playerIDNEQ={selectedPlayersIDs}
|
||||
className={classes.formGroup}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</Card>
|
||||
<Grid item xs={12}>
|
||||
<Typography align="center" component="div">
|
||||
<Button
|
||||
type="submit"
|
||||
size="large"
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
disabled={
|
||||
isSubmitting ||
|
||||
(sideOnePlayers.length === 0 &&
|
||||
sideOneTribes.length === 0) ||
|
||||
(sideTwoPlayers.length === 0 &&
|
||||
sideTwoTribes.length === 0)
|
||||
}
|
||||
>
|
||||
{t('buttons.generateStats')}
|
||||
</Button>
|
||||
</Typography>
|
||||
</Grid>
|
||||
{results && (
|
||||
<Grid item xs={12}>
|
||||
<Results data={results} server={server.key} />
|
||||
</Grid>
|
||||
)}
|
||||
<Content component="div" minHeight={false}>
|
||||
<Container>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Grid container spacing={2}>
|
||||
<Card>
|
||||
<Typography variant="h4" align="center" gutterBottom>
|
||||
{t('sections.settings')}
|
||||
</Typography>
|
||||
<div className={classes.formGroup}>
|
||||
{[
|
||||
{
|
||||
name: 'ennobledAtGTE',
|
||||
val: query.ennobledAtGTE,
|
||||
maxDate: query.ennobledAtLTE,
|
||||
},
|
||||
{
|
||||
name: 'ennobledAtLTE',
|
||||
val: query.ennobledAtLTE,
|
||||
minDate: query.ennobledAtGTE,
|
||||
},
|
||||
].map(({ name, val, maxDate, minDate }) => {
|
||||
return (
|
||||
<DateTimePicker
|
||||
key={name}
|
||||
maxDate={maxDate}
|
||||
minDate={minDate}
|
||||
disableFuture
|
||||
disabled={isSubmitting}
|
||||
TextFieldComponent={props => {
|
||||
return (
|
||||
<TextField
|
||||
{...props}
|
||||
helperText=""
|
||||
fullWidth
|
||||
variant="standard"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
label={t('inputLabels.' + name)}
|
||||
value={val}
|
||||
onChange={d => {
|
||||
setQuery({ [name]: d ? d : undefined });
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<OneSide
|
||||
title={t('sections.sideOne')}
|
||||
players={sideOnePlayers}
|
||||
tribes={sideOneTribes}
|
||||
onChangePlayers={sideOneHandleChangePlayers}
|
||||
onChangeTribes={sideOneHandleChangeTribes}
|
||||
server={server.key}
|
||||
tribeIDNEQ={selectedTribesIDs}
|
||||
playerIDNEQ={selectedPlayersIDs}
|
||||
className={classes.formGroup}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</Card>
|
||||
<Card>
|
||||
<OneSide
|
||||
title={t('sections.sideTwo')}
|
||||
players={sideTwoPlayers}
|
||||
tribes={sideTwoTribes}
|
||||
onChangePlayers={sideTwoHandleChangePlayers}
|
||||
onChangeTribes={sideTwoHandleChangeTribes}
|
||||
server={server.key}
|
||||
tribeIDNEQ={selectedTribesIDs}
|
||||
playerIDNEQ={selectedPlayersIDs}
|
||||
className={classes.formGroup}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</Card>
|
||||
<Grid item xs={12}>
|
||||
<Typography align="center" component="div">
|
||||
<Button
|
||||
type="submit"
|
||||
size="large"
|
||||
color="secondary"
|
||||
variant="contained"
|
||||
disabled={
|
||||
isSubmitting ||
|
||||
(sideOnePlayers.length === 0 &&
|
||||
sideOneTribes.length === 0) ||
|
||||
(sideTwoPlayers.length === 0 && sideTwoTribes.length === 0)
|
||||
}
|
||||
>
|
||||
{t('buttons.generateStats')}
|
||||
</Button>
|
||||
</Typography>
|
||||
</Grid>
|
||||
</form>
|
||||
</Container>
|
||||
)}
|
||||
</ServerPageLayout>
|
||||
{results && (
|
||||
<Grid item xs={12}>
|
||||
<Results data={results} server={server.key} />
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
</form>
|
||||
</Container>
|
||||
</Content>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
25
src/libs/serialize-query-params/helpers.ts
Normal file
25
src/libs/serialize-query-params/helpers.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
export function getEncodedValue(
|
||||
input: string | (string | null)[] | null | undefined,
|
||||
allowEmptyString?: boolean
|
||||
): string | null | undefined {
|
||||
if (!input) {
|
||||
return undefined;
|
||||
}
|
||||
// '' or []
|
||||
if (
|
||||
input.length === 0 &&
|
||||
(!allowEmptyString || (allowEmptyString && input !== ''))
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const str = input instanceof Array ? input[0] : input;
|
||||
if (str == null) {
|
||||
return str;
|
||||
}
|
||||
if (!allowEmptyString && str === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
Reference in New Issue
Block a user