-
-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat(block): built-in remix * fix: improve remix prompt * refactor(extension): new layout for extension editor * refactor: extension config * feat(lab): input editor * feat(extension): generate extension code via chat * fix: updat block template * fix(v3): support use-toast * chore(i18n): i18n for ext * chore: disable electron prerelease update channel * feat: save chat history * feat: Add confirmation dialog for LLM provider deletion * fix: disable chat for prompt&udf * feat: add alpha status indicator for UDF feature * Update to version 0.11.0
- Loading branch information
Showing
98 changed files
with
8,564 additions
and
979 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
apps/web-app/[database]/scripts/components/NewExtensionButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { ChevronDownIcon } from "lucide-react" | ||
import { useTranslation } from "react-i18next" | ||
|
||
import { Badge } from "@/components/ui/badge" | ||
import { Button } from "@/components/ui/button" | ||
import { | ||
DropdownMenu, | ||
DropdownMenuContent, | ||
DropdownMenuItem, | ||
DropdownMenuLabel, | ||
DropdownMenuSeparator, | ||
DropdownMenuTrigger, | ||
} from "@/components/ui/dropdown-menu" | ||
|
||
import { useNewScript } from "../hooks/use-new-script" | ||
|
||
const ScriptTooltip = ({ children }: { children: React.ReactNode }) => { | ||
return ( | ||
<div | ||
className="ring invisible group-hover:visible absolute left-full top-0 ml-2 w-64 rounded-md border bg-popover p-3 text-sm before:absolute before:-left-4 before:top-0 before:h-full before:w-4" | ||
onClick={(e) => e.stopPropagation()} | ||
> | ||
{children} | ||
</div> | ||
) | ||
} | ||
|
||
export const NewExtensionButton = () => { | ||
const { handleCreateNewScript } = useNewScript() | ||
const { t } = useTranslation() | ||
|
||
return ( | ||
<DropdownMenu> | ||
<DropdownMenuTrigger asChild> | ||
<Button size="xs"> | ||
{t('common.new')} <ChevronDownIcon className="ml-1 h-4 w-4" /> | ||
</Button> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent className="overflow-visible"> | ||
<DropdownMenuLabel>{t('extension.createNew')}</DropdownMenuLabel> | ||
<DropdownMenuSeparator /> | ||
<DropdownMenuItem | ||
className="group relative" | ||
onClick={() => handleCreateNewScript("m_block")} | ||
> | ||
{t('extension.microBlock')} <Badge variant="secondary">{t('common.badge.new')}</Badge> | ||
<ScriptTooltip> | ||
{t('extension.microBlockDescription')} | ||
</ScriptTooltip> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem | ||
className="group relative" | ||
onClick={() => handleCreateNewScript()} | ||
> | ||
{t('extension.script')} | ||
<ScriptTooltip> | ||
{t('extension.scriptDescription')} | ||
</ScriptTooltip> | ||
</DropdownMenuItem> | ||
|
||
<DropdownMenuItem | ||
className="group relative" | ||
onClick={() => handleCreateNewScript("udf")} | ||
> | ||
{t('extension.udf')} <Badge variant="secondary">{t('common.badge.alpha')}</Badge> | ||
<ScriptTooltip> | ||
{t('extension.udfDescription')} | ||
<br /> | ||
<span className="text-red-400"> | ||
{t('extension.udfWarning')} | ||
</span> | ||
</ScriptTooltip> | ||
</DropdownMenuItem> | ||
<DropdownMenuItem | ||
className="group relative" | ||
onClick={() => handleCreateNewScript("prompt")} | ||
> | ||
{t('extension.prompt')} | ||
<ScriptTooltip>{t('extension.promptDescription')}</ScriptTooltip> | ||
</DropdownMenuItem> | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
) | ||
} |
136 changes: 136 additions & 0 deletions
136
apps/web-app/[database]/scripts/components/ScriptCard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import { IScript } from "@/worker/web-worker/meta-table/script" | ||
import { | ||
AppWindowIcon, | ||
FunctionSquareIcon, | ||
RotateCcwIcon, | ||
ShapesIcon, | ||
SparkleIcon, | ||
SquareCodeIcon, | ||
ToyBrickIcon, | ||
} from "lucide-react" | ||
import { Link } from "react-router-dom" | ||
|
||
import { cn } from "@/lib/utils" | ||
import { | ||
AlertDialog, | ||
AlertDialogAction, | ||
AlertDialogCancel, | ||
AlertDialogContent, | ||
AlertDialogDescription, | ||
AlertDialogFooter, | ||
AlertDialogHeader, | ||
AlertDialogTitle, | ||
AlertDialogTrigger, | ||
} from "@/components/ui/alert-dialog" | ||
import { Button } from "@/components/ui/button" | ||
import { Switch } from "@/components/ui/switch" | ||
import { useTranslation } from "react-i18next" | ||
|
||
const IconMap = { | ||
script: SquareCodeIcon, | ||
udf: FunctionSquareIcon, | ||
prompt: SparkleIcon, | ||
block: ShapesIcon, | ||
m_block: ToyBrickIcon, | ||
app: AppWindowIcon, | ||
} | ||
|
||
interface ScriptCardProps { | ||
script: IScript | ||
space: string | ||
onDelete: (id: string) => void | ||
onToggleEnabled: (script: IScript, checked: boolean) => void | ||
showReload?: boolean | ||
onReload?: () => void | ||
} | ||
|
||
export const ScriptCard = ({ | ||
script, | ||
space, | ||
onDelete, | ||
onToggleEnabled, | ||
showReload, | ||
onReload, | ||
}: ScriptCardProps) => { | ||
const { t } = useTranslation() | ||
const Icon = IconMap[script.type] | ||
|
||
return ( | ||
<div className="group relative overflow-hidden rounded-lg border bg-card text-card-foreground shadow transition-all hover:shadow-lg flex flex-col min-h-[160px]"> | ||
<div className="flex flex-col space-y-1.5 p-4"> | ||
<div className="flex items-center gap-2"> | ||
<Icon className="h-10 w-10 shrink-0 opacity-70" /> | ||
<div> | ||
<h3 className="text-lg font-semibold tracking-tight"> | ||
{script.name}{" "} | ||
<span className="text-sm text-muted-foreground"> | ||
{t("extension.version", { version: script.version })} | ||
</span> | ||
</h3> | ||
<p className="text-sm text-muted-foreground"> | ||
{script.description} | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div | ||
className={cn("flex items-center justify-between p-4 pt-0 mt-auto", { | ||
"opacity-0 pointer-events-none": ["block", "app"].includes( | ||
script.type | ||
), | ||
})} | ||
> | ||
<div className="flex items-center gap-2"> | ||
<Link to={`/${space}/extensions/${script.id}`}> | ||
<Button size="xs" variant="outline"> | ||
{t("extension.details")} | ||
</Button> | ||
</Link> | ||
<AlertDialog> | ||
<AlertDialogTrigger asChild> | ||
<Button size="xs" variant="ghost"> | ||
{t("common.delete")} | ||
</Button> | ||
</AlertDialogTrigger> | ||
<AlertDialogContent> | ||
<AlertDialogHeader> | ||
<AlertDialogTitle> | ||
{t("extension.deleteScriptConfirm")} | ||
</AlertDialogTitle> | ||
<AlertDialogDescription> | ||
{t("extension.deleteScriptDescription")} | ||
</AlertDialogDescription> | ||
</AlertDialogHeader> | ||
<AlertDialogFooter> | ||
<AlertDialogCancel>{t("common.cancel")}</AlertDialogCancel> | ||
<AlertDialogAction onClick={() => onDelete(script.id)}> | ||
{t("common.continue")} | ||
</AlertDialogAction> | ||
</AlertDialogFooter> | ||
</AlertDialogContent> | ||
</AlertDialog> | ||
</div> | ||
|
||
<div className="flex items-center gap-2"> | ||
{script.type !== "app" && ( | ||
<Switch | ||
checked={script.enabled} | ||
onCheckedChange={(checked) => onToggleEnabled(script, checked)} | ||
/> | ||
)} | ||
{showReload && ( | ||
<Button | ||
onClick={onReload} | ||
variant="ghost" | ||
size="icon" | ||
title={t("extension.reloadLocalScript")} | ||
> | ||
<RotateCcwIcon className="h-4 w-4" /> | ||
</Button> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} |
40 changes: 40 additions & 0 deletions
40
apps/web-app/[database]/scripts/components/extension-breadcrumb.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { Link } from "react-router-dom" | ||
import { useTranslation } from "react-i18next" | ||
|
||
import { useCurrentPathInfo } from "@/hooks/use-current-pathinfo" | ||
import { | ||
Breadcrumb, | ||
BreadcrumbItem, | ||
BreadcrumbLink, | ||
BreadcrumbList, | ||
BreadcrumbPage, | ||
BreadcrumbSeparator, | ||
} from "@/components/ui/breadcrumb" | ||
|
||
import { useScriptById } from "../hooks/use-script" | ||
|
||
interface ScriptBreadcrumbProps { | ||
scriptId: string | ||
} | ||
|
||
export const ScriptBreadcrumb = ({ scriptId }: ScriptBreadcrumbProps) => { | ||
const script = useScriptById(scriptId) | ||
const { space } = useCurrentPathInfo() | ||
const { t } = useTranslation() | ||
|
||
return ( | ||
<Breadcrumb> | ||
<BreadcrumbList> | ||
<BreadcrumbItem> | ||
<BreadcrumbLink asChild> | ||
<Link to={`/${space}/extensions`}>{t("extension.breadcrumb.extensions")}</Link> | ||
</BreadcrumbLink> | ||
<BreadcrumbSeparator /> | ||
</BreadcrumbItem> | ||
<BreadcrumbItem> | ||
<BreadcrumbPage>{script?.name}</BreadcrumbPage> | ||
</BreadcrumbItem> | ||
</BreadcrumbList> | ||
</Breadcrumb> | ||
) | ||
} |
Oops, something went wrong.