Skip to content

Commit c5327d2

Browse files
committed
Fixed role link
1 parent 445d9b0 commit c5327d2

2 files changed

Lines changed: 32 additions & 65 deletions

File tree

  • apps/webapp/app/routes
    • _app.orgs.$organizationSlug.settings.roles
    • _app.orgs.$organizationSlug.settings.team

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

Lines changed: 29 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
import { CheckIcon, XMarkIcon } from "@heroicons/react/20/solid";
22
import { type MetaFunction } from "@remix-run/react";
33
import { useState } from "react";
4-
import {
5-
type UseDataFunctionReturn,
6-
typedjson,
7-
useTypedLoaderData,
8-
} from "remix-typedjson";
4+
import { type UseDataFunctionReturn, typedjson, useTypedLoaderData } from "remix-typedjson";
95
import { z } from "zod";
106
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
117
import { Badge } from "~/components/primitives/Badge";
128
import { Button } from "~/components/primitives/Buttons";
13-
import {
14-
Dialog,
15-
DialogContent,
16-
DialogHeader,
17-
DialogTrigger,
18-
} from "~/components/primitives/Dialog";
9+
import { Dialog, DialogContent, DialogHeader, DialogTrigger } from "~/components/primitives/Dialog";
1910
import { Header3 } from "~/components/primitives/Headers";
2011
import { NavBar, PageTitle } from "~/components/primitives/PageHeader";
2112
import { Paragraph } from "~/components/primitives/Paragraph";
@@ -32,10 +23,9 @@ import { cn } from "~/utils/cn";
3223
import { $replica } from "~/db.server";
3324
import { useOrganization } from "~/hooks/useOrganizations";
3425
import { rbac } from "~/services/rbac.server";
35-
import {
36-
dashboardLoader,
37-
} from "~/services/routeBuilders/dashboardBuilder";
26+
import { dashboardLoader } from "~/services/routeBuilders/dashboardBuilder";
3827
import { useCurrentPlan } from "../_app.orgs.$organizationSlug/route";
28+
import { TextLink } from "~/components/primitives/TextLink";
3929

4030
export const meta: MetaFunction = () => {
4131
return [
@@ -72,13 +62,12 @@ export const loader = dashboardLoader(
7262
throw new Response("Not Found", { status: 404 });
7363
}
7464

75-
const [roles, assignableRoleIds, allPermissions, systemRoleIds] =
76-
await Promise.all([
77-
rbac.allRoles(orgId),
78-
rbac.getAssignableRoleIds(orgId),
79-
rbac.allPermissions(orgId),
80-
rbac.systemRoleIds(),
81-
]);
65+
const [roles, assignableRoleIds, allPermissions, systemRoleIds] = await Promise.all([
66+
rbac.allRoles(orgId),
67+
rbac.getAssignableRoleIds(orgId),
68+
rbac.allPermissions(orgId),
69+
rbac.systemRoleIds(),
70+
]);
8271

8372
return typedjson({
8473
roles,
@@ -160,15 +149,14 @@ export default function Page() {
160149
// custom roles in the order rbac.allRoles returned them. systemRoleIds
161150
// is null when no plugin is installed — there are no system roles to
162151
// pin; fall through to whatever order rbac.allRoles returns.
163-
const systemRoleOrder: ReadonlyArray<{ id: string; name: string }> =
164-
systemRoleIds
165-
? [
166-
{ id: systemRoleIds.owner, name: "Owner" },
167-
{ id: systemRoleIds.admin, name: "Admin" },
168-
{ id: systemRoleIds.developer, name: "Developer" },
169-
{ id: systemRoleIds.member, name: "Member" },
170-
]
171-
: [];
152+
const systemRoleOrder: ReadonlyArray<{ id: string; name: string }> = systemRoleIds
153+
? [
154+
{ id: systemRoleIds.owner, name: "Owner" },
155+
{ id: systemRoleIds.admin, name: "Admin" },
156+
{ id: systemRoleIds.developer, name: "Developer" },
157+
{ id: systemRoleIds.member, name: "Member" },
158+
]
159+
: [];
172160
const systemRoleIdSet = new Set(systemRoleOrder.map((r) => r.id));
173161
const systemColumns = systemRoleOrder.flatMap((meta) => {
174162
const role = rolesById.get(meta.id);
@@ -190,17 +178,10 @@ export default function Page() {
190178
<PageBody scrollable={false}>
191179
<div className="grid max-h-full min-h-full grid-rows-[auto_1fr]">
192180
<div className="border-b border-grid-bright px-4 py-6">
193-
<Paragraph>
194-
Roles control what each team member can do in{" "}
195-
<strong>{organization.title}</strong>. Compare what each role
196-
grants below; assign a role to a team member from the{" "}
197-
<a
198-
className="text-text-link hover:underline"
199-
href={`/orgs/${organization.slug}/settings/team`}
200-
>
201-
Team page
202-
</a>
203-
.
181+
<Paragraph variant="small">
182+
Roles control what each team member can do in <strong>{organization.title}</strong>.
183+
Compare what each role grants below; assign a role to a team member from the{" "}
184+
<TextLink to={`/orgs/${organization.slug}/settings/team`}>Team page</TextLink>.
204185
</Paragraph>
205186
</div>
206187
<div className="overflow-y-auto scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600">
@@ -236,10 +217,7 @@ export default function Page() {
236217
) : (
237218
grouped.flatMap(({ group, permissions }) => [
238219
<TableRow key={`${group}-header`}>
239-
<TableCell
240-
colSpan={columns.length + 2}
241-
className="bg-charcoal-800"
242-
>
220+
<TableCell colSpan={columns.length + 2} className="bg-charcoal-800">
243221
<Header3 className="text-xs uppercase tracking-wide text-text-dimmed">
244222
{group}
245223
</Header3>
@@ -305,10 +283,7 @@ function PlanBadge({
305283
if (assignable.has(roleId)) return null;
306284
// System role gating: Owner+Admin always available; Member/Developer
307285
// only on Pro+; custom roles only on Enterprise.
308-
if (
309-
systemRoleIds &&
310-
(roleId === systemRoleIds.member || roleId === systemRoleIds.developer)
311-
) {
286+
if (systemRoleIds && (roleId === systemRoleIds.member || roleId === systemRoleIds.developer)) {
312287
return <Badge variant="extra-small">Pro</Badge>;
313288
}
314289
return <Badge variant="extra-small">Enterprise</Badge>;
@@ -355,9 +330,7 @@ function RoleCell({
355330
const conditionalDeny = denied.find((p) => p.conditions);
356331
if (conditionalDeny?.conditions) {
357332
return (
358-
<span className="text-xs text-text-dimmed">
359-
{conditionLabel(conditionalDeny.conditions)}
360-
</span>
333+
<span className="text-xs text-text-dimmed">{conditionLabel(conditionalDeny.conditions)}</span>
361334
);
362335
}
363336
return (
@@ -405,13 +378,12 @@ function CreateRoleUpsell() {
405378
<DialogHeader>Custom roles are an Enterprise feature</DialogHeader>
406379
<div className="flex flex-col gap-3 pt-2">
407380
<Paragraph>
408-
Define your own roles with bespoke permission sets — perfect for
409-
"Member, but no production deploys" or a vendor/contractor role.
410-
Available on the Enterprise plan.
381+
Define your own roles with bespoke permission sets — perfect for "Member, but no
382+
production deploys" or a vendor/contractor role. Available on the Enterprise plan.
411383
</Paragraph>
412384
<Paragraph variant="small" className="text-text-dimmed">
413-
Get in touch and we'll walk you through the Enterprise plan and how
414-
custom roles fit your team.
385+
Get in touch and we'll walk you through the Enterprise plan and how custom roles fit
386+
your team.
415387
</Paragraph>
416388
</div>
417389
<div className="mt-6 flex justify-end gap-2">

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ import * as Property from "~/components/primitives/PropertyTable";
4444
import { Select, SelectItem, SelectLinkItem } from "~/components/primitives/Select";
4545
import { SpinnerWhite } from "~/components/primitives/Spinner";
4646
import { SimpleTooltip } from "~/components/primitives/Tooltip";
47-
import { cn } from "~/utils/cn";
4847
import { $replica } from "~/db.server";
4948
import { useOrganization } from "~/hooks/useOrganizations";
5049
import { useUser } from "~/hooks/useUser";
@@ -53,16 +52,16 @@ import { redirectWithSuccessMessage } from "~/models/message.server";
5352
import { TeamPresenter } from "~/presenters/TeamPresenter.server";
5453
import { rbac } from "~/services/rbac.server";
5554
import { dashboardAction, dashboardLoader } from "~/services/routeBuilders/dashboardBuilder";
55+
import { cn } from "~/utils/cn";
56+
import { formatCurrency, formatNumber } from "~/utils/numberFormatter";
5657
import {
5758
inviteTeamMemberPath,
5859
organizationRolesPath,
5960
organizationTeamPath,
6061
resendInvitePath,
6162
revokeInvitePath,
62-
selectPlanPath,
6363
v3BillingPath,
6464
} from "~/utils/pathBuilder";
65-
import { formatCurrency, formatNumber } from "~/utils/numberFormatter";
6665
import { SetSeatsAddOnService } from "~/v3/services/setSeatsAddOn.server";
6766
import { useCurrentPlan } from "../_app.orgs.$organizationSlug/route";
6867

@@ -620,11 +619,7 @@ function RolePicker({
620619
{role.name}
621620
</SelectItem>
622621
) : (
623-
<SelectLinkItem
624-
key={role.id}
625-
value={role.id}
626-
to={selectPlanPath(organization)}
627-
>
622+
<SelectLinkItem key={role.id} value={role.id} to={v3BillingPath(organization)}>
628623
{role.name} (upgrade)
629624
</SelectLinkItem>
630625
);

0 commit comments

Comments
 (0)