autocomplete component

This commit is contained in:
gempir 2020-02-08 12:58:47 +01:00
parent 3d9e50ea7a
commit dbdaee0069
10 changed files with 61 additions and 77 deletions

View file

@ -4,15 +4,13 @@
"description": "frontend for justlog",
"repository": "github.com/gempir/justlog",
"dependencies": {
"material-design-icons": "^3.0.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"react-string-replace": "^0.4.4",
"react-toastify": "^5.5.0",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"whatwg-fetch": "^3.0.0"
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": "webpack-dev-server --mode development --content-base public",

View file

@ -3,9 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
<meta name="theme-color" content="#282828">
<title>logsearch</title>
</head>
<body>

View file

@ -0,0 +1,19 @@
import React, { Component } from "react";
export default class AutocompleteInput extends Component {
render() {
return <div className="AutocompleteInput">
<input
type="text"
placeholder={this.props.placeholder}
onChange={this.props.onChange}
value={this.props.value}
/>
<ul>
{this.props.autocompletions
.filter(channel => channel.name.includes(this.props.value))
.map(channel => <li key={channel.userID} onClick={() => this.setChannel(channel.name)}>{channel.name}</li>)}
</ul>
</div>
}
}

View file

@ -1,6 +1,7 @@
import React, { Component } from "react";
import {connect} from "react-redux";
import { connect } from "react-redux";
import setCurrent from "./../actions/setCurrent";
import AutocompleteInput from "./AutocompleteInput";
class Filter extends Component {
@ -22,21 +23,17 @@ class Filter extends Component {
}
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 (
<form className="filter" autoComplete="off" onSubmit={this.onSubmit}>
<div className="channel-wrapper">
<input
type="text"
placeholder="pajlada"
onChange={this.onChannelChange}
value={this.props.currentChannel}
/>
<ul className="channel-autocomplete">
{this.props.channels
.filter(channel => channel.name.includes(this.props.currentChannel))
.map(channel => <li key={channel.userID} onClick={() => this.setChannel(channel.name)}>{channel.name}</li>)}
</ul>
</div>
<AutocompleteInput placeholder="pajlada" onChange={this.onChannelChange} value={this.props.currentChannel} autocompletions={this.props.channels} />
<input
type="text"
placeholder="gempir"
@ -48,8 +45,6 @@ class Filter extends Component {
)
}
setChannel = channel => this.props.dispatch(setCurrent(channel, this.props.currentUsername));
onChannelChange = (e) => {
this.props.dispatch(setCurrent(e.target.value, this.props.currentUsername));
}
@ -68,6 +63,13 @@ class Filter extends Component {
onSubmit = (e) => {
e.preventDefault();
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
params.set('channel', this.props.currentChannel);
params.set('username', this.props.currentUsername);
window.location.search = params.toString();
this.props.searchLogs(this.props.currentChannel, this.props.currentUsername, this.state.year, this.state.month);
}
}

View file

@ -8,4 +8,5 @@
@import "modules/log-search";
@import "modules/filter";
@import "modules/log-view";
@import "modules/AutocompleteInput";

View file

@ -24,7 +24,6 @@ input {
background: $grey-dark;
outline: none;
border: 0;
padding: 10px;
border-radius: 3px;
&:focus {

View file

@ -0,0 +1,15 @@
.AutocompleteInput {
position: relative;
input {
height: 100%;
}
ul {
position: absolute;
background: $grey-medium;
top: 100%;
left: 0;
right: 0;
}
}

View file

@ -11,54 +11,18 @@
input {
width: 100%;
padding: 0 0.5rem;
&::-webkit-input-placeholder {
opacity: 0.25;
}
}
.channel-wrapper {
.AutocompleteInput {
width: 100%;
position: relative;
margin-right: 0.5rem;
input:focus {
& + .channel-autocomplete {
display: block;
}
}
.channel-autocomplete {
display: none;
position: absolute;
list-style-type: none;
padding: 0;
margin: 0;
background: $grey-medium;
z-index: 100;
top: 100%;
left: 0;
right: 0;
padding: 0;
font-size: 0.8rem;
@include box-shadow(2);
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
color: white;
li {
cursor: pointer;
padding: 5px;
&:hover {
background: $grey-light;
}
}
}
}
.show-logs {
width: 200px;
margin-left: 0.5rem;

View file

@ -18,6 +18,10 @@
background: $grey-light;
}
&:empty {
display: none;
}
.line {
padding: 0.25rem;
color: white;

View file

@ -4695,13 +4695,6 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
"material-design-icons@npm:^3.0.1":
version: 3.0.1
resolution: "material-design-icons@npm:3.0.1"
checksum: 1248effdfb7175ce9ade19224ebe83741142b1668732fddab064083c7c9b70561d42b3e59d770d26c95ac892ceecfe65079ebca31a07ba179a7a8fdf28203af6
languageName: node
linkType: hard
"md5.js@npm:^1.3.4":
version: 1.3.5
resolution: "md5.js@npm:1.3.5"
@ -7817,7 +7810,6 @@ fsevents@^1.2.7:
"@babel/preset-react": ^7.8.3
babel-loader: ^8.0.6
css-loader: ^3.4.2
material-design-icons: ^3.0.1
mini-css-extract-plugin: ^0.9.0
node-sass: ^4.13.1
pnp-webpack-plugin: ^1.6.0
@ -7833,7 +7825,6 @@ fsevents@^1.2.7:
webpack: ^4.41.5
webpack-cli: ^3.3.10
webpack-dev-server: ^3.10.1
whatwg-fetch: ^3.0.0
languageName: unknown
linkType: soft
@ -7991,13 +7982,6 @@ fsevents@^1.2.7:
languageName: node
linkType: hard
"whatwg-fetch@npm:^3.0.0":
version: 3.0.0
resolution: "whatwg-fetch@npm:3.0.0"
checksum: a3033a72d7300f899073ed30fe46e12ff7142ed06221879a610a919c01b8b26d3f82ac7a5c18c397a1cb6a95b3df95a644e45ead93c10872118fc0e961ea9f2c
languageName: node
linkType: hard
"which-module@npm:^1.0.0":
version: 1.0.0
resolution: "which-module@npm:1.0.0"