Skip to content

Commit

Permalink
fix: tabs hanging when more than 3 are open (#493)
Browse files Browse the repository at this point in the history
  • Loading branch information
wesbillman authored Oct 13, 2023
1 parent 2983809 commit a5b573a
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 223 deletions.
162 changes: 17 additions & 145 deletions console/client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 2 additions & 6 deletions console/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@
],
"source": "index.html",
"dependencies": {
"@bufbuild/connect": "0.12.0",
"@bufbuild/connect-web": "0.12.0",
"@bufbuild/protobuf": "1.3.0",
"@connectrpc/connect": "^1.1.2",
"@connectrpc/connect-web": "^1.1.2",
"@headlessui/react": "1.7.16",
"@heroicons/react": "2.0.18",
"@monaco-editor/react": "4.5.2",
Expand All @@ -49,9 +48,6 @@
"vite": "^4.4.9"
},
"devDependencies": {
"@bufbuild/buf": "1.26.1",
"@bufbuild/protoc-gen-connect-es": "0.12.0",
"@bufbuild/protoc-gen-es": "1.3.0",
"@jest/globals": "29.6.2",
"@swc/core": "1.3.77",
"@swc/jest": "0.2.29",
Expand Down
12 changes: 9 additions & 3 deletions console/client/src/features/timeline/Timeline.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Timestamp } from '@bufbuild/protobuf'
import { useContext, useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { useVisibility } from '../../hooks/use-visibility.ts'
import { Event, EventsQuery_Filter } from '../../protos/xyz/block/ftl/v1/console/console_pb.ts'
import { SidePanelContext } from '../../providers/side-panel-provider.tsx'
import { eventIdFilter, getEvents, streamEvents, timeFilter } from '../../services/console.service.ts'
Expand All @@ -25,10 +26,15 @@ export const Timeline = ({ timeSettings, filters }: { timeSettings: TimeSettings
const { openPanel, closePanel, isOpen } = useContext(SidePanelContext)
const [entries, setEntries] = useState<Event[]>([])
const [selectedEntry, setSelectedEntry] = useState<Event | null>(null)
const isVisible = useVisibility()

useEffect(() => {
const eventId = searchParams.get('id')
const abortController = new AbortController()
if (!isVisible) {
abortController.abort()
return
}

const fetchEvents = async () => {
let eventFilters = filters
Expand Down Expand Up @@ -56,9 +62,9 @@ export const Timeline = ({ timeSettings, filters }: { timeSettings: TimeSettings
streamEvents({
abortControllerSignal: abortController.signal,
filters,
onEventReceived: (event) => {
onEventsReceived: (events) => {
if (!timeSettings.isPaused) {
setEntries((prev) => [event, ...prev].slice(0, maxTimelineEntries))
setEntries((prev) => [...events, ...prev].slice(0, maxTimelineEntries))
}
},
})
Expand All @@ -68,7 +74,7 @@ export const Timeline = ({ timeSettings, filters }: { timeSettings: TimeSettings
return () => {
abortController.abort()
}
}, [filters, timeSettings])
}, [filters, timeSettings, isVisible])

useEffect(() => {
if (!isOpen) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,15 @@ export const TimelineFilterPanel = ({
const [selectedLogLevel, setSelectedLogLevel] = useState<number>(1)

useEffect(() => {
if (modules.modules.length === 0) {
return
}
const newModules = modules.modules.map((module) => module.deploymentName)
const addedModules = newModules.filter((name) => !previousModules.includes(name))

setSelectedModules((prevSelected) => [...prevSelected, ...addedModules])
if (addedModules.length > 0) {
setSelectedModules((prevSelected) => [...prevSelected, ...addedModules])
}
setPreviousModules(newModules)
}, [modules])

Expand Down
5 changes: 3 additions & 2 deletions console/client/src/features/verbs/VerbPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ export const VerbPage = () => {
streamEvents({
abortControllerSignal: abortController.signal,
filters: [callFilter(module.name, verb?.verb?.name), eventTypesFilter([EventType.CALL])],
onEventReceived: (event) => {
setCalls((prev) => [event.entry.value as CallEvent, ...prev])
onEventsReceived: (events) => {
const callEvents = events.map((event) => event.entry.value as CallEvent)
setCalls((prev) => [...callEvents, ...prev])
},
})
}
Expand Down
4 changes: 2 additions & 2 deletions console/client/src/hooks/use-client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PromiseClient, createPromiseClient } from '@bufbuild/connect'
import { createConnectTransport } from '@bufbuild/connect-web'
import { ServiceType } from '@bufbuild/protobuf'
import { PromiseClient, createPromiseClient } from '@connectrpc/connect'
import { createConnectTransport } from '@connectrpc/connect-web'
import { useMemo } from 'react'

const transport = createConnectTransport({
Expand Down
66 changes: 66 additions & 0 deletions console/client/src/hooks/use-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Code, ConnectError } from '@connectrpc/connect'
import { useEffect, useState } from 'react'
import { useClient } from '../hooks/use-client'
import { useVisibility } from '../hooks/use-visibility.ts'
import { ControllerService } from '../protos/xyz/block/ftl/v1/ftl_connect.ts'
import { DeploymentChangeType, PullSchemaResponse } from '../protos/xyz/block/ftl/v1/ftl_pb'

export const useSchema = () => {
const client = useClient(ControllerService)
const [schema, setSchema] = useState<PullSchemaResponse[]>([])
const isVisible = useVisibility()

useEffect(() => {
const abortController = new AbortController()

const fetchSchema = async () => {
try {
if (!isVisible) {
abortController.abort()
return
}

const schemaMap = new Map<string, PullSchemaResponse>()
for await (const response of client.pullSchema(
{},
{
signal: abortController.signal,
},
)) {
const moduleName = response.moduleName ?? ''
switch (response.changeType) {
case DeploymentChangeType.DEPLOYMENT_ADDED:
schemaMap.set(moduleName, response)
break
case DeploymentChangeType.DEPLOYMENT_CHANGED:
schemaMap.set(moduleName, response)
break
case DeploymentChangeType.DEPLOYMENT_REMOVED:
schemaMap.delete(moduleName)
}

if (!response.more) {
setSchema(
Array.from(schemaMap.values()).sort((a, b) => a.schema?.name?.localeCompare(b.schema?.name ?? '') ?? 0),
)
}
}
} catch (error) {
if (error instanceof ConnectError) {
if (error.code !== Code.Canceled) {
console.error('Console service - streamEvents - Connect error:', error)
}
} else {
console.error('Console service - streamEvents:', error)
}
}
}

fetchSchema()
return () => {
abortController.abort()
}
}, [client, isVisible])

return schema
}
19 changes: 19 additions & 0 deletions console/client/src/hooks/use-visibility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useEffect, useState } from 'react'

export const useVisibility = () => {
const [isVisible, setIsVisible] = useState(document.visibilityState === 'visible')

useEffect(() => {
const handleVisibilityChange = () => {
setIsVisible(document.visibilityState === 'visible')
}

document.addEventListener('visibilitychange', handleVisibilityChange)

return () => {
document.removeEventListener('visibilitychange', handleVisibilityChange)
}
}, [])

return isVisible
}
Loading

0 comments on commit a5b573a

Please sign in to comment.