receptor/src/ui/navigation.js

107 lines
3.0 KiB
JavaScript
Raw Normal View History

2017-08-22 21:49:48 +02:00
import React from 'react';
2017-12-30 18:23:50 +01:00
import { connect } from 'react-redux';
2017-08-25 02:01:15 +02:00
import { Link, NavLink } from 'react-router-dom';
2017-12-30 18:23:50 +01:00
import { filter_subscribe } from '../actions/filter_subscribe';
import { push } from 'react-router-redux';
import query from 'query-string';
2017-08-22 21:49:48 +02:00
2017-12-30 18:23:50 +01:00
function search_qs(text) {
const qs = query.stringify({
...query.parse(location.search),
s: text || undefined
});
return `${
location.pathname === "/" ? location.pathname : ""
}${qs && "?" + qs}`;
}
2017-12-30 18:41:44 +01:00
// via https://stackoverflow.com/a/46946490
const ssplit = str => str.match(/\\?.|^$/g).reduce((p, c) => {
if (c === '"') {
p.quote ^= 1;
} else if (!p.quote && c === ' ') {
p.a.push('');
} else {
p.a[p.a.length-1] += c.replace(/\\(.)/,"$1");
}
return p;
}, {a: ['']}).a;
function search_criteria(text) {
const terms = ssplit(text);
return terms.map(t => {
if (t.indexOf("status:") === 0) {
return {
field: "status",
op: "==",
value: t.split(":")[1]
};
} else {
return {
field: "name",
op: "ilike",
value: `%${t}%`
};
}
});
}
2017-12-30 18:23:50 +01:00
function update_filter(text, fs, location, dispatch) {
2017-12-30 18:41:44 +01:00
// there will always be one torrent filter
const tfilter = fs.filter(fs => fs.kind === "torrent")[0];
const criteria = search_criteria(text);
dispatch(filter_subscribe("torrent", criteria, tfilter.serial));
2017-12-30 18:23:50 +01:00
dispatch(push(search_qs(text)));
}
function render(props) {
const { dispatch, router } = props;
const qs = query.parse(router.location.search);
2017-12-30 18:41:44 +01:00
const update = text => update_filter(
text || "", props.filter_subscribe, router.location, dispatch);
2017-12-30 18:23:50 +01:00
const navto = where => e => {
e.preventDefault();
2017-12-30 18:41:44 +01:00
update(where);
2017-12-30 18:23:50 +01:00
};
2017-12-30 18:41:44 +01:00
const searchLink = (target, text) => <li className="nav-item">
<a
className={`nav-link ${qs.s === target && "active"}`}
href={search_qs(target)}
onClick={navto(target)}
>{text}</a>
</li>;
2017-08-22 21:49:48 +02:00
return <nav className="navbar navbar-light navbar-toggleable-xl">
2017-08-25 02:01:15 +02:00
<Link to="/" className="navbar-brand">receptor</Link>
2017-08-22 21:49:48 +02:00
<div className="navbar-collapse collapse">
<ul className="navbar-nav mr-auto">
2017-08-23 14:42:00 +02:00
<li className="nav-item">
2017-08-24 14:30:22 +02:00
<NavLink
to="/add-torrent"
2017-08-24 15:50:14 +02:00
className="nav-link btn-primary"
2017-08-24 14:30:22 +02:00
activeClassName="nav-link active"
>add torrent</NavLink>
2017-08-23 14:42:00 +02:00
</li>
<li className="nav-item" style={{minWidth: "1rem"}}>
</li>
2017-12-30 18:41:44 +01:00
{searchLink(undefined, "all")}
{searchLink("status:leeching", "leeching")}
{searchLink("status:seeding", "seeding")}
2017-08-23 14:42:00 +02:00
<form className="form-inline">
<input
className="form-control mr-sm-2"
type="text"
placeholder="Search"
2017-12-30 18:23:50 +01:00
aria-label="Search"
value={qs.s}
2017-12-30 18:41:44 +01:00
onChange={e => update(e.target.value)} />
2017-08-23 14:42:00 +02:00
</form>
2017-08-22 21:49:48 +02:00
</ul>
</div>
</nav>;
}
2017-12-30 18:23:50 +01:00
export default connect(state => ({
filter_subscribe: state.filter_subscribe,
router: state.router,
}))(render);