Remove trusted users Closes #1640

This commit is contained in:
Kalle
2024-05-02 20:21:34 +03:00
parent 93ea425462
commit 31c590010f
4 changed files with 136 additions and 2 deletions

View File

@@ -1,6 +1,7 @@
import { db } from "~/db/sql";
import type { Tables, UserMapModePreferences } from "~/db/tables";
import { modesShort, type MainWeaponId } from "~/modules/in-game-lists";
import { COMMON_USER_FIELDS } from "~/utils/kysely.server";
export async function settingsByUserId(userId: number) {
const preferences = await db
@@ -100,3 +101,35 @@ export function updateNoScreen({
.where("User.id", "=", userId)
.execute();
}
export function currentTeamByUserId(userId: number) {
return db
.selectFrom("TeamMember")
.innerJoin("Team", "Team.id", "TeamMember.teamId")
.select(["Team.name"])
.where("TeamMember.userId", "=", userId)
.executeTakeFirst();
}
export function findTrustedUsersByGiverId(trustGiverUserId: number) {
return db
.selectFrom("TrustRelationship")
.innerJoin("User", "User.id", "TrustRelationship.trustReceiverUserId")
.select(COMMON_USER_FIELDS)
.where("TrustRelationship.trustGiverUserId", "=", trustGiverUserId)
.execute();
}
export function deleteTrustedUser({
trustGiverUserId,
trustReceiverUserId,
}: {
trustGiverUserId: number;
trustReceiverUserId: number;
}) {
return db
.deleteFrom("TrustRelationship")
.where("TrustRelationship.trustGiverUserId", "=", trustGiverUserId)
.where("TrustRelationship.trustReceiverUserId", "=", trustReceiverUserId)
.execute();
}

View File

@@ -3,6 +3,7 @@ import { languagesUnified } from "~/modules/i18n/config";
import {
_action,
checkboxValueToBoolean,
id,
modeShort,
noDuplicates,
safeJSONParse,
@@ -73,4 +74,8 @@ export const settingsActionSchema = z.union([
_action: _action("UPDATE_NO_SCREEN"),
noScreen: z.preprocess(checkboxValueToBoolean, z.boolean()),
}),
z.object({
_action: _action("REMOVE_TRUST"),
userToRemoveTrustFromId: id,
}),
]);

View File

@@ -44,6 +44,11 @@ import {
SENDOUQ_WEAPON_POOL_MAX_SIZE,
} from "../q-settings-constants";
import { settingsActionSchema } from "../q-settings-schemas.server";
import { FormMessage } from "~/components/FormMessage";
import { UsersIcon } from "~/components/icons/Users";
import { Avatar } from "~/components/Avatar";
import { FormWithConfirm } from "~/components/FormWithConfirm";
import { Trans } from "react-i18next";
import "../q-settings.css";
@@ -100,6 +105,13 @@ export const action = async ({ request }: ActionFunctionArgs) => {
});
break;
}
case "REMOVE_TRUST": {
await QSettingsRepository.deleteTrustedUser({
trustGiverUserId: user.id,
trustReceiverUserId: data.userToRemoveTrustFromId,
});
break;
}
default: {
assertUnreachable(data);
}
@@ -113,6 +125,8 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
return {
settings: await QSettingsRepository.settingsByUserId(user.id),
trusted: await QSettingsRepository.findTrustedUsersByGiverId(user.id),
team: await QSettingsRepository.currentTeamByUserId(user.id),
};
};
@@ -124,6 +138,7 @@ export default function SendouQSettingsPage() {
<WeaponPool />
<VoiceChat />
<Sounds />
<TrustedUsers />
<Misc />
</div>
</Main>
@@ -587,8 +602,10 @@ function Sounds() {
<span>{t("q:settings.sounds.header")}</span> <SpeakerFilledIcon />
</div>
</summary>
{isMounted && <SoundCheckboxes />}
{isMounted && <SoundSlider />}
<div className="mb-4">
{isMounted && <SoundCheckboxes />}
{isMounted && <SoundSlider />}
</div>
</details>
);
}
@@ -689,6 +706,80 @@ function SoundSlider() {
);
}
function TrustedUsers() {
const { t } = useTranslation(["q"]);
const data = useLoaderData<typeof loader>();
return (
<details>
<summary className="q-settings__summary">
<span>{t("q:settings.trusted.header")}</span> <UsersIcon />
</summary>
<div className="mb-4">
{data.trusted.length > 0 ? (
<>
<div className="stack md mt-2">
{data.trusted.map((trustedUser) => {
return (
<div
key={trustedUser.id}
className="stack horizontal xs items-center"
>
<Avatar user={trustedUser} size="xxs" />
<div className="text-sm font-semi-bold">
{trustedUser.discordName}
</div>
<FormWithConfirm
dialogHeading={t("q:settings.trusted.confirm", {
name: trustedUser.discordName,
})}
fields={[
["_action", "REMOVE_TRUST"],
["userToRemoveTrustFromId", trustedUser.id],
]}
deleteButtonText="Remove"
>
<Button
className="build__small-text"
variant="minimal-destructive"
size="tiny"
type="submit"
>
<TrashIcon className="build__icon" />
</Button>
</FormWithConfirm>
</div>
);
})}
<FormMessage type="info">
{t("q:settings.trusted.trustedExplanation")}
</FormMessage>
</div>
</>
) : (
<FormMessage type="info" className="mb-2">
{t("q:settings.trusted.noTrustedExplanation")}
</FormMessage>
)}
{data.team ? (
<FormMessage type="info" className="mb-2">
<Trans
i18nKey="q:settings.trusted.teamExplanation"
t={t}
values={{
name: data.team.name,
}}
>
In addition to the users above, a member of your team{" "}
<b>{data.team.name}</b> can you add you directly.
</Trans>
</FormMessage>
) : null}
</div>
</details>
);
}
function Misc() {
const data = useLoaderData<typeof loader>();
const [checked, setChecked] = React.useState(Boolean(data.settings.noScreen));

View File

@@ -73,6 +73,11 @@
"settings.misc.header": "Misc",
"settings.banned": "Banned",
"settings.avoid.label": "Avoid {{special}}",
"settings.trusted.header": "Trusted users",
"settings.trusted.confirm": "Remove {{name}} from trusted users?",
"settings.trusted.trustedExplanation": "Trusted users can add you to groups and tournament teams directly. If removed from this list, in the future you need to join via a link they share.",
"settings.trusted.noTrustedExplanation": "You don't currently trust any users. Users can be trusted when you join their SendouQ group or tournament team via a link. Trusted users can add you to groups and tournament teams directly.",
"settings.trusted.teamExplanation": "In addition to the users above, a member of your team <2>{{name}}</2> can you add you directly.",
"looking.joiningGroupError": "Before joining another group, leave the current one",
"looking.goToSettingsPrompt": "To help group finding set your weapon pool and voice chat status on the settings page",