Flesh out filtering

This commit is contained in:
Drew DeVault 2017-12-30 13:06:59 -05:00
parent 1fa75747f2
commit 6d509a4f29
5 changed files with 50 additions and 32 deletions

View File

@ -46,6 +46,7 @@
"isomorphic-fetch": "^2.2.1", "isomorphic-fetch": "^2.2.1",
"moment": "^2.20.1", "moment": "^2.20.1",
"node-sass": "^4.7.2", "node-sass": "^4.7.2",
"numeral": "^2.0.6",
"preact": "^8.2.7", "preact": "^8.2.7",
"preact-compat": "^3.17.0", "preact-compat": "^3.17.0",
"query-string": "^5.0.1", "query-string": "^5.0.1",

View File

@ -3,6 +3,7 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux'; import { ConnectedRouter } from 'react-router-redux';
import query from 'query-string';
import 'preact/devtools'; import 'preact/devtools';
import './polyfills'; import './polyfills';
@ -11,6 +12,7 @@ import scss from '../scss/main.scss';
import { ws_init } from './socket'; import { ws_init } from './socket';
import { filter_subscribe } from './actions/filter_subscribe'; import { filter_subscribe } from './actions/filter_subscribe';
import { socket_uri, socket_update, SOCKET_STATE } from './actions/socket'; import { socket_uri, socket_update, SOCKET_STATE } from './actions/socket';
import search_criteria from './search';
import Main from './ui/main'; import Main from './ui/main';
import Connection from './ui/connection'; import Connection from './ui/connection';
@ -19,8 +21,9 @@ export function initialize(uri) {
store.dispatch(socket_uri(uri)); store.dispatch(socket_uri(uri));
store.dispatch(socket_update(SOCKET_STATE.CONNECTING)); store.dispatch(socket_update(SOCKET_STATE.CONNECTING));
ws_init(uri, () => { ws_init(uri, () => {
const qs = query.parse(window.location.search);
store.dispatch(socket_update(SOCKET_STATE.CONNECTED)); store.dispatch(socket_update(SOCKET_STATE.CONNECTED));
store.dispatch(filter_subscribe()); store.dispatch(filter_subscribe('torrent', search_criteria(qs.s)));
store.dispatch(filter_subscribe('server')); store.dispatch(filter_subscribe('server'));
}, () => { }, () => {
store.dispatch(socket_update(SOCKET_STATE.DISCONNECTED, store.dispatch(socket_update(SOCKET_STATE.DISCONNECTED,

43
src/search.js Normal file
View File

@ -0,0 +1,43 @@
import numeral from "numeral";
// 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;
export default function search_criteria(text) {
if (!text) {
return [];
}
const terms = ssplit(text);
const operators = [":", "==", "!=", ">", ">=", "<", "<="];
return terms.map(t => operators.reduce((a, op) => {
if (t.indexOf(op) === -1) {
return a;
}
const [field, value] = t.split(op);
if (op == ":") {
return { op: "ilike", field, value: `%${t}%` };
}
if (!isNaN(numeral(value).value())) {
return {
op,
field,
value: numeral(value).value()
};
}
return { op, field, value };
}, null) || {
field: "name",
op: "ilike",
value: `%${t}%`
}
);
}

View File

@ -4,6 +4,7 @@ import { Link, NavLink } from 'react-router-dom';
import { filter_subscribe } from '../actions/filter_subscribe'; import { filter_subscribe } from '../actions/filter_subscribe';
import { push } from 'react-router-redux'; import { push } from 'react-router-redux';
import query from 'query-string'; import query from 'query-string';
import search_criteria from '../search';
function search_qs(text) { function search_qs(text) {
const qs = query.stringify({ const qs = query.stringify({
@ -15,37 +16,6 @@ function search_qs(text) {
}${qs && "?" + qs}`; }${qs && "?" + qs}`;
} }
// 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}%`
};
}
});
}
function update_filter(text, fs, location, dispatch) { function update_filter(text, fs, location, dispatch) {
// there will always be one torrent filter // there will always be one torrent filter
const tfilter = fs.filter(fs => fs.kind === "torrent")[0]; const tfilter = fs.filter(fs => fs.kind === "torrent")[0];

View File

@ -8,6 +8,7 @@ function color(torrent) {
case "seeding": case "seeding":
return "primary"; return "primary";
case "hashing": case "hashing":
case "magnet":
return "info"; return "info";
case "idle": case "idle":
case "pending": case "pending":