Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import {
} from "@/app/(app)/[emailAccountId]/assistant/constants";
import { TooltipExplanation } from "@/components/TooltipExplanation";
import { getEmailTerminology } from "@/utils/terminology";
import type { EmailLabel } from "@/providers/EmailProvider";

export function ActionSummaryCard({
action,
typeOptions,
provider,
labels,
}: {
action: CreateRuleBody["actions"][number];
typeOptions: { label: string; value: ActionType }[];
provider: string;
labels: EmailLabel[];
}) {
// don't display
if (
Expand All @@ -37,13 +40,17 @@ export function ActionSummaryCard({

switch (action.type) {
case ActionType.LABEL: {
const labelValue = action.label?.value || "";
if (action.label?.ai) {
summaryContent = labelValue
? `AI ${terminology.label.action}: ${labelValue}`
const labelId = action.labelId?.value || "";
const labelName = labelId
? labels.find((label) => label.id === labelId)?.name
: action.labelId?.name || "";

if (action.labelId?.ai) {
summaryContent = labelName
? `AI ${terminology.label.action}: ${labelName}`
: `AI ${terminology.label.action}`;
} else {
summaryContent = `${terminology.label.action} as "${labelValue || "unset"}"`;
summaryContent = `${terminology.label.action} as "${labelName || "unset"}"`;
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { CheckCircle2 } from "lucide-react";
import { useRouter } from "next/navigation";
import { prefixPath } from "@/utils/path";
import type { CreateRuleResult } from "@/utils/rule/types";
import { useLabels } from "@/hooks/useLabels";

export function CreatedRulesModal({
open,
Expand Down Expand Up @@ -54,6 +55,8 @@ export function CreatedRulesContent({
router.push(prefixPath(emailAccountId, "/automation?tab=test"));
};

const { userLabels } = useLabels();

return (
<>
<DialogHeader>
Expand Down Expand Up @@ -90,7 +93,11 @@ export function CreatedRulesContent({

<div className="flex items-center gap-2">
<span className="text-sm font-medium">Actions:</span>
<ActionBadges actions={rule.actions} provider={provider} />
<ActionBadges
actions={rule.actions}
provider={provider}
labels={userLabels}
/>
</div>
</div>
</Card>
Expand Down
10 changes: 1 addition & 9 deletions apps/web/app/(app)/[emailAccountId]/assistant/FixWithChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from "@/components/ui/dialog";
import { LoadingContent } from "@/components/LoadingContent";
import { useRules } from "@/hooks/useRules";
import { useAccount } from "@/providers/EmailAccountProvider";
import { useModal } from "@/hooks/useModal";
import { NEW_RULE_ID } from "@/app/(app)/[emailAccountId]/assistant/consts";
import { Label } from "@/components/Input";
Expand All @@ -35,7 +34,6 @@ export function FixWithChat({
result: RunRulesResult | null;
}) {
const { data, isLoading, error } = useRules();
const { emailAccountId } = useAccount();
const { isModalOpen, setIsModalOpen } = useModal();
const [selectedRuleId, setSelectedRuleId] = useState<string | null>(null);
const [explanation, setExplanation] = useState("");
Expand Down Expand Up @@ -107,7 +105,6 @@ export function FixWithChat({
<LoadingContent loading={isLoading} error={error}>
{data && !showExplanation ? (
<RuleMismatch
emailAccountId={emailAccountId}
result={result}
rules={data}
onSelectExpectedRuleId={handleRuleSelect}
Expand Down Expand Up @@ -211,23 +208,18 @@ ${
function RuleMismatch({
result,
rules,
emailAccountId,
onSelectExpectedRuleId,
}: {
result: RunRulesResult | null;
rules: RulesResponse;
emailAccountId: string;
onSelectExpectedRuleId: (ruleId: string | null) => void;
}) {
return (
<div>
<Label name="matchedRule" label="Matched:" />
<div className="mt-1">
{result ? (
<ProcessResultDisplay
result={result}
emailAccountId={emailAccountId}
/>
<ProcessResultDisplay result={result} />
) : (
<p>No rule matched</p>
)}
Expand Down
117 changes: 67 additions & 50 deletions apps/web/app/(app)/[emailAccountId]/assistant/ProcessResultDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
"use client";

import Link from "next/link";
import { capitalCase } from "capital-case";
import { CheckCircle2Icon, EyeIcon, ExternalLinkIcon } from "lucide-react";
import type { RunRulesResult } from "@/utils/ai/choose-rule/run-rules";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { HoverCard } from "@/components/HoverCard";
import { Badge } from "@/components/Badge";
import { isAIRule } from "@/utils/condition";
import { prefixPath } from "@/utils/path";
import { ActionType } from "@prisma/client";
import { useRuleDialog } from "./RuleDialog";

export function ProcessResultDisplay({
result,
prefix,
emailAccountId,
}: {
result: RunRulesResult;
prefix?: string;
emailAccountId: string;
}) {
const { ruleDialog, RuleDialogComponent } = useRuleDialog();

if (!result) return null;

if (!result.rule) {
Expand Down Expand Up @@ -48,6 +47,36 @@ export function ProcessResultDisplay({
);
}

const handleViewRule = (ruleId: string) => {
ruleDialog.onOpen({ ruleId });
};

return (
<>
<HoverCard
className="w-auto max-w-5xl"
content={
<ActionSummaryCard result={result} onViewRule={handleViewRule} />
}
>
<Badge color="green">
{prefix ? prefix : ""}
{result.rule.name}
<EyeIcon className="ml-1.5 size-3.5 opacity-70" />
</Badge>
</HoverCard>
<RuleDialogComponent />
</>
);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

function ActionSummaryCard({
result,
onViewRule,
}: {
result: RunRulesResult;
onViewRule: (ruleId: string) => void;
}) {
const MAX_LENGTH = 280;

const aiGeneratedContent = result.actionItems
Expand Down Expand Up @@ -91,52 +120,40 @@ export function ProcessResultDisplay({
</div>
));

if (!result.rule) return null;

return (
<HoverCard
className="w-auto max-w-5xl"
content={
<Alert variant="blue" className="max-w-prose bg-background">
<CheckCircle2Icon className="h-4 w-4" />
<AlertTitle className="flex items-center justify-between">
Matched rule "{result.rule.name}"
<Link
href={prefixPath(
emailAccountId,
`/assistant?tab=rule&ruleId=${result.rule.id}`,
)}
target="_blank"
className="ml-1.5"
>
<span className="sr-only">View rule</span>
<ExternalLinkIcon className="size-3.5 opacity-70" />
</Link>
</AlertTitle>
<AlertDescription className="mt-2 space-y-4">
{isAIRule(result.rule) && (
<div className="text-sm">
<span className="font-medium">AI Instructions: </span>
{result.rule.instructions.substring(0, MAX_LENGTH)}
{result.rule.instructions.length >= MAX_LENGTH && "..."}
</div>
)}
{!!aiGeneratedContent?.length && (
<div className="space-y-3">{aiGeneratedContent}</div>
)}
{!!result.reason && (
<div className="border-l-2 border-blue-200 pl-3 text-sm">
<span className="font-medium">Reason: </span>
{result.reason}
</div>
)}
</AlertDescription>
</Alert>
}
>
<Badge color="green">
{prefix ? prefix : ""}
{result.rule.name}
<EyeIcon className="ml-1.5 size-3.5 opacity-70" />
</Badge>
</HoverCard>
<Alert variant="blue" className="max-w-prose bg-background">
<CheckCircle2Icon className="h-4 w-4" />
<AlertTitle className="flex items-center justify-between">
Matched rule "{result.rule.name}"
<button
onClick={() => onViewRule(result.rule!.id)}
className="ml-1.5"
type="button"
>
<span className="sr-only">View rule</span>
<ExternalLinkIcon className="size-3.5 opacity-70" />
</button>
</AlertTitle>
<AlertDescription className="mt-2 space-y-4">
{isAIRule(result.rule) && (
<div className="text-sm">
<span className="font-medium">AI Instructions: </span>
{result.rule.instructions.substring(0, MAX_LENGTH)}
{result.rule.instructions.length >= MAX_LENGTH && "..."}
</div>
)}
{!!aiGeneratedContent?.length && (
<div className="space-y-3">{aiGeneratedContent}</div>
)}
{!!result.reason && (
<div className="border-l-2 border-blue-200 pl-3 text-sm">
<span className="font-medium">Reason: </span>
{result.reason}
</div>
)}
</AlertDescription>
</Alert>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ export function ProcessRulesContent({ testMode }: { testMode: boolean }) {
result={allResults[message.id]}
onRun={(rerun) => onRun(message, rerun)}
testMode={testMode}
emailAccountId={emailAccountId}
setInput={setInput}
/>
))}
Expand Down Expand Up @@ -336,7 +335,6 @@ function ProcessRulesRow({
result,
onRun,
testMode,
emailAccountId,
setInput,
}: {
message: Message;
Expand All @@ -345,7 +343,6 @@ function ProcessRulesRow({
result: RunRulesResult;
onRun: (rerun?: boolean) => void;
testMode: boolean;
emailAccountId: string;
setInput: (input: string) => void;
}) {
return (
Expand All @@ -369,10 +366,7 @@ function ProcessRulesRow({
{result ? (
<>
<div className="flex max-w-xs flex-col justify-center gap-0.5 whitespace-nowrap">
<ProcessResultDisplay
result={result}
emailAccountId={emailAccountId}
/>
<ProcessResultDisplay result={result} />
</div>
<FixWithChat
setInput={setInput}
Expand Down
Loading
Loading