mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
Details page redesign (#3946)
* mobile improvements to performer page * updated remaining details pages * fixes tag page on mobile * implemented show hide for performer details * fixes card width cutoff on mobile(not related to redesign) * added background image option plus more improvements * add tooltip for age field * translate encoding message string
This commit is contained in:
@@ -1,119 +1,100 @@
|
||||
import React from "react";
|
||||
import { Badge } from "react-bootstrap";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import * as GQL from "src/core/generated-graphql";
|
||||
import TextUtils from "src/utils/text";
|
||||
import { RatingSystem } from "src/components/Shared/Rating/RatingSystem";
|
||||
import { TextField, URLField } from "src/utils/field";
|
||||
import { DetailItem } from "src/components/Shared/DetailItem";
|
||||
|
||||
interface IStudioDetailsPanel {
|
||||
studio: GQL.StudioDataFragment;
|
||||
collapsed?: boolean;
|
||||
fullWidth?: boolean;
|
||||
}
|
||||
|
||||
export const StudioDetailsPanel: React.FC<IStudioDetailsPanel> = ({
|
||||
studio,
|
||||
collapsed,
|
||||
fullWidth,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
function renderRatingField() {
|
||||
if (!studio.rating100) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<dt>{intl.formatMessage({ id: "rating" })}</dt>
|
||||
<dd>
|
||||
<RatingSystem value={studio.rating100} disabled />
|
||||
</dd>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderTagsList() {
|
||||
if (!studio.aliases?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<dt>
|
||||
<FormattedMessage id="aliases" />
|
||||
</dt>
|
||||
<dd>
|
||||
{studio.aliases.map((a) => (
|
||||
<Badge className="tag-item" variant="secondary" key={a}>
|
||||
{a}
|
||||
</Badge>
|
||||
))}
|
||||
</dd>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderStashIDs() {
|
||||
if (!studio.stash_ids?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<dt>
|
||||
<FormattedMessage id="stash_ids" />
|
||||
</dt>
|
||||
<dd>
|
||||
<ul className="pl-0">
|
||||
{studio.stash_ids.map((stashID) => {
|
||||
const base = stashID.endpoint.match(/https?:\/\/.*?\//)?.[0];
|
||||
const link = base ? (
|
||||
<a
|
||||
href={`${base}studios/${stashID.stash_id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{stashID.stash_id}
|
||||
</a>
|
||||
) : (
|
||||
stashID.stash_id
|
||||
);
|
||||
return (
|
||||
<li key={stashID.stash_id} className="row no-gutters">
|
||||
{link}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</dd>
|
||||
</>
|
||||
<ul className="pl-0">
|
||||
{studio.stash_ids.map((stashID) => {
|
||||
const base = stashID.endpoint.match(/https?:\/\/.*?\//)?.[0];
|
||||
const link = base ? (
|
||||
<a
|
||||
href={`${base}studios/${stashID.stash_id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{stashID.stash_id}
|
||||
</a>
|
||||
) : (
|
||||
stashID.stash_id
|
||||
);
|
||||
return (
|
||||
<li key={stashID.stash_id} className="row no-gutters">
|
||||
{link}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
function maybeRenderExtraDetails() {
|
||||
if (!collapsed) {
|
||||
return (
|
||||
<DetailItem
|
||||
id="StashIDs"
|
||||
value={renderStashIDs()}
|
||||
fullWidth={fullWidth}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="studio-details">
|
||||
<div>
|
||||
<h2>{studio.name}</h2>
|
||||
</div>
|
||||
|
||||
<dl className="details-list">
|
||||
<URLField
|
||||
id="url"
|
||||
value={studio.url}
|
||||
url={TextUtils.sanitiseURL(studio.url ?? "")}
|
||||
/>
|
||||
|
||||
<TextField id="details" value={studio.details} />
|
||||
|
||||
<URLField
|
||||
id="parent_studios"
|
||||
value={studio.parent_studio?.name}
|
||||
url={`/studios/${studio.parent_studio?.id}`}
|
||||
trusted
|
||||
target="_self"
|
||||
/>
|
||||
|
||||
{renderRatingField()}
|
||||
{renderTagsList()}
|
||||
{renderStashIDs()}
|
||||
</dl>
|
||||
<div className="detail-group">
|
||||
<DetailItem id="details" value={studio.details} fullWidth={fullWidth} />
|
||||
<DetailItem
|
||||
id="parent_studios"
|
||||
value={
|
||||
studio.parent_studio?.name ? (
|
||||
<a href={`/studios/${studio.parent_studio?.id}`} target="_self">
|
||||
{studio.parent_studio.name}
|
||||
</a>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
}
|
||||
fullWidth={fullWidth}
|
||||
/>
|
||||
{maybeRenderExtraDetails()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const CompressedStudioDetailsPanel: React.FC<IStudioDetailsPanel> = ({
|
||||
studio,
|
||||
}) => {
|
||||
function scrollToTop() {
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="sticky detail-header">
|
||||
<div className="sticky detail-header-group">
|
||||
<a className="studio-name" onClick={() => scrollToTop()}>
|
||||
{studio.name}
|
||||
</a>
|
||||
{studio?.parent_studio?.name ? (
|
||||
<span className="studio-parent">{studio?.parent_studio?.name}</span>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user