mirror of
https://github.com/stashapp/stash.git
synced 2026-02-09 17:01:34 +01:00
Merge a03532c909 into 8dec195c2d
This commit is contained in:
commit
993e81c031
33 changed files with 404 additions and 229 deletions
|
|
@ -328,6 +328,8 @@ input SceneFilterType {
|
|||
last_played_at: TimestampCriterionInput
|
||||
"Filter by date"
|
||||
date: DateCriterionInput
|
||||
"Filter by production date"
|
||||
production_date: DateCriterionInput
|
||||
"Filter by creation time"
|
||||
created_at: TimestampCriterionInput
|
||||
"Filter by last update time"
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ type Scene {
|
|||
url: String @deprecated(reason: "Use urls")
|
||||
urls: [String!]!
|
||||
date: String
|
||||
production_date: String
|
||||
# rating expressed as 1-100
|
||||
rating100: Int
|
||||
organized: Boolean!
|
||||
|
|
@ -101,6 +102,7 @@ input SceneCreateInput {
|
|||
url: String @deprecated(reason: "Use urls")
|
||||
urls: [String!]
|
||||
date: String
|
||||
production_date: String
|
||||
# rating expressed as 1-100
|
||||
rating100: Int
|
||||
organized: Boolean
|
||||
|
|
@ -132,6 +134,7 @@ input SceneUpdateInput {
|
|||
url: String @deprecated(reason: "Use urls")
|
||||
urls: [String!]
|
||||
date: String
|
||||
production_date: String
|
||||
# rating expressed as 1-100
|
||||
rating100: Int
|
||||
o_counter: Int
|
||||
|
|
@ -181,6 +184,7 @@ input BulkSceneUpdateInput {
|
|||
url: String @deprecated(reason: "Use urls")
|
||||
urls: BulkUpdateStrings
|
||||
date: String
|
||||
production_date: String
|
||||
# rating expressed as 1-100
|
||||
rating100: Int
|
||||
organized: Boolean
|
||||
|
|
@ -237,6 +241,7 @@ type SceneParserResult {
|
|||
director: String
|
||||
url: String
|
||||
date: String
|
||||
production_date: String
|
||||
# rating expressed as 1-5
|
||||
rating: Int @deprecated(reason: "Use 1-100 range with rating100")
|
||||
# rating expressed as 1-100
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ type ScrapedScene {
|
|||
url: String @deprecated(reason: "use urls")
|
||||
urls: [String!]
|
||||
date: String
|
||||
production_date: String
|
||||
|
||||
"This should be a base64 encoded data URL"
|
||||
image: String
|
||||
|
|
@ -107,6 +108,7 @@ input ScrapedSceneInput {
|
|||
url: String @deprecated(reason: "use urls")
|
||||
urls: [String!]
|
||||
date: String
|
||||
production_date: String
|
||||
|
||||
# no image, file, duration or relationships
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ fragment SceneFragment on Scene {
|
|||
director
|
||||
duration
|
||||
date
|
||||
production_date
|
||||
urls {
|
||||
...URLFragment
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,14 @@ func (r *sceneResolver) Date(ctx context.Context, obj *models.Scene) (*string, e
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *sceneResolver) ProductionDate(ctx context.Context, obj *models.Scene) (*string, error) {
|
||||
if obj.ProductionDate != nil {
|
||||
result := obj.ProductionDate.String()
|
||||
return &result, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *sceneResolver) Files(ctx context.Context, obj *models.Scene) ([]*VideoFile, error) {
|
||||
files, err := r.getFiles(ctx, obj)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ func (r *mutationResolver) SceneCreate(ctx context.Context, input models.SceneCr
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("converting date: %w", err)
|
||||
}
|
||||
newScene.ProductionDate, err = translator.datePtr(input.ProductionDate)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting date: %w", err)
|
||||
}
|
||||
newScene.StudioID, err = translator.intPtrFromString(input.StudioID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting studio id: %w", err)
|
||||
|
|
@ -200,6 +204,10 @@ func scenePartialFromInput(input models.SceneUpdateInput, translator changesetTr
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("converting date: %w", err)
|
||||
}
|
||||
updatedScene.ProductionDate, err = translator.optionalDate(input.ProductionDate, "production_date")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting production date: %w", err)
|
||||
}
|
||||
updatedScene.StudioID, err = translator.optionalIntFromString(input.StudioID, "studio_id")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting studio id: %w", err)
|
||||
|
|
@ -355,6 +363,10 @@ func (r *mutationResolver) BulkSceneUpdate(ctx context.Context, input BulkSceneU
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("converting date: %w", err)
|
||||
}
|
||||
updatedScene.ProductionDate, err = translator.optionalDate(input.ProductionDate, "production_date")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting production date: %w", err)
|
||||
}
|
||||
updatedScene.StudioID, err = translator.optionalIntFromString(input.StudioID, "studio_id")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("converting studio id: %w", err)
|
||||
|
|
|
|||
|
|
@ -8,20 +8,21 @@ type SceneParserInput struct {
|
|||
}
|
||||
|
||||
type SceneParserResult struct {
|
||||
Scene *Scene `json:"scene"`
|
||||
Title *string `json:"title"`
|
||||
Code *string `json:"code"`
|
||||
Details *string `json:"details"`
|
||||
Director *string `json:"director"`
|
||||
URL *string `json:"url"`
|
||||
Date *string `json:"date"`
|
||||
Rating *int `json:"rating"`
|
||||
Rating100 *int `json:"rating100"`
|
||||
StudioID *string `json:"studio_id"`
|
||||
GalleryIds []string `json:"gallery_ids"`
|
||||
PerformerIds []string `json:"performer_ids"`
|
||||
Movies []*SceneMovieID `json:"movies"`
|
||||
TagIds []string `json:"tag_ids"`
|
||||
Scene *Scene `json:"scene"`
|
||||
Title *string `json:"title"`
|
||||
Code *string `json:"code"`
|
||||
Details *string `json:"details"`
|
||||
Director *string `json:"director"`
|
||||
URL *string `json:"url"`
|
||||
Date *string `json:"date"`
|
||||
ProductionDate *string `json:"production_date"`
|
||||
Rating *int `json:"rating"`
|
||||
Rating100 *int `json:"rating100"`
|
||||
StudioID *string `json:"studio_id"`
|
||||
GalleryIds []string `json:"gallery_ids"`
|
||||
PerformerIds []string `json:"performer_ids"`
|
||||
Movies []*SceneMovieID `json:"movies"`
|
||||
TagIds []string `json:"tag_ids"`
|
||||
}
|
||||
|
||||
type SceneMovieID struct {
|
||||
|
|
|
|||
|
|
@ -47,10 +47,11 @@ type Scene struct {
|
|||
// deprecated - for import only
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
URLs []string `json:"urls,omitempty"`
|
||||
Date string `json:"date,omitempty"`
|
||||
Rating int `json:"rating,omitempty"`
|
||||
Organized bool `json:"organized,omitempty"`
|
||||
URLs []string `json:"urls,omitempty"`
|
||||
Date string `json:"date,omitempty"`
|
||||
ProductionDate string `json:"production_date,omitempty"`
|
||||
Rating int `json:"rating,omitempty"`
|
||||
Organized bool `json:"organized,omitempty"`
|
||||
|
||||
// deprecated - for import only
|
||||
OCounter int `json:"o_counter,omitempty"`
|
||||
|
|
|
|||
|
|
@ -10,12 +10,13 @@ import (
|
|||
|
||||
// Scene stores the metadata for a single video scene.
|
||||
type Scene struct {
|
||||
ID int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Code string `json:"code"`
|
||||
Details string `json:"details"`
|
||||
Director string `json:"director"`
|
||||
Date *Date `json:"date"`
|
||||
ID int `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Code string `json:"code"`
|
||||
Details string `json:"details"`
|
||||
Director string `json:"director"`
|
||||
Date *Date `json:"date"`
|
||||
ProductionDate *Date `json:"production_date"`
|
||||
// Rating expressed in 1-100 scale
|
||||
Rating *int `json:"rating"`
|
||||
Organized bool `json:"organized"`
|
||||
|
|
@ -56,11 +57,12 @@ func NewScene() Scene {
|
|||
// ScenePartial represents part of a Scene object. It is used to update
|
||||
// the database entry.
|
||||
type ScenePartial struct {
|
||||
Title OptionalString
|
||||
Code OptionalString
|
||||
Details OptionalString
|
||||
Director OptionalString
|
||||
Date OptionalDate
|
||||
Title OptionalString
|
||||
Code OptionalString
|
||||
Details OptionalString
|
||||
Director OptionalString
|
||||
Date OptionalDate
|
||||
ProductionDate OptionalDate
|
||||
// Rating expressed in 1-100 scale
|
||||
Rating OptionalInt
|
||||
Organized OptionalBool
|
||||
|
|
@ -192,27 +194,35 @@ func (s ScenePartial) UpdateInput(id int) SceneUpdateInput {
|
|||
dateStr = &v
|
||||
}
|
||||
|
||||
var productionDateStr *string
|
||||
if s.ProductionDate.Set {
|
||||
d := s.ProductionDate.Value
|
||||
v := d.String()
|
||||
productionDateStr = &v
|
||||
}
|
||||
|
||||
var stashIDs StashIDs
|
||||
if s.StashIDs != nil {
|
||||
stashIDs = StashIDs(s.StashIDs.StashIDs)
|
||||
}
|
||||
|
||||
ret := SceneUpdateInput{
|
||||
ID: strconv.Itoa(id),
|
||||
Title: s.Title.Ptr(),
|
||||
Code: s.Code.Ptr(),
|
||||
Details: s.Details.Ptr(),
|
||||
Director: s.Director.Ptr(),
|
||||
Urls: s.URLs.Strings(),
|
||||
Date: dateStr,
|
||||
Rating100: s.Rating.Ptr(),
|
||||
Organized: s.Organized.Ptr(),
|
||||
StudioID: s.StudioID.StringPtr(),
|
||||
GalleryIds: s.GalleryIDs.IDStrings(),
|
||||
PerformerIds: s.PerformerIDs.IDStrings(),
|
||||
Movies: s.GroupIDs.SceneMovieInputs(),
|
||||
TagIds: s.TagIDs.IDStrings(),
|
||||
StashIds: stashIDs.ToStashIDInputs(),
|
||||
ID: strconv.Itoa(id),
|
||||
Title: s.Title.Ptr(),
|
||||
Code: s.Code.Ptr(),
|
||||
Details: s.Details.Ptr(),
|
||||
Director: s.Director.Ptr(),
|
||||
Urls: s.URLs.Strings(),
|
||||
Date: dateStr,
|
||||
ProductionDate: productionDateStr,
|
||||
Rating100: s.Rating.Ptr(),
|
||||
Organized: s.Organized.Ptr(),
|
||||
StudioID: s.StudioID.StringPtr(),
|
||||
GalleryIds: s.GalleryIDs.IDStrings(),
|
||||
PerformerIds: s.PerformerIDs.IDStrings(),
|
||||
Movies: s.GroupIDs.SceneMovieInputs(),
|
||||
TagIds: s.TagIDs.IDStrings(),
|
||||
StashIds: stashIDs.ToStashIDInputs(),
|
||||
}
|
||||
|
||||
return ret
|
||||
|
|
|
|||
|
|
@ -12,19 +12,21 @@ func TestScenePartial_UpdateInput(t *testing.T) {
|
|||
)
|
||||
|
||||
var (
|
||||
title = "title"
|
||||
code = "1337"
|
||||
details = "details"
|
||||
director = "director"
|
||||
url = "url"
|
||||
date = "2001-02-03"
|
||||
rating100 = 80
|
||||
organized = true
|
||||
studioID = 2
|
||||
studioIDStr = "2"
|
||||
title = "title"
|
||||
code = "1337"
|
||||
details = "details"
|
||||
director = "director"
|
||||
url = "url"
|
||||
date = "2001-02-03"
|
||||
productionDate = "2001-01-02"
|
||||
rating100 = 80
|
||||
organized = true
|
||||
studioID = 2
|
||||
studioIDStr = "2"
|
||||
)
|
||||
|
||||
dateObj, _ := ParseDate(date)
|
||||
productionDateObj, _ := ParseDate(productionDate)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
@ -44,22 +46,24 @@ func TestScenePartial_UpdateInput(t *testing.T) {
|
|||
Values: []string{url},
|
||||
Mode: RelationshipUpdateModeSet,
|
||||
},
|
||||
Date: NewOptionalDate(dateObj),
|
||||
Rating: NewOptionalInt(rating100),
|
||||
Organized: NewOptionalBool(organized),
|
||||
StudioID: NewOptionalInt(studioID),
|
||||
Date: NewOptionalDate(dateObj),
|
||||
ProductionDate: NewOptionalDate(productionDateObj),
|
||||
Rating: NewOptionalInt(rating100),
|
||||
Organized: NewOptionalBool(organized),
|
||||
StudioID: NewOptionalInt(studioID),
|
||||
},
|
||||
SceneUpdateInput{
|
||||
ID: idStr,
|
||||
Title: &title,
|
||||
Code: &code,
|
||||
Details: &details,
|
||||
Director: &director,
|
||||
Urls: []string{url},
|
||||
Date: &date,
|
||||
Rating100: &rating100,
|
||||
Organized: &organized,
|
||||
StudioID: &studioIDStr,
|
||||
ID: idStr,
|
||||
Title: &title,
|
||||
Code: &code,
|
||||
Details: &details,
|
||||
Director: &director,
|
||||
Urls: []string{url},
|
||||
Date: &date,
|
||||
ProductionDate: &productionDate,
|
||||
Rating100: &rating100,
|
||||
Organized: &organized,
|
||||
StudioID: &studioIDStr,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -576,13 +576,14 @@ func (g ScrapedGroup) ScrapedMovie() ScrapedMovie {
|
|||
}
|
||||
|
||||
type ScrapedScene struct {
|
||||
Title *string `json:"title"`
|
||||
Code *string `json:"code"`
|
||||
Details *string `json:"details"`
|
||||
Director *string `json:"director"`
|
||||
URL *string `json:"url"`
|
||||
URLs []string `json:"urls"`
|
||||
Date *string `json:"date"`
|
||||
Title *string `json:"title"`
|
||||
Code *string `json:"code"`
|
||||
Details *string `json:"details"`
|
||||
Director *string `json:"director"`
|
||||
URL *string `json:"url"`
|
||||
URLs []string `json:"urls"`
|
||||
Date *string `json:"date"`
|
||||
ProductionDate *string `json:"production_date"`
|
||||
// This should be a base64 encoded data URL
|
||||
Image *string `json:"image"`
|
||||
File *SceneFileType `json:"file"`
|
||||
|
|
@ -599,14 +600,15 @@ type ScrapedScene struct {
|
|||
func (ScrapedScene) IsScrapedContent() {}
|
||||
|
||||
type ScrapedSceneInput struct {
|
||||
Title *string `json:"title"`
|
||||
Code *string `json:"code"`
|
||||
Details *string `json:"details"`
|
||||
Director *string `json:"director"`
|
||||
URL *string `json:"url"`
|
||||
URLs []string `json:"urls"`
|
||||
Date *string `json:"date"`
|
||||
RemoteSiteID *string `json:"remote_site_id"`
|
||||
Title *string `json:"title"`
|
||||
Code *string `json:"code"`
|
||||
Details *string `json:"details"`
|
||||
Director *string `json:"director"`
|
||||
URL *string `json:"url"`
|
||||
URLs []string `json:"urls"`
|
||||
Date *string `json:"date"`
|
||||
ProductionDate *string `json:"production_date"`
|
||||
RemoteSiteID *string `json:"remote_site_id"`
|
||||
}
|
||||
|
||||
type ScrapedImage struct {
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ type SceneFilterType struct {
|
|||
LastPlayedAt *TimestampCriterionInput `json:"last_played_at"`
|
||||
// Filter by date
|
||||
Date *DateCriterionInput `json:"date"`
|
||||
// Filter by production date
|
||||
ProductionDate *DateCriterionInput `json:"production_date"`
|
||||
// Filter by related galleries that meet this criteria
|
||||
GalleriesFilter *GalleryFilterType `json:"galleries_filter"`
|
||||
// Filter by related performers that meet this criteria
|
||||
|
|
@ -153,21 +155,22 @@ type SceneGroupInput struct {
|
|||
}
|
||||
|
||||
type SceneCreateInput struct {
|
||||
Title *string `json:"title"`
|
||||
Code *string `json:"code"`
|
||||
Details *string `json:"details"`
|
||||
Director *string `json:"director"`
|
||||
URL *string `json:"url"`
|
||||
Urls []string `json:"urls"`
|
||||
Date *string `json:"date"`
|
||||
Rating100 *int `json:"rating100"`
|
||||
Organized *bool `json:"organized"`
|
||||
StudioID *string `json:"studio_id"`
|
||||
GalleryIds []string `json:"gallery_ids"`
|
||||
PerformerIds []string `json:"performer_ids"`
|
||||
Movies []SceneMovieInput `json:"movies"`
|
||||
Groups []SceneGroupInput `json:"groups"`
|
||||
TagIds []string `json:"tag_ids"`
|
||||
Title *string `json:"title"`
|
||||
Code *string `json:"code"`
|
||||
Details *string `json:"details"`
|
||||
Director *string `json:"director"`
|
||||
URL *string `json:"url"`
|
||||
Urls []string `json:"urls"`
|
||||
Date *string `json:"date"`
|
||||
ProductionDate *string `json:"production_date"`
|
||||
Rating100 *int `json:"rating100"`
|
||||
Organized *bool `json:"organized"`
|
||||
StudioID *string `json:"studio_id"`
|
||||
GalleryIds []string `json:"gallery_ids"`
|
||||
PerformerIds []string `json:"performer_ids"`
|
||||
Movies []SceneMovieInput `json:"movies"`
|
||||
Groups []SceneGroupInput `json:"groups"`
|
||||
TagIds []string `json:"tag_ids"`
|
||||
// This should be a URL or a base64 encoded data URL
|
||||
CoverImage *string `json:"cover_image"`
|
||||
StashIds []StashIDInput `json:"stash_ids"`
|
||||
|
|
@ -187,6 +190,7 @@ type SceneUpdateInput struct {
|
|||
URL *string `json:"url"`
|
||||
Urls []string `json:"urls"`
|
||||
Date *string `json:"date"`
|
||||
ProductionDate *string `json:"production_date"`
|
||||
Rating100 *int `json:"rating100"`
|
||||
OCounter *int `json:"o_counter"`
|
||||
Organized *bool `json:"organized"`
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ func ToBasicJSON(ctx context.Context, reader ExportGetter, scene *models.Scene)
|
|||
newSceneJSON.Date = scene.Date.String()
|
||||
}
|
||||
|
||||
if scene.ProductionDate != nil {
|
||||
newSceneJSON.ProductionDate = scene.ProductionDate.String()
|
||||
}
|
||||
|
||||
if scene.Rating != nil {
|
||||
newSceneJSON.Rating = *scene.Rating
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,12 @@ func (i *Importer) sceneJSONToScene(sceneJSON jsonschema.Scene) models.Scene {
|
|||
newScene.Date = &d
|
||||
}
|
||||
}
|
||||
if sceneJSON.ProductionDate != "" {
|
||||
d, err := models.ParseDate(sceneJSON.ProductionDate)
|
||||
if err == nil {
|
||||
newScene.ProductionDate = &d
|
||||
}
|
||||
}
|
||||
if sceneJSON.Rating != 0 {
|
||||
newScene.Rating = &sceneJSON.Rating
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ func queryURLParametersFromScrapedScene(scene models.ScrapedSceneInput) queryURL
|
|||
setField("url", scene.URL)
|
||||
}
|
||||
setField("date", scene.Date)
|
||||
setField("production_date", scene.ProductionDate)
|
||||
setField("details", scene.Details)
|
||||
setField("director", scene.Director)
|
||||
setField("remote_site_id", scene.RemoteSiteID)
|
||||
|
|
|
|||
|
|
@ -328,15 +328,16 @@ func (f stashVideoFile) SceneFileType() models.SceneFileType {
|
|||
}
|
||||
|
||||
type scrapedSceneStash struct {
|
||||
ID string `graphql:"id" json:"id"`
|
||||
Title *string `graphql:"title" json:"title"`
|
||||
Details *string `graphql:"details" json:"details"`
|
||||
URLs []string `graphql:"urls" json:"urls"`
|
||||
Date *string `graphql:"date" json:"date"`
|
||||
Files []stashVideoFile `graphql:"files" json:"files"`
|
||||
Studio *scrapedStudioStash `graphql:"studio" json:"studio"`
|
||||
Tags []*scrapedTagStash `graphql:"tags" json:"tags"`
|
||||
Performers []*scrapedPerformerStash `graphql:"performers" json:"performers"`
|
||||
ID string `graphql:"id" json:"id"`
|
||||
Title *string `graphql:"title" json:"title"`
|
||||
Details *string `graphql:"details" json:"details"`
|
||||
URLs []string `graphql:"urls" json:"urls"`
|
||||
Date *string `graphql:"date" json:"date"`
|
||||
ProductionDate *string `graphql:"production_date" json:"production_date"`
|
||||
Files []stashVideoFile `graphql:"files" json:"files"`
|
||||
Studio *scrapedStudioStash `graphql:"studio" json:"studio"`
|
||||
Tags []*scrapedTagStash `graphql:"tags" json:"tags"`
|
||||
Performers []*scrapedPerformerStash `graphql:"performers" json:"performers"`
|
||||
}
|
||||
|
||||
func (s *stashScraper) scrapeSceneByScene(ctx context.Context, scene *models.Scene) (*models.ScrapedScene, error) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ const (
|
|||
cacheSizeEnv = "STASH_SQLITE_CACHE_SIZE"
|
||||
)
|
||||
|
||||
var appSchemaVersion uint = 77
|
||||
var appSchemaVersion uint = 78
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
var migrationsBox embed.FS
|
||||
|
|
|
|||
2
pkg/sqlite/migrations/78_scene_production_date.up.sql
Normal file
2
pkg/sqlite/migrations/78_scene_production_date.up.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE `scenes` ADD COLUMN `production_date` date;
|
||||
ALTER TABLE `scenes` ADD COLUMN `production_date_precision` TINYINT;
|
||||
|
|
@ -77,13 +77,15 @@ ORDER BY files.size DESC;
|
|||
`
|
||||
|
||||
type sceneRow struct {
|
||||
ID int `db:"id" goqu:"skipinsert"`
|
||||
Title zero.String `db:"title"`
|
||||
Code zero.String `db:"code"`
|
||||
Details zero.String `db:"details"`
|
||||
Director zero.String `db:"director"`
|
||||
Date NullDate `db:"date"`
|
||||
DatePrecision null.Int `db:"date_precision"`
|
||||
ID int `db:"id" goqu:"skipinsert"`
|
||||
Title zero.String `db:"title"`
|
||||
Code zero.String `db:"code"`
|
||||
Details zero.String `db:"details"`
|
||||
Director zero.String `db:"director"`
|
||||
Date NullDate `db:"date"`
|
||||
DatePrecision null.Int `db:"date_precision"`
|
||||
ProductionDate NullDate `db:"production_date"`
|
||||
ProductionDatePrecision null.Int `db:"production_date_precision"`
|
||||
// expressed as 1-100
|
||||
Rating null.Int `db:"rating"`
|
||||
Organized bool `db:"organized"`
|
||||
|
|
@ -105,6 +107,8 @@ func (r *sceneRow) fromScene(o models.Scene) {
|
|||
r.Director = zero.StringFrom(o.Director)
|
||||
r.Date = NullDateFromDatePtr(o.Date)
|
||||
r.DatePrecision = datePrecisionFromDatePtr(o.Date)
|
||||
r.ProductionDate = NullDateFromDatePtr(o.ProductionDate)
|
||||
r.ProductionDatePrecision = datePrecisionFromDatePtr(o.ProductionDate)
|
||||
r.Rating = intFromPtr(o.Rating)
|
||||
r.Organized = o.Organized
|
||||
r.StudioID = intFromPtr(o.StudioID)
|
||||
|
|
@ -125,15 +129,16 @@ type sceneQueryRow struct {
|
|||
|
||||
func (r *sceneQueryRow) resolve() *models.Scene {
|
||||
ret := &models.Scene{
|
||||
ID: r.ID,
|
||||
Title: r.Title.String,
|
||||
Code: r.Code.String,
|
||||
Details: r.Details.String,
|
||||
Director: r.Director.String,
|
||||
Date: r.Date.DatePtr(r.DatePrecision),
|
||||
Rating: nullIntPtr(r.Rating),
|
||||
Organized: r.Organized,
|
||||
StudioID: nullIntPtr(r.StudioID),
|
||||
ID: r.ID,
|
||||
Title: r.Title.String,
|
||||
Code: r.Code.String,
|
||||
Details: r.Details.String,
|
||||
Director: r.Director.String,
|
||||
Date: r.Date.DatePtr(r.DatePrecision),
|
||||
ProductionDate: r.ProductionDate.DatePtr(r.ProductionDatePrecision),
|
||||
Rating: nullIntPtr(r.Rating),
|
||||
Organized: r.Organized,
|
||||
StudioID: nullIntPtr(r.StudioID),
|
||||
|
||||
PrimaryFileID: nullIntFileIDPtr(r.PrimaryFileID),
|
||||
OSHash: r.PrimaryFileOshash.String,
|
||||
|
|
@ -163,6 +168,7 @@ func (r *sceneRowRecord) fromPartial(o models.ScenePartial) {
|
|||
r.setNullString("details", o.Details)
|
||||
r.setNullString("director", o.Director)
|
||||
r.setNullDate("date", "date_precision", o.Date)
|
||||
r.setNullDate("production_date", "production_date_precision", o.ProductionDate)
|
||||
r.setNullInt("rating", o.Rating)
|
||||
r.setBool("organized", o.Organized)
|
||||
r.setNullInt("studio_id", o.StudioID)
|
||||
|
|
@ -1117,6 +1123,7 @@ var sceneSortOptions = sortOptions{
|
|||
"created_at",
|
||||
"code",
|
||||
"date",
|
||||
"production_date",
|
||||
"file_count",
|
||||
"filesize",
|
||||
"duration",
|
||||
|
|
|
|||
|
|
@ -94,7 +94,8 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
|||
stashID1 = "stashid1"
|
||||
stashID2 = "stashid2"
|
||||
|
||||
date, _ = models.ParseDate("2003-02-01")
|
||||
date, _ = models.ParseDate("2003-02-01")
|
||||
productionDate, _ = models.ParseDate("2003-01-02")
|
||||
|
||||
videoFile = makeFileWithID(fileIdxStartVideoFiles)
|
||||
)
|
||||
|
|
@ -107,20 +108,21 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
|||
{
|
||||
"full",
|
||||
models.Scene{
|
||||
Title: title,
|
||||
Code: code,
|
||||
Details: details,
|
||||
Director: director,
|
||||
URLs: models.NewRelatedStrings([]string{url}),
|
||||
Date: &date,
|
||||
Rating: &rating,
|
||||
Organized: true,
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Title: title,
|
||||
Code: code,
|
||||
Details: details,
|
||||
Director: director,
|
||||
URLs: models.NewRelatedStrings([]string{url}),
|
||||
Date: &date,
|
||||
ProductionDate: &productionDate,
|
||||
Rating: &rating,
|
||||
Organized: true,
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Groups: models.NewRelatedGroups([]models.GroupsScenes{
|
||||
{
|
||||
GroupID: groupIDs[groupIdxWithScene],
|
||||
|
|
@ -151,15 +153,16 @@ func Test_sceneQueryBuilder_Create(t *testing.T) {
|
|||
{
|
||||
"with file",
|
||||
models.Scene{
|
||||
Title: title,
|
||||
Code: code,
|
||||
Details: details,
|
||||
Director: director,
|
||||
URLs: models.NewRelatedStrings([]string{url}),
|
||||
Date: &date,
|
||||
Rating: &rating,
|
||||
Organized: true,
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
Title: title,
|
||||
Code: code,
|
||||
Details: details,
|
||||
Director: director,
|
||||
URLs: models.NewRelatedStrings([]string{url}),
|
||||
Date: &date,
|
||||
ProductionDate: &productionDate,
|
||||
Rating: &rating,
|
||||
Organized: true,
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
Files: models.NewRelatedVideoFiles([]*models.VideoFile{
|
||||
videoFile.(*models.VideoFile),
|
||||
}),
|
||||
|
|
@ -328,7 +331,8 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
|||
stashID1 = "stashid1"
|
||||
stashID2 = "stashid2"
|
||||
|
||||
date, _ = models.ParseDate("2003-02-01")
|
||||
date, _ = models.ParseDate("2003-02-01")
|
||||
productionDate, _ = models.ParseDate("2003-01-02")
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
|
|
@ -339,21 +343,22 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
|||
{
|
||||
"full",
|
||||
&models.Scene{
|
||||
ID: sceneIDs[sceneIdxWithGallery],
|
||||
Title: title,
|
||||
Code: code,
|
||||
Details: details,
|
||||
Director: director,
|
||||
URLs: models.NewRelatedStrings([]string{url}),
|
||||
Date: &date,
|
||||
Rating: &rating,
|
||||
Organized: true,
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
ID: sceneIDs[sceneIdxWithGallery],
|
||||
Title: title,
|
||||
Code: code,
|
||||
Details: details,
|
||||
Director: director,
|
||||
URLs: models.NewRelatedStrings([]string{url}),
|
||||
Date: &date,
|
||||
ProductionDate: &productionDate,
|
||||
Rating: &rating,
|
||||
Organized: true,
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Groups: models.NewRelatedGroups([]models.GroupsScenes{
|
||||
{
|
||||
GroupID: groupIDs[groupIdxWithScene],
|
||||
|
|
@ -506,18 +511,19 @@ func Test_sceneQueryBuilder_Update(t *testing.T) {
|
|||
func clearScenePartial() models.ScenePartial {
|
||||
// leave mandatory fields
|
||||
return models.ScenePartial{
|
||||
Title: models.OptionalString{Set: true, Null: true},
|
||||
Code: models.OptionalString{Set: true, Null: true},
|
||||
Details: models.OptionalString{Set: true, Null: true},
|
||||
Director: models.OptionalString{Set: true, Null: true},
|
||||
URLs: &models.UpdateStrings{Mode: models.RelationshipUpdateModeSet},
|
||||
Date: models.OptionalDate{Set: true, Null: true},
|
||||
Rating: models.OptionalInt{Set: true, Null: true},
|
||||
StudioID: models.OptionalInt{Set: true, Null: true},
|
||||
GalleryIDs: &models.UpdateIDs{Mode: models.RelationshipUpdateModeSet},
|
||||
TagIDs: &models.UpdateIDs{Mode: models.RelationshipUpdateModeSet},
|
||||
PerformerIDs: &models.UpdateIDs{Mode: models.RelationshipUpdateModeSet},
|
||||
StashIDs: &models.UpdateStashIDs{Mode: models.RelationshipUpdateModeSet},
|
||||
Title: models.OptionalString{Set: true, Null: true},
|
||||
Code: models.OptionalString{Set: true, Null: true},
|
||||
Details: models.OptionalString{Set: true, Null: true},
|
||||
Director: models.OptionalString{Set: true, Null: true},
|
||||
URLs: &models.UpdateStrings{Mode: models.RelationshipUpdateModeSet},
|
||||
Date: models.OptionalDate{Set: true, Null: true},
|
||||
ProductionDate: models.OptionalDate{Set: true, Null: true},
|
||||
Rating: models.OptionalInt{Set: true, Null: true},
|
||||
StudioID: models.OptionalInt{Set: true, Null: true},
|
||||
GalleryIDs: &models.UpdateIDs{Mode: models.RelationshipUpdateModeSet},
|
||||
TagIDs: &models.UpdateIDs{Mode: models.RelationshipUpdateModeSet},
|
||||
PerformerIDs: &models.UpdateIDs{Mode: models.RelationshipUpdateModeSet},
|
||||
StashIDs: &models.UpdateStashIDs{Mode: models.RelationshipUpdateModeSet},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -540,7 +546,8 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
|||
stashID1 = "stashid1"
|
||||
stashID2 = "stashid2"
|
||||
|
||||
date, _ = models.ParseDate("2003-02-01")
|
||||
date, _ = models.ParseDate("2003-02-01")
|
||||
productionDate, _ = models.ParseDate("2003-01-02")
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
|
|
@ -562,12 +569,13 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
|||
Values: []string{url},
|
||||
Mode: models.RelationshipUpdateModeSet,
|
||||
},
|
||||
Date: models.NewOptionalDate(date),
|
||||
Rating: models.NewOptionalInt(rating),
|
||||
Organized: models.NewOptionalBool(true),
|
||||
StudioID: models.NewOptionalInt(studioIDs[studioIdxWithScene]),
|
||||
CreatedAt: models.NewOptionalTime(createdAt),
|
||||
UpdatedAt: models.NewOptionalTime(updatedAt),
|
||||
Date: models.NewOptionalDate(date),
|
||||
ProductionDate: models.NewOptionalDate(productionDate),
|
||||
Rating: models.NewOptionalInt(rating),
|
||||
Organized: models.NewOptionalBool(true),
|
||||
StudioID: models.NewOptionalInt(studioIDs[studioIdxWithScene]),
|
||||
CreatedAt: models.NewOptionalTime(createdAt),
|
||||
UpdatedAt: models.NewOptionalTime(updatedAt),
|
||||
GalleryIDs: &models.UpdateIDs{
|
||||
IDs: []int{galleryIDs[galleryIdxWithScene]},
|
||||
Mode: models.RelationshipUpdateModeSet,
|
||||
|
|
@ -616,20 +624,21 @@ func Test_sceneQueryBuilder_UpdatePartial(t *testing.T) {
|
|||
Files: models.NewRelatedVideoFiles([]*models.VideoFile{
|
||||
makeSceneFile(sceneIdxWithSpacedName),
|
||||
}),
|
||||
Title: title,
|
||||
Code: code,
|
||||
Details: details,
|
||||
Director: director,
|
||||
URLs: models.NewRelatedStrings([]string{url}),
|
||||
Date: &date,
|
||||
Rating: &rating,
|
||||
Organized: true,
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Title: title,
|
||||
Code: code,
|
||||
Details: details,
|
||||
Director: director,
|
||||
URLs: models.NewRelatedStrings([]string{url}),
|
||||
Date: &date,
|
||||
ProductionDate: &productionDate,
|
||||
Rating: &rating,
|
||||
Organized: true,
|
||||
StudioID: &studioIDs[studioIdxWithScene],
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
GalleryIDs: models.NewRelatedIDs([]int{galleryIDs[galleryIdxWithScene]}),
|
||||
TagIDs: models.NewRelatedIDs([]int{tagIDs[tagIdx1WithDupName], tagIDs[tagIdx1WithScene]}),
|
||||
PerformerIDs: models.NewRelatedIDs([]int{performerIDs[performerIdx1WithScene], performerIDs[performerIdx1WithDupName]}),
|
||||
Groups: models.NewRelatedGroups([]models.GroupsScenes{
|
||||
{
|
||||
GroupID: groupIDs[groupIdxWithScene],
|
||||
|
|
@ -3292,6 +3301,28 @@ func TestSceneQueryIsMissingDate(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestSceneQueryIsMissingProductionDate(t *testing.T) {
|
||||
withTxn(func(ctx context.Context) error {
|
||||
sqb := db.Scene
|
||||
isMissing := "production_date"
|
||||
sceneFilter := models.SceneFilterType{
|
||||
IsMissing: &isMissing,
|
||||
}
|
||||
|
||||
scenes := queryScene(ctx, t, sqb, &sceneFilter, nil)
|
||||
|
||||
// one in four scenes have no production date
|
||||
assert.Len(t, scenes, int(math.Ceil(float64(totalScenes)/4)))
|
||||
|
||||
// ensure production date is null
|
||||
for _, scene := range scenes {
|
||||
assert.Nil(t, scene.ProductionDate)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestSceneQueryIsMissingTags(t *testing.T) {
|
||||
withTxn(func(ctx context.Context) error {
|
||||
sqb := db.Scene
|
||||
|
|
|
|||
|
|
@ -1174,16 +1174,17 @@ func makeScene(i int) *models.Scene {
|
|||
URLs: models.NewRelatedStrings([]string{
|
||||
getSceneEmptyString(i, urlField),
|
||||
}),
|
||||
Rating: getIntPtr(rating),
|
||||
Date: getObjectDate(i),
|
||||
StudioID: studioID,
|
||||
GalleryIDs: models.NewRelatedIDs(gids),
|
||||
PerformerIDs: models.NewRelatedIDs(pids),
|
||||
TagIDs: models.NewRelatedIDs(tids),
|
||||
Groups: models.NewRelatedGroups(groups),
|
||||
StashIDs: models.NewRelatedStashIDs(sceneStashIDs(i)),
|
||||
PlayDuration: getScenePlayDuration(i),
|
||||
ResumeTime: getSceneResumeTime(i),
|
||||
Rating: getIntPtr(rating),
|
||||
Date: getObjectDate(i),
|
||||
ProductionDate: getObjectDate(i),
|
||||
StudioID: studioID,
|
||||
GalleryIDs: models.NewRelatedIDs(gids),
|
||||
PerformerIDs: models.NewRelatedIDs(pids),
|
||||
TagIDs: models.NewRelatedIDs(tids),
|
||||
Groups: models.NewRelatedGroups(groups),
|
||||
StashIDs: models.NewRelatedStashIDs(sceneStashIDs(i)),
|
||||
PlayDuration: getScenePlayDuration(i),
|
||||
ResumeTime: getSceneResumeTime(i),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -406,19 +406,20 @@ func (t *FingerprintFragment) GetDuration() int {
|
|||
}
|
||||
|
||||
type SceneFragment struct {
|
||||
ID string "json:\"id\" graphql:\"id\""
|
||||
Title *string "json:\"title,omitempty\" graphql:\"title\""
|
||||
Code *string "json:\"code,omitempty\" graphql:\"code\""
|
||||
Details *string "json:\"details,omitempty\" graphql:\"details\""
|
||||
Director *string "json:\"director,omitempty\" graphql:\"director\""
|
||||
Duration *int "json:\"duration,omitempty\" graphql:\"duration\""
|
||||
Date *string "json:\"date,omitempty\" graphql:\"date\""
|
||||
Urls []*URLFragment "json:\"urls\" graphql:\"urls\""
|
||||
Images []*ImageFragment "json:\"images\" graphql:\"images\""
|
||||
Studio *StudioFragment "json:\"studio,omitempty\" graphql:\"studio\""
|
||||
Tags []*TagFragment "json:\"tags\" graphql:\"tags\""
|
||||
Performers []*PerformerAppearanceFragment "json:\"performers\" graphql:\"performers\""
|
||||
Fingerprints []*FingerprintFragment "json:\"fingerprints\" graphql:\"fingerprints\""
|
||||
ID string "json:\"id\" graphql:\"id\""
|
||||
Title *string "json:\"title,omitempty\" graphql:\"title\""
|
||||
Code *string "json:\"code,omitempty\" graphql:\"code\""
|
||||
Details *string "json:\"details,omitempty\" graphql:\"details\""
|
||||
Director *string "json:\"director,omitempty\" graphql:\"director\""
|
||||
Duration *int "json:\"duration,omitempty\" graphql:\"duration\""
|
||||
Date *string "json:\"date,omitempty\" graphql:\"date\""
|
||||
ProductionDate *string "json:\"production_date,omitempty\" graphql:\"production_date\""
|
||||
Urls []*URLFragment "json:\"urls\" graphql:\"urls\""
|
||||
Images []*ImageFragment "json:\"images\" graphql:\"images\""
|
||||
Studio *StudioFragment "json:\"studio,omitempty\" graphql:\"studio\""
|
||||
Tags []*TagFragment "json:\"tags\" graphql:\"tags\""
|
||||
Performers []*PerformerAppearanceFragment "json:\"performers\" graphql:\"performers\""
|
||||
Fingerprints []*FingerprintFragment "json:\"fingerprints\" graphql:\"fingerprints\""
|
||||
}
|
||||
|
||||
func (t *SceneFragment) GetID() string {
|
||||
|
|
@ -463,6 +464,12 @@ func (t *SceneFragment) GetDate() *string {
|
|||
}
|
||||
return t.Date
|
||||
}
|
||||
func (t *SceneFragment) GetProductionDate() *string {
|
||||
if t == nil {
|
||||
t = &SceneFragment{}
|
||||
}
|
||||
return t.ProductionDate
|
||||
}
|
||||
func (t *SceneFragment) GetUrls() []*URLFragment {
|
||||
if t == nil {
|
||||
t = &SceneFragment{}
|
||||
|
|
@ -862,6 +869,7 @@ fragment SceneFragment on Scene {
|
|||
director
|
||||
duration
|
||||
date
|
||||
production_date
|
||||
urls {
|
||||
... URLFragment
|
||||
}
|
||||
|
|
@ -998,6 +1006,7 @@ fragment SceneFragment on Scene {
|
|||
director
|
||||
duration
|
||||
date
|
||||
production_date
|
||||
urls {
|
||||
... URLFragment
|
||||
}
|
||||
|
|
@ -1134,6 +1143,7 @@ fragment SceneFragment on Scene {
|
|||
director
|
||||
duration
|
||||
date
|
||||
production_date
|
||||
urls {
|
||||
... URLFragment
|
||||
}
|
||||
|
|
@ -1270,6 +1280,7 @@ fragment SceneFragment on Scene {
|
|||
director
|
||||
duration
|
||||
date
|
||||
production_date
|
||||
urls {
|
||||
... URLFragment
|
||||
}
|
||||
|
|
@ -1564,6 +1575,7 @@ fragment SceneFragment on Scene {
|
|||
director
|
||||
duration
|
||||
date
|
||||
production_date
|
||||
urls {
|
||||
... URLFragment
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,15 +158,16 @@ func (c Client) sceneFragmentToScrapedScene(ctx context.Context, s *graphql.Scen
|
|||
stashID := s.ID
|
||||
|
||||
ss := &models.ScrapedScene{
|
||||
Title: s.Title,
|
||||
Code: s.Code,
|
||||
Date: s.Date,
|
||||
Details: s.Details,
|
||||
Director: s.Director,
|
||||
URL: findURL(s.Urls, "STUDIO"),
|
||||
Duration: s.Duration,
|
||||
RemoteSiteID: &stashID,
|
||||
Fingerprints: getFingerprints(s),
|
||||
Title: s.Title,
|
||||
Code: s.Code,
|
||||
Date: s.Date,
|
||||
ProductionDate: s.ProductionDate,
|
||||
Details: s.Details,
|
||||
Director: s.Director,
|
||||
URL: findURL(s.Urls, "STUDIO"),
|
||||
Duration: s.Duration,
|
||||
RemoteSiteID: &stashID,
|
||||
Fingerprints: getFingerprints(s),
|
||||
// Image
|
||||
// stash_id
|
||||
}
|
||||
|
|
@ -296,6 +297,11 @@ func newSceneDraftInput(d SceneDraft, endpoint string) graphql.SceneDraftInput {
|
|||
draft.Date = &v
|
||||
}
|
||||
|
||||
if scene.ProductionDate != nil {
|
||||
v := scene.ProductionDate.String()
|
||||
draft.ProductionDate = &v
|
||||
}
|
||||
|
||||
if d.Studio != nil {
|
||||
studio := d.Studio
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ fragment SlimSceneData on Scene {
|
|||
director
|
||||
urls
|
||||
date
|
||||
production_date
|
||||
rating100
|
||||
o_counter
|
||||
organized
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ fragment SceneData on Scene {
|
|||
director
|
||||
urls
|
||||
date
|
||||
production_date
|
||||
rating100
|
||||
o_counter
|
||||
organized
|
||||
|
|
@ -85,6 +86,7 @@ fragment SelectSceneData on Scene {
|
|||
id
|
||||
title
|
||||
date
|
||||
production_date
|
||||
code
|
||||
studio {
|
||||
name
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ fragment ScrapedSceneData on ScrapedScene {
|
|||
director
|
||||
urls
|
||||
date
|
||||
production_date
|
||||
image
|
||||
remote_site_id
|
||||
|
||||
|
|
@ -254,6 +255,7 @@ fragment ScrapedStashBoxSceneData on ScrapedScene {
|
|||
director
|
||||
url
|
||||
date
|
||||
production_date
|
||||
image
|
||||
remote_site_id
|
||||
duration
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||
code: yup.string().ensure(),
|
||||
urls: yupUniqueStringList(intl),
|
||||
date: yupDateString(intl),
|
||||
production_date: yupDateString(intl),
|
||||
director: yup.string().ensure(),
|
||||
gallery_ids: yup.array(yup.string().required()).defined(),
|
||||
studio_id: yup.string().required().nullable(),
|
||||
|
|
@ -148,6 +149,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||
code: scene.code ?? "",
|
||||
urls: scene.urls ?? [],
|
||||
date: scene.date ?? "",
|
||||
production_date: scene.production_date ?? "",
|
||||
director: scene.director ?? "",
|
||||
gallery_ids: (scene.galleries ?? []).map((g) => g.id),
|
||||
studio_id: scene.studio?.id ?? null,
|
||||
|
|
@ -332,6 +334,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||
try {
|
||||
const input: GQL.ScrapedSceneInput = {
|
||||
date: fragment.date,
|
||||
production_date: fragment.production_date,
|
||||
code: fragment.code,
|
||||
details: fragment.details,
|
||||
director: fragment.director,
|
||||
|
|
@ -464,6 +467,10 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||
formik.setFieldValue("date", updatedScene.date);
|
||||
}
|
||||
|
||||
if (updatedScene.production_date) {
|
||||
formik.setFieldValue("production_date", updatedScene.production_date);
|
||||
}
|
||||
|
||||
if (updatedScene.urls) {
|
||||
formik.setFieldValue("urls", updatedScene.urls);
|
||||
}
|
||||
|
|
@ -825,6 +832,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
|
|||
)}
|
||||
|
||||
{renderDateField("date")}
|
||||
{renderDateField("production_date")}
|
||||
{renderInputField("director")}
|
||||
|
||||
{renderGalleriesField()}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ export const SceneScrapeDialog: React.FC<ISceneScrapeDialogProps> = ({
|
|||
const [date, setDate] = useState<ScrapeResult<string>>(
|
||||
new ScrapeResult<string>(scene.date, scraped.date)
|
||||
);
|
||||
const [production_date, setProductionDate] = useState<ScrapeResult<string>>(
|
||||
new ScrapeResult<string>(scene.production_date, scraped.production_date)
|
||||
);
|
||||
const [director, setDirector] = useState<ScrapeResult<string>>(
|
||||
new ScrapeResult<string>(scene.director, scraped.director)
|
||||
);
|
||||
|
|
@ -177,6 +180,7 @@ export const SceneScrapeDialog: React.FC<ISceneScrapeDialogProps> = ({
|
|||
code,
|
||||
urls,
|
||||
date,
|
||||
production_date,
|
||||
director,
|
||||
studio,
|
||||
performers,
|
||||
|
|
@ -203,6 +207,7 @@ export const SceneScrapeDialog: React.FC<ISceneScrapeDialogProps> = ({
|
|||
code: code.getNewValue(),
|
||||
urls: urls.getNewValue(),
|
||||
date: date.getNewValue(),
|
||||
production_date: production_date.getNewValue(),
|
||||
director: director.getNewValue(),
|
||||
studio: newStudioValue,
|
||||
performers: performers.getNewValue(),
|
||||
|
|
@ -242,6 +247,13 @@ export const SceneScrapeDialog: React.FC<ISceneScrapeDialogProps> = ({
|
|||
result={date}
|
||||
onChange={(value) => setDate(value)}
|
||||
/>
|
||||
<ScrapedInputGroupRow
|
||||
field="production_date"
|
||||
title={intl.formatMessage({ id: "production_date" })}
|
||||
placeholder="YYYY-MM-DD"
|
||||
result={production_date}
|
||||
onChange={(value) => setProductionDate(value)}
|
||||
/>
|
||||
<ScrapedInputGroupRow
|
||||
field="director"
|
||||
title={intl.formatMessage({ id: "director" })}
|
||||
|
|
|
|||
|
|
@ -381,6 +381,11 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
|||
title: resolveField("title", stashScene.title, scene.title),
|
||||
details: resolveField("details", stashScene.details, scene.details),
|
||||
date: resolveField("date", stashScene.date, scene.date),
|
||||
production_date: resolveField(
|
||||
"production_date",
|
||||
stashScene.production_date,
|
||||
scene.production_date
|
||||
),
|
||||
performer_ids: uniq(
|
||||
stashScene.performers.map((p) => p.id).concat(filteredPerformerIDs)
|
||||
),
|
||||
|
|
@ -514,6 +519,7 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
|||
cover_image: "cover_image",
|
||||
title: "title",
|
||||
date: "date",
|
||||
production_date: "production_date",
|
||||
url: "url",
|
||||
details: "details",
|
||||
studio: "studio",
|
||||
|
|
@ -630,6 +636,21 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
|||
}
|
||||
};
|
||||
|
||||
const maybeRenderProductionDateField = () => {
|
||||
if (isActive && scene.production_date) {
|
||||
return (
|
||||
<h5>
|
||||
<OptionalField
|
||||
exclude={excludedFields[fields.production_date]}
|
||||
setExclude={(v) => setExcludedField(fields.production_date, v)}
|
||||
>
|
||||
{scene.production_date}
|
||||
</OptionalField>
|
||||
</h5>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const maybeRenderDirector = () => {
|
||||
if (scene.director) {
|
||||
return (
|
||||
|
|
@ -833,6 +854,7 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
|||
|
||||
{maybeRenderStudioCode()}
|
||||
{maybeRenderDateField()}
|
||||
{maybeRenderProductionDateField()}
|
||||
{getDurationStatus(scene, stashSceneFile?.duration)}
|
||||
{getFingerprintStatus(scene, stashScene)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -924,6 +924,7 @@
|
|||
"value": "Value"
|
||||
},
|
||||
"date": "Date",
|
||||
"production_date": "Production Date",
|
||||
"date_format": "YYYY-MM-DD",
|
||||
"datetime_format": "YYYY-MM-DD HH:MM",
|
||||
"death_date": "Death Date",
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ export const SceneIsMissingCriterionOption = new IsMissingCriterionOption(
|
|||
"details",
|
||||
"url",
|
||||
"date",
|
||||
"production_date",
|
||||
"galleries",
|
||||
"studio",
|
||||
"group",
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ const defaultSortBy = "date";
|
|||
const sortByOptions = [
|
||||
"organized",
|
||||
"date",
|
||||
"production_date",
|
||||
"file_count",
|
||||
"filesize",
|
||||
"duration",
|
||||
|
|
@ -139,6 +140,7 @@ const criterionOptions = [
|
|||
createMandatoryNumberCriterionOption("interactive_speed"),
|
||||
createMandatoryNumberCriterionOption("file_count"),
|
||||
createDateCriterionOption("date"),
|
||||
createDateCriterionOption("production_date"),
|
||||
createMandatoryTimestampCriterionOption("created_at"),
|
||||
createMandatoryTimestampCriterionOption("updated_at"),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ export type CriterionType =
|
|||
| "stash_id_endpoint"
|
||||
| "stash_id_count"
|
||||
| "date"
|
||||
| "production_date"
|
||||
| "created_at"
|
||||
| "updated_at"
|
||||
| "birthdate"
|
||||
|
|
|
|||
Loading…
Reference in a new issue