in pca-ui/src/www/src/routes/Search.js [31:222]
function Search({ setAlert }) {
const [editing, setEditing] = useState(true);
const [query, setQuery] = useState({});
const [shouldSearch, setShouldSearch] = useState(true);
useEffect(() => {
(query.timestampTo && query.timestampTo) ||
(!query.timestampTo && !query.timestampFrom)
? setShouldSearch(true)
: setShouldSearch(false);
}, [query.timestampTo, query.timestampFrom]);
const { data: entities, error: errorEntities } = useSWR(
`/entities`,
getEntities
);
const { data: languageCodes, error: errorLanguageCodes } = useSWR(
`/languages`,
getLanguages
);
const { data: results, error: errorResults } = useSWR(
shouldSearch ? [`/search`, query] : null,
() => search(query)
);
const handleDates = (dates) => {
const [start, end] = dates;
const timestampFrom = new Date(start).getTime();
const timestampTo = end ? new Date(end).setUTCHours(23, 59, 59, 999) : null;
handleQueryInput(timestampFrom, "timestampFrom");
handleQueryInput(timestampTo, "timestampTo");
};
const filterEmptyKeys = (obj) => {
const shouldKeep = (v) => (Array.isArray(v) ? v.length > 0 : v !== null);
return Object.fromEntries(
Object.entries(obj).filter(([_, v]) => shouldKeep(v))
);
};
const handleQueryInput = (input, field) =>
setQuery((q) => filterEmptyKeys({ ...q, [field]: input }));
const onClick = () => {
setEditing(false);
};
useDangerAlert(errorEntities || errorLanguageCodes || errorResults, setAlert);
return (
<>
<h3>Search</h3>
<Form className="mb-5">
<Form.Group className="mb-5">
<Form.Label>
<h5>Language Code</h5>
</Form.Label>
<Select
onChange={(event) => handleQueryInput(event.value, "language")}
options={(languageCodes || []).map((code, i) => ({
label: code,
value: code,
}))}
isLoading={!languageCodes && !errorLanguageCodes}
value={
query.language
? { label: query.language, value: query.language }
: null
}
/>
<Button
className="mt-2"
variant="outline-secondary"
onClick={() => {
handleQueryInput(null, "language");
}}
>
Clear
</Button>
</Form.Group>
<Form.Group className="mb-5">
<Form.Label>
<h5>Date Range</h5>
</Form.Label>
<DatePicker
selectsRange
startDate={query.timestampFrom}
endDate={query.timestampTo}
dateFormat="yyyy-MM-dd"
onChange={handleDates}
maxDate={new Date()}
placeholderText="Select a start and end date"
/>
<Button
className="mt-2"
variant="outline-secondary"
onClick={() => {
handleQueryInput(null, "timestampTo");
handleQueryInput(null, "timestampFrom");
}}
>
Clear
</Button>
</Form.Group>
<Form.Group className="mb-5">
<Form.Label>
<h5>Sentiment</h5>
</Form.Label>
<div className="d-flex gap-3">
<p className="align-self-end mb-0">The</p>
<Select
className="flex-grow-1"
options={sentimentWhat}
onChange={(event) =>
handleQueryInput(event.value, "sentimentWhat")
}
value={
sentimentWhat.find((o) => o.value === query.sentimentWhat) ||
null
}
/>
<p className="align-self-end mb-0"> sentiment of the</p>
<Select
className="flex-grow-1"
options={sentimentWho}
onChange={(event) =>
handleQueryInput(event.value, "sentimentWho")
}
value={
sentimentWho.find((o) => o.value === query.sentimentWho) || null
}
/>
<p className="align-self-end mb-0">is</p>
<Select
className="flex-grow-1"
options={sentimentDirection}
onChange={(event) =>
handleQueryInput(event.value, "sentimentDirection")
}
value={
sentimentDirection.find(
(o) => o.value === query.sentimentDirection
) || null
}
/>
</div>
<Button
className="mt-2"
variant="outline-secondary"
onClick={() => {
handleQueryInput(null, "sentimentWhat");
handleQueryInput(null, "sentimentWho");
handleQueryInput(null, "sentimentDirection");
}}
>
Clear
</Button>
</Form.Group>
<Form.Group className="mb-5">
<Form.Label>
<h5>Entities</h5>
</Form.Label>
<MultiSelect
options={(entities || []).map((entity) => ({
value: entity,
label: entity,
}))}
onChange={(value) => handleQueryInput(value, "entity")}
isLoading={!entities && !errorEntities}
/>
</Form.Group>
<Button bg={"primary"} onClick={onClick}>
Search
</Button>
</Form>
{!editing && (
<ContactTable
data={results}
loading={!results && !errorResults}
empty={<NoMatches />}
/>
)}
</>
);
}