Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: just schemagen improved with explicit yarn install step #102

Merged
merged 5 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions cmd/ui/src/components/GraphButton/GraphButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ const GraphButton: FC<GraphButtonProps> = ({ onClick, displayText, disabled }) =
const styles = useStyles();

return (
<Button
onClick={onClick}
disabled={disabled}
classes={{ root: styles.button }}>
<Button onClick={onClick} disabled={disabled} classes={{ root: styles.button }}>
{displayText}
</Button>
);
Expand Down
7 changes: 6 additions & 1 deletion cmd/ui/src/components/GraphButtons/GraphButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ const GraphButtons: FC<GraphButtonsProps> = ({ rankDirection, options, nonLayout
{nonLayoutButtons?.length && (
<>
{nonLayoutButtons.map((props, index) => (
<GraphButton key={index} onClick={props.onClick} displayText={props.displayText} disabled={props.disabled} />
<GraphButton
key={index}
onClick={props.onClick}
displayText={props.displayText}
disabled={props.disabled}
/>
))}
</>
)}
Expand Down
2 changes: 1 addition & 1 deletion cmd/ui/src/components/GraphEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export const GraphEvents: FC<GraphEventProps> = ({
setSelectedEdge(null);
setHighlightedNode(selectedNode.graphId);
}
}, [selectedNode])
}, [selectedNode]);

return null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { List, ListItem, ListItemText, Paper, TextField, useTheme } from '@mui/material';
import { useCombobox } from 'downshift';
import { useState } from 'react';
import { NodeIcon, SearchResultItem } from 'bh-shared-ui';
import { NodeIcon, SearchResultItem } from 'bh-shared-ui';
import { useDebouncedValue } from 'src/hooks/useDebouncedValue';
import { getEmptyResultsText, getKeywordAndTypeValues, SearchResult, useSearch } from 'src/hooks/useSearch';

Expand Down Expand Up @@ -124,7 +124,7 @@ const ExploreSearchCombobox: React.FC<{
item={{
label: item.name,
objectId: item.objectid,
kind: item.type
kind: item.type,
}}
index={index}
key={index}
Expand Down
7 changes: 2 additions & 5 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,12 @@ yarn-local *ARGS="":
@yarn {{ARGS}}

# run yarn commands in the context of the workspace root and rebuild containers
yarn *ARGS="":
yarn *ARGS="": && (bh-dev "build bh-ui")
@yarn {{ARGS}}
@just bh-dev build bh-ui

# run the code generation from the cue schema
schemagen:
schemagen: yarn-local && check-license (yarn "format")
go run github.com/specterops/bloodhound/schemagen
@just check-license
@just yarn format

# run imagemagick commands in the context of the project root
imagemagick *ARGS:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,42 @@
//
// SPDX-License-Identifier: Apache-2.0

import { fireEvent, render } from "@testing-library/react";
import SearchCurrentNodes, { NO_RESULTS_TEXT } from "./SearchCurrentNodes";
import { GraphNodes } from "./types";
import { fireEvent, render } from '@testing-library/react';
import SearchCurrentNodes, { NO_RESULTS_TEXT } from './SearchCurrentNodes';
import { GraphNodes } from './types';

const nodes: GraphNodes = {
'1': {
label: 'computer_node',
kind: 'Computer',
objectId: '001',
isTierZero: false,
lastSeen: ''
lastSeen: '',
},
'2': {
label: 'user_node',
kind: 'User',
objectId: '002',
isTierZero: false,
lastSeen: ''
lastSeen: '',
},
'3': {
label: 'group_node',
kind: 'Group',
objectId: '003',
isTierZero: false,
lastSeen: ''
}
}
lastSeen: '',
},
};

const RESULT_ID = 'explore_search_result-list-item';

