Skip to content

Commit ff6e246

Browse files
committed
Add admin tooltips to make support/debugging easier for admin users
1 parent 3ed016b commit ff6e246

File tree

12 files changed

+209
-14
lines changed

12 files changed

+209
-14
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { ShieldCheckIcon } from "@heroicons/react/20/solid";
2+
import {
3+
Tooltip,
4+
TooltipContent,
5+
TooltipProvider,
6+
TooltipTrigger,
7+
} from "~/components/primitives/Tooltip";
8+
import { useHasAdminAccess } from "~/hooks/useUser";
9+
10+
export function AdminDebugTooltip({ children }: { children: React.ReactNode }) {
11+
const hasAdminAccess = useHasAdminAccess();
12+
13+
if (!hasAdminAccess) {
14+
return null;
15+
}
16+
17+
return (
18+
<TooltipProvider>
19+
<Tooltip>
20+
<TooltipTrigger>
21+
<ShieldCheckIcon className="h-5 w-5" />
22+
</TooltipTrigger>
23+
<TooltipContent className="flex items-center gap-1">{children}</TooltipContent>
24+
</Tooltip>
25+
</TooltipProvider>
26+
);
27+
}

apps/webapp/app/hooks/useUser.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,9 @@ export function useUser(matches?: UIMatch[]): User {
2626
export function useUserChanged(callback: (user: User | undefined) => void) {
2727
useChanged(useOptionalUser, callback);
2828
}
29+
30+
export function useHasAdminAccess(matches?: UIMatch[]): boolean {
31+
const user = useOptionalUser(matches);
32+
33+
return Boolean(user?.admin);
34+
}

apps/webapp/app/models/admin.server.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ export async function adminGetOrganizations(userId: string, { page, search }: Se
168168
mode: "insensitive",
169169
},
170170
},
171+
{
172+
id: {
173+
contains: search,
174+
mode: "insensitive",
175+
},
176+
},
171177
],
172178
}
173179
: undefined,

apps/webapp/app/presenters/v3/RunPresenter.server.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class RunPresenter {
3838
id: true,
3939
type: true,
4040
slug: true,
41+
organizationId: true,
4142
orgMember: {
4243
select: {
4344
user: {
@@ -66,9 +67,13 @@ export class RunPresenter {
6667
if (!traceSummary) {
6768
return {
6869
run: {
70+
id: run.id,
6971
number: run.number,
7072
friendlyId: run.friendlyId,
73+
traceId: run.traceId,
7174
environment: {
75+
id: run.runtimeEnvironment.id,
76+
organizationId: run.runtimeEnvironment.organizationId,
7277
type: run.runtimeEnvironment.type,
7378
slug: run.runtimeEnvironment.slug,
7479
userId: run.runtimeEnvironment.orgMember?.user.id,
@@ -118,9 +123,13 @@ export class RunPresenter {
118123

119124
return {
120125
run: {
126+
id: run.id,
121127
number: run.number,
122128
friendlyId: run.friendlyId,
129+
traceId: run.traceId,
123130
environment: {
131+
id: run.runtimeEnvironment.id,
132+
organizationId: run.runtimeEnvironment.organizationId,
124133
type: run.runtimeEnvironment.type,
125134
slug: run.runtimeEnvironment.slug,
126135
userId: run.runtimeEnvironment.orgMember?.user.id,

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam._index/route.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { TypedAwait, typeddefer, useTypedLoaderData } from "remix-typedjson";
99
import { Feedback } from "~/components/Feedback";
1010
import { InitCommandV3, TriggerDevStepV3, TriggerLoginStepV3 } from "~/components/SetupCommands";
1111
import { StepContentContainer } from "~/components/StepContentContainer";
12+
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
1213
import { InlineCode } from "~/components/code/InlineCode";
1314
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
1415
import { MainCenteredContainer, PageBody, PageContainer } from "~/components/layout/AppLayout";
@@ -17,8 +18,9 @@ import { Callout } from "~/components/primitives/Callout";
1718
import { formatDateTime } from "~/components/primitives/DateTime";
1819
import { Header1, Header2, Header3 } from "~/components/primitives/Headers";
1920
import { Input } from "~/components/primitives/Input";
20-
import { NavBar, PageTitle } from "~/components/primitives/PageHeader";
21+
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
2122
import { Paragraph } from "~/components/primitives/Paragraph";
23+
import { Property, PropertyTable } from "~/components/primitives/PropertyTable";
2224
import { Spinner } from "~/components/primitives/Spinner";
2325
import { StepNumber } from "~/components/primitives/StepNumber";
2426
import {
@@ -125,6 +127,25 @@ export default function Page() {
125127
<PageContainer>
126128
<NavBar>
127129
<PageTitle title="Tasks" />
130+
<PageAccessories>
131+
<AdminDebugTooltip>
132+
<PropertyTable>
133+
{tasks.map((task) => (
134+
<Property label={task.exportName} key={task.slug}>
135+
<div className="flex items-center gap-2">
136+
<Paragraph variant="extra-small/bright/mono">
137+
{task.environments
138+
.map((e) =>
139+
e.userName ? `${e.userName}/${e.id}` : `${e.type.slice(0, 3)}/${e.id}`
140+
)
141+
.join(", ")}
142+
</Paragraph>
143+
</div>
144+
</Property>
145+
))}
146+
</PropertyTable>
147+
</AdminDebugTooltip>
148+
</PageAccessories>
128149
</NavBar>
129150
<PageBody>
130151
<div className={cn("grid h-full grid-rows-1")}>

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.apikeys/route.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { BookOpenIcon } from "@heroicons/react/20/solid";
1+
import { BookOpenIcon, LightBulbIcon, ShieldCheckIcon } from "@heroicons/react/20/solid";
22
import { Form } from "@remix-run/react";
33
import { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/server-runtime";
44
import { typedjson, useTypedLoaderData } from "remix-typedjson";
5+
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
56
import { EnvironmentLabel, environmentTitle } from "~/components/environments/EnvironmentLabel";
67
import { RegenerateApiKeyModal } from "~/components/environments/RegenerateApiKeyModal";
78
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
@@ -10,8 +11,9 @@ import { Callout } from "~/components/primitives/Callout";
1011
import { ClipboardField } from "~/components/primitives/ClipboardField";
1112
import { DateTime } from "~/components/primitives/DateTime";
1213
import { Header3 } from "~/components/primitives/Headers";
13-
import { PageAccessories, NavBar, PageTitle } from "~/components/primitives/PageHeader";
14+
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
1415
import { Paragraph } from "~/components/primitives/Paragraph";
16+
import { Property, PropertyTable } from "~/components/primitives/PropertyTable";
1517
import {
1618
Table,
1719
TableBody,
@@ -24,7 +26,6 @@ import {
2426
import { TextLink } from "~/components/primitives/TextLink";
2527
import { prisma } from "~/db.server";
2628
import { useFeatures } from "~/hooks/useFeatures";
27-
import { useProject } from "~/hooks/useProject";
2829
import { redirectWithErrorMessage, redirectWithSuccessMessage } from "~/models/message.server";
2930
import { createEnvironment } from "~/models/organization.server";
3031
import { ApiKeysPresenter } from "~/presenters/v3/ApiKeysPresenter.server";
@@ -132,6 +133,18 @@ export default function Page() {
132133
<NavBar>
133134
<PageTitle title="API keys" />
134135
<PageAccessories>
136+
<AdminDebugTooltip>
137+
<PropertyTable>
138+
{environments.map((environment) => (
139+
<Property label={environment.slug} key={environment.id}>
140+
<div className="flex items-center gap-2">
141+
<Paragraph variant="extra-small/bright/mono">{environment.id}</Paragraph>
142+
</div>
143+
</Property>
144+
))}
145+
</PropertyTable>
146+
</AdminDebugTooltip>
147+
135148
<LinkButton
136149
variant={"minimal/small"}
137150
LeadingIcon={BookOpenIcon}

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.runs.$runParam/route.tsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ import {
6767
v3RunsPath,
6868
} from "~/utils/pathBuilder";
6969
import { SpanView } from "../resources.orgs.$organizationSlug.projects.v3.$projectParam.runs.$runParam.spans.$spanParam/route";
70+
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
71+
import { Property, PropertyTable } from "~/components/primitives/PropertyTable";
7072

7173
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
7274
const userId = await requireUserId(request);
@@ -116,6 +118,33 @@ export default function Page() {
116118
title={`Run #${run.number}`}
117119
/>
118120
<PageAccessories>
121+
<AdminDebugTooltip>
122+
<PropertyTable>
123+
<Property label="ID">
124+
<div className="flex items-center gap-2">
125+
<Paragraph variant="extra-small/bright/mono">{run.id}</Paragraph>
126+
</div>
127+
</Property>
128+
<Property label="Trace ID">
129+
<div className="flex items-center gap-2">
130+
<Paragraph variant="extra-small/bright/mono">{run.traceId}</Paragraph>
131+
</div>
132+
</Property>
133+
<Property label="Env ID">
134+
<div className="flex items-center gap-2">
135+
<Paragraph variant="extra-small/bright/mono">{run.environment.id}</Paragraph>
136+
</div>
137+
</Property>
138+
<Property label="Org ID">
139+
<div className="flex items-center gap-2">
140+
<Paragraph variant="extra-small/bright/mono">
141+
{run.environment.organizationId}
142+
</Paragraph>
143+
</div>
144+
</Property>
145+
</PropertyTable>
146+
</AdminDebugTooltip>
147+
119148
<EnvironmentLabel
120149
size="large"
121150
environment={run.environment}
@@ -165,6 +194,33 @@ export default function Page() {
165194
title={`Run #${run.number}`}
166195
/>
167196
<PageAccessories>
197+
<AdminDebugTooltip>
198+
<PropertyTable>
199+
<Property label="ID">
200+
<div className="flex items-center gap-2">
201+
<Paragraph variant="extra-small/bright/mono">{run.id}</Paragraph>
202+
</div>
203+
</Property>
204+
<Property label="Trace ID">
205+
<div className="flex items-center gap-2">
206+
<Paragraph variant="extra-small/bright/mono">{run.traceId}</Paragraph>
207+
</div>
208+
</Property>
209+
<Property label="Env ID">
210+
<div className="flex items-center gap-2">
211+
<Paragraph variant="extra-small/bright/mono">{run.environment.id}</Paragraph>
212+
</div>
213+
</Property>
214+
<Property label="Org ID">
215+
<div className="flex items-center gap-2">
216+
<Paragraph variant="extra-small/bright/mono">
217+
{run.environment.organizationId}
218+
</Paragraph>
219+
</div>
220+
</Property>
221+
</PropertyTable>
222+
</AdminDebugTooltip>
223+
168224
<EnvironmentLabel size="large" environment={run.environment} userName={usernameForEnv} />
169225
</PageAccessories>
170226
</NavBar>

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.schedules/route.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Outlet, useLocation, useParams } from "@remix-run/react";
44
import { LoaderFunctionArgs } from "@remix-run/server-runtime";
55
import { typedjson, useTypedLoaderData } from "remix-typedjson";
66
import { BlankstateInstructions } from "~/components/BlankstateInstructions";
7+
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
78
import { InlineCode } from "~/components/code/InlineCode";
89
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel";
910
import { MainCenteredContainer, PageBody, PageContainer } from "~/components/layout/AppLayout";
@@ -12,6 +13,7 @@ import { DateTime } from "~/components/primitives/DateTime";
1213
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
1314
import { PaginationControls } from "~/components/primitives/Pagination";
1415
import { Paragraph } from "~/components/primitives/Paragraph";
16+
import { Property, PropertyTable } from "~/components/primitives/PropertyTable";
1517
import {
1618
ResizableHandle,
1719
ResizablePanel,
@@ -93,6 +95,18 @@ export default function Page() {
9395
<NavBar>
9496
<PageTitle title="Schedules" />
9597
<PageAccessories>
98+
<AdminDebugTooltip>
99+
<PropertyTable>
100+
{schedules.map((schedule) => (
101+
<Property label={schedule.friendlyId} key={schedule.id}>
102+
<div className="flex items-center gap-2">
103+
<Paragraph variant="extra-small/bright/mono">{schedule.id}</Paragraph>
104+
</div>
105+
</Property>
106+
))}
107+
</PropertyTable>
108+
</AdminDebugTooltip>
109+
96110
<LinkButton
97111
LeadingIcon={PlusIcon}
98112
to={`${v3NewSchedulePath(organization, project)}${location.search}`}

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.settings/route.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { parse } from "@conform-to/zod";
33
import { Form, useActionData, useNavigation } from "@remix-run/react";
44
import { ActionFunction, json } from "@remix-run/server-runtime";
55
import { z } from "zod";
6+
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
67
import { InlineCode } from "~/components/code/InlineCode";
78
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
89
import { Button } from "~/components/primitives/Buttons";
@@ -14,7 +15,9 @@ import { Hint } from "~/components/primitives/Hint";
1415
import { Input } from "~/components/primitives/Input";
1516
import { InputGroup } from "~/components/primitives/InputGroup";
1617
import { Label } from "~/components/primitives/Label";
17-
import { NavBar, PageTitle } from "~/components/primitives/PageHeader";
18+
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
19+
import { Paragraph } from "~/components/primitives/Paragraph";
20+
import { Property, PropertyTable } from "~/components/primitives/PropertyTable";
1821
import { prisma } from "~/db.server";
1922
import { useProject } from "~/hooks/useProject";
2023
import { redirectWithSuccessMessage } from "~/models/message.server";
@@ -110,6 +113,23 @@ export default function Page() {
110113
<PageContainer>
111114
<NavBar>
112115
<PageTitle title={`${project.name} project settings`} />
116+
117+
<PageAccessories>
118+
<AdminDebugTooltip>
119+
<PropertyTable>
120+
<Property label="ID">
121+
<div className="flex items-center gap-2">
122+
<Paragraph variant="extra-small/bright/mono">{project.id}</Paragraph>
123+
</div>
124+
</Property>
125+
<Property label="Org ID">
126+
<div className="flex items-center gap-2">
127+
<Paragraph variant="extra-small/bright/mono">{project.organizationId}</Paragraph>
128+
</div>
129+
</Property>
130+
</PropertyTable>
131+
</AdminDebugTooltip>
132+
</PageAccessories>
113133
</NavBar>
114134

115135
<PageBody>

apps/webapp/app/routes/_app.orgs.$organizationSlug.team/route.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { UseDataFunctionReturn, typedjson, useTypedLoaderData } from "remix-type
88
import invariant from "tiny-invariant";
99
import { z } from "zod";
1010
import { UserAvatar } from "~/components/UserProfilePhoto";
11+
import { AdminDebugTooltip } from "~/components/admin/debugTooltip";
1112
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
1213
import {
1314
Alert,
@@ -23,8 +24,9 @@ import { Button, ButtonContent, LinkButton } from "~/components/primitives/Butto
2324
import { DateTime } from "~/components/primitives/DateTime";
2425
import { Header2, Header3 } from "~/components/primitives/Headers";
2526
import { NamedIcon } from "~/components/primitives/NamedIcon";
26-
import { NavBar, PageTitle } from "~/components/primitives/PageHeader";
27+
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
2728
import { Paragraph } from "~/components/primitives/Paragraph";
29+
import { Property, PropertyTable } from "~/components/primitives/PropertyTable";
2830
import { SimpleTooltip } from "~/components/primitives/Tooltip";
2931
import { useOrganization } from "~/hooks/useOrganizations";
3032
import { useUser } from "~/hooks/useUser";
@@ -107,6 +109,28 @@ export default function Page() {
107109
<PageContainer>
108110
<NavBar>
109111
<PageTitle title="Team" />
112+
113+
<PageAccessories>
114+
<AdminDebugTooltip>
115+
<PropertyTable>
116+
<Property label="Org ID">
117+
<div className="flex items-center gap-2">
118+
<Paragraph variant="extra-small/bright/mono">{organization.id}</Paragraph>
119+
</div>
120+
</Property>
121+
122+
{members.map((member) => (
123+
<Property label={member.user.name} key={member.id}>
124+
<div className="flex items-center gap-2">
125+
<Paragraph variant="extra-small/bright/mono">
126+
{member.user.email} - {member.user.id}
127+
</Paragraph>
128+
</div>
129+
</Property>
130+
))}
131+
</PropertyTable>
132+
</AdminDebugTooltip>
133+
</PageAccessories>
110134
</NavBar>
111135
<PageBody>
112136
<Header2>Members</Header2>

apps/webapp/app/routes/_app/route.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
1515
return redirect(confirmBasicDetailsPath());
1616
}
1717

18-
return typedjson({
19-
headers: [["Set-Cookie", await commitSession(await clearRedirectTo(request))]],
20-
});
18+
return typedjson(
19+
{},
20+
{
21+
headers: { "Set-Cookie": await commitSession(await clearRedirectTo(request)) },
22+
}
23+
);
2124
};
2225

2326
export default function App() {

0 commit comments

Comments
 (0)