finished top 500 browser

This commit is contained in:
Sendou
2019-08-23 23:11:50 +03:00
parent 0f9ae2a5cb
commit 43191649b0
10 changed files with 261 additions and 425 deletions

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react'
import { Form, Message, Button } from 'semantic-ui-react'
import WeaponForm from '../XSearch/WeaponForm'
import Select from '../elements/Select'
import Build from './Build'
import AbilityButtons from './AbilityButtons'
@@ -57,7 +57,7 @@ const BuildForm = ({ addBuild, setShowForm, setSuccessMsg, existingBuild, setSho
<Build build={build} existingAbilities={abilities} setAbilities={setAbilities} />
</div>
<div style={{"paddingTop": "15px"}}>
<WeaponForm weaponForm={weaponForm} setWeaponForm={setWeaponForm} showImages={false} />
<Select content="MAINWEAPONS" value={weaponForm} onChange={setWeaponForm} />
</div>
<div style={{"paddingTop": "15px"}}>
<Form error={title.length > 100}>

View File

@@ -24,7 +24,7 @@ const PageBuilds = withRouter(({ history, weaponFromUrl, setMenuSelection }) =>
return (
<Segment>
<div>
<PageHeader title={localization["Build Search"]} subTitle={localization["Learn how others spend those valuable Ability Points"]} />
<PageHeader title={localization["Build Search"]}/>
</div>
<div style={{margin: "0 1.5em"}}>
<Select content="MAINWEAPONS" value={weapon} onChange={handleFormChange} />

View File

@@ -1,5 +1,5 @@
import React from "react"
import { Table, Icon, Popup, Segment } from "semantic-ui-react"
import { Table, Icon, Popup } from "semantic-ui-react"
import { useQuery } from "@apollo/react-hooks"
import { useSelector } from "react-redux"
import { Loader } from "semantic-ui-react"

View File

@@ -1,19 +1,65 @@
import React, { useEffect } from "react"
import React, { useEffect, useState } from "react"
import { Segment } from "semantic-ui-react"
import { Spin, Table } from "antd"
import { Spin, Table, Avatar, Button, Input, Radio, InputNumber } from "antd"
import { useQuery } from "@apollo/react-hooks"
import { useSelector } from "react-redux"
import { Link } from "react-router-dom"
import { searchForPlacements } from "../../graphql/queries/searchForPlacements"
import language_dict from '../../utils/english_internal.json'
import { modesArr } from '../../img/imports'
import language_dict from "../../utils/english_internal.json"
import { modesArr } from "../../img/imports"
import Select from "../elements/Select"
const PageXBrowser = ({ setMenuSelection }) => {
const localization = useSelector(state => state.localization)
const { data, error, loading } = useQuery(searchForPlacements, {
variables: {}
const [page, setPage] = useState(1)
const [filter, setFilter] = useState({
name: null,
weapon: null,
mode: null,
unique_id: null,
month: null,
year: null
})
const [showForms, setShowForms] = useState(false)
const [nameForm, setNameForm] = useState("")
const [weaponForm, setWeaponForm] = useState(null)
const [modeForm, setModeForm] = useState(0)
const [idForm, setIdForm] = useState("")
const [monthForm, setMonthForm] = useState("")
const [yearForm, setYearForm] = useState("")
const { data, error, loading } = useQuery(searchForPlacements, {
variables: { page, ...filter }
})
const handleFilterChange = () => {
// Empty input gets changed to null
const name = nameForm === "" ? null : nameForm
const mode = modeForm === 0 ? null : modeForm
const unique_id = idForm === "" ? null : idForm
const month = monthForm === "" ? null : monthForm
const year = yearForm === "" ? null : yearForm
const weapon = weaponForm
setPage(1)
setFilter({
name,
weapon,
mode,
unique_id,
month,
year
})
}
const handleClear = () => {
setNameForm("")
setModeForm(0)
setIdForm("")
setMonthForm("")
setYearForm("")
setWeaponForm(null)
}
useEffect(() => {
document.title = `${localization["Top 500 Browser"]} - sendou.ink`
@@ -21,56 +67,210 @@ const PageXBrowser = ({ setMenuSelection }) => {
}, [localization, setMenuSelection])
if (error) return <div style={{ color: "red" }}>{error.message}</div>
if (loading) return <Spin />
if (loading && !data.searchForPlacements) return <Spin />
const columns = [
{
title: localization['Name'],
dataIndex: 'name',
render: name => <Link to>{name}</Link>,
dataIndex: "player",
render: player =>
player.twitter ? (
<Avatar
size="small"
src={`https://avatars.io/twitter/${player.twitter}/small`}
/>
) : null
},
{
title: localization['X Power'],
dataIndex: 'x_power',
title: localization["Name"],
dataIndex: "name",
render: (name, record) => (
<Link to={`/xsearch/p/${record.unique_id}`}>{name}</Link>
)
},
{
title: localization['Mode'],
dataIndex: 'mode',
render: mode => <img src={modesArr[mode]} alt={mode} />,
title: localization["X Power"],
dataIndex: "x_power"
},
{
title: localization['Placement'],
dataIndex: 'rank',
title: localization["Weapon"],
dataIndex: "weapon",
render: weapon => (
<img
style={{cursor: "pointer"}}
src={
process.env.PUBLIC_URL +
`/wpnSmall/Wst_${language_dict[weapon]}.png`
}
alt={weapon}
onClick={() => {
setWeaponForm(weapon)
setShowForms(true)
}}
/>
)
},
{
title: localization['Weapon'],
dataIndex: 'weapon',
render: weapon => <img src={process.env.PUBLIC_URL + `/wpnSmall/Wst_${language_dict[weapon]}.png`} alt={weapon} />
title: localization["Mode"],
dataIndex: "mode",
render: mode => (
<img
style={{ height: "32px", width: "auto", cursor: "pointer" }}
src={modesArr[mode]}
alt={mode}
onClick={() => {
setModeForm(mode)
setShowForms(true)
}}
/>
)
},
{
title: localization['Month'],
dataIndex: 'month',
}
title: localization["Placement"],
dataIndex: "rank"
},
{
title: localization['Year'],
dataIndex: 'year',
}
title: localization["Month"],
dataIndex: "month",
render: month => (
<span
style={{cursor: "pointer"}}
onClick={() => {
setMonthForm(month)
setShowForms(true)
}}
>
{month}
</span>
)
},
{
title: localization['ID'],
dataIndex: 'unique_id',
title: localization["Year"],
dataIndex: "year",
render: year => (
<span
style={{cursor: "pointer"}}
onClick={() => {
setYearForm(year)
setShowForms(true)
}}
>
{year}
</span>
)
},
{
title: localization["ID"],
dataIndex: "unique_id",
render: unique_id => (
<span
style={{cursor: "pointer"}}
onClick={() => {
setIdForm(unique_id)
setShowForms(true)
}}
>
{unique_id}
</span>
)
}
]
console.log("data", data)
return (
<Segment>
<Table
columns={columns}
dataSource={data}
bordered
title={() => "Header"}
footer={() => "Footer"}
/>
<div style={{ margin: "1em" }}>
<Button onClick={() => setShowForms(!showForms)}>
{showForms
? localization["Hide filter options"]
: localization["Show filter options"]}
</Button>
</div>
{showForms && (
<div style={{ margin: "1em" }}>
<div style={{ margin: "0.5em 0" }}>
{localization["Name"]}
<br />
<Input
value={nameForm}
onChange={e => setNameForm(e.target.value)}
style={{ width: 200 }}
maxLength={10}
/>
</div>
<div style={{ margin: "0.5em 0" }}>
{localization["ID"]}
<br />
<Input
value={idForm}
onChange={e => setIdForm(e.target.value)}
style={{ width: 200 }}
/>
</div>
<div style={{ margin: "0.5em 0" }}>
{localization["Weapon"]}
<br />
<Select
value={weaponForm}
onChange={value => setWeaponForm(value)}
content="MAINWEAPONS"
/>
</div>
<div style={{ margin: "0.5em 0" }}>
{localization["Mode"]}
<br />
<Radio.Group
onChange={e => setModeForm(e.target.value)}
value={modeForm}
>
<Radio value={0}>{localization["All Modes"]}</Radio>
<Radio value={1}>{localization["Splat Zones"]}</Radio>
<Radio value={2}>{localization["Tower Control"]}</Radio>
<Radio value={3}>{localization["Rainmaker"]}</Radio>
<Radio value={4}>{localization["Clam Blitz"]}</Radio>
</Radio.Group>
</div>
<div style={{ margin: "0.5em 0" }}>
{`${localization["Month"]} / ${localization["Year"]}`}
<br />
<InputNumber
min={1}
max={12}
value={monthForm}
onChange={value => setMonthForm(value)}
/>{" "}
<InputNumber
min={2018}
max={new Date().getFullYear()}
value={yearForm}
onChange={value => setYearForm(value)}
/>
</div>
<div style={{ margin: "1em 0" }}>
<Button type="primary" onClick={handleFilterChange}>
{localization["Search"]}
</Button>{" "}
<Button type="danger" onClick={handleClear}>
{localization["Clear All"]}
</Button>
</div>
</div>
)}
<div style={{ margin: "1em" }}>
<Table
columns={columns}
dataSource={data.searchForPlacements.placements}
pagination={{
pageSize: 25,
position: "both",
showQuickJumper: true,
total: data.searchForPlacements.pageCount * 25,
current: page,
onChange: page => setPage(page)
}}
rowKey="id"
scroll={{ x: true }}
loading={loading}
/>
</div>
</Segment>
)
}

View File

@@ -1,369 +0,0 @@
import React, { useState } from "react"
import { Dropdown, Button } from "semantic-ui-react"
import { withRouter } from "react-router-dom"
import { weapons } from "../../utils/lists"
import weaponDict from "../../utils/english_internal.json"
const WeaponForm = withRouter(
({
history,
weaponForm,
setWeaponForm,
showImages = true,
push = false,
setPage,
showSubSpecials = false
}) => {
const subSpecialOptions = [
{
key: "Splat Bomb",
text: "Splat Bomb",
value: "Splat Bomb",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_Bomb_Splash.png`
}
: null
},
{
key: "Suction Bomb",
text: "Suction Bomb",
value: "Suction Bomb",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_Bomb_Suction.png`
}
: null
},
{
key: "Burst Bomb",
text: "Burst Bomb",
value: "Burst Bomb",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_Bomb_Quick.png`
}
: null
},
{
key: "Curling Bomb",
text: "Curling Bomb",
value: "Curling Bomb",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_Bomb_Curling.png`
}
: null
},
{
key: "Autobomb",
text: "Autobomb",
value: "Autobomb",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_Bomb_Robo.png`
}
: null
},
{
key: "Ink Mine",
text: "Ink Mine",
value: "Ink Mine",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_TimerTrap.png`
}
: null
},
{
key: "Toxic Mist",
text: "Toxic Mist",
value: "Toxic Mist",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_PoisonFog.png`
}
: null
},
{
key: "Point Sensor",
text: "Point Sensor",
value: "Point Sensor",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_PointSensor.png`
}
: null
},
{
key: "Splash Wall",
text: "Splash Wall",
value: "Splash Wall",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_Shield.png`
}
: null
},
{
key: "Sprinkler",
text: "Sprinkler",
value: "Sprinkler",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_Sprinkler.png`
}
: null
},
{
key: "Squid Beakon",
text: "Squid Beakon",
value: "Squid Beakon",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_Flag.png`
}
: null
},
{
key: "Fizzy Bomb",
text: "Fizzy Bomb",
value: "Fizzy Bomb",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_Bomb_Piyo.png`
}
: null
},
{
key: "Torpedo",
text: "Torpedo",
value: "Torpedo",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_Bomb_Tako.png`
}
: null
},
{
key: "Tenta Missiles",
text: "Tenta Missiles",
value: "Tenta Missiles",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_SuperMissile.png`
}
: null
},
{
key: "Sting Ray",
text: "Sting Ray",
value: "Sting Ray",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_WaterCutter.png`
}
: null
},
{
key: "Inkjet",
text: "Inkjet",
value: "Inkjet",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_Jetpack.png`
}
: null
},
{
key: "Splashdown",
text: "Splashdown",
value: "Splashdown",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_SuperLanding.png`
}
: null
},
{
key: "Ink Armor",
text: "Ink Armor",
value: "Ink Armor",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_SuperArmor.png`
}
: null
},
{
key: "Autobomb Launcher",
text: "Autobomb Launcher",
value: "Autobomb Launcher",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_LauncherRobo.png`
}
: null
},
{
key: "Burst-Bomb Launcher",
text: "Burst-Bomb Launcher",
value: "Burst-Bomb Launcher",
image: showImages
? {
src:
process.env.PUBLIC_URL +
`/wpnSmall/Wst_LauncherQuick.png`
}
: null
},
{
key: "Curling-Bomb Launcher",
text: "Curling-Bomb Launcher",
value: "Curling-Bomb Launcher",
image: showImages
? {
src:
process.env.PUBLIC_URL +
`/wpnSmall/Wst_LauncherCurling.png`
}
: null
},
{
key: "Splat-Bomb Launcher",
text: "Splat-Bomb Launcher",
value: "Splat-Bomb Launcher",
image: showImages
? {
src:
process.env.PUBLIC_URL +
`/wpnSmall/Wst_LauncherSplash.png`
}
: null
},
{
key: "Suction-Bomb Launcher",
text: "Suction-Bomb Launcher",
value: "Suction-Bomb Launcher",
image: showImages
? {
src:
process.env.PUBLIC_URL +
`/wpnSmall/Wst_LauncherSuction.png`
}
: null
},
{
key: "Ink Storm",
text: "Ink Storm",
value: "Ink Storm",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_RainCloud.png`
}
: null
},
{
key: "Baller",
text: "Baller",
value: "Baller",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_AquaBall.png`
}
: null
},
{
key: "Bubble Blower",
text: "Bubble Blower",
value: "Bubble Blower",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_SuperBubble.png`
}
: null
},
{
key: "Booyah Bomb",
text: "Booyah Bomb",
value: "Booyah Bomb",
image: showImages
? {
src: process.env.PUBLIC_URL + `/wpnSmall/Wst_SuperBall.png`
}
: null
},
{
key: "Ultra Stamp",
text: "Ultra Stamp",
value: "Ultra Stamp",
image: showImages
? {
src:
process.env.PUBLIC_URL + `/wpnSmall/Wst_SuperStamp.png`
}
: null
}
]
let options = weapons.map(w => ({
key: w,
text: w,
value: w,
image: showImages
? { src: process.env.PUBLIC_URL + `/wpnSmall/Wst_${weaponDict[w]}.png` }
: null
}))
if (showSubSpecials) options = options.concat(subSpecialOptions)
return (
<div>
<Dropdown
placeholder="Choose a weapon"
fluid
search
selection
options={options}
onChange={(event, { value }) => {
setWeaponForm(value)
if (push) history.push(`/builds/${value.replace(/ /g, "_")}`)
if (setPage) setPage(1)
}}
value={weaponForm}
/>
</div>
)
}
)
export const WeaponFormWithButton = withRouter(({ history }) => {
const [weaponForm, setWeaponForm] = useState("")
return (
<div>
<WeaponForm weaponForm={weaponForm} setWeaponForm={setWeaponForm} />
<div style={{ paddingTop: "13px" }}>
<Button
disabled={weaponForm === ""}
onClick={() =>
history.push(
`/xsearch/w/${weaponDict[weaponForm].replace(/_/g, "-")}`
)
}
>
Search for a weapon
</Button>
</div>
</div>
)
})
export default WeaponForm