describe("SearchCurrentNodes", () => {

describe('SearchCurrentNodes', () => {
const setup = () => {
const testOnSelect = vi.fn();
const testOnClose = vi.fn();
const screen = render(
<SearchCurrentNodes
currentNodes={nodes}
onSelect={testOnSelect}
onClose={testOnClose}
/>
<SearchCurrentNodes currentNodes={nodes} onSelect={testOnSelect} onClose={testOnClose} />
);

const input = screen.getByRole('textbox');
Expand All @@ -67,10 +62,10 @@ describe("SearchCurrentNodes", () => {
...screen,
input,
resultList,
setInputValue
}
}
setInputValue,
};
};

it('displays an autofocused text input', () => {
const { input } = setup();

Expand All @@ -87,7 +82,7 @@ describe("SearchCurrentNodes", () => {

it('displays expected results when searching by label', async () => {
const { resultList, setInputValue, queryByText, findAllByTestId } = setup();

setInputValue('node');
expect(resultList).toBeInTheDocument();
expect(queryByText(NO_RESULTS_TEXT)).not.toBeInTheDocument();
Expand All @@ -99,7 +94,7 @@ describe("SearchCurrentNodes", () => {

it('displays expected results when searching by objectid', async () => {
const { resultList, setInputValue, queryByText, findAllByTestId } = setup();

setInputValue('00');
expect(resultList).toBeInTheDocument();
expect(queryByText(NO_RESULTS_TEXT)).not.toBeInTheDocument();
Expand All @@ -109,7 +104,7 @@ describe("SearchCurrentNodes", () => {
expect(await findAllByTestId(RESULT_ID)).toHaveLength(1);
});

it('displays the label for each result', async () => {
it('displays the label for each result', async () => {
const { setInputValue, findByTestId } = setup();

setInputValue('002');
Expand All @@ -127,4 +122,4 @@ describe("SearchCurrentNodes", () => {
fireEvent.click(result);
expect(testOnSelect).toHaveBeenCalled();
});
})
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
//
// SPDX-License-Identifier: Apache-2.0

import { Box, List, ListItem, Paper, SxProps, TextField } from "@mui/material";
import { useCombobox } from "downshift";
import { FC, useEffect, useRef, useState } from "react";
import SearchResultItem from "../SearchResultItem";
import { FlatNode, GraphNodes } from "./types";
import { useOnClickOutside } from "../../hooks";
import { FixedSizeList } from "react-window";
import { Box, List, ListItem, Paper, SxProps, TextField } from '@mui/material';
import { useCombobox } from 'downshift';
import { FC, useEffect, useRef, useState } from 'react';
import SearchResultItem from '../SearchResultItem';
import { FlatNode, GraphNodes } from './types';
import { useOnClickOutside } from '../../hooks';
import { FixedSizeList } from 'react-window';

export const PLACEHOLDER_TEXT = "Search Current Results";
export const NO_RESULTS_TEXT = "No result found in current results";
export const PLACEHOLDER_TEXT = 'Search Current Results';
export const NO_RESULTS_TEXT = 'No result found in current results';

const LIST_ITEM_HEIGHT = 38;
const MAX_CONTAINER_HEIGHT = 350;
Expand All @@ -34,7 +34,6 @@ const SearchCurrentNodes: FC<{
onSelect: (node: FlatNode) => void;
onClose?: () => void;
}> = ({ sx, currentNodes, onSelect, onClose }) => {

const containerRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);

Expand All @@ -46,18 +45,18 @@ const SearchCurrentNodes: FC<{
// Node data is a lot easier to work with in the combobox if we transform to an array of flat objects
useEffect(() => {
const flatNodeList: FlatNode[] = Object.entries(currentNodes).map(([key, value]) => {
return { id: key, ...value }
return { id: key, ...value };
});
setFlatNodeList(flatNodeList);
}, [currentNodes])
}, [currentNodes]);

useEffect(() => inputRef.current?.focus(), []);

useEffect(() => {
if (selectedNode) onSelect(selectedNode);
}, [selectedNode, onSelect]);

// Since we are using a virtualized results container, we need to calculate the height for shorter
// Since we are using a virtualized results container, we need to calculate the height for shorter
// lists to avoid whitespace
useEffect(() => {
const resultsHeight = LIST_ITEM_HEIGHT * items.length;
Expand All @@ -73,7 +72,7 @@ const SearchCurrentNodes: FC<{
const { getInputProps, getMenuProps, getComboboxProps, getItemProps, inputValue } = useCombobox({
items,
onInputValueChange: ({ inputValue }) => {
const filteredNodes = flatNodeList.filter(node => {
const filteredNodes = flatNodeList.filter((node) => {
const label = node.label.toLowerCase();
const objectId = node.objectId.toLowerCase();
const lowercaseInputValue = inputValue?.toLowerCase() || '';
Expand All @@ -88,16 +87,16 @@ const SearchCurrentNodes: FC<{
switch (type) {
case useCombobox.stateChangeTypes.ItemClick:
if (changes.selectedItem) setSelectedNode(changes.selectedItem);
return { ...changes, inputValue: '' }
return { ...changes, inputValue: '' };
default:
return changes
return changes;
}
}
},
});

const Row = ({ index, style }: any) => {
return (
<Box style={style} overflow={"hidden"}>
<Box style={style} overflow={'hidden'}>
<SearchResultItem
item={items[index]}
index={index}
Expand All @@ -107,40 +106,48 @@ const SearchCurrentNodes: FC<{
getItemProps={getItemProps}
/>
</Box>
)
}
);
};

return (
<div ref={containerRef}>
<Box component={Paper} {...sx} {...getComboboxProps()}>
<Box overflow={"auto"} maxHeight={MAX_CONTAINER_HEIGHT} marginBottom={items.length === 0 ? 0 : 1}>
<List data-testid={"current-results-list"} dense {...getMenuProps({
hidden: items.length === 0 && !inputValue,
style: { paddingTop: 0 }
})}>
{<FixedSizeList
height={virtualizationHeight}
width={"100%"}
itemSize={LIST_ITEM_HEIGHT}
itemCount={items.length}
>
{Row}
</FixedSizeList>}
{items.length === 0 && inputValue && <ListItem disabled sx={{ fontSize: 14 }}>{NO_RESULTS_TEXT}</ListItem>}
<Box overflow={'auto'} maxHeight={MAX_CONTAINER_HEIGHT} marginBottom={items.length === 0 ? 0 : 1}>
<List
data-testid={'current-results-list'}
dense
{...getMenuProps({
hidden: items.length === 0 && !inputValue,
style: { paddingTop: 0 },
})}>
{
<FixedSizeList
height={virtualizationHeight}
width={'100%'}
itemSize={LIST_ITEM_HEIGHT}
itemCount={items.length}>
{Row}
</FixedSizeList>
}
{items.length === 0 && inputValue && (
<ListItem disabled sx={{ fontSize: 14 }}>
{NO_RESULTS_TEXT}
</ListItem>
)}
</List>
</Box>
<TextField
inputRef={inputRef}
placeholder={PLACEHOLDER_TEXT}
variant="outlined"
size="small"
variant='outlined'
size='small'
fullWidth
{...getInputProps()}
InputProps={{ sx: { fontSize: 14 } }}
/>
</Box>
</div>
);
}
};

export default SearchCurrentNodes;
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@
//
// SPDX-License-Identifier: Apache-2.0

import { FC } from "react";
import { Box, ListItem, ListItemText } from "@mui/material";
import HighlightedText from "../HighlightedText";
import NodeIcon from "../NodeIcon";
import { FC } from 'react';
import { Box, ListItem, ListItemText } from '@mui/material';
import HighlightedText from '../HighlightedText';
import NodeIcon from '../NodeIcon';

type NodeSearchResult = {
label: string;
objectId: string;
kind: string;
}
};

const SearchResultItem: FC<{
item: NodeSearchResult;
index: number;
highlightedIndex?: number;
keyword: string;
getItemProps: (options: any) => any
getItemProps: (options: any) => any;
}> = ({ item, index, highlightedIndex, keyword, getItemProps }) => {
return (
<ListItem
Expand All @@ -54,10 +54,7 @@ const SearchResultItem: FC<{
flexGrow: 1,
marginRight: '1em',
}}>
<HighlightedText
text={item.label || item.objectId}
search={keyword}
/>
<HighlightedText text={item.label || item.objectId} search={keyword} />
</Box>
</Box>
}
Expand All @@ -70,6 +67,6 @@ const SearchResultItem: FC<{
/>
</ListItem>
);
}
};

export default SearchResultItem;
Loading