index.community/frontend/src/components/InstanceSearch.tsx

90 lines
3 KiB
TypeScript
Raw Normal View History

2018-08-27 15:27:09 +00:00
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
2018-08-29 00:17:08 +00:00
import { Button, MenuItem } from '@blueprintjs/core';
import { IconNames } from '@blueprintjs/icons';
import { IItemRendererProps, ItemPredicate, Select } from '@blueprintjs/select';
2018-08-27 15:27:09 +00:00
import { selectInstance } from '../redux/actions';
import { IAppState, IInstance } from '../redux/types';
interface IInstanceSearchProps {
currentInstanceName: string | null;
2018-08-27 15:27:09 +00:00
instances?: IInstance[];
selectInstance: (instanceName: string) => void;
}
2018-08-29 00:17:08 +00:00
const InstanceSelect = Select.ofType<IInstance>();
2018-08-27 15:27:09 +00:00
class InstanceSearchImpl extends React.Component<IInstanceSearchProps> {
2018-08-27 21:31:27 +00:00
2018-08-27 15:27:09 +00:00
public render() {
return (
2018-08-29 00:17:08 +00:00
<InstanceSelect
items={this.props.instances && this.props.instances.slice(50) || []}
2018-08-27 15:27:09 +00:00
itemRenderer={this.itemRenderer}
onItemSelect={this.onItemSelect}
2018-08-29 00:17:08 +00:00
itemPredicate={this.itemPredicate}
disabled={!this.props.instances}
initialContent={this.renderInitialContent()}
noResults={this.renderNoResults()}
popoverProps={{popoverClassName: "fediverse-instance-search-popover"}}
2018-08-29 00:17:08 +00:00
>
<Button
icon={IconNames.SELECTION}
rightIcon={IconNames.CARET_DOWN}
text={this.props.currentInstanceName || ("Select an instance")}
2018-08-29 00:17:08 +00:00
disabled={!this.props.instances}
/>
</InstanceSelect>
);
2018-08-27 15:27:09 +00:00
}
private renderInitialContent = () => {
return (
<MenuItem disabled={true} text={"Start typing"} />
);
}
private renderNoResults = () => {
return (
<MenuItem disabled={true} text={"Keep typing"} />
);
}
private itemRenderer = (item: IInstance, itemProps: IItemRendererProps) => {
if (!itemProps.modifiers.matchesPredicate) {
2018-08-29 00:17:08 +00:00
return null;
}
return (
<MenuItem
text={item.name}
key={item.name}
active={itemProps.modifiers.active}
onClick={itemProps.handleClick}
2018-08-29 00:17:08 +00:00
/>
);
2018-08-27 15:27:09 +00:00
}
2018-08-29 00:17:08 +00:00
private itemPredicate: ItemPredicate<IInstance> = (query, item, index) => {
if (!item.name || query.length < 4) {
2018-08-29 00:17:08 +00:00
return false;
}
return item.name.toLowerCase().indexOf(query.toLowerCase()) >= 0;
2018-08-27 15:27:09 +00:00
}
2018-08-27 21:31:27 +00:00
private onItemSelect = (item: IInstance, event?: React.SyntheticEvent<HTMLElement>) => {
this.props.selectInstance(item.name);
2018-08-27 15:27:09 +00:00
}
}
const mapStateToProps = (state: IAppState) => ({
currentInstanceName: state.currentInstanceName,
2018-08-27 15:27:09 +00:00
instances: state.data.instances,
})
const mapDispatchToProps = (dispatch: Dispatch) => ({
selectInstance: (instanceName: string) => dispatch(selectInstance(instanceName)),
})
export const InstanceSearch = connect(mapStateToProps, mapDispatchToProps)(InstanceSearchImpl)