View File

@@ -11,10 +11,10 @@ import {
Message,
Header
} from "semantic-ui-react"
import WeaponForm from "./WeaponForm"
import useTrends from "../hooks/useTrends"
import useWindowDimensions from "../hooks/useWindowDimensions"
import english_internal from "../../utils/english_internal.json"
import Select from '../elements/Select'
import {
LineChart,
Line,
@@ -121,15 +121,15 @@ const XTrends = ({ setMenuSelection }) => {
}
return (
<div>
<Segment>
<div style={{ padding: "5px" }}>
<Header as="h2">
Compare weapons based on their X Rank Top 500 appearances
</Header>
<WeaponForm
showSubSpecials
weaponForm={weaponForm}
setWeaponForm={setWeaponForm}
<Select
content="ALLWEAPONS"
value={weaponForm}
onChange={setWeaponForm}
/>
<div style={{ paddingTop: "10px" }}>
<Form>
@@ -366,7 +366,7 @@ const XTrends = ({ setMenuSelection }) => {
</Message.Item>
</Message.List>
</Message>
</div>
</Segment>
)
}

View File

@@ -154,7 +154,7 @@ const SelectElement = ({ value, onChange, content }) => {
else if (content === "ALLWEAPONS") contentArr = allWeapons
return (
<>
<Select style={{ width: 200 }} value={value} onChange={onChange} showSearch placeholder={localization["Select a weapon"]}>
<Select style={{ width: 200 }} value={value} onChange={onChange} showSearch placeholder={localization["Select a weapon"]} allowClear>
{contentArr.map(c => {
return (
<OptGroup key={c.categoryName} label={localization[c.categoryName]}>

File diff suppressed because one or more lines are too long

View File

@@ -98,9 +98,12 @@ const resolvers = {
})
const pageCount = Math.ceil(buildCount / buildsPerPage)
if (args.page > pageCount) throw new UserInputError('too big page number given', {
invalidArgs: args,
})
// if 0 documents we don't care if the page is wrong
if (buildCount !== 0) {
if (args.page > pageCount) throw new UserInputError('too big page number given', {
invalidArgs: args,
})
}
const builds = await Build
.find(searchCriteria)

View File

@@ -155,11 +155,13 @@ const resolvers = {
})
})
// This is currently broken
const pageCount = Math.ceil(placementCount / perPage)
if (args.page > pageCount) throw new UserInputError('too big page number given', {
invalidArgs: args,
})
// if 0 documents we don't care if the page is wrong
if (placementCount !== 0) {
if (args.page > pageCount) throw new UserInputError('too big page number given', {
invalidArgs: args,
})
}
const placements = await Placement
.find(searchCriteria)