11import { CheckIcon , XMarkIcon } from "@heroicons/react/20/solid" ;
22import { type MetaFunction } from "@remix-run/react" ;
3- import { useState } from "react" ;
43import { type UseDataFunctionReturn , typedjson , useTypedLoaderData } from "remix-typedjson" ;
54import { z } from "zod" ;
65import { PageBody , PageContainer } from "~/components/layout/AppLayout" ;
76import { Badge } from "~/components/primitives/Badge" ;
8- import { Button } from "~/components/primitives/Buttons" ;
9- import { Dialog , DialogContent , DialogHeader , DialogTrigger } from "~/components/primitives/Dialog" ;
107import { Header3 } from "~/components/primitives/Headers" ;
118import { NavBar , PageTitle } from "~/components/primitives/PageHeader" ;
129import { Paragraph } from "~/components/primitives/Paragraph" ;
@@ -24,7 +21,6 @@ import { $replica } from "~/db.server";
2421import { useOrganization } from "~/hooks/useOrganizations" ;
2522import { rbac } from "~/services/rbac.server" ;
2623import { dashboardLoader } from "~/services/routeBuilders/dashboardBuilder" ;
27- import { useCurrentPlan } from "../_app.orgs.$organizationSlug/route" ;
2824import { TextLink } from "~/components/primitives/TextLink" ;
2925
3026export const meta : MetaFunction = ( ) => {
@@ -99,9 +95,6 @@ export default function Page() {
9995 const { roles, assignableRoleIds, allPermissions, systemRoles, isUsingPlugin } =
10096 useTypedLoaderData < typeof loader > ( ) ;
10197 const organization = useOrganization ( ) ;
102- const plan = useCurrentPlan ( ) ;
103- const planCode = plan ?. v3Subscription ?. plan ?. code ;
104- const isEnterprise = planCode === "enterprise" ;
10598
10699 // Map role-id → role for fast cell lookup. Each role's permissions are
107100 // already the expanded `effectivePermissions` output (system roles
@@ -134,12 +127,6 @@ export default function Page() {
134127 < PageContainer >
135128 < NavBar >
136129 < PageTitle title = "Roles" />
137- { /* Suppress the Enterprise-upsell button on OSS — there's no
138- plan to upgrade to in a self-hosted deployment, and the
139- dialog copy ("Available on the Enterprise plan") doesn't
140- apply. The not-supported empty state below makes the
141- absence of role infrastructure clear instead. */ }
142- { isUsingPlugin && ! isEnterprise ? < CreateRoleUpsell /> : null }
143130 </ NavBar >
144131 < PageBody scrollable = { false } >
145132 < div className = "grid max-h-full min-h-full grid-rows-[auto_1fr]" >
@@ -357,40 +344,3 @@ function groupPermissions(
357344 return Array . from ( buckets , ( [ group , permissions ] ) => ( { group, permissions } ) ) ;
358345}
359346
360- function CreateRoleUpsell ( ) {
361- const [ open , setOpen ] = useState ( false ) ;
362- return (
363- < Dialog open = { open } onOpenChange = { setOpen } >
364- < DialogTrigger asChild >
365- < Button variant = "primary/small" > Create role</ Button >
366- </ DialogTrigger >
367- < DialogContent >
368- < DialogHeader > Custom roles are an Enterprise feature</ DialogHeader >
369- < div className = "flex flex-col gap-3 pt-2" >
370- < Paragraph >
371- Define your own roles with bespoke permission sets — perfect for "Member, but no
372- production deploys" or a vendor/contractor role. Available on the Enterprise plan.
373- </ Paragraph >
374- < Paragraph variant = "small" className = "text-text-dimmed" >
375- Get in touch and we'll walk you through the Enterprise plan and how custom roles fit
376- your team.
377- </ Paragraph >
378- </ div >
379- < div className = "mt-6 flex justify-end gap-2" >
380- < Button variant = "secondary/medium" onClick = { ( ) => setOpen ( false ) } >
381- Maybe later
382- </ Button >
383- < Button
384- variant = "primary/medium"
385- onClick = { ( ) => {
386- window . open ( "https://trigger.dev/contact" , "_blank" ) ;
387- setOpen ( false ) ;
388- } }
389- >
390- Contact us
391- </ Button >
392- </ div >
393- </ DialogContent >
394- </ Dialog >
395- ) ;
396- }
0 commit comments