Add support for submitting stash-box scene updates by draft (#2577)

This commit is contained in:
InfiniteTF
2022-06-01 06:53:31 +02:00
committed by GitHub
parent e51083c26d
commit d68d022893
8 changed files with 332 additions and 267 deletions

View File

@@ -239,6 +239,52 @@ fragment URLFragment on URL {
url url
type type
} }
fragment ImageFragment on Image {
id
url
width
height
}
fragment TagFragment on Tag {
name
id
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment SceneFragment on Scene {
id
title
details
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment StudioFragment on Studio { fragment StudioFragment on Studio {
name name
id id
@@ -249,9 +295,11 @@ fragment StudioFragment on Studio {
... ImageFragment ... ImageFragment
} }
} }
fragment TagFragment on Tag { fragment PerformerAppearanceFragment on PerformerAppearance {
name as
id performer {
... PerformerFragment
}
} }
fragment PerformerFragment on Performer { fragment PerformerFragment on Performer {
id id
@@ -287,61 +335,13 @@ fragment PerformerFragment on Performer {
... BodyModificationFragment ... BodyModificationFragment
} }
} }
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment SceneFragment on Scene {
id
title
details
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
fragment FuzzyDateFragment on FuzzyDate { fragment FuzzyDateFragment on FuzzyDate {
date date
accuracy accuracy
} }
fragment MeasurementsFragment on Measurements { fragment BodyModificationFragment on BodyModification {
band_size location
cup_size description
waist
hip
} }
` `
@@ -363,6 +363,35 @@ const FindScenesByFullFingerprintsDocument = `query FindScenesByFullFingerprints
... SceneFragment ... SceneFragment
} }
} }
fragment SceneFragment on Scene {
id
title
details
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment URLFragment on URL {
url
type
}
fragment StudioFragment on Studio { fragment StudioFragment on Studio {
name name
id id
@@ -373,6 +402,27 @@ fragment StudioFragment on Studio {
... ImageFragment ... ImageFragment
} }
} }
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment TagFragment on Tag { fragment TagFragment on Tag {
name name
id id
@@ -415,62 +465,12 @@ fragment FuzzyDateFragment on FuzzyDate {
date date
accuracy accuracy
} }
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment SceneFragment on Scene {
id
title
details
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment MeasurementsFragment on Measurements { fragment MeasurementsFragment on Measurements {
band_size band_size
cup_size cup_size
waist waist
hip hip
} }
fragment URLFragment on URL {
url
type
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
` `
func (c *Client) FindScenesByFullFingerprints(ctx context.Context, fingerprints []*FingerprintQueryInput, httpRequestOptions ...client.HTTPRequestOption) (*FindScenesByFullFingerprints, error) { func (c *Client) FindScenesByFullFingerprints(ctx context.Context, fingerprints []*FingerprintQueryInput, httpRequestOptions ...client.HTTPRequestOption) (*FindScenesByFullFingerprints, error) {
@@ -491,6 +491,26 @@ const FindScenesBySceneFingerprintsDocument = `query FindScenesBySceneFingerprin
... SceneFragment ... SceneFragment
} }
} }
fragment URLFragment on URL {
url
type
}
fragment ImageFragment on Image {
id
url
width
height
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
images {
... ImageFragment
}
}
fragment PerformerFragment on Performer { fragment PerformerFragment on Performer {
id id
name name
@@ -531,49 +551,11 @@ fragment MeasurementsFragment on Measurements {
waist waist
hip hip
} }
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment FingerprintFragment on Fingerprint { fragment FingerprintFragment on Fingerprint {
algorithm algorithm
hash hash
duration duration
} }
fragment ImageFragment on Image {
id
url
width
height
}
fragment URLFragment on URL {
url
type
}
fragment StudioFragment on Studio {
name
id
urls {
... URLFragment
}
images {
... ImageFragment
}
}
fragment TagFragment on Tag {
name
id
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment SceneFragment on Scene { fragment SceneFragment on Scene {
id id
title title
@@ -599,6 +581,24 @@ fragment SceneFragment on Scene {
... FingerprintFragment ... FingerprintFragment
} }
} }
fragment TagFragment on Tag {
name
id
}
fragment PerformerAppearanceFragment on PerformerAppearance {
as
performer {
... PerformerFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment BodyModificationFragment on BodyModification {
location
description
}
` `
func (c *Client) FindScenesBySceneFingerprints(ctx context.Context, fingerprints [][]*FingerprintQueryInput, httpRequestOptions ...client.HTTPRequestOption) (*FindScenesBySceneFingerprints, error) { func (c *Client) FindScenesBySceneFingerprints(ctx context.Context, fingerprints [][]*FingerprintQueryInput, httpRequestOptions ...client.HTTPRequestOption) (*FindScenesBySceneFingerprints, error) {
@@ -619,10 +619,41 @@ const SearchSceneDocument = `query SearchScene ($term: String!) {
... SceneFragment ... SceneFragment
} }
} }
fragment SceneFragment on Scene {
id
title
details
duration
date
urls {
... URLFragment
}
images {
... ImageFragment
}
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
}
fragment URLFragment on URL { fragment URLFragment on URL {
url url
type type
} }
fragment ImageFragment on Image {
id
url
width
height
}
fragment TagFragment on Tag { fragment TagFragment on Tag {
name name
id id
@@ -661,30 +692,14 @@ fragment PerformerFragment on Performer {
... BodyModificationFragment ... BodyModificationFragment
} }
} }
fragment SceneFragment on Scene { fragment FuzzyDateFragment on FuzzyDate {
id
title
details
duration
date date
urls { accuracy
... URLFragment }
} fragment FingerprintFragment on Fingerprint {
images { algorithm
... ImageFragment hash
} duration
studio {
... StudioFragment
}
tags {
... TagFragment
}
performers {
... PerformerAppearanceFragment
}
fingerprints {
... FingerprintFragment
}
} }
fragment StudioFragment on Studio { fragment StudioFragment on Studio {
name name
@@ -702,10 +717,6 @@ fragment PerformerAppearanceFragment on PerformerAppearance {
... PerformerFragment ... PerformerFragment
} }
} }
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements { fragment MeasurementsFragment on Measurements {
band_size band_size
cup_size cup_size
@@ -716,17 +727,6 @@ fragment BodyModificationFragment on BodyModification {
location location
description description
} }
fragment FingerprintFragment on Fingerprint {
algorithm
hash
duration
}
fragment ImageFragment on Image {
id
url
width
height
}
` `
func (c *Client) SearchScene(ctx context.Context, term string, httpRequestOptions ...client.HTTPRequestOption) (*SearchScene, error) { func (c *Client) SearchScene(ctx context.Context, term string, httpRequestOptions ...client.HTTPRequestOption) (*SearchScene, error) {
@@ -747,20 +747,6 @@ const SearchPerformerDocument = `query SearchPerformer ($term: String!) {
... PerformerFragment ... PerformerFragment
} }
} }
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment PerformerFragment on Performer { fragment PerformerFragment on Performer {
id id
name name
@@ -805,6 +791,20 @@ fragment ImageFragment on Image {
width width
height height
} }
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment BodyModificationFragment on BodyModification {
location
description
}
` `
func (c *Client) SearchPerformer(ctx context.Context, term string, httpRequestOptions ...client.HTTPRequestOption) (*SearchPerformer, error) { func (c *Client) SearchPerformer(ctx context.Context, term string, httpRequestOptions ...client.HTTPRequestOption) (*SearchPerformer, error) {
@@ -825,20 +825,6 @@ const FindPerformerByIDDocument = `query FindPerformerByID ($id: ID!) {
... PerformerFragment ... PerformerFragment
} }
} }
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment PerformerFragment on Performer { fragment PerformerFragment on Performer {
id id
name name
@@ -883,6 +869,20 @@ fragment ImageFragment on Image {
width width
height height
} }
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
}
fragment MeasurementsFragment on Measurements {
band_size
cup_size
waist
hip
}
fragment BodyModificationFragment on BodyModification {
location
description
}
` `
func (c *Client) FindPerformerByID(ctx context.Context, id string, httpRequestOptions ...client.HTTPRequestOption) (*FindPerformerByID, error) { func (c *Client) FindPerformerByID(ctx context.Context, id string, httpRequestOptions ...client.HTTPRequestOption) (*FindPerformerByID, error) {
@@ -903,6 +903,14 @@ const FindSceneByIDDocument = `query FindSceneByID ($id: ID!) {
... SceneFragment ... SceneFragment
} }
} }
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment URLFragment on URL {
url
type
}
fragment ImageFragment on Image { fragment ImageFragment on Image {
id id
url url
@@ -913,11 +921,43 @@ fragment TagFragment on Tag {
name name
id id
} }
fragment PerformerAppearanceFragment on PerformerAppearance { fragment PerformerFragment on Performer {
as id
performer { name
... PerformerFragment disambiguation
aliases
gender
merged_ids
urls {
... URLFragment
} }
images {
... ImageFragment
}
birthdate {
... FuzzyDateFragment
}
ethnicity
country
eye_color
hair_color
height
measurements {
... MeasurementsFragment
}
breast_type
career_start_year
career_end_year
tattoos {
... BodyModificationFragment
}
piercings {
... BodyModificationFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
} }
fragment MeasurementsFragment on Measurements { fragment MeasurementsFragment on Measurements {
band_size band_size
@@ -925,10 +965,6 @@ fragment MeasurementsFragment on Measurements {
waist waist
hip hip
} }
fragment BodyModificationFragment on BodyModification {
location
description
}
fragment SceneFragment on Scene { fragment SceneFragment on Scene {
id id
title title
@@ -954,10 +990,6 @@ fragment SceneFragment on Scene {
... FingerprintFragment ... FingerprintFragment
} }
} }
fragment URLFragment on URL {
url
type
}
fragment StudioFragment on Studio { fragment StudioFragment on Studio {
name name
id id
@@ -968,43 +1000,11 @@ fragment StudioFragment on Studio {
... ImageFragment ... ImageFragment
} }
} }
fragment PerformerFragment on Performer { fragment PerformerAppearanceFragment on PerformerAppearance {
id as
name performer {
disambiguation ... PerformerFragment
aliases
gender
merged_ids
urls {
... URLFragment
} }
images {
... ImageFragment
}
birthdate {
... FuzzyDateFragment
}
ethnicity
country
eye_color
hair_color
height
measurements {
... MeasurementsFragment
}
breast_type
career_start_year
career_end_year
tattoos {
... BodyModificationFragment
}
piercings {
... BodyModificationFragment
}
}
fragment FuzzyDateFragment on FuzzyDate {
date
accuracy
} }
fragment FingerprintFragment on Fingerprint { fragment FingerprintFragment on Fingerprint {
algorithm algorithm

View File

@@ -88,8 +88,8 @@ type DraftEntity struct {
ID *string `json:"id,omitempty"` ID *string `json:"id,omitempty"`
} }
func (DraftEntity) IsSceneDraftStudio() {}
func (DraftEntity) IsSceneDraftPerformer() {} func (DraftEntity) IsSceneDraftPerformer() {}
func (DraftEntity) IsSceneDraftStudio() {}
func (DraftEntity) IsSceneDraftTag() {} func (DraftEntity) IsSceneDraftTag() {}
type DraftEntityInput struct { type DraftEntityInput struct {
@@ -339,8 +339,8 @@ type Performer struct {
Updated time.Time `json:"updated"` Updated time.Time `json:"updated"`
} }
func (Performer) IsEditTarget() {}
func (Performer) IsSceneDraftPerformer() {} func (Performer) IsSceneDraftPerformer() {}
func (Performer) IsEditTarget() {}
type PerformerAppearance struct { type PerformerAppearance struct {
Performer *Performer `json:"performer,omitempty"` Performer *Performer `json:"performer,omitempty"`
@@ -846,8 +846,8 @@ type Studio struct {
Updated time.Time `json:"updated"` Updated time.Time `json:"updated"`
} }
func (Studio) IsSceneDraftStudio() {}
func (Studio) IsEditTarget() {} func (Studio) IsEditTarget() {}
func (Studio) IsSceneDraftStudio() {}
type StudioCreateInput struct { type StudioCreateInput struct {
Name string `json:"name"` Name string `json:"name"`

View File

@@ -5,6 +5,7 @@ import "github.com/99designs/gqlgen/graphql"
// Override for generated struct due to mistaken omitempty // Override for generated struct due to mistaken omitempty
// https://github.com/Yamashou/gqlgenc/issues/77 // https://github.com/Yamashou/gqlgenc/issues/77
type SceneDraftInput struct { type SceneDraftInput struct {
ID *string `json:"id,omitempty"`
Title *string `json:"title,omitempty"` Title *string `json:"title,omitempty"`
Details *string `json:"details,omitempty"` Details *string `json:"details,omitempty"`
URL *string `json:"url,omitempty"` URL *string `json:"url,omitempty"`

View File

@@ -825,6 +825,19 @@ func (c Client) SubmitSceneDraft(ctx context.Context, sceneID int, endpoint stri
} }
} }
stashIDs, err := qb.GetStashIDs(sceneID)
if err != nil {
return err
}
var stashID *string
for _, v := range stashIDs {
if v.Endpoint == endpoint {
stashID = &v.StashID
break
}
}
draft.ID = stashID
return nil return nil
}); err != nil { }); err != nil {
return nil, err return nil, err
@@ -910,6 +923,19 @@ func (c Client) SubmitPerformerDraft(ctx context.Context, performer *models.Perf
draft.Urls = urls draft.Urls = urls
} }
stashIDs, err := pqb.GetStashIDs(performer.ID)
if err != nil {
return err
}
var stashID *string
for _, v := range stashIDs {
if v.Endpoint == endpoint {
stashID = &v.StashID
break
}
}
draft.ID = stashID
return nil return nil
}); err != nil { }); err != nil {
return nil, err return nil, err

View File

@@ -19,6 +19,7 @@ import V0130 from "./versions/v0130.md";
import V0131 from "./versions/v0131.md"; import V0131 from "./versions/v0131.md";
import V0140 from "./versions/v0140.md"; import V0140 from "./versions/v0140.md";
import V0150 from "./versions/v0150.md"; import V0150 from "./versions/v0150.md";
import V0160 from "./versions/v0160.md";
import { MarkdownPage } from "../Shared/MarkdownPage"; import { MarkdownPage } from "../Shared/MarkdownPage";
// to avoid use of explicit any // to avoid use of explicit any
@@ -57,9 +58,9 @@ const Changelog: React.FC = () => {
// after new release: // after new release:
// add entry to releases, using the current* fields // add entry to releases, using the current* fields
// then update the current fields. // then update the current fields.
const currentVersion = stashVersion || "v0.15.0"; const currentVersion = stashVersion || "v0.16.0";
const currentDate = buildDate; const currentDate = buildDate;
const currentPage = V0150; const currentPage = V0160;
const releases: IStashRelease[] = [ const releases: IStashRelease[] = [
{ {
@@ -68,6 +69,11 @@ const Changelog: React.FC = () => {
page: currentPage, page: currentPage,
defaultOpen: true, defaultOpen: true,
}, },
{
version: "v0.15.0",
date: "2022-05-18",
page: V0150,
},
{ {
version: "v0.14.0", version: "v0.14.0",
date: "2022-04-11", date: "2022-04-11",

View File

@@ -0,0 +1,5 @@
### ✨ New Features
* Support submitting stash-box scene updates for scenes with stash ids. ([#2577](https://github.com/stashapp/stash/pull/2577))
### 🐛 Bug fixes
* Fix moved gallery zip files not being rescanned. ([#2611](https://github.com/stashapp/stash/pull/2611))

View File

@@ -8,7 +8,12 @@ import { FormattedMessage, useIntl } from "react-intl";
interface IProps { interface IProps {
show: boolean; show: boolean;
entity: { name?: string | null; id: string; title?: string | null }; entity: {
name?: string | null;
id: string;
title?: string | null;
stash_ids: { stash_id: string; endpoint: string }[];
};
boxes: Pick<GQL.StashBox, "name" | "endpoint">[]; boxes: Pick<GQL.StashBox, "name" | "endpoint">[];
query: DocumentNode; query: DocumentNode;
onHide: () => void; onHide: () => void;
@@ -59,6 +64,12 @@ export const SubmitStashBoxDraft: React.FC<IProps> = ({
const handleSelectBox = (e: React.ChangeEvent<HTMLSelectElement>) => const handleSelectBox = (e: React.ChangeEvent<HTMLSelectElement>) =>
setSelectedBox(Number.parseInt(e.currentTarget.value) ?? 0); setSelectedBox(Number.parseInt(e.currentTarget.value) ?? 0);
// If the scene has an attached stash_id from that endpoint, the operation will be an update
const isUpdate =
entity.stash_ids.find(
(id) => id.endpoint === boxes[selectedBox].endpoint
) !== undefined;
return ( return (
<Modal <Modal
icon="paper-plane" icon="paper-plane"
@@ -87,10 +98,24 @@ export const SubmitStashBoxDraft: React.FC<IProps> = ({
))} ))}
</Form.Control> </Form.Control>
</Form.Group> </Form.Group>
<Button onClick={handleSubmit}> <div className="text-right">
<FormattedMessage id="actions.submit" />{" "} {isUpdate && (
{`"${entity.name ?? entity.title}"`} <span className="mr-2">
</Button> <FormattedMessage
id="stashbox.submit_update"
values={{ endpoint_name: boxes[selectedBox].name }}
/>
</span>
)}
<Button
onClick={handleSubmit}
variant={isUpdate ? "primary" : "success"}
>
<FormattedMessage
id={`actions.${isUpdate ? "submit_update" : "submit"}`}
/>{" "}
</Button>
</div>
</> </>
) : ( ) : (
<> <>

View File

@@ -106,6 +106,7 @@
"view_random": "View Random", "view_random": "View Random",
"continue": "Continue", "continue": "Continue",
"submit": "Submit", "submit": "Submit",
"submit_update": "Submit update",
"logout": "Log out", "logout": "Log out",
"remove_from_gallery": "Remove from Gallery", "remove_from_gallery": "Remove from Gallery",
"delete_stashid": "Delete StashID", "delete_stashid": "Delete StashID",
@@ -976,7 +977,8 @@
"selected_stash_box": "Selected Stash-Box endpoint", "selected_stash_box": "Selected Stash-Box endpoint",
"submission_successful": "Submission successful", "submission_successful": "Submission successful",
"submission_failed": "Submission failed", "submission_failed": "Submission failed",
"go_review_draft": "Go to {endpoint_name} to review draft." "go_review_draft": "Go to {endpoint_name} to review draft.",
"submit_update": "Already exists in {endpoint_name}"
}, },
"performer_tagger": { "performer_tagger": {
"network_error": "Network Error", "network_error": "Network Error",