make UI for table filters nicer

This commit is contained in:
Simon Larsen 2024-10-14 20:23:20 +01:00
parent 5d9252d1ff
commit f0a3ddbf2e
No known key found for this signature in database
GPG Key ID: 96C5DCA24769DBCA
7 changed files with 127 additions and 63 deletions

View File

@ -906,9 +906,7 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
headerbuttons.push({
title: "",
buttonStyle: ButtonStyleType.ICON,
className: props.showRefreshButton
? "p-1 px-1 pr-0 pl-0 py-0 mt-1"
: "py-0 pr-0 pl-1 mt-1",
className: "py-0 pr-0 pl-1 mt-1",
onClick: () => {
setQuery({});
setShowFilterModal(true);

View File

@ -14,7 +14,7 @@ import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
import SortOrder from "../../../Types/BaseDatabase/SortOrder";
import API from "../../../Utils/API";
import MoreMenuSection from "../MoreMenu/MoreMenuSection";
import Button, { ButtonStyleType } from "../Button/Button";
import { ButtonStyleType } from "../Button/Button";
import IconProp from "../../../Types/Icon/IconProp";
import { BarLoader } from "react-spinners";
import ConfirmModal from "../Modal/ConfirmModal";
@ -22,9 +22,10 @@ import ModelFormModal from "../ModelFormModal/ModelFormModal";
import { FormType } from "../Forms/ModelForm";
import FormFieldSchemaType from "../Forms/Types/FormFieldSchemaType";
import { PromiseVoidFunction } from "../../../Types/FunctionTypes";
import { GetReactElementFunction } from "../../Types/FunctionTypes";
import { GetReactElementArrayFunction } from "../../Types/FunctionTypes";
import ProjectUtil from "../../Utils/Project";
import User from "../../Utils/User";
import Icon, { SizeProp, ThickProp } from "../Icon/Icon";
export interface ComponentProps {
tableId: string;
@ -122,21 +123,28 @@ const TableViewElement: FunctionComponent<ComponentProps> = (
(item: TableView): ReactElement => {
return (
<div className="flex">
<Button
icon={IconProp.Edit}
buttonStyle={ButtonStyleType.ICON_LIGHT}
onClick={() => {
setTableViewToEdit(item);
}}
/>
<Button
icon={IconProp.Trash}
buttonStyle={ButtonStyleType.ICON_LIGHT}
onClick={() => {
setTableViewToDelete(item);
}}
/>
<div className="h-4 w-4 mr-2">
<Icon
icon={IconProp.Edit}
className="text-gray-400 hover:text-gray-600"
size={SizeProp.Regular}
thick={ThickProp.Thick}
onClick={() => {
setTableViewToEdit(item);
}}
/>
</div>
<div className="h-4 w-4">
<Icon
className="text-gray-400 hover:text-gray-600"
icon={IconProp.Trash}
size={SizeProp.Regular}
thick={ThickProp.Thick}
onClick={() => {
setTableViewToDelete(item);
}}
/>
</div>
</div>
);
};
@ -150,6 +158,8 @@ const TableViewElement: FunctionComponent<ComponentProps> = (
key={index}
rightElement={getRightElementForTableViewMenuItem(item)}
text={item.name || ""}
className="text-gray-600 hover:text-gray-800"
icon={IconProp.Window}
onClick={() => {
props.onViewChange && props.onViewChange(item);
setCurrentlySelectedView(item);
@ -159,42 +169,36 @@ const TableViewElement: FunctionComponent<ComponentProps> = (
});
};
const getMenuContents: GetReactElementFunction = (): ReactElement => {
if (isLoading) {
return <BarLoader />;
}
const getMenuContents: GetReactElementArrayFunction =
(): Array<ReactElement> => {
if (isLoading) {
return [<BarLoader />];
}
return (
<>
{allTableViews.length > 0 ? (
const elements: Array<ReactElement> = [];
if (allTableViews.length > 0) {
elements.push(
<MoreMenuSection title="Saved Views">
{getViewItems()}
</MoreMenuSection>
) : (
<></>
)}
{currentlySelectedView ? (
<MoreMenuItem
text="Deselect View"
onClick={() => {
setCurrentlySelectedView(null);
props.onViewChange && props.onViewChange(null);
}}
></MoreMenuItem>
) : (
<></>
)}
</MoreMenuSection>,
);
}
elements.push(
<MoreMenuItem
text="Save View"
text="Save as New View"
className="bg-gray-50 hover:bg-gray-100 text-gray-700 hover:text-gray-900 font-medium -mt-2"
icon={IconProp.Add}
iconClassName=""
onClick={() => {
setShowCreateNewViewModel(true);
}}
></MoreMenuItem>
</>
);
};
></MoreMenuItem>,
);
return elements;
};
if (error) {
return (
@ -311,7 +315,38 @@ const TableViewElement: FunctionComponent<ComponentProps> = (
);
}
return <MoreMenu>{getMenuContents()}</MoreMenu>;
type GetElementToBeShownInsteadOfButtonFunction = () => ReactElement | undefined;
const getElementToBeShownInsteadOfButton: GetElementToBeShownInsteadOfButtonFunction = (): ReactElement | undefined => {
if (!currentlySelectedView) {
return undefined;
}
return (
<div className="ml-2 mt-1 cursor-pointer font-semibold flex rounded-full border-2 border-gray-600 text-gray-600 text-xs p-1 pl-2 pr-2">
{currentlySelectedView.name}
<div className="h-4 w-4 rounded-full bg-gray-500 text-white hover:bg-gray-800 ml-3 -mr-1 p-1">
<Icon
icon={IconProp.Close}
size={SizeProp.Regular}
thick={ThickProp.Thick}
onClick={() => {
setCurrentlySelectedView(null);
props.onViewChange && props.onViewChange(null);
}}
/>
</div>
</div>
);
};
return (
<MoreMenu
elementToBeShownInsteadOfButton={getElementToBeShownInsteadOfButton()}
>
{getMenuContents()}
</MoreMenu>
);
};
export default TableViewElement;

View File

@ -9,7 +9,8 @@ import IconProp from "../../../Types/Icon/IconProp";
import useComponentOutsideClick from "../../Types/UseComponentOutsideClick";
export interface ComponentProps {
children: Array<ReactElement> | ReactElement;
children: Array<ReactElement>;
elementToBeShownInsteadOfButton?: ReactElement | undefined;
}
const MoreMenu: FunctionComponent<ComponentProps> = (
@ -26,15 +27,27 @@ const MoreMenu: FunctionComponent<ComponentProps> = (
return (
<div className="relative inline-block text-left">
<div>
<Button
icon={IconProp.More}
buttonStyle={ButtonStyleType.ICON}
{!props.elementToBeShownInsteadOfButton && (
<div>
<Button
icon={IconProp.More}
buttonStyle={ButtonStyleType.ICON}
onClick={() => {
setIsComponentVisible(!isDropdownVisible);
}}
/>
</div>
)}
{props.elementToBeShownInsteadOfButton && (
<div
onClick={() => {
setIsComponentVisible(!isDropdownVisible);
}}
/>
</div>
>
{props.elementToBeShownInsteadOfButton}
</div>
)}
{isComponentVisible && (
<div
@ -44,7 +57,21 @@ const MoreMenu: FunctionComponent<ComponentProps> = (
aria-orientation="vertical"
aria-labelledby="menu-button"
>
{props.children}
{props.children.map((child: ReactElement, index: number) => {
return (
<div
key={index}
role="menuitem"
onClick={() => {
if (isComponentVisible) {
setIsComponentVisible(false);
}
}}
>
{child}
</div>
);
})}
</div>
)}
</div>

View File

@ -7,6 +7,8 @@ export interface ComponentProps {
text: string;
onClick: () => void;
rightElement?: Array<ReactElement> | ReactElement | undefined;
className?: string | undefined;
iconClassName?: string | undefined;
}
const MoreMenuItem: FunctionComponent<ComponentProps> = (
@ -14,7 +16,7 @@ const MoreMenuItem: FunctionComponent<ComponentProps> = (
): ReactElement => {
return (
<a
className="cursor-pointer group flex items-center px-4 py-2 text-sm text-gray-700 hover:text-gray-900 hover:bg-gray-50"
className={`cursor-pointer group flex items-center px-4 py-2 text-sm text-gray-600 hover:text-gray-700 hover:bg-gray-50 ${props.className}`}
role="menuitem"
onClick={() => {
props.onClick();
@ -23,10 +25,10 @@ const MoreMenuItem: FunctionComponent<ComponentProps> = (
{props.icon && (
<Icon
icon={props.icon}
className="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-500"
className={`mr-3 h-5 w-5 text-gray-400 text-gray-700 hover:text-gray-900 ${props.iconClassName}`}
/>
)}
<div className="flex justify-between">
<div className="flex w-full justify-between">
<div>{props.text}</div>
<div>{props.rightElement}</div>
</div>

View File

@ -10,8 +10,8 @@ const MoreMenuSection: FunctionComponent<ComponentProps> = (
): ReactElement => {
return (
<div>
<div className="text-gray-400 text-sm font-medium">
{props.title.toLocaleUpperCase()}
<div className="text-gray-400 text-xs font-medium pt-2 pl-3 pr-3 pb-2">
{props.title.toUpperCase()}
</div>
{props.children}
<MoreMenuDivider />

View File

@ -2,4 +2,6 @@ import { ReactElement } from "react";
export type GetReactElementFunction = () => ReactElement;
export type GetReactElementArrayFunction = () => Array<ReactElement>;
export type GetReactElementOrStringFunction = () => ReactElement | string;

View File

@ -60,7 +60,7 @@ const MonitorsTable: FunctionComponent<ComponentProps> = (
modelType={Monitor}
name="Monitors"
id="Monitors-table"
// saveFilterProps={props.saveFilterProps}
saveFilterProps={props.saveFilterProps}
bulkActions={{
buttons: [
{