feat: allow custom install and start commands (#892)
# Description Gives the ability to define an `install` and `startup` command when importing a project, so we can work on a project locally without any issue. # Preview <img width="2256" height="1422" alt="image" src="https://github.com/user-attachments/assets/2132b1cb-5f71-4b88-84db-8ecc81cf1f66" /> --------- Co-authored-by: Will Chen <willchen90@gmail.com>
This commit is contained in:
@@ -27,6 +27,12 @@ import {
|
||||
import { selectedAppIdAtom } from "@/atoms/appAtoms";
|
||||
import { useSetAtom } from "jotai";
|
||||
import { useLoadApps } from "@/hooks/useLoadApps";
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "./ui/accordion";
|
||||
|
||||
interface ImportAppDialogProps {
|
||||
isOpen: boolean;
|
||||
@@ -39,6 +45,8 @@ export function ImportAppDialog({ isOpen, onClose }: ImportAppDialogProps) {
|
||||
const [customAppName, setCustomAppName] = useState<string>("");
|
||||
const [nameExists, setNameExists] = useState<boolean>(false);
|
||||
const [isCheckingName, setIsCheckingName] = useState<boolean>(false);
|
||||
const [installCommand, setInstallCommand] = useState("pnpm install");
|
||||
const [startCommand, setStartCommand] = useState("pnpm dev");
|
||||
const navigate = useNavigate();
|
||||
const { streamMessage } = useStreamChat({ hasChatId: false });
|
||||
const { refreshApps } = useLoadApps();
|
||||
@@ -89,6 +97,8 @@ export function ImportAppDialog({ isOpen, onClose }: ImportAppDialogProps) {
|
||||
return IpcClient.getInstance().importApp({
|
||||
path: selectedPath,
|
||||
appName: customAppName,
|
||||
installCommand: installCommand || undefined,
|
||||
startCommand: startCommand || undefined,
|
||||
});
|
||||
},
|
||||
onSuccess: async (result) => {
|
||||
@@ -128,6 +138,8 @@ export function ImportAppDialog({ isOpen, onClose }: ImportAppDialogProps) {
|
||||
setHasAiRules(null);
|
||||
setCustomAppName("");
|
||||
setNameExists(false);
|
||||
setInstallCommand("pnpm install");
|
||||
setStartCommand("pnpm dev");
|
||||
};
|
||||
|
||||
const handleAppNameChange = async (
|
||||
@@ -140,6 +152,10 @@ export function ImportAppDialog({ isOpen, onClose }: ImportAppDialogProps) {
|
||||
}
|
||||
};
|
||||
|
||||
const hasInstallCommand = installCommand.trim().length > 0;
|
||||
const hasStartCommand = startCommand.trim().length > 0;
|
||||
const commandsValid = hasInstallCommand === hasStartCommand;
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={onClose}>
|
||||
<DialogContent>
|
||||
@@ -221,6 +237,41 @@ export function ImportAppDialog({ isOpen, onClose }: ImportAppDialogProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Accordion type="single" collapsible>
|
||||
<AccordionItem value="advanced-options">
|
||||
<AccordionTrigger className="text-sm hover:no-underline">
|
||||
Advanced options
|
||||
</AccordionTrigger>
|
||||
<AccordionContent className="space-y-4">
|
||||
<div className="grid gap-2">
|
||||
<Label className="text-sm ml-2 mb-2">
|
||||
Install command
|
||||
</Label>
|
||||
<Input
|
||||
value={installCommand}
|
||||
onChange={(e) => setInstallCommand(e.target.value)}
|
||||
placeholder="pnpm install"
|
||||
disabled={importAppMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<Label className="text-sm ml-2 mb-2">Start command</Label>
|
||||
<Input
|
||||
value={startCommand}
|
||||
onChange={(e) => setStartCommand(e.target.value)}
|
||||
placeholder="pnpm dev"
|
||||
disabled={importAppMutation.isPending}
|
||||
/>
|
||||
</div>
|
||||
{!commandsValid && (
|
||||
<p className="text-sm text-red-500">
|
||||
Both commands are required when customizing.
|
||||
</p>
|
||||
)}
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
|
||||
{hasAiRules === false && (
|
||||
<Alert className="border-yellow-500/20 text-yellow-500 flex items-start gap-2">
|
||||
<TooltipProvider>
|
||||
@@ -264,7 +315,10 @@ export function ImportAppDialog({ isOpen, onClose }: ImportAppDialogProps) {
|
||||
<Button
|
||||
onClick={handleImport}
|
||||
disabled={
|
||||
!selectedPath || importAppMutation.isPending || nameExists
|
||||
!selectedPath ||
|
||||
importAppMutation.isPending ||
|
||||
nameExists ||
|
||||
!commandsValid
|
||||
}
|
||||
className="min-w-[80px]"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user