Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional performer urls #1959

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions graphql/documents/data/performer-slim.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ fragment SlimPerformerData on Performer {
stash_id
}
rating
urls
}
1 change: 1 addition & 0 deletions graphql/documents/data/performer.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ fragment PerformerData on Performer {
death_date
hair_color
weight
urls
}
3 changes: 3 additions & 0 deletions graphql/schema/types/performer.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Performer {
updated_at: Time!
movie_count: Int
movies: [Movie!]!
urls: [String!]!
}

input PerformerCreateInput {
Expand Down Expand Up @@ -73,6 +74,7 @@ input PerformerCreateInput {
death_date: String
hair_color: String
weight: Int
urls: [String!]
}

input PerformerUpdateInput {
Expand Down Expand Up @@ -103,6 +105,7 @@ input PerformerUpdateInput {
death_date: String
hair_color: String
weight: Int
urls: [String!]
}

input BulkPerformerUpdateInput {
Expand Down
11 changes: 11 additions & 0 deletions pkg/api/resolver_model_performer.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,14 @@ func (r *performerResolver) MovieCount(ctx context.Context, obj *models.Performe

return &res, nil
}

func (r *performerResolver) Urls(ctx context.Context, obj *models.Performer) (ret []string, err error) {
if err := r.withReadTxn(ctx, func(repo models.ReaderRepository) error {
ret, err = repo.Performer().GetUrls(obj.ID)
return err
}); err != nil {
return nil, err
}

return ret, err
}
7 changes: 7 additions & 0 deletions pkg/api/resolver_mutation_performer.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,13 @@ func (r *mutationResolver) PerformerUpdate(ctx context.Context, input models.Per
}
}

// Save the urls
if translator.hasField("urls") {
if err := qb.UpdateUrls(performerID, input.Urls); err != nil {
return err
}
}

return nil
}); err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion pkg/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
var DB *sqlx.DB
var WriteMu sync.Mutex
var dbPath string
var appSchemaVersion uint = 28
var appSchemaVersion uint = 29
var databaseSchemaVersion uint

//go:embed migrations/*.sql
Expand Down
7 changes: 7 additions & 0 deletions pkg/database/migrations/29_performers_urls.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE `performers_urls` (
`performer_id` integer NOT NULL,
`url` varchar(255) NOT NULL,
foreign key(`performer_id`) references `performers`(`id`) on delete CASCADE
);

CREATE INDEX `index_performers_urls_on_performer_id` on `performers_urls` (`performer_id`);
1 change: 1 addition & 0 deletions pkg/manager/jsonschema/performer.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Performer struct {
HairColor string `json:"hair_color,omitempty"`
Weight int `json:"weight,omitempty"`
StashIDs []models.StashID `json:"stash_ids,omitempty"`
Urls []string `json:"urls,omitempty"`
}

