Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions apps/api/src/app/api/automations/evaluate/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { dbWs } from "@superset/db/client";
import { automations } from "@superset/db/schema";
import { automations, subscriptions } from "@superset/db/schema";
import { ACTIVE_SUBSCRIPTION_STATUSES } from "@superset/shared/billing";
import { nextOccurrenceAfter } from "@superset/shared/rrule";
import { Client, Receiver } from "@upstash/qstash";
import { and, eq, lte } from "drizzle-orm";
import { and, eq, exists, inArray, lte, ne, sql } from "drizzle-orm";

import { env } from "@/env";

Expand Down Expand Up @@ -45,7 +46,26 @@ export async function POST(request: Request): Promise<Response> {
const due = await dbWs
.select()
.from(automations)
.where(and(eq(automations.enabled, true), lte(automations.nextRunAt, now)))
.where(
and(
eq(automations.enabled, true),
lte(automations.nextRunAt, now),
// Catches orgs that downgraded with automations still enabled — the
// create-time gate only blocks new ones.
exists(
dbWs
.select({ one: sql`1` })
.from(subscriptions)
.where(
and(
eq(subscriptions.referenceId, automations.organizationId),
inArray(subscriptions.status, ACTIVE_SUBSCRIPTION_STATUSES),
ne(subscriptions.plan, "free"),
),
),
),
),
)
.orderBy(automations.nextRunAt)
.limit(BATCH_SIZE);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { Badge } from "@superset/ui/badge";
import { MeshGradient } from "@superset/ui/mesh-gradient";
import { cn } from "@superset/ui/utils";
import type { ComponentType } from "react";
import type { ProFeature } from "../../constants";
import { PRO_FEATURES } from "../../constants";
import { CloudWorkspacesDemo } from "./components/CloudWorkspacesDemo";
import { IntegrationsDemo } from "./components/IntegrationsDemo";
import { AutomationsDemo } from "./components/AutomationsDemo";
import { DitheredBackground } from "./components/DitheredBackground";
import { MobileAppDemo } from "./components/MobileAppDemo";
import { RemoteWorkspacesDemo } from "./components/RemoteWorkspacesDemo";
import { TasksDemo } from "./components/TasksDemo";
import { TeamCollaborationDemo } from "./components/TeamCollaborationDemo";

const DEMO_COMPONENTS: Record<string, ComponentType> = {
"team-collaboration": TeamCollaborationDemo,
integrations: IntegrationsDemo,
tasks: TasksDemo,
"cloud-workspaces": CloudWorkspacesDemo,
automations: AutomationsDemo,
"remote-workspaces": RemoteWorkspacesDemo,
"mobile-app": MobileAppDemo,
};

Expand All @@ -27,7 +27,7 @@ export function FeaturePreview({ selectedFeature }: FeaturePreviewProps) {

return (
<div className="flex w-[495px] flex-col">
<div className="relative h-[346px] overflow-hidden">
<div className="relative h-[346px] overflow-hidden bg-[#0a0a0f]">
{PRO_FEATURES.map((proFeature) => (
<div
key={`gradient-${proFeature.id}`}
Expand All @@ -38,7 +38,7 @@ export function FeaturePreview({ selectedFeature }: FeaturePreviewProps) {
: "opacity-0",
)}
>
<MeshGradient
<DitheredBackground
colors={proFeature.gradientColors}
className="absolute inset-0 w-full h-full"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { LuClock, LuPlay } from "react-icons/lu";

const SCHEDULED = [
{ id: "1", name: "Triage new issues", schedule: "Every weekday at 9am" },
{ id: "2", name: "Bump dependencies", schedule: "Every Monday" },
{ id: "3", name: "Sweep stale PRs", schedule: "Every 6 hours" },
];

export function AutomationsDemo() {
return (
<div className="w-full h-full flex items-center justify-center">
<div className="w-[300px] bg-card/90 backdrop-blur-sm rounded-lg border border-border shadow-2xl overflow-hidden">
<div className="flex items-center justify-between px-4 py-3 bg-muted/80 border-b border-border/50">
<div className="flex items-center gap-2">
<div className="flex gap-1.5">
<div className="w-2.5 h-2.5 rounded-full bg-[#ff5f57]" />
<div className="w-2.5 h-2.5 rounded-full bg-[#febc2e]" />
<div className="w-2.5 h-2.5 rounded-full bg-[#28c840]" />
</div>
<span className="text-xs text-muted-foreground ml-1">
Automations
</span>
</div>
</div>

<div className="p-4 space-y-1.5">
{SCHEDULED.map((item) => (
<div
key={item.id}
className="flex items-center gap-2 px-2 py-2 rounded bg-foreground/5"
>
<div className="size-2 rounded-full bg-emerald-500 shrink-0" />
<div className="flex-1 min-w-0">
<div className="text-xs text-foreground/90 truncate">
{item.name}
</div>
<div className="flex items-center gap-1 text-[10px] text-muted-foreground/80">
<LuClock className="size-3 shrink-0" />
<span className="truncate">{item.schedule}</span>
</div>
</div>
<LuPlay className="size-3 text-muted-foreground/60 shrink-0" />
</div>
))}
</div>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AutomationsDemo } from "./AutomationsDemo";

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { lazy, Suspense } from "react";

const Dithering = lazy(() =>
import("@paper-design/shaders-react").then((mod) => ({
default: mod.Dithering,
})),
);

interface DitheredBackgroundProps {
colors: readonly [string, string, string, string];
className?: string;
}

export function DitheredBackground({
colors,
className = "",
}: DitheredBackgroundProps) {
return (
<div className={`${className} pointer-events-none mix-blend-screen`}>
<Suspense fallback={null}>
<Dithering
colorBack="#00000000"
colorFront={colors[0]}
shape="warp"
type="4x4"
speed={0.15}
className="size-full"
minPixelRatio={1}
/>
</Suspense>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { DitheredBackground } from "./DitheredBackground";

This file was deleted.

This file was deleted.

Loading
Loading