mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
More configuration options
* Allow configuration of generated file path and database path. Closes #33 * Added checkboxes to choose what gets generated for the generate task. Closes #32
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -6,13 +6,10 @@ import (
|
||||
"github.com/stashapp/stash/pkg/manager/config"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/utils"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input *models.ConfigGeneralInput) (models.ConfigGeneralResult, error) {
|
||||
if input == nil {
|
||||
return makeConfigGeneralResult(), fmt.Errorf("nil input")
|
||||
}
|
||||
|
||||
func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input models.ConfigGeneralInput) (models.ConfigGeneralResult, error) {
|
||||
if len(input.Stashes) > 0 {
|
||||
for _, stashPath := range input.Stashes {
|
||||
exists, err := utils.DirExists(stashPath)
|
||||
@@ -23,6 +20,21 @@ func (r *mutationResolver) ConfigureGeneral(ctx context.Context, input *models.C
|
||||
config.Set(config.Stash, input.Stashes)
|
||||
}
|
||||
|
||||
if input.DatabasePath != nil {
|
||||
ext := filepath.Ext(*input.DatabasePath)
|
||||
if ext != ".db" && ext != ".sqlite" && ext != ".sqlite3" {
|
||||
return makeConfigGeneralResult(), fmt.Errorf("invalid database path, use extension db, sqlite, or sqlite3")
|
||||
}
|
||||
config.Set(config.Database, input.DatabasePath)
|
||||
}
|
||||
|
||||
if input.GeneratedPath != nil {
|
||||
if err := utils.EnsureDir(*input.GeneratedPath); err != nil {
|
||||
return makeConfigGeneralResult(), err
|
||||
}
|
||||
config.Set(config.Generated, input.GeneratedPath)
|
||||
}
|
||||
|
||||
if err := config.Write(); err != nil {
|
||||
return makeConfigGeneralResult(), err
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ func makeConfigResult() models.ConfigResult {
|
||||
|
||||
func makeConfigGeneralResult() models.ConfigGeneralResult {
|
||||
return models.ConfigGeneralResult{
|
||||
Stashes: config.GetStashPaths(),
|
||||
Stashes: config.GetStashPaths(),
|
||||
DatabasePath: config.GetDatabasePath(),
|
||||
GeneratedPath: config.GetGeneratedPath(),
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"github.com/stashapp/stash/pkg/manager"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
)
|
||||
|
||||
func (r *queryResolver) MetadataScan(ctx context.Context) (string, error) {
|
||||
@@ -20,8 +21,8 @@ func (r *queryResolver) MetadataExport(ctx context.Context) (string, error) {
|
||||
return "todo", nil
|
||||
}
|
||||
|
||||
func (r *queryResolver) MetadataGenerate(ctx context.Context) (string, error) {
|
||||
manager.GetInstance().Generate(true, true, true, true)
|
||||
func (r *queryResolver) MetadataGenerate(ctx context.Context, input models.GenerateMetadataInput) (string, error) {
|
||||
manager.GetInstance().Generate(input.Sprites, input.Previews, input.Markers, input.Transcodes)
|
||||
return "todo", nil
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,9 @@ type DirectiveRoot struct {
|
||||
|
||||
type ComplexityRoot struct {
|
||||
ConfigGeneralResult struct {
|
||||
Stashes func(childComplexity int) int
|
||||
Stashes func(childComplexity int) int
|
||||
DatabasePath func(childComplexity int) int
|
||||
GeneratedPath func(childComplexity int) int
|
||||
}
|
||||
|
||||
ConfigResult struct {
|
||||
@@ -112,7 +114,7 @@ type ComplexityRoot struct {
|
||||
TagCreate func(childComplexity int, input TagCreateInput) int
|
||||
TagUpdate func(childComplexity int, input TagUpdateInput) int
|
||||
TagDestroy func(childComplexity int, input TagDestroyInput) int
|
||||
ConfigureGeneral func(childComplexity int, input *ConfigGeneralInput) int
|
||||
ConfigureGeneral func(childComplexity int, input ConfigGeneralInput) int
|
||||
}
|
||||
|
||||
Performer struct {
|
||||
@@ -163,7 +165,7 @@ type ComplexityRoot struct {
|
||||
MetadataImport func(childComplexity int) int
|
||||
MetadataExport func(childComplexity int) int
|
||||
MetadataScan func(childComplexity int) int
|
||||
MetadataGenerate func(childComplexity int) int
|
||||
MetadataGenerate func(childComplexity int, input GenerateMetadataInput) int
|
||||
MetadataClean func(childComplexity int) int
|
||||
AllPerformers func(childComplexity int) int
|
||||
AllStudios func(childComplexity int) int
|
||||
@@ -290,7 +292,7 @@ type MutationResolver interface {
|
||||
TagCreate(ctx context.Context, input TagCreateInput) (*Tag, error)
|
||||
TagUpdate(ctx context.Context, input TagUpdateInput) (*Tag, error)
|
||||
TagDestroy(ctx context.Context, input TagDestroyInput) (bool, error)
|
||||
ConfigureGeneral(ctx context.Context, input *ConfigGeneralInput) (ConfigGeneralResult, error)
|
||||
ConfigureGeneral(ctx context.Context, input ConfigGeneralInput) (ConfigGeneralResult, error)
|
||||
}
|
||||
type PerformerResolver interface {
|
||||
ID(ctx context.Context, obj *Performer) (string, error)
|
||||
@@ -339,7 +341,7 @@ type QueryResolver interface {
|
||||
MetadataImport(ctx context.Context) (string, error)
|
||||
MetadataExport(ctx context.Context) (string, error)
|
||||
MetadataScan(ctx context.Context) (string, error)
|
||||
MetadataGenerate(ctx context.Context) (string, error)
|
||||
MetadataGenerate(ctx context.Context, input GenerateMetadataInput) (string, error)
|
||||
MetadataClean(ctx context.Context) (string, error)
|
||||
AllPerformers(ctx context.Context) ([]Performer, error)
|
||||
AllStudios(ctx context.Context) ([]Studio, error)
|
||||
@@ -617,26 +619,19 @@ func (e *executableSchema) field_Mutation_tagDestroy_args(ctx context.Context, r
|
||||
|
||||
func (e *executableSchema) field_Mutation_configureGeneral_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
args := map[string]interface{}{}
|
||||
var arg0 *ConfigGeneralInput
|
||||
var arg0 ConfigGeneralInput
|
||||
if tmp, ok := rawArgs["input"]; ok {
|
||||
var err error
|
||||
var ptr1 ConfigGeneralInput
|
||||
if tmp != nil {
|
||||
ptr1, err = UnmarshalConfigGeneralInput(tmp)
|
||||
arg0 = &ptr1
|
||||
}
|
||||
|
||||
arg0, err = UnmarshalConfigGeneralInput(tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if arg0 != nil {
|
||||
var err error
|
||||
arg0, err = e.ConfigGeneralInputMiddleware(ctx, arg0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mConfigGeneralInput1, err := e.ConfigGeneralInputMiddleware(ctx, &arg0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arg0 = *mConfigGeneralInput1
|
||||
}
|
||||
args["input"] = arg0
|
||||
return args, nil
|
||||
@@ -1122,6 +1117,27 @@ func (e *executableSchema) field_Query_directories_args(ctx context.Context, raw
|
||||
|
||||
}
|
||||
|
||||
func (e *executableSchema) field_Query_metadataGenerate_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
args := map[string]interface{}{}
|
||||
var arg0 GenerateMetadataInput
|
||||
if tmp, ok := rawArgs["input"]; ok {
|
||||
var err error
|
||||
arg0, err = UnmarshalGenerateMetadataInput(tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mGenerateMetadataInput1, err := e.GenerateMetadataInputMiddleware(ctx, &arg0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arg0 = *mGenerateMetadataInput1
|
||||
}
|
||||
args["input"] = arg0
|
||||
return args, nil
|
||||
|
||||
}
|
||||
|
||||
func (e *executableSchema) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
args := map[string]interface{}{}
|
||||
var arg0 string
|
||||
@@ -1187,6 +1203,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.ConfigGeneralResult.Stashes(childComplexity), true
|
||||
|
||||
case "ConfigGeneralResult.databasePath":
|
||||
if e.complexity.ConfigGeneralResult.DatabasePath == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.ConfigGeneralResult.DatabasePath(childComplexity), true
|
||||
|
||||
case "ConfigGeneralResult.generatedPath":
|
||||
if e.complexity.ConfigGeneralResult.GeneratedPath == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.ConfigGeneralResult.GeneratedPath(childComplexity), true
|
||||
|
||||
case "ConfigResult.general":
|
||||
if e.complexity.ConfigResult.General == nil {
|
||||
break
|
||||
@@ -1483,7 +1513,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.ConfigureGeneral(childComplexity, args["input"].(*ConfigGeneralInput)), true
|
||||
return e.complexity.Mutation.ConfigureGeneral(childComplexity, args["input"].(ConfigGeneralInput)), true
|
||||
|
||||
case "Performer.id":
|
||||
if e.complexity.Performer.Id == nil {
|
||||
@@ -1888,7 +1918,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.Query.MetadataGenerate(childComplexity), true
|
||||
args, err := e.field_Query_metadataGenerate_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Query.MetadataGenerate(childComplexity, args["input"].(GenerateMetadataInput)), true
|
||||
|
||||
case "Query.metadataClean":
|
||||
if e.complexity.Query.MetadataClean == nil {
|
||||
@@ -2504,6 +2539,19 @@ func (ec *executionContext) _ConfigGeneralResult(ctx context.Context, sel ast.Se
|
||||
out.Values[i] = graphql.MarshalString("ConfigGeneralResult")
|
||||
case "stashes":
|
||||
out.Values[i] = ec._ConfigGeneralResult_stashes(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalid = true
|
||||
}
|
||||
case "databasePath":
|
||||
out.Values[i] = ec._ConfigGeneralResult_databasePath(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalid = true
|
||||
}
|
||||
case "generatedPath":
|
||||
out.Values[i] = ec._ConfigGeneralResult_generatedPath(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalid = true
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
@@ -2531,6 +2579,9 @@ func (ec *executionContext) _ConfigGeneralResult_stashes(ctx context.Context, fi
|
||||
return obj.Stashes, nil
|
||||
})
|
||||
if resTmp == nil {
|
||||
if !ec.HasError(rctx) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]string)
|
||||
@@ -2548,6 +2599,60 @@ func (ec *executionContext) _ConfigGeneralResult_stashes(ctx context.Context, fi
|
||||
return arr1
|
||||
}
|
||||
|
||||
// nolint: vetshadow
|
||||
func (ec *executionContext) _ConfigGeneralResult_databasePath(ctx context.Context, field graphql.CollectedField, obj *ConfigGeneralResult) graphql.Marshaler {
|
||||
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
|
||||
rctx := &graphql.ResolverContext{
|
||||
Object: "ConfigGeneralResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
}
|
||||
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
|
||||
resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.DatabasePath, nil
|
||||
})
|
||||
if resTmp == nil {
|
||||
if !ec.HasError(rctx) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
rctx.Result = res
|
||||
ctx = ec.Tracer.StartFieldChildExecution(ctx)
|
||||
return graphql.MarshalString(res)
|
||||
}
|
||||
|
||||
// nolint: vetshadow
|
||||
func (ec *executionContext) _ConfigGeneralResult_generatedPath(ctx context.Context, field graphql.CollectedField, obj *ConfigGeneralResult) graphql.Marshaler {
|
||||
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
|
||||
rctx := &graphql.ResolverContext{
|
||||
Object: "ConfigGeneralResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
}
|
||||
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
|
||||
resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.GeneratedPath, nil
|
||||
})
|
||||
if resTmp == nil {
|
||||
if !ec.HasError(rctx) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
rctx.Result = res
|
||||
ctx = ec.Tracer.StartFieldChildExecution(ctx)
|
||||
return graphql.MarshalString(res)
|
||||
}
|
||||
|
||||
var configResultImplementors = []string{"ConfigResult"}
|
||||
|
||||
// nolint: gocyclo, errcheck, gas, goconst
|
||||
@@ -4136,7 +4241,7 @@ func (ec *executionContext) _Mutation_configureGeneral(ctx context.Context, fiel
|
||||
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
|
||||
resTmp := ec.FieldMiddleware(ctx, nil, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Mutation().ConfigureGeneral(rctx, args["input"].(*ConfigGeneralInput))
|
||||
return ec.resolvers.Mutation().ConfigureGeneral(rctx, args["input"].(ConfigGeneralInput))
|
||||
})
|
||||
if resTmp == nil {
|
||||
if !ec.HasError(rctx) {
|
||||
@@ -6153,10 +6258,17 @@ func (ec *executionContext) _Query_metadataGenerate(ctx context.Context, field g
|
||||
Args: nil,
|
||||
}
|
||||
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Query_metadataGenerate_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
rctx.Args = args
|
||||
ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
|
||||
resTmp := ec.FieldMiddleware(ctx, nil, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Query().MetadataGenerate(rctx)
|
||||
return ec.resolvers.Query().MetadataGenerate(rctx, args["input"].(GenerateMetadataInput))
|
||||
})
|
||||
if resTmp == nil {
|
||||
if !ec.HasError(rctx) {
|
||||
@@ -10597,6 +10709,28 @@ func UnmarshalConfigGeneralInput(v interface{}) (ConfigGeneralInput, error) {
|
||||
for idx1 := range rawIf1 {
|
||||
it.Stashes[idx1], err = graphql.UnmarshalString(rawIf1[idx1])
|
||||
}
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "databasePath":
|
||||
var err error
|
||||
var ptr1 string
|
||||
if v != nil {
|
||||
ptr1, err = graphql.UnmarshalString(v)
|
||||
it.DatabasePath = &ptr1
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "generatedPath":
|
||||
var err error
|
||||
var ptr1 string
|
||||
if v != nil {
|
||||
ptr1, err = graphql.UnmarshalString(v)
|
||||
it.GeneratedPath = &ptr1
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
@@ -10683,6 +10817,47 @@ func (e *executableSchema) FindFilterTypeMiddleware(ctx context.Context, obj *Fi
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func UnmarshalGenerateMetadataInput(v interface{}) (GenerateMetadataInput, error) {
|
||||
var it GenerateMetadataInput
|
||||
var asMap = v.(map[string]interface{})
|
||||
|
||||
for k, v := range asMap {
|
||||
switch k {
|
||||
case "sprites":
|
||||
var err error
|
||||
it.Sprites, err = graphql.UnmarshalBoolean(v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "previews":
|
||||
var err error
|
||||
it.Previews, err = graphql.UnmarshalBoolean(v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "markers":
|
||||
var err error
|
||||
it.Markers, err = graphql.UnmarshalBoolean(v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "transcodes":
|
||||
var err error
|
||||
it.Transcodes, err = graphql.UnmarshalBoolean(v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (e *executableSchema) GenerateMetadataInputMiddleware(ctx context.Context, obj *GenerateMetadataInput) (*GenerateMetadataInput, error) {
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func UnmarshalPerformerCreateInput(v interface{}) (PerformerCreateInput, error) {
|
||||
var it PerformerCreateInput
|
||||
var asMap = v.(map[string]interface{})
|
||||
@@ -12148,11 +12323,19 @@ input SceneFilterType {
|
||||
input ConfigGeneralInput {
|
||||
"""Array of file paths to content"""
|
||||
stashes: [String!]
|
||||
"""Path to the SQLite database"""
|
||||
databasePath: String
|
||||
"""Path to generated files"""
|
||||
generatedPath: String
|
||||
}
|
||||
|
||||
type ConfigGeneralResult {
|
||||
"""Array of file paths to content"""
|
||||
stashes: [String!]
|
||||
stashes: [String!]!
|
||||
"""Path to the SQLite database"""
|
||||
databasePath: String!
|
||||
"""Path to generated files"""
|
||||
generatedPath: String!
|
||||
}
|
||||
|
||||
"""All configuration settings"""
|
||||
@@ -12160,6 +12343,17 @@ type ConfigResult {
|
||||
general: ConfigGeneralResult!
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Metadata
|
||||
#######################################
|
||||
|
||||
input GenerateMetadataInput {
|
||||
sprites: Boolean!
|
||||
previews: Boolean!
|
||||
markers: Boolean!
|
||||
transcodes: Boolean!
|
||||
}
|
||||
|
||||
#############
|
||||
# Root Schema
|
||||
#############
|
||||
@@ -12225,7 +12419,7 @@ type Query {
|
||||
"""Start a scan. Returns the job ID"""
|
||||
metadataScan: String!
|
||||
"""Start generating content. Returns the job ID"""
|
||||
metadataGenerate: String!
|
||||
metadataGenerate(input: GenerateMetadataInput!): String!
|
||||
"""Clean metadata. Returns the job ID"""
|
||||
metadataClean: String!
|
||||
|
||||
@@ -12254,7 +12448,7 @@ type Mutation {
|
||||
tagDestroy(input: TagDestroyInput!): Boolean!
|
||||
|
||||
"""Change general configuration options"""
|
||||
configureGeneral(input: ConfigGeneralInput): ConfigGeneralResult!
|
||||
configureGeneral(input: ConfigGeneralInput!): ConfigGeneralResult!
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
|
||||
@@ -11,11 +11,19 @@ import (
|
||||
type ConfigGeneralInput struct {
|
||||
// Array of file paths to content
|
||||
Stashes []string `json:"stashes"`
|
||||
// Path to the SQLite database
|
||||
DatabasePath *string `json:"databasePath"`
|
||||
// Path to generated files
|
||||
GeneratedPath *string `json:"generatedPath"`
|
||||
}
|
||||
|
||||
type ConfigGeneralResult struct {
|
||||
// Array of file paths to content
|
||||
Stashes []string `json:"stashes"`
|
||||
// Path to the SQLite database
|
||||
DatabasePath string `json:"databasePath"`
|
||||
// Path to generated files
|
||||
GeneratedPath string `json:"generatedPath"`
|
||||
}
|
||||
|
||||
// All configuration settings
|
||||
@@ -62,6 +70,13 @@ type GalleryFilesType struct {
|
||||
Path *string `json:"path"`
|
||||
}
|
||||
|
||||
type GenerateMetadataInput struct {
|
||||
Sprites bool `json:"sprites"`
|
||||
Previews bool `json:"previews"`
|
||||
Markers bool `json:"markers"`
|
||||
Transcodes bool `json:"transcodes"`
|
||||
}
|
||||
|
||||
type MarkerStringsResultType struct {
|
||||
Count int `json:"count"`
|
||||
ID string `json:"id"`
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
fragment ConfigGeneralData on ConfigGeneralResult {
|
||||
stashes
|
||||
databasePath
|
||||
generatedPath
|
||||
}
|
||||
|
||||
fragment ConfigData on ConfigResult {
|
||||
|
||||
@@ -10,8 +10,8 @@ query MetadataScan {
|
||||
metadataScan
|
||||
}
|
||||
|
||||
query MetadataGenerate {
|
||||
metadataGenerate
|
||||
query MetadataGenerate($input: GenerateMetadataInput!) {
|
||||
metadataGenerate(input: $input)
|
||||
}
|
||||
|
||||
query MetadataClean {
|
||||
|
||||
@@ -379,11 +379,19 @@ input SceneFilterType {
|
||||
input ConfigGeneralInput {
|
||||
"""Array of file paths to content"""
|
||||
stashes: [String!]
|
||||
"""Path to the SQLite database"""
|
||||
databasePath: String
|
||||
"""Path to generated files"""
|
||||
generatedPath: String
|
||||
}
|
||||
|
||||
type ConfigGeneralResult {
|
||||
"""Array of file paths to content"""
|
||||
stashes: [String!]
|
||||
stashes: [String!]!
|
||||
"""Path to the SQLite database"""
|
||||
databasePath: String!
|
||||
"""Path to generated files"""
|
||||
generatedPath: String!
|
||||
}
|
||||
|
||||
"""All configuration settings"""
|
||||
@@ -391,6 +399,17 @@ type ConfigResult {
|
||||
general: ConfigGeneralResult!
|
||||
}
|
||||
|
||||
#######################################
|
||||
# Metadata
|
||||
#######################################
|
||||
|
||||
input GenerateMetadataInput {
|
||||
sprites: Boolean!
|
||||
previews: Boolean!
|
||||
markers: Boolean!
|
||||
transcodes: Boolean!
|
||||
}
|
||||
|
||||
#############
|
||||
# Root Schema
|
||||
#############
|
||||
@@ -456,7 +475,7 @@ type Query {
|
||||
"""Start a scan. Returns the job ID"""
|
||||
metadataScan: String!
|
||||
"""Start generating content. Returns the job ID"""
|
||||
metadataGenerate: String!
|
||||
metadataGenerate(input: GenerateMetadataInput!): String!
|
||||
"""Clean metadata. Returns the job ID"""
|
||||
metadataClean: String!
|
||||
|
||||
@@ -485,7 +504,7 @@ type Mutation {
|
||||
tagDestroy(input: TagDestroyInput!): Boolean!
|
||||
|
||||
"""Change general configuration options"""
|
||||
configureGeneral(input: ConfigGeneralInput): ConfigGeneralResult!
|
||||
configureGeneral(input: ConfigGeneralInput!): ConfigGeneralResult!
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IBaseProps } from "../../models";
|
||||
import { SettingsAboutPanel } from "./SettingsAboutPanel";
|
||||
import { SettingsConfigurationPanel } from "./SettingsConfigurationPanel";
|
||||
import { SettingsLogsPanel } from "./SettingsLogsPanel";
|
||||
import { SettingsTasksPanel } from "./SettingsTasksPanel";
|
||||
import { SettingsTasksPanel } from "./SettingsTasksPanel/SettingsTasksPanel";
|
||||
|
||||
interface IProps extends IBaseProps {}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
H6,
|
||||
Spinner,
|
||||
Tag,
|
||||
InputGroup,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent, useEffect, useState } from "react";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
@@ -21,12 +22,15 @@ interface IProps {}
|
||||
export const SettingsConfigurationPanel: FunctionComponent<IProps> = (props: IProps) => {
|
||||
// Editing config state
|
||||
const [stashes, setStashes] = useState<string[]>([]);
|
||||
const [databasePath, setDatabasePath] = useState<string | undefined>(undefined);
|
||||
const [generatedPath, setGeneratedPath] = useState<string | undefined>(undefined);
|
||||
|
||||
// const [config, setConfig] = useState<Partial<GQL.ConfigDataFragment>>({});
|
||||
const { data, error, loading } = StashService.useConfiguration();
|
||||
|
||||
const updateGeneralConfig = StashService.useConfigureGeneral({
|
||||
stashes,
|
||||
databasePath,
|
||||
generatedPath,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -34,8 +38,9 @@ export const SettingsConfigurationPanel: FunctionComponent<IProps> = (props: IPr
|
||||
const conf = StashService.nullToUndefined(data.configuration) as GQL.ConfigDataFragment;
|
||||
if (!!conf.general) {
|
||||
setStashes(conf.general.stashes || []);
|
||||
setDatabasePath(conf.general.databasePath);
|
||||
setGeneratedPath(conf.general.generatedPath);
|
||||
}
|
||||
// setConfig(conf);
|
||||
}, [data]);
|
||||
|
||||
function onStashesChanged(directories: string[]) {
|
||||
@@ -54,7 +59,7 @@ export const SettingsConfigurationPanel: FunctionComponent<IProps> = (props: IPr
|
||||
|
||||
return (
|
||||
<>
|
||||
{!!error ? error : undefined}
|
||||
{!!error ? <h1>{error.message}</h1> : undefined}
|
||||
{(!data || !data.configuration || loading) ? <Spinner size={Spinner.SIZE_LARGE} /> : undefined}
|
||||
<H4>Library</H4>
|
||||
<FormGroup
|
||||
@@ -66,6 +71,18 @@ export const SettingsConfigurationPanel: FunctionComponent<IProps> = (props: IPr
|
||||
onDirectoriesChanged={onStashesChanged}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label="Database Path"
|
||||
helperText="File location for the SQLite database (requires restart)"
|
||||
>
|
||||
<InputGroup defaultValue={databasePath} onChange={(e: any) => setDatabasePath(e.target.value)} />
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label="Generated Path"
|
||||
helperText="Directory location for the generated files (scene markers, scene previews, sprites, etc)"
|
||||
>
|
||||
<InputGroup defaultValue={generatedPath} onChange={(e: any) => setGeneratedPath(e.target.value)} />
|
||||
</FormGroup>
|
||||
<Divider />
|
||||
<Button intent="primary" onClick={() => onSave()}>Save</Button>
|
||||
</>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
FormGroup,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import { StashService } from "../../../core/StashService";
|
||||
import { ErrorUtils } from "../../../utils/errors";
|
||||
import { ToastUtils } from "../../../utils/toasts";
|
||||
|
||||
interface IProps {}
|
||||
|
||||
export const GenerateButton: FunctionComponent<IProps> = () => {
|
||||
const [sprites, setSprites] = useState<boolean>(true);
|
||||
const [previews, setPreviews] = useState<boolean>(true);
|
||||
const [markers, setMarkers] = useState<boolean>(true);
|
||||
const [transcodes, setTranscodes] = useState<boolean>(true);
|
||||
|
||||
async function onGenerate() {
|
||||
try {
|
||||
await StashService.queryMetadataGenerate({sprites, previews, markers, transcodes});
|
||||
ToastUtils.success("Started generating");
|
||||
} catch (e) {
|
||||
ErrorUtils.handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
helperText="Generate supporting image, sprite, video, vtt and other files."
|
||||
labelFor="generate"
|
||||
inline={true}
|
||||
>
|
||||
<Checkbox checked={sprites} label="Sprites (for the scene scrubber)" onChange={() => setSprites(!sprites)} />
|
||||
<Checkbox
|
||||
checked={previews}
|
||||
label="Previews (video previews which play when hovering over a scene)"
|
||||
onChange={() => setPreviews(!previews)}
|
||||
/>
|
||||
<Checkbox
|
||||
checked={markers}
|
||||
label="Markers (20 second videos which begin at the given timecode)"
|
||||
onChange={() => setMarkers(!markers)}
|
||||
/>
|
||||
<Checkbox
|
||||
checked={transcodes}
|
||||
label="Transcodes (MP4 conversions of unsupported video formats)"
|
||||
onChange={() => setTranscodes(!transcodes)}
|
||||
/>
|
||||
<Button id="generate" text="Generate" onClick={() => onGenerate()} />
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
@@ -10,9 +10,12 @@ import {
|
||||
Tag,
|
||||
} from "@blueprintjs/core";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import * as GQL from "../../core/generated-graphql";
|
||||
import { StashService } from "../../core/StashService";
|
||||
import { TextUtils } from "../../utils/text";
|
||||
import * as GQL from "../../../core/generated-graphql";
|
||||
import { StashService } from "../../../core/StashService";
|
||||
import { TextUtils } from "../../../utils/text";
|
||||
import { GenerateButton } from "./GenerateButton";
|
||||
import { ToastUtils } from "../../../utils/toasts";
|
||||
import { ErrorUtils } from "../../../utils/errors";
|
||||
|
||||
interface IProps {}
|
||||
|
||||
@@ -43,6 +46,15 @@ export const SettingsTasksPanel: FunctionComponent<IProps> = (props: IProps) =>
|
||||
);
|
||||
}
|
||||
|
||||
async function onScan() {
|
||||
try {
|
||||
await StashService.queryMetadataScan();
|
||||
ToastUtils.success("Started scan");
|
||||
} catch (e) {
|
||||
ErrorUtils.handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{renderImportAlert()}
|
||||
@@ -53,18 +65,12 @@ export const SettingsTasksPanel: FunctionComponent<IProps> = (props: IProps) =>
|
||||
labelFor="scan"
|
||||
inline={true}
|
||||
>
|
||||
<Button id="scan" text="Scan" onClick={() => StashService.queryMetadataScan()} />
|
||||
<Button id="scan" text="Scan" onClick={() => onScan()} />
|
||||
</FormGroup>
|
||||
<Divider />
|
||||
|
||||
<H4>Generated Content</H4>
|
||||
<FormGroup
|
||||
helperText="Generate supporting image, sprite, video, vtt and other files."
|
||||
labelFor="generate"
|
||||
inline={true}
|
||||
>
|
||||
<Button id="generate" text="Generate" onClick={() => StashService.queryMetadataGenerate()} />
|
||||
</FormGroup>
|
||||
<GenerateButton />
|
||||
<FormGroup
|
||||
helperText="TODO"
|
||||
labelFor="clean"
|
||||
@@ -74,7 +74,7 @@ export const FolderSelect: FunctionComponent<IProps> = (props: IProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{!!error ? error : undefined}
|
||||
{!!error ? <h1>{error.message}</h1> : undefined}
|
||||
{renderDialog()}
|
||||
{selectedDirectories.map((path) => {
|
||||
return <div key={path}>{path} <a onClick={() => onRemoveDirectory(path)}>Remove</a></div>;
|
||||
|
||||
@@ -166,9 +166,10 @@ export class StashService {
|
||||
});
|
||||
}
|
||||
|
||||
public static queryMetadataGenerate() {
|
||||
public static queryMetadataGenerate(input: GQL.GenerateMetadataInput) {
|
||||
return StashService.client.query<GQL.MetadataGenerateQuery>({
|
||||
query: GQL.MetadataGenerateDocument,
|
||||
variables: { input },
|
||||
fetchPolicy: "network-only",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* tslint:disable */
|
||||
// Generated in 2019-03-23T12:23:40-07:00
|
||||
// Generated in 2019-03-24T09:16:39-07:00
|
||||
export type Maybe<T> = T | undefined;
|
||||
|
||||
export interface SceneFilterType {
|
||||
@@ -47,6 +47,16 @@ export interface PerformerFilterType {
|
||||
filter_favorites?: Maybe<boolean>;
|
||||
}
|
||||
|
||||
export interface GenerateMetadataInput {
|
||||
sprites: boolean;
|
||||
|
||||
previews: boolean;
|
||||
|
||||
markers: boolean;
|
||||
|
||||
transcodes: boolean;
|
||||
}
|
||||
|
||||
export interface SceneUpdateInput {
|
||||
clientMutationId?: Maybe<string>;
|
||||
|
||||
@@ -206,6 +216,10 @@ export interface TagDestroyInput {
|
||||
export interface ConfigGeneralInput {
|
||||
/** Array of file paths to content */
|
||||
stashes?: Maybe<string[]>;
|
||||
/** Path to the SQLite database */
|
||||
databasePath?: Maybe<string>;
|
||||
/** Path to generated files */
|
||||
generatedPath?: Maybe<string>;
|
||||
}
|
||||
|
||||
export enum ResolutionEnum {
|
||||
@@ -804,7 +818,9 @@ export type MetadataScanQuery = {
|
||||
metadataScan: string;
|
||||
};
|
||||
|
||||
export type MetadataGenerateVariables = {};
|
||||
export type MetadataGenerateVariables = {
|
||||
input: GenerateMetadataInput;
|
||||
};
|
||||
|
||||
export type MetadataGenerateQuery = {
|
||||
__typename?: "Query";
|
||||
@@ -863,7 +879,11 @@ export type MetadataUpdateSubscription = {
|
||||
export type ConfigGeneralDataFragment = {
|
||||
__typename?: "ConfigGeneralResult";
|
||||
|
||||
stashes: Maybe<string[]>;
|
||||
stashes: string[];
|
||||
|
||||
databasePath: string;
|
||||
|
||||
generatedPath: string;
|
||||
};
|
||||
|
||||
export type ConfigDataFragment = {
|
||||
@@ -1244,6 +1264,8 @@ import * as ReactApolloHooks from "react-apollo-hooks";
|
||||
export const ConfigGeneralDataFragmentDoc = gql`
|
||||
fragment ConfigGeneralData on ConfigGeneralResult {
|
||||
stashes
|
||||
databasePath
|
||||
generatedPath
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -2276,8 +2298,8 @@ export function useMetadataScan(
|
||||
);
|
||||
}
|
||||
export const MetadataGenerateDocument = gql`
|
||||
query MetadataGenerate {
|
||||
metadataGenerate
|
||||
query MetadataGenerate($input: GenerateMetadataInput!) {
|
||||
metadataGenerate(input: $input)
|
||||
}
|
||||
`;
|
||||
export function useMetadataGenerate(
|
||||
|
||||
Reference in New Issue
Block a user