mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-20 23:21:06 +02:00
feat(amazon): enhance playground with Amazon-specific field options and hints
This commit is contained in:
parent
4abf95427b
commit
aa3c62b754
3 changed files with 91 additions and 1 deletions
|
|
@ -14,6 +14,11 @@ import { AppError } from "@/lib/error";
|
|||
import { findVerb } from "@/lib/playground/catalog";
|
||||
import { formatCost, formatDuration, formatPricing } from "@/lib/playground/format";
|
||||
import { buildPayload, initialFormValues, parseSchemaFields } from "@/lib/playground/json-schema";
|
||||
import {
|
||||
AmazonMarketplaceHint,
|
||||
getAmazonFieldOptions,
|
||||
hasAmazonFranceValue,
|
||||
} from "@/lib/playground/platform-overrides/amazon";
|
||||
import { ApiReference } from "./api-reference";
|
||||
import { OutputViewer } from "./output-viewer";
|
||||
import { RunProgressPanel } from "./run-progress-panel";
|
||||
|
|
@ -171,6 +176,8 @@ export function PlaygroundRunner({ workspaceId, platform, verb }: PlaygroundRunn
|
|||
[run.detail]
|
||||
);
|
||||
const endpoint = `POST /workspaces/${workspaceId}/scrapers/${platform}/${verb}`;
|
||||
const isAmazonScrape = platform === "amazon" && verb === "scrape";
|
||||
const hasAmazonFranceUrl = useMemo(() => hasAmazonFranceValue(values), [values]);
|
||||
|
||||
useEffect(() => {
|
||||
const previousStatus = previousStatusRef.current;
|
||||
|
|
@ -260,7 +267,9 @@ export function PlaygroundRunner({ workspaceId, platform, verb }: PlaygroundRunn
|
|||
values={values}
|
||||
onChange={handleChange}
|
||||
disabled={isRunning}
|
||||
getFieldOptions={isAmazonScrape ? getAmazonFieldOptions : undefined}
|
||||
/>
|
||||
{isAmazonScrape ? <AmazonMarketplaceHint showFranceWarning={hasAmazonFranceUrl} /> : null}
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<Button type="button" onClick={handleRun} disabled={isRunning} className="relative">
|
||||
|
|
|
|||
|
|
@ -17,11 +17,19 @@ import { Textarea } from "@/components/ui/textarea";
|
|||
import type { FormField } from "@/lib/playground/json-schema";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export interface FieldOption {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
type FieldOptionsResolver = (field: FormField) => FieldOption[] | undefined;
|
||||
|
||||
interface SchemaFormProps {
|
||||
fields: FormField[];
|
||||
values: Record<string, unknown>;
|
||||
onChange: (name: string, value: unknown) => void;
|
||||
disabled?: boolean;
|
||||
getFieldOptions?: FieldOptionsResolver;
|
||||
/** Field names flagged by a 422 response, shown with error styling. */
|
||||
fieldErrors?: Record<string, string>;
|
||||
}
|
||||
|
|
@ -32,12 +40,14 @@ function FieldControl({
|
|||
onChange,
|
||||
disabled,
|
||||
invalid,
|
||||
options,
|
||||
}: {
|
||||
field: FormField;
|
||||
value: unknown;
|
||||
onChange: (value: unknown) => void;
|
||||
disabled?: boolean;
|
||||
invalid?: boolean;
|
||||
options?: FieldOption[];
|
||||
}) {
|
||||
const id = `field-${field.name}`;
|
||||
|
||||
|
|
@ -68,6 +78,27 @@ function FieldControl({
|
|||
);
|
||||
}
|
||||
|
||||
if (options) {
|
||||
return (
|
||||
<Select
|
||||
value={value ? String(value) : options[0]?.value}
|
||||
onValueChange={onChange}
|
||||
disabled={disabled}
|
||||
>
|
||||
<SelectTrigger id={id} className={cn("w-full", invalid && "border-destructive")}>
|
||||
<SelectValue placeholder="Select…" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{options.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label} ({option.value})
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
||||
if (field.kind === "string_array") {
|
||||
return (
|
||||
<Textarea
|
||||
|
|
@ -116,12 +147,14 @@ function FieldRow({
|
|||
onChange,
|
||||
disabled,
|
||||
error,
|
||||
options,
|
||||
}: {
|
||||
field: FormField;
|
||||
value: unknown;
|
||||
onChange: (value: unknown) => void;
|
||||
disabled?: boolean;
|
||||
error?: string;
|
||||
options?: FieldOption[];
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-1.5">
|
||||
|
|
@ -143,13 +176,21 @@ function FieldRow({
|
|||
onChange={onChange}
|
||||
disabled={disabled}
|
||||
invalid={!!error}
|
||||
options={options}
|
||||
/>
|
||||
{error && <p className="text-xs text-destructive">{error}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function SchemaForm({ fields, values, onChange, disabled, fieldErrors }: SchemaFormProps) {
|
||||
export function SchemaForm({
|
||||
fields,
|
||||
values,
|
||||
onChange,
|
||||
disabled,
|
||||
getFieldOptions,
|
||||
fieldErrors,
|
||||
}: SchemaFormProps) {
|
||||
const [showAdvanced, setShowAdvanced] = useState(false);
|
||||
|
||||
const { primary, advanced } = useMemo(() => {
|
||||
|
|
@ -168,6 +209,7 @@ export function SchemaForm({ fields, values, onChange, disabled, fieldErrors }:
|
|||
onChange={(value) => onChange(field.name, value)}
|
||||
disabled={disabled}
|
||||
error={fieldErrors?.[field.name]}
|
||||
options={getFieldOptions?.(field)}
|
||||
/>
|
||||
))}
|
||||
|
||||
|
|
@ -197,6 +239,7 @@ export function SchemaForm({ fields, values, onChange, disabled, fieldErrors }:
|
|||
onChange={(value) => onChange(field.name, value)}
|
||||
disabled={disabled}
|
||||
error={fieldErrors?.[field.name]}
|
||||
options={getFieldOptions?.(field)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
38
surfsense_web/lib/playground/platform-overrides/amazon.tsx
Normal file
38
surfsense_web/lib/playground/platform-overrides/amazon.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { Info } from "lucide-react";
|
||||
import type { FieldOption } from "@/app/dashboard/[workspace_id]/playground/components/schema-form";
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||
import type { FormField } from "@/lib/playground/json-schema";
|
||||
|
||||
export const AMAZON_DOMAIN_OPTIONS: FieldOption[] = [
|
||||
{ label: "US", value: "www.amazon.com" },
|
||||
{ label: "UK", value: "www.amazon.co.uk" },
|
||||
{ label: "Germany", value: "www.amazon.de" },
|
||||
{ label: "Italy", value: "www.amazon.it" },
|
||||
{ label: "Spain", value: "www.amazon.es" },
|
||||
{ label: "France, best effort", value: "www.amazon.fr" },
|
||||
];
|
||||
|
||||
const AMAZON_SUPPORTED_COUNTRIES = "US, UK, Germany, Italy, Spain, France";
|
||||
|
||||
export function getAmazonFieldOptions(field: FormField): FieldOption[] | undefined {
|
||||
return field.name === "domain" ? AMAZON_DOMAIN_OPTIONS : undefined;
|
||||
}
|
||||
|
||||
export function hasAmazonFranceValue(values: Record<string, unknown>): boolean {
|
||||
return JSON.stringify(values).toLowerCase().includes("amazon.fr");
|
||||
}
|
||||
|
||||
export function AmazonMarketplaceHint({ showFranceWarning }: { showFranceWarning: boolean }) {
|
||||
return (
|
||||
<Alert>
|
||||
<Info />
|
||||
<AlertDescription className="flex flex-wrap items-baseline gap-x-1">
|
||||
<span className="font-medium text-foreground">Supported countries: </span>
|
||||
<span>{AMAZON_SUPPORTED_COUNTRIES}</span>
|
||||
{showFranceWarning
|
||||
? " France is more WAF-sensitive. If this run returns no results, retry later or use another marketplace."
|
||||
: null}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue