mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Update prettier to v2.0.1 and enable for SCSS (#420)
This commit is contained in:
@@ -21,6 +21,16 @@
|
|||||||
"warn",
|
"warn",
|
||||||
{ "prefixWithI": "always" }
|
{ "prefixWithI": "always" }
|
||||||
],
|
],
|
||||||
|
"import/extensions": [
|
||||||
|
"error",
|
||||||
|
"ignorePackages",
|
||||||
|
{
|
||||||
|
"js": "never",
|
||||||
|
"jsx": "never",
|
||||||
|
"ts": "never",
|
||||||
|
"tsx": "never"
|
||||||
|
}
|
||||||
|
],
|
||||||
"import/named": "off",
|
"import/named": "off",
|
||||||
"import/namespace": "off",
|
"import/namespace": "off",
|
||||||
"import/default": "off",
|
"import/default": "off",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
"stylelint-order"
|
"stylelint-order"
|
||||||
],
|
],
|
||||||
|
"extends": "stylelint-config-prettier",
|
||||||
"rules": {
|
"rules": {
|
||||||
"indentation": 2,
|
"indentation": 2,
|
||||||
"at-rule-empty-line-before": [ "always", {
|
"at-rule-empty-line-before": [ "always", {
|
||||||
@@ -33,7 +34,6 @@
|
|||||||
"declaration-block-semicolon-space-before": "never",
|
"declaration-block-semicolon-space-before": "never",
|
||||||
"declaration-block-single-line-max-declarations": 1,
|
"declaration-block-single-line-max-declarations": 1,
|
||||||
"declaration-block-trailing-semicolon": "always",
|
"declaration-block-trailing-semicolon": "always",
|
||||||
"declaration-colon-newline-after": "always-multi-line",
|
|
||||||
"declaration-colon-space-after": "always-single-line",
|
"declaration-colon-space-after": "always-single-line",
|
||||||
"declaration-colon-space-before": "never",
|
"declaration-colon-space-before": "never",
|
||||||
"declaration-no-important": true,
|
"declaration-no-important": true,
|
||||||
@@ -61,7 +61,6 @@
|
|||||||
"no-descending-specificity": null,
|
"no-descending-specificity": null,
|
||||||
"no-invalid-double-slash-comments": true,
|
"no-invalid-double-slash-comments": true,
|
||||||
"no-missing-end-of-source-newline": true,
|
"no-missing-end-of-source-newline": true,
|
||||||
"number-leading-zero": "never",
|
|
||||||
"number-max-precision": 2,
|
"number-max-precision": 2,
|
||||||
"number-no-trailing-zeros": true,
|
"number-no-trailing-zeros": true,
|
||||||
"order/order": [
|
"order/order": [
|
||||||
@@ -87,7 +86,6 @@
|
|||||||
"string-quotes": "double",
|
"string-quotes": "double",
|
||||||
"time-min-milliseconds": 100,
|
"time-min-milliseconds": 100,
|
||||||
"unit-blacklist": ["em"],
|
"unit-blacklist": ["em"],
|
||||||
"value-list-comma-newline-after": "always-multi-line",
|
|
||||||
"value-list-comma-space-after": "always-single-line",
|
"value-list-comma-space-after": "always-single-line",
|
||||||
"value-list-comma-space-before": "never",
|
"value-list-comma-space-before": "never",
|
||||||
"value-no-vendor-prefix": true
|
"value-no-vendor-prefix": true
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"lint": "yarn lint:css && yarn lint:js",
|
"lint": "yarn lint:css && yarn lint:js",
|
||||||
"lint:js": "eslint --cache src/**/*.{ts,tsx}",
|
"lint:js": "eslint --cache src/**/*.{ts,tsx}",
|
||||||
"lint:css": "stylelint 'src/**/*.scss'",
|
"lint:css": "stylelint 'src/**/*.scss'",
|
||||||
"format": "prettier --write \"src/**/!(generated-graphql).{js,jsx,ts,tsx}\"",
|
"format": "prettier --write \"src/**/!(generated-graphql).{js,jsx,ts,tsx,scss}\"",
|
||||||
"gqlgen": "gql-gen --config codegen.yml",
|
"gqlgen": "gql-gen --config codegen.yml",
|
||||||
"extract": "NODE_ENV=development extract-messages -l=en,de -o src/locale -d en --flat false 'src/**/!(*.test).tsx'"
|
"extract": "NODE_ENV=development extract-messages -l=en,de -o src/locale -d en --flat false 'src/**/!(*.test).tsx'"
|
||||||
},
|
},
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
"@typescript-eslint/parser": "^2.16.0",
|
"@typescript-eslint/parser": "^2.16.0",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-config-airbnb-typescript": "^6.3.1",
|
"eslint-config-airbnb-typescript": "^6.3.1",
|
||||||
"eslint-config-prettier": "^6.9.0",
|
"eslint-config-prettier": "^6.10.1",
|
||||||
"eslint-plugin-import": "^2.20.0",
|
"eslint-plugin-import": "^2.20.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||||
"eslint-plugin-react": "^7.18.0",
|
"eslint-plugin-react": "^7.18.0",
|
||||||
@@ -88,9 +88,10 @@
|
|||||||
"extract-react-intl-messages": "^2.3.5",
|
"extract-react-intl-messages": "^2.3.5",
|
||||||
"node-sass": "4.13.1",
|
"node-sass": "4.13.1",
|
||||||
"postcss-safe-parser": "^4.0.1",
|
"postcss-safe-parser": "^4.0.1",
|
||||||
"prettier": "1.19.1",
|
"prettier": "2.0.2",
|
||||||
"react-scripts": "^3.3.1",
|
"react-scripts": "^3.3.1",
|
||||||
"stylelint": "^13.0.0",
|
"stylelint": "^13.0.0",
|
||||||
|
"stylelint-config-prettier": "^8.0.1",
|
||||||
"stylelint-order": "^4.0.0",
|
"stylelint-order": "^4.0.0",
|
||||||
"typescript": "^3.7.5"
|
"typescript": "^3.7.5"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export class ErrorBoundary extends React.Component<
|
|||||||
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||||
this.setState({
|
this.setState({
|
||||||
error,
|
error,
|
||||||
errorInfo
|
errorInfo,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { DisplayMode } from "src/models/list-filter/types";
|
|||||||
|
|
||||||
export const GalleryList: React.FC = () => {
|
export const GalleryList: React.FC = () => {
|
||||||
const listData = useGalleriesList({
|
const listData = useGalleriesList({
|
||||||
renderContent
|
renderContent,
|
||||||
});
|
});
|
||||||
|
|
||||||
function renderContent(
|
function renderContent(
|
||||||
@@ -31,7 +31,7 @@ export const GalleryList: React.FC = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{result.data.findGalleries.galleries.map(gallery => (
|
{result.data.findGalleries.galleries.map((gallery) => (
|
||||||
<tr key={gallery.id}>
|
<tr key={gallery.id}>
|
||||||
<td>
|
<td>
|
||||||
<Link to={`/galleries/${gallery.id}`}>
|
<Link to={`/galleries/${gallery.id}`}>
|
||||||
@@ -41,9 +41,7 @@ export const GalleryList: React.FC = () => {
|
|||||||
className="w-100 w-sm-auto"
|
className="w-100 w-sm-auto"
|
||||||
src={`${gallery.files[0].path}?thumb=true`}
|
src={`${gallery.files[0].path}?thumb=true`}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : undefined}
|
||||||
undefined
|
|
||||||
)}
|
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
<td className="d-none d-sm-block">
|
<td className="d-none d-sm-block">
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ export const GalleryViewer: FunctionComponent<IProps> = ({ gallery }) => {
|
|||||||
setCurrentImage(currentImage + 1);
|
setCurrentImage(currentImage + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const photos = gallery.files.map(file => ({
|
const photos = gallery.files.map((file) => ({
|
||||||
src: file.path ?? "",
|
src: file.path ?? "",
|
||||||
caption: file.name ?? ""
|
caption: file.name ?? "",
|
||||||
}));
|
}));
|
||||||
const thumbs = gallery.files.map(file => ({
|
const thumbs = gallery.files.map((file) => ({
|
||||||
src: `${file.path}?thumb=true` || "",
|
src: `${file.path}?thumb=true` || "",
|
||||||
width: 1,
|
width: 1,
|
||||||
height: 1
|
height: 1,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
Criterion,
|
Criterion,
|
||||||
CriterionType,
|
CriterionType,
|
||||||
DurationCriterion,
|
DurationCriterion,
|
||||||
CriterionValue
|
CriterionValue,
|
||||||
} from "src/models/list-filter/criteria/criterion";
|
} from "src/models/list-filter/criteria/criterion";
|
||||||
import { NoneCriterion } from "src/models/list-filter/criteria/none";
|
import { NoneCriterion } from "src/models/list-filter/criteria/none";
|
||||||
import { makeCriteria } from "src/models/list-filter/criteria/utils";
|
import { makeCriteria } from "src/models/list-filter/criteria/utils";
|
||||||
@@ -118,7 +118,7 @@ export const AddFilter: React.FC<IAddFilterProps> = (
|
|||||||
onChange={onChangedModifierSelect}
|
onChange={onChangedModifierSelect}
|
||||||
value={criterion.modifier}
|
value={criterion.modifier}
|
||||||
>
|
>
|
||||||
{criterion.modifierOptions.map(c => (
|
{criterion.modifierOptions.map((c) => (
|
||||||
<option key={c.value} value={c.value}>
|
<option key={c.value} value={c.value}>
|
||||||
{c.label}
|
{c.label}
|
||||||
</option>
|
</option>
|
||||||
@@ -149,15 +149,15 @@ export const AddFilter: React.FC<IAddFilterProps> = (
|
|||||||
<FilterSelect
|
<FilterSelect
|
||||||
type={criterion.type}
|
type={criterion.type}
|
||||||
isMulti
|
isMulti
|
||||||
onSelect={items => {
|
onSelect={(items) => {
|
||||||
const newCriterion = _.cloneDeep(criterion);
|
const newCriterion = _.cloneDeep(criterion);
|
||||||
newCriterion.value = items.map(i => ({
|
newCriterion.value = items.map((i) => ({
|
||||||
id: i.id,
|
id: i.id,
|
||||||
label: i.name!
|
label: i.name!,
|
||||||
}));
|
}));
|
||||||
setCriterion(newCriterion);
|
setCriterion(newCriterion);
|
||||||
}}
|
}}
|
||||||
ids={criterion.value.map(labeled => labeled.id)}
|
ids={criterion.value.map((labeled) => labeled.id)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ export const AddFilter: React.FC<IAddFilterProps> = (
|
|||||||
onChange={onChangedSingleSelect}
|
onChange={onChangedSingleSelect}
|
||||||
value={criterion.value.toString()}
|
value={criterion.value.toString()}
|
||||||
>
|
>
|
||||||
{criterion.options.map(c => (
|
{criterion.options.map((c) => (
|
||||||
<option key={c.toString()} value={c.toString()}>
|
<option key={c.toString()} value={c.toString()}>
|
||||||
{c}
|
{c}
|
||||||
</option>
|
</option>
|
||||||
@@ -215,7 +215,7 @@ export const AddFilter: React.FC<IAddFilterProps> = (
|
|||||||
onChange={onChangedCriteriaType}
|
onChange={onChangedCriteriaType}
|
||||||
value={criterion.type}
|
value={criterion.type}
|
||||||
>
|
>
|
||||||
{props.filter.criterionOptions.map(c => (
|
{props.filter.criterionOptions.map((c) => (
|
||||||
<option key={c.value} value={c.value}>
|
<option key={c.value} value={c.value}>
|
||||||
{c.label}
|
{c.label}
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
Form,
|
Form,
|
||||||
OverlayTrigger,
|
OverlayTrigger,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
SafeAnchor
|
SafeAnchor,
|
||||||
} from "react-bootstrap";
|
} from "react-bootstrap";
|
||||||
|
|
||||||
import { Icon } from "src/components/Shared";
|
import { Icon } from "src/components/Shared";
|
||||||
@@ -106,7 +106,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderSortByOptions() {
|
function renderSortByOptions() {
|
||||||
return props.filter.sortByOptions.map(option => (
|
return props.filter.sortByOptions.map((option) => (
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
onClick={onChangeSortBy}
|
onClick={onChangeSortBy}
|
||||||
key={option}
|
key={option}
|
||||||
@@ -138,7 +138,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
return "Wall";
|
return "Wall";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return props.filter.displayModeOptions.map(option => (
|
return props.filter.displayModeOptions.map((option) => (
|
||||||
<OverlayTrigger
|
<OverlayTrigger
|
||||||
key={option}
|
key={option}
|
||||||
overlay={
|
overlay={
|
||||||
@@ -157,7 +157,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderFilterTags() {
|
function renderFilterTags() {
|
||||||
return props.filter.criteria.map(criterion => (
|
return props.filter.criteria.map((criterion) => (
|
||||||
<Badge
|
<Badge
|
||||||
className="tag-item"
|
className="tag-item"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@@ -219,7 +219,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
const options = [renderSelectAll(), renderSelectNone()];
|
const options = [renderSelectAll(), renderSelectNone()];
|
||||||
|
|
||||||
if (props.otherOperations) {
|
if (props.otherOperations) {
|
||||||
props.otherOperations.forEach(o => {
|
props.otherOperations.forEach((o) => {
|
||||||
options.push(
|
options.push(
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
key={o.text}
|
key={o.text}
|
||||||
@@ -285,7 +285,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
value={props.filter.itemsPerPage.toString()}
|
value={props.filter.itemsPerPage.toString()}
|
||||||
className="btn-secondary filter-item col-1 d-none d-sm-inline"
|
className="btn-secondary filter-item col-1 d-none d-sm-inline"
|
||||||
>
|
>
|
||||||
{PAGE_SIZE_OPTIONS.map(s => (
|
{PAGE_SIZE_OPTIONS.map((s) => (
|
||||||
<option value={s} key={s}>
|
<option value={s} key={s}>
|
||||||
{s}
|
{s}
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const Pagination: React.FC<IPaginationProps> = ({
|
|||||||
itemsPerPage,
|
itemsPerPage,
|
||||||
currentPage,
|
currentPage,
|
||||||
totalItems,
|
totalItems,
|
||||||
onChangePage
|
onChangePage,
|
||||||
}) => {
|
}) => {
|
||||||
const totalPages = Math.ceil(totalItems / itemsPerPage);
|
const totalPages = Math.ceil(totalItems / itemsPerPage);
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ export const Pagination: React.FC<IPaginationProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const pages = [...Array(endPage + 1 - startPage).keys()].map(
|
const pages = [...Array(endPage + 1 - startPage).keys()].map(
|
||||||
i => startPage + i
|
(i) => startPage + i
|
||||||
);
|
);
|
||||||
|
|
||||||
const calculatePageClass = (buttonPage: number) => {
|
const calculatePageClass = (buttonPage: number) => {
|
||||||
|
|||||||
@@ -17,38 +17,38 @@ const menuItems: IMenuItem[] = [
|
|||||||
{
|
{
|
||||||
icon: "play-circle",
|
icon: "play-circle",
|
||||||
messageID: "scenes",
|
messageID: "scenes",
|
||||||
href: "/scenes"
|
href: "/scenes",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/movies",
|
href: "/movies",
|
||||||
icon: "film",
|
icon: "film",
|
||||||
messageID: "movies"
|
messageID: "movies",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/scenes/markers",
|
href: "/scenes/markers",
|
||||||
icon: "map-marker-alt",
|
icon: "map-marker-alt",
|
||||||
messageID: "markers"
|
messageID: "markers",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/galleries",
|
href: "/galleries",
|
||||||
icon: "image",
|
icon: "image",
|
||||||
messageID: "galleries"
|
messageID: "galleries",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/performers",
|
href: "/performers",
|
||||||
icon: "user",
|
icon: "user",
|
||||||
messageID: "performers"
|
messageID: "performers",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/studios",
|
href: "/studios",
|
||||||
icon: "video",
|
icon: "video",
|
||||||
messageID: "studios"
|
messageID: "studios",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/tags",
|
href: "/tags",
|
||||||
icon: "tag",
|
icon: "tag",
|
||||||
messageID: "tags"
|
messageID: "tags",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const MainNavbar: React.FC = () => {
|
export const MainNavbar: React.FC = () => {
|
||||||
@@ -127,7 +127,7 @@ export const MainNavbar: React.FC = () => {
|
|||||||
<Navbar.Toggle className="order-0" />
|
<Navbar.Toggle className="order-0" />
|
||||||
<Navbar.Collapse className="order-3 order-md-1">
|
<Navbar.Collapse className="order-3 order-md-1">
|
||||||
<Nav className="mr-md-auto">
|
<Nav className="mr-md-auto">
|
||||||
{menuItems.map(i => (
|
{menuItems.map((i) => (
|
||||||
<Nav.Link eventKey={i.href} as="div" key={i.href}>
|
<Nav.Link eventKey={i.href} as="div" key={i.href}>
|
||||||
<LinkContainer
|
<LinkContainer
|
||||||
activeClassName="active"
|
activeClassName="active"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import cx from "classnames";
|
|||||||
import {
|
import {
|
||||||
DetailsEditNavbar,
|
DetailsEditNavbar,
|
||||||
LoadingIndicator,
|
LoadingIndicator,
|
||||||
Modal
|
Modal,
|
||||||
} from "src/components/Shared";
|
} from "src/components/Shared";
|
||||||
import { useToast } from "src/hooks";
|
import { useToast } from "src/hooks";
|
||||||
import { Table, Form } from "react-bootstrap";
|
import { Table, Form } from "react-bootstrap";
|
||||||
@@ -117,7 +117,7 @@ export const Movie: React.FC = () => {
|
|||||||
synopsis,
|
synopsis,
|
||||||
url,
|
url,
|
||||||
front_image: frontImage,
|
front_image: frontImage,
|
||||||
back_image: backImage
|
back_image: backImage,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isNew) {
|
if (!isNew) {
|
||||||
@@ -183,7 +183,7 @@ export const Movie: React.FC = () => {
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<div
|
<div
|
||||||
className={cx("movie-details", "col", {
|
className={cx("movie-details", "col", {
|
||||||
"col ml-sm-5": !isNew
|
"col ml-sm-5": !isNew,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{isNew && <h2>Add Movie</h2>}
|
{isNew && <h2>Add Movie</h2>}
|
||||||
@@ -198,38 +198,38 @@ export const Movie: React.FC = () => {
|
|||||||
title: "Name",
|
title: "Name",
|
||||||
value: movie.name ?? "",
|
value: movie.name ?? "",
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setName
|
onChange: setName,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Aliases",
|
title: "Aliases",
|
||||||
value: aliases,
|
value: aliases,
|
||||||
isEditing,
|
isEditing,
|
||||||
onChange: setAliases
|
onChange: setAliases,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Duration",
|
title: "Duration",
|
||||||
value: duration,
|
value: duration,
|
||||||
isEditing,
|
isEditing,
|
||||||
onChange: setDuration
|
onChange: setDuration,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Date (YYYY-MM-DD)",
|
title: "Date (YYYY-MM-DD)",
|
||||||
value: date,
|
value: date,
|
||||||
isEditing,
|
isEditing,
|
||||||
onChange: setDate
|
onChange: setDate,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Director",
|
title: "Director",
|
||||||
value: director,
|
value: director,
|
||||||
isEditing,
|
isEditing,
|
||||||
onChange: setDirector
|
onChange: setDirector,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderHtmlSelect({
|
{TableUtils.renderHtmlSelect({
|
||||||
title: "Rating",
|
title: "Rating",
|
||||||
value: rating,
|
value: rating,
|
||||||
isEditing,
|
isEditing,
|
||||||
onChange: (value: string) => setRating(value),
|
onChange: (value: string) => setRating(value),
|
||||||
selectOptions: ["", "1", "2", "3", "4", "5"]
|
selectOptions: ["", "1", "2", "3", "4", "5"],
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const MovieScenesPanel: React.FC<IMovieScenesPanel> = ({ movie }) => {
|
|||||||
function filterHook(filter: ListFilterModel) {
|
function filterHook(filter: ListFilterModel) {
|
||||||
const movieValue = { id: movie.id!, label: movie.name! };
|
const movieValue = { id: movie.id!, label: movie.name! };
|
||||||
// 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.type === "movies";
|
return c.type === "movies";
|
||||||
}) as MoviesCriterion;
|
}) as MoviesCriterion;
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ export const MovieScenesPanel: React.FC<IMovieScenesPanel> = ({ movie }) => {
|
|||||||
) {
|
) {
|
||||||
// add the movie if not present
|
// add the movie if not present
|
||||||
if (
|
if (
|
||||||
!movieCriterion.value.find(p => {
|
!movieCriterion.value.find((p) => {
|
||||||
return p.id === movie.id;
|
return p.id === movie.id;
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { MovieCard } from "./MovieCard";
|
|||||||
|
|
||||||
export const MovieList: React.FC = () => {
|
export const MovieList: React.FC = () => {
|
||||||
const listData = useMoviesList({
|
const listData = useMoviesList({
|
||||||
renderContent
|
renderContent,
|
||||||
});
|
});
|
||||||
|
|
||||||
function renderContent(
|
function renderContent(
|
||||||
@@ -20,7 +20,7 @@ export const MovieList: React.FC = () => {
|
|||||||
if (filter.displayMode === DisplayMode.Grid) {
|
if (filter.displayMode === DisplayMode.Grid) {
|
||||||
return (
|
return (
|
||||||
<div className="row justify-content-center">
|
<div className="row justify-content-center">
|
||||||
{result.data.findMovies.movies.map(p => (
|
{result.data.findMovies.movies.map((p) => (
|
||||||
<MovieCard key={p.id} movie={p} />
|
<MovieCard key={p.id} movie={p} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ interface IPerformerCardProps {
|
|||||||
|
|
||||||
export const PerformerCard: React.FC<IPerformerCardProps> = ({
|
export const PerformerCard: React.FC<IPerformerCardProps> = ({
|
||||||
performer,
|
performer,
|
||||||
ageFromDate
|
ageFromDate,
|
||||||
}) => {
|
}) => {
|
||||||
const age = TextUtils.age(performer.birthdate, ageFromDate);
|
const age = TextUtils.age(performer.birthdate, ageFromDate);
|
||||||
const ageString = `${age} years old${ageFromDate ? " in this scene." : "."}`;
|
const ageString = `${age} years old${ageFromDate ? " in this scene." : "."}`;
|
||||||
|
|||||||
@@ -62,13 +62,13 @@ export const Performer: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
if (!isNew) {
|
if (!isNew) {
|
||||||
const result = await updatePerformer({
|
const result = await updatePerformer({
|
||||||
variables: performerInput as GQL.PerformerUpdateInput
|
variables: performerInput as GQL.PerformerUpdateInput,
|
||||||
});
|
});
|
||||||
if (result.data?.performerUpdate)
|
if (result.data?.performerUpdate)
|
||||||
setPerformer(result.data?.performerUpdate);
|
setPerformer(result.data?.performerUpdate);
|
||||||
} else {
|
} else {
|
||||||
const result = await createPerformer({
|
const result = await createPerformer({
|
||||||
variables: performerInput as GQL.PerformerCreateInput
|
variables: performerInput as GQL.PerformerCreateInput,
|
||||||
});
|
});
|
||||||
if (result.data?.performerCreate) {
|
if (result.data?.performerCreate) {
|
||||||
setPerformer(result.data.performerCreate);
|
setPerformer(result.data.performerCreate);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
Modal,
|
Modal,
|
||||||
ImageInput,
|
ImageInput,
|
||||||
ScrapePerformerSuggest,
|
ScrapePerformerSuggest,
|
||||||
LoadingIndicator
|
LoadingIndicator,
|
||||||
} from "src/components/Shared";
|
} from "src/components/Shared";
|
||||||
import { ImageUtils, TableUtils } from "src/utils";
|
import { ImageUtils, TableUtils } from "src/utils";
|
||||||
import { useToast } from "src/hooks";
|
import { useToast } from "src/hooks";
|
||||||
@@ -33,7 +33,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
isEditing,
|
isEditing,
|
||||||
onSave,
|
onSave,
|
||||||
onDelete,
|
onDelete,
|
||||||
onImageChange
|
onImageChange,
|
||||||
}) => {
|
}) => {
|
||||||
const Toast = useToast();
|
const Toast = useToast();
|
||||||
|
|
||||||
@@ -93,7 +93,11 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
setUrl(state.url ?? undefined);
|
setUrl(state.url ?? undefined);
|
||||||
setTwitter(state.twitter ?? undefined);
|
setTwitter(state.twitter ?? undefined);
|
||||||
setInstagram(state.instagram ?? undefined);
|
setInstagram(state.instagram ?? undefined);
|
||||||
setGender(StashService.genderToString((state as GQL.PerformerDataFragment).gender ?? undefined));
|
setGender(
|
||||||
|
StashService.genderToString(
|
||||||
|
(state as GQL.PerformerDataFragment).gender ?? undefined
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePerformerEditStateFromScraper(
|
function updatePerformerEditStateFromScraper(
|
||||||
@@ -128,7 +132,9 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newQueryableScrapers = (
|
const newQueryableScrapers = (
|
||||||
Scrapers?.data?.listPerformerScrapers ?? []
|
Scrapers?.data?.listPerformerScrapers ?? []
|
||||||
).filter(s => s.performer?.supported_scrapes.includes(GQL.ScrapeType.Name));
|
).filter((s) =>
|
||||||
|
s.performer?.supported_scrapes.includes(GQL.ScrapeType.Name)
|
||||||
|
);
|
||||||
|
|
||||||
setQueryableScrapers(newQueryableScrapers);
|
setQueryableScrapers(newQueryableScrapers);
|
||||||
}, [Scrapers]);
|
}, [Scrapers]);
|
||||||
@@ -156,7 +162,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
twitter,
|
twitter,
|
||||||
instagram,
|
instagram,
|
||||||
image,
|
image,
|
||||||
gender: StashService.stringToGender(gender)
|
gender: StashService.stringToGender(gender),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isNew) {
|
if (!isNew) {
|
||||||
@@ -226,7 +232,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
value: ethnicity,
|
value: ethnicity,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
placeholder: "Ethnicity",
|
placeholder: "Ethnicity",
|
||||||
onChange: setEthnicity
|
onChange: setEthnicity,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +246,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
<Popover.Content>
|
<Popover.Content>
|
||||||
<div>
|
<div>
|
||||||
{queryableScrapers
|
{queryableScrapers
|
||||||
? queryableScrapers.map(s => (
|
? queryableScrapers.map((s) => (
|
||||||
<div key={s.name}>
|
<div key={s.name}>
|
||||||
<Button
|
<Button
|
||||||
key={s.name}
|
key={s.name}
|
||||||
@@ -278,7 +284,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
scraperId={
|
scraperId={
|
||||||
isDisplayingScraperDialog ? isDisplayingScraperDialog.id : ""
|
isDisplayingScraperDialog ? isDisplayingScraperDialog.id : ""
|
||||||
}
|
}
|
||||||
onSelectPerformer={query => setScrapePerformerDetails(query)}
|
onSelectPerformer={(query) => setScrapePerformerDetails(query)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
@@ -288,8 +294,8 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
function urlScrapable(scrapedUrl: string) {
|
function urlScrapable(scrapedUrl: string) {
|
||||||
return (
|
return (
|
||||||
!!scrapedUrl &&
|
!!scrapedUrl &&
|
||||||
(Scrapers?.data?.listPerformerScrapers ?? []).some(s =>
|
(Scrapers?.data?.listPerformerScrapers ?? []).some((s) =>
|
||||||
(s?.performer?.urls ?? []).some(u => scrapedUrl.includes(u))
|
(s?.performer?.urls ?? []).some((u) => scrapedUrl.includes(u))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -383,7 +389,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
value: name,
|
value: name,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
placeholder: "Name",
|
placeholder: "Name",
|
||||||
onChange: setName
|
onChange: setName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,7 +401,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
value: aliases,
|
value: aliases,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
placeholder: "Aliases",
|
placeholder: "Aliases",
|
||||||
onChange: setAliases
|
onChange: setAliases,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -424,69 +430,69 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
title: "Birthdate",
|
title: "Birthdate",
|
||||||
value: birthdate,
|
value: birthdate,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setBirthdate
|
onChange: setBirthdate,
|
||||||
})}
|
})}
|
||||||
{renderEthnicity()}
|
{renderEthnicity()}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Eye Color",
|
title: "Eye Color",
|
||||||
value: eyeColor,
|
value: eyeColor,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setEyeColor
|
onChange: setEyeColor,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Country",
|
title: "Country",
|
||||||
value: country,
|
value: country,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setCountry
|
onChange: setCountry,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Height (cm)",
|
title: "Height (cm)",
|
||||||
value: height,
|
value: height,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setHeight
|
onChange: setHeight,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Measurements",
|
title: "Measurements",
|
||||||
value: measurements,
|
value: measurements,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setMeasurements
|
onChange: setMeasurements,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Fake Tits",
|
title: "Fake Tits",
|
||||||
value: fakeTits,
|
value: fakeTits,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setFakeTits
|
onChange: setFakeTits,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Career Length",
|
title: "Career Length",
|
||||||
value: careerLength,
|
value: careerLength,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setCareerLength
|
onChange: setCareerLength,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Tattoos",
|
title: "Tattoos",
|
||||||
value: tattoos,
|
value: tattoos,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setTattoos
|
onChange: setTattoos,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Piercings",
|
title: "Piercings",
|
||||||
value: piercings,
|
value: piercings,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setPiercings
|
onChange: setPiercings,
|
||||||
})}
|
})}
|
||||||
{renderURLField()}
|
{renderURLField()}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Twitter",
|
title: "Twitter",
|
||||||
value: twitter,
|
value: twitter,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setTwitter
|
onChange: setTwitter,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Instagram",
|
title: "Instagram",
|
||||||
value: instagram,
|
value: instagram,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setInstagram
|
onChange: setInstagram,
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ interface IPerformerOperationsProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PerformerOperationsPanel: React.FC<IPerformerOperationsProps> = ({
|
export const PerformerOperationsPanel: React.FC<IPerformerOperationsProps> = ({
|
||||||
performer
|
performer,
|
||||||
}) => {
|
}) => {
|
||||||
const Toast = useToast();
|
const Toast = useToast();
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ interface IPerformerDetailsProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PerformerScenesPanel: React.FC<IPerformerDetailsProps> = ({
|
export const PerformerScenesPanel: React.FC<IPerformerDetailsProps> = ({
|
||||||
performer
|
performer,
|
||||||
}) => {
|
}) => {
|
||||||
function filterHook(filter: ListFilterModel) {
|
function filterHook(filter: ListFilterModel) {
|
||||||
const performerValue = { id: performer.id!, label: performer.name! };
|
const performerValue = { id: performer.id!, label: performer.name! };
|
||||||
// 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.type === "performers";
|
return c.type === "performers";
|
||||||
}) as PerformersCriterion;
|
}) as PerformersCriterion;
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export const PerformerScenesPanel: React.FC<IPerformerDetailsProps> = ({
|
|||||||
) {
|
) {
|
||||||
// add the performer if not present
|
// add the performer if not present
|
||||||
if (
|
if (
|
||||||
!performerCriterion.value.find(p => {
|
!performerCriterion.value.find((p) => {
|
||||||
return p.id === performer.id;
|
return p.id === performer.id;
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ export const PerformerList: React.FC = () => {
|
|||||||
const otherOperations = [
|
const otherOperations = [
|
||||||
{
|
{
|
||||||
text: "Open Random",
|
text: "Open Random",
|
||||||
onClick: getRandom
|
onClick: getRandom,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const listData = usePerformersList({
|
const listData = usePerformersList({
|
||||||
otherOperations,
|
otherOperations,
|
||||||
renderContent
|
renderContent,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getRandom(
|
async function getRandom(
|
||||||
@@ -56,7 +56,7 @@ export const PerformerList: React.FC = () => {
|
|||||||
if (filter.displayMode === DisplayMode.Grid) {
|
if (filter.displayMode === DisplayMode.Grid) {
|
||||||
return (
|
return (
|
||||||
<div className="row justify-content-center">
|
<div className="row justify-content-center">
|
||||||
{result.data.findPerformers.performers.map(p => (
|
{result.data.findPerformers.performers.map((p) => (
|
||||||
<PerformerCard key={p.id} performer={p} />
|
<PerformerCard key={p.id} performer={p} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.scrape-url-button {
|
.scrape-url-button {
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: .5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
|
||||||
.not-favorite {
|
.not-favorite {
|
||||||
color: rgba(191, 204, 214, .5);
|
color: rgba(191, 204, 214, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.favorite {
|
.favorite {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export class ParserField {
|
|||||||
ParserField.DDMMYYYY,
|
ParserField.DDMMYYYY,
|
||||||
ParserField.DDMMYY,
|
ParserField.DDMMYY,
|
||||||
ParserField.MMDDYYYY,
|
ParserField.MMDDYYYY,
|
||||||
ParserField.MMDDYY
|
ParserField.MMDDYY,
|
||||||
];
|
];
|
||||||
|
|
||||||
static fullDateFields = [
|
static fullDateFields = [
|
||||||
@@ -61,6 +61,6 @@ export class ParserField {
|
|||||||
ParserField.DDMMYYYY,
|
ParserField.DDMMYYYY,
|
||||||
ParserField.DDMMYY,
|
ParserField.DDMMYY,
|
||||||
ParserField.MMDDYYYY,
|
ParserField.MMDDYYYY,
|
||||||
ParserField.MMDDYY
|
ParserField.MMDDYY,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
Dropdown,
|
Dropdown,
|
||||||
DropdownButton,
|
DropdownButton,
|
||||||
Form,
|
Form,
|
||||||
InputGroup
|
InputGroup,
|
||||||
} from "react-bootstrap";
|
} from "react-bootstrap";
|
||||||
import { ParserField } from "./ParserField";
|
import { ParserField } from "./ParserField";
|
||||||
import { ShowFields } from "./ShowFields";
|
import { ShowFields } from "./ShowFields";
|
||||||
@@ -15,43 +15,43 @@ const builtInRecipes = [
|
|||||||
ignoreWords: [],
|
ignoreWords: [],
|
||||||
whitespaceCharacters: "",
|
whitespaceCharacters: "",
|
||||||
capitalizeTitle: false,
|
capitalizeTitle: false,
|
||||||
description: "Filename"
|
description: "Filename",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "{title}.{ext}",
|
pattern: "{title}.{ext}",
|
||||||
ignoreWords: [],
|
ignoreWords: [],
|
||||||
whitespaceCharacters: "",
|
whitespaceCharacters: "",
|
||||||
capitalizeTitle: false,
|
capitalizeTitle: false,
|
||||||
description: "Without extension"
|
description: "Without extension",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "{}.{yy}.{mm}.{dd}.{title}.XXX.{}.{ext}",
|
pattern: "{}.{yy}.{mm}.{dd}.{title}.XXX.{}.{ext}",
|
||||||
ignoreWords: [],
|
ignoreWords: [],
|
||||||
whitespaceCharacters: ".",
|
whitespaceCharacters: ".",
|
||||||
capitalizeTitle: true,
|
capitalizeTitle: true,
|
||||||
description: ""
|
description: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "{}.{yy}.{mm}.{dd}.{title}.{ext}",
|
pattern: "{}.{yy}.{mm}.{dd}.{title}.{ext}",
|
||||||
ignoreWords: [],
|
ignoreWords: [],
|
||||||
whitespaceCharacters: ".",
|
whitespaceCharacters: ".",
|
||||||
capitalizeTitle: true,
|
capitalizeTitle: true,
|
||||||
description: ""
|
description: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "{title}.XXX.{}.{ext}",
|
pattern: "{title}.XXX.{}.{ext}",
|
||||||
ignoreWords: [],
|
ignoreWords: [],
|
||||||
whitespaceCharacters: ".",
|
whitespaceCharacters: ".",
|
||||||
capitalizeTitle: true,
|
capitalizeTitle: true,
|
||||||
description: ""
|
description: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: "{}.{yy}.{mm}.{dd}.{title}.{i}.{ext}",
|
pattern: "{}.{yy}.{mm}.{dd}.{title}.{i}.{ext}",
|
||||||
ignoreWords: ["cz", "fr"],
|
ignoreWords: ["cz", "fr"],
|
||||||
whitespaceCharacters: ".",
|
whitespaceCharacters: ".",
|
||||||
capitalizeTitle: true,
|
capitalizeTitle: true,
|
||||||
description: "Foreign language"
|
description: "Foreign language",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface IParserInput {
|
export interface IParserInput {
|
||||||
@@ -102,7 +102,7 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
capitalizeTitle,
|
capitalizeTitle,
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: props.input.pageSize,
|
pageSize: props.input.pageSize,
|
||||||
findClicked: props.input.findClicked
|
findClicked: props.input.findClicked,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
/>
|
/>
|
||||||
<InputGroup.Append>
|
<InputGroup.Append>
|
||||||
<DropdownButton id="parser-field-select" title="Add Field">
|
<DropdownButton id="parser-field-select" title="Add Field">
|
||||||
{validFields.map(item => (
|
{validFields.map((item) => (
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
key={item.field}
|
key={item.field}
|
||||||
onSelect={() => addParserField(item)}
|
onSelect={() => addParserField(item)}
|
||||||
@@ -207,7 +207,7 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
id="recipe-select"
|
id="recipe-select"
|
||||||
title="Select Parser Recipe"
|
title="Select Parser Recipe"
|
||||||
>
|
>
|
||||||
{builtInRecipes.map(item => (
|
{builtInRecipes.map((item) => (
|
||||||
<Dropdown.Item
|
<Dropdown.Item
|
||||||
key={item.pattern}
|
key={item.pattern}
|
||||||
onSelect={() => setParserRecipe(item)}
|
onSelect={() => setParserRecipe(item)}
|
||||||
@@ -222,7 +222,7 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
<Form.Group>
|
<Form.Group>
|
||||||
<ShowFields
|
<ShowFields
|
||||||
fields={props.showFields}
|
fields={props.showFields}
|
||||||
onShowFieldsChanged={fields => props.setShowFields(fields)}
|
onShowFieldsChanged={(fields) => props.setShowFields(fields)}
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
defaultValue={props.input.pageSize}
|
defaultValue={props.input.pageSize}
|
||||||
className="col-1 filter-item"
|
className="col-1 filter-item"
|
||||||
>
|
>
|
||||||
{PAGE_SIZE_OPTIONS.map(val => (
|
{PAGE_SIZE_OPTIONS.map((val) => (
|
||||||
<option key={val} value={val}>
|
<option key={val} value={val}>
|
||||||
{val}
|
{val}
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const initialParserInput = {
|
|||||||
capitalizeTitle: true,
|
capitalizeTitle: true,
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
findClicked: false
|
findClicked: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialShowFieldsState = new Map<string, boolean>([
|
const initialShowFieldsState = new Map<string, boolean>([
|
||||||
@@ -27,7 +27,7 @@ const initialShowFieldsState = new Map<string, boolean>([
|
|||||||
["Date", true],
|
["Date", true],
|
||||||
["Performers", true],
|
["Performers", true],
|
||||||
["Tags", true],
|
["Tags", true],
|
||||||
["Studio", true]
|
["Studio", true],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const SceneFilenameParser: React.FC = () => {
|
export const SceneFilenameParser: React.FC = () => {
|
||||||
@@ -60,7 +60,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
const dateSet =
|
const dateSet =
|
||||||
pattern.includes("{date}") ||
|
pattern.includes("{date}") ||
|
||||||
pattern.includes("{dd}") || // don't worry about other partial date fields since this should be implied
|
pattern.includes("{dd}") || // don't worry about other partial date fields since this should be implied
|
||||||
ParserField.fullDateFields.some(f => {
|
ParserField.fullDateFields.some((f) => {
|
||||||
return pattern.includes(`{${f.field}}`);
|
return pattern.includes(`{${f.field}}`);
|
||||||
});
|
});
|
||||||
const performerSet = pattern.includes("{performer}");
|
const performerSet = pattern.includes("{performer}");
|
||||||
@@ -72,7 +72,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
["Date", dateSet],
|
["Date", dateSet],
|
||||||
["Performers", performerSet],
|
["Performers", performerSet],
|
||||||
["Tags", tagSet],
|
["Tags", tagSet],
|
||||||
["Studio", studioSet]
|
["Studio", studioSet],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setShowFields(newShowFields);
|
setShowFields(newShowFields);
|
||||||
@@ -84,10 +84,10 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
) => {
|
) => {
|
||||||
if (results) {
|
if (results) {
|
||||||
const result = results
|
const result = results
|
||||||
.map(r => {
|
.map((r) => {
|
||||||
return new SceneParserResult(r);
|
return new SceneParserResult(r);
|
||||||
})
|
})
|
||||||
.filter(r => !!r) as SceneParserResult[];
|
.filter((r) => !!r) as SceneParserResult[];
|
||||||
|
|
||||||
setParserResult(result);
|
setParserResult(result);
|
||||||
determineFieldsToHide();
|
determineFieldsToHide();
|
||||||
@@ -106,24 +106,24 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
page: parserInput.page,
|
page: parserInput.page,
|
||||||
per_page: parserInput.pageSize,
|
per_page: parserInput.pageSize,
|
||||||
sort: "path",
|
sort: "path",
|
||||||
direction: GQL.SortDirectionEnum.Asc
|
direction: GQL.SortDirectionEnum.Asc,
|
||||||
};
|
};
|
||||||
|
|
||||||
const parserInputData = {
|
const parserInputData = {
|
||||||
ignoreWords: parserInput.ignoreWords,
|
ignoreWords: parserInput.ignoreWords,
|
||||||
whitespaceCharacters: parserInput.whitespaceCharacters,
|
whitespaceCharacters: parserInput.whitespaceCharacters,
|
||||||
capitalizeTitle: parserInput.capitalizeTitle
|
capitalizeTitle: parserInput.capitalizeTitle,
|
||||||
};
|
};
|
||||||
|
|
||||||
StashService.queryParseSceneFilenames(parserFilter, parserInputData)
|
StashService.queryParseSceneFilenames(parserFilter, parserInputData)
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
const result = response.data.parseSceneFilenames;
|
const result = response.data.parseSceneFilenames;
|
||||||
if (result) {
|
if (result) {
|
||||||
parseResults(result.results);
|
parseResults(result.results);
|
||||||
setTotalItems(result.count);
|
setTotalItems(result.count);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => Toast.error(err))
|
.catch((err) => Toast.error(err))
|
||||||
.finally(() => setIsLoading(false));
|
.finally(() => setIsLoading(false));
|
||||||
}
|
}
|
||||||
}, [parserInput, parseResults, Toast]);
|
}, [parserInput, parseResults, Toast]);
|
||||||
@@ -152,8 +152,8 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
|
|
||||||
function getScenesUpdateData() {
|
function getScenesUpdateData() {
|
||||||
return parserResult
|
return parserResult
|
||||||
.filter(result => result.isChanged())
|
.filter((result) => result.isChanged())
|
||||||
.map(result => result.toSceneUpdateInput());
|
.map((result) => result.toSceneUpdateInput());
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onApply() {
|
async function onApply() {
|
||||||
@@ -170,19 +170,19 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newAllTitleSet = !parserResult.some(r => {
|
const newAllTitleSet = !parserResult.some((r) => {
|
||||||
return !r.title.isSet;
|
return !r.title.isSet;
|
||||||
});
|
});
|
||||||
const newAllDateSet = !parserResult.some(r => {
|
const newAllDateSet = !parserResult.some((r) => {
|
||||||
return !r.date.isSet;
|
return !r.date.isSet;
|
||||||
});
|
});
|
||||||
const newAllPerformerSet = !parserResult.some(r => {
|
const newAllPerformerSet = !parserResult.some((r) => {
|
||||||
return !r.performers.isSet;
|
return !r.performers.isSet;
|
||||||
});
|
});
|
||||||
const newAllTagSet = !parserResult.some(r => {
|
const newAllTagSet = !parserResult.some((r) => {
|
||||||
return !r.tags.isSet;
|
return !r.tags.isSet;
|
||||||
});
|
});
|
||||||
const newAllStudioSet = !parserResult.some(r => {
|
const newAllStudioSet = !parserResult.some((r) => {
|
||||||
return !r.studio.isSet;
|
return !r.studio.isSet;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
function onSelectAllTitleSet(selected: boolean) {
|
function onSelectAllTitleSet(selected: boolean) {
|
||||||
const newResult = [...parserResult];
|
const newResult = [...parserResult];
|
||||||
|
|
||||||
newResult.forEach(r => {
|
newResult.forEach((r) => {
|
||||||
r.title.isSet = selected;
|
r.title.isSet = selected;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
function onSelectAllDateSet(selected: boolean) {
|
function onSelectAllDateSet(selected: boolean) {
|
||||||
const newResult = [...parserResult];
|
const newResult = [...parserResult];
|
||||||
|
|
||||||
newResult.forEach(r => {
|
newResult.forEach((r) => {
|
||||||
r.date.isSet = selected;
|
r.date.isSet = selected;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
function onSelectAllPerformerSet(selected: boolean) {
|
function onSelectAllPerformerSet(selected: boolean) {
|
||||||
const newResult = [...parserResult];
|
const newResult = [...parserResult];
|
||||||
|
|
||||||
newResult.forEach(r => {
|
newResult.forEach((r) => {
|
||||||
r.performers.isSet = selected;
|
r.performers.isSet = selected;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
function onSelectAllTagSet(selected: boolean) {
|
function onSelectAllTagSet(selected: boolean) {
|
||||||
const newResult = [...parserResult];
|
const newResult = [...parserResult];
|
||||||
|
|
||||||
newResult.forEach(r => {
|
newResult.forEach((r) => {
|
||||||
r.tags.isSet = selected;
|
r.tags.isSet = selected;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
function onSelectAllStudioSet(selected: boolean) {
|
function onSelectAllStudioSet(selected: boolean) {
|
||||||
const newResult = [...parserResult];
|
const newResult = [...parserResult];
|
||||||
|
|
||||||
newResult.forEach(r => {
|
newResult.forEach((r) => {
|
||||||
r.studio.isSet = selected;
|
r.studio.isSet = selected;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -305,11 +305,11 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{parserResult.map(scene => (
|
{parserResult.map((scene) => (
|
||||||
<SceneParserRow
|
<SceneParserRow
|
||||||
scene={scene}
|
scene={scene}
|
||||||
key={scene.id}
|
key={scene.id}
|
||||||
onChange={changedScene => onChange(scene, changedScene)}
|
onChange={(changedScene) => onChange(scene, changedScene)}
|
||||||
showFields={showFields}
|
showFields={showFields}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@@ -320,7 +320,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
currentPage={parserInput.page}
|
currentPage={parserInput.page}
|
||||||
itemsPerPage={parserInput.pageSize}
|
itemsPerPage={parserInput.pageSize}
|
||||||
totalItems={totalItems}
|
totalItems={totalItems}
|
||||||
onChangePage={page => onPageChanged(page)}
|
onChangePage={(page) => onPageChanged(page)}
|
||||||
/>
|
/>
|
||||||
<Button variant="primary" onClick={onApply}>
|
<Button variant="primary" onClick={onApply}>
|
||||||
Apply
|
Apply
|
||||||
@@ -334,7 +334,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
<h4>Scene Filename Parser</h4>
|
<h4>Scene Filename Parser</h4>
|
||||||
<ParserInput
|
<ParserInput
|
||||||
input={parserInput}
|
input={parserInput}
|
||||||
onFind={input => onFindClicked(input)}
|
onFind={(input) => onFindClicked(input)}
|
||||||
onPageSizeChanged={onPageSizeChanged}
|
onPageSizeChanged={onPageSizeChanged}
|
||||||
showFields={showFields}
|
showFields={showFields}
|
||||||
setShowFields={setShowFields}
|
setShowFields={setShowFields}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ import _ from "lodash";
|
|||||||
import { Form } from "react-bootstrap";
|
import { Form } from "react-bootstrap";
|
||||||
import {
|
import {
|
||||||
ParseSceneFilenamesQuery,
|
ParseSceneFilenamesQuery,
|
||||||
SlimSceneDataFragment
|
SlimSceneDataFragment,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import {
|
import {
|
||||||
PerformerSelect,
|
PerformerSelect,
|
||||||
TagSelect,
|
TagSelect,
|
||||||
StudioSelect
|
StudioSelect,
|
||||||
} from "src/components/Shared";
|
} from "src/components/Shared";
|
||||||
import { TextUtils } from "src/utils";
|
import { TextUtils } from "src/utils";
|
||||||
|
|
||||||
@@ -51,8 +51,8 @@ export class SceneParserResult {
|
|||||||
this.filename = TextUtils.fileNameFromPath(this.scene.path);
|
this.filename = TextUtils.fileNameFromPath(this.scene.path);
|
||||||
this.title.setOriginalValue(this.scene.title ?? undefined);
|
this.title.setOriginalValue(this.scene.title ?? undefined);
|
||||||
this.date.setOriginalValue(this.scene.date ?? undefined);
|
this.date.setOriginalValue(this.scene.date ?? undefined);
|
||||||
this.performers.setOriginalValue(this.scene.performers.map(p => p.id));
|
this.performers.setOriginalValue(this.scene.performers.map((p) => p.id));
|
||||||
this.tags.setOriginalValue(this.scene.tags.map(t => t.id));
|
this.tags.setOriginalValue(this.scene.tags.map((t) => t.id));
|
||||||
this.studio.setOriginalValue(this.scene.studio?.id);
|
this.studio.setOriginalValue(this.scene.studio?.id);
|
||||||
|
|
||||||
this.title.setValue(result.title ?? undefined);
|
this.title.setValue(result.title ?? undefined);
|
||||||
@@ -82,10 +82,10 @@ export class SceneParserResult {
|
|||||||
studio_id: this.studio.isSet ? this.studio.value : this.scene.studio?.id,
|
studio_id: this.studio.isSet ? this.studio.value : this.scene.studio?.id,
|
||||||
performer_ids: this.performers.isSet
|
performer_ids: this.performers.isSet
|
||||||
? this.performers.value
|
? this.performers.value
|
||||||
: this.scene.performers.map(performer => performer.id),
|
: this.scene.performers.map((performer) => performer.id),
|
||||||
tag_ids: this.tags.isSet
|
tag_ids: this.tags.isSet
|
||||||
? this.tags.value
|
? this.tags.value
|
||||||
: this.scene.tags.map(tag => tag.id)
|
: this.scene.tags.map((tag) => tag.id),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,8 +165,8 @@ function SceneParserPerformerField(props: ISceneParserFieldProps<string[]>) {
|
|||||||
<PerformerSelect isDisabled isMulti ids={originalPerformers} />
|
<PerformerSelect isDisabled isMulti ids={originalPerformers} />
|
||||||
<PerformerSelect
|
<PerformerSelect
|
||||||
isMulti
|
isMulti
|
||||||
onSelect={items => {
|
onSelect={(items) => {
|
||||||
maybeValueChanged(items.map(i => i.id));
|
maybeValueChanged(items.map((i) => i.id));
|
||||||
}}
|
}}
|
||||||
ids={newPerformers}
|
ids={newPerformers}
|
||||||
/>
|
/>
|
||||||
@@ -201,8 +201,8 @@ function SceneParserTagField(props: ISceneParserFieldProps<string[]>) {
|
|||||||
<TagSelect isDisabled isMulti ids={originalTags} />
|
<TagSelect isDisabled isMulti ids={originalTags} />
|
||||||
<TagSelect
|
<TagSelect
|
||||||
isMulti
|
isMulti
|
||||||
onSelect={items => {
|
onSelect={(items) => {
|
||||||
maybeValueChanged(items.map(i => i.id));
|
maybeValueChanged(items.map((i) => i.id));
|
||||||
}}
|
}}
|
||||||
ids={newTags}
|
ids={newTags}
|
||||||
/>
|
/>
|
||||||
@@ -238,7 +238,7 @@ function SceneParserStudioField(props: ISceneParserFieldProps<string>) {
|
|||||||
<Form.Group className={props.className}>
|
<Form.Group className={props.className}>
|
||||||
<StudioSelect isDisabled ids={originalStudio} />
|
<StudioSelect isDisabled ids={originalStudio} />
|
||||||
<StudioSelect
|
<StudioSelect
|
||||||
onSelect={items => {
|
onSelect={(items) => {
|
||||||
maybeValueChanged(items[0].id);
|
maybeValueChanged(items[0].id);
|
||||||
}}
|
}}
|
||||||
ids={newStudio}
|
ids={newStudio}
|
||||||
@@ -304,10 +304,10 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
|
|||||||
fieldName="Title"
|
fieldName="Title"
|
||||||
className="parser-field-title"
|
className="parser-field-title"
|
||||||
parserResult={props.scene.title}
|
parserResult={props.scene.title}
|
||||||
onSetChanged={isSet =>
|
onSetChanged={(isSet) =>
|
||||||
onTitleChanged(isSet, props.scene.title.value ?? "")
|
onTitleChanged(isSet, props.scene.title.value ?? "")
|
||||||
}
|
}
|
||||||
onValueChanged={value =>
|
onValueChanged={(value) =>
|
||||||
onTitleChanged(props.scene.title.isSet, value)
|
onTitleChanged(props.scene.title.isSet, value)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -318,10 +318,12 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
|
|||||||
fieldName="Date"
|
fieldName="Date"
|
||||||
className="parser-field-date"
|
className="parser-field-date"
|
||||||
parserResult={props.scene.date}
|
parserResult={props.scene.date}
|
||||||
onSetChanged={isSet =>
|
onSetChanged={(isSet) =>
|
||||||
onDateChanged(isSet, props.scene.date.value ?? "")
|
onDateChanged(isSet, props.scene.date.value ?? "")
|
||||||
}
|
}
|
||||||
onValueChanged={value => onDateChanged(props.scene.date.isSet, value)}
|
onValueChanged={(value) =>
|
||||||
|
onDateChanged(props.scene.date.isSet, value)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{props.showFields.get("Performers") && (
|
{props.showFields.get("Performers") && (
|
||||||
@@ -331,10 +333,10 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
|
|||||||
className="parser-field-performers"
|
className="parser-field-performers"
|
||||||
parserResult={props.scene.performers}
|
parserResult={props.scene.performers}
|
||||||
originalParserResult={props.scene.performers}
|
originalParserResult={props.scene.performers}
|
||||||
onSetChanged={set =>
|
onSetChanged={(set) =>
|
||||||
onPerformerIdsChanged(set, props.scene.performers.value ?? [])
|
onPerformerIdsChanged(set, props.scene.performers.value ?? [])
|
||||||
}
|
}
|
||||||
onValueChanged={value =>
|
onValueChanged={(value) =>
|
||||||
onPerformerIdsChanged(props.scene.performers.isSet, value)
|
onPerformerIdsChanged(props.scene.performers.isSet, value)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -346,10 +348,10 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
|
|||||||
className="parser-field-tags"
|
className="parser-field-tags"
|
||||||
parserResult={props.scene.tags}
|
parserResult={props.scene.tags}
|
||||||
originalParserResult={props.scene.tags}
|
originalParserResult={props.scene.tags}
|
||||||
onSetChanged={isSet =>
|
onSetChanged={(isSet) =>
|
||||||
onTagIdsChanged(isSet, props.scene.tags.value ?? [])
|
onTagIdsChanged(isSet, props.scene.tags.value ?? [])
|
||||||
}
|
}
|
||||||
onValueChanged={value =>
|
onValueChanged={(value) =>
|
||||||
onTagIdsChanged(props.scene.tags.isSet, value)
|
onTagIdsChanged(props.scene.tags.isSet, value)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -361,10 +363,10 @@ export const SceneParserRow = (props: ISceneParserRowProps) => {
|
|||||||
className="parser-field-studio"
|
className="parser-field-studio"
|
||||||
parserResult={props.scene.studio}
|
parserResult={props.scene.studio}
|
||||||
originalParserResult={props.scene.studio}
|
originalParserResult={props.scene.studio}
|
||||||
onSetChanged={set =>
|
onSetChanged={(set) =>
|
||||||
onStudioIdChanged(set, props.scene.studio.value ?? "")
|
onStudioIdChanged(set, props.scene.studio.value ?? "")
|
||||||
}
|
}
|
||||||
onValueChanged={value =>
|
onValueChanged={(value) =>
|
||||||
onStudioIdChanged(props.scene.studio.isSet, value)
|
onStudioIdChanged(props.scene.studio.isSet, value)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -35,11 +35,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.form-control + .form-control {
|
.form-control + .form-control {
|
||||||
margin-top: .5rem;
|
margin-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge-items {
|
.badge-items {
|
||||||
background-color: #e9ecef;
|
background-color: #e9ecef;
|
||||||
margin-bottom: .25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const KeyMap = {
|
|||||||
NUM0: "0",
|
NUM0: "0",
|
||||||
NUM1: "1",
|
NUM1: "1",
|
||||||
NUM2: "2",
|
NUM2: "2",
|
||||||
SPACE: " "
|
SPACE: " ",
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ScenePlayerImpl extends React.Component<
|
export class ScenePlayerImpl extends React.Component<
|
||||||
@@ -49,7 +49,7 @@ export class ScenePlayerImpl extends React.Component<
|
|||||||
},
|
},
|
||||||
SPACE: () => {
|
SPACE: () => {
|
||||||
this.onPause();
|
this.onPause();
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props: IScenePlayerProps) {
|
constructor(props: IScenePlayerProps) {
|
||||||
@@ -63,15 +63,15 @@ export class ScenePlayerImpl extends React.Component<
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
scrubberPosition: 0,
|
scrubberPosition: 0,
|
||||||
config: this.makeJWPlayerConfig(props.scene)
|
config: this.makeJWPlayerConfig(props.scene),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public UNSAFE_componentWillReceiveProps(props: IScenePlayerProps) {
|
public UNSAFE_componentWillReceiveProps(props: IScenePlayerProps) {
|
||||||
if (props.scene !== this.props.scene) {
|
if (props.scene !== this.props.scene) {
|
||||||
this.setState(state => ({
|
this.setState((state) => ({
|
||||||
...state,
|
...state,
|
||||||
config: this.makeJWPlayerConfig(this.props.scene)
|
config: this.makeJWPlayerConfig(this.props.scene),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,17 +177,17 @@ export class ScenePlayerImpl extends React.Component<
|
|||||||
tracks: [
|
tracks: [
|
||||||
{
|
{
|
||||||
file: scene.paths.vtt,
|
file: scene.paths.vtt,
|
||||||
kind: "thumbnails"
|
kind: "thumbnails",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: scene.paths.chapters_vtt,
|
file: scene.paths.chapters_vtt,
|
||||||
kind: "chapters"
|
kind: "chapters",
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
aspectratio: "16:9",
|
aspectratio: "16:9",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
floating: {
|
floating: {
|
||||||
dismissible: true
|
dismissible: true,
|
||||||
},
|
},
|
||||||
cast: {},
|
cast: {},
|
||||||
primary: "html5",
|
primary: "html5",
|
||||||
@@ -199,7 +199,7 @@ export class ScenePlayerImpl extends React.Component<
|
|||||||
playbackRates: [0.75, 1, 1.5, 2, 3, 4],
|
playbackRates: [0.75, 1, 1.5, 2, 3, 4],
|
||||||
getDurationHook,
|
getDurationHook,
|
||||||
seekHook,
|
seekHook,
|
||||||
getCurrentTimeHook
|
getCurrentTimeHook,
|
||||||
};
|
};
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import React, {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
useCallback
|
useCallback,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Button } from "react-bootstrap";
|
import { Button } from "react-bootstrap";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
@@ -45,10 +45,7 @@ async function fetchSpriteInfo(vttPath: string) {
|
|||||||
const line = lines.shift();
|
const line = lines.shift();
|
||||||
if (line !== undefined) {
|
if (line !== undefined) {
|
||||||
if (line.includes("#") && line.includes("=") && line.includes(",")) {
|
if (line.includes("#") && line.includes("=") && line.includes(",")) {
|
||||||
const size = line
|
const size = line.split("#")[1].split("=")[1].split(",");
|
||||||
.split("#")[1]
|
|
||||||
.split("=")[1]
|
|
||||||
.split(",");
|
|
||||||
item.x = Number(size[0]);
|
item.x = Number(size[0]);
|
||||||
item.y = Number(size[1]);
|
item.y = Number(size[1]);
|
||||||
item.w = Number(size[2]);
|
item.w = Number(size[2]);
|
||||||
@@ -120,13 +117,14 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = (
|
|||||||
if (!scrubberSliderEl.current) {
|
if (!scrubberSliderEl.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scrubberSliderEl.current.style.transform = `translateX(${scrubberSliderEl
|
scrubberSliderEl.current.style.transform = `translateX(${
|
||||||
.current.clientWidth / 2}px)`;
|
scrubberSliderEl.current.clientWidth / 2
|
||||||
|
}px)`;
|
||||||
}, [scrubberSliderEl]);
|
}, [scrubberSliderEl]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!props.scene.paths.vtt) return;
|
if (!props.scene.paths.vtt) return;
|
||||||
fetchSpriteInfo(props.scene.paths.vtt).then(sprites => {
|
fetchSpriteInfo(props.scene.paths.vtt).then((sprites) => {
|
||||||
if (sprites) setSpriteItems(sprites);
|
if (sprites) setSpriteItems(sprites);
|
||||||
});
|
});
|
||||||
}, [props.scene]);
|
}, [props.scene]);
|
||||||
@@ -297,13 +295,13 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = (
|
|||||||
tag!.clientWidth / 2;
|
tag!.clientWidth / 2;
|
||||||
return {
|
return {
|
||||||
left: `${left}px`,
|
left: `${left}px`,
|
||||||
height: 20
|
height: 20,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return props.scene.scene_markers.map((marker, index) => {
|
return props.scene.scene_markers.map((marker, index) => {
|
||||||
const dataAttrs = {
|
const dataAttrs = {
|
||||||
"data-marker-id": index
|
"data-marker-id": index,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -332,13 +330,13 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = (
|
|||||||
margin: "0px auto",
|
margin: "0px auto",
|
||||||
backgroundPosition: `${-sprite.x}px ${-sprite.y}px`,
|
backgroundPosition: `${-sprite.x}px ${-sprite.y}px`,
|
||||||
backgroundImage: `url(${path})`,
|
backgroundImage: `url(${path})`,
|
||||||
left: `${left}px`
|
left: `${left}px`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return spriteItems.map((spriteItem, index) => {
|
return spriteItems.map((spriteItem, index) => {
|
||||||
const dataAttrs = {
|
const dataAttrs = {
|
||||||
"data-sprite-item-id": index
|
"data-sprite-item-id": index,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
cursor: grab;
|
cursor: grab;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 120px;
|
height: 120px;
|
||||||
margin: 0 .5%;
|
margin: 0 0.5%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
) => {
|
) => {
|
||||||
const [previewPath, setPreviewPath] = useState<string>();
|
const [previewPath, setPreviewPath] = useState<string>();
|
||||||
const videoHoverHook = VideoHoverHook.useVideoHover({
|
const videoHoverHook = VideoHoverHook.useVideoHover({
|
||||||
resetOnMouseLeave: false
|
resetOnMouseLeave: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const config = StashService.useConfiguration();
|
const config = StashService.useConfiguration();
|
||||||
@@ -83,7 +83,7 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
function maybeRenderTagPopoverButton() {
|
function maybeRenderTagPopoverButton() {
|
||||||
if (props.scene.tags.length <= 0) return;
|
if (props.scene.tags.length <= 0) return;
|
||||||
|
|
||||||
const popoverContent = props.scene.tags.map(tag => (
|
const popoverContent = props.scene.tags.map((tag) => (
|
||||||
<TagLink key={tag.id} tag={tag} />
|
<TagLink key={tag.id} tag={tag} />
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
function maybeRenderPerformerPopoverButton() {
|
function maybeRenderPerformerPopoverButton() {
|
||||||
if (props.scene.performers.length <= 0) return;
|
if (props.scene.performers.length <= 0) return;
|
||||||
|
|
||||||
const popoverContent = props.scene.performers.map(performer => (
|
const popoverContent = props.scene.performers.map((performer) => (
|
||||||
<div className="performer-tag-container row" key="performer">
|
<div className="performer-tag-container row" key="performer">
|
||||||
<Link
|
<Link
|
||||||
to={`/performers/${performer.id}`}
|
to={`/performers/${performer.id}`}
|
||||||
@@ -129,7 +129,7 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
function maybeRenderMoviePopoverButton() {
|
function maybeRenderMoviePopoverButton() {
|
||||||
if (props.scene.movies.length <= 0) return;
|
if (props.scene.movies.length <= 0) return;
|
||||||
|
|
||||||
const popoverContent = props.scene.movies.map(sceneMovie => (
|
const popoverContent = props.scene.movies.map((sceneMovie) => (
|
||||||
<div className="movie-tag-container row" key="movie">
|
<div className="movie-tag-container row" key="movie">
|
||||||
<Link
|
<Link
|
||||||
to={`/movies/${sceneMovie.movie.id}`}
|
to={`/movies/${sceneMovie.movie.id}`}
|
||||||
@@ -162,7 +162,7 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
function maybeRenderSceneMarkerPopoverButton() {
|
function maybeRenderSceneMarkerPopoverButton() {
|
||||||
if (props.scene.scene_markers.length <= 0) return;
|
if (props.scene.scene_markers.length <= 0) return;
|
||||||
|
|
||||||
const popoverContent = props.scene.scene_markers.map(marker => {
|
const popoverContent = props.scene.scene_markers.map((marker) => {
|
||||||
const markerPopover = { ...marker, scene: { id: props.scene.id } };
|
const markerPopover = { ...marker, scene: { id: props.scene.id } };
|
||||||
return <TagLink key={marker.id} marker={markerPopover} />;
|
return <TagLink key={marker.id} marker={markerPopover} />;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ interface IPrimaryTags {
|
|||||||
export const PrimaryTags: React.FC<IPrimaryTags> = ({
|
export const PrimaryTags: React.FC<IPrimaryTags> = ({
|
||||||
sceneMarkers,
|
sceneMarkers,
|
||||||
onClickMarker,
|
onClickMarker,
|
||||||
onEdit
|
onEdit,
|
||||||
}) => {
|
}) => {
|
||||||
if (!sceneMarkers?.length) return <div />;
|
if (!sceneMarkers?.length) return <div />;
|
||||||
|
|
||||||
const primaries: Record<string, GQL.Tag> = {};
|
const primaries: Record<string, GQL.Tag> = {};
|
||||||
const primaryTags: Record<string, GQL.SceneMarkerDataFragment[]> = {};
|
const primaryTags: Record<string, GQL.SceneMarkerDataFragment[]> = {};
|
||||||
sceneMarkers.forEach(m => {
|
sceneMarkers.forEach((m) => {
|
||||||
if (primaryTags[m.primary_tag.id]) primaryTags[m.primary_tag.id].push(m);
|
if (primaryTags[m.primary_tag.id]) primaryTags[m.primary_tag.id].push(m);
|
||||||
else {
|
else {
|
||||||
primaryTags[m.primary_tag.id] = [m];
|
primaryTags[m.primary_tag.id] = [m];
|
||||||
@@ -26,9 +26,9 @@ export const PrimaryTags: React.FC<IPrimaryTags> = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const primaryCards = Object.keys(primaryTags).map(id => {
|
const primaryCards = Object.keys(primaryTags).map((id) => {
|
||||||
const markers = primaryTags[id].map(marker => {
|
const markers = primaryTags[id].map((marker) => {
|
||||||
const tags = marker.tags.map(tag => (
|
const tags = marker.tags.map((tag) => (
|
||||||
<Badge key={tag.id} variant="secondary" className="tag-item">
|
<Badge key={tag.id} variant="secondary" className="tag-item">
|
||||||
{tag.name}
|
{tag.name}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ export const Scene: React.FC = () => {
|
|||||||
<Tab eventKey="scene-edit-panel" title="Edit">
|
<Tab eventKey="scene-edit-panel" title="Edit">
|
||||||
<SceneEditPanel
|
<SceneEditPanel
|
||||||
scene={scene}
|
scene={scene}
|
||||||
onUpdate={newScene => setScene(newScene)}
|
onUpdate={(newScene) => setScene(newScene)}
|
||||||
onDelete={() => history.push("/scenes")}
|
onDelete={() => history.push("/scenes")}
|
||||||
/>
|
/>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface ISceneDetailProps {
|
|||||||
scene: GQL.SceneDataFragment;
|
scene: GQL.SceneDataFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SceneDetailPanel: React.FC<ISceneDetailProps> = props => {
|
export const SceneDetailPanel: React.FC<ISceneDetailProps> = (props) => {
|
||||||
function renderDetails() {
|
function renderDetails() {
|
||||||
if (!props.scene.details || props.scene.details === "") return;
|
if (!props.scene.details || props.scene.details === "") return;
|
||||||
return (
|
return (
|
||||||
@@ -21,7 +21,7 @@ export const SceneDetailPanel: React.FC<ISceneDetailProps> = props => {
|
|||||||
|
|
||||||
function renderTags() {
|
function renderTags() {
|
||||||
if (props.scene.tags.length === 0) return;
|
if (props.scene.tags.length === 0) return;
|
||||||
const tags = props.scene.tags.map(tag => (
|
const tags = props.scene.tags.map((tag) => (
|
||||||
<TagLink key={tag.id} tag={tag} />
|
<TagLink key={tag.id} tag={tag} />
|
||||||
));
|
));
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
Modal,
|
Modal,
|
||||||
Icon,
|
Icon,
|
||||||
LoadingIndicator,
|
LoadingIndicator,
|
||||||
ImageInput
|
ImageInput,
|
||||||
} from "src/components/Shared";
|
} from "src/components/Shared";
|
||||||
import { useToast } from "src/hooks";
|
import { useToast } from "src/hooks";
|
||||||
import { ImageUtils, TableUtils } from "src/utils";
|
import { ImageUtils, TableUtils } from "src/utils";
|
||||||
@@ -60,7 +60,9 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newQueryableScrapers = (
|
const newQueryableScrapers = (
|
||||||
Scrapers?.data?.listSceneScrapers ?? []
|
Scrapers?.data?.listSceneScrapers ?? []
|
||||||
).filter(s => s.scene?.supported_scrapes.includes(GQL.ScrapeType.Fragment));
|
).filter((s) =>
|
||||||
|
s.scene?.supported_scrapes.includes(GQL.ScrapeType.Fragment)
|
||||||
|
);
|
||||||
|
|
||||||
setQueryableScrapers(newQueryableScrapers);
|
setQueryableScrapers(newQueryableScrapers);
|
||||||
}, [Scrapers]);
|
}, [Scrapers]);
|
||||||
@@ -69,7 +71,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
let changed = false;
|
let changed = false;
|
||||||
const newMap: MovieSceneIndexMap = new Map();
|
const newMap: MovieSceneIndexMap = new Map();
|
||||||
if (movieIds) {
|
if (movieIds) {
|
||||||
movieIds.forEach(id => {
|
movieIds.forEach((id) => {
|
||||||
if (!movieSceneIndexes.has(id)) {
|
if (!movieSceneIndexes.has(id)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
newMap.set(id, undefined);
|
newMap.set(id, undefined);
|
||||||
@@ -94,14 +96,14 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
}, [movieIds, movieSceneIndexes]);
|
}, [movieIds, movieSceneIndexes]);
|
||||||
|
|
||||||
function updateSceneEditState(state: Partial<GQL.SceneDataFragment>) {
|
function updateSceneEditState(state: Partial<GQL.SceneDataFragment>) {
|
||||||
const perfIds = state.performers?.map(performer => performer.id);
|
const perfIds = state.performers?.map((performer) => performer.id);
|
||||||
const tIds = state.tags ? state.tags.map(tag => tag.id) : undefined;
|
const tIds = state.tags ? state.tags.map((tag) => tag.id) : undefined;
|
||||||
const moviIds = state.movies
|
const moviIds = state.movies
|
||||||
? state.movies.map(sceneMovie => sceneMovie.movie.id)
|
? state.movies.map((sceneMovie) => sceneMovie.movie.id)
|
||||||
: undefined;
|
: undefined;
|
||||||
const movieSceneIdx: MovieSceneIndexMap = new Map();
|
const movieSceneIdx: MovieSceneIndexMap = new Map();
|
||||||
if (state.movies) {
|
if (state.movies) {
|
||||||
state.movies.forEach(m => {
|
state.movies.forEach((m) => {
|
||||||
movieSceneIdx.set(m.movie.id, m.scene_index ?? undefined);
|
movieSceneIdx.set(m.movie.id, m.scene_index ?? undefined);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -140,7 +142,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
performer_ids: performerIds,
|
performer_ids: performerIds,
|
||||||
movies: makeMovieInputs(),
|
movies: makeMovieInputs(),
|
||||||
tag_ids: tagIds,
|
tag_ids: tagIds,
|
||||||
cover_image: coverImage
|
cover_image: coverImage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,14 +151,14 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret = movieIds.map(id => {
|
let ret = movieIds.map((id) => {
|
||||||
const r: GQL.SceneMovieInput = {
|
const r: GQL.SceneMovieInput = {
|
||||||
movie_id: id
|
movie_id: id,
|
||||||
};
|
};
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
|
|
||||||
ret = ret.map(r => {
|
ret = ret.map((r) => {
|
||||||
return { scene_index: movieSceneIndexes.get(r.movie_id), ...r };
|
return { scene_index: movieSceneIndexes.get(r.movie_id), ...r };
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -181,7 +183,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
return {
|
return {
|
||||||
id: props.scene.id,
|
id: props.scene.id,
|
||||||
delete_file: deleteFile,
|
delete_file: deleteFile,
|
||||||
delete_generated: deleteGenerated
|
delete_generated: deleteGenerated,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +204,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
return (
|
return (
|
||||||
<SceneMovieTable
|
<SceneMovieTable
|
||||||
movieSceneIndexes={movieSceneIndexes}
|
movieSceneIndexes={movieSceneIndexes}
|
||||||
onUpdate={items => {
|
onUpdate={(items) => {
|
||||||
setMovieSceneIndexes(items);
|
setMovieSceneIndexes(items);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -272,7 +274,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownButton id="scene-scrape" title="Scrape with...">
|
<DropdownButton id="scene-scrape" title="Scrape with...">
|
||||||
{queryableScrapers.map(s => (
|
{queryableScrapers.map((s) => (
|
||||||
<Dropdown.Item key={s.name} onClick={() => onScrapeClicked(s)}>
|
<Dropdown.Item key={s.name} onClick={() => onScrapeClicked(s)}>
|
||||||
{s.name}
|
{s.name}
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
@@ -282,8 +284,8 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function urlScrapable(scrapedUrl: string): boolean {
|
function urlScrapable(scrapedUrl: string): boolean {
|
||||||
return (Scrapers?.data?.listSceneScrapers ?? []).some(s =>
|
return (Scrapers?.data?.listSceneScrapers ?? []).some((s) =>
|
||||||
(s?.scene?.urls ?? []).some(u => scrapedUrl.includes(u))
|
(s?.scene?.urls ?? []).some((u) => scrapedUrl.includes(u))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,12 +315,12 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
scene.performers &&
|
scene.performers &&
|
||||||
scene.performers.length > 0
|
scene.performers.length > 0
|
||||||
) {
|
) {
|
||||||
const idPerfs = scene.performers.filter(p => {
|
const idPerfs = scene.performers.filter((p) => {
|
||||||
return p.id !== undefined && p.id !== null;
|
return p.id !== undefined && p.id !== null;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (idPerfs.length > 0) {
|
if (idPerfs.length > 0) {
|
||||||
const newIds = idPerfs.map(p => p.id);
|
const newIds = idPerfs.map((p) => p.id);
|
||||||
setPerformerIds(newIds as string[]);
|
setPerformerIds(newIds as string[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,23 +330,23 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
scene.movies &&
|
scene.movies &&
|
||||||
scene.movies.length > 0
|
scene.movies.length > 0
|
||||||
) {
|
) {
|
||||||
const idMovis = scene.movies.filter(p => {
|
const idMovis = scene.movies.filter((p) => {
|
||||||
return p.id !== undefined && p.id !== null;
|
return p.id !== undefined && p.id !== null;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (idMovis.length > 0) {
|
if (idMovis.length > 0) {
|
||||||
const newIds = idMovis.map(p => p.id);
|
const newIds = idMovis.map((p) => p.id);
|
||||||
setMovieIds(newIds as string[]);
|
setMovieIds(newIds as string[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tagIds?.length && scene?.tags?.length) {
|
if (!tagIds?.length && scene?.tags?.length) {
|
||||||
const idTags = scene.tags.filter(p => {
|
const idTags = scene.tags.filter((p) => {
|
||||||
return p.id !== undefined && p.id !== null;
|
return p.id !== undefined && p.id !== null;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (idTags.length > 0) {
|
if (idTags.length > 0) {
|
||||||
const newIds = idTags.map(p => p.id);
|
const newIds = idTags.map((p) => p.id);
|
||||||
setTagIds(newIds as string[]);
|
setTagIds(newIds as string[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,7 +398,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
title: "Title",
|
title: "Title",
|
||||||
value: title,
|
value: title,
|
||||||
onChange: setTitle,
|
onChange: setTitle,
|
||||||
isEditing: true
|
isEditing: true,
|
||||||
})}
|
})}
|
||||||
<tr>
|
<tr>
|
||||||
<td>URL</td>
|
<td>URL</td>
|
||||||
@@ -417,7 +419,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
value: date,
|
value: date,
|
||||||
isEditing: true,
|
isEditing: true,
|
||||||
onChange: setDate,
|
onChange: setDate,
|
||||||
placeholder: "YYYY-MM-DD"
|
placeholder: "YYYY-MM-DD",
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderHtmlSelect({
|
{TableUtils.renderHtmlSelect({
|
||||||
title: "Rating",
|
title: "Rating",
|
||||||
@@ -425,7 +427,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
isEditing: true,
|
isEditing: true,
|
||||||
onChange: (value: string) =>
|
onChange: (value: string) =>
|
||||||
setRating(Number.parseInt(value, 10)),
|
setRating(Number.parseInt(value, 10)),
|
||||||
selectOptions: ["", 1, 2, 3, 4, 5]
|
selectOptions: ["", 1, 2, 3, 4, 5],
|
||||||
})}
|
})}
|
||||||
<tr>
|
<tr>
|
||||||
<td>Gallery</td>
|
<td>Gallery</td>
|
||||||
@@ -433,7 +435,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
<SceneGallerySelect
|
<SceneGallerySelect
|
||||||
sceneId={props.scene.id}
|
sceneId={props.scene.id}
|
||||||
initialId={galleryId}
|
initialId={galleryId}
|
||||||
onSelect={item => setGalleryId(item ? item.id : undefined)}
|
onSelect={(item) => setGalleryId(item ? item.id : undefined)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -441,7 +443,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
<td>Studio</td>
|
<td>Studio</td>
|
||||||
<td>
|
<td>
|
||||||
<StudioSelect
|
<StudioSelect
|
||||||
onSelect={items =>
|
onSelect={(items) =>
|
||||||
setStudioId(items.length > 0 ? items[0]?.id : undefined)
|
setStudioId(items.length > 0 ? items[0]?.id : undefined)
|
||||||
}
|
}
|
||||||
ids={studioId ? [studioId] : []}
|
ids={studioId ? [studioId] : []}
|
||||||
@@ -453,8 +455,8 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
<td>
|
<td>
|
||||||
<PerformerSelect
|
<PerformerSelect
|
||||||
isMulti
|
isMulti
|
||||||
onSelect={items =>
|
onSelect={(items) =>
|
||||||
setPerformerIds(items.map(item => item.id))
|
setPerformerIds(items.map((item) => item.id))
|
||||||
}
|
}
|
||||||
ids={performerIds}
|
ids={performerIds}
|
||||||
/>
|
/>
|
||||||
@@ -465,7 +467,9 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
<td>
|
<td>
|
||||||
<MovieSelect
|
<MovieSelect
|
||||||
isMulti
|
isMulti
|
||||||
onSelect={items => setMovieIds(items.map(item => item.id))}
|
onSelect={(items) =>
|
||||||
|
setMovieIds(items.map((item) => item.id))
|
||||||
|
}
|
||||||
ids={movieIds}
|
ids={movieIds}
|
||||||
/>
|
/>
|
||||||
{renderTableMovies()}
|
{renderTableMovies()}
|
||||||
@@ -476,7 +480,7 @@ export const SceneEditPanel: React.FC<IProps> = (props: IProps) => {
|
|||||||
<td>
|
<td>
|
||||||
<TagSelect
|
<TagSelect
|
||||||
isMulti
|
isMulti
|
||||||
onSelect={items => setTagIds(items.map(item => item.id))}
|
onSelect={(items) => setTagIds(items.map((item) => item.id))}
|
||||||
ids={tagIds}
|
ids={tagIds}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
|
|
||||||
function renderPath() {
|
function renderPath() {
|
||||||
const {
|
const {
|
||||||
scene: { path }
|
scene: { path },
|
||||||
} = props;
|
} = props;
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { StashService } from "src/core/StashService";
|
|||||||
import {
|
import {
|
||||||
DurationInput,
|
DurationInput,
|
||||||
TagSelect,
|
TagSelect,
|
||||||
MarkerTitleSuggest
|
MarkerTitleSuggest,
|
||||||
} from "src/components/Shared";
|
} from "src/components/Shared";
|
||||||
import { useToast } from "src/hooks";
|
import { useToast } from "src/hooks";
|
||||||
import { JWUtils } from "src/utils";
|
import { JWUtils } from "src/utils";
|
||||||
@@ -27,7 +27,7 @@ interface ISceneMarkerForm {
|
|||||||
export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
||||||
sceneID,
|
sceneID,
|
||||||
editingMarker,
|
editingMarker,
|
||||||
onClose
|
onClose,
|
||||||
}) => {
|
}) => {
|
||||||
const [sceneMarkerCreate] = StashService.useSceneMarkerCreate();
|
const [sceneMarkerCreate] = StashService.useSceneMarkerCreate();
|
||||||
const [sceneMarkerUpdate] = StashService.useSceneMarkerUpdate();
|
const [sceneMarkerUpdate] = StashService.useSceneMarkerUpdate();
|
||||||
@@ -40,18 +40,18 @@ export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
|||||||
seconds: parseFloat(values.seconds),
|
seconds: parseFloat(values.seconds),
|
||||||
scene_id: sceneID,
|
scene_id: sceneID,
|
||||||
primary_tag_id: values.primaryTagId,
|
primary_tag_id: values.primaryTagId,
|
||||||
tag_ids: values.tagIds
|
tag_ids: values.tagIds,
|
||||||
};
|
};
|
||||||
if (!editingMarker) {
|
if (!editingMarker) {
|
||||||
sceneMarkerCreate({ variables })
|
sceneMarkerCreate({ variables })
|
||||||
.then(onClose)
|
.then(onClose)
|
||||||
.catch(err => Toast.error(err));
|
.catch((err) => Toast.error(err));
|
||||||
} else {
|
} else {
|
||||||
const updateVariables = variables as GQL.SceneMarkerUpdateInput;
|
const updateVariables = variables as GQL.SceneMarkerUpdateInput;
|
||||||
updateVariables.id = editingMarker!.id;
|
updateVariables.id = editingMarker!.id;
|
||||||
sceneMarkerUpdate({ variables: updateVariables })
|
sceneMarkerUpdate({ variables: updateVariables })
|
||||||
.then(onClose)
|
.then(onClose)
|
||||||
.catch(err => Toast.error(err));
|
.catch((err) => Toast.error(err));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
|||||||
|
|
||||||
sceneMarkerDestroy({ variables: { id: editingMarker.id } })
|
sceneMarkerDestroy({ variables: { id: editingMarker.id } })
|
||||||
.then(onClose)
|
.then(onClose)
|
||||||
.catch(err => Toast.error(err));
|
.catch((err) => Toast.error(err));
|
||||||
};
|
};
|
||||||
const renderTitleField = (fieldProps: FieldProps<string>) => (
|
const renderTitleField = (fieldProps: FieldProps<string>) => (
|
||||||
<div className="col-10">
|
<div className="col-10">
|
||||||
@@ -76,7 +76,7 @@ export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
|||||||
const renderSecondsField = (fieldProps: FieldProps<string>) => (
|
const renderSecondsField = (fieldProps: FieldProps<string>) => (
|
||||||
<div className="col-3">
|
<div className="col-3">
|
||||||
<DurationInput
|
<DurationInput
|
||||||
onValueChange={s => fieldProps.form.setFieldValue("seconds", s)}
|
onValueChange={(s) => fieldProps.form.setFieldValue("seconds", s)}
|
||||||
onReset={() =>
|
onReset={() =>
|
||||||
fieldProps.form.setFieldValue(
|
fieldProps.form.setFieldValue(
|
||||||
"seconds",
|
"seconds",
|
||||||
@@ -90,7 +90,7 @@ export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
|||||||
|
|
||||||
const renderPrimaryTagField = (fieldProps: FieldProps<string>) => (
|
const renderPrimaryTagField = (fieldProps: FieldProps<string>) => (
|
||||||
<TagSelect
|
<TagSelect
|
||||||
onSelect={tags =>
|
onSelect={(tags) =>
|
||||||
fieldProps.form.setFieldValue("primaryTagId", tags[0]?.id)
|
fieldProps.form.setFieldValue("primaryTagId", tags[0]?.id)
|
||||||
}
|
}
|
||||||
ids={fieldProps.field.value ? [fieldProps.field.value] : []}
|
ids={fieldProps.field.value ? [fieldProps.field.value] : []}
|
||||||
@@ -101,10 +101,10 @@ export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
|||||||
const renderTagsField = (fieldProps: FieldProps<string[]>) => (
|
const renderTagsField = (fieldProps: FieldProps<string[]>) => (
|
||||||
<TagSelect
|
<TagSelect
|
||||||
isMulti
|
isMulti
|
||||||
onSelect={tags =>
|
onSelect={(tags) =>
|
||||||
fieldProps.form.setFieldValue(
|
fieldProps.form.setFieldValue(
|
||||||
"tagIds",
|
"tagIds",
|
||||||
tags.map(tag => tag.id)
|
tags.map((tag) => tag.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ids={fieldProps.field.value}
|
ids={fieldProps.field.value}
|
||||||
@@ -119,7 +119,7 @@ export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
|||||||
Math.round(JWUtils.getPlayer()?.getPosition() ?? 0)
|
Math.round(JWUtils.getPlayer()?.getPosition() ?? 0)
|
||||||
).toString(),
|
).toString(),
|
||||||
primaryTagId: editingMarker?.primary_tag.id ?? "",
|
primaryTagId: editingMarker?.primary_tag.id ?? "",
|
||||||
tagIds: editingMarker?.tags.map(tag => tag.id) ?? []
|
tagIds: editingMarker?.tags.map((tag) => tag.id) ?? [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const SceneMarkersPanel: React.FC<ISceneMarkersPanelProps> = (
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<WallPanel
|
<WallPanel
|
||||||
sceneMarkers={props.scene.scene_markers}
|
sceneMarkers={props.scene.scene_markers}
|
||||||
clickHandler={marker => {
|
clickHandler={(marker) => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
onClickMarker(marker as GQL.SceneMarkerDataFragment);
|
onClickMarker(marker as GQL.SceneMarkerDataFragment);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ interface ISceneMoviePanelProps {
|
|||||||
export const SceneMoviePanel: FunctionComponent<ISceneMoviePanelProps> = (
|
export const SceneMoviePanel: FunctionComponent<ISceneMoviePanelProps> = (
|
||||||
props: ISceneMoviePanelProps
|
props: ISceneMoviePanelProps
|
||||||
) => {
|
) => {
|
||||||
const cards = props.scene.movies.map(sceneMovie => (
|
const cards = props.scene.movies.map((sceneMovie) => (
|
||||||
<MovieCard
|
<MovieCard
|
||||||
key={sceneMovie.movie.id}
|
key={sceneMovie.movie.id}
|
||||||
movie={sceneMovie.movie}
|
movie={sceneMovie.movie}
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ export const SceneMovieTable: React.FunctionComponent<IProps> = (
|
|||||||
|
|
||||||
if (!!props.movieSceneIndexes && !!items) {
|
if (!!props.movieSceneIndexes && !!items) {
|
||||||
props.movieSceneIndexes.forEach((index, movieId) => {
|
props.movieSceneIndexes.forEach((index, movieId) => {
|
||||||
itemsFilter = itemsFilter.concat(items.filter(x => x.id === movieId));
|
itemsFilter = itemsFilter.concat(items.filter((x) => x.id === movieId));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const storeIdx = itemsFilter.map(movie => {
|
const storeIdx = itemsFilter.map((movie) => {
|
||||||
return props.movieSceneIndexes.get(movie.id);
|
return props.movieSceneIndexes.get(movie.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ export const SceneMovieTable: React.FunctionComponent<IProps> = (
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{["", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"].map(
|
{["", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"].map(
|
||||||
opt => (
|
(opt) => (
|
||||||
<option value={opt} key={opt}>
|
<option value={opt} key={opt}>
|
||||||
{opt}
|
{opt}
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ export const SceneOperationsPanel: FunctionComponent<IOperationsPanelProps> = (
|
|||||||
await generateScreenshot({
|
await generateScreenshot({
|
||||||
variables: {
|
variables: {
|
||||||
id: props.scene.id,
|
id: props.scene.id,
|
||||||
at
|
at,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
Toast.success({ content: "Generating screenshot" });
|
Toast.success({ content: "Generating screenshot" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ interface IScenePerformerPanelProps {
|
|||||||
export const ScenePerformerPanel: FunctionComponent<IScenePerformerPanelProps> = (
|
export const ScenePerformerPanel: FunctionComponent<IScenePerformerPanelProps> = (
|
||||||
props: IScenePerformerPanelProps
|
props: IScenePerformerPanelProps
|
||||||
) => {
|
) => {
|
||||||
const cards = props.scene.performers.map(performer => (
|
const cards = props.scene.performers.map((performer) => (
|
||||||
<PerformerCard
|
<PerformerCard
|
||||||
key={performer.id}
|
key={performer.id}
|
||||||
performer={performer}
|
performer={performer}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import _ from "lodash";
|
|||||||
import { useHistory } from "react-router-dom";
|
import { useHistory } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
FindScenesQueryResult,
|
FindScenesQueryResult,
|
||||||
SlimSceneDataFragment
|
SlimSceneDataFragment,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import { StashService } from "src/core/StashService";
|
import { StashService } from "src/core/StashService";
|
||||||
import { useScenesList } from "src/hooks";
|
import { useScenesList } from "src/hooks";
|
||||||
@@ -21,14 +21,14 @@ interface ISceneList {
|
|||||||
|
|
||||||
export const SceneList: React.FC<ISceneList> = ({
|
export const SceneList: React.FC<ISceneList> = ({
|
||||||
subComponent,
|
subComponent,
|
||||||
filterHook
|
filterHook,
|
||||||
}) => {
|
}) => {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const otherOperations = [
|
const otherOperations = [
|
||||||
{
|
{
|
||||||
text: "Play Random",
|
text: "Play Random",
|
||||||
onClick: playRandom
|
onClick: playRandom,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const listData = useScenesList({
|
const listData = useScenesList({
|
||||||
@@ -37,7 +37,7 @@ export const SceneList: React.FC<ISceneList> = ({
|
|||||||
renderContent,
|
renderContent,
|
||||||
renderSelectedOptions,
|
renderSelectedOptions,
|
||||||
subComponent,
|
subComponent,
|
||||||
filterHook
|
filterHook,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function playRandom(
|
async function playRandom(
|
||||||
@@ -78,8 +78,8 @@ export const SceneList: React.FC<ISceneList> = ({
|
|||||||
const { scenes } = result.data.findScenes;
|
const { scenes } = result.data.findScenes;
|
||||||
|
|
||||||
const selectedScenes: SlimSceneDataFragment[] = [];
|
const selectedScenes: SlimSceneDataFragment[] = [];
|
||||||
selectedIds.forEach(id => {
|
selectedIds.forEach((id) => {
|
||||||
const scene = scenes.find(s => s.id === id);
|
const scene = scenes.find((s) => s.id === id);
|
||||||
|
|
||||||
if (scene) {
|
if (scene) {
|
||||||
selectedScenes.push(scene);
|
selectedScenes.push(scene);
|
||||||
@@ -126,7 +126,7 @@ export const SceneList: React.FC<ISceneList> = ({
|
|||||||
if (filter.displayMode === DisplayMode.Grid) {
|
if (filter.displayMode === DisplayMode.Grid) {
|
||||||
return (
|
return (
|
||||||
<div className="row justify-content-center">
|
<div className="row justify-content-center">
|
||||||
{result.data.findScenes.scenes.map(scene =>
|
{result.data.findScenes.scenes.map((scene) =>
|
||||||
renderSceneCard(scene, selectedIds, zoomIndex)
|
renderSceneCard(scene, selectedIds, zoomIndex)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,24 +13,22 @@ export const SceneListTable: React.FC<ISceneListTableProps> = (
|
|||||||
props: ISceneListTableProps
|
props: ISceneListTableProps
|
||||||
) => {
|
) => {
|
||||||
const renderTags = (tags: GQL.Tag[]) =>
|
const renderTags = (tags: GQL.Tag[]) =>
|
||||||
tags.map(tag => (
|
tags.map((tag) => (
|
||||||
<Link key={tag.id} to={NavUtils.makeTagScenesUrl(tag)}>
|
<Link key={tag.id} to={NavUtils.makeTagScenesUrl(tag)}>
|
||||||
<h6>{tag.name}</h6>
|
<h6>{tag.name}</h6>
|
||||||
</Link>
|
</Link>
|
||||||
));
|
));
|
||||||
|
|
||||||
const renderPerformers = (performers: Partial<GQL.Performer>[]) =>
|
const renderPerformers = (performers: Partial<GQL.Performer>[]) =>
|
||||||
performers.map(performer => (
|
performers.map((performer) => (
|
||||||
<Link key={performer.id} to={NavUtils.makePerformerScenesUrl(performer)}>
|
<Link key={performer.id} to={NavUtils.makePerformerScenesUrl(performer)}>
|
||||||
<h6>{performer.name}</h6>
|
<h6>{performer.name}</h6>
|
||||||
</Link>
|
</Link>
|
||||||
));
|
));
|
||||||
|
|
||||||
const renderMovies = (movies: Partial<GQL.SceneMovie>[]) => {
|
const renderMovies = (movies: Partial<GQL.SceneMovie>[]) => {
|
||||||
return movies.map(sceneMovie =>
|
return movies.map((sceneMovie) =>
|
||||||
!sceneMovie.movie ? (
|
!sceneMovie.movie ? undefined : (
|
||||||
undefined
|
|
||||||
) : (
|
|
||||||
<Link to={NavUtils.makeMovieScenesUrl(sceneMovie.movie)}>
|
<Link to={NavUtils.makeMovieScenesUrl(sceneMovie.movie)}>
|
||||||
<h6>{sceneMovie.movie.name}</h6>
|
<h6>{sceneMovie.movie.name}</h6>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ export const SceneMarkerList: React.FC = () => {
|
|||||||
const otherOperations = [
|
const otherOperations = [
|
||||||
{
|
{
|
||||||
text: "Play Random",
|
text: "Play Random",
|
||||||
onClick: playRandom
|
onClick: playRandom,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const listData = useSceneMarkersList({
|
const listData = useSceneMarkersList({
|
||||||
otherOperations,
|
otherOperations,
|
||||||
renderContent
|
renderContent,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function playRandom(
|
async function playRandom(
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ import { Button, Form } from "react-bootstrap";
|
|||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { StashService } from "src/core/StashService";
|
import { StashService } from "src/core/StashService";
|
||||||
import * as GQL from "src/core/generated-graphql";
|
import * as GQL from "src/core/generated-graphql";
|
||||||
import {
|
import { StudioSelect, LoadingIndicator } from "src/components/Shared";
|
||||||
StudioSelect,
|
|
||||||
LoadingIndicator
|
|
||||||
} from "src/components/Shared";
|
|
||||||
import { useToast } from "src/hooks";
|
import { useToast } from "src/hooks";
|
||||||
import MultiSet from "../Shared/MultiSet";
|
import MultiSet from "../Shared/MultiSet";
|
||||||
|
|
||||||
@@ -21,9 +18,13 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
const Toast = useToast();
|
const Toast = useToast();
|
||||||
const [rating, setRating] = useState<string>("");
|
const [rating, setRating] = useState<string>("");
|
||||||
const [studioId, setStudioId] = useState<string>();
|
const [studioId, setStudioId] = useState<string>();
|
||||||
const [performerMode, setPerformerMode] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
const [performerMode, setPerformerMode] = React.useState<
|
||||||
|
GQL.BulkUpdateIdMode
|
||||||
|
>(GQL.BulkUpdateIdMode.Add);
|
||||||
const [performerIds, setPerformerIds] = useState<string[]>();
|
const [performerIds, setPerformerIds] = useState<string[]>();
|
||||||
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
||||||
|
GQL.BulkUpdateIdMode.Add
|
||||||
|
);
|
||||||
const [tagIds, setTagIds] = useState<string[]>();
|
const [tagIds, setTagIds] = useState<string[]>();
|
||||||
|
|
||||||
const [updateScenes] = StashService.useBulkSceneUpdate(getSceneInput());
|
const [updateScenes] = StashService.useBulkSceneUpdate(getSceneInput());
|
||||||
@@ -31,10 +32,13 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
// Network state
|
// Network state
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
function makeBulkUpdateIds(ids: string[], mode: GQL.BulkUpdateIdMode) : GQL.BulkUpdateIds {
|
function makeBulkUpdateIds(
|
||||||
|
ids: string[],
|
||||||
|
mode: GQL.BulkUpdateIdMode
|
||||||
|
): GQL.BulkUpdateIds {
|
||||||
return {
|
return {
|
||||||
mode,
|
mode,
|
||||||
ids
|
ids,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,9 +50,9 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
const aggregateTagIds = getTagIds(props.selected);
|
const aggregateTagIds = getTagIds(props.selected);
|
||||||
|
|
||||||
const sceneInput: GQL.BulkSceneUpdateInput = {
|
const sceneInput: GQL.BulkSceneUpdateInput = {
|
||||||
ids: props.selected.map(scene => {
|
ids: props.selected.map((scene) => {
|
||||||
return scene.id;
|
return scene.id;
|
||||||
})
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
// if rating is undefined
|
// if rating is undefined
|
||||||
@@ -78,19 +82,31 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if performerIds are empty
|
// if performerIds are empty
|
||||||
if (performerMode === GQL.BulkUpdateIdMode.Set && (!performerIds || performerIds.length === 0)) {
|
if (
|
||||||
|
performerMode === GQL.BulkUpdateIdMode.Set &&
|
||||||
|
(!performerIds || performerIds.length === 0)
|
||||||
|
) {
|
||||||
// and all scenes have the same ids,
|
// and all scenes have the same ids,
|
||||||
if (aggregatePerformerIds.length > 0) {
|
if (aggregatePerformerIds.length > 0) {
|
||||||
// then unset the performerIds, otherwise ignore
|
// then unset the performerIds, otherwise ignore
|
||||||
sceneInput.performer_ids = makeBulkUpdateIds(performerIds || [], performerMode);
|
sceneInput.performer_ids = makeBulkUpdateIds(
|
||||||
|
performerIds || [],
|
||||||
|
performerMode
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if performerIds non-empty, then we are setting them
|
// if performerIds non-empty, then we are setting them
|
||||||
sceneInput.performer_ids = makeBulkUpdateIds(performerIds || [], performerMode);
|
sceneInput.performer_ids = makeBulkUpdateIds(
|
||||||
|
performerIds || [],
|
||||||
|
performerMode
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if tagIds non-empty, then we are setting them
|
// if tagIds non-empty, then we are setting them
|
||||||
if (tagMode === GQL.BulkUpdateIdMode.Set && (!tagIds || tagIds.length === 0)) {
|
if (
|
||||||
|
tagMode === GQL.BulkUpdateIdMode.Set &&
|
||||||
|
(!tagIds || tagIds.length === 0)
|
||||||
|
) {
|
||||||
// and all scenes have the same ids,
|
// and all scenes have the same ids,
|
||||||
if (aggregateTagIds.length > 0) {
|
if (aggregateTagIds.length > 0) {
|
||||||
// then unset the tagIds, otherwise ignore
|
// then unset the tagIds, otherwise ignore
|
||||||
@@ -157,11 +173,11 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
|
|
||||||
state.forEach((scene: GQL.SlimSceneDataFragment) => {
|
state.forEach((scene: GQL.SlimSceneDataFragment) => {
|
||||||
if (first) {
|
if (first) {
|
||||||
ret = scene.performers ? scene.performers.map(p => p.id).sort() : [];
|
ret = scene.performers ? scene.performers.map((p) => p.id).sort() : [];
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
const perfIds = scene.performers
|
const perfIds = scene.performers
|
||||||
? scene.performers.map(p => p.id).sort()
|
? scene.performers.map((p) => p.id).sort()
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
if (!_.isEqual(ret, perfIds)) {
|
if (!_.isEqual(ret, perfIds)) {
|
||||||
@@ -179,10 +195,10 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
|
|
||||||
state.forEach((scene: GQL.SlimSceneDataFragment) => {
|
state.forEach((scene: GQL.SlimSceneDataFragment) => {
|
||||||
if (first) {
|
if (first) {
|
||||||
ret = scene.tags ? scene.tags.map(t => t.id).sort() : [];
|
ret = scene.tags ? scene.tags.map((t) => t.id).sort() : [];
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
const tIds = scene.tags ? scene.tags.map(t => t.id).sort() : [];
|
const tIds = scene.tags ? scene.tags.map((t) => t.id).sort() : [];
|
||||||
|
|
||||||
if (!_.isEqual(ret, tIds)) {
|
if (!_.isEqual(ret, tIds)) {
|
||||||
ret = [];
|
ret = [];
|
||||||
@@ -204,8 +220,10 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
state.forEach((scene: GQL.SlimSceneDataFragment) => {
|
state.forEach((scene: GQL.SlimSceneDataFragment) => {
|
||||||
const sceneRating = scene.rating?.toString() ?? "";
|
const sceneRating = scene.rating?.toString() ?? "";
|
||||||
const sceneStudioID = scene?.studio?.id;
|
const sceneStudioID = scene?.studio?.id;
|
||||||
const scenePerformerIDs = (scene.performers ?? []).map(p => p.id).sort();
|
const scenePerformerIDs = (scene.performers ?? [])
|
||||||
const sceneTagIDs = (scene.tags ?? []).map(p => p.id).sort();
|
.map((p) => p.id)
|
||||||
|
.sort();
|
||||||
|
const sceneTagIDs = (scene.tags ?? []).map((p) => p.id).sort();
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
updateRating = sceneRating;
|
updateRating = sceneRating;
|
||||||
@@ -248,15 +266,19 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
) {
|
) {
|
||||||
let mode = GQL.BulkUpdateIdMode.Add;
|
let mode = GQL.BulkUpdateIdMode.Add;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers": mode = performerMode; break;
|
case "performers":
|
||||||
case "tags": mode = tagMode; break;
|
mode = performerMode;
|
||||||
|
break;
|
||||||
|
case "tags":
|
||||||
|
mode = tagMode;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MultiSet
|
<MultiSet
|
||||||
type={type}
|
type={type}
|
||||||
onUpdate={items => {
|
onUpdate={(items) => {
|
||||||
const itemIDs = items.map(i => i.id);
|
const itemIDs = items.map((i) => i.id);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers":
|
case "performers":
|
||||||
setPerformerIds(itemIDs);
|
setPerformerIds(itemIDs);
|
||||||
@@ -266,10 +288,14 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onSetMode={(mode) => {
|
onSetMode={(newMode) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers": setPerformerMode(mode); break;
|
case "performers":
|
||||||
case "tags": setTagMode(mode); break;
|
setPerformerMode(newMode);
|
||||||
|
break;
|
||||||
|
case "tags":
|
||||||
|
setTagMode(newMode);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
ids={ids ?? []}
|
ids={ids ?? []}
|
||||||
@@ -296,7 +322,7 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
setRating(event.currentTarget.value)
|
setRating(event.currentTarget.value)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{["", "1", "2", "3", "4", "5"].map(opt => (
|
{["", "1", "2", "3", "4", "5"].map((opt) => (
|
||||||
<option key={opt} value={opt}>
|
<option key={opt} value={opt}>
|
||||||
{opt}
|
{opt}
|
||||||
</option>
|
</option>
|
||||||
@@ -307,7 +333,7 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
<Form.Group controlId="studio" className="operation-item">
|
<Form.Group controlId="studio" className="operation-item">
|
||||||
<Form.Label>Studio</Form.Label>
|
<Form.Label>Studio</Form.Label>
|
||||||
<StudioSelect
|
<StudioSelect
|
||||||
onSelect={items => setStudioId(items[0]?.id)}
|
onSelect={(items) => setStudioId(items[0]?.id)}
|
||||||
ids={studioId ? [studioId] : []}
|
ids={studioId ? [studioId] : []}
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
.card-section {
|
.card-section {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding: .5rem 1rem 0 1rem;
|
padding: 0.5rem 1rem 0 1rem;
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -25,12 +25,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.scene-card-check {
|
.scene-card-check {
|
||||||
left: .5rem;
|
left: 0.5rem;
|
||||||
margin-top: -12px;
|
margin-top: -12px;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: .7rem;
|
top: 0.7rem;
|
||||||
width: 1.2rem;
|
width: 1.2rem;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
|
|
||||||
.file-info-panel {
|
.file-info-panel {
|
||||||
div {
|
div {
|
||||||
margin-bottom: .5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.studio-card {
|
.studio-card {
|
||||||
padding: .5rem;
|
padding: 0.5rem;
|
||||||
|
|
||||||
&-header {
|
&-header {
|
||||||
height: 150px;
|
height: 150px;
|
||||||
@@ -138,9 +138,9 @@
|
|||||||
color: $text-color;
|
color: $text-color;
|
||||||
display: block;
|
display: block;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
letter-spacing: -.03rem;
|
letter-spacing: -0.03rem;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: .7rem;
|
right: 0.7rem;
|
||||||
text-shadow: 0 0 3px #000;
|
text-shadow: 0 0 3px #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,10 +149,10 @@
|
|||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
height: 10%;
|
height: 10%;
|
||||||
max-width: 40%;
|
max-width: 40%;
|
||||||
opacity: .75;
|
opacity: 0.75;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: .7rem;
|
right: 0.7rem;
|
||||||
top: .7rem;
|
top: 0.7rem;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
|
|
||||||
.image-thumbnail {
|
.image-thumbnail {
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
a {
|
a {
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
letter-spacing: -.03rem;
|
letter-spacing: -0.03rem;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-shadow: 0 0 3px #000;
|
text-shadow: 0 0 3px #000;
|
||||||
@@ -173,7 +173,7 @@
|
|||||||
|
|
||||||
.overlay-resolution {
|
.overlay-resolution {
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
margin-right: .3rem;
|
margin-right: 0.3rem;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
.scene-specs-overlay,
|
.scene-specs-overlay,
|
||||||
.rating-banner,
|
.rating-banner,
|
||||||
.scene-studio-overlay {
|
.scene-studio-overlay {
|
||||||
transition: opacity .5s;
|
transition: opacity 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -198,12 +198,12 @@
|
|||||||
.rating-banner,
|
.rating-banner,
|
||||||
.scene-studio-overlay {
|
.scene-studio-overlay {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity .5s;
|
transition: opacity 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scene-studio-overlay:hover {
|
.scene-studio-overlay:hover {
|
||||||
opacity: .75;
|
opacity: 0.75;
|
||||||
transition: opacity .5s;
|
transition: opacity 0.5s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const SettingsAboutPanel: React.FC = () => {
|
|||||||
error: errorLatest,
|
error: errorLatest,
|
||||||
loading: loadingLatest,
|
loading: loadingLatest,
|
||||||
refetch,
|
refetch,
|
||||||
networkStatus
|
networkStatus,
|
||||||
} = StashService.useLatestVersion();
|
} = StashService.useLatestVersion();
|
||||||
|
|
||||||
function maybeRenderTag() {
|
function maybeRenderTag() {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
logLevel,
|
logLevel,
|
||||||
logAccess,
|
logAccess,
|
||||||
excludes,
|
excludes,
|
||||||
scraperUserAgent
|
scraperUserAgent,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -116,7 +116,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
GQL.StreamingResolutionEnum.StandardHd,
|
GQL.StreamingResolutionEnum.StandardHd,
|
||||||
GQL.StreamingResolutionEnum.FullHd,
|
GQL.StreamingResolutionEnum.FullHd,
|
||||||
GQL.StreamingResolutionEnum.FourK,
|
GQL.StreamingResolutionEnum.FourK,
|
||||||
GQL.StreamingResolutionEnum.Original
|
GQL.StreamingResolutionEnum.Original,
|
||||||
].map(resolutionToString);
|
].map(resolutionToString);
|
||||||
|
|
||||||
function resolutionToString(r: GQL.StreamingResolutionEnum | undefined) {
|
function resolutionToString(r: GQL.StreamingResolutionEnum | undefined) {
|
||||||
@@ -258,7 +258,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
}
|
}
|
||||||
value={resolutionToString(maxTranscodeSize)}
|
value={resolutionToString(maxTranscodeSize)}
|
||||||
>
|
>
|
||||||
{transcodeQualities.map(q => (
|
{transcodeQualities.map((q) => (
|
||||||
<option key={q} value={q}>
|
<option key={q} value={q}>
|
||||||
{q}
|
{q}
|
||||||
</option>
|
</option>
|
||||||
@@ -280,7 +280,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
}
|
}
|
||||||
value={resolutionToString(maxStreamingTranscodeSize)}
|
value={resolutionToString(maxStreamingTranscodeSize)}
|
||||||
>
|
>
|
||||||
{transcodeQualities.map(q => (
|
{transcodeQualities.map((q) => (
|
||||||
<option key={q} value={q}>
|
<option key={q} value={q}>
|
||||||
{q}
|
{q}
|
||||||
</option>
|
</option>
|
||||||
@@ -382,7 +382,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
}
|
}
|
||||||
value={logLevel}
|
value={logLevel}
|
||||||
>
|
>
|
||||||
{["Debug", "Info", "Warning", "Error"].map(o => (
|
{["Debug", "Info", "Warning", "Error"].map((o) => (
|
||||||
<option key={o} value={o}>
|
<option key={o} value={o}>
|
||||||
{o}
|
{o}
|
||||||
</option>
|
</option>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const SettingsInterfacePanel: React.FC = () => {
|
|||||||
showStudioAsText,
|
showStudioAsText,
|
||||||
css,
|
css,
|
||||||
cssEnabled,
|
cssEnabled,
|
||||||
language
|
language,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -119,7 +119,7 @@ export const SettingsInterfacePanel: React.FC = () => {
|
|||||||
<DurationInput
|
<DurationInput
|
||||||
className="row col col-4"
|
className="row col col-4"
|
||||||
numericValue={maximumLoopDuration}
|
numericValue={maximumLoopDuration}
|
||||||
onValueChange={duration => setMaximumLoopDuration(duration)}
|
onValueChange={(duration) => setMaximumLoopDuration(duration)}
|
||||||
/>
|
/>
|
||||||
<Form.Text className="text-muted">
|
<Form.Text className="text-muted">
|
||||||
Maximum scene duration where scene player will loop the video - 0 to
|
Maximum scene duration where scene player will loop the video - 0 to
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ export const SettingsLogsPanel: React.FC = () => {
|
|||||||
const { data: existingData } = StashService.useLogs();
|
const { data: existingData } = StashService.useLogs();
|
||||||
const [logLevel, setLogLevel] = useState<string>("Info");
|
const [logLevel, setLogLevel] = useState<string>("Info");
|
||||||
|
|
||||||
const oldData = (existingData?.logs ?? []).map(e => new LogEntry(e));
|
const oldData = (existingData?.logs ?? []).map((e) => new LogEntry(e));
|
||||||
const newData = (data?.loggingSubscribe ?? []).map(e => new LogEntry(e));
|
const newData = (data?.loggingSubscribe ?? []).map((e) => new LogEntry(e));
|
||||||
|
|
||||||
const filteredLogEntries = [...newData.reverse(), ...oldData]
|
const filteredLogEntries = [...newData.reverse(), ...oldData]
|
||||||
.filter(filterByLogLevel)
|
.filter(filterByLogLevel)
|
||||||
@@ -104,9 +104,9 @@ export const SettingsLogsPanel: React.FC = () => {
|
|||||||
className="col-6 col-sm-2 input-control"
|
className="col-6 col-sm-2 input-control"
|
||||||
as="select"
|
as="select"
|
||||||
defaultValue={logLevel}
|
defaultValue={logLevel}
|
||||||
onChange={event => setLogLevel(event.currentTarget.value)}
|
onChange={(event) => setLogLevel(event.currentTarget.value)}
|
||||||
>
|
>
|
||||||
{logLevels.map(level => (
|
{logLevels.map((level) => (
|
||||||
<option key={level} value={level}>
|
<option key={level} value={level}>
|
||||||
{level}
|
{level}
|
||||||
</option>
|
</option>
|
||||||
@@ -115,7 +115,7 @@ export const SettingsLogsPanel: React.FC = () => {
|
|||||||
</Form.Row>
|
</Form.Row>
|
||||||
<div className="logs">
|
<div className="logs">
|
||||||
{maybeRenderError}
|
{maybeRenderError}
|
||||||
{filteredLogEntries.map(logEntry => (
|
{filteredLogEntries.map((logEntry) => (
|
||||||
<LogElement logEntry={logEntry} key={logEntry.id} />
|
<LogElement logEntry={logEntry} key={logEntry.id} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const GenerateButton: React.FC = () => {
|
|||||||
sprites,
|
sprites,
|
||||||
previews,
|
previews,
|
||||||
markers,
|
markers,
|
||||||
transcodes
|
transcodes,
|
||||||
});
|
});
|
||||||
Toast.success({ content: "Started generating" });
|
Toast.success({ content: "Started generating" });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ export const SettingsTasksPanel: React.FC = () => {
|
|||||||
return {
|
return {
|
||||||
performers: autoTagPerformers ? wildcard : [],
|
performers: autoTagPerformers ? wildcard : [],
|
||||||
studios: autoTagStudios ? wildcard : [],
|
studios: autoTagStudios ? wildcard : [],
|
||||||
tags: autoTagTags ? wildcard : []
|
tags: autoTagTags ? wildcard : [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
.logs {
|
.logs {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
||||||
|
monospace;
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
max-height: 100vh;
|
max-height: 100vh;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
|
|||||||
|
|
||||||
function onRemoveDirectory(directory: string) {
|
function onRemoveDirectory(directory: string) {
|
||||||
const newSelectedDirectories = selectedDirectories.filter(
|
const newSelectedDirectories = selectedDirectories.filter(
|
||||||
dir => dir !== directory
|
(dir) => dir !== directory
|
||||||
);
|
);
|
||||||
setSelectedDirectories(newSelectedDirectories);
|
setSelectedDirectories(newSelectedDirectories);
|
||||||
props.onDirectoriesChanged(newSelectedDirectories);
|
props.onDirectoriesChanged(newSelectedDirectories);
|
||||||
@@ -66,7 +66,7 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
|
|||||||
</InputGroup.Append>
|
</InputGroup.Append>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<ul className="folder-list">
|
<ul className="folder-list">
|
||||||
{selectableDirectories.map(path => {
|
{selectableDirectories.map((path) => {
|
||||||
return (
|
return (
|
||||||
<li key={path} className="folder-item">
|
<li key={path} className="folder-item">
|
||||||
<Button
|
<Button
|
||||||
@@ -96,7 +96,7 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
|
|||||||
{error ? <h1>{error.message}</h1> : ""}
|
{error ? <h1>{error.message}</h1> : ""}
|
||||||
{renderDialog()}
|
{renderDialog()}
|
||||||
<Form.Group>
|
<Form.Group>
|
||||||
{selectedDirectories.map(path => {
|
{selectedDirectories.map((path) => {
|
||||||
return (
|
return (
|
||||||
<div key={path}>
|
<div key={path}>
|
||||||
{path}{" "}
|
{path}{" "}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const HoverPopover: React.FC<IHoverPopover> = ({
|
|||||||
className,
|
className,
|
||||||
placement = "top",
|
placement = "top",
|
||||||
onOpen,
|
onOpen,
|
||||||
onClose
|
onClose,
|
||||||
}) => {
|
}) => {
|
||||||
const [show, setShow] = useState(false);
|
const [show, setShow] = useState(false);
|
||||||
const triggerRef = useRef<HTMLDivElement>(null);
|
const triggerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const ImageInput: React.FC<IImageInput> = ({
|
|||||||
isEditing,
|
isEditing,
|
||||||
text,
|
text,
|
||||||
onImageChange,
|
onImageChange,
|
||||||
acceptSVG = false
|
acceptSVG = false,
|
||||||
}) => {
|
}) => {
|
||||||
if (!isEditing) return <div />;
|
if (!isEditing) return <div />;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const CLASSNAME_MESSAGE = `${CLASSNAME}-message`;
|
|||||||
|
|
||||||
const LoadingIndicator: React.FC<ILoadingProps> = ({
|
const LoadingIndicator: React.FC<ILoadingProps> = ({
|
||||||
message,
|
message,
|
||||||
inline = false
|
inline = false,
|
||||||
}) => (
|
}) => (
|
||||||
<div className={cx(CLASSNAME, { inline })}>
|
<div className={cx(CLASSNAME, { inline })}>
|
||||||
<Spinner animation="border" role="status">
|
<Spinner animation="border" role="status">
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const ModalComponent: React.FC<IModal> = ({
|
|||||||
header,
|
header,
|
||||||
cancel,
|
cancel,
|
||||||
accept,
|
accept,
|
||||||
onHide
|
onHide,
|
||||||
}) => (
|
}) => (
|
||||||
<Modal keyboard={false} onHide={onHide} show={show}>
|
<Modal keyboard={false} onHide={onHide} show={show}>
|
||||||
<Modal.Header>
|
<Modal.Header>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import * as GQL from "src/core/generated-graphql";
|
import * as GQL from "src/core/generated-graphql";
|
||||||
import { FilterSelect } from "./Select";
|
|
||||||
import { Button, InputGroup } from "react-bootstrap";
|
import { Button, InputGroup } from "react-bootstrap";
|
||||||
import { Icon } from "src/components/Shared";
|
import { Icon } from "src/components/Shared";
|
||||||
|
import { FilterSelect } from "./Select";
|
||||||
|
|
||||||
type ValidTypes =
|
type ValidTypes =
|
||||||
| GQL.SlimPerformerDataFragment
|
| GQL.SlimPerformerDataFragment
|
||||||
@@ -18,7 +18,9 @@ interface IMultiSetProps {
|
|||||||
onSetMode: (mode: GQL.BulkUpdateIdMode) => void;
|
onSetMode: (mode: GQL.BulkUpdateIdMode) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MultiSet: React.FunctionComponent<IMultiSetProps> = (props: IMultiSetProps) => {
|
const MultiSet: React.FunctionComponent<IMultiSetProps> = (
|
||||||
|
props: IMultiSetProps
|
||||||
|
) => {
|
||||||
function onUpdate(items: ValidTypes[]) {
|
function onUpdate(items: ValidTypes[]) {
|
||||||
props.onUpdate(items);
|
props.onUpdate(items);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ interface ISceneGallerySelect {
|
|||||||
const getSelectedValues = (selectedItems: ValueType<Option>) =>
|
const getSelectedValues = (selectedItems: ValueType<Option>) =>
|
||||||
selectedItems
|
selectedItems
|
||||||
? (Array.isArray(selectedItems) ? selectedItems : [selectedItems]).map(
|
? (Array.isArray(selectedItems) ? selectedItems : [selectedItems]).map(
|
||||||
item => item.value
|
(item) => item.value
|
||||||
)
|
)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
export const SceneGallerySelect: React.FC<ISceneGallerySelect> = props => {
|
export const SceneGallerySelect: React.FC<ISceneGallerySelect> = (props) => {
|
||||||
const { data, loading } = StashService.useValidGalleriesForScene(
|
const { data, loading } = StashService.useValidGalleriesForScene(
|
||||||
props.sceneId
|
props.sceneId
|
||||||
);
|
);
|
||||||
@@ -69,17 +69,17 @@ export const SceneGallerySelect: React.FC<ISceneGallerySelect> = props => {
|
|||||||
const items = (galleries.length > 0
|
const items = (galleries.length > 0
|
||||||
? [{ path: "None", id: "0" }, ...galleries]
|
? [{ path: "None", id: "0" }, ...galleries]
|
||||||
: []
|
: []
|
||||||
).map(g => ({ label: g.path, value: g.id }));
|
).map((g) => ({ label: g.path, value: g.id }));
|
||||||
|
|
||||||
const onChange = (selectedItems: ValueType<Option>) => {
|
const onChange = (selectedItems: ValueType<Option>) => {
|
||||||
const selectedItem = getSelectedValues(selectedItems)[0];
|
const selectedItem = getSelectedValues(selectedItems)[0];
|
||||||
props.onSelect(
|
props.onSelect(
|
||||||
selectedItem ? galleries.find(g => g.id === selectedItem) : undefined
|
selectedItem ? galleries.find((g) => g.id === selectedItem) : undefined
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const selectedOptions: Option[] = props.initialId
|
const selectedOptions: Option[] = props.initialId
|
||||||
? items.filter(item => props.initialId?.indexOf(item.value) !== -1)
|
? items.filter((item) => props.initialId?.indexOf(item.value) !== -1)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -98,7 +98,9 @@ interface IScrapePerformerSuggestProps {
|
|||||||
onSelectPerformer: (performer: GQL.ScrapedPerformerDataFragment) => void;
|
onSelectPerformer: (performer: GQL.ScrapedPerformerDataFragment) => void;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
}
|
}
|
||||||
export const ScrapePerformerSuggest: React.FC<IScrapePerformerSuggestProps> = props => {
|
export const ScrapePerformerSuggest: React.FC<IScrapePerformerSuggestProps> = (
|
||||||
|
props
|
||||||
|
) => {
|
||||||
const [query, setQuery] = React.useState<string>("");
|
const [query, setQuery] = React.useState<string>("");
|
||||||
const { data, loading } = StashService.useScrapePerformerList(
|
const { data, loading } = StashService.useScrapePerformerList(
|
||||||
props.scraperId,
|
props.scraperId,
|
||||||
@@ -106,9 +108,9 @@ export const ScrapePerformerSuggest: React.FC<IScrapePerformerSuggestProps> = pr
|
|||||||
);
|
);
|
||||||
|
|
||||||
const performers = data?.scrapePerformerList ?? [];
|
const performers = data?.scrapePerformerList ?? [];
|
||||||
const items = performers.map(item => ({
|
const items = performers.map((item) => ({
|
||||||
label: item.name ?? "",
|
label: item.name ?? "",
|
||||||
value: item.name ?? ""
|
value: item.name ?? "",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const onInputChange = useCallback(
|
const onInputChange = useCallback(
|
||||||
@@ -119,7 +121,7 @@ export const ScrapePerformerSuggest: React.FC<IScrapePerformerSuggestProps> = pr
|
|||||||
);
|
);
|
||||||
const onChange = (selectedItems: ValueType<Option>) => {
|
const onChange = (selectedItems: ValueType<Option>) => {
|
||||||
const name = getSelectedValues(selectedItems)[0];
|
const name = getSelectedValues(selectedItems)[0];
|
||||||
const performer = performers.find(p => p.name === name);
|
const performer = performers.find((p) => p.name === name);
|
||||||
if (performer) props.onSelectPerformer(performer);
|
if (performer) props.onSelectPerformer(performer);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -141,16 +143,16 @@ interface IMarkerSuggestProps {
|
|||||||
initialMarkerTitle?: string;
|
initialMarkerTitle?: string;
|
||||||
onChange: (title: string) => void;
|
onChange: (title: string) => void;
|
||||||
}
|
}
|
||||||
export const MarkerTitleSuggest: React.FC<IMarkerSuggestProps> = props => {
|
export const MarkerTitleSuggest: React.FC<IMarkerSuggestProps> = (props) => {
|
||||||
const { data, loading } = StashService.useMarkerStrings();
|
const { data, loading } = StashService.useMarkerStrings();
|
||||||
const suggestions = data?.markerStrings ?? [];
|
const suggestions = data?.markerStrings ?? [];
|
||||||
|
|
||||||
const onChange = (selectedItems: ValueType<Option>) =>
|
const onChange = (selectedItems: ValueType<Option>) =>
|
||||||
props.onChange(getSelectedValues(selectedItems)[0]);
|
props.onChange(getSelectedValues(selectedItems)[0]);
|
||||||
|
|
||||||
const items = suggestions.map(item => ({
|
const items = suggestions.map((item) => ({
|
||||||
label: item?.title ?? "",
|
label: item?.title ?? "",
|
||||||
value: item?.title ?? ""
|
value: item?.title ?? "",
|
||||||
}));
|
}));
|
||||||
const initialIds = props.initialMarkerTitle ? [props.initialMarkerTitle] : [];
|
const initialIds = props.initialMarkerTitle ? [props.initialMarkerTitle] : [];
|
||||||
return (
|
return (
|
||||||
@@ -167,7 +169,7 @@ export const MarkerTitleSuggest: React.FC<IMarkerSuggestProps> = props => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export const FilterSelect: React.FC<IFilterProps & ITypeProps> = props =>
|
export const FilterSelect: React.FC<IFilterProps & ITypeProps> = (props) =>
|
||||||
props.type === "performers" ? (
|
props.type === "performers" ? (
|
||||||
<PerformerSelect {...(props as IFilterProps)} />
|
<PerformerSelect {...(props as IFilterProps)} />
|
||||||
) : props.type === "studios" ? (
|
) : props.type === "studios" ? (
|
||||||
@@ -178,23 +180,23 @@ export const FilterSelect: React.FC<IFilterProps & ITypeProps> = props =>
|
|||||||
<TagSelect {...(props as IFilterProps)} />
|
<TagSelect {...(props as IFilterProps)} />
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PerformerSelect: React.FC<IFilterProps> = props => {
|
export const PerformerSelect: React.FC<IFilterProps> = (props) => {
|
||||||
const { data, loading } = StashService.useAllPerformersForFilter();
|
const { data, loading } = StashService.useAllPerformersForFilter();
|
||||||
|
|
||||||
const normalizedData = data?.allPerformers ?? [];
|
const normalizedData = data?.allPerformers ?? [];
|
||||||
const items: Option[] = normalizedData.map(item => ({
|
const items: Option[] = normalizedData.map((item) => ({
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name ?? ""
|
label: item.name ?? "",
|
||||||
}));
|
}));
|
||||||
const placeholder = props.noSelectionString ?? "Select performer...";
|
const placeholder = props.noSelectionString ?? "Select performer...";
|
||||||
const selectedOptions: Option[] = props.ids
|
const selectedOptions: Option[] = props.ids
|
||||||
? items.filter(item => props.ids?.indexOf(item.value) !== -1)
|
? items.filter((item) => props.ids?.indexOf(item.value) !== -1)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const onChange = (selectedItems: ValueType<Option>) => {
|
const onChange = (selectedItems: ValueType<Option>) => {
|
||||||
const selectedIds = getSelectedValues(selectedItems);
|
const selectedIds = getSelectedValues(selectedItems);
|
||||||
props.onSelect?.(
|
props.onSelect?.(
|
||||||
normalizedData.filter(item => selectedIds.indexOf(item.id) !== -1)
|
normalizedData.filter((item) => selectedIds.indexOf(item.id) !== -1)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -211,7 +213,7 @@ export const PerformerSelect: React.FC<IFilterProps> = props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const StudioSelect: React.FC<IFilterProps> = props => {
|
export const StudioSelect: React.FC<IFilterProps> = (props) => {
|
||||||
const { data, loading } = StashService.useAllStudiosForFilter();
|
const { data, loading } = StashService.useAllStudiosForFilter();
|
||||||
|
|
||||||
const normalizedData = data?.allStudios ?? [];
|
const normalizedData = data?.allStudios ?? [];
|
||||||
@@ -219,20 +221,20 @@ export const StudioSelect: React.FC<IFilterProps> = props => {
|
|||||||
const items = (normalizedData.length > 0
|
const items = (normalizedData.length > 0
|
||||||
? [{ name: "None", id: "0" }, ...normalizedData]
|
? [{ name: "None", id: "0" }, ...normalizedData]
|
||||||
: []
|
: []
|
||||||
).map(item => ({
|
).map((item) => ({
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name
|
label: item.name,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const placeholder = props.noSelectionString ?? "Select studio...";
|
const placeholder = props.noSelectionString ?? "Select studio...";
|
||||||
const selectedOptions: Option[] = props.ids
|
const selectedOptions: Option[] = props.ids
|
||||||
? items.filter(item => props.ids?.indexOf(item.value) !== -1)
|
? items.filter((item) => props.ids?.indexOf(item.value) !== -1)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const onChange = (selectedItems: ValueType<Option>) => {
|
const onChange = (selectedItems: ValueType<Option>) => {
|
||||||
const selectedIds = getSelectedValues(selectedItems);
|
const selectedIds = getSelectedValues(selectedItems);
|
||||||
props.onSelect?.(
|
props.onSelect?.(
|
||||||
normalizedData.filter(item => selectedIds.indexOf(item.id) !== -1)
|
normalizedData.filter((item) => selectedIds.indexOf(item.id) !== -1)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -249,7 +251,7 @@ export const StudioSelect: React.FC<IFilterProps> = props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MovieSelect: React.FC<IFilterProps> = props => {
|
export const MovieSelect: React.FC<IFilterProps> = (props) => {
|
||||||
const { data, loading } = StashService.useAllMoviesForFilter();
|
const { data, loading } = StashService.useAllMoviesForFilter();
|
||||||
|
|
||||||
const normalizedData = data?.allMovies ?? [];
|
const normalizedData = data?.allMovies ?? [];
|
||||||
@@ -257,20 +259,20 @@ export const MovieSelect: React.FC<IFilterProps> = props => {
|
|||||||
const items = (normalizedData.length > 0
|
const items = (normalizedData.length > 0
|
||||||
? [{ name: "None", id: "0" }, ...normalizedData]
|
? [{ name: "None", id: "0" }, ...normalizedData]
|
||||||
: []
|
: []
|
||||||
).map(item => ({
|
).map((item) => ({
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name
|
label: item.name,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const placeholder = props.noSelectionString ?? "Select movie...";
|
const placeholder = props.noSelectionString ?? "Select movie...";
|
||||||
const selectedOptions: Option[] = props.ids
|
const selectedOptions: Option[] = props.ids
|
||||||
? items.filter(item => props.ids?.indexOf(item.value) !== -1)
|
? items.filter((item) => props.ids?.indexOf(item.value) !== -1)
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
const onChange = (selectedItems: ValueType<Option>) => {
|
const onChange = (selectedItems: ValueType<Option>) => {
|
||||||
const selectedIds = getSelectedValues(selectedItems);
|
const selectedIds = getSelectedValues(selectedItems);
|
||||||
props.onSelect?.(
|
props.onSelect?.(
|
||||||
normalizedData.filter(item => selectedIds.indexOf(item.id) !== -1)
|
normalizedData.filter((item) => selectedIds.indexOf(item.id) !== -1)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -287,7 +289,7 @@ export const MovieSelect: React.FC<IFilterProps> = props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TagSelect: React.FC<IFilterProps> = props => {
|
export const TagSelect: React.FC<IFilterProps> = (props) => {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [selectedIds, setSelectedIds] = useState<string[]>(props.ids ?? []);
|
const [selectedIds, setSelectedIds] = useState<string[]>(props.ids ?? []);
|
||||||
const { data, loading: dataLoading } = StashService.useAllTagsForFilter();
|
const { data, loading: dataLoading } = StashService.useAllTagsForFilter();
|
||||||
@@ -299,25 +301,25 @@ export const TagSelect: React.FC<IFilterProps> = props => {
|
|||||||
|
|
||||||
const tags = data?.allTags ?? [];
|
const tags = data?.allTags ?? [];
|
||||||
const selected = tags
|
const selected = tags
|
||||||
.filter(tag => selectedTags.indexOf(tag.id) !== -1)
|
.filter((tag) => selectedTags.indexOf(tag.id) !== -1)
|
||||||
.map(tag => ({ value: tag.id, label: tag.name }));
|
.map((tag) => ({ value: tag.id, label: tag.name }));
|
||||||
const items: Option[] = tags.map(item => ({
|
const items: Option[] = tags.map((item) => ({
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name
|
label: item.name,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const onCreate = async (tagName: string) => {
|
const onCreate = async (tagName: string) => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const result = await createTag({
|
const result = await createTag({
|
||||||
variables: { name: tagName }
|
variables: { name: tagName },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result?.data?.tagCreate) {
|
if (result?.data?.tagCreate) {
|
||||||
setSelectedIds([...selectedIds, result.data.tagCreate.id]);
|
setSelectedIds([...selectedIds, result.data.tagCreate.id]);
|
||||||
props.onSelect?.(
|
props.onSelect?.(
|
||||||
[...tags, result.data.tagCreate].filter(
|
[...tags, result.data.tagCreate].filter(
|
||||||
item => selectedIds.indexOf(item.id) !== -1
|
(item) => selectedIds.indexOf(item.id) !== -1
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@@ -327,7 +329,7 @@ export const TagSelect: React.FC<IFilterProps> = props => {
|
|||||||
<span>
|
<span>
|
||||||
Created tag: <b>{tagName}</b>
|
Created tag: <b>{tagName}</b>
|
||||||
</span>
|
</span>
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -339,7 +341,7 @@ export const TagSelect: React.FC<IFilterProps> = props => {
|
|||||||
const selectedValues = getSelectedValues(selectedItems);
|
const selectedValues = getSelectedValues(selectedItems);
|
||||||
setSelectedIds(selectedValues);
|
setSelectedIds(selectedValues);
|
||||||
props.onSelect?.(
|
props.onSelect?.(
|
||||||
tags.filter(item => selectedValues.indexOf(item.id) !== -1)
|
tags.filter((item) => selectedValues.indexOf(item.id) !== -1)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -374,35 +376,35 @@ const SelectComponent: React.FC<ISelectProps & ITypeProps> = ({
|
|||||||
onInputChange,
|
onInputChange,
|
||||||
placeholder,
|
placeholder,
|
||||||
showDropdown = true,
|
showDropdown = true,
|
||||||
groupHeader
|
groupHeader,
|
||||||
}) => {
|
}) => {
|
||||||
const defaultValue =
|
const defaultValue =
|
||||||
items.filter(item => initialIds?.indexOf(item.value) !== -1) ?? null;
|
items.filter((item) => initialIds?.indexOf(item.value) !== -1) ?? null;
|
||||||
|
|
||||||
const options = groupHeader
|
const options = groupHeader
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
label: groupHeader,
|
label: groupHeader,
|
||||||
options: items
|
options: items,
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
: items;
|
: items;
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
option: (base: CSSProperties) => ({
|
option: (base: CSSProperties) => ({
|
||||||
...base,
|
...base,
|
||||||
color: "#000"
|
color: "#000",
|
||||||
}),
|
}),
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
container: (base: CSSProperties, state: any) => ({
|
container: (base: CSSProperties, state: any) => ({
|
||||||
...base,
|
...base,
|
||||||
zIndex: state.isFocused ? 10 : base.zIndex
|
zIndex: state.isFocused ? 10 : base.zIndex,
|
||||||
}),
|
}),
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
multiValueRemove: (base: CSSProperties, state: any) => ({
|
multiValueRemove: (base: CSSProperties, state: any) => ({
|
||||||
...base,
|
...base,
|
||||||
color: state.isFocused ? base.color : "#333333"
|
color: state.isFocused ? base.color : "#333333",
|
||||||
})
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
@@ -423,8 +425,8 @@ const SelectComponent: React.FC<ISelectProps & ITypeProps> = ({
|
|||||||
components: {
|
components: {
|
||||||
IndicatorSeparator: () => null,
|
IndicatorSeparator: () => null,
|
||||||
...((!showDropdown || isDisabled) && { DropdownIndicator: () => null }),
|
...((!showDropdown || isDisabled) && { DropdownIndicator: () => null }),
|
||||||
...(isDisabled && { MultiValueRemove: () => null })
|
...(isDisabled && { MultiValueRemove: () => null }),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return creatable ? (
|
return creatable ? (
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
PerformerDataFragment,
|
PerformerDataFragment,
|
||||||
SceneMarkerDataFragment,
|
SceneMarkerDataFragment,
|
||||||
TagDataFragment,
|
TagDataFragment,
|
||||||
MovieDataFragment
|
MovieDataFragment,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import { NavUtils, TextUtils } from "src/utils";
|
import { NavUtils, TextUtils } from "src/utils";
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export {
|
|||||||
FilterSelect,
|
FilterSelect,
|
||||||
PerformerSelect,
|
PerformerSelect,
|
||||||
StudioSelect,
|
StudioSelect,
|
||||||
TagSelect
|
TagSelect,
|
||||||
} from "./Select";
|
} from "./Select";
|
||||||
|
|
||||||
export { default as Icon } from "./Icon";
|
export { default as Icon } from "./Icon";
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
justify-content: left;
|
justify-content: left;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
margin-right: .5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.delete,
|
.delete,
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.folder-list {
|
.folder-list {
|
||||||
margin-top: .5rem 0 0 0;
|
margin-top: 0.5rem 0 0 0;
|
||||||
max-height: 30vw;
|
max-height: 30vw;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
@@ -70,8 +70,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.multi-set > div.input-group-prepend + div {
|
.multi-set > div.input-group-prepend + div {
|
||||||
position: relative;
|
|
||||||
flex: 1 1;
|
flex: 1 1;
|
||||||
min-width: 0;
|
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
min-width: 0;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ import { ImageUtils, TableUtils } from "src/utils";
|
|||||||
import {
|
import {
|
||||||
DetailsEditNavbar,
|
DetailsEditNavbar,
|
||||||
Modal,
|
Modal,
|
||||||
LoadingIndicator
|
LoadingIndicator,
|
||||||
} from "src/components/Shared";
|
} from "src/components/Shared";
|
||||||
import { useToast } from "src/hooks";
|
import { useToast } from "src/hooks";
|
||||||
import { StudioScenesPanel } from "./StudioScenesPanel";
|
import { StudioScenesPanel } from "./StudioScenesPanel";
|
||||||
@@ -83,7 +83,7 @@ export const Studio: React.FC = () => {
|
|||||||
const input: Partial<GQL.StudioCreateInput | GQL.StudioUpdateInput> = {
|
const input: Partial<GQL.StudioCreateInput | GQL.StudioUpdateInput> = {
|
||||||
name,
|
name,
|
||||||
url,
|
url,
|
||||||
image
|
image,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isNew) {
|
if (!isNew) {
|
||||||
@@ -155,7 +155,7 @@ export const Studio: React.FC = () => {
|
|||||||
<div
|
<div
|
||||||
className={cx("studio-details", {
|
className={cx("studio-details", {
|
||||||
"col ml-sm-5": !isNew,
|
"col ml-sm-5": !isNew,
|
||||||
"col-8": isNew
|
"col-8": isNew,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{isNew && <h2>Add Studio</h2>}
|
{isNew && <h2>Add Studio</h2>}
|
||||||
@@ -166,13 +166,13 @@ export const Studio: React.FC = () => {
|
|||||||
title: "Name",
|
title: "Name",
|
||||||
value: studio.name ?? "",
|
value: studio.name ?? "",
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setName
|
onChange: setName,
|
||||||
})}
|
})}
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "URL",
|
title: "URL",
|
||||||
value: url,
|
value: url,
|
||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setUrl
|
onChange: setUrl,
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export const StudioScenesPanel: React.FC<IStudioScenesPanel> = ({ studio }) => {
|
|||||||
function filterHook(filter: ListFilterModel) {
|
function filterHook(filter: ListFilterModel) {
|
||||||
const studioValue = { id: studio.id!, label: studio.name! };
|
const studioValue = { id: studio.id!, label: studio.name! };
|
||||||
// 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.type === "studios";
|
return c.type === "studios";
|
||||||
}) as StudiosCriterion;
|
}) as StudiosCriterion;
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ export const StudioScenesPanel: React.FC<IStudioScenesPanel> = ({ studio }) => {
|
|||||||
) {
|
) {
|
||||||
// add the studio if not present
|
// add the studio if not present
|
||||||
if (
|
if (
|
||||||
!studioCriterion.value.find(p => {
|
!studioCriterion.value.find((p) => {
|
||||||
return p.id === studio.id;
|
return p.id === studio.id;
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { StudioCard } from "./StudioCard";
|
|||||||
|
|
||||||
export const StudioList: React.FC = () => {
|
export const StudioList: React.FC = () => {
|
||||||
const listData = useStudiosList({
|
const listData = useStudiosList({
|
||||||
renderContent
|
renderContent,
|
||||||
});
|
});
|
||||||
|
|
||||||
function renderContent(
|
function renderContent(
|
||||||
@@ -19,7 +19,7 @@ export const StudioList: React.FC = () => {
|
|||||||
if (filter.displayMode === DisplayMode.Grid) {
|
if (filter.displayMode === DisplayMode.Grid) {
|
||||||
return (
|
return (
|
||||||
<div className="row px-xl-5 justify-content-center">
|
<div className="row px-xl-5 justify-content-center">
|
||||||
{result.data.findStudios.studios.map(studio => (
|
{result.data.findStudios.studios.map((studio) => (
|
||||||
<StudioCard key={studio.id} studio={studio} />
|
<StudioCard key={studio.id} studio={studio} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export const TagList: React.FC = () => {
|
|||||||
if (!data?.allTags) return <LoadingIndicator />;
|
if (!data?.allTags) return <LoadingIndicator />;
|
||||||
if (error) return <div>{error.message}</div>;
|
if (error) return <div>{error.message}</div>;
|
||||||
|
|
||||||
const tagElements = data.allTags.map(tag => {
|
const tagElements = data.allTags.map((tag) => {
|
||||||
return (
|
return (
|
||||||
<div key={tag.id} className="tag-list-row row">
|
<div key={tag.id} className="tag-list-row row">
|
||||||
<Button variant="link" onClick={() => setEditingTag(tag)}>
|
<Button variant="link" onClick={() => setEditingTag(tag)}>
|
||||||
@@ -154,7 +154,7 @@ export const TagList: React.FC = () => {
|
|||||||
accept={{
|
accept={{
|
||||||
onClick: onEdit,
|
onClick: onEdit,
|
||||||
variant: "danger",
|
variant: "danger",
|
||||||
text: editingTag?.id ? "Update" : "Create"
|
text: editingTag?.id ? "Update" : "Create",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Form.Group controlId="tag-name">
|
<Form.Group controlId="tag-name">
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
.tag-list {
|
.tag-list {
|
||||||
&-row {
|
&-row {
|
||||||
margin: .5rem 0;
|
margin: 0.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-button {
|
&-button {
|
||||||
margin: 0 .5rem;
|
margin: 0 0.5rem;
|
||||||
width: 8rem;
|
width: 8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
&-count {
|
&-count {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 .5rem;
|
margin: 0 0.5rem;
|
||||||
min-width: 6rem;
|
min-width: 6rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export const WallItem: React.FC<IWallItemProps> = (props: IWallItemProps) => {
|
|||||||
const [tags, setTags] = useState<JSX.Element[]>([]);
|
const [tags, setTags] = useState<JSX.Element[]>([]);
|
||||||
const config = StashService.useConfiguration();
|
const config = StashService.useConfiguration();
|
||||||
const videoHoverHook = VideoHoverHook.useVideoHover({
|
const videoHoverHook = VideoHoverHook.useVideoHover({
|
||||||
resetOnMouseLeave: true
|
resetOnMouseLeave: true,
|
||||||
});
|
});
|
||||||
const showTextContainer =
|
const showTextContainer =
|
||||||
config.data?.configuration.interface.wallShowTitle ?? true;
|
config.data?.configuration.interface.wallShowTitle ?? true;
|
||||||
@@ -86,7 +86,7 @@ export const WallItem: React.FC<IWallItemProps> = (props: IWallItemProps) => {
|
|||||||
props.sceneMarker.seconds
|
props.sceneMarker.seconds
|
||||||
)}`
|
)}`
|
||||||
);
|
);
|
||||||
const thisTags = props.sceneMarker.tags.map(tag => (
|
const thisTags = props.sceneMarker.tags.map((tag) => (
|
||||||
<span key={tag.id} className="wall-tag">
|
<span key={tag.id} className="wall-tag">
|
||||||
{tag.name}
|
{tag.name}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
.wall-overlay {
|
.wall-overlay {
|
||||||
background-color: rgba(0, 0, 0, .8);
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
transition: transform .5s ease-in-out;
|
transition: transform 0.5s ease-in-out;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.visible {
|
.visible {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity .5s ease-in-out;
|
transition: opacity 0.5s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity .5s ease-in-out;
|
transition: opacity 0.5s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.visible-unanimated {
|
.visible-unanimated {
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
max-height: 253px;
|
max-height: 253px;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: transform .5s;
|
transition: transform 0.5s;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.scene-wall-item-text-container {
|
.scene-wall-item-text-container {
|
||||||
background: linear-gradient(rgba(255, 255, 255, .25), rgba(255, 255, 255, .65));
|
background: linear-gradient(
|
||||||
|
rgba(255, 255, 255, 0.25),
|
||||||
|
rgba(255, 255, 255, 0.65)
|
||||||
|
);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
color: #444;
|
color: #444;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ export class StashService {
|
|||||||
const wsUrl = `${wsPlatformUrl.toString().slice(0, -1)}/graphql`;
|
const wsUrl = `${wsPlatformUrl.toString().slice(0, -1)}/graphql`;
|
||||||
|
|
||||||
const httpLink = new HttpLink({
|
const httpLink = new HttpLink({
|
||||||
uri: url
|
uri: url,
|
||||||
});
|
});
|
||||||
|
|
||||||
const wsLink = new WebSocketLink({
|
const wsLink = new WebSocketLink({
|
||||||
uri: wsUrl,
|
uri: wsUrl,
|
||||||
options: {
|
options: {
|
||||||
reconnect: true
|
reconnect: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const link = split(
|
const link = split(
|
||||||
@@ -66,7 +66,7 @@ export class StashService {
|
|||||||
StashService.cache = new InMemoryCache();
|
StashService.cache = new InMemoryCache();
|
||||||
StashService.client = new ApolloClient({
|
StashService.client = new ApolloClient({
|
||||||
link,
|
link,
|
||||||
cache: StashService.cache
|
cache: StashService.cache,
|
||||||
});
|
});
|
||||||
|
|
||||||
return StashService.client;
|
return StashService.client;
|
||||||
@@ -77,14 +77,14 @@ export class StashService {
|
|||||||
if (StashService.cache) {
|
if (StashService.cache) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const cache = StashService.cache as any;
|
const cache = StashService.cache as any;
|
||||||
const keyMatchers = queries.map(query => {
|
const keyMatchers = queries.map((query) => {
|
||||||
return new RegExp(`^${query}`);
|
return new RegExp(`^${query}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
const rootQuery = cache.data.data.ROOT_QUERY;
|
const rootQuery = cache.data.data.ROOT_QUERY;
|
||||||
Object.keys(rootQuery).forEach(key => {
|
Object.keys(rootQuery).forEach((key) => {
|
||||||
if (
|
if (
|
||||||
keyMatchers.some(matcher => {
|
keyMatchers.some((matcher) => {
|
||||||
return !!key.match(matcher);
|
return !!key.match(matcher);
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
@@ -97,8 +97,8 @@ export class StashService {
|
|||||||
public static useFindGalleries(filter: ListFilterModel) {
|
public static useFindGalleries(filter: ListFilterModel) {
|
||||||
return GQL.useFindGalleriesQuery({
|
return GQL.useFindGalleriesQuery({
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter()
|
filter: filter.makeFindFilter(),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,8 +116,8 @@ export class StashService {
|
|||||||
return GQL.useFindScenesQuery({
|
return GQL.useFindScenesQuery({
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter(),
|
filter: filter.makeFindFilter(),
|
||||||
scene_filter: sceneFilter
|
scene_filter: sceneFilter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +129,8 @@ export class StashService {
|
|||||||
query: GQL.FindScenesDocument,
|
query: GQL.FindScenesDocument,
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter(),
|
filter: filter.makeFindFilter(),
|
||||||
scene_filter: sceneFilter
|
scene_filter: sceneFilter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,8 +148,8 @@ export class StashService {
|
|||||||
return GQL.useFindSceneMarkersQuery({
|
return GQL.useFindSceneMarkersQuery({
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter(),
|
filter: filter.makeFindFilter(),
|
||||||
scene_marker_filter: sceneMarkerFilter
|
scene_marker_filter: sceneMarkerFilter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,24 +161,24 @@ export class StashService {
|
|||||||
query: GQL.FindSceneMarkersDocument,
|
query: GQL.FindSceneMarkersDocument,
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter(),
|
filter: filter.makeFindFilter(),
|
||||||
scene_marker_filter: sceneMarkerFilter
|
scene_marker_filter: sceneMarkerFilter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static useFindStudios(filter: ListFilterModel) {
|
public static useFindStudios(filter: ListFilterModel) {
|
||||||
return GQL.useFindStudiosQuery({
|
return GQL.useFindStudiosQuery({
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter()
|
filter: filter.makeFindFilter(),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static useFindMovies(filter: ListFilterModel) {
|
public static useFindMovies(filter: ListFilterModel) {
|
||||||
return GQL.useFindMoviesQuery({
|
return GQL.useFindMoviesQuery({
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter()
|
filter: filter.makeFindFilter(),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,8 +196,8 @@ export class StashService {
|
|||||||
return GQL.useFindPerformersQuery({
|
return GQL.useFindPerformersQuery({
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter(),
|
filter: filter.makeFindFilter(),
|
||||||
performer_filter: performerFilter
|
performer_filter: performerFilter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,8 +209,8 @@ export class StashService {
|
|||||||
query: GQL.FindPerformersDocument,
|
query: GQL.FindPerformersDocument,
|
||||||
variables: {
|
variables: {
|
||||||
filter: filter.makeFindFilter(),
|
filter: filter.makeFindFilter(),
|
||||||
performer_filter: performerFilter
|
performer_filter: performerFilter,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ export class StashService {
|
|||||||
"findSceneMarkers",
|
"findSceneMarkers",
|
||||||
"findScenes",
|
"findScenes",
|
||||||
"markerStrings",
|
"markerStrings",
|
||||||
"sceneMarkerTags"
|
"sceneMarkerTags",
|
||||||
];
|
];
|
||||||
|
|
||||||
public static useSceneMarkerCreate() {
|
public static useSceneMarkerCreate() {
|
||||||
@@ -257,7 +257,7 @@ export class StashService {
|
|||||||
public static useScrapePerformerList(scraperId: string, q: string) {
|
public static useScrapePerformerList(scraperId: string, q: string) {
|
||||||
return GQL.useScrapePerformerListQuery({
|
return GQL.useScrapePerformerListQuery({
|
||||||
variables: { scraper_id: scraperId, query: q },
|
variables: { scraper_id: scraperId, query: q },
|
||||||
skip: q === ""
|
skip: q === "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static useScrapePerformer(
|
public static useScrapePerformer(
|
||||||
@@ -265,7 +265,7 @@ export class StashService {
|
|||||||
scrapedPerformer: GQL.ScrapedPerformerInput
|
scrapedPerformer: GQL.ScrapedPerformerInput
|
||||||
) {
|
) {
|
||||||
return GQL.useScrapePerformerQuery({
|
return GQL.useScrapePerformerQuery({
|
||||||
variables: { scraper_id: scraperId, scraped_performer: scrapedPerformer }
|
variables: { scraper_id: scraperId, scraped_performer: scrapedPerformer },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ export class StashService {
|
|||||||
}
|
}
|
||||||
public static useValidGalleriesForScene(sceneId: string) {
|
public static useValidGalleriesForScene(sceneId: string) {
|
||||||
return GQL.useValidGalleriesForSceneQuery({
|
return GQL.useValidGalleriesForSceneQuery({
|
||||||
variables: { scene_id: sceneId }
|
variables: { scene_id: sceneId },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static useStats() {
|
public static useStats() {
|
||||||
@@ -308,7 +308,7 @@ export class StashService {
|
|||||||
public static useLatestVersion() {
|
public static useLatestVersion() {
|
||||||
return GQL.useLatestVersionQuery({
|
return GQL.useLatestVersionQuery({
|
||||||
notifyOnNetworkStatusChange: true,
|
notifyOnNetworkStatusChange: true,
|
||||||
errorPolicy: "ignore"
|
errorPolicy: "ignore",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ export class StashService {
|
|||||||
"findPerformers",
|
"findPerformers",
|
||||||
"findScenes",
|
"findScenes",
|
||||||
"findSceneMarkers",
|
"findSceneMarkers",
|
||||||
"allPerformers"
|
"allPerformers",
|
||||||
];
|
];
|
||||||
|
|
||||||
public static usePerformerCreate() {
|
public static usePerformerCreate() {
|
||||||
@@ -331,7 +331,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.performerMutationImpactedQueries
|
StashService.performerMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static usePerformerUpdate() {
|
public static usePerformerUpdate() {
|
||||||
@@ -339,7 +339,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.performerMutationImpactedQueries
|
StashService.performerMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static usePerformerDestroy() {
|
public static usePerformerDestroy() {
|
||||||
@@ -347,7 +347,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.performerMutationImpactedQueries
|
StashService.performerMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +357,7 @@ export class StashService {
|
|||||||
"findSceneMarkers",
|
"findSceneMarkers",
|
||||||
"findStudios",
|
"findStudios",
|
||||||
"findMovies",
|
"findMovies",
|
||||||
"allTags"
|
"allTags",
|
||||||
// TODO - add "findTags" when it is implemented
|
// TODO - add "findTags" when it is implemented
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -368,7 +368,7 @@ export class StashService {
|
|||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.sceneMutationImpactedQueries
|
StashService.sceneMutationImpactedQueries
|
||||||
),
|
),
|
||||||
refetchQueries: ["AllTagsForFilter"]
|
refetchQueries: ["AllTagsForFilter"],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +379,7 @@ export class StashService {
|
|||||||
"findSceneMarkers",
|
"findSceneMarkers",
|
||||||
"findStudios",
|
"findStudios",
|
||||||
"findMovies",
|
"findMovies",
|
||||||
"allTags"
|
"allTags",
|
||||||
];
|
];
|
||||||
|
|
||||||
public static useBulkSceneUpdate(input: GQL.BulkSceneUpdateInput) {
|
public static useBulkSceneUpdate(input: GQL.BulkSceneUpdateInput) {
|
||||||
@@ -388,7 +388,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.sceneBulkMutationImpactedQueries
|
StashService.sceneBulkMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,19 +398,19 @@ export class StashService {
|
|||||||
|
|
||||||
public static useSceneIncrementO(id: string) {
|
public static useSceneIncrementO(id: string) {
|
||||||
return GQL.useSceneIncrementOMutation({
|
return GQL.useSceneIncrementOMutation({
|
||||||
variables: { id }
|
variables: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static useSceneDecrementO(id: string) {
|
public static useSceneDecrementO(id: string) {
|
||||||
return GQL.useSceneDecrementOMutation({
|
return GQL.useSceneDecrementOMutation({
|
||||||
variables: { id }
|
variables: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static useSceneResetO(id: string) {
|
public static useSceneResetO(id: string) {
|
||||||
return GQL.useSceneResetOMutation({
|
return GQL.useSceneResetOMutation({
|
||||||
variables: { id }
|
variables: { id },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,20 +420,20 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.sceneMutationImpactedQueries
|
StashService.sceneMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static useSceneGenerateScreenshot() {
|
public static useSceneGenerateScreenshot() {
|
||||||
return GQL.useSceneGenerateScreenshotMutation({
|
return GQL.useSceneGenerateScreenshotMutation({
|
||||||
update: () => StashService.invalidateQueries(["findScenes"])
|
update: () => StashService.invalidateQueries(["findScenes"]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static studioMutationImpactedQueries = [
|
private static studioMutationImpactedQueries = [
|
||||||
"findStudios",
|
"findStudios",
|
||||||
"findScenes",
|
"findScenes",
|
||||||
"allStudios"
|
"allStudios",
|
||||||
];
|
];
|
||||||
|
|
||||||
public static useStudioCreate(input: GQL.StudioCreateInput) {
|
public static useStudioCreate(input: GQL.StudioCreateInput) {
|
||||||
@@ -442,7 +442,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.studioMutationImpactedQueries
|
StashService.studioMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +452,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.studioMutationImpactedQueries
|
StashService.studioMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,14 +462,14 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.studioMutationImpactedQueries
|
StashService.studioMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static movieMutationImpactedQueries = [
|
private static movieMutationImpactedQueries = [
|
||||||
"findMovies",
|
"findMovies",
|
||||||
"findScenes",
|
"findScenes",
|
||||||
"allMovies"
|
"allMovies",
|
||||||
];
|
];
|
||||||
|
|
||||||
public static useMovieCreate(input: GQL.MovieCreateInput) {
|
public static useMovieCreate(input: GQL.MovieCreateInput) {
|
||||||
@@ -478,7 +478,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.movieMutationImpactedQueries
|
StashService.movieMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,7 +488,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.movieMutationImpactedQueries
|
StashService.movieMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +498,7 @@ export class StashService {
|
|||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(
|
StashService.invalidateQueries(
|
||||||
StashService.movieMutationImpactedQueries
|
StashService.movieMutationImpactedQueries
|
||||||
)
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,20 +506,20 @@ export class StashService {
|
|||||||
"findScenes",
|
"findScenes",
|
||||||
"findSceneMarkers",
|
"findSceneMarkers",
|
||||||
"sceneMarkerTags",
|
"sceneMarkerTags",
|
||||||
"allTags"
|
"allTags",
|
||||||
];
|
];
|
||||||
|
|
||||||
public static useTagCreate(input: GQL.TagCreateInput) {
|
public static useTagCreate(input: GQL.TagCreateInput) {
|
||||||
return GQL.useTagCreateMutation({
|
return GQL.useTagCreateMutation({
|
||||||
variables: input,
|
variables: input,
|
||||||
refetchQueries: ["AllTags", "AllTagsForFilter"]
|
refetchQueries: ["AllTags", "AllTagsForFilter"],
|
||||||
// update: () => StashService.invalidateQueries(StashService.tagMutationImpactedQueries)
|
// update: () => StashService.invalidateQueries(StashService.tagMutationImpactedQueries)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static useTagUpdate(input: GQL.TagUpdateInput) {
|
public static useTagUpdate(input: GQL.TagUpdateInput) {
|
||||||
return GQL.useTagUpdateMutation({
|
return GQL.useTagUpdateMutation({
|
||||||
variables: input,
|
variables: input,
|
||||||
refetchQueries: ["AllTags", "AllTagsForFilter"]
|
refetchQueries: ["AllTags", "AllTagsForFilter"],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public static useTagDestroy(input: GQL.TagDestroyInput) {
|
public static useTagDestroy(input: GQL.TagDestroyInput) {
|
||||||
@@ -527,21 +527,21 @@ export class StashService {
|
|||||||
variables: input,
|
variables: input,
|
||||||
refetchQueries: ["AllTags", "AllTagsForFilter"],
|
refetchQueries: ["AllTags", "AllTagsForFilter"],
|
||||||
update: () =>
|
update: () =>
|
||||||
StashService.invalidateQueries(StashService.tagMutationImpactedQueries)
|
StashService.invalidateQueries(StashService.tagMutationImpactedQueries),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static useConfigureGeneral(input: GQL.ConfigGeneralInput) {
|
public static useConfigureGeneral(input: GQL.ConfigGeneralInput) {
|
||||||
return GQL.useConfigureGeneralMutation({
|
return GQL.useConfigureGeneralMutation({
|
||||||
variables: { input },
|
variables: { input },
|
||||||
refetchQueries: ["Configuration"]
|
refetchQueries: ["Configuration"],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static useConfigureInterface(input: GQL.ConfigInterfaceInput) {
|
public static useConfigureInterface(input: GQL.ConfigInterfaceInput) {
|
||||||
return GQL.useConfigureInterfaceMutation({
|
return GQL.useConfigureInterfaceMutation({
|
||||||
variables: { input },
|
variables: { input },
|
||||||
refetchQueries: ["Configuration"]
|
refetchQueries: ["Configuration"],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -555,19 +555,19 @@ export class StashService {
|
|||||||
|
|
||||||
public static useLogs() {
|
public static useLogs() {
|
||||||
return GQL.useLogsQuery({
|
return GQL.useLogsQuery({
|
||||||
fetchPolicy: "no-cache"
|
fetchPolicy: "no-cache",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static useJobStatus() {
|
public static useJobStatus() {
|
||||||
return GQL.useJobStatusQuery({
|
return GQL.useJobStatusQuery({
|
||||||
fetchPolicy: "no-cache"
|
fetchPolicy: "no-cache",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static mutateStopJob() {
|
public static mutateStopJob() {
|
||||||
return StashService.client.mutate<GQL.StopJobMutation>({
|
return StashService.client.mutate<GQL.StopJobMutation>({
|
||||||
mutation: GQL.StopJobDocument
|
mutation: GQL.StopJobDocument,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,8 +575,8 @@ export class StashService {
|
|||||||
return StashService.client.query<GQL.ScrapeFreeonesQuery>({
|
return StashService.client.query<GQL.ScrapeFreeonesQuery>({
|
||||||
query: GQL.ScrapeFreeonesDocument,
|
query: GQL.ScrapeFreeonesDocument,
|
||||||
variables: {
|
variables: {
|
||||||
performer_name: performerName
|
performer_name: performerName,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,8 +588,8 @@ export class StashService {
|
|||||||
query: GQL.ScrapePerformerDocument,
|
query: GQL.ScrapePerformerDocument,
|
||||||
variables: {
|
variables: {
|
||||||
scraper_id: scraperId,
|
scraper_id: scraperId,
|
||||||
scraped_performer: scrapedPerformer
|
scraped_performer: scrapedPerformer,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,8 +597,8 @@ export class StashService {
|
|||||||
return StashService.client.query<GQL.ScrapePerformerUrlQuery>({
|
return StashService.client.query<GQL.ScrapePerformerUrlQuery>({
|
||||||
query: GQL.ScrapePerformerUrlDocument,
|
query: GQL.ScrapePerformerUrlDocument,
|
||||||
variables: {
|
variables: {
|
||||||
url
|
url,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,8 +606,8 @@ export class StashService {
|
|||||||
return StashService.client.query<GQL.ScrapeSceneUrlQuery>({
|
return StashService.client.query<GQL.ScrapeSceneUrlQuery>({
|
||||||
query: GQL.ScrapeSceneUrlDocument,
|
query: GQL.ScrapeSceneUrlDocument,
|
||||||
variables: {
|
variables: {
|
||||||
url
|
url,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,54 +619,54 @@ export class StashService {
|
|||||||
query: GQL.ScrapeSceneDocument,
|
query: GQL.ScrapeSceneDocument,
|
||||||
variables: {
|
variables: {
|
||||||
scraper_id: scraperId,
|
scraper_id: scraperId,
|
||||||
scene
|
scene,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static mutateMetadataScan(input: GQL.ScanMetadataInput) {
|
public static mutateMetadataScan(input: GQL.ScanMetadataInput) {
|
||||||
return StashService.client.mutate<GQL.MetadataScanMutation>({
|
return StashService.client.mutate<GQL.MetadataScanMutation>({
|
||||||
mutation: GQL.MetadataScanDocument,
|
mutation: GQL.MetadataScanDocument,
|
||||||
variables: { input }
|
variables: { input },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static mutateMetadataAutoTag(input: GQL.AutoTagMetadataInput) {
|
public static mutateMetadataAutoTag(input: GQL.AutoTagMetadataInput) {
|
||||||
return StashService.client.mutate<GQL.MetadataAutoTagMutation>({
|
return StashService.client.mutate<GQL.MetadataAutoTagMutation>({
|
||||||
mutation: GQL.MetadataAutoTagDocument,
|
mutation: GQL.MetadataAutoTagDocument,
|
||||||
variables: { input }
|
variables: { input },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static mutateMetadataGenerate(input: GQL.GenerateMetadataInput) {
|
public static mutateMetadataGenerate(input: GQL.GenerateMetadataInput) {
|
||||||
return StashService.client.mutate<GQL.MetadataGenerateMutation>({
|
return StashService.client.mutate<GQL.MetadataGenerateMutation>({
|
||||||
mutation: GQL.MetadataGenerateDocument,
|
mutation: GQL.MetadataGenerateDocument,
|
||||||
variables: { input }
|
variables: { input },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static mutateMetadataClean() {
|
public static mutateMetadataClean() {
|
||||||
return StashService.client.mutate<GQL.MetadataCleanMutation>({
|
return StashService.client.mutate<GQL.MetadataCleanMutation>({
|
||||||
mutation: GQL.MetadataCleanDocument
|
mutation: GQL.MetadataCleanDocument,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static mutateMetadataExport() {
|
public static mutateMetadataExport() {
|
||||||
return StashService.client.mutate<GQL.MetadataExportMutation>({
|
return StashService.client.mutate<GQL.MetadataExportMutation>({
|
||||||
mutation: GQL.MetadataExportDocument
|
mutation: GQL.MetadataExportDocument,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static mutateMetadataImport() {
|
public static mutateMetadataImport() {
|
||||||
return StashService.client.mutate<GQL.MetadataImportMutation>({
|
return StashService.client.mutate<GQL.MetadataImportMutation>({
|
||||||
mutation: GQL.MetadataImportDocument
|
mutation: GQL.MetadataImportDocument,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static querySceneByPathRegex(filter: GQL.FindFilterType) {
|
public static querySceneByPathRegex(filter: GQL.FindFilterType) {
|
||||||
return StashService.client.query<GQL.FindScenesByPathRegexQuery>({
|
return StashService.client.query<GQL.FindScenesByPathRegexQuery>({
|
||||||
query: GQL.FindScenesByPathRegexDocument,
|
query: GQL.FindScenesByPathRegexDocument,
|
||||||
variables: { filter }
|
variables: { filter },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,26 +677,28 @@ export class StashService {
|
|||||||
return StashService.client.query<GQL.ParseSceneFilenamesQuery>({
|
return StashService.client.query<GQL.ParseSceneFilenamesQuery>({
|
||||||
query: GQL.ParseSceneFilenamesDocument,
|
query: GQL.ParseSceneFilenamesDocument,
|
||||||
variables: { filter, config },
|
variables: { filter, config },
|
||||||
fetchPolicy: "network-only"
|
fetchPolicy: "network-only",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static stringGenderMap = new Map<string, GQL.GenderEnum>(
|
private static stringGenderMap = new Map<string, GQL.GenderEnum>([
|
||||||
[["Male", GQL.GenderEnum.Male],
|
["Male", GQL.GenderEnum.Male],
|
||||||
["Female", GQL.GenderEnum.Female],
|
["Female", GQL.GenderEnum.Female],
|
||||||
["Transgender Male", GQL.GenderEnum.TransgenderMale],
|
["Transgender Male", GQL.GenderEnum.TransgenderMale],
|
||||||
["Transgender Female", GQL.GenderEnum.TransgenderFemale],
|
["Transgender Female", GQL.GenderEnum.TransgenderFemale],
|
||||||
["Intersex", GQL.GenderEnum.Intersex]]
|
["Intersex", GQL.GenderEnum.Intersex],
|
||||||
);
|
]);
|
||||||
|
|
||||||
public static genderToString(value?: GQL.GenderEnum) {
|
public static genderToString(value?: GQL.GenderEnum) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const foundEntry = Array.from(StashService.stringGenderMap.entries()).find((e) => {
|
const foundEntry = Array.from(StashService.stringGenderMap.entries()).find(
|
||||||
|
(e) => {
|
||||||
return e[1] === value;
|
return e[1] === value;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (foundEntry) {
|
if (foundEntry) {
|
||||||
return foundEntry[0];
|
return foundEntry[0];
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ import {
|
|||||||
FindStudiosQueryResult,
|
FindStudiosQueryResult,
|
||||||
FindPerformersQueryResult,
|
FindPerformersQueryResult,
|
||||||
FindMoviesQueryResult,
|
FindMoviesQueryResult,
|
||||||
MovieDataFragment
|
MovieDataFragment,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
import {
|
import {
|
||||||
useInterfaceLocalForage,
|
useInterfaceLocalForage,
|
||||||
IInterfaceConfig
|
IInterfaceConfig,
|
||||||
} from "src/hooks/LocalForage";
|
} from "src/hooks/LocalForage";
|
||||||
import { LoadingIndicator } from "src/components/Shared";
|
import { LoadingIndicator } from "src/components/Shared";
|
||||||
import { ListFilter } from "src/components/List/ListFilter";
|
import { ListFilter } from "src/components/List/ListFilter";
|
||||||
@@ -100,14 +100,14 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
|
|
||||||
const updateInterfaceConfig = useCallback(
|
const updateInterfaceConfig = useCallback(
|
||||||
(updatedFilter: ListFilterModel) => {
|
(updatedFilter: ListFilterModel) => {
|
||||||
setInterfaceState(config => {
|
setInterfaceState((config) => {
|
||||||
const data = { ...config } as IInterfaceConfig;
|
const data = { ...config } as IInterfaceConfig;
|
||||||
data.queries = {
|
data.queries = {
|
||||||
[options.filterMode]: {
|
[options.filterMode]: {
|
||||||
filter: updatedFilter.makeQueryParameters(),
|
filter: updatedFilter.makeQueryParameters(),
|
||||||
itemsPerPage: updatedFilter.itemsPerPage,
|
itemsPerPage: updatedFilter.itemsPerPage,
|
||||||
currentPage: updatedFilter.currentPage
|
currentPage: updatedFilter.currentPage,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
@@ -133,7 +133,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
sortdir: storedFilter.sortdir,
|
sortdir: storedFilter.sortdir,
|
||||||
disp: storedFilter.disp,
|
disp: storedFilter.disp,
|
||||||
perPage: storedFilter.perPage,
|
perPage: storedFilter.perPage,
|
||||||
...queryFilter
|
...queryFilter,
|
||||||
}
|
}
|
||||||
: storedFilter;
|
: storedFilter;
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
options.subComponent,
|
options.subComponent,
|
||||||
options.filterMode,
|
options.filterMode,
|
||||||
forageInitialised,
|
forageInitialised,
|
||||||
updateInterfaceConfig
|
updateInterfaceConfig,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function getFilter() {
|
function getFilter() {
|
||||||
@@ -221,7 +221,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
const newFilter = _.cloneDeep(filter);
|
const newFilter = _.cloneDeep(filter);
|
||||||
|
|
||||||
// Find if we are editing an existing criteria, then modify that. Or create a new one.
|
// Find if we are editing an existing criteria, then modify that. Or create a new one.
|
||||||
const existingIndex = newFilter.criteria.findIndex(c => {
|
const existingIndex = newFilter.criteria.findIndex((c) => {
|
||||||
// If we modified an existing criterion, then look for the old id.
|
// If we modified an existing criterion, then look for the old id.
|
||||||
const id = oldId || criterion.getId();
|
const id = oldId || criterion.getId();
|
||||||
return c.getId() === id;
|
return c.getId() === id;
|
||||||
@@ -234,7 +234,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
|
|
||||||
// Remove duplicate modifiers
|
// Remove duplicate modifiers
|
||||||
newFilter.criteria = newFilter.criteria.filter((obj, pos, arr) => {
|
newFilter.criteria = newFilter.criteria.filter((obj, pos, arr) => {
|
||||||
return arr.map(mapObj => mapObj.getId()).indexOf(obj.getId()) === pos;
|
return arr.map((mapObj) => mapObj.getId()).indexOf(obj.getId()) === pos;
|
||||||
});
|
});
|
||||||
|
|
||||||
newFilter.currentPage = 1;
|
newFilter.currentPage = 1;
|
||||||
@@ -244,7 +244,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
function onRemoveCriterion(removedCriterion: Criterion) {
|
function onRemoveCriterion(removedCriterion: Criterion) {
|
||||||
const newFilter = _.cloneDeep(filter);
|
const newFilter = _.cloneDeep(filter);
|
||||||
newFilter.criteria = newFilter.criteria.filter(
|
newFilter.criteria = newFilter.criteria.filter(
|
||||||
criterion => criterion.getId() !== removedCriterion.getId()
|
(criterion) => criterion.getId() !== removedCriterion.getId()
|
||||||
);
|
);
|
||||||
newFilter.currentPage = 1;
|
newFilter.currentPage = 1;
|
||||||
updateQueryParams(newFilter);
|
updateQueryParams(newFilter);
|
||||||
@@ -281,7 +281,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
const subset = items.slice(start, end + 1);
|
const subset = items.slice(start, end + 1);
|
||||||
const newSelectedIds: Set<string> = new Set();
|
const newSelectedIds: Set<string> = new Set();
|
||||||
|
|
||||||
subset.forEach(item => {
|
subset.forEach((item) => {
|
||||||
newSelectedIds.add(item.id);
|
newSelectedIds.add(item.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -293,12 +293,12 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
let thisIndex = -1;
|
let thisIndex = -1;
|
||||||
|
|
||||||
if (lastClickedId) {
|
if (lastClickedId) {
|
||||||
startIndex = items.findIndex(item => {
|
startIndex = items.findIndex((item) => {
|
||||||
return item.id === lastClickedId;
|
return item.id === lastClickedId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
thisIndex = items.findIndex(item => {
|
thisIndex = items.findIndex((item) => {
|
||||||
return item.id === id;
|
return item.id === id;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -315,7 +315,7 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
|
|
||||||
function onSelectAll() {
|
function onSelectAll() {
|
||||||
const newSelectedIds: Set<string> = new Set();
|
const newSelectedIds: Set<string> = new Set();
|
||||||
items.forEach(item => {
|
items.forEach((item) => {
|
||||||
newSelectedIds.add(item.id);
|
newSelectedIds.add(item.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -334,12 +334,12 @@ const useList = <QueryResult extends IQueryResult, QueryData extends IDataItem>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const otherOperations = options.otherOperations
|
const otherOperations = options.otherOperations
|
||||||
? options.otherOperations.map(o => {
|
? options.otherOperations.map((o) => {
|
||||||
return {
|
return {
|
||||||
text: o.text,
|
text: o.text,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
o.onClick(result, filter, selectedIds);
|
o.onClick(result, filter, selectedIds);
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
@@ -401,7 +401,7 @@ export const useScenesList = (props: IListHookOptions<FindScenesQueryResult>) =>
|
|||||||
getData: (result: FindScenesQueryResult) =>
|
getData: (result: FindScenesQueryResult) =>
|
||||||
result?.data?.findScenes?.scenes ?? [],
|
result?.data?.findScenes?.scenes ?? [],
|
||||||
getCount: (result: FindScenesQueryResult) =>
|
getCount: (result: FindScenesQueryResult) =>
|
||||||
result?.data?.findScenes?.count ?? 0
|
result?.data?.findScenes?.count ?? 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useSceneMarkersList = (
|
export const useSceneMarkersList = (
|
||||||
@@ -414,7 +414,7 @@ export const useSceneMarkersList = (
|
|||||||
getData: (result: FindSceneMarkersQueryResult) =>
|
getData: (result: FindSceneMarkersQueryResult) =>
|
||||||
result?.data?.findSceneMarkers?.scene_markers ?? [],
|
result?.data?.findSceneMarkers?.scene_markers ?? [],
|
||||||
getCount: (result: FindSceneMarkersQueryResult) =>
|
getCount: (result: FindSceneMarkersQueryResult) =>
|
||||||
result?.data?.findSceneMarkers?.count ?? 0
|
result?.data?.findSceneMarkers?.count ?? 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useGalleriesList = (
|
export const useGalleriesList = (
|
||||||
@@ -427,7 +427,7 @@ export const useGalleriesList = (
|
|||||||
getData: (result: FindGalleriesQueryResult) =>
|
getData: (result: FindGalleriesQueryResult) =>
|
||||||
result?.data?.findGalleries?.galleries ?? [],
|
result?.data?.findGalleries?.galleries ?? [],
|
||||||
getCount: (result: FindGalleriesQueryResult) =>
|
getCount: (result: FindGalleriesQueryResult) =>
|
||||||
result?.data?.findGalleries?.count ?? 0
|
result?.data?.findGalleries?.count ?? 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useStudiosList = (
|
export const useStudiosList = (
|
||||||
@@ -440,7 +440,7 @@ export const useStudiosList = (
|
|||||||
getData: (result: FindStudiosQueryResult) =>
|
getData: (result: FindStudiosQueryResult) =>
|
||||||
result?.data?.findStudios?.studios ?? [],
|
result?.data?.findStudios?.studios ?? [],
|
||||||
getCount: (result: FindStudiosQueryResult) =>
|
getCount: (result: FindStudiosQueryResult) =>
|
||||||
result?.data?.findStudios?.count ?? 0
|
result?.data?.findStudios?.count ?? 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const usePerformersList = (
|
export const usePerformersList = (
|
||||||
@@ -453,7 +453,7 @@ export const usePerformersList = (
|
|||||||
getData: (result: FindPerformersQueryResult) =>
|
getData: (result: FindPerformersQueryResult) =>
|
||||||
result?.data?.findPerformers?.performers ?? [],
|
result?.data?.findPerformers?.performers ?? [],
|
||||||
getCount: (result: FindPerformersQueryResult) =>
|
getCount: (result: FindPerformersQueryResult) =>
|
||||||
result?.data?.findPerformers?.count ?? 0
|
result?.data?.findPerformers?.count ?? 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useMoviesList = (props: IListHookOptions<FindMoviesQueryResult>) =>
|
export const useMoviesList = (props: IListHookOptions<FindMoviesQueryResult>) =>
|
||||||
@@ -464,5 +464,5 @@ export const useMoviesList = (props: IListHookOptions<FindMoviesQueryResult>) =>
|
|||||||
getData: (result: FindMoviesQueryResult) =>
|
getData: (result: FindMoviesQueryResult) =>
|
||||||
result?.data?.findMovies?.movies ?? [],
|
result?.data?.findMovies?.movies ?? [],
|
||||||
getCount: (result: FindMoviesQueryResult) =>
|
getCount: (result: FindMoviesQueryResult) =>
|
||||||
result?.data?.findMovies?.count ?? 0
|
result?.data?.findMovies?.count ?? 0,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ export const ToastProvider: React.FC = ({ children }) => {
|
|||||||
const [toasts, setToasts] = useState<IActiveToast[]>([]);
|
const [toasts, setToasts] = useState<IActiveToast[]>([]);
|
||||||
|
|
||||||
const removeToast = (id: number) =>
|
const removeToast = (id: number) =>
|
||||||
setToasts(toasts.filter(item => item.id !== id));
|
setToasts(toasts.filter((item) => item.id !== id));
|
||||||
|
|
||||||
const toastItems = toasts.map(toast => (
|
const toastItems = toasts.map((toast) => (
|
||||||
<Toast
|
<Toast
|
||||||
autohide
|
autohide
|
||||||
key={toast.id}
|
key={toast.id}
|
||||||
@@ -55,9 +55,9 @@ function createHookObject(toastFunc: (toast: IToast) => void) {
|
|||||||
toastFunc({
|
toastFunc({
|
||||||
variant: "danger",
|
variant: "danger",
|
||||||
header: "Error",
|
header: "Error",
|
||||||
content: error.message ?? error.toString()
|
content: error.message ?? error.toString(),
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export class VideoHoverHook {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (videoTag.paused && !data.isPlaying.current) {
|
if (videoTag.paused && !data.isPlaying.current) {
|
||||||
videoTag.play().catch(error => {
|
videoTag.play().catch((error) => {
|
||||||
console.log(error.message);
|
console.log(error.message);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ export {
|
|||||||
useSceneMarkersList,
|
useSceneMarkersList,
|
||||||
useGalleriesList,
|
useGalleriesList,
|
||||||
useStudiosList,
|
useStudiosList,
|
||||||
usePerformersList
|
usePerformersList,
|
||||||
} from "./ListHook";
|
} from "./ListHook";
|
||||||
|
|||||||
@@ -32,18 +32,23 @@ a {
|
|||||||
|
|
||||||
code,
|
code,
|
||||||
.code {
|
.code {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
||||||
|
monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-control,
|
.input-control,
|
||||||
.text-input {
|
.text-input {
|
||||||
border: 0;
|
border: 0;
|
||||||
box-shadow: 0 0 0 0 rgba(19, 124, 189, 0), 0 0 0 0 rgba(19, 124, 189, 0), 0 0 0 0 rgba(19, 124, 189, 0), inset 0 0 0 1px rgba(16, 22, 26, .3), inset 0 1px 1px rgba(16, 22, 26, .4);
|
box-shadow: 0 0 0 0 rgba(19, 124, 189, 0), 0 0 0 0 rgba(19, 124, 189, 0),
|
||||||
|
0 0 0 0 rgba(19, 124, 189, 0), inset 0 0 0 1px rgba(16, 22, 26, 0.3),
|
||||||
|
inset 0 1px 1px rgba(16, 22, 26, 0.4);
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border: 0;
|
border: 0;
|
||||||
box-shadow: 0 0 0 1px $primary, 0 0 0 1px $primary, 0 0 0 3px rgba(19, 124, 189, .3), inset 0 0 0 1px rgba(16, 22, 26, .3), inset 0 1px 1px rgba(16, 22, 26, .4);
|
box-shadow: 0 0 0 1px $primary, 0 0 0 1px $primary,
|
||||||
|
0 0 0 3px rgba(19, 124, 189, 0.3), inset 0 0 0 1px rgba(16, 22, 26, 0.3),
|
||||||
|
inset 0 1px 1px rgba(16, 22, 26, 0.4);
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,7 +212,7 @@ div.react-select__menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.react-select__option--is-focused {
|
.react-select__option--is-focused {
|
||||||
background-color: rgba(167, 182, 194, .3);
|
background-color: rgba(167, 182, 194, 0.3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,8 +256,8 @@ div.react-select__menu {
|
|||||||
color: $dark-text;
|
color: $dark-text;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1rem;
|
line-height: 1rem;
|
||||||
margin-left: .5rem;
|
margin-left: 0.5rem;
|
||||||
opacity: .5;
|
opacity: 0.5;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@@ -308,7 +313,7 @@ div.react-select__menu {
|
|||||||
.rating-banner {
|
.rating-banner {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: block;
|
display: block;
|
||||||
font-size: .86rem;
|
font-size: 0.86rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
left: -46px;
|
left: -46px;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
@@ -324,7 +329,8 @@ div.react-select__menu {
|
|||||||
.card {
|
.card {
|
||||||
background-color: #30404d;
|
background-color: #30404d;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-shadow: 0 0 0 1px rgba(16, 22, 26, .4), 0 0 0 rgba(16, 22, 26, 0), 0 0 0 rgba(16, 22, 26, 0);
|
box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.4), 0 0 0 rgba(16, 22, 26, 0),
|
||||||
|
0 0 0 rgba(16, 22, 26, 0);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,12 +374,13 @@ div.react-select__menu {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
input[type=file], /* FF, IE7+, chrome (except button) */
|
input[type="file"], /* FF, IE7+, chrome (except button) */
|
||||||
input[type=file]::-webkit-file-upload-button { /* chromes and blink button */
|
input[type="file"]::-webkit-file-upload-button {
|
||||||
|
/* chromes and blink button */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
[type=file] {
|
[type="file"] {
|
||||||
display: block;
|
display: block;
|
||||||
filter: alpha(opacity=0);
|
filter: alpha(opacity=0);
|
||||||
font-size: 999px;
|
font-size: 999px;
|
||||||
@@ -388,7 +395,7 @@ div.react-select__menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.fa-icon {
|
.fa-icon {
|
||||||
margin: 0 .4rem;
|
margin: 0 0.4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn .fa-icon {
|
.btn .fa-icon {
|
||||||
@@ -406,7 +413,7 @@ div.react-select__menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.top-nav {
|
.top-nav {
|
||||||
padding: .25rem 1rem;
|
padding: 0.25rem 1rem;
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -439,7 +446,7 @@ div.react-select__menu {
|
|||||||
.stats {
|
.stats {
|
||||||
&-element {
|
&-element {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
margin: auto .5rem;
|
margin: auto 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ import de from "./de.json";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
en,
|
en,
|
||||||
de
|
de,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ export abstract class Criterion {
|
|||||||
public getLabelValue(): string {
|
public getLabelValue(): string {
|
||||||
if (typeof this.value === "string") return this.value;
|
if (typeof this.value === "string") return this.value;
|
||||||
if (typeof this.value === "number") return this.value.toString();
|
if (typeof this.value === "number") return this.value.toString();
|
||||||
return this.value.map(v => v.label).join(", ");
|
return this.value.map((v) => v.label).join(", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public getLabel(): string {
|
public getLabel(): string {
|
||||||
@@ -221,7 +221,7 @@ export class StringCriterion extends Criterion {
|
|||||||
Criterion.getModifierOption(CriterionModifier.Equals),
|
Criterion.getModifierOption(CriterionModifier.Equals),
|
||||||
Criterion.getModifierOption(CriterionModifier.NotEquals),
|
Criterion.getModifierOption(CriterionModifier.NotEquals),
|
||||||
Criterion.getModifierOption(CriterionModifier.IsNull),
|
Criterion.getModifierOption(CriterionModifier.IsNull),
|
||||||
Criterion.getModifierOption(CriterionModifier.NotNull)
|
Criterion.getModifierOption(CriterionModifier.NotNull),
|
||||||
];
|
];
|
||||||
public options: string[] | undefined;
|
public options: string[] | undefined;
|
||||||
public value: string = "";
|
public value: string = "";
|
||||||
@@ -255,7 +255,7 @@ export class NumberCriterion extends Criterion {
|
|||||||
Criterion.getModifierOption(CriterionModifier.GreaterThan),
|
Criterion.getModifierOption(CriterionModifier.GreaterThan),
|
||||||
Criterion.getModifierOption(CriterionModifier.LessThan),
|
Criterion.getModifierOption(CriterionModifier.LessThan),
|
||||||
Criterion.getModifierOption(CriterionModifier.IsNull),
|
Criterion.getModifierOption(CriterionModifier.IsNull),
|
||||||
Criterion.getModifierOption(CriterionModifier.NotNull)
|
Criterion.getModifierOption(CriterionModifier.NotNull),
|
||||||
];
|
];
|
||||||
public options: number[] | undefined;
|
public options: number[] | undefined;
|
||||||
public value: number = 0;
|
public value: number = 0;
|
||||||
@@ -287,7 +287,7 @@ export class DurationCriterion extends Criterion {
|
|||||||
Criterion.getModifierOption(CriterionModifier.Equals),
|
Criterion.getModifierOption(CriterionModifier.Equals),
|
||||||
Criterion.getModifierOption(CriterionModifier.NotEquals),
|
Criterion.getModifierOption(CriterionModifier.NotEquals),
|
||||||
Criterion.getModifierOption(CriterionModifier.GreaterThan),
|
Criterion.getModifierOption(CriterionModifier.GreaterThan),
|
||||||
Criterion.getModifierOption(CriterionModifier.LessThan)
|
Criterion.getModifierOption(CriterionModifier.LessThan),
|
||||||
];
|
];
|
||||||
public options: number[] | undefined;
|
public options: number[] | undefined;
|
||||||
public value: number = 0;
|
public value: number = 0;
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import { CriterionModifier } from "src/core/generated-graphql";
|
import { CriterionModifier } from "src/core/generated-graphql";
|
||||||
import { StashService } from "src/core/StashService";
|
import { StashService } from "src/core/StashService";
|
||||||
import {
|
import { Criterion, CriterionType, ICriterionOption } from "./criterion";
|
||||||
Criterion,
|
|
||||||
CriterionType,
|
|
||||||
ICriterionOption,
|
|
||||||
} from "./criterion";
|
|
||||||
|
|
||||||
export class GenderCriterion extends Criterion {
|
export class GenderCriterion extends Criterion {
|
||||||
public type: CriterionType = "gender";
|
public type: CriterionType = "gender";
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export class IsMissingCriterion extends Criterion {
|
|||||||
"gallery",
|
"gallery",
|
||||||
"studio",
|
"studio",
|
||||||
"movie",
|
"movie",
|
||||||
"performers"
|
"performers",
|
||||||
];
|
];
|
||||||
public value: string = "";
|
public value: string = "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ export class MoviesCriterion extends Criterion {
|
|||||||
public modifier = CriterionModifier.Includes;
|
public modifier = CriterionModifier.Includes;
|
||||||
public modifierOptions = [
|
public modifierOptions = [
|
||||||
Criterion.getModifierOption(CriterionModifier.Includes),
|
Criterion.getModifierOption(CriterionModifier.Includes),
|
||||||
Criterion.getModifierOption(CriterionModifier.Excludes)
|
Criterion.getModifierOption(CriterionModifier.Excludes),
|
||||||
];
|
];
|
||||||
public options: IOptionType[] = [];
|
public options: IOptionType[] = [];
|
||||||
public value: ILabeledId[] = [];
|
public value: ILabeledId[] = [];
|
||||||
|
|
||||||
public encodeValue() {
|
public encodeValue() {
|
||||||
return this.value.map(o => {
|
return this.value.map((o) => {
|
||||||
return encodeILabeledId(o);
|
return encodeILabeledId(o);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ export class PerformersCriterion extends Criterion {
|
|||||||
public modifierOptions = [
|
public modifierOptions = [
|
||||||
Criterion.getModifierOption(CriterionModifier.IncludesAll),
|
Criterion.getModifierOption(CriterionModifier.IncludesAll),
|
||||||
Criterion.getModifierOption(CriterionModifier.Includes),
|
Criterion.getModifierOption(CriterionModifier.Includes),
|
||||||
Criterion.getModifierOption(CriterionModifier.Excludes)
|
Criterion.getModifierOption(CriterionModifier.Excludes),
|
||||||
];
|
];
|
||||||
public options: IOptionType[] = [];
|
public options: IOptionType[] = [];
|
||||||
public value: ILabeledId[] = [];
|
public value: ILabeledId[] = [];
|
||||||
|
|
||||||
public encodeValue() {
|
public encodeValue() {
|
||||||
return this.value.map(o => {
|
return this.value.map((o) => {
|
||||||
return encodeILabeledId(o);
|
return encodeILabeledId(o);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export class RatingCriterion extends Criterion {
|
|||||||
Criterion.getModifierOption(CriterionModifier.GreaterThan),
|
Criterion.getModifierOption(CriterionModifier.GreaterThan),
|
||||||
Criterion.getModifierOption(CriterionModifier.LessThan),
|
Criterion.getModifierOption(CriterionModifier.LessThan),
|
||||||
Criterion.getModifierOption(CriterionModifier.IsNull),
|
Criterion.getModifierOption(CriterionModifier.IsNull),
|
||||||
Criterion.getModifierOption(CriterionModifier.NotNull)
|
Criterion.getModifierOption(CriterionModifier.NotNull),
|
||||||
];
|
];
|
||||||
public options: number[] = [1, 2, 3, 4, 5];
|
public options: number[] = [1, 2, 3, 4, 5];
|
||||||
public value: number = 0;
|
public value: number = 0;
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ export class StudiosCriterion extends Criterion {
|
|||||||
public modifier = CriterionModifier.Includes;
|
public modifier = CriterionModifier.Includes;
|
||||||
public modifierOptions = [
|
public modifierOptions = [
|
||||||
Criterion.getModifierOption(CriterionModifier.Includes),
|
Criterion.getModifierOption(CriterionModifier.Includes),
|
||||||
Criterion.getModifierOption(CriterionModifier.Excludes)
|
Criterion.getModifierOption(CriterionModifier.Excludes),
|
||||||
];
|
];
|
||||||
public options: IOptionType[] = [];
|
public options: IOptionType[] = [];
|
||||||
public value: ILabeledId[] = [];
|
public value: ILabeledId[] = [];
|
||||||
|
|
||||||
public encodeValue() {
|
public encodeValue() {
|
||||||
return this.value.map(o => {
|
return this.value.map((o) => {
|
||||||
return encodeILabeledId(o);
|
return encodeILabeledId(o);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export class TagsCriterion extends Criterion {
|
|||||||
public modifierOptions = [
|
public modifierOptions = [
|
||||||
Criterion.getModifierOption(GQL.CriterionModifier.IncludesAll),
|
Criterion.getModifierOption(GQL.CriterionModifier.IncludesAll),
|
||||||
Criterion.getModifierOption(GQL.CriterionModifier.Includes),
|
Criterion.getModifierOption(GQL.CriterionModifier.Includes),
|
||||||
Criterion.getModifierOption(GQL.CriterionModifier.Excludes)
|
Criterion.getModifierOption(GQL.CriterionModifier.Excludes),
|
||||||
];
|
];
|
||||||
public options: IOptionType[] = [];
|
public options: IOptionType[] = [];
|
||||||
public value: ILabeledId[] = [];
|
public value: ILabeledId[] = [];
|
||||||
@@ -24,7 +24,7 @@ export class TagsCriterion extends Criterion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public encodeValue() {
|
public encodeValue() {
|
||||||
return this.value.map(o => {
|
return this.value.map((o) => {
|
||||||
return encodeILabeledId(o);
|
return encodeILabeledId(o);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
CriterionType,
|
CriterionType,
|
||||||
StringCriterion,
|
StringCriterion,
|
||||||
NumberCriterion,
|
NumberCriterion,
|
||||||
DurationCriterion
|
DurationCriterion,
|
||||||
} from "./criterion";
|
} from "./criterion";
|
||||||
import { FavoriteCriterion } from "./favorite";
|
import { FavoriteCriterion } from "./favorite";
|
||||||
import { HasMarkersCriterion } from "./has-markers";
|
import { HasMarkersCriterion } from "./has-markers";
|
||||||
@@ -57,7 +57,7 @@ export function makeCriteria(type: CriterionType = "none") {
|
|||||||
Criterion.getModifierOption(CriterionModifier.Equals),
|
Criterion.getModifierOption(CriterionModifier.Equals),
|
||||||
Criterion.getModifierOption(CriterionModifier.NotEquals),
|
Criterion.getModifierOption(CriterionModifier.NotEquals),
|
||||||
Criterion.getModifierOption(CriterionModifier.GreaterThan),
|
Criterion.getModifierOption(CriterionModifier.GreaterThan),
|
||||||
Criterion.getModifierOption(CriterionModifier.LessThan)
|
Criterion.getModifierOption(CriterionModifier.LessThan),
|
||||||
];
|
];
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import {
|
|||||||
ResolutionEnum,
|
ResolutionEnum,
|
||||||
SceneFilterType,
|
SceneFilterType,
|
||||||
SceneMarkerFilterType,
|
SceneMarkerFilterType,
|
||||||
SortDirectionEnum
|
SortDirectionEnum,
|
||||||
} from "src/core/generated-graphql";
|
} from "src/core/generated-graphql";
|
||||||
|
import { StashService } from "src/core/StashService";
|
||||||
import {
|
import {
|
||||||
Criterion,
|
Criterion,
|
||||||
ICriterionOption,
|
ICriterionOption,
|
||||||
@@ -14,40 +15,39 @@ import {
|
|||||||
CriterionOption,
|
CriterionOption,
|
||||||
NumberCriterion,
|
NumberCriterion,
|
||||||
StringCriterion,
|
StringCriterion,
|
||||||
DurationCriterion
|
DurationCriterion,
|
||||||
} from "./criteria/criterion";
|
} from "./criteria/criterion";
|
||||||
import {
|
import {
|
||||||
FavoriteCriterion,
|
FavoriteCriterion,
|
||||||
FavoriteCriterionOption
|
FavoriteCriterionOption,
|
||||||
} from "./criteria/favorite";
|
} from "./criteria/favorite";
|
||||||
import {
|
import {
|
||||||
HasMarkersCriterion,
|
HasMarkersCriterion,
|
||||||
HasMarkersCriterionOption
|
HasMarkersCriterionOption,
|
||||||
} from "./criteria/has-markers";
|
} from "./criteria/has-markers";
|
||||||
import {
|
import {
|
||||||
IsMissingCriterion,
|
IsMissingCriterion,
|
||||||
IsMissingCriterionOption
|
IsMissingCriterionOption,
|
||||||
} from "./criteria/is-missing";
|
} from "./criteria/is-missing";
|
||||||
import { NoneCriterionOption } from "./criteria/none";
|
import { NoneCriterionOption } from "./criteria/none";
|
||||||
import {
|
import {
|
||||||
PerformersCriterion,
|
PerformersCriterion,
|
||||||
PerformersCriterionOption
|
PerformersCriterionOption,
|
||||||
} from "./criteria/performers";
|
} from "./criteria/performers";
|
||||||
import { RatingCriterion, RatingCriterionOption } from "./criteria/rating";
|
import { RatingCriterion, RatingCriterionOption } from "./criteria/rating";
|
||||||
import {
|
import {
|
||||||
ResolutionCriterion,
|
ResolutionCriterion,
|
||||||
ResolutionCriterionOption
|
ResolutionCriterionOption,
|
||||||
} from "./criteria/resolution";
|
} from "./criteria/resolution";
|
||||||
import { StudiosCriterion, StudiosCriterionOption } from "./criteria/studios";
|
import { StudiosCriterion, StudiosCriterionOption } from "./criteria/studios";
|
||||||
import {
|
import {
|
||||||
SceneTagsCriterionOption,
|
SceneTagsCriterionOption,
|
||||||
TagsCriterion,
|
TagsCriterion,
|
||||||
TagsCriterionOption
|
TagsCriterionOption,
|
||||||
} from "./criteria/tags";
|
} from "./criteria/tags";
|
||||||
import { makeCriteria } from "./criteria/utils";
|
import { makeCriteria } from "./criteria/utils";
|
||||||
import { DisplayMode, FilterMode } from "./types";
|
import { DisplayMode, FilterMode } from "./types";
|
||||||
import { GenderCriterionOption, GenderCriterion } from "./criteria/gender";
|
import { GenderCriterionOption, GenderCriterion } from "./criteria/gender";
|
||||||
import { StashService } from "src/core/StashService";
|
|
||||||
import { MoviesCriterionOption, MoviesCriterion } from "./criteria/movies";
|
import { MoviesCriterionOption, MoviesCriterion } from "./criteria/movies";
|
||||||
|
|
||||||
interface IQueryParameters {
|
interface IQueryParameters {
|
||||||
@@ -64,7 +64,7 @@ const DEFAULT_PARAMS = {
|
|||||||
sortDirection: SortDirectionEnum.Asc,
|
sortDirection: SortDirectionEnum.Asc,
|
||||||
displayMode: DisplayMode.Grid,
|
displayMode: DisplayMode.Grid,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
itemsPerPage: 40
|
itemsPerPage: 40,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: handle customCriteria
|
// TODO: handle customCriteria
|
||||||
@@ -101,12 +101,12 @@ export class ListFilterModel {
|
|||||||
"duration",
|
"duration",
|
||||||
"framerate",
|
"framerate",
|
||||||
"bitrate",
|
"bitrate",
|
||||||
"random"
|
"random",
|
||||||
];
|
];
|
||||||
this.displayModeOptions = [
|
this.displayModeOptions = [
|
||||||
DisplayMode.Grid,
|
DisplayMode.Grid,
|
||||||
DisplayMode.List,
|
DisplayMode.List,
|
||||||
DisplayMode.Wall
|
DisplayMode.Wall,
|
||||||
];
|
];
|
||||||
this.criterionOptions = [
|
this.criterionOptions = [
|
||||||
new NoneCriterionOption(),
|
new NoneCriterionOption(),
|
||||||
@@ -119,7 +119,7 @@ export class ListFilterModel {
|
|||||||
new TagsCriterionOption(),
|
new TagsCriterionOption(),
|
||||||
new PerformersCriterionOption(),
|
new PerformersCriterionOption(),
|
||||||
new StudiosCriterionOption(),
|
new StudiosCriterionOption(),
|
||||||
new MoviesCriterionOption()
|
new MoviesCriterionOption(),
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
case FilterMode.Performers: {
|
case FilterMode.Performers: {
|
||||||
@@ -138,7 +138,7 @@ export class ListFilterModel {
|
|||||||
"career_length",
|
"career_length",
|
||||||
"tattoos",
|
"tattoos",
|
||||||
"piercings",
|
"piercings",
|
||||||
"aliases"
|
"aliases",
|
||||||
];
|
];
|
||||||
|
|
||||||
this.criterionOptions = [
|
this.criterionOptions = [
|
||||||
@@ -148,7 +148,7 @@ export class ListFilterModel {
|
|||||||
];
|
];
|
||||||
|
|
||||||
this.criterionOptions = this.criterionOptions.concat(
|
this.criterionOptions = this.criterionOptions.concat(
|
||||||
numberCriteria.concat(stringCriteria).map(c => {
|
numberCriteria.concat(stringCriteria).map((c) => {
|
||||||
return ListFilterModel.createCriterionOption(c);
|
return ListFilterModel.createCriterionOption(c);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -179,14 +179,14 @@ export class ListFilterModel {
|
|||||||
"seconds",
|
"seconds",
|
||||||
"scene_id",
|
"scene_id",
|
||||||
"random",
|
"random",
|
||||||
"scenes_updated_at"
|
"scenes_updated_at",
|
||||||
];
|
];
|
||||||
this.displayModeOptions = [DisplayMode.Wall];
|
this.displayModeOptions = [DisplayMode.Wall];
|
||||||
this.criterionOptions = [
|
this.criterionOptions = [
|
||||||
new NoneCriterionOption(),
|
new NoneCriterionOption(),
|
||||||
new TagsCriterionOption(),
|
new TagsCriterionOption(),
|
||||||
new SceneTagsCriterionOption(),
|
new SceneTagsCriterionOption(),
|
||||||
new PerformersCriterionOption()
|
new PerformersCriterionOption(),
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -244,7 +244,7 @@ export class ListFilterModel {
|
|||||||
jsonParameters = [params.c];
|
jsonParameters = [params.c];
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonParameters.forEach(jsonString => {
|
jsonParameters.forEach((jsonString) => {
|
||||||
const encodedCriterion = JSON.parse(jsonString);
|
const encodedCriterion = JSON.parse(jsonString);
|
||||||
const criterion = makeCriteria(encodedCriterion.type);
|
const criterion = makeCriteria(encodedCriterion.type);
|
||||||
// it's possible that we have unsupported criteria. Just skip if so.
|
// it's possible that we have unsupported criteria. Just skip if so.
|
||||||
@@ -281,7 +281,7 @@ export class ListFilterModel {
|
|||||||
|
|
||||||
public makeQueryParameters(): string {
|
public makeQueryParameters(): string {
|
||||||
const encodedCriteria: string[] = [];
|
const encodedCriteria: string[] = [];
|
||||||
this.criteria.forEach(criterion => {
|
this.criteria.forEach((criterion) => {
|
||||||
const encodedCriterion: Partial<Criterion> = {
|
const encodedCriterion: Partial<Criterion> = {
|
||||||
type: criterion.type,
|
type: criterion.type,
|
||||||
// #394 - the presence of a # symbol results in the query URL being
|
// #394 - the presence of a # symbol results in the query URL being
|
||||||
@@ -289,7 +289,7 @@ export class ListFilterModel {
|
|||||||
// call below, but this results in a URL that gets pretty long and ugly.
|
// call below, but this results in a URL that gets pretty long and ugly.
|
||||||
// Instead, we'll encode the criteria values.
|
// Instead, we'll encode the criteria values.
|
||||||
value: criterion.encodeValue(),
|
value: criterion.encodeValue(),
|
||||||
modifier: criterion.modifier
|
modifier: criterion.modifier,
|
||||||
};
|
};
|
||||||
const jsonCriterion = JSON.stringify(encodedCriterion);
|
const jsonCriterion = JSON.stringify(encodedCriterion);
|
||||||
encodedCriteria.push(jsonCriterion);
|
encodedCriteria.push(jsonCriterion);
|
||||||
@@ -312,7 +312,7 @@ export class ListFilterModel {
|
|||||||
this.currentPage !== DEFAULT_PARAMS.currentPage
|
this.currentPage !== DEFAULT_PARAMS.currentPage
|
||||||
? this.currentPage
|
? this.currentPage
|
||||||
: undefined,
|
: undefined,
|
||||||
c: encodedCriteria
|
c: encodedCriteria,
|
||||||
};
|
};
|
||||||
return queryString.stringify(result, { encode: false });
|
return queryString.stringify(result, { encode: false });
|
||||||
}
|
}
|
||||||
@@ -325,19 +325,19 @@ export class ListFilterModel {
|
|||||||
page: this.currentPage,
|
page: this.currentPage,
|
||||||
per_page: this.itemsPerPage,
|
per_page: this.itemsPerPage,
|
||||||
sort: this.getSortBy(),
|
sort: this.getSortBy(),
|
||||||
direction: this.sortDirection
|
direction: this.sortDirection,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public makeSceneFilter(): SceneFilterType {
|
public makeSceneFilter(): SceneFilterType {
|
||||||
const result: SceneFilterType = {};
|
const result: SceneFilterType = {};
|
||||||
this.criteria.forEach(criterion => {
|
this.criteria.forEach((criterion) => {
|
||||||
switch (criterion.type) {
|
switch (criterion.type) {
|
||||||
case "rating": {
|
case "rating": {
|
||||||
const ratingCrit = criterion as RatingCriterion;
|
const ratingCrit = criterion as RatingCriterion;
|
||||||
result.rating = {
|
result.rating = {
|
||||||
value: ratingCrit.value,
|
value: ratingCrit.value,
|
||||||
modifier: ratingCrit.modifier
|
modifier: ratingCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -345,7 +345,7 @@ export class ListFilterModel {
|
|||||||
const oCounterCrit = criterion as NumberCriterion;
|
const oCounterCrit = criterion as NumberCriterion;
|
||||||
result.o_counter = {
|
result.o_counter = {
|
||||||
value: oCounterCrit.value,
|
value: oCounterCrit.value,
|
||||||
modifier: oCounterCrit.modifier
|
modifier: oCounterCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -374,7 +374,7 @@ export class ListFilterModel {
|
|||||||
const durationCrit = criterion as DurationCriterion;
|
const durationCrit = criterion as DurationCriterion;
|
||||||
result.duration = {
|
result.duration = {
|
||||||
value: durationCrit.value,
|
value: durationCrit.value,
|
||||||
modifier: durationCrit.modifier
|
modifier: durationCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -387,32 +387,32 @@ export class ListFilterModel {
|
|||||||
case "tags": {
|
case "tags": {
|
||||||
const tagsCrit = criterion as TagsCriterion;
|
const tagsCrit = criterion as TagsCriterion;
|
||||||
result.tags = {
|
result.tags = {
|
||||||
value: tagsCrit.value.map(tag => tag.id),
|
value: tagsCrit.value.map((tag) => tag.id),
|
||||||
modifier: tagsCrit.modifier
|
modifier: tagsCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "performers": {
|
case "performers": {
|
||||||
const perfCrit = criterion as PerformersCriterion;
|
const perfCrit = criterion as PerformersCriterion;
|
||||||
result.performers = {
|
result.performers = {
|
||||||
value: perfCrit.value.map(perf => perf.id),
|
value: perfCrit.value.map((perf) => perf.id),
|
||||||
modifier: perfCrit.modifier
|
modifier: perfCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "studios": {
|
case "studios": {
|
||||||
const studCrit = criterion as StudiosCriterion;
|
const studCrit = criterion as StudiosCriterion;
|
||||||
result.studios = {
|
result.studios = {
|
||||||
value: studCrit.value.map(studio => studio.id),
|
value: studCrit.value.map((studio) => studio.id),
|
||||||
modifier: studCrit.modifier
|
modifier: studCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "movies": {
|
case "movies": {
|
||||||
const movCrit = criterion as MoviesCriterion;
|
const movCrit = criterion as MoviesCriterion;
|
||||||
result.movies = {
|
result.movies = {
|
||||||
value: movCrit.value.map(movie => movie.id),
|
value: movCrit.value.map((movie) => movie.id),
|
||||||
modifier: movCrit.modifier
|
modifier: movCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -424,7 +424,7 @@ export class ListFilterModel {
|
|||||||
|
|
||||||
public makePerformerFilter(): PerformerFilterType {
|
public makePerformerFilter(): PerformerFilterType {
|
||||||
const result: PerformerFilterType = {};
|
const result: PerformerFilterType = {};
|
||||||
this.criteria.forEach(criterion => {
|
this.criteria.forEach((criterion) => {
|
||||||
switch (criterion.type) {
|
switch (criterion.type) {
|
||||||
case "favorite":
|
case "favorite":
|
||||||
result.filter_favorites =
|
result.filter_favorites =
|
||||||
@@ -434,7 +434,7 @@ export class ListFilterModel {
|
|||||||
const byCrit = criterion as NumberCriterion;
|
const byCrit = criterion as NumberCriterion;
|
||||||
result.birth_year = {
|
result.birth_year = {
|
||||||
value: byCrit.value,
|
value: byCrit.value,
|
||||||
modifier: byCrit.modifier
|
modifier: byCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -447,7 +447,7 @@ export class ListFilterModel {
|
|||||||
const ethCrit = criterion as StringCriterion;
|
const ethCrit = criterion as StringCriterion;
|
||||||
result.ethnicity = {
|
result.ethnicity = {
|
||||||
value: ethCrit.value,
|
value: ethCrit.value,
|
||||||
modifier: ethCrit.modifier
|
modifier: ethCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -455,7 +455,7 @@ export class ListFilterModel {
|
|||||||
const cntryCrit = criterion as StringCriterion;
|
const cntryCrit = criterion as StringCriterion;
|
||||||
result.country = {
|
result.country = {
|
||||||
value: cntryCrit.value,
|
value: cntryCrit.value,
|
||||||
modifier: cntryCrit.modifier
|
modifier: cntryCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -473,7 +473,7 @@ export class ListFilterModel {
|
|||||||
const mCrit = criterion as StringCriterion;
|
const mCrit = criterion as StringCriterion;
|
||||||
result.measurements = {
|
result.measurements = {
|
||||||
value: mCrit.value,
|
value: mCrit.value,
|
||||||
modifier: mCrit.modifier
|
modifier: mCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -486,7 +486,7 @@ export class ListFilterModel {
|
|||||||
const clCrit = criterion as StringCriterion;
|
const clCrit = criterion as StringCriterion;
|
||||||
result.career_length = {
|
result.career_length = {
|
||||||
value: clCrit.value,
|
value: clCrit.value,
|
||||||
modifier: clCrit.modifier
|
modifier: clCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -507,7 +507,10 @@ export class ListFilterModel {
|
|||||||
}
|
}
|
||||||
case "gender": {
|
case "gender": {
|
||||||
const gCrit = criterion as GenderCriterion;
|
const gCrit = criterion as GenderCriterion;
|
||||||
result.gender = { value: StashService.stringToGender(gCrit.value), modifier: gCrit.modifier };
|
result.gender = {
|
||||||
|
value: StashService.stringToGender(gCrit.value),
|
||||||
|
modifier: gCrit.modifier,
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// no default
|
// no default
|
||||||
@@ -518,29 +521,29 @@ export class ListFilterModel {
|
|||||||
|
|
||||||
public makeSceneMarkerFilter(): SceneMarkerFilterType {
|
public makeSceneMarkerFilter(): SceneMarkerFilterType {
|
||||||
const result: SceneMarkerFilterType = {};
|
const result: SceneMarkerFilterType = {};
|
||||||
this.criteria.forEach(criterion => {
|
this.criteria.forEach((criterion) => {
|
||||||
switch (criterion.type) {
|
switch (criterion.type) {
|
||||||
case "tags": {
|
case "tags": {
|
||||||
const tagsCrit = criterion as TagsCriterion;
|
const tagsCrit = criterion as TagsCriterion;
|
||||||
result.tags = {
|
result.tags = {
|
||||||
value: tagsCrit.value.map(tag => tag.id),
|
value: tagsCrit.value.map((tag) => tag.id),
|
||||||
modifier: tagsCrit.modifier
|
modifier: tagsCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "sceneTags": {
|
case "sceneTags": {
|
||||||
const sceneTagsCrit = criterion as TagsCriterion;
|
const sceneTagsCrit = criterion as TagsCriterion;
|
||||||
result.scene_tags = {
|
result.scene_tags = {
|
||||||
value: sceneTagsCrit.value.map(tag => tag.id),
|
value: sceneTagsCrit.value.map((tag) => tag.id),
|
||||||
modifier: sceneTagsCrit.modifier
|
modifier: sceneTagsCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "performers": {
|
case "performers": {
|
||||||
const performersCrit = criterion as PerformersCriterion;
|
const performersCrit = criterion as PerformersCriterion;
|
||||||
result.performers = {
|
result.performers = {
|
||||||
value: performersCrit.value.map(performer => performer.id),
|
value: performersCrit.value.map((performer) => performer.id),
|
||||||
modifier: performersCrit.modifier
|
modifier: performersCrit.modifier,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
export enum DisplayMode {
|
export enum DisplayMode {
|
||||||
Grid,
|
Grid,
|
||||||
List,
|
List,
|
||||||
Wall
|
Wall,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FilterMode {
|
export enum FilterMode {
|
||||||
@@ -12,7 +12,7 @@ export enum FilterMode {
|
|||||||
Studios,
|
Studios,
|
||||||
Galleries,
|
Galleries,
|
||||||
SceneMarkers,
|
SceneMarkers,
|
||||||
Movies
|
Movies,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ILabeledId {
|
export interface ILabeledId {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ interface IConfig {
|
|||||||
function registerValidSW(swUrl: string, config?: IConfig) {
|
function registerValidSW(swUrl: string, config?: IConfig) {
|
||||||
navigator.serviceWorker
|
navigator.serviceWorker
|
||||||
.register(swUrl)
|
.register(swUrl)
|
||||||
.then(registration => {
|
.then((registration) => {
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
registration.onupdatefound = () => {
|
registration.onupdatefound = () => {
|
||||||
const installingWorker = registration.installing;
|
const installingWorker = registration.installing;
|
||||||
@@ -67,7 +67,7 @@ function registerValidSW(swUrl: string, config?: IConfig) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
console.error("Error during service worker registration:", error);
|
console.error("Error during service worker registration:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ function registerValidSW(swUrl: string, config?: IConfig) {
|
|||||||
function checkValidServiceWorker(swUrl: string, config?: IConfig) {
|
function checkValidServiceWorker(swUrl: string, config?: IConfig) {
|
||||||
// Check if the service worker can be found. If it can't reload the page.
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
fetch(swUrl)
|
fetch(swUrl)
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
// Ensure service worker exists, and that we really are getting a JS file.
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
const contentType = response.headers.get("content-type");
|
const contentType = response.headers.get("content-type");
|
||||||
if (
|
if (
|
||||||
@@ -83,7 +83,7 @@ function checkValidServiceWorker(swUrl: string, config?: IConfig) {
|
|||||||
(contentType != null && contentType.indexOf("javascript") === -1)
|
(contentType != null && contentType.indexOf("javascript") === -1)
|
||||||
) {
|
) {
|
||||||
// No service worker found. Probably a different app. Reload the page.
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then((registration) => {
|
||||||
registration.unregister().then(() => {
|
registration.unregister().then(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
@@ -139,7 +139,7 @@ export function register(config?: IConfig) {
|
|||||||
|
|
||||||
export function unregister() {
|
export function unregister() {
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
navigator.serviceWorker.ready.then(registration => {
|
navigator.serviceWorker.ready.then((registration) => {
|
||||||
registration.unregister();
|
registration.unregister();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
input[type=range] {
|
input[type="range"] {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
@@ -14,7 +14,7 @@ input[type=range] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-slider-runnable-track {
|
&::-webkit-slider-runnable-track {
|
||||||
animate: .2s;
|
animate: 0.2s;
|
||||||
background: #137cbd;
|
background: #137cbd;
|
||||||
border: 0 solid #000101;
|
border: 0 solid #000101;
|
||||||
border-radius: 25px;
|
border-radius: 25px;
|
||||||
@@ -41,7 +41,7 @@ input[type=range] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&::-moz-range-track {
|
&::-moz-range-track {
|
||||||
animate: .2s;
|
animate: 0.2s;
|
||||||
background: #137cbd;
|
background: #137cbd;
|
||||||
border: 0 solid #000101;
|
border: 0 solid #000101;
|
||||||
border-radius: 25px;
|
border-radius: 25px;
|
||||||
@@ -62,7 +62,7 @@ input[type=range] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&::-ms-track {
|
&::-ms-track {
|
||||||
animate: .2s;
|
animate: 0.2s;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
textarea::selection,
|
textarea::selection,
|
||||||
input::selection {
|
input::selection {
|
||||||
background-color: rgba(100, 100, 100, .4);
|
background-color: rgba(100, 100, 100, 0.4);
|
||||||
color: $dark-text;
|
color: $dark-text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,21 +24,21 @@ body ::-webkit-scrollbar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body ::-webkit-scrollbar-track {
|
body ::-webkit-scrollbar-track {
|
||||||
background: rgba(0, 0, 0, .1);
|
background: rgba(0, 0, 0, 0.1);
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
body ::-webkit-scrollbar-thumb {
|
body ::-webkit-scrollbar-thumb {
|
||||||
background: rgba(0, 0, 0, .25);
|
background: rgba(0, 0, 0, 0.25);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: color .2s ease;
|
transition: color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
body ::-webkit-scrollbar-thumb:window-inactive {
|
body ::-webkit-scrollbar-thumb:window-inactive {
|
||||||
background: rgba(0, 0, 0, .15);
|
background: rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
body ::-webkit-scrollbar-thumb:hover {
|
body ::-webkit-scrollbar-thumb:hover {
|
||||||
background: rgba(128, 135, 139, .8);
|
background: rgba(128, 135, 139, 0.8);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/* Blueprint dark theme */
|
/* Blueprint dark theme */
|
||||||
|
|
||||||
$secondary: #394b59;
|
$secondary: #394b59;
|
||||||
@@ -13,7 +12,7 @@ $theme-colors: (
|
|||||||
success: $success,
|
success: $success,
|
||||||
warning: $warning,
|
warning: $warning,
|
||||||
danger: $danger,
|
danger: $danger,
|
||||||
dark: #394b59
|
dark: #394b59,
|
||||||
);
|
);
|
||||||
|
|
||||||
$body-bg: #202b33;
|
$body-bg: #202b33;
|
||||||
@@ -25,7 +24,7 @@ $pre-color: $text-color;
|
|||||||
$navbar-dark-color: rgb(245, 248, 250);
|
$navbar-dark-color: rgb(245, 248, 250);
|
||||||
$popover-bg: $secondary;
|
$popover-bg: $secondary;
|
||||||
$dark-text: #182026;
|
$dark-text: #182026;
|
||||||
$textfield-bg: rgba(16, 22, 26, .3);
|
$textfield-bg: rgba(16, 22, 26, 0.3);
|
||||||
|
|
||||||
@import "node_modules/bootstrap/scss/bootstrap";
|
@import "node_modules/bootstrap/scss/bootstrap";
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@ $dark-gray5: #394b59;
|
|||||||
|
|
||||||
.btn.active:not(.disabled),
|
.btn.active:not(.disabled),
|
||||||
.btn.active.minimal:not(.disabled) {
|
.btn.active.minimal:not(.disabled) {
|
||||||
background-color: rgba(138, 155, 168, .3);
|
background-color: rgba(138, 155, 168, 0.3);
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,12 +48,12 @@ button.minimal {
|
|||||||
transition: none;
|
transition: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba(138, 155, 168, .15);
|
background: rgba(138, 155, 168, 0.15);
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
background: rgba(138, 155, 168, .3);
|
background: rgba(138, 155, 168, 0.3);
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +73,7 @@ hr {
|
|||||||
.nav-tabs {
|
.nav-tabs {
|
||||||
border: none;
|
border: none;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
margin-bottom: .5rem;
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
border: none;
|
border: none;
|
||||||
@@ -102,7 +101,7 @@ hr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.table-striped tr:nth-child(odd) td {
|
.table-striped tr:nth-child(odd) td {
|
||||||
background: rgba(92, 112, 128, .15);
|
background: rgba(92, 112, 128, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
@@ -120,7 +119,7 @@ hr {
|
|||||||
td {
|
td {
|
||||||
border: none;
|
border: none;
|
||||||
border-color: #414c53;
|
border-color: #414c53;
|
||||||
padding: .25rem .75rem;
|
padding: 0.25rem 0.75rem;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
|||||||
@@ -47,5 +47,5 @@ const stringToSeconds = (v: string) => {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
secondsToString,
|
secondsToString,
|
||||||
stringToSeconds
|
stringToSeconds,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,6 +36,6 @@ const usePasteImage = (onLoadEnd: (this: FileReader) => void) => {
|
|||||||
|
|
||||||
const Image = {
|
const Image = {
|
||||||
onImageChange,
|
onImageChange,
|
||||||
usePasteImage
|
usePasteImage,
|
||||||
};
|
};
|
||||||
export default Image;
|
export default Image;
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ const getPlayer = () => (window as any).jwplayer(playerID);
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
playerID,
|
playerID,
|
||||||
getPlayer
|
getPlayer,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const makePerformerScenesUrl = (
|
|||||||
const filter = new ListFilterModel(FilterMode.Scenes);
|
const filter = new ListFilterModel(FilterMode.Scenes);
|
||||||
const criterion = new PerformersCriterion();
|
const criterion = new PerformersCriterion();
|
||||||
criterion.value = [
|
criterion.value = [
|
||||||
{ id: performer.id, label: performer.name || `Performer ${performer.id}` }
|
{ id: performer.id, label: performer.name || `Performer ${performer.id}` },
|
||||||
];
|
];
|
||||||
filter.criteria.push(criterion);
|
filter.criteria.push(criterion);
|
||||||
return `/scenes?${filter.makeQueryParameters()}`;
|
return `/scenes?${filter.makeQueryParameters()}`;
|
||||||
@@ -24,7 +24,7 @@ const makeStudioScenesUrl = (studio: Partial<GQL.StudioDataFragment>) => {
|
|||||||
const filter = new ListFilterModel(FilterMode.Scenes);
|
const filter = new ListFilterModel(FilterMode.Scenes);
|
||||||
const criterion = new StudiosCriterion();
|
const criterion = new StudiosCriterion();
|
||||||
criterion.value = [
|
criterion.value = [
|
||||||
{ id: studio.id, label: studio.name || `Studio ${studio.id}` }
|
{ id: studio.id, label: studio.name || `Studio ${studio.id}` },
|
||||||
];
|
];
|
||||||
filter.criteria.push(criterion);
|
filter.criteria.push(criterion);
|
||||||
return `/scenes?${filter.makeQueryParameters()}`;
|
return `/scenes?${filter.makeQueryParameters()}`;
|
||||||
@@ -35,7 +35,7 @@ const makeMovieScenesUrl = (movie: Partial<GQL.MovieDataFragment>) => {
|
|||||||
const filter = new ListFilterModel(FilterMode.Scenes);
|
const filter = new ListFilterModel(FilterMode.Scenes);
|
||||||
const criterion = new MoviesCriterion();
|
const criterion = new MoviesCriterion();
|
||||||
criterion.value = [
|
criterion.value = [
|
||||||
{ id: movie.id, label: movie.name || `Movie ${movie.id}` }
|
{ id: movie.id, label: movie.name || `Movie ${movie.id}` },
|
||||||
];
|
];
|
||||||
filter.criteria.push(criterion);
|
filter.criteria.push(criterion);
|
||||||
return `/scenes?${filter.makeQueryParameters()}`;
|
return `/scenes?${filter.makeQueryParameters()}`;
|
||||||
@@ -72,5 +72,5 @@ export default {
|
|||||||
makeTagSceneMarkersUrl,
|
makeTagSceneMarkersUrl,
|
||||||
makeTagScenesUrl,
|
makeTagScenesUrl,
|
||||||
makeSceneMarkerUrl,
|
makeSceneMarkerUrl,
|
||||||
makeMovieScenesUrl
|
makeMovieScenesUrl,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ const renderHtmlSelect = (options: {
|
|||||||
options.onChange(event.currentTarget.value)
|
options.onChange(event.currentTarget.value)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{options.selectOptions.map(opt => (
|
{options.selectOptions.map((opt) => (
|
||||||
<option value={opt} key={opt}>
|
<option value={opt} key={opt}>
|
||||||
{opt}
|
{opt}
|
||||||
</option>
|
</option>
|
||||||
@@ -119,7 +119,7 @@ const renderFilterSelect = (options: {
|
|||||||
<td>
|
<td>
|
||||||
<FilterSelect
|
<FilterSelect
|
||||||
type={options.type}
|
type={options.type}
|
||||||
onSelect={items => options.onChange(items[0]?.id)}
|
onSelect={(items) => options.onChange(items[0]?.id)}
|
||||||
initialIds={options.initialId ? [options.initialId] : []}
|
initialIds={options.initialId ? [options.initialId] : []}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
@@ -139,7 +139,7 @@ const renderMultiSelect = (options: {
|
|||||||
<FilterSelect
|
<FilterSelect
|
||||||
type={options.type}
|
type={options.type}
|
||||||
isMulti
|
isMulti
|
||||||
onSelect={items => options.onChange(items.map(i => i.id))}
|
onSelect={(items) => options.onChange(items.map((i) => i.id))}
|
||||||
initialIds={options.initialIds ?? []}
|
initialIds={options.initialIds ?? []}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
@@ -152,6 +152,6 @@ const Table = {
|
|||||||
renderInputGroup,
|
renderInputGroup,
|
||||||
renderHtmlSelect,
|
renderHtmlSelect,
|
||||||
renderFilterSelect,
|
renderFilterSelect,
|
||||||
renderMultiSelect
|
renderMultiSelect,
|
||||||
};
|
};
|
||||||
export default Table;
|
export default Table;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ const TextUtils = {
|
|||||||
fileNameFromPath,
|
fileNameFromPath,
|
||||||
age: getAge,
|
age: getAge,
|
||||||
bitRate,
|
bitRate,
|
||||||
resolution
|
resolution,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TextUtils;
|
export default TextUtils;
|
||||||
|
|||||||
@@ -5438,10 +5438,10 @@ eslint-config-airbnb@^18.0.1:
|
|||||||
object.assign "^4.1.0"
|
object.assign "^4.1.0"
|
||||||
object.entries "^1.1.0"
|
object.entries "^1.1.0"
|
||||||
|
|
||||||
eslint-config-prettier@^6.9.0:
|
eslint-config-prettier@^6.10.1:
|
||||||
version "6.9.0"
|
version "6.10.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.9.0.tgz#430d24822e82f7deb1e22a435bfa3999fae4ad64"
|
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a"
|
||||||
integrity sha512-k4E14HBtcLv0uqThaI6I/n1LEqROp8XaPu6SO9Z32u5NlGRC07Enu1Bh2KEFw4FNHbekH8yzbIU9kUGxbiGmCA==
|
integrity sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
get-stdin "^6.0.0"
|
get-stdin "^6.0.0"
|
||||||
|
|
||||||
@@ -11027,6 +11027,11 @@ prettier@1.19.1:
|
|||||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
||||||
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
|
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
|
||||||
|
|
||||||
|
prettier@2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.2.tgz#1ba8f3eb92231e769b7fcd7cb73ae1b6b74ade08"
|
||||||
|
integrity sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg==
|
||||||
|
|
||||||
pretty-bytes@^5.1.0:
|
pretty-bytes@^5.1.0:
|
||||||
version "5.3.0"
|
version "5.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2"
|
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2"
|
||||||
@@ -13145,6 +13150,11 @@ stylehacks@^4.0.0:
|
|||||||
postcss "^7.0.0"
|
postcss "^7.0.0"
|
||||||
postcss-selector-parser "^3.0.0"
|
postcss-selector-parser "^3.0.0"
|
||||||
|
|
||||||
|
stylelint-config-prettier@^8.0.1:
|
||||||
|
version "8.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/stylelint-config-prettier/-/stylelint-config-prettier-8.0.1.tgz#ec7cdd7faabaff52ebfa56c28fed3d995ebb8cab"
|
||||||
|
integrity sha512-RcjNW7MUaNVqONhJH4+rtlAE3ow/9SsAM0YWV0Lgu3dbTKdWTa/pQXRdFWgoHWpzUKn+9oBKR5x8JdH+20wmgw==
|
||||||
|
|
||||||
stylelint-order@^4.0.0:
|
stylelint-order@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-4.0.0.tgz#2a945c2198caac3ff44687d7c8582c81d044b556"
|
resolved "https://registry.yarnpkg.com/stylelint-order/-/stylelint-order-4.0.0.tgz#2a945c2198caac3ff44687d7c8582c81d044b556"
|
||||||
|
|||||||
Reference in New Issue
Block a user