replace roles & users in uptime alert section

This commit is contained in:
Fred KISSIE
2026-04-29 07:29:05 +02:00
parent c4cf4cdec4
commit 081940dff8

View File

@@ -1,18 +1,5 @@
"use client"; "use client";
import { useState, useMemo } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import Link from "next/link";
import { BellPlus, BellRing } from "lucide-react";
import {
SettingsSection,
SettingsSectionHeader,
SettingsSectionTitle,
SettingsSectionDescription,
SettingsSectionBody
} from "@app/components/Settings";
import UptimeBar from "@app/components/UptimeBar";
import { Button } from "@app/components/ui/button";
import { import {
Credenza, Credenza,
CredenzaBody, CredenzaBody,
@@ -23,18 +10,32 @@ import {
CredenzaHeader, CredenzaHeader,
CredenzaTitle CredenzaTitle
} from "@app/components/Credenza"; } from "@app/components/Credenza";
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
import {
SettingsSection,
SettingsSectionBody,
SettingsSectionDescription,
SettingsSectionHeader,
SettingsSectionTitle
} from "@app/components/Settings";
import UptimeBar from "@app/components/UptimeBar";
import { TagInput, type Tag } from "@app/components/tags/tag-input";
import { Button } from "@app/components/ui/button";
import { Input } from "@app/components/ui/input"; import { Input } from "@app/components/ui/input";
import { Label } from "@app/components/ui/label"; import { Label } from "@app/components/ui/label";
import { TagInput, type Tag } from "@app/components/tags/tag-input";
import { getUserDisplayName } from "@app/lib/getUserDisplayName";
import { createApiClient, formatAxiosError } from "@app/lib/api";
import { useEnvContext } from "@app/hooks/useEnvContext"; import { useEnvContext } from "@app/hooks/useEnvContext";
import { toast } from "@app/hooks/useToast";
import { orgQueries } from "@app/lib/queries";
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
import { usePaidStatus } from "@app/hooks/usePaidStatus"; import { usePaidStatus } from "@app/hooks/usePaidStatus";
import { toast } from "@app/hooks/useToast";
import { createApiClient, formatAxiosError } from "@app/lib/api";
import { orgQueries } from "@app/lib/queries";
import { tierMatrix } from "@server/lib/billing/tierMatrix"; import { tierMatrix } from "@server/lib/billing/tierMatrix";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { BellPlus, BellRing } from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import Link from "next/link";
import { useState } from "react";
import { RolesSelector } from "./roles-selector";
import { UsersSelector } from "./users-selector";
interface UptimeAlertSectionProps { interface UptimeAlertSectionProps {
orgId: string; orgId: string;
@@ -64,12 +65,7 @@ export default function UptimeAlertSection({
const [userTags, setUserTags] = useState<Tag[]>([]); const [userTags, setUserTags] = useState<Tag[]>([]);
const [roleTags, setRoleTags] = useState<Tag[]>([]); const [roleTags, setRoleTags] = useState<Tag[]>([]);
const [emailTags, setEmailTags] = useState<Tag[]>([]); const [emailTags, setEmailTags] = useState<Tag[]>([]);
const [activeUserTagIndex, setActiveUserTagIndex] = useState<number | null>(
null
);
const [activeRoleTagIndex, setActiveRoleTagIndex] = useState<number | null>(
null
);
const [activeEmailTagIndex, setActiveEmailTagIndex] = useState< const [activeEmailTagIndex, setActiveEmailTagIndex] = useState<
number | null number | null
>(null); >(null);
@@ -80,27 +76,6 @@ export default function UptimeAlertSection({
enabled: isPaid enabled: isPaid
}); });
const { data: orgUsers = [] } = useQuery(orgQueries.users({ orgId }));
const { data: orgRoles = [] } = useQuery(orgQueries.roles({ orgId }));
const allUsers = useMemo(
() =>
orgUsers.map((u) => ({
id: String(u.id),
text: getUserDisplayName({
email: u.email,
name: u.name,
username: u.username
})
})),
[orgUsers]
);
const allRoles = useMemo(
() => orgRoles.map((r) => ({ id: String(r.roleId), text: r.name })),
[orgRoles]
);
const hasRules = (alertRules?.length ?? 0) > 0; const hasRules = (alertRules?.length ?? 0) > 0;
async function handleSubmit() { async function handleSubmit() {
@@ -227,10 +202,16 @@ export default function UptimeAlertSection({
</CredenzaHeader> </CredenzaHeader>
<CredenzaBody> <CredenzaBody>
<div className="space-y-4"> <div className="space-y-4">
<PaidFeaturesAlert tiers={tierMatrix.alertingRules} /> <PaidFeaturesAlert
tiers={tierMatrix.alertingRules}
/>
<fieldset <fieldset
disabled={!isPaid} disabled={!isPaid}
className={!isPaid ? "opacity-50 pointer-events-none" : ""} className={
!isPaid
? "opacity-50 pointer-events-none"
: ""
}
> >
<div className="space-y-4"> <div className="space-y-4">
<div className="space-y-2"> <div className="space-y-2">
@@ -240,65 +221,53 @@ export default function UptimeAlertSection({
<Input <Input
id="alert-name" id="alert-name"
value={name} value={name}
onChange={(e) => setName(e.target.value)} onChange={(e) =>
placeholder={t("uptimeAlertNamePlaceholder")} setName(e.target.value)
}
placeholder={t(
"uptimeAlertNamePlaceholder"
)}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("alertingNotifyUsers")}</Label> <Label>
<TagInput {t("alertingNotifyUsers")}
activeTagIndex={activeUserTagIndex} </Label>
setActiveTagIndex={setActiveUserTagIndex} <UsersSelector
placeholder={t("alertingSelectUsers")} selectedUsers={userTags}
size="sm" orgId={orgId}
tags={userTags} onSelectUsers={setUserTags}
setTags={(newTags) => {
const next =
typeof newTags === "function"
? newTags(userTags)
: newTags;
setUserTags(next as Tag[]);
}}
enableAutocomplete
autocompleteOptions={allUsers}
restrictTagsToAutocompleteOptions
allowDuplicates={false}
sortTags
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("alertingNotifyRoles")}</Label> <Label>
<TagInput {t("alertingNotifyRoles")}
activeTagIndex={activeRoleTagIndex} </Label>
setActiveTagIndex={setActiveRoleTagIndex} <RolesSelector
placeholder={t("alertingSelectRoles")} selectedRoles={roleTags}
size="sm" restrictAdminRole
tags={roleTags} orgId={orgId}
setTags={(newTags) => { onSelectRoles={setRoleTags}
const next =
typeof newTags === "function"
? newTags(roleTags)
: newTags;
setRoleTags(next as Tag[]);
}}
enableAutocomplete
autocompleteOptions={allRoles}
restrictTagsToAutocompleteOptions
allowDuplicates={false}
sortTags
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label>{t("uptimeAdditionalEmails")}</Label> <Label>
{t("uptimeAdditionalEmails")}
</Label>
<TagInput <TagInput
activeTagIndex={activeEmailTagIndex} activeTagIndex={activeEmailTagIndex}
setActiveTagIndex={setActiveEmailTagIndex} setActiveTagIndex={
placeholder={t("alertingEmailPlaceholder")} setActiveEmailTagIndex
}
placeholder={t(
"alertingEmailPlaceholder"
)}
size="sm" size="sm"
tags={emailTags} tags={emailTags}
setTags={(newTags) => { setTags={(newTags) => {
const next = const next =
typeof newTags === "function" typeof newTags ===
"function"
? newTags(emailTags) ? newTags(emailTags)
: newTags; : newTags;
setEmailTags(next as Tag[]); setEmailTags(next as Tag[]);
@@ -306,7 +275,9 @@ export default function UptimeAlertSection({
allowDuplicates={false} allowDuplicates={false}
sortTags sortTags
validateTag={(tag) => validateTag={(tag) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(tag) /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(
tag
)
} }
delimiterList={[",", "Enter"]} delimiterList={[",", "Enter"]}
/> />