Skip to content

Commit

Permalink
feat: delete Deployments tab, module tree uses old deployments compon…
Browse files Browse the repository at this point in the history
…ents (#2560)

* Removes `Deployments` tab
* Removes all the extraneous page headers
(#2490)
* Fixes all the routing to point to `/modules/{moduleName}/...` instead
of `/deployments/{deploymentKey}/...`
* Minor cleanup of deployment components' internal logic after replacing
`deploymentKey` with `moduleName` in the outermost interface


https://github.com/user-attachments/assets/ad785b7c-3e88-4d8d-8edb-b14bed441c98
  • Loading branch information
deniseli authored Sep 3, 2024
1 parent 4d31576 commit 8d0cdac
Show file tree
Hide file tree
Showing 17 changed files with 134 additions and 116 deletions.
14 changes: 0 additions & 14 deletions frontend/console/e2e/deployment.spec.ts

This file was deleted.

10 changes: 0 additions & 10 deletions frontend/console/e2e/deployments.spec.ts

This file was deleted.

15 changes: 15 additions & 0 deletions frontend/console/e2e/module.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { expect, ftlTest } from './ftl-test'

ftlTest('shows verbs for deployment', async ({ page }) => {
const modulesNavItem = page.getByRole('link', { name: 'Modules' })
await modulesNavItem.click()

const moduleEchoRow = page.getByRole('button', { name: 'echo' })
const moduleEcho = moduleEchoRow.locator('svg').nth(1)
await moduleEcho.click()

await expect(page).toHaveURL(/\/modules\/echo/)

await expect(page.getByText('Deployment', { exact: true })).toBeVisible()
await expect(page.getByText('Deployed dpl-echo')).toBeVisible()
})
10 changes: 10 additions & 0 deletions frontend/console/e2e/modules.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { expect, ftlTest } from './ftl-test'

ftlTest('shows active modules', async ({ page }) => {
const modulesNavItem = page.getByRole('link', { name: 'Modules' })
await modulesNavItem.click()
await expect(page).toHaveURL(/\/modules$/)

await expect(page.getByText('dpl-time')).toBeVisible()
await expect(page.getByText('dpl-echo')).toBeVisible()
})
12 changes: 6 additions & 6 deletions frontend/console/e2e/verb.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { expect, ftlTest } from './ftl-test'

ftlTest.beforeEach(async ({ page }) => {
const deploymentsNavItem = page.getByRole('link', { name: 'Deployments' })
await deploymentsNavItem.click()
const modulesNavItem = page.getByRole('link', { name: 'Modules' })
await modulesNavItem.click()

const deploymentEcho = page.getByText('dpl-echo')
await deploymentEcho.click()
const moduleEcho = page.getByRole('button', { name: 'echo' })
await moduleEcho.click()

const verbEcho = page.getByText('echo', { exact: true })
const verbEcho = page.getByRole('button', { name: 'echo Exported' })
await verbEcho.click()

await expect(page).toHaveURL(/\/deployments\/dpl-echo-[^/]+\/verbs\/echo/)
await expect(page).toHaveURL(/\/modules\/echo\/verb\/echo/)
})

ftlTest('shows verb form', async ({ page }) => {
Expand Down
68 changes: 68 additions & 0 deletions frontend/console/playwright-report/index.html

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const DeploymentCard = ({ deploymentKey, className }: { deploymentKey: st
}, [modules.data])

return (
<Card key={deploymentKey} topBarColor='bg-green-500' className={className} onClick={() => navigate(`/deployments/${deploymentKey}`)}>
<Card key={deploymentKey} topBarColor='bg-green-500' className={className} onClick={() => navigate(`/modules/${module?.name}`)}>
<div className='flex flex-col'>
<div className='flex items-center'>
<p className={`truncate flex-grow min-w-0 pr-2 ${deploymentTextColor(deploymentKey)}`}>{deploymentKey}</p>
Expand Down
44 changes: 9 additions & 35 deletions frontend/console/src/features/deployments/DeploymentPage.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
import { RocketLaunchIcon } from '@heroicons/react/24/outline'
import { useContext, useEffect, useMemo, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { useEffect, useMemo, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useModules } from '../../api/modules/use-modules'
import { modulesFilter } from '../../api/timeline'
import { Badge } from '../../components/Badge'
import { Card } from '../../components/Card'
import { Page } from '../../layout'
import type { Module, Verb } from '../../protos/xyz/block/ftl/v1/console/console_pb'
import { NotificationType, NotificationsContext } from '../../providers/notifications-provider'
import { SidePanelProvider } from '../../providers/side-panel-provider'
import { deploymentKeyModuleName } from '../modules/module.utils'
import { Timeline } from '../timeline/Timeline'
import { isCron, isExported, isHttpIngress } from '../verbs/verb.utils'

const timeSettings = { isTailing: true, isPaused: false }

export const DeploymentPage = () => {
const navigate = useNavigate()
const { deploymentKey } = useParams()
export const DeploymentPage = ({ moduleName }: { moduleName: string }) => {
const modules = useModules()
const notification = useContext(NotificationsContext)
const navgation = useNavigate()
const navigate = useNavigate()
const [module, setModule] = useState<Module | undefined>()

const filters = useMemo(() => {
Expand All @@ -30,41 +24,21 @@ export const DeploymentPage = () => {
}, [module?.deploymentKey])

useEffect(() => {
if (modules.isSuccess && modules.data.modules.length > 0 && deploymentKey) {
let module = modules.data.modules.find((module) => module.deploymentKey === deploymentKey)
if (!module) {
const moduleName = deploymentKeyModuleName(deploymentKey)
if (moduleName) {
module = modules.data.modules.find((module) => module.name === moduleName)
navgation(`/deployments/${module?.deploymentKey}`)
notification.showNotification({
title: 'Showing latest deployment',
message: `The previous deployment of ${module?.deploymentKey} was not found. Showing the latest deployment of ${module?.name} instead.`,
type: NotificationType.Info,
})
setModule(module)
}
} else {
setModule(module)
}
if (modules.isSuccess && modules.data.modules.length > 0) {
const module = modules.data.modules.find((module) => module.name === moduleName)
setModule(module)
}
}, [modules.data, deploymentKey])
}, [modules.data, moduleName])

return (
<SidePanelProvider>
<Page>
<Page.Header icon={<RocketLaunchIcon />} title={module?.deploymentKey || 'Loading...'} breadcrumbs={[{ label: 'Deployments', link: '/deployments' }]} />

<Page.Body className='flex'>
<div className=''>
<div className='flex-1 h-1/2 p-4 overflow-y-scroll'>
<div className='grid grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4'>
{module?.verbs.map((verb) => (
<Card
key={verb.verb?.name}
topBarColor='bg-green-500'
onClick={() => navigate(`/deployments/${module.deploymentKey}/verbs/${verb.verb?.name}`)}
>
<Card key={verb.verb?.name} topBarColor='bg-green-500' onClick={() => navigate(`/modules/${module.name}/verb/${verb.verb?.name}`)}>
<p className='trucate text-sm overflow-hidden'>{verb.verb?.name}</p>
{badges(verb).length > 0 && (
<div className='pt-1 space-x-1'>
Expand Down
2 changes: 0 additions & 2 deletions frontend/console/src/features/deployments/DeploymentsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { RocketLaunchIcon } from '@heroicons/react/24/outline'
import { useModules } from '../../api/modules/use-modules'
import { Page } from '../../layout'
import { DeploymentCard } from './DeploymentCard'
Expand All @@ -12,7 +11,6 @@ export const DeploymentsPage = () => {

return (
<Page>
<Page.Header icon={<RocketLaunchIcon />} title='Deployments' />
<Page.Body className='flex'>
{modules.isLoading && <div>Loading...</div>}
{modules.isSuccess && (
Expand Down
7 changes: 2 additions & 5 deletions frontend/console/src/features/modules/ModulePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { useParams } from 'react-router-dom'
import { DeploymentPage } from '../deployments/DeploymentPage'

export const ModulePanel = () => {
const { moduleName } = useParams()

return (
<div className='flex-1 py-2 px-4'>
<p>Module: {moduleName}</p>
</div>
)
return <DeploymentPage moduleName={moduleName || ''} />
}
7 changes: 2 additions & 5 deletions frontend/console/src/features/modules/ModulesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@ import type React from 'react'
import { useMemo, useState } from 'react'
import { useSchema } from '../../api/schema/use-schema'
import { ResizableHorizontalPanels } from '../../components/ResizableHorizontalPanels'
import { DeploymentsPage } from '../deployments/DeploymentsPage'
import { ModulesTree } from './ModulesTree'
import { moduleTreeFromSchema } from './module.utils'

const treeWidthStorageKey = 'tree_w'

export const ModulesPanel = () => {
return (
<div className='flex-1 py-2 px-4'>
<p>Content</p>
</div>
)
return <DeploymentsPage />
}

export const ModulesPage = ({ body }: { body: React.ReactNode }) => {
Expand Down
1 change: 0 additions & 1 deletion frontend/console/src/features/modules/ModulesTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ const ModuleSection = ({ module, isExpanded, toggleExpansion }: { module: Module
<BookOpenIcon aria-hidden='true' className='size-4 my-1 shrink-0 ' />
{module.name}
<ArrowRightCircleIcon
aria-hidden='true'
className='size-4 shrink-0 rounded-md hover:bg-gray-200 dark:hover:bg-gray-600'
onClick={(e) => {
e.preventDefault()
Expand Down
4 changes: 2 additions & 2 deletions frontend/console/src/features/modules/decls/DeclPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMemo } from 'react'
import { useParams } from 'react-router-dom'
import { useSchema } from '../../../api/schema/use-schema'
import { VerbPage } from '../../verbs/VerbPage'
import { declFromSchema } from '../module.utils'
import { DataPanel } from './DataPanel'
import { VerbPanel } from './VerbPanel'

export const DeclPanel = () => {
const { moduleName, declCase, declName } = useParams()
Expand All @@ -23,7 +23,7 @@ export const DeclPanel = () => {
case 'data':
return <DataPanel value={decl.value.value} {...nameProps} />
case 'verb':
return <VerbPanel value={decl.value.value} {...nameProps} />
return <VerbPage {...nameProps} />
}
return (
<div className='flex-1 py-2 px-4'>
Expand Down
43 changes: 15 additions & 28 deletions frontend/console/src/features/verbs/VerbPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BoltIcon, Square3Stack3DIcon } from '@heroicons/react/24/outline'
import { BoltIcon } from '@heroicons/react/24/outline'
import { useContext, useEffect, useState } from 'react'
import { useNavigate, useParams } from 'react-router-dom'
import { useNavigate } from 'react-router-dom'
import { useModules } from '../../api/modules/use-modules'
import { useStreamVerbCalls } from '../../api/timeline/stream-verb-calls'
import { Loader } from '../../components/Loader'
Expand All @@ -10,12 +10,10 @@ import type { CallEvent, Module, Verb } from '../../protos/xyz/block/ftl/v1/cons
import { NotificationType, NotificationsContext } from '../../providers/notifications-provider'
import { SidePanelProvider } from '../../providers/side-panel-provider'
import { CallList } from '../calls/CallList'
import { deploymentKeyModuleName } from '../modules/module.utils'
import { VerbRequestForm } from './VerbRequestForm'
import { verbPanels } from './VerbRightPanel'

export const VerbPage = () => {
const { deploymentKey, verbName } = useParams()
export const VerbPage = ({ moduleName, declName }: { moduleName: string; declName: string }) => {
const notification = useContext(NotificationsContext)
const navgation = useNavigate()
const modules = useModules()
Expand All @@ -24,25 +22,22 @@ export const VerbPage = () => {

useEffect(() => {
if (!modules.isSuccess) return
if (modules.data.modules.length === 0 || !deploymentKey || !verbName) return
if (modules.data.modules.length === 0 || !moduleName || !declName) return

let module = modules.data.modules.find((module) => module.deploymentKey === deploymentKey)
if (!module) {
const moduleName = deploymentKeyModuleName(deploymentKey)
if (moduleName) {
module = modules.data.modules.find((module) => module.name === moduleName)
navgation(`/deployments/${module?.deploymentKey}/verbs/${verbName}`)
notification.showNotification({
title: 'Showing latest deployment',
message: `The previous deployment of ${module?.deploymentKey} was not found. Showing the latest deployment of ${module?.name}.${verbName} instead.`,
type: NotificationType.Info,
})
}
let module = modules.data.modules.find((module) => module.name === moduleName)
if (!module && moduleName) {
module = modules.data.modules.find((module) => module.name === moduleName)
navgation(`/modules/${module?.name}/verb/${declName}`)
notification.showNotification({
title: 'Showing latest deployment',
message: `The previous deployment of ${module?.name} was not found. Showing the latest deployment of ${module?.name}.${declName} instead.`,
type: NotificationType.Info,
})
}
setModule(module)
const verb = module?.verbs.find((verb) => verb.verb?.name.toLocaleLowerCase() === verbName?.toLocaleLowerCase())
const verb = module?.verbs.find((verb) => verb.verb?.name.toLocaleLowerCase() === declName?.toLocaleLowerCase())
setVerb(verb)
}, [modules.data, deploymentKey])
}, [modules.data, moduleName])

const callEvents = useStreamVerbCalls(module?.name, verb?.verb?.name)
const calls: CallEvent[] = callEvents.data || []
Expand All @@ -65,14 +60,6 @@ export const VerbPage = () => {
return (
<SidePanelProvider>
<Page>
<Page.Header
icon={<Square3Stack3DIcon />}
title={verb?.verb?.name || ''}
breadcrumbs={[
{ label: 'Deployments', link: '/deployments' },
{ label: module?.deploymentKey || '', link: `/deployments/${module?.deploymentKey}` },
]}
/>
<Page.Body className='flex h-full'>
<ResizablePanels
mainContent={<VerbRequestForm module={module} verb={verb} />}
Expand Down
1 change: 0 additions & 1 deletion frontend/console/src/layout/navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Version } from './Version'

const navigation = [
{ name: 'Events', href: '/events', icon: ListBulletIcon },
{ name: 'Deployments', href: '/deployments', icon: Square3Stack3DIcon },
{ name: 'Modules', href: '/modules', icon: Square3Stack3DIcon },
{ name: 'Graph', href: '/graph', icon: CubeTransparentIcon },
{ name: 'Infrastructure', href: '/infrastructure', icon: ServerStackIcon },
Expand Down
6 changes: 0 additions & 6 deletions frontend/console/src/providers/routing-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { Navigate, Route, RouterProvider, createBrowserRouter, createRoutesFromElements } from 'react-router-dom'
import { ConsolePage } from '../features/console/ConsolePage'
import { DeploymentPage } from '../features/deployments/DeploymentPage'
import { DeploymentsPage } from '../features/deployments/DeploymentsPage'
import { InfrastructurePage } from '../features/infrastructure/InfrastructurePage'
import { ModulePanel } from '../features/modules/ModulePanel'
import { ModulesPage, ModulesPanel } from '../features/modules/ModulesPage'
import { DeclPanel } from '../features/modules/decls/DeclPanel'
import { TimelinePage } from '../features/timeline/TimelinePage'
import { VerbPage } from '../features/verbs/VerbPage'
import { Layout } from '../layout/Layout'
import { NotFoundPage } from '../layout/NotFoundPage'

Expand All @@ -20,9 +17,6 @@ const router = createBrowserRouter(
<Route path='modules' element={<ModulesPage body={<ModulesPanel />} />} />
<Route path='modules/:moduleName' element={<ModulesPage body={<ModulePanel />} />} />
<Route path='modules/:moduleName/:declCase/:declName' element={<ModulesPage body={<DeclPanel />} />} />
<Route path='deployments' element={<DeploymentsPage />} />
<Route path='deployments/:deploymentKey' element={<DeploymentPage />} />
<Route path='deployments/:deploymentKey/verbs/:verbName' element={<VerbPage />} />
<Route path='graph' element={<ConsolePage />} />
<Route path='infrastructure' element={<InfrastructurePage />} />
</Route>
Expand Down
4 changes: 4 additions & 0 deletions frontend/console/test-results/.last-run.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"status": "passed",
"failedTests": []
}

0 comments on commit 8d0cdac

Please sign in to comment.