Merge pull request #3244 from fosrl/dev

fix paywalling
This commit is contained in:
Owen Schwartz
2026-06-11 12:27:49 -07:00
committed by GitHub
5 changed files with 57 additions and 76 deletions
@@ -3,7 +3,9 @@ import { authCookieHeader } from "@app/lib/api/cookies";
import { ListOrgLabelsResponse } from "@server/routers/labels/types"; import { ListOrgLabelsResponse } from "@server/routers/labels/types";
import { AxiosResponse } from "axios"; import { AxiosResponse } from "axios";
import OrgLabelsTable from "@app/components/OrgLabelsTable"; import OrgLabelsTable from "@app/components/OrgLabelsTable";
import { PaidFeaturesAlert } from "@app/components/PaidFeaturesAlert";
import SettingsSectionTitle from "@app/components/SettingsSectionTitle"; import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
import { tierMatrix } from "@server/lib/billing/tierMatrix";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { getTranslations } from "next-intl/server"; import { getTranslations } from "next-intl/server";
@@ -49,6 +51,8 @@ export default async function LabelsPage({ params, searchParams }: Props) {
description={t("orgLabelsDescription")} description={t("orgLabelsDescription")}
/> />
<PaidFeaturesAlert tiers={tierMatrix.labels} />
<OrgLabelsTable <OrgLabelsTable
labels={labels} labels={labels}
orgId={orgId} orgId={orgId}
@@ -19,14 +19,14 @@ import {
SettingsSectionBody, SettingsSectionBody,
SettingsSectionDescription, SettingsSectionDescription,
SettingsSectionFooter, SettingsSectionFooter,
SettingsFormCell,
SettingsFormGrid, SettingsFormGrid,
SettingsSectionForm, SettingsSectionForm,
SettingsSectionHeader, SettingsSectionHeader,
SettingsSectionTitle, SettingsSectionTitle,
SettingsSubsectionDescription, SettingsSubsectionDescription,
SettingsSubsectionHeader, SettingsSubsectionHeader,
SettingsSubsectionTitle SettingsSubsectionTitle,
SettingsFormCell
} from "@app/components/Settings"; } from "@app/components/Settings";
import { SwitchInput } from "@app/components/SwitchInput"; import { SwitchInput } from "@app/components/SwitchInput";
import { useEnvContext } from "@app/hooks/useEnvContext"; import { useEnvContext } from "@app/hooks/useEnvContext";
@@ -70,7 +70,7 @@ export default function GeneralForm() {
const api = createApiClient({ env }); const api = createApiClient({ env });
const showResourcePolicy = const hasResourcePolicies =
build !== "oss" && build !== "oss" &&
isPaidUser(tierMatrix[TierFeature.ResourcePolicies]); isPaidUser(tierMatrix[TierFeature.ResourcePolicies]);
@@ -86,7 +86,7 @@ export default function GeneralForm() {
...orgQueries.resourcePolicy({ ...orgQueries.resourcePolicy({
resourcePolicyId: selectedSharedPolicyId! resourcePolicyId: selectedSharedPolicyId!
}), }),
enabled: showResourcePolicy && selectedSharedPolicyId !== null enabled: hasResourcePolicies && selectedSharedPolicyId !== null
}); });
const [resourceFullDomain, setResourceFullDomain] = useState( const [resourceFullDomain, setResourceFullDomain] = useState(
@@ -153,11 +153,10 @@ export default function GeneralForm() {
let resourcePolicyId: number | null | undefined; let resourcePolicyId: number | null | undefined;
if ( if (!["tcp", "udp"].includes(resource.mode)) {
showResourcePolicy && if (hasResourcePolicies || selectedSharedPolicyId === null) {
!["tcp", "udp"].includes(resource.mode) resourcePolicyId = selectedSharedPolicyId;
) { }
resourcePolicyId = selectedSharedPolicyId;
} }
const res = await api const res = await api
@@ -297,28 +296,6 @@ export default function GeneralForm() {
/> />
</SettingsFormCell> </SettingsFormCell>
<SettingsFormCell span="full">
<SettingsSubsectionHeader>
<SettingsSubsectionTitle>
{t(
"resourceGeneralDetailsSubsection"
)}
</SettingsSubsectionTitle>
<SettingsSubsectionDescription>
{t(
[
"tcp",
"udp",
].includes(
resource.mode
)
? "resourceGeneralDetailsSubsectionPortDescription"
: "resourceGeneralDetailsSubsectionDescription"
)}
</SettingsSubsectionDescription>
</SettingsSubsectionHeader>
</SettingsFormCell>
<SettingsFormCell span="half"> <SettingsFormCell span="half">
<FormField <FormField
control={form.control} control={form.control}
@@ -476,8 +453,7 @@ export default function GeneralForm() {
</div> </div>
</SettingsFormCell> </SettingsFormCell>
)} )}
{showResourcePolicy && { !["tcp", "udp"].includes(
!["tcp", "udp"].includes(
resource.mode resource.mode
) && ( ) && (
<> <>
+1 -1
View File
@@ -259,7 +259,7 @@ export const orgNavSections = (
href: "/{orgId}/settings/api-keys", href: "/{orgId}/settings/api-keys",
icon: <KeyRound className="size-4 flex-none" /> icon: <KeyRound className="size-4 flex-none" />
}, },
...(build !== "oss" ...(!env?.flags.disableEnterpriseFeatures
? [ ? [
{ {
title: "labels", title: "labels",
+36 -37
View File
@@ -12,14 +12,7 @@ import { useNavigationContext } from "@app/hooks/useNavigationContext";
import { toast } from "@app/hooks/useToast"; import { toast } from "@app/hooks/useToast";
import { createApiClient, formatAxiosError } from "@app/lib/api"; import { createApiClient, formatAxiosError } from "@app/lib/api";
import { type PaginationState } from "@tanstack/react-table"; import { type PaginationState } from "@tanstack/react-table";
import { import { ArrowRight, MoreHorizontal } from "lucide-react";
ArrowDown01Icon,
ArrowUp10Icon,
ChevronsUpDownIcon,
MoreHorizontal,
PencilIcon,
PencilLineIcon
} from "lucide-react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { usePathname, useRouter } from "next/navigation"; import { usePathname, useRouter } from "next/navigation";
import { useActionState, useMemo, useState, useTransition } from "react"; import { useActionState, useMemo, useState, useTransition } from "react";
@@ -109,7 +102,7 @@ export default function OrgLabelsTable({
cell: ({ row }) => ( cell: ({ row }) => (
<div className="flex items-center gap-1.5 group"> <div className="flex items-center gap-1.5 group">
<div <div
className="size-2.5 rounded-full bg-(--color) flex-none" className="size-2 rounded-full bg-(--color) flex-none"
style={{ style={{
// @ts-expect-error css color // @ts-expect-error css color
"--color": row.original.color "--color": row.original.color
@@ -125,34 +118,40 @@ export default function OrgLabelsTable({
enableHiding: false, enableHiding: false,
header: () => <span className="p-3"></span>, header: () => <span className="p-3"></span>,
cell: ({ row }) => ( cell: ({ row }) => (
<DropdownMenu> <div className="flex items-center gap-2 justify-end">
<DropdownMenuTrigger asChild> <DropdownMenu>
<Button variant="ghost" className="h-8 w-8 p-0"> <DropdownMenuTrigger asChild>
<span className="sr-only">{t("openMenu")}</span> <Button variant="ghost" className="h-8 w-8 p-0">
<MoreHorizontal className="h-4 w-4" /> <span className="sr-only">
</Button> {t("openMenu")}
</DropdownMenuTrigger> </span>
<DropdownMenuContent align="end"> <MoreHorizontal className="h-4 w-4" />
<DropdownMenuItem </Button>
onClick={() => { </DropdownMenuTrigger>
setSelectedLabel(row.original); <DropdownMenuContent align="end">
setIsEditModalOpen(true); <DropdownMenuItem
}} onClick={() => {
> setSelectedLabel(row.original);
{t("edit")} setIsDeleteModalOpen(true);
</DropdownMenuItem> }}
<DropdownMenuItem >
onClick={() => { <span className="text-red-500">
setSelectedLabel(row.original); {t("delete")}
setIsDeleteModalOpen(true); </span>
}} </DropdownMenuItem>
> </DropdownMenuContent>
<span className="text-red-500"> </DropdownMenu>
{t("delete")} <Button
</span> variant="outline"
</DropdownMenuItem> onClick={() => {
</DropdownMenuContent> setSelectedLabel(row.original);
</DropdownMenu> setIsEditModalOpen(true);
}}
>
{t("edit")}
<ArrowRight className="ml-2 w-4 h-4" />
</Button>
</div>
) )
} }
], ],
@@ -73,7 +73,9 @@ export function EditPolicyForm({
} }
const policyTiers = tierMatrix[TierFeature.ResourcePolicies]; const policyTiers = tierMatrix[TierFeature.ResourcePolicies];
const isDisabled = !isPaidUser(policyTiers); const isInlinePolicy = hidePolicyNameForm && resourceId === undefined;
const showPaidAlert = !isInlinePolicy;
const isDisabled = showPaidAlert && !isPaidUser(policyTiers);
const effectiveReadonly = readonly || isDisabled; const effectiveReadonly = readonly || isDisabled;
const authSection = ( const authSection = (
@@ -100,7 +102,7 @@ export function EditPolicyForm({
if (section === "general") { if (section === "general") {
return ( return (
<> <>
<PaidFeaturesAlert tiers={policyTiers} /> {showPaidAlert && <PaidFeaturesAlert tiers={policyTiers} />}
<div <div
className={ className={
isDisabled isDisabled
@@ -117,7 +119,7 @@ export function EditPolicyForm({
if (section === "authentication") { if (section === "authentication") {
return ( return (
<> <>
<PaidFeaturesAlert tiers={policyTiers} /> {showPaidAlert && <PaidFeaturesAlert tiers={policyTiers} />}
<div <div
className={ className={
isDisabled isDisabled
@@ -134,7 +136,7 @@ export function EditPolicyForm({
if (section === "rules") { if (section === "rules") {
return ( return (
<> <>
<PaidFeaturesAlert tiers={policyTiers} /> {showPaidAlert && <PaidFeaturesAlert tiers={policyTiers} />}
<div <div
className={ className={
isDisabled isDisabled
@@ -150,7 +152,7 @@ export function EditPolicyForm({
return ( return (
<> <>
<PaidFeaturesAlert tiers={policyTiers} /> {showPaidAlert && <PaidFeaturesAlert tiers={policyTiers} />}
<div <div
className={ className={
isDisabled ? "pointer-events-none opacity-50" : undefined isDisabled ? "pointer-events-none opacity-50" : undefined