react-virtualized#List TypeScript Examples
The following examples show how to use
react-virtualized#List.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: VirtualizedList.tsx From symphony-ui-toolkit with Apache License 2.0 | 6 votes |
VirtualizedList: React.FC<ListProps> = ({
width,
height,
rowCount,
rowHeight,
rowRenderer,
...rest
}: ListProps) => {
return (
<List
rowCount={rowCount}
rowHeight={rowHeight}
width={width}
height={height}
rowRenderer={rowRenderer}
{...rest}
/>
);
}
Example #2
Source File: list.tsx From gio-design with Apache License 2.0 | 6 votes |
private renderList = () => {
const { height, disabledOptions, rowHeight, options, value, prefixCls } = this.props;
const getRowHeight = ({ index }: { index: number }) => {
if (typeof rowHeight === 'function') {
return rowHeight(options[index]);
}
return rowHeight;
};
return (
<AutoSizer style={{ width: '100%', height: '100%' }}>
{({ width }) => (
<List
value={value}
width={width}
height={2000}
style={{ height: height || '100%', overflow: 'auto', marginBottom: '-4px' }}
rowCount={options.length}
rowHeight={typeof rowHeight === 'function' ? getRowHeight : this._cache.rowHeight}
deferredMeasurementCache={this._cache}
rowRenderer={this.renderListItem(options)}
disabledOptions={disabledOptions}
className={`${prefixCls}-list`}
/>
)}
</AutoSizer>
);
};
Example #3
Source File: LogViewer.tsx From kfp-tekton-backend with Apache License 2.0 | 6 votes |
public render(): JSX.Element {
return (
<AutoSizer>
{({ height, width }) => (
<List
id='logViewer'
containerStyle={listContainerStyleOverride}
width={width}
height={height}
rowCount={this.props.logLines.length}
rowHeight={15}
className={css.root}
ref={this._rootRef}
overscanIndicesGetter={overscanOnBothDirections}
overscanRowCount={
400 /* make this large, so selecting maximum 400 lines is supported */
}
rowRenderer={this._rowRenderer.bind(this)}
onScroll={this.handleScroll}
/>
)}
</AutoSizer>
);
}
Example #4
Source File: LogViewer.tsx From kfp-tekton-backend with Apache License 2.0 | 5 votes |
private _rootRef = React.createRef<List>();
Example #5
Source File: IconList.tsx From iconsax-react with MIT License | 5 votes |
IconList = () => {
const [filtered, setFiltered] = useState<IIconsArray[]>(icons)
const [numColumns, setNumColumns] = useState(1)
const query = searchStore((state) => state.query)
const onResize = ({ width }: { width: number }) => {
if (width <= 576) {
setNumColumns(Math.floor(width / ICON_CONTAINER_SIZE))
} else {
setNumColumns(Math.floor(width / ICON_CONTAINER_SIZE))
}
}
useEffect(() => {
console.log(query)
const f =
icons.filter((x) =>
x.name.toLowerCase().includes(query!.toLowerCase())
) || []
setFiltered(f)
}, [query])
return (
<div className="container flex justify-center m-auto min-h-[400px]">
<div className="w-full relative mb-10">
{filtered.length > 0 ? (
<WindowScroller>
{({ height, isScrolling, onChildScroll, scrollTop }) => (
<AutoSizer disableHeight onResize={onResize}>
{({ width }) => (
<List
tabIndex={-1}
autoHeight
width={width}
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
scrollTop={scrollTop}
rowCount={Math.ceil(filtered.length / numColumns)}
rowHeight={ICON_CONTAINER_SIZE + 10}
rowRenderer={({ key, index: rowIndex, style }) => (
<div
key={key}
className="grid place-items-center"
style={{
...style,
gridTemplateColumns: `repeat(${numColumns}, 1fr)`,
}}
>
{Array.from(
{ length: numColumns },
(_, columnIndex) => {
const icon =
filtered[rowIndex * numColumns + columnIndex]
if (!icon) {
return null
}
return (
<IconItem name={icon.name} Icon={icon.Icon} />
)
}
)}
</div>
)}
/>
)}
</AutoSizer>
)}
</WindowScroller>
) : (
<Empty />
)}
</div>
</div>
)
}
Example #6
Source File: SearchResults.tsx From yana with MIT License | 5 votes |
SearchResults: React.FC<{
onClickItem?: (item: DataItem) => void;
hideItemIds: string[];
hiddenSearch: SearchQuery;
}> = props => {
const search = useSearchBar();
const searchResult = useDataSearch({ ...search.searchQuery, ...props.hiddenSearch }, 30);
const items = searchResult.items.filter(i => !props.hideItemIds.includes(i.id));
return (
<AutoSizer>
{({ width, height }) => {
return (
<List
rowCount={items.length + (searchResult.nextPageAvailable ? 50 : 0)}
rowHeight={OVERLAY_SEARCH_ITEM_HEIGHT}
width={width}
height={height}
containerStyle={{ paddingRight: '10px' }}
rowRenderer={cellProps => {
const itemId = cellProps.index;
if (itemId >= items.length) {
if (searchResult.nextPageAvailable) {
searchResult.fetchNextPage();
return (
<ResultItem
key={cellProps.key}
containerStyle={cellProps.style}
icon={<Spinner size={16} />}
title="Loading..."
meta=""
/>
);
} else {
return null;
}
}
const item = items[itemId];
return (
<ResultItem
key={cellProps.key}
containerStyle={cellProps.style}
icon={(item.icon || (item.kind === DataItemKind.Collection ? 'folder-open' : 'document')) as any}
title={item.name}
meta={ago(new Date(item.lastChange))}
onClick={() => props.onClickItem?.(item)}
dataItem={item}
/>
);
}}
/>
);
}}
</AutoSizer>
);
}
Example #7
Source File: BatchList.tsx From lightning-terminal with MIT License | 5 votes |
BatchList: React.FC = () => {
const { batchStore } = useStore();
const { Wrapper, Content, More } = Styled;
return (
<Wrapper>
<BatchRowHeader />
<Content>
<AutoSizer>
{({ width, height }) => (
<Observer>
{() => (
<List
rowCount={batchStore.sortedBatches.length}
rowHeight={ROW_HEIGHT}
rowRenderer={({ index, key, style }) => (
<BatchRow
key={key}
style={style}
batch={batchStore.sortedBatches[index]}
/>
)}
width={width}
height={height}
/>
)}
</Observer>
)}
</AutoSizer>
</Content>
{batchStore.hasMoreBatches && (
<More>
{batchStore.loading ? (
<LoaderLines />
) : (
<Button
borderless
ghost
onClick={batchStore.fetchBatches}
disabled={batchStore.loading}
>
Load Older Batches
</Button>
)}
</More>
)}
</Wrapper>
);
}
Example #8
Source File: ChannelList.tsx From lightning-terminal with MIT License | 5 votes |
ChannelList: React.FC = () => {
const { buildSwapView } = useStore();
const { Wrapper, ListContainer } = Styled;
return (
<Wrapper data-tour="channel-list">
<ChannelRowHeader />
<ListContainer>
<AutoSizer disableHeight>
{({ width }) => (
<WindowScroller>
{({ height, isScrolling, onChildScroll, scrollTop, registerChild }) => (
<Observer>
{() => (
<div ref={ref => ref && registerChild(ref)}>
<List
autoHeight
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
rowCount={buildSwapView.channels.length}
rowHeight={ROW_HEIGHT}
rowRenderer={({ index, key, style }) => (
<ChannelRow
key={key}
style={style}
channel={buildSwapView.channels[index]}
/>
)}
scrollTop={scrollTop}
width={width}
/>
</div>
)}
</Observer>
)}
</WindowScroller>
)}
</AutoSizer>
</ListContainer>
</Wrapper>
);
}
Example #9
Source File: HistoryList.tsx From lightning-terminal with MIT License | 5 votes |
HistoryList: React.FC = () => {
const { swapStore } = useStore();
const { Wrapper } = Styled;
return (
<Wrapper>
<HistoryRowHeader />
<ListContainer>
<AutoSizer disableHeight>
{({ width }) => (
<WindowScroller>
{({ height, isScrolling, onChildScroll, scrollTop, registerChild }) => (
<Observer>
{() => (
<div ref={ref => ref && registerChild(ref)}>
<List
autoHeight
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
rowCount={swapStore.sortedSwaps.length}
rowHeight={ROW_HEIGHT}
rowRenderer={({ index, key, style }) => (
<HistoryRow
key={key}
style={style}
swap={swapStore.sortedSwaps[index]}
/>
)}
scrollTop={scrollTop}
width={width}
/>
</div>
)}
</Observer>
)}
</WindowScroller>
)}
</AutoSizer>
</ListContainer>
</Wrapper>
);
}
Example #10
Source File: SessionList.tsx From lightning-terminal with MIT License | 5 votes |
SessionList: React.FC = () => {
const { sessionStore } = useStore();
if (sessionStore.sortedSessions.length === 0) return null;
const { Wrapper } = Styled;
return (
<Wrapper>
<SessionRowHeader />
<ListContainer>
<AutoSizer disableHeight>
{({ width }) => (
<WindowScroller>
{({ height, isScrolling, onChildScroll, scrollTop, registerChild }) => (
<Observer>
{() => (
<div ref={ref => ref && registerChild(ref)}>
<List
autoHeight
height={height}
isScrolling={isScrolling}
onScroll={onChildScroll}
rowCount={sessionStore.sortedSessions.length}
rowHeight={ROW_HEIGHT}
rowRenderer={({ index, key, style }) => (
<SessionRow
key={key}
style={style}
session={sessionStore.sortedSessions[index]}
/>
)}
scrollTop={scrollTop}
width={width}
/>
</div>
)}
</Observer>
)}
</WindowScroller>
)}
</AutoSizer>
</ListContainer>
</Wrapper>
);
}
Example #11
Source File: TransactionInfiniteList.tsx From End-to-End-Web-Testing-with-Cypress with MIT License | 5 votes |
TransactionInfiniteList: React.FC<TransactionListProps> = ({
transactions,
loadNextPage,
pagination,
}) => {
const classes = useStyles();
const theme = useTheme();
const isXsBreakpoint = useMediaQuery(theme.breakpoints.down("xs"));
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const itemCount = pagination.hasNextPages ? transactions.length + 1 : transactions.length;
const loadMoreItems = () => {
return new Promise((resolve) => {
return resolve(pagination.hasNextPages && loadNextPage(pagination.page + 1));
});
};
const isRowLoaded = (params: Index) =>
!pagination.hasNextPages || params.index < transactions.length;
// @ts-ignore
function rowRenderer({ key, index, style }) {
const transaction = get(index, transactions);
if (index < transactions.length) {
return (
<div key={key} style={style}>
<TransactionItem transaction={transaction} />
<Divider variant={isMobile ? "fullWidth" : "inset"} />
</div>
);
}
}
return (
<InfiniteLoader
isRowLoaded={isRowLoaded}
loadMoreRows={loadMoreItems}
rowCount={itemCount}
threshold={2}
>
{({ onRowsRendered, registerChild }) => (
<div data-test="transaction-list" className={classes.transactionList}>
<List
rowCount={itemCount}
ref={registerChild}
onRowsRendered={onRowsRendered}
height={isXsBreakpoint ? theme.spacing(74) : theme.spacing(88)}
width={isXsBreakpoint ? theme.spacing(38) : theme.spacing(110)}
rowHeight={isXsBreakpoint ? theme.spacing(28) : theme.spacing(16)}
rowRenderer={rowRenderer}
/>
</div>
)}
</InfiniteLoader>
);
}
Example #12
Source File: index.tsx From metaflow-ui with Apache License 2.0 | 4 votes |
LogList: React.FC<LogProps> = ({ logdata, fixedHeight, onScroll, downloadUrl, setFullscreen }) => {
const { timezone } = useContext(TimezoneContext);
const { t } = useTranslation();
const rows = logdata.logs;
const [stickBottom, setStickBottom] = useState(true);
const [cache] = useState(
new CellMeasurerCache({
fixedWidth: true,
minHeight: 25,
}),
);
const _list = useRef<List>(null);
const search = logdata.localSearch;
const count = rows.length;
const okCount = rows.reduce((okAmount, item) => {
return typeof item === 'object' ? okAmount + 1 : okAmount;
}, 0);
const totalHeight = rows.reduce((val, _item, index) => {
return val + (cache.getHeight(index, 0) || 0);
}, 0);
// Clear cached row heights on window resize events
useEffect(() => {
const listener = () => {
cache.clearAll();
};
window.addEventListener('resize', listener);
return () => window.removeEventListener('resize', listener);
}, []); // eslint-disable-line
// Force row height calculations after fetch ok
useEffect(() => {
if (_list?.current) {
cache.clearAll();
_list.current.recomputeRowHeights();
}
}, [okCount]); // eslint-disable-line
useEffect(() => {
if (stickBottom && _list) {
_list.current?.scrollToRow(count);
}
}, [count, okCount, stickBottom]);
//
// Index tracking
//
const [scrollIndex, setIndex] = useState(0);
const [debouncedIndex] = useDebounce(scrollIndex, 300);
useEffect(() => {
if (onScroll && !stickBottom) {
onScroll(debouncedIndex);
}
}, [debouncedIndex, onScroll]); // eslint-disable-line
//
// Search features
//
const searchActive = search.result.active;
const searchCurrent = search.result.current;
const searchQuery = search.result.query;
useEffect(() => {
if (searchActive && search.result.result[searchCurrent]) {
_list.current?.scrollToRow(search.result.result[searchCurrent].line);
}
}, [searchActive, searchCurrent, searchQuery]); //eslint-disable-line
return (
<div style={{ flex: '1 1 0' }} data-testid="loglist-wrapper">
<LogActionBar
data={logdata.logs}
downloadlink={downloadUrl}
setFullscreen={setFullscreen}
search={logdata.localSearch}
spaceAround={!!fixedHeight}
/>
{rows.length === 0 && ['Ok', 'Error'].includes(logdata.preloadStatus) && logdata.status === 'NotAsked' && (
<div data-testid="loglist-preload-empty">{t('task.no-preload-logs')}</div>
)}
{rows.length === 0 && logdata.status === 'Ok' && <div data-testid="loglist-empty">{t('task.no-logs')}</div>}
{rows.length > 0 && (
<LogListContainer data-testid="loglist-container">
<AutoSizer disableHeight>
{({ width }) => (
<List
ref={_list}
overscanRowCount={5}
rowCount={rows.length}
rowHeight={cache.rowHeight}
onRowsRendered={(data) => {
if (onScroll) {
setIndex(data.overscanStartIndex);
}
}}
deferredMeasurementCache={cache}
onScroll={(args: { scrollTop: number; clientHeight: number; scrollHeight: number }) => {
if (args.scrollTop + args.clientHeight >= args.scrollHeight) {
setStickBottom(true);
} else if (stickBottom) {
setStickBottom(false);
}
}}
rowRenderer={({ index, style, key, parent }) => (
<CellMeasurer cache={cache} columnIndex={0} key={key} rowIndex={index} parent={parent}>
{() => {
const item = rows[index];
return (
<LogLine style={style} data-testid="log-line">
<LogLineNumber className="logline-number">{index}</LogLineNumber>
{getTimestamp(item, timezone)}
<LogLineText>
{typeof item === 'object' ? getLineText(item as Log, search.result) : 'Loading...'}
</LogLineText>
</LogLine>
);
}}
</CellMeasurer>
)}
height={fixedHeight ? fixedHeight - 16 : totalHeight < LIST_MAX_HEIGHT ? totalHeight : LIST_MAX_HEIGHT}
width={width}
/>
)}
</AutoSizer>
{!stickBottom && (
<ScrollToBottomButton onClick={() => setStickBottom(true)} data-testid="loglist-stick-bottom">
{t('run.scroll-to-bottom')}
</ScrollToBottomButton>
)}
<PollLoader status={logdata.status} preloadStatus={logdata.preloadStatus} />
</LogListContainer>
)}
</div>
);
}
Example #13
Source File: index.tsx From yasd with MIT License | 4 votes |
Page: React.FC = () => {
const { setModal } = useModal()
const { t } = useTranslation()
const profile = useProfile()
const [isAutoRefresh, setIsAutoRefresh] = useState<boolean>(true)
const [group, setGroup] = useState<'recent' | 'active'>('recent')
const { data: recentRequestsResponse, error: requestsError } =
useSWR<RecentRequests>(() => '/requests/' + group, fetcher, {
revalidateOnFocus: false,
revalidateOnReconnect: false,
dedupingInterval: 1000,
refreshInterval: isAutoRefresh
? profile?.platform === 'macos'
? 2000
: 4000
: 0,
})
const [requestList, setRequestList] = useState<Array<RequestItem>>([])
const [activeRequestList, setActiveRequestList] = useState<
Array<RequestItem>
>([])
const currentList = useMemo(
() => (group === 'recent' ? requestList : activeRequestList),
[group, requestList, activeRequestList],
)
const query = useQuery()
const sourceIp = useMemo<string | null>(() => query.get('source'), [query])
useEffect(
() => {
if (!recentRequestsResponse?.requests) return
const pendingList = [...recentRequestsResponse.requests]
const now = new Date()
let newList = [...currentList]
while (pendingList.length) {
const request = pendingList.pop() as RequestItem
const existingIndex = newList.findIndex(
(item) => item.id === request.id,
)
if (existingIndex >= 0) {
Object.assign(newList[existingIndex], {
...omit(request, ['id']),
lastUpdated: now,
})
} else {
if (newList.length && request.id > newList[0].id) {
newList.unshift({
...request,
lastUpdated: now,
})
} else {
newList.push({
...request,
lastUpdated: now,
})
}
}
}
if (group === 'recent') {
newList = newList
.filter((request) => {
if (sourceIp) {
return sourceIp === request.sourceAddress
}
return true
})
.slice(0, LIST_ITEMS_MAX)
} else {
newList = newList
.filter((request) => {
if (sourceIp) {
return (
request.lastUpdated === now &&
sourceIp === request.sourceAddress
)
}
return request.lastUpdated === now
})
.sort((a, b) => b.id - a.id)
}
if (group === 'recent') {
setRequestList(newList)
setActiveRequestList([])
} else {
setRequestList([])
setActiveRequestList(newList)
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[recentRequestsResponse, group, sourceIp],
)
const openRequestDetail = useCallback(
(req: RequestItem) => {
setModal({
children({ onClose }) {
return onClose ? (
<RequestModal req={req} onClose={onClose} />
) : (
<React.Fragment />
)
},
onClose() {
// noop
},
})
},
[setModal],
)
const rowRenderer: ListRowRenderer = useCallback(
({
key, // Unique key within array of rows
index, // Index of row within collection
isScrolling, // The List is currently being scrolled
isVisible, // This row is visible within the List (eg it is not an overscanned row)
style, // Style object to be applied to row (to position it)
}) => {
const req = currentList[index]
return (
<div
key={key}
style={style}
onClick={() => openRequestDetail(req)}
tw="flex flex-col justify-center py-2 cursor-pointer hover:bg-gray-100"
css={css`
padding-left: calc(env(safe-area-inset-left) + 0.75rem);
padding-right: calc(env(safe-area-inset-right) + 0.75rem);
`}
>
<ListItem req={req} />
</div>
)
},
[currentList, openRequestDetail],
)
return (
<FixedFullscreenContainer>
<React.Fragment>
<PageTitle
title={t('home.requests')}
hasAutoRefresh={true}
defaultAutoRefreshState={true}
onAuthRefreshStateChange={(newState) => setIsAutoRefresh(newState)}
/>
<div tw="flex-1">
{recentRequestsResponse ? (
currentList.length ? (
<AutoSizer>
{({ width, height }) => {
return (
<List
width={width}
height={height}
rowCount={currentList.length}
rowHeight={64}
rowRenderer={rowRenderer}
style={{
outline: 'none',
}}
css={css`
& > div {
${tw`divide-y divide-gray-200`}
}
`}
/>
)
}}
</AutoSizer>
) : (
<div tw="h-full flex items-center justify-center text-base text-gray-500">
{t('common.no_data')}
</div>
)
) : (
<div tw="h-full flex items-center justify-center text-base text-gray-500">
{t('common.is_loading')}...
</div>
)}
</div>
<div
css={[
tw`flex divide-x divide-gray-200 border-t border-solid border-gray-200 py-2 px-2`,
css`
& > div {
${tw`mx-2`}
}
& > div:first-of-type {
margin-left: 0;
}
`,
]}
>
<SelectorGroup
css={[
tw`flex justify-center items-center`,
css`
& label {
${tw`py-2 px-4 ml-2 my-1 text-sm`}
}
& label:first-of-type {
margin-left: 0;
}
`,
]}
label="choose the dns result group"
name="selector-group"
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setGroup(() => {
const newState = event.target.value as 'recent' | 'active'
mutate('/requests/' + newState)
return newState
})
}}
options={[
{
children: t('requests.recent'),
value: 'recent',
},
{
children: t('requests.active'),
value: 'active',
},
]}
value={group}
/>
</div>
</React.Fragment>
</FixedFullscreenContainer>
)
}
Example #14
Source File: index.tsx From yasd with MIT License | 4 votes |
Page: React.FC = () => {
const { t } = useTranslation()
const [group, setGroup] = useState<'dynamic' | 'static'>('dynamic')
const { data: dnsResult, error: dnsResultError } = useSWR<DnsResult>(
'/dns',
fetcher,
)
const list = useMemo(() => {
if (group === 'dynamic') {
return dnsResult?.dnsCache ?? []
}
return dnsResult?.local ?? []
}, [dnsResult, group])
const flushDns: MouseEventHandler = () => {
fetcher({
url: '/dns/flush',
method: 'POST',
})
.then(() => {
toast.success(t('common.success_interaction'))
return mutate('/dns')
})
.catch((err) => {
toast.error(t('common.failed_interaction'))
console.error(err)
})
}
const openIpDetail = (ip: string) => {
window.open(`https://ip.sb/ip/${ip}`, '_blank', 'noopener noreferrer')
}
const rowRenderer: ListRowRenderer = useCallback(
({
key, // Unique key within array of rows
index, // Index of row within collection
isScrolling, // The List is currently being scrolled
isVisible, // This row is visible within the List (eg it is not an overscanned row)
style, // Style object to be applied to row (to position it)
}) => {
if (group === 'dynamic') {
const record = (list as DnsResult['dnsCache'])[index]
return (
<div
key={key}
style={style}
onClick={() => openIpDetail(record.data[0])}
css={[
tw`flex flex-col justify-center py-2`,
tw`cursor-pointer hover:bg-gray-100`,
css`
padding-left: calc(env(safe-area-inset-left) + 0.75rem);
padding-right: calc(env(safe-area-inset-right) + 0.75rem);
`,
]}
>
<div tw="text-sm truncate">{record.domain}</div>
<div tw="text-xs text-gray-700 leading-tight">
DNS: {record.server}
</div>
<div tw="text-xs text-gray-700 leading-tight truncate">
{t('dns.result')}: {record.data.join(', ')}
</div>
<div tw="text-xs text-gray-700 leading-tight truncate">
{t('dns.path')}: {record.path}
</div>
</div>
)
} else {
const record = (list as DnsResult['local'])[index]
return (
<div
key={key}
style={style}
css={[
tw`flex flex-col justify-center py-2`,
css`
padding-left: calc(env(safe-area-inset-left) + 0.75rem);
padding-right: calc(env(safe-area-inset-right) + 0.75rem);
`,
]}
>
<div tw="text-sm truncate">{record.domain}</div>
{!!record.server && (
<div tw="text-xs text-gray-700 leading-tight">
DNS: {record.server}
</div>
)}
<div tw="text-xs text-gray-700 leading-tight">
{t('dns.result')}: {record.data ?? 'N/A'}
</div>
<div tw="text-xs text-gray-700 leading-tight">
{t('dns.source')}: {record.source ?? 'N/A'}
</div>
{!!record.comment && (
<div tw="text-xs text-gray-700 leading-tight">
{t('dns.comment')}: {record.comment}
</div>
)}
</div>
)
}
},
[group, list],
)
return (
<FixedFullscreenContainer>
<PageTitle title="DNS" />
<div tw="flex-1">
<AutoSizer>
{({ width, height }) => {
return (
<List
width={width}
height={height}
rowCount={list.length}
rowHeight={85}
rowRenderer={rowRenderer}
style={{
outline: 'none',
}}
css={css`
& > div {
${tw`divide-y divide-gray-200`}
}
`}
/>
)
}}
</AutoSizer>
</div>
<div
css={[
tw`flex divide-x divide-gray-200 border-t border-solid border-gray-200 py-2 px-2`,
css`
& > div {
${tw`mx-2`}
}
& > div:first-of-type {
margin-left: 0;
}
`,
]}
>
<SelectorGroup
css={[
tw`flex justify-center items-center`,
css`
& label {
${tw`py-2 px-4 ml-2 my-1 text-sm`}
}
& label:first-of-type {
margin-left: 0;
}
`,
]}
label="choose the dns result group"
name="selector-group"
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setGroup(event.target.value as 'dynamic' | 'static')
}}
options={[
{
children: t('dns.dynamic'),
value: 'dynamic',
},
{
children: t('dns.static'),
value: 'static',
},
]}
value={group}
/>
<div tw="flex items-center">
<Button
tw="font-normal"
variant="tertiary"
size="kilo"
onClick={flushDns}
>
{t('dns.flush_dns')}
</Button>
</div>
</div>
</FixedFullscreenContainer>
)
}
Example #15
Source File: TaskList.tsx From metaflow-ui with Apache License 2.0 | 4 votes |
TaskList: React.FC<Props> = ({
rows,
rowDataDispatch,
taskStatus,
activeTaskId,
results,
grouped,
paramsString,
}) => {
const [viewScrollTop, setScrollTop] = useState(0);
const ref = useRef<HTMLDivElement>(null);
const { t } = useTranslation();
useEffect(() => {
const listener = () => {
setScrollTop(window.scrollY);
};
window.addEventListener('scroll', listener);
return () => window.removeEventListener('scroll', listener);
}, []);
const listSize = ref?.current
? window.innerHeight -
(viewScrollTop + 25 > ref.current.offsetTop ? HEADER_SIZE_PX + 25 : ref.current.offsetTop - viewScrollTop + 25)
: 0;
return (
<TaskListContainer ref={ref}>
<FixedList style={{ position: 'sticky', top: HEADER_SIZE_PX + 'px' }}>
{rows.length > 0 && (
<List
overscanRowCount={5}
rowCount={rows.length}
rowHeight={toRelativeSize(28)}
rowRenderer={({ index, style }) => {
const item = rows[index];
return (
<TaskListRow
key={index}
index={index}
style={style}
item={item}
grouped={grouped}
paramsString={paramsString}
duration={
item.type === 'step'
? getStepDuration(item.data, item.rowObject.status, item.rowObject.duration)
: item.data[item.data.length - 1].duration || null
}
toggle={
item.type === 'step'
? () => (item.data ? rowDataDispatch({ type: 'toggle', id: item.data.step_name }) : null)
: undefined
}
active={item.type === 'task' && getTaskId(item.data[0]) === activeTaskId}
isOpen={item.type === 'step' && item.rowObject.isOpen}
/>
);
}}
height={listSize}
width={toRelativeSize(245)}
/>
)}
{/* Search ok, no results */}
{rows.length === 0 && results.status === 'Ok' && (
<div style={{ padding: '1rem 0' }}>{t('search.no-results')}</div>
)}
{/* Not searched, no more loading, no results -> Not tasks message */}
{rows.length === 0 && results.status === 'NotAsked' && taskStatus !== 'Loading' && (
<div style={{ padding: '1rem 0' }}>{t('search.no-tasks')}</div>
)}
{/* No rows, still loading more */}
{rows.length === 0 && taskStatus === 'Loading' && (
<div style={{ padding: '1rem 0', display: 'flex', justifyContent: 'center' }}>
<Spinner sm />
</div>
)}
</FixedList>
</TaskListContainer>
);
}
Example #16
Source File: VersionsNavigator.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
VersionsNavigator = ({
classes,
internalPaths,
bucketName,
}: IVersionsNavigatorProps) => {
const dispatch = useDispatch();
const searchVersions = useSelector(
(state: AppState) => state.objectBrowser.searchVersions
);
const loadingVersions = useSelector(
(state: AppState) => state.objectBrowser.loadingVersions
);
const selectedVersion = useSelector(
(state: AppState) => state.objectBrowser.selectedVersion
);
const distributedSetup = useSelector(selDistSet);
const [shareFileModalOpen, setShareFileModalOpen] = useState<boolean>(false);
const [actualInfo, setActualInfo] = useState<IFileInfo | null>(null);
const [objectToShare, setObjectToShare] = useState<IFileInfo | null>(null);
const [versions, setVersions] = useState<IFileInfo[]>([]);
const [restoreVersionOpen, setRestoreVersionOpen] = useState<boolean>(false);
const [restoreVersion, setRestoreVersion] = useState<string>("");
const [sortValue, setSortValue] = useState<string>("date");
const [previewOpen, setPreviewOpen] = useState<boolean>(false);
const [deleteNonCurrentOpen, setDeleteNonCurrentOpen] =
useState<boolean>(false);
const [selectEnabled, setSelectEnabled] = useState<boolean>(false);
const [selectedItems, setSelectedItems] = useState<string[]>([]);
const [delSelectedVOpen, setDelSelectedVOpen] = useState<boolean>(false);
// calculate object name to display
let objectNameArray: string[] = [];
if (actualInfo) {
objectNameArray = actualInfo.name.split("/");
}
useEffect(() => {
if (!loadingVersions && !actualInfo) {
dispatch(setLoadingVersions(true));
}
}, [loadingVersions, actualInfo, dispatch]);
useEffect(() => {
if (loadingVersions && internalPaths !== "") {
api
.invoke(
"GET",
`/api/v1/buckets/${bucketName}/objects?prefix=${internalPaths}${
distributedSetup ? "&with_versions=true" : ""
}`
)
.then((res: IFileInfo[]) => {
const result = get(res, "objects", []);
if (distributedSetup) {
setActualInfo(
result.find((el: IFileInfo) => el.is_latest) || emptyFile
);
setVersions(result);
} else {
setActualInfo(result[0]);
setVersions([]);
}
dispatch(setLoadingVersions(false));
})
.catch((err: ErrorResponseHandler) => {
dispatch(setErrorSnackMessage(err));
dispatch(setLoadingVersions(false));
});
}
}, [loadingVersions, bucketName, internalPaths, dispatch, distributedSetup]);
const shareObject = () => {
setShareFileModalOpen(true);
};
const closeShareModal = () => {
setObjectToShare(null);
setShareFileModalOpen(false);
setPreviewOpen(false);
};
const downloadObject = (object: IFileInfo) => {
const identityDownload = encodeURLString(
`${bucketName}-${object.name}-${new Date().getTime()}-${Math.random()}`
);
const downloadCall = download(
bucketName,
internalPaths,
object.version_id,
parseInt(object.size || "0"),
(progress) => {
dispatch(
updateProgress({
instanceID: identityDownload,
progress: progress,
})
);
},
() => {
dispatch(completeObject(identityDownload));
},
() => {
dispatch(failObject(identityDownload));
},
() => {
dispatch(cancelObjectInList(identityDownload));
}
);
const ID = makeid(8);
storeCallForObjectWithID(ID, downloadCall);
dispatch(
setNewObject({
ID,
bucketName,
done: false,
instanceID: identityDownload,
percentage: 0,
prefix: object.name,
type: "download",
waitingForFile: true,
failed: false,
cancelled: false,
})
);
downloadCall.send();
};
const onShareItem = (item: IFileInfo) => {
setObjectToShare(item);
shareObject();
};
const onPreviewItem = (item: IFileInfo) => {
setObjectToShare(item);
setPreviewOpen(true);
};
const onRestoreItem = (item: IFileInfo) => {
setRestoreVersion(item.version_id || "");
setRestoreVersionOpen(true);
};
const onDownloadItem = (item: IFileInfo) => {
downloadObject(item);
};
const onGlobalClick = (item: IFileInfo) => {
dispatch(setSelectedVersion(item.version_id || ""));
};
const filteredRecords = versions.filter((version) => {
if (version.version_id) {
return version.version_id.includes(searchVersions);
}
return false;
});
const closeRestoreModal = (reloadObjectData: boolean) => {
setRestoreVersionOpen(false);
setRestoreVersion("");
if (reloadObjectData) {
dispatch(setLoadingVersions(true));
dispatch(setLoadingObjectInfo(true));
}
};
const closeDeleteNonCurrent = (reloadAfterDelete: boolean) => {
setDeleteNonCurrentOpen(false);
if (reloadAfterDelete) {
dispatch(setLoadingVersions(true));
dispatch(setSelectedVersion(""));
dispatch(setLoadingObjectInfo(true));
}
};
const closeSelectedVersions = (reloadOnComplete: boolean) => {
setDelSelectedVOpen(false);
if (reloadOnComplete) {
dispatch(setLoadingVersions(true));
dispatch(setSelectedVersion(""));
dispatch(setLoadingObjectInfo(true));
setSelectedItems([]);
}
};
const totalSpace = versions.reduce((acc: number, currValue: IFileInfo) => {
if (currValue.size) {
return acc + parseInt(currValue.size);
}
return acc;
}, 0);
filteredRecords.sort((a, b) => {
switch (sortValue) {
case "size":
if (a.size && b.size) {
if (a.size < b.size) {
return -1;
}
if (a.size > b.size) {
return 1;
}
return 0;
}
return 0;
default:
const dateA = new Date(a.last_modified).getTime();
const dateB = new Date(b.last_modified).getTime();
if (dateA < dateB) {
return 1;
}
if (dateA > dateB) {
return -1;
}
return 0;
}
});
const onCheckVersion = (selectedVersion: string) => {
if (selectedItems.includes(selectedVersion)) {
const filteredItems = selectedItems.filter(
(element) => element !== selectedVersion
);
setSelectedItems(filteredItems);
return;
}
const cloneState = [...selectedItems];
cloneState.push(selectedVersion);
setSelectedItems(cloneState);
};
const rowRenderer = ({
key, // Unique key within array of rows
index, // Index of row within collection
isScrolling, // The List is currently being scrolled
isVisible, // This row is visible within the List (eg it is not an overscanned row)
style, // Style object to be applied to row (to position it)
}: ListRowProps) => {
const versOrd = versions.length - index;
return (
<FileVersionItem
style={style}
key={key}
fileName={actualInfo?.name || ""}
versionInfo={filteredRecords[index]}
index={versOrd}
onDownload={onDownloadItem}
onRestore={onRestoreItem}
onShare={onShareItem}
onPreview={onPreviewItem}
globalClick={onGlobalClick}
isSelected={selectedVersion === filteredRecords[index].version_id}
checkable={selectEnabled}
onCheck={onCheckVersion}
isChecked={selectedItems.includes(
filteredRecords[index].version_id || ""
)}
/>
);
};
return (
<Fragment>
{shareFileModalOpen && actualInfo && (
<ShareFile
open={shareFileModalOpen}
closeModalAndRefresh={closeShareModal}
bucketName={bucketName}
dataObject={objectToShare || actualInfo}
/>
)}
{restoreVersionOpen && actualInfo && (
<RestoreFileVersion
restoreOpen={restoreVersionOpen}
bucketName={bucketName}
versionID={restoreVersion}
objectPath={actualInfo.name}
onCloseAndUpdate={closeRestoreModal}
/>
)}
{previewOpen && actualInfo && (
<PreviewFileModal
open={previewOpen}
bucketName={bucketName}
object={{
name: actualInfo.name,
version_id:
objectToShare && objectToShare.version_id
? objectToShare.version_id
: "null",
size: parseInt(
objectToShare && objectToShare.size ? objectToShare.size : "0"
),
content_type: "",
last_modified: new Date(actualInfo.last_modified),
}}
onClosePreview={() => {
setPreviewOpen(false);
}}
/>
)}
{deleteNonCurrentOpen && (
<DeleteNonCurrent
deleteOpen={deleteNonCurrentOpen}
closeDeleteModalAndRefresh={closeDeleteNonCurrent}
selectedBucket={bucketName}
selectedObject={internalPaths}
/>
)}
{delSelectedVOpen && (
<DeleteSelectedVersions
selectedBucket={bucketName}
selectedObject={decodeURLString(internalPaths)}
deleteOpen={delSelectedVOpen}
selectedVersions={selectedItems}
closeDeleteModalAndRefresh={closeSelectedVersions}
/>
)}
<Grid container className={classes.versionsContainer}>
{!actualInfo && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
{actualInfo && (
<Fragment>
<Grid item xs={12}>
<BrowserBreadcrumbs
bucketName={bucketName}
internalPaths={decodeURLString(internalPaths)}
existingFiles={[]}
hidePathButton={true}
/>
</Grid>
<Grid item xs={12} className={classes.screenTitleContainer}>
<ScreenTitle
icon={
<span className={classes.listIcon}>
<VersionsIcon />
</span>
}
title={
<span className={classes.titleSpacer}>
{objectNameArray.length > 0
? objectNameArray[objectNameArray.length - 1]
: actualInfo.name}{" "}
Versions
</span>
}
subTitle={
<Fragment>
<Grid item xs={12} className={classes.bucketDetails}>
<span className={classes.detailsSpacer}>
<strong>
{versions.length} Version
{versions.length === 1 ? "" : "s"}
</strong>
</span>
<span className={classes.detailsSpacer}>
<strong>{niceBytesInt(totalSpace)}</strong>
</span>
</Grid>
</Fragment>
}
actions={
<Fragment>
<RBIconButton
id={"select-multiple-versions"}
tooltip={"Select Multiple Versions"}
onClick={() => {
setSelectEnabled(!selectEnabled);
}}
text={""}
icon={<SelectMultipleIcon />}
color="primary"
variant={selectEnabled ? "contained" : "outlined"}
style={{ marginRight: 8 }}
/>
{selectEnabled && (
<RBIconButton
id={"delete-multiple-versions"}
tooltip={"Delete Selected Versions"}
onClick={() => {
setDelSelectedVOpen(true);
}}
text={""}
icon={<DeleteIcon />}
color="secondary"
style={{ marginRight: 8 }}
disabled={selectedItems.length === 0}
/>
)}
<RBIconButton
id={"delete-non-current"}
tooltip={"Delete Non Current Versions"}
onClick={() => {
setDeleteNonCurrentOpen(true);
}}
text={""}
icon={<DeleteNonCurrentIcon />}
color="secondary"
style={{ marginRight: 15 }}
disabled={versions.length <= 1}
/>
<span className={classes.sortByLabel}>Sort by</span>
<SelectWrapper
id={"sort-by"}
label={""}
value={sortValue}
onChange={(e: SelectChangeEvent<string>) => {
setSortValue(e.target.value as string);
}}
name={"sort-by"}
options={[
{ label: "Date", value: "date" },
{
label: "Size",
value: "size",
},
]}
/>
</Fragment>
}
className={classes.noBottomBorder}
/>
</Grid>
<Grid item xs={12} className={classes.versionsVirtualPanel}>
{actualInfo.version_id && actualInfo.version_id !== "null" && (
// @ts-ignore
<List
style={{
width: "100%",
}}
containerStyle={{
width: "100%",
maxWidth: "100%",
}}
width={1}
height={800}
rowCount={filteredRecords.length}
rowHeight={108}
rowRenderer={rowRenderer}
/>
)}
</Grid>
</Fragment>
)}
</Grid>
</Fragment>
);
}
Example #17
Source File: PodLogs.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
PodLogs = ({ classes, tenant, namespace, podName, propLoading, }: IPodLogsProps) => { const dispatch = useDispatch(); const loadingTenant = useSelector( (state: AppState) => state.tenants.loadingTenant ); const [highlight, setHighlight] = useState<string>(""); const [logLines, setLogLines] = useState<string[]>([]); const [loading, setLoading] = useState<boolean>(true); const cache = new CellMeasurerCache({ minWidth: 5, fixedHeight: false, }); useEffect(() => { if (propLoading) { setLoading(true); } }, [propLoading]); useEffect(() => { if (loadingTenant) { setLoading(true); } }, [loadingTenant]); const renderLog = (logMessage: string, index: number) => { if (!logMessage) { return null; } // remove any non ascii characters, exclude any control codes logMessage = logMessage.replace(/([^\x20-\x7F])/g, ""); // regex for terminal colors like e.g. `[31;4m ` const tColorRegex = /((\[[0-9;]+m))/g; // get substring if there was a match for to split what // is going to be colored and what not, here we add color // only to the first match. let substr = logMessage.replace(tColorRegex, ""); // in case highlight is set, we select the line that contains the requested string let highlightedLine = highlight !== "" ? logMessage.toLowerCase().includes(highlight.toLowerCase()) : false; // if starts with multiple spaces add padding if (substr.startsWith(" ")) { return ( <div key={index} className={`${highlightedLine ? classes.highlight : ""}`} > <span className={classes.tab}>{substr}</span> </div> ); } else { // for all remaining set default class return ( <div key={index} className={`${highlightedLine ? classes.highlight : ""}`} > <span className={classes.ansidefault}>{substr}</span> </div> ); } }; useEffect(() => { if (loading) { api .invoke( "GET", `/api/v1/namespaces/${namespace}/tenants/${tenant}/pods/${podName}` ) .then((res: string) => { setLogLines(res.split("\n")); setLoading(false); }) .catch((err: ErrorResponseHandler) => { dispatch(setErrorSnackMessage(err)); setLoading(false); }); } }, [loading, podName, namespace, tenant, dispatch]); function cellRenderer({ columnIndex, key, parent, index, style }: any) { return ( // @ts-ignore <CellMeasurer cache={cache} columnIndex={columnIndex} key={key} parent={parent} rowIndex={index} > <div style={{ ...style, }} > {renderLog(logLines[index], index)} </div> </CellMeasurer> ); } return ( <React.Fragment> <Grid item xs={12} className={classes.actionsTray}> <TextField placeholder="Highlight Line" className={classes.searchField} id="search-resource" label="" onChange={(val) => { setHighlight(val.target.value); }} InputProps={{ disableUnderline: true, startAdornment: ( <InputAdornment position="start"> <SearchIcon /> </InputAdornment> ), }} variant="standard" /> </Grid> <Grid item xs={12}> <br /> </Grid> <Grid item xs={12}> <Paper> <div className={classes.logList}> {logLines.length >= 1 && ( // @ts-ignore <AutoSizer> {({ width, height }) => ( // @ts-ignore <List rowHeight={(item) => cache.rowHeight(item)} overscanRowCount={15} rowCount={logLines.length} rowRenderer={cellRenderer} width={width} height={height} /> )} </AutoSizer> )} </div> </Paper> </Grid> </React.Fragment> ); }
Example #18
Source File: InfinityScroll.tsx From querybook with Apache License 2.0 | 4 votes |
function InfinityScrollComponent<T>({
labelField = 'name',
itemClass = '',
itemHeight = 24,
elements,
className,
onClick,
itemRenderer,
onLoadMore,
hasMore,
defaultListHeight,
autoSizerStyles,
}: React.PropsWithChildren<IInfinityScrollProps<T>>) {
const listRef = useRef<List>();
const rowRenderer = useCallback(
({
index, // Index of row
key, // Unique key within array of rendered rows
style, // Style object to be applied to row (to position it);
}: // This must be passed through to the rendered row element.
{
index: number;
key: string;
style: CSSProperties;
}) => {
if (index >= elements.length) {
return (
<div
key={key}
style={style}
className="InfiniteScroll-loader flex-center"
>
<LoadingRow />
</div>
);
}
const element = elements[index];
const content = itemRenderer ? (
itemRenderer(element)
) : (
<span
className={itemClass}
onClick={onClick.bind(null, element)}
>
{element[labelField]}
</span>
);
return (
<div key={key} style={style}>
{content}
</div>
);
},
[itemClass, itemRenderer, elements, labelField, onClick]
);
const isRowLoaded = useCallback(
({ index }: { index: number }) => index < elements.length,
[elements.length]
);
const handleLoadMoreRows = useCallback(
() =>
new Promise<void>(async (resolve) => {
try {
if (onLoadMore) {
await onLoadMore();
}
} finally {
resolve();
}
}),
[onLoadMore]
);
useEffect(() => {
if (listRef.current) {
listRef.current.forceUpdateGrid();
}
}, [elements]);
const rowCount = hasMore ? elements.length + 1 : elements.length;
return (
<InfiniteLoader
isRowLoaded={isRowLoaded}
loadMoreRows={handleLoadMoreRows}
rowCount={rowCount}
>
{({ onRowsRendered, registerChild }) => (
<AutoSizer style={autoSizerStyles}>
{({ height, width }) => (
<List
className={className}
onRowsRendered={onRowsRendered}
ref={(ref) => {
registerChild(ref);
listRef.current = ref;
}}
height={defaultListHeight ?? height}
width={width}
rowCount={rowCount}
rowHeight={itemHeight}
rowRenderer={rowRenderer}
/>
)}
</AutoSizer>
)}
</InfiniteLoader>
);
}
Example #19
Source File: Timeline.tsx From metaflow-ui with Apache License 2.0 | 4 votes |
Timeline: React.FC<TimelineProps> = ({
rows,
timeline,
searchStatus,
footerType = 'minimap',
paramsString = '',
customMinimumHeight = 31.25,
onHandleMove = () => null,
onMove = () => null,
onStepRowClick = () => null,
}) => {
const { t } = useTranslation();
// Position of each step in timeline. Used to track if we should use sticky header (move to rowDataState?)
const [stepPositions, setStepPositions] = useState<StepIndex[]>([]);
// Name of sticky header (if should be visible)
const [stickyHeader, setStickyHeader] = useState<null | string>(null);
const [dragging, setDragging] = useState(false);
// Update step position indexes (for sticky headers). We might wanna do this else where
useEffect(() => {
const stepPos: StepIndex[] = [];
let index = 0;
for (const current of rows) {
index++;
if (current.type === 'step') {
stepPos.push({ name: current.data.step_name, index });
}
}
setStepPositions(stepPos);
}, [rows]);
//
// Event handling
//
const onRowsRendered = (params: RenderedRows) => {
const stepNeedsSticky = timelineNeedStickyHeader(stepPositions, params.startIndex);
if (stepNeedsSticky) {
setStickyHeader(stepNeedsSticky.name);
} else {
if (stickyHeader) {
setStickyHeader(null);
}
}
};
return (
<ListContainer customMinHeight={customMinimumHeight}>
<AutoSizer>
{({ width, height }) => (
<>
<List
overscanRowCount={10}
rowCount={rows.length}
onRowsRendered={onRowsRendered}
rowHeight={ROW_HEIGHT}
rowRenderer={createRowRenderer({
rows,
timeline,
searchStatus,
onStepRowClick,
paramsString,
t: t,
dragging: dragging,
})}
height={
height - SPACE_UNDER_TIMELINE(footerType) > rows.length * ROW_HEIGHT
? rows.length * ROW_HEIGHT
: height - SPACE_UNDER_TIMELINE(footerType)
}
width={width}
style={{ transition: 'height 0.25s' }}
/>
{stickyHeader && timeline.groupingEnabled && (
<StickyHeader
stickyStep={stickyHeader}
items={rows}
timeline={timeline}
onToggle={() => onStepRowClick(stickyHeader)}
t={t}
dragging={dragging}
/>
)}
<div style={{ width: width + 'px' }}>
<TimelineFooter
{...(footerType === 'minimap'
? {
type: 'minimap',
props: {
timeline,
rows,
onMove: onMove,
onHandleMove: onHandleMove,
onDraggingStateChange: setDragging,
},
}
: {
type: 'minimal',
props: {
startTime: timeline.startTime,
visibleStartTime: timeline.visibleStartTime,
visibleEndtime: timeline.visibleEndTime,
},
})}
/>
</div>
</>
)}
</AutoSizer>
</ListContainer>
);
}