Skip to content

Commit

Permalink
Performer custom fields (#5487)
Browse files Browse the repository at this point in the history
* Backend changes
* Show custom field values
* Add custom fields table input
* Add custom field filtering
* Add unit tests
* Include custom fields in import/export
* Anonymise performer custom fields
* Move json.Number handler functions to api
* Handle json.Number conversion in api
  • Loading branch information
WithoutPants authored Dec 3, 2024
1 parent a0e09bb commit 8c8be22
Show file tree
Hide file tree
Showing 56 changed files with 2,158 additions and 277 deletions.
8 changes: 8 additions & 0 deletions graphql/schema/types/filters.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ input StashIDCriterionInput {
modifier: CriterionModifier!
}

input CustomFieldCriterionInput {
field: String!
value: [Any!]
modifier: CriterionModifier!
}

input PerformerFilterType {
AND: PerformerFilterType
OR: PerformerFilterType
Expand Down Expand Up @@ -182,6 +188,8 @@ input PerformerFilterType {
created_at: TimestampCriterionInput
"Filter by last update time"
updated_at: TimestampCriterionInput

custom_fields: [CustomFieldCriterionInput!]
}

input SceneMarkerFilterType {
Expand Down
7 changes: 7 additions & 0 deletions graphql/schema/types/metadata.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -338,3 +338,10 @@ type SystemStatus {
input MigrateInput {
backupPath: String!
}

input CustomFieldsInput {
"If populated, the entire custom fields map will be replaced with this value"
full: Map
"If populated, only the keys in this map will be updated"
partial: Map
}
8 changes: 8 additions & 0 deletions graphql/schema/types/performer.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ type Performer {
updated_at: Time!
groups: [Group!]!
movies: [Movie!]! @deprecated(reason: "use groups instead")

custom_fields: Map!
}

input PerformerCreateInput {
Expand Down Expand Up @@ -93,6 +95,8 @@ input PerformerCreateInput {
hair_color: String
weight: Int
ignore_auto_tag: Boolean

custom_fields: Map
}

input PerformerUpdateInput {
Expand Down Expand Up @@ -129,6 +133,8 @@ input PerformerUpdateInput {
hair_color: String
weight: Int
ignore_auto_tag: Boolean

custom_fields: CustomFieldsInput
}

input BulkUpdateStrings {
Expand Down Expand Up @@ -167,6 +173,8 @@ input BulkPerformerUpdateInput {
hair_color: String
weight: Int
ignore_auto_tag: Boolean

custom_fields: CustomFieldsInput
}

input PerformerDestroyInput {
Expand Down
36 changes: 36 additions & 0 deletions internal/api/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package api

import (
"encoding/json"
"strings"
)

// JSONNumberToNumber converts a JSON number to either a float64 or int64.
func jsonNumberToNumber(n json.Number) interface{} {
if strings.Contains(string(n), ".") {
f, _ := n.Float64()
return f
}
ret, _ := n.Int64()
return ret
}

// ConvertMapJSONNumbers converts all JSON numbers in a map to either float64 or int64.
func convertMapJSONNumbers(m map[string]interface{}) (ret map[string]interface{}) {
if m == nil {
return nil
}

ret = make(map[string]interface{})
for k, v := range m {
if n, ok := v.(json.Number); ok {
ret[k] = jsonNumberToNumber(n)
} else if mm, ok := v.(map[string]interface{}); ok {
ret[k] = convertMapJSONNumbers(mm)
} else {
ret[k] = v
}
}

return ret
}
60 changes: 60 additions & 0 deletions internal/api/json_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package api

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/assert"
)

func TestConvertMapJSONNumbers(t *testing.T) {
tests := []struct {
name string
input map[string]interface{}
expected map[string]interface{}
}{
{
name: "Convert JSON numbers to numbers",
input: map[string]interface{}{
"int": json.Number("12"),
"float": json.Number("12.34"),
"string": "foo",
},
expected: map[string]interface{}{
"int": int64(12),
"float": 12.34,
"string": "foo",
},
},
{
name: "Convert JSON numbers to numbers in nested maps",
input: map[string]interface{}{
"foo": map[string]interface{}{
"int": json.Number("56"),
"float": json.Number("56.78"),
"nested-string": "bar",
},
"int": json.Number("12"),
"float": json.Number("12.34"),
"string": "foo",
},
expected: map[string]interface{}{
"foo": map[string]interface{}{
"int": int64(56),
"float": 56.78,
"nested-string": "bar",
},
"int": int64(12),
"float": 12.34,
"string": "foo",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := convertMapJSONNumbers(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}
221 changes: 221 additions & 0 deletions internal/api/loaders/customfieldsloader_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8c8be22

Please sign in to comment.