func LoadPerformerFile(filePath string) (*Performer, error) {
Expand Down
37 changes: 37 additions & 0 deletions pkg/models/mocks/PerformerReaderWriter.go

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

2 changes: 2 additions & 0 deletions pkg/models/performer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type PerformerReader interface {
GetImage(performerID int) ([]byte, error)
GetStashIDs(performerID int) ([]*StashID, error)
GetTagIDs(performerID int) ([]int, error)
GetUrls(performerID int) ([]string, error)
}

type PerformerWriter interface {
Expand All @@ -30,6 +31,7 @@ type PerformerWriter interface {
DestroyImage(performerID int) error
UpdateStashIDs(performerID int, stashIDs []StashID) error
UpdateTags(performerID int, tagIDs []int) error
UpdateUrls(performerID int, urls []string) error
}

type PerformerReaderWriter interface {
Expand Down
21 changes: 21 additions & 0 deletions pkg/sqlite/performer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const performerTable = "performers"
const performerIDColumn = "performer_id"
const performersTagsTable = "performers_tags"
const performersImageTable = "performers_image" // performer cover image
const performersUrlsTable = "performers_urls"
const performersUrlColumn = "url"

var countPerformersForTagQuery = `
SELECT tag_id AS id FROM performers_tags
Expand Down Expand Up @@ -607,3 +609,22 @@ func (qb *performerQueryBuilder) FindByStashIDStatus(hasStashID bool, stashboxEn
args := []interface{}{stashboxEndpoint}
return qb.queryPerformers(query, args)
}

func (qb *performerQueryBuilder) urlRepository() *stringRepository {
return &stringRepository{
repository: repository{
tx: qb.tx,
tableName: performersUrlsTable,
idColumn: performerIDColumn,
},
stringColumn: performersUrlColumn,
}
}

func (qb *performerQueryBuilder) GetUrls(performerID int) ([]string, error) {
return qb.urlRepository().get(performerID)
}

func (qb *performerQueryBuilder) UpdateUrls(performerID int, urls []string) error {
return qb.urlRepository().replace(performerID, urls)
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,31 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
);
}

function renderUrls() {
if (!performer.urls.length) {
return;
}

return (
<>
<dt>Additional URLs</dt>
<dd>
<ul className="pl-0">
{performer.urls.map((url) => {
return (
<li key={url} className="row no-gutters">
<a href={url} target="_blank" rel="noopener noreferrer">
{url}
</a>
</li>
);
})}
</ul>
</dd>
</>
);
}

const formatHeight = (height?: string | null) => {
if (!height) {
return "";
Expand Down Expand Up @@ -143,6 +168,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
/>
{renderTagsField()}
{renderStashIDs()}
{renderUrls()}
</dl>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ import { stashboxDisplayName } from "src/utils/stashbox";
import { PerformerScrapeDialog } from "./PerformerScrapeDialog";
import PerformerScrapeModal from "./PerformerScrapeModal";
import PerformerStashBoxModal, { IStashBox } from "./PerformerStashBoxModal";
import {
PerformerURLInput,
IPerformerURLInputInstance,
} from "./PerformerURLInput";

const isScraper = (
scraper: GQL.Scraper | GQL.StashBox
Expand Down Expand Up @@ -68,6 +72,14 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
const [newTags, setNewTags] = useState<GQL.ScrapedTag[]>();
const [isScraperModalOpen, setIsScraperModalOpen] = useState<boolean>(false);
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState<boolean>(false);
const [additionalURLs, setAdditionalURLs] = useState<
IPerformerURLInputInstance[]
>(
(performer!.urls ?? []).map((url, i) => ({
url,
index: i,
}))
);

// Network state
const [isLoading, setIsLoading] = useState(false);
Expand Down Expand Up @@ -118,6 +130,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
death_date: yup.string().optional(),
hair_color: yup.string().optional(),
weight: yup.number().optional(),
urls: yup.array(yup.string().required()).optional(),
});

const initialValues = {
Expand All @@ -144,6 +157,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
death_date: performer.death_date ?? "",
hair_color: performer.hair_color ?? "",
weight: performer.weight ?? undefined,
urls: performer.urls ?? [],
};

type InputValues = typeof initialValues;
Expand Down Expand Up @@ -512,8 +526,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
}
}

async function onScrapePerformerURL() {
const { url } = formik.values;
async function onScrapePerformerURL(url: string) {
if (!url) return;
setIsLoading(true);
try {
Expand Down Expand Up @@ -817,6 +830,14 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
);
}

const saveAdditionalURLs = (instances: IPerformerURLInputInstance[]) => {
setAdditionalURLs(instances);
formik.setFieldValue(
"urls",
instances.map((instance) => instance.url ?? "").filter((s) => s !== "")
);
};

function renderTextField(field: string, title: string, placeholder?: string) {
return (
<Form.Group controlId={field} as={Row}>
Expand Down Expand Up @@ -945,7 +966,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
<Col xs={fieldXS} xl={fieldXL}>
<URLField
{...formik.getFieldProps("url")}
onScrapeClick={onScrapePerformerURL}
onScrapeClick={onScrapePerformerURL.bind(this, formik.values.url)}
urlScrapable={urlScrapable}
/>
</Col>
Expand All @@ -970,6 +991,20 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({

{renderStashIDs()}

<Form.Group controlId="urls" as={Row}>
<Form.Label column xs={labelXS} xl={labelXL}>
<FormattedMessage id="urls" defaultMessage="Additional URLs" />
</Form.Label>
<Col xs={fieldXS} xl={fieldXL}>
<PerformerURLInput
urls={additionalURLs}
saveURLs={saveAdditionalURLs}
onScrapeClick={onScrapePerformerURL}
urlScrapable={urlScrapable}
/>
</Col>
</Form.Group>

{renderButtons()}
</Form>
</>
Expand Down
Loading