mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-08 22:22:17 +02:00
feat: docs and ui tweaks
This commit is contained in:
parent
64f2b4a6eb
commit
271a21aee6
103 changed files with 2161 additions and 2625 deletions
|
|
@ -1,11 +1,11 @@
|
|||
import {
|
||||
IconBrandGoogle,
|
||||
IconBrandGoogleMaps,
|
||||
IconBrandReddit,
|
||||
IconBrandYoutube,
|
||||
IconWorldWww,
|
||||
} from "@tabler/icons-react";
|
||||
import type { ComponentType } from "react";
|
||||
import {
|
||||
GoogleMapsIcon,
|
||||
GoogleSearchIcon,
|
||||
RedditIcon,
|
||||
WebIcon,
|
||||
YouTubeIcon,
|
||||
} from "./platform-icons";
|
||||
|
||||
/** Icon component that accepts a ``className`` (Tabler + Lucide both satisfy this). */
|
||||
export type PlatformIcon = ComponentType<{ className?: string }>;
|
||||
|
|
@ -36,13 +36,13 @@ export const PLAYGROUND_PLATFORMS: PlaygroundPlatform[] = [
|
|||
{
|
||||
id: "reddit",
|
||||
label: "Reddit",
|
||||
icon: IconBrandReddit,
|
||||
icon: RedditIcon,
|
||||
verbs: [{ name: "reddit.scrape", verb: "scrape", label: "Scrape" }],
|
||||
},
|
||||
{
|
||||
id: "youtube",
|
||||
label: "YouTube",
|
||||
icon: IconBrandYoutube,
|
||||
icon: YouTubeIcon,
|
||||
verbs: [
|
||||
{ name: "youtube.scrape", verb: "scrape", label: "Scrape" },
|
||||
{ name: "youtube.comments", verb: "comments", label: "Comments" },
|
||||
|
|
@ -51,7 +51,7 @@ export const PLAYGROUND_PLATFORMS: PlaygroundPlatform[] = [
|
|||
{
|
||||
id: "google_maps",
|
||||
label: "Google Maps",
|
||||
icon: IconBrandGoogleMaps,
|
||||
icon: GoogleMapsIcon,
|
||||
verbs: [
|
||||
{ name: "google_maps.scrape", verb: "scrape", label: "Scrape" },
|
||||
{ name: "google_maps.reviews", verb: "reviews", label: "Reviews" },
|
||||
|
|
@ -60,13 +60,13 @@ export const PLAYGROUND_PLATFORMS: PlaygroundPlatform[] = [
|
|||
{
|
||||
id: "google_search",
|
||||
label: "Google Search",
|
||||
icon: IconBrandGoogle,
|
||||
icon: GoogleSearchIcon,
|
||||
verbs: [{ name: "google_search.scrape", verb: "scrape", label: "Scrape" }],
|
||||
},
|
||||
{
|
||||
id: "web",
|
||||
label: "Web",
|
||||
icon: IconWorldWww,
|
||||
icon: WebIcon,
|
||||
verbs: [{ name: "web.crawl", verb: "crawl", label: "Crawl" }],
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,11 +1,28 @@
|
|||
/** Formatting helpers shared by the playground runs table and runner output. */
|
||||
|
||||
import type { ScraperPricingMeter } from "@/contracts/types/scraper.types";
|
||||
|
||||
export function formatCost(costMicros: number | null | undefined): string {
|
||||
if (costMicros == null) return "—";
|
||||
if (costMicros === 0) return "Free";
|
||||
return `$${(costMicros / 1_000_000).toFixed(4)}`;
|
||||
}
|
||||
|
||||
/** One meter as a per-1k rate, e.g. 3500 micros/place -> "$3.50 / 1k places". */
|
||||
export function formatRate(meter: ScraperPricingMeter): string {
|
||||
const perThousand = (meter.micros_per_unit * 1000) / 1_000_000;
|
||||
const dollars = Number.isInteger(perThousand)
|
||||
? perThousand.toString()
|
||||
: perThousand.toFixed(2);
|
||||
return `$${dollars} / 1k ${meter.unit}s`;
|
||||
}
|
||||
|
||||
/** A capability's full price line: "Free", one rate, or "rate + rate". */
|
||||
export function formatPricing(pricing: ScraperPricingMeter[] | undefined): string {
|
||||
if (!pricing || pricing.length === 0) return "Free";
|
||||
return pricing.map(formatRate).join(" + ");
|
||||
}
|
||||
|
||||
export function formatDuration(ms: number | null | undefined): string {
|
||||
if (ms == null) return "—";
|
||||
if (ms < 1000) return `${ms}ms`;
|
||||
|
|
|
|||
29
surfsense_web/lib/playground/platform-icons.tsx
Normal file
29
surfsense_web/lib/playground/platform-icons.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import Image from "next/image";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
/**
|
||||
* Full-color brand marks for the platform-native scraper verbs, served from
|
||||
* `/public/connectors/*.svg` (same asset library the connector UI uses). Each
|
||||
* is a `ComponentType<{ className?: string }>` so it drops into the playground
|
||||
* catalog and the composer badge exactly like a Lucide/Tabler icon.
|
||||
*/
|
||||
function brandIcon(src: string, alt: string) {
|
||||
return function BrandIcon({ className }: { className?: string }) {
|
||||
return (
|
||||
<Image
|
||||
src={src}
|
||||
alt={alt}
|
||||
width={20}
|
||||
height={20}
|
||||
className={cn("select-none object-contain pointer-events-none", className)}
|
||||
draggable={false}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export const RedditIcon = brandIcon("/connectors/reddit.svg", "Reddit");
|
||||
export const YouTubeIcon = brandIcon("/connectors/youtube.svg", "YouTube");
|
||||
export const GoogleMapsIcon = brandIcon("/connectors/google-maps.svg", "Google Maps");
|
||||
export const GoogleSearchIcon = brandIcon("/connectors/google-search.svg", "Google Search");
|
||||
export const WebIcon = brandIcon("/connectors/web.svg", "Web");
|
||||
Loading…
Add table
Add a link
Reference in a new issue