mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-12 13:49:22 -05:00
Merge branch 'main' of https://github.com/Sendouc/sendou.ink into main
This commit is contained in:
commit
63ee770ab4
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
|
|
|||
43
.github/workflows/ci.yml
vendored
43
.github/workflows/ci.yml
vendored
|
|
@ -5,8 +5,47 @@ jobs:
|
|||
cypress-run:
|
||||
name: Cypress tests
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres
|
||||
env:
|
||||
POSTGRES_PASSWORD: password
|
||||
POSTGRES_USER: sendou_ink
|
||||
ports:
|
||||
- 5432:5432
|
||||
# Set health checks to wait until postgres has started
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- name: Checkout
|
||||
- name: Check out code
|
||||
uses: actions/checkout@25a956c84d5dd820d28caab9f86b8d183aeeff3d # v2
|
||||
- name: Cypress run
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@5c355be17065acf11598c7a9bb47112fbcf2bbdc # v2
|
||||
with:
|
||||
node-version: "14"
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
- name: Write .env file for Prisma
|
||||
run: echo "DATABASE_URL=postgresql://sendou_ink:password@localhost:${{ job.services.postgres.ports[5432] }}" > prisma/.env
|
||||
- name: Prep the database
|
||||
run: npm run migrate
|
||||
- name: Prep other resources
|
||||
run: npm run compile && npm run prebuild
|
||||
- name: Run prettier
|
||||
run: npm run prettier:check
|
||||
- name: Run Cypress
|
||||
uses: cypress-io/github-action@9eab5368cd2520a946489cd3f937583ff5a30443 # v2
|
||||
with:
|
||||
start: npm run dev
|
||||
- name: Save Cypress artifacts
|
||||
uses: actions/upload-artifact@ea3d524381d563437a7d64af63f3d75ca55521c4 # v2
|
||||
if: failure()
|
||||
with:
|
||||
name: cypress-outputs
|
||||
path: |
|
||||
cypress/screenshots/*
|
||||
cypress/videos/*
|
||||
retention-days: 30
|
||||
|
|
|
|||
|
|
@ -2,3 +2,7 @@
|
|||
|
||||
prisma/scripts/data
|
||||
prisma/scripts/mongo
|
||||
|
||||
# Ignore JSON files generated via script
|
||||
utils/data/patrons.json
|
||||
locale/*/*.js
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Button } from "@chakra-ui/button";
|
||||
import { Input, InputGroup, InputLeftElement } from "@chakra-ui/input";
|
||||
import { Box } from "@chakra-ui/layout";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import SubText from "components/common/SubText";
|
||||
import { useMyTheme } from "hooks/common";
|
||||
import { Fragment, useState } from "react";
|
||||
|
|
@ -9,6 +9,7 @@ import { FiSearch } from "react-icons/fi";
|
|||
import { trpc } from "utils/trpc";
|
||||
import EventInfo from "./EventInfo";
|
||||
import { EventModal, FormData } from "./EventModal";
|
||||
import MyHead from "../../../components/common/MyHead";
|
||||
|
||||
export default function CalendarPage() {
|
||||
const { gray } = useMyTheme();
|
||||
|
|
@ -22,6 +23,7 @@ export default function CalendarPage() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Calendar`} />
|
||||
<div>
|
||||
<Button
|
||||
size="sm"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import HeaderBanner from "components/layout/HeaderBanner";
|
|||
import { useRouter } from "next/router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Top500PlacementsByMonth } from "../service";
|
||||
import MyHead from "../../../components/common/MyHead";
|
||||
|
||||
export interface XSearchPageProps {
|
||||
placements: Top500PlacementsByMonth;
|
||||
|
|
@ -34,6 +35,7 @@ const XSearchPage = ({ placements, monthOptions }: XSearchPageProps) => {
|
|||
//TODO: layout can be persistent between route changes
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Top 500 Browser`} />
|
||||
<Select
|
||||
value={`${variables.month},${variables.year}`}
|
||||
onChange={(e) => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { useMyTheme } from "hooks/common";
|
|||
import { useXTrends } from "../hooks/useXTrends";
|
||||
import { XTrends } from "../service";
|
||||
import TrendTier from "./TrendTier";
|
||||
import MyHead from "../../../components/common/MyHead";
|
||||
|
||||
const tiers = [
|
||||
{
|
||||
|
|
@ -71,6 +72,7 @@ const XTrendsPage = ({ trends }: XTrendsPageProps) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title="Top 500 Trends" />
|
||||
<Box color={gray} fontSize="sm" mb={8}>
|
||||
<Trans>
|
||||
Here you can find X Rank Top 500 usage tier lists. For example for a
|
||||
|
|
|
|||
1878
package-lock.json
generated
1878
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
|
|
@ -19,6 +19,7 @@
|
|||
"compile": "lingui compile",
|
||||
"restore": "pg_restore -d 'postgresql://sendou@localhost:5432/dev' --jobs 4 dumped.sql --clean",
|
||||
"seed": "prisma db seed --preview-feature",
|
||||
"prettier:check": "prettier --check .",
|
||||
"prettier:format": "prettier --write .",
|
||||
"cy:open": "cypress open",
|
||||
"cy:run": "cypress run",
|
||||
|
|
@ -26,13 +27,13 @@
|
|||
"cy:install": "cypress install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/icons": "^1.0.8",
|
||||
"@chakra-ui/react": "^1.4.2",
|
||||
"@chakra-ui/theme-tools": "^1.1.2",
|
||||
"@chakra-ui/icons": "^1.0.9",
|
||||
"@chakra-ui/react": "^1.5.0",
|
||||
"@chakra-ui/theme-tools": "^1.1.3",
|
||||
"@emotion/react": "^11.1.5",
|
||||
"@emotion/styled": "^11.1.5",
|
||||
"@hookform/resolvers": "1.3.0",
|
||||
"@lingui/react": "^3.8.2",
|
||||
"@lingui/react": "^3.8.3",
|
||||
"@next/bundle-analyzer": "^10.1.3",
|
||||
"@prisma/client": "^2.20.1",
|
||||
"@sendou/react-sketch": "^0.5.2",
|
||||
|
|
@ -41,8 +42,8 @@
|
|||
"@trpc/server": "5.0.0",
|
||||
"countries-list": "^2.6.1",
|
||||
"focus-visible": "^5.2.0",
|
||||
"framer-motion": "^4.1.2",
|
||||
"next": "^10.1.2",
|
||||
"framer-motion": "^4.1.3",
|
||||
"next": "^10.1.3",
|
||||
"next-auth": "^3.14.0",
|
||||
"next-images": "^1.7.0",
|
||||
"next-seo": "^4.23.0",
|
||||
|
|
@ -81,12 +82,12 @@
|
|||
"@types/recharts": "^1.8.19",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"cypress": "^7.0.0",
|
||||
"cypress": "^7.0.1",
|
||||
"fishery": "^1.2.0",
|
||||
"prettier": "^2.2.1",
|
||||
"prisma": "^2.20.1",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.2.3"
|
||||
"typescript": "^4.2.4"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import { FiSettings } from "react-icons/fi";
|
|||
import { isAbilityArray } from "utils/lists/abilities";
|
||||
import { isWeapon } from "utils/lists/weapons";
|
||||
import { AbilityOrUnknown } from "utils/types";
|
||||
import MyHead from "../components/common/MyHead";
|
||||
|
||||
const CURRENT_PATCH = "5.4.";
|
||||
|
||||
|
|
@ -73,6 +74,7 @@ const BuildAnalyzerPage = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Build Analyzer`} />
|
||||
<Flex justifyContent="space-between">
|
||||
<Badge>
|
||||
<Trans>Patch {CURRENT_PATCH}</Trans>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, Button, Flex } from "@chakra-ui/react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import APStats from "components/builds/APStats";
|
||||
import BuildCard from "components/builds/BuildCard";
|
||||
import BuildFilters from "components/builds/BuildFilters";
|
||||
|
|
@ -13,6 +13,7 @@ import { useBuildsByWeapon } from "hooks/builds";
|
|||
import { useMyTheme, useUser } from "hooks/common";
|
||||
import { useState } from "react";
|
||||
import { RiBarChart2Fill, RiTShirtLine } from "react-icons/ri";
|
||||
import MyHead from "../../components/common/MyHead";
|
||||
|
||||
const BuildsPage = () => {
|
||||
const {
|
||||
|
|
@ -29,6 +30,7 @@ const BuildsPage = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Builds`} />
|
||||
<Box mb={4} maxW={80} mx="auto">
|
||||
<WeaponSelector
|
||||
value={state.weapon}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import {
|
|||
import { mutate } from "swr";
|
||||
import { sendData } from "utils/postData";
|
||||
import { Unpacked } from "utils/types";
|
||||
import MyHead from "../components/common/MyHead";
|
||||
|
||||
const FreeAgentsPage = () => {
|
||||
const {
|
||||
|
|
@ -89,6 +90,7 @@ const FreeAgentsPage = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Free Agents`} />
|
||||
{modalIsOpen && (
|
||||
<FAModal post={usersPost} onClose={() => setModalIsOpen(false)} />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Box, Button, Flex, Heading } from "@chakra-ui/react";
|
||||
import { useState } from "react";
|
||||
import MyHead from "../components/common/MyHead";
|
||||
|
||||
//https://stackoverflow.com/a/19303725
|
||||
function seededRandom(seed: number) {
|
||||
|
|
@ -54,6 +55,7 @@ const EventsPage = () => {
|
|||
const [runningNumber, setRunningNumber] = useState(20);
|
||||
return (
|
||||
<>
|
||||
<MyHead title="In The Zone" />
|
||||
<Box>
|
||||
<Heading size="lg" textAlign="center">
|
||||
In The Zone
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import {
|
|||
Stack,
|
||||
Textarea,
|
||||
} from "@chakra-ui/react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import { useLingui } from "@lingui/react";
|
||||
import { RankedMode } from "@prisma/client";
|
||||
import ModeImage from "components/common/ModeImage";
|
||||
|
|
@ -32,6 +32,7 @@ import { FiCheck, FiFilter, FiRotateCw } from "react-icons/fi";
|
|||
import { shuffleArray } from "utils/arrays";
|
||||
import { stages } from "utils/lists/stages";
|
||||
import { setManySearchParams } from "utils/setSearchParams";
|
||||
import MyHead from "../components/common/MyHead";
|
||||
|
||||
const MapsGeneratorPage = () => {
|
||||
const router = useRouter();
|
||||
|
|
@ -186,6 +187,7 @@ const MapsGeneratorPage = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Maplist Generator`} />
|
||||
{editing ? (
|
||||
<>
|
||||
<Alert status="info" mb={8}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Button, ButtonGroup, Flex } from "@chakra-ui/react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import HeaderBanner from "components/layout/HeaderBanner";
|
||||
import DraggableImageAdder from "components/plans/DraggableImageAdder";
|
||||
import DraggableToolsSelector from "components/plans/DraggableToolsSelector";
|
||||
|
|
@ -13,6 +13,7 @@ import {
|
|||
FaFileUpload,
|
||||
} from "react-icons/fa";
|
||||
import { stages } from "utils/lists/stages";
|
||||
import MyHead from "../components/common/MyHead";
|
||||
|
||||
const MapSketch = dynamic(() => import("components/plans/MapSketch"), {
|
||||
ssr: false,
|
||||
|
|
@ -276,6 +277,7 @@ const MapPlannerPage = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Map Planner`} />
|
||||
<DraggableToolsSelector
|
||||
tool={tool}
|
||||
setTool={setTool}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, HStack, Radio, RadioGroup } from "@chakra-ui/react";
|
||||
import { Trans } from "@lingui/macro";
|
||||
import { t, Trans } from "@lingui/macro";
|
||||
import MyLink from "components/common/MyLink";
|
||||
import QuadTable from "components/player/QuadTable";
|
||||
import TwinTable from "components/player/TwinTable";
|
||||
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from "prisma/queries/getPlayerWithPlacements";
|
||||
import { useState } from "react";
|
||||
import { setSearchParams } from "utils/setSearchParams";
|
||||
import MyHead from "../../components/common/MyHead";
|
||||
|
||||
interface Props {
|
||||
player: GetPlayerWithPlacementsData;
|
||||
|
|
@ -29,6 +30,7 @@ const PlayerPage = (props: Props) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title="Results" />
|
||||
{player.user?.discordId && (
|
||||
<Box>
|
||||
<MyLink href={`/u/${player.user.discordId}`}>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import fs from "fs";
|
|||
import { GetStaticPaths, GetStaticProps } from "next";
|
||||
import { join } from "path";
|
||||
import { Fragment } from "react";
|
||||
import MyHead from "../../../components/common/MyHead";
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
|
|
@ -20,6 +21,7 @@ interface Props {
|
|||
const SalmonRunGuidePage = ({ text, sections }: Props) => {
|
||||
return (
|
||||
<>
|
||||
<MyHead title="Salmon Run Guide" />
|
||||
<SubText>Contents</SubText>
|
||||
<OrderedList>
|
||||
{sections.map((section) => (
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
Select,
|
||||
Stack,
|
||||
} from "@chakra-ui/react";
|
||||
import { Plural, Trans } from "@lingui/macro";
|
||||
import { Plural, t, Trans } from "@lingui/macro";
|
||||
import { useLingui } from "@lingui/react";
|
||||
import { SalmonRunRecordCategory } from "@prisma/client";
|
||||
import LinkButton from "components/common/LinkButton";
|
||||
|
|
@ -34,6 +34,7 @@ import Link from "next/link";
|
|||
import { salmonRunStages } from "utils/lists/stages";
|
||||
import { getRankingString } from "utils/strings";
|
||||
import { salmonRunCategoryToNatural } from "./new";
|
||||
import MyHead from "../../../components/common/MyHead";
|
||||
|
||||
const SalmonRunLeaderboardsPage = ({}) => {
|
||||
const { i18n } = useLingui();
|
||||
|
|
@ -49,6 +50,7 @@ const SalmonRunLeaderboardsPage = ({}) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Salmon Run Records`} />
|
||||
{pendingCount > 0 && (
|
||||
<Alert status="info" mb={4}>
|
||||
<AlertIcon />
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import { mutate } from "swr";
|
|||
import { sendData } from "utils/postData";
|
||||
import { salmonRunRecordSchema } from "utils/validators/salmonRunRecord";
|
||||
import * as z from "zod";
|
||||
import MyHead from "../../../components/common/MyHead";
|
||||
|
||||
export const salmonRunCategoryToNatural = {
|
||||
TOTAL: t`All waves`,
|
||||
|
|
@ -83,6 +84,7 @@ const AddRecordModal = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Salmon Run Records`} />
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
name="rotationId"
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import { FiEdit } from "react-icons/fi";
|
|||
import useSWR, { mutate } from "swr";
|
||||
import { getToastOptions } from "utils/getToastOptions";
|
||||
import { sendData } from "utils/postData";
|
||||
import MyHead from "../../components/common/MyHead";
|
||||
|
||||
interface Props {
|
||||
team: GetTeamData;
|
||||
|
|
@ -132,6 +133,7 @@ const TeamPage: React.FC<Props> = (props) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={team.name ? team.name : ""} />
|
||||
{profileModalIsOpen && (
|
||||
<TeamProfileModal
|
||||
team={team}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import Image from "next/image";
|
|||
import { getAllTeams, GetAllTeamsData } from "prisma/queries/getAllTeams";
|
||||
import { useState } from "react";
|
||||
import { FiSearch } from "react-icons/fi";
|
||||
import MyHead from "../../components/common/MyHead";
|
||||
|
||||
interface Props {
|
||||
teams: GetAllTeamsData;
|
||||
|
|
@ -44,6 +45,7 @@ const TeamsPage = ({ teams }: Props) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`Teams`} />
|
||||
{!isInTeam && <CreateNewTeamModal />}
|
||||
{teams.length > 0 && (
|
||||
<Box mb={8}>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { RiTShirtLine } from "react-icons/ri";
|
|||
import useSWR from "swr";
|
||||
import { GANBA_DISCORD_ID } from "utils/constants";
|
||||
import { isCustomUrl } from "utils/validators/profile";
|
||||
import MyHead from "../../components/common/MyHead";
|
||||
|
||||
interface Props {
|
||||
user: GetUserByIdentifierData;
|
||||
|
|
@ -74,6 +75,7 @@ const ProfilePage = (props: Props) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={user.username} />
|
||||
{showProfileModal && (
|
||||
<ProfileModal onClose={() => setShowProfileModal(false)} user={user} />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import { FaTwitter } from "react-icons/fa";
|
|||
import { FiSearch } from "react-icons/fi";
|
||||
import { setSearchParams } from "utils/setSearchParams";
|
||||
import { Unpacked } from "utils/types";
|
||||
import { t } from "@lingui/macro";
|
||||
import MyHead from "../../components/common/MyHead";
|
||||
|
||||
interface Props {
|
||||
users: GetAllUsersData;
|
||||
|
|
@ -61,6 +63,7 @@ const UserSearchPage = ({ users }: Props) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<MyHead title={t`User Search`} />
|
||||
<Head>
|
||||
<meta name="robots" content="noindex" />
|
||||
</Head>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user