Skip to content

Commit

Permalink
Devtools: moved table and header to own component
Browse files Browse the repository at this point in the history
  • Loading branch information
dhuebner committed Jul 28, 2023
1 parent 656950b commit d6b861a
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 323 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@ export function createDiagramData(componentState: DiagramState): GraphData {
storedState = componentState;

const unqualifiedName = (name: string) => name.split('.').pop();
graphData.nodes.push({
id: 'host extension',
name: componentState.extensionName,
shortName: unqualifiedName(componentState.extensionName),
value: 20
} as ComponentNode);

if (componentState.extensionName) {
graphData.nodes.push({
id: 'host extension',
name: componentState.extensionName,
shortName: unqualifiedName(componentState.extensionName),
value: 20
} as ComponentNode);

}
if (componentState.webviews) {
componentState.webviews.forEach((webview) => {
graphData.nodes.push({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ColDef, GridApi } from 'ag-grid-community';
import { AgGridReact } from 'ag-grid-react';
import { ExtendedMessengerEvent } from '../devtools-view';
import React from 'react';
import { MessengerEvent } from 'vscode-messenger';

const columnDefs: ColDef[] = [
{
field: 'type',
initialWidth: 110,
cellRenderer: (params: any) => {
const rowType = params.data.type ?? 'unknown';
const error = params.data.error ? <span className='table-cell codicon codicon-stop' title={params.data.error}></span> : undefined;
return <div className={'rowType_' + rowType} style={{ display: 'flex', alignContent: 'space-between' }}><span style={{ flexGrow: 1 }}>{params.value}</span>{error}</div>;
}
},
{ field: 'sender', initialWidth: 180 },
{ field: 'receiver', initialWidth: 180 },
{
field: 'method', initialWidth: 135,
tooltipField: 'methodTooltip'
},
{
field: 'size', headerName: 'Size (Time)', initialWidth: 135,
cellRenderer: (params: any) => {
const event = (params.data as ExtendedMessengerEvent);
const charsCount = Intl.NumberFormat('en', { notation: 'compact' }).format(event.size);
if (event.type === 'response' && typeof event.timeAfterRequest === 'number') {
const tookMs = event.timeAfterRequest % 1000;
const tookSec = Math.trunc(event.timeAfterRequest / 1000);
const secPart = (tookSec > 0) ? `${tookSec}s ` : '';
return `${charsCount} (${secPart}${tookMs}ms)`;
}
return charsCount;

}
},
{ field: 'id' },
{
field: 'timestamp',
initialWidth: 135,
cellRenderer: (params: any) => {
const time = params.data.timestamp;
if (typeof time === 'number') {
const date = new Date(time);
const prependZero = (n: number) => ('0' + n).slice(-2);
return `${prependZero(date.getHours())}:${prependZero(date.getMinutes())}:${prependZero(date.getSeconds())}-${('00' + date.getMilliseconds()).slice(-3)}`;
}
return String(time);
}
},
{ field: 'error' },
];

/**
* Table that shows messages exchanged between the extension and the webviews.
*/
export class EventTable extends React.Component {

gridRefObj: React.RefObject<AgGridReact<MessengerEvent>>;
props: { gridRowSelected: (e: any) => void };

constructor(props: { gridRowSelected: (e: any) => void }) {
super({});
this.props = props;
this.gridRefObj = React.createRef();
}

getGridApi(): GridApi<MessengerEvent> | undefined {
return this.gridRefObj.current?.api;
}

render(): JSX.Element {
return (
<div id='event-table'
className={getComputedStyle(document.getElementById('root')!).getPropertyValue('--event-table-class')}>
<AgGridReact
ref={this.gridRefObj}
columnDefs={
columnDefs.map(col => {
return {
filter: true, resizable: true, sortable: true,
cellStyle: (params: any) => {
if (params.value === 'Police') {
//mark police cells as red
return { color: 'red', backgroundColor: 'green' };
}
return null;
},
tooltipField: col.field,
...col
};
})}
rowHeight={25}
headerHeight={28}
enableBrowserTooltips={true}
onCellFocused={(e) => this.props.gridRowSelected(e)}
>
</AgGridReact>
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { VSCodeButton, VSCodeDropdown, VSCodeOption } from '@vscode/webview-ui-toolkit/react';
import { MouseEventHandler } from 'react';
import { ExtensionData } from '../devtools-view';

export function ViewHeader(props: {
state: { selectedExtension: string | undefined; extensions: ExtensionData[]; },
onExtensionSelected: (extId: string) => void,
onRefreshClicked: MouseEventHandler<HTMLElement> | undefined,
onClearClicked: (extId: string | undefined) => void,
onToggleCharts: MouseEventHandler<HTMLElement> | undefined,
onToggleDiagram: () => void,
}): JSX.Element {
return (
<div id='header'>
<VSCodeDropdown value={props.state.selectedExtension} title='List of extensions using vscode-messenger.'>
{props.state.extensions.map((ext) => (
<VSCodeOption key={ext.id} value={ext.id} onClick={() => props.onExtensionSelected(ext.id)}>
{ext.name}
</VSCodeOption>
))}
</VSCodeDropdown>
<VSCodeButton className='refresh-button' appearance='icon' aria-label='Refresh Extension Data' onClick={props.onRefreshClicked}>
<span className='codicon codicon-refresh' title='Refresh' />
</VSCodeButton>
<VSCodeButton className='clear-button' appearance='icon' aria-label='Clear Data' onClick={() => props.onClearClicked(props.state.selectedExtension)}>
<span className='codicon codicon-trashcan' title='Clear Data' />
</VSCodeButton>
<VSCodeButton className='toggle-charts-button' appearance='icon' aria-label='Toggle Charts' onClick={props.onToggleCharts}>
<span className='codicon codicon-graph' title='Toggle Charts' />
</VSCodeButton>
<VSCodeButton className='toggle-diagram-button' appearance='icon' aria-label='Toggle Diagram' onClick={
() => {
props.onToggleDiagram();
}
}>
<span className='codicon codicon-type-hierarchy' title='Toggle Diagram' />
</VSCodeButton>
</div>
);
}
Loading

0 comments on commit d6b861a

Please sign in to comment.