#659 - Implement a filter for the taxonomy dashboard

This commit is contained in:
Elio Struyf
2023-09-12 10:17:15 +02:00
parent 8967d236fe
commit feebdadaa5
4 changed files with 118 additions and 17 deletions
+12
View File
@@ -1,5 +1,17 @@
# Change Log
## [9.3.0] - 2023-xx-xx
### ✨ New features
### 🎨 Enhancements
- [#659](https://github.com/estruyf/vscode-front-matter/issues/659): Implement a filter for the taxonomy dashboard
### ⚡️ Optimizations
### 🐞 Fixes
## [9.2.0] - 2023-09-11
### ✨ New features
@@ -0,0 +1,56 @@
import { FilterIcon, XCircleIcon } from '@heroicons/react/outline';
import * as React from 'react';
export interface IFilterInputProps {
label?: string;
placeholder?: string;
value?: string;
disabled?: boolean;
onChange?: (value: string) => void;
onReset?: () => void;
}
export const FilterInput: React.FunctionComponent<IFilterInputProps> = ({
label,
placeholder,
value,
disabled,
onChange,
onReset,
}: React.PropsWithChildren<IFilterInputProps>) => {
return (
<div className="flex space-x-4 flex-1">
<div className="min-w-0">
{
label && (
<label htmlFor="filter" className="sr-only">
{label}
</label>
)
}
<div className="relative flex justify-center">
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<FilterIcon className={`h-4 w-4 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
</div>
<input
type="text"
name="filter"
className={`block w-full py-2 pl-10 pr-3 sm:text-sm appearance-none disabled:opacity-50 rounded bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border-[var(--vscode-editorWidget-border)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-[var(--vscode-focusBorder)] focus:outline-1 focus:outline-offset-0 focus:shadow-none focus:border-transparent`}
placeholder={placeholder || ""}
value={value}
onChange={(e) => onChange && onChange(e.target.value)}
disabled={disabled}
/>
{value && (
<button onClick={onReset} className="absolute inset-y-0 right-0 pr-3 flex items-center">
<XCircleIcon className={`h-5 w-5 text-[var(--vscode-input-foreground)]`} aria-hidden="true" />
</button>
)}
</div>
</div>
</div>
);
};
@@ -13,6 +13,9 @@ import { TaxonomyLookup } from './TaxonomyLookup';
import useThemeColors from '../../hooks/useThemeColors';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
import { FilterInput } from './FilterInput';
import { useDebounce } from '../../../hooks/useDebounce';
import { usePrevious } from '../../../panelWebView/hooks/usePrevious';
export interface ITaxonomyManagerProps {
data: TaxonomyData | undefined;
@@ -27,6 +30,9 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
}: React.PropsWithChildren<ITaxonomyManagerProps>) => {
const settings = useRecoilValue(SettingsSelector);
const { getColors } = useThemeColors();
const [filterValue, setFilterValue] = React.useState('');
const debounceFilterValue = useDebounce<string>(filterValue, 500);
const prevTaxonomy = usePrevious<string | null>(taxonomy);
const onCreate = () => {
Messenger.send(DashboardMessage.createTaxonomy, {
@@ -63,11 +69,15 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
return 0;
});
if (debounceFilterValue) {
crntItems = crntItems.filter((i) => i.toLowerCase().includes(debounceFilterValue.toLowerCase()));
}
return crntItems.filter(i => i);
}
return [];
}, [data, taxonomy]);
}, [data, taxonomy, debounceFilterValue]);
const unmappedItems = useMemo(() => {
let unmapped: string[] = [];
@@ -108,8 +118,20 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
}
}
return [...new Set(unmapped)].filter(i => i);
}, [items, taxonomy, pages, settings?.contentTypes]);
const unmappedItems = [...new Set(unmapped)].filter(i => i);
if (debounceFilterValue) {
return unmappedItems.filter((i) => i.toLowerCase().includes(debounceFilterValue.toLowerCase()));
}
return unmappedItems;
}, [items, taxonomy, pages, settings?.contentTypes, debounceFilterValue]);
React.useEffect(() => {
if (prevTaxonomy !== taxonomy) {
setFilterValue('');
}
}, [prevTaxonomy, taxonomy])
if (!taxonomy) {
return null;
@@ -134,19 +156,27 @@ export const TaxonomyManager: React.FunctionComponent<ITaxonomyManagerProps> = (
{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerDescription, taxonomy)}
</p>
</div>
<div>
<button
className={`inline-flex items-center px-3 py-1 border border-transparent text-xs leading-4 font-medium focus:outline-none rounded ${getColors(
`text-white dark:text-vulcan-500 bg-teal-600 hover:bg-teal-700 disabled:bg-gray-500`,
`text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] disabled:opacity-50`
)
}`}
title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}
onClick={onCreate}
>
<PlusSmIcon className={`mr-2 h-6 w-6`} />
<span className={`text-sm`}>{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}</span>
</button>
<div className='flex gap-4 justify-center items-center'>
<FilterInput
placeholder='Filter'
value={filterValue}
onChange={(value) => setFilterValue(value)}
onReset={() => setFilterValue('')} />
<div>
<button
className={`inline-flex items-center px-3 py-1 border border-transparent text-xs leading-4 font-medium focus:outline-none rounded ${getColors(
`text-white dark:text-vulcan-500 bg-teal-600 hover:bg-teal-700 disabled:bg-gray-500`,
`text-[var(--vscode-button-foreground)] bg-[var(--frontmatter-button-background)] hover:bg-[var(--vscode-button-hoverBackground)] disabled:opacity-50`
)
}`}
title={l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}
onClick={onCreate}
>
<PlusSmIcon className={`mr-2 h-6 w-6`} />
<span className={`text-sm`}>{l10n.t(LocalizationKey.dashboardTaxonomyViewTaxonomyManagerButtonCreate, taxonomy)}</span>
</button>
</div>
</div>
</div>
@@ -90,7 +90,10 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
</NavigationBar>
<div className={`w-10/12 h-full overflow-hidden`}>
<TaxonomyManager data={taxonomySettings} taxonomy={selectedTaxonomy} pages={pages} />
<TaxonomyManager
data={taxonomySettings}
taxonomy={selectedTaxonomy}
pages={pages} />
</div>
</div>