mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 21:04:37 +03:00
Support setting galleries in multiple images (#4608)
This commit is contained in:
@@ -32,6 +32,7 @@ import {
|
|||||||
Criterion,
|
Criterion,
|
||||||
CriterionValue,
|
CriterionValue,
|
||||||
} from "src/models/list-filter/criteria/criterion";
|
} from "src/models/list-filter/criteria/criterion";
|
||||||
|
import { PathCriterion } from "src/models/list-filter/criteria/path";
|
||||||
|
|
||||||
export type Gallery = Pick<GQL.Gallery, "id" | "title"> & {
|
export type Gallery = Pick<GQL.Gallery, "id" | "title"> & {
|
||||||
files: Pick<GQL.GalleryFile, "path">[];
|
files: Pick<GQL.GalleryFile, "path">[];
|
||||||
@@ -39,14 +40,14 @@ export type Gallery = Pick<GQL.Gallery, "id" | "title"> & {
|
|||||||
};
|
};
|
||||||
type Option = SelectOption<Gallery>;
|
type Option = SelectOption<Gallery>;
|
||||||
|
|
||||||
|
type ExtraGalleryProps = {
|
||||||
|
hoverPlacement?: Placement;
|
||||||
|
excludeIds?: string[];
|
||||||
|
extraCriteria?: Array<Criterion<CriterionValue>>;
|
||||||
|
};
|
||||||
|
|
||||||
const _GallerySelect: React.FC<
|
const _GallerySelect: React.FC<
|
||||||
IFilterProps &
|
IFilterProps & IFilterValueProps<Gallery> & ExtraGalleryProps
|
||||||
IFilterValueProps<Gallery> & {
|
|
||||||
hoverPlacement?: Placement;
|
|
||||||
excludeIds?: string[];
|
|
||||||
} & {
|
|
||||||
extraCriteria?: Array<Criterion<CriterionValue>>;
|
|
||||||
}
|
|
||||||
> = (props) => {
|
> = (props) => {
|
||||||
const { configuration } = React.useContext(ConfigurationContext);
|
const { configuration } = React.useContext(ConfigurationContext);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@@ -187,9 +188,9 @@ const _GallerySelect: React.FC<
|
|||||||
|
|
||||||
export const GallerySelect = PatchComponent("GallerySelect", _GallerySelect);
|
export const GallerySelect = PatchComponent("GallerySelect", _GallerySelect);
|
||||||
|
|
||||||
const _GalleryIDSelect: React.FC<IFilterProps & IFilterIDProps<Gallery>> = (
|
const _GalleryIDSelect: React.FC<
|
||||||
props
|
IFilterProps & IFilterIDProps<Gallery> & ExtraGalleryProps
|
||||||
) => {
|
> = (props) => {
|
||||||
const { ids, onSelect: onSelectValues } = props;
|
const { ids, onSelect: onSelectValues } = props;
|
||||||
|
|
||||||
const [values, setValues] = useState<Gallery[]>([]);
|
const [values, setValues] = useState<Gallery[]>([]);
|
||||||
@@ -238,3 +239,11 @@ export const GalleryIDSelect = PatchComponent(
|
|||||||
"GalleryIDSelect",
|
"GalleryIDSelect",
|
||||||
_GalleryIDSelect
|
_GalleryIDSelect
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function getExcludeFilebaseGalleriesFilter() {
|
||||||
|
const ret = new PathCriterion();
|
||||||
|
ret.modifier = GQL.CriterionModifier.IsNull;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const excludeFileBasedGalleries = [getExcludeFilebaseGalleriesFilter()];
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import * as FormUtils from "src/utils/form";
|
|||||||
import { MultiSet } from "../Shared/MultiSet";
|
import { MultiSet } from "../Shared/MultiSet";
|
||||||
import { RatingSystem } from "../Shared/Rating/RatingSystem";
|
import { RatingSystem } from "../Shared/Rating/RatingSystem";
|
||||||
import {
|
import {
|
||||||
|
getAggregateGalleryIds,
|
||||||
getAggregateInputIDs,
|
getAggregateInputIDs,
|
||||||
getAggregateInputValue,
|
getAggregateInputValue,
|
||||||
getAggregatePerformerIds,
|
getAggregatePerformerIds,
|
||||||
@@ -36,11 +37,19 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
||||||
const [performerIds, setPerformerIds] = useState<string[]>();
|
const [performerIds, setPerformerIds] = useState<string[]>();
|
||||||
const [existingPerformerIds, setExistingPerformerIds] = useState<string[]>();
|
const [existingPerformerIds, setExistingPerformerIds] = useState<string[]>();
|
||||||
|
|
||||||
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
||||||
GQL.BulkUpdateIdMode.Add
|
GQL.BulkUpdateIdMode.Add
|
||||||
);
|
);
|
||||||
const [tagIds, setTagIds] = useState<string[]>();
|
const [tagIds, setTagIds] = useState<string[]>();
|
||||||
const [existingTagIds, setExistingTagIds] = useState<string[]>();
|
const [existingTagIds, setExistingTagIds] = useState<string[]>();
|
||||||
|
|
||||||
|
const [galleryMode, setGalleryMode] = React.useState<GQL.BulkUpdateIdMode>(
|
||||||
|
GQL.BulkUpdateIdMode.Add
|
||||||
|
);
|
||||||
|
const [galleryIds, setGalleryIds] = useState<string[]>();
|
||||||
|
const [existingGalleryIds, setExistingGalleryIds] = useState<string[]>();
|
||||||
|
|
||||||
const [organized, setOrganized] = useState<boolean | undefined>();
|
const [organized, setOrganized] = useState<boolean | undefined>();
|
||||||
|
|
||||||
const [updateImages] = useBulkImageUpdate();
|
const [updateImages] = useBulkImageUpdate();
|
||||||
@@ -56,6 +65,7 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
const aggregateStudioId = getAggregateStudioId(props.selected);
|
const aggregateStudioId = getAggregateStudioId(props.selected);
|
||||||
const aggregatePerformerIds = getAggregatePerformerIds(props.selected);
|
const aggregatePerformerIds = getAggregatePerformerIds(props.selected);
|
||||||
const aggregateTagIds = getAggregateTagIds(props.selected);
|
const aggregateTagIds = getAggregateTagIds(props.selected);
|
||||||
|
const aggregateGalleryIds = getAggregateGalleryIds(props.selected);
|
||||||
|
|
||||||
const imageInput: GQL.BulkImageUpdateInput = {
|
const imageInput: GQL.BulkImageUpdateInput = {
|
||||||
ids: props.selected.map((image) => {
|
ids: props.selected.map((image) => {
|
||||||
@@ -72,6 +82,11 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
aggregatePerformerIds
|
aggregatePerformerIds
|
||||||
);
|
);
|
||||||
imageInput.tag_ids = getAggregateInputIDs(tagMode, tagIds, aggregateTagIds);
|
imageInput.tag_ids = getAggregateInputIDs(tagMode, tagIds, aggregateTagIds);
|
||||||
|
imageInput.gallery_ids = getAggregateInputIDs(
|
||||||
|
galleryMode,
|
||||||
|
galleryIds,
|
||||||
|
aggregateGalleryIds
|
||||||
|
);
|
||||||
|
|
||||||
if (organized !== undefined) {
|
if (organized !== undefined) {
|
||||||
imageInput.organized = organized;
|
imageInput.organized = organized;
|
||||||
@@ -107,6 +122,7 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
let updateStudioID: string | undefined;
|
let updateStudioID: string | undefined;
|
||||||
let updatePerformerIds: string[] = [];
|
let updatePerformerIds: string[] = [];
|
||||||
let updateTagIds: string[] = [];
|
let updateTagIds: string[] = [];
|
||||||
|
let updateGalleryIds: string[] = [];
|
||||||
let updateOrganized: boolean | undefined;
|
let updateOrganized: boolean | undefined;
|
||||||
let first = true;
|
let first = true;
|
||||||
|
|
||||||
@@ -117,12 +133,14 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
.map((p) => p.id)
|
.map((p) => p.id)
|
||||||
.sort();
|
.sort();
|
||||||
const imageTagIDs = (image.tags ?? []).map((p) => p.id).sort();
|
const imageTagIDs = (image.tags ?? []).map((p) => p.id).sort();
|
||||||
|
const imageGalleryIDs = (image.galleries ?? []).map((p) => p.id).sort();
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
updateRating = imageRating ?? undefined;
|
updateRating = imageRating ?? undefined;
|
||||||
updateStudioID = imageStudioID;
|
updateStudioID = imageStudioID;
|
||||||
updatePerformerIds = imagePerformerIDs;
|
updatePerformerIds = imagePerformerIDs;
|
||||||
updateTagIds = imageTagIDs;
|
updateTagIds = imageTagIDs;
|
||||||
|
updateGalleryIds = imageGalleryIDs;
|
||||||
updateOrganized = image.organized;
|
updateOrganized = image.organized;
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -138,6 +156,9 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
if (!isEqual(imageTagIDs, updateTagIds)) {
|
if (!isEqual(imageTagIDs, updateTagIds)) {
|
||||||
updateTagIds = [];
|
updateTagIds = [];
|
||||||
}
|
}
|
||||||
|
if (!isEqual(imageGalleryIDs, updateGalleryIds)) {
|
||||||
|
updateGalleryIds = [];
|
||||||
|
}
|
||||||
if (image.organized !== updateOrganized) {
|
if (image.organized !== updateOrganized) {
|
||||||
updateOrganized = undefined;
|
updateOrganized = undefined;
|
||||||
}
|
}
|
||||||
@@ -148,6 +169,7 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
setStudioId(updateStudioID);
|
setStudioId(updateStudioID);
|
||||||
setExistingPerformerIds(updatePerformerIds);
|
setExistingPerformerIds(updatePerformerIds);
|
||||||
setExistingTagIds(updateTagIds);
|
setExistingTagIds(updateTagIds);
|
||||||
|
setExistingGalleryIds(updateGalleryIds);
|
||||||
setOrganized(updateOrganized);
|
setOrganized(updateOrganized);
|
||||||
}, [props.selected, performerMode, tagMode]);
|
}, [props.selected, performerMode, tagMode]);
|
||||||
|
|
||||||
@@ -157,54 +179,6 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
}
|
}
|
||||||
}, [organized, checkboxRef]);
|
}, [organized, checkboxRef]);
|
||||||
|
|
||||||
function renderMultiSelect(
|
|
||||||
type: "performers" | "tags",
|
|
||||||
ids: string[] | undefined
|
|
||||||
) {
|
|
||||||
let mode = GQL.BulkUpdateIdMode.Add;
|
|
||||||
let existingIds: string[] | undefined = [];
|
|
||||||
switch (type) {
|
|
||||||
case "performers":
|
|
||||||
mode = performerMode;
|
|
||||||
existingIds = existingPerformerIds;
|
|
||||||
break;
|
|
||||||
case "tags":
|
|
||||||
mode = tagMode;
|
|
||||||
existingIds = existingTagIds;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MultiSet
|
|
||||||
type={type}
|
|
||||||
disabled={isUpdating}
|
|
||||||
onUpdate={(itemIDs) => {
|
|
||||||
switch (type) {
|
|
||||||
case "performers":
|
|
||||||
setPerformerIds(itemIDs);
|
|
||||||
break;
|
|
||||||
case "tags":
|
|
||||||
setTagIds(itemIDs);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onSetMode={(newMode) => {
|
|
||||||
switch (type) {
|
|
||||||
case "performers":
|
|
||||||
setPerformerMode(newMode);
|
|
||||||
break;
|
|
||||||
case "tags":
|
|
||||||
setTagMode(newMode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
existingIds={existingIds ?? []}
|
|
||||||
ids={ids ?? []}
|
|
||||||
mode={mode}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function cycleOrganized() {
|
function cycleOrganized() {
|
||||||
if (organized) {
|
if (organized) {
|
||||||
setOrganized(undefined);
|
setOrganized(undefined);
|
||||||
@@ -271,14 +245,45 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
<Form.Label>
|
<Form.Label>
|
||||||
<FormattedMessage id="performers" />
|
<FormattedMessage id="performers" />
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
{renderMultiSelect("performers", performerIds)}
|
<MultiSet
|
||||||
|
type="performers"
|
||||||
|
disabled={isUpdating}
|
||||||
|
onUpdate={(itemIDs) => setPerformerIds(itemIDs)}
|
||||||
|
onSetMode={(newMode) => setPerformerMode(newMode)}
|
||||||
|
existingIds={existingPerformerIds ?? []}
|
||||||
|
ids={performerIds ?? []}
|
||||||
|
mode={performerMode}
|
||||||
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group controlId="tags">
|
<Form.Group controlId="tags">
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
<FormattedMessage id="tags" />
|
<FormattedMessage id="tags" />
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
{renderMultiSelect("tags", tagIds)}
|
<MultiSet
|
||||||
|
type="tags"
|
||||||
|
disabled={isUpdating}
|
||||||
|
onUpdate={(itemIDs) => setTagIds(itemIDs)}
|
||||||
|
onSetMode={(newMode) => setTagMode(newMode)}
|
||||||
|
existingIds={existingTagIds ?? []}
|
||||||
|
ids={tagIds ?? []}
|
||||||
|
mode={tagMode}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
|
||||||
|
<Form.Group controlId="galleries">
|
||||||
|
<Form.Label>
|
||||||
|
<FormattedMessage id="galleries" />
|
||||||
|
</Form.Label>
|
||||||
|
<MultiSet
|
||||||
|
type="galleries"
|
||||||
|
disabled={isUpdating}
|
||||||
|
onUpdate={(itemIDs) => setGalleryIds(itemIDs)}
|
||||||
|
onSetMode={(newMode) => setGalleryMode(newMode)}
|
||||||
|
existingIds={existingGalleryIds ?? []}
|
||||||
|
ids={galleryIds ?? []}
|
||||||
|
mode={galleryMode}
|
||||||
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group controlId="organized">
|
<Form.Group controlId="organized">
|
||||||
|
|||||||
@@ -24,8 +24,11 @@ import { formikUtils } from "src/utils/form";
|
|||||||
import { Tag, TagSelect } from "src/components/Tags/TagSelect";
|
import { Tag, TagSelect } from "src/components/Tags/TagSelect";
|
||||||
import { Studio, StudioSelect } from "src/components/Studios/StudioSelect";
|
import { Studio, StudioSelect } from "src/components/Studios/StudioSelect";
|
||||||
import { galleryTitle } from "src/core/galleries";
|
import { galleryTitle } from "src/core/galleries";
|
||||||
import { Gallery, GallerySelect } from "src/components/Galleries/GallerySelect";
|
import {
|
||||||
import { PathCriterion } from "src/models/list-filter/criteria/path";
|
Gallery,
|
||||||
|
GallerySelect,
|
||||||
|
excludeFileBasedGalleries,
|
||||||
|
} from "src/components/Galleries/GallerySelect";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
image: GQL.ImageDataFragment;
|
image: GQL.ImageDataFragment;
|
||||||
@@ -34,14 +37,6 @@ interface IProps {
|
|||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getExcludeFilebaseGalleriesFilter() {
|
|
||||||
const ret = new PathCriterion();
|
|
||||||
ret.modifier = GQL.CriterionModifier.IsNull;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const excludeFileBasedGalleries = [getExcludeFilebaseGalleriesFilter()];
|
|
||||||
|
|
||||||
export const ImageEditPanel: React.FC<IProps> = ({
|
export const ImageEditPanel: React.FC<IProps> = ({
|
||||||
image,
|
image,
|
||||||
isVisible,
|
isVisible,
|
||||||
|
|||||||
@@ -4,9 +4,13 @@ import { useIntl } from "react-intl";
|
|||||||
import * as GQL from "src/core/generated-graphql";
|
import * as GQL from "src/core/generated-graphql";
|
||||||
import { Button, ButtonGroup } from "react-bootstrap";
|
import { Button, ButtonGroup } from "react-bootstrap";
|
||||||
import { FilterSelect, SelectObject } from "./Select";
|
import { FilterSelect, SelectObject } from "./Select";
|
||||||
|
import {
|
||||||
|
GalleryIDSelect,
|
||||||
|
excludeFileBasedGalleries,
|
||||||
|
} from "../Galleries/GallerySelect";
|
||||||
|
|
||||||
interface IMultiSetProps {
|
interface IMultiSetProps {
|
||||||
type: "performers" | "studios" | "tags" | "movies";
|
type: "performers" | "studios" | "tags" | "movies" | "galleries";
|
||||||
existingIds?: string[];
|
existingIds?: string[];
|
||||||
ids?: string[];
|
ids?: string[];
|
||||||
mode: GQL.BulkUpdateIdMode;
|
mode: GQL.BulkUpdateIdMode;
|
||||||
@@ -15,6 +19,39 @@ interface IMultiSetProps {
|
|||||||
onSetMode: (mode: GQL.BulkUpdateIdMode) => void;
|
onSetMode: (mode: GQL.BulkUpdateIdMode) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Select: React.FC<IMultiSetProps> = (props) => {
|
||||||
|
const { type, disabled } = props;
|
||||||
|
|
||||||
|
function onUpdate(items: SelectObject[]) {
|
||||||
|
props.onUpdate(items.map((i) => i.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "galleries") {
|
||||||
|
return (
|
||||||
|
<GalleryIDSelect
|
||||||
|
isDisabled={disabled}
|
||||||
|
isMulti
|
||||||
|
isClearable={false}
|
||||||
|
onSelect={onUpdate}
|
||||||
|
ids={props.ids ?? []}
|
||||||
|
// exclude file-based galleries when setting galleries
|
||||||
|
extraCriteria={excludeFileBasedGalleries}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FilterSelect
|
||||||
|
type={type}
|
||||||
|
isDisabled={disabled}
|
||||||
|
isMulti
|
||||||
|
isClearable={false}
|
||||||
|
onSelect={onUpdate}
|
||||||
|
ids={props.ids ?? []}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const MultiSet: React.FC<IMultiSetProps> = (props) => {
|
export const MultiSet: React.FC<IMultiSetProps> = (props) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const modes = [
|
const modes = [
|
||||||
@@ -23,10 +60,6 @@ export const MultiSet: React.FC<IMultiSetProps> = (props) => {
|
|||||||
GQL.BulkUpdateIdMode.Remove,
|
GQL.BulkUpdateIdMode.Remove,
|
||||||
];
|
];
|
||||||
|
|
||||||
function onUpdate(items: SelectObject[]) {
|
|
||||||
props.onUpdate(items.map((i) => i.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getModeText(mode: GQL.BulkUpdateIdMode) {
|
function getModeText(mode: GQL.BulkUpdateIdMode) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case GQL.BulkUpdateIdMode.Set:
|
case GQL.BulkUpdateIdMode.Set:
|
||||||
@@ -83,14 +116,7 @@ export const MultiSet: React.FC<IMultiSetProps> = (props) => {
|
|||||||
<ButtonGroup className="button-group-above">
|
<ButtonGroup className="button-group-above">
|
||||||
{modes.map((m) => renderModeButton(m))}
|
{modes.map((m) => renderModeButton(m))}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<FilterSelect
|
<Select {...props} />
|
||||||
type={props.type}
|
|
||||||
isDisabled={props.disabled}
|
|
||||||
isMulti
|
|
||||||
isClearable={false}
|
|
||||||
onSelect={onUpdate}
|
|
||||||
ids={props.ids ?? []}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,22 +48,16 @@ export function getAggregateStudioId(state: IHasStudio[]) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IHasPerformers {
|
export function getAggregateIds(sortedLists: string[][]) {
|
||||||
performers: IHasID[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAggregatePerformerIds(state: IHasPerformers[]) {
|
|
||||||
let ret: string[] = [];
|
let ret: string[] = [];
|
||||||
let first = true;
|
let first = true;
|
||||||
|
|
||||||
state.forEach((o) => {
|
sortedLists.forEach((l) => {
|
||||||
if (first) {
|
if (first) {
|
||||||
ret = o.performers ? o.performers.map((p) => p.id).sort() : [];
|
ret = l;
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
const perfIds = o.performers ? o.performers.map((p) => p.id).sort() : [];
|
if (!isEqual(ret, l)) {
|
||||||
|
|
||||||
if (!isEqual(ret, perfIds)) {
|
|
||||||
ret = [];
|
ret = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,56 +66,30 @@ export function getAggregatePerformerIds(state: IHasPerformers[]) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IHasTags {
|
export function getAggregateGalleryIds(state: { galleries: IHasID[] }[]) {
|
||||||
tags: IHasID[];
|
const sortedLists = state.map((o) => o.galleries.map((oo) => oo.id).sort());
|
||||||
|
return getAggregateIds(sortedLists);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAggregateTagIds(state: IHasTags[]) {
|
export function getAggregatePerformerIds(state: { performers: IHasID[] }[]) {
|
||||||
let ret: string[] = [];
|
const sortedLists = state.map((o) => o.performers.map((oo) => oo.id).sort());
|
||||||
let first = true;
|
return getAggregateIds(sortedLists);
|
||||||
|
}
|
||||||
|
|
||||||
state.forEach((o) => {
|
export function getAggregateTagIds(state: { tags: IHasID[] }[]) {
|
||||||
if (first) {
|
const sortedLists = state.map((o) => o.tags.map((oo) => oo.id).sort());
|
||||||
ret = o.tags ? o.tags.map((t) => t.id).sort() : [];
|
return getAggregateIds(sortedLists);
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
const tIds = o.tags ? o.tags.map((t) => t.id).sort() : [];
|
|
||||||
|
|
||||||
if (!isEqual(ret, tIds)) {
|
|
||||||
ret = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMovie {
|
interface IMovie {
|
||||||
movie: IHasID;
|
movie: IHasID;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IHasMovies {
|
export function getAggregateMovieIds(state: { movies: IMovie[] }[]) {
|
||||||
movies: IMovie[];
|
const sortedLists = state.map((o) =>
|
||||||
}
|
o.movies.map((oo) => oo.movie.id).sort()
|
||||||
|
);
|
||||||
export function getAggregateMovieIds(state: IHasMovies[]) {
|
return getAggregateIds(sortedLists);
|
||||||
let ret: string[] = [];
|
|
||||||
let first = true;
|
|
||||||
|
|
||||||
state.forEach((o) => {
|
|
||||||
if (first) {
|
|
||||||
ret = o.movies ? o.movies.map((m) => m.movie.id).sort() : [];
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
const mIds = o.movies ? o.movies.map((m) => m.movie.id).sort() : [];
|
|
||||||
|
|
||||||
if (!isEqual(ret, mIds)) {
|
|
||||||
ret = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeBulkUpdateIds(
|
export function makeBulkUpdateIds(
|
||||||
|
|||||||
Reference in New Issue
Block a user