mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
Add modes for performer/tag for bulk scene editing (#412)
This commit is contained in:
@@ -39,8 +39,8 @@ mutation BulkSceneUpdate(
|
||||
$rating: Int,
|
||||
$studio_id: ID,
|
||||
$gallery_id: ID,
|
||||
$performer_ids: [ID!],
|
||||
$tag_ids: [ID!]) {
|
||||
$performer_ids: BulkUpdateIds,
|
||||
$tag_ids: BulkUpdateIds) {
|
||||
|
||||
bulkSceneUpdate(input: {
|
||||
ids: $ids,
|
||||
|
||||
@@ -68,6 +68,17 @@ input SceneUpdateInput {
|
||||
cover_image: String
|
||||
}
|
||||
|
||||
enum BulkUpdateIdMode {
|
||||
SET
|
||||
ADD
|
||||
REMOVE
|
||||
}
|
||||
|
||||
input BulkUpdateIds {
|
||||
ids: [ID!]
|
||||
mode: BulkUpdateIdMode!
|
||||
}
|
||||
|
||||
input BulkSceneUpdateInput {
|
||||
clientMutationId: String
|
||||
ids: [ID!]
|
||||
@@ -78,8 +89,8 @@ input BulkSceneUpdateInput {
|
||||
rating: Int
|
||||
studio_id: ID
|
||||
gallery_id: ID
|
||||
performer_ids: [ID!]
|
||||
tag_ids: [ID!]
|
||||
performer_ids: BulkUpdateIds
|
||||
tag_ids: BulkUpdateIds
|
||||
}
|
||||
|
||||
input SceneDestroyInput {
|
||||
|
||||
@@ -269,9 +269,14 @@ func (r *mutationResolver) BulkSceneUpdate(ctx context.Context, input models.Bul
|
||||
|
||||
// Save the performers
|
||||
if wasFieldIncluded(ctx, "performer_ids") {
|
||||
performerIDs, err := adjustScenePerformerIDs(tx, sceneID, *input.PerformerIds)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var performerJoins []models.PerformersScenes
|
||||
for _, pid := range input.PerformerIds {
|
||||
performerID, _ := strconv.Atoi(pid)
|
||||
for _, performerID := range performerIDs {
|
||||
performerJoin := models.PerformersScenes{
|
||||
PerformerID: performerID,
|
||||
SceneID: sceneID,
|
||||
@@ -286,9 +291,14 @@ func (r *mutationResolver) BulkSceneUpdate(ctx context.Context, input models.Bul
|
||||
|
||||
// Save the tags
|
||||
if wasFieldIncluded(ctx, "tag_ids") {
|
||||
tagIDs, err := adjustSceneTagIDs(tx, sceneID, *input.TagIds)
|
||||
if err != nil {
|
||||
_ = tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tagJoins []models.ScenesTags
|
||||
for _, tid := range input.TagIds {
|
||||
tagID, _ := strconv.Atoi(tid)
|
||||
for _, tagID := range tagIDs {
|
||||
tagJoin := models.ScenesTags{
|
||||
SceneID: sceneID,
|
||||
TagID: tagID,
|
||||
@@ -310,6 +320,72 @@ func (r *mutationResolver) BulkSceneUpdate(ctx context.Context, input models.Bul
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func adjustIDs(existingIDs []int, updateIDs models.BulkUpdateIds) []int {
|
||||
for _, idStr := range updateIDs.Ids {
|
||||
id, _ := strconv.Atoi(idStr)
|
||||
|
||||
// look for the id in the list
|
||||
foundExisting := false
|
||||
for idx, existingID := range existingIDs {
|
||||
if existingID == id {
|
||||
if updateIDs.Mode == models.BulkUpdateIDModeRemove {
|
||||
// remove from the list
|
||||
existingIDs = append(existingIDs[:idx], existingIDs[idx+1:]...)
|
||||
}
|
||||
|
||||
foundExisting = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !foundExisting && updateIDs.Mode != models.BulkUpdateIDModeRemove {
|
||||
existingIDs = append(existingIDs, id)
|
||||
}
|
||||
}
|
||||
|
||||
return existingIDs
|
||||
}
|
||||
|
||||
func adjustScenePerformerIDs(tx *sqlx.Tx, sceneID int, ids models.BulkUpdateIds) ([]int, error) {
|
||||
var ret []int
|
||||
|
||||
jqb := models.NewJoinsQueryBuilder()
|
||||
if ids.Mode == models.BulkUpdateIDModeAdd || ids.Mode == models.BulkUpdateIDModeRemove {
|
||||
// adding to the joins
|
||||
performerJoins, err := jqb.GetScenePerformers(sceneID, tx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, join := range performerJoins {
|
||||
ret = append(ret, join.PerformerID)
|
||||
}
|
||||
}
|
||||
|
||||
return adjustIDs(ret, ids), nil
|
||||
}
|
||||
|
||||
func adjustSceneTagIDs(tx *sqlx.Tx, sceneID int, ids models.BulkUpdateIds) ([]int, error) {
|
||||
var ret []int
|
||||
|
||||
jqb := models.NewJoinsQueryBuilder()
|
||||
if ids.Mode == models.BulkUpdateIDModeAdd || ids.Mode == models.BulkUpdateIDModeRemove {
|
||||
// adding to the joins
|
||||
tagJoins, err := jqb.GetSceneTags(sceneID, tx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, join := range tagJoins {
|
||||
ret = append(ret, join.TagID)
|
||||
}
|
||||
}
|
||||
|
||||
return adjustIDs(ret, ids), nil
|
||||
}
|
||||
|
||||
func (r *mutationResolver) SceneDestroy(ctx context.Context, input models.SceneDestroyInput) (bool, error) {
|
||||
qb := models.NewSceneQueryBuilder()
|
||||
tx := database.DB.MustBeginTx(ctx, nil)
|
||||
|
||||
@@ -4,11 +4,11 @@ import _ from "lodash";
|
||||
import { StashService } from "src/core/StashService";
|
||||
import * as GQL from "src/core/generated-graphql";
|
||||
import {
|
||||
FilterSelect,
|
||||
StudioSelect,
|
||||
LoadingIndicator
|
||||
} from "src/components/Shared";
|
||||
import { useToast } from "src/hooks";
|
||||
import MultiSet from "../Shared/MultiSet";
|
||||
|
||||
interface IListOperationProps {
|
||||
selected: GQL.SlimSceneDataFragment[];
|
||||
@@ -21,7 +21,9 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
||||
const Toast = useToast();
|
||||
const [rating, setRating] = useState<string>("");
|
||||
const [studioId, setStudioId] = useState<string>();
|
||||
const [performerMode, setPerformerMode] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
||||
const [performerIds, setPerformerIds] = useState<string[]>();
|
||||
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
||||
const [tagIds, setTagIds] = useState<string[]>();
|
||||
|
||||
const [updateScenes] = StashService.useBulkSceneUpdate(getSceneInput());
|
||||
@@ -29,6 +31,13 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
||||
// Network state
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
function makeBulkUpdateIds(ids: string[], mode: GQL.BulkUpdateIdMode) : GQL.BulkUpdateIds {
|
||||
return {
|
||||
mode,
|
||||
ids
|
||||
};
|
||||
}
|
||||
|
||||
function getSceneInput(): GQL.BulkSceneUpdateInput {
|
||||
// need to determine what we are actually setting on each scene
|
||||
const aggregateRating = getRating(props.selected);
|
||||
@@ -69,27 +78,27 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
||||
}
|
||||
|
||||
// if performerIds are empty
|
||||
if (!performerIds || performerIds.length === 0) {
|
||||
if (performerMode === GQL.BulkUpdateIdMode.Set && (!performerIds || performerIds.length === 0)) {
|
||||
// and all scenes have the same ids,
|
||||
if (aggregatePerformerIds.length > 0) {
|
||||
// then unset the performerIds, otherwise ignore
|
||||
sceneInput.performer_ids = performerIds;
|
||||
sceneInput.performer_ids = makeBulkUpdateIds(performerIds || [], performerMode);
|
||||
}
|
||||
} else {
|
||||
// if performerIds non-empty, then we are setting them
|
||||
sceneInput.performer_ids = performerIds;
|
||||
sceneInput.performer_ids = makeBulkUpdateIds(performerIds || [], performerMode);
|
||||
}
|
||||
|
||||
// if tagIds non-empty, then we are setting them
|
||||
if (!tagIds || tagIds.length === 0) {
|
||||
if (tagMode === GQL.BulkUpdateIdMode.Set && (!tagIds || tagIds.length === 0)) {
|
||||
// and all scenes have the same ids,
|
||||
if (aggregateTagIds.length > 0) {
|
||||
// then unset the tagIds, otherwise ignore
|
||||
sceneInput.tag_ids = tagIds;
|
||||
sceneInput.tag_ids = makeBulkUpdateIds(tagIds || [], tagMode);
|
||||
}
|
||||
} else {
|
||||
// if tagIds non-empty, then we are setting them
|
||||
sceneInput.tag_ids = tagIds;
|
||||
sceneInput.tag_ids = makeBulkUpdateIds(tagIds || [], tagMode);
|
||||
}
|
||||
|
||||
return sceneInput;
|
||||
@@ -222,21 +231,31 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
||||
|
||||
setRating(updateRating);
|
||||
setStudioId(updateStudioID);
|
||||
setPerformerIds(updatePerformerIds);
|
||||
setTagIds(updateTagIds);
|
||||
if (performerMode === GQL.BulkUpdateIdMode.Set) {
|
||||
setPerformerIds(updatePerformerIds);
|
||||
}
|
||||
|
||||
if (tagMode === GQL.BulkUpdateIdMode.Set) {
|
||||
setTagIds(updateTagIds);
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
}, [props.selected]);
|
||||
}, [props.selected, performerMode, tagMode]);
|
||||
|
||||
function renderMultiSelect(
|
||||
type: "performers" | "tags",
|
||||
ids: string[] | undefined
|
||||
) {
|
||||
let mode = GQL.BulkUpdateIdMode.Add;
|
||||
switch (type) {
|
||||
case "performers": mode = performerMode; break;
|
||||
case "tags": mode = tagMode; break;
|
||||
}
|
||||
|
||||
return (
|
||||
<FilterSelect
|
||||
<MultiSet
|
||||
type={type}
|
||||
isMulti
|
||||
isClearable={false}
|
||||
onSelect={items => {
|
||||
onUpdate={items => {
|
||||
const itemIDs = items.map(i => i.id);
|
||||
switch (type) {
|
||||
case "performers":
|
||||
@@ -247,7 +266,14 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
||||
break;
|
||||
}
|
||||
}}
|
||||
onSetMode={(mode) => {
|
||||
switch (type) {
|
||||
case "performers": setPerformerMode(mode); break;
|
||||
case "tags": setTagMode(mode); break;
|
||||
}
|
||||
}}
|
||||
ids={ids ?? []}
|
||||
mode={mode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -264,6 +290,7 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
||||
<Form.Label>Rating</Form.Label>
|
||||
<Form.Control
|
||||
as="select"
|
||||
className="btn-secondary"
|
||||
value={rating}
|
||||
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
|
||||
setRating(event.currentTarget.value)
|
||||
|
||||
83
ui/v2.5/src/components/Shared/MultiSet.tsx
Normal file
83
ui/v2.5/src/components/Shared/MultiSet.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import * as React from "react";
|
||||
|
||||
import * as GQL from "src/core/generated-graphql";
|
||||
import { FilterSelect } from "./Select";
|
||||
import { Button, InputGroup } from "react-bootstrap";
|
||||
import { Icon } from "src/components/Shared";
|
||||
|
||||
type ValidTypes =
|
||||
| GQL.SlimPerformerDataFragment
|
||||
| GQL.Tag
|
||||
| GQL.SlimStudioDataFragment;
|
||||
|
||||
interface IMultiSetProps {
|
||||
type: "performers" | "studios" | "tags";
|
||||
ids?: string[];
|
||||
mode: GQL.BulkUpdateIdMode;
|
||||
onUpdate: (items: ValidTypes[]) => void;
|
||||
onSetMode: (mode: GQL.BulkUpdateIdMode) => void;
|
||||
}
|
||||
|
||||
const MultiSet: React.FunctionComponent<IMultiSetProps> = (props: IMultiSetProps) => {
|
||||
function onUpdate(items: ValidTypes[]) {
|
||||
props.onUpdate(items);
|
||||
}
|
||||
|
||||
function getModeIcon() {
|
||||
switch(props.mode) {
|
||||
case GQL.BulkUpdateIdMode.Set:
|
||||
return "pencil-alt";
|
||||
case GQL.BulkUpdateIdMode.Add:
|
||||
return "plus";
|
||||
case GQL.BulkUpdateIdMode.Remove:
|
||||
return "times";
|
||||
}
|
||||
}
|
||||
|
||||
function getModeText() {
|
||||
switch(props.mode) {
|
||||
case GQL.BulkUpdateIdMode.Set:
|
||||
return "Set";
|
||||
case GQL.BulkUpdateIdMode.Add:
|
||||
return "Add";
|
||||
case GQL.BulkUpdateIdMode.Remove:
|
||||
return "Remove";
|
||||
}
|
||||
}
|
||||
|
||||
function nextMode() {
|
||||
switch(props.mode) {
|
||||
case GQL.BulkUpdateIdMode.Set:
|
||||
return GQL.BulkUpdateIdMode.Add;
|
||||
case GQL.BulkUpdateIdMode.Add:
|
||||
return GQL.BulkUpdateIdMode.Remove;
|
||||
case GQL.BulkUpdateIdMode.Remove:
|
||||
return GQL.BulkUpdateIdMode.Set;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<InputGroup className="multi-set">
|
||||
<InputGroup.Prepend>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
onClick={() => props.onSetMode(nextMode())}
|
||||
title={getModeText()}
|
||||
>
|
||||
<Icon icon={getModeIcon()} className="fa-fw" />
|
||||
</Button>
|
||||
</InputGroup.Prepend>
|
||||
|
||||
<FilterSelect
|
||||
type={props.type}
|
||||
isMulti
|
||||
isClearable={false}
|
||||
onSelect={onUpdate}
|
||||
ids={props.ids ?? []}
|
||||
/>
|
||||
</InputGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export default MultiSet;
|
||||
@@ -68,3 +68,10 @@
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.multi-set > div.input-group-prepend + div {
|
||||
position: relative;
|
||||
flex: 1 1;
|
||||
min-width: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@@ -8,11 +8,11 @@ import {
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import { FilterSelect } from "../select/FilterSelect";
|
||||
import { FilterMultiSelect } from "../select/FilterMultiSelect";
|
||||
import { StashService } from "../../core/StashService";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import { ErrorUtils } from "../../utils/errors";
|
||||
import { ToastUtils } from "../../utils/toasts";
|
||||
import { FilterMultiSet } from "../select/FilterMultiSet";
|
||||
|
||||
interface IListOperationProps {
|
||||
selected: GQL.SlimSceneDataFragment[],
|
||||
@@ -22,7 +22,9 @@ interface IListOperationProps {
|
||||
export const SceneSelectedOptions: FunctionComponent<IListOperationProps> = (props: IListOperationProps) => {
|
||||
const [rating, setRating] = useState<string>("");
|
||||
const [studioId, setStudioId] = useState<string | undefined>(undefined);
|
||||
const [performerMode, setPerformerMode] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
||||
const [performerIds, setPerformerIds] = useState<string[] | undefined>(undefined);
|
||||
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
||||
const [tagIds, setTagIds] = useState<string[] | undefined>(undefined);
|
||||
|
||||
const updateScenes = StashService.useBulkSceneUpdate(getSceneInput());
|
||||
@@ -30,6 +32,13 @@ export const SceneSelectedOptions: FunctionComponent<IListOperationProps> = (pro
|
||||
// Network state
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
function makeBulkUpdateIds(ids: string[], mode: GQL.BulkUpdateIdMode) : GQL.BulkUpdateIds {
|
||||
return {
|
||||
mode,
|
||||
ids
|
||||
};
|
||||
}
|
||||
|
||||
function getSceneInput() : GQL.BulkSceneUpdateInput {
|
||||
// need to determine what we are actually setting on each scene
|
||||
var aggregateRating = getRating(props.selected);
|
||||
@@ -70,27 +79,27 @@ export const SceneSelectedOptions: FunctionComponent<IListOperationProps> = (pro
|
||||
}
|
||||
|
||||
// if performerIds are empty
|
||||
if (!performerIds || performerIds.length === 0) {
|
||||
if (performerMode == GQL.BulkUpdateIdMode.Set && (!performerIds || performerIds.length === 0)) {
|
||||
// and all scenes have the same ids,
|
||||
if (aggregatePerformerIds.length > 0) {
|
||||
// then unset the performerIds, otherwise ignore
|
||||
sceneInput.performer_ids = performerIds;
|
||||
sceneInput.performer_ids = makeBulkUpdateIds(performerIds || [], performerMode);
|
||||
}
|
||||
} else {
|
||||
// if performerIds non-empty, then we are setting them
|
||||
sceneInput.performer_ids = performerIds;
|
||||
sceneInput.performer_ids = makeBulkUpdateIds(performerIds || [], performerMode);
|
||||
}
|
||||
|
||||
// if tagIds non-empty, then we are setting them
|
||||
if (!tagIds || tagIds.length === 0) {
|
||||
if (tagMode == GQL.BulkUpdateIdMode.Set && (!tagIds || tagIds.length === 0)) {
|
||||
// and all scenes have the same ids,
|
||||
if (aggregateTagIds.length > 0) {
|
||||
// then unset the tagIds, otherwise ignore
|
||||
sceneInput.tag_ids = tagIds;
|
||||
sceneInput.tag_ids = makeBulkUpdateIds(tagIds || [], tagMode);
|
||||
}
|
||||
} else {
|
||||
// if tagIds non-empty, then we are setting them
|
||||
sceneInput.tag_ids = tagIds;
|
||||
sceneInput.tag_ids = makeBulkUpdateIds(tagIds || [], tagMode);
|
||||
}
|
||||
|
||||
return sceneInput;
|
||||
@@ -232,17 +241,28 @@ export const SceneSelectedOptions: FunctionComponent<IListOperationProps> = (pro
|
||||
|
||||
setRating(rating);
|
||||
setStudioId(studioId);
|
||||
setPerformerIds(performerIds);
|
||||
setTagIds(tagIds);
|
||||
if (performerMode == GQL.BulkUpdateIdMode.Set) {
|
||||
setPerformerIds(performerIds);
|
||||
}
|
||||
|
||||
if (tagMode == GQL.BulkUpdateIdMode.Set) {
|
||||
setTagIds(tagIds);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
updateScenesEditState(props.selected);
|
||||
}, [props.selected]);
|
||||
}, [props.selected, performerMode, tagMode]);
|
||||
|
||||
function renderMultiSelect(type: "performers" | "tags", initialIds: string[] | undefined) {
|
||||
let mode = GQL.BulkUpdateIdMode.Add;
|
||||
switch (type) {
|
||||
case "performers": mode = performerMode; break;
|
||||
case "tags": mode = tagMode; break;
|
||||
}
|
||||
|
||||
return (
|
||||
<FilterMultiSelect
|
||||
<FilterMultiSet
|
||||
type={type}
|
||||
onUpdate={(items) => {
|
||||
const ids = items.map((i) => i.id);
|
||||
@@ -251,7 +271,14 @@ export const SceneSelectedOptions: FunctionComponent<IListOperationProps> = (pro
|
||||
case "tags": setTagIds(ids); break;
|
||||
}
|
||||
}}
|
||||
onSetMode={(mode) => {
|
||||
switch (type) {
|
||||
case "performers": setPerformerMode(mode); break;
|
||||
case "tags": setTagMode(mode); break;
|
||||
}
|
||||
}}
|
||||
initialIds={initialIds}
|
||||
mode={mode}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
74
ui/v2/src/components/select/FilterMultiSet.tsx
Normal file
74
ui/v2/src/components/select/FilterMultiSet.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { ControlGroup, Button } from "@blueprintjs/core";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import { FilterMultiSelect } from "./FilterMultiSelect";
|
||||
|
||||
type ValidTypes =
|
||||
GQL.AllPerformersForFilterAllPerformers |
|
||||
GQL.AllTagsForFilterAllTags |
|
||||
GQL.AllMoviesForFilterAllMovies |
|
||||
GQL.AllStudiosForFilterAllStudios;
|
||||
|
||||
interface IFilterMultiSetProps {
|
||||
type: "performers" | "studios" | "movies" | "tags";
|
||||
initialIds?: string[];
|
||||
mode: GQL.BulkUpdateIdMode;
|
||||
onUpdate: (items: ValidTypes[]) => void;
|
||||
onSetMode: (mode: GQL.BulkUpdateIdMode) => void;
|
||||
}
|
||||
|
||||
export const FilterMultiSet: React.FunctionComponent<IFilterMultiSetProps> = (props: IFilterMultiSetProps) => {
|
||||
function onUpdate(items: ValidTypes[]) {
|
||||
props.onUpdate(items);
|
||||
}
|
||||
|
||||
function getModeIcon() {
|
||||
switch(props.mode) {
|
||||
case GQL.BulkUpdateIdMode.Set:
|
||||
return "edit";
|
||||
case GQL.BulkUpdateIdMode.Add:
|
||||
return "plus";
|
||||
case GQL.BulkUpdateIdMode.Remove:
|
||||
return "cross";
|
||||
}
|
||||
}
|
||||
|
||||
function getModeText() {
|
||||
switch(props.mode) {
|
||||
case GQL.BulkUpdateIdMode.Set:
|
||||
return "Set";
|
||||
case GQL.BulkUpdateIdMode.Add:
|
||||
return "Add";
|
||||
case GQL.BulkUpdateIdMode.Remove:
|
||||
return "Remove";
|
||||
}
|
||||
}
|
||||
|
||||
function nextMode() {
|
||||
switch(props.mode) {
|
||||
case GQL.BulkUpdateIdMode.Set:
|
||||
return GQL.BulkUpdateIdMode.Add;
|
||||
case GQL.BulkUpdateIdMode.Add:
|
||||
return GQL.BulkUpdateIdMode.Remove;
|
||||
case GQL.BulkUpdateIdMode.Remove:
|
||||
return GQL.BulkUpdateIdMode.Set;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ControlGroup>
|
||||
<Button
|
||||
icon={getModeIcon()}
|
||||
minimal={true}
|
||||
onClick={() => props.onSetMode(nextMode())}
|
||||
title={getModeText()}
|
||||
/>
|
||||
<FilterMultiSelect
|
||||
type={props.type}
|
||||
initialIds={props.initialIds}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
</ControlGroup>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user