mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-06-19 17:45:44 +02:00
#659 - Implement a filter for the taxonomy dashboard
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user