add listing filter to web

This commit is contained in:
Roland Osborne 2022-10-28 11:18:49 -07:00
parent 3e37cde3f7
commit adeebf9b00
4 changed files with 72 additions and 15 deletions

View File

@ -1,12 +1,10 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil'; import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getListing(server) { export async function getListing(server, filter) {
let host = ""; const host = server ? `https://${server}` : '';
if (server) { const param = filter ? `?filter=${filter}` : '';
host = `https://${server}`;
}
let listing = await fetchWithTimeout(`${host}/account/listing`, { method: 'GET' }); let listing = await fetchWithTimeout(`${host}/account/listing${param}`, { method: 'GET' });
checkResponse(listing); checkResponse(listing);
return await listing.json(); return await listing.json();
} }

View File

@ -1,6 +1,6 @@
import { Modal, Button, Input, List } from 'antd'; import { Modal, Button, Input, List } from 'antd';
import { ListingWrapper } from './Listing.styled'; import { ListingWrapper } from './Listing.styled';
import { DownOutlined, CloseOutlined, DatabaseOutlined, SearchOutlined } from '@ant-design/icons'; import { UserOutlined, FilterOutlined, DownOutlined, CloseOutlined, DatabaseOutlined, SearchOutlined } from '@ant-design/icons';
import { useListing } from './useListing.hook'; import { useListing } from './useListing.hook';
import { ListingItem } from './listingItem/ListingItem'; import { ListingItem } from './listingItem/ListingItem';
@ -24,10 +24,29 @@ export function Listing({ closeListing, openContact }) {
return ( return (
<ListingWrapper> <ListingWrapper>
<div class="search"> <div class="search">
<div class="node"> { !state.showFilter && (
<Input bordered={false} allowClear={true} placeholder="Server" <div class="showfilter" onClick={actions.showFilter}>
prefix={<DatabaseOutlined />} value={state.node} spellCheck="false" <FilterOutlined />
disabled={state.disabled} onChange={(e) => actions.onNode(e.target.value)} /> </div>
)}
{ state.showFilter && (
<div class="hidefilter" onClick={actions.hideFilter}>
<FilterOutlined />
</div>
)}
<div class="params">
<div class="node">
<Input bordered={false} allowClear={true} placeholder="Server"
prefix={<DatabaseOutlined />} value={state.node} spellCheck="false"
disabled={state.disabled} onChange={(e) => actions.onNode(e.target.value)} />
</div>
{ state.showFilter && (
<div class="username">
<Input bordered={false} allowClear={true} placeholder="Username"
prefix={<UserOutlined />} value={state.username} spellCheck="false"
onChange={(e) => actions.setUsername(e.target.value)} />
</div>
)}
</div> </div>
<div class="inline"> <div class="inline">
<Button type="text" icon={<SearchOutlined />} loading={state.busy} onClick={getListing}></Button> <Button type="text" icon={<SearchOutlined />} loading={state.busy} onClick={getListing}></Button>

View File

@ -27,21 +27,50 @@ export const ListingWrapper = styled.div`
border-bottom: 1px solid ${Colors.divider}; border-bottom: 1px solid ${Colors.divider};
display: flex; display: flex;
flex-direction: row; flex-direction: row;
height: 48px; min-height: 48px;
padding-left: 16px; padding-left: 16px;
padding-right: 16px; padding-right: 16px;
padding-top: 8px; padding-top: 8px;
padding-bottom: 8px; padding-bottom: 8px;
flex-shrink: 0;
.showfilter {
color: ${Colors.disabled};
font-size: 18px;
padding-right: 8px;
display: flex;
align-items: center;
cursor: pointer;
}
.hidefilter {
color: ${Colors.enabled};
font-size: 18px;
padding-right: 8px;
display: flex;
align-items: center;
cursor: pointer;
}
.params {
flex-grow: 1;
}
.username {
border: 1px solid ${Colors.divider};
background-color: ${Colors.white};
border-radius: 8px;
margin-top: 4px;
}
.node { .node {
border: 1px solid ${Colors.divider}; border: 1px solid ${Colors.divider};
background-color: ${Colors.white}; background-color: ${Colors.white};
border-radius: 8px; border-radius: 8px;
flex-grow: 1;
} }
.inline { .inline {
padding-left: 8px; padding-left: 4px;
display: flex; display: flex;
flex-shrink: 0; flex-shrink: 0;
align-items: center; align-items: center;

View File

@ -11,6 +11,8 @@ export function useListing() {
busy: false, busy: false,
disabled: true, disabled: true,
display: null, display: null,
showFilter: false,
username: null,
}); });
const profile = useContext(ProfileContext); const profile = useContext(ProfileContext);
@ -25,13 +27,22 @@ export function useListing() {
}, [state.node]); }, [state.node]);
const actions = { const actions = {
showFilter: () => {
updateState({ showFilter: true });
},
hideFilter: () => {
updateState({ showFilter: false });
},
setUsername: (username) => {
updateState({ username });
},
onNode: (value) => { onNode: (value) => {
updateState({ node: value }); updateState({ node: value });
}, },
getListing: async () => { getListing: async () => {
updateState({ busy: true }); updateState({ busy: true });
try { try {
let contacts = await getListing(state.node); let contacts = await getListing(state.node, state.username);
let filtered = contacts.filter(contact => (contact.guid !== profile.state.profile.guid)); let filtered = contacts.filter(contact => (contact.guid !== profile.state.profile.guid));
let sorted = filtered.sort((a, b) => { let sorted = filtered.sort((a, b) => {
if (a?.name < b?.name) { if (a?.name < b?.name) {