Skip to content

Commit

Permalink
feat: clean up layout and side bar components (#412)
Browse files Browse the repository at this point in the history
<img width="1582" alt="Screenshot 2023-09-20 at 11 15 26 AM"
src="https://github.com/TBD54566975/ftl/assets/51647/7e38ea2d-6186-436f-872a-83ae14429f07">
<img width="1582" alt="Screenshot 2023-09-20 at 11 15 30 AM"
src="https://github.com/TBD54566975/ftl/assets/51647/41352905-a149-43dc-b383-223437e270da">
<img width="1582" alt="Screenshot 2023-09-20 at 11 15 40 AM"
src="https://github.com/TBD54566975/ftl/assets/51647/650d1e46-f665-488b-8846-2b9595cd1677">
<img width="1582" alt="Screenshot 2023-09-20 at 11 15 37 AM"
src="https://github.com/TBD54566975/ftl/assets/51647/fced1ec0-cdb7-4fd9-8b96-314dba1c3e61">
<img width="1582" alt="Screenshot 2023-09-20 at 11 15 48 AM"
src="https://github.com/TBD54566975/ftl/assets/51647/7b36fa39-68dd-4c8d-a327-c95e9830bc6a">
<img width="1582" alt="Screenshot 2023-09-20 at 11 15 53 AM"
src="https://github.com/TBD54566975/ftl/assets/51647/632dd4e1-6df8-4d96-a522-8343e4913c7f">
  • Loading branch information
wesbillman authored Sep 20, 2023
1 parent 4bf4378 commit 901c5e7
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 132 deletions.
14 changes: 14 additions & 0 deletions console/client/src/components/AttributeBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
interface Props {
name: string
value: string
}

export const AttributeBadge = ({ name, value }: Props) => {
return (
<span className='inline-flex items-center px-2 py-0.5 space-x-1 rounded-md text-sm bg-gray-100 dark:bg-slate-700'>
<span className='text-gray-500 dark:text-gray-400'>{name}</span>
<span>:</span>
<span className='text-gray-900 dark:text-gray-100 font-medium'>{value}</span>
</span>
)
}
6 changes: 6 additions & 0 deletions console/client/src/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface Props {
children: React.ReactNode
}
export const Card = ({ children }: Props) => {
return <div className='p-2 rounded-md border border-gray-500'>{children}</div>
}
13 changes: 13 additions & 0 deletions console/client/src/components/CloseButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { XMarkIcon } from '@heroicons/react/24/outline'

interface Props {
onClick: () => void
}

export const CloseButton = ({ onClick }: Props) => {
return (
<button onClick={onClick} className='rounded-sm hover:bg-gray-200 dark:hover:bg-slate-500'>
<XMarkIcon className={`h-5 w-5`} />
</button>
)
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Timestamp } from '@bufbuild/protobuf'
import { useEffect, useState } from 'react'
import React, { useEffect, useState } from 'react'
import { AttributeBadge } from '../../../components/AttributeBadge'
import { CloseButton } from '../../../components/CloseButton'
import { CodeBlock } from '../../../components/CodeBlock'
import { useClient } from '../../../hooks/use-client'
import { ConsoleService } from '../../../protos/xyz/block/ftl/v1/console/console_connect'
import { Call } from '../../../protos/xyz/block/ftl/v1/console/console_pb'
import { SidePanelContext } from '../../../providers/side-panel-provider'
import { getRequestCalls } from '../../../services/console.service'
import { formatDuration } from '../../../utils/date.utils'
import { textColor } from '../../../utils/style.utils'
import { RequestGraph } from '../../requests/RequestGraph'
import { verbRefString } from '../../verbs/verb.utils'
import { TimelineTimestamp } from './TimelineTimestamp'
Expand All @@ -18,6 +20,7 @@ interface Props {

export const TimelineCallDetails = ({ timestamp, call }: Props) => {
const client = useClient(ConsoleService)
const { closePanel } = React.useContext(SidePanelContext)
const [requestCalls, setRequestCalls] = useState<Call[]>([])
const [selectedCall, setSelectedCall] = useState(call)

Expand All @@ -38,21 +41,25 @@ export const TimelineCallDetails = ({ timestamp, call }: Props) => {
}, [client, selectedCall])

return (
<>
<TimelineTimestamp timestamp={timestamp} />

<div className='pt-2'>
<RequestGraph calls={requestCalls} call={selectedCall} setSelectedCall={setSelectedCall} />
<div className='p-4'>
<div className='flex items-center justify-between'>
<div className='flex items-center space-x-2'>
<div className=''>
{call.destinationVerbRef && (
<div
className={`inline-block rounded-md bg-indigo-200 dark:bg-indigo-700 px-2 py-1 mr-1 text-sm font-medium text-gray-700 dark:text-gray-100`}
>
{verbRefString(call.destinationVerbRef)}
</div>
)}
</div>
<TimelineTimestamp timestamp={timestamp} />
</div>
<CloseButton onClick={closePanel} />
</div>

<div className='pt-4'>
{call.destinationVerbRef && (
<div
className={`inline-block rounded-md dark:bg-gray-700/40 px-2 py-1 mr-1 text-xs font-medium 'text-gray-500 dark:text-gray-400 ring-1 ring-inset ring-black/10 dark:ring-white/10`}
>
{verbRefString(call.destinationVerbRef)}
</div>
)}
<RequestGraph calls={requestCalls} call={selectedCall} setSelectedCall={setSelectedCall} />
</div>

<div className='text-sm pt-2'>Request</div>
Expand All @@ -68,40 +75,29 @@ export const TimelineCallDetails = ({ timestamp, call }: Props) => {
</>
)}

<div className='pt-2 text-gray-500 dark:text-gray-400'>
<div className='flex pt-2 justify-between'>
<dt>Deployment</dt>
<dd className={`${textColor}`}>{selectedCall.deploymentName}</dd>
</div>
<div className='flex pt-2 justify-between'>
<dt>Request</dt>
<dd className={`${textColor}`}>{selectedCall.requestName}</dd>
</div>
<div className='flex pt-2 justify-between'>
<dt>Duration</dt>
<dd className={`${textColor}`}>{formatDuration(selectedCall.duration)}</dd>
</div>
<div className='flex pt-2 justify-between'>
<dt>Module</dt>
<dd className={`${textColor}`}>{selectedCall.destinationVerbRef?.module}</dd>
</div>
<div className='flex pt-2 justify-between'>
<dt>Verb</dt>
<dd className={`${textColor}`}>{selectedCall.destinationVerbRef?.name}</dd>
</div>
{selectedCall.sourceVerbRef?.module && (
<>
<div className='flex pt-2 justify-between'>
<dt>Source module</dt>
<dd className={`${textColor}`}>{selectedCall.sourceVerbRef?.module}</dd>
</div>
<div className='flex pt-2 justify-between'>
<dt>Source verb</dt>
<dd className={`${textColor}`}>{selectedCall.sourceVerbRef?.name}</dd>
</div>
</>
<ul className='pt-4 space-y-2'>
<li>
<AttributeBadge name='Deployment' value={selectedCall.deploymentName} />
</li>
{selectedCall.requestName && (
<li>
<AttributeBadge name='Request' value={selectedCall.requestName} />
</li>
)}
</div>
</>
<li>
<AttributeBadge name='Duration' value={formatDuration(selectedCall.duration)} />
</li>
{selectedCall.destinationVerbRef && (
<li>
<AttributeBadge name='Destination' value={verbRefString(selectedCall.destinationVerbRef)} />
</li>
)}
{selectedCall.sourceVerbRef && (
<li>
<AttributeBadge name='Source' value={verbRefString(selectedCall.sourceVerbRef)} />
</li>
)}
</ul>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Timestamp } from '@bufbuild/protobuf'
import React from 'react'
import { AttributeBadge } from '../../../components/AttributeBadge'
import { CloseButton } from '../../../components/CloseButton'
import { Deployment, DeploymentEventType, Event } from '../../../protos/xyz/block/ftl/v1/console/console_pb'
import { SidePanelContext } from '../../../providers/side-panel-provider'
import { classNames } from '../../../utils/react.utils'
import { textColor } from '../../../utils/style.utils'
import { TimelineTimestamp } from './TimelineTimestamp'

interface Props {
Expand All @@ -16,55 +19,61 @@ export const deploymentTypeText: { [key in DeploymentEventType]: string } = {
[DeploymentEventType.DEPLOYMENT_REPLACED]: 'Replaced',
}

export const deploymentTypeBarColor: { [key in DeploymentEventType]: string } = {
[DeploymentEventType.DEPLOYMENT_UNKNOWN]: '',
[DeploymentEventType.DEPLOYMENT_CREATED]: 'bg-green-500 dark:bg-green-300',
[DeploymentEventType.DEPLOYMENT_UPDATED]: 'bg-blue-500 dark:bg-blue-300',
[DeploymentEventType.DEPLOYMENT_REPLACED]: 'bg-indigo-600 dark:bg-indigo-300',
}

export const deploymentTypeBadge: { [key in DeploymentEventType]: string } = {
[DeploymentEventType.DEPLOYMENT_UNKNOWN]: '',
[DeploymentEventType.DEPLOYMENT_CREATED]: 'text-green-600 bg-green-400/30 dark:text-green-300 dark:bg-green-700/10',
[DeploymentEventType.DEPLOYMENT_UPDATED]: 'text-blue-350 bg-blue-300/30 dark:text-blue-300 dark:bg-blue-700/30',
[DeploymentEventType.DEPLOYMENT_CREATED]: 'text-green-500 bg-green-400/30 dark:text-green-300 dark:bg-green-700/10',
[DeploymentEventType.DEPLOYMENT_UPDATED]: 'text-blue-500 bg-blue-300/30 dark:text-blue-300 dark:bg-blue-700/30',
[DeploymentEventType.DEPLOYMENT_REPLACED]:
'text-indigo-600 bg-indigo-400/30 dark:text-indigo-300 dark:bg-indigo-700/10',
'text-indigo-600 bg-indigo-400/30 dark:text-indigo-300 dark:bg-indigo-700/50',
}

export const TimelineDeploymentDetails = ({ event, deployment }: Props) => {
const { closePanel } = React.useContext(SidePanelContext)
return (
<>
<div>
<TimelineTimestamp timestamp={event.timeStamp ?? new Timestamp()} />
</div>
<div className={`${deploymentTypeBarColor[deployment.eventType]} h-2 w-full`}></div>
<div className='p-4'>
<div className='flex items-center justify-between'>
<div className='flex items-center space-x-2'>
<span
className={classNames(
deploymentTypeBadge[deployment.eventType],
'inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-gray-600',
)}
>
{deploymentTypeText[deployment.eventType]}
</span>
<TimelineTimestamp timestamp={event.timeStamp ?? new Timestamp()} />
</div>
<CloseButton onClick={closePanel} />
</div>

<div className='pt-4'>
<span
className={classNames(
deploymentTypeBadge[deployment.eventType],
'inline-flex items-center rounded-md px-2 py-1 text-xs font-medium text-gray-600',
<ul className='pt-4 space-y-2'>
<li>
<AttributeBadge name='Name' value={deployment.name} />
</li>
<li>
<AttributeBadge name='Module' value={deployment.moduleName} />
</li>
<li>
<AttributeBadge name='Language' value={deployment.language} />
</li>
<li>
<AttributeBadge name='MinReplicas' value={deployment.minReplicas.toString()} />
</li>
{deployment.replaced && (
<li>
<AttributeBadge name='Replaced' value={deployment.replaced} />
</li>
)}
>
{deploymentTypeText[deployment.eventType]}
</span>
</div>

<div className='pt-2 text-gray-500 dark:text-gray-400'>
<div className='flex pt-2 justify-between'>
<dt>Name</dt>
<dd className={`${textColor}`}>{deployment.name}</dd>
</div>
<div className='flex pt-2 justify-between'>
<dt>Module</dt>
<dd className={`${textColor}`}>{deployment.moduleName}</dd>
</div>
<div className='flex pt-2 justify-between'>
<dt>Language</dt>
<dd className={`${textColor}`}>{deployment.language}</dd>
</div>
<div className='flex pt-2 justify-between'>
<dt>Min replicas</dt>
<dd className={`${textColor}`}>{deployment.minReplicas}</dd>
</div>
{deployment.replaced && (
<div className='flex pt-2 justify-between'>
<dt>Replaced</dt>
<dd className={`${textColor}`}>{deployment.replaced}</dd>
</div>
)}
</ul>
</div>
</>
)
Expand Down
64 changes: 34 additions & 30 deletions console/client/src/features/timeline/details/TimelineLogDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Timestamp } from '@bufbuild/protobuf'
import React from 'react'
import { AttributeBadge } from '../../../components/AttributeBadge'
import { CloseButton } from '../../../components/CloseButton'
import { CodeBlock } from '../../../components/CodeBlock'
import { Event, LogEntry } from '../../../protos/xyz/block/ftl/v1/console/console_pb'
import { SidePanelContext } from '../../../providers/side-panel-provider'
import { textColor } from '../../../utils/style.utils'
import { LogLevelBadge } from '../../logs/LogLevelBadge'
import { logLevelBgColor } from '../../logs/log.utils'
import { TimelineTimestamp } from './TimelineTimestamp'

interface Props {
Expand All @@ -11,41 +16,40 @@ interface Props {
}

export const TimelineLogDetails = ({ event, log }: Props) => {
const { closePanel } = React.useContext(SidePanelContext)
return (
<>
<div>
<TimelineTimestamp timestamp={event.timeStamp ?? new Timestamp()} />
</div>
<div className={`pt-4 text-xs ${textColor}`}>
<p className='flex-wrap font-mono'>{log.message}</p>
</div>

<h2 className='pt-4 text-sm'>Attributes</h2>
<CodeBlock code={JSON.stringify(log.attributes, null, 2)} language='json' />

<div className='pt-2 text-gray-500 dark:text-gray-400'>
<div className='flex pt-2 justify-between'>
<dt>Level</dt>
<dd className={`${textColor}`}>
<div className={`${logLevelBgColor[log.logLevel]} h-2 w-full`}></div>
<div className='p-4'>
<div className='flex items-center justify-between'>
<div className='flex items-center space-x-2'>
<LogLevelBadge logLevel={log.logLevel} />
</dd>
<TimelineTimestamp timestamp={event.timeStamp ?? new Timestamp()} />
</div>
<CloseButton onClick={closePanel} />
</div>
<div className='flex pt-2 justify-between'>
<dt>Deployment</dt>
<dd className={`${textColor}`}>{log.deploymentName}</dd>
<div className={`mt-4 p-2 text-sm bg-gray-100 dark:bg-slate-700 rounded ${textColor}`}>
<p className='break-words whitespace-normal font-roboto-mono'>{log.message}</p>
</div>
{log.requestName && (
<div className='flex pt-2 justify-between'>
<dt>Request</dt>
<dd className={`${textColor}`}>{log.requestName}</dd>
</div>
)}
{log.error && (
<div className='flex pt-2 justify-between'>
<dt>Error</dt>
<dd className={`${textColor}`}>{log.error}</dd>
</div>
)}

<h2 className='pt-4 text-sm'>Attributes</h2>
<CodeBlock code={JSON.stringify(log.attributes, null, 2)} language='json' />

<ul className='pt-4 space-y-2'>
<li>
<AttributeBadge name='Deployment' value={log.deploymentName} />
</li>
{log.requestName && (
<li>
<AttributeBadge name='Request' value={log.requestName} />
</li>
)}
{log.error && (
<li>
<AttributeBadge name='Error' value={log.error} />
</li>
)}
</ul>
</div>
</>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Timestamp } from '@bufbuild/protobuf'
import { formatTimestampShort } from '../../../utils/date.utils'
import { lightTextColor } from '../../../utils/style.utils'
import { textColor } from '../../../utils/style.utils'

interface Props {
timestamp: Timestamp
}

export const TimelineTimestamp = ({ timestamp }: Props) => {
return (
<time dateTime={formatTimestampShort(timestamp)} className={`flex-none text-xs ${lightTextColor}`}>
<time dateTime={formatTimestampShort(timestamp)} className={`flex-none text-sm ${textColor}`}>
{formatTimestampShort(timestamp)}
</time>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const TimelineFilterPanel = ({ onFiltersChanged }: Props) => {
return (
<div className='flex-shrink-0 w-52'>
<div className='w-full'>
<div className='mx-auto w-full max-w-md p-2'>
<div className='mx-auto w-full max-w-md pt-2 pl-2 pb-2'>
<FilterPanelSection title='Event types'>
{Object.keys(EVENT_TYPES).map((key) => (
<div key={key} className='relative flex items-start'>
Expand Down
Loading

0 comments on commit 901c5e7

Please sign in to comment.