Skip to content

Commit

Permalink
fix filter settings
Browse files Browse the repository at this point in the history
  • Loading branch information
simlarsen committed Oct 15, 2024
1 parent 9d50f77 commit f1dda4a
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 141 deletions.
11 changes: 3 additions & 8 deletions Common/UI/Components/Filters/FilterViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface ComponentProps<T extends GenericObject> {
onFilterModalOpen: () => void;
isModalLoading?: boolean;
onFilterRefreshClick?: undefined | (() => void);
initialFilterData?: FilterData<T> | undefined;
filterData?: FilterData<T> | undefined;
}

type FilterComponentFunction = <T extends GenericObject>(
Expand All @@ -38,9 +38,6 @@ type FilterComponentFunction = <T extends GenericObject>(
const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
props: ComponentProps<T>,
): ReactElement => {
const [filterData, setFilterData] = useState<FilterData<T>>(
props.initialFilterData || {},
);
const [tempFilterDataForModal, setTempFilterDataForModal] = useState<
FilterData<T>
>({});
Expand All @@ -50,14 +47,13 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
const changeFilterData: ChangeFilterDataFunction = (
filterData: FilterData<T>,
) => {
setFilterData(filterData);
setTempFilterDataForModal(filterData);
props.onFilterChanged?.(filterData);
};

useEffect(() => {
if (props.showFilterModal) {
setTempFilterDataForModal({ ...filterData });
setTempFilterDataForModal({ ...props.filterData });
}
}, [props.showFilterModal]);

Expand Down Expand Up @@ -337,7 +333,7 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(

const filterTexts: Array<ReactElement> = translateFilterToText({
filters: props.filters,
filterData: filterData,
filterData: props.filterData || {},
});

if (props.filterError) {
Expand Down Expand Up @@ -419,7 +415,6 @@ const FilterComponent: FilterComponentFunction = <T extends GenericObject>(
props.onFilterModalClose();
}}
onSubmit={() => {
setFilterData({ ...tempFilterDataForModal });
setTempFilterDataForModal({});
if (props.onFilterChanged) {
props.onFilterChanged({
Expand Down
55 changes: 37 additions & 18 deletions Common/UI/Components/ModelTable/BaseModelTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
) => ReactElement = <TBaseModel extends BaseModel | AnalyticsBaseModel>(
props: ComponentProps<TBaseModel>,
): ReactElement => {
const [tableView, setTableView] = useState<TableView | null>(null);

const matchBulkSelectedItemByField: keyof TBaseModel =
props.bulkActions?.matchBulkSelectedItemByField || "_id";

Expand Down Expand Up @@ -800,23 +802,17 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
}

if (props.saveFilterProps && props.saveFilterProps.tableId) {
const currentTableView: TableView = new TableView();
currentTableView.query = (query || {}) as any;
currentTableView.itemsOnPage = itemsOnPage || 10;

if (sortBy && sortOrder) {
currentTableView.sort = {
[sortBy as string]: sortOrder,
};
} else {
currentTableView.sort = {};
}

return (
<TableViewElement
tableId={props.saveFilterProps.tableId}
currentTableView={currentTableView}
onViewChange={(tableView: TableView | null) => {
tableView={tableView}
currentQuery={query}
currentSortBy={sortBy}
currentItemsOnPage={itemsOnPage}
currentSortOrder={sortOrder}
onViewChange={async (tableView: TableView | null) => {
setTableView(tableView);

if (tableView) {
const sortBy: string | undefined = Object.keys(
tableView.sort || {},
Expand All @@ -831,9 +827,14 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(

// then set query, sort and items on the page
setQuery(tableView.query || {});
setFilterData(tableView.query || {});
setItemsOnPage(tableView.itemsOnPage || 10);
setSortBy(sortBy as keyof TBaseModel);
setSortBy((sortBy as keyof TBaseModel) || null);
setSortOrder(sortOrder);

if (classicTableFilters.length === 0) {
await getFilterDropdownItems();
}
} else {
setQuery({});
setSortBy(null);
Expand Down Expand Up @@ -1236,13 +1237,19 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
setActionButtonSchema(actionsSchema);
};

const [filterData, setFilterData] = useState<FilterData<TBaseModel>>(
props.initialFilterData || {},
);

type OnFilterChangedFunction = (filterData: FilterData<TBaseModel>) => void;

const onFilterChanged: OnFilterChangedFunction = (
filterData: FilterData<TBaseModel>,
): void => {
const newQuery: Query<TBaseModel> = {};

setFilterData(filterData);

for (const key in filterData) {
if (filterData[key] && typeof filterData[key] === Typeof.String) {
newQuery[key as keyof TBaseModel] = (filterData[key] || "").toString();
Expand Down Expand Up @@ -1347,8 +1354,9 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
<Table
onFilterChanged={(filterData: FilterData<TBaseModel>) => {
onFilterChanged(filterData);
setTableView(null);
}}
initialFilterData={props.initialFilterData}
filterData={filterData}
className={
props.cardProps
? ""
Expand Down Expand Up @@ -1398,6 +1406,8 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
}),
);
}}
sortBy={sortBy}
sortOrder={sortOrder}
onBulkSelectItemsOnCurrentPage={() => {
const items: TBaseModel[] = [...bulkSelectedItems, ...data];

Expand Down Expand Up @@ -1450,6 +1460,7 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
) => {
setSortBy(sortBy);
setSortOrder(sortOrder);
setTableView(null);
}}
singularLabel={props.singularName || model.singularName || "Item"}
pluralLabel={props.pluralName || model.pluralName || "Items"}
Expand Down Expand Up @@ -1481,9 +1492,17 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
await fetchItems();
}}
disablePagination={props.disablePagination || false}
onNavigateToPage={async (pageNumber: number, itemsOnPage: number) => {
onNavigateToPage={async (
pageNumber: number,
newItemsOnPage: number,
) => {
setCurrentPageNumber(pageNumber);
setItemsOnPage(itemsOnPage);

if (newItemsOnPage !== itemsOnPage) {
setTableView(null);
}

setItemsOnPage(newItemsOnPage);
}}
noItemsMessage={props.noItemsMessage || ""}
onRefreshClick={async () => {
Expand Down
113 changes: 81 additions & 32 deletions Common/UI/Components/ModelTable/TableView.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import React, {
FunctionComponent,
ReactElement,
useEffect,
useState,
} from "react";
import React, { ReactElement, useEffect, useRef, useState } from "react";
import TableView from "../../../Models/DatabaseModels/TableView";
import ObjectID from "../../../Types/ObjectID";
import MoreMenu from "../MoreMenu/MoreMenu";
Expand All @@ -26,15 +21,26 @@ import { GetReactElementArrayFunction } from "../../Types/FunctionTypes";
import ProjectUtil from "../../Utils/Project";
import User from "../../Utils/User";
import Icon, { SizeProp, ThickProp } from "../Icon/Icon";
import GenericObject from "../../../Types/GenericObject";
import Query from "../../../Types/BaseDatabase/Query";
import DatabaseBaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
import Sort from "../../../Types/BaseDatabase/Sort";

export interface ComponentProps {
export interface ComponentProps<T extends GenericObject> {
tableId: string;
onViewChange: (tableView: TableView | null) => void;
currentTableView: TableView | null;
currentQuery: Query<T>;
currentSortOrder: SortOrder | null;
currentSortBy: keyof T | null;
currentItemsOnPage: number;
tableView: TableView | null;
}

const TableViewElement: FunctionComponent<ComponentProps> = (
props: ComponentProps,
const TableViewElement: <T extends DatabaseBaseModel | AnalyticsBaseModel>(
props: ComponentProps<T>,
) => ReactElement = <T extends DatabaseBaseModel | AnalyticsBaseModel>(
props: ComponentProps<T>,
): ReactElement => {
const [error, setError] = useState<string>("");
const [isLoading, setIsLoading] = useState<boolean>(false);
Expand All @@ -48,9 +54,15 @@ const TableViewElement: FunctionComponent<ComponentProps> = (
const [showCreateNewViewModal, setShowCreateNewViewModel] =
useState<boolean>(false);

const moreMenuRef: React.MutableRefObject<undefined> = useRef();

const [currentlySelectedView, setCurrentlySelectedView] =
useState<TableView | null>(null);

useEffect(() => {
setCurrentlySelectedView(props.tableView);
}, [props.tableView]);

// load all the filters for this user and for this project.
const fetchTableViews: PromiseVoidFunction = async (): Promise<void> => {
try {
Expand Down Expand Up @@ -228,6 +240,7 @@ const TableViewElement: FunctionComponent<ComponentProps> = (
submitButtonText="Save Changes"
onSuccess={async () => {
setTableViewToEdit(undefined);

await fetchTableViews();
}}
formProps={{
Expand Down Expand Up @@ -283,15 +296,28 @@ const TableViewElement: FunctionComponent<ComponentProps> = (
}}
submitButtonText="Save Changes"
onBeforeCreate={(tableView: TableView) => {
let sort: Sort<T> = {};

if (props.currentSortOrder && props.currentSortBy) {
sort = {
[props.currentSortBy]: props.currentSortOrder,
} as Sort<T>;
}

tableView.tableId = props.tableId;
tableView.query = props.currentTableView?.query || {};
tableView.itemsOnPage = props.currentTableView?.itemsOnPage || 10;
tableView.sort = props.currentTableView?.sort || {};
tableView.query =
(props.currentQuery as Query<
DatabaseBaseModel | AnalyticsBaseModel
>) || {};
tableView.itemsOnPage = props?.currentItemsOnPage || 10;
tableView.sort = sort || {};
return Promise.resolve(tableView);
}}
onSuccess={async () => {
onSuccess={async (tableView: TableView) => {
setShowCreateNewViewModel(false);
await fetchTableViews();
// set as current view
props.onViewChange && props.onViewChange(tableView);
}}
formProps={{
name: "Save New View",
Expand All @@ -315,34 +341,57 @@ const TableViewElement: FunctionComponent<ComponentProps> = (
);
}

type GetElementToBeShownInsteadOfButtonFunction = () => ReactElement | undefined;
type GetElementToBeShownInsteadOfButtonFunction = () =>
| ReactElement
| undefined;

const getElementToBeShownInsteadOfButton: GetElementToBeShownInsteadOfButtonFunction = (): ReactElement | undefined => {
if (!currentlySelectedView) {
return 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}
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">
<div
onClick={() => {
setCurrentlySelectedView(null);
props.onViewChange && props.onViewChange(null);
flipDropdown();
}}
/>
>
{currentlySelectedView.name}
</div>
<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);
closeDropdownMenu();
}}
/>
</div>
</div>
</div>
);
);
};

const closeDropdownMenu: VoidFunction = (): void => {
if (moreMenuRef.current) {
(moreMenuRef.current as any).closeDropdown();
}
};

const flipDropdown: VoidFunction = (): void => {
if (moreMenuRef.current) {
(moreMenuRef.current as any).flipDropdown();
}
};

return (
<MoreMenu
elementToBeShownInsteadOfButton={getElementToBeShownInsteadOfButton()}
ref={moreMenuRef}
>
{getMenuContents()}
</MoreMenu>
Expand Down
Loading

0 comments on commit f1dda4a

Please sign in to comment.