Blueprint removed

This commit is contained in:
Infinite
2020-01-11 23:14:20 +01:00
parent e18e67b512
commit 129dcecdef
85 changed files with 1429 additions and 1996 deletions

View File

@@ -0,0 +1,211 @@
import React, { useState, useCallback } from "react";
import Select, { ValueType } from 'react-select';
import CreatableSelect from 'react-select/creatable';
import { debounce } from 'lodash';
import * as GQL from "src/core/generated-graphql";
import { StashService } from "src/core/StashService";
import { useToast } from 'src/hooks';
type ValidTypes =
GQL.AllPerformersForFilterAllPerformers |
GQL.AllTagsForFilterAllTags |
GQL.AllStudiosForFilterAllStudios;
type Option = { value:string, label:string };
interface ITypeProps {
type?: 'performers' | 'studios' | 'tags';
}
interface IFilterProps {
initialIds: string[];
onSelect: (item: ValidTypes[]) => void;
noSelectionString?: string;
className?: string;
isMulti?: boolean;
}
interface ISelectProps {
className?: string;
items: Option[];
selectedOptions?: Option[];
creatable?: boolean;
onCreateOption?: (value: string) => void;
isLoading: boolean;
onChange: (item: ValueType<Option>) => void;
initialIds: string[];
isMulti?: boolean;
onInputChange?: (input: string) => void;
placeholder?: string;
}
interface ISceneGallerySelect {
initialId?: string;
sceneId: string;
onSelect: (item: GQL.ValidGalleriesForSceneValidGalleriesForScene | undefined) => void;
}
export const SceneGallerySelect: React.FC<ISceneGallerySelect> = (props) => {
const { data, loading } = StashService.useValidGalleriesForScene(props.sceneId);
const galleries = data?.validGalleriesForScene ?? [];
const items = (galleries.length > 0 ? [{ path: 'None', id: '0' }, ...galleries] : [])
.map(g => ({ label: g.path, value: g.id }));
const onChange = (selectedItems:ValueType<Option>) => {
const selectedItem = getSelectedValues(selectedItems)[0];
props.onSelect(galleries.find(g => g.id === selectedItem.value));
};
const initialId = props.initialId ? [props.initialId] : [];
return <SelectComponent onChange={onChange} isLoading={loading} items={items} initialIds={initialId} />
};
interface IScrapePerformerSuggestProps {
scraperId: string;
onSelectPerformer: (query: GQL.ScrapePerformerListScrapePerformerList) => void;
placeholder?: string;
}
export const ScrapePerformerSuggest: React.FC<IScrapePerformerSuggestProps> = (props) => {
const [query, setQuery] = React.useState<string>("");
const { data, loading } = StashService.useScrapePerformerList(props.scraperId, query);
const onInputChange = useCallback(debounce((input:string) => { setQuery(input)}, 500), []);
const onChange = (selectedItems:ValueType<Option>) => (
props.onSelectPerformer(getSelectedValues(selectedItems)[0])
);
const performers = data?.scrapePerformerList ?? [];
console.log(`performers: ${performers}, loading: ${loading}, query: ${query}`);
const items = performers.map(item => ({ label: item.name ?? '', value: item.name ?? '' }));
return <SelectComponent onChange={onChange} onInputChange={onInputChange} isLoading={loading} items={items} initialIds={[]} placeholder={props.placeholder} />
}
interface IMarkerSuggestProps {
initialMarkerTitle?: string;
onChange: (title:string) => void;
}
export const MarkerTitleSuggest: React.FC<IMarkerSuggestProps> = (props) => {
const { data, loading } = StashService.useMarkerStrings();
const suggestions = data?.markerStrings ?? [];
const onChange = (selectedItems:ValueType<Option>) => (
props.onChange(getSelectedValues(selectedItems)[0])
);
const items = suggestions.map(item => ({ label: item?.title ?? '', value: item?.title ?? '' }));
const initialIds = props.initialMarkerTitle ? [props.initialMarkerTitle] : [];
return <SelectComponent creatable onChange={onChange} isLoading={loading} items={items} initialIds={initialIds} />
}
export const FilterSelect: React.FC<IFilterProps & ITypeProps> = (props) => (
props.type === 'performers' ? <PerformerSelect {...props as IFilterProps} />
: props.type === 'studios' ? <StudioSelect {...props as IFilterProps} />
: <TagSelect {...props as IFilterProps} />
);
export const PerformerSelect: React.FC<IFilterProps> = (props) => {
const { data, loading } = StashService.useAllPerformersForFilter();
const normalizedData = data?.allPerformers ?? [];
const items:Option[] = normalizedData.map(item => ({ value: item.id, label: item.name ?? '' }));
const placeholder = props.noSelectionString ?? "Select performer..."
const onChange = (selectedItems:ValueType<Option>) => {
const selectedIds = getSelectedValues(selectedItems);
props.onSelect(normalizedData.filter(item => selectedIds.indexOf(item.id) !== -1));
};
return <SelectComponent {...props} onChange={onChange} type="performers" isLoading={loading} items={items} placeholder={placeholder} />
}
export const StudioSelect: React.FC<IFilterProps> = (props) => {
const { data, loading } = StashService.useAllStudiosForFilter();
const normalizedData = data?.allStudios ?? [];
const items:Option[] = normalizedData.map(item => ({ value: item.id, label: item.name }));
const placeholder = props.noSelectionString ?? "Select studio..."
const onChange = (selectedItems:ValueType<Option>) => {
const selectedIds = getSelectedValues(selectedItems);
props.onSelect(normalizedData.filter(item => selectedIds.indexOf(item.id) !== -1));
};
return <SelectComponent {...props} onChange={onChange} type="studios" isLoading={loading} items={items} placeholder={placeholder} />
}
export const TagSelect: React.FC<IFilterProps> = (props) => {
const [loading, setLoading] = useState(false);
const [selectedIds, setSelectedIds] = useState<string[]>([]);
const { data, loading: dataLoading } = StashService.useAllTagsForFilter();
const createTag = StashService.useTagCreate({name: ''});
const Toast = useToast();
const placeholder = props.noSelectionString ?? "Select tags..."
const tags = data?.allTags ?? [];
const onCreate = async (tagName: string) => {
try {
setLoading(true);
const result = await createTag({
variables: { name: tagName },
});
setSelectedIds([...selectedIds, result.data.tagCreate.id]);
props.onSelect([...tags, result.data.tagCreate].filter(item => selected.indexOf(item.id) !== -1));
setLoading(false);
Toast.success({ content: (<span>Created tag: <b>{tagName}</b></span>) });
} catch (e) {
Toast.error(e);
}
};
const onChange = (selectedItems:ValueType<Option>) => {
const selected = getSelectedValues(selectedItems);
setSelectedIds(selected);
props.onSelect(tags.filter(item => selected.indexOf(item.id) !== -1));
};
const selected = tags.filter(tag => selectedIds.indexOf(tag.id) !== -1).map(tag => ({value: tag.id, label: tag.name}));
const items:Option[] = tags.map(item => ({ value: item.id, label: item.name }));
return <SelectComponent {...props} onChange={onChange} creatable={true} type="tags" placeholder={placeholder}
isLoading={loading || dataLoading} items={items} onCreateOption={onCreate} selectedOptions={selected} />
}
const SelectComponent: React.FC<ISelectProps & ITypeProps> = ({
type,
initialIds,
onChange,
className,
items,
selectedOptions,
isLoading,
onCreateOption,
creatable = false,
isMulti = false,
onInputChange,
placeholder
}) => {
const defaultValue = items.filter(item => initialIds?.indexOf(item.value) !== -1) ?? null;
const props = {
className: className,
options: items,
value: selectedOptions,
onChange: onChange,
isMulti: isMulti,
defaultValue: defaultValue,
noOptionsMessage: () => (type !== 'tags' ? 'None' : null),
placeholder: placeholder,
onInputChange
}
return (
creatable
? <CreatableSelect {...props} isLoading={isLoading} isDisabled={isLoading} onCreateOption={onCreateOption} />
: <Select {...props} isLoading={isLoading} />
);
};
const getSelectedValues = (selectedItems:ValueType<Option>) => (
(Array.isArray(selectedItems) ? selectedItems : [selectedItems])
.map(item => item.value)
);