Neon / portal template support (#713)

TODOs:
- [x] Do restart when checkout / restore if there is a DB
- [x] List all branches (branch id, name, date)
- [x] Allow checking out versions with no DB
- [x] safeguard to never delete main branches
- [x] create app hook for neon template
- [x] weird UX with connector on configure panel
- [x] tiny neon logo in connector
- [x] deploy to vercel
- [x] build forgot password page
- [x] what about email setup
- [x] lots of imgix errors
- [x] edit file - db snapshot
- [x] DYAD_DISABLE_DB_PUSH
- [ ] update portal doc
- [x] switch preview branch to be read-only endpoint
- [x] disable supabase sys prompt if neon is enabled
- [ ] https://payloadcms.com/docs/upload/storage-adapters
- [x] need to use main branch...

Phase 2?
- [x] generate DB migrations
This commit is contained in:
Will Chen
2025-08-04 16:36:09 -07:00
committed by GitHub
parent 0f1a5c5c77
commit b0f08eaf15
50 changed files with 3525 additions and 205 deletions

View File

@@ -4,17 +4,22 @@ import { IpcClient } from "@/ipc/ipc_client";
import { useSettings } from "@/hooks/useSettings";
import { CommunityCodeConsentDialog } from "./CommunityCodeConsentDialog";
import type { Template } from "@/shared/templates";
import { Button } from "./ui/button";
import { cn } from "@/lib/utils";
import { showWarning } from "@/lib/toast";
interface TemplateCardProps {
template: Template;
isSelected: boolean;
onSelect: (templateId: string) => void;
onCreateApp: () => void;
}
export const TemplateCard: React.FC<TemplateCardProps> = ({
template,
isSelected,
onSelect,
onCreateApp,
}) => {
const { settings, updateSettings } = useSettings();
const [showConsentDialog, setShowConsentDialog] = useState(false);
@@ -26,6 +31,11 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
return;
}
if (template.requiresNeon && !settings?.neon?.accessToken) {
showWarning("Please connect your Neon account to use this template.");
return;
}
// Otherwise, proceed with selection
onSelect(template.id);
};
@@ -93,7 +103,7 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
>
{template.title}
</h2>
{template.isOfficial && (
{template.isOfficial && !template.isExperimental && (
<span
className={`text-xs font-semibold px-2 py-0.5 rounded-full ${
isSelected
@@ -104,8 +114,13 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
Official
</span>
)}
{template.isExperimental && (
<span className="text-xs font-semibold px-2 py-0.5 rounded-full bg-yellow-100 text-yellow-800 dark:bg-yellow-700 dark:text-yellow-200">
Experimental
</span>
)}
</div>
<p className="text-sm text-gray-500 dark:text-gray-400 mb-3 h-8 overflow-y-auto">
<p className="text-sm text-gray-500 dark:text-gray-400 mb-3 h-10 overflow-y-auto">
{template.description}
</p>
{template.githubUrl && (
@@ -121,6 +136,20 @@ export const TemplateCard: React.FC<TemplateCardProps> = ({
<ArrowLeft className="w-4 h-4 ml-1 transform rotate-180" />
</a>
)}
<Button
onClick={(e) => {
e.stopPropagation();
onCreateApp();
}}
size="sm"
className={cn(
"w-full bg-indigo-600 hover:bg-indigo-700 text-white font-semibold mt-2",
settings?.selectedTemplateId !== template.id && "invisible",
)}
>
Create App
</Button>
</div>
</div>