mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 16:34:02 +01:00
Merge branch 'master' into delete_scene
This commit is contained in:
commit
c3e4c5702a
21 changed files with 458 additions and 17 deletions
|
|
@ -82,4 +82,8 @@ mutation PerformerUpdate(
|
||||||
}) {
|
}) {
|
||||||
...PerformerData
|
...PerformerData
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutation PerformerDestroy($id: ID!) {
|
||||||
|
performerDestroy(input: { id: $id })
|
||||||
}
|
}
|
||||||
|
|
@ -17,4 +17,8 @@ mutation StudioUpdate(
|
||||||
studioUpdate(input: { id: $id, name: $name, url: $url, image: $image }) {
|
studioUpdate(input: { id: $id, name: $name, url: $url, image: $image }) {
|
||||||
...StudioData
|
...StudioData
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutation StudioDestroy($id: ID!) {
|
||||||
|
studioDestroy(input: { id: $id })
|
||||||
}
|
}
|
||||||
|
|
@ -80,9 +80,11 @@ type Mutation {
|
||||||
|
|
||||||
performerCreate(input: PerformerCreateInput!): Performer
|
performerCreate(input: PerformerCreateInput!): Performer
|
||||||
performerUpdate(input: PerformerUpdateInput!): Performer
|
performerUpdate(input: PerformerUpdateInput!): Performer
|
||||||
|
performerDestroy(input: PerformerDestroyInput!): Boolean!
|
||||||
|
|
||||||
studioCreate(input: StudioCreateInput!): Studio
|
studioCreate(input: StudioCreateInput!): Studio
|
||||||
studioUpdate(input: StudioUpdateInput!): Studio
|
studioUpdate(input: StudioUpdateInput!): Studio
|
||||||
|
studioDestroy(input: StudioDestroyInput!): Boolean!
|
||||||
|
|
||||||
tagCreate(input: TagCreateInput!): Tag
|
tagCreate(input: TagCreateInput!): Tag
|
||||||
tagUpdate(input: TagUpdateInput!): Tag
|
tagUpdate(input: TagUpdateInput!): Tag
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,10 @@ input PerformerUpdateInput {
|
||||||
image: String
|
image: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input PerformerDestroyInput {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
type FindPerformersResultType {
|
type FindPerformersResultType {
|
||||||
count: Int!
|
count: Int!
|
||||||
performers: [Performer!]!
|
performers: [Performer!]!
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@ input StudioUpdateInput {
|
||||||
image: String
|
image: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input StudioDestroyInput {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
type FindStudiosResultType {
|
type FindStudiosResultType {
|
||||||
count: Int!
|
count: Int!
|
||||||
studios: [Studio!]!
|
studios: [Studio!]!
|
||||||
|
|
|
||||||
|
|
@ -175,3 +175,17 @@ func (r *mutationResolver) PerformerUpdate(ctx context.Context, input models.Per
|
||||||
|
|
||||||
return performer, nil
|
return performer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) PerformerDestroy(ctx context.Context, input models.PerformerDestroyInput) (bool, error) {
|
||||||
|
qb := models.NewPerformerQueryBuilder()
|
||||||
|
tx := database.DB.MustBeginTx(ctx, nil)
|
||||||
|
if err := qb.Destroy(input.ID, tx); err != nil {
|
||||||
|
_ = tx.Rollback()
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@ package api
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stashapp/stash/pkg/database"
|
"github.com/stashapp/stash/pkg/database"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (r *mutationResolver) StudioCreate(ctx context.Context, input models.StudioCreateInput) (*models.Studio, error) {
|
func (r *mutationResolver) StudioCreate(ctx context.Context, input models.StudioCreateInput) (*models.Studio, error) {
|
||||||
|
|
@ -85,3 +86,16 @@ func (r *mutationResolver) StudioUpdate(ctx context.Context, input models.Studio
|
||||||
|
|
||||||
return studio, nil
|
return studio, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *mutationResolver) StudioDestroy(ctx context.Context, input models.StudioDestroyInput) (bool, error) {
|
||||||
|
qb := models.NewStudioQueryBuilder()
|
||||||
|
tx := database.DB.MustBeginTx(ctx, nil)
|
||||||
|
if err := qb.Destroy(input.ID, tx); err != nil {
|
||||||
|
_ = tx.Rollback()
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if err := tx.Commit(); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -28,6 +29,8 @@ type VideoFile struct {
|
||||||
VideoStream *FFProbeStream
|
VideoStream *FFProbeStream
|
||||||
|
|
||||||
Path string
|
Path string
|
||||||
|
Title string
|
||||||
|
Comment string
|
||||||
Container string
|
Container string
|
||||||
Duration float64
|
Duration float64
|
||||||
StartTime float64
|
StartTime float64
|
||||||
|
|
@ -82,6 +85,14 @@ func parse(filePath string, probeJSON *FFProbeJSON) (*VideoFile, error) {
|
||||||
//} // TODO nil_or_unsupported.(video_stream) && nil_or_unsupported.(audio_stream)
|
//} // TODO nil_or_unsupported.(video_stream) && nil_or_unsupported.(audio_stream)
|
||||||
|
|
||||||
result.Path = filePath
|
result.Path = filePath
|
||||||
|
result.Title = probeJSON.Format.Tags.Title
|
||||||
|
|
||||||
|
if result.Title == "" {
|
||||||
|
// default title to filename
|
||||||
|
result.Title = filepath.Base(result.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Comment = probeJSON.Format.Tags.Comment
|
||||||
|
|
||||||
result.Bitrate, _ = strconv.ParseInt(probeJSON.Format.BitRate, 10, 64)
|
result.Bitrate, _ = strconv.ParseInt(probeJSON.Format.BitRate, 10, 64)
|
||||||
result.Container = probeJSON.Format.FormatName
|
result.Container = probeJSON.Format.FormatName
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ type FFProbeJSON struct {
|
||||||
Encoder string `json:"encoder"`
|
Encoder string `json:"encoder"`
|
||||||
MajorBrand string `json:"major_brand"`
|
MajorBrand string `json:"major_brand"`
|
||||||
MinorVersion string `json:"minor_version"`
|
MinorVersion string `json:"minor_version"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Comment string `json:"comment"`
|
||||||
} `json:"tags"`
|
} `json:"tags"`
|
||||||
} `json:"format"`
|
} `json:"format"`
|
||||||
Streams []FFProbeStream `json:"streams"`
|
Streams []FFProbeStream `json:"streams"`
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
package manager
|
package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/bmatcuk/doublestar"
|
"github.com/bmatcuk/doublestar"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/manager/config"
|
"github.com/stashapp/stash/pkg/manager/config"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *singleton) Scan() {
|
func (s *singleton) Scan() {
|
||||||
|
|
@ -34,6 +35,8 @@ func (s *singleton) Scan() {
|
||||||
go task.Start(&wg)
|
go task.Start(&wg)
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.Info("Finished scan")
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,16 @@ package manager
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stashapp/stash/pkg/database"
|
"github.com/stashapp/stash/pkg/database"
|
||||||
"github.com/stashapp/stash/pkg/ffmpeg"
|
"github.com/stashapp/stash/pkg/ffmpeg"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/models"
|
"github.com/stashapp/stash/pkg/models"
|
||||||
"github.com/stashapp/stash/pkg/utils"
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ScanTask struct {
|
type ScanTask struct {
|
||||||
|
|
@ -46,9 +47,15 @@ func (t *ScanTask) scanGallery() {
|
||||||
tx := database.DB.MustBeginTx(ctx, nil)
|
tx := database.DB.MustBeginTx(ctx, nil)
|
||||||
gallery, _ = qb.FindByChecksum(checksum, tx)
|
gallery, _ = qb.FindByChecksum(checksum, tx)
|
||||||
if gallery != nil {
|
if gallery != nil {
|
||||||
logger.Infof("%s already exists. Updating path...", t.FilePath)
|
exists, _ := utils.FileExists(t.FilePath)
|
||||||
gallery.Path = t.FilePath
|
if exists {
|
||||||
_, err = qb.Update(*gallery, tx)
|
logger.Infof("%s already exists. Duplicate of %s ", t.FilePath, gallery.Path)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
logger.Infof("%s already exists. Updating path...", t.FilePath)
|
||||||
|
gallery.Path = t.FilePath
|
||||||
|
_, err = qb.Update(*gallery, tx)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Infof("%s doesn't exist. Creating new item...", t.FilePath)
|
logger.Infof("%s doesn't exist. Creating new item...", t.FilePath)
|
||||||
currentTime := time.Now()
|
currentTime := time.Now()
|
||||||
|
|
@ -95,15 +102,23 @@ func (t *ScanTask) scanScene() {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
tx := database.DB.MustBeginTx(ctx, nil)
|
tx := database.DB.MustBeginTx(ctx, nil)
|
||||||
if scene != nil {
|
if scene != nil {
|
||||||
logger.Infof("%s already exists. Updating path...", t.FilePath)
|
exists, _ := utils.FileExists(t.FilePath)
|
||||||
scene.Path = t.FilePath
|
if exists {
|
||||||
_, err = qb.Update(*scene, tx)
|
logger.Infof("%s already exists. Duplicate of %s ", t.FilePath, scene.Path)
|
||||||
|
} else {
|
||||||
|
logger.Infof("%s already exists. Updating path...", t.FilePath)
|
||||||
|
scene.Path = t.FilePath
|
||||||
|
_, err = qb.Update(*scene, tx)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.Infof("%s doesn't exist. Creating new item...", t.FilePath)
|
logger.Infof("%s doesn't exist. Creating new item...", t.FilePath)
|
||||||
currentTime := time.Now()
|
currentTime := time.Now()
|
||||||
newScene := models.Scene{
|
newScene := models.Scene{
|
||||||
Checksum: checksum,
|
Checksum: checksum,
|
||||||
Path: t.FilePath,
|
Path: t.FilePath,
|
||||||
|
Title: sql.NullString{String: videoFile.Title, Valid: true},
|
||||||
|
Details: sql.NullString{String: videoFile.Comment, Valid: true},
|
||||||
|
Date: models.SQLiteDate{String: videoFile.CreationTime.Format("2006-01-02")},
|
||||||
Duration: sql.NullFloat64{Float64: videoFile.Duration, Valid: true},
|
Duration: sql.NullFloat64{Float64: videoFile.Duration, Valid: true},
|
||||||
VideoCodec: sql.NullString{String: videoFile.VideoCodec, Valid: true},
|
VideoCodec: sql.NullString{String: videoFile.VideoCodec, Valid: true},
|
||||||
AudioCodec: sql.NullString{String: videoFile.AudioCodec, Valid: true},
|
AudioCodec: sql.NullString{String: videoFile.AudioCodec, Valid: true},
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ type ComplexityRoot struct {
|
||||||
Mutation struct {
|
Mutation struct {
|
||||||
ConfigureGeneral func(childComplexity int, input ConfigGeneralInput) int
|
ConfigureGeneral func(childComplexity int, input ConfigGeneralInput) int
|
||||||
PerformerCreate func(childComplexity int, input PerformerCreateInput) int
|
PerformerCreate func(childComplexity int, input PerformerCreateInput) int
|
||||||
|
PerformerDestroy func(childComplexity int, input PerformerDestroyInput) int
|
||||||
PerformerUpdate func(childComplexity int, input PerformerUpdateInput) int
|
PerformerUpdate func(childComplexity int, input PerformerUpdateInput) int
|
||||||
SceneDestroy func(childComplexity int, input SceneDestroyInput) int
|
SceneDestroy func(childComplexity int, input SceneDestroyInput) int
|
||||||
SceneMarkerCreate func(childComplexity int, input SceneMarkerCreateInput) int
|
SceneMarkerCreate func(childComplexity int, input SceneMarkerCreateInput) int
|
||||||
|
|
@ -115,6 +116,7 @@ type ComplexityRoot struct {
|
||||||
SceneMarkerUpdate func(childComplexity int, input SceneMarkerUpdateInput) int
|
SceneMarkerUpdate func(childComplexity int, input SceneMarkerUpdateInput) int
|
||||||
SceneUpdate func(childComplexity int, input SceneUpdateInput) int
|
SceneUpdate func(childComplexity int, input SceneUpdateInput) int
|
||||||
StudioCreate func(childComplexity int, input StudioCreateInput) int
|
StudioCreate func(childComplexity int, input StudioCreateInput) int
|
||||||
|
StudioDestroy func(childComplexity int, input StudioDestroyInput) int
|
||||||
StudioUpdate func(childComplexity int, input StudioUpdateInput) int
|
StudioUpdate func(childComplexity int, input StudioUpdateInput) int
|
||||||
TagCreate func(childComplexity int, input TagCreateInput) int
|
TagCreate func(childComplexity int, input TagCreateInput) int
|
||||||
TagDestroy func(childComplexity int, input TagDestroyInput) int
|
TagDestroy func(childComplexity int, input TagDestroyInput) int
|
||||||
|
|
@ -290,8 +292,10 @@ type MutationResolver interface {
|
||||||
SceneMarkerDestroy(ctx context.Context, id string) (bool, error)
|
SceneMarkerDestroy(ctx context.Context, id string) (bool, error)
|
||||||
PerformerCreate(ctx context.Context, input PerformerCreateInput) (*Performer, error)
|
PerformerCreate(ctx context.Context, input PerformerCreateInput) (*Performer, error)
|
||||||
PerformerUpdate(ctx context.Context, input PerformerUpdateInput) (*Performer, error)
|
PerformerUpdate(ctx context.Context, input PerformerUpdateInput) (*Performer, error)
|
||||||
|
PerformerDestroy(ctx context.Context, input PerformerDestroyInput) (bool, error)
|
||||||
StudioCreate(ctx context.Context, input StudioCreateInput) (*Studio, error)
|
StudioCreate(ctx context.Context, input StudioCreateInput) (*Studio, error)
|
||||||
StudioUpdate(ctx context.Context, input StudioUpdateInput) (*Studio, error)
|
StudioUpdate(ctx context.Context, input StudioUpdateInput) (*Studio, error)
|
||||||
|
StudioDestroy(ctx context.Context, input StudioDestroyInput) (bool, error)
|
||||||
TagCreate(ctx context.Context, input TagCreateInput) (*Tag, error)
|
TagCreate(ctx context.Context, input TagCreateInput) (*Tag, error)
|
||||||
TagUpdate(ctx context.Context, input TagUpdateInput) (*Tag, error)
|
TagUpdate(ctx context.Context, input TagUpdateInput) (*Tag, error)
|
||||||
TagDestroy(ctx context.Context, input TagDestroyInput) (bool, error)
|
TagDestroy(ctx context.Context, input TagDestroyInput) (bool, error)
|
||||||
|
|
@ -600,6 +604,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||||
|
|
||||||
return e.complexity.Mutation.PerformerCreate(childComplexity, args["input"].(PerformerCreateInput)), true
|
return e.complexity.Mutation.PerformerCreate(childComplexity, args["input"].(PerformerCreateInput)), true
|
||||||
|
|
||||||
|
case "Mutation.performerDestroy":
|
||||||
|
if e.complexity.Mutation.PerformerDestroy == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := ec.field_Mutation_performerDestroy_args(context.TODO(), rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Mutation.PerformerDestroy(childComplexity, args["input"].(PerformerDestroyInput)), true
|
||||||
|
|
||||||
case "Mutation.performerUpdate":
|
case "Mutation.performerUpdate":
|
||||||
if e.complexity.Mutation.PerformerUpdate == nil {
|
if e.complexity.Mutation.PerformerUpdate == nil {
|
||||||
break
|
break
|
||||||
|
|
@ -684,6 +700,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||||
|
|
||||||
return e.complexity.Mutation.StudioCreate(childComplexity, args["input"].(StudioCreateInput)), true
|
return e.complexity.Mutation.StudioCreate(childComplexity, args["input"].(StudioCreateInput)), true
|
||||||
|
|
||||||
|
case "Mutation.studioDestroy":
|
||||||
|
if e.complexity.Mutation.StudioDestroy == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
args, err := ec.field_Mutation_studioDestroy_args(context.TODO(), rawArgs)
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.complexity.Mutation.StudioDestroy(childComplexity, args["input"].(StudioDestroyInput)), true
|
||||||
|
|
||||||
case "Mutation.studioUpdate":
|
case "Mutation.studioUpdate":
|
||||||
if e.complexity.Mutation.StudioUpdate == nil {
|
if e.complexity.Mutation.StudioUpdate == nil {
|
||||||
break
|
break
|
||||||
|
|
@ -1855,9 +1883,11 @@ type Mutation {
|
||||||
|
|
||||||
performerCreate(input: PerformerCreateInput!): Performer
|
performerCreate(input: PerformerCreateInput!): Performer
|
||||||
performerUpdate(input: PerformerUpdateInput!): Performer
|
performerUpdate(input: PerformerUpdateInput!): Performer
|
||||||
|
performerDestroy(input: PerformerDestroyInput!): Boolean!
|
||||||
|
|
||||||
studioCreate(input: StudioCreateInput!): Studio
|
studioCreate(input: StudioCreateInput!): Studio
|
||||||
studioUpdate(input: StudioUpdateInput!): Studio
|
studioUpdate(input: StudioUpdateInput!): Studio
|
||||||
|
studioDestroy(input: StudioDestroyInput!): Boolean!
|
||||||
|
|
||||||
tagCreate(input: TagCreateInput!): Tag
|
tagCreate(input: TagCreateInput!): Tag
|
||||||
tagUpdate(input: TagUpdateInput!): Tag
|
tagUpdate(input: TagUpdateInput!): Tag
|
||||||
|
|
@ -2069,6 +2099,10 @@ input PerformerUpdateInput {
|
||||||
image: String
|
image: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input PerformerDestroyInput {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
type FindPerformersResultType {
|
type FindPerformersResultType {
|
||||||
count: Int!
|
count: Int!
|
||||||
performers: [Performer!]!
|
performers: [Performer!]!
|
||||||
|
|
@ -2233,6 +2267,10 @@ input StudioUpdateInput {
|
||||||
image: String
|
image: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input StudioDestroyInput {
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
type FindStudiosResultType {
|
type FindStudiosResultType {
|
||||||
count: Int!
|
count: Int!
|
||||||
studios: [Studio!]!
|
studios: [Studio!]!
|
||||||
|
|
@ -2291,6 +2329,20 @@ func (ec *executionContext) field_Mutation_performerCreate_args(ctx context.Cont
|
||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) field_Mutation_performerDestroy_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
|
var err error
|
||||||
|
args := map[string]interface{}{}
|
||||||
|
var arg0 PerformerDestroyInput
|
||||||
|
if tmp, ok := rawArgs["input"]; ok {
|
||||||
|
arg0, err = ec.unmarshalNPerformerDestroyInput2githubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐPerformerDestroyInput(ctx, tmp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args["input"] = arg0
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) field_Mutation_performerUpdate_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
func (ec *executionContext) field_Mutation_performerUpdate_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
var err error
|
var err error
|
||||||
args := map[string]interface{}{}
|
args := map[string]interface{}{}
|
||||||
|
|
@ -2389,6 +2441,20 @@ func (ec *executionContext) field_Mutation_studioCreate_args(ctx context.Context
|
||||||
return args, nil
|
return args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) field_Mutation_studioDestroy_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
|
var err error
|
||||||
|
args := map[string]interface{}{}
|
||||||
|
var arg0 StudioDestroyInput
|
||||||
|
if tmp, ok := rawArgs["input"]; ok {
|
||||||
|
arg0, err = ec.unmarshalNStudioDestroyInput2githubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐStudioDestroyInput(ctx, tmp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
args["input"] = arg0
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) field_Mutation_studioUpdate_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
func (ec *executionContext) field_Mutation_studioUpdate_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||||
var err error
|
var err error
|
||||||
args := map[string]interface{}{}
|
args := map[string]interface{}{}
|
||||||
|
|
@ -3694,6 +3760,40 @@ func (ec *executionContext) _Mutation_performerUpdate(ctx context.Context, field
|
||||||
return ec.marshalOPerformer2ᚖgithubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐPerformer(ctx, field.Selections, res)
|
return ec.marshalOPerformer2ᚖgithubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐPerformer(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Mutation_performerDestroy(ctx context.Context, field graphql.CollectedField) graphql.Marshaler {
|
||||||
|
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||||
|
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
|
||||||
|
rctx := &graphql.ResolverContext{
|
||||||
|
Object: "Mutation",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: true,
|
||||||
|
}
|
||||||
|
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||||
|
rawArgs := field.ArgumentMap(ec.Variables)
|
||||||
|
args, err := ec.field_Mutation_performerDestroy_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.Mutation().PerformerDestroy(rctx, args["input"].(PerformerDestroyInput))
|
||||||
|
})
|
||||||
|
if resTmp == nil {
|
||||||
|
if !ec.HasError(rctx) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(bool)
|
||||||
|
rctx.Result = res
|
||||||
|
ctx = ec.Tracer.StartFieldChildExecution(ctx)
|
||||||
|
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Mutation_studioCreate(ctx context.Context, field graphql.CollectedField) graphql.Marshaler {
|
func (ec *executionContext) _Mutation_studioCreate(ctx context.Context, field graphql.CollectedField) graphql.Marshaler {
|
||||||
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||||
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
|
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
|
||||||
|
|
@ -3756,6 +3856,40 @@ func (ec *executionContext) _Mutation_studioUpdate(ctx context.Context, field gr
|
||||||
return ec.marshalOStudio2ᚖgithubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐStudio(ctx, field.Selections, res)
|
return ec.marshalOStudio2ᚖgithubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐStudio(ctx, field.Selections, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) _Mutation_studioDestroy(ctx context.Context, field graphql.CollectedField) graphql.Marshaler {
|
||||||
|
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||||
|
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
|
||||||
|
rctx := &graphql.ResolverContext{
|
||||||
|
Object: "Mutation",
|
||||||
|
Field: field,
|
||||||
|
Args: nil,
|
||||||
|
IsMethod: true,
|
||||||
|
}
|
||||||
|
ctx = graphql.WithResolverContext(ctx, rctx)
|
||||||
|
rawArgs := field.ArgumentMap(ec.Variables)
|
||||||
|
args, err := ec.field_Mutation_studioDestroy_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.Mutation().StudioDestroy(rctx, args["input"].(StudioDestroyInput))
|
||||||
|
})
|
||||||
|
if resTmp == nil {
|
||||||
|
if !ec.HasError(rctx) {
|
||||||
|
ec.Errorf(ctx, "must not be null")
|
||||||
|
}
|
||||||
|
return graphql.Null
|
||||||
|
}
|
||||||
|
res := resTmp.(bool)
|
||||||
|
rctx.Result = res
|
||||||
|
ctx = ec.Tracer.StartFieldChildExecution(ctx)
|
||||||
|
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) _Mutation_tagCreate(ctx context.Context, field graphql.CollectedField) graphql.Marshaler {
|
func (ec *executionContext) _Mutation_tagCreate(ctx context.Context, field graphql.CollectedField) graphql.Marshaler {
|
||||||
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
ctx = ec.Tracer.StartFieldExecution(ctx, field)
|
||||||
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
|
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
|
||||||
|
|
@ -8200,6 +8334,24 @@ func (ec *executionContext) unmarshalInputPerformerCreateInput(ctx context.Conte
|
||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalInputPerformerDestroyInput(ctx context.Context, v interface{}) (PerformerDestroyInput, error) {
|
||||||
|
var it PerformerDestroyInput
|
||||||
|
var asMap = v.(map[string]interface{})
|
||||||
|
|
||||||
|
for k, v := range asMap {
|
||||||
|
switch k {
|
||||||
|
case "id":
|
||||||
|
var err error
|
||||||
|
it.ID, err = ec.unmarshalNID2string(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return it, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalInputPerformerFilterType(ctx context.Context, v interface{}) (PerformerFilterType, error) {
|
func (ec *executionContext) unmarshalInputPerformerFilterType(ctx context.Context, v interface{}) (PerformerFilterType, error) {
|
||||||
var it PerformerFilterType
|
var it PerformerFilterType
|
||||||
var asMap = v.(map[string]interface{})
|
var asMap = v.(map[string]interface{})
|
||||||
|
|
@ -8656,6 +8808,24 @@ func (ec *executionContext) unmarshalInputStudioCreateInput(ctx context.Context,
|
||||||
return it, nil
|
return it, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalInputStudioDestroyInput(ctx context.Context, v interface{}) (StudioDestroyInput, error) {
|
||||||
|
var it StudioDestroyInput
|
||||||
|
var asMap = v.(map[string]interface{})
|
||||||
|
|
||||||
|
for k, v := range asMap {
|
||||||
|
switch k {
|
||||||
|
case "id":
|
||||||
|
var err error
|
||||||
|
it.ID, err = ec.unmarshalNID2string(ctx, v)
|
||||||
|
if err != nil {
|
||||||
|
return it, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return it, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalInputStudioUpdateInput(ctx context.Context, v interface{}) (StudioUpdateInput, error) {
|
func (ec *executionContext) unmarshalInputStudioUpdateInput(ctx context.Context, v interface{}) (StudioUpdateInput, error) {
|
||||||
var it StudioUpdateInput
|
var it StudioUpdateInput
|
||||||
var asMap = v.(map[string]interface{})
|
var asMap = v.(map[string]interface{})
|
||||||
|
|
@ -9149,10 +9319,20 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
||||||
out.Values[i] = ec._Mutation_performerCreate(ctx, field)
|
out.Values[i] = ec._Mutation_performerCreate(ctx, field)
|
||||||
case "performerUpdate":
|
case "performerUpdate":
|
||||||
out.Values[i] = ec._Mutation_performerUpdate(ctx, field)
|
out.Values[i] = ec._Mutation_performerUpdate(ctx, field)
|
||||||
|
case "performerDestroy":
|
||||||
|
out.Values[i] = ec._Mutation_performerDestroy(ctx, field)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "studioCreate":
|
case "studioCreate":
|
||||||
out.Values[i] = ec._Mutation_studioCreate(ctx, field)
|
out.Values[i] = ec._Mutation_studioCreate(ctx, field)
|
||||||
case "studioUpdate":
|
case "studioUpdate":
|
||||||
out.Values[i] = ec._Mutation_studioUpdate(ctx, field)
|
out.Values[i] = ec._Mutation_studioUpdate(ctx, field)
|
||||||
|
case "studioDestroy":
|
||||||
|
out.Values[i] = ec._Mutation_studioDestroy(ctx, field)
|
||||||
|
if out.Values[i] == graphql.Null {
|
||||||
|
invalids++
|
||||||
|
}
|
||||||
case "tagCreate":
|
case "tagCreate":
|
||||||
out.Values[i] = ec._Mutation_tagCreate(ctx, field)
|
out.Values[i] = ec._Mutation_tagCreate(ctx, field)
|
||||||
case "tagUpdate":
|
case "tagUpdate":
|
||||||
|
|
@ -11114,6 +11294,10 @@ func (ec *executionContext) unmarshalNPerformerCreateInput2githubᚗcomᚋstasha
|
||||||
return ec.unmarshalInputPerformerCreateInput(ctx, v)
|
return ec.unmarshalInputPerformerCreateInput(ctx, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalNPerformerDestroyInput2githubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐPerformerDestroyInput(ctx context.Context, v interface{}) (PerformerDestroyInput, error) {
|
||||||
|
return ec.unmarshalInputPerformerDestroyInput(ctx, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalNPerformerUpdateInput2githubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐPerformerUpdateInput(ctx context.Context, v interface{}) (PerformerUpdateInput, error) {
|
func (ec *executionContext) unmarshalNPerformerUpdateInput2githubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐPerformerUpdateInput(ctx context.Context, v interface{}) (PerformerUpdateInput, error) {
|
||||||
return ec.unmarshalInputPerformerUpdateInput(ctx, v)
|
return ec.unmarshalInputPerformerUpdateInput(ctx, v)
|
||||||
}
|
}
|
||||||
|
|
@ -11427,6 +11611,10 @@ func (ec *executionContext) unmarshalNStudioCreateInput2githubᚗcomᚋstashapp
|
||||||
return ec.unmarshalInputStudioCreateInput(ctx, v)
|
return ec.unmarshalInputStudioCreateInput(ctx, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *executionContext) unmarshalNStudioDestroyInput2githubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐStudioDestroyInput(ctx context.Context, v interface{}) (StudioDestroyInput, error) {
|
||||||
|
return ec.unmarshalInputStudioDestroyInput(ctx, v)
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *executionContext) unmarshalNStudioUpdateInput2githubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐStudioUpdateInput(ctx context.Context, v interface{}) (StudioUpdateInput, error) {
|
func (ec *executionContext) unmarshalNStudioUpdateInput2githubᚗcomᚋstashappᚋstashᚋpkgᚋmodelsᚐStudioUpdateInput(ctx context.Context, v interface{}) (StudioUpdateInput, error) {
|
||||||
return ec.unmarshalInputStudioUpdateInput(ctx, v)
|
return ec.unmarshalInputStudioUpdateInput(ctx, v)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,10 @@ type PerformerCreateInput struct {
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PerformerDestroyInput struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
type PerformerFilterType struct {
|
type PerformerFilterType struct {
|
||||||
// Filter by favorite
|
// Filter by favorite
|
||||||
FilterFavorites *bool `json:"filter_favorites"`
|
FilterFavorites *bool `json:"filter_favorites"`
|
||||||
|
|
@ -260,6 +264,10 @@ type StudioCreateInput struct {
|
||||||
Image string `json:"image"`
|
Image string `json:"image"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StudioDestroyInput struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
type StudioUpdateInput struct {
|
type StudioUpdateInput struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/stashapp/stash/pkg/database"
|
"github.com/stashapp/stash/pkg/database"
|
||||||
)
|
)
|
||||||
|
|
@ -54,6 +55,15 @@ func (qb *PerformerQueryBuilder) Update(updatedPerformer Performer, tx *sqlx.Tx)
|
||||||
return &updatedPerformer, nil
|
return &updatedPerformer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qb *PerformerQueryBuilder) Destroy(id string, tx *sqlx.Tx) error {
|
||||||
|
_, err := tx.Exec("DELETE FROM performers_scenes WHERE performer_id = ?", id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeDeleteQuery("performers", id, tx)
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *PerformerQueryBuilder) Find(id int) (*Performer, error) {
|
func (qb *PerformerQueryBuilder) Find(id int) (*Performer, error) {
|
||||||
query := "SELECT * FROM performers WHERE id = ? LIMIT 1"
|
query := "SELECT * FROM performers WHERE id = ? LIMIT 1"
|
||||||
args := []interface{}{id}
|
args := []interface{}{id}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/stashapp/stash/pkg/database"
|
"github.com/stashapp/stash/pkg/database"
|
||||||
)
|
)
|
||||||
|
|
@ -50,6 +51,22 @@ func (qb *StudioQueryBuilder) Update(updatedStudio Studio, tx *sqlx.Tx) (*Studio
|
||||||
return &updatedStudio, nil
|
return &updatedStudio, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qb *StudioQueryBuilder) Destroy(id string, tx *sqlx.Tx) error {
|
||||||
|
// remove studio from scenes
|
||||||
|
_, err := tx.Exec("UPDATE scenes SET studio_id = null WHERE studio_id = ?", id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove studio from scraped items
|
||||||
|
_, err = tx.Exec("UPDATE scraped_items SET studio_id = null WHERE studio_id = ?", id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeDeleteQuery("studios", id, tx)
|
||||||
|
}
|
||||||
|
|
||||||
func (qb *StudioQueryBuilder) Find(id int, tx *sqlx.Tx) (*Studio, error) {
|
func (qb *StudioQueryBuilder) Find(id int, tx *sqlx.Tx) (*Studio, error) {
|
||||||
query := "SELECT * FROM studios WHERE id = ? LIMIT 1"
|
query := "SELECT * FROM studios WHERE id = ? LIMIT 1"
|
||||||
args := []interface{}{id}
|
args := []interface{}{id}
|
||||||
|
|
@ -86,7 +103,7 @@ func (qb *StudioQueryBuilder) Query(findFilter *FindFilterType) ([]*Studio, int)
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
body := selectDistinctIDs("studios")
|
body := selectDistinctIDs("studios")
|
||||||
body += `
|
body += `
|
||||||
join scenes on studios.id = scenes.studio_id
|
left join scenes on studios.id = scenes.studio_id
|
||||||
`
|
`
|
||||||
|
|
||||||
if q := findFilter.Q; q != nil && *q != "" {
|
if q := findFilter.Q; q != nil && *q != "" {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import {
|
import {
|
||||||
|
Alert,
|
||||||
Button,
|
Button,
|
||||||
FileInput,
|
FileInput,
|
||||||
Menu,
|
Menu,
|
||||||
|
|
@ -8,7 +9,7 @@ import {
|
||||||
Popover,
|
Popover,
|
||||||
} from "@blueprintjs/core";
|
} from "@blueprintjs/core";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React, { FunctionComponent } from "react";
|
import React, { FunctionComponent, useState } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import * as GQL from "../../core/generated-graphql";
|
import * as GQL from "../../core/generated-graphql";
|
||||||
import { NavigationUtils } from "../../utils/navigation";
|
import { NavigationUtils } from "../../utils/navigation";
|
||||||
|
|
@ -20,6 +21,7 @@ interface IProps {
|
||||||
isEditing: boolean;
|
isEditing: boolean;
|
||||||
onToggleEdit: () => void;
|
onToggleEdit: () => void;
|
||||||
onSave: () => void;
|
onSave: () => void;
|
||||||
|
onDelete: () => void;
|
||||||
onImageChange: (event: React.FormEvent<HTMLInputElement>) => void;
|
onImageChange: (event: React.FormEvent<HTMLInputElement>) => void;
|
||||||
|
|
||||||
// TODO: only for performers. make generic
|
// TODO: only for performers. make generic
|
||||||
|
|
@ -27,6 +29,8 @@ interface IProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DetailsEditNavbar: FunctionComponent<IProps> = (props: IProps) => {
|
export const DetailsEditNavbar: FunctionComponent<IProps> = (props: IProps) => {
|
||||||
|
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
function renderEditButton() {
|
function renderEditButton() {
|
||||||
if (props.isNew) { return; }
|
if (props.isNew) { return; }
|
||||||
return (
|
return (
|
||||||
|
|
@ -43,6 +47,11 @@ export const DetailsEditNavbar: FunctionComponent<IProps> = (props: IProps) => {
|
||||||
return <Button intent="success" text="Save" onClick={() => props.onSave()} />;
|
return <Button intent="success" text="Save" onClick={() => props.onSave()} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDeleteButton() {
|
||||||
|
if (props.isNew || props.isEditing) { return; }
|
||||||
|
return <Button intent="danger" text="Delete" onClick={() => setIsDeleteAlertOpen(true)} />;
|
||||||
|
}
|
||||||
|
|
||||||
function renderImageInput() {
|
function renderImageInput() {
|
||||||
if (!props.isEditing) { return; }
|
if (!props.isEditing) { return; }
|
||||||
return <FileInput text="Choose image..." onInputChange={props.onImageChange} inputProps={{accept: ".jpg,.jpeg"}} />;
|
return <FileInput text="Choose image..." onInputChange={props.onImageChange} inputProps={{accept: ".jpg,.jpeg"}} />;
|
||||||
|
|
@ -81,7 +90,37 @@ export const DetailsEditNavbar: FunctionComponent<IProps> = (props: IProps) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDeleteAlert() {
|
||||||
|
var name;
|
||||||
|
|
||||||
|
if (props.performer) {
|
||||||
|
name = props.performer.name;
|
||||||
|
}
|
||||||
|
if (props.studio) {
|
||||||
|
name = props.studio.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
cancelButtonText="Cancel"
|
||||||
|
confirmButtonText="Delete"
|
||||||
|
icon="trash"
|
||||||
|
intent="danger"
|
||||||
|
isOpen={isDeleteAlertOpen}
|
||||||
|
onCancel={() => setIsDeleteAlertOpen(false)}
|
||||||
|
onConfirm={() => props.onDelete()}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Are you sure you want to delete {name}?
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{renderDeleteAlert()}
|
||||||
<Navbar>
|
<Navbar>
|
||||||
<Navbar.Group>
|
<Navbar.Group>
|
||||||
{renderEditButton()}
|
{renderEditButton()}
|
||||||
|
|
@ -91,7 +130,9 @@ export const DetailsEditNavbar: FunctionComponent<IProps> = (props: IProps) => {
|
||||||
{renderSaveButton()}
|
{renderSaveButton()}
|
||||||
|
|
||||||
{renderScenesButton()}
|
{renderScenesButton()}
|
||||||
|
{renderDeleteButton()}
|
||||||
</Navbar.Group>
|
</Navbar.Group>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ export const Studio: FunctionComponent<IProps> = (props: IProps) => {
|
||||||
const { data, error, loading } = StashService.useFindStudio(props.match.params.id);
|
const { data, error, loading } = StashService.useFindStudio(props.match.params.id);
|
||||||
const updateStudio = StashService.useStudioUpdate(getStudioInput() as GQL.StudioUpdateInput);
|
const updateStudio = StashService.useStudioUpdate(getStudioInput() as GQL.StudioUpdateInput);
|
||||||
const createStudio = StashService.useStudioCreate(getStudioInput() as GQL.StudioCreateInput);
|
const createStudio = StashService.useStudioCreate(getStudioInput() as GQL.StudioCreateInput);
|
||||||
|
const deleteStudio = StashService.useStudioDestroy(getStudioInput() as GQL.StudioDestroyInput);
|
||||||
|
|
||||||
function updateStudioEditState(state: Partial<GQL.StudioDataFragment>) {
|
function updateStudioEditState(state: Partial<GQL.StudioDataFragment>) {
|
||||||
setName(state.name);
|
setName(state.name);
|
||||||
|
|
@ -95,6 +96,19 @@ export const Studio: FunctionComponent<IProps> = (props: IProps) => {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onDelete() {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const result = await deleteStudio();
|
||||||
|
} catch (e) {
|
||||||
|
ErrorUtils.handle(e);
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
|
||||||
|
// redirect to studios page
|
||||||
|
props.history.push(`/studios`);
|
||||||
|
}
|
||||||
|
|
||||||
function onImageChange(event: React.FormEvent<HTMLInputElement>) {
|
function onImageChange(event: React.FormEvent<HTMLInputElement>) {
|
||||||
const file: File = (event.target as any).files[0];
|
const file: File = (event.target as any).files[0];
|
||||||
const reader: FileReader = new FileReader();
|
const reader: FileReader = new FileReader();
|
||||||
|
|
@ -120,6 +134,7 @@ export const Studio: FunctionComponent<IProps> = (props: IProps) => {
|
||||||
isEditing={isEditing}
|
isEditing={isEditing}
|
||||||
onToggleEdit={() => { setIsEditing(!isEditing); updateStudioEditState(studio); }}
|
onToggleEdit={() => { setIsEditing(!isEditing); updateStudioEditState(studio); }}
|
||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
|
onDelete={onDelete}
|
||||||
onImageChange={onImageChange}
|
onImageChange={onImageChange}
|
||||||
/>
|
/>
|
||||||
<h1 className="bp3-heading">
|
<h1 className="bp3-heading">
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ export const Performer: FunctionComponent<IPerformerProps> = (props: IPerformerP
|
||||||
const { data, error, loading } = StashService.useFindPerformer(props.match.params.id);
|
const { data, error, loading } = StashService.useFindPerformer(props.match.params.id);
|
||||||
const updatePerformer = StashService.usePerformerUpdate(getPerformerInput() as GQL.PerformerUpdateInput);
|
const updatePerformer = StashService.usePerformerUpdate(getPerformerInput() as GQL.PerformerUpdateInput);
|
||||||
const createPerformer = StashService.usePerformerCreate(getPerformerInput() as GQL.PerformerCreateInput);
|
const createPerformer = StashService.usePerformerCreate(getPerformerInput() as GQL.PerformerCreateInput);
|
||||||
|
const deletePerformer = StashService.usePerformerDestroy(getPerformerInput() as GQL.PerformerDestroyInput);
|
||||||
|
|
||||||
function updatePerformerEditState(state: Partial<GQL.PerformerDataFragment | GQL.ScrapeFreeonesScrapeFreeones>) {
|
function updatePerformerEditState(state: Partial<GQL.PerformerDataFragment | GQL.ScrapeFreeonesScrapeFreeones>) {
|
||||||
if ((state as GQL.PerformerDataFragment).favorite !== undefined) {
|
if ((state as GQL.PerformerDataFragment).favorite !== undefined) {
|
||||||
|
|
@ -141,6 +142,19 @@ export const Performer: FunctionComponent<IPerformerProps> = (props: IPerformerP
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onDelete() {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const result = await deletePerformer();
|
||||||
|
} catch (e) {
|
||||||
|
ErrorUtils.handle(e);
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
|
||||||
|
// redirect to performers page
|
||||||
|
props.history.push(`/performers`);
|
||||||
|
}
|
||||||
|
|
||||||
function onImageChange(event: React.FormEvent<HTMLInputElement>) {
|
function onImageChange(event: React.FormEvent<HTMLInputElement>) {
|
||||||
const file: File = (event.target as any).files[0];
|
const file: File = (event.target as any).files[0];
|
||||||
const reader: FileReader = new FileReader();
|
const reader: FileReader = new FileReader();
|
||||||
|
|
@ -218,6 +232,7 @@ export const Performer: FunctionComponent<IPerformerProps> = (props: IPerformerP
|
||||||
isEditing={isEditing}
|
isEditing={isEditing}
|
||||||
onToggleEdit={() => { setIsEditing(!isEditing); updatePerformerEditState(performer); }}
|
onToggleEdit={() => { setIsEditing(!isEditing); updatePerformerEditState(performer); }}
|
||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
|
onDelete={onDelete}
|
||||||
onImageChange={onImageChange}
|
onImageChange={onImageChange}
|
||||||
onDisplayFreeOnesDialog={onDisplayFreeOnesDialog}
|
onDisplayFreeOnesDialog={onDisplayFreeOnesDialog}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,9 @@ export class StashService {
|
||||||
public static usePerformerUpdate(input: GQL.PerformerUpdateInput) {
|
public static usePerformerUpdate(input: GQL.PerformerUpdateInput) {
|
||||||
return GQL.usePerformerUpdate({ variables: input });
|
return GQL.usePerformerUpdate({ variables: input });
|
||||||
}
|
}
|
||||||
|
public static usePerformerDestroy(input: GQL.PerformerDestroyInput) {
|
||||||
|
return GQL.usePerformerDestroy({ variables: input });
|
||||||
|
}
|
||||||
|
|
||||||
public static useSceneUpdate(input: GQL.SceneUpdateInput) {
|
public static useSceneUpdate(input: GQL.SceneUpdateInput) {
|
||||||
return GQL.useSceneUpdate({ variables: input });
|
return GQL.useSceneUpdate({ variables: input });
|
||||||
|
|
@ -148,6 +151,9 @@ export class StashService {
|
||||||
public static useStudioUpdate(input: GQL.StudioUpdateInput) {
|
public static useStudioUpdate(input: GQL.StudioUpdateInput) {
|
||||||
return GQL.useStudioUpdate({ variables: input });
|
return GQL.useStudioUpdate({ variables: input });
|
||||||
}
|
}
|
||||||
|
public static useStudioDestroy(input: GQL.StudioDestroyInput) {
|
||||||
|
return GQL.useStudioDestroy({ variables: input });
|
||||||
|
}
|
||||||
|
|
||||||
public static useTagCreate(input: GQL.TagCreateInput) {
|
public static useTagCreate(input: GQL.TagCreateInput) {
|
||||||
return GQL.useTagCreate({ variables: input, refetchQueries: ["AllTags"] });
|
return GQL.useTagCreate({ variables: input, refetchQueries: ["AllTags"] });
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,10 @@ export interface PerformerUpdateInput {
|
||||||
image?: Maybe<string>;
|
image?: Maybe<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PerformerDestroyInput {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface StudioCreateInput {
|
export interface StudioCreateInput {
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
|
|
@ -214,6 +218,10 @@ export interface StudioUpdateInput {
|
||||||
image?: Maybe<string>;
|
image?: Maybe<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface StudioDestroyInput {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TagCreateInput {
|
export interface TagCreateInput {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
@ -334,6 +342,16 @@ export type PerformerUpdateMutation = {
|
||||||
|
|
||||||
export type PerformerUpdatePerformerUpdate = PerformerDataFragment;
|
export type PerformerUpdatePerformerUpdate = PerformerDataFragment;
|
||||||
|
|
||||||
|
export type PerformerDestroyVariables = {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PerformerDestroyMutation = {
|
||||||
|
__typename?: "Mutation";
|
||||||
|
|
||||||
|
performerDestroy: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type SceneMarkerCreateVariables = {
|
export type SceneMarkerCreateVariables = {
|
||||||
title: string;
|
title: string;
|
||||||
seconds: number;
|
seconds: number;
|
||||||
|
|
@ -439,6 +457,16 @@ export type StudioUpdateMutation = {
|
||||||
|
|
||||||
export type StudioUpdateStudioUpdate = StudioDataFragment;
|
export type StudioUpdateStudioUpdate = StudioDataFragment;
|
||||||
|
|
||||||
|
export type StudioDestroyVariables = {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type StudioDestroyMutation = {
|
||||||
|
__typename?: "Mutation";
|
||||||
|
|
||||||
|
studioDestroy: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type TagCreateVariables = {
|
export type TagCreateVariables = {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
@ -1664,6 +1692,22 @@ export function usePerformerUpdate(
|
||||||
PerformerUpdateVariables
|
PerformerUpdateVariables
|
||||||
>(PerformerUpdateDocument, baseOptions);
|
>(PerformerUpdateDocument, baseOptions);
|
||||||
}
|
}
|
||||||
|
export const PerformerDestroyDocument = gql`
|
||||||
|
mutation PerformerDestroy($id: ID!) {
|
||||||
|
performerDestroy(input: { id: $id })
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export function usePerformerDestroy(
|
||||||
|
baseOptions?: ReactApolloHooks.MutationHookOptions<
|
||||||
|
PerformerDestroyMutation,
|
||||||
|
PerformerDestroyVariables
|
||||||
|
>
|
||||||
|
) {
|
||||||
|
return ReactApolloHooks.useMutation<
|
||||||
|
PerformerDestroyMutation,
|
||||||
|
PerformerDestroyVariables
|
||||||
|
>(PerformerDestroyDocument, baseOptions);
|
||||||
|
}
|
||||||
export const SceneMarkerCreateDocument = gql`
|
export const SceneMarkerCreateDocument = gql`
|
||||||
mutation SceneMarkerCreate(
|
mutation SceneMarkerCreate(
|
||||||
$title: String!
|
$title: String!
|
||||||
|
|
@ -1860,6 +1904,22 @@ export function useStudioUpdate(
|
||||||
StudioUpdateVariables
|
StudioUpdateVariables
|
||||||
>(StudioUpdateDocument, baseOptions);
|
>(StudioUpdateDocument, baseOptions);
|
||||||
}
|
}
|
||||||
|
export const StudioDestroyDocument = gql`
|
||||||
|
mutation StudioDestroy($id: ID!) {
|
||||||
|
studioDestroy(input: { id: $id })
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export function useStudioDestroy(
|
||||||
|
baseOptions?: ReactApolloHooks.MutationHookOptions<
|
||||||
|
StudioDestroyMutation,
|
||||||
|
StudioDestroyVariables
|
||||||
|
>
|
||||||
|
) {
|
||||||
|
return ReactApolloHooks.useMutation<
|
||||||
|
StudioDestroyMutation,
|
||||||
|
StudioDestroyVariables
|
||||||
|
>(StudioDestroyDocument, baseOptions);
|
||||||
|
}
|
||||||
export const TagCreateDocument = gql`
|
export const TagCreateDocument = gql`
|
||||||
mutation TagCreate($name: String!) {
|
mutation TagCreate($name: String!) {
|
||||||
tagCreate(input: { name: $name }) {
|
tagCreate(input: { name: $name }) {
|
||||||
|
|
|
||||||
|
|
@ -186,10 +186,14 @@ span.block {
|
||||||
|
|
||||||
& .tag-list-row {
|
& .tag-list-row {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
& .bp3-button {
|
& .bp3-button {
|
||||||
margin: 0 10px;
|
margin: 0 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
& .tag-list-row:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue