mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-26 00:16:51 +00:00
Put tags and search of changelogs and versions in URL
This commit is contained in:
@@ -1,29 +1,26 @@
|
||||
import { useMemo, useState } from 'preact/hooks'
|
||||
import { Btn, TextInput } from '..'
|
||||
import { useLocale } from '../../contexts'
|
||||
import { useSearchParam } from '../../hooks'
|
||||
import { useTags } from '../../hooks/useTags'
|
||||
import type { Change } from '../../services'
|
||||
import { ChangelogEntry } from './ChangelogEntry'
|
||||
import { ChangelogTag } from './ChangelogTag'
|
||||
|
||||
const SEARCH_KEY = 'search'
|
||||
|
||||
interface Props {
|
||||
changes: Change[] | undefined,
|
||||
defaultOrder: 'asc' | 'desc',
|
||||
}
|
||||
export function ChangelogList({ changes, defaultOrder }: Props) {
|
||||
const { locale } = useLocale()
|
||||
|
||||
const [search, setSearch] = useState('')
|
||||
const [tags, setTags] = useState<string[]>([])
|
||||
const toggleTag = (tag: string) => {
|
||||
if (!tags.includes(tag)) {
|
||||
setTags([...tags, tag])
|
||||
} else {
|
||||
setTags(tags.filter(t => t !== tag))
|
||||
}
|
||||
}
|
||||
|
||||
const [search, setSearch] = useSearchParam(SEARCH_KEY)
|
||||
const [tags, toggleTag] = useTags()
|
||||
|
||||
const filteredChangelogs = useMemo(() => {
|
||||
const query = search.split(' ').map(q => q.trim().toLowerCase()).filter(q => q.length > 0)
|
||||
const query = (search ?? '').split(' ').map(q => q.trim().toLowerCase()).filter(q => q.length > 0)
|
||||
if (query.length === 0 && tags.length === 0) return changes
|
||||
return changes?.filter(change => {
|
||||
if (!tags.every(tag => change.tags.includes(tag))) {
|
||||
@@ -48,11 +45,11 @@ export function ChangelogList({ changes, defaultOrder }: Props) {
|
||||
return <>
|
||||
<div class="changelog-query">
|
||||
<TextInput class="btn btn-input changelog-search" list="sound-list" placeholder={locale('changelog.search')}
|
||||
value={search} onChange={setSearch} />
|
||||
value={search} onChange={v => setSearch(v, true)} />
|
||||
<Btn icon={sort ? 'sort_desc' : 'sort_asc'} label={sort ? 'Newest first' : 'Oldest first'} onClick={() => setSort(!sort)} />
|
||||
</div>
|
||||
{tags.length > 0 && <div class="changelog-tags">
|
||||
{tags.map(tag => <ChangelogTag label={tag} onClick={() => setTags(tags.filter(t => t !== tag))} />)}
|
||||
{tags.map(tag => <ChangelogTag label={tag} onClick={() => toggleTag(tag)} />)}
|
||||
</div>}
|
||||
<div class="changelog-list">
|
||||
{sortedChangelogs === undefined
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { useMemo, useState } from 'preact/hooks'
|
||||
import { Checkbox, TextInput } from '..'
|
||||
import { useLocale } from '../../contexts'
|
||||
import { useSearchParam } from '../../hooks'
|
||||
import type { VersionMeta } from '../../services'
|
||||
import { VersionEntry } from './VersionEntry'
|
||||
|
||||
const SEARCH_KEY = 'search'
|
||||
|
||||
interface Props {
|
||||
versions: VersionMeta[]
|
||||
link?: (id: string) => string
|
||||
@@ -12,11 +15,11 @@ export function VersionList({ versions, link }: Props) {
|
||||
const { locale } = useLocale()
|
||||
|
||||
const [snapshots, setSnapshots] = useState(true)
|
||||
const [search, setSearch] = useState('')
|
||||
const [search, setSearch] = useSearchParam(SEARCH_KEY)
|
||||
|
||||
const filteredVersions = useMemo(() => versions.filter(v => {
|
||||
if (v.type === 'snapshot' && !snapshots) return false
|
||||
return v.id.includes(search)
|
||||
return v.id.includes(search ?? '')
|
||||
}), [versions, snapshots, search])
|
||||
|
||||
|
||||
|
||||
20
src/app/hooks/useTags.ts
Normal file
20
src/app/hooks/useTags.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useMemo } from 'preact/hooks'
|
||||
import { useSearchParam } from './useSearchParam'
|
||||
|
||||
const TAG_KEY = 'tags'
|
||||
const TAG_SEP = '|'
|
||||
|
||||
export function useTags(): [string[], (tag: string, force?: boolean) => void] {
|
||||
const [tags, setTags] = useSearchParam(TAG_KEY)
|
||||
const activeTags = useMemo(() => tags?.split(TAG_SEP) ?? [], [tags])
|
||||
|
||||
const toggleTag = (tag: string, force?: boolean) => {
|
||||
if (force === false || (activeTags.includes(tag) && force !== true)) {
|
||||
setTags(activeTags.filter(t => t !== tag).join(TAG_SEP), true)
|
||||
} else {
|
||||
setTags([...activeTags, tag].sort().join(TAG_SEP), true)
|
||||
}
|
||||
}
|
||||
|
||||
return [activeTags, toggleTag]
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { useMemo, useState } from 'preact/hooks'
|
||||
import config from '../../config.json'
|
||||
import { Btn, BtnMenu, ChangelogTag, GuideCard, TextInput } from '../components'
|
||||
import { useLocale, useTitle, useVersion } from '../contexts'
|
||||
import { useSearchParam } from '../hooks'
|
||||
import { useTags } from '../hooks/useTags'
|
||||
import type { VersionId } from '../services'
|
||||
|
||||
interface Guide {
|
||||
@@ -14,9 +14,6 @@ interface Guide {
|
||||
|
||||
declare var __GUIDES__: Guide[]
|
||||
|
||||
const TAG_KEY = 'tags'
|
||||
const TAG_SEP = '|'
|
||||
|
||||
interface Props {
|
||||
path?: string
|
||||
}
|
||||
@@ -26,15 +23,7 @@ export function Guides({}: Props) {
|
||||
useTitle(locale('title.guides'))
|
||||
|
||||
const [search, setSearch] = useState('')
|
||||
const [tags, setTags] = useSearchParam(TAG_KEY)
|
||||
const activeTags = useMemo(() => tags?.split(TAG_SEP) ?? [], [tags])
|
||||
const toggleTag = (tag: string) => {
|
||||
if (activeTags.includes(tag)) {
|
||||
setTags(activeTags.filter(t => t !== tag).join(TAG_SEP))
|
||||
} else {
|
||||
setTags([...activeTags, tag].sort().join(TAG_SEP))
|
||||
}
|
||||
}
|
||||
const [activeTags, toggleTag] = useTags()
|
||||
|
||||
const [versionFilter, setVersionFiler] = useState(false)
|
||||
|
||||
@@ -59,7 +48,7 @@ export function Guides({}: Props) {
|
||||
return content.includes(q)
|
||||
})
|
||||
})
|
||||
}, [versionedGuides, search, tags])
|
||||
}, [versionedGuides, search, activeTags])
|
||||
|
||||
return <main>
|
||||
<div class="guides">
|
||||
|
||||
Reference in New Issue
Block a user