Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7205aeab77 |
@ -1,40 +1,119 @@
|
|||||||
import { Index } from 'flexsearch';
|
import { Index } from 'flexsearch';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import DebouncedInput from './DebouncedInput';
|
import DebouncedInput from './DebouncedInput';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
|
||||||
export default function Catalog({ datasets }: { datasets: any[] }) {
|
export default function Catalog({
|
||||||
|
datasets,
|
||||||
|
facets,
|
||||||
|
}: {
|
||||||
|
datasets: any[];
|
||||||
|
facets: string[];
|
||||||
|
}) {
|
||||||
const [indexFilter, setIndexFilter] = useState('');
|
const [indexFilter, setIndexFilter] = useState('');
|
||||||
const index = new Index({ tokenize: "full"});
|
const index = new Index({ tokenize: 'full' });
|
||||||
datasets.forEach((dataset) =>
|
datasets.forEach((dataset) =>
|
||||||
index.add(
|
index.add(
|
||||||
dataset._id,
|
dataset._id,
|
||||||
|
//This will join every metadata value + the url_path into one big string and index that
|
||||||
Object.entries(dataset.metadata).reduce(
|
Object.entries(dataset.metadata).reduce(
|
||||||
(acc, curr) => acc + ' ' + curr.toString(),
|
(acc, curr) => acc + ' ' + curr[1].toString(),
|
||||||
''
|
''
|
||||||
) + ' ' + dataset.url_path
|
) +
|
||||||
|
' ' +
|
||||||
|
dataset.url_path
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return (
|
|
||||||
<>
|
const facetValues = facets
|
||||||
<DebouncedInput
|
? facets.reduce((acc, facet) => {
|
||||||
value={indexFilter ?? ''}
|
const possibleValues = datasets.reduce((acc, curr) => {
|
||||||
onChange={(value) => setIndexFilter(String(value))}
|
const facetValue = curr.metadata[facet];
|
||||||
className="p-2 text-sm shadow border border-block"
|
if (facetValue) {
|
||||||
placeholder="Search all datasets..."
|
return Array.isArray(facetValue)
|
||||||
/>
|
? acc.concat(facetValue)
|
||||||
<ul>
|
: acc.concat([facetValue]);
|
||||||
{datasets
|
}
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
acc[facet] = {
|
||||||
|
possibleValues: [...new Set(possibleValues)],
|
||||||
|
selectedValue: null,
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const { register, watch } = useForm(facetValues);
|
||||||
|
|
||||||
|
const filteredDatasets = datasets
|
||||||
|
// First filter by flex search
|
||||||
.filter((dataset) =>
|
.filter((dataset) =>
|
||||||
indexFilter !== ''
|
indexFilter !== ''
|
||||||
? index.search(indexFilter).includes(dataset._id)
|
? index.search(indexFilter).includes(dataset._id)
|
||||||
: true
|
: true
|
||||||
)
|
)
|
||||||
.map((dataset) => (
|
//Then check if the selectedValue for the given facet is included in the dataset metadata
|
||||||
|
.filter((dataset) => {
|
||||||
|
//Avoids a server rendering breakage
|
||||||
|
if (!watch() || Object.keys(watch()).length === 0) return true
|
||||||
|
//This will filter only the key pairs of the metadata values that were selected as facets
|
||||||
|
const datasetFacets = Object.entries(dataset.metadata).filter((entry) =>
|
||||||
|
facets.includes(entry[0])
|
||||||
|
);
|
||||||
|
//Check if the value present is included in the selected value in the form
|
||||||
|
return datasetFacets.every((elem) =>
|
||||||
|
watch()[elem[0]].selectedValue
|
||||||
|
? (elem[1] as string | string[]).includes(
|
||||||
|
watch()[elem[0]].selectedValue
|
||||||
|
)
|
||||||
|
: true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DebouncedInput
|
||||||
|
value={indexFilter ?? ''}
|
||||||
|
onChange={(value) => setIndexFilter(String(value))}
|
||||||
|
className="p-2 text-sm shadow border border-block mr-1"
|
||||||
|
placeholder="Search all datasets..."
|
||||||
|
/>
|
||||||
|
{Object.entries(facetValues).map((elem) => (
|
||||||
|
<select
|
||||||
|
key={elem[0]}
|
||||||
|
defaultValue=""
|
||||||
|
className="p-2 ml-1 text-sm shadow border border-block"
|
||||||
|
{...register(elem[0] + '.selectedValue')}
|
||||||
|
>
|
||||||
|
<option value="">
|
||||||
|
Filter by {elem[0]}
|
||||||
|
</option>
|
||||||
|
{(elem[1] as { possibleValues: string[] }).possibleValues.map(
|
||||||
|
(val) => (
|
||||||
|
<option
|
||||||
|
key={val}
|
||||||
|
className="dark:bg-white dark:text-black"
|
||||||
|
value={val}
|
||||||
|
>
|
||||||
|
{val}
|
||||||
|
</option>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
))}
|
||||||
|
<ul>
|
||||||
|
{filteredDatasets.map((dataset) => (
|
||||||
<li key={dataset._id}>
|
<li key={dataset._id}>
|
||||||
<a href={dataset.url_path}>{dataset.metadata.title ? dataset.metadata.title : dataset.url_path}</a>
|
<a href={dataset.url_path}>
|
||||||
|
{dataset.metadata.title
|
||||||
|
? dataset.metadata.title
|
||||||
|
: dataset.url_path}
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -91,7 +91,7 @@ const parse = async function (source, format, scope) {
|
|||||||
],
|
],
|
||||||
format,
|
format,
|
||||||
},
|
},
|
||||||
scope: { ...scope, ...data},
|
scope,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
16
examples/learn-example/package-lock.json
generated
16
examples/learn-example/package-lock.json
generated
@ -31,6 +31,7 @@
|
|||||||
"papaparse": "^5.4.1",
|
"papaparse": "^5.4.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
|
"react-hook-form": "^7.43.9",
|
||||||
"react-vega": "^7.6.0",
|
"react-vega": "^7.6.0",
|
||||||
"rehype-autolink-headings": "^6.1.1",
|
"rehype-autolink-headings": "^6.1.1",
|
||||||
"rehype-katex": "^6.0.3",
|
"rehype-katex": "^6.0.3",
|
||||||
@ -9301,6 +9302,21 @@
|
|||||||
"react": "^18.2.0"
|
"react": "^18.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-hook-form": {
|
||||||
|
"version": "7.43.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.43.9.tgz",
|
||||||
|
"integrity": "sha512-AUDN3Pz2NSeoxQ7Hs6OhQhDr6gtF9YRuutGDwPQqhSUAHJSgGl2VeY3qN19MG0SucpjgDiuMJ4iC5T5uB+eaNQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.22.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/react-hook-form"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17 || ^18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
"papaparse": "^5.4.1",
|
"papaparse": "^5.4.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
|
"react-hook-form": "^7.43.9",
|
||||||
"react-vega": "^7.6.0",
|
"react-vega": "^7.6.0",
|
||||||
"rehype-autolink-headings": "^6.1.1",
|
"rehype-autolink-headings": "^6.1.1",
|
||||||
"rehype-katex": "^6.0.3",
|
"rehype-katex": "^6.0.3",
|
||||||
@ -48,9 +49,9 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.9",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
|
"@types/flexsearch": "^0.7.3",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"postcss": "^8.4.23",
|
"postcss": "^8.4.23",
|
||||||
"tailwindcss": "^3.3.1",
|
"tailwindcss": "^3.3.1"
|
||||||
"@types/flexsearch": "^0.7.3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es6",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user