add autocompletion
This commit is contained in:
parent
dbdaee0069
commit
a86f9e5baa
5 changed files with 52 additions and 17 deletions
|
@ -4,6 +4,7 @@
|
||||||
"description": "frontend for justlog",
|
"description": "frontend for justlog",
|
||||||
"repository": "github.com/gempir/justlog",
|
"repository": "github.com/gempir/justlog",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
"react": "^16.12.0",
|
"react": "^16.12.0",
|
||||||
"react-dom": "^16.12.0",
|
"react-dom": "^16.12.0",
|
||||||
"react-redux": "^7.1.3",
|
"react-redux": "^7.1.3",
|
||||||
|
|
|
@ -1,19 +1,39 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
|
|
||||||
export default class AutocompleteInput extends Component {
|
export default class AutocompleteInput extends Component {
|
||||||
render() {
|
|
||||||
|
state = {
|
||||||
|
focused: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
input;
|
||||||
|
|
||||||
|
render() {
|
||||||
return <div className="AutocompleteInput">
|
return <div className="AutocompleteInput">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
|
ref={el => this.input = el}
|
||||||
placeholder={this.props.placeholder}
|
placeholder={this.props.placeholder}
|
||||||
onChange={this.props.onChange}
|
onChange={e => this.props.onChange(e.target.value)}
|
||||||
|
onFocus={() => this.setState({ focused: true })}
|
||||||
|
onBlur={() => this.setState({ focused: false })}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
/>
|
/>
|
||||||
<ul>
|
{this.state.focused && <ul>
|
||||||
{this.props.autocompletions
|
{this.props.autocompletions
|
||||||
.filter(channel => channel.name.includes(this.props.value))
|
.filter(completion => completion.includes(this.props.value))
|
||||||
.map(channel => <li key={channel.userID} onClick={() => this.setChannel(channel.name)}>{channel.name}</li>)}
|
.map(completion =>
|
||||||
</ul>
|
<li key={completion} onClick={() => this.handleClick(completion)} onMouseDown={e => e.preventDefault()}>
|
||||||
|
{completion}
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleClick = (completion) => {
|
||||||
|
this.props.onChange(completion);
|
||||||
|
this.input.blur();
|
||||||
|
this.props.onAutocompletionClick(completion);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -16,6 +16,8 @@ class Filter extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
username;
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (this.props.currentChannel && this.props.currentUsername) {
|
if (this.props.currentChannel && this.props.currentUsername) {
|
||||||
this.props.searchLogs(this.props.currentChannel, this.props.currentUsername, this.state.year, this.state.month);
|
this.props.searchLogs(this.props.currentChannel, this.props.currentUsername, this.state.year, this.state.month);
|
||||||
|
@ -23,18 +25,11 @@ class Filter extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const completions = this.props.channels
|
|
||||||
.filter(channel => channel.name.includes(this.props.currentChannel));
|
|
||||||
|
|
||||||
const autocompletions = [];
|
|
||||||
for (const completion of completions) {
|
|
||||||
autocompletions.push(<li key={completion.userID} onClick={() => this.setChannel(completion.name)}>{completion.name}</li>);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="filter" autoComplete="off" onSubmit={this.onSubmit}>
|
<form className="filter" autoComplete="off" onSubmit={this.onSubmit}>
|
||||||
<AutocompleteInput placeholder="pajlada" onChange={this.onChannelChange} value={this.props.currentChannel} autocompletions={this.props.channels} />
|
<AutocompleteInput placeholder="pajlada" onChange={this.onChannelChange} value={this.props.currentChannel} onAutocompletionClick={() => this.username.focus()} autocompletions={this.props.channels.map(channel => channel.name)} />
|
||||||
<input
|
<input
|
||||||
|
ref={el => this.username = el}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="gempir"
|
placeholder="gempir"
|
||||||
onChange={this.onUsernameChange}
|
onChange={this.onUsernameChange}
|
||||||
|
@ -45,8 +40,8 @@ class Filter extends Component {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
onChannelChange = (e) => {
|
onChannelChange = (channel) => {
|
||||||
this.props.dispatch(setCurrent(e.target.value, this.props.currentUsername));
|
this.props.dispatch(setCurrent(channel, this.props.currentUsername));
|
||||||
}
|
}
|
||||||
|
|
||||||
onUsernameChange = (e) => {
|
onUsernameChange = (e) => {
|
||||||
|
|
|
@ -7,9 +7,27 @@
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
z-index: 100;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: white;
|
||||||
|
list-style-type: none;
|
||||||
background: $grey-medium;
|
background: $grey-medium;
|
||||||
top: 100%;
|
top: 100%;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@include box-shadow(2);
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.5rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $grey-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7813,6 +7813,7 @@ fsevents@^1.2.7:
|
||||||
mini-css-extract-plugin: ^0.9.0
|
mini-css-extract-plugin: ^0.9.0
|
||||||
node-sass: ^4.13.1
|
node-sass: ^4.13.1
|
||||||
pnp-webpack-plugin: ^1.6.0
|
pnp-webpack-plugin: ^1.6.0
|
||||||
|
prop-types: ^15.7.2
|
||||||
react: ^16.12.0
|
react: ^16.12.0
|
||||||
react-dom: ^16.12.0
|
react-dom: ^16.12.0
|
||||||
react-redux: ^7.1.3
|
react-redux: ^7.1.3
|
||||||
|
|
Loading…
Add table
Reference in a new issue