Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor scene list to not use ItemList component #5767

Merged
merged 7 commits into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
GroupsCriterionOption,
} from "src/models/list-filter/criteria/groups";
import { ListFilterModel } from "src/models/list-filter/filter";
import { SceneList } from "src/components/Scenes/SceneList";
import { FilteredSceneList } from "src/components/Scenes/SceneList";
import { View } from "src/components/List/views";

interface IGroupScenesPanel {
Expand Down Expand Up @@ -64,7 +64,7 @@ export const GroupScenesPanel: React.FC<IGroupScenesPanel> = ({

if (group && group.id) {
return (
<SceneList
<FilteredSceneList
filterHook={filterHook}
defaultSort="group_scene_number"
alterQuery={active}
Expand Down
30 changes: 30 additions & 0 deletions ui/v2.5/src/components/List/EditFilterDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -488,3 +488,33 @@ export const EditFilterDialog: React.FC<IEditFilterProps> = ({
</>
);
};

export function useShowEditFilter(props: {
filter: ListFilterModel;
setFilter: (f: ListFilterModel) => void;
showModal: (content: React.ReactNode) => void;
closeModal: () => void;
}) {
const { filter, setFilter, showModal, closeModal } = props;

const showEditFilter = useCallback(
(editingCriterion?: string) => {
function onApplyEditFilter(f: ListFilterModel) {
closeModal();
setFilter(f);
}

showModal(
<EditFilterDialog
filter={filter}
onApply={onApplyEditFilter}
onCancel={() => closeModal()}
editingCriterion={editingCriterion}
/>
);
},
[filter, setFilter, showModal, closeModal]
);

return showEditFilter;
}
36 changes: 18 additions & 18 deletions ui/v2.5/src/components/List/FilteredListToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ import {
IListFilterOperation,
ListOperationButtons,
} from "./ListOperationButtons";
import { DisplayMode } from "src/models/list-filter/types";
import { ButtonToolbar } from "react-bootstrap";
import { View } from "./views";
import { useListContext } from "./ListProvider";
import { useFilter } from "./FilterProvider";
import { IListSelect, useFilterOperations } from "./util";

export interface IItemListOperation<T extends QueryResult> {
text: string;
Expand All @@ -32,34 +30,36 @@ export interface IItemListOperation<T extends QueryResult> {
}

export interface IFilteredListToolbar {
showEditFilter?: (editingCriterion?: string) => void;
filter: ListFilterModel;
setFilter: (
value: ListFilterModel | ((prevState: ListFilterModel) => ListFilterModel)
) => void;
showEditFilter: () => void;
view?: View;
listSelect: IListSelect;
onEdit?: () => void;
onDelete?: () => void;
operations?: IListFilterOperation[];
zoomable?: boolean;
}

export const FilteredListToolbar: React.FC<IFilteredListToolbar> = ({
filter,
setFilter,
showEditFilter,
view,
listSelect,
onEdit,
onDelete,
operations,
zoomable = false,
}) => {
const { getSelected, onSelectAll, onSelectNone } = useListContext();
const { filter, setFilter } = useFilter();

const filterOptions = filter.options;

function onChangeDisplayMode(displayMode: DisplayMode) {
setFilter(filter.setDisplayMode(displayMode));
}

function onChangeZoom(newZoomIndex: number) {
setFilter(filter.setZoom(newZoomIndex));
}
const { setDisplayMode, setZoom } = useFilterOperations({
filter,
setFilter,
});
const { selectedIds, onSelectAll, onSelectNone } = listSelect;

return (
<ButtonToolbar className="filtered-list-toolbar">
Expand All @@ -75,16 +75,16 @@ export const FilteredListToolbar: React.FC<IFilteredListToolbar> = ({
onSelectAll={onSelectAll}
onSelectNone={onSelectNone}
otherOperations={operations}
itemsSelected={getSelected().length > 0}
itemsSelected={selectedIds.size > 0}
onEdit={onEdit}
onDelete={onDelete}
/>
<ListViewOptions
displayMode={filter.displayMode}
displayModeOptions={filterOptions.displayModeOptions}
onSetDisplayMode={onChangeDisplayMode}
onSetDisplayMode={setDisplayMode}
zoomIndex={zoomable ? filter.zoomIndex : undefined}
onSetZoom={zoomable ? onChangeZoom : undefined}
onSetZoom={zoomable ? setZoom : undefined}
/>
</ButtonToolbar>
);
Expand Down
85 changes: 82 additions & 3 deletions ui/v2.5/src/components/List/ItemList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import * as GQL from "src/core/generated-graphql";
import { QueryResult } from "@apollo/client";
import { Criterion } from "src/models/list-filter/criteria/criterion";
import { ListFilterModel } from "src/models/list-filter/filter";
import { EditFilterDialog } from "src/components/List/EditFilterDialog";
import {
EditFilterDialog,
useShowEditFilter,
} from "src/components/List/EditFilterDialog";
import { FilterTags } from "./FilterTags";
import { View } from "./views";
import { IHasID } from "src/utils/data";
Expand All @@ -23,9 +26,15 @@ import {
import { FilterContext, SetFilterURL, useFilter } from "./FilterProvider";
import { useModal } from "src/hooks/modal";
import {
IFilterStateHook,
IQueryResultHook,
useDefaultFilter,
useEnsureValidPage,
useFilterOperations,
useFilterState,
useListKeyboardShortcuts,
useListSelect,
useQueryResult,
useScrollToTopOnPageChange,
} from "./util";
import {
Expand All @@ -36,6 +45,72 @@ import {
import { PagedList } from "./PagedList";
import { ConfigurationContext } from "src/hooks/Config";

interface IFilteredItemList<T extends QueryResult, E extends IHasID = IHasID> {
filterStateProps: IFilterStateHook;
queryResultProps: IQueryResultHook<T, E>;
}

// Provides the common state and behaviour for filtered item list components
export function useFilteredItemList<
T extends QueryResult,
E extends IHasID = IHasID
>(props: IFilteredItemList<T, E>) {
const { configuration: config } = useContext(ConfigurationContext);

// States
const filterState = useFilterState({
config,
...props.filterStateProps,
});

const { filter, setFilter } = filterState;

const queryResult = useQueryResult({
filter,
...props.queryResultProps,
});
const { result, items, totalCount, pages } = queryResult;

const listSelect = useListSelect(items);
const { onSelectAll, onSelectNone } = listSelect;

const modalState = useModal();
const { showModal, closeModal } = modalState;

// Utility hooks
const { setPage } = useFilterOperations({ filter, setFilter });

// scroll to the top of the page when the page changes
useScrollToTopOnPageChange(filter.currentPage, result.loading);

// ensure that the current page is valid
useEnsureValidPage(filter, totalCount, setFilter);

const showEditFilter = useShowEditFilter({
showModal,
closeModal,
filter,
setFilter,
});

useListKeyboardShortcuts({
currentPage: filter.currentPage,
onChangePage: setPage,
onSelectAll,
onSelectNone,
pages,
showEditFilter,
});

return {
filterState,
queryResult,
listSelect,
modalState,
showEditFilter,
};
}

interface IItemListProps<T extends QueryResult, E extends IHasID> {
view?: View;
zoomable?: boolean;
Expand Down Expand Up @@ -83,13 +158,14 @@ export const ItemList = <T extends QueryResult, E extends IHasID>(
const { filter, setFilter: updateFilter } = useFilter();
const { effectiveFilter, result, cachedResult, totalCount } =
useQueryResultContext<T, E>();
const listSelect = useListContext<E>();
const {
selectedIds,
getSelected,
onSelectChange,
onSelectAll,
onSelectNone,
} = useListContext<E>();
} = listSelect;

// scroll to the top of the page when the page changes
useScrollToTopOnPageChange(filter.currentPage, result.loading);
Expand Down Expand Up @@ -236,7 +312,10 @@ export const ItemList = <T extends QueryResult, E extends IHasID>(
updateFilter(filter.clearCriteria());
}

const filterListToolbarProps = {
const filterListToolbarProps: IFilteredListToolbar = {
filter,
setFilter: updateFilter,
listSelect,
showEditFilter,
view: view,
operations: operations,
Expand Down
16 changes: 4 additions & 12 deletions ui/v2.5/src/components/List/ListProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,12 @@ export const ListContext = <T extends IHasID = IHasID>(
) => {
const { selectable = false, items, children } = props;

const {
selectedIds,
getSelected,
onSelectChange,
onSelectAll,
onSelectNone,
} = useListSelect(items);
const listSelect = useListSelect(items);

const state: IListContextState<T> = {
selectable,
selectedIds,
getSelected,
onSelectChange,
onSelectAll,
onSelectNone,
items,
...listSelect,
};

return (
Expand Down Expand Up @@ -74,6 +64,8 @@ const emptyState: IListContextState = {
onSelectAll: () => {},
onSelectNone: () => {},
items: [],
hasSelection: false,
selectedItems: [],
};

export function useListContextOptional<T extends IHasID = IHasID>() {
Expand Down
Loading