;
operations: IOperations[];
onToggleSidebar: () => void;
onEditCriterion: (c: Criterion) => void;
onRemoveCriterion: (criterion: Criterion, valueIndex?: number) => void;
onRemoveAllCriterion: () => void;
onSelectAll: () => void;
onSelectNone: () => void;
onEdit: () => void;
onDelete: () => void;
onPlay: () => void;
onCreateNew: () => void;
}> = ({
criteria,
items,
selectedIds,
operations,
onToggleSidebar,
onEditCriterion,
onRemoveCriterion,
onRemoveAllCriterion,
onSelectAll,
onSelectNone,
onEdit,
onDelete,
onPlay,
onCreateNew,
}) => {
const intl = useIntl();
const hasSelection = selectedIds.size > 0;
return (
<>
{!hasSelection && (
onToggleSidebar()}
count={criteria.length}
title={intl.formatMessage({ id: "actions.sidebar.toggle" })}
/>
)}
{hasSelection && (
{selectedIds.size} selected
)}
{!!items.length && (
)}
{!hasSelection && (
)}
{hasSelection && (
<>
>
)}
{operations.map((o) => {
if (o.isDisplayed && !o.isDisplayed()) {
return null;
}
return (
);
})}
>
);
};
const ListResultsHeader: React.FC<{
loading: boolean;
filter: ListFilterModel;
totalCount: number;
metadataByline?: React.ReactNode;
onChangeFilter: (filter: ListFilterModel) => void;
}> = ({ loading, filter, totalCount, metadataByline, onChangeFilter }) => {
return (
onChangeFilter(filter.setSortBy(s ?? undefined))
}
onChangeSortDirection={() =>
onChangeFilter(filter.toggleSortDirection())
}
onReshuffleRandomSort={() =>
onChangeFilter(filter.reshuffleRandomSort())
}
/>
onChangeFilter(filter.setPageSize(s))}
/>
onChangeFilter(filter.setDisplayMode(mode))
}
onSetZoom={(zoom) => onChangeFilter(filter.setZoom(zoom))}
/>
);
};
interface IFilteredScenes {
filterHook?: (filter: ListFilterModel) => ListFilterModel;
defaultSort?: string;
view?: View;
alterQuery?: boolean;
fromGroupId?: string;
}
export const FilteredSceneList = (props: IFilteredScenes) => {
const intl = useIntl();
const history = useHistory();
const { filterHook, defaultSort, view, alterQuery, fromGroupId } = props;
// States
const {
showSidebar,
setShowSidebar,
loading: sidebarStateLoading,
} = useSidebarState(view);
const { filterState, queryResult, modalState, listSelect, showEditFilter } =
useFilteredItemList({
filterStateProps: {
filterMode: GQL.FilterMode.Scenes,
defaultSort,
view,
useURL: alterQuery,
},
queryResultProps: {
useResult: useFindScenes,
getCount: (r) => r.data?.findScenes.count ?? 0,
getItems: (r) => r.data?.findScenes.scenes ?? [],
filterHook,
},
});
const { filter, setFilter, loading: filterLoading } = filterState;
const { effectiveFilter, result, cachedResult, items, totalCount } =
queryResult;
const {
selectedIds,
selectedItems,
onSelectChange,
onSelectAll,
onSelectNone,
hasSelection,
} = listSelect;
const { modal, showModal, closeModal } = modalState;
// Utility hooks
const { setPage, removeCriterion, clearAllCriteria } = useFilterOperations({
filter,
setFilter,
});
useAddKeybinds(filter, totalCount);
useFilteredSidebarKeybinds({
showSidebar,
setShowSidebar,
});
useEffect(() => {
Mousetrap.bind("e", () => {
if (hasSelection) {
onEdit?.();
}
});
Mousetrap.bind("d d", () => {
if (hasSelection) {
onDelete?.();
}
});
return () => {
Mousetrap.unbind("e");
Mousetrap.unbind("d d");
};
});
const onCloseEditDelete = useCloseEditDelete({
closeModal,
onSelectNone,
result,
});
const metadataByline = useMemo(() => {
if (cachedResult.loading) return null;
return renderMetadataByline(cachedResult) ?? null;
}, [cachedResult]);
const queue = useMemo(() => SceneQueue.fromListFilterModel(filter), [filter]);
const playRandom = usePlayRandom(filter, totalCount);
const playSelected = usePlaySelected(selectedIds);
const playFirst = usePlayFirst();
function onCreateNew() {
history.push("/scenes/new");
}
function onPlay() {
if (items.length === 0) {
return;
}
// if there are selected items, play those
if (hasSelection) {
playSelected();
return;
}
// otherwise, play the first item in the list
const sceneID = items[0].id;
playFirst(queue, sceneID, 0);
}
function onExport(all: boolean) {
showModal(
closeModal()}
/>
);
}
function onMerge() {
const selected =
selectedItems.map((s) => {
return {
id: s.id,
title: objectTitle(s),
};
}) ?? [];
showModal(
{
closeModal();
if (mergedID) {
history.push(`/scenes/${mergedID}`);
}
}}
show
/>
);
}
function onEdit() {
showModal(
);
}
function onDelete() {
showModal(
);
}
const otherOperations = [
{
text: intl.formatMessage({ id: "actions.play" }),
onClick: () => onPlay(),
isDisplayed: () => items.length > 0,
className: "play-item",
},
{
text: intl.formatMessage(
{ id: "actions.create_entity" },
{ entityType: intl.formatMessage({ id: "scene" }) }
),
onClick: () => onCreateNew(),
isDisplayed: () => !hasSelection,
className: "create-new-item",
},
{
text: intl.formatMessage({ id: "actions.select_all" }),
onClick: () => onSelectAll(),
isDisplayed: () => totalCount > 0,
},
{
text: intl.formatMessage({ id: "actions.select_none" }),
onClick: () => onSelectNone(),
isDisplayed: () => hasSelection,
},
{
text: intl.formatMessage({ id: "actions.play_random" }),
onClick: playRandom,
isDisplayed: () => totalCount > 1,
},
{
text: `${intl.formatMessage({ id: "actions.generate" })}…`,
onClick: () =>
showModal(
closeModal()}
/>
),
isDisplayed: () => hasSelection,
},
{
text: `${intl.formatMessage({ id: "actions.identify" })}…`,
onClick: () =>
showModal(
closeModal()}
/>
),
isDisplayed: () => hasSelection,
},
{
text: `${intl.formatMessage({ id: "actions.merge" })}…`,
onClick: () => onMerge(),
isDisplayed: () => hasSelection,
},
{
text: intl.formatMessage({ id: "actions.export" }),
onClick: () => onExport(false),
isDisplayed: () => hasSelection,
},
{
text: intl.formatMessage({ id: "actions.export_all" }),
onClick: () => onExport(true),
},
];
// render
if (filterLoading || sidebarStateLoading) return null;
return (
{modal}
setShowSidebar(false)}>
setShowSidebar(false)}
count={cachedResult.loading ? undefined : totalCount}
/>
setShowSidebar(!showSidebar)}
onEditCriterion={(c) => showEditFilter(c.criterionOption.type)}
onRemoveCriterion={removeCriterion}
onRemoveAllCriterion={() => clearAllCriteria()}
onSelectAll={() => onSelectAll()}
onSelectNone={() => onSelectNone()}
onEdit={onEdit}
onDelete={onDelete}
onCreateNew={onCreateNew}
onPlay={onPlay}
/>
setFilter(newFilter)}
/>
{totalCount > filter.itemsPerPage && (
)}
);
};
export default FilteredSceneList;