Improve member search
This commit is contained in:
parent
64e7f4d8f4
commit
5edf23de0e
|
@ -6,11 +6,13 @@
|
||||||
"@testing-library/jest-dom": "^4.2.4",
|
"@testing-library/jest-dom": "^4.2.4",
|
||||||
"@testing-library/react": "^9.3.2",
|
"@testing-library/react": "^9.3.2",
|
||||||
"@testing-library/user-event": "^7.1.2",
|
"@testing-library/user-event": "^7.1.2",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
"blueimp-load-image": "^5.13.0",
|
"blueimp-load-image": "^5.13.0",
|
||||||
"darkmode-js": "~1.5.5",
|
"darkmode-js": "~1.5.5",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
"moment": "~2.24.0",
|
"moment": "~2.24.0",
|
||||||
"moment-timezone": "~0.5.28",
|
"moment-timezone": "~0.5.28",
|
||||||
|
"query-string": "^7.0.1",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-datetime": "~2.16.3",
|
"react-datetime": "~2.16.3",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import React, { useState, useEffect, useReducer } from 'react';
|
import React, { useState, useEffect, useReducer } from 'react';
|
||||||
import { BrowserRouter as Router, Switch, Route, Link, useParams, useLocation } from 'react-router-dom';
|
import { BrowserRouter as Router, Switch, Route, Link, useParams, useLocation, useHistory } from 'react-router-dom';
|
||||||
import './light.css';
|
import './light.css';
|
||||||
import { Button, Container, Divider, Dropdown, Form, Grid, Header, Icon, Image, Input, Item, Menu, Message, Segment, Table } from 'semantic-ui-react';
|
import { Button, Container, Divider, Dropdown, Form, Grid, Header, Icon, Image, Input, Item, Menu, Message, Segment, Table } from 'semantic-ui-react';
|
||||||
import { statusColor, isAdmin, isInstructor, BasicTable, staticUrl, requester } from './utils.js';
|
import { statusColor, isAdmin, isInstructor, BasicTable, staticUrl, requester } from './utils.js';
|
||||||
import { NotFound, PleaseLogin } from './Misc.js';
|
import { NotFound, PleaseLogin } from './Misc.js';
|
||||||
import { AdminMemberInfo, AdminMemberPause, AdminMemberForm, AdminMemberCards, AdminMemberTraining, AdminMemberCertifications } from './AdminMembers.js';
|
import { AdminMemberInfo, AdminMemberPause, AdminMemberForm, AdminMemberCards, AdminMemberTraining, AdminMemberCertifications } from './AdminMembers.js';
|
||||||
import { AdminMemberTransactions } from './AdminTransactions.js';
|
import { AdminMemberTransactions } from './AdminTransactions.js';
|
||||||
|
import queryString from 'query-string';
|
||||||
|
import AbortController from 'abort-controller';
|
||||||
|
|
||||||
const memberSorts = {
|
const memberSorts = {
|
||||||
recently_vetted: 'Recently Vetted',
|
recently_vetted: 'Recently Vetted',
|
||||||
|
@ -59,38 +61,52 @@ export function MembersDropdown(props) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let searchCache = '';
|
|
||||||
let numShowCache = 20;
|
let numShowCache = 20;
|
||||||
|
|
||||||
export function Members(props) {
|
export function Members(props) {
|
||||||
|
const history = useHistory();
|
||||||
const qs = useLocation().search;
|
const qs = useLocation().search;
|
||||||
const params = new URLSearchParams(qs);
|
const params = new URLSearchParams(qs);
|
||||||
const sort = params.get('sort') || 'recently_vetted';
|
const sort = params.get('sort') || 'recently_vetted';
|
||||||
|
const search = params.get('q') || '';
|
||||||
|
|
||||||
const [response, setResponse] = useState(false);
|
const [response, setResponse] = useState(false);
|
||||||
const [numShow, setNumShow] = useState(numShowCache);
|
const [numShow, setNumShow] = useState(numShowCache);
|
||||||
const searchDefault = {seq: 0, q: searchCache};
|
const [controller, setController] = useState(false);
|
||||||
const [search, setSearch] = useState(searchDefault);
|
|
||||||
const { token } = props;
|
const { token } = props;
|
||||||
|
|
||||||
useEffect(() => {
|
const doSearch = (q) => {
|
||||||
setResponse(false);
|
console.log('doing search', q);
|
||||||
searchCache = search.q;
|
if (q.length) {
|
||||||
search.sort = sort;
|
const qs = queryString.stringify({ 'q': q });
|
||||||
requester('/search/', 'POST', token, search)
|
history.replace('/members?' + qs);
|
||||||
.then(res => {
|
} else {
|
||||||
if (!search.seq || res.seq > response.seq) {
|
history.replace('/members');
|
||||||
setResponse(res);
|
|
||||||
}
|
}
|
||||||
})
|
};
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
const handleChange = (event) => {
|
||||||
});
|
const q = event.target.value;
|
||||||
}, [search, sort]);
|
doSearch(q);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSearch({seq: 0, q: ''});
|
if (controller) {
|
||||||
}, [sort]);
|
controller.abort();
|
||||||
|
}
|
||||||
|
const ctl = new AbortController();
|
||||||
|
setController(ctl);
|
||||||
|
const signal = ctl.signal;
|
||||||
|
|
||||||
|
const data = {q: search, sort: sort};
|
||||||
|
requester('/search/', 'POST', token, data, signal)
|
||||||
|
.then(res => {
|
||||||
|
setResponse(res);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
;
|
||||||
|
});
|
||||||
|
}, [search, sort]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
|
@ -100,16 +116,16 @@ export function Members(props) {
|
||||||
|
|
||||||
<Input autoFocus focus icon='search'
|
<Input autoFocus focus icon='search'
|
||||||
placeholder='Search...'
|
placeholder='Search...'
|
||||||
value={search.q}
|
value={search}
|
||||||
onChange={(e, v) => setSearch({seq: parseInt(e.timeStamp), q: v.value})}
|
onChange={handleChange}
|
||||||
aria-label='search products'
|
aria-label='search products'
|
||||||
style={{ marginRight: '0.5rem' }}
|
style={{ marginRight: '0.5rem' }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{search.q.length ?
|
{search.length ?
|
||||||
<Button
|
<Button
|
||||||
content='Clear'
|
content='Clear'
|
||||||
onClick={() => setSearch({seq: 0, q: ''})}
|
onClick={() => doSearch('')}
|
||||||
/> : ''
|
/> : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +142,7 @@ export function Members(props) {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<Header size='medium'>
|
<Header size='medium'>
|
||||||
{search.q.length ? 'Search Results' : memberSorts[sort] + ' Members'}
|
{search.length ? 'Search Results' : memberSorts[sort] + ' Members'}
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
{sort === 'best_looking' ?
|
{sort === 'best_looking' ?
|
||||||
|
|
|
@ -32,8 +32,8 @@ export const BasicTable = (props) => (
|
||||||
</Table>
|
</Table>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const requester = (route, method, token, data) => {
|
export const requester = (route, method, token, data, signal=null) => {
|
||||||
let options = {headers: {}};
|
let options = {headers: {}, signal: signal};
|
||||||
let url = '';
|
let url = '';
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
|
@ -106,6 +106,8 @@ export const requester = (route, method, token, data) => {
|
||||||
});
|
});
|
||||||
} else if (code >= 500 && code < 600) {
|
} else if (code >= 500 && code < 600) {
|
||||||
throw customError({non_field_errors: ['Server Error']});
|
throw customError({non_field_errors: ['Server Error']});
|
||||||
|
} else if (error.message === 'The operation was aborted. ') {
|
||||||
|
throw error;
|
||||||
} else {
|
} else {
|
||||||
throw customError({non_field_errors: ['Network Error']});
|
throw customError({non_field_errors: ['Network Error']});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1854,6 +1854,13 @@ abab@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a"
|
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a"
|
||||||
integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==
|
integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==
|
||||||
|
|
||||||
|
abort-controller@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
|
||||||
|
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
|
||||||
|
dependencies:
|
||||||
|
event-target-shim "^5.0.0"
|
||||||
|
|
||||||
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
|
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
|
||||||
version "1.3.7"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
||||||
|
@ -4370,6 +4377,11 @@ etag@~1.8.1:
|
||||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||||
|
|
||||||
|
event-target-shim@^5.0.0:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
|
||||||
|
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
|
||||||
|
|
||||||
eventemitter3@^2.0.3:
|
eventemitter3@^2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba"
|
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba"
|
||||||
|
@ -4669,6 +4681,11 @@ fill-range@^7.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range "^5.0.1"
|
to-regex-range "^5.0.1"
|
||||||
|
|
||||||
|
filter-obj@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
|
||||||
|
integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs=
|
||||||
|
|
||||||
finalhandler@~1.1.2:
|
finalhandler@~1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
|
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
|
||||||
|
@ -8802,6 +8819,16 @@ query-string@^4.1.0:
|
||||||
object-assign "^4.1.0"
|
object-assign "^4.1.0"
|
||||||
strict-uri-encode "^1.0.0"
|
strict-uri-encode "^1.0.0"
|
||||||
|
|
||||||
|
query-string@^7.0.1:
|
||||||
|
version "7.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.0.1.tgz#45bd149cf586aaa582dffc7ec7a8ad97dd02f75d"
|
||||||
|
integrity sha512-uIw3iRvHnk9to1blJCG3BTc+Ro56CBowJXKmNNAm3RulvPBzWLRqKSiiDk+IplJhsydwtuNMHi8UGQFcCLVfkA==
|
||||||
|
dependencies:
|
||||||
|
decode-uri-component "^0.2.0"
|
||||||
|
filter-obj "^1.1.0"
|
||||||
|
split-on-first "^1.0.0"
|
||||||
|
strict-uri-encode "^2.0.0"
|
||||||
|
|
||||||
querystring-es3@^0.2.0:
|
querystring-es3@^0.2.0:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
|
||||||
|
@ -10083,6 +10110,11 @@ spdy@^4.0.1:
|
||||||
select-hose "^2.0.0"
|
select-hose "^2.0.0"
|
||||||
spdy-transport "^3.0.0"
|
spdy-transport "^3.0.0"
|
||||||
|
|
||||||
|
split-on-first@^1.0.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
|
||||||
|
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
|
||||||
|
|
||||||
split-string@^3.0.1, split-string@^3.0.2:
|
split-string@^3.0.1, split-string@^3.0.2:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
|
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
|
||||||
|
@ -10190,6 +10222,11 @@ strict-uri-encode@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||||
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
|
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
|
||||||
|
|
||||||
|
strict-uri-encode@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
|
||||||
|
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
|
||||||
|
|
||||||
string-length@^2.0.0:
|
string-length@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
|
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user