added local search to stream

This commit is contained in:
Orion Reed 2023-08-12 15:22:18 +01:00
parent eae89dbe3a
commit 694893baa7
1 changed files with 68 additions and 45 deletions

View File

@ -1,19 +1,32 @@
import { import {
Group, Group,
Text, Text,
useMantineTheme,
Container, Container,
Stack, Stack,
Flex, Flex,
createStyles, createStyles,
Divider, Title,
TextInput,
} from '@mantine/core' } from '@mantine/core'
import { format } from 'date-fns'
import { useEffect, useState } from 'preact/hooks'
import { Header } from '@/components/Header' import { Header } from '@/components/Header'
import Markdown from 'markdown-to-jsx' import Markdown from 'markdown-to-jsx'
import MiniSearch from 'minisearch'
import { signal } from '@preact/signals'
import { friendlyDate, getJsonl } from '@/utils'
const search = signal('')
const margin = '0.3em' const margin = '0.3em'
const streamItems = await getJsonl('stream.jsonl')
const miniSearch = new MiniSearch({
fields: ['text'], // fields to index for full-text search
storeFields: ['date', 'text'], // fields to return with search results
searchOptions: {
fuzzy: 0.2,
prefix: true,
},
})
miniSearch.addAll(streamItems)
const useStyles = createStyles((theme) => ({ const useStyles = createStyles((theme) => ({
group: { group: {
@ -23,7 +36,7 @@ const useStyles = createStyles((theme) => ({
}, },
item: { item: {
flexWrap: 'nowrap', flexWrap: 'nowrap',
'& :first-child': { '& :first-of-type': {
marginTop: 0, marginTop: 0,
}, },
'& p': { '& p': {
@ -54,23 +67,18 @@ const useStyles = createStyles((theme) => ({
marginRight: '0.2em', marginRight: '0.2em',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
}, },
search: {
fontFamily: theme.headings.fontFamily,
// border: `1px solid red`,
fontSize: '4em',
'& :focus': {
border: `1px solid ${theme.black}`,
},
},
})) }))
function friendlyDate(dateString: string): string {
const inputDate = new Date(dateString)
return format(inputDate, 'do MMM yyyy')
}
async function getStream() {
const response = await fetch('stream.jsonl')
return await (await response.text()).split('\n').map((post) => {
return JSON.parse(post)
})
}
function StreamItem({ date, markdown }) { function StreamItem({ date, markdown }) {
const { classes } = useStyles() const { classes } = useStyles()
const black = useMantineTheme().black
return ( return (
<Group className={classes.item} align="start"> <Group className={classes.item} align="start">
<Text color="dimmed" className={classes.date}> <Text color="dimmed" className={classes.date}>
@ -83,34 +91,49 @@ function StreamItem({ date, markdown }) {
) )
} }
type StreamItem = {
date: string
markdown: string
}
function Search() {
const { classes } = useStyles()
return (
<TextInput
onInput={(event) => {
search.value = event.target.value
}}
my="sm"
className={classes.search}
placeholder="Search"
/>
)
}
export default function Stream() { export default function Stream() {
const { classes } = useStyles() const { classes } = useStyles()
const [stream, setPost] = useState<Array<object>>(null) console.log(search.value)
useEffect(() => { const results = !search.value ? streamItems : miniSearch.search(search.value)
getStream().then(setPost) console.log(results)
}, [])
if (!stream) { return (
return <Text>Loading stream...</Text> <>
} else { <Header />
return ( <Container size="40em" className={classes.group}>
<> <Title order={2}>What is this?</Title>
<Header /> <Text>
<Container size="40em" className={classes.group}> This <b>stream</b> is a place for me to think out loud and to share as
<Text> I learn. It's not a place for well-formed ideas or for things I'm sure
This <b>stream</b> is a place for me to think out loud and to share about. It's a place to explore, to be wrong, and to trust the reader
as I learn. It's not a place for well-formed ideas or for things I'm (and myself) that this is okay.
sure about. It's a place to explore, to be wrong, and to trust the </Text>
reader (and myself) that this is okay. <Search />
</Text> <Stack>
<Divider my="lg" /> {results.map((s) => {
<Stack> return <StreamItem markdown={s.text} date={s.date} />
{stream.map((s) => { })}
return <StreamItem markdown={s.markdown} date={s.date} /> </Stack>
})} </Container>
</Stack> </>
</Container> )
</>
)
}
} }