Add search page (#1293)

* Got search working in frontend

* Got search bar working

* Make frontent lint

* Remove unused state from search page

* Update frontend build

* Reset search results to empty array on search bar enter

* Make frontent lint

* Update frontend build
This commit is contained in:
Jonathan Zernik 2021-09-15 18:21:05 -07:00 committed by GitHub
parent 047c3a7d67
commit d9f86b2fb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 335 additions and 24 deletions

View file

@ -38,6 +38,7 @@ import {
} from '../../squeakclient/requests';
import {
reloadRoute,
goToSearchPage,
} from '../../navigation/navigation';
const notifications = [];
@ -121,6 +122,14 @@ export default function Header(props) {
root: classes.inputRoot,
input: classes.inputInput,
}}
onKeyPress={(ev) => {
console.log(`Pressed keyCode ${ev.key}`);
if (ev.key === 'Enter') {
ev.preventDefault();
const encodedText = encodeURIComponent(ev.target.value);
goToSearchPage(history, encodedText);
}
}}
/>
</div>
<IconButton

View file

@ -18,6 +18,7 @@ import Sidebar from '../Sidebar';
import Timeline from '../../pages/timeline';
import Dashboard from '../../pages/dashboard';
import SqueakAddress from '../../pages/squeakaddress';
import Search from '../../pages/search';
import Squeak from '../../pages/squeak';
import Profile from '../../pages/profile';
import Wallet from '../../pages/wallet';
@ -60,6 +61,7 @@ function Layout(props) {
<Route path="/app/timeline" component={Timeline} />
<Route path="/app/dashboard" component={Dashboard} />
<Route path="/app/squeakaddress/:address" component={SqueakAddress} />
<Route path="/app/search/:searchText" component={Search} />
<Route path="/app/squeak/:hash" component={Squeak} />
<Route path="/app/profile/:id" component={Profile} />
<Route path="/app/profiles" component={Profiles} />

View file

@ -29,6 +29,10 @@ export const goToSqueakAddressPage = (history, squeakAddress) => {
history.push(`/app/squeakaddress/${squeakAddress}`);
};
export const goToSearchPage = (history, searchText) => {
history.push(`/app/search/${searchText}`);
};
export const goToChannelPage = (history, txId, outputIndex) => {
history.push(`/app/channel/${txId}/${outputIndex}`);
};

View file

@ -0,0 +1,210 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useParams, useHistory } from 'react-router-dom';
import {
Grid,
Button,
CircularProgress,
TextField,
} from '@material-ui/core';
// components
import Paper from '@material-ui/core/Paper';
import ReplayIcon from '@material-ui/icons/Replay';
import SqueakList from '../../components/SqueakList';
import useStyles from './styles';
import {
getSearchSqueakDisplaysRequest,
getNetworkRequest,
// subscribeAddressSqueakDisplaysRequest,
} from '../../squeakclient/requests';
import {
goToSearchPage,
} from '../../navigation/navigation';
// // styles
// const useStyles = makeStyles((theme) => ({
// root: {
// '& .MuiTextField-root': {
// margin: theme.spacing(1),
// width: '25ch',
// },
// },
// }));
const SQUEAKS_PER_PAGE = 10;
export default function SearchPage() {
const classes = useStyles();
const history = useHistory();
const { searchText } = useParams();
const [squeaks, setSqueaks] = useState([]);
const [network, setNetwork] = useState('');
const [waitingForSqueaks, setWaitingForSqueaks] = useState(false);
const [inputText, setInputText] = useState(searchText);
const getSqueaks = useCallback((searchText, limit, lastEntry) => {
setWaitingForSqueaks(true);
getSearchSqueakDisplaysRequest(searchText, limit, lastEntry, handleLoadedAddressSqueaks);
},
[]);
// const subscribeSqueaks = (address) => subscribeAddressSqueakDisplaysRequest(address, (resp) => {
// setSqueaks((prevSqueaks) => [resp].concat(prevSqueaks));
// });
const getNetwork = () => {
getNetworkRequest(setNetwork);
};
const handleLoadedAddressSqueaks = (loadedAddressSqueaks) => {
setWaitingForSqueaks(false);
setSqueaks((prevSqueaks) => {
if (!prevSqueaks) {
return loadedAddressSqueaks;
}
return prevSqueaks.concat(loadedAddressSqueaks);
});
};
const handleChangeSearchInput = (event) => {
setInputText(event.target.value);
};
const handleClickSearch = () => {
resetResults();
const encodedText = encodeURIComponent(inputText);
goToSearchPage(history, encodedText);
};
const resetResults = () => {
setSqueaks([]);
};
useEffect(() => {
getSqueaks(searchText, SQUEAKS_PER_PAGE, null);
}, [getSqueaks, searchText]);
// useEffect(() => {
// const stream = subscribeSqueaks(address);
// return () => stream.cancel();
// }, [address]);
useEffect(() => {
getNetwork();
}, []);
function NoSqueaksContent() {
return (
<div>
Unable to load squeaks.
</div>
);
}
function SqueaksContent() {
return (
<SqueakList
squeaks={squeaks}
network={network}
setSqueaksFn={setSqueaks}
/>
);
}
function GridContent() {
return (
<Grid container spacing={0}>
<Grid item xs={12} sm={9}>
<Paper className={classes.paper}>
{(squeaks)
? SqueaksContent()
: NoSqueaksContent()}
</Paper>
{ViewMoreSqueaksButton()}
</Grid>
<Grid item xs={12} sm={3}>
<Paper className={classes.paper} />
</Grid>
</Grid>
);
}
function AddressSqueaksContent() {
return (
<>
{GridContent()}
{waitingForSqueaks && <CircularProgress size={24} className={classes.buttonProgress} />}
</>
);
}
function ViewMoreSqueaksButton() {
return (
<>
<Grid item xs={12}>
<div className={classes.wrapper}>
{!waitingForSqueaks
&& (
<Button
variant="contained"
color="primary"
disabled={waitingForSqueaks}
onClick={() => {
const latestSqueak = squeaks.slice(-1).pop();
getSqueaks(searchText, SQUEAKS_PER_PAGE, latestSqueak);
}}
>
<ReplayIcon />
View more squeaks
</Button>
)}
{waitingForSqueaks && <CircularProgress size={48} className={classes.buttonProgress} />}
</div>
</Grid>
</>
);
}
function SearchBar() {
return (
<form className={classes.root} noValidate autoComplete="off">
<div>
<TextField
id="outlined-search"
label="Search field"
type="search"
variant="outlined"
onChange={handleChangeSearchInput}
value={inputText}
onKeyPress={(ev) => {
console.log(`Pressed keyCode ${ev.key}`);
if (ev.key === 'Enter') {
ev.preventDefault();
handleClickSearch();
}
}}
/>
</div>
<div>
<Button
variant="contained"
onClick={() => {
handleClickSearch();
}}
>
Search
</Button>
</div>
</form>
);
}
return (
<>
{SearchBar()}
{AddressSqueaksContent()}
</>
);
}

View file

@ -0,0 +1,6 @@
{
"name": "Search",
"version": "0.0.0",
"main": "Search.js",
"private": true
}

View file

@ -0,0 +1,60 @@
import { makeStyles } from '@material-ui/styles';
import { green } from '@material-ui/core/colors';
export default makeStyles((theme) => ({
dashedBorder: {
border: '1px dashed',
borderColor: theme.palette.primary.main,
padding: theme.spacing(2),
paddingTop: theme.spacing(4),
paddingBottom: theme.spacing(4),
marginTop: theme.spacing(1),
},
text: {
marginBottom: theme.spacing(2),
},
fab: {
position: 'fixed',
bottom: theme.spacing(4),
right: theme.spacing(4),
},
refreshFab: {
position: 'fixed',
top: theme.spacing(14),
margin: 'auto',
justifyContent: 'center',
},
root: {
display: 'flex',
alignItems: 'center',
'& .MuiTextField-root': {
margin: theme.spacing(1),
width: '25ch',
},
},
wrapper: {
margin: theme.spacing(1),
position: 'relative',
},
buttonSuccess: {
backgroundColor: green[500],
'&:hover': {
backgroundColor: green[700],
},
},
fabProgress: {
color: green[500],
position: 'absolute',
top: -6,
left: -6,
zIndex: 1,
},
buttonProgress: {
color: green[500],
position: 'absolute',
top: '50%',
left: '50%',
marginTop: -12,
marginLeft: -12,
},
}));

View file

@ -125,6 +125,8 @@ import {
DisconnectPeerReply as DisconnectSqueakPeerReply,
GetExternalAddressRequest,
GetExternalAddressReply,
GetSearchSqueakDisplaysRequest,
GetSearchSqueakDisplaysReply,
} from '../proto/squeak_admin_pb';
console.log('The value of REACT_APP_DEV_MODE_ENABLED is:', Boolean(process.env.REACT_APP_DEV_MODE_ENABLED));
@ -688,6 +690,24 @@ export function getAddressSqueakDisplaysRequest(address, limit, lastEntry, handl
// });
}
export function getSearchSqueakDisplaysRequest(searchText, limit, lastEntry, handleResponse) {
const request = new GetSearchSqueakDisplaysRequest();
request.setSearchText(searchText);
request.setLimit(limit);
request.setLastEntry(lastEntry);
makeRequest(
'getsearchsqueakdisplays',
request,
GetSearchSqueakDisplaysReply.deserializeBinary,
(response) => {
handleResponse(response.getSqueakDisplayEntriesList());
},
);
// client.getAddressSqueakDisplays(request, {}, (err, response) => {
// handleResponse(response.getSqueakDisplayEntriesList());
// });
}
export function createContactProfileRequest(profileName, squeakAddress, handleResponse, handleErr) {
const request = new CreateContactProfileRequest();
request.setProfileName(profileName);

View file

@ -1,17 +1,17 @@
{
"files": {
"main.js": "/static/js/main.496b0c9c.chunk.js",
"main.js.map": "/static/js/main.496b0c9c.chunk.js.map",
"main.js": "/static/js/main.251520a8.chunk.js",
"main.js.map": "/static/js/main.251520a8.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.9f0ba400.js",
"runtime-main.js.map": "/static/js/runtime-main.9f0ba400.js.map",
"static/css/2.ea4ba2f0.chunk.css": "/static/css/2.ea4ba2f0.chunk.css",
"static/js/2.32cf15fd.chunk.js": "/static/js/2.32cf15fd.chunk.js",
"static/js/2.32cf15fd.chunk.js.map": "/static/js/2.32cf15fd.chunk.js.map",
"static/js/2.4667e88e.chunk.js": "/static/js/2.4667e88e.chunk.js",
"static/js/2.4667e88e.chunk.js.map": "/static/js/2.4667e88e.chunk.js.map",
"index.html": "/index.html",
"precache-manifest.0a49f27336eda29f2836aad34e7bacdc.js": "/precache-manifest.0a49f27336eda29f2836aad34e7bacdc.js",
"precache-manifest.290aaf402a90ef5eddeabd13bb7d25d4.js": "/precache-manifest.290aaf402a90ef5eddeabd13bb7d25d4.js",
"service-worker.js": "/service-worker.js",
"static/css/2.ea4ba2f0.chunk.css.map": "/static/css/2.ea4ba2f0.chunk.css.map",
"static/js/2.32cf15fd.chunk.js.LICENSE.txt": "/static/js/2.32cf15fd.chunk.js.LICENSE.txt",
"static/js/2.4667e88e.chunk.js.LICENSE.txt": "/static/js/2.4667e88e.chunk.js.LICENSE.txt",
"static/media/font-awesome.min.css": "/static/media/fontawesome-webfont.fee66e71.woff",
"static/media/google.svg": "/static/media/google.695a3160.svg",
"static/media/logo.svg": "/static/media/logo.a0185b04.svg"
@ -19,7 +19,7 @@
"entrypoints": [
"static/js/runtime-main.9f0ba400.js",
"static/css/2.ea4ba2f0.chunk.css",
"static/js/2.32cf15fd.chunk.js",
"static/js/main.496b0c9c.chunk.js"
"static/js/2.4667e88e.chunk.js",
"static/js/main.251520a8.chunk.js"
]
}

View file

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.32cf15fd.chunk.js"></script><script src="/static/js/main.496b0c9c.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.4667e88e.chunk.js"></script><script src="/static/js/main.251520a8.chunk.js"></script></body></html>

View file

@ -1,23 +1,23 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "4dff8ab5d476563e42b33796d1dfa25e",
"revision": "4c76d87c4365bd354e794618937d3a78",
"url": "/index.html"
},
{
"revision": "6718651bd8fedd76a898",
"revision": "339f5ac38f31e7fed4b8",
"url": "/static/css/2.ea4ba2f0.chunk.css"
},
{
"revision": "6718651bd8fedd76a898",
"url": "/static/js/2.32cf15fd.chunk.js"
"revision": "339f5ac38f31e7fed4b8",
"url": "/static/js/2.4667e88e.chunk.js"
},
{
"revision": "279b8724b89bf7d504758b3fa917239f",
"url": "/static/js/2.32cf15fd.chunk.js.LICENSE.txt"
"url": "/static/js/2.4667e88e.chunk.js.LICENSE.txt"
},
{
"revision": "5bdedb9d2a958648e15b",
"url": "/static/js/main.496b0c9c.chunk.js"
"revision": "6d286f6ed33b177aac80",
"url": "/static/js/main.251520a8.chunk.js"
},
{
"revision": "cc9816de5a8639d377ea",

View file

@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
"/precache-manifest.0a49f27336eda29f2836aad34e7bacdc.js"
"/precache-manifest.290aaf402a90ef5eddeabd13bb7d25d4.js"
);
self.addEventListener('message', (event) => {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long