Files
vscode-front-matter/src/dashboardWebView/components/Header/Sorting.tsx
2024-01-16 14:22:17 +01:00

203 lines
6.3 KiB
TypeScript

import { Messenger, messageHandler } from '@estruyf/vscode/dist/client';
import { Menu } from '@headlessui/react';
import * as React from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
import { ExtensionState } from '../../../constants';
import { SortOrder, SortType } from '../../../models';
import { SortOption } from '../../constants/SortOption';
import { DashboardMessage } from '../../DashboardMessage';
import { NavigationType } from '../../models';
import { SortingOption } from '../../models/SortingOption';
import { SearchSelector, SettingsSelector, SortingAtom } from '../../state';
import { MenuButton, MenuItem, MenuItems } from '../Menu';
import { Sorting as SortingHelpers } from '../../../helpers/Sorting';
import * as l10n from '@vscode/l10n';
import { LocalizationKey } from '../../../localization';
export interface ISortingProps {
disableCustomSorting?: boolean;
view: NavigationType;
}
export const Sorting: React.FunctionComponent<ISortingProps> = ({
disableCustomSorting,
view
}: React.PropsWithChildren<ISortingProps>) => {
const [crntSorting, setCrntSorting] = useRecoilState(SortingAtom);
const searchValue = useRecoilValue(SearchSelector);
const settings = useRecoilValue(SettingsSelector);
const [crntSort, setCrntSort] = React.useState<SortingOption | null>(null);
const sortOptions: SortingOption[] = [
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingLastModifiedAsc),
id: SortOption.LastModifiedAsc,
order: SortOrder.asc,
type: SortType.date
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingLastModifiedDesc),
id: SortOption.LastModifiedDesc,
order: SortOrder.desc,
type: SortType.date
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingFilenameAsc),
id: SortOption.FileNameAsc,
order: SortOrder.asc,
type: SortType.string
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingFilenameDesc),
id: SortOption.FileNameDesc,
order: SortOrder.desc,
type: SortType.string
}
];
const contentSortOptions: SortingOption[] = [
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingPublishedAsc),
id: SortOption.PublishedAsc,
order: SortOrder.asc,
type: SortType.date
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingPublishedDesc),
id: SortOption.PublishedDesc,
order: SortOrder.desc,
type: SortType.date
}
];
const mediaSortOptions: SortingOption[] = [
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingSizeAsc),
id: SortOption.SizeAsc,
order: SortOrder.asc,
type: SortType.number
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingSizeDesc),
id: SortOption.SizeDesc,
order: SortOrder.desc,
type: SortType.number
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingCaptionAsc),
id: SortOption.CaptionAsc,
order: SortOrder.asc,
type: SortType.string
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingCaptionDesc),
id: SortOption.CaptionDesc,
order: SortOrder.desc,
type: SortType.string
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingAltAsc),
id: SortOption.AltAsc,
order: SortOrder.asc,
type: SortType.string
},
{
name: l10n.t(LocalizationKey.dashboardHeaderSortingAltDesc),
id: SortOption.AltDesc,
order: SortOrder.desc,
type: SortType.string
}
];
const updateSorting = (value: SortingOption) => {
Messenger.send(DashboardMessage.setState, {
key: `${view === NavigationType.Contents
? ExtensionState.Dashboard.Contents.Sorting
: ExtensionState.Dashboard.Media.Sorting
}`,
value: value
});
setCrntSorting(value);
};
let allOptions = [...sortOptions];
if (view === NavigationType.Media) {
allOptions = [...allOptions, ...mediaSortOptions];
} else if (view === NavigationType.Contents) {
allOptions = [...contentSortOptions, ...allOptions];
}
allOptions = allOptions.sort(SortingHelpers.alphabetically('name'));
if (settings?.customSorting && !disableCustomSorting) {
allOptions = [
...allOptions,
...settings.customSorting.map((s) => ({
title: s.title || s.name,
name: s.name,
id: s.id || `${s.name}-${s.order}`,
order: s.order,
type: s.type
}))
];
}
React.useEffect(() => {
const getSorting = async () => {
let crntSortingOption = crntSorting;
if (!crntSortingOption) {
const sortingState = await messageHandler.request<{ key: string; value: SortingOption; }>(DashboardMessage.getState, { key: view === NavigationType.Media ? ExtensionState.Dashboard.Media.Sorting : ExtensionState.Dashboard.Contents.Sorting });
crntSortingOption = sortingState?.value || null;
if (crntSortingOption === null) {
if (view === NavigationType.Contents && settings?.dashboardState.contents.defaultSorting) {
crntSortingOption =
allOptions.find((f) => f.id === settings?.dashboardState.contents.defaultSorting) || null;
} else if (
view === NavigationType.Media &&
settings?.dashboardState.media.defaultSorting
) {
crntSortingOption =
allOptions.find((f) => f.id === settings?.dashboardState.media.defaultSorting) || null;
}
}
}
let sort = allOptions.find((x) => x.id === crntSortingOption?.id) || sortOptions[0];
setCrntSort(sort);
};
getSorting();
}, [crntSorting]);
if (crntSort === null) {
return null;
}
return (
<div className="flex items-center">
<Menu as="div" className="relative z-10 inline-block text-left">
<MenuButton
label={l10n.t(LocalizationKey.dashboardHeaderSortingLabel)}
title={crntSort?.title || crntSort?.name || ''}
disabled={!!searchValue}
/>
<MenuItems widthClass="w-48" disablePopper>
{allOptions.map((option) => (
<MenuItem
key={option.id}
title={option.title || option.name}
value={option}
isCurrent={option.id === crntSort.id}
onClick={(value) => updateSorting(value)}
/>
))}
</MenuItems>
</Menu>
</div>
);
};