openship 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +19 -3
- package/CONTRIBUTING.md +69 -19
- package/LICENSE +661 -0
- package/README.md +304 -108
- package/apps/api/Dockerfile +6 -8
- package/apps/api/package.json +25 -21
- package/apps/api/src/app.ts +46 -3
- package/apps/api/src/config/env.ts +81 -7
- package/apps/api/src/lib/auth-mode.ts +42 -0
- package/apps/api/src/lib/auth.ts +105 -0
- package/apps/api/src/lib/cache.ts +128 -0
- package/apps/api/src/lib/cloud-auth-proxy.ts +310 -0
- package/apps/api/src/lib/cloud-client.ts +103 -0
- package/apps/api/src/lib/compose-parser.ts +138 -0
- package/apps/api/src/lib/controller-helpers.ts +90 -0
- package/apps/api/src/lib/email-templates.ts +94 -0
- package/apps/api/src/lib/encryption.ts +102 -0
- package/apps/api/src/lib/local-user.ts +65 -0
- package/apps/api/src/lib/mail.ts +48 -0
- package/apps/api/src/lib/notifications.ts +195 -0
- package/apps/api/src/lib/openship-cloud.ts +101 -0
- package/apps/api/src/lib/resources.ts +96 -0
- package/apps/api/src/lib/screenshots.ts +189 -0
- package/apps/api/src/lib/ssh-manager.ts +369 -0
- package/apps/api/src/lib/ssl-scheduler.ts +109 -0
- package/apps/api/src/lib/stack-detector.ts +708 -0
- package/apps/api/src/lib/system-debug.ts +10 -0
- package/apps/api/src/middleware/auth.ts +49 -13
- package/apps/api/src/middleware/error-handler.ts +23 -3
- package/apps/api/src/middleware/index.ts +2 -0
- package/apps/api/src/middleware/internal-auth.ts +40 -0
- package/apps/api/src/middleware/local-only.ts +20 -0
- package/apps/api/src/middleware/rate-limiter.ts +9 -0
- package/apps/api/src/modules/analytics/analytics.controller.ts +111 -0
- package/apps/api/src/modules/analytics/analytics.routes.ts +29 -0
- package/apps/api/src/modules/analytics/analytics.schema.ts +37 -0
- package/apps/api/src/modules/analytics/analytics.service.ts +264 -0
- package/apps/api/src/modules/auth/auth.routes.ts +233 -6
- package/apps/api/src/modules/billing/billing.routes.ts +8 -0
- package/apps/api/src/modules/cloud/cloud.controller.ts +225 -0
- package/apps/api/src/modules/cloud/cloud.routes.ts +40 -0
- package/apps/api/src/modules/deployments/build.service.ts +791 -0
- package/apps/api/src/modules/deployments/deployment-lifecycle.ts +138 -0
- package/apps/api/src/modules/deployments/deployment.controller.ts +324 -16
- package/apps/api/src/modules/deployments/deployment.routes.ts +33 -7
- package/apps/api/src/modules/deployments/deployment.schema.ts +37 -5
- package/apps/api/src/modules/deployments/deployment.service.ts +178 -11
- package/apps/api/src/modules/deployments/preflight.ts +280 -0
- package/apps/api/src/modules/deployments/prepare.service.ts +252 -0
- package/apps/api/src/modules/deployments/session-manager.ts +283 -0
- package/apps/api/src/modules/deployments/ssl.service.ts +73 -0
- package/apps/api/src/modules/domains/domain.controller.ts +59 -7
- package/apps/api/src/modules/domains/domain.routes.ts +20 -5
- package/apps/api/src/modules/domains/domain.schema.ts +35 -0
- package/apps/api/src/modules/domains/domain.service.ts +375 -9
- package/apps/api/src/modules/github/github.auth.ts +397 -0
- package/apps/api/src/modules/github/github.controller.ts +387 -0
- package/apps/api/src/modules/github/github.local-auth.ts +251 -0
- package/apps/api/src/modules/github/github.routes.ts +50 -0
- package/apps/api/src/modules/github/github.schema.ts +52 -0
- package/apps/api/src/modules/github/github.service.ts +592 -0
- package/apps/api/src/modules/github/github.types.ts +158 -0
- package/apps/api/src/modules/github/github.webhook.ts +186 -0
- package/apps/api/src/modules/github/index.ts +16 -0
- package/apps/api/src/modules/health/health.routes.ts +35 -0
- package/apps/api/src/modules/projects/project.controller.ts +481 -12
- package/apps/api/src/modules/projects/project.routes.ts +63 -6
- package/apps/api/src/modules/projects/project.schema.ts +104 -6
- package/apps/api/src/modules/projects/project.service.ts +502 -11
- package/apps/api/src/modules/settings/settings.controller.ts +55 -0
- package/apps/api/src/modules/settings/settings.routes.ts +25 -0
- package/apps/api/src/modules/settings/settings.service.ts +49 -0
- package/apps/api/src/modules/system/filesystem.controller.ts +66 -0
- package/apps/api/src/modules/system/index.ts +1 -0
- package/apps/api/src/modules/system/server-check.controller.ts +475 -0
- package/apps/api/src/modules/system/setup-session.ts +255 -0
- package/apps/api/src/modules/system/setup.controller.ts +128 -0
- package/apps/api/src/modules/system/system.routes.ts +42 -0
- package/apps/api/src/modules/webhooks/webhook.controller.ts +57 -15
- package/apps/api/src/modules/webhooks/webhook.routes.ts +11 -8
- package/apps/api/src/modules/webhooks/webhook.service.ts +46 -5
- package/apps/api/src/modules/webhooks/webhook.types.ts +35 -0
- package/apps/api/tsconfig.json +3 -1
- package/apps/cli/package.json +8 -10
- package/apps/cli/tsconfig.json +2 -1
- package/apps/dashboard/Dockerfile +4 -6
- package/apps/dashboard/components.json +20 -0
- package/apps/dashboard/next-env.d.ts +6 -0
- package/apps/dashboard/next.config.mjs +11 -1
- package/apps/dashboard/package.json +25 -13
- package/apps/dashboard/postcss.config.mjs +5 -0
- package/apps/dashboard/public/android-chrome-192x192.png +0 -0
- package/apps/dashboard/public/android-chrome-512x512.png +0 -0
- package/apps/dashboard/public/apple-touch-icon.png +0 -0
- package/apps/dashboard/public/favicon-16x16.png +0 -0
- package/apps/dashboard/public/favicon-32x32.png +0 -0
- package/apps/dashboard/public/favicon.ico +0 -0
- package/apps/dashboard/public/site.webmanifest +19 -0
- package/apps/dashboard/src/app/(auth)/forgot-password/page.tsx +114 -0
- package/apps/dashboard/src/app/(auth)/layout.tsx +18 -3
- package/apps/dashboard/src/app/(auth)/login/page.tsx +215 -6
- package/apps/dashboard/src/app/(auth)/providers.tsx +34 -0
- package/apps/dashboard/src/app/(auth)/register/page.tsx +171 -5
- package/apps/dashboard/src/app/(auth)/reset-password/page.tsx +172 -0
- package/apps/dashboard/src/app/(auth)/verify-email/page.tsx +190 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/build/[id]/page.tsx +162 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/BuildSummary.tsx +166 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DnsConfiguration.tsx +119 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/DomainSettings.tsx +291 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Header.tsx +71 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/Sidebar.tsx +270 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/components/SkeletonLoader.tsx +87 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/deploy/[slug]/page.tsx +169 -0
- package/apps/dashboard/src/app/(dashboard)/(deployment)/layout.tsx +7 -0
- package/apps/dashboard/src/app/(dashboard)/billing/page.tsx +1 -8
- package/apps/dashboard/src/app/(dashboard)/deployments/components/CommitDetailsModal.tsx +240 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentCard.tsx +121 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentHeader.tsx +89 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentMenu.tsx +182 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsContent.tsx +324 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsFilters.tsx +99 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/DeploymentsList.tsx +31 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/EmptyState.tsx +101 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/LoadingSkeleton.tsx +57 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/ProjectFilter.tsx +109 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/components/index.ts +9 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/page.tsx +9 -3
- package/apps/dashboard/src/app/(dashboard)/deployments/types.ts +44 -0
- package/apps/dashboard/src/app/(dashboard)/deployments/utils.ts +176 -0
- package/apps/dashboard/src/app/(dashboard)/domains/page.tsx +1 -6
- package/apps/dashboard/src/app/(dashboard)/integrations/page.tsx +321 -0
- package/apps/dashboard/src/app/(dashboard)/layout.tsx +22 -32
- package/apps/dashboard/src/app/(dashboard)/library/components/ConnectPrompt.tsx +187 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/LibrarySidebar.tsx +147 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/LoadingSkeleton.tsx +39 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/LocalProjects.tsx +548 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/RepositoryList.tsx +292 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/TemplateGrid.tsx +36 -0
- package/apps/dashboard/src/app/(dashboard)/library/components/UrlImport.tsx +74 -0
- package/apps/dashboard/src/app/(dashboard)/library/page.tsx +121 -0
- package/apps/dashboard/src/app/(dashboard)/library/types.ts +26 -0
- package/apps/dashboard/src/app/(dashboard)/monitoring/page.tsx +1 -6
- package/apps/dashboard/src/app/(dashboard)/page.tsx +485 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/layout.tsx +22 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/[[...slug]]/page.tsx +286 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/AdvancedSettings.tsx +235 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/BuildSettings.tsx +174 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeleteConfirmationDialog.tsx +45 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DeletionModal.tsx +95 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/Deployments.tsx +11 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/DomainSettings.tsx +523 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/EnvironmentSettings.tsx +246 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GeneralSettings.tsx +93 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitInfo.tsx +261 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/GitSettings.tsx +391 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/LogsSettings.tsx +133 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectNotFound.tsx +95 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ProjectsBottomNavigation.tsx +62 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/ResourceSettings.tsx +333 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingSection.tsx +66 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SettingsNavigation.tsx +27 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/SleepModeSettings.tsx +134 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProductionUrl.tsx +25 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectIdentity.tsx +159 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectInfo.tsx +58 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/SkeletonLoader.tsx +170 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/StatsCards.tsx +33 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TopPaths.tsx +56 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/TrafficChart.tsx +157 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/index.ts +14 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/LogsActions.tsx +52 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/ServerLogs.tsx +249 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/TerminalLogs.tsx +682 -0
- package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/logs/logs.css +127 -0
- package/apps/dashboard/src/app/(dashboard)/projects/components/DeploymentCard.tsx +73 -0
- package/apps/dashboard/src/app/(dashboard)/projects/components/ProjectCard.tsx +330 -0
- package/apps/dashboard/src/app/(dashboard)/projects/page.tsx +326 -4
- package/apps/dashboard/src/app/(dashboard)/providers.tsx +23 -0
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/components-tab.tsx +329 -0
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/overview-tab.tsx +229 -0
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/_components/terminal-tab.tsx +38 -0
- package/apps/dashboard/src/app/(dashboard)/servers/[serverId]/page.tsx +437 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/checking-state.tsx +15 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/choose-mode.tsx +54 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/component-row.tsx +65 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/error-banner.tsx +13 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/installing-panel.tsx +227 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/results-panel.tsx +90 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/setup-header.tsx +56 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/_components/types.ts +13 -0
- package/apps/dashboard/src/app/(dashboard)/servers/new/page.tsx +666 -0
- package/apps/dashboard/src/app/(dashboard)/servers/page.tsx +283 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/BuildPreferences.tsx +110 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/CloudConnection.tsx +147 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/InstanceInfo.tsx +54 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/ServerConnection.tsx +407 -0
- package/apps/dashboard/src/app/(dashboard)/settings/_components/SettingsSection.tsx +32 -0
- package/apps/dashboard/src/app/(dashboard)/settings/page.tsx +62 -3
- package/apps/dashboard/src/app/auth/callback/close/page.tsx +23 -0
- package/apps/dashboard/src/app/auth/callback/install/page.tsx +40 -0
- package/apps/dashboard/src/app/authorize/page.tsx +137 -0
- package/apps/dashboard/src/app/globals.css +57 -3
- package/apps/dashboard/src/app/layout.tsx +43 -3
- package/apps/dashboard/src/components/auth-shell.tsx +66 -0
- package/apps/dashboard/src/components/deployments/types.ts +44 -0
- package/apps/dashboard/src/components/global-deployments/index.ts +17 -0
- package/apps/dashboard/src/components/i18n-provider.tsx +100 -0
- package/apps/dashboard/src/components/import-project/BuildSettings.tsx +376 -0
- package/apps/dashboard/src/components/import-project/BuildSkeleton.tsx +161 -0
- package/apps/dashboard/src/components/import-project/BuildTerminal.tsx +358 -0
- package/apps/dashboard/src/components/import-project/ComposeServices.tsx +455 -0
- package/apps/dashboard/src/components/import-project/DeploymentProcessing.tsx +510 -0
- package/apps/dashboard/src/components/import-project/DockerSettings.tsx +64 -0
- package/apps/dashboard/src/components/import-project/EnvironmentVariables.tsx +481 -0
- package/apps/dashboard/src/components/import-project/Frameworks.tsx +90 -0
- package/apps/dashboard/src/components/import-project/ProjectSettings.tsx +160 -0
- package/apps/dashboard/src/components/import-project/types.ts +82 -0
- package/apps/dashboard/src/components/integrations/GithubPermissionModal.tsx +173 -0
- package/apps/dashboard/src/components/language-switcher.tsx +36 -0
- package/apps/dashboard/src/components/logo.tsx +13 -0
- package/apps/dashboard/src/components/network-error-handler.tsx +27 -0
- package/apps/dashboard/src/components/oauth-buttons.tsx +81 -0
- package/apps/dashboard/src/components/overview/ActivityChart.tsx +247 -0
- package/apps/dashboard/src/components/overview/ApiRequestsCard.tsx +111 -0
- package/apps/dashboard/src/components/overview/CreditsCard.tsx +137 -0
- package/apps/dashboard/src/components/overview/DeploymentsChart.tsx +195 -0
- package/apps/dashboard/src/components/overview/EmptyState.tsx +126 -0
- package/apps/dashboard/src/components/overview/LoadingSkeleton.tsx +92 -0
- package/apps/dashboard/src/components/overview/OverviewHeader.tsx +74 -0
- package/apps/dashboard/src/components/overview/OverviewHeroChart.tsx +344 -0
- package/apps/dashboard/src/components/overview/ProjectsCard.tsx +134 -0
- package/apps/dashboard/src/components/overview/QuickLinks.tsx +119 -0
- package/apps/dashboard/src/components/overview/SandboxesCard.tsx +150 -0
- package/apps/dashboard/src/components/overview/StatsGrid.tsx +166 -0
- package/apps/dashboard/src/components/overview/TokenUsageChart.tsx +206 -0
- package/apps/dashboard/src/components/overview/UsageStats.tsx +79 -0
- package/apps/dashboard/src/components/overview/index.ts +30 -0
- package/apps/dashboard/src/components/overview/types.ts +116 -0
- package/apps/dashboard/src/components/page-header.tsx +25 -0
- package/apps/dashboard/src/components/project-settings/ServerSideSwitch.jsx +60 -0
- package/apps/dashboard/src/components/shared/AlertBox.tsx +39 -0
- package/apps/dashboard/src/components/shared/CTASection.tsx +45 -0
- package/apps/dashboard/src/components/shared/ErrorState.tsx +176 -0
- package/apps/dashboard/src/components/shared/FeatureCard.tsx +20 -0
- package/apps/dashboard/src/components/shared/MDXComponents.tsx +24 -0
- package/apps/dashboard/src/components/shared/MachineSettingsModal.tsx +286 -0
- package/apps/dashboard/src/components/shared/Modal.tsx +39 -0
- package/apps/dashboard/src/components/shared/OTPInput.tsx +122 -0
- package/apps/dashboard/src/components/shared/PageHero.tsx +21 -0
- package/apps/dashboard/src/components/shared/PlatformFeatureCard.tsx +27 -0
- package/apps/dashboard/src/components/shared/StatCard.tsx +14 -0
- package/apps/dashboard/src/components/shared/ValueCard.tsx +20 -0
- package/apps/dashboard/src/components/shared/index.ts +8 -0
- package/apps/dashboard/src/components/sidebar.tsx +282 -0
- package/apps/dashboard/src/components/theme-provider.tsx +96 -0
- package/apps/dashboard/src/components/toast.tsx +106 -0
- package/apps/dashboard/src/components/ui/CustomCursor.tsx +107 -0
- package/apps/dashboard/src/components/ui/CustomSelect.tsx +126 -0
- package/apps/dashboard/src/components/ui/DropdownMenu.tsx +174 -0
- package/apps/dashboard/src/components/ui/FileIcon.jsx +59 -0
- package/apps/dashboard/src/components/ui/IconPickerModal.tsx +273 -0
- package/apps/dashboard/src/components/ui/InfoBanner.jsx +39 -0
- package/apps/dashboard/src/components/ui/Logo.tsx +14 -0
- package/apps/dashboard/src/components/ui/Modal.tsx +117 -0
- package/apps/dashboard/src/components/ui/PageContainer.tsx +12 -0
- package/apps/dashboard/src/components/ui/SectionContainer.jsx +7 -0
- package/apps/dashboard/src/components/ui/SlidingToggle.tsx +128 -0
- package/apps/dashboard/src/components/ui/Toast.tsx +29 -0
- package/apps/dashboard/src/components/ui/button.tsx +58 -0
- package/apps/dashboard/src/components/ui/card.tsx +60 -0
- package/apps/dashboard/src/components/ui/input.tsx +20 -0
- package/apps/dashboard/src/components/ui/label.tsx +19 -0
- package/apps/dashboard/src/components/ui/select.tsx +10 -0
- package/apps/dashboard/src/components/ui/textarea.tsx +9 -0
- package/apps/dashboard/src/constants/lang-colors.ts +25 -0
- package/apps/dashboard/src/constants/mock.ts +38 -0
- package/apps/dashboard/src/context/AuthContext.tsx +91 -0
- package/apps/dashboard/src/context/CloudContext.tsx +275 -0
- package/apps/dashboard/src/context/DeploymentContext.tsx +71 -0
- package/apps/dashboard/src/context/GitHubContext.tsx +288 -0
- package/apps/dashboard/src/context/ModalContext.tsx +300 -0
- package/apps/dashboard/src/context/NetworkContext.tsx +32 -0
- package/apps/dashboard/src/context/ProjectSettingsContext.tsx +727 -0
- package/apps/dashboard/src/context/ToastContext.tsx +129 -0
- package/apps/dashboard/src/context/deployment/index.ts +3 -0
- package/apps/dashboard/src/context/deployment/types.ts +183 -0
- package/apps/dashboard/src/context/deployment/useDeploymentBuild.ts +547 -0
- package/apps/dashboard/src/context/deployment/useDeploymentConfig.ts +176 -0
- package/apps/dashboard/src/hooks/useBuildConnection.ts +334 -0
- package/apps/dashboard/src/hooks/useMonitorStream.ts +146 -0
- package/apps/dashboard/src/hooks/useProjectData.ts +110 -0
- package/apps/dashboard/src/hooks/useSSEConnection.ts +465 -0
- package/apps/dashboard/src/hooks/useSSEStream.ts +309 -0
- package/apps/dashboard/src/hooks/useSessions.ts +104 -0
- package/apps/dashboard/src/hooks/useSetupStream.ts +223 -0
- package/apps/dashboard/src/i18n/dictionaries/ar.json +218 -0
- package/apps/dashboard/src/i18n/dictionaries/en.json +218 -0
- package/apps/dashboard/src/i18n/index.ts +16 -0
- package/apps/dashboard/src/lib/api/ai.ts +22 -0
- package/apps/dashboard/src/lib/api/auth.ts +13 -0
- package/apps/dashboard/src/lib/api/client.ts +199 -0
- package/apps/dashboard/src/lib/api/cloud.ts +15 -0
- package/apps/dashboard/src/lib/api/deploy.ts +58 -0
- package/apps/dashboard/src/lib/api/domains.ts +13 -0
- package/apps/dashboard/src/lib/api/endpoints.ts +129 -0
- package/apps/dashboard/src/lib/api/github.ts +31 -0
- package/apps/dashboard/src/lib/api/icons.ts +12 -0
- package/apps/dashboard/src/lib/api/index.ts +41 -0
- package/apps/dashboard/src/lib/api/projects.ts +153 -0
- package/apps/dashboard/src/lib/api/sandbox.ts +14 -0
- package/apps/dashboard/src/lib/api/settings.ts +21 -0
- package/apps/dashboard/src/lib/api/system.ts +159 -0
- package/apps/dashboard/src/lib/auth-client.ts +54 -0
- package/apps/dashboard/src/lib/country.ts +25 -0
- package/apps/dashboard/src/lib/server/api.ts +140 -0
- package/apps/dashboard/src/lib/server/session.ts +103 -0
- package/apps/dashboard/src/lib/sseClient.ts +241 -0
- package/apps/dashboard/src/lib/sseMessageProcessors.ts +323 -0
- package/apps/dashboard/src/lib/utils.ts +6 -0
- package/apps/dashboard/src/proxy.ts +46 -0
- package/apps/dashboard/src/styles/Toast.module.css +92 -0
- package/apps/dashboard/src/styles/fonts.css +93 -0
- package/apps/dashboard/src/styles/theme.css +336 -0
- package/apps/dashboard/src/types/research.ts +42 -0
- package/apps/dashboard/src/utils/SSEParser.js +150 -0
- package/apps/dashboard/src/utils/authWindow.ts +143 -0
- package/apps/dashboard/src/utils/codeTheme.ts +127 -0
- package/apps/dashboard/src/utils/colors.json +2810 -0
- package/apps/dashboard/src/utils/date.ts +121 -0
- package/apps/dashboard/src/utils/deployment.ts +128 -0
- package/apps/dashboard/src/utils/deploymentPhaseDetector.ts +232 -0
- package/apps/dashboard/src/utils/extToLang.js +103 -0
- package/apps/dashboard/src/utils/github.ts +62 -0
- package/apps/dashboard/src/utils/icons.js +46 -0
- package/apps/dashboard/src/utils/repoSlug.ts +110 -0
- package/apps/dashboard/src/utils/research-api.ts +163 -0
- package/apps/dashboard/src/utils/suggestions.ts +84 -0
- package/apps/dashboard/src/utils/theme.js +1 -0
- package/apps/dashboard/src/utils/ui-helpers.tsx +30 -0
- package/apps/dashboard/src/utils/upload.js +12 -0
- package/apps/dashboard/tsconfig.json +27 -5
- package/apps/desktop/forge.config.json +36 -0
- package/apps/desktop/package.json +26 -0
- package/apps/desktop/scripts/dev.mjs +58 -0
- package/apps/desktop/src/main/index.ts +675 -0
- package/apps/desktop/src/main/types/desktop.d.ts +33 -0
- package/apps/desktop/src/preload/index.ts +88 -0
- package/apps/desktop/src/renderer/index.html +462 -0
- package/apps/desktop/src/renderer/onboarding.js +511 -0
- package/apps/desktop/src/renderer/styles.css +1139 -0
- package/apps/desktop/tsconfig.json +17 -0
- package/apps/web/.source/browser.ts +13 -0
- package/apps/web/.source/dynamic.ts +8 -0
- package/apps/web/.source/server.ts +22 -0
- package/apps/web/.source/source.config.mjs +20 -0
- package/apps/web/Dockerfile +4 -6
- package/apps/web/content/blog/how-ai-builds-work.mdx +55 -0
- package/apps/web/content/blog/introducing-openship.mdx +46 -0
- package/apps/web/content/blog/self-hosting-cost-breakdown.mdx +59 -0
- package/apps/web/content/docs/_meta.json +14 -0
- package/apps/web/content/docs/api.mdx +98 -0
- package/apps/web/content/docs/cli.mdx +80 -0
- package/apps/web/content/docs/first-deployment.mdx +56 -0
- package/apps/web/content/docs/index.mdx +27 -0
- package/apps/web/content/docs/installation.mdx +65 -0
- package/apps/web/content/docs/quickstart.mdx +45 -0
- package/apps/web/next-env.d.ts +6 -0
- package/apps/web/next.config.mjs +16 -2
- package/apps/web/package.json +19 -12
- package/apps/web/postcss.config.mjs +5 -0
- package/apps/web/public/android-chrome-192x192.png +0 -0
- package/apps/web/public/android-chrome-512x512.png +0 -0
- package/apps/web/public/apple-touch-icon.png +0 -0
- package/apps/web/public/favicon-16x16.png +0 -0
- package/apps/web/public/favicon-32x32.png +0 -0
- package/apps/web/public/favicon.ico +0 -0
- package/apps/web/public/site.webmanifest +1 -0
- package/apps/web/source.config.ts +17 -0
- package/apps/web/src/app/(marketing)/layout.tsx +7 -22
- package/apps/web/src/app/blog/[...slug]/page.tsx +247 -0
- package/apps/web/src/app/blog/blog.css +575 -0
- package/apps/web/src/app/blog/layout.tsx +50 -0
- package/apps/web/src/app/blog/page.tsx +235 -0
- package/apps/web/src/app/docs/[[...slug]]/page.tsx +67 -0
- package/apps/web/src/app/docs/layout.tsx +62 -0
- package/apps/web/src/app/docs/toc-theme.css +71 -0
- package/apps/web/src/app/download/page.tsx +396 -0
- package/apps/web/src/app/globals.css +20 -3
- package/apps/web/src/app/layout.tsx +57 -3
- package/apps/web/src/app/page.tsx +47 -6
- package/apps/web/src/app/robots.ts +15 -0
- package/apps/web/src/app/sitemap.ts +35 -0
- package/apps/web/src/components/blog/share-sidebar.tsx +81 -0
- package/apps/web/src/components/blog/writer-sidebar.tsx +81 -0
- package/apps/web/src/components/landing/ai-native.tsx +169 -0
- package/apps/web/src/components/landing/backups.tsx +139 -0
- package/apps/web/src/components/landing/cdn.tsx +109 -0
- package/apps/web/src/components/landing/coming-soon.tsx +180 -0
- package/apps/web/src/components/landing/dark-section.tsx +166 -0
- package/apps/web/src/components/landing/dashboard.tsx +407 -0
- package/apps/web/src/components/landing/developer-experience.tsx +224 -0
- package/apps/web/src/components/landing/dns-domains.tsx +146 -0
- package/apps/web/src/components/landing/download-button.tsx +151 -0
- package/apps/web/src/components/landing/features/ai-visual.tsx +48 -0
- package/apps/web/src/components/landing/features/cloud-visual.tsx +44 -0
- package/apps/web/src/components/landing/features/git-visual.tsx +61 -0
- package/apps/web/src/components/landing/features/index.tsx +642 -0
- package/apps/web/src/components/landing/features/infra-visual.tsx +69 -0
- package/apps/web/src/components/landing/features/rollback-visual.tsx +42 -0
- package/apps/web/src/components/landing/features/ssl-visual.tsx +41 -0
- package/apps/web/src/components/landing/features/stacks-visual.tsx +54 -0
- package/apps/web/src/components/landing/final-cta.tsx +116 -0
- package/apps/web/src/components/landing/footer.tsx +145 -0
- package/apps/web/src/components/landing/hero.tsx +110 -0
- package/apps/web/src/components/landing/how-it-works.tsx +210 -0
- package/apps/web/src/components/landing/index.ts +21 -0
- package/apps/web/src/components/landing/mail-server.tsx +122 -0
- package/apps/web/src/components/landing/navbar.tsx +199 -0
- package/apps/web/src/components/landing/no-lockin.tsx +185 -0
- package/apps/web/src/components/landing/open-source-cta.tsx +151 -0
- package/apps/web/src/components/landing/portability.tsx +190 -0
- package/apps/web/src/components/landing/pricing.tsx +263 -0
- package/apps/web/src/components/landing/scaling.tsx +209 -0
- package/apps/web/src/components/landing/why-openship.tsx +291 -0
- package/apps/web/src/hooks/use-gsap-scroll.ts +158 -0
- package/apps/web/src/hooks/use-platform.ts +86 -0
- package/apps/web/src/lib/source.ts +12 -0
- package/apps/web/src/styles/fonts.css +84 -0
- package/apps/web/src/styles/landing.css +951 -0
- package/apps/web/src/styles/theme.css +227 -0
- package/apps/web/tsconfig.json +8 -3
- package/bun.lock +3260 -0
- package/docker-compose.yml +3 -0
- package/docs/screenshots/.gitkeep +0 -0
- package/docs/screenshots/screen.png +0 -0
- package/openship.code-workspace +7 -0
- package/package.json +23 -9
- package/packages/adapters/docs/ARCHITECTURE.md +160 -0
- package/packages/adapters/docs/BUILD-PIPELINE.md +171 -0
- package/packages/adapters/docs/CLOUD.md +239 -0
- package/packages/adapters/docs/EXECUTOR.md +174 -0
- package/packages/adapters/docs/LOG-STREAMING.md +175 -0
- package/packages/adapters/docs/SYSTEM.md +191 -0
- package/packages/adapters/package.json +14 -9
- package/packages/adapters/src/index.ts +144 -4
- package/packages/adapters/src/infra/cloud.ts +42 -0
- package/packages/adapters/src/infra/index.ts +9 -0
- package/packages/adapters/src/infra/noop.ts +27 -0
- package/packages/adapters/src/infra/traefik.ts +297 -0
- package/packages/adapters/src/infra/types.ts +36 -0
- package/packages/adapters/src/platform.ts +255 -0
- package/packages/adapters/src/runtime/bare.ts +567 -0
- package/packages/adapters/src/runtime/build-pipeline.ts +237 -0
- package/packages/adapters/src/runtime/cloud.ts +791 -0
- package/packages/adapters/src/runtime/deploy-pipeline.ts +146 -0
- package/packages/adapters/src/runtime/docker.ts +443 -0
- package/packages/adapters/src/runtime/index.ts +69 -0
- package/packages/adapters/src/runtime/local-build.ts +112 -0
- package/packages/adapters/src/runtime/transfer.ts +82 -0
- package/packages/adapters/src/runtime/types.ts +138 -0
- package/packages/adapters/src/system/catalog.ts +188 -0
- package/packages/adapters/src/system/checks.ts +228 -0
- package/packages/adapters/src/system/components.ts +45 -0
- package/packages/adapters/src/system/debug.ts +18 -0
- package/packages/adapters/src/system/environment.ts +168 -0
- package/packages/adapters/src/system/errors.ts +34 -0
- package/packages/adapters/src/system/executor.ts +600 -0
- package/packages/adapters/src/system/index.ts +58 -0
- package/packages/adapters/src/system/installer.ts +310 -0
- package/packages/adapters/src/system/setup.ts +442 -0
- package/packages/adapters/src/system/state.ts +96 -0
- package/packages/adapters/src/system/types.ts +116 -0
- package/packages/adapters/src/toolchain/catalog.ts +439 -0
- package/packages/adapters/src/toolchain/checks.ts +181 -0
- package/packages/adapters/src/toolchain/index.ts +38 -0
- package/packages/adapters/src/toolchain/installer.ts +189 -0
- package/packages/adapters/src/toolchain/types.ts +84 -0
- package/packages/adapters/src/types.ts +277 -0
- package/packages/adapters/tsconfig.json +3 -1
- package/packages/core/package.json +9 -9
- package/packages/core/src/constants.ts +44 -1
- package/packages/core/src/index.ts +2 -0
- package/packages/core/src/stacks.ts +778 -0
- package/packages/core/src/system.ts +111 -0
- package/packages/core/src/types.ts +22 -1
- package/packages/core/src/utils.ts +8 -0
- package/packages/core/tsconfig.json +3 -1
- package/packages/db/drizzle/0000_init.sql +231 -0
- package/packages/db/drizzle/0001_add_server_name.sql +1 -0
- package/packages/db/drizzle/meta/_journal.json +20 -0
- package/packages/db/drizzle.config.ts +10 -0
- package/packages/db/package.json +26 -14
- package/packages/db/src/client.ts +119 -0
- package/packages/db/src/index.ts +57 -8
- package/packages/db/src/repos/account.repo.ts +92 -0
- package/packages/db/src/repos/deployment.repo.ts +168 -0
- package/packages/db/src/repos/domain.repo.ts +102 -0
- package/packages/db/src/repos/git-installation.repo.ts +95 -0
- package/packages/db/src/repos/index.ts +43 -0
- package/packages/db/src/repos/instance-settings.repo.ts +43 -0
- package/packages/db/src/repos/project.repo.ts +159 -0
- package/packages/db/src/repos/session.repo.ts +82 -0
- package/packages/db/src/repos/settings.repo.ts +51 -0
- package/packages/db/src/repos/user.repo.ts +94 -0
- package/packages/db/src/schema/auth.ts +56 -0
- package/packages/db/src/schema/deployment.ts +87 -0
- package/packages/db/src/schema/domain.ts +46 -0
- package/packages/db/src/schema/github.ts +24 -0
- package/packages/db/src/schema/index.ts +6 -0
- package/packages/db/src/schema/project.ts +117 -0
- package/packages/db/src/schema/settings.ts +103 -0
- package/packages/db/tsconfig.json +3 -1
- package/packages/ui/package.json +17 -17
- package/packages/ui/src/components/status-dot.tsx +1 -1
- package/packages/ui/tsconfig.json +7 -2
- package/pnpm-workspace.yaml +0 -1
- package/{tooling/tsconfig/base.json → tsconfig.base.json} +0 -1
- package/turbo.json +4 -0
- package/apps/api/src/modules/auth/auth.controller.ts +0 -26
- package/apps/api/src/modules/auth/auth.schema.ts +0 -12
- package/apps/api/src/modules/auth/auth.service.ts +0 -23
- package/apps/dashboard/src/app/page.tsx +0 -6
- package/apps/web/src/app/(marketing)/docs/page.tsx +0 -10
- package/packages/adapters/src/base-adapter.ts +0 -49
- package/packages/adapters/src/docker-adapter.ts +0 -43
- package/packages/adapters/src/oblien-adapter.ts +0 -46
- package/packages/adapters/src/registry.ts +0 -22
- package/packages/db/prisma/schema.prisma +0 -160
- package/tooling/tsconfig/nextjs.json +0 -10
- package/tooling/tsconfig/node.json +0 -10
- package/tooling/tsconfig/package.json +0 -7
package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/ProjectIdentity.tsx
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { generateIcon } from "@/utils/icons";
|
|
4
|
+
import { useProjectSettings } from "@/context/ProjectSettingsContext";
|
|
5
|
+
import { projectsApi } from "@/lib/api";
|
|
6
|
+
import { useToast } from "@/context/ToastContext";
|
|
7
|
+
|
|
8
|
+
export const ProjectIdentity: React.FC = () => {
|
|
9
|
+
const { projectData, updateProjectData } = useProjectSettings();
|
|
10
|
+
const [isEditingName, setIsEditingName] = useState(false);
|
|
11
|
+
const [isEditingDescription, setIsEditingDescription] = useState(false);
|
|
12
|
+
|
|
13
|
+
const [tempData, setTempData] = useState({
|
|
14
|
+
name: projectData.name || '',
|
|
15
|
+
description: projectData.description || '',
|
|
16
|
+
framework: projectData.framework || ''
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const [loading, setLoading] = useState({
|
|
20
|
+
name: false,
|
|
21
|
+
description: false,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const { showToast } = useToast();
|
|
25
|
+
|
|
26
|
+
const handleSaveName = async () => {
|
|
27
|
+
setLoading({ ...loading, name: true });
|
|
28
|
+
const response = await projectsApi.update(projectData.id, 'name', tempData.name);
|
|
29
|
+
if (response.success) {
|
|
30
|
+
updateProjectData({ name: tempData.name });
|
|
31
|
+
setIsEditingName(false);
|
|
32
|
+
} else {
|
|
33
|
+
showToast(response.message, 'error', 'Failed to update project name');
|
|
34
|
+
}
|
|
35
|
+
setLoading({ ...loading, name: false });
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const handleSaveDescription = async () => {
|
|
39
|
+
const response = await projectsApi.update(projectData.id, 'description', tempData.description);
|
|
40
|
+
if (response.success) {
|
|
41
|
+
updateProjectData({ description: tempData.description });
|
|
42
|
+
setIsEditingDescription(false);
|
|
43
|
+
} else {
|
|
44
|
+
showToast(response.message, 'error', 'Failed to update project description');
|
|
45
|
+
}
|
|
46
|
+
setLoading({ ...loading, description: false });
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const handleCancelName = () => {
|
|
50
|
+
setTempData((prev) => ({ ...prev, name: projectData.name || '' }));
|
|
51
|
+
setIsEditingName(false);
|
|
52
|
+
setLoading({ ...loading, name: false });
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const handleCancelDescription = () => {
|
|
56
|
+
setTempData((prev) => ({ ...prev, description: projectData.description || '' }));
|
|
57
|
+
setIsEditingDescription(false);
|
|
58
|
+
setLoading({ ...loading, description: false });
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div className="bg-white rounded-[20px] border border-black/5 p-6">
|
|
64
|
+
{/* Header */}
|
|
65
|
+
<div className="flex items-center gap-3 mb-6">
|
|
66
|
+
{generateIcon('layers-363-1658238246.png', 28, 'rgb(79, 70, 229)')}
|
|
67
|
+
<h3 className="text-lg font-semibold text-black">Project Identity</h3>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div className="flex flex-col lg:flex-row gap-5 lg:gap-6">
|
|
71
|
+
{/* Project Name */}
|
|
72
|
+
<div className="flex-1">
|
|
73
|
+
<label className="text-sm font-medium text-black/70 mb-2 block">Project Name</label>
|
|
74
|
+
|
|
75
|
+
{isEditingName ? (
|
|
76
|
+
<div className="space-y-3">
|
|
77
|
+
<input
|
|
78
|
+
type="text"
|
|
79
|
+
value={tempData.name}
|
|
80
|
+
onChange={(e) => setTempData((prev) => ({ ...prev, name: e.target.value }))}
|
|
81
|
+
placeholder="my-awesome-project"
|
|
82
|
+
className="w-full px-4 py-2.5 bg-black/5 border border-transparent rounded-xl focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500/20 focus:bg-white outline-none text-sm transition-all"
|
|
83
|
+
autoFocus
|
|
84
|
+
/>
|
|
85
|
+
<div className="flex gap-2">
|
|
86
|
+
<button
|
|
87
|
+
onClick={handleSaveName}
|
|
88
|
+
className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-full transition-all text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed"
|
|
89
|
+
>
|
|
90
|
+
Save
|
|
91
|
+
</button>
|
|
92
|
+
<button
|
|
93
|
+
onClick={handleCancelName}
|
|
94
|
+
className="px-4 py-2 bg-black/5 hover:bg-black/10 text-black rounded-full transition-all text-sm font-medium"
|
|
95
|
+
>
|
|
96
|
+
Cancel
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
) : (
|
|
101
|
+
<div className="relative p-4 bg-black/5 rounded-xl group hover:bg-black/10 transition-all">
|
|
102
|
+
<p className="text-sm font-medium text-black pr-8">{projectData.name || 'Unnamed Project'}</p>
|
|
103
|
+
<button
|
|
104
|
+
onClick={() => setIsEditingName(true)}
|
|
105
|
+
className="absolute right-3 top-1/2 -translate-y-1/2 p-1.5 text-black/40 hover:text-indigo-600 transition-colors"
|
|
106
|
+
>
|
|
107
|
+
{generateIcon("pen-411-1658238246.png", 18, "currentColor")}
|
|
108
|
+
</button>
|
|
109
|
+
</div>
|
|
110
|
+
)}
|
|
111
|
+
</div>
|
|
112
|
+
|
|
113
|
+
{/* Description */}
|
|
114
|
+
<div className="flex-1">
|
|
115
|
+
<label className="text-sm font-medium text-black/70 mb-2 block">Description</label>
|
|
116
|
+
|
|
117
|
+
{isEditingDescription ? (
|
|
118
|
+
<div className="space-y-3">
|
|
119
|
+
<textarea
|
|
120
|
+
value={tempData.description}
|
|
121
|
+
onChange={(e) => setTempData((prev) => ({ ...prev, description: e.target.value }))}
|
|
122
|
+
rows={3}
|
|
123
|
+
placeholder="A modern web application built with..."
|
|
124
|
+
className="w-full px-4 py-2.5 bg-black/5 border border-transparent rounded-xl focus:ring-2 focus:ring-indigo-500/20 focus:border-indigo-500/20 focus:bg-white outline-none resize-none text-sm transition-all"
|
|
125
|
+
autoFocus
|
|
126
|
+
/>
|
|
127
|
+
<div className="flex gap-2">
|
|
128
|
+
<button
|
|
129
|
+
onClick={handleSaveDescription}
|
|
130
|
+
className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-full transition-all text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed"
|
|
131
|
+
>
|
|
132
|
+
Save
|
|
133
|
+
</button>
|
|
134
|
+
<button
|
|
135
|
+
onClick={handleCancelDescription}
|
|
136
|
+
className="px-4 py-2 bg-black/5 hover:bg-black/10 text-black rounded-full transition-all text-sm font-medium"
|
|
137
|
+
>
|
|
138
|
+
Cancel
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
) : (
|
|
143
|
+
<div className="relative p-4 bg-black/5 rounded-xl group hover:bg-black/10 transition-all">
|
|
144
|
+
<p className="text-sm text-black/70 pr-8">
|
|
145
|
+
{projectData.description || 'No description provided'}
|
|
146
|
+
</p>
|
|
147
|
+
<button
|
|
148
|
+
onClick={() => setIsEditingDescription(true)}
|
|
149
|
+
className="absolute right-3 top-3 p-1.5 text-black/40 hover:text-indigo-600 transition-colors"
|
|
150
|
+
>
|
|
151
|
+
{generateIcon("pen-411-1658238246.png", 18, "currentColor")}
|
|
152
|
+
</button>
|
|
153
|
+
</div>
|
|
154
|
+
)}
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Activity, GitBranch, Calendar, Hash, Sparkles, Info } from "lucide-react";
|
|
4
|
+
import { generateIcon } from "@/utils/icons";
|
|
5
|
+
import { useProjectSettings } from "@/context/ProjectSettingsContext";
|
|
6
|
+
import { formatDate } from "@/utils/date";
|
|
7
|
+
import { useToast } from "@/context/ToastContext";
|
|
8
|
+
|
|
9
|
+
export const ProjectInfo: React.FC = () => {
|
|
10
|
+
const { projectData } = useProjectSettings();
|
|
11
|
+
const { showToast } = useToast();
|
|
12
|
+
const handleEditWithBlurs = () => {
|
|
13
|
+
showToast('Editing with Blurs is not available yet', 'success', 'Coming Soon');
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
{/* Project Metadata - Compact */}
|
|
19
|
+
<div className="bg-white rounded-[20px] border border-black/5 p-5">
|
|
20
|
+
<div className="flex items-center gap-2 mb-4">
|
|
21
|
+
{generateIcon('qr%20scan-120-1658435460.png', 24, 'rgb(79, 70, 229)')}
|
|
22
|
+
<h3 className="text-base font-semibold text-black">Project Info</h3>
|
|
23
|
+
</div>
|
|
24
|
+
<div className="space-y-3">
|
|
25
|
+
<div className="flex items-center justify-between">
|
|
26
|
+
<p className="text-xs text-black/50">Project ID</p>
|
|
27
|
+
<p className="text-xs text-black font-medium font-mono">{projectData.id?.substring(0, 8)}</p>
|
|
28
|
+
</div>
|
|
29
|
+
<div className="flex items-center justify-between">
|
|
30
|
+
<p className="text-xs text-black/50">Branch</p>
|
|
31
|
+
<p className="text-xs text-black font-medium">{projectData.branch || 'main'}</p>
|
|
32
|
+
</div>
|
|
33
|
+
<div className="flex items-center justify-between">
|
|
34
|
+
<p className="text-xs text-black/50">Last Deploy</p>
|
|
35
|
+
<p className="text-xs text-black font-medium">{formatDate(projectData.last_deployed)}</p>
|
|
36
|
+
</div>
|
|
37
|
+
<div className="flex items-center justify-between">
|
|
38
|
+
<p className="text-xs text-black/50">Framework</p>
|
|
39
|
+
<p className="text-xs text-black font-medium">{projectData.framework || 'Unknown'}</p>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
{/* AI Assistant - Simplified */}
|
|
45
|
+
<div className="bg-white rounded-[20px] border border-black/5 p-5">
|
|
46
|
+
<div className="flex items-center gap-2 mb-4">
|
|
47
|
+
{generateIcon('star-103-1687505465.png', 24, 'rgb(79, 70, 229)')}
|
|
48
|
+
<h3 className="text-base font-semibold text-black">AI Assistant</h3>
|
|
49
|
+
</div>
|
|
50
|
+
<p className="text-xs text-black/40 mb-4">Powered by Blurs</p>
|
|
51
|
+
<button onClick={handleEditWithBlurs} className="w-full px-4 py-2.5 bg-black text-white rounded-full font-medium text-sm hover:bg-gray-900 transition-all hover:shadow-md flex items-center justify-center gap-2">
|
|
52
|
+
<Sparkles className="w-4 h-4" />
|
|
53
|
+
Edit with Blurs
|
|
54
|
+
</button>
|
|
55
|
+
</div>
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
};
|
package/apps/dashboard/src/app/(dashboard)/projects/[id]/components/general/SkeletonLoader.tsx
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
// Fixed heights for skeleton bars to avoid hydration mismatches
|
|
4
|
+
const SKELETON_BAR_HEIGHTS = [
|
|
5
|
+
45, 62, 38, 71, 55, 42, 68, 49, 75, 33,
|
|
6
|
+
58, 44, 66, 52, 39, 73, 47, 61, 35, 69,
|
|
7
|
+
51, 43, 64, 56
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
export const TrafficChartSkeleton = () => {
|
|
11
|
+
return (
|
|
12
|
+
<div className="bg-white rounded-2xl border border-gray-200 p-6 h-[320px] flex flex-col animate-pulse">
|
|
13
|
+
<div className="flex items-center justify-between mb-6">
|
|
14
|
+
<div className="flex items-center gap-3">
|
|
15
|
+
<div className="w-12 h-12 rounded-2xl bg-gray-200/50"></div>
|
|
16
|
+
<div>
|
|
17
|
+
<div className="h-6 w-40 bg-gray-200/50 rounded-2xl mb-2"></div>
|
|
18
|
+
<div className="h-4 w-32 bg-gray-200/30 rounded-2xl"></div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<div className="flex items-center gap-4">
|
|
22
|
+
<div className="h-10 w-40 bg-gray-200/50 rounded-2xl"></div>
|
|
23
|
+
<div className="h-5 w-20 bg-gray-200/30 rounded-2xl"></div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
<div className="flex-1 flex items-end gap-1.5">
|
|
27
|
+
{SKELETON_BAR_HEIGHTS.map((height, i) => (
|
|
28
|
+
<div
|
|
29
|
+
key={i}
|
|
30
|
+
className="flex-1 bg-gray-200/50 rounded-t-2xl"
|
|
31
|
+
style={{ height: `${height}%` }}
|
|
32
|
+
></div>
|
|
33
|
+
))}
|
|
34
|
+
</div>
|
|
35
|
+
<div className="flex justify-between mt-3">
|
|
36
|
+
{Array.from({ length: 6 }).map((_, i) => (
|
|
37
|
+
<div key={i} className="h-3 w-10 bg-gray-200/30 rounded-2xl"></div>
|
|
38
|
+
))}
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const TopPathsSkeleton = () => {
|
|
45
|
+
return (
|
|
46
|
+
<div className="bg-white rounded-2xl border border-gray-200 p-6 h-[320px] flex flex-col animate-pulse">
|
|
47
|
+
<div className="flex items-center justify-between mb-5">
|
|
48
|
+
<div className="flex items-center gap-3">
|
|
49
|
+
<div className="w-12 h-12 rounded-2xl bg-gray-200/50"></div>
|
|
50
|
+
<div className="h-6 w-32 bg-gray-200/50 rounded-2xl"></div>
|
|
51
|
+
</div>
|
|
52
|
+
<div className="h-5 w-20 bg-gray-200/30 rounded-2xl"></div>
|
|
53
|
+
</div>
|
|
54
|
+
<div className="space-y-5 flex-1">
|
|
55
|
+
{Array.from({ length: 3 }).map((_, i) => (
|
|
56
|
+
<div key={i} className="space-y-2">
|
|
57
|
+
<div className="flex items-center justify-between mb-2">
|
|
58
|
+
<div className="h-4 w-32 bg-gray-200/50 rounded-2xl"></div>
|
|
59
|
+
<div className="h-4 w-16 bg-gray-200/30 rounded-2xl"></div>
|
|
60
|
+
</div>
|
|
61
|
+
<div className="w-full h-2.5 bg-gray-200/50 rounded-2xl"></div>
|
|
62
|
+
<div className="h-3 w-20 bg-gray-200/30 rounded-2xl"></div>
|
|
63
|
+
</div>
|
|
64
|
+
))}
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const StatsCardsSkeleton = () => {
|
|
71
|
+
return (
|
|
72
|
+
<div className="grid grid-cols-4 gap-4 h-[100px]">
|
|
73
|
+
{Array.from({ length: 4 }).map((_, i) => (
|
|
74
|
+
<div
|
|
75
|
+
key={i}
|
|
76
|
+
className="bg-white border border-gray-200 rounded-2xl p-4 h-full flex items-center animate-pulse"
|
|
77
|
+
>
|
|
78
|
+
<div className="flex items-center gap-3 w-full">
|
|
79
|
+
<div className="w-12 h-12 rounded-2xl bg-gray-200/50 flex-shrink-0"></div>
|
|
80
|
+
<div className="flex-1 min-w-0">
|
|
81
|
+
<div className="h-6 w-20 bg-gray-200/50 rounded-2xl mb-2"></div>
|
|
82
|
+
<div className="h-4 w-24 bg-gray-200/30 rounded-2xl mb-1"></div>
|
|
83
|
+
<div className="h-3 w-20 bg-gray-200/30 rounded-2xl"></div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
))}
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const ProductionUrlSkeleton = () => {
|
|
93
|
+
return (
|
|
94
|
+
<div className="bg-gradient-to-br from-gray-50 to-gray-100 rounded-2xl border border-gray-200 p-6 h-[100px] flex items-center animate-pulse">
|
|
95
|
+
<div className="flex items-center gap-4 flex-1">
|
|
96
|
+
<div className="w-12 h-12 bg-gray-200/50 rounded-2xl flex-shrink-0"></div>
|
|
97
|
+
<div className="flex-1 min-w-0">
|
|
98
|
+
<div className="h-4 w-32 bg-gray-200/30 rounded-2xl mb-2"></div>
|
|
99
|
+
<div className="h-5 w-40 bg-gray-200/50 rounded-2xl"></div>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const ProjectIdentitySkeleton = () => {
|
|
107
|
+
return (
|
|
108
|
+
<div className="bg-white rounded-2xl border border-gray-200 overflow-hidden animate-pulse">
|
|
109
|
+
<div className="bg-gray-50 px-6 py-5 border-b border-gray-200 flex items-center gap-3">
|
|
110
|
+
<div className="w-12 h-12 rounded-2xl bg-gray-200/50"></div>
|
|
111
|
+
<div>
|
|
112
|
+
<div className="h-6 w-40 bg-gray-200/50 rounded-2xl mb-2"></div>
|
|
113
|
+
<div className="h-4 w-48 bg-gray-200/30 rounded-2xl"></div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div className="p-6 space-y-5">
|
|
118
|
+
{Array.from({ length: 3 }).map((_, i) => (
|
|
119
|
+
<div key={i}>
|
|
120
|
+
<div className="flex items-center justify-between mb-3">
|
|
121
|
+
<div className="h-5 w-32 bg-gray-200/50 rounded-2xl"></div>
|
|
122
|
+
<div className="h-4 w-16 bg-gray-200/30 rounded-2xl"></div>
|
|
123
|
+
</div>
|
|
124
|
+
<div className="p-4 bg-gray-50 rounded-2xl">
|
|
125
|
+
<div className="h-5 w-full bg-gray-200/50 rounded-2xl"></div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
))}
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const ProjectInfoSkeleton = () => {
|
|
135
|
+
return (
|
|
136
|
+
<>
|
|
137
|
+
<div className="bg-white rounded-2xl border border-gray-200 p-6 animate-pulse">
|
|
138
|
+
<div className="flex items-center gap-3 mb-5">
|
|
139
|
+
<div className="w-12 h-12 rounded-2xl bg-gray-200/50"></div>
|
|
140
|
+
<div className="h-6 w-36 bg-gray-200/50 rounded-2xl"></div>
|
|
141
|
+
</div>
|
|
142
|
+
<div className="space-y-4">
|
|
143
|
+
{Array.from({ length: 4 }).map((_, i) => (
|
|
144
|
+
<div key={i} className="flex items-center gap-4">
|
|
145
|
+
<div className="w-5 h-5 rounded-xl bg-gray-200/50"></div>
|
|
146
|
+
<div className="flex-1">
|
|
147
|
+
<div className="h-4 w-20 bg-gray-200/50 rounded-2xl mb-2"></div>
|
|
148
|
+
<div className="h-4 w-32 bg-gray-200/30 rounded-2xl"></div>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
))}
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<div className="bg-gradient-to-br from-gray-50 to-gray-100 rounded-2xl border border-gray-200 p-6 animate-pulse">
|
|
156
|
+
<div className="flex items-start justify-between mb-4">
|
|
157
|
+
<div className="flex items-center gap-3">
|
|
158
|
+
<div className="w-12 h-12 bg-gray-200/50 rounded-2xl"></div>
|
|
159
|
+
<div>
|
|
160
|
+
<div className="h-5 w-32 bg-gray-200/50 rounded-2xl mb-2"></div>
|
|
161
|
+
<div className="h-4 w-36 bg-gray-200/30 rounded-2xl"></div>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
<div className="w-full h-12 bg-gray-200/50 rounded-2xl"></div>
|
|
166
|
+
<div className="h-4 w-40 bg-gray-200/30 rounded-2xl mt-4 mx-auto"></div>
|
|
167
|
+
</div>
|
|
168
|
+
</>
|
|
169
|
+
);
|
|
170
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { generateIcon } from "@/utils/icons";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
stats: any[];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const StatsCards: React.FC<Props> = ({ stats }) => {
|
|
9
|
+
return (
|
|
10
|
+
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
|
11
|
+
{stats.map((stat) => {
|
|
12
|
+
return (
|
|
13
|
+
<div key={stat.label} className="bg-white border border-black/5 rounded-[20px] hover:shadow-md transition-all p-4">
|
|
14
|
+
<div className="flex flex-col">
|
|
15
|
+
<div className="flex items-center gap-2 mb-3">
|
|
16
|
+
{generateIcon(stat.icon, 24, 'rgb(79, 70, 229)')}
|
|
17
|
+
<p className="text-xs font-medium text-black/50">{stat.label}</p>
|
|
18
|
+
</div>
|
|
19
|
+
<p className="text-2xl font-semibold text-black mb-1">
|
|
20
|
+
{stat.value}
|
|
21
|
+
</p>
|
|
22
|
+
{stat.subtext && (
|
|
23
|
+
<p className="text-xs text-black/40 font-normal">
|
|
24
|
+
{stat.subtext}
|
|
25
|
+
</p>
|
|
26
|
+
)}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
})}
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { generateIcon } from "@/utils/icons";
|
|
4
|
+
|
|
5
|
+
interface PathData {
|
|
6
|
+
path: string;
|
|
7
|
+
count: number;
|
|
8
|
+
percentage: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
paths: PathData[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const TopPaths: React.FC<Props> = ({ paths }) => {
|
|
16
|
+
const [showAll, setShowAll] = useState(false);
|
|
17
|
+
|
|
18
|
+
const displayedPaths = showAll ? paths : paths.slice(0, 5);
|
|
19
|
+
const hasMorePaths = paths.length > 5;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className="bg-white rounded-[20px] border border-black/5 p-5">
|
|
23
|
+
<div className="flex items-center justify-between mb-5">
|
|
24
|
+
<div className="flex items-center gap-2">
|
|
25
|
+
{generateIcon('trend%20up-79-1681196106.png', 24, 'rgb(79, 70, 229)')}
|
|
26
|
+
<h3 className="text-base font-semibold text-black">Top Paths</h3>
|
|
27
|
+
</div>
|
|
28
|
+
{hasMorePaths && (
|
|
29
|
+
<button
|
|
30
|
+
onClick={() => setShowAll(!showAll)}
|
|
31
|
+
className="text-xs font-medium text-indigo-600 hover:text-indigo-700 transition-colors"
|
|
32
|
+
>
|
|
33
|
+
{showAll ? 'Show Less' : `+${paths.length - 5}`}
|
|
34
|
+
</button>
|
|
35
|
+
)}
|
|
36
|
+
</div>
|
|
37
|
+
<div className="space-y-4">
|
|
38
|
+
{displayedPaths.map((path, idx) => (
|
|
39
|
+
<div key={idx}>
|
|
40
|
+
<div className="flex items-center justify-between mb-2">
|
|
41
|
+
<span className="text-xs text-black/70 font-medium truncate pr-2">{path.path}</span>
|
|
42
|
+
<span className="text-xs font-medium text-indigo-600">{path.percentage}%</span>
|
|
43
|
+
</div>
|
|
44
|
+
<div className="w-full bg-black/5 rounded-full h-2 overflow-hidden">
|
|
45
|
+
<div
|
|
46
|
+
className="h-full bg-indigo-600 rounded-full transition-all"
|
|
47
|
+
style={{ width: `${path.percentage}%` }}
|
|
48
|
+
></div>
|
|
49
|
+
</div>
|
|
50
|
+
<p className="text-xs text-black/40 mt-1">{path.count} requests</p>
|
|
51
|
+
</div>
|
|
52
|
+
))}
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import { BarChart3, TrendingUp } from "lucide-react";
|
|
4
|
+
import { generateIcon } from "@/utils/icons";
|
|
5
|
+
import { SlidingToggle } from "@/components/ui/SlidingToggle";
|
|
6
|
+
|
|
7
|
+
interface TrafficData {
|
|
8
|
+
hour: number;
|
|
9
|
+
requests: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
trafficData: TrafficData[];
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
dateRange?: string;
|
|
16
|
+
totalRequests?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const TrafficChart: React.FC<Props> = ({
|
|
20
|
+
trafficData,
|
|
21
|
+
isLoading,
|
|
22
|
+
dateRange,
|
|
23
|
+
totalRequests,
|
|
24
|
+
}) => {
|
|
25
|
+
const [chartType, setChartType] = useState<'bar' | 'area'>('area');
|
|
26
|
+
const maxRequests = Math.max(...trafficData.map(d => d.requests), 1);
|
|
27
|
+
if(trafficData.length === 0) {
|
|
28
|
+
trafficData = Array.from({ length: 24 }, (_, i) => ({
|
|
29
|
+
hour: i,
|
|
30
|
+
requests: 0,
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="bg-white rounded-[20px] border border-black/5 p-4 sm:p-6 h-[280px] sm:h-[320px] flex flex-col">
|
|
36
|
+
<div className="flex items-center justify-between gap-2 sm:gap-0 mb-4 sm:mb-5">
|
|
37
|
+
<div className="flex items-center gap-2 sm:gap-3 flex-1 min-w-0">
|
|
38
|
+
{generateIcon('chart%204%20line-5-1666004410.png', 24, 'rgb(79, 70, 229)')}
|
|
39
|
+
<div className="min-w-0">
|
|
40
|
+
<h3 className="text-sm sm:text-lg font-semibold text-black truncate">Traffic Overview</h3>
|
|
41
|
+
<p className="text-[10px] sm:text-sm text-black/40 truncate">{dateRange || 'Last 24 hours'}</p>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
<div className="flex items-center gap-3 flex-shrink-0">
|
|
45
|
+
{/* Chart Type Selector */}
|
|
46
|
+
<SlidingToggle
|
|
47
|
+
options={[
|
|
48
|
+
{
|
|
49
|
+
value: 'bar',
|
|
50
|
+
icon: <BarChart3 className="w-3.5 h-3.5 sm:w-4 sm:h-4" />,
|
|
51
|
+
label: 'Bar',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
value: 'area',
|
|
55
|
+
icon: <TrendingUp className="w-3.5 h-3.5 sm:w-4 sm:h-4" />,
|
|
56
|
+
label: 'Area',
|
|
57
|
+
},
|
|
58
|
+
]}
|
|
59
|
+
value={chartType}
|
|
60
|
+
onChange={(value) => setChartType(value as 'bar' | 'area')}
|
|
61
|
+
variant="rounded"
|
|
62
|
+
selectedBg="bg-indigo-600"
|
|
63
|
+
selectedTextColor="text-white"
|
|
64
|
+
unselectedTextColor="text-black/60"
|
|
65
|
+
backgroundColor="bg-white"
|
|
66
|
+
size="sm"
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
{/* Traffic Chart */}
|
|
73
|
+
{isLoading ? (
|
|
74
|
+
<div className="flex items-center justify-center flex-1">
|
|
75
|
+
<div className="text-sm text-gray-400">Loading analytics...</div>
|
|
76
|
+
</div>
|
|
77
|
+
) : (
|
|
78
|
+
<div className="flex-1 flex flex-col">
|
|
79
|
+
<div className="relative flex-1">
|
|
80
|
+
<svg className="absolute inset-0 w-full h-full" viewBox="0 0 1000 160" preserveAspectRatio="none">
|
|
81
|
+
<defs>
|
|
82
|
+
<linearGradient id="trafficGradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
83
|
+
<stop offset={`${chartType == 'bar' ? 100 : 20}%`} stopColor="rgb(99, 102, 241)" stopOpacity="0.3" />
|
|
84
|
+
<stop offset="100%" stopColor="rgb(99, 102, 241)" stopOpacity="0.1" />
|
|
85
|
+
</linearGradient>
|
|
86
|
+
</defs>
|
|
87
|
+
|
|
88
|
+
{chartType === 'bar' && (
|
|
89
|
+
/* Bar Chart */
|
|
90
|
+
<>
|
|
91
|
+
{trafficData.map((d, i) => {
|
|
92
|
+
const containerWidth = 1000;
|
|
93
|
+
const containerHeight = 160;
|
|
94
|
+
const barWidth = containerWidth / trafficData.length * 0.8;
|
|
95
|
+
const x = (i / trafficData.length) * containerWidth + barWidth * 0.1;
|
|
96
|
+
const height = (d.requests / maxRequests) * 140;
|
|
97
|
+
const y = containerHeight - height;
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<rect
|
|
101
|
+
key={i}
|
|
102
|
+
x={x}
|
|
103
|
+
y={y}
|
|
104
|
+
width={barWidth}
|
|
105
|
+
height={height}
|
|
106
|
+
fill="url(#trafficGradient)"
|
|
107
|
+
rx="4"
|
|
108
|
+
ry="4"
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
})}
|
|
112
|
+
</>
|
|
113
|
+
)}
|
|
114
|
+
|
|
115
|
+
{chartType === 'area' && (
|
|
116
|
+
/* Area Chart with Border Line */
|
|
117
|
+
<>
|
|
118
|
+
{/* Area Fill */}
|
|
119
|
+
<path
|
|
120
|
+
d={`M 0 150 ${trafficData.map((d, i) => {
|
|
121
|
+
const x = (i / (trafficData.length - 1)) * 1000;
|
|
122
|
+
const baseHeight = 110; // Raised baseline for zero state
|
|
123
|
+
const maxHeight = 110; // Maximum height for visualization
|
|
124
|
+
const y = baseHeight - (d.requests / maxRequests) * maxHeight;
|
|
125
|
+
return `L ${x} ${y}`;
|
|
126
|
+
}).join(' ')} L 1000 150 Z`}
|
|
127
|
+
fill="url(#trafficGradient)"
|
|
128
|
+
/>
|
|
129
|
+
{/* Top Border Line - More Visible */}
|
|
130
|
+
<path
|
|
131
|
+
d={`M ${trafficData.map((d, i) => {
|
|
132
|
+
const x = (i / (trafficData.length - 1)) * 1000;
|
|
133
|
+
const baseHeight = 0;
|
|
134
|
+
const maxHeight = 130;
|
|
135
|
+
const y = baseHeight - (d.requests / maxRequests) * maxHeight;
|
|
136
|
+
return `${i === 0 ? 'M' : 'L'} ${x} ${y}`;
|
|
137
|
+
}).join(' ')}`}
|
|
138
|
+
fill="none"
|
|
139
|
+
stroke="rgb(99, 102, 241)"
|
|
140
|
+
strokeWidth="0.5"
|
|
141
|
+
/>
|
|
142
|
+
</>
|
|
143
|
+
)}
|
|
144
|
+
</svg>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
{/* Hour Labels */}
|
|
148
|
+
<div className="flex items-center justify-between mt-2 text-[9px] sm:text-[10px] text-gray-500">
|
|
149
|
+
{trafficData.filter((_, i) => i % 4 === 0).map((d, i) => (
|
|
150
|
+
<span key={i}>{d.hour}:00</span>
|
|
151
|
+
))}
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
)}
|
|
155
|
+
</div>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { TrafficChart } from './TrafficChart';
|
|
2
|
+
export { TopPaths } from './TopPaths';
|
|
3
|
+
export { StatsCards } from './StatsCards';
|
|
4
|
+
export { ProductionUrl } from './ProductionUrl';
|
|
5
|
+
export { ProjectIdentity } from './ProjectIdentity';
|
|
6
|
+
export { ProjectInfo } from './ProjectInfo';
|
|
7
|
+
export {
|
|
8
|
+
TrafficChartSkeleton,
|
|
9
|
+
TopPathsSkeleton,
|
|
10
|
+
StatsCardsSkeleton,
|
|
11
|
+
ProductionUrlSkeleton,
|
|
12
|
+
ProjectIdentitySkeleton,
|
|
13
|
+
ProjectInfoSkeleton,
|
|
14
|
+
} from './SkeletonLoader';
|