Compare commits
No commits in common. "main" and "main" have entirely different histories.
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"enableAllProjectMcpServers": false
|
|
||||||
}
|
|
@ -63,11 +63,14 @@ export default async function Page() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: We're keeping the token approach for now, but aware it's not working
|
||||||
|
const authToken = githubAccount.accessToken;
|
||||||
|
|
||||||
// Try using GitHub token
|
// Try using GitHub token
|
||||||
let octokit;
|
let octokit;
|
||||||
try {
|
try {
|
||||||
octokit = new Octokit({
|
octokit = new Octokit({
|
||||||
auth: process.env.GITHUB_TOKEN
|
auth: authToken || process.env.GITHUB_TOKEN
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test with a simple request
|
// Test with a simple request
|
||||||
@ -142,7 +145,7 @@ export default async function Page() {
|
|||||||
Failed to access GitHub API
|
Failed to access GitHub API
|
||||||
</div>
|
</div>
|
||||||
<div className="text-red-500 mb-4">
|
<div className="text-red-500 mb-4">
|
||||||
{authError instanceof Error ? authError.message : 'An error occurred'}
|
{authError.message}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-muted-foreground text-center max-w-md mb-6">
|
<div className="text-muted-foreground text-center max-w-md mb-6">
|
||||||
<p>This issue may be related to how Clerk is managing the GitHub token.</p>
|
<p>This issue may be related to how Clerk is managing the GitHub token.</p>
|
||||||
@ -179,7 +182,7 @@ export default async function Page() {
|
|||||||
Failed to authenticate with GitHub
|
Failed to authenticate with GitHub
|
||||||
</div>
|
</div>
|
||||||
<div className="text-red-500">
|
<div className="text-red-500">
|
||||||
{error instanceof Error ? error.message : 'Unknown error occurred'}
|
{error.message}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
|
@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'
|
|||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import { X } from 'lucide-react'
|
import { X } from 'lucide-react'
|
||||||
import { useTheme } from 'next-themes'
|
import { useTheme } from 'next-themes'
|
||||||
import { useOnboarding } from '@/components/onboarding/store'
|
import { useOnboarding } from '@/components/onboarding/useOnboarding'
|
||||||
import { ConnectStep } from '@/components/onboarding/connect-step/connect-step'
|
import { ConnectStep } from '@/components/onboarding/connect-step/connect-step'
|
||||||
import { ConfigureStep } from '@/components/onboarding/configure-step/configure-step'
|
import { ConfigureStep } from '@/components/onboarding/configure-step/configure-step'
|
||||||
import { DeployStep } from '@/components/onboarding/deploy-step/deploy-step'
|
import { DeployStep } from '@/components/onboarding/deploy-step/deploy-step'
|
||||||
|
@ -30,7 +30,7 @@ export default function DeploymentsPage() {
|
|||||||
|
|
||||||
// State for deployment logs modal
|
// State for deployment logs modal
|
||||||
const [isLogsOpen, setIsLogsOpen] = useState(false);
|
const [isLogsOpen, setIsLogsOpen] = useState(false);
|
||||||
const [, setSelectedDeploymentId] = useState<string | null>(null);
|
const [selectedDeploymentId, setSelectedDeploymentId] = useState<string | null>(null);
|
||||||
const [deploymentLogs, setDeploymentLogs] = useState<string>('');
|
const [deploymentLogs, setDeploymentLogs] = useState<string>('');
|
||||||
|
|
||||||
// Create a default deployment
|
// Create a default deployment
|
||||||
@ -48,6 +48,19 @@ export default function DeploymentsPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const secondDeployment: Deployment = {
|
||||||
|
id: 'previous',
|
||||||
|
branch: 'feature/new-ui',
|
||||||
|
status: 'COMPLETED',
|
||||||
|
isCurrent: false,
|
||||||
|
createdAt: Date.now() - 3 * 24 * 60 * 60 * 1000, // 3 days ago
|
||||||
|
applicationDeploymentRecordData: {
|
||||||
|
url: repoData ? `https://dev.${repoData.name.toLowerCase()}.example.com` : 'https://dev.example.com'
|
||||||
|
},
|
||||||
|
createdBy: {
|
||||||
|
name: repoData?.owner?.login || 'username'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Initialize with empty data for testing the empty state
|
// Initialize with empty data for testing the empty state
|
||||||
// Comment this out to see the mock deployments
|
// Comment this out to see the mock deployments
|
||||||
@ -66,9 +79,7 @@ export default function DeploymentsPage() {
|
|||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
name: repoData ? `${repoData.name.toLowerCase()}.example.com` : 'example.com',
|
name: repoData ? `${repoData.name.toLowerCase()}.example.com` : 'example.com',
|
||||||
branch: 'main', // Add missing branch
|
|
||||||
status: 'ACTIVE',
|
status: 'ACTIVE',
|
||||||
createdAt: Date.now(), // Add missing createdAt
|
|
||||||
isCustom: false
|
isCustom: false
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -3,7 +3,12 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { LoadingOverlay } from "@/components/foundation/loading/loading-overlay";
|
import { LoadingOverlay } from "@/components/foundation/loading/loading-overlay";
|
||||||
import { PlusIcon, ChevronDownIcon, ChevronUpIcon, PencilIcon, TrashIcon } from "lucide-react";
|
import { PlusIcon, ChevronDownIcon, ChevronUpIcon, PencilIcon, TrashIcon } from "lucide-react";
|
||||||
import type { EnvVarItem } from '@/types'
|
|
||||||
|
interface EnvVarItem {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
isEditing?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface EnvGroupProps {
|
interface EnvGroupProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -199,7 +204,7 @@ export default function EnvVarsPage() {
|
|||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="p-2 hover:bg-accent hover:text-accent-foreground rounded-md text-foreground transition-colors"
|
className="p-2 hover:bg-accent hover:text-accent-foreground rounded-md text-foreground transition-colors"
|
||||||
onClick={() => updateVariable(env, index, variable.key || '', variable.value || '')}
|
onClick={() => updateVariable(env, index, variable.key, variable.value)}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
|
@ -278,9 +278,11 @@ export default function ProjectSettingsPage({ project, onProjectUpdated }: Proje
|
|||||||
Select account
|
Select account
|
||||||
</Label>
|
</Label>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
placeholder="Select"
|
label="Select"
|
||||||
options={accountOptions}
|
options={accountOptions}
|
||||||
onChange={(option) => setSelectedAccount(option.value)}
|
selectedValue={selectedAccount}
|
||||||
|
onSelect={(value) => setSelectedAccount(value)}
|
||||||
|
className="w-full mt-1"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -0,0 +1,159 @@
|
|||||||
|
'use client'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { PageWrapper } from '@/components/foundation'
|
||||||
|
import { FixedProjectCard } from '@/components/projects/project/ProjectCard/FixedProjectCard'
|
||||||
|
import { Button } from '@workspace/ui/components/button'
|
||||||
|
import { Shapes } from 'lucide-react'
|
||||||
|
import { useAuth } from '@clerk/nextjs'
|
||||||
|
|
||||||
|
interface Deployment {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
repositoryId: string
|
||||||
|
status: 'running' | 'complete' | 'failed'
|
||||||
|
url?: string
|
||||||
|
branch: string
|
||||||
|
createdAt: string
|
||||||
|
createdBy: {
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ProjectsPage() {
|
||||||
|
const [deployments, setDeployments] = useState<Deployment[]>([])
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(true)
|
||||||
|
const [error, setError] = useState<string | null>(null)
|
||||||
|
|
||||||
|
const { isLoaded: isAuthLoaded, userId } = useAuth()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchDeployments() {
|
||||||
|
if (!isAuthLoaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!userId) {
|
||||||
|
setError('Not authenticated');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In a real implementation, you would query your GraphQL backend
|
||||||
|
// For now, we'll mock some deployments
|
||||||
|
const mockDeployments: Deployment[] = [
|
||||||
|
{
|
||||||
|
id: 'dep_abc123',
|
||||||
|
name: 'My Project',
|
||||||
|
repositoryId: '123456',
|
||||||
|
status: 'complete',
|
||||||
|
url: 'https://my-project.example.com',
|
||||||
|
branch: 'main',
|
||||||
|
createdAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
|
||||||
|
createdBy: {
|
||||||
|
name: 'John Doe'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'dep_def456',
|
||||||
|
name: 'Another Project',
|
||||||
|
repositoryId: '789012',
|
||||||
|
status: 'running',
|
||||||
|
branch: 'develop',
|
||||||
|
createdAt: new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString(),
|
||||||
|
createdBy: {
|
||||||
|
name: 'Jane Smith'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
setDeployments(mockDeployments);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching deployments:', err)
|
||||||
|
setError('Failed to fetch deployments')
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchDeployments()
|
||||||
|
}, [isAuthLoaded, userId]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageWrapper
|
||||||
|
header={{
|
||||||
|
title: 'Projects',
|
||||||
|
actions: [{ label: 'Create Project', href: '/projects/create' }]
|
||||||
|
}}
|
||||||
|
layout="bento"
|
||||||
|
className="pb-0"
|
||||||
|
>
|
||||||
|
{isLoading ? (
|
||||||
|
<div className="md:col-span-3 flex justify-center items-center min-h-[600px]">
|
||||||
|
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-primary"></div>
|
||||||
|
</div>
|
||||||
|
) : error ? (
|
||||||
|
<div className="md:col-span-3 border border-gray-800 rounded-lg min-h-[600px] flex flex-col items-center justify-center p-6">
|
||||||
|
<div className="mb-6">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<Shapes size={64} className="stroke-current" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2 className="text-xl font-semibold mb-2">Error: {error}</h2>
|
||||||
|
<p className="text-gray-400 text-center max-w-md mb-6">
|
||||||
|
There was an error loading your deployments.
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
className="bg-white text-black hover:bg-gray-200"
|
||||||
|
onClick={() => window.location.reload()}
|
||||||
|
>
|
||||||
|
Try Again
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : deployments.length === 0 ? (
|
||||||
|
<div className="md:col-span-3 border border-gray-800 rounded-lg min-h-[600px] flex flex-col items-center justify-center p-6">
|
||||||
|
<div className="mb-6">
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<Shapes size={64} className="stroke-current" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h2 className="text-xl font-semibold mb-2">Deploy your first app</h2>
|
||||||
|
<p className="text-gray-400 text-center max-w-md mb-6">
|
||||||
|
You haven't deployed any projects yet. Start by importing a repository from your GitHub account.
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
className="bg-white text-black hover:bg-gray-200"
|
||||||
|
onClick={() => window.location.href = '/projects/create'}
|
||||||
|
>
|
||||||
|
Create Project
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="md:col-span-3">
|
||||||
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
{deployments.map((deployment) => (
|
||||||
|
<FixedProjectCard
|
||||||
|
project={{
|
||||||
|
id: deployment.id,
|
||||||
|
name: deployment.name,
|
||||||
|
deployments: [{
|
||||||
|
applicationDeploymentRecordData: {
|
||||||
|
url: deployment.url
|
||||||
|
},
|
||||||
|
branch: deployment.branch,
|
||||||
|
createdAt: deployment.createdAt,
|
||||||
|
createdBy: deployment.createdBy
|
||||||
|
}]
|
||||||
|
}}
|
||||||
|
key={deployment.id}
|
||||||
|
status={deployment.status === 'complete' ? 'success' :
|
||||||
|
deployment.status === 'running' ? 'pending' : 'error'}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</PageWrapper>
|
||||||
|
)
|
||||||
|
}
|
@ -42,7 +42,6 @@ export default function ProjectOverviewPage() {
|
|||||||
const [deployments, setDeployments] = useState<any[]>([]);
|
const [deployments, setDeployments] = useState<any[]>([]);
|
||||||
const [filteredDeployments, setFilteredDeployments] = useState<any[]>([]);
|
const [filteredDeployments, setFilteredDeployments] = useState<any[]>([]);
|
||||||
const [isLogsOpen, setIsLogsOpen] = useState(false);
|
const [isLogsOpen, setIsLogsOpen] = useState(false);
|
||||||
const [, setSelectedDeploymentId] = useState<string | null>(null);
|
|
||||||
const [deploymentLogs, setDeploymentLogs] = useState<string>('');
|
const [deploymentLogs, setDeploymentLogs] = useState<string>('');
|
||||||
|
|
||||||
// Load project data
|
// Load project data
|
||||||
@ -139,25 +138,18 @@ export default function ProjectOverviewPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Handle deployment logs
|
// Handle deployment logs
|
||||||
const handleViewLogs = (deploymentId: string) => {
|
const handleViewLogs = () => {
|
||||||
setSelectedDeploymentId(deploymentId);
|
const mockLogs = `[2025-02-12 10:03:12] INFO Starting deployment process for service: ${project?.name}
|
||||||
|
[2025-02-12 10:03:14] INFO Fetching latest commit from main branch (commit: a1b2c3d)
|
||||||
// Mock logs data
|
[2025-02-12 10:03:15] INFO Building Docker image: registry.company.com/${project?.name}:latest
|
||||||
const mockLogs = `[2025-02-12 10:03:12] INFO Starting deployment process for service: api-gateway
|
[2025-02-12 10:03:26] INFO Running security scan on built image
|
||||||
[2025-02-12 10:03:14] INFO Fetching latest commit from main branch (commit: a1b2c3d)
|
[2025-02-12 10:03:30] INFO Pushing image to container registry
|
||||||
[2025-02-12 10:03:15] INFO Building Docker image: registry.company.com/api-gateway:latest
|
[2025-02-12 10:03:35] INFO Updating deployment configuration
|
||||||
[2025-02-12 10:03:26] INFO Running security scan on built image
|
[2025-02-12 10:03:40] INFO Scaling down old pods
|
||||||
[2025-02-12 10:03:27] WARNING Medium severity vulnerability detected in package 'openssl'
|
[2025-02-12 10:03:42] INFO Scaling up new pods
|
||||||
[2025-02-12 10:03:30] INFO Pushing image to container registry
|
[2025-02-12 10:03:50] INFO Running health checks on new pods
|
||||||
[2025-02-12 10:03:35] INFO Updating Kubernetes deployment
|
[2025-02-12 10:03:55] INFO Deployment completed successfully
|
||||||
[2025-02-12 10:03:40] INFO Scaling down old pods
|
[2025-02-12 10:03:56] INFO Service is now live at ${currentDeployment?.applicationDeploymentRecordData?.url}`;
|
||||||
[2025-02-12 10:03:42] INFO Scaling up new pods
|
|
||||||
[2025-02-12 10:03:50] INFO Running health checks on new pods
|
|
||||||
[2025-02-12 10:03:52] ERROR Pod 'api-gateway-7df9bbb500-tx2k4' failed readiness probe (502 Bad Gateway)
|
|
||||||
[2025-02-12 10:03:55] INFO Retrying deployment with previous stable image
|
|
||||||
[2025-02-12 10:04:03] INFO Rolling back to registry.company.com/api-gateway:previous
|
|
||||||
[2025-02-12 10:04:10] INFO Deployment rolled back successfully
|
|
||||||
[2025-02-12 10:04:11] ERROR Deployment failed, please review logs and fix errors`;
|
|
||||||
|
|
||||||
setDeploymentLogs(mockLogs);
|
setDeploymentLogs(mockLogs);
|
||||||
setIsLogsOpen(true);
|
setIsLogsOpen(true);
|
||||||
|
@ -156,7 +156,7 @@ export default function TestConnectionPage() {
|
|||||||
|
|
||||||
// Set default org if available
|
// Set default org if available
|
||||||
if (orgsData.organizations && orgsData.organizations.length > 0) {
|
if (orgsData.organizations && orgsData.organizations.length > 0) {
|
||||||
setSelectedOrg(orgsData.organizations[0]!.slug)
|
setSelectedOrg(orgsData.organizations[0].slug)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching organizations:', error)
|
console.error('Error fetching organizations:', error)
|
||||||
@ -230,7 +230,7 @@ const fetchDeployers = async () => {
|
|||||||
|
|
||||||
// Auto-select first deployer if available
|
// Auto-select first deployer if available
|
||||||
if (deployersData.deployers && deployersData.deployers.length > 0) {
|
if (deployersData.deployers && deployersData.deployers.length > 0) {
|
||||||
setSelectedDeployer(deployersData.deployers[0]!.deployerLrn)
|
setSelectedDeployer(deployersData.deployers[0].deployerLrn)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching deployers:', error)
|
console.error('Error fetching deployers:', error)
|
||||||
|
@ -194,7 +194,7 @@ Issued At: ${issuedAt}`
|
|||||||
setDebugInfo(prev => `${prev}\nValidation response: ${JSON.stringify(responseData)}`)
|
setDebugInfo(prev => `${prev}\nValidation response: ${JSON.stringify(responseData)}`)
|
||||||
|
|
||||||
// If successful, we're done
|
// If successful, we're done
|
||||||
if (response.ok && (responseData as any).success) {
|
if (response.ok && responseData.success) {
|
||||||
console.log('Authentication successful!')
|
console.log('Authentication successful!')
|
||||||
setDebugInfo(prev => `${prev}\nAuthentication successful!`)
|
setDebugInfo(prev => `${prev}\nAuthentication successful!`)
|
||||||
|
|
||||||
|
@ -8,10 +8,9 @@ import {
|
|||||||
DropdownMenuTrigger
|
DropdownMenuTrigger
|
||||||
} from '@workspace/ui/components/dropdown-menu'
|
} from '@workspace/ui/components/dropdown-menu'
|
||||||
import { cn } from '@workspace/ui/lib/utils'
|
import { cn } from '@workspace/ui/lib/utils'
|
||||||
import { MoreVertical, ExternalLink } from 'lucide-react'
|
import { MoreVertical } from 'lucide-react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
import type { LucideIcon } from 'lucide-react'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for header action buttons/links
|
* Configuration for header action buttons/links
|
||||||
@ -20,7 +19,6 @@ import type { LucideIcon } from 'lucide-react'
|
|||||||
* - Use onClick for JS actions OR href for navigation (not both)
|
* - Use onClick for JS actions OR href for navigation (not both)
|
||||||
* - Multiple visual styles via variant prop
|
* - Multiple visual styles via variant prop
|
||||||
* - Optional primary emphasis for main call-to-action
|
* - Optional primary emphasis for main call-to-action
|
||||||
* - Optional icon support
|
|
||||||
*/
|
*/
|
||||||
export interface PageAction {
|
export interface PageAction {
|
||||||
/**
|
/**
|
||||||
@ -29,23 +27,6 @@ export interface PageAction {
|
|||||||
*/
|
*/
|
||||||
label: string
|
label: string
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional icon for the action
|
|
||||||
* @remarks
|
|
||||||
* - Can be string identifier or Lucide icon component
|
|
||||||
* - Common values: 'external-link', 'plus', 'edit', etc.
|
|
||||||
* - Displayed alongside the label
|
|
||||||
*/
|
|
||||||
icon?: string | LucideIcon
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether this is an external link
|
|
||||||
* @remarks
|
|
||||||
* - When true, opens in new tab/window
|
|
||||||
* - Automatically adds external link icon if no icon specified
|
|
||||||
*/
|
|
||||||
external?: boolean
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visual style variant for the button
|
* Visual style variant for the button
|
||||||
* @remarks
|
* @remarks
|
||||||
@ -131,14 +112,6 @@ export interface PageHeaderProps {
|
|||||||
*/
|
*/
|
||||||
subtitle?: string | ReactNode
|
subtitle?: string | ReactNode
|
||||||
|
|
||||||
/**
|
|
||||||
* Additional description text
|
|
||||||
* @remarks
|
|
||||||
* - Displayed below subtitle
|
|
||||||
* - Useful for longer explanatory text
|
|
||||||
*/
|
|
||||||
description?: string
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of action buttons/links
|
* Array of action buttons/links
|
||||||
* @remarks
|
* @remarks
|
||||||
@ -146,7 +119,6 @@ export interface PageHeaderProps {
|
|||||||
* - Mobile: Primary actions shown, secondary in dropdown
|
* - Mobile: Primary actions shown, secondary in dropdown
|
||||||
* - Actions can be buttons (onClick) or links (href)
|
* - Actions can be buttons (onClick) or links (href)
|
||||||
* - Support multiple visual styles via variant prop
|
* - Support multiple visual styles via variant prop
|
||||||
* - Support icons and external links
|
|
||||||
*
|
*
|
||||||
* @see {@link PageAction} for detailed action configuration
|
* @see {@link PageAction} for detailed action configuration
|
||||||
*
|
*
|
||||||
@ -156,15 +128,12 @@ export interface PageHeaderProps {
|
|||||||
* {
|
* {
|
||||||
* label: "Create New",
|
* label: "Create New",
|
||||||
* isPrimary: true,
|
* isPrimary: true,
|
||||||
* icon: "plus",
|
|
||||||
* onClick: () => setOpen(true)
|
* onClick: () => setOpen(true)
|
||||||
* },
|
* },
|
||||||
* {
|
* {
|
||||||
* label: "View All",
|
* label: "View All",
|
||||||
* href: "/items",
|
* href: "/items",
|
||||||
* variant: "outline",
|
* variant: "outline"
|
||||||
* icon: "external-link",
|
|
||||||
* external: true
|
|
||||||
* }
|
* }
|
||||||
* ]}
|
* ]}
|
||||||
* ```
|
* ```
|
||||||
@ -183,11 +152,102 @@ export interface PageHeaderProps {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A responsive page header component with title, subtitle, and actions.
|
* A responsive page header component with title, subtitle, and actions.
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* PageHeader provides a consistent header structure with:
|
||||||
|
* - Prominent title as h1
|
||||||
|
* - Optional subtitle or custom component
|
||||||
|
* - Configurable action buttons/links
|
||||||
|
* - Responsive layout with mobile optimization
|
||||||
|
* - Customizable styling
|
||||||
|
*
|
||||||
|
* @keywords header, page-title, action-buttons, responsive-header, foundation-component
|
||||||
|
* @category Layout
|
||||||
|
* @scope Foundation
|
||||||
|
*
|
||||||
|
* @usage
|
||||||
|
* Common patterns:
|
||||||
|
*
|
||||||
|
* Basic title only:
|
||||||
|
* ```tsx
|
||||||
|
* <PageHeader title="Dashboard" />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* With subtitle and primary action:
|
||||||
|
* ```tsx
|
||||||
|
* <PageHeader
|
||||||
|
* title="Projects"
|
||||||
|
* subtitle="Your active projects"
|
||||||
|
* actions={[
|
||||||
|
* { label: "New Project", isPrimary: true, onClick: handleCreate }
|
||||||
|
* ]}
|
||||||
|
* />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* With search component and multiple actions:
|
||||||
|
* ```tsx
|
||||||
|
* <PageHeader
|
||||||
|
* title="Team Members"
|
||||||
|
* subtitle={<SearchInput placeholder="Search members..." />}
|
||||||
|
* actions={[
|
||||||
|
* { label: "Invite", isPrimary: true, onClick: handleInvite },
|
||||||
|
* { label: "Export", variant: "outline", onClick: handleExport },
|
||||||
|
* { label: "Settings", href: "/team/settings", variant: "ghost" }
|
||||||
|
* ]}
|
||||||
|
* />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* With navigation actions:
|
||||||
|
* ```tsx
|
||||||
|
* <PageHeader
|
||||||
|
* title="Edit Profile"
|
||||||
|
* actions={[
|
||||||
|
* { label: "Save", isPrimary: true, onClick: handleSave },
|
||||||
|
* { label: "Cancel", href: "/profile", variant: "ghost" }
|
||||||
|
* ]}
|
||||||
|
* />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```tsx
|
||||||
|
* <PageHeader
|
||||||
|
* title="Dashboard"
|
||||||
|
* subtitle="Welcome back!"
|
||||||
|
* actions={[
|
||||||
|
* {
|
||||||
|
* label: "New Item",
|
||||||
|
* isPrimary: true,
|
||||||
|
* onClick: () => console.log("clicked")
|
||||||
|
* }
|
||||||
|
* ]}
|
||||||
|
* className="mb-8"
|
||||||
|
* />
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @related {@link PageWrapper} - Often used together for page layout
|
||||||
|
* @related {@link Button} - Used for rendering actions
|
||||||
|
* @composition Uses {@link DropdownMenu} for mobile action menu
|
||||||
|
*
|
||||||
|
* @cssUtilities
|
||||||
|
* - flex-col/flex-row: Responsive layout
|
||||||
|
* - gap-6/gap-2: Consistent spacing
|
||||||
|
* - text-2xl/text-[30px]: Responsive typography
|
||||||
|
* - text-foreground/text-muted-foreground: Text hierarchy
|
||||||
|
*
|
||||||
|
* @accessibility
|
||||||
|
* - Uses semantic h1 for title
|
||||||
|
* - Maintains text contrast ratios
|
||||||
|
* - Dropdown menu is keyboard navigable
|
||||||
|
* - Preserves action button/link semantics
|
||||||
|
*
|
||||||
|
* @performance
|
||||||
|
* - Conditional rendering of subtitle and actions
|
||||||
|
* - Mobile-first CSS with responsive modifiers
|
||||||
|
* - Efficient action rendering with key prop
|
||||||
*/
|
*/
|
||||||
export default function PageHeader({
|
export default function PageHeader({
|
||||||
title,
|
title,
|
||||||
subtitle,
|
subtitle,
|
||||||
description,
|
|
||||||
actions = [],
|
actions = [],
|
||||||
className
|
className
|
||||||
}: PageHeaderProps) {
|
}: PageHeaderProps) {
|
||||||
@ -195,51 +255,21 @@ export default function PageHeader({
|
|||||||
const primaryActions = actions.filter((action) => action.isPrimary)
|
const primaryActions = actions.filter((action) => action.isPrimary)
|
||||||
const secondaryActions = actions.filter((action) => !action.isPrimary)
|
const secondaryActions = actions.filter((action) => !action.isPrimary)
|
||||||
|
|
||||||
// Get icon component from string or return the component directly
|
|
||||||
const getIconComponent = (icon: string | LucideIcon | undefined) => {
|
|
||||||
if (!icon) return null
|
|
||||||
|
|
||||||
if (typeof icon === 'string') {
|
|
||||||
switch (icon) {
|
|
||||||
case 'external-link':
|
|
||||||
return ExternalLink
|
|
||||||
default:
|
|
||||||
return ExternalLink // fallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return icon
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render an action (either as button or link)
|
// Render an action (either as button or link)
|
||||||
const renderAction = (action: PageAction, key: string) => {
|
const renderAction = (action: PageAction, key: string) => {
|
||||||
const variant = action.variant || (action.isPrimary ? 'default' : 'outline')
|
const variant = action.variant || (action.isPrimary ? 'default' : 'outline')
|
||||||
const IconComponent = getIconComponent(action.icon || (action.external ? 'external-link' : undefined))
|
|
||||||
|
|
||||||
const content = (
|
|
||||||
<>
|
|
||||||
{action.label}
|
|
||||||
{IconComponent && <IconComponent className="h-4 w-4 ml-2" />}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
if (action.href) {
|
if (action.href) {
|
||||||
return (
|
return (
|
||||||
<Button key={key} variant={variant} asChild>
|
<Button key={key} variant={variant} asChild>
|
||||||
<Link
|
<Link href={action.href}>{action.label}</Link>
|
||||||
href={action.href}
|
|
||||||
target={action.external ? '_blank' : undefined}
|
|
||||||
rel={action.external ? 'noopener noreferrer' : undefined}
|
|
||||||
>
|
|
||||||
{content}
|
|
||||||
</Link>
|
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button key={key} variant={variant} onClick={action.onClick}>
|
<Button key={key} variant={variant} onClick={action.onClick}>
|
||||||
{content}
|
{action.label}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -262,11 +292,6 @@ export default function PageHeader({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{description && (
|
|
||||||
<p className="text-sm text-muted-foreground mt-1">
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{actions.length > 0 && (
|
{actions.length > 0 && (
|
||||||
@ -295,16 +320,7 @@ export default function PageHeader({
|
|||||||
{secondaryActions.map((action) =>
|
{secondaryActions.map((action) =>
|
||||||
action.href ? (
|
action.href ? (
|
||||||
<DropdownMenuItem asChild key={action.label}>
|
<DropdownMenuItem asChild key={action.label}>
|
||||||
<Link
|
<Link href={action.href}>{action.label}</Link>
|
||||||
href={action.href}
|
|
||||||
target={action.external ? '_blank' : undefined}
|
|
||||||
rel={action.external ? 'noopener noreferrer' : undefined}
|
|
||||||
>
|
|
||||||
{action.label}
|
|
||||||
{getIconComponent(action.icon || (action.external ? 'external-link' : undefined)) && (
|
|
||||||
<ExternalLink className="h-4 w-4 ml-2" />
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
) : (
|
) : (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
'use client'
|
'use client'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useWallet } from '@/context/WalletContext'
|
import { useWallet } from '@/context/WalletContextProvider'
|
||||||
import { Button } from '@workspace/ui/components/button'
|
import { Button } from '@workspace/ui/components/button'
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
|
@ -269,7 +269,7 @@ const OnboardingDialog: React.FC<OnboardingDialogProps> = ({
|
|||||||
defaultOpen = false,
|
defaultOpen = false,
|
||||||
onClose
|
onClose
|
||||||
}) => {
|
}) => {
|
||||||
const { nextStep, setFormData, formData, currentStep, previousStep } = useOnboarding()
|
const { nextStep, setFormData, formData, currentStep } = useOnboarding()
|
||||||
const [selectedRepo, setSelectedRepo] = useState<string>(formData.githubRepo || '')
|
const [selectedRepo, setSelectedRepo] = useState<string>(formData.githubRepo || '')
|
||||||
const [isImportMode, setIsImportMode] = useState(true)
|
const [isImportMode, setIsImportMode] = useState(true)
|
||||||
const [isOpen, setIsOpen] = useState(defaultOpen)
|
const [isOpen, setIsOpen] = useState(defaultOpen)
|
||||||
@ -489,7 +489,7 @@ const OnboardingDialog: React.FC<OnboardingDialogProps> = ({
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="text-zinc-400 bg-zinc-900 border-zinc-800 hover:bg-zinc-800"
|
className="text-zinc-400 bg-zinc-900 border-zinc-800 hover:bg-zinc-800"
|
||||||
onClick={() => previousStep()}
|
onClick={() => useOnboarding.getState().previousStep()}
|
||||||
>
|
>
|
||||||
Previous
|
Previous
|
||||||
</Button>
|
</Button>
|
||||||
@ -527,7 +527,7 @@ const OnboardingDialog: React.FC<OnboardingDialogProps> = ({
|
|||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
className="text-zinc-400 bg-zinc-900 border-zinc-800 hover:bg-zinc-800"
|
className="text-zinc-400 bg-zinc-900 border-zinc-800 hover:bg-zinc-800"
|
||||||
onClick={() => previousStep()}
|
onClick={() => useOnboarding.getState().previousStep()}
|
||||||
>
|
>
|
||||||
Previous
|
Previous
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { PlusCircle, Loader2, AlertTriangle, Info } from 'lucide-react'
|
import { PlusCircle, Loader2, AlertTriangle, Info } from 'lucide-react'
|
||||||
import { useTheme } from 'next-themes'
|
import { useTheme } from 'next-themes'
|
||||||
import { useOnboarding } from '@/components/onboarding/store'
|
import { useOnboarding } from '@/components/onboarding/useOnboarding'
|
||||||
import { useGQLClient } from '@/context'
|
import { useGQLClient } from '@/context'
|
||||||
import { useWallet } from '@/context/WalletContext'
|
import { useWallet } from '@/context/WalletContext'
|
||||||
import { Button } from '@workspace/ui/components/button'
|
import { Button } from '@workspace/ui/components/button'
|
||||||
@ -16,7 +16,6 @@ import { Alert, AlertDescription } from '@workspace/ui/components/alert'
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card'
|
import { Card, CardContent, CardHeader, CardTitle } from '@workspace/ui/components/card'
|
||||||
import { Badge } from '@workspace/ui/components/badge'
|
import { Badge } from '@workspace/ui/components/badge'
|
||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
import { adaptDeployers } from '../../../utils/typeAdapters';
|
|
||||||
|
|
||||||
interface Deployer {
|
interface Deployer {
|
||||||
deployerLrn: string
|
deployerLrn: string
|
||||||
@ -94,11 +93,11 @@ export function ConfigureStep() {
|
|||||||
setIsLoadingDeployers(true)
|
setIsLoadingDeployers(true)
|
||||||
const deployersData = await gqlClient.getDeployers()
|
const deployersData = await gqlClient.getDeployers()
|
||||||
console.log('Available deployers:', deployersData)
|
console.log('Available deployers:', deployersData)
|
||||||
setDeployers(adaptDeployers(deployersData.deployers || []));
|
setDeployers(deployersData.deployers || [])
|
||||||
|
|
||||||
// Auto-select first deployer if available and none selected
|
// Auto-select first deployer if available and none selected
|
||||||
if (deployersData.deployers && deployersData.deployers.length > 0 && !selectedLrn) {
|
if (deployersData.deployers && deployersData.deployers.length > 0 && !selectedLrn) {
|
||||||
setSelectedLrn(deployersData.deployers[0]!.deployerLrn)
|
setSelectedLrn(deployersData.deployers[0].deployerLrn)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching deployers:', error)
|
console.error('Error fetching deployers:', error)
|
||||||
@ -118,7 +117,7 @@ export function ConfigureStep() {
|
|||||||
|
|
||||||
// Auto-select first organization if available and none selected
|
// Auto-select first organization if available and none selected
|
||||||
if (orgsData.organizations && orgsData.organizations.length > 0 && !selectedOrg) {
|
if (orgsData.organizations && orgsData.organizations.length > 0 && !selectedOrg) {
|
||||||
setSelectedOrg(orgsData.organizations[0]!.slug)
|
setSelectedOrg(orgsData.organizations[0].slug)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching organizations:', error)
|
console.error('Error fetching organizations:', error)
|
||||||
@ -143,32 +142,27 @@ export function ConfigureStep() {
|
|||||||
// Update environment variable
|
// Update environment variable
|
||||||
const updateEnvVar = (index: number, field: 'key' | 'value', value: string) => {
|
const updateEnvVar = (index: number, field: 'key' | 'value', value: string) => {
|
||||||
const newEnvVars = [...envVars]
|
const newEnvVars = [...envVars]
|
||||||
if (newEnvVars[index]) {
|
newEnvVars[index][field] = value
|
||||||
newEnvVars[index][field] = value
|
|
||||||
}
|
|
||||||
setEnvVars(newEnvVars)
|
setEnvVars(newEnvVars)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle environment for variable
|
// Toggle environment for variable
|
||||||
const toggleEnvironment = (index: number, environment: string) => {
|
const toggleEnvironment = (index: number, environment: string) => {
|
||||||
const newEnvVars = [...envVars]
|
const newEnvVars = [...envVars]
|
||||||
if (newEnvVars[index]?.environments) {
|
const currentEnvs = newEnvVars[index].environments
|
||||||
const currentEnvs = newEnvVars[index].environments
|
|
||||||
|
|
||||||
|
if (currentEnvs.includes(environment)) {
|
||||||
if (currentEnvs.includes(environment)) {
|
newEnvVars[index].environments = currentEnvs.filter(env => env !== environment)
|
||||||
newEnvVars[index].environments = currentEnvs.filter(env => env !== environment)
|
} else {
|
||||||
} else {
|
newEnvVars[index].environments = [...currentEnvs, environment]
|
||||||
newEnvVars[index].environments = [...currentEnvs, environment]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure at least one environment is selected
|
|
||||||
if (newEnvVars[index].environments.length === 0) {
|
|
||||||
newEnvVars[index].environments = ['Production']
|
|
||||||
}
|
|
||||||
|
|
||||||
setEnvVars(newEnvVars)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure at least one environment is selected
|
||||||
|
if (newEnvVars[index].environments.length === 0) {
|
||||||
|
newEnvVars[index].environments = ['Production']
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnvVars(newEnvVars)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle deployment option
|
// Toggle deployment option
|
||||||
|
@ -5,7 +5,7 @@ import { useState, useEffect } from 'react'
|
|||||||
import { Github, Wallet, CheckCircle2, AlertTriangle, Loader2, ExternalLink, ChevronDown } from 'lucide-react'
|
import { Github, Wallet, CheckCircle2, AlertTriangle, Loader2, ExternalLink, ChevronDown } from 'lucide-react'
|
||||||
import { useTheme } from 'next-themes'
|
import { useTheme } from 'next-themes'
|
||||||
import { SignIn } from '@clerk/nextjs'
|
import { SignIn } from '@clerk/nextjs'
|
||||||
import { useOnboarding } from '@/components/onboarding/store'
|
import { useOnboarding } from '@/components/onboarding/useOnboarding'
|
||||||
import { useAuthStatus } from '@/hooks/useAuthStatus'
|
import { useAuthStatus } from '@/hooks/useAuthStatus'
|
||||||
import { useRepoData } from '@/hooks/useRepoData'
|
import { useRepoData } from '@/hooks/useRepoData'
|
||||||
import { Button } from '@workspace/ui/components/button'
|
import { Button } from '@workspace/ui/components/button'
|
||||||
@ -17,8 +17,6 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@workspace/
|
|||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
import { GitHubBackendAuth } from '@/components/GitHubBackendAuth'
|
import { GitHubBackendAuth } from '@/components/GitHubBackendAuth'
|
||||||
import { AVAILABLE_TEMPLATES, type TemplateDetail } from '@/constants/templates'
|
import { AVAILABLE_TEMPLATES, type TemplateDetail } from '@/constants/templates'
|
||||||
import { Template } from '@/types/onboarding'
|
|
||||||
import { adaptOptionalTemplate } from '@/utils/typeAdapters'
|
|
||||||
|
|
||||||
interface Repository {
|
interface Repository {
|
||||||
id: string | number
|
id: string | number
|
||||||
@ -34,8 +32,8 @@ export function ConnectStep() {
|
|||||||
|
|
||||||
// Repository vs Template selection
|
// Repository vs Template selection
|
||||||
const [selectedRepo, setSelectedRepo] = useState<string>(formData.githubRepo || '')
|
const [selectedRepo, setSelectedRepo] = useState<string>(formData.githubRepo || '')
|
||||||
const [selectedTemplate, setSelectedTemplate] = useState(
|
const [selectedTemplate, setSelectedTemplate] = useState<TemplateDetail | undefined>(
|
||||||
adaptOptionalTemplate(formData.template)
|
formData.template || undefined
|
||||||
)
|
)
|
||||||
const [projectName, setProjectName] = useState<string>(formData.projectName || '')
|
const [projectName, setProjectName] = useState<string>(formData.projectName || '')
|
||||||
const [isImportMode, setIsImportMode] = useState(true)
|
const [isImportMode, setIsImportMode] = useState(true)
|
||||||
@ -46,6 +44,8 @@ export function ConnectStep() {
|
|||||||
// Auth status hook
|
// Auth status hook
|
||||||
const {
|
const {
|
||||||
clerk,
|
clerk,
|
||||||
|
wallet,
|
||||||
|
backend,
|
||||||
isFullyAuthenticated,
|
isFullyAuthenticated,
|
||||||
isReady,
|
isReady,
|
||||||
missing,
|
missing,
|
||||||
@ -169,7 +169,7 @@ export function ConnectStep() {
|
|||||||
setFormData({
|
setFormData({
|
||||||
deploymentMode: isImportMode ? 'repository' : 'template',
|
deploymentMode: isImportMode ? 'repository' : 'template',
|
||||||
githubRepo: isImportMode ? selectedRepo : '',
|
githubRepo: isImportMode ? selectedRepo : '',
|
||||||
template: !isImportMode ? (selectedTemplate as Template) : undefined,
|
template: !isImportMode ? selectedTemplate : undefined,
|
||||||
projectName: finalProjectName
|
projectName: finalProjectName
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ export function ConnectStep() {
|
|||||||
<div className="flex items-center gap-2 px-4 py-2 bg-zinc-100 dark:bg-zinc-800 rounded-md cursor-pointer hover:bg-zinc-200 dark:hover:bg-zinc-700">
|
<div className="flex items-center gap-2 px-4 py-2 bg-zinc-100 dark:bg-zinc-800 rounded-md cursor-pointer hover:bg-zinc-200 dark:hover:bg-zinc-700">
|
||||||
<Github className="h-4 w-4" />
|
<Github className="h-4 w-4" />
|
||||||
<span className="text-sm font-medium">
|
<span className="text-sm font-medium">
|
||||||
{clerk.user?.externalAccounts?.find((acc: any) => acc.provider === 'github')?.username || 'git-account'}
|
{clerk.user?.externalAccounts?.find(acc => acc.provider === 'github')?.username || 'git-account'}
|
||||||
</span>
|
</span>
|
||||||
<ChevronDown className="h-4 w-4" />
|
<ChevronDown className="h-4 w-4" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -90,7 +90,6 @@ export const ConnectStep = () => {
|
|||||||
<StepHeader
|
<StepHeader
|
||||||
title="Connect"
|
title="Connect"
|
||||||
description="Connect and import a GitHub repo or start from a template"
|
description="Connect and import a GitHub repo or start from a template"
|
||||||
icon={<GitBranch />}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Git account selector */}
|
{/* Git account selector */}
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { useTheme } from 'next-themes'
|
import { useTheme } from 'next-themes'
|
||||||
import { Github, Loader2, AlertTriangle, CheckCircle2 } from 'lucide-react'
|
import { Github, Loader2, AlertTriangle, CheckCircle2 } from 'lucide-react'
|
||||||
import { useOnboarding } from '@/components/onboarding/store'
|
import { useOnboarding } from '@/components/onboarding/useOnboarding'
|
||||||
|
import { useGQLClient } from '@/context'
|
||||||
import { useWallet } from '@/context/WalletContext'
|
import { useWallet } from '@/context/WalletContext'
|
||||||
import { useDeployment } from '@/hooks/useDeployment'
|
import { useDeployment } from '@/hooks/useDeployment'
|
||||||
import { useTemplateDeployment } from '@/hooks/useTemplate'
|
import { useTemplateDeployment } from '@/hooks/useTemplate'
|
||||||
@ -116,17 +117,16 @@ export function DeployStep() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
template: {
|
template: formData.template,
|
||||||
...formData.template,
|
|
||||||
id: formData.template?.id || '',
|
|
||||||
icon: formData.template?.icon || ''
|
|
||||||
},
|
|
||||||
projectName: formData.projectName,
|
projectName: formData.projectName,
|
||||||
organizationSlug: formData.selectedOrg,
|
organizationSlug: formData.selectedOrg,
|
||||||
environmentVariables: formData.environmentVariables || [],
|
environmentVariables: formData.environmentVariables || [],
|
||||||
deployerLrn: formData.selectedLrn
|
deployerLrn: formData.selectedLrn
|
||||||
};
|
}
|
||||||
const result = await deployTemplate(config);
|
|
||||||
|
console.log('Deploying template with config:', config)
|
||||||
|
|
||||||
|
const result = await deployTemplate(config)
|
||||||
|
|
||||||
// Save deployment results
|
// Save deployment results
|
||||||
setFormData({
|
setFormData({
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
export { default as Onboarding } from './Onboarding'
|
export { default as Onboarding } from './Onboarding'
|
||||||
export {
|
export {
|
||||||
default as OnboardingDialog,
|
default as OnboardingDialog,
|
||||||
|
hasCompletedOnboarding
|
||||||
} from './OnboardingDialog'
|
} from './OnboardingDialog'
|
||||||
|
|
||||||
// Step components
|
// Step components
|
||||||
|
@ -1,120 +1,86 @@
|
|||||||
// src/components/onboarding/useOnboarding.ts
|
'use client'
|
||||||
import { useState } from 'react'
|
|
||||||
import type {
|
import { create } from 'zustand'
|
||||||
OnboardingFormData} from '@/types'
|
import { persist } from 'zustand/middleware'
|
||||||
|
|
||||||
// Step type for navigation
|
|
||||||
export type Step = 'connect' | 'configure' | 'deploy' | 'success'
|
export type Step = 'connect' | 'configure' | 'deploy' | 'success'
|
||||||
|
|
||||||
// Initial form data
|
export interface EnvironmentVariables {
|
||||||
const initialFormData: OnboardingFormData = {
|
key: string
|
||||||
// Step 1: Connect
|
value: string
|
||||||
githubRepo: undefined,
|
|
||||||
template: undefined,
|
|
||||||
projectName: undefined,
|
|
||||||
deploymentMode: undefined,
|
|
||||||
|
|
||||||
// Step 2: Configure
|
|
||||||
selectedLrn: undefined,
|
|
||||||
selectedOrg: undefined, // Add this property
|
|
||||||
environmentVariables: [], // Use array type
|
|
||||||
deploymentType: undefined, // Add missing properties
|
|
||||||
deployerCount: undefined,
|
|
||||||
maxPrice: undefined,
|
|
||||||
|
|
||||||
// Step 3: Deploy
|
|
||||||
deploymentId: undefined,
|
|
||||||
repositoryUrl: undefined,
|
|
||||||
deploymentUrl: undefined, // Add missing property
|
|
||||||
projectId: undefined // Add missing property
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useOnboarding() {
|
export interface OnboardingFormData {
|
||||||
const [formData, setFormData] = useState<OnboardingFormData>(initialFormData)
|
// Connect step
|
||||||
const [currentStep, setCurrentStep] = useState<Step>('connect')
|
githubRepo?: string
|
||||||
|
|
||||||
// Update form data (partial update)
|
// Configure step
|
||||||
const updateFormData = (updates: Partial<OnboardingFormData>) => {
|
deploymentType?: 'auction' | 'lrn'
|
||||||
setFormData(prev => ({ ...prev, ...updates }))
|
deployerCount?: string
|
||||||
|
maxPrice?: string
|
||||||
|
selectedLrn?: string
|
||||||
|
environments?: {
|
||||||
|
production: boolean
|
||||||
|
preview: boolean
|
||||||
|
development: boolean
|
||||||
}
|
}
|
||||||
|
environmentVariables?: Record<string, string>
|
||||||
|
|
||||||
// Reset form data
|
// Deploy step
|
||||||
const resetFormData = () => {
|
deploymentId?: string
|
||||||
setFormData(initialFormData)
|
deploymentUrl?: string
|
||||||
setCurrentStep('connect')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step navigation
|
// Success step
|
||||||
const nextStep = () => {
|
projectId?: string
|
||||||
switch (currentStep) {
|
|
||||||
case 'connect':
|
|
||||||
setCurrentStep('configure')
|
|
||||||
break
|
|
||||||
case 'configure':
|
|
||||||
setCurrentStep('deploy')
|
|
||||||
break
|
|
||||||
case 'deploy':
|
|
||||||
setCurrentStep('success')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const previousStep = () => {
|
|
||||||
switch (currentStep) {
|
|
||||||
case 'configure':
|
|
||||||
setCurrentStep('connect')
|
|
||||||
break
|
|
||||||
case 'deploy':
|
|
||||||
setCurrentStep('configure')
|
|
||||||
break
|
|
||||||
case 'success':
|
|
||||||
setCurrentStep('deploy')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validation helpers
|
|
||||||
const validateStep1 = () => {
|
|
||||||
if (formData.deploymentMode === 'template') {
|
|
||||||
return !!(formData.template && formData.projectName)
|
|
||||||
}
|
|
||||||
return !!formData.githubRepo
|
|
||||||
}
|
|
||||||
|
|
||||||
const validateStep2 = () => {
|
|
||||||
return !!(formData.selectedLrn && formData.selectedOrg)
|
|
||||||
}
|
|
||||||
|
|
||||||
const validateStep3 = () => {
|
|
||||||
return !!formData.deploymentId
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
// Data
|
|
||||||
formData,
|
|
||||||
currentStep,
|
|
||||||
|
|
||||||
// Actions
|
|
||||||
setFormData: updateFormData,
|
|
||||||
setCurrentStep,
|
|
||||||
resetFormData,
|
|
||||||
resetOnboarding: resetFormData, // Alias for compatibility
|
|
||||||
nextStep,
|
|
||||||
previousStep,
|
|
||||||
|
|
||||||
// Validation
|
|
||||||
validateStep1,
|
|
||||||
validateStep2,
|
|
||||||
validateStep3,
|
|
||||||
|
|
||||||
// Store-like interface for compatibility
|
|
||||||
getState: () => ({
|
|
||||||
formData,
|
|
||||||
currentStep,
|
|
||||||
nextStep,
|
|
||||||
previousStep,
|
|
||||||
setFormData: updateFormData,
|
|
||||||
resetFormData
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OnboardingState {
|
||||||
|
currentStep: Step
|
||||||
|
formData: OnboardingFormData
|
||||||
|
setCurrentStep: (step: Step) => void
|
||||||
|
setFormData: (data: Partial<OnboardingFormData>) => void
|
||||||
|
nextStep: () => void
|
||||||
|
previousStep: () => void
|
||||||
|
resetOnboarding: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const STEP_ORDER: Step[] = ['connect', 'configure', 'deploy', 'success']
|
||||||
|
|
||||||
|
export const useOnboarding = create<OnboardingState>()(
|
||||||
|
persist(
|
||||||
|
(set) => ({
|
||||||
|
currentStep: 'connect',
|
||||||
|
formData: {},
|
||||||
|
|
||||||
|
setCurrentStep: (step) => set({ currentStep: step }),
|
||||||
|
|
||||||
|
setFormData: (data) =>
|
||||||
|
set((state) => ({
|
||||||
|
formData: { ...state.formData, ...data }
|
||||||
|
})),
|
||||||
|
|
||||||
|
nextStep: () =>
|
||||||
|
set((state) => {
|
||||||
|
const currentIndex = STEP_ORDER.indexOf(state.currentStep)
|
||||||
|
const nextStep = STEP_ORDER[currentIndex + 1]
|
||||||
|
return nextStep ? { currentStep: nextStep } : state
|
||||||
|
}),
|
||||||
|
|
||||||
|
previousStep: () =>
|
||||||
|
set((state) => {
|
||||||
|
const currentIndex = STEP_ORDER.indexOf(state.currentStep)
|
||||||
|
const previousStep = STEP_ORDER[currentIndex - 1]
|
||||||
|
return previousStep ? { currentStep: previousStep } : state
|
||||||
|
}),
|
||||||
|
|
||||||
|
resetOnboarding: () =>
|
||||||
|
set({
|
||||||
|
currentStep: 'connect',
|
||||||
|
formData: {}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: 'laconic-onboarding-storage'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
@ -8,9 +8,9 @@
|
|||||||
export interface TemplateDetail {
|
export interface TemplateDetail {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
icon: string // Required string
|
icon: string
|
||||||
repoFullName: string
|
repoFullName: string
|
||||||
description: string // Required string
|
description: string
|
||||||
isComingSoon?: boolean
|
isComingSoon?: boolean
|
||||||
tags?: string[]
|
tags?: string[]
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ export const BackendProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
|
|
||||||
// Check backend connection
|
// Check backend connection
|
||||||
const checkBackendConnection = useCallback(async (): Promise<void> => {
|
const checkBackendConnection = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('http://localhost:8000/auth/session', {
|
const response = await fetch('http://localhost:8000/auth/session', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -59,11 +59,11 @@ export const BackendProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
console.log('❌ Backend not connected')
|
console.log('❌ Backend not connected')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't return anything - function returns Promise<void>
|
return connected
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error checking backend connection:', error)
|
console.error('Error checking backend connection:', error)
|
||||||
setIsBackendConnected(false)
|
setIsBackendConnected(false)
|
||||||
// Don't return anything - function returns Promise<void>
|
return false
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ export function useAuthStatus(): AuthStatus & AuthActions {
|
|||||||
// Calculate what's missing
|
// Calculate what's missing
|
||||||
const missing = {
|
const missing = {
|
||||||
clerkSignIn: !isSignedIn,
|
clerkSignIn: !isSignedIn,
|
||||||
clerkGithub: (isSignedIn ?? false) && !hasGithubInClerk,
|
clerkGithub: isSignedIn && !hasGithubInClerk,
|
||||||
walletConnection: !hasWalletAddress, // Just need wallet address for this step
|
walletConnection: !hasWalletAddress, // Just need wallet address for this step
|
||||||
backendConnection: hasWalletAddress && !isWalletSessionActive, // Need SIWE auth for backend
|
backendConnection: hasWalletAddress && !isWalletSessionActive, // Need SIWE auth for backend
|
||||||
githubBackendSync: isBackendConnected && !isGithubBackendAuth
|
githubBackendSync: isBackendConnected && !isGithubBackendAuth
|
||||||
@ -177,7 +177,7 @@ export function useAuthStatus(): AuthStatus & AuthActions {
|
|||||||
return {
|
return {
|
||||||
// Individual systems
|
// Individual systems
|
||||||
clerk: {
|
clerk: {
|
||||||
isSignedIn: isSignedIn ?? false,
|
isSignedIn,
|
||||||
isLoaded: isClerkLoaded && isUserLoaded,
|
isLoaded: isClerkLoaded && isUserLoaded,
|
||||||
hasGithubConnected: hasGithubInClerk,
|
hasGithubConnected: hasGithubInClerk,
|
||||||
user
|
user
|
||||||
|
@ -37,13 +37,13 @@ export function useRepoData(repoId: string): UseRepoDataReturn {
|
|||||||
try {
|
try {
|
||||||
// Check if user has connected GitHub account
|
// Check if user has connected GitHub account
|
||||||
const githubAccount = user.externalAccounts.find(
|
const githubAccount = user.externalAccounts.find(
|
||||||
account => account.provider === 'github'
|
account => account.provider === 'oauth_github'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (githubAccount) {
|
if (githubAccount) {
|
||||||
// Try to get GitHub OAuth token from Clerk
|
// Try to get GitHub OAuth token from Clerk
|
||||||
try {
|
try {
|
||||||
// token = await user.getToken({ template: 'github' });
|
token = await user.getToken({ template: 'github' });
|
||||||
console.log('Using GitHub token from Clerk');
|
console.log('Using GitHub token from Clerk');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error getting GitHub token from Clerk:', err);
|
console.error('Error getting GitHub token from Clerk:', err);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// src/hooks/useRepoSelection.ts
|
// src/hooks/useRepoSelection.ts
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { useOctokit } from '@/context/OctokitContext'
|
import { useOctokit } from '@/context/OctokitContext'
|
||||||
import { adaptRepositories, type GitHubRepo } from '../utils/typeAdapters';
|
|
||||||
|
|
||||||
interface Repository {
|
interface Repository {
|
||||||
id: string;
|
id: string;
|
||||||
@ -59,7 +58,7 @@ export function useRepoSelection(): UseRepoSelectionResult {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setRepositories(adaptRepositories(repoData as GitHubRepo[]));
|
setRepositories(repoData);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to fetch repositories:', err);
|
console.error('Failed to fetch repositories:', err);
|
||||||
@ -90,9 +89,6 @@ export function useRepoSelection(): UseRepoSelectionResult {
|
|||||||
try {
|
try {
|
||||||
if (isAuth && octokit) {
|
if (isAuth && octokit) {
|
||||||
const [owner, repo] = repoFullName.split('/');
|
const [owner, repo] = repoFullName.split('/');
|
||||||
if (!owner || !repo) {
|
|
||||||
throw new Error('Invalid repository format');
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await octokit.request('GET /repos/{owner}/{repo}/branches', {
|
const response = await octokit.request('GET /repos/{owner}/{repo}/branches', {
|
||||||
owner,
|
owner,
|
||||||
|
@ -4,7 +4,6 @@ export interface Deployment {
|
|||||||
status: string
|
status: string
|
||||||
isCurrent: boolean
|
isCurrent: boolean
|
||||||
createdAt: string | number
|
createdAt: string | number
|
||||||
commit?: string
|
|
||||||
createdBy?: {
|
createdBy?: {
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
@ -19,17 +18,4 @@ export interface Domain {
|
|||||||
branch: string
|
branch: string
|
||||||
status: string
|
status: string
|
||||||
createdAt: string | number
|
createdAt: string | number
|
||||||
isCustom: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add missing types that are referenced in components
|
|
||||||
export interface EnvVarItem {
|
|
||||||
key?: string
|
|
||||||
value?: string
|
|
||||||
environments?: string[]
|
|
||||||
isEditing?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export type EditableEnvVarItem = Partial<EnvVarItem> & {
|
|
||||||
isEditing?: boolean
|
|
||||||
}
|
}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
import type { LucideIcon } from 'lucide-react'
|
|
||||||
import type { ReactNode } from 'react'
|
|
||||||
|
|
||||||
// Page action type (for header actions)
|
|
||||||
export interface PageAction {
|
|
||||||
label: string
|
|
||||||
href: string
|
|
||||||
icon?: string | LucideIcon // Add missing icon property
|
|
||||||
external?: boolean
|
|
||||||
onClick?: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page header configuration
|
|
||||||
export interface PageHeaderProps {
|
|
||||||
title: string
|
|
||||||
description?: string // Add missing description property
|
|
||||||
actions?: PageAction[]
|
|
||||||
breadcrumbs?: Array<{
|
|
||||||
label: string
|
|
||||||
href?: string
|
|
||||||
}>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Page wrapper layout types
|
|
||||||
export type PageLayout = 'default' | 'bento' | 'centered'
|
|
||||||
|
|
||||||
export interface PageWrapperProps {
|
|
||||||
children: ReactNode
|
|
||||||
header?: PageHeaderProps
|
|
||||||
layout?: PageLayout
|
|
||||||
className?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dropdown component types
|
|
||||||
export interface DropdownOption {
|
|
||||||
label: string
|
|
||||||
value: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DropdownProps {
|
|
||||||
label?: string
|
|
||||||
options: DropdownOption[]
|
|
||||||
selectedValue?: string | undefined
|
|
||||||
onSelect: (value: string) => void
|
|
||||||
placeholder?: string
|
|
||||||
className?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step header types (for onboarding)
|
|
||||||
export interface StepHeaderProps {
|
|
||||||
title: string
|
|
||||||
description: string
|
|
||||||
icon?: ReactNode // Required icon property
|
|
||||||
}
|
|
@ -1,6 +1,2 @@
|
|||||||
export * from './deployment'
|
export * from './deployment'
|
||||||
export * from './project'
|
export * from './project'
|
||||||
export * from './dashboard'
|
|
||||||
export * from './common'
|
|
||||||
export * from './foundation'
|
|
||||||
export * from './onboarding'
|
|
@ -1,88 +0,0 @@
|
|||||||
// Template type for onboarding
|
|
||||||
export interface Template {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
description: string // Required string
|
|
||||||
repoFullName: string // Required string
|
|
||||||
framework?: string
|
|
||||||
icon?: string // Optional string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deployer type (compatible with GraphQL client)
|
|
||||||
export interface Deployer {
|
|
||||||
deployerLrn: string
|
|
||||||
deploymentLrn: string
|
|
||||||
name: string
|
|
||||||
baseDomain: string
|
|
||||||
minimumPayment?: string | null
|
|
||||||
}
|
|
||||||
|
|
||||||
// Organization type
|
|
||||||
export interface Organization {
|
|
||||||
id: string
|
|
||||||
slug: string
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Environment variable type for onboarding
|
|
||||||
export interface OnboardingEnvVar {
|
|
||||||
key: string
|
|
||||||
value: string
|
|
||||||
environments: string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Complete onboarding form data interface
|
|
||||||
export interface OnboardingFormData {
|
|
||||||
// Step 1: Connect (Repository or Template selection)
|
|
||||||
githubRepo?: string
|
|
||||||
template?: Template
|
|
||||||
projectName?: string
|
|
||||||
deploymentMode?: 'repository' | 'template'
|
|
||||||
|
|
||||||
// Step 2: Configure
|
|
||||||
selectedLrn?: string
|
|
||||||
selectedOrg?: string // Add the missing selectedOrg property
|
|
||||||
environmentVariables?: OnboardingEnvVar[] // Use proper array type
|
|
||||||
deploymentType?: 'auction' | 'lrn' // Add missing properties
|
|
||||||
deployerCount?: string
|
|
||||||
maxPrice?: string
|
|
||||||
paymentAddress?: string // Add missing paymentAddress property
|
|
||||||
|
|
||||||
// Step 3: Deploy
|
|
||||||
deploymentId?: string
|
|
||||||
repositoryUrl?: string // Add missing repositoryUrl property
|
|
||||||
deploymentUrl?: string // Add missing deploymentUrl property
|
|
||||||
projectId?: string // Add missing projectId property
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deployment configuration types
|
|
||||||
export interface TemplateDeploymentConfig {
|
|
||||||
template: Template
|
|
||||||
projectName: string
|
|
||||||
organizationSlug: string
|
|
||||||
environmentVariables?: OnboardingEnvVar[]
|
|
||||||
deployerLrn: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DeploymentConfig {
|
|
||||||
projectId: string
|
|
||||||
organizationSlug: string
|
|
||||||
repository: string
|
|
||||||
branch: string
|
|
||||||
name: string
|
|
||||||
environmentVariables?: OnboardingEnvVar[]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repository type for GitHub integration
|
|
||||||
export interface Repository {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
full_name: string
|
|
||||||
default_branch: string
|
|
||||||
html_url: string
|
|
||||||
description?: string | null
|
|
||||||
owner: {
|
|
||||||
login: string
|
|
||||||
avatar_url: string
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,10 +18,3 @@ export interface Project {
|
|||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ProjectStatus {
|
|
||||||
Building = 'Building',
|
|
||||||
Ready = 'Ready',
|
|
||||||
Error = 'Error',
|
|
||||||
Deleting = 'Deleting'
|
|
||||||
}
|
|
@ -1,174 +0,0 @@
|
|||||||
// src/utils/typeAdapters.ts
|
|
||||||
import {
|
|
||||||
Deployer as GQLDeployer,
|
|
||||||
DeploymentStatus } from '../../../../services/gql-client/src/types';
|
|
||||||
|
|
||||||
// Define your frontend types that may be missing
|
|
||||||
export type ProjectStatus = 'success' | 'pending' | 'error' | 'building' | 'deleting';
|
|
||||||
|
|
||||||
export interface TemplateDetail {
|
|
||||||
id?: string;
|
|
||||||
name: string;
|
|
||||||
icon: string;
|
|
||||||
description?: string;
|
|
||||||
repoFullName?: string;
|
|
||||||
[key: string]: any; // Allow other properties
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Template {
|
|
||||||
id?: string;
|
|
||||||
name: string;
|
|
||||||
icon?: string;
|
|
||||||
description?: string;
|
|
||||||
repoFullName?: string;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Repository {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
full_name: string;
|
|
||||||
default_branch: string;
|
|
||||||
html_url: string;
|
|
||||||
description?: string; // Note: undefined, not null
|
|
||||||
owner: {
|
|
||||||
login: string;
|
|
||||||
avatar_url: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Deployer {
|
|
||||||
deployerLrn: string;
|
|
||||||
deployerId: string;
|
|
||||||
deployerApiUrl: string;
|
|
||||||
baseDomain: string;
|
|
||||||
minimumPayment?: string; // Note: undefined, not null
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GitHubRepo {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
full_name: string;
|
|
||||||
default_branch: string;
|
|
||||||
html_url: string;
|
|
||||||
description: string | null;
|
|
||||||
owner: {
|
|
||||||
login: string;
|
|
||||||
avatar_url: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert GraphQL Deployer to Frontend Deployer
|
|
||||||
*/
|
|
||||||
export const adaptDeployer = (gqlDeployer: GQLDeployer): Deployer => ({
|
|
||||||
...gqlDeployer,
|
|
||||||
minimumPayment: gqlDeployer.minimumPayment ?? undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert array of GraphQL Deployers to Frontend Deployers
|
|
||||||
*/
|
|
||||||
export const adaptDeployers = (gqlDeployers: GQLDeployer[]): Deployer[] => {
|
|
||||||
return gqlDeployers.map(adaptDeployer);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert Template to TemplateDetail (ensuring icon is always string)
|
|
||||||
*/
|
|
||||||
export const adaptTemplate = (template: Template): TemplateDetail => ({
|
|
||||||
...template,
|
|
||||||
icon: template.icon || '/default-template-icon.svg' // Provide a default icon path
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert DeploymentStatus to ProjectStatus
|
|
||||||
*/
|
|
||||||
export const adaptDeploymentStatus = (status: string | DeploymentStatus): ProjectStatus => {
|
|
||||||
// Convert to string safely
|
|
||||||
const statusStr = String(status);
|
|
||||||
|
|
||||||
switch (statusStr) {
|
|
||||||
case 'Building':
|
|
||||||
case 'building':
|
|
||||||
return 'building';
|
|
||||||
case 'Ready':
|
|
||||||
case 'ready':
|
|
||||||
case 'complete':
|
|
||||||
return 'success';
|
|
||||||
case 'Error':
|
|
||||||
case 'error':
|
|
||||||
case 'failed':
|
|
||||||
return 'error';
|
|
||||||
case 'Deleting':
|
|
||||||
case 'deleting':
|
|
||||||
return 'deleting';
|
|
||||||
case 'pending':
|
|
||||||
return 'pending';
|
|
||||||
default:
|
|
||||||
console.warn(`Unknown deployment status: ${statusStr}`);
|
|
||||||
return 'pending';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert GitHub API Repository to Frontend Repository
|
|
||||||
*/
|
|
||||||
export const adaptRepository = (githubRepo: GitHubRepo): Repository => ({
|
|
||||||
...githubRepo,
|
|
||||||
description: githubRepo.description ?? undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert array of GitHub repositories
|
|
||||||
*/
|
|
||||||
export const adaptRepositories = (githubRepos: GitHubRepo[]): Repository[] => {
|
|
||||||
return githubRepos.map(adaptRepository);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Safely extract owner and repo name from selected repository
|
|
||||||
*/
|
|
||||||
export const extractRepoInfo = (selectedRepo: Repository | null | undefined): { owner: string; repo: string } => {
|
|
||||||
if (!selectedRepo) {
|
|
||||||
throw new Error('No repository selected');
|
|
||||||
}
|
|
||||||
|
|
||||||
const owner = selectedRepo.owner?.login;
|
|
||||||
const repo = selectedRepo.name;
|
|
||||||
|
|
||||||
if (!owner || !repo) {
|
|
||||||
throw new Error('Repository owner and name are required');
|
|
||||||
}
|
|
||||||
|
|
||||||
return { owner, repo };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Template deployment configuration adapter
|
|
||||||
*/
|
|
||||||
export interface TemplateDeploymentConfig {
|
|
||||||
template: TemplateDetail;
|
|
||||||
projectName: string;
|
|
||||||
organizationSlug: string;
|
|
||||||
environmentVariables: any[];
|
|
||||||
deployerLrn?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const adaptTemplateDeploymentConfig = (config: {
|
|
||||||
template: Template;
|
|
||||||
projectName: string;
|
|
||||||
organizationSlug: string;
|
|
||||||
environmentVariables: any[];
|
|
||||||
deployerLrn?: string;
|
|
||||||
}): TemplateDeploymentConfig => ({
|
|
||||||
...config,
|
|
||||||
template: adaptTemplate(config.template)
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility to handle optional template conversion
|
|
||||||
*/
|
|
||||||
export const adaptOptionalTemplate = (template: Template | undefined): TemplateDetail | undefined => {
|
|
||||||
return template ? adaptTemplate(template) : undefined;
|
|
||||||
};
|
|
@ -1,396 +0,0 @@
|
|||||||
./.github/CONTRIBUTING.md
|
|
||||||
./.turbo/cache/88602030b8f39256-meta.json
|
|
||||||
./.turbo/cache/981738a1c69b2e12-meta.json
|
|
||||||
./.turbo/cache/cff97096ef4824bd-meta.json
|
|
||||||
./.turbo/preferences/tui.json
|
|
||||||
./.vscode/extensions.json
|
|
||||||
./.vscode/settings.json
|
|
||||||
./BACKEND_CONNECTION.md
|
|
||||||
./apps/backend/README.md
|
|
||||||
./apps/backend/biome.json
|
|
||||||
./apps/backend/dist/config.d.ts
|
|
||||||
./apps/backend/dist/constants.d.ts
|
|
||||||
./apps/backend/dist/database.d.ts
|
|
||||||
./apps/backend/dist/entity/Deployer.d.ts
|
|
||||||
./apps/backend/dist/entity/Deployment.d.ts
|
|
||||||
./apps/backend/dist/entity/Domain.d.ts
|
|
||||||
./apps/backend/dist/entity/EnvironmentVariable.d.ts
|
|
||||||
./apps/backend/dist/entity/Organization.d.ts
|
|
||||||
./apps/backend/dist/entity/Project.d.ts
|
|
||||||
./apps/backend/dist/entity/ProjectMember.d.ts
|
|
||||||
./apps/backend/dist/entity/User.d.ts
|
|
||||||
./apps/backend/dist/entity/UserOrganization.d.ts
|
|
||||||
./apps/backend/dist/index.d.ts
|
|
||||||
./apps/backend/dist/registry.d.ts
|
|
||||||
./apps/backend/dist/resolvers.d.ts
|
|
||||||
./apps/backend/dist/routes/auth.d.ts
|
|
||||||
./apps/backend/dist/routes/github.d.ts
|
|
||||||
./apps/backend/dist/routes/staging.d.ts
|
|
||||||
./apps/backend/dist/server.d.ts
|
|
||||||
./apps/backend/dist/service.d.ts
|
|
||||||
./apps/backend/dist/turnkey-backend.d.ts
|
|
||||||
./apps/backend/dist/types.d.ts
|
|
||||||
./apps/backend/dist/utils.d.ts
|
|
||||||
./apps/backend/environments/local.toml
|
|
||||||
./apps/backend/package.json
|
|
||||||
./apps/backend/src/config.ts
|
|
||||||
./apps/backend/src/constants.ts
|
|
||||||
./apps/backend/src/database.ts
|
|
||||||
./apps/backend/src/entity/Deployer.ts
|
|
||||||
./apps/backend/src/entity/Deployment.ts
|
|
||||||
./apps/backend/src/entity/Domain.ts
|
|
||||||
./apps/backend/src/entity/EnvironmentVariable.ts
|
|
||||||
./apps/backend/src/entity/Organization.ts
|
|
||||||
./apps/backend/src/entity/Project.ts
|
|
||||||
./apps/backend/src/entity/ProjectMember.ts
|
|
||||||
./apps/backend/src/entity/User.ts
|
|
||||||
./apps/backend/src/entity/UserOrganization.ts
|
|
||||||
./apps/backend/src/index.ts
|
|
||||||
./apps/backend/src/registry.ts
|
|
||||||
./apps/backend/src/resolvers.ts
|
|
||||||
./apps/backend/src/routes/auth.ts
|
|
||||||
./apps/backend/src/routes/github.ts
|
|
||||||
./apps/backend/src/routes/staging.ts
|
|
||||||
./apps/backend/src/server.ts
|
|
||||||
./apps/backend/src/service.ts
|
|
||||||
./apps/backend/src/turnkey-backend.ts
|
|
||||||
./apps/backend/src/types.ts
|
|
||||||
./apps/backend/src/utils.ts
|
|
||||||
./apps/backend/test/delete-db.ts
|
|
||||||
./apps/backend/test/fixtures/deployments.json
|
|
||||||
./apps/backend/test/fixtures/environment-variables.json
|
|
||||||
./apps/backend/test/fixtures/organizations.json
|
|
||||||
./apps/backend/test/fixtures/primary-domains.json
|
|
||||||
./apps/backend/test/fixtures/project-members.json
|
|
||||||
./apps/backend/test/fixtures/projects.json
|
|
||||||
./apps/backend/test/fixtures/redirected-domains.json
|
|
||||||
./apps/backend/test/fixtures/user-organizations.json
|
|
||||||
./apps/backend/test/fixtures/users.json
|
|
||||||
./apps/backend/test/initialize-db.ts
|
|
||||||
./apps/backend/test/initialize-registry.ts
|
|
||||||
./apps/backend/test/publish-deploy-records.ts
|
|
||||||
./apps/backend/test/publish-deployment-removal-records.ts
|
|
||||||
./apps/backend/tsconfig.json
|
|
||||||
./apps/deploy-fe/.vscode/settings.json
|
|
||||||
./apps/deploy-fe/components.json
|
|
||||||
./apps/deploy-fe/next-env.d.ts
|
|
||||||
./apps/deploy-fe/package.json
|
|
||||||
./apps/deploy-fe/src/actions/github.ts
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/documentation/DocumentationPlaceholder.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/documentation/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/home/loading.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/home/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/layout.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/(create)/cr/(template)/tm/(configure)/cf/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/(create)/cr/(template)/tm/(deploy)/dp/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/(create)/cr/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(deployments)/dep/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(integrations)/int/GitPage.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(integrations)/int/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(settings)/set/(collaborators)/col/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(settings)/set/(domains)/dom/(add)/cf/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(settings)/set/(domains)/dom/(add)/config/cf/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(settings)/set/(environment-variables)/env/EnvVarsPage.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(settings)/set/(environment-variables)/env/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(settings)/set/(git)/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(settings)/set/ProjectSettingsPage.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/(settings)/set/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/deployments/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/layout.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/loading.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/[provider]/ps/[id]/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/error.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/loading.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/projects/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/purchase/BuyServices.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/purchase/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/store/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/support/SupportPlaceholder.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/support/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/(dashboard)/wallet/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/(web3-authenticated)/layout.tsx
|
|
||||||
./apps/deploy-fe/src/app/actions/github.ts
|
|
||||||
./apps/deploy-fe/src/app/api/auth/route.ts
|
|
||||||
./apps/deploy-fe/src/app/api/github/webhook/route.ts
|
|
||||||
./apps/deploy-fe/src/app/auth/github/backend-callback/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/layout.tsx
|
|
||||||
./apps/deploy-fe/src/app/loading.tsx
|
|
||||||
./apps/deploy-fe/src/app/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/sign-in/[[...sign-in]]/page.tsx
|
|
||||||
./apps/deploy-fe/src/app/test-connection/page.tsx
|
|
||||||
./apps/deploy-fe/src/components/AuthTest.tsx
|
|
||||||
./apps/deploy-fe/src/components/DeploymentTest.tsx
|
|
||||||
./apps/deploy-fe/src/components/DevAuth.tsx
|
|
||||||
./apps/deploy-fe/src/components/DirectKeyAuth.tsx
|
|
||||||
./apps/deploy-fe/src/components/GItHubBackendAuth.tsx
|
|
||||||
./apps/deploy-fe/src/components/GQLTest.tsx
|
|
||||||
./apps/deploy-fe/src/components/TurnkeyAuth.tsx
|
|
||||||
./apps/deploy-fe/src/components/WalletConnectAuth.tsx
|
|
||||||
./apps/deploy-fe/src/components/assets/laconic-mark.tsx
|
|
||||||
./apps/deploy-fe/src/components/core/dropdown/Dropdown.tsx
|
|
||||||
./apps/deploy-fe/src/components/core/dropdown/README.md
|
|
||||||
./apps/deploy-fe/src/components/core/dropdown/index.ts
|
|
||||||
./apps/deploy-fe/src/components/core/dropdown/types.ts
|
|
||||||
./apps/deploy-fe/src/components/core/format-milli-second/FormatMilliSecond.tsx
|
|
||||||
./apps/deploy-fe/src/components/core/format-milli-second/README.md
|
|
||||||
./apps/deploy-fe/src/components/core/format-milli-second/index.ts
|
|
||||||
./apps/deploy-fe/src/components/core/format-milli-second/types.ts
|
|
||||||
./apps/deploy-fe/src/components/core/logo/Logo.tsx
|
|
||||||
./apps/deploy-fe/src/components/core/logo/README.md
|
|
||||||
./apps/deploy-fe/src/components/core/logo/index.ts
|
|
||||||
./apps/deploy-fe/src/components/core/logo/types.ts
|
|
||||||
./apps/deploy-fe/src/components/core/search-bar/README.md
|
|
||||||
./apps/deploy-fe/src/components/core/search-bar/SearchBar.tsx
|
|
||||||
./apps/deploy-fe/src/components/core/search-bar/index.ts
|
|
||||||
./apps/deploy-fe/src/components/core/search-bar/types.ts
|
|
||||||
./apps/deploy-fe/src/components/core/stepper/README.md
|
|
||||||
./apps/deploy-fe/src/components/core/stepper/Stepper.tsx
|
|
||||||
./apps/deploy-fe/src/components/core/stepper/index.ts
|
|
||||||
./apps/deploy-fe/src/components/core/stepper/types.ts
|
|
||||||
./apps/deploy-fe/src/components/core/stop-watch/README.md
|
|
||||||
./apps/deploy-fe/src/components/core/stop-watch/StopWatch.tsx
|
|
||||||
./apps/deploy-fe/src/components/core/stop-watch/index.ts
|
|
||||||
./apps/deploy-fe/src/components/core/stop-watch/types.ts
|
|
||||||
./apps/deploy-fe/src/components/core/vertical-stepper/README.md
|
|
||||||
./apps/deploy-fe/src/components/core/vertical-stepper/VerticalStepper.tsx
|
|
||||||
./apps/deploy-fe/src/components/core/vertical-stepper/index.ts
|
|
||||||
./apps/deploy-fe/src/components/core/vertical-stepper/types.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/coming-soon-overlay/ComingSoonOverlay.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/coming-soon-overlay/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/github-session-button/GitHubSessionButton.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/github-session-button/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/github-session-button/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/github-session-button/types.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/laconic-icon/LaconicIcon.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/laconic-icon/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/laconic-icon/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/laconic-icon/types.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/loading/loading-overlay/LoadingOverlay.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/loading/loading-overlay/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/loading/loading-overlay/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/navigation-wrapper/NavigationWrapper.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/navigation-wrapper/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/navigation-wrapper/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/page-header/PageHeader.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/page-header/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/page-header/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/page-wrapper/PageWrapper.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/page-wrapper/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/page-wrapper/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/project-search-bar/ProjectSearchBar.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/project-search-bar/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/project-search-bar/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/project-search-bar/types.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/dark-mode-toggle/DarkModeToggle.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/dark-mode-toggle/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/dark-mode-toggle/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/main-navigation/MainNavigation.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/main-navigation/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/main-navigation/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/navigation-item/NavigationItem.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/navigation-item/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/navigation-item/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/types.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/wallet-session-badge/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/wallet-session-badge/WalletSessionBadge.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/top-navigation/wallet-session-badge/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/types.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/wallet-session-id/README.md
|
|
||||||
./apps/deploy-fe/src/components/foundation/wallet-session-id/WalletSessionId.tsx
|
|
||||||
./apps/deploy-fe/src/components/foundation/wallet-session-id/index.ts
|
|
||||||
./apps/deploy-fe/src/components/foundation/wallet-session-id/types.ts
|
|
||||||
./apps/deploy-fe/src/components/iframe/auto-sign-in/AutoSignInIFrameModal.tsx
|
|
||||||
./apps/deploy-fe/src/components/iframe/auto-sign-in/README.md
|
|
||||||
./apps/deploy-fe/src/components/iframe/auto-sign-in/index.ts
|
|
||||||
./apps/deploy-fe/src/components/iframe/auto-sign-in/types.ts
|
|
||||||
./apps/deploy-fe/src/components/iframe/check-balance-iframe/CheckBalanceIframe.tsx
|
|
||||||
./apps/deploy-fe/src/components/iframe/check-balance-iframe/CheckBalanceWrapper.tsx
|
|
||||||
./apps/deploy-fe/src/components/iframe/check-balance-iframe/useCheckBalance.tsx
|
|
||||||
./apps/deploy-fe/src/components/layout/index.ts
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/github-session-button/GitHubSessionButton.tsx
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/github-session-button/README.md
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/github-session-button/index.ts
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/github-session-button/types.ts
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/laconic-icon/LaconicIcon.tsx
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/laconic-icon/README.md
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/laconic-icon/index.ts
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/laconic-icon/types.ts
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/navigation-actions/NavigationActions.tsx
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/navigation-actions/README.md
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/navigation-actions/index.ts
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/navigation-actions/types.ts
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/wallet-session-id/README.md
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/wallet-session-id/WalletSessionId.tsx
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/wallet-session-id/index.ts
|
|
||||||
./apps/deploy-fe/src/components/layout/navigation/wallet-session-id/types.ts
|
|
||||||
./apps/deploy-fe/src/components/loading/loading-overlay.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/OPTIMIZATION.md
|
|
||||||
./apps/deploy-fe/src/components/onboarding/Onboarding.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/OnboardingButton.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/OnboardingDialog.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/OnboardingSidebar.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/README.md
|
|
||||||
./apps/deploy-fe/src/components/onboarding/common/background-svg.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/common/index.ts
|
|
||||||
./apps/deploy-fe/src/components/onboarding/common/laconic-icon-lettering.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/common/onboarding-container.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/common/step-header.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/common/step-navigation.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/configure-step/configure-step.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/configure-step/disable_configure-step.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/configure-step/index.ts
|
|
||||||
./apps/deploy-fe/src/components/onboarding/connect-step/connect-button.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/connect-step/connect-deploy-first-app.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/connect-step/connect-initial.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/connect-step/connect-step.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/connect-step/disabled_connect-step.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/connect-step/index.ts
|
|
||||||
./apps/deploy-fe/src/components/onboarding/connect-step/repository-list.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/connect-step/template-list.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/deploy-step/deploy-step.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/deploy-step/disabled_deploy-step.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/deploy-step/index.ts
|
|
||||||
./apps/deploy-fe/src/components/onboarding/index.ts
|
|
||||||
./apps/deploy-fe/src/components/onboarding/sidebar/index.ts
|
|
||||||
./apps/deploy-fe/src/components/onboarding/sidebar/sidebar-nav.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/store.ts
|
|
||||||
./apps/deploy-fe/src/components/onboarding/success-step/success-step.tsx
|
|
||||||
./apps/deploy-fe/src/components/onboarding/types.ts
|
|
||||||
./apps/deploy-fe/src/components/onboarding/useOnboarding.ts
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectCard/FixedProjectCard.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectCard/ProjectCard.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectCard/ProjectCardActions.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectCard/ProjectDeploymentInfo.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectCard/ProjectStatusDot.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectCard/index.ts
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectSearchBar/ProjectSearchBar.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectSearchBar/ProjectSearchBarDialog.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectSearchBar/ProjectSearchBarEmpty.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectSearchBar/ProjectSearchBarItem.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/ProjectSearchBar/index.ts
|
|
||||||
./apps/deploy-fe/src/components/projects/project/deployments/DeploymentDetailsCard.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/deployments/FilterForm.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/overview/Activity/AuctionCard.tsx
|
|
||||||
./apps/deploy-fe/src/components/projects/project/overview/OverviewInfo.tsx
|
|
||||||
./apps/deploy-fe/src/components/providers.tsx
|
|
||||||
./apps/deploy-fe/src/context/GQLClientContext.tsx
|
|
||||||
./apps/deploy-fe/src/context/OctokitContext.tsx
|
|
||||||
./apps/deploy-fe/src/context/OctokitProviderWithRouter.tsx
|
|
||||||
./apps/deploy-fe/src/context/WalletContext.tsx
|
|
||||||
./apps/deploy-fe/src/context/WalletContextProvider.tsx
|
|
||||||
./apps/deploy-fe/src/context/index.ts
|
|
||||||
./apps/deploy-fe/src/hooks/disabled_useDeployment.tsx
|
|
||||||
./apps/deploy-fe/src/hooks/disabled_useRepoData.tsx
|
|
||||||
./apps/deploy-fe/src/hooks/useDeployment.tsx
|
|
||||||
./apps/deploy-fe/src/hooks/useRepoData.tsx
|
|
||||||
./apps/deploy-fe/src/hooks/useRepoSelection.tsx
|
|
||||||
./apps/deploy-fe/src/lib/utils.ts
|
|
||||||
./apps/deploy-fe/src/middleware.ts
|
|
||||||
./apps/deploy-fe/src/types/common.ts
|
|
||||||
./apps/deploy-fe/src/types/dashboard.ts
|
|
||||||
./apps/deploy-fe/src/types/deployment.ts
|
|
||||||
./apps/deploy-fe/src/types/hooks/use-mobile.tsx
|
|
||||||
./apps/deploy-fe/src/types/index.ts
|
|
||||||
./apps/deploy-fe/src/types/project.ts
|
|
||||||
./apps/deploy-fe/src/utils/getInitials.ts
|
|
||||||
./apps/deploy-fe/src/utils/time.ts
|
|
||||||
./apps/deploy-fe/standards/architecture/routes.md
|
|
||||||
./apps/deploy-fe/tailwind.config.ts
|
|
||||||
./apps/deploy-fe/tsconfig.json
|
|
||||||
./apps/deployer/README.md
|
|
||||||
./apps/deployer/biome.json
|
|
||||||
./apps/deployer/package.json
|
|
||||||
./apps/deployer/test/README.md
|
|
||||||
./biome.json
|
|
||||||
./docs/architecture/wallet_migration/0-wallet-integration-overview.md
|
|
||||||
./docs/architecture/wallet_migration/1-phase-1-wallet-core.md
|
|
||||||
./docs/architecture/wallet_migration/2-phase-2-wallet-ui.md
|
|
||||||
./docs/architecture/wallet_migration/3-phase-3-clerk-integration.md
|
|
||||||
./next-agent-01.md
|
|
||||||
./package.json
|
|
||||||
./readme.md
|
|
||||||
./scripts/README.md
|
|
||||||
./services/gql-client/biome.json
|
|
||||||
./services/gql-client/dist/index.d.ts
|
|
||||||
./services/gql-client/package.json
|
|
||||||
./services/gql-client/src/client.ts
|
|
||||||
./services/gql-client/src/index.ts
|
|
||||||
./services/gql-client/src/mutations.ts
|
|
||||||
./services/gql-client/src/queries.ts
|
|
||||||
./services/gql-client/src/types.ts
|
|
||||||
./services/gql-client/tsconfig.json
|
|
||||||
./services/gql-client/tsup.config.ts
|
|
||||||
./services/typescript-config/README.md
|
|
||||||
./services/typescript-config/base.json
|
|
||||||
./services/typescript-config/nextjs.json
|
|
||||||
./services/typescript-config/package.json
|
|
||||||
./services/typescript-config/react-library.json
|
|
||||||
./services/ui/components.json
|
|
||||||
./services/ui/package.json
|
|
||||||
./services/ui/src/components/accordion.tsx
|
|
||||||
./services/ui/src/components/alert-dialog.tsx
|
|
||||||
./services/ui/src/components/alert.tsx
|
|
||||||
./services/ui/src/components/aspect-ratio.tsx
|
|
||||||
./services/ui/src/components/avatar.tsx
|
|
||||||
./services/ui/src/components/badge.tsx
|
|
||||||
./services/ui/src/components/breadcrumb.tsx
|
|
||||||
./services/ui/src/components/button.tsx
|
|
||||||
./services/ui/src/components/calendar.tsx
|
|
||||||
./services/ui/src/components/card.tsx
|
|
||||||
./services/ui/src/components/carousel.tsx
|
|
||||||
./services/ui/src/components/chart.tsx
|
|
||||||
./services/ui/src/components/checkbox.tsx
|
|
||||||
./services/ui/src/components/collapsible.tsx
|
|
||||||
./services/ui/src/components/command.tsx
|
|
||||||
./services/ui/src/components/context-menu.tsx
|
|
||||||
./services/ui/src/components/dialog.tsx
|
|
||||||
./services/ui/src/components/drawer.tsx
|
|
||||||
./services/ui/src/components/dropdown-menu.tsx
|
|
||||||
./services/ui/src/components/form.tsx
|
|
||||||
./services/ui/src/components/hover-card.tsx
|
|
||||||
./services/ui/src/components/input-otp.tsx
|
|
||||||
./services/ui/src/components/input.tsx
|
|
||||||
./services/ui/src/components/label.tsx
|
|
||||||
./services/ui/src/components/menubar.tsx
|
|
||||||
./services/ui/src/components/navigation-menu.tsx
|
|
||||||
./services/ui/src/components/pagination.tsx
|
|
||||||
./services/ui/src/components/popover.tsx
|
|
||||||
./services/ui/src/components/progress.tsx
|
|
||||||
./services/ui/src/components/radio-group.tsx
|
|
||||||
./services/ui/src/components/resizable.tsx
|
|
||||||
./services/ui/src/components/scroll-area.tsx
|
|
||||||
./services/ui/src/components/select.tsx
|
|
||||||
./services/ui/src/components/separator.tsx
|
|
||||||
./services/ui/src/components/sheet.tsx
|
|
||||||
./services/ui/src/components/sidebar.tsx
|
|
||||||
./services/ui/src/components/skeleton.tsx
|
|
||||||
./services/ui/src/components/slider.tsx
|
|
||||||
./services/ui/src/components/sonner.tsx
|
|
||||||
./services/ui/src/components/switch.tsx
|
|
||||||
./services/ui/src/components/table.tsx
|
|
||||||
./services/ui/src/components/tabs.tsx
|
|
||||||
./services/ui/src/components/textarea.tsx
|
|
||||||
./services/ui/src/components/toggle-group.tsx
|
|
||||||
./services/ui/src/components/toggle.tsx
|
|
||||||
./services/ui/src/components/tooltip.tsx
|
|
||||||
./services/ui/src/hooks/use-mobile.ts
|
|
||||||
./services/ui/src/lib/utils.ts
|
|
||||||
./services/ui/tailwind.config.ts
|
|
||||||
./services/ui/tsconfig.json
|
|
||||||
./services/ui/tsconfig.lint.json
|
|
||||||
./standards/blueprints/file-migration-list.md
|
|
||||||
./standards/blueprints/next-app-router-structure.md
|
|
||||||
./standards/blueprints/nextjs-templates.md
|
|
||||||
./standards/blueprints/qwrk-laconic-migration-guide.md
|
|
||||||
./standards/current-tech-reference.md
|
|
||||||
./standards/documentation/COMPONENT_DOCUMENTATION.md
|
|
||||||
./standards/documentation/FEATURE_BUILDING.md
|
|
||||||
./standards/documentation/FEATURE_BUILDING_TEMPLATE.md
|
|
||||||
./standards/documentation/README.md
|
|
||||||
./standards/documentation/react-component-conventions.md
|
|
||||||
./tsconfig.base.json
|
|
||||||
./tsconfig.json
|
|
||||||
./turbo.json
|
|
Loading…
Reference in New Issue
Block a user