mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 21:04:37 +03:00
Filter criterion fixes (#4090)
* Reorder * Remove PhashDuplicateCriterion * Improve DurationInput * Register abloop outside of player init function * Remove none criterion * Typing improvements * Move makeCriteria to ListFilterModel * Separate PathCriterionOption * Add makeCriterion arg to StringCriterionOption * Remove unused options args * Add DurationCriterionOption * Use createNumberCriterionOption * Add StringBooleanCriterion
This commit is contained in:
@@ -30,7 +30,7 @@ export const GalleryAddPanel: React.FC<IGalleryAddProps> = ({
|
|||||||
// if galleries is already present, then we modify it, otherwise add
|
// if galleries is already present, then we modify it, otherwise add
|
||||||
let galleryCriterion = filter.criteria.find((c) => {
|
let galleryCriterion = filter.criteria.find((c) => {
|
||||||
return c.criterionOption.type === "galleries";
|
return c.criterionOption.type === "galleries";
|
||||||
}) as GalleriesCriterion;
|
}) as GalleriesCriterion | undefined;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
galleryCriterion &&
|
galleryCriterion &&
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const GalleryImagesPanel: React.FC<IGalleryDetailsProps> = ({
|
|||||||
// if galleries is already present, then we modify it, otherwise add
|
// if galleries is already present, then we modify it, otherwise add
|
||||||
let galleryCriterion = filter.criteria.find((c) => {
|
let galleryCriterion = filter.criteria.find((c) => {
|
||||||
return c.criterionOption.type === "galleries";
|
return c.criterionOption.type === "galleries";
|
||||||
}) as GalleriesCriterion;
|
}) as GalleriesCriterion | undefined;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
galleryCriterion &&
|
galleryCriterion &&
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
DateCriterion,
|
DateCriterion,
|
||||||
TimestampCriterion,
|
TimestampCriterion,
|
||||||
BooleanCriterion,
|
BooleanCriterion,
|
||||||
PathCriterionOption,
|
|
||||||
} from "src/models/list-filter/criteria/criterion";
|
} from "src/models/list-filter/criteria/criterion";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
import {
|
import {
|
||||||
@@ -47,6 +46,7 @@ import TagsFilter from "./Filters/TagsFilter";
|
|||||||
import { PhashCriterion } from "src/models/list-filter/criteria/phash";
|
import { PhashCriterion } from "src/models/list-filter/criteria/phash";
|
||||||
import { PhashFilter } from "./Filters/PhashFilter";
|
import { PhashFilter } from "./Filters/PhashFilter";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
|
import { PathCriterion } from "src/models/list-filter/criteria/path";
|
||||||
|
|
||||||
interface IGenericCriterionEditor {
|
interface IGenericCriterionEditor {
|
||||||
criterion: Criterion<CriterionValue>;
|
criterion: Criterion<CriterionValue>;
|
||||||
@@ -175,7 +175,7 @@ const GenericCriterionEditor: React.FC<IGenericCriterionEditor> = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (criterion.criterionOption instanceof PathCriterionOption) {
|
if (criterion instanceof PathCriterion) {
|
||||||
return (
|
return (
|
||||||
<PathFilter criterion={criterion} onValueChanged={onValueChanged} />
|
<PathFilter criterion={criterion} onValueChanged={onValueChanged} />
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
Criterion,
|
Criterion,
|
||||||
CriterionOption,
|
CriterionOption,
|
||||||
} from "src/models/list-filter/criteria/criterion";
|
} from "src/models/list-filter/criteria/criterion";
|
||||||
import { makeCriteria } from "src/models/list-filter/criteria/factory";
|
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { ConfigurationContext } from "src/hooks/Config";
|
import { ConfigurationContext } from "src/hooks/Config";
|
||||||
import { ListFilterModel } from "src/models/list-filter/filter";
|
import { ListFilterModel } from "src/models/list-filter/filter";
|
||||||
@@ -243,17 +242,11 @@ export const EditFilterDialog: React.FC<IEditFilterProps> = ({
|
|||||||
}, [currentFilter.mode]);
|
}, [currentFilter.mode]);
|
||||||
|
|
||||||
const criterionOptions = useMemo(() => {
|
const criterionOptions = useMemo(() => {
|
||||||
const filteredOptions = filterOptions.criterionOptions.filter((o) => {
|
return [...filterOptions.criterionOptions].sort((a, b) => {
|
||||||
return o.type !== "none";
|
|
||||||
});
|
|
||||||
|
|
||||||
filteredOptions.sort((a, b) => {
|
|
||||||
return intl
|
return intl
|
||||||
.formatMessage({ id: a.messageID })
|
.formatMessage({ id: a.messageID })
|
||||||
.localeCompare(intl.formatMessage({ id: b.messageID }));
|
.localeCompare(intl.formatMessage({ id: b.messageID }));
|
||||||
});
|
});
|
||||||
|
|
||||||
return filteredOptions;
|
|
||||||
}, [intl, filterOptions.criterionOptions]);
|
}, [intl, filterOptions.criterionOptions]);
|
||||||
|
|
||||||
const optionSelected = useCallback(
|
const optionSelected = useCallback(
|
||||||
@@ -270,11 +263,11 @@ export const EditFilterDialog: React.FC<IEditFilterProps> = ({
|
|||||||
if (existing) {
|
if (existing) {
|
||||||
setCriterion(existing);
|
setCriterion(existing);
|
||||||
} else {
|
} else {
|
||||||
const newCriterion = makeCriteria(filter.mode, option.type);
|
const newCriterion = filter.makeCriterion(option.type);
|
||||||
setCriterion(newCriterion);
|
setCriterion(newCriterion);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[filter.mode, criteria]
|
[filter, criteria]
|
||||||
);
|
);
|
||||||
|
|
||||||
const ui = (configuration?.ui ?? {}) as IUIConfig;
|
const ui = (configuration?.ui ?? {}) as IUIConfig;
|
||||||
|
|||||||
@@ -17,67 +17,50 @@ export const DurationFilter: React.FC<IDurationFilterProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
function onChanged(valueAsNumber: number, property: "value" | "value2") {
|
function onChanged(v: number | undefined, property: "value" | "value2") {
|
||||||
const { value } = criterion;
|
const { value } = criterion;
|
||||||
value[property] = valueAsNumber;
|
value[property] = v;
|
||||||
onValueChanged(value);
|
onValueChanged(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let equalsControl: JSX.Element | null = null;
|
function renderTop() {
|
||||||
if (
|
let placeholder: string;
|
||||||
criterion.modifier === CriterionModifier.Equals ||
|
if (
|
||||||
criterion.modifier === CriterionModifier.NotEquals
|
criterion.modifier === CriterionModifier.GreaterThan ||
|
||||||
) {
|
criterion.modifier === CriterionModifier.Between ||
|
||||||
equalsControl = (
|
criterion.modifier === CriterionModifier.NotBetween
|
||||||
|
) {
|
||||||
|
placeholder = intl.formatMessage({ id: "criterion.greater_than" });
|
||||||
|
} else if (criterion.modifier === CriterionModifier.LessThan) {
|
||||||
|
placeholder = intl.formatMessage({ id: "criterion.less_than" });
|
||||||
|
} else {
|
||||||
|
placeholder = intl.formatMessage({ id: "criterion.value" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
<Form.Group>
|
<Form.Group>
|
||||||
<DurationInput
|
<DurationInput
|
||||||
numericValue={criterion.value?.value}
|
value={criterion.value?.value}
|
||||||
onValueChange={(v: number) => onChanged(v, "value")}
|
setValue={(v) => onChanged(v, "value")}
|
||||||
placeholder={intl.formatMessage({ id: "criterion.value" })}
|
placeholder={placeholder}
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lowerControl: JSX.Element | null = null;
|
function renderBottom() {
|
||||||
if (
|
if (
|
||||||
criterion.modifier === CriterionModifier.GreaterThan ||
|
criterion.modifier !== CriterionModifier.Between &&
|
||||||
criterion.modifier === CriterionModifier.Between ||
|
criterion.modifier !== CriterionModifier.NotBetween
|
||||||
criterion.modifier === CriterionModifier.NotBetween
|
) {
|
||||||
) {
|
return;
|
||||||
lowerControl = (
|
}
|
||||||
<Form.Group>
|
|
||||||
<DurationInput
|
|
||||||
numericValue={criterion.value?.value}
|
|
||||||
onValueChange={(v: number) => onChanged(v, "value")}
|
|
||||||
placeholder={intl.formatMessage({ id: "criterion.greater_than" })}
|
|
||||||
/>
|
|
||||||
</Form.Group>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let upperControl: JSX.Element | null = null;
|
return (
|
||||||
if (
|
|
||||||
criterion.modifier === CriterionModifier.LessThan ||
|
|
||||||
criterion.modifier === CriterionModifier.Between ||
|
|
||||||
criterion.modifier === CriterionModifier.NotBetween
|
|
||||||
) {
|
|
||||||
upperControl = (
|
|
||||||
<Form.Group>
|
<Form.Group>
|
||||||
<DurationInput
|
<DurationInput
|
||||||
numericValue={
|
value={criterion.value?.value2}
|
||||||
criterion.modifier === CriterionModifier.LessThan
|
setValue={(v) => onChanged(v, "value2")}
|
||||||
? criterion.value?.value
|
|
||||||
: criterion.value?.value2
|
|
||||||
}
|
|
||||||
onValueChange={(v: number) =>
|
|
||||||
onChanged(
|
|
||||||
v,
|
|
||||||
criterion.modifier === CriterionModifier.LessThan
|
|
||||||
? "value"
|
|
||||||
: "value2"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
placeholder={intl.formatMessage({ id: "criterion.less_than" })}
|
placeholder={intl.formatMessage({ id: "criterion.less_than" })}
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
@@ -86,9 +69,8 @@ export const DurationFilter: React.FC<IDurationFilterProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{equalsControl}
|
{renderTop()}
|
||||||
{lowerControl}
|
{renderBottom()}
|
||||||
{upperControl}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -135,10 +135,10 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state.duration) {
|
if (state.duration) {
|
||||||
formik.setFieldValue(
|
const seconds = DurationUtils.stringToSeconds(state.duration);
|
||||||
"duration",
|
if (seconds !== undefined) {
|
||||||
DurationUtils.stringToSeconds(state.duration)
|
formik.setFieldValue("duration", seconds);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.date) {
|
if (state.date) {
|
||||||
@@ -402,10 +402,8 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
|
|||||||
</Form.Label>
|
</Form.Label>
|
||||||
<Col xs={fieldXS} xl={fieldXL}>
|
<Col xs={fieldXS} xl={fieldXL}>
|
||||||
<DurationInput
|
<DurationInput
|
||||||
numericValue={formik.values.duration ?? undefined}
|
value={formik.values.duration ?? undefined}
|
||||||
onValueChange={(valueAsNumber) => {
|
setValue={(v) => formik.setFieldValue("duration", v ?? null)}
|
||||||
formik.setFieldValue("duration", valueAsNumber ?? null);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const MovieScenesPanel: React.FC<IMovieScenesPanel> = ({
|
|||||||
// if movie is already present, then we modify it, otherwise add
|
// if movie is already present, then we modify it, otherwise add
|
||||||
let movieCriterion = filter.criteria.find((c) => {
|
let movieCriterion = filter.criteria.find((c) => {
|
||||||
return c.criterionOption.type === "movies";
|
return c.criterionOption.type === "movies";
|
||||||
}) as MoviesCriterion;
|
}) as MoviesCriterion | undefined;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
movieCriterion &&
|
movieCriterion &&
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import React, {
|
|||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from "video.js";
|
import videojs, { VideoJsPlayer, VideoJsPlayerOptions } from "video.js";
|
||||||
import abLoopPlugin from "videojs-abloop";
|
|
||||||
import useScript from "src/hooks/useScript";
|
import useScript from "src/hooks/useScript";
|
||||||
import "videojs-contrib-dash";
|
import "videojs-contrib-dash";
|
||||||
import "videojs-mobile-ui";
|
import "videojs-mobile-ui";
|
||||||
@@ -24,12 +23,6 @@ import "./big-buttons";
|
|||||||
import "./track-activity";
|
import "./track-activity";
|
||||||
import "./vrmode";
|
import "./vrmode";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
// @ts-ignore
|
|
||||||
import airplay from "@silvermine/videojs-airplay";
|
|
||||||
// @ts-ignore
|
|
||||||
import chromecast from "@silvermine/videojs-chromecast";
|
|
||||||
airplay(videojs);
|
|
||||||
chromecast(videojs);
|
|
||||||
import {
|
import {
|
||||||
useSceneSaveActivity,
|
useSceneSaveActivity,
|
||||||
useSceneIncrementPlayCount,
|
useSceneIncrementPlayCount,
|
||||||
@@ -47,6 +40,17 @@ import { languageMap } from "src/utils/caption";
|
|||||||
import { VIDEO_PLAYER_ID } from "./util";
|
import { VIDEO_PLAYER_ID } from "./util";
|
||||||
import { IUIConfig } from "src/core/config";
|
import { IUIConfig } from "src/core/config";
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
import airplay from "@silvermine/videojs-airplay";
|
||||||
|
// @ts-ignore
|
||||||
|
import chromecast from "@silvermine/videojs-chromecast";
|
||||||
|
import abLoopPlugin from "videojs-abloop";
|
||||||
|
|
||||||
|
// register videojs plugins
|
||||||
|
airplay(videojs);
|
||||||
|
chromecast(videojs);
|
||||||
|
abLoopPlugin(window, videojs);
|
||||||
|
|
||||||
function handleHotkeys(player: VideoJsPlayer, event: videojs.KeyboardEvent) {
|
function handleHotkeys(player: VideoJsPlayer, event: videojs.KeyboardEvent) {
|
||||||
function seekStep(step: number) {
|
function seekStep(step: number) {
|
||||||
const time = player.currentTime() + step;
|
const time = player.currentTime() + step;
|
||||||
@@ -378,8 +382,6 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
|
|||||||
videoEl.classList.add("vjs-big-play-centered");
|
videoEl.classList.add("vjs-big-play-centered");
|
||||||
videoRef.current!.appendChild(videoEl);
|
videoRef.current!.appendChild(videoEl);
|
||||||
|
|
||||||
abLoopPlugin(window, videojs);
|
|
||||||
|
|
||||||
const vjs = videojs(videoEl, options);
|
const vjs = videojs(videoEl, options);
|
||||||
|
|
||||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||||
|
|||||||
@@ -145,15 +145,14 @@ export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
|||||||
</Form.Label>
|
</Form.Label>
|
||||||
<div className="col-sm-8 col-xl-12">
|
<div className="col-sm-8 col-xl-12">
|
||||||
<DurationInput
|
<DurationInput
|
||||||
onValueChange={(s) => formik.setFieldValue("seconds", s)}
|
value={formik.values.seconds ?? 0}
|
||||||
|
setValue={(v) => formik.setFieldValue("seconds", v ?? null)}
|
||||||
onReset={() =>
|
onReset={() =>
|
||||||
formik.setFieldValue(
|
formik.setFieldValue(
|
||||||
"seconds",
|
"seconds",
|
||||||
Math.round(getPlayerPosition() ?? 0)
|
Math.round(getPlayerPosition() ?? 0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
numericValue={formik.values.seconds}
|
|
||||||
mandatory
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -356,8 +356,8 @@ export const SettingsInterfacePanel: React.FC = () => {
|
|||||||
onChange={(v) => saveInterface({ maximumLoopDuration: v })}
|
onChange={(v) => saveInterface({ maximumLoopDuration: v })}
|
||||||
renderField={(value, setValue) => (
|
renderField={(value, setValue) => (
|
||||||
<DurationInput
|
<DurationInput
|
||||||
numericValue={value}
|
value={value}
|
||||||
onValueChange={(duration) => setValue(duration ?? 0)}
|
setValue={(duration) => setValue(duration ?? 0)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
renderValue={(v) => {
|
renderValue={(v) => {
|
||||||
|
|||||||
@@ -43,17 +43,13 @@ export const SettingsServicesPanel: React.FC = () => {
|
|||||||
} = React.useContext(SettingStateContext);
|
} = React.useContext(SettingStateContext);
|
||||||
|
|
||||||
// undefined to hide dialog, true for enable, false for disable
|
// undefined to hide dialog, true for enable, false for disable
|
||||||
const [enableDisable, setEnableDisable] = useState<boolean | undefined>(
|
const [enableDisable, setEnableDisable] = useState<boolean>();
|
||||||
undefined
|
|
||||||
);
|
|
||||||
|
|
||||||
const [enableUntilRestart, setEnableUntilRestart] = useState<boolean>(false);
|
const [enableUntilRestart, setEnableUntilRestart] = useState<boolean>(false);
|
||||||
const [enableDuration, setEnableDuration] = useState<number | undefined>(
|
const [enableDuration, setEnableDuration] = useState<number>(0);
|
||||||
undefined
|
|
||||||
);
|
|
||||||
|
|
||||||
const [ipEntry, setIPEntry] = useState<string>("");
|
const [ipEntry, setIPEntry] = useState<string>("");
|
||||||
const [tempIP, setTempIP] = useState<string | undefined>();
|
const [tempIP, setTempIP] = useState<string>();
|
||||||
|
|
||||||
const { data: statusData, loading, refetch: statusRefetch } = useDLNAStatus();
|
const { data: statusData, loading, refetch: statusRefetch } = useDLNAStatus();
|
||||||
|
|
||||||
@@ -273,8 +269,8 @@ export const SettingsServicesPanel: React.FC = () => {
|
|||||||
|
|
||||||
<Form.Group id="temp-enable-duration">
|
<Form.Group id="temp-enable-duration">
|
||||||
<DurationInput
|
<DurationInput
|
||||||
numericValue={enableDuration ?? 0}
|
value={enableDuration}
|
||||||
onValueChange={(v) => setEnableDuration(v ?? 0)}
|
setValue={(v) => setEnableDuration(v ?? 0)}
|
||||||
disabled={enableUntilRestart}
|
disabled={enableUntilRestart}
|
||||||
/>
|
/>
|
||||||
<Form.Text className="text-muted">
|
<Form.Text className="text-muted">
|
||||||
@@ -315,8 +311,8 @@ export const SettingsServicesPanel: React.FC = () => {
|
|||||||
|
|
||||||
<Form.Group id="temp-enable-duration">
|
<Form.Group id="temp-enable-duration">
|
||||||
<DurationInput
|
<DurationInput
|
||||||
numericValue={enableDuration ?? 0}
|
value={enableDuration}
|
||||||
onValueChange={(v) => setEnableDuration(v ?? 0)}
|
setValue={(v) => setEnableDuration(v ?? 0)}
|
||||||
disabled={enableUntilRestart}
|
disabled={enableUntilRestart}
|
||||||
/>
|
/>
|
||||||
<Form.Text className="text-muted">
|
<Form.Text className="text-muted">
|
||||||
|
|||||||
@@ -3,67 +3,58 @@ import {
|
|||||||
faChevronUp,
|
faChevronUp,
|
||||||
faClock,
|
faClock,
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState } from "react";
|
||||||
import { Button, ButtonGroup, InputGroup, Form } from "react-bootstrap";
|
import { Button, ButtonGroup, InputGroup, Form } from "react-bootstrap";
|
||||||
import { Icon } from "./Icon";
|
import { Icon } from "./Icon";
|
||||||
import DurationUtils from "src/utils/duration";
|
import DurationUtils from "src/utils/duration";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
numericValue: number | undefined;
|
value: number | undefined;
|
||||||
mandatory?: boolean;
|
setValue(value: number | undefined): void;
|
||||||
onValueChange(
|
|
||||||
valueAsNumber: number | undefined,
|
|
||||||
valueAsString?: string
|
|
||||||
): void;
|
|
||||||
onReset?(): void;
|
onReset?(): void;
|
||||||
className?: string;
|
className?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DurationInput: React.FC<IProps> = (props: IProps) => {
|
export const DurationInput: React.FC<IProps> = ({
|
||||||
const [value, setValue] = useState<string | undefined>(
|
disabled,
|
||||||
props.numericValue !== undefined
|
value,
|
||||||
? DurationUtils.secondsToString(props.numericValue)
|
setValue,
|
||||||
: undefined
|
onReset,
|
||||||
);
|
className,
|
||||||
|
placeholder,
|
||||||
|
}) => {
|
||||||
|
const [tmpValue, setTmpValue] = useState<string>();
|
||||||
|
|
||||||
useEffect(() => {
|
function onChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||||
if (props.numericValue !== undefined || props.mandatory) {
|
setTmpValue(e.currentTarget.value);
|
||||||
setValue(DurationUtils.secondsToString(props.numericValue ?? 0));
|
}
|
||||||
} else {
|
|
||||||
setValue(undefined);
|
function onBlur() {
|
||||||
|
if (tmpValue !== undefined) {
|
||||||
|
setValue(DurationUtils.stringToSeconds(tmpValue));
|
||||||
|
setTmpValue(undefined);
|
||||||
}
|
}
|
||||||
}, [props.numericValue, props.mandatory]);
|
}
|
||||||
|
|
||||||
function increment() {
|
function increment() {
|
||||||
if (value === undefined) {
|
setTmpValue(undefined);
|
||||||
return;
|
setValue((value ?? 0) + 1);
|
||||||
}
|
|
||||||
|
|
||||||
let seconds = DurationUtils.stringToSeconds(value);
|
|
||||||
seconds += 1;
|
|
||||||
props.onValueChange(seconds, DurationUtils.secondsToString(seconds));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function decrement() {
|
function decrement() {
|
||||||
if (value === undefined) {
|
setTmpValue(undefined);
|
||||||
return;
|
setValue((value ?? 0) - 1);
|
||||||
}
|
|
||||||
|
|
||||||
let seconds = DurationUtils.stringToSeconds(value);
|
|
||||||
seconds -= 1;
|
|
||||||
props.onValueChange(seconds, DurationUtils.secondsToString(seconds));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderButtons() {
|
function renderButtons() {
|
||||||
if (!props.disabled) {
|
if (!disabled) {
|
||||||
return (
|
return (
|
||||||
<ButtonGroup vertical>
|
<ButtonGroup vertical>
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="duration-button"
|
className="duration-button"
|
||||||
disabled={props.disabled}
|
|
||||||
onClick={() => increment()}
|
onClick={() => increment()}
|
||||||
>
|
>
|
||||||
<Icon icon={faChevronUp} />
|
<Icon icon={faChevronUp} />
|
||||||
@@ -71,7 +62,6 @@ export const DurationInput: React.FC<IProps> = (props: IProps) => {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="duration-button"
|
className="duration-button"
|
||||||
disabled={props.disabled}
|
|
||||||
onClick={() => decrement()}
|
onClick={() => decrement()}
|
||||||
>
|
>
|
||||||
<Icon icon={faChevronDown} />
|
<Icon icon={faChevronDown} />
|
||||||
@@ -81,46 +71,33 @@ export const DurationInput: React.FC<IProps> = (props: IProps) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onReset() {
|
|
||||||
if (props.onReset) {
|
|
||||||
props.onReset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function maybeRenderReset() {
|
function maybeRenderReset() {
|
||||||
if (props.onReset) {
|
if (onReset) {
|
||||||
return (
|
return (
|
||||||
<Button variant="secondary" onClick={onReset}>
|
<Button variant="secondary" onClick={() => onReset()}>
|
||||||
<Icon icon={faClock} />
|
<Icon icon={faClock} />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let inputValue = "";
|
||||||
|
if (tmpValue !== undefined) {
|
||||||
|
inputValue = tmpValue;
|
||||||
|
} else if (value !== undefined) {
|
||||||
|
inputValue = DurationUtils.secondsToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`duration-input ${props.className}`}>
|
<div className={`duration-input ${className}`}>
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="duration-control text-input"
|
className="duration-control text-input"
|
||||||
disabled={props.disabled}
|
disabled={disabled}
|
||||||
value={value}
|
value={inputValue}
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
onChange={onChange}
|
||||||
setValue(e.currentTarget.value)
|
onBlur={onBlur}
|
||||||
}
|
placeholder={placeholder ? `${placeholder} (hh:mm:ss)` : "hh:mm:ss"}
|
||||||
onBlur={() => {
|
|
||||||
if (props.mandatory || (value !== undefined && value !== "")) {
|
|
||||||
props.onValueChange(DurationUtils.stringToSeconds(value), value);
|
|
||||||
} else {
|
|
||||||
props.onValueChange(undefined);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
placeholder={
|
|
||||||
!props.disabled
|
|
||||||
? props.placeholder
|
|
||||||
? `${props.placeholder} (hh:mm:ss)`
|
|
||||||
: "hh:mm:ss"
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<InputGroup.Append>
|
<InputGroup.Append>
|
||||||
{maybeRenderReset()}
|
{maybeRenderReset()}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const StudioChildrenPanel: React.FC<IStudioChildrenPanel> = ({
|
|||||||
// if studio is already present, then we modify it, otherwise add
|
// if studio is already present, then we modify it, otherwise add
|
||||||
let parentStudioCriterion = filter.criteria.find((c) => {
|
let parentStudioCriterion = filter.criteria.find((c) => {
|
||||||
return c.criterionOption.type === "parents";
|
return c.criterionOption.type === "parents";
|
||||||
}) as ParentStudiosCriterion;
|
}) as ParentStudiosCriterion | undefined;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
parentStudioCriterion &&
|
parentStudioCriterion &&
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export const TagMarkersPanel: React.FC<ITagMarkersPanel> = ({
|
|||||||
// if tag is already present, then we modify it, otherwise add
|
// if tag is already present, then we modify it, otherwise add
|
||||||
let tagCriterion = filter.criteria.find((c) => {
|
let tagCriterion = filter.criteria.find((c) => {
|
||||||
return c.criterionOption.type === "tags";
|
return c.criterionOption.type === "tags";
|
||||||
}) as TagsCriterion;
|
}) as TagsCriterion | undefined;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
tagCriterion &&
|
tagCriterion &&
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const usePerformerFilterHook = (
|
|||||||
// if performers is already present, then we modify it, otherwise add
|
// if performers is already present, then we modify it, otherwise add
|
||||||
let performerCriterion = filter.criteria.find((c) => {
|
let performerCriterion = filter.criteria.find((c) => {
|
||||||
return c.criterionOption.type === "performers";
|
return c.criterionOption.type === "performers";
|
||||||
}) as PerformersCriterion;
|
}) as PerformersCriterion | undefined;
|
||||||
|
|
||||||
if (performerCriterion) {
|
if (performerCriterion) {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const useStudioFilterHook = (studio: GQL.StudioDataFragment) => {
|
|||||||
// if studio is already present, then we modify it, otherwise add
|
// if studio is already present, then we modify it, otherwise add
|
||||||
let studioCriterion = filter.criteria.find((c) => {
|
let studioCriterion = filter.criteria.find((c) => {
|
||||||
return c.criterionOption.type === "studios";
|
return c.criterionOption.type === "studios";
|
||||||
}) as StudiosCriterion;
|
}) as StudiosCriterion | undefined;
|
||||||
|
|
||||||
if (studioCriterion) {
|
if (studioCriterion) {
|
||||||
// we should be showing studio only. Remove other values
|
// we should be showing studio only. Remove other values
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export const useTagFilterHook = (tag: GQL.TagDataFragment) => {
|
|||||||
// if tag is already present, then we modify it, otherwise add
|
// if tag is already present, then we modify it, otherwise add
|
||||||
let tagCriterion = filter.criteria.find((c) => {
|
let tagCriterion = filter.criteria.find((c) => {
|
||||||
return c.criterionOption.type === "tags";
|
return c.criterionOption.type === "tags";
|
||||||
}) as TagsCriterion;
|
}) as TagsCriterion | undefined;
|
||||||
|
|
||||||
if (tagCriterion) {
|
if (tagCriterion) {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -1,33 +1,28 @@
|
|||||||
import { CriterionModifier } from "src/core/generated-graphql";
|
import { CriterionModifier } from "src/core/generated-graphql";
|
||||||
import { languageMap, valueToCode } from "src/utils/caption";
|
import { languageMap, valueToCode } from "src/utils/caption";
|
||||||
import { CriterionType } from "../types";
|
|
||||||
import { CriterionOption, StringCriterion } from "./criterion";
|
import { CriterionOption, StringCriterion } from "./criterion";
|
||||||
|
|
||||||
const languageStrings = Array.from(languageMap.values());
|
const languageStrings = Array.from(languageMap.values());
|
||||||
|
|
||||||
class CaptionsCriterionOptionType extends CriterionOption {
|
export const CaptionsCriterionOption = new CriterionOption({
|
||||||
constructor(value: CriterionType) {
|
messageID: "captions",
|
||||||
super({
|
type: "captions",
|
||||||
messageID: value,
|
modifierOptions: [
|
||||||
type: value,
|
CriterionModifier.Includes,
|
||||||
modifierOptions: [
|
CriterionModifier.Excludes,
|
||||||
CriterionModifier.Includes,
|
CriterionModifier.IsNull,
|
||||||
CriterionModifier.Excludes,
|
CriterionModifier.NotNull,
|
||||||
CriterionModifier.IsNull,
|
],
|
||||||
CriterionModifier.NotNull,
|
defaultModifier: CriterionModifier.Includes,
|
||||||
],
|
options: languageStrings,
|
||||||
defaultModifier: CriterionModifier.Includes,
|
makeCriterion: () => new CaptionCriterion(),
|
||||||
options: languageStrings,
|
});
|
||||||
makeCriterion: () => new CaptionCriterion(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CaptionsCriterionOption = new CaptionsCriterionOptionType(
|
|
||||||
"captions"
|
|
||||||
);
|
|
||||||
|
|
||||||
export class CaptionCriterion extends StringCriterion {
|
export class CaptionCriterion extends StringCriterion {
|
||||||
|
constructor() {
|
||||||
|
super(CaptionsCriterionOption);
|
||||||
|
}
|
||||||
|
|
||||||
protected toCriterionInput() {
|
protected toCriterionInput() {
|
||||||
const value = valueToCode(this.value) ?? "";
|
const value = valueToCode(this.value) ?? "";
|
||||||
|
|
||||||
@@ -36,8 +31,4 @@ export class CaptionCriterion extends StringCriterion {
|
|||||||
modifier: this.modifier,
|
modifier: this.modifier,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super(CaptionsCriterionOption);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import { CriterionOption, MultiStringCriterion } from "./criterion";
|
|||||||
export const CircumcisedCriterionOption = new CriterionOption({
|
export const CircumcisedCriterionOption = new CriterionOption({
|
||||||
messageID: "circumcised",
|
messageID: "circumcised",
|
||||||
type: "circumcised",
|
type: "circumcised",
|
||||||
options: circumcisedStrings,
|
|
||||||
modifierOptions: [
|
modifierOptions: [
|
||||||
CriterionModifier.Includes,
|
CriterionModifier.Includes,
|
||||||
CriterionModifier.Excludes,
|
CriterionModifier.Excludes,
|
||||||
CriterionModifier.IsNull,
|
CriterionModifier.IsNull,
|
||||||
CriterionModifier.NotNull,
|
CriterionModifier.NotNull,
|
||||||
],
|
],
|
||||||
|
options: circumcisedStrings,
|
||||||
makeCriterion: () => new CircumcisedCriterion(),
|
makeCriterion: () => new CircumcisedCriterion(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,13 @@
|
|||||||
import { IntlShape } from "react-intl";
|
import { IntlShape } from "react-intl";
|
||||||
import { CriterionModifier } from "src/core/generated-graphql";
|
import { CriterionModifier } from "src/core/generated-graphql";
|
||||||
import { getCountryByISO } from "src/utils/country";
|
import { getCountryByISO } from "src/utils/country";
|
||||||
import {
|
import { StringCriterion, StringCriterionOption } from "./criterion";
|
||||||
CriterionOption,
|
|
||||||
StringCriterion,
|
|
||||||
StringCriterionOption,
|
|
||||||
} from "./criterion";
|
|
||||||
|
|
||||||
export const CountryCriterionOption = new CriterionOption({
|
export const CountryCriterionOption = new StringCriterionOption(
|
||||||
messageID: "country",
|
"country",
|
||||||
type: "country",
|
"country",
|
||||||
modifierOptions: StringCriterionOption.modifierOptions,
|
() => new CountryCriterion()
|
||||||
defaultModifier: StringCriterionOption.defaultModifier,
|
);
|
||||||
makeCriterion: () => new CountryCriterion(),
|
|
||||||
inputType: StringCriterionOption.inputType,
|
|
||||||
});
|
|
||||||
|
|
||||||
export class CountryCriterion extends StringCriterion {
|
export class CountryCriterion extends StringCriterion {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
/* eslint-disable consistent-return */
|
|
||||||
/* eslint @typescript-eslint/no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
|
/* eslint @typescript-eslint/no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
|
||||||
|
|
||||||
import { IntlShape } from "react-intl";
|
import { IntlShape } from "react-intl";
|
||||||
import {
|
import {
|
||||||
CriterionModifier,
|
CriterionModifier,
|
||||||
HierarchicalMultiCriterionInput,
|
HierarchicalMultiCriterionInput,
|
||||||
IntCriterionInput,
|
IntCriterionInput,
|
||||||
MultiCriterionInput,
|
MultiCriterionInput,
|
||||||
PHashDuplicationCriterionInput,
|
|
||||||
DateCriterionInput,
|
DateCriterionInput,
|
||||||
TimestampCriterionInput,
|
TimestampCriterionInput,
|
||||||
ConfigDataFragment,
|
ConfigDataFragment,
|
||||||
@@ -152,22 +149,18 @@ export abstract class Criterion<V extends CriterionValue> {
|
|||||||
this.modifier = encodedCriterion.modifier;
|
this.modifier = encodedCriterion.modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
public apply(outputFilter: Record<string, unknown>) {
|
||||||
public apply(outputFilter: Record<string, any>) {
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
|
||||||
outputFilter[this.criterionOption.type] = this.toCriterionInput();
|
outputFilter[this.criterionOption.type] = this.toCriterionInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
protected toCriterionInput(): unknown {
|
||||||
protected toCriterionInput(): any {
|
|
||||||
return {
|
return {
|
||||||
value: this.value,
|
value: this.value,
|
||||||
modifier: this.modifier,
|
modifier: this.modifier,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
public toSavedFilter(outputFilter: Record<string, unknown>) {
|
||||||
public toSavedFilter(outputFilter: Record<string, any>) {
|
|
||||||
outputFilter[this.criterionOption.type] = {
|
outputFilter[this.criterionOption.type] = {
|
||||||
value: this.value,
|
value: this.value,
|
||||||
modifier: this.modifier,
|
modifier: this.modifier,
|
||||||
@@ -226,274 +219,13 @@ export class CriterionOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StringCriterionOption extends CriterionOption {
|
|
||||||
public static readonly modifierOptions = [
|
|
||||||
CriterionModifier.Equals,
|
|
||||||
CriterionModifier.NotEquals,
|
|
||||||
CriterionModifier.Includes,
|
|
||||||
CriterionModifier.Excludes,
|
|
||||||
CriterionModifier.IsNull,
|
|
||||||
CriterionModifier.NotNull,
|
|
||||||
CriterionModifier.MatchesRegex,
|
|
||||||
CriterionModifier.NotMatchesRegex,
|
|
||||||
];
|
|
||||||
|
|
||||||
public static readonly defaultModifier = CriterionModifier.Equals;
|
|
||||||
public static readonly inputType = "text";
|
|
||||||
|
|
||||||
constructor(messageID: string, type: CriterionType, options?: Option[]) {
|
|
||||||
super({
|
|
||||||
messageID,
|
|
||||||
type,
|
|
||||||
modifierOptions: StringCriterionOption.modifierOptions,
|
|
||||||
defaultModifier: StringCriterionOption.defaultModifier,
|
|
||||||
options,
|
|
||||||
inputType: StringCriterionOption.inputType,
|
|
||||||
makeCriterion: () => new StringCriterion(this),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createStringCriterionOption(
|
|
||||||
type: CriterionType,
|
|
||||||
messageID?: string
|
|
||||||
) {
|
|
||||||
return new StringCriterionOption(messageID ?? type, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class StringCriterion extends Criterion<string> {
|
|
||||||
constructor(type: CriterionOption) {
|
|
||||||
super(type, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected getLabelValue(_intl: IntlShape) {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isValid(): boolean {
|
|
||||||
return (
|
|
||||||
this.modifier === CriterionModifier.IsNull ||
|
|
||||||
this.modifier === CriterionModifier.NotNull ||
|
|
||||||
this.value.length > 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MultiStringCriterion extends Criterion<string[]> {
|
|
||||||
constructor(type: CriterionOption) {
|
|
||||||
super(type, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected getLabelValue(_intl: IntlShape) {
|
|
||||||
return this.value.join(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public isValid(): boolean {
|
|
||||||
return (
|
|
||||||
this.modifier === CriterionModifier.IsNull ||
|
|
||||||
this.modifier === CriterionModifier.NotNull ||
|
|
||||||
this.value.length > 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MandatoryStringCriterionOption extends CriterionOption {
|
|
||||||
constructor(messageID: string, value: CriterionType, options?: Option[]) {
|
|
||||||
super({
|
|
||||||
messageID,
|
|
||||||
type: value,
|
|
||||||
modifierOptions: [
|
|
||||||
CriterionModifier.Equals,
|
|
||||||
CriterionModifier.NotEquals,
|
|
||||||
CriterionModifier.Includes,
|
|
||||||
CriterionModifier.Excludes,
|
|
||||||
CriterionModifier.MatchesRegex,
|
|
||||||
CriterionModifier.NotMatchesRegex,
|
|
||||||
],
|
|
||||||
defaultModifier: CriterionModifier.Equals,
|
|
||||||
options,
|
|
||||||
inputType: "text",
|
|
||||||
makeCriterion: () => new StringCriterion(this),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createMandatoryStringCriterionOption(
|
|
||||||
value: CriterionType,
|
|
||||||
messageID?: string
|
|
||||||
) {
|
|
||||||
return new MandatoryStringCriterionOption(messageID ?? value, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PathCriterionOption extends StringCriterionOption {}
|
|
||||||
|
|
||||||
export function createPathCriterionOption(
|
|
||||||
type: CriterionType,
|
|
||||||
messageID?: string
|
|
||||||
) {
|
|
||||||
return new PathCriterionOption(messageID ?? type, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class BooleanCriterionOption extends CriterionOption {
|
|
||||||
constructor(
|
|
||||||
messageID: string,
|
|
||||||
value: CriterionType,
|
|
||||||
makeCriterion?: () => Criterion<CriterionValue>
|
|
||||||
) {
|
|
||||||
super({
|
|
||||||
messageID,
|
|
||||||
type: value,
|
|
||||||
modifierOptions: [],
|
|
||||||
defaultModifier: CriterionModifier.Equals,
|
|
||||||
options: [true.toString(), false.toString()],
|
|
||||||
makeCriterion: makeCriterion
|
|
||||||
? makeCriterion
|
|
||||||
: () => new BooleanCriterion(this),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class BooleanCriterion extends StringCriterion {
|
|
||||||
protected toCriterionInput(): boolean {
|
|
||||||
return this.value === "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
public isValid() {
|
|
||||||
return this.value === "true" || this.value === "false";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBooleanCriterionOption(
|
|
||||||
value: CriterionType,
|
|
||||||
messageID?: string
|
|
||||||
) {
|
|
||||||
return new BooleanCriterionOption(messageID ?? value, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NumberCriterionOption extends CriterionOption {
|
|
||||||
constructor(messageID: string, value: CriterionType, options?: Option[]) {
|
|
||||||
super({
|
|
||||||
messageID,
|
|
||||||
type: value,
|
|
||||||
modifierOptions: [
|
|
||||||
CriterionModifier.Equals,
|
|
||||||
CriterionModifier.NotEquals,
|
|
||||||
CriterionModifier.GreaterThan,
|
|
||||||
CriterionModifier.LessThan,
|
|
||||||
CriterionModifier.IsNull,
|
|
||||||
CriterionModifier.NotNull,
|
|
||||||
CriterionModifier.Between,
|
|
||||||
CriterionModifier.NotBetween,
|
|
||||||
],
|
|
||||||
defaultModifier: CriterionModifier.Equals,
|
|
||||||
options,
|
|
||||||
inputType: "number",
|
|
||||||
makeCriterion: () => new NumberCriterion(this),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NullNumberCriterionOption extends CriterionOption {
|
|
||||||
constructor(messageID: string, value: CriterionType) {
|
|
||||||
super({
|
|
||||||
messageID,
|
|
||||||
type: value,
|
|
||||||
modifierOptions: [
|
|
||||||
CriterionModifier.Equals,
|
|
||||||
CriterionModifier.NotEquals,
|
|
||||||
CriterionModifier.GreaterThan,
|
|
||||||
CriterionModifier.LessThan,
|
|
||||||
CriterionModifier.Between,
|
|
||||||
CriterionModifier.NotBetween,
|
|
||||||
CriterionModifier.IsNull,
|
|
||||||
CriterionModifier.NotNull,
|
|
||||||
],
|
|
||||||
defaultModifier: CriterionModifier.Equals,
|
|
||||||
inputType: "number",
|
|
||||||
makeCriterion: () => new NumberCriterion(this),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createNumberCriterionOption(value: CriterionType) {
|
|
||||||
return new NumberCriterionOption(value, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createNullNumberCriterionOption(value: CriterionType) {
|
|
||||||
return new NullNumberCriterionOption(value, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class NumberCriterion extends Criterion<INumberValue> {
|
|
||||||
public get value(): INumberValue {
|
|
||||||
return this._value;
|
|
||||||
}
|
|
||||||
public set value(newValue: number | INumberValue) {
|
|
||||||
// backwards compatibility - if this.value is a number, use that
|
|
||||||
if (typeof newValue !== "object") {
|
|
||||||
this._value = {
|
|
||||||
value: newValue,
|
|
||||||
value2: undefined,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
this._value = newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected toCriterionInput(): IntCriterionInput {
|
|
||||||
return {
|
|
||||||
modifier: this.modifier,
|
|
||||||
value: this.value?.value ?? 0,
|
|
||||||
value2: this.value?.value2,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected getLabelValue(_intl: IntlShape) {
|
|
||||||
const { value, value2 } = this.value;
|
|
||||||
if (
|
|
||||||
this.modifier === CriterionModifier.Between ||
|
|
||||||
this.modifier === CriterionModifier.NotBetween
|
|
||||||
) {
|
|
||||||
return `${value}, ${value2 ?? 0}`;
|
|
||||||
} else {
|
|
||||||
return `${value}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public isValid(): boolean {
|
|
||||||
if (
|
|
||||||
this.modifier === CriterionModifier.IsNull ||
|
|
||||||
this.modifier === CriterionModifier.NotNull
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { value, value2 } = this.value;
|
|
||||||
if (value === undefined) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
value2 === undefined &&
|
|
||||||
(this.modifier === CriterionModifier.Between ||
|
|
||||||
this.modifier === CriterionModifier.NotBetween)
|
|
||||||
) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(type: CriterionOption) {
|
|
||||||
super(type, { value: undefined, value2: undefined });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ILabeledIdCriterionOption extends CriterionOption {
|
export class ILabeledIdCriterionOption extends CriterionOption {
|
||||||
constructor(
|
constructor(
|
||||||
messageID: string,
|
messageID: string,
|
||||||
value: CriterionType,
|
value: CriterionType,
|
||||||
includeAll: boolean,
|
includeAll: boolean,
|
||||||
inputType: InputType
|
inputType: InputType,
|
||||||
|
makeCriterion?: () => Criterion<CriterionValue>
|
||||||
) {
|
) {
|
||||||
const modifierOptions = [
|
const modifierOptions = [
|
||||||
CriterionModifier.Includes,
|
CriterionModifier.Includes,
|
||||||
@@ -513,8 +245,10 @@ export class ILabeledIdCriterionOption extends CriterionOption {
|
|||||||
type: value,
|
type: value,
|
||||||
modifierOptions,
|
modifierOptions,
|
||||||
defaultModifier,
|
defaultModifier,
|
||||||
makeCriterion: () => new ILabeledIdCriterion(this),
|
|
||||||
inputType,
|
inputType,
|
||||||
|
makeCriterion: makeCriterion
|
||||||
|
? makeCriterion
|
||||||
|
: () => new ILabeledIdCriterion(this),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -689,8 +423,231 @@ export class IHierarchicalLabeledIdCriterion extends Criterion<IHierarchicalLabe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MandatoryNumberCriterionOption extends CriterionOption {
|
export class StringCriterionOption extends CriterionOption {
|
||||||
|
constructor(
|
||||||
|
messageID: string,
|
||||||
|
value: CriterionType,
|
||||||
|
makeCriterion?: () => Criterion<CriterionValue>
|
||||||
|
) {
|
||||||
|
super({
|
||||||
|
messageID,
|
||||||
|
type: value,
|
||||||
|
modifierOptions: [
|
||||||
|
CriterionModifier.Equals,
|
||||||
|
CriterionModifier.NotEquals,
|
||||||
|
CriterionModifier.Includes,
|
||||||
|
CriterionModifier.Excludes,
|
||||||
|
CriterionModifier.IsNull,
|
||||||
|
CriterionModifier.NotNull,
|
||||||
|
CriterionModifier.MatchesRegex,
|
||||||
|
CriterionModifier.NotMatchesRegex,
|
||||||
|
],
|
||||||
|
defaultModifier: CriterionModifier.Equals,
|
||||||
|
inputType: "text",
|
||||||
|
makeCriterion: makeCriterion
|
||||||
|
? makeCriterion
|
||||||
|
: () => new StringCriterion(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createStringCriterionOption(
|
||||||
|
type: CriterionType,
|
||||||
|
messageID?: string
|
||||||
|
) {
|
||||||
|
return new StringCriterionOption(messageID ?? type, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MandatoryStringCriterionOption extends CriterionOption {
|
||||||
constructor(messageID: string, value: CriterionType) {
|
constructor(messageID: string, value: CriterionType) {
|
||||||
|
super({
|
||||||
|
messageID,
|
||||||
|
type: value,
|
||||||
|
modifierOptions: [
|
||||||
|
CriterionModifier.Equals,
|
||||||
|
CriterionModifier.NotEquals,
|
||||||
|
CriterionModifier.Includes,
|
||||||
|
CriterionModifier.Excludes,
|
||||||
|
CriterionModifier.MatchesRegex,
|
||||||
|
CriterionModifier.NotMatchesRegex,
|
||||||
|
],
|
||||||
|
defaultModifier: CriterionModifier.Equals,
|
||||||
|
inputType: "text",
|
||||||
|
makeCriterion: () => new StringCriterion(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMandatoryStringCriterionOption(
|
||||||
|
value: CriterionType,
|
||||||
|
messageID?: string
|
||||||
|
) {
|
||||||
|
return new MandatoryStringCriterionOption(messageID ?? value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StringCriterion extends Criterion<string> {
|
||||||
|
constructor(type: CriterionOption) {
|
||||||
|
super(type, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getLabelValue(_intl: IntlShape) {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isValid(): boolean {
|
||||||
|
return (
|
||||||
|
this.modifier === CriterionModifier.IsNull ||
|
||||||
|
this.modifier === CriterionModifier.NotNull ||
|
||||||
|
this.value.length > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MultiStringCriterion extends Criterion<string[]> {
|
||||||
|
constructor(type: CriterionOption) {
|
||||||
|
super(type, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getLabelValue(_intl: IntlShape) {
|
||||||
|
return this.value.join(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
public isValid(): boolean {
|
||||||
|
return (
|
||||||
|
this.modifier === CriterionModifier.IsNull ||
|
||||||
|
this.modifier === CriterionModifier.NotNull ||
|
||||||
|
this.value.length > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BooleanCriterionOption extends CriterionOption {
|
||||||
|
constructor(
|
||||||
|
messageID: string,
|
||||||
|
value: CriterionType,
|
||||||
|
makeCriterion?: () => Criterion<CriterionValue>
|
||||||
|
) {
|
||||||
|
super({
|
||||||
|
messageID,
|
||||||
|
type: value,
|
||||||
|
modifierOptions: [],
|
||||||
|
defaultModifier: CriterionModifier.Equals,
|
||||||
|
options: ["true", "false"],
|
||||||
|
makeCriterion: makeCriterion
|
||||||
|
? makeCriterion
|
||||||
|
: () => new BooleanCriterion(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createBooleanCriterionOption(
|
||||||
|
value: CriterionType,
|
||||||
|
messageID?: string
|
||||||
|
) {
|
||||||
|
return new BooleanCriterionOption(messageID ?? value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BooleanCriterion extends StringCriterion {
|
||||||
|
protected toCriterionInput(): boolean {
|
||||||
|
return this.value === "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
public isValid() {
|
||||||
|
return this.value === "true" || this.value === "false";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StringBooleanCriterionOption extends CriterionOption {
|
||||||
|
constructor(
|
||||||
|
messageID: string,
|
||||||
|
value: CriterionType,
|
||||||
|
makeCriterion?: () => Criterion<CriterionValue>
|
||||||
|
) {
|
||||||
|
super({
|
||||||
|
messageID,
|
||||||
|
type: value,
|
||||||
|
options: ["true", "false"],
|
||||||
|
makeCriterion: makeCriterion
|
||||||
|
? makeCriterion
|
||||||
|
: () => new StringBooleanCriterion(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class StringBooleanCriterion extends StringCriterion {
|
||||||
|
protected toCriterionInput(): string {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isValid() {
|
||||||
|
return this.value === "true" || this.value === "false";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NumberCriterionOption extends CriterionOption {
|
||||||
|
constructor(messageID: string, value: CriterionType) {
|
||||||
|
super({
|
||||||
|
messageID,
|
||||||
|
type: value,
|
||||||
|
modifierOptions: [
|
||||||
|
CriterionModifier.Equals,
|
||||||
|
CriterionModifier.NotEquals,
|
||||||
|
CriterionModifier.GreaterThan,
|
||||||
|
CriterionModifier.LessThan,
|
||||||
|
CriterionModifier.IsNull,
|
||||||
|
CriterionModifier.NotNull,
|
||||||
|
CriterionModifier.Between,
|
||||||
|
CriterionModifier.NotBetween,
|
||||||
|
],
|
||||||
|
defaultModifier: CriterionModifier.Equals,
|
||||||
|
inputType: "number",
|
||||||
|
makeCriterion: () => new NumberCriterion(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createNumberCriterionOption(
|
||||||
|
value: CriterionType,
|
||||||
|
messageID?: string
|
||||||
|
) {
|
||||||
|
return new NumberCriterionOption(messageID ?? value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NullNumberCriterionOption extends CriterionOption {
|
||||||
|
constructor(messageID: string, value: CriterionType) {
|
||||||
|
super({
|
||||||
|
messageID,
|
||||||
|
type: value,
|
||||||
|
modifierOptions: [
|
||||||
|
CriterionModifier.Equals,
|
||||||
|
CriterionModifier.NotEquals,
|
||||||
|
CriterionModifier.GreaterThan,
|
||||||
|
CriterionModifier.LessThan,
|
||||||
|
CriterionModifier.Between,
|
||||||
|
CriterionModifier.NotBetween,
|
||||||
|
CriterionModifier.IsNull,
|
||||||
|
CriterionModifier.NotNull,
|
||||||
|
],
|
||||||
|
defaultModifier: CriterionModifier.Equals,
|
||||||
|
inputType: "number",
|
||||||
|
makeCriterion: () => new NumberCriterion(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createNullNumberCriterionOption(
|
||||||
|
value: CriterionType,
|
||||||
|
messageID?: string
|
||||||
|
) {
|
||||||
|
return new NullNumberCriterionOption(messageID ?? value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MandatoryNumberCriterionOption extends CriterionOption {
|
||||||
|
constructor(
|
||||||
|
messageID: string,
|
||||||
|
value: CriterionType,
|
||||||
|
makeCriterion?: () => Criterion<CriterionValue>
|
||||||
|
) {
|
||||||
super({
|
super({
|
||||||
messageID,
|
messageID,
|
||||||
type: value,
|
type: value,
|
||||||
@@ -704,7 +661,9 @@ export class MandatoryNumberCriterionOption extends CriterionOption {
|
|||||||
],
|
],
|
||||||
defaultModifier: CriterionModifier.Equals,
|
defaultModifier: CriterionModifier.Equals,
|
||||||
inputType: "number",
|
inputType: "number",
|
||||||
makeCriterion: () => new NumberCriterion(this),
|
makeCriterion: makeCriterion
|
||||||
|
? makeCriterion
|
||||||
|
: () => new NumberCriterion(this),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -716,6 +675,84 @@ export function createMandatoryNumberCriterionOption(
|
|||||||
return new MandatoryNumberCriterionOption(messageID ?? value, value);
|
return new MandatoryNumberCriterionOption(messageID ?? value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NumberCriterion extends Criterion<INumberValue> {
|
||||||
|
public get value(): INumberValue {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
public set value(newValue: number | INumberValue) {
|
||||||
|
// backwards compatibility - if this.value is a number, use that
|
||||||
|
if (typeof newValue !== "object") {
|
||||||
|
this._value = {
|
||||||
|
value: newValue,
|
||||||
|
value2: undefined,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this._value = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected toCriterionInput(): IntCriterionInput {
|
||||||
|
return {
|
||||||
|
modifier: this.modifier,
|
||||||
|
value: this.value?.value ?? 0,
|
||||||
|
value2: this.value?.value2,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getLabelValue(_intl: IntlShape) {
|
||||||
|
const { value, value2 } = this.value;
|
||||||
|
if (
|
||||||
|
this.modifier === CriterionModifier.Between ||
|
||||||
|
this.modifier === CriterionModifier.NotBetween
|
||||||
|
) {
|
||||||
|
return `${value}, ${value2 ?? 0}`;
|
||||||
|
} else {
|
||||||
|
return `${value}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public isValid(): boolean {
|
||||||
|
if (
|
||||||
|
this.modifier === CriterionModifier.IsNull ||
|
||||||
|
this.modifier === CriterionModifier.NotNull
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { value, value2 } = this.value;
|
||||||
|
if (value === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
value2 === undefined &&
|
||||||
|
(this.modifier === CriterionModifier.Between ||
|
||||||
|
this.modifier === CriterionModifier.NotBetween)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(type: CriterionOption) {
|
||||||
|
super(type, { value: undefined, value2: undefined });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DurationCriterionOption extends MandatoryNumberCriterionOption {
|
||||||
|
constructor(messageID: string, value: CriterionType) {
|
||||||
|
super(messageID, value, () => new DurationCriterion(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDurationCriterionOption(
|
||||||
|
value: CriterionType,
|
||||||
|
messageID?: string
|
||||||
|
) {
|
||||||
|
return new DurationCriterionOption(messageID ?? value, value);
|
||||||
|
}
|
||||||
|
|
||||||
export class DurationCriterion extends Criterion<INumberValue> {
|
export class DurationCriterion extends Criterion<INumberValue> {
|
||||||
constructor(type: CriterionOption) {
|
constructor(type: CriterionOption) {
|
||||||
super(type, { value: undefined, value2: undefined });
|
super(type, { value: undefined, value2: undefined });
|
||||||
@@ -730,17 +767,16 @@ export class DurationCriterion extends Criterion<INumberValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getLabelValue(_intl: IntlShape) {
|
protected getLabelValue(_intl: IntlShape) {
|
||||||
return this.modifier === CriterionModifier.Between ||
|
const value = DurationUtils.secondsToString(this.value.value ?? 0);
|
||||||
|
const value2 = DurationUtils.secondsToString(this.value.value2 ?? 0);
|
||||||
|
if (
|
||||||
|
this.modifier === CriterionModifier.Between ||
|
||||||
this.modifier === CriterionModifier.NotBetween
|
this.modifier === CriterionModifier.NotBetween
|
||||||
? `${DurationUtils.secondsToString(
|
) {
|
||||||
this.value.value ?? 0
|
return `${value}, ${value2}`;
|
||||||
)} ${DurationUtils.secondsToString(this.value.value2 ?? 0)}`
|
} else {
|
||||||
: this.modifier === CriterionModifier.GreaterThan ||
|
return value;
|
||||||
this.modifier === CriterionModifier.LessThan ||
|
}
|
||||||
this.modifier === CriterionModifier.Equals ||
|
|
||||||
this.modifier === CriterionModifier.NotEquals
|
|
||||||
? DurationUtils.secondsToString(this.value.value ?? 0)
|
|
||||||
: "?";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public isValid(): boolean {
|
public isValid(): boolean {
|
||||||
@@ -768,16 +804,8 @@ export class DurationCriterion extends Criterion<INumberValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PhashDuplicateCriterion extends StringCriterion {
|
|
||||||
protected toCriterionInput(): PHashDuplicationCriterionInput {
|
|
||||||
return {
|
|
||||||
duplicated: this.value === "true",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DateCriterionOption extends CriterionOption {
|
export class DateCriterionOption extends CriterionOption {
|
||||||
constructor(messageID: string, value: CriterionType, options?: Option[]) {
|
constructor(messageID: string, value: CriterionType) {
|
||||||
super({
|
super({
|
||||||
messageID,
|
messageID,
|
||||||
type: value,
|
type: value,
|
||||||
@@ -792,7 +820,6 @@ export class DateCriterionOption extends CriterionOption {
|
|||||||
CriterionModifier.NotBetween,
|
CriterionModifier.NotBetween,
|
||||||
],
|
],
|
||||||
defaultModifier: CriterionModifier.Equals,
|
defaultModifier: CriterionModifier.Equals,
|
||||||
options,
|
|
||||||
inputType: "text",
|
inputType: "text",
|
||||||
makeCriterion: () => new DateCriterion(this),
|
makeCriterion: () => new DateCriterion(this),
|
||||||
});
|
});
|
||||||
@@ -857,7 +884,7 @@ export class DateCriterion extends Criterion<IDateValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TimestampCriterionOption extends CriterionOption {
|
export class TimestampCriterionOption extends CriterionOption {
|
||||||
constructor(messageID: string, value: CriterionType, options?: Option[]) {
|
constructor(messageID: string, value: CriterionType) {
|
||||||
super({
|
super({
|
||||||
messageID,
|
messageID,
|
||||||
type: value,
|
type: value,
|
||||||
@@ -870,7 +897,6 @@ export class TimestampCriterionOption extends CriterionOption {
|
|||||||
CriterionModifier.NotBetween,
|
CriterionModifier.NotBetween,
|
||||||
],
|
],
|
||||||
defaultModifier: CriterionModifier.GreaterThan,
|
defaultModifier: CriterionModifier.GreaterThan,
|
||||||
options,
|
|
||||||
inputType: "text",
|
inputType: "text",
|
||||||
makeCriterion: () => new TimestampCriterion(this),
|
makeCriterion: () => new TimestampCriterion(this),
|
||||||
});
|
});
|
||||||
@@ -881,6 +907,28 @@ export function createTimestampCriterionOption(value: CriterionType) {
|
|||||||
return new TimestampCriterionOption(value, value);
|
return new TimestampCriterionOption(value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class MandatoryTimestampCriterionOption extends CriterionOption {
|
||||||
|
constructor(messageID: string, value: CriterionType) {
|
||||||
|
super({
|
||||||
|
messageID,
|
||||||
|
type: value,
|
||||||
|
modifierOptions: [
|
||||||
|
CriterionModifier.GreaterThan,
|
||||||
|
CriterionModifier.LessThan,
|
||||||
|
CriterionModifier.Between,
|
||||||
|
CriterionModifier.NotBetween,
|
||||||
|
],
|
||||||
|
defaultModifier: CriterionModifier.GreaterThan,
|
||||||
|
inputType: "text",
|
||||||
|
makeCriterion: () => new TimestampCriterion(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createMandatoryTimestampCriterionOption(value: CriterionType) {
|
||||||
|
return new MandatoryTimestampCriterionOption(value, value);
|
||||||
|
}
|
||||||
|
|
||||||
export class TimestampCriterion extends Criterion<ITimestampValue> {
|
export class TimestampCriterion extends Criterion<ITimestampValue> {
|
||||||
public encodeValue() {
|
public encodeValue() {
|
||||||
return {
|
return {
|
||||||
@@ -944,26 +992,3 @@ export class TimestampCriterion extends Criterion<ITimestampValue> {
|
|||||||
super(type, { value: "", value2: undefined });
|
super(type, { value: "", value2: undefined });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MandatoryTimestampCriterionOption extends CriterionOption {
|
|
||||||
constructor(messageID: string, value: CriterionType, options?: Option[]) {
|
|
||||||
super({
|
|
||||||
messageID,
|
|
||||||
type: value,
|
|
||||||
modifierOptions: [
|
|
||||||
CriterionModifier.GreaterThan,
|
|
||||||
CriterionModifier.LessThan,
|
|
||||||
CriterionModifier.Between,
|
|
||||||
CriterionModifier.NotBetween,
|
|
||||||
],
|
|
||||||
defaultModifier: CriterionModifier.GreaterThan,
|
|
||||||
options,
|
|
||||||
inputType: "text",
|
|
||||||
makeCriterion: () => new TimestampCriterion(this),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createMandatoryTimestampCriterionOption(value: CriterionType) {
|
|
||||||
return new MandatoryTimestampCriterionOption(value, value);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
import * as GQL from "src/core/generated-graphql";
|
|
||||||
import { SceneListFilterOptions } from "../scenes";
|
|
||||||
import { MovieListFilterOptions } from "../movies";
|
|
||||||
import { GalleryListFilterOptions } from "../galleries";
|
|
||||||
import { PerformerListFilterOptions } from "../performers";
|
|
||||||
import { ImageListFilterOptions } from "../images";
|
|
||||||
import { SceneMarkerListFilterOptions } from "../scene-markers";
|
|
||||||
import { StudioListFilterOptions } from "../studios";
|
|
||||||
import { TagListFilterOptions } from "../tags";
|
|
||||||
import { CriterionType } from "../types";
|
|
||||||
|
|
||||||
const filterModeOptions = {
|
|
||||||
[GQL.FilterMode.Galleries]: GalleryListFilterOptions.criterionOptions,
|
|
||||||
[GQL.FilterMode.Images]: ImageListFilterOptions.criterionOptions,
|
|
||||||
[GQL.FilterMode.Movies]: MovieListFilterOptions.criterionOptions,
|
|
||||||
[GQL.FilterMode.Performers]: PerformerListFilterOptions.criterionOptions,
|
|
||||||
[GQL.FilterMode.SceneMarkers]: SceneMarkerListFilterOptions.criterionOptions,
|
|
||||||
[GQL.FilterMode.Scenes]: SceneListFilterOptions.criterionOptions,
|
|
||||||
[GQL.FilterMode.Studios]: StudioListFilterOptions.criterionOptions,
|
|
||||||
[GQL.FilterMode.Tags]: TagListFilterOptions.criterionOptions,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function makeCriteria(
|
|
||||||
mode: GQL.FilterMode,
|
|
||||||
type: CriterionType,
|
|
||||||
config?: GQL.ConfigDataFragment
|
|
||||||
) {
|
|
||||||
const criterionOptions = filterModeOptions[mode];
|
|
||||||
|
|
||||||
const option = criterionOptions.find((o) => o.type === type);
|
|
||||||
|
|
||||||
if (!option) {
|
|
||||||
throw new Error(`Unknown criterion parameter name: ${type}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return option?.makeCriterion(config);
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,8 @@ import { BooleanCriterion, BooleanCriterionOption } from "./criterion";
|
|||||||
|
|
||||||
export const FavoriteCriterionOption = new BooleanCriterionOption(
|
export const FavoriteCriterionOption = new BooleanCriterionOption(
|
||||||
"favourite",
|
"favourite",
|
||||||
"filter_favorites"
|
"filter_favorites",
|
||||||
|
() => new FavoriteCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class FavoriteCriterion extends BooleanCriterion {
|
export class FavoriteCriterion extends BooleanCriterion {
|
||||||
@@ -13,7 +14,8 @@ export class FavoriteCriterion extends BooleanCriterion {
|
|||||||
|
|
||||||
export const PerformerFavoriteCriterionOption = new BooleanCriterionOption(
|
export const PerformerFavoriteCriterionOption = new BooleanCriterionOption(
|
||||||
"performer_favorite",
|
"performer_favorite",
|
||||||
"performer_favorite"
|
"performer_favorite",
|
||||||
|
() => new PerformerFavoriteCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class PerformerFavoriteCriterion extends BooleanCriterion {
|
export class PerformerFavoriteCriterion extends BooleanCriterion {
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ import { ILabeledIdCriterion, ILabeledIdCriterionOption } from "./criterion";
|
|||||||
|
|
||||||
const inputType = "galleries";
|
const inputType = "galleries";
|
||||||
|
|
||||||
const galleriesCriterionOption = new ILabeledIdCriterionOption(
|
export const GalleriesCriterionOption = new ILabeledIdCriterionOption(
|
||||||
"galleries",
|
"galleries",
|
||||||
"galleries",
|
"galleries",
|
||||||
true,
|
true,
|
||||||
inputType
|
inputType,
|
||||||
|
() => new GalleriesCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class GalleriesCriterion extends ILabeledIdCriterion {
|
export class GalleriesCriterion extends ILabeledIdCriterion {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(galleriesCriterionOption);
|
super(GalleriesCriterionOption);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
import { CriterionOption, StringCriterion } from "./criterion";
|
import {
|
||||||
|
StringBooleanCriterion,
|
||||||
|
StringBooleanCriterionOption,
|
||||||
|
} from "./criterion";
|
||||||
|
|
||||||
export const HasChaptersCriterionOption = new CriterionOption({
|
export const HasChaptersCriterionOption = new StringBooleanCriterionOption(
|
||||||
messageID: "hasChapters",
|
"hasChapters",
|
||||||
type: "has_chapters",
|
"has_chapters",
|
||||||
options: [true.toString(), false.toString()],
|
() => new HasChaptersCriterion()
|
||||||
makeCriterion: () => new HasChaptersCriterion(),
|
);
|
||||||
});
|
|
||||||
|
|
||||||
export class HasChaptersCriterion extends StringCriterion {
|
export class HasChaptersCriterion extends StringBooleanCriterion {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(HasChaptersCriterionOption);
|
super(HasChaptersCriterionOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected toCriterionInput(): string {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
import { CriterionOption, StringCriterion } from "./criterion";
|
import {
|
||||||
|
StringBooleanCriterion,
|
||||||
|
StringBooleanCriterionOption,
|
||||||
|
} from "./criterion";
|
||||||
|
|
||||||
export const HasMarkersCriterionOption = new CriterionOption({
|
export const HasMarkersCriterionOption = new StringBooleanCriterionOption(
|
||||||
messageID: "hasMarkers",
|
"hasMarkers",
|
||||||
type: "has_markers",
|
"has_markers",
|
||||||
options: [true.toString(), false.toString()],
|
() => new HasMarkersCriterion()
|
||||||
makeCriterion: () => new HasMarkersCriterion(),
|
);
|
||||||
});
|
|
||||||
|
|
||||||
export class HasMarkersCriterion extends StringCriterion {
|
export class HasMarkersCriterion extends StringBooleanCriterion {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(HasMarkersCriterionOption);
|
super(HasMarkersCriterionOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected toCriterionInput(): string {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { BooleanCriterion, BooleanCriterionOption } from "./criterion";
|
|||||||
|
|
||||||
export const InteractiveCriterionOption = new BooleanCriterionOption(
|
export const InteractiveCriterionOption = new BooleanCriterionOption(
|
||||||
"interactive",
|
"interactive",
|
||||||
"interactive"
|
"interactive",
|
||||||
|
() => new InteractiveCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class InteractiveCriterion extends BooleanCriterion {
|
export class InteractiveCriterion extends BooleanCriterion {
|
||||||
|
|||||||
@@ -3,26 +3,25 @@ import { CriterionType } from "../types";
|
|||||||
import { CriterionOption, StringCriterion, Option } from "./criterion";
|
import { CriterionOption, StringCriterion, Option } from "./criterion";
|
||||||
|
|
||||||
export class IsMissingCriterion extends StringCriterion {
|
export class IsMissingCriterion extends StringCriterion {
|
||||||
public modifierOptions = [];
|
|
||||||
|
|
||||||
protected toCriterionInput(): string {
|
protected toCriterionInput(): string {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IsMissingCriterionOptionClass extends CriterionOption {
|
class IsMissingCriterionOption extends CriterionOption {
|
||||||
constructor(messageID: string, type: CriterionType, options: Option[]) {
|
constructor(messageID: string, type: CriterionType, options: Option[]) {
|
||||||
super({
|
super({
|
||||||
messageID,
|
messageID,
|
||||||
type,
|
type,
|
||||||
options,
|
options,
|
||||||
|
modifierOptions: [],
|
||||||
defaultModifier: CriterionModifier.Equals,
|
defaultModifier: CriterionModifier.Equals,
|
||||||
makeCriterion: () => new IsMissingCriterion(this),
|
makeCriterion: () => new IsMissingCriterion(this),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SceneIsMissingCriterionOption = new IsMissingCriterionOptionClass(
|
export const SceneIsMissingCriterionOption = new IsMissingCriterionOption(
|
||||||
"isMissing",
|
"isMissing",
|
||||||
"is_missing",
|
"is_missing",
|
||||||
[
|
[
|
||||||
@@ -40,14 +39,16 @@ export const SceneIsMissingCriterionOption = new IsMissingCriterionOptionClass(
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ImageIsMissingCriterionOption = new IsMissingCriterionOptionClass(
|
export const ImageIsMissingCriterionOption = new IsMissingCriterionOption(
|
||||||
"isMissing",
|
"isMissing",
|
||||||
"is_missing",
|
"is_missing",
|
||||||
["title", "galleries", "studio", "performers", "tags"]
|
["title", "galleries", "studio", "performers", "tags"]
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PerformerIsMissingCriterionOption =
|
export const PerformerIsMissingCriterionOption = new IsMissingCriterionOption(
|
||||||
new IsMissingCriterionOptionClass("isMissing", "is_missing", [
|
"isMissing",
|
||||||
|
"is_missing",
|
||||||
|
[
|
||||||
"url",
|
"url",
|
||||||
"twitter",
|
"twitter",
|
||||||
"instagram",
|
"instagram",
|
||||||
@@ -67,33 +68,28 @@ export const PerformerIsMissingCriterionOption =
|
|||||||
"image",
|
"image",
|
||||||
"details",
|
"details",
|
||||||
"stash_id",
|
"stash_id",
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
|
|
||||||
export const GalleryIsMissingCriterionOption =
|
export const GalleryIsMissingCriterionOption = new IsMissingCriterionOption(
|
||||||
new IsMissingCriterionOptionClass("isMissing", "is_missing", [
|
"isMissing",
|
||||||
"title",
|
"is_missing",
|
||||||
"details",
|
["title", "details", "url", "date", "studio", "performers", "tags", "scenes"]
|
||||||
"url",
|
);
|
||||||
"date",
|
|
||||||
"studio",
|
|
||||||
"performers",
|
|
||||||
"tags",
|
|
||||||
"scenes",
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const TagIsMissingCriterionOption = new IsMissingCriterionOptionClass(
|
export const TagIsMissingCriterionOption = new IsMissingCriterionOption(
|
||||||
"isMissing",
|
"isMissing",
|
||||||
"is_missing",
|
"is_missing",
|
||||||
["image"]
|
["image"]
|
||||||
);
|
);
|
||||||
|
|
||||||
export const StudioIsMissingCriterionOption = new IsMissingCriterionOptionClass(
|
export const StudioIsMissingCriterionOption = new IsMissingCriterionOption(
|
||||||
"isMissing",
|
"isMissing",
|
||||||
"is_missing",
|
"is_missing",
|
||||||
["image", "stash_id", "details"]
|
["image", "stash_id", "details"]
|
||||||
);
|
);
|
||||||
|
|
||||||
export const MovieIsMissingCriterionOption = new IsMissingCriterionOptionClass(
|
export const MovieIsMissingCriterionOption = new IsMissingCriterionOption(
|
||||||
"isMissing",
|
"isMissing",
|
||||||
"is_missing",
|
"is_missing",
|
||||||
["front_image", "back_image", "scenes"]
|
["front_image", "back_image", "scenes"]
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ export const MoviesCriterionOption = new ILabeledIdCriterionOption(
|
|||||||
"movies",
|
"movies",
|
||||||
"movies",
|
"movies",
|
||||||
false,
|
false,
|
||||||
inputType
|
inputType,
|
||||||
|
() => new MoviesCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class MoviesCriterion extends ILabeledIdCriterion {
|
export class MoviesCriterion extends ILabeledIdCriterion {
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
import { Criterion, StringCriterionOption } from "./criterion";
|
|
||||||
|
|
||||||
export const NoneCriterionOption = new StringCriterionOption("none", "none");
|
|
||||||
export class NoneCriterion extends Criterion<string> {
|
|
||||||
constructor() {
|
|
||||||
super(NoneCriterionOption, "none");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected getLabelValue(): string {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,8 @@ import { BooleanCriterion, BooleanCriterionOption } from "./criterion";
|
|||||||
|
|
||||||
export const OrganizedCriterionOption = new BooleanCriterionOption(
|
export const OrganizedCriterionOption = new BooleanCriterionOption(
|
||||||
"organized",
|
"organized",
|
||||||
"organized"
|
"organized",
|
||||||
|
() => new OrganizedCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class OrganizedCriterion extends BooleanCriterion {
|
export class OrganizedCriterion extends BooleanCriterion {
|
||||||
|
|||||||
13
ui/v2.5/src/models/list-filter/criteria/path.ts
Normal file
13
ui/v2.5/src/models/list-filter/criteria/path.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { StringCriterion, StringCriterionOption } from "./criterion";
|
||||||
|
|
||||||
|
export const PathCriterionOption = new StringCriterionOption(
|
||||||
|
"path",
|
||||||
|
"path",
|
||||||
|
() => new PathCriterion()
|
||||||
|
);
|
||||||
|
|
||||||
|
export class PathCriterion extends StringCriterion {
|
||||||
|
constructor() {
|
||||||
|
super(PathCriterionOption);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,8 +24,8 @@ export const PerformersCriterionOption = new CriterionOption({
|
|||||||
type: "performers",
|
type: "performers",
|
||||||
modifierOptions,
|
modifierOptions,
|
||||||
defaultModifier,
|
defaultModifier,
|
||||||
makeCriterion: () => new PerformersCriterion(),
|
|
||||||
inputType,
|
inputType,
|
||||||
|
makeCriterion: () => new PerformersCriterion(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export class PerformersCriterion extends Criterion<ILabeledValueListValue> {
|
export class PerformersCriterion extends Criterion<ILabeledValueListValue> {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
CriterionModifier,
|
CriterionModifier,
|
||||||
PhashDistanceCriterionInput,
|
PhashDistanceCriterionInput,
|
||||||
|
PHashDuplicationCriterionInput,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import { IPhashDistanceValue } from "../types";
|
import { IPhashDistanceValue } from "../types";
|
||||||
import {
|
import {
|
||||||
BooleanCriterionOption,
|
BooleanCriterionOption,
|
||||||
Criterion,
|
Criterion,
|
||||||
CriterionOption,
|
CriterionOption,
|
||||||
PhashDuplicateCriterion,
|
StringCriterion,
|
||||||
} from "./criterion";
|
} from "./criterion";
|
||||||
|
|
||||||
export const PhashCriterionOption = new CriterionOption({
|
export const PhashCriterionOption = new CriterionOption({
|
||||||
@@ -56,8 +57,14 @@ export const DuplicatedCriterionOption = new BooleanCriterionOption(
|
|||||||
() => new DuplicatedCriterion()
|
() => new DuplicatedCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class DuplicatedCriterion extends PhashDuplicateCriterion {
|
export class DuplicatedCriterion extends StringCriterion {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(DuplicatedCriterionOption);
|
super(DuplicatedCriterionOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected toCriterionInput(): PHashDuplicationCriterionInput {
|
||||||
|
return {
|
||||||
|
duplicated: this.value === "true",
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
ConfigDataFragment,
|
ConfigDataFragment,
|
||||||
CriterionModifier,
|
CriterionModifier,
|
||||||
IntCriterionInput,
|
IntCriterionInput,
|
||||||
} from "../../../core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import { INumberValue } from "../types";
|
import { INumberValue } from "../types";
|
||||||
import { Criterion, CriterionOption } from "./criterion";
|
import { Criterion, CriterionOption } from "./criterion";
|
||||||
import { IUIConfig } from "src/core/config";
|
import { IUIConfig } from "src/core/config";
|
||||||
|
|||||||
@@ -11,20 +11,7 @@ import {
|
|||||||
StringCriterion,
|
StringCriterion,
|
||||||
} from "./criterion";
|
} from "./criterion";
|
||||||
|
|
||||||
abstract class AbstractResolutionCriterion extends StringCriterion {
|
class BaseResolutionCriterionOption extends CriterionOption {
|
||||||
protected toCriterionInput(): ResolutionCriterionInput | undefined {
|
|
||||||
const value = stringToResolution(this.value);
|
|
||||||
|
|
||||||
if (value !== undefined) {
|
|
||||||
return {
|
|
||||||
value,
|
|
||||||
modifier: this.modifier,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ResolutionCriterionOptionType extends CriterionOption {
|
|
||||||
constructor(
|
constructor(
|
||||||
value: CriterionType,
|
value: CriterionType,
|
||||||
makeCriterion: () => Criterion<CriterionValue>
|
makeCriterion: () => Criterion<CriterionValue>
|
||||||
@@ -44,23 +31,37 @@ class ResolutionCriterionOptionType extends CriterionOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ResolutionCriterionOption = new ResolutionCriterionOptionType(
|
class BaseResolutionCriterion extends StringCriterion {
|
||||||
|
protected toCriterionInput(): ResolutionCriterionInput | undefined {
|
||||||
|
const value = stringToResolution(this.value);
|
||||||
|
|
||||||
|
if (value !== undefined) {
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
modifier: this.modifier,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ResolutionCriterionOption = new BaseResolutionCriterionOption(
|
||||||
"resolution",
|
"resolution",
|
||||||
() => new ResolutionCriterion()
|
() => new ResolutionCriterion()
|
||||||
);
|
);
|
||||||
export class ResolutionCriterion extends AbstractResolutionCriterion {
|
|
||||||
|
export class ResolutionCriterion extends BaseResolutionCriterion {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(ResolutionCriterionOption);
|
super(ResolutionCriterionOption);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AverageResolutionCriterionOption =
|
export const AverageResolutionCriterionOption =
|
||||||
new ResolutionCriterionOptionType(
|
new BaseResolutionCriterionOption(
|
||||||
"average_resolution",
|
"average_resolution",
|
||||||
() => new AverageResolutionCriterion()
|
() => new AverageResolutionCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class AverageResolutionCriterion extends AbstractResolutionCriterion {
|
export class AverageResolutionCriterion extends BaseResolutionCriterion {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(AverageResolutionCriterionOption);
|
super(AverageResolutionCriterionOption);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ export const StudiosCriterionOption = new CriterionOption({
|
|||||||
type: "studios",
|
type: "studios",
|
||||||
modifierOptions,
|
modifierOptions,
|
||||||
defaultModifier,
|
defaultModifier,
|
||||||
makeCriterion: () => new StudiosCriterion(),
|
|
||||||
inputType,
|
inputType,
|
||||||
|
makeCriterion: () => new StudiosCriterion(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export class StudiosCriterion extends IHierarchicalLabeledIdCriterion {
|
export class StudiosCriterion extends IHierarchicalLabeledIdCriterion {
|
||||||
@@ -34,8 +34,10 @@ export const ParentStudiosCriterionOption = new ILabeledIdCriterionOption(
|
|||||||
"parent_studios",
|
"parent_studios",
|
||||||
"parents",
|
"parents",
|
||||||
false,
|
false,
|
||||||
inputType
|
inputType,
|
||||||
|
() => new ParentStudiosCriterion()
|
||||||
);
|
);
|
||||||
|
|
||||||
export class ParentStudiosCriterion extends ILabeledIdCriterion {
|
export class ParentStudiosCriterion extends ILabeledIdCriterion {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(ParentStudiosCriterionOption);
|
super(ParentStudiosCriterionOption);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const withoutEqualsModifierOptions = [
|
|||||||
const defaultModifier = CriterionModifier.IncludesAll;
|
const defaultModifier = CriterionModifier.IncludesAll;
|
||||||
const inputType = "tags";
|
const inputType = "tags";
|
||||||
|
|
||||||
export class TagsCriterionOptionClass extends CriterionOption {
|
class BaseTagsCriterionOption extends CriterionOption {
|
||||||
constructor(
|
constructor(
|
||||||
messageID: string,
|
messageID: string,
|
||||||
type: CriterionType,
|
type: CriterionType,
|
||||||
@@ -31,37 +31,37 @@ export class TagsCriterionOptionClass extends CriterionOption {
|
|||||||
type,
|
type,
|
||||||
modifierOptions,
|
modifierOptions,
|
||||||
defaultModifier,
|
defaultModifier,
|
||||||
makeCriterion: () => new TagsCriterion(this),
|
|
||||||
inputType,
|
inputType,
|
||||||
|
makeCriterion: () => new TagsCriterion(this),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TagsCriterionOption = new TagsCriterionOptionClass(
|
export const TagsCriterionOption = new BaseTagsCriterionOption(
|
||||||
"tags",
|
"tags",
|
||||||
"tags",
|
"tags",
|
||||||
defaultModifierOptions
|
defaultModifierOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
export const SceneTagsCriterionOption = new TagsCriterionOptionClass(
|
export const SceneTagsCriterionOption = new BaseTagsCriterionOption(
|
||||||
"scene_tags",
|
"scene_tags",
|
||||||
"scene_tags",
|
"scene_tags",
|
||||||
defaultModifierOptions
|
defaultModifierOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PerformerTagsCriterionOption = new TagsCriterionOptionClass(
|
export const PerformerTagsCriterionOption = new BaseTagsCriterionOption(
|
||||||
"performer_tags",
|
"performer_tags",
|
||||||
"performer_tags",
|
"performer_tags",
|
||||||
withoutEqualsModifierOptions
|
withoutEqualsModifierOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ParentTagsCriterionOption = new TagsCriterionOptionClass(
|
export const ParentTagsCriterionOption = new BaseTagsCriterionOption(
|
||||||
"parent_tags",
|
"parent_tags",
|
||||||
"parents",
|
"parents",
|
||||||
withoutEqualsModifierOptions
|
withoutEqualsModifierOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ChildTagsCriterionOption = new TagsCriterionOptionClass(
|
export const ChildTagsCriterionOption = new BaseTagsCriterionOption(
|
||||||
"sub_tags",
|
"sub_tags",
|
||||||
"children",
|
"children",
|
||||||
withoutEqualsModifierOptions
|
withoutEqualsModifierOptions
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
SortDirectionEnum,
|
SortDirectionEnum,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import { Criterion, CriterionValue } from "./criteria/criterion";
|
import { Criterion, CriterionValue } from "./criteria/criterion";
|
||||||
import { makeCriteria } from "./criteria/factory";
|
import { getFilterOptions } from "./factory";
|
||||||
import { CriterionType, DisplayMode } from "./types";
|
import { CriterionType, DisplayMode } from "./types";
|
||||||
|
|
||||||
interface IDecodedParams {
|
interface IDecodedParams {
|
||||||
@@ -128,16 +128,9 @@ export class ListFilterModel {
|
|||||||
for (const jsonString of params.c) {
|
for (const jsonString of params.c) {
|
||||||
try {
|
try {
|
||||||
const encodedCriterion = JSON.parse(jsonString);
|
const encodedCriterion = JSON.parse(jsonString);
|
||||||
const criterion = makeCriteria(
|
const criterion = this.makeCriterion(encodedCriterion.type);
|
||||||
this.mode,
|
criterion.setFromEncodedCriterion(encodedCriterion);
|
||||||
encodedCriterion.type,
|
this.criteria.push(criterion);
|
||||||
this.config
|
|
||||||
);
|
|
||||||
// it's possible that we have unsupported criteria. Just skip if so.
|
|
||||||
if (criterion) {
|
|
||||||
criterion.setFromEncodedCriterion(encodedCriterion);
|
|
||||||
this.criteria.push(criterion);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.error("Failed to parse encoded criterion:", err);
|
console.error("Failed to parse encoded criterion:", err);
|
||||||
@@ -280,16 +273,9 @@ export class ListFilterModel {
|
|||||||
this.criteria = [];
|
this.criteria = [];
|
||||||
if (objectFilter) {
|
if (objectFilter) {
|
||||||
Object.keys(objectFilter).forEach((key) => {
|
Object.keys(objectFilter).forEach((key) => {
|
||||||
const criterion = makeCriteria(
|
const criterion = this.makeCriterion(key as CriterionType);
|
||||||
this.mode,
|
criterion.setFromEncodedCriterion(objectFilter[key]);
|
||||||
key as CriterionType,
|
this.criteria.push(criterion);
|
||||||
this.config
|
|
||||||
);
|
|
||||||
// it's possible that we have unsupported criteria. Just skip if so.
|
|
||||||
if (criterion) {
|
|
||||||
criterion.setFromEncodedCriterion(objectFilter[key]);
|
|
||||||
this.criteria.push(criterion);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,6 +412,18 @@ export class ListFilterModel {
|
|||||||
return query.join("&");
|
return query.join("&");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public makeCriterion(type: CriterionType) {
|
||||||
|
const { criterionOptions } = getFilterOptions(this.mode);
|
||||||
|
|
||||||
|
const option = criterionOptions.find((o) => o.type === type);
|
||||||
|
|
||||||
|
if (!option) {
|
||||||
|
throw new Error(`Unknown criterion parameter name: ${type}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return option.makeCriterion(this.config);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: These don't support multiple of the same criteria, only the last one set is used.
|
// TODO: These don't support multiple of the same criteria, only the last one set is used.
|
||||||
|
|
||||||
public makeFindFilter(): FindFilterType {
|
public makeFindFilter(): FindFilterType {
|
||||||
@@ -439,8 +437,7 @@ export class ListFilterModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public makeFilter() {
|
public makeFilter() {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
const output: Record<string, unknown> = {};
|
||||||
const output: Record<string, any> = {};
|
|
||||||
this.criteria.forEach((criterion) => {
|
this.criteria.forEach((criterion) => {
|
||||||
criterion.apply(output);
|
criterion.apply(output);
|
||||||
});
|
});
|
||||||
@@ -449,8 +446,7 @@ export class ListFilterModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public makeSavedFindFilter() {
|
public makeSavedFindFilter() {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
const output: Record<string, unknown> = {};
|
||||||
const output: Record<string, any> = {};
|
|
||||||
this.criteria.forEach((criterion) => {
|
this.criteria.forEach((criterion) => {
|
||||||
criterion.toSavedFilter(output);
|
criterion.toSavedFilter(output);
|
||||||
});
|
});
|
||||||
@@ -458,8 +454,7 @@ export class ListFilterModel {
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
public makeUIOptions(): Record<string, unknown> {
|
||||||
public makeUIOptions(): Record<string, any> {
|
|
||||||
return {
|
return {
|
||||||
display_mode: this.displayMode,
|
display_mode: this.displayMode,
|
||||||
zoom_index: this.zoomIndex,
|
zoom_index: this.zoomIndex,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
createStringCriterionOption,
|
createStringCriterionOption,
|
||||||
createDateCriterionOption,
|
createDateCriterionOption,
|
||||||
createMandatoryTimestampCriterionOption,
|
createMandatoryTimestampCriterionOption,
|
||||||
createPathCriterionOption,
|
|
||||||
} from "./criteria/criterion";
|
} from "./criteria/criterion";
|
||||||
import { PerformerFavoriteCriterionOption } from "./criteria/favorite";
|
import { PerformerFavoriteCriterionOption } from "./criteria/favorite";
|
||||||
import { GalleryIsMissingCriterionOption } from "./criteria/is-missing";
|
import { GalleryIsMissingCriterionOption } from "./criteria/is-missing";
|
||||||
@@ -19,6 +18,7 @@ import {
|
|||||||
import { ListFilterOptions, MediaSortByOptions } from "./filter-options";
|
import { ListFilterOptions, MediaSortByOptions } from "./filter-options";
|
||||||
import { DisplayMode } from "./types";
|
import { DisplayMode } from "./types";
|
||||||
import { RatingCriterionOption } from "./criteria/rating";
|
import { RatingCriterionOption } from "./criteria/rating";
|
||||||
|
import { PathCriterionOption } from "./criteria/path";
|
||||||
|
|
||||||
const defaultSortBy = "path";
|
const defaultSortBy = "path";
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ const displayModeOptions = [
|
|||||||
const criterionOptions = [
|
const criterionOptions = [
|
||||||
createStringCriterionOption("title"),
|
createStringCriterionOption("title"),
|
||||||
createStringCriterionOption("details"),
|
createStringCriterionOption("details"),
|
||||||
createPathCriterionOption("path"),
|
PathCriterionOption,
|
||||||
createStringCriterionOption("checksum", "media_info.checksum"),
|
createStringCriterionOption("checksum", "media_info.checksum"),
|
||||||
RatingCriterionOption,
|
RatingCriterionOption,
|
||||||
OrganizedCriterionOption,
|
OrganizedCriterionOption,
|
||||||
@@ -52,13 +52,13 @@ const criterionOptions = [
|
|||||||
GalleryIsMissingCriterionOption,
|
GalleryIsMissingCriterionOption,
|
||||||
TagsCriterionOption,
|
TagsCriterionOption,
|
||||||
HasChaptersCriterionOption,
|
HasChaptersCriterionOption,
|
||||||
createStringCriterionOption("tag_count"),
|
createMandatoryNumberCriterionOption("tag_count"),
|
||||||
PerformerTagsCriterionOption,
|
PerformerTagsCriterionOption,
|
||||||
PerformersCriterionOption,
|
PerformersCriterionOption,
|
||||||
createStringCriterionOption("performer_count"),
|
createMandatoryNumberCriterionOption("performer_count"),
|
||||||
createMandatoryNumberCriterionOption("performer_age"),
|
createMandatoryNumberCriterionOption("performer_age"),
|
||||||
PerformerFavoriteCriterionOption,
|
PerformerFavoriteCriterionOption,
|
||||||
createStringCriterionOption("image_count"),
|
createMandatoryNumberCriterionOption("image_count"),
|
||||||
StudiosCriterionOption,
|
StudiosCriterionOption,
|
||||||
createStringCriterionOption("url"),
|
createStringCriterionOption("url"),
|
||||||
createMandatoryNumberCriterionOption("file_count", "zip_file_count"),
|
createMandatoryNumberCriterionOption("file_count", "zip_file_count"),
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import {
|
|||||||
createStringCriterionOption,
|
createStringCriterionOption,
|
||||||
createMandatoryTimestampCriterionOption,
|
createMandatoryTimestampCriterionOption,
|
||||||
createDateCriterionOption,
|
createDateCriterionOption,
|
||||||
createPathCriterionOption,
|
|
||||||
} from "./criteria/criterion";
|
} from "./criteria/criterion";
|
||||||
import { PerformerFavoriteCriterionOption } from "./criteria/favorite";
|
import { PerformerFavoriteCriterionOption } from "./criteria/favorite";
|
||||||
import { ImageIsMissingCriterionOption } from "./criteria/is-missing";
|
import { ImageIsMissingCriterionOption } from "./criteria/is-missing";
|
||||||
import { OrganizedCriterionOption } from "./criteria/organized";
|
import { OrganizedCriterionOption } from "./criteria/organized";
|
||||||
|
import { PathCriterionOption } from "./criteria/path";
|
||||||
import { PerformersCriterionOption } from "./criteria/performers";
|
import { PerformersCriterionOption } from "./criteria/performers";
|
||||||
import { RatingCriterionOption } from "./criteria/rating";
|
import { RatingCriterionOption } from "./criteria/rating";
|
||||||
import { ResolutionCriterionOption } from "./criteria/resolution";
|
import { ResolutionCriterionOption } from "./criteria/resolution";
|
||||||
@@ -34,7 +34,7 @@ const displayModeOptions = [DisplayMode.Grid, DisplayMode.Wall];
|
|||||||
const criterionOptions = [
|
const criterionOptions = [
|
||||||
createStringCriterionOption("title"),
|
createStringCriterionOption("title"),
|
||||||
createMandatoryStringCriterionOption("checksum", "media_info.checksum"),
|
createMandatoryStringCriterionOption("checksum", "media_info.checksum"),
|
||||||
createPathCriterionOption("path"),
|
PathCriterionOption,
|
||||||
OrganizedCriterionOption,
|
OrganizedCriterionOption,
|
||||||
createMandatoryNumberCriterionOption("o_counter"),
|
createMandatoryNumberCriterionOption("o_counter"),
|
||||||
ResolutionCriterionOption,
|
ResolutionCriterionOption,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
createMandatoryNumberCriterionOption,
|
|
||||||
createStringCriterionOption,
|
createStringCriterionOption,
|
||||||
createDateCriterionOption,
|
createDateCriterionOption,
|
||||||
createMandatoryTimestampCriterionOption,
|
createMandatoryTimestampCriterionOption,
|
||||||
|
createDurationCriterionOption,
|
||||||
} from "./criteria/criterion";
|
} from "./criteria/criterion";
|
||||||
import { MovieIsMissingCriterionOption } from "./criteria/is-missing";
|
import { MovieIsMissingCriterionOption } from "./criteria/is-missing";
|
||||||
import { StudiosCriterionOption } from "./criteria/studios";
|
import { StudiosCriterionOption } from "./criteria/studios";
|
||||||
@@ -29,7 +29,7 @@ const criterionOptions = [
|
|||||||
createStringCriterionOption("name"),
|
createStringCriterionOption("name"),
|
||||||
createStringCriterionOption("director"),
|
createStringCriterionOption("director"),
|
||||||
createStringCriterionOption("synopsis"),
|
createStringCriterionOption("synopsis"),
|
||||||
createMandatoryNumberCriterionOption("duration"),
|
createDurationCriterionOption("duration"),
|
||||||
RatingCriterionOption,
|
RatingCriterionOption,
|
||||||
PerformersCriterionOption,
|
PerformersCriterionOption,
|
||||||
createDateCriterionOption("date"),
|
createDateCriterionOption("date"),
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {
|
|||||||
createBooleanCriterionOption,
|
createBooleanCriterionOption,
|
||||||
createDateCriterionOption,
|
createDateCriterionOption,
|
||||||
createMandatoryTimestampCriterionOption,
|
createMandatoryTimestampCriterionOption,
|
||||||
NumberCriterionOption,
|
|
||||||
} from "./criteria/criterion";
|
} from "./criteria/criterion";
|
||||||
import { FavoriteCriterionOption } from "./criteria/favorite";
|
import { FavoriteCriterionOption } from "./criteria/favorite";
|
||||||
import { GenderCriterionOption } from "./criteria/gender";
|
import { GenderCriterionOption } from "./criteria/gender";
|
||||||
@@ -94,9 +93,9 @@ const criterionOptions = [
|
|||||||
createMandatoryNumberCriterionOption("gallery_count"),
|
createMandatoryNumberCriterionOption("gallery_count"),
|
||||||
createMandatoryNumberCriterionOption("o_counter"),
|
createMandatoryNumberCriterionOption("o_counter"),
|
||||||
createBooleanCriterionOption("ignore_auto_tag"),
|
createBooleanCriterionOption("ignore_auto_tag"),
|
||||||
new NumberCriterionOption("height", "height_cm"),
|
|
||||||
...numberCriteria.map((c) => createNumberCriterionOption(c)),
|
|
||||||
CountryCriterionOption,
|
CountryCriterionOption,
|
||||||
|
createNumberCriterionOption("height_cm", "height"),
|
||||||
|
...numberCriteria.map((c) => createNumberCriterionOption(c)),
|
||||||
...stringCriteria.map((c) => createStringCriterionOption(c)),
|
...stringCriteria.map((c) => createStringCriterionOption(c)),
|
||||||
createDateCriterionOption("birthdate"),
|
createDateCriterionOption("birthdate"),
|
||||||
createDateCriterionOption("death_date"),
|
createDateCriterionOption("death_date"),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
createStringCriterionOption,
|
createStringCriterionOption,
|
||||||
createDateCriterionOption,
|
createDateCriterionOption,
|
||||||
createMandatoryTimestampCriterionOption,
|
createMandatoryTimestampCriterionOption,
|
||||||
createPathCriterionOption,
|
createDurationCriterionOption,
|
||||||
} from "./criteria/criterion";
|
} from "./criteria/criterion";
|
||||||
import { HasMarkersCriterionOption } from "./criteria/has-markers";
|
import { HasMarkersCriterionOption } from "./criteria/has-markers";
|
||||||
import { SceneIsMissingCriterionOption } from "./criteria/is-missing";
|
import { SceneIsMissingCriterionOption } from "./criteria/is-missing";
|
||||||
@@ -28,6 +28,7 @@ import { PerformerFavoriteCriterionOption } from "./criteria/favorite";
|
|||||||
import { CaptionsCriterionOption } from "./criteria/captions";
|
import { CaptionsCriterionOption } from "./criteria/captions";
|
||||||
import { StashIDCriterionOption } from "./criteria/stash-ids";
|
import { StashIDCriterionOption } from "./criteria/stash-ids";
|
||||||
import { RatingCriterionOption } from "./criteria/rating";
|
import { RatingCriterionOption } from "./criteria/rating";
|
||||||
|
import { PathCriterionOption } from "./criteria/path";
|
||||||
|
|
||||||
const defaultSortBy = "date";
|
const defaultSortBy = "date";
|
||||||
const sortByOptions = [
|
const sortByOptions = [
|
||||||
@@ -60,7 +61,7 @@ const displayModeOptions = [
|
|||||||
const criterionOptions = [
|
const criterionOptions = [
|
||||||
createStringCriterionOption("title"),
|
createStringCriterionOption("title"),
|
||||||
createStringCriterionOption("code", "scene_code"),
|
createStringCriterionOption("code", "scene_code"),
|
||||||
createPathCriterionOption("path"),
|
PathCriterionOption,
|
||||||
createStringCriterionOption("details"),
|
createStringCriterionOption("details"),
|
||||||
createStringCriterionOption("director"),
|
createStringCriterionOption("director"),
|
||||||
createMandatoryStringCriterionOption("oshash", "media_info.hash"),
|
createMandatoryStringCriterionOption("oshash", "media_info.hash"),
|
||||||
@@ -73,9 +74,9 @@ const criterionOptions = [
|
|||||||
ResolutionCriterionOption,
|
ResolutionCriterionOption,
|
||||||
createStringCriterionOption("video_codec"),
|
createStringCriterionOption("video_codec"),
|
||||||
createStringCriterionOption("audio_codec"),
|
createStringCriterionOption("audio_codec"),
|
||||||
createMandatoryNumberCriterionOption("duration"),
|
createDurationCriterionOption("duration"),
|
||||||
createMandatoryNumberCriterionOption("resume_time"),
|
createDurationCriterionOption("resume_time"),
|
||||||
createMandatoryNumberCriterionOption("play_duration"),
|
createDurationCriterionOption("play_duration"),
|
||||||
createMandatoryNumberCriterionOption("play_count"),
|
createMandatoryNumberCriterionOption("play_count"),
|
||||||
HasMarkersCriterionOption,
|
HasMarkersCriterionOption,
|
||||||
SceneIsMissingCriterionOption,
|
SceneIsMissingCriterionOption,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// NOTE: add new enum values to the end, to ensure existing data
|
// NOTE: add new enum values to the end, to ensure existing data
|
||||||
|
|
||||||
// is not impacted
|
// is not impacted
|
||||||
export enum DisplayMode {
|
export enum DisplayMode {
|
||||||
Grid,
|
Grid,
|
||||||
@@ -60,38 +59,51 @@ export interface IPhashDistanceValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function criterionIsHierarchicalLabelValue(
|
export function criterionIsHierarchicalLabelValue(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
value: unknown
|
||||||
value: any
|
|
||||||
): value is IHierarchicalLabelValue {
|
): value is IHierarchicalLabelValue {
|
||||||
return typeof value === "object" && "items" in value && "depth" in value;
|
return (
|
||||||
|
typeof value === "object" && !!value && "items" in value && "depth" in value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function criterionIsNumberValue(
|
export function criterionIsNumberValue(value: unknown): value is INumberValue {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
return (
|
||||||
value: any
|
typeof value === "object" &&
|
||||||
): value is INumberValue {
|
!!value &&
|
||||||
return typeof value === "object" && "value" in value && "value2" in value;
|
"value" in value &&
|
||||||
|
"value2" in value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function criterionIsStashIDValue(
|
export function criterionIsStashIDValue(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
value: unknown
|
||||||
value: any
|
|
||||||
): value is IStashIDValue {
|
): value is IStashIDValue {
|
||||||
return typeof value === "object" && "endpoint" in value && "stashID" in value;
|
return (
|
||||||
|
typeof value === "object" &&
|
||||||
|
!!value &&
|
||||||
|
"endpoint" in value &&
|
||||||
|
"stashID" in value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function criterionIsDateValue(
|
export function criterionIsDateValue(value: unknown): value is IDateValue {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
return (
|
||||||
value: any
|
typeof value === "object" &&
|
||||||
): value is IDateValue {
|
!!value &&
|
||||||
return typeof value === "object" && "value" in value && "value2" in value;
|
"value" in value &&
|
||||||
|
"value2" in value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function criterionIsTimestampValue(
|
export function criterionIsTimestampValue(
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
value: unknown
|
||||||
value: any
|
|
||||||
): value is ITimestampValue {
|
): value is ITimestampValue {
|
||||||
return typeof value === "object" && "value" in value && "value2" in value;
|
return (
|
||||||
|
typeof value === "object" &&
|
||||||
|
!!value &&
|
||||||
|
"value" in value &&
|
||||||
|
"value2" in value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IOptionType {
|
export interface IOptionType {
|
||||||
@@ -101,7 +113,6 @@ export interface IOptionType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type CriterionType =
|
export type CriterionType =
|
||||||
| "none"
|
|
||||||
| "path"
|
| "path"
|
||||||
| "rating"
|
| "rating"
|
||||||
| "rating100"
|
| "rating100"
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ const secondsToString = (seconds: number) => {
|
|||||||
|
|
||||||
const stringToSeconds = (v?: string) => {
|
const stringToSeconds = (v?: string) => {
|
||||||
if (!v) {
|
if (!v) {
|
||||||
return 0;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const splits = v.split(":");
|
const splits = v.split(":");
|
||||||
|
|
||||||
if (splits.length > 3) {
|
if (splits.length > 3) {
|
||||||
return 0;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let seconds = 0;
|
let seconds = 0;
|
||||||
@@ -30,12 +30,12 @@ const stringToSeconds = (v?: string) => {
|
|||||||
while (splits.length > 0) {
|
while (splits.length > 0) {
|
||||||
const thisSplit = splits.pop();
|
const thisSplit = splits.pop();
|
||||||
if (thisSplit === undefined) {
|
if (thisSplit === undefined) {
|
||||||
return 0;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const thisInt = parseInt(thisSplit, 10);
|
const thisInt = parseInt(thisSplit, 10);
|
||||||
if (Number.isNaN(thisInt)) {
|
if (Number.isNaN(thisInt)) {
|
||||||
return 0;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds += factor * thisInt;
|
seconds += factor * thisInt;
|
||||||
|
|||||||
@@ -79,29 +79,14 @@ const renderInputGroup = (options: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderDurationInput = (options: {
|
const renderDurationInput = (options: {
|
||||||
value: string | undefined;
|
value: number | undefined;
|
||||||
isEditing: boolean;
|
isEditing: boolean;
|
||||||
url?: string;
|
onChange: (value: number | undefined) => void;
|
||||||
asString?: boolean;
|
|
||||||
onChange: (value: string | undefined) => void;
|
|
||||||
}) => {
|
}) => {
|
||||||
let numericValue: number | undefined;
|
|
||||||
if (options.value) {
|
|
||||||
if (!options.asString) {
|
|
||||||
try {
|
|
||||||
numericValue = Number.parseInt(options.value, 10);
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
numericValue = DurationUtils.stringToSeconds(options.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.isEditing) {
|
if (!options.isEditing) {
|
||||||
let durationString;
|
let durationString;
|
||||||
if (numericValue !== undefined) {
|
if (options.value !== undefined) {
|
||||||
durationString = DurationUtils.secondsToString(numericValue);
|
durationString = DurationUtils.secondsToString(options.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -113,19 +98,11 @@ const renderDurationInput = (options: {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DurationInput
|
<DurationInput
|
||||||
disabled={!options.isEditing}
|
value={options.value}
|
||||||
numericValue={numericValue}
|
setValue={(v) => options.onChange(v)}
|
||||||
onValueChange={(valueAsNumber: number, valueAsString?: string) => {
|
|
||||||
let value = valueAsString;
|
|
||||||
if (!options.asString) {
|
|
||||||
value =
|
|
||||||
valueAsNumber !== undefined ? valueAsNumber.toString() : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.onChange(value);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -86,10 +86,9 @@ const renderInputGroup = (options: {
|
|||||||
const renderDurationInput = (options: {
|
const renderDurationInput = (options: {
|
||||||
title: string;
|
title: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
value: string | undefined;
|
value: number | undefined;
|
||||||
isEditing: boolean;
|
isEditing: boolean;
|
||||||
asString?: boolean;
|
onChange: (value: number | undefined) => void;
|
||||||
onChange: (value: string | undefined) => void;
|
|
||||||
labelProps?: FormLabelProps;
|
labelProps?: FormLabelProps;
|
||||||
inputProps?: ColProps;
|
inputProps?: ColProps;
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@@ -41,10 +41,9 @@ const renderInputGroup = (options: {
|
|||||||
const renderDurationInput = (options: {
|
const renderDurationInput = (options: {
|
||||||
title: string;
|
title: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
value: string | undefined;
|
value: number | undefined;
|
||||||
isEditing: boolean;
|
isEditing: boolean;
|
||||||
asString?: boolean;
|
onChange: (value: number | undefined) => void;
|
||||||
onChange: (value: string | undefined) => void;
|
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user