mirror of
https://github.com/stashapp/stash.git
synced 2025-12-16 20:07:05 +03:00
Add support for favorite Studios (#4675)
* Backend changes * Add favorite icon to studio cards * Add favorite button to studio page * Add studio favorite filtering
This commit is contained in:
@@ -18,6 +18,7 @@ type Studio struct {
|
||||
CreatedAt json.JSONTime `json:"created_at,omitempty"`
|
||||
UpdatedAt json.JSONTime `json:"updated_at,omitempty"`
|
||||
Rating int `json:"rating,omitempty"`
|
||||
Favorite bool `json:"favorite,omitempty"`
|
||||
Details string `json:"details,omitempty"`
|
||||
Aliases []string `json:"aliases,omitempty"`
|
||||
StashIDs []models.StashID `json:"stash_ids,omitempty"`
|
||||
|
||||
@@ -14,6 +14,7 @@ type Studio struct {
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
// Rating expressed in 1-100 scale
|
||||
Rating *int `json:"rating"`
|
||||
Favorite bool `json:"favorite"`
|
||||
Details string `json:"details"`
|
||||
IgnoreAutoTag bool `json:"ignore_auto_tag"`
|
||||
|
||||
@@ -37,6 +38,7 @@ type StudioPartial struct {
|
||||
ParentID OptionalInt
|
||||
// Rating expressed in 1-100 scale
|
||||
Rating OptionalInt
|
||||
Favorite OptionalBool
|
||||
Details OptionalString
|
||||
CreatedAt OptionalTime
|
||||
UpdatedAt OptionalTime
|
||||
|
||||
@@ -16,6 +16,8 @@ type StudioFilterType struct {
|
||||
IsMissing *string `json:"is_missing"`
|
||||
// Filter by rating expressed as 1-100
|
||||
Rating100 *IntCriterionInput `json:"rating100"`
|
||||
// Filter by favorite
|
||||
Favorite *bool `json:"favorite"`
|
||||
// Filter by scene count
|
||||
SceneCount *IntCriterionInput `json:"scene_count"`
|
||||
// Filter by image count
|
||||
@@ -44,6 +46,7 @@ type StudioCreateInput struct {
|
||||
Image *string `json:"image"`
|
||||
StashIds []StashID `json:"stash_ids"`
|
||||
Rating100 *int `json:"rating100"`
|
||||
Favorite *bool `json:"favorite"`
|
||||
Details *string `json:"details"`
|
||||
Aliases []string `json:"aliases"`
|
||||
IgnoreAutoTag *bool `json:"ignore_auto_tag"`
|
||||
@@ -58,6 +61,7 @@ type StudioUpdateInput struct {
|
||||
Image *string `json:"image"`
|
||||
StashIds []StashID `json:"stash_ids"`
|
||||
Rating100 *int `json:"rating100"`
|
||||
Favorite *bool `json:"favorite"`
|
||||
Details *string `json:"details"`
|
||||
Aliases []string `json:"aliases"`
|
||||
IgnoreAutoTag *bool `json:"ignore_auto_tag"`
|
||||
|
||||
@@ -30,7 +30,7 @@ const (
|
||||
dbConnTimeout = 30
|
||||
)
|
||||
|
||||
var appSchemaVersion uint = 55
|
||||
var appSchemaVersion uint = 56
|
||||
|
||||
//go:embed migrations/*.sql
|
||||
var migrationsBox embed.FS
|
||||
|
||||
1
pkg/sqlite/migrations/56_studio_favorite.up.sql
Normal file
1
pkg/sqlite/migrations/56_studio_favorite.up.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE `studios` ADD COLUMN `favorite` boolean not null default '0';
|
||||
@@ -1610,6 +1610,11 @@ func createStudioFromModel(ctx context.Context, sqb *sqlite.StudioStore, studio
|
||||
return nil
|
||||
}
|
||||
|
||||
func getStudioBoolValue(index int) bool {
|
||||
index = index % 2
|
||||
return index == 1
|
||||
}
|
||||
|
||||
// createStudios creates n studios with plain Name and o studios with camel cased NaMe included
|
||||
func createStudios(ctx context.Context, n int, o int) error {
|
||||
sqb := db.Studio
|
||||
@@ -1630,6 +1635,7 @@ func createStudios(ctx context.Context, n int, o int) error {
|
||||
studio := models.Studio{
|
||||
Name: name,
|
||||
URL: getStudioStringValue(index, urlField),
|
||||
Favorite: getStudioBoolValue(index),
|
||||
IgnoreAutoTag: getIgnoreAutoTag(i),
|
||||
}
|
||||
// only add aliases for some scenes
|
||||
|
||||
@@ -36,6 +36,7 @@ type studioRow struct {
|
||||
UpdatedAt Timestamp `db:"updated_at"`
|
||||
// expressed as 1-100
|
||||
Rating null.Int `db:"rating"`
|
||||
Favorite bool `db:"favorite"`
|
||||
Details zero.String `db:"details"`
|
||||
IgnoreAutoTag bool `db:"ignore_auto_tag"`
|
||||
|
||||
@@ -51,6 +52,7 @@ func (r *studioRow) fromStudio(o models.Studio) {
|
||||
r.CreatedAt = Timestamp{Timestamp: o.CreatedAt}
|
||||
r.UpdatedAt = Timestamp{Timestamp: o.UpdatedAt}
|
||||
r.Rating = intFromPtr(o.Rating)
|
||||
r.Favorite = o.Favorite
|
||||
r.Details = zero.StringFrom(o.Details)
|
||||
r.IgnoreAutoTag = o.IgnoreAutoTag
|
||||
}
|
||||
@@ -64,6 +66,7 @@ func (r *studioRow) resolve() *models.Studio {
|
||||
CreatedAt: r.CreatedAt.Timestamp,
|
||||
UpdatedAt: r.UpdatedAt.Timestamp,
|
||||
Rating: nullIntPtr(r.Rating),
|
||||
Favorite: r.Favorite,
|
||||
Details: r.Details.String,
|
||||
IgnoreAutoTag: r.IgnoreAutoTag,
|
||||
}
|
||||
@@ -82,6 +85,7 @@ func (r *studioRowRecord) fromPartial(o models.StudioPartial) {
|
||||
r.setTimestamp("created_at", o.CreatedAt)
|
||||
r.setTimestamp("updated_at", o.UpdatedAt)
|
||||
r.setNullInt("rating", o.Rating)
|
||||
r.setBool("favorite", o.Favorite)
|
||||
r.setNullString("details", o.Details)
|
||||
r.setBool("ignore_auto_tag", o.IgnoreAutoTag)
|
||||
}
|
||||
@@ -496,6 +500,7 @@ func (qb *StudioStore) makeFilter(ctx context.Context, studioFilter *models.Stud
|
||||
query.handleCriterion(ctx, stringCriterionHandler(studioFilter.Details, studioTable+".details"))
|
||||
query.handleCriterion(ctx, stringCriterionHandler(studioFilter.URL, studioTable+".url"))
|
||||
query.handleCriterion(ctx, intCriterionHandler(studioFilter.Rating100, studioTable+".rating", nil))
|
||||
query.handleCriterion(ctx, boolCriterionHandler(studioFilter.Favorite, studioTable+".favorite", nil))
|
||||
query.handleCriterion(ctx, boolCriterionHandler(studioFilter.IgnoreAutoTag, studioTable+".ignore_auto_tag", nil))
|
||||
|
||||
query.handleCriterion(ctx, criterionHandlerFunc(func(ctx context.Context, f *filterBuilder) {
|
||||
|
||||
@@ -24,6 +24,7 @@ func ToJSON(ctx context.Context, reader FinderImageStashIDGetter, studio *models
|
||||
Name: studio.Name,
|
||||
URL: studio.URL,
|
||||
Details: studio.Details,
|
||||
Favorite: studio.Favorite,
|
||||
IgnoreAutoTag: studio.IgnoreAutoTag,
|
||||
CreatedAt: json.JSONTime{Time: studio.CreatedAt},
|
||||
UpdatedAt: json.JSONTime{Time: studio.UpdatedAt},
|
||||
|
||||
@@ -62,6 +62,7 @@ func createFullStudio(id int, parentID int) models.Studio {
|
||||
Name: studioName,
|
||||
URL: url,
|
||||
Details: details,
|
||||
Favorite: true,
|
||||
CreatedAt: createTime,
|
||||
UpdatedAt: updateTime,
|
||||
Rating: &rating,
|
||||
@@ -89,9 +90,10 @@ func createEmptyStudio(id int) models.Studio {
|
||||
|
||||
func createFullJSONStudio(parentStudio, image string, aliases []string) *jsonschema.Studio {
|
||||
return &jsonschema.Studio{
|
||||
Name: studioName,
|
||||
URL: url,
|
||||
Details: details,
|
||||
Name: studioName,
|
||||
URL: url,
|
||||
Details: details,
|
||||
Favorite: true,
|
||||
CreatedAt: json.JSONTime{
|
||||
Time: createTime,
|
||||
},
|
||||
|
||||
@@ -144,6 +144,7 @@ func studioJSONtoStudio(studioJSON jsonschema.Studio) models.Studio {
|
||||
URL: studioJSON.URL,
|
||||
Aliases: models.NewRelatedStrings(studioJSON.Aliases),
|
||||
Details: studioJSON.Details,
|
||||
Favorite: studioJSON.Favorite,
|
||||
IgnoreAutoTag: studioJSON.IgnoreAutoTag,
|
||||
CreatedAt: studioJSON.CreatedAt.GetTime(),
|
||||
UpdatedAt: studioJSON.UpdatedAt.GetTime(),
|
||||
|
||||
Reference in New Issue
Block a user