mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-09 06:59:00 -05:00
Supporter uploaded avatar
This commit is contained in:
parent
62f1b33321
commit
bd14f88eaa
|
|
@ -110,7 +110,9 @@ export function Avatar({
|
|||
alt = "",
|
||||
...rest
|
||||
}: {
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar">;
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar"> & {
|
||||
customAvatarUrl?: string | null;
|
||||
};
|
||||
url?: string | null;
|
||||
identiconInput?: string;
|
||||
className?: string;
|
||||
|
|
@ -122,21 +124,25 @@ export function Avatar({
|
|||
const isClient = useHydrated();
|
||||
|
||||
const isIdenticon =
|
||||
!url && (!user?.discordAvatar || isErrored || identiconInput);
|
||||
!url &&
|
||||
(!user?.customAvatarUrl || isErrored) &&
|
||||
(!user?.discordAvatar || isErrored || identiconInput);
|
||||
|
||||
const identiconSource = identiconInput ?? user?.discordId ?? "unknown";
|
||||
|
||||
const src = url
|
||||
? url
|
||||
: user?.discordAvatar && !isErrored
|
||||
? discordAvatarUrl({
|
||||
discordAvatar: user.discordAvatar,
|
||||
discordId: user.discordId,
|
||||
size: size === "lg" || size === "xmd" ? "lg" : "sm",
|
||||
})
|
||||
: isClient
|
||||
? generateIdenticon(identiconSource, dimensions[size], 7)
|
||||
: BLANK_IMAGE_URL;
|
||||
: user?.customAvatarUrl && !isErrored
|
||||
? user.customAvatarUrl
|
||||
: user?.discordAvatar && !isErrored
|
||||
? discordAvatarUrl({
|
||||
discordAvatar: user.discordAvatar,
|
||||
discordId: user.discordId,
|
||||
size: size === "lg" || size === "xmd" ? "lg" : "sm",
|
||||
})
|
||||
: isClient
|
||||
? generateIdenticon(identiconSource, dimensions[size], 7)
|
||||
: BLANK_IMAGE_URL;
|
||||
|
||||
return (
|
||||
<div className={clsx(styles.avatarWrapper, className)}>
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ function ListItemContent({
|
|||
suppressSubtitleHydrationWarning,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar">;
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar"> & {
|
||||
customAvatarUrl?: string | null;
|
||||
};
|
||||
imageUrl?: string;
|
||||
overlayIconUrl?: string;
|
||||
subtitle?: React.ReactNode;
|
||||
|
|
@ -155,7 +157,9 @@ export function ListLink({
|
|||
isActive?: boolean;
|
||||
imageUrl?: string;
|
||||
overlayIconUrl?: string;
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar">;
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar"> & {
|
||||
customAvatarUrl?: string | null;
|
||||
};
|
||||
subtitle?: React.ReactNode;
|
||||
badge?: React.ReactNode;
|
||||
badgeVariant?: "default" | "warning";
|
||||
|
|
@ -190,7 +194,9 @@ export function ListButton({
|
|||
badgeVariant,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar">;
|
||||
user?: Pick<Tables["User"], "discordId" | "discordAvatar"> & {
|
||||
customAvatarUrl?: string | null;
|
||||
};
|
||||
subtitle?: string | null;
|
||||
badge?: string | null;
|
||||
badgeVariant?: "default" | "warning";
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ function user(id: number): CommonUser {
|
|||
discordId: `discord${id}`,
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1099,6 +1099,7 @@ export interface User {
|
|||
customTheme: JSONColumnTypeNullable<CustomTheme>;
|
||||
customUrl: string | null;
|
||||
discordAvatar: string | null;
|
||||
customAvatarImgId: number | null;
|
||||
discordId: string;
|
||||
discordName: string;
|
||||
customName: string | null;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ import { jsonArrayFrom } from "kysely/helpers/sqlite";
|
|||
import { db } from "~/db/sql";
|
||||
import type { DB, Tables } from "~/db/tables";
|
||||
import { actorId } from "~/features/auth/core/user.server";
|
||||
import { concatUserSubmittedImagePrefix } from "~/utils/kysely.server";
|
||||
import {
|
||||
concatUserSubmittedImagePrefix,
|
||||
customAvatarUrl,
|
||||
} from "~/utils/kysely.server";
|
||||
import { seededRandom } from "~/utils/random";
|
||||
import type { ListedArt } from "./art-types";
|
||||
|
||||
|
|
@ -37,6 +40,7 @@ export async function findShowcaseArts(): Promise<ListedArt[]> {
|
|||
"User.username",
|
||||
"User.discordAvatar",
|
||||
"User.commissionsOpen",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
concatUserSubmittedImagePrefix(eb.ref("UserSubmittedImage.url")).as(
|
||||
"url",
|
||||
),
|
||||
|
|
@ -66,6 +70,7 @@ export async function findShowcaseArts(): Promise<ListedArt[]> {
|
|||
author: {
|
||||
commissionsOpen: a.commissionsOpen,
|
||||
discordAvatar: a.discordAvatar,
|
||||
customAvatarUrl: a.customAvatarUrl,
|
||||
discordId: a.discordId,
|
||||
username: a.username,
|
||||
},
|
||||
|
|
@ -92,6 +97,7 @@ export async function findShowcaseArtsByTag(
|
|||
"User.username",
|
||||
"User.discordAvatar",
|
||||
"User.commissionsOpen",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
concatUserSubmittedImagePrefix(eb.ref("UserSubmittedImage.url")).as(
|
||||
"url",
|
||||
),
|
||||
|
|
@ -121,6 +127,7 @@ export async function findShowcaseArtsByTag(
|
|||
author: {
|
||||
commissionsOpen: a.commissionsOpen,
|
||||
discordAvatar: a.discordAvatar,
|
||||
customAvatarUrl: a.customAvatarUrl,
|
||||
discordId: a.discordId,
|
||||
username: a.username,
|
||||
},
|
||||
|
|
@ -140,6 +147,7 @@ export async function findRecentlyUploadedArts(): Promise<ListedArt[]> {
|
|||
"User.username",
|
||||
"User.discordAvatar",
|
||||
"User.commissionsOpen",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
concatUserSubmittedImagePrefix(eb.ref("UserSubmittedImage.url")).as(
|
||||
"url",
|
||||
),
|
||||
|
|
@ -156,6 +164,7 @@ export async function findRecentlyUploadedArts(): Promise<ListedArt[]> {
|
|||
author: {
|
||||
commissionsOpen: a.commissionsOpen,
|
||||
discordAvatar: a.discordAvatar,
|
||||
customAvatarUrl: a.customAvatarUrl,
|
||||
discordId: a.discordId,
|
||||
username: a.username,
|
||||
},
|
||||
|
|
@ -197,6 +206,7 @@ export async function findArtsByUserId(
|
|||
"User.username",
|
||||
"User.discordAvatar",
|
||||
"User.commissionsOpen",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
jsonArrayFrom(
|
||||
eb
|
||||
.selectFrom("TaggedArt")
|
||||
|
|
@ -279,6 +289,7 @@ export async function findArtsByUserId(
|
|||
discordId: row.discordId,
|
||||
username: row.username,
|
||||
discordAvatar: row.discordAvatar,
|
||||
customAvatarUrl: row.customAvatarUrl,
|
||||
commissionsOpen: row.commissionsOpen ?? undefined,
|
||||
},
|
||||
})),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export interface ListedArt {
|
|||
discordId: Tables["User"]["discordId"];
|
||||
username: Tables["User"]["username"];
|
||||
discordAvatar: Tables["User"]["discordAvatar"];
|
||||
customAvatarUrl: string | null;
|
||||
commissionsOpen?: Tables["User"]["commissionsOpen"];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { ASSOCIATION } from "~/features/associations/associations-constants";
|
|||
import * as FriendRepository from "~/features/friends/FriendRepository.server";
|
||||
import { LimitReachedError } from "~/utils/errors";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { commonUserSelect } from "~/utils/kysely.server";
|
||||
import { logger } from "~/utils/logger";
|
||||
|
||||
interface FindOptions {
|
||||
|
|
@ -61,7 +61,10 @@ const baseFindQuery = (options: FindOptions) =>
|
|||
.selectFrom("AssociationMember")
|
||||
.innerJoin("User", "User.id", "AssociationMember.userId")
|
||||
.whereRef("AssociationMember.associationId", "=", "Association.id")
|
||||
.select([...COMMON_USER_FIELDS, "AssociationMember.role"]),
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"AssociationMember.role",
|
||||
]),
|
||||
).as("members"),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { db } from "~/db/sql";
|
|||
import type { DB } from "~/db/tables";
|
||||
import { sortBadgesByFavorites } from "~/features/user-page/core/badge-sorting.server";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { commonUserSelect } from "~/utils/kysely.server";
|
||||
import { SPLATOON_3_XP_BADGE_VALUES } from "./badges-constants";
|
||||
import { findSplatoon3XpBadgeValue } from "./badges-utils";
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ const withAuthor = (eb: ExpressionBuilder<DB, "Badge">) => {
|
|||
return jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.select(COMMON_USER_FIELDS)
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.whereRef("User.id", "=", "Badge.authorId"),
|
||||
).as("author");
|
||||
};
|
||||
|
|
@ -31,7 +31,7 @@ const withManagers = (eb: ExpressionBuilder<DB, "Badge">) => {
|
|||
eb
|
||||
.selectFrom("BadgeManager")
|
||||
.innerJoin("User", "BadgeManager.userId", "User.id")
|
||||
.select(["userId", ...COMMON_USER_FIELDS])
|
||||
.select((eb) => ["userId", ...commonUserSelect(eb)])
|
||||
.whereRef("BadgeManager.badgeId", "=", "Badge.id"),
|
||||
).as("managers");
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import {
|
|||
import invariant from "~/utils/invariant";
|
||||
import {
|
||||
concatUserSubmittedImagePrefix,
|
||||
customAvatarUrl,
|
||||
tournamentLogoWithDefault,
|
||||
} from "~/utils/kysely.server";
|
||||
import { calendarEventPage, tournamentPage } from "~/utils/urls";
|
||||
|
|
@ -396,13 +397,14 @@ export async function findResultsByEventId(eventId: number) {
|
|||
eb
|
||||
.selectFrom("CalendarEventResultPlayer")
|
||||
.leftJoin("User", "User.id", "CalendarEventResultPlayer.userId")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"CalendarEventResultPlayer.userId as id",
|
||||
"CalendarEventResultPlayer.name",
|
||||
"User.username",
|
||||
"User.discordId",
|
||||
"User.discordAvatar",
|
||||
"User.customUrl",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
])
|
||||
.whereRef(
|
||||
"CalendarEventResultPlayer.teamId",
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ export type ChatUser = Pick<
|
|||
Tables["User"],
|
||||
"username" | "discordId" | "discordAvatar" | "pronouns"
|
||||
> & {
|
||||
customAvatarUrl: string | null;
|
||||
chatNameHue: string | null;
|
||||
title?: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { db } from "~/db/sql";
|
|||
import type { DB } from "~/db/tables";
|
||||
import { actorId } from "~/features/auth/core/user.server";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { commonUserSelect, customAvatarUrl } from "~/utils/kysely.server";
|
||||
|
||||
export async function findByUserIdWithActivity(userId: number) {
|
||||
const [friendRows, teamMemberRows] = await Promise.all([
|
||||
|
|
@ -99,8 +99,8 @@ function withLfgJoins<QB extends SelectQueryBuilder<any, any, any>>(qb: QB) {
|
|||
"CalendarEventDate.eventId",
|
||||
"CalendarEvent.id",
|
||||
)
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"CalendarEvent.name as tournamentName",
|
||||
"TournamentTeam.tournamentId",
|
||||
"CalendarEventDate.startTime as tournamentStartTime",
|
||||
|
|
@ -121,7 +121,7 @@ export async function findPendingSentRequests(senderId: number) {
|
|||
return db
|
||||
.selectFrom("FriendRequest")
|
||||
.innerJoin("User", "User.id", "FriendRequest.receiverId")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"FriendRequest.id",
|
||||
"FriendRequest.createdAt",
|
||||
"User.id as receiverId",
|
||||
|
|
@ -129,6 +129,7 @@ export async function findPendingSentRequests(senderId: number) {
|
|||
"User.discordId as receiverDiscordId",
|
||||
"User.discordAvatar as receiverDiscordAvatar",
|
||||
"User.customUrl as receiverCustomUrl",
|
||||
customAvatarUrl(eb).as("receiverCustomAvatarUrl"),
|
||||
])
|
||||
.where("FriendRequest.senderId", "=", senderId)
|
||||
.orderBy("FriendRequest.createdAt", "desc")
|
||||
|
|
@ -205,7 +206,7 @@ export async function findPendingReceivedRequests(receiverId: number) {
|
|||
return db
|
||||
.selectFrom("FriendRequest")
|
||||
.innerJoin("User", "User.id", "FriendRequest.senderId")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"FriendRequest.id",
|
||||
"FriendRequest.createdAt",
|
||||
"User.id as senderId",
|
||||
|
|
@ -213,6 +214,7 @@ export async function findPendingReceivedRequests(receiverId: number) {
|
|||
"User.discordId as senderDiscordId",
|
||||
"User.discordAvatar as senderDiscordAvatar",
|
||||
"User.customUrl as senderCustomUrl",
|
||||
customAvatarUrl(eb).as("senderCustomAvatarUrl"),
|
||||
])
|
||||
.where("FriendRequest.receiverId", "=", receiverId)
|
||||
.orderBy("FriendRequest.createdAt", "desc")
|
||||
|
|
@ -329,13 +331,7 @@ export async function findMutualFriends({
|
|||
eb("f2.userTwoId", "=", targetUserId),
|
||||
]),
|
||||
)
|
||||
.select([
|
||||
"User.id",
|
||||
"User.username",
|
||||
"User.discordId",
|
||||
"User.discordAvatar",
|
||||
"User.customUrl",
|
||||
])
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.execute();
|
||||
}
|
||||
|
||||
|
|
@ -374,7 +370,7 @@ export async function findFriendsByUserId(userId: number) {
|
|||
eb("Friendship.userTwoId", "=", userId),
|
||||
]),
|
||||
)
|
||||
.select([...COMMON_USER_FIELDS])
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.orderBy("User.username", "asc")
|
||||
.execute();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { SENDOUQ_LOOKING_PAGE, tournamentSubsPage } from "~/utils/urls";
|
|||
export function FriendMenu({
|
||||
discordId,
|
||||
discordAvatar,
|
||||
customAvatarUrl,
|
||||
name,
|
||||
subtitle,
|
||||
badge,
|
||||
|
|
@ -28,6 +29,7 @@ export function FriendMenu({
|
|||
}: {
|
||||
discordId: string;
|
||||
discordAvatar: string | null;
|
||||
customAvatarUrl: string | null;
|
||||
name: string;
|
||||
subtitle: string | null;
|
||||
badge: string | null;
|
||||
|
|
@ -59,7 +61,7 @@ export function FriendMenu({
|
|||
<SendouMenu
|
||||
trigger={
|
||||
<ListButton
|
||||
user={{ discordId, discordAvatar }}
|
||||
user={{ discordId, discordAvatar, customAvatarUrl }}
|
||||
subtitle={subtitle}
|
||||
badge={badge}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export const loader = async () => {
|
|||
username: friend.username,
|
||||
discordId: friend.discordId,
|
||||
discordAvatar: friend.discordAvatar,
|
||||
customAvatarUrl: friend.customAvatarUrl,
|
||||
url: userPage({
|
||||
discordId: friend.discordId,
|
||||
customUrl: friend.customUrl,
|
||||
|
|
@ -68,6 +69,7 @@ export const loader = async () => {
|
|||
username: tm.username,
|
||||
discordId: tm.discordId,
|
||||
discordAvatar: tm.discordAvatar,
|
||||
customAvatarUrl: tm.customAvatarUrl,
|
||||
url: userPage({
|
||||
discordId: tm.discordId,
|
||||
customUrl: tm.customUrl,
|
||||
|
|
@ -94,6 +96,7 @@ export const loader = async () => {
|
|||
username: req.senderUsername,
|
||||
discordId: req.senderDiscordId,
|
||||
discordAvatar: req.senderDiscordAvatar,
|
||||
customAvatarUrl: req.senderCustomAvatarUrl,
|
||||
url: userPage({
|
||||
discordId: req.senderDiscordId,
|
||||
customUrl: req.senderCustomUrl,
|
||||
|
|
@ -108,6 +111,7 @@ export const loader = async () => {
|
|||
username: req.receiverUsername,
|
||||
discordId: req.receiverDiscordId,
|
||||
discordAvatar: req.receiverDiscordAvatar,
|
||||
customAvatarUrl: req.receiverCustomAvatarUrl,
|
||||
url: userPage({
|
||||
discordId: req.receiverDiscordId,
|
||||
customUrl: req.receiverCustomUrl,
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ function IncomingRequestsSection() {
|
|||
user={{
|
||||
discordId: request.sender.discordId,
|
||||
discordAvatar: request.sender.discordAvatar,
|
||||
customAvatarUrl: request.sender.customAvatarUrl,
|
||||
}}
|
||||
size="xxsm"
|
||||
/>
|
||||
|
|
@ -120,6 +121,7 @@ function PendingRequestsSection() {
|
|||
user={{
|
||||
discordId: request.receiver.discordId,
|
||||
discordAvatar: request.receiver.discordAvatar,
|
||||
customAvatarUrl: request.receiver.customAvatarUrl,
|
||||
}}
|
||||
size="xxsm"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -381,6 +381,7 @@ function buildFirstPlacerEntry(
|
|||
const members = withMembers
|
||||
? rows.slice(0, MEMBERS_TO_SHOW).map((row) => ({
|
||||
customUrl: row.customUrl,
|
||||
customAvatarUrl: row.customAvatarUrl,
|
||||
discordAvatar: row.discordAvatar,
|
||||
discordId: row.discordId,
|
||||
id: row.id,
|
||||
|
|
|
|||
|
|
@ -83,13 +83,15 @@ function cachedLeaderboards(): Promise<{
|
|||
power: entry.power,
|
||||
name: entry.username,
|
||||
url: userPage(entry),
|
||||
avatarUrl: entry.discordAvatar
|
||||
? discordAvatarUrl({
|
||||
discordAvatar: entry.discordAvatar,
|
||||
discordId: entry.discordId,
|
||||
size: "sm",
|
||||
})
|
||||
: null,
|
||||
avatarUrl: entry.customAvatarUrl
|
||||
? entry.customAvatarUrl
|
||||
: entry.discordAvatar
|
||||
? discordAvatarUrl({
|
||||
discordAvatar: entry.discordAvatar,
|
||||
discordId: entry.discordId,
|
||||
size: "sm",
|
||||
})
|
||||
: null,
|
||||
})),
|
||||
team: team
|
||||
.filter((entry) => entry.team)
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ const PERKS = [
|
|||
name: "customizedColorsUser",
|
||||
extraInfo: false,
|
||||
},
|
||||
{
|
||||
tier: 2,
|
||||
name: "customAvatar",
|
||||
extraInfo: true,
|
||||
},
|
||||
{
|
||||
tier: 2,
|
||||
name: "favoriteBadges",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import type {
|
|||
RankedModeShort,
|
||||
} from "~/modules/in-game-lists/types";
|
||||
import {
|
||||
COMMON_USER_FIELDS,
|
||||
commonUserSelect,
|
||||
concatUserSubmittedImagePrefix,
|
||||
} from "~/utils/kysely.server";
|
||||
import { dateToDatabaseTimestamp } from "../../utils/dates";
|
||||
|
|
@ -62,7 +62,7 @@ const teamLeaderboardBySeasonQuery = (season: number) =>
|
|||
eb
|
||||
.selectFrom("SkillTeamUser")
|
||||
.innerJoin("User", "SkillTeamUser.userId", "User.id")
|
||||
.select(COMMON_USER_FIELDS)
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.whereRef("SkillTeamUser.skillId", "=", "Skill.id"),
|
||||
).as("members"),
|
||||
jsonArrayFrom(
|
||||
|
|
@ -318,8 +318,8 @@ function xpLeaderboardQuery(where?: {
|
|||
})
|
||||
.innerJoin("SplatoonPlayer", "SplatoonPlayer.id", "Placement.playerId")
|
||||
.leftJoin("User", "User.id", "SplatoonPlayer.userId")
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"Placement.entryId",
|
||||
"Placement.playerId",
|
||||
"Placement.weaponSplId",
|
||||
|
|
@ -369,8 +369,8 @@ export async function userSPLeaderboard(season: number) {
|
|||
.onRef("Latest.userId", "=", "Skill.userId")
|
||||
.onRef("Latest.maxId", "=", "Skill.id"),
|
||||
)
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"Skill.id as entryId",
|
||||
"Skill.ordinal",
|
||||
"User.plusSkippedForSeasonNth",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { db } from "~/db/sql";
|
|||
import type { DB, TablesInsertable } from "~/db/tables";
|
||||
import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import {
|
||||
COMMON_USER_FIELDS,
|
||||
commonUserSelect,
|
||||
concatUserSubmittedImagePrefix,
|
||||
userProfileWeapons,
|
||||
} from "~/utils/kysely.server";
|
||||
|
|
@ -31,7 +31,7 @@ export async function posts(user?: { id: number; plusTier: number | null }) {
|
|||
.selectFrom("User")
|
||||
.leftJoin("PlusTier", "PlusTier.userId", "User.id")
|
||||
.select(({ eb: innerEb }) => [
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(innerEb),
|
||||
"User.languages",
|
||||
"User.country",
|
||||
"PlusTier.tier as plusTier",
|
||||
|
|
@ -59,7 +59,7 @@ export async function posts(user?: { id: number; plusTier: number | null }) {
|
|||
.innerJoin("User", "User.id", "TeamMemberWithSecondary.userId")
|
||||
.leftJoin("PlusTier", "PlusTier.userId", "User.id")
|
||||
.select(({ eb: innestEb }) => [
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(innestEb),
|
||||
"User.languages",
|
||||
"User.country",
|
||||
"PlusTier.tier as plusTier",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { db } from "~/db/sql";
|
||||
import type { Tables, TablesInsertable } from "~/db/tables";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { commonUserSelect } from "~/utils/kysely.server";
|
||||
import * as StreamRanking from "../sidebar/core/StreamRanking";
|
||||
|
||||
export function replaceAll(
|
||||
|
|
@ -40,8 +40,8 @@ export function findXRankStreams() {
|
|||
StreamRanking.minXpForStreamToBeShown(),
|
||||
)
|
||||
.where("LiveStream.twitch", "is not", null)
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"SplatoonPlayer.peakXp",
|
||||
"LiveStream.viewerCount",
|
||||
"LiveStream.thumbnailUrl",
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "123",
|
||||
discordAvatar: null,
|
||||
customUrl: "sendou",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
|
|
@ -114,6 +115,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "456",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
|
|
@ -121,6 +123,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "789",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
|
|
@ -128,6 +131,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "012",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
bravo: [
|
||||
|
|
@ -137,6 +141,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "345",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
|
|
@ -144,6 +149,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "678",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
|
|
@ -151,6 +157,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "901",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
|
|
@ -158,6 +165,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "234",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
}}
|
||||
|
|
@ -195,6 +203,7 @@ export default function MatchPageTestRoute() {
|
|||
tier: { name: "LEVIATHAN", isPlus: true },
|
||||
plusTier: 1,
|
||||
weaponPool: [0, 2000, 4000],
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
|
|
@ -205,6 +214,7 @@ export default function MatchPageTestRoute() {
|
|||
tier: { name: "DIAMOND", isPlus: false },
|
||||
plusTier: 2,
|
||||
weaponPool: [20, 1100],
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
|
|
@ -213,6 +223,7 @@ export default function MatchPageTestRoute() {
|
|||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
tier: "CALCULATING",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
|
|
@ -220,6 +231,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "012",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
|
|
@ -228,6 +240,7 @@ export default function MatchPageTestRoute() {
|
|||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
tier: { name: "GOLD", isPlus: true },
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
subbedOut: [9],
|
||||
|
|
@ -244,6 +257,7 @@ export default function MatchPageTestRoute() {
|
|||
tier: { name: "PLATINUM", isPlus: false },
|
||||
plusTier: 3,
|
||||
weaponPool: [40, 3000],
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
|
|
@ -252,6 +266,7 @@ export default function MatchPageTestRoute() {
|
|||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
tier: { name: "SILVER", isPlus: true },
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
|
|
@ -259,6 +274,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "901",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
|
|
@ -267,6 +283,7 @@ export default function MatchPageTestRoute() {
|
|||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
tier: { name: "BRONZE", isPlus: false },
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -376,6 +393,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "123",
|
||||
discordAvatar: null,
|
||||
customUrl: "sendou",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
skillDifference: {
|
||||
calculated: true,
|
||||
|
|
@ -391,6 +409,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "456",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
skillDifference: {
|
||||
calculated: true,
|
||||
|
|
@ -406,6 +425,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "789",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
skillDifference: {
|
||||
calculated: false,
|
||||
|
|
@ -420,6 +440,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "012",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
skillDifference: {
|
||||
calculated: false,
|
||||
|
|
@ -444,6 +465,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "345",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
skillDifference: {
|
||||
calculated: true,
|
||||
|
|
@ -459,6 +481,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "678",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
skillDifference: {
|
||||
calculated: true,
|
||||
|
|
@ -474,6 +497,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "901",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
skillDifference: {
|
||||
calculated: true,
|
||||
|
|
@ -489,6 +513,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "234",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
skillDifference: {
|
||||
calculated: true,
|
||||
|
|
@ -523,6 +548,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "123",
|
||||
discordAvatar: null,
|
||||
customUrl: "sendou",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
|
|
@ -530,6 +556,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "456",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
|
|
@ -537,6 +564,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "789",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
|
|
@ -544,6 +572,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "012",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
bravo: [
|
||||
|
|
@ -553,6 +582,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "345",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
|
|
@ -560,6 +590,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "678",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
|
|
@ -567,6 +598,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "901",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
|
|
@ -574,6 +606,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "234",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -595,6 +628,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "123",
|
||||
discordAvatar: null,
|
||||
customUrl: "sendou",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
|
|
@ -602,6 +636,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "456",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
|
|
@ -609,6 +644,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "789",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
|
|
@ -616,6 +652,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "012",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
bravo: [
|
||||
|
|
@ -625,6 +662,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "345",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
|
|
@ -632,6 +670,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "678",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
|
|
@ -639,6 +678,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "901",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
|
|
@ -646,6 +686,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "234",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -668,6 +709,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "123",
|
||||
discordAvatar: null,
|
||||
customUrl: "sendou",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
|
|
@ -675,6 +717,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "456",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
|
|
@ -682,6 +725,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "789",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
|
|
@ -689,6 +733,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "012",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
bravo: [
|
||||
|
|
@ -698,6 +743,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "345",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
|
|
@ -705,6 +751,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "678",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
|
|
@ -712,6 +759,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "567",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
|
|
@ -719,6 +767,7 @@ export default function MatchPageTestRoute() {
|
|||
discordId: "234",
|
||||
discordAvatar: null,
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { db } from "~/db/sql";
|
|||
import type { DB } from "~/db/tables";
|
||||
import type { MonthYear } from "~/features/plus-voting/core";
|
||||
import { databaseTimestampNow, databaseTimestampToDate } from "~/utils/dates";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { commonUserSelect } from "~/utils/kysely.server";
|
||||
import type { Unwrapped } from "~/utils/types";
|
||||
|
||||
export type FindAllByMonthItem = Unwrapped<typeof findAllByMonth>;
|
||||
|
|
@ -21,15 +21,15 @@ export async function findAllByMonth(args: MonthYear) {
|
|||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.select(COMMON_USER_FIELDS)
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.whereRef("PlusSuggestion.authorId", "=", "User.id"),
|
||||
).as("author"),
|
||||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.leftJoin("PlusTier", "PlusSuggestion.suggestedId", "PlusTier.userId")
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"User.bio",
|
||||
"PlusTier.tier as plusTier",
|
||||
])
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
rangeToMonthYear,
|
||||
} from "~/features/plus-voting/core";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { commonUserSelect } from "~/utils/kysely.server";
|
||||
import type { Unwrapped } from "~/utils/types";
|
||||
import * as PlusVoting from "./core/PlusVoting";
|
||||
|
||||
|
|
@ -17,8 +17,8 @@ const resultsByMonthYearQuery = (args: MonthYear) =>
|
|||
db
|
||||
.selectFrom("PlusVotingResult")
|
||||
.innerJoin("User", "PlusVotingResult.votedId", "User.id")
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"PlusVotingResult.wasSuggested",
|
||||
"PlusVotingResult.tier",
|
||||
"PlusVotingResult.score",
|
||||
|
|
@ -136,7 +136,7 @@ export type UsersForVoting = {
|
|||
user: Pick<
|
||||
Tables["User"],
|
||||
"id" | "discordId" | "username" | "discordAvatar" | "bio"
|
||||
>;
|
||||
> & { customAvatarUrl: string | null };
|
||||
suggestion?: PlusSuggestionRepository.FindAllByMonthItem;
|
||||
}[];
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ export async function usersForVoting(loggedInUser: {
|
|||
const members = await db
|
||||
.selectFrom("User")
|
||||
.innerJoin("PlusTier", "PlusTier.userId", "User.id")
|
||||
.select([...COMMON_USER_FIELDS, "User.bio"])
|
||||
.select((eb) => [...commonUserSelect(eb), "User.bio"])
|
||||
.where("PlusTier.tier", "=", loggedInUser.plusTier)
|
||||
.execute();
|
||||
|
||||
|
|
@ -167,6 +167,7 @@ export async function usersForVoting(loggedInUser: {
|
|||
discordId: member.discordId,
|
||||
username: member.username,
|
||||
discordAvatar: member.discordAvatar,
|
||||
customAvatarUrl: member.customAvatarUrl,
|
||||
bio: member.bio,
|
||||
},
|
||||
});
|
||||
|
|
@ -179,6 +180,7 @@ export async function usersForVoting(loggedInUser: {
|
|||
discordId: suggestion.suggested.discordId,
|
||||
username: suggestion.suggested.username,
|
||||
discordAvatar: suggestion.suggested.discordAvatar,
|
||||
customAvatarUrl: suggestion.suggested.customAvatarUrl,
|
||||
bio: suggestion.suggested.bio,
|
||||
},
|
||||
suggestion,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
|||
import { ConcurrentModificationError } from "~/utils/errors";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import {
|
||||
COMMON_USER_FIELDS,
|
||||
commonUserSelect,
|
||||
concatUserSubmittedImagePrefix,
|
||||
tournamentLogoWithDefault,
|
||||
} from "~/utils/kysely.server";
|
||||
|
|
@ -153,8 +153,8 @@ const baseFindQuery = db
|
|||
eb
|
||||
.selectFrom("ScrimPostUser")
|
||||
.innerJoin("User", "ScrimPostUser.userId", "User.id")
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"User.inGameName",
|
||||
"ScrimPostUser.isOwner",
|
||||
])
|
||||
|
|
@ -186,8 +186,8 @@ const baseFindQuery = db
|
|||
innerEb
|
||||
.selectFrom("ScrimPostRequestUser")
|
||||
.innerJoin("User", "ScrimPostRequestUser.userId", "User.id")
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"User.inGameName",
|
||||
"ScrimPostRequestUser.isOwner",
|
||||
])
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { dateToDatabaseTimestamp } from "~/utils/dates";
|
|||
import { shortNanoid } from "~/utils/id";
|
||||
import invariant from "~/utils/invariant";
|
||||
import {
|
||||
COMMON_USER_FIELDS,
|
||||
commonUserSelect,
|
||||
concatUserSubmittedImagePrefix,
|
||||
matchProfileWeapons,
|
||||
tournamentLogoWithDefault,
|
||||
|
|
@ -138,7 +138,7 @@ function groupWithTeamAndMembers(
|
|||
),
|
||||
)
|
||||
.select((arrayEb) => [
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(arrayEb),
|
||||
"GroupMember.role",
|
||||
"GroupMember.note",
|
||||
"User.inGameName",
|
||||
|
|
@ -229,7 +229,7 @@ const groupMatchResultsSubQuery = (eb: ExpressionBuilder<DB, "Skill">) => {
|
|||
eb
|
||||
.selectFrom("GroupMember")
|
||||
.innerJoin("User", "GroupMember.userId", "User.id")
|
||||
.select([...COMMON_USER_FIELDS])
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.whereRef(
|
||||
"GroupMember.groupId",
|
||||
"=",
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ export function resolveTimelineSpChanges(
|
|||
discordId: m.discordId,
|
||||
discordAvatar: m.discordAvatar,
|
||||
customUrl: m.customUrl,
|
||||
customAvatarUrl: m.customAvatarUrl,
|
||||
},
|
||||
skillDifference: m.skillDifference!,
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { jsonObjectFrom } from "kysely/helpers/sqlite";
|
||||
import { db } from "~/db/sql";
|
||||
import { dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { commonUserSelect } from "~/utils/kysely.server";
|
||||
import type { Unwrapped } from "~/utils/types";
|
||||
|
||||
export type ActiveMatchPlayersItem = Unwrapped<typeof activeMatchPlayers>;
|
||||
|
|
@ -29,7 +29,7 @@ export function activeMatchPlayers() {
|
|||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.select([...COMMON_USER_FIELDS, "User.twitch"])
|
||||
.select((eb) => [...commonUserSelect(eb), "User.twitch"])
|
||||
.whereRef("GroupMember.userId", "=", "User.id"),
|
||||
).as("user"),
|
||||
])
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ import { actorId } from "~/features/auth/core/user.server";
|
|||
import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import { shortNanoid } from "~/utils/id";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { COMMON_USER_FIELDS, matchProfileWeapons } from "~/utils/kysely.server";
|
||||
import {
|
||||
commonUserSelect,
|
||||
customAvatarUrl,
|
||||
matchProfileWeapons,
|
||||
} from "~/utils/kysely.server";
|
||||
import { errorIsSqliteForeignKeyConstraintFailure } from "~/utils/sql";
|
||||
import { userIsBanned } from "../ban/core/banned.server";
|
||||
import { FULL_GROUP_SIZE } from "./q-constants";
|
||||
|
|
@ -54,6 +58,7 @@ export async function findCurrentGroups() {
|
|||
username: Tables["User"]["username"];
|
||||
discordId: Tables["User"]["discordId"];
|
||||
discordAvatar: Tables["User"]["discordAvatar"];
|
||||
customAvatarUrl: string | null;
|
||||
customUrl: Tables["User"]["customUrl"];
|
||||
pronouns: Tables["User"]["pronouns"] | null;
|
||||
mapModePreferences: Tables["User"]["mapModePreferences"];
|
||||
|
|
@ -99,6 +104,7 @@ export async function findCurrentGroups() {
|
|||
username: eb.ref("User.username"),
|
||||
discordId: eb.ref("User.discordId"),
|
||||
discordAvatar: eb.ref("User.discordAvatar"),
|
||||
customAvatarUrl: customAvatarUrl(eb),
|
||||
customUrl: eb.ref("User.customUrl"),
|
||||
mapModePreferences: eb.ref("User.mapModePreferences"),
|
||||
noScreen: eb.ref("User.noScreen"),
|
||||
|
|
@ -433,8 +439,8 @@ export async function friendsAndTeammates(userId: number) {
|
|||
const rows = await db
|
||||
.selectFrom("TeamMemberWithSecondary")
|
||||
.innerJoin("User", "User.id", "TeamMemberWithSecondary.userId")
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"User.inGameName",
|
||||
"TeamMemberWithSecondary.teamId",
|
||||
])
|
||||
|
|
@ -460,8 +466,8 @@ export async function friendsAndTeammates(userId: number) {
|
|||
]),
|
||||
),
|
||||
)
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"User.inGameName",
|
||||
sql<any>`null`.as("teamId"),
|
||||
]),
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ function createMember(overrides: Partial<SQGroupMember> = {}): SQGroupMember {
|
|||
discordId: "123456789",
|
||||
username: "TestUser",
|
||||
discordAvatar: null,
|
||||
customAvatarUrl: null,
|
||||
customUrl: null,
|
||||
role: "OWNER",
|
||||
vc: "NO",
|
||||
|
|
@ -75,6 +76,7 @@ function createOwnGroupMember(
|
|||
discordId: "123456789",
|
||||
username: "TestUser",
|
||||
discordAvatar: null,
|
||||
customAvatarUrl: null,
|
||||
customUrl: null,
|
||||
role: "OWNER",
|
||||
vc: "NO",
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export type SidebarFriend = {
|
|||
name: string;
|
||||
discordId: string;
|
||||
discordAvatar: string | null;
|
||||
customAvatarUrl: string | null;
|
||||
url: string;
|
||||
subtitle: string;
|
||||
badge: string;
|
||||
|
|
@ -191,13 +192,15 @@ async function combinedStreams(): Promise<SidebarStream[]> {
|
|||
stream: {
|
||||
id: `xrank-${row.id}`,
|
||||
name: row.username,
|
||||
imageUrl: row.discordAvatar
|
||||
? discordAvatarUrl({
|
||||
discordId: row.discordId,
|
||||
discordAvatar: row.discordAvatar,
|
||||
size: "sm",
|
||||
})
|
||||
: BLANK_IMAGE_URL,
|
||||
imageUrl: row.customAvatarUrl
|
||||
? row.customAvatarUrl
|
||||
: row.discordAvatar
|
||||
? discordAvatarUrl({
|
||||
discordId: row.discordId,
|
||||
discordAvatar: row.discordAvatar,
|
||||
size: "sm",
|
||||
})
|
||||
: BLANK_IMAGE_URL,
|
||||
url: row.twitchUsername
|
||||
? twitchUrl(row.twitchUsername)
|
||||
: userPage({ discordId: row.discordId, customUrl: row.customUrl }),
|
||||
|
|
@ -365,6 +368,7 @@ function rowToSidebarFriend(
|
|||
name: row.username,
|
||||
discordId: row.discordId,
|
||||
discordAvatar: row.discordAvatar,
|
||||
customAvatarUrl: row.customAvatarUrl,
|
||||
url: userPage({ discordId: row.discordId, customUrl: row.customUrl }),
|
||||
subtitle,
|
||||
badge,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { databaseTimestampNow } from "~/utils/dates";
|
|||
import { shortNanoid } from "~/utils/id";
|
||||
import invariant from "~/utils/invariant";
|
||||
import {
|
||||
COMMON_USER_FIELDS,
|
||||
commonUserSelect,
|
||||
concatUserSubmittedImagePrefix,
|
||||
tournamentLogoOrNull,
|
||||
userProfileWeapons,
|
||||
|
|
@ -175,7 +175,7 @@ export function findByCustomUrl(
|
|||
.selectFrom("TeamMemberWithSecondary")
|
||||
.innerJoin("User", "User.id", "TeamMemberWithSecondary.userId")
|
||||
.select(({ eb: innerEb }) => [
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(innerEb),
|
||||
"TeamMemberWithSecondary.role",
|
||||
"TeamMemberWithSecondary.customRole",
|
||||
"TeamMemberWithSecondary.roleType",
|
||||
|
|
@ -274,7 +274,7 @@ export async function findResultsById(teamId: number) {
|
|||
)
|
||||
.innerJoin("User", "User.id", "TournamentResult.userId")
|
||||
.whereRef("results2.tournamentId", "=", "results.tournamentId")
|
||||
.select(COMMON_USER_FIELDS),
|
||||
.select((eb) => commonUserSelect(eb)),
|
||||
).as("participants"),
|
||||
])
|
||||
.orderBy("CalendarEventDate.startTime", "desc")
|
||||
|
|
@ -320,7 +320,7 @@ export async function teamsByMemberUserId(
|
|||
eb
|
||||
.selectFrom("TeamMemberWithSecondary as m2")
|
||||
.innerJoin("User", "User.id", "m2.userId")
|
||||
.select([...COMMON_USER_FIELDS, "m2.role", "m2.roleType"])
|
||||
.select((eb) => [...commonUserSelect(eb), "m2.role", "m2.roleType"])
|
||||
.whereRef("TeamMemberWithSecondary.teamId", "=", "m2.teamId"),
|
||||
).as("members"),
|
||||
])
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ const createMember = (userId: number) =>
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
}) as const;
|
||||
|
||||
const createTestTournament = (
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ describe("tournamentSummary()", () => {
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
})),
|
||||
name: `Team ${teamId}`,
|
||||
prefersNotToHost: 0,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -336,6 +336,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
discordId: "308483655515373570",
|
||||
discordAvatar: "a5fff2b4706d99364e646cab28c8085b",
|
||||
customUrl: "puma",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
staff: [
|
||||
{
|
||||
|
|
@ -346,6 +347,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
discordAvatar: "2a569302e9545c6a07f8f8aa337d139d",
|
||||
customUrl: "penis",
|
||||
role: "ORGANIZER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 3147,
|
||||
|
|
@ -355,6 +357,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
discordAvatar: "85090cfe2e0da693355bcec9740c1eaa",
|
||||
customUrl: "cookie",
|
||||
role: "ORGANIZER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 5212,
|
||||
|
|
@ -364,6 +367,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
discordAvatar: "bd634c91f7d0475f3671956fa9a2110a",
|
||||
customUrl: null,
|
||||
role: "ORGANIZER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
id: 23120,
|
||||
|
|
@ -373,6 +377,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
discordAvatar: "f1191c94b1da5396a06b620408017c1f",
|
||||
customUrl: "weizihao",
|
||||
role: "ORGANIZER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
bracketProgressionOverrides: [],
|
||||
|
|
@ -406,6 +411,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "OWNER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 2899,
|
||||
|
|
@ -422,6 +428,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 6114,
|
||||
|
|
@ -438,6 +445,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 33963,
|
||||
|
|
@ -454,6 +462,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 30176,
|
||||
|
|
@ -470,6 +479,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
checkIns: [
|
||||
|
|
@ -517,6 +527,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "OWNER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 21689,
|
||||
|
|
@ -533,6 +544,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 3147,
|
||||
|
|
@ -549,6 +561,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 2072,
|
||||
|
|
@ -565,6 +578,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
checkIns: [
|
||||
|
|
@ -607,6 +621,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "OWNER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 13370,
|
||||
|
|
@ -623,6 +638,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 45,
|
||||
|
|
@ -639,6 +655,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 1843,
|
||||
|
|
@ -655,6 +672,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
checkIns: [
|
||||
|
|
@ -697,6 +715,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "OWNER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 13590,
|
||||
|
|
@ -713,6 +732,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 10757,
|
||||
|
|
@ -729,6 +749,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 33047,
|
||||
|
|
@ -745,6 +766,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 41024,
|
||||
|
|
@ -761,6 +783,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
checkIns: [
|
||||
|
|
@ -808,6 +831,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "OWNER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 29665,
|
||||
|
|
@ -824,6 +848,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 46006,
|
||||
|
|
@ -840,6 +865,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 33483,
|
||||
|
|
@ -856,6 +882,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 11780,
|
||||
|
|
@ -872,6 +899,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 37901,
|
||||
|
|
@ -888,6 +916,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
checkIns: [
|
||||
|
|
@ -930,6 +959,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "OWNER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 43662,
|
||||
|
|
@ -946,6 +976,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 33491,
|
||||
|
|
@ -962,6 +993,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 46467,
|
||||
|
|
@ -978,6 +1010,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 46813,
|
||||
|
|
@ -994,6 +1027,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
checkIns: [
|
||||
|
|
@ -1041,6 +1075,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "OWNER",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 33611,
|
||||
|
|
@ -1057,6 +1092,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 31148,
|
||||
|
|
@ -1073,6 +1109,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
{
|
||||
userId: 33578,
|
||||
|
|
@ -1089,6 +1126,7 @@ export const ZONES_WEEKLY_38 = (): TournamentData => ({
|
|||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
role: "REGULAR",
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
checkIns: [
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -97,6 +97,7 @@ export const testTournament = ({
|
|||
teams: nTeams(participant.length, Math.min(...participant)),
|
||||
author: {
|
||||
customUrl: null,
|
||||
customAvatarUrl: null,
|
||||
discordAvatar: null,
|
||||
discordId: "123",
|
||||
username: "test",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { shortNanoid } from "~/utils/id";
|
|||
import invariant from "~/utils/invariant";
|
||||
import {
|
||||
concatUserSubmittedImagePrefix,
|
||||
customAvatarUrl,
|
||||
matchProfileWeapons,
|
||||
} from "~/utils/kysely.server";
|
||||
import { errorIsSqliteForeignKeyConstraintFailure } from "~/utils/sql";
|
||||
|
|
@ -64,6 +65,7 @@ type TournamentLFGMemberObject = {
|
|||
username: Tables["User"]["username"];
|
||||
discordId: Tables["User"]["discordId"];
|
||||
discordAvatar: Tables["User"]["discordAvatar"];
|
||||
customAvatarUrl: string | null;
|
||||
customUrl: Tables["User"]["customUrl"];
|
||||
languages: Tables["User"]["languages"];
|
||||
vc: Tables["User"]["vc"];
|
||||
|
|
@ -108,6 +110,7 @@ export async function findLookingTeamsByTournamentId(tournamentId: number) {
|
|||
username: eb.ref("User.username"),
|
||||
discordId: eb.ref("User.discordId"),
|
||||
discordAvatar: eb.ref("User.discordAvatar"),
|
||||
customAvatarUrl: customAvatarUrl(eb),
|
||||
customUrl: eb.ref("User.customUrl"),
|
||||
languages: eb.ref("User.languages"),
|
||||
vc: eb.ref("User.vc"),
|
||||
|
|
@ -147,6 +150,7 @@ export async function findSubGroups(tournamentId: number) {
|
|||
username: eb.ref("User.username"),
|
||||
discordId: eb.ref("User.discordId"),
|
||||
discordAvatar: eb.ref("User.discordAvatar"),
|
||||
customAvatarUrl: customAvatarUrl(eb),
|
||||
customUrl: eb.ref("User.customUrl"),
|
||||
languages: eb.ref("User.languages"),
|
||||
vc: eb.ref("User.vc"),
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export type LFGGroupMember = {
|
|||
username: string;
|
||||
discordId: string;
|
||||
discordAvatar: string | null;
|
||||
customAvatarUrl: string | null;
|
||||
customUrl: string | null;
|
||||
languages: string[];
|
||||
vc: "YES" | "NO" | "LISTEN_ONLY" | null;
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ async function subsMode({
|
|||
username: member.username,
|
||||
discordId: member.discordId,
|
||||
discordAvatar: member.discordAvatar,
|
||||
customAvatarUrl: member.customAvatarUrl,
|
||||
customUrl: member.customUrl,
|
||||
vc: member.vc,
|
||||
languages,
|
||||
|
|
@ -160,6 +161,7 @@ async function resolveOwnTeam({
|
|||
username: m.username,
|
||||
discordId: m.discordId,
|
||||
discordAvatar: m.discordAvatar,
|
||||
customAvatarUrl: m.customAvatarUrl,
|
||||
customUrl: m.customUrl,
|
||||
languages: [],
|
||||
vc: null,
|
||||
|
|
@ -200,6 +202,7 @@ function transformMembers(
|
|||
username: m.username,
|
||||
discordId: m.discordId,
|
||||
discordAvatar: m.discordAvatar,
|
||||
customAvatarUrl: m.customAvatarUrl,
|
||||
customUrl: m.customUrl,
|
||||
languages,
|
||||
vc: m.vc,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { db } from "~/db/sql";
|
|||
import { TournamentMatchStatus, type TournamentRoundMaps } from "~/db/tables";
|
||||
import type { ModeShort, StageId } from "~/modules/in-game-lists/types";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { customAvatarUrl } from "~/utils/kysely.server";
|
||||
import type { Unwrapped } from "~/utils/types";
|
||||
|
||||
const opponentOneId = sql<number>`"TournamentMatch"."opponentOne" ->> '$.id'`;
|
||||
|
|
@ -52,7 +53,7 @@ export async function findMatchById(id: number) {
|
|||
eb
|
||||
.selectFrom("TournamentTeamMember")
|
||||
.innerJoin("User", "User.id", "TournamentTeamMember.userId")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"User.id",
|
||||
"User.username",
|
||||
"TournamentTeamMember.tournamentTeamId",
|
||||
|
|
@ -65,6 +66,7 @@ export async function findMatchById(id: number) {
|
|||
"User.customUrl",
|
||||
"User.discordAvatar",
|
||||
"User.pronouns",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
])
|
||||
.where(({ or, eb: innerEb }) =>
|
||||
or([
|
||||
|
|
@ -405,12 +407,13 @@ export function findByTournamentTeamId(tournamentTeamId: number) {
|
|||
"otherTeam.id",
|
||||
),
|
||||
)
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"User.id",
|
||||
"User.username",
|
||||
"User.discordAvatar",
|
||||
"User.discordId",
|
||||
"User.customUrl",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
])
|
||||
.whereRef(
|
||||
"TournamentMatchGameResult.matchId",
|
||||
|
|
|
|||
|
|
@ -223,12 +223,14 @@ function buildSetEndingData({
|
|||
discordId: string;
|
||||
discordAvatar: string | null;
|
||||
customUrl: string | null;
|
||||
customAvatarUrl: string | null;
|
||||
}): CommonUser => ({
|
||||
id: m.userId,
|
||||
username: m.username,
|
||||
discordId: m.discordId,
|
||||
discordAvatar: m.discordAvatar,
|
||||
customUrl: m.customUrl,
|
||||
customAvatarUrl: m.customAvatarUrl,
|
||||
});
|
||||
|
||||
const teamOneMembersMap = new Map(
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ function resolveTimelineMaps(
|
|||
discordId: u.discordId,
|
||||
discordAvatar: u.discordAvatar,
|
||||
customUrl: u.customUrl,
|
||||
customAvatarUrl: u.customAvatarUrl,
|
||||
}));
|
||||
|
||||
return data.results.map((result, mapIndex) => {
|
||||
|
|
@ -398,6 +399,7 @@ function TournamentMatchRosterTab({
|
|||
discordId: m.discordId,
|
||||
discordAvatar: m.discordAvatar,
|
||||
customUrl: m.customUrl,
|
||||
customAvatarUrl: m.customAvatarUrl,
|
||||
inGameName: m.inGameName,
|
||||
})),
|
||||
subbedOut,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@ import {
|
|||
dateToDatabaseTimestamp,
|
||||
} from "~/utils/dates";
|
||||
import {
|
||||
COMMON_USER_FIELDS,
|
||||
commonUserSelect,
|
||||
concatUserSubmittedImagePrefix,
|
||||
customAvatarUrl,
|
||||
tournamentLogoWithDefault,
|
||||
} from "~/utils/kysely.server";
|
||||
import { mySlugify } from "~/utils/urls";
|
||||
|
|
@ -74,10 +75,10 @@ export async function findBySlug(slug: string) {
|
|||
eb
|
||||
.selectFrom("TournamentOrganizationMember")
|
||||
.innerJoin("User", "User.id", "TournamentOrganizationMember.userId")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"TournamentOrganizationMember.role",
|
||||
"TournamentOrganizationMember.roleDisplayName",
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
])
|
||||
.whereRef(
|
||||
"TournamentOrganizationMember.organizationId",
|
||||
|
|
@ -250,7 +251,11 @@ const findEventsBaseQuery = (organizationId: number) =>
|
|||
innerEb
|
||||
.selectFrom("TournamentResult as WinnerResult")
|
||||
.innerJoin("User", "User.id", "WinnerResult.userId")
|
||||
.select(["User.discordAvatar", "User.discordId"])
|
||||
.select((winnerEb) => [
|
||||
"User.discordAvatar",
|
||||
"User.discordId",
|
||||
customAvatarUrl(winnerEb).as("customAvatarUrl"),
|
||||
])
|
||||
.whereRef(
|
||||
"WinnerResult.tournamentTeamId",
|
||||
"=",
|
||||
|
|
@ -284,7 +289,11 @@ const findEventsBaseQuery = (organizationId: number) =>
|
|||
"User.id",
|
||||
"CalendarEventResultPlayer.userId",
|
||||
)
|
||||
.select(["User.discordAvatar", "User.discordId"])
|
||||
.select((playerEb) => [
|
||||
"User.discordAvatar",
|
||||
"User.discordId",
|
||||
customAvatarUrl(playerEb).as("customAvatarUrl"),
|
||||
])
|
||||
.whereRef(
|
||||
"CalendarEventResultPlayer.teamId",
|
||||
"=",
|
||||
|
|
@ -617,11 +626,11 @@ export function allBannedUsersByOrganizationId(organizationId: number) {
|
|||
return db
|
||||
.selectFrom("TournamentOrganizationBannedUser")
|
||||
.innerJoin("User", "User.id", "TournamentOrganizationBannedUser.userId")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"TournamentOrganizationBannedUser.privateNote",
|
||||
"TournamentOrganizationBannedUser.updatedAt",
|
||||
"TournamentOrganizationBannedUser.expiresAt",
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
])
|
||||
.where(
|
||||
"TournamentOrganizationBannedUser.organizationId",
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ async function calendarEventPoints(
|
|||
leaderboardInfo.set(player.id, {
|
||||
user: {
|
||||
customUrl: player.customUrl,
|
||||
customAvatarUrl: player.customAvatarUrl,
|
||||
discordAvatar: player.discordAvatar,
|
||||
discordId: player.discordId!,
|
||||
id: player.id,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { db } from "~/db/sql";
|
|||
import type { DB, Tables, TournamentAuditLogMetadata } from "~/db/tables";
|
||||
import { actorId } from "~/features/auth/core/user.server";
|
||||
import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
|
||||
import { commonUserSelect } from "~/utils/kysely.server";
|
||||
|
||||
export const AUDIT_LOG_PAGE_SIZE = 30;
|
||||
|
||||
|
|
@ -138,13 +138,13 @@ export function findByTournamentId({
|
|||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.select(COMMON_USER_FIELDS)
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.whereRef("User.id", "=", "TournamentAuditLog.actorUserId"),
|
||||
).as("actor"),
|
||||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.select(COMMON_USER_FIELDS)
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.whereRef("User.id", "=", "TournamentAuditLog.subjectUserId"),
|
||||
).as("subject"),
|
||||
jsonObjectFrom(
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
|||
import { shortNanoid } from "~/utils/id";
|
||||
import invariant from "~/utils/invariant";
|
||||
import {
|
||||
COMMON_USER_FIELDS,
|
||||
commonUserSelect,
|
||||
concatUserSubmittedImagePrefix,
|
||||
customAvatarUrl,
|
||||
tournamentLogoWithDefault,
|
||||
} from "~/utils/kysely.server";
|
||||
import type { Unwrapped } from "~/utils/types";
|
||||
|
|
@ -95,10 +96,10 @@ export async function findById(id: number) {
|
|||
"TournamentOrganizationMember.userId",
|
||||
"User.id",
|
||||
)
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"TournamentOrganizationMember.userId",
|
||||
"TournamentOrganizationMember.role",
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
"User.pronouns",
|
||||
])
|
||||
.whereRef(
|
||||
|
|
@ -128,15 +129,15 @@ export async function findById(id: number) {
|
|||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.select([...COMMON_USER_FIELDS, "User.pronouns"])
|
||||
.select((eb) => [...commonUserSelect(eb), "User.pronouns"])
|
||||
.whereRef("User.id", "=", "CalendarEvent.authorId"),
|
||||
).as("author"),
|
||||
jsonArrayFrom(
|
||||
eb
|
||||
.selectFrom("TournamentStaff")
|
||||
.innerJoin("User", "TournamentStaff.userId", "User.id")
|
||||
.select([
|
||||
...COMMON_USER_FIELDS,
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"User.pronouns",
|
||||
"TournamentStaff.role",
|
||||
])
|
||||
|
|
@ -194,7 +195,7 @@ export async function findById(id: number) {
|
|||
)
|
||||
.leftJoin("PlusTier", "PlusTier.userId", "User.id")
|
||||
.leftJoin("LiveStream", "LiveStream.userId", "User.id")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"User.id as userId",
|
||||
"User.username",
|
||||
"User.discordId",
|
||||
|
|
@ -213,6 +214,7 @@ export async function findById(id: number) {
|
|||
"LiveStream.twitch as streamTwitch",
|
||||
"LiveStream.viewerCount as streamViewerCount",
|
||||
"LiveStream.thumbnailUrl as streamThumbnailUrl",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
])
|
||||
.whereRef(
|
||||
"TournamentTeamMember.tournamentTeamId",
|
||||
|
|
@ -584,7 +586,7 @@ export function forShowcase() {
|
|||
.whereRef("TournamentResult.tournamentId", "=", "Tournament.id")
|
||||
.where("TournamentResult.placement", "=", 1)
|
||||
.select((eb) => [
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
"User.country",
|
||||
"TournamentResult.div",
|
||||
"TournamentTeam.name as teamName",
|
||||
|
|
@ -665,7 +667,7 @@ export function topThreeResultsByTournamentId(tournamentId: number) {
|
|||
jsonObjectFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.select([...COMMON_USER_FIELDS])
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.whereRef("User.id", "=", "TournamentResult.userId"),
|
||||
).as("user"),
|
||||
])
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export interface PlayedSet {
|
|||
Pick<
|
||||
Tables["User"],
|
||||
"id" | "username" | "discordAvatar" | "discordId" | "customUrl"
|
||||
>
|
||||
> & { customAvatarUrl: string | null }
|
||||
>;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { ExpressionBuilder, FunctionModule, NotNull } from "kysely";
|
||||
import type { ExpressionBuilder, NotNull } from "kysely";
|
||||
import { sql } from "kysely";
|
||||
import { jsonArrayFrom } from "kysely/helpers/sqlite";
|
||||
import * as R from "remeda";
|
||||
|
|
@ -17,8 +17,9 @@ import { isSupporter } from "~/modules/permissions/utils";
|
|||
import { databaseTimestampNow, dateToDatabaseTimestamp } from "~/utils/dates";
|
||||
import invariant from "~/utils/invariant";
|
||||
import {
|
||||
COMMON_USER_FIELDS,
|
||||
commonUserSelect,
|
||||
concatUserSubmittedImagePrefix,
|
||||
customAvatarUrl,
|
||||
tournamentLogoOrNull,
|
||||
userChatNameHue,
|
||||
userProfileWeapons,
|
||||
|
|
@ -87,7 +88,7 @@ export function findLayoutDataByIdentifier(
|
|||
return identifierToUserIdQuery(identifier)
|
||||
.leftJoin("PlusTier", "PlusTier.userId", "User.id")
|
||||
.select((eb) => [
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
"User.pronouns",
|
||||
"User.country",
|
||||
"User.inGameName",
|
||||
|
|
@ -182,6 +183,8 @@ export async function findProfileByIdentifier(
|
|||
"User.patronTier",
|
||||
"PlusTier.tier as plusTier",
|
||||
"User.pronouns",
|
||||
"User.customAvatarImgId",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
userProfileWeapons(eb).as("weapons"),
|
||||
jsonArrayFrom(
|
||||
eb
|
||||
|
|
@ -380,7 +383,7 @@ export function findByFriendCode(friendCode: string) {
|
|||
return db
|
||||
.selectFrom("UserFriendCode")
|
||||
.innerJoin("User", "User.id", "UserFriendCode.userId")
|
||||
.select([...COMMON_USER_FIELDS])
|
||||
.select((eb) => commonUserSelect(eb))
|
||||
.where("UserFriendCode.friendCode", "=", friendCode)
|
||||
.execute();
|
||||
}
|
||||
|
|
@ -391,7 +394,7 @@ export async function findLeanById(id: number) {
|
|||
.leftJoin("PlusTier", "PlusTier.userId", "User.id")
|
||||
.where("User.id", "=", id)
|
||||
.select(({ eb }) => [
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
"User.customTheme",
|
||||
"User.isArtist",
|
||||
"User.isVideoAdder",
|
||||
|
|
@ -439,11 +442,11 @@ export function findModInfoById(id: number) {
|
|||
eb
|
||||
.selectFrom("ModNote")
|
||||
.innerJoin("User", "User.id", "ModNote.authorId")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"ModNote.id as noteId",
|
||||
"ModNote.text",
|
||||
"ModNote.createdAt",
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
])
|
||||
.where("ModNote.isDeleted", "=", 0)
|
||||
.where("ModNote.userId", "=", id)
|
||||
|
|
@ -453,11 +456,11 @@ export function findModInfoById(id: number) {
|
|||
eb
|
||||
.selectFrom("BanLog")
|
||||
.innerJoin("User", "User.id", "BanLog.bannedByUserId")
|
||||
.select([
|
||||
.select((eb) => [
|
||||
"BanLog.banned",
|
||||
"BanLog.bannedReason",
|
||||
"BanLog.createdAt",
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
])
|
||||
.where("BanLog.userId", "=", id)
|
||||
.orderBy("BanLog.createdAt", "desc"),
|
||||
|
|
@ -492,14 +495,7 @@ export function findAllPlusServerMembers() {
|
|||
export async function findChatUsersByUserIds(userIds: number[]) {
|
||||
const users = await db
|
||||
.selectFrom("User")
|
||||
.select([
|
||||
"User.id",
|
||||
"User.discordId",
|
||||
"User.discordAvatar",
|
||||
"User.username",
|
||||
"User.pronouns",
|
||||
userChatNameHue,
|
||||
])
|
||||
.select((eb) => [...commonUserSelect(eb), "User.pronouns", userChatNameHue])
|
||||
.where("User.id", "in", userIds)
|
||||
.execute();
|
||||
|
||||
|
|
@ -601,7 +597,10 @@ export function findResultsByUserId(
|
|||
eb
|
||||
.selectFrom("CalendarEventResultPlayer")
|
||||
.leftJoin("User", "User.id", "CalendarEventResultPlayer.userId")
|
||||
.select([...COMMON_USER_FIELDS, "CalendarEventResultPlayer.name"])
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
"CalendarEventResultPlayer.name",
|
||||
])
|
||||
.whereRef(
|
||||
"CalendarEventResultPlayer.teamId",
|
||||
"=",
|
||||
|
|
@ -636,7 +635,10 @@ export function findResultsByUserId(
|
|||
eb
|
||||
.selectFrom("TournamentResult as TournamentResult2")
|
||||
.innerJoin("User", "User.id", "TournamentResult2.userId")
|
||||
.select([...COMMON_USER_FIELDS, sql<string | null>`null`.as("name")])
|
||||
.select((eb) => [
|
||||
...commonUserSelect(eb),
|
||||
sql<string | null>`null`.as("name"),
|
||||
])
|
||||
.whereRef(
|
||||
"TournamentResult2.tournamentTeamId",
|
||||
"=",
|
||||
|
|
@ -777,16 +779,18 @@ export async function findResultPlacementsByUserId(userId: number) {
|
|||
];
|
||||
}
|
||||
|
||||
const searchSelectedFields = ({ fn }: { fn: FunctionModule<DB, "User"> }) =>
|
||||
const searchSelectedFields = (eb: ExpressionBuilder<DB, "User">) =>
|
||||
[
|
||||
...COMMON_USER_FIELDS,
|
||||
...commonUserSelect(eb),
|
||||
"User.inGameName",
|
||||
"PlusTier.tier as plusTier",
|
||||
fn<string | null>("iif", [
|
||||
"User.showDiscordUniqueName",
|
||||
"User.discordUniqueName",
|
||||
sql`null`,
|
||||
]).as("discordUniqueName"),
|
||||
eb
|
||||
.fn<string | null>("iif", [
|
||||
"User.showDiscordUniqueName",
|
||||
"User.discordUniqueName",
|
||||
sql`null`,
|
||||
])
|
||||
.as("discordUniqueName"),
|
||||
] as const;
|
||||
export async function search({
|
||||
query,
|
||||
|
|
@ -1069,12 +1073,31 @@ type UpdateProfileArgs = Pick<
|
|||
> & {
|
||||
weapons: Pick<TablesInsertable["UserWeapon"], "weaponSplId" | "isFavorite">[];
|
||||
favoriteBadgeIds?: number[] | null;
|
||||
customAvatarImgId?: number | null;
|
||||
};
|
||||
export function updateOwnProfile(args: UpdateProfileArgs) {
|
||||
const userId = actorId();
|
||||
return db.transaction().execute(async (trx) => {
|
||||
await trx.deleteFrom("UserWeapon").where("userId", "=", userId).execute();
|
||||
|
||||
// a removed or replaced custom avatar is no longer referenced by anything,
|
||||
// so its submitted image row is cleaned up
|
||||
const current = await trx
|
||||
.selectFrom("User")
|
||||
.select("User.customAvatarImgId")
|
||||
.where("id", "=", userId)
|
||||
.executeTakeFirst();
|
||||
if (
|
||||
current?.customAvatarImgId &&
|
||||
current.customAvatarImgId !== args.customAvatarImgId
|
||||
) {
|
||||
await trx
|
||||
.deleteFrom("UnvalidatedUserSubmittedImage")
|
||||
.where("id", "=", current.customAvatarImgId)
|
||||
.where("UnvalidatedUserSubmittedImage.submitterUserId", "=", userId)
|
||||
.execute();
|
||||
}
|
||||
|
||||
if (args.weapons.length > 0) {
|
||||
await trx
|
||||
.insertInto("UserWeapon")
|
||||
|
|
@ -1109,6 +1132,7 @@ export function updateOwnProfile(args: UpdateProfileArgs) {
|
|||
commissionsOpen: args.commissionsOpen,
|
||||
commissionsOpenedAt:
|
||||
args.commissionsOpen === 1 ? databaseTimestampNow() : null,
|
||||
customAvatarImgId: args.customAvatarImgId ?? null,
|
||||
})
|
||||
.where("id", "=", userId)
|
||||
.returning(["User.id", "User.customUrl", "User.discordId"])
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@ import { BADGE } from "~/features/badges/badges-constants";
|
|||
import * as TournamentTeamRepository from "~/features/tournament/TournamentTeamRepository.server";
|
||||
import { clearTournamentDataCache } from "~/features/tournament-bracket/core/Tournament.server";
|
||||
import * as UserRepository from "~/features/user-page/UserRepository.server";
|
||||
import { parseFormData } from "~/form/parse.server";
|
||||
import { parseFormDataWithImages } from "~/form/parse.server";
|
||||
import { userPage } from "~/utils/urls";
|
||||
import { userEditProfileSchemaServer } from "../user-page-schemas.server";
|
||||
import { userEditProfileBaseSchema } from "../user-page-schemas";
|
||||
|
||||
export const action: ActionFunction = async ({ request }) => {
|
||||
const user = requireUser();
|
||||
|
||||
const result = await parseFormData({
|
||||
const result = await parseFormDataWithImages({
|
||||
request,
|
||||
schema: userEditProfileSchemaServer,
|
||||
schema: userEditProfileBaseSchema,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
|
|
@ -22,6 +22,17 @@ export const action: ActionFunction = async ({ request }) => {
|
|||
|
||||
const data = result.data;
|
||||
|
||||
if (data.customUrl) {
|
||||
const existingUser = await UserRepository.findByCustomUrl(data.customUrl);
|
||||
if (existingUser && existingUser.id !== user.id) {
|
||||
return {
|
||||
fieldErrors: {
|
||||
customUrl: "forms:errors.profileCustomUrlDuplicate",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const [subjectPronoun, objectPronoun] = data.pronouns ?? [null, null];
|
||||
const pronouns =
|
||||
subjectPronoun && objectPronoun
|
||||
|
|
@ -58,6 +69,7 @@ export const action: ActionFunction = async ({ request }) => {
|
|||
showDiscordUniqueName: data.showDiscordUniqueName ? 1 : 0,
|
||||
commissionsOpen: isArtist && data.commissionsOpen ? 1 : 0,
|
||||
commissionText: isArtist ? data.commissionText : null,
|
||||
customAvatarImgId: isSupporter ? data.customAvatar : null,
|
||||
});
|
||||
|
||||
await UserRepository.updateOwnPreferences({
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const DEFAULT_FIELDS = {
|
|||
commissionsOpen: false,
|
||||
commissionText: null,
|
||||
country: "FI",
|
||||
customAvatar: null,
|
||||
customName: null,
|
||||
customUrl: null,
|
||||
favoriteBadgeIds: [],
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Link, useLoaderData, useMatches } from "react-router";
|
|||
import { FormMessage } from "~/components/FormMessage";
|
||||
import { FriendCodePopover } from "~/components/FriendCodePopover";
|
||||
import { BADGE } from "~/features/badges/badges-constants";
|
||||
import { existingImage } from "~/form/image-field";
|
||||
import { SendouForm } from "~/form/SendouForm";
|
||||
import { useHydrated } from "~/hooks/useHydrated";
|
||||
import { useHasRole } from "~/modules/permissions/hooks";
|
||||
|
|
@ -41,6 +42,10 @@ export default function UserEditPage() {
|
|||
}));
|
||||
|
||||
const defaultValues = {
|
||||
customAvatar: existingImage(
|
||||
data.user.customAvatarImgId,
|
||||
data.user.customAvatarUrl,
|
||||
),
|
||||
customName: data.user.customName ?? "",
|
||||
customUrl: layoutData.user.customUrl ?? "",
|
||||
inGameName: data.user.inGameName ?? "",
|
||||
|
|
@ -66,12 +71,14 @@ export default function UserEditPage() {
|
|||
schema={userEditProfileBaseSchema}
|
||||
defaultValues={defaultValues}
|
||||
submitButtonText={t("common:actions.save")}
|
||||
revalidateRoot
|
||||
>
|
||||
{({ FormField }) => (
|
||||
<>
|
||||
<FriendCodePopover />
|
||||
<FormField name="customName" />
|
||||
<FormField name="customUrl" />
|
||||
<FormField name="customAvatar" disabled={!isSupporter} />
|
||||
<FormField name="inGameName" />
|
||||
<FormField name="sensitivity" />
|
||||
<FormField name="pronouns" />
|
||||
|
|
|
|||
|
|
@ -46,7 +46,17 @@ export const handle: SendouRouteHandle = {
|
|||
|
||||
if (!data) return [];
|
||||
|
||||
if (!data.user.discordAvatar) {
|
||||
const imgPath = data.user.customAvatarUrl
|
||||
? data.user.customAvatarUrl
|
||||
: data.user.discordAvatar
|
||||
? discordAvatarUrl({
|
||||
discordId: data.user.discordId,
|
||||
discordAvatar: data.user.discordAvatar,
|
||||
size: "sm",
|
||||
})
|
||||
: null;
|
||||
|
||||
if (!imgPath) {
|
||||
return {
|
||||
text: data.user.username,
|
||||
href: userPage(data.user),
|
||||
|
|
@ -55,11 +65,7 @@ export const handle: SendouRouteHandle = {
|
|||
}
|
||||
|
||||
return {
|
||||
imgPath: discordAvatarUrl({
|
||||
discordId: data.user.discordId,
|
||||
discordAvatar: data.user.discordAvatar,
|
||||
size: "sm",
|
||||
}),
|
||||
imgPath,
|
||||
href: userPage(data.user),
|
||||
type: "IMAGE",
|
||||
text: data.user.username,
|
||||
|
|
|
|||
|
|
@ -1,29 +1,6 @@
|
|||
import { z } from "zod";
|
||||
import { requireUser } from "~/features/auth/core/user.server";
|
||||
import * as BuildRepository from "~/features/builds/BuildRepository.server";
|
||||
import * as UserRepository from "./UserRepository.server";
|
||||
import {
|
||||
gearAllOrNoneRefine,
|
||||
newBuildBaseSchema,
|
||||
userEditProfileBaseSchema,
|
||||
} from "./user-page-schemas";
|
||||
|
||||
export const userEditProfileSchemaServer =
|
||||
userEditProfileBaseSchema.superRefine(async (data, ctx) => {
|
||||
if (!data.customUrl) return;
|
||||
|
||||
const existingUser = await UserRepository.findByCustomUrl(data.customUrl);
|
||||
if (!existingUser) return;
|
||||
|
||||
const currentUser = requireUser();
|
||||
if (existingUser.id === currentUser.id) return;
|
||||
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "forms:errors.profileCustomUrlDuplicate",
|
||||
path: ["customUrl"],
|
||||
});
|
||||
});
|
||||
import { gearAllOrNoneRefine, newBuildBaseSchema } from "./user-page-schemas";
|
||||
|
||||
export const newBuildSchemaServer = newBuildBaseSchema
|
||||
.refine(gearAllOrNoneRefine.fn, gearAllOrNoneRefine.opts)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
customField,
|
||||
dualSelectOptional,
|
||||
idConstantOptional,
|
||||
image,
|
||||
selectDynamicOptional,
|
||||
stringConstant,
|
||||
textAreaOptional,
|
||||
|
|
@ -61,6 +62,11 @@ const SENS_ITEMS = [
|
|||
}));
|
||||
|
||||
export const userEditProfileBaseSchema = z.object({
|
||||
customAvatar: image({
|
||||
label: "labels.profileCustomAvatar",
|
||||
bottomText: "bottomTexts.profileCustomAvatar",
|
||||
autoValidate: true,
|
||||
}),
|
||||
customName: textFieldOptional({
|
||||
label: "labels.profileCustomName",
|
||||
bottomText: "bottomTexts.profileCustomName",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,11 @@ import {
|
|||
dayMonthYearToDatabaseTimestamp,
|
||||
} from "~/utils/dates";
|
||||
import invariant from "~/utils/invariant";
|
||||
import { type CommonUser, commonUserJsonObject } from "~/utils/kysely.server";
|
||||
import {
|
||||
type CommonUser,
|
||||
commonUserJsonObject,
|
||||
commonUserSelect,
|
||||
} from "~/utils/kysely.server";
|
||||
import { VODS_PAGE_BATCH_SIZE } from "./vods-constants";
|
||||
import type { VideoBeingAdded, Vod } from "./vods-types";
|
||||
import {
|
||||
|
|
@ -65,12 +69,7 @@ export async function findVods({
|
|||
jsonArrayFrom(
|
||||
eb
|
||||
.selectFrom("User")
|
||||
.select([
|
||||
"User.username",
|
||||
"User.discordId",
|
||||
"User.discordAvatar",
|
||||
"User.customUrl",
|
||||
])
|
||||
.select((playerEb) => commonUserSelect(playerEb))
|
||||
.whereRef("User.id", "=", "VideoMatchPlayer.playerUserId"),
|
||||
).as("players"),
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ export type VideoBeingAdded = z.infer<typeof videoSchema>;
|
|||
export interface Vod {
|
||||
id: Tables["Video"]["id"];
|
||||
pov?:
|
||||
| Pick<
|
||||
| (Pick<
|
||||
Tables["User"],
|
||||
"username" | "discordId" | "discordAvatar" | "customUrl" | "id"
|
||||
>
|
||||
> & { customAvatarUrl: string | null })
|
||||
| string;
|
||||
title: Tables["Video"]["title"];
|
||||
type: Tables["Video"]["type"];
|
||||
|
|
|
|||
|
|
@ -333,6 +333,7 @@ export function FormField({
|
|||
<ImageFormField
|
||||
{...commonProps}
|
||||
{...formField}
|
||||
disabled={disabled}
|
||||
value={value as ImageFieldValue}
|
||||
onChange={handleChange as (v: ImageFieldValue) => void}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ function prefixItems<V extends string>(
|
|||
|
||||
export function image(args: {
|
||||
label: FormsTranslationKey;
|
||||
bottomText?: FormsTranslationKey;
|
||||
dimensions?: "logo" | "thick-banner" | { width: number; height: number };
|
||||
autoValidate?: boolean;
|
||||
}) {
|
||||
|
|
@ -91,6 +92,7 @@ export function image(args: {
|
|||
// instance would otherwise have its metadata overwritten by later fields)
|
||||
return imageValue.clone().register(formRegistry, {
|
||||
label: prefixKey(args.label),
|
||||
bottomText: prefixKey(args.bottomText),
|
||||
dimensions: args.dimensions ?? "logo",
|
||||
autoValidate: args.autoValidate ?? false,
|
||||
type: "image",
|
||||
|
|
|
|||
|
|
@ -15,16 +15,19 @@ import styles from "./ImageFormField.module.css";
|
|||
type ImageFormFieldProps = Omit<FormFieldProps<"image">, "onBlur"> & {
|
||||
value: ImageFieldValue;
|
||||
onChange: (value: ImageFieldValue) => void;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export function ImageFormField({
|
||||
name,
|
||||
label,
|
||||
bottomText,
|
||||
dimensions,
|
||||
autoValidate,
|
||||
error,
|
||||
value,
|
||||
onChange,
|
||||
disabled,
|
||||
}: ImageFormFieldProps) {
|
||||
const id = React.useId();
|
||||
const { t } = useTranslation(["common"]);
|
||||
|
|
@ -72,7 +75,8 @@ export function ImageFormField({
|
|||
label={label}
|
||||
error={error}
|
||||
bottomText={
|
||||
autoValidate ? undefined : "forms:bottomTexts.imageModeration"
|
||||
bottomText ??
|
||||
(autoValidate ? undefined : "forms:bottomTexts.imageModeration")
|
||||
}
|
||||
>
|
||||
<div className="stack sm items-start">
|
||||
|
|
@ -88,6 +92,7 @@ export function ImageFormField({
|
|||
variant="minimal-destructive"
|
||||
size="small"
|
||||
onPress={() => onChange(null)}
|
||||
isDisabled={disabled}
|
||||
>
|
||||
{t("common:actions.remove")}
|
||||
</SendouButton>
|
||||
|
|
@ -97,6 +102,7 @@ export function ImageFormField({
|
|||
type="file"
|
||||
accept="image/png, image/jpeg, image/webp"
|
||||
onChange={handleFileChange}
|
||||
disabled={disabled}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -117,8 +117,7 @@ interface FormFieldMapPool<T extends string> extends FormFieldBase<T> {
|
|||
disableBannedMaps?: boolean;
|
||||
}
|
||||
|
||||
interface FormFieldImage<T extends string>
|
||||
extends Omit<FormFieldBase<T>, "bottomText"> {
|
||||
interface FormFieldImage<T extends string> extends FormFieldBase<T> {
|
||||
dimensions?: ImageFieldDimensions;
|
||||
/** Validate uploaded images immediately, bypassing the moderator queue (e.g. trusted org logos). */
|
||||
autoValidate?: boolean;
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|||
discordId: user.discordId,
|
||||
id: user.id,
|
||||
customUrl: user.customUrl,
|
||||
customAvatarUrl: user.customAvatarUrl,
|
||||
inGameName: user.inGameName,
|
||||
friendCode: user.friendCode,
|
||||
preferences: user.preferences ?? {},
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ describe("syncLiveStreams tournament streamers", () => {
|
|||
streamTwitch: null,
|
||||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
|
@ -148,6 +149,7 @@ describe("syncLiveStreams tournament streamers", () => {
|
|||
streamTwitch: null,
|
||||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
|
@ -201,6 +203,7 @@ describe("syncLiveStreams tournament streamers", () => {
|
|||
streamTwitch: null,
|
||||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
|
@ -237,6 +240,7 @@ describe("syncLiveStreams tournament streamers", () => {
|
|||
streamTwitch: null,
|
||||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
|
@ -276,6 +280,7 @@ describe("syncLiveStreams tournament streamers", () => {
|
|||
streamTwitch: null,
|
||||
streamViewerCount: null,
|
||||
streamThumbnailUrl: null,
|
||||
customAvatarUrl: null,
|
||||
},
|
||||
],
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -9,18 +9,44 @@ import { jsonArrayFrom, jsonBuildObject } from "kysely/helpers/sqlite";
|
|||
import type { DB, Tables } from "~/db/tables";
|
||||
import { IS_E2E_TEST_RUN } from "./e2e";
|
||||
|
||||
export const COMMON_USER_FIELDS = [
|
||||
"User.id",
|
||||
"User.username",
|
||||
"User.discordId",
|
||||
"User.discordAvatar",
|
||||
"User.customUrl",
|
||||
] as const;
|
||||
/**
|
||||
* Select list for the fields shared by every user representation across the app. Includes
|
||||
* `customAvatarUrl`, the full URL of the user's supporter custom avatar (resolved from
|
||||
* `User.customAvatarImgId`), or `null` when they have none. `"User"` must be in scope at the call
|
||||
* site (it always is, since the other fields reference `User.*`).
|
||||
*/
|
||||
export function commonUserSelect(eb: ExpressionBuilder<Tables, "User">) {
|
||||
return [
|
||||
"User.id",
|
||||
"User.username",
|
||||
"User.discordId",
|
||||
"User.discordAvatar",
|
||||
"User.customUrl",
|
||||
customAvatarUrl(eb).as("customAvatarUrl"),
|
||||
] as const;
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL expression resolving to the full URL of a user's supporter custom avatar (from
|
||||
* `User.customAvatarImgId`), or `null` when they have none. Alias it
|
||||
* (`.as("customAvatarUrl")`) when selecting it directly. Prefer {@link commonUserSelect} /
|
||||
* {@link commonUserJsonObject}; reach for this only when those don't fit (e.g. prefixed aliases or
|
||||
* a hand-built `jsonBuildObject`).
|
||||
*/
|
||||
export function customAvatarUrl(eb: ExpressionBuilder<Tables, "User">) {
|
||||
return concatUserSubmittedImagePrefix(
|
||||
eb
|
||||
.selectFrom("UserSubmittedImage")
|
||||
.select("UserSubmittedImage.url")
|
||||
.whereRef("UserSubmittedImage.id", "=", "User.customAvatarImgId")
|
||||
.$asScalar(),
|
||||
).$castTo<string | null>();
|
||||
}
|
||||
|
||||
export type CommonUser = Pick<
|
||||
Tables["User"],
|
||||
"id" | "username" | "discordId" | "discordAvatar" | "customUrl"
|
||||
>;
|
||||
> & { customAvatarUrl: string | null };
|
||||
|
||||
const userChatNameHueRaw = sql<
|
||||
string | null
|
||||
|
|
@ -35,6 +61,13 @@ export function commonUserJsonObject(eb: ExpressionBuilder<Tables, "User">) {
|
|||
discordId: eb.ref("User.discordId"),
|
||||
discordAvatar: eb.ref("User.discordAvatar"),
|
||||
customUrl: eb.ref("User.customUrl"),
|
||||
customAvatarUrl: concatUserSubmittedImagePrefix(
|
||||
eb
|
||||
.selectFrom("UserSubmittedImage")
|
||||
.select("UserSubmittedImage.url")
|
||||
.whereRef("UserSubmittedImage.id", "=", "User.customAvatarImgId")
|
||||
.$asScalar(),
|
||||
).$castTo<string | null>(),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
BIN
db-test.sqlite3
BIN
db-test.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "",
|
||||
"support.perk.userShortLink.extra": "",
|
||||
"support.perk.customizedColorsUser": "Tilpas farver på brugerprofil",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "Tilpas far holdprofil",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "Brugerdefineret Navn",
|
||||
"labels.profileCustomUrl": "Brugerdefineret URL",
|
||||
"labels.inGameName": "Splatoon 3 Brugernavn",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "Åben for bestillinger",
|
||||
"labels.profileCommissionText": "info om bestilling",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "Hvis feltet ikke udfyldes bruges dit discordbrugernavn: \"{{discordName}}\"",
|
||||
"bottomTexts.profileCustomUrl": "",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "",
|
||||
"support.perk.userShortLink.extra": "",
|
||||
"support.perk.customizedColorsUser": "Farben anpassen (User-Seite)",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "Farben anpassen (Team-Seite)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "",
|
||||
"labels.profileCustomUrl": "Benutzerdefinierte URL",
|
||||
"labels.inGameName": "Name im Spiel",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "",
|
||||
"labels.profileCommissionText": "",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "",
|
||||
"bottomTexts.profileCustomUrl": "",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "User page short link",
|
||||
"support.perk.userShortLink.extra": "Instead of e.g. sendou.ink/u/sendou you can also use snd.ink/sendou when linking to your user profile.",
|
||||
"support.perk.customizedColorsUser": "Customize colors (user page)",
|
||||
"support.perk.customAvatar": "Custom avatar",
|
||||
"support.perk.customAvatar.extra": "Upload a custom avatar to use instead of your Discord avatar.",
|
||||
"support.perk.favoriteBadges": "Set profile first page badges",
|
||||
"support.perk.favoriteBadges.extra": "You can set which badges appear on the first page and the order. Normally it's only possible to choose the first badge.",
|
||||
"support.perk.customizedColorsTeam": "Customize colors (team page)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "This user has already been suggested",
|
||||
"errors.plusAlreadyMember": "This user is already a member of this tier",
|
||||
"errors.plusCannotSuggest": "Can't make a suggestion right now",
|
||||
"labels.profileCustomAvatar": "Custom avatar",
|
||||
"labels.profileCustomName": "Custom name",
|
||||
"labels.profileCustomUrl": "Custom URL",
|
||||
"labels.inGameName": "In-game name",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "Commissions open",
|
||||
"labels.profileCommissionText": "Commission info",
|
||||
"labels.profileNewProfileEnabled": "New profile page",
|
||||
"bottomTexts.profileCustomAvatar": "Patrons (Supporter & above) can upload an image to be used instead of Discord avatar",
|
||||
"bottomTexts.profileCustomName": "If empty, your Discord display name is shown",
|
||||
"bottomTexts.profileCustomUrl": "For patrons (Supporter & above) short link is available. E.g. instead of sendou.ink/u/sendou, snd.ink/sendou can be used.",
|
||||
"bottomTexts.profileInGameName": "Format: Name#disc (e.g. Player#1234)",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "Enlace corto de perfil",
|
||||
"support.perk.userShortLink.extra": "En lugar de sendou.ink/u/sendou también puedes usar snd.ink/sendou al enlazar a tu perfil de usuario.",
|
||||
"support.perk.customizedColorsUser": "Colores personalizados (perfil)",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "Fijar insignias favoritas",
|
||||
"support.perk.favoriteBadges.extra": "Puedes elegir qué insignias aparecen en la página principal de tu perfil y en qué orden.",
|
||||
"support.perk.customizedColorsTeam": "Colores personalizados (equipo)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "",
|
||||
"labels.profileCustomUrl": "Enlace personalizado",
|
||||
"labels.inGameName": "Nombre en el juego",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "Comisiones abiertas",
|
||||
"labels.profileCommissionText": "Info de comisiones",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "",
|
||||
"bottomTexts.profileCustomUrl": "",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "",
|
||||
"support.perk.userShortLink.extra": "",
|
||||
"support.perk.customizedColorsUser": "Colores personalizados (perfil)",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "Colores personalizados (página de equipo)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "Nombre personalizado",
|
||||
"labels.profileCustomUrl": "Enlace personalizado",
|
||||
"labels.inGameName": "Nombre en el juego",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "Comisiones abiertas",
|
||||
"labels.profileCommissionText": "Info de comisiones",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "Si vacío, se mostrará tu nombre de Discord: \"{{discordName}}\"",
|
||||
"bottomTexts.profileCustomUrl": "",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "",
|
||||
"support.perk.userShortLink.extra": "",
|
||||
"support.perk.customizedColorsUser": "Personalisation des couleurs (page perso)",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "Personalisation des couleurs (page d'équipe)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "",
|
||||
"labels.profileCustomUrl": "URL personnalisée",
|
||||
"labels.inGameName": "Pseudo en jeu",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "Commissions acceptées",
|
||||
"labels.profileCommissionText": "Info pour les commissions",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "",
|
||||
"bottomTexts.profileCustomUrl": "",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "Lien de la page de l'utilisateur plus court",
|
||||
"support.perk.userShortLink.extra": "Au lieu d'utiliser par exemple sendou.ink/u/sendou, vous pouvez également utiliser snd.ink/sendou lorsque vous créez un lien vers votre profil.",
|
||||
"support.perk.customizedColorsUser": "Personalisation des couleurs (page personnelle)",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "Choisissez le badge qui apparaitra en premier sur votre profil",
|
||||
"support.perk.favoriteBadges.extra": "Vous pouvez choisir l'ordre des badges qui vont apparaitre sur la première page de votre profil. Normalement, il est seulement possible de choisir le premier badge.",
|
||||
"support.perk.customizedColorsTeam": "Personalisation des couleurs (page d'équipe)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "Nom personnalisée",
|
||||
"labels.profileCustomUrl": "URL personnalisée",
|
||||
"labels.inGameName": "Pseudo en jeu",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "Commissions acceptées",
|
||||
"labels.profileCommissionText": "Info pour les commissions",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "Si il n'est pas présent, votre pseudo discord est utilisé: \"{{discordName}}\"",
|
||||
"bottomTexts.profileCustomUrl": "Pour les Supporter patrons (& plus), les liens courts sont disponibles. Exemple: Au mieux de sendou.ink/u/sendou, snd.ink/sendou peut être utilisé.",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "",
|
||||
"support.perk.userShortLink.extra": "",
|
||||
"support.perk.customizedColorsUser": "התאמה אישית של צבעים (דף משתמש)",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "התאמה אישית של צבעים (דף צוות)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "",
|
||||
"labels.profileCustomUrl": "כתובת URL מותאמת אישית",
|
||||
"labels.inGameName": "שם במשחק",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "בקשות פתוחות",
|
||||
"labels.profileCommissionText": "מידע עבור בקשות",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "",
|
||||
"bottomTexts.profileCustomUrl": "",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "Short link per la pagina utente",
|
||||
"support.perk.userShortLink.extra": "Invece di es. sendou.ink/u/sendou puoi anche usare snd.ink/sendou quando linki la tua pagina utente.",
|
||||
"support.perk.customizedColorsUser": "Personalizza colori (pagina utente)",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "Personalizza colori (Pagina team)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "Nome personalizzato",
|
||||
"labels.profileCustomUrl": "URL personalizzato",
|
||||
"labels.inGameName": "Nome nel gioco",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "Commissioni aperte",
|
||||
"labels.profileCommissionText": "Info sulle commissioni",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "Se mancante, viene usato il tuo nome visualizzato Discord: \"{{discordName}}\"",
|
||||
"bottomTexts.profileCustomUrl": "Per gli iscritti al Patreon (Supporter compreso in su) è disponibile il link corto. Es. invece di sendou.ink/u/sendou, può essere usato snd.ink/sendou.",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "",
|
||||
"support.perk.userShortLink.extra": "",
|
||||
"support.perk.customizedColorsUser": "カラーをカスタマイズする (ユーザーページ)",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "カラーをカスタマイズする (チームページ)",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "カスタム 名前",
|
||||
"labels.profileCustomUrl": "カスタム URL",
|
||||
"labels.inGameName": "ゲーム中の名前",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "依頼を受付中",
|
||||
"labels.profileCommissionText": "依頼に関する情報",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "記入されてない場合ディスコードの表示名 \"{{discordName}}\"を使います",
|
||||
"bottomTexts.profileCustomUrl": "",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "",
|
||||
"support.perk.userShortLink.extra": "",
|
||||
"support.perk.customizedColorsUser": "",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "",
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@
|
|||
"errors.plusAlreadySuggested": "",
|
||||
"errors.plusAlreadyMember": "",
|
||||
"errors.plusCannotSuggest": "",
|
||||
"labels.profileCustomAvatar": "",
|
||||
"labels.profileCustomName": "",
|
||||
"labels.profileCustomUrl": "",
|
||||
"labels.inGameName": "",
|
||||
|
|
@ -248,6 +249,7 @@
|
|||
"labels.profileCommissionsOpen": "",
|
||||
"labels.profileCommissionText": "",
|
||||
"labels.profileNewProfileEnabled": "",
|
||||
"bottomTexts.profileCustomAvatar": "",
|
||||
"bottomTexts.profileCustomName": "",
|
||||
"bottomTexts.profileCustomUrl": "",
|
||||
"bottomTexts.profileInGameName": "",
|
||||
|
|
|
|||
|
|
@ -252,6 +252,8 @@
|
|||
"support.perk.userShortLink": "",
|
||||
"support.perk.userShortLink.extra": "",
|
||||
"support.perk.customizedColorsUser": "",
|
||||
"support.perk.customAvatar": "",
|
||||
"support.perk.customAvatar.extra": "",
|
||||
"support.perk.favoriteBadges": "",
|
||||
"support.perk.favoriteBadges.extra": "",
|
||||
"support.perk.customizedColorsTeam": "",
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user