From 43b2c1545a334fea86553fc0d943c409a2fd46c8 Mon Sep 17 00:00:00 2001 From: flakronademi Date: Mon, 14 Sep 2026 16:07:19 +0200 Subject: [PATCH 1/5] feat(dashboard): add dashboard screen and reorganize app navigation --- assets/icons/analytics.png | Bin 0 -> 8714 bytes assets/icons/cloud-search.png | Bin 0 -> 25252 bytes assets/icons/data-migration.png | Bin 0 -> 50974 bytes assets/icons/datalake_card.png | Bin 0 -> 24784 bytes assets/icons/index.ts | 8 + src/renderer/App.tsx | 11 +- src/renderer/components/menu/index.tsx | 124 ++-- src/renderer/components/sidebar/elements.ts | 8 +- src/renderer/components/sidebar/icons.tsx | 3 + src/renderer/components/sidebar/index.tsx | 10 + .../components/sidebar/project-sidebar.tsx | 12 + src/renderer/screens/dashboard/index.tsx | 612 ++++++++++++++++++ src/renderer/screens/dashboard/styles.ts | 94 +++ src/renderer/screens/index.ts | 2 + src/renderer/screens/projectDetails/index.tsx | 17 +- src/renderer/screens/sql/index.tsx | 14 +- 16 files changed, 848 insertions(+), 67 deletions(-) create mode 100644 assets/icons/analytics.png create mode 100644 assets/icons/cloud-search.png create mode 100644 assets/icons/data-migration.png create mode 100644 assets/icons/datalake_card.png create mode 100644 src/renderer/screens/dashboard/index.tsx create mode 100644 src/renderer/screens/dashboard/styles.ts diff --git a/assets/icons/analytics.png b/assets/icons/analytics.png new file mode 100644 index 0000000000000000000000000000000000000000..6fbfa6a40db7bb39e139e00ad97d33fa01d2c80c GIT binary patch literal 8714 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 z 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 YcTvZh(d8XR*kl>ekwML=9xiDd< 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 I)$OAH2Sw<9X8-^I literal 0 HcmV?d00001 diff --git a/assets/icons/data-migration.png b/assets/icons/data-migration.png new file mode 100644 index 0000000000000000000000000000000000000000..8546d5da75268eb8ed57f3bc4927d722a81b3b99 GIT binary patch literal 50974 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 B1poj5 literal 0 HcmV?d00001 diff --git a/assets/icons/datalake_card.png b/assets/icons/datalake_card.png new file mode 100644 index 0000000000000000000000000000000000000000..dffd2f55f2c717206d2a8ec01e5245bcd510dd27 GIT binary patch literal 24784 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 { }> - } /> - } /> - } /> + } /> + } /> + } /> + } /> }> - } /> + } /> + } /> } /> } /> } /> diff --git a/src/renderer/components/menu/index.tsx b/src/renderer/components/menu/index.tsx index 0c25c54e..cf3514a2 100644 --- a/src/renderer/components/menu/index.tsx +++ b/src/renderer/components/menu/index.tsx @@ -97,67 +97,71 @@ export const Menu: React.FC = ({ actions }) => { return ( - {!isSidebarOpen && ( - - setIsSidebarOpen(true)} - sx={{ - opacity: 0.5, - '&:hover': { opacity: 1 }, - }} - > - - - - )} - - - All Projects - - ), - }, - ...projects.map((p) => ({ - value: String(p.id), - label: ( - - - {p?.name} - - ), - })), - ]} - onSelect={async (value) => { - if (value === 'all') { - navigate('/app/select-project'); - } else { - await selectProject({ projectId: value }); - navigate('/app'); + {!isSidebarOpen && + location.pathname !== '/app' && + !location.pathname.includes('flows') && ( + + setIsSidebarOpen(true)} + sx={{ + opacity: 0.5, + '&:hover': { opacity: 1 }, + }} + > + + + + )} + {!isOnProjectDetails && ( + + + All Projects + + ), + }, + ...projects.map((p) => ({ + value: String(p.id), + label: ( + + + {p?.name} + + ), + })), + ]} + onSelect={async (value) => { + if (value === 'all') { + navigate('/app/select-project'); + } else { + await selectProject({ projectId: value }); + navigate('/app'); + } + }} + selectedItem={project ? String(project.id) : 'all'} + anchorElement={ + + {project ? ( + <> + + {project.name} + + ) : ( + <> + + Select Project + + )} + + } - }} - selectedItem={project ? String(project.id) : 'all'} - anchorElement={ - - {project ? ( - <> - - {project.name} - - ) : ( - <> - - Select Project - - )} - - - } - /> + /> + )} {isProjectSelected && actions} diff --git a/src/renderer/components/sidebar/elements.ts b/src/renderer/components/sidebar/elements.ts index 323fcf67..5416cbc8 100644 --- a/src/renderer/components/sidebar/elements.ts +++ b/src/renderer/components/sidebar/elements.ts @@ -12,6 +12,12 @@ interface SideBarElementType { const baseElements: SideBarElementType[] = [ { path: '/app', + text: 'Home', + icon: Icons.HomeIcon, + testId: 'nav-item-home', + }, + { + path: '/app/dbt-project', text: 'DBT Studio', icon: Icons.DBTProjects, testId: 'nav-item-files', @@ -52,7 +58,7 @@ export const getMainElements = ( isProjectSelected: boolean, ): SideBarElementType[] => { return baseElements.map((element) => { - if (!isProjectSelected && element.path === '/app') { + if (!isProjectSelected && element.path === '/app/dbt-project') { return { ...element, disabled: true }; } return element; diff --git a/src/renderer/components/sidebar/icons.tsx b/src/renderer/components/sidebar/icons.tsx index ae0868d7..4d0387ce 100644 --- a/src/renderer/components/sidebar/icons.tsx +++ b/src/renderer/components/sidebar/icons.tsx @@ -7,6 +7,7 @@ import { ElectricalServices as ElectricalServicesIcon, LibraryBooks, Settings, + Home as HomeMuiIcon, } from '@mui/icons-material'; import { useTheme } from '@mui/material/styles'; import { icons } from '../../../../assets'; @@ -151,3 +152,5 @@ export const FlowsIcon: React.FC = () => { /> ); }; + +export const HomeIcon: React.FC = () => ; diff --git a/src/renderer/components/sidebar/index.tsx b/src/renderer/components/sidebar/index.tsx index 99074b35..470c3eea 100644 --- a/src/renderer/components/sidebar/index.tsx +++ b/src/renderer/components/sidebar/index.tsx @@ -50,6 +50,7 @@ export const Sidebar: React.FC = ({ const activeItemPath = React.useMemo(() => { const path = location.pathname; + if (path.includes('dbt-project')) return '/app/dbt-project'; if (path.includes('cloud-explorer')) return '/app/cloud-explorer'; if (path.includes('data-lake') || path.includes('datalake')) return '/app/data-lake'; @@ -71,6 +72,15 @@ export const Sidebar: React.FC = ({ const isPanelOpen = Boolean(content) && isSidebarOpen; + // Auto-collapse sidebar panel when on Home (/app) and auto-expand when navigating to any module + React.useEffect(() => { + if (location.pathname === '/app') { + setIsSidebarOpen(false); + } else { + setIsSidebarOpen(true); + } + }, [location.pathname, setIsSidebarOpen]); + const renderItem = (element: (typeof mainElements)[0], isActive: boolean) => { const isDisabled = element.disabled; const targetPath = diff --git a/src/renderer/components/sidebar/project-sidebar.tsx b/src/renderer/components/sidebar/project-sidebar.tsx index 877463ad..66365799 100644 --- a/src/renderer/components/sidebar/project-sidebar.tsx +++ b/src/renderer/components/sidebar/project-sidebar.tsx @@ -266,6 +266,7 @@ interface ExplorerTabProps { onRenameFile?: (oldPath: string, newPath: string) => void; onRunPipeline?: (filePath: string) => void; onRunPipelineLocal?: (filePath: string) => void; + openCreatePipeline?: boolean; } const ExplorerTab: React.FC = ({ @@ -282,10 +283,18 @@ const ExplorerTab: React.FC = ({ onRenameFile, onRunPipeline, onRunPipelineLocal, + openCreatePipeline, }) => { const theme = useTheme(); const [createPipelineOpen, setCreatePipelineOpen] = React.useState(false); + // Open the modal when triggered externally (e.g. from the home screen pipeline card) + React.useEffect(() => { + if (openCreatePipeline) { + setCreatePipelineOpen(true); + } + }, [openCreatePipeline]); + const { refetch: refetchPipelines } = useListPipelines(project?.id); const handlePipelineCreated = React.useCallback( @@ -456,6 +465,7 @@ interface ProjectSidebarProps { // Pipeline onRunPipeline?: (filePath: string) => void; + openCreatePipeline?: boolean; // Search (find in files) onSearchResultSelect: (selection: SearchResultSelection) => void; @@ -487,6 +497,7 @@ export const ProjectSidebar: React.FC = ({ onRunPipeline, onSearchResultSelect, onRunPipelineLocal, + openCreatePipeline, }) => { return ( = ({ onRenameFile={onRenameFile} onRunPipeline={onRunPipeline} onRunPipelineLocal={onRunPipelineLocal} + openCreatePipeline={openCreatePipeline} /> )} diff --git a/src/renderer/screens/dashboard/index.tsx b/src/renderer/screens/dashboard/index.tsx new file mode 100644 index 00000000..96357a68 --- /dev/null +++ b/src/renderer/screens/dashboard/index.tsx @@ -0,0 +1,612 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + Box, + Button, + Card, + CardActionArea, + Chip, + Divider, + Grid, + List, + ListItemButton, + ListItemIcon, + ListItemText, + Paper, + Typography, + useTheme, +} from '@mui/material'; +import FolderSpecialIcon from '@mui/icons-material/FolderSpecial'; +import Terminal from '@mui/icons-material/Terminal'; +import AutoStoriesIcon from '@mui/icons-material/AutoStories'; +import AddIcon from '@mui/icons-material/Add'; +import FolderOpenIcon from '@mui/icons-material/FolderOpen'; +import SettingsOutlinedIcon from '@mui/icons-material/SettingsOutlined'; +import StorageOutlinedIcon from '@mui/icons-material/StorageOutlined'; + +import { icons, rosettaIcon } from '../../../../assets'; +import { ReactComponent as RouteIcon } from '../../assets/icons/lucide/route.svg'; +import { useAppContext } from '../../hooks'; +import { + useGetProjects, + useGetConnections, + useSelectProject, +} from '../../controllers'; + +const DbtCardIcon: React.FC = () => ( + dbt +); + +const PipelineCardIcon: React.FC = () => { + const theme = useTheme(); + return ( + + ); +}; + +const AnalyticsCardIcon: React.FC = () => ( + analytics +); + +const DataLakeCardIcon: React.FC = () => ( + datalake +); + +const EtlCardIcon: React.FC = () => ( + etl +); + +const CloudExplorerCardIcon: React.FC = () => ( + cloud explorer +); + +const SqlEditorCardIcon: React.FC = () => ( + +); + +const features = [ + { + id: 'dbt-project', + title: 'DBT Project', + category: 'dbt Core', + description: + 'Manage and explore your dbt models, sources, and documentation.', + icon: DbtCardIcon, + path: '/select-project', + }, + { + id: 'notebook', + title: 'Notebook', + category: 'Analytics', + description: + 'Create interactive notebooks for data exploration and analysis.', + icon: AutoStoriesIcon, + path: '/app/notebooks', + }, + { + id: 'sql-editor', + title: 'SQL Editor', + category: 'SQL', + description: 'Write, execute, and profile high-performance SQL queries.', + icon: SqlEditorCardIcon, + path: '/app/sql', + }, + { + id: 'analytics', + title: 'Analytics', + category: 'BI & Viz', + description: 'Visualize your data with powerful dashboards and charts.', + icon: AnalyticsCardIcon, + // navigated programmatically with state: { tab: 2 } + path: '/app/sql', + }, + { + id: 'datalake', + title: 'Data Lake', + category: 'Storage', + description: 'Access and manage raw data across your data lake storage.', + icon: DataLakeCardIcon, + path: '/app/data-lake', + }, + { + id: 'object-explorer', + title: 'Object Explorer', + category: 'Cloud', + description: 'Browse and manage cloud storage objects effortlessly.', + icon: CloudExplorerCardIcon, + path: '/app/cloud-explorer', + }, + { + id: 'pipeline', + title: 'Pipeline', + category: 'Orchestration', + description: 'Design and monitor robust data pipelines and workflows.', + icon: PipelineCardIcon, + // opened via modal — path unused + path: '', + }, + { + id: 'etl', + title: 'ETL (Migrate)', + category: 'Migration', + description: + 'Extract, transform, and load data seamlessly between systems.', + icon: EtlCardIcon, + path: '/app/flows', + }, +]; + +const Dashboard: React.FC = () => { + const navigate = useNavigate(); + const theme = useTheme(); + const { setIsSidebarOpen } = useAppContext(); + const { data: projects = [] } = useGetProjects(); + const { data: connections = [] } = useGetConnections(); + const { mutateAsync: selectProject } = useSelectProject(); + + const handleFeatureClick = (path: string) => { + setIsSidebarOpen(true); + navigate(path); + }; + + const handleCardClick = (feature: (typeof features)[number]) => { + if (feature.id === 'pipeline') { + setIsSidebarOpen(true); + navigate('/app/dbt-project', { state: { openCreatePipeline: true } }); + return; + } + if (feature.id === 'analytics') { + setIsSidebarOpen(true); + navigate('/app/sql', { state: { tab: 2 } }); + return; + } + handleFeatureClick(feature.path); + }; + + const handleOpenProject = async (projectId: string) => { + try { + await selectProject({ projectId }); + setIsSidebarOpen(true); + navigate('/app/dbt-project'); + } catch (err) { + // eslint-disable-next-line no-console + console.error('Failed to select project:', err); + } + }; + + return ( + + {/* Hero / Welcome Header */} + + + + + + Workspace Overview + + + Access your data engineering modules, analytics notebooks, and + pipelines. + + + + + {/* Quick Header Actions */} + + + + + + + + {/* Main Studio Modules (7 Cards) */} + + Studio Modules + + + {features.map((feature) => { + const IconComponent = feature.icon; + return ( + + + handleCardClick(feature)} + sx={{ + height: '100%', + p: 2.5, + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + justifyContent: 'space-between', + }} + > + + + + + + + + + {feature.title} + + + {feature.description} + + + + + + ); + })} + + + {/* Bottom Panels: Recent Projects & Active Connections */} + + {/* Recent Projects */} + + + + + + Recent Projects ({projects.length}) + + + + + {projects.length === 0 ? ( + + No recent projects found. + + ) : ( + + {projects.slice(0, 4).map((p: any) => ( + handleOpenProject(String(p.id))} + sx={{ + borderRadius: 1.5, + mb: 0.5, + '&:hover': { + backgroundColor: theme.palette.action.hover, + }, + }} + > + + + + + + ))} + + )} + + + + {/* Database Connections */} + + + + + + Configured Connections ({connections.length}) + + + + + {connections.length === 0 ? ( + + No connections configured yet. + + ) : ( + + {connections.slice(0, 4).map((c: any) => ( + handleFeatureClick('/app/connections')} + sx={{ + borderRadius: 1.5, + mb: 0.5, + '&:hover': { + backgroundColor: theme.palette.action.hover, + }, + }} + > + + + + + + ))} + + )} + + + + + ); +}; + +export default Dashboard; diff --git a/src/renderer/screens/dashboard/styles.ts b/src/renderer/screens/dashboard/styles.ts new file mode 100644 index 00000000..b947f866 --- /dev/null +++ b/src/renderer/screens/dashboard/styles.ts @@ -0,0 +1,94 @@ +import { styled } from '@mui/material/styles'; +import { Box, Typography, Card, CardContent } from '@mui/material'; + +export const DashboardContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + height: '100%', + width: '100%', + background: theme.palette.background.default, + padding: theme.spacing(6), + boxSizing: 'border-box', + overflowY: 'auto', + alignItems: 'center', + justifyContent: 'center', +})); + +export const CardsGrid = styled(Box)(({ theme }) => ({ + display: 'grid', + gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', + gap: theme.spacing(4), + width: '100%', + maxWidth: '1200px', +})); + +export const FeatureCard = styled(Card)(({ theme }) => ({ + position: 'relative', + background: theme.palette.background.paper, + border: `1px solid ${theme.palette.divider}`, + borderRadius: theme.spacing(2), + overflow: 'hidden', + transition: 'all 0.25s ease-in-out', + cursor: 'pointer', + height: '100%', + display: 'flex', + flexDirection: 'column', + + '&:hover': { + transform: 'translateY(-4px)', + boxShadow: + theme.palette.mode === 'dark' + ? '0 12px 24px rgba(255, 107, 0, 0.2)' + : '0 12px 24px rgba(255, 107, 0, 0.15)', + borderColor: '#ff6b00', + + '& .icon-container': { + transform: 'scale(1.08)', + color: '#ff6b00', + background: 'rgba(255, 107, 0, 0.15)', + }, + + '& .arrow-icon': { + transform: 'translateX(4px)', + opacity: 1, + }, + }, +})); + +export const CardContentWrapper = styled(CardContent)(({ theme }) => ({ + padding: theme.spacing(4, 3), + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + textAlign: 'center', + height: '100%', + position: 'relative', + zIndex: 1, + '&:last-child': { + paddingBottom: theme.spacing(4), + }, +})); + +export const IconContainer = styled(Box)(({ theme }) => ({ + width: '60px', + height: '60px', + borderRadius: '14px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + marginBottom: theme.spacing(2), + background: 'rgba(255, 107, 0, 0.1)', + color: '#ff6b00', + transition: 'all 0.25s ease', + + '& svg': { + fontSize: '30px', + }, +})); + +export const CardTitle = styled(Typography)(({ theme }) => ({ + fontWeight: 700, + fontSize: '1.15rem', + color: theme.palette.text.primary, +})); diff --git a/src/renderer/screens/index.ts b/src/renderer/screens/index.ts index ad13e465..ca326bc4 100644 --- a/src/renderer/screens/index.ts +++ b/src/renderer/screens/index.ts @@ -10,6 +10,7 @@ import CloudExplorer from './cloudExplorer'; import DuckLake from './dataLake'; import Notebooks from './notebooks'; import Flows from './flows'; +import Dashboard from './dashboard'; export { Settings, @@ -24,4 +25,5 @@ export { DuckLake, Notebooks, Flows, + Dashboard, }; diff --git a/src/renderer/screens/projectDetails/index.tsx b/src/renderer/screens/projectDetails/index.tsx index 75e61ca5..8c4b233a 100644 --- a/src/renderer/screens/projectDetails/index.tsx +++ b/src/renderer/screens/projectDetails/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import SplitPane, { Pane } from 'split-pane-react'; import 'split-pane-react/esm/themes/default.css'; -import { Navigate, useNavigate } from 'react-router-dom'; +import { Navigate, useNavigate, useLocation } from 'react-router-dom'; import { AccountTree, AutoAwesome, @@ -168,6 +168,20 @@ const getPipelineRelativeName = ( const ProjectDetails: React.FC = () => { const navigate = useNavigate(); + const location = useLocation(); + const openCreatePipeline = React.useMemo(() => { + const state = location.state as { openCreatePipeline?: boolean } | null; + return state?.openCreatePipeline === true; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + // Clear the nav state so a back-navigation doesn't re-trigger the modal + React.useEffect(() => { + if (openCreatePipeline) { + navigate(location.pathname, { replace: true, state: {} }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const [verticalSizes, setVerticalSizes] = React.useState<(number | string)[]>( ['auto', 500], ); @@ -1516,6 +1530,7 @@ const ProjectDetails: React.FC = () => { }} onRunPipeline={handleRunPipelineFile} onRunPipelineLocal={handleRunPipelineFileLocally} + openCreatePipeline={openCreatePipeline} /> diff --git a/src/renderer/screens/sql/index.tsx b/src/renderer/screens/sql/index.tsx index 4dcd13d1..fa742e9a 100644 --- a/src/renderer/screens/sql/index.tsx +++ b/src/renderer/screens/sql/index.tsx @@ -37,7 +37,7 @@ import { InsertChart, } from '@mui/icons-material'; import { toast } from 'react-toastify'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate, useLocation } from 'react-router-dom'; import { connectorsServices, DuckLakeService } from '../../services'; import { QueryResultStore } from './queryResultStore'; import { registerQueryResultBridge } from '../../services/agentEditorBridge.service'; @@ -111,6 +111,7 @@ const VerticalSash = (_: number, active: boolean) => ( const Sql = () => { const theme = useTheme(); const navigate = useNavigate(); + const location = useLocation(); const { selectedProject, projects, isChatOpen, setIsChatOpen } = useContext(AppContext); const tabManager = useSqlTabManager(); @@ -121,6 +122,17 @@ const Sql = () => { refetch: refetchDuckLakeInstances, } = useDuckLakeInstances(); const [sidebarTab, setSidebarTab] = useState(0); + + // Open the Analytics tab when navigated here with state { tab: 2 } + useEffect(() => { + const state = location.state as { tab?: number } | null; + if (state?.tab === 2) { + setSidebarTab(2); + // Clear the state so a back-navigation doesn't re-trigger + navigate(location.pathname, { replace: true, state: {} }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); const [activeAnalyticsPageId, setActiveAnalyticsPageId] = useState< string | null >(null); From 9f8e70bc11f8601cdb037d8847129456a6f71c43 Mon Sep 17 00:00:00 2001 From: flakronademi Date: Tue, 15 Sep 2026 15:27:50 +0200 Subject: [PATCH 2/5] feat(dashboard): require project selection before creating pipeline --- src/renderer/screens/dashboard/index.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/renderer/screens/dashboard/index.tsx b/src/renderer/screens/dashboard/index.tsx index 96357a68..b79fb83a 100644 --- a/src/renderer/screens/dashboard/index.tsx +++ b/src/renderer/screens/dashboard/index.tsx @@ -163,7 +163,7 @@ const features = [ const Dashboard: React.FC = () => { const navigate = useNavigate(); const theme = useTheme(); - const { setIsSidebarOpen } = useAppContext(); + const { setIsSidebarOpen, selectedProject } = useAppContext(); const { data: projects = [] } = useGetProjects(); const { data: connections = [] } = useGetConnections(); const { mutateAsync: selectProject } = useSelectProject(); @@ -175,6 +175,10 @@ const Dashboard: React.FC = () => { const handleCardClick = (feature: (typeof features)[number]) => { if (feature.id === 'pipeline') { + if (!selectedProject) { + navigate('/app/select-project'); + return; + } setIsSidebarOpen(true); navigate('/app/dbt-project', { state: { openCreatePipeline: true } }); return; From d9f2400eb37d6cf8f6cd2bbfe73d0fe907497c76 Mon Sep 17 00:00:00 2001 From: flakronademi Date: Fri, 18 Sep 2026 15:23:59 +0200 Subject: [PATCH 3/5] feat(dashboard): redesign quick start tour for home screen navigation --- .../components/QuickStartTour/index.tsx | 63 +++--- src/renderer/components/sidebar/index.tsx | 5 +- src/renderer/screens/dashboard/index.tsx | 211 ++++++++++-------- src/renderer/screens/selectProject/index.tsx | 17 +- 4 files changed, 147 insertions(+), 149 deletions(-) diff --git a/src/renderer/components/QuickStartTour/index.tsx b/src/renderer/components/QuickStartTour/index.tsx index e6aa902a..2db80256 100644 --- a/src/renderer/components/QuickStartTour/index.tsx +++ b/src/renderer/components/QuickStartTour/index.tsx @@ -7,10 +7,11 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import CheckIcon from '@mui/icons-material/Check'; import RocketLaunchIcon from '@mui/icons-material/RocketLaunch'; import FolderOpenIcon from '@mui/icons-material/FolderOpen'; -import AddIcon from '@mui/icons-material/Add'; import ElectricalServicesIcon from '@mui/icons-material/ElectricalServices'; -import SearchIcon from '@mui/icons-material/Search'; import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'; +import SpaceDashboardIcon from '@mui/icons-material/SpaceDashboard'; +import AppsIcon from '@mui/icons-material/Apps'; +import MenuIcon from '@mui/icons-material/Menu'; const TOUR_SEEN_KEY = 'dbt-studio-quickstart-tour-seen'; @@ -51,61 +52,61 @@ const TOUR_STEPS: TourStep[] = [ { title: 'Welcome to DBT Studio! 🎉', description: - "We'll give you a quick tour of the key features so you can hit the ground running. This only takes about 30 seconds.", + "We'll give you a quick tour of the home screen and the key features so you can hit the ground running. This only takes about 30 seconds.", icon: , placement: 'center', }, { - targetId: 'tour-projects-area', - title: 'Your Projects', + targetId: 'tour-workspace-overview', + title: 'Your Home Screen', description: - 'This is your project workspace. All your dbt projects live here. Click any project to open it and start working.', - icon: , + 'This is your workspace overview. From here you can jump into any module, open your projects, or manage your database connections.', + icon: , placement: 'bottom', padding: 12, }, { - targetId: 'tour-new-project-btn', - title: 'Create a New Project', - description: - 'Click here to create a brand new dbt project from scratch. Give it a name, choose a location, and optionally link a database connection.', - icon: , - placement: 'bottom', - padding: 8, - }, - { - targetId: 'tour-get-started-btn', - title: 'Get Started Fast', + targetId: 'tour-modules-area', + title: 'Studio Modules', description: - 'New to dbt Studio? Import a pre-built example project with sample data and dbt models — ready to explore instantly. Perfect for learning the ropes.', - icon: , + 'These cards give you one-click access to every tool — SQL Editor, Notebooks, Analytics, Data Lake, Pipeline, and more. Click any card to jump in.', + icon: , placement: 'bottom', - padding: 8, + padding: 12, }, { - targetId: 'tour-import-btn', - title: 'Import an Existing Project', + targetId: 'tour-recent-projects', + title: 'Recent Projects', description: - 'Already have a dbt project on your machine? Use Import to load it directly from your filesystem or from a compressed archive (.zip, .tar.gz).', + 'Your projects live here. Click any project to open it and pick up right where you left off.', icon: , - placement: 'bottom', - padding: 8, + placement: 'top', + padding: 12, }, { - targetId: 'tour-connections-nav', + targetId: 'tour-configured-connections', title: 'Database Connections', description: - 'Manage your database connections here — connect to BigQuery, Snowflake, DuckDB, Redshift, and more. Connections can be shared across multiple projects.', + 'Your configured connections are listed here — BigQuery, Snowflake, DuckDB, Redshift, and more. Add or manage them anytime.', icon: , + placement: 'top', + padding: 12, + }, + { + targetId: 'tour-sidebar-nav', + title: 'Navigate the App', + description: + 'Use the sidebar to move around DBT Studio at any time — Home, your project, and every module are just a click away.', + icon: , placement: 'right', padding: 8, }, { - targetId: 'tour-search-bar', + targetId: 'tour-open-project-btn', title: "You're All Set! 🚀", description: - 'Start by creating your first project or importing an existing one. Use the search bar to quickly find projects as your list grows. Happy building!', - icon: , + 'Start by creating your first project or importing an existing one — the Open Project button takes you to the project manager. Happy building!', + icon: , placement: 'bottom', padding: 8, }, diff --git a/src/renderer/components/sidebar/index.tsx b/src/renderer/components/sidebar/index.tsx index 470c3eea..a8f81fcd 100644 --- a/src/renderer/components/sidebar/index.tsx +++ b/src/renderer/components/sidebar/index.tsx @@ -124,14 +124,10 @@ export const Sidebar: React.FC = ({ ); - const tourAttr = - element.path === '/app/connections' ? 'tour-connections-nav' : undefined; - const wrapped = ( = ({ open={isPanelOpen} activityBarWidth={activityBarWidth} data-testid="sidebar" + data-tour="tour-sidebar-nav" > diff --git a/src/renderer/screens/dashboard/index.tsx b/src/renderer/screens/dashboard/index.tsx index b79fb83a..69cc0fcd 100644 --- a/src/renderer/screens/dashboard/index.tsx +++ b/src/renderer/screens/dashboard/index.tsx @@ -27,6 +27,7 @@ import StorageOutlinedIcon from '@mui/icons-material/StorageOutlined'; import { icons, rosettaIcon } from '../../../../assets'; import { ReactComponent as RouteIcon } from '../../assets/icons/lucide/route.svg'; import { useAppContext } from '../../hooks'; +import { QuickStartTour, hasSeenTour, markTourSeen } from '../../components'; import { useGetProjects, useGetConnections, @@ -202,6 +203,12 @@ const Dashboard: React.FC = () => { } }; + React.useEffect(() => { + if (projects.length > 0 && !hasSeenTour()) { + markTourSeen(); + } + }, [projects.length]); + return ( { {/* Hero / Welcome Header */} { variant="outlined" startIcon={} onClick={() => handleFeatureClick('/select-project')} + data-tour="tour-open-project-btn" sx={{ borderColor: theme.palette.divider, color: theme.palette.text.primary, @@ -309,120 +318,122 @@ const Dashboard: React.FC = () => { {/* Main Studio Modules (7 Cards) */} - - Studio Modules - - - {features.map((feature) => { - const IconComponent = feature.icon; - return ( - - - handleCardClick(feature)} + + + Studio Modules + + + {features.map((feature) => { + const IconComponent = feature.icon; + return ( + + - - + handleCardClick(feature)} + sx={{ + height: '100%', + p: 2.5, + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + justifyContent: 'space-between', + }} + > + - + + + + - + {feature.title} + + + > + {feature.description} + - - {feature.title} - - - {feature.description} - - - - - - ); - })} - + + + + ); + })} + + {/* Bottom Panels: Recent Projects & Active Connections */} @@ -430,6 +441,7 @@ const Dashboard: React.FC = () => { { { + {/* Only show the quick start tour for brand-new users with no projects */} + {projects.length === 0 && } ); }; diff --git a/src/renderer/screens/selectProject/index.tsx b/src/renderer/screens/selectProject/index.tsx index 995bffbf..3a426e5a 100644 --- a/src/renderer/screens/selectProject/index.tsx +++ b/src/renderer/screens/selectProject/index.tsx @@ -48,9 +48,6 @@ import { Icon, GetStartedModal, NewProject, - QuickStartTour, - markTourSeen, - hasSeenTour, } from '../../components'; import { icons } from '../../../../assets'; import connectionIcons from '../../../../assets/connectionIcons'; @@ -578,12 +575,6 @@ const SelectProject: React.FC = () => { setDefaultProjectPath(settings?.projectsDirectory ?? ''); }, [settings?.projectsDirectory]); - React.useEffect(() => { - if (projects.length > 0 && !hasSeenTour()) { - markTourSeen(); - } - }, [projects.length]); - return ( @@ -617,7 +608,7 @@ const SelectProject: React.FC = () => { - + { color="primary" onClick={handleGetStarted} sx={{ height: 40 }} - data-tour="tour-get-started-btn" > { variant="contained" color="primary" data-testid="import-project-btn" - data-tour="tour-import-btn" onClick={async () => { try { const project = @@ -749,7 +738,6 @@ const SelectProject: React.FC = () => { onClick={() => setIsAddingProject(true)} sx={{ height: 40 }} data-testid="create-project-btn" - data-tour="tour-new-project-btn" > New @@ -758,7 +746,6 @@ const SelectProject: React.FC = () => { { isOpen={isGetStartedModalOpen} onClose={() => setIsGetStartedModalOpen(false)} /> - {/* Only show the quick start tour for brand-new users with no projects */} - {projects.length === 0 && } {isCloneModalOpen && ( Date: Mon, 21 Sep 2026 14:06:22 +0200 Subject: [PATCH 4/5] fix: e2e testings --- e2e/fixtures/electron.fixture.ts | 8 ++-- e2e/helpers/window.helper.ts | 40 ++++++++++++++++++- e2e/page-objects/components/QuickStartTour.ts | 6 +-- e2e/tests/onboarding/quick-start-tour.spec.ts | 40 ++++++++++--------- e2e/tests/projects/project-lifecycle.spec.ts | 14 +------ e2e/tests/projects/project-selection.spec.ts | 12 +----- e2e/tests/shell/app-shell.spec.ts | 5 +++ 7 files changed, 77 insertions(+), 48 deletions(-) diff --git a/e2e/fixtures/electron.fixture.ts b/e2e/fixtures/electron.fixture.ts index 55dac1d9..63b8884a 100644 --- a/e2e/fixtures/electron.fixture.ts +++ b/e2e/fixtures/electron.fixture.ts @@ -32,10 +32,10 @@ export type ElectronFixtures = { extraProjects: string[]; /** * Mark the Quick Start tour as already seen before the renderer loads. - * The tour auto-opens ~700ms after the project selection screen mounts - * with zero projects and its full-screen overlay swallows every click, so - * tests that don't target it would otherwise race against it. Set to false - * in specs that test the tour itself. + * The tour auto-opens ~700ms after the Home screen (dashboard) mounts with + * zero projects and its full-screen overlay swallows every click, so tests + * that don't target it would otherwise race against it. Set to false in + * specs that test the tour itself. */ skipQuickStartTour: boolean; /** The Electron application instance */ diff --git a/e2e/helpers/window.helper.ts b/e2e/helpers/window.helper.ts index 299af094..b3dd5a1f 100644 --- a/e2e/helpers/window.helper.ts +++ b/e2e/helpers/window.helper.ts @@ -37,7 +37,28 @@ export const findStableWindow = async ( }; /** - * Land on the project selection screen with setup skipped. + * Land on the Home screen (dashboard) with setup skipped. Home is the app's + * default route, so this simply waits for the workspace overview to mount. + */ +export const openHome = async ( + electronApp: ElectronApplication, +): Promise => { + const window = await findStableWindow(electronApp); + await window.waitForLoadState('domcontentloaded'); + + const appHelper = new AppHelper(electronApp, window); + await appHelper.skipSetupIfPresent(); + + await window.waitForSelector('[data-tour="tour-workspace-overview"]', { + timeout: 10000, + }); + return window; +}; + +/** + * Land on the project selection screen with setup skipped. The app opens on + * the Home screen, so when the selection screen is not already mounted we take + * the "Open Project" shortcut from Home. */ export const openProjectSelection = async ( electronApp: ElectronApplication, @@ -48,6 +69,19 @@ export const openProjectSelection = async ( const appHelper = new AppHelper(electronApp, window); await appHelper.skipSetupIfPresent(); + const selection = window.locator('[data-testid="project-selection"]'); + const home = window.locator('[data-tour="tour-workspace-overview"]'); + + await Promise.race([ + selection.waitFor({ state: 'visible', timeout: 10000 }), + home.waitFor({ state: 'visible', timeout: 10000 }), + ]); + + if (await home.isVisible().catch(() => false)) { + await appHelper.dismissQuickStartTourIfPresent(); + await window.locator('[data-tour="tour-open-project-btn"]').click(); + } + await window.waitForSelector('[data-testid="project-selection"]', { timeout: 10000, }); @@ -77,5 +111,9 @@ export const openProject = async ( await expect(window.locator('[data-testid="sidebar"]')).toBeVisible({ timeout: 30000, }); + + // The app opens on the Home screen, so enter the selected project's + // workspace to mount the project-scoped chrome (file tree, dbt actions). + await window.locator('[data-testid="nav-item-files"]').click(); return window; }; diff --git a/e2e/page-objects/components/QuickStartTour.ts b/e2e/page-objects/components/QuickStartTour.ts index 0cab05f9..920b3aa5 100644 --- a/e2e/page-objects/components/QuickStartTour.ts +++ b/e2e/page-objects/components/QuickStartTour.ts @@ -1,9 +1,9 @@ /** * Quick Start Tour Component * - * Page object for the custom onboarding tour overlay shown on the project - * selection screen for users with no projects. It has no testids, so it is - * located through its visible text and the "Skip tour" icon title. + * Page object for the custom onboarding tour overlay shown on the Home screen + * (dashboard) for users with no projects. It has no testids, so it is located + * through its visible text and the "Skip tour" icon title. */ import { Page, Locator, expect } from '@playwright/test'; diff --git a/e2e/tests/onboarding/quick-start-tour.spec.ts b/e2e/tests/onboarding/quick-start-tour.spec.ts index b98a3eb6..58bf1042 100644 --- a/e2e/tests/onboarding/quick-start-tour.spec.ts +++ b/e2e/tests/onboarding/quick-start-tour.spec.ts @@ -1,14 +1,14 @@ /** * Quick Start Tour Tests * - * The tour auto-opens on the project selection screen when there are no + * The tour auto-opens on the Home screen (dashboard) when there are no * projects and it has not been seen before. Its overlay blocks the whole * page until it is skipped or completed. The fixture suppresses it by * default; these specs opt back in. */ import { test, expect } from '../../fixtures/electron.fixture'; -import { openProjectSelection } from '../../helpers/window.helper'; +import { openHome } from '../../helpers/window.helper'; import { QuickStartTourComponent } from '../../page-objects/components/QuickStartTour'; import { ProjectSelectionPage } from '../../page-objects/screens/ProjectSelection'; @@ -18,7 +18,7 @@ test.describe('Quick Start Tour', () => { test('should open automatically for a new user with no projects', async ({ electronApp, }) => { - const window = await openProjectSelection(electronApp); + const window = await openHome(electronApp); const tour = new QuickStartTourComponent(window); await tour.expectVisible(); @@ -32,52 +32,56 @@ test.describe('Quick Start Tour', () => { test('should block the page underneath until dismissed', async ({ electronApp, }) => { - const window = await openProjectSelection(electronApp); + const window = await openHome(electronApp); const tour = new QuickStartTourComponent(window); const projectSelection = new ProjectSelectionPage(window); await tour.expectVisible(); // The overlay intercepts pointer events, so a normal click never lands + const openProjectBtn = window.locator('[data-tour="tour-open-project-btn"]'); await expect( - projectSelection.createProjectBtn.click({ timeout: 1500 }), + openProjectBtn.click({ timeout: 1500 }), ).rejects.toThrow(); await tour.skip(); await tour.expectHidden(); // Now the page is interactive again - await projectSelection.clickCreateProject(); - await expect( - window.locator('[data-testid="project-name-input"]'), - ).toBeVisible(); + await openProjectBtn.click(); + await expect(projectSelection.container).toBeVisible(); }); test('should step forward and back through the tour', async ({ electronApp, }) => { - const window = await openProjectSelection(electronApp); + const window = await openHome(electronApp); const tour = new QuickStartTourComponent(window); await tour.expectStep(1); await tour.letsGo(); await tour.expectStep(2); await expect( - window.getByRole('heading', { name: 'Your Projects' }), + window.getByRole('heading', { name: 'Workspace Overview' }), ).toBeVisible(); + await expect(window.getByText('Your Home Screen')).toBeVisible(); await tour.next(); await tour.expectStep(3); + await expect(window.getByText('Studio Modules').first()).toBeVisible(); + + await tour.next(); + await tour.expectStep(4); await expect( - window.getByRole('heading', { name: 'Create a New Project' }), + window.getByText('Recent Projects', { exact: true }), ).toBeVisible(); await tour.back(); - await tour.expectStep(2); + await tour.expectStep(3); }); test('should mark the tour as seen when skipped', async ({ electronApp }) => { - const window = await openProjectSelection(electronApp); + const window = await openHome(electronApp); const tour = new QuickStartTourComponent(window); await tour.expectVisible(); @@ -90,7 +94,7 @@ test.describe('Quick Start Tour', () => { test('should close with the skip icon at any step', async ({ electronApp, }) => { - const window = await openProjectSelection(electronApp); + const window = await openHome(electronApp); const tour = new QuickStartTourComponent(window); await tour.letsGo(); @@ -102,7 +106,7 @@ test.describe('Quick Start Tour', () => { }); test('should finish with Done on the last step', async ({ electronApp }) => { - const window = await openProjectSelection(electronApp); + const window = await openHome(electronApp); const tour = new QuickStartTourComponent(window); await tour.letsGo(); @@ -128,7 +132,7 @@ test.describe('Quick Start Tour', () => { test('should not open when the user already has projects', async ({ electronApp, }) => { - const window = await openProjectSelection(electronApp); + const window = await openHome(electronApp); const tour = new QuickStartTourComponent(window); // Give the 700ms auto-open timer a chance to fire @@ -144,7 +148,7 @@ test.describe('Quick Start Tour - fixture default', () => { test('should be suppressed by the fixture for ordinary specs', async ({ electronApp, }) => { - const window = await openProjectSelection(electronApp); + const window = await openHome(electronApp); const tour = new QuickStartTourComponent(window); await window.waitForTimeout(1500); diff --git a/e2e/tests/projects/project-lifecycle.spec.ts b/e2e/tests/projects/project-lifecycle.spec.ts index 06111244..c3a34baa 100644 --- a/e2e/tests/projects/project-lifecycle.spec.ts +++ b/e2e/tests/projects/project-lifecycle.spec.ts @@ -1,7 +1,7 @@ import { Page, ElectronApplication } from '@playwright/test'; import { test, expect } from '../../fixtures/electron.fixture'; import { ProjectSelectionPage } from '../../page-objects/screens/ProjectSelection'; -import { AppHelper } from '../../helpers/app.helper'; +import { openProjectSelection } from '../../helpers/window.helper'; // Helper to find a stable window (after splash screen closes) const findStableWindow = async ( @@ -31,17 +31,7 @@ const findStableWindow = async ( test.describe('Project Lifecycle', () => { test.beforeEach(async ({ electronApp }) => { - // Wait for stable window (splash screen to close) - const stableWindow = await findStableWindow(electronApp); - await stableWindow.waitForLoadState('domcontentloaded'); - - const appHelper = new AppHelper(electronApp, stableWindow); - await appHelper.skipSetupIfPresent(); - - // Wait for project selection screen to be visible - await stableWindow.waitForSelector('[data-testid="project-selection"]', { - timeout: 10000, - }); + await openProjectSelection(electronApp); }); test('should create a new project', async ({ electronApp }) => { diff --git a/e2e/tests/projects/project-selection.spec.ts b/e2e/tests/projects/project-selection.spec.ts index fef5ab6a..91735737 100644 --- a/e2e/tests/projects/project-selection.spec.ts +++ b/e2e/tests/projects/project-selection.spec.ts @@ -12,7 +12,7 @@ import * as path from 'path'; import { Page, ElectronApplication } from '@playwright/test'; import { test, expect } from '../../fixtures/electron.fixture'; import { ProjectSelectionPage } from '../../page-objects/screens/ProjectSelection'; -import { AppHelper } from '../../helpers/app.helper'; +import { openProjectSelection } from '../../helpers/window.helper'; // Helper to find a stable window (after splash screen closes) const findStableWindow = async ( @@ -45,15 +45,7 @@ const errorToast = (page: Page, text: string) => test.describe('Project Selection', () => { test.beforeEach(async ({ electronApp }) => { - const stableWindow = await findStableWindow(electronApp); - await stableWindow.waitForLoadState('domcontentloaded'); - - const appHelper = new AppHelper(electronApp, stableWindow); - await appHelper.skipSetupIfPresent(); - - await stableWindow.waitForSelector('[data-testid="project-selection"]', { - timeout: 10000, - }); + await openProjectSelection(electronApp); }); test.describe('with no projects', () => { diff --git a/e2e/tests/shell/app-shell.spec.ts b/e2e/tests/shell/app-shell.spec.ts index c1233ce5..92f4f0c0 100644 --- a/e2e/tests/shell/app-shell.spec.ts +++ b/e2e/tests/shell/app-shell.spec.ts @@ -8,6 +8,7 @@ import { test, expect } from '../../fixtures/electron-seeded.fixture'; import { openProject } from '../../helpers/window.helper'; +import { NavigationSidebarComponent } from '../../page-objects/components/NavigationSidebar'; const PROJECT = 'test_project'; @@ -63,7 +64,11 @@ test.describe('App Shell', () => { test('should open the AI assistant and point to provider settings', async ({ electronApp, }) => { + // The assistant pane is mounted by the workspace screens (SQL/Notebooks/ + // project details), so open it from the SQL editor. const window = await openProject(electronApp, PROJECT); + const nav = new NavigationSidebarComponent(window); + await nav.goToSqlEditor(); await window.getByRole('button', { name: 'AI Assistant (beta)' }).click(); From 5ab90d3fe903c48f3060adf3f69bddc773539b78 Mon Sep 17 00:00:00 2001 From: flakronademi Date: Tue, 22 Sep 2026 12:02:24 +0200 Subject: [PATCH 5/5] fixed: post-create navigation and DBT card extra padding --- src/renderer/screens/dashboard/index.tsx | 6 +++--- src/renderer/screens/selectProject/index.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderer/screens/dashboard/index.tsx b/src/renderer/screens/dashboard/index.tsx index 69cc0fcd..e965a7b9 100644 --- a/src/renderer/screens/dashboard/index.tsx +++ b/src/renderer/screens/dashboard/index.tsx @@ -97,7 +97,7 @@ const features = [ description: 'Manage and explore your dbt models, sources, and documentation.', icon: DbtCardIcon, - path: '/select-project', + path: '/app/select-project', }, { id: 'notebook', @@ -280,7 +280,7 @@ const Dashboard: React.FC = () => {