added local search to stream
This commit is contained in:
parent
eae89dbe3a
commit
694893baa7
|
|
@ -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>
|
)
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue