1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix item list layout header rendering bug

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-01-26 15:51:51 -05:00
parent 9746309949
commit cf033adc2f
5 changed files with 45 additions and 154 deletions

View File

@ -1,17 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { observer } from "mobx-react";
import React from "react";
import type { HeaderPlaceholders } from "./list-layout";
export interface ItemListLayoutHeaderFiltersProps {
headerPlaceholders: HeaderPlaceholders
}
export const ItemListLayoutHeaderFilters = observer(({ headerPlaceholders }: ItemListLayoutHeaderFiltersProps) => (
<>
{headerPlaceholders.filters}
</>
));

View File

@ -1,54 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import React from "react";
import { observer } from "mobx-react";
import type { ItemObject, ItemStore } from "../../../common/item.store";
import type { Filter } from "./page-filters.store";
import type { HeaderPlaceholders } from "./list-layout";
interface ItemListLayoutHeaderInfoProps<I extends ItemObject> {
headerPlaceholders: HeaderPlaceholders;
getItems: () => I[];
store: ItemStore<I>;
getFilters: () => Filter[]
toggleFilters: () => void
}
export const ItemListLayoutHeaderInfo = observer(<I extends ItemObject>({
headerPlaceholders,
getItems,
getFilters,
store,
toggleFilters,
}: ItemListLayoutHeaderInfoProps<I>) => {
const renderInfo = () => {
const allItemsCount = store.getTotalCount();
const itemsCount = getItems().length;
if (getFilters().length > 0) {
return (
<>
<a onClick={toggleFilters}>Filtered</a>: {itemsCount} / {allItemsCount}
</>
);
}
return allItemsCount === 1
? `${allItemsCount} item`
: `${allItemsCount} items`;
};
const info = headerPlaceholders.info ?? renderInfo();
if (!info) {
return null;
}
return (
<div className="info-panel box grow">
{info}
</div>
);
});

View File

@ -1,27 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { observer } from "mobx-react";
import type { ItemObject } from "../../../common/item.store";
import { SearchInputUrl } from "../input";
import React from "react";
import type { HeaderPlaceholders, SearchFilter } from "./list-layout";
interface ItemListLayoutHeaderSearchProps<I extends ItemObject> {
searchFilters: SearchFilter<I>[];
headerPlaceholders: HeaderPlaceholders;
}
export const ItemListLayoutHeaderSearch = observer(<I extends ItemObject>({
searchFilters,
headerPlaceholders = {},
}: ItemListLayoutHeaderSearchProps<I>) => {
const { searchProps } = headerPlaceholders;
if (searchFilters.length === 0 || !searchProps) {
return null;
}
return <SearchInputUrl {...searchProps} />;
});

View File

@ -1,25 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { observer } from "mobx-react";
import React from "react";
import type { HeaderPlaceholders } from "./list-layout";
interface ItemListLayoutHeaderTitleProps {
renderHeaderTitle: React.ReactNode | (() => React.ReactNode);
headerPlaceholders: HeaderPlaceholders;
}
export const ItemListLayoutHeaderTitle = observer(({ renderHeaderTitle, headerPlaceholders }: ItemListLayoutHeaderTitleProps) => {
if (headerPlaceholders.title) {
return <>{headerPlaceholders.title}</>;
}
const title =
typeof renderHeaderTitle === "function"
? renderHeaderTitle()
: renderHeaderTitle;
return <h5 className="title">{title}</h5>;
});

View File

@ -10,11 +10,8 @@ import { observer } from "mobx-react";
import { cssNames, IClassName } from "../../utils"; import { cssNames, IClassName } from "../../utils";
import type { ItemObject, ItemStore } from "../../../common/item.store"; import type { ItemObject, ItemStore } from "../../../common/item.store";
import type { Filter } from "./page-filters.store"; import type { Filter } from "./page-filters.store";
import { ItemListLayoutHeaderTitle } from "./header-title"; import type { HeaderCustomizer, HeaderPlaceholders, SearchFilter } from "./list-layout";
import { ItemListLayoutHeaderInfo } from "./header-info"; import { SearchInputUrl } from "../input";
import { ItemListLayoutHeaderFilters } from "./header-filters";
import { ItemListLayoutHeaderSearch } from "./header-search";
import type { HeaderCustomizer, SearchFilter } from "./list-layout";
export interface ItemListLayoutHeaderProps<I extends ItemObject> { export interface ItemListLayoutHeaderProps<I extends ItemObject> {
getItems: () => I[]; getItems: () => I[];
@ -54,37 +51,54 @@ export class ItemListLayoutHeader<I extends ItemObject> extends React.Component<
return null; return null;
} }
const customizeHeaders = [customizeHeader].flat().filter(Boolean); const renderInfo = () => {
const allItemsCount = store.getTotalCount();
const itemsCount = getItems().length;
const headerPlaceholders = customizeHeaders.reduce( if (getFilters().length > 0) {
return (
<>
<a onClick={toggleFilters}>Filtered</a>: {itemsCount} / {allItemsCount}
</>
);
}
return allItemsCount === 1
? `${allItemsCount} item`
: `${allItemsCount} items`;
};
const customizeHeaderFunctions = [customizeHeader].flat().filter(Boolean);
const renderedTitle = typeof renderHeaderTitle === "function"
? renderHeaderTitle(this)
: renderHeaderTitle;
const {
filters,
info,
searchProps,
title,
} = customizeHeaderFunctions.reduce<HeaderPlaceholders>(
(prevPlaceholders, customizer) => customizer(prevPlaceholders), (prevPlaceholders, customizer) => customizer(prevPlaceholders),
{}, {
title: <h5 className="title">{renderedTitle}</h5>,
info: renderInfo(),
searchProps: {},
},
); );
return ( return (
<div <div className={cssNames("header flex gaps align-center", headerClassName)}>
className={cssNames("header flex gaps align-center", headerClassName)} {title}
> {
<ItemListLayoutHeaderTitle info && (
renderHeaderTitle={renderHeaderTitle} <div className="info-panel box grow">
headerPlaceholders={headerPlaceholders} {info}
/> </div>
)
<ItemListLayoutHeaderInfo }
headerPlaceholders={headerPlaceholders} {filters}
getItems={getItems} {searchFilters.length > 0 && searchProps && <SearchInputUrl {...searchProps} />}
store={store}
getFilters={getFilters}
toggleFilters={toggleFilters}
/>
<ItemListLayoutHeaderFilters headerPlaceholders={headerPlaceholders} />
<ItemListLayoutHeaderSearch
headerPlaceholders={headerPlaceholders}
searchFilters={searchFilters}
/>
</div> </div>
); );
} }