This commit is contained in:
Infinite
2020-02-13 19:57:25 +01:00
parent 8fe6eb0d77
commit 750759e4bf
20 changed files with 120 additions and 100 deletions

View File

@@ -1,11 +1,11 @@
import React from "react";
interface IErrorBoundaryProps {
children?: React.ReactNode,
children?: React.ReactNode;
}
type ErrorInfo = {
componentStack: string,
componentStack: string;
};
interface IErrorBoundaryState {
@@ -13,7 +13,10 @@ interface IErrorBoundaryState {
errorInfo?: ErrorInfo;
}
export class ErrorBoundary extends React.Component<IErrorBoundaryProps, IErrorBoundaryState> {
export class ErrorBoundary extends React.Component<
IErrorBoundaryProps,
IErrorBoundaryState
> {
constructor(props: IErrorBoundaryProps) {
super(props);
this.state = {};

View File

@@ -26,9 +26,7 @@ export const AddFilter: React.FC<IAddFilterProps> = (
const defaultValue = useRef<string | number | undefined>();
const [isOpen, setIsOpen] = useState(false);
const [criterion, setCriterion] = useState<Criterion>(
new NoneCriterion()
);
const [criterion, setCriterion] = useState<Criterion>(new NoneCriterion());
const valueStage = useRef<CriterionValue>(criterion.value);
@@ -140,10 +138,11 @@ export const AddFilter: React.FC<IAddFilterProps> = (
}
if (Array.isArray(criterion.value)) {
if(
if (
criterion.type !== "performers" &&
criterion.type !== "studios" &&
criterion.type !== "tags")
criterion.type !== "tags"
)
return;
return (

View File

@@ -72,8 +72,8 @@ export const ListFilter: React.FC<IListFilterProps> = (
}
}
function onChangeSortBy(event:React.MouseEvent<SafeAnchor>) {
const target = event.currentTarget as unknown as HTMLAnchorElement;
function onChangeSortBy(event: React.MouseEvent<SafeAnchor>) {
const target = (event.currentTarget as unknown) as HTMLAnchorElement;
props.onChangeSortBy(target.text);
}

View File

@@ -132,7 +132,9 @@ export const ParserInput: React.FC<IParserInputProps> = (
<InputGroup className="col-8">
<Form.Control
id="filename-pattern"
onChange={(e: React.FormEvent<HTMLInputElement>) => setPattern(e.currentTarget.value)}
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setPattern(e.currentTarget.value)
}
value={pattern}
/>
<InputGroup.Append>
@@ -158,7 +160,9 @@ export const ParserInput: React.FC<IParserInputProps> = (
<Form.Label className="col-2">Ignored words</Form.Label>
<InputGroup className="col-8">
<Form.Control
onChange={(e: React.FormEvent<HTMLInputElement>) => setIgnoreWords(e.currentTarget.value)}
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setIgnoreWords(e.currentTarget.value)
}
value={ignoreWords}
/>
</InputGroup>

View File

@@ -10,7 +10,7 @@ import { useToast } from "src/hooks";
import { Pagination } from "src/components/List/Pagination";
import { IParserInput, ParserInput } from "./ParserInput";
import { ParserField } from "./ParserField";
import { SceneParserResult, SceneParserRow } from './SceneParserRow';
import { SceneParserResult, SceneParserRow } from "./SceneParserRow";
const initialParserInput = {
pattern: "{title}.{ext}",

View File

@@ -1,9 +1,9 @@
import React from "react";
import _ from "lodash";
import { Form } from 'react-bootstrap';
import { Form } from "react-bootstrap";
import {
ParseSceneFilenamesQuery,
SlimSceneDataFragment,
SlimSceneDataFragment
} from "src/core/generated-graphql";
import {
PerformerSelect,
@@ -77,15 +77,9 @@ export class SceneParserResult {
url: this.scene.url,
rating: this.scene.rating,
gallery_id: this.scene.gallery?.id,
title: this.title.isSet
? this.title.value
: this.scene.title,
date: this.date.isSet
? this.date.value
: this.scene.date,
studio_id: this.studio.isSet
? this.studio.value
: this.scene.studio?.id,
title: this.title.isSet ? this.title.value : this.scene.title,
date: this.date.isSet ? this.date.value : this.scene.date,
studio_id: this.studio.isSet ? this.studio.value : this.scene.studio?.id,
performer_ids: this.performers.isSet
? this.performers.value
: this.scene.performers.map(performer => performer.id),
@@ -135,7 +129,9 @@ function SceneParserStringField(props: ISceneParserFieldProps<string>) {
disabled={!props.parserResult.isSet}
className={props.className}
value={props.parserResult.value || ""}
onChange={(event: React.FormEvent<HTMLInputElement>) => maybeValueChanged(event.currentTarget.value)}
onChange={(event: React.FormEvent<HTMLInputElement>) =>
maybeValueChanged(event.currentTarget.value)
}
/>
</Form.Group>
</td>
@@ -150,7 +146,8 @@ function SceneParserPerformerField(props: ISceneParserFieldProps<string[]>) {
}
}
const originalPerformers = (props.originalParserResult?.originalValue ?? []) as string[];
const originalPerformers = (props.originalParserResult?.originalValue ??
[]) as string[];
const newPerformers = props.parserResult.value ?? [];
return (
@@ -165,11 +162,7 @@ function SceneParserPerformerField(props: ISceneParserFieldProps<string[]>) {
</td>
<td>
<Form.Group className={props.className}>
<PerformerSelect
isDisabled
isMulti
ids={originalPerformers}
/>
<PerformerSelect isDisabled isMulti ids={originalPerformers} />
<PerformerSelect
isMulti
onSelect={items => {
@@ -205,11 +198,7 @@ function SceneParserTagField(props: ISceneParserFieldProps<string[]>) {
</td>
<td>
<Form.Group className={props.className}>
<TagSelect
isDisabled
isMulti
ids={originalTags}
/>
<TagSelect isDisabled isMulti ids={originalTags} />
<TagSelect
isMulti
onSelect={items => {
@@ -230,7 +219,9 @@ function SceneParserStudioField(props: ISceneParserFieldProps<string>) {
}
}
const originalStudio = props.originalParserResult?.originalValue ? [props.originalParserResult?.originalValue] : [];
const originalStudio = props.originalParserResult?.originalValue
? [props.originalParserResult?.originalValue]
: [];
const newStudio = props.parserResult.value ? [props.parserResult.value] : [];
return (
@@ -245,10 +236,7 @@ function SceneParserStudioField(props: ISceneParserFieldProps<string>) {
</td>
<td>
<Form.Group className={props.className}>
<StudioSelect
isDisabled
ids={originalStudio}
/>
<StudioSelect isDisabled ids={originalStudio} />
<StudioSelect
onSelect={items => {
maybeValueChanged(items[0].id);
@@ -295,7 +283,7 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
function onTagIdsChanged(set: boolean, value: string[]) {
const newResult = _.clone(props.scene);
newResult.tags= changeParser(newResult.tags, set, value);
newResult.tags = changeParser(newResult.tags, set, value);
props.onChange(newResult);
}
@@ -310,31 +298,33 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
<td className="text-left parser-field-filename">
{props.scene.filename}
</td>
{ props.showFields.get("Title") && (
{props.showFields.get("Title") && (
<SceneParserStringField
key="title"
fieldName="Title"
className="parser-field-title"
parserResult={props.scene.title}
onSetChanged={isSet =>
onTitleChanged(isSet, props.scene.title.value ?? '')
onTitleChanged(isSet, props.scene.title.value ?? "")
}
onValueChanged={value =>
onTitleChanged(props.scene.title.isSet, value)
}
onValueChanged={value => onTitleChanged(props.scene.title.isSet, value)}
/>
)}
{ props.showFields.get("Date") && (
{props.showFields.get("Date") && (
<SceneParserStringField
key="date"
fieldName="Date"
className="parser-field-date"
parserResult={props.scene.date}
onSetChanged={isSet =>
onDateChanged(isSet, props.scene.date.value ?? '')
onDateChanged(isSet, props.scene.date.value ?? "")
}
onValueChanged={value => onDateChanged(props.scene.date.isSet, value)}
/>
)}
{ props.showFields.get("Performers") && (
{props.showFields.get("Performers") && (
<SceneParserPerformerField
key="performers"
fieldName="Performers"
@@ -342,17 +332,14 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
parserResult={props.scene.performers}
originalParserResult={props.scene.performers}
onSetChanged={set =>
onPerformerIdsChanged(
set,
props.scene.performers.value ?? []
)
onPerformerIdsChanged(set, props.scene.performers.value ?? [])
}
onValueChanged={value =>
onPerformerIdsChanged(props.scene.performers.isSet, value)
}
/>
)}
{ props.showFields.get("Tags") && (
{props.showFields.get("Tags") && (
<SceneParserTagField
key="tags"
fieldName="Tags"
@@ -367,7 +354,7 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
}
/>
)}
{ props.showFields.get("Studio") && (
{props.showFields.get("Studio") && (
<SceneParserStudioField
key="studio"
fieldName="Studio"
@@ -375,11 +362,13 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
parserResult={props.scene.studio}
originalParserResult={props.scene.studio}
onSetChanged={set =>
onStudioIdChanged(set, props.scene.studio.value ?? '')
onStudioIdChanged(set, props.scene.studio.value ?? "")
}
onValueChanged={value =>
onStudioIdChanged(props.scene.studio.isSet, value)
}
onValueChanged={value => onStudioIdChanged(props.scene.studio.isSet, value)}
/>
)}
</tr>
);
}
};

View File

@@ -68,10 +68,11 @@ export class ScenePlayerImpl extends React.Component<
}
public UNSAFE_componentWillReceiveProps(props: IScenePlayerProps) {
if(props.scene !== this.props.scene) {
this.setState( state => (
{ ...state, config: this.makeJWPlayerConfig(this.props.scene) }
));
if (props.scene !== this.props.scene) {
this.setState(state => ({
...state,
config: this.makeJWPlayerConfig(this.props.scene)
}));
}
}
@@ -147,7 +148,9 @@ export class ScenePlayerImpl extends React.Component<
let seekHook:
| ((seekToPosition: number, _videoTag: HTMLVideoElement) => void)
| undefined;
let getCurrentTimeHook: ((_videoTag: HTMLVideoElement) => number) | undefined;
let getCurrentTimeHook:
| ((_videoTag: HTMLVideoElement) => number)
| undefined;
if (!this.props.scene.is_streamable) {
getDurationHook = () => {
@@ -163,7 +166,7 @@ export class ScenePlayerImpl extends React.Component<
};
getCurrentTimeHook = (_videoTag: HTMLVideoElement) => {
const start = Number.parseInt(_videoTag.dataset?.start ?? '0', 10);
const start = Number.parseInt(_videoTag.dataset?.start ?? "0", 10);
return _videoTag.currentTime + start;
};
}

View File

@@ -78,8 +78,8 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = (
const positionIndicatorEl = useRef<HTMLDivElement>(null);
const scrubberSliderEl = useRef<HTMLDivElement>(null);
const mouseDown = useRef(false);
const lastMouseEvent = useRef<MouseEvent|null>(null);
const startMouseEvent = useRef<MouseEvent|null>(null);
const lastMouseEvent = useRef<MouseEvent | null>(null);
const startMouseEvent = useRef<MouseEvent | null>(null);
const velocity = useRef(0);
const _position = useRef(0);
@@ -279,7 +279,7 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = (
return {};
}
let tag: Element|null;
let tag: Element | null;
for (let index = 0; index < tags.length; index++) {
tag = tags.item(index);
const id = tag?.getAttribute("data-marker-id") ?? null;
@@ -293,7 +293,8 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = (
const percentage = marker.seconds / duration;
const left =
scrubberSliderEl.current.scrollWidth * percentage - tag!.clientWidth / 2;
scrubberSliderEl.current.scrollWidth * percentage -
tag!.clientWidth / 2;
return {
left: `${left}px`,
height: 20

View File

@@ -305,7 +305,9 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
<td>URL</td>
<td>
<Form.Control
onChange={(newValue: React.FormEvent<HTMLInputElement>) => setUrl(newValue.currentTarget.value)}
onChange={(newValue: React.FormEvent<HTMLInputElement>) =>
setUrl(newValue.currentTarget.value)
}
value={url}
placeholder="URL"
/>
@@ -376,7 +378,9 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
<Form.Control
as="textarea"
className="scene-description"
onChange={(newValue: React.FormEvent<HTMLTextAreaElement>) => setDetails(newValue.currentTarget.value)}
onChange={(newValue: React.FormEvent<HTMLTextAreaElement>) =>
setDetails(newValue.currentTarget.value)
}
value={details}
/>
</Form.Group>

View File

@@ -265,7 +265,9 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
<Form.Control
as="select"
value={rating}
onChange={(event: React.FormEvent<HTMLSelectElement>) => setRating(event.currentTarget.value)}
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
setRating(event.currentTarget.value)
}
>
{["", "1", "2", "3", "4", "5"].map(opt => (
<option key={opt} value={opt}>

View File

@@ -175,7 +175,9 @@ export const SettingsConfigurationPanel: React.FC = () => {
<Form.Control
className="col col-sm-6"
defaultValue={databasePath}
onChange={(e: React.FormEvent<HTMLInputElement>) => setDatabasePath(e.currentTarget.value)}
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setDatabasePath(e.currentTarget.value)
}
/>
<Form.Text className="text-muted">
File location for the SQLite database (requires restart)
@@ -187,7 +189,9 @@ export const SettingsConfigurationPanel: React.FC = () => {
<Form.Control
className="col col-sm-6"
defaultValue={generatedPath}
onChange={(e: React.FormEvent<HTMLInputElement>) => setGeneratedPath(e.currentTarget.value)}
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setGeneratedPath(e.currentTarget.value)
}
/>
<Form.Text className="text-muted">
Directory location for the generated files (scene markers, scene

View File

@@ -141,7 +141,9 @@ export const SettingsInterfacePanel: React.FC = () => {
<Form.Control
as="textarea"
value={css}
onChange={(e: React.FormEvent<HTMLTextAreaElement>) => setCSS(e.currentTarget.value)}
onChange={(e: React.FormEvent<HTMLTextAreaElement>) =>
setCSS(e.currentTarget.value)
}
rows={16}
className="col col-sm-6"
></Form.Control>

View File

@@ -78,7 +78,9 @@ export const DurationInput: React.FC<IProps> = (props: IProps) => {
className="duration-control"
disabled={props.disabled}
value={value}
onChange={(e: React.FormEvent<HTMLInputElement>) => setValue(e.currentTarget.value)}
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setValue(e.currentTarget.value)
}
onBlur={() =>
props.onValueChange(DurationUtils.stringToSeconds(value))
}

View File

@@ -51,7 +51,9 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
<InputGroup>
<Form.Control
placeholder="File path"
onChange={(e: React.FormEvent<HTMLInputElement>) => setCurrentDirectory(e.currentTarget.value)}
onChange={(e: React.FormEvent<HTMLInputElement>) =>
setCurrentDirectory(e.currentTarget.value)
}
defaultValue={currentDirectory}
/>
<InputGroup.Append>

View File

@@ -287,7 +287,9 @@ export const TagSelect: React.FC<IFilterProps> = props => {
const onChange = (selectedItems: ValueType<Option>) => {
const selectedValues = getSelectedValues(selectedItems);
setSelectedIds(selectedValues);
props.onSelect?.(tags.filter(item => selectedValues.indexOf(item.id) !== -1));
props.onSelect?.(
tags.filter(item => selectedValues.indexOf(item.id) !== -1)
);
};
return (
@@ -361,7 +363,7 @@ const SelectComponent: React.FC<ISelectProps & ITypeProps> = ({
isClearable,
defaultValue,
noOptionsMessage: () => (type !== "tags" ? "None" : null),
placeholder: isDisabled ? '' : placeholder,
placeholder: isDisabled ? "" : placeholder,
onInputChange,
isDisabled,
isLoading,

View File

@@ -160,7 +160,9 @@ export const TagList: React.FC = () => {
<Form.Group controlId="tag-name">
<Form.Label>Name</Form.Label>
<Form.Control
onChange={(newValue:React.FormEvent<HTMLInputElement>) => setName(newValue.currentTarget.value)}
onChange={(newValue: React.FormEvent<HTMLInputElement>) =>
setName(newValue.currentTarget.value)
}
defaultValue={(editingTag && editingTag.name) || ""}
/>
</Form.Group>

View File

@@ -16,7 +16,10 @@ import {
FindStudiosQueryResult,
FindPerformersQueryResult
} from "src/core/generated-graphql";
import { useInterfaceLocalForage, IInterfaceConfig } from "src/hooks/LocalForage";
import {
useInterfaceLocalForage,
IInterfaceConfig
} from "src/hooks/LocalForage";
import { LoadingIndicator } from "src/components/Shared";
import { ListFilter } from "src/components/List/ListFilter";
import { Pagination } from "src/components/List/Pagination";
@@ -75,7 +78,7 @@ interface IQuery<T extends IQueryResult, T2 extends IDataItem> {
const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
options: IListHookOptions<QueryResult> & IQuery<QueryResult, QueryData>
): IListHookData => {
const [interfaceState, setInterfaceState]= useInterfaceLocalForage();
const [interfaceState, setInterfaceState] = useInterfaceLocalForage();
const forageInitialised = useRef(false);
const history = useHistory();
const location = useLocation();
@@ -142,7 +145,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
itemsPerPage: newFilter.itemsPerPage,
currentPage: newFilter.currentPage
}
}
};
return data;
});
}
@@ -214,9 +217,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
// Remove duplicate modifiers
newFilter.criteria = newFilter.criteria.filter((obj, pos, arr) => {
return (
arr.map(mapObj => mapObj.getId()).indexOf(obj.getId()) === pos
);
return arr.map(mapObj => mapObj.getId()).indexOf(obj.getId()) === pos;
});
newFilter.currentPage = 1;

View File

@@ -23,10 +23,12 @@ interface ILocalForage<T> {
loading: boolean;
}
const Loading:Record<string, boolean> = {};
const Cache:Record<string, ValidTypes> = {};
const Loading: Record<string, boolean> = {};
const Cache: Record<string, ValidTypes> = {};
function useLocalForage(key: Key): [ILocalForage<ValidTypes>, Dispatch<SetStateAction<ValidTypes>>] {
function useLocalForage(
key: Key
): [ILocalForage<ValidTypes>, Dispatch<SetStateAction<ValidTypes>>] {
const [error, setError] = React.useState(null);
const [data, setData] = React.useState(Cache[key]);
const [loading, setLoading] = React.useState(Loading[key]);
@@ -48,7 +50,7 @@ function useLocalForage(key: Key): [ILocalForage<ValidTypes>, Dispatch<SetStateA
setLoading(false);
}
}
if(!loading && !Cache[key]) {
if (!loading && !Cache[key]) {
Loading[key] = true;
setLoading(true);
runAsync();
@@ -67,9 +69,9 @@ function useLocalForage(key: Key): [ILocalForage<ValidTypes>, Dispatch<SetStateA
return [{ data, error, loading: isLoading }, setData];
}
export function useInterfaceLocalForage():
[ILocalForage<IInterfaceConfig>,
Dispatch<SetStateAction<IInterfaceConfig>>]
{
export function useInterfaceLocalForage(): [
ILocalForage<IInterfaceConfig>,
Dispatch<SetStateAction<IInterfaceConfig>>
] {
return useLocalForage("interface");
}

View File

@@ -121,11 +121,9 @@ export abstract class Criterion {
public inputType: "number" | "text" | undefined;
public getLabelValue(): string {
if(typeof this.value === "string")
return this.value;
if(typeof this.value === "number")
return this.value.toString();
return this.value.map(v => v.label).join(', ');
if (typeof this.value === "string") return this.value;
if (typeof this.value === "number") return this.value.toString();
return this.value.map(v => v.label).join(", ");
}
public getLabel(): string {

View File

@@ -268,10 +268,10 @@ export class ListFilterModel {
public makeQueryParameters(): string {
const encodedCriteria: string[] = [];
this.criteria.forEach(criterion => {
const encodedCriterion:Partial<Criterion> = {
const encodedCriterion: Partial<Criterion> = {
type: criterion.type,
value: criterion.value,
modifier: criterion.modifier,
modifier: criterion.modifier
};
const jsonCriterion = JSON.stringify(encodedCriterion);
encodedCriteria.push(jsonCriterion);