mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Styles
This commit is contained in:
@@ -19,7 +19,7 @@ export class ErrorBoundary extends React.Component<any, any> {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2>Something went wrong.</h2>
|
<h2>Something went wrong.</h2>
|
||||||
<details style={{ whiteSpace: "pre-wrap" }}>
|
<details className="error-message">
|
||||||
{this.state.error && this.state.error.toString()}
|
{this.state.error && this.state.error.toString()}
|
||||||
<br />
|
<br />
|
||||||
{this.state.errorInfo.componentStack}
|
{this.state.errorInfo.componentStack}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const Gallery: React.FC = () => {
|
|||||||
if (error) return <div>{error.message}</div>;
|
if (error) return <div>{error.message}</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: "75vw", margin: "0 auto" }}>
|
<div className="col-9 m-auto">
|
||||||
<GalleryViewer gallery={gallery as any} />
|
<GalleryViewer gallery={gallery as any} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export const GalleryList: React.FC = () => {
|
|||||||
}
|
}
|
||||||
if (filter.displayMode === DisplayMode.List) {
|
if (filter.displayMode === DisplayMode.List) {
|
||||||
return (
|
return (
|
||||||
<Table style={{ margin: "0 auto" }}>
|
<Table className="m-auto">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Preview</th>
|
<th>Preview</th>
|
||||||
|
|||||||
@@ -156,11 +156,12 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
|
|
||||||
<Form.Group className="row" controlId="ignored-words">
|
<Form.Group className="row" controlId="ignored-words">
|
||||||
<Form.Label className="col-2">Ignored words</Form.Label>
|
<Form.Label className="col-2">Ignored words</Form.Label>
|
||||||
|
<InputGroup className="col-8">
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-8"
|
|
||||||
onChange={(newValue: any) => setIgnoreWords(newValue.target.value)}
|
onChange={(newValue: any) => setIgnoreWords(newValue.target.value)}
|
||||||
value={ignoreWords}
|
value={ignoreWords}
|
||||||
/>
|
/>
|
||||||
|
</InputGroup>
|
||||||
<Form.Text className="text-muted col-10 offset-2">
|
<Form.Text className="text-muted col-10 offset-2">
|
||||||
Matches with {"{i}"}
|
Matches with {"{i}"}
|
||||||
</Form.Text>
|
</Form.Text>
|
||||||
@@ -171,27 +172,29 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
<Form.Label htmlFor="whitespace-characters" className="col-2">
|
<Form.Label htmlFor="whitespace-characters" className="col-2">
|
||||||
Whitespace characters:
|
Whitespace characters:
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
|
<InputGroup className="col-8">
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-8"
|
|
||||||
onChange={(newValue: any) =>
|
onChange={(newValue: any) =>
|
||||||
setWhitespaceCharacters(newValue.target.value)
|
setWhitespaceCharacters(newValue.target.value)
|
||||||
}
|
}
|
||||||
value={whitespaceCharacters}
|
value={whitespaceCharacters}
|
||||||
/>
|
/>
|
||||||
|
</InputGroup>
|
||||||
<Form.Text className="text-muted col-10 offset-2">
|
<Form.Text className="text-muted col-10 offset-2">
|
||||||
These characters will be replaced with whitespace in the title
|
These characters will be replaced with whitespace in the title
|
||||||
</Form.Text>
|
</Form.Text>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
<Form.Group className="row">
|
<Form.Group>
|
||||||
<Form.Label htmlFor="capitalize-title" className="col-2">
|
<Form.Check
|
||||||
Capitalize title
|
inline
|
||||||
</Form.Label>
|
className="m-0"
|
||||||
<Form.Control
|
id="capitalize-title"
|
||||||
className="col-8"
|
|
||||||
type="checkbox"
|
|
||||||
checked={capitalizeTitle}
|
checked={capitalizeTitle}
|
||||||
onChange={() => setCapitalizeTitle(!capitalizeTitle)}
|
onChange={() => setCapitalizeTitle(!capitalizeTitle)}
|
||||||
/>
|
/>
|
||||||
|
<Form.Label htmlFor="capitalize-title">
|
||||||
|
Capitalize title
|
||||||
|
</Form.Label>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
{/* TODO - mapping stuff will go here */}
|
{/* TODO - mapping stuff will go here */}
|
||||||
@@ -222,12 +225,11 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group className="row">
|
<Form.Group className="row">
|
||||||
<Button variant="secondary" className="col-1" onClick={onFind}>
|
<Button variant="secondary" className="ml-3 col-1" onClick={onFind}>
|
||||||
Find
|
Find
|
||||||
</Button>
|
</Button>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
as="select"
|
as="select"
|
||||||
style={{ flexBasis: "min-content" }}
|
|
||||||
options={PAGE_SIZE_OPTIONS}
|
options={PAGE_SIZE_OPTIONS}
|
||||||
onChange={(event: any) =>
|
onChange={(event: any) =>
|
||||||
props.onPageSizeChanged(parseInt(event.target.value, 10))
|
props.onPageSizeChanged(parseInt(event.target.value, 10))
|
||||||
@@ -236,7 +238,7 @@ export const ParserInput: React.FC<IParserInputProps> = (
|
|||||||
className="col-1 filter-item"
|
className="col-1 filter-item"
|
||||||
>
|
>
|
||||||
{PAGE_SIZE_OPTIONS.map(val => (
|
{PAGE_SIZE_OPTIONS.map(val => (
|
||||||
<option value="val">{val}</option>
|
<option key={val} value={val}>{val}</option>
|
||||||
))}
|
))}
|
||||||
</Form.Control>
|
</Form.Control>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|||||||
@@ -414,8 +414,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<td>
|
<td>
|
||||||
<Form.Control
|
<Form.Check
|
||||||
type="checkbox"
|
|
||||||
checked={props.parserResult.set}
|
checked={props.parserResult.set}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
props.onSetChanged(!props.parserResult.set);
|
props.onSetChanged(!props.parserResult.set);
|
||||||
@@ -458,7 +457,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
disabled={!props.parserResult.set}
|
disabled={!props.parserResult.set}
|
||||||
className={props.className}
|
className={props.className}
|
||||||
value={props.parserResult.value || ""}
|
value={props.parserResult.value || ""}
|
||||||
onBlur={(event: any) => props.onChange(event.target.value)}
|
onChange={(event: any) => props.onChange(event.target.value)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -494,7 +493,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{elements.map((name: string) => (
|
{elements.map((name: string) => (
|
||||||
<Badge variant="secondary">{name}</Badge>
|
<Badge key={name} variant="secondary">{name}</Badge>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -592,7 +591,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className="scene-parser-row">
|
<tr className="scene-parser-row">
|
||||||
<td style={{ textAlign: "left" }}>{props.scene.filename}</td>
|
<td className="text-left">{props.scene.filename}</td>
|
||||||
<SceneParserField
|
<SceneParserField
|
||||||
key="title"
|
key="title"
|
||||||
fieldName="Title"
|
fieldName="Title"
|
||||||
@@ -689,9 +688,8 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<td>
|
<td className="w-15">
|
||||||
<Form.Control
|
<Form.Check
|
||||||
type="checkbox"
|
|
||||||
checked={allSet}
|
checked={allSet}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
onAllSet(!allSet);
|
onAllSet(!allSet);
|
||||||
@@ -715,7 +713,7 @@ export const SceneFilenameParser: React.FC = () => {
|
|||||||
<Table>
|
<Table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="scene-parser-row">
|
<tr className="scene-parser-row">
|
||||||
<th>Filename</th>
|
<th className="w-25">Filename</th>
|
||||||
{renderHeader("Title", allTitleSet, onSelectAllTitleSet)}
|
{renderHeader("Title", allTitleSet, onSelectAllTitleSet)}
|
||||||
{renderHeader("Date", allDateSet, onSelectAllDateSet)}
|
{renderHeader("Date", allDateSet, onSelectAllDateSet)}
|
||||||
{renderHeader(
|
{renderHeader(
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import { useToast } from "src/hooks";
|
|||||||
export const SettingsInterfacePanel: React.FC = () => {
|
export const SettingsInterfacePanel: React.FC = () => {
|
||||||
const Toast = useToast();
|
const Toast = useToast();
|
||||||
const config = StashService.useConfiguration();
|
const config = StashService.useConfiguration();
|
||||||
const [soundOnPreview, setSoundOnPreview] = useState<boolean>();
|
const [soundOnPreview, setSoundOnPreview] = useState<boolean>(true);
|
||||||
const [wallShowTitle, setWallShowTitle] = useState<boolean>();
|
const [wallShowTitle, setWallShowTitle] = useState<boolean>(true);
|
||||||
const [maximumLoopDuration, setMaximumLoopDuration] = useState<number>(0);
|
const [maximumLoopDuration, setMaximumLoopDuration] = useState<number>(0);
|
||||||
const [autostartVideo, setAutostartVideo] = useState<boolean>();
|
const [autostartVideo, setAutostartVideo] = useState<boolean>(false);
|
||||||
const [showStudioAsText, setShowStudioAsText] = useState<boolean>();
|
const [showStudioAsText, setShowStudioAsText] = useState<boolean>(false);
|
||||||
const [css, setCSS] = useState<string>();
|
const [css, setCSS] = useState<string>();
|
||||||
const [cssEnabled, setCSSEnabled] = useState<boolean>();
|
const [cssEnabled, setCSSEnabled] = useState<boolean>(false);
|
||||||
|
|
||||||
const [updateInterfaceConfig] = StashService.useConfigureInterface({
|
const [updateInterfaceConfig] = StashService.useConfigureInterface({
|
||||||
soundOnPreview,
|
soundOnPreview,
|
||||||
|
|||||||
@@ -340,6 +340,10 @@ const SelectComponent: React.FC<ISelectProps & ITypeProps> = ({
|
|||||||
container: (base: CSSProperties, state: any) => ({
|
container: (base: CSSProperties, state: any) => ({
|
||||||
...base,
|
...base,
|
||||||
zIndex: state.isFocused ? 10 : base.zIndex
|
zIndex: state.isFocused ? 10 : base.zIndex
|
||||||
|
}),
|
||||||
|
multiValueRemove: (base: CSSProperties, state: any) => ({
|
||||||
|
...base,
|
||||||
|
color: state.isFocused ? base.color: '#333333'
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ interface IProps {
|
|||||||
tag?: Partial<TagDataFragment>;
|
tag?: Partial<TagDataFragment>;
|
||||||
performer?: Partial<PerformerDataFragment>;
|
performer?: Partial<PerformerDataFragment>;
|
||||||
marker?: Partial<SceneMarkerDataFragment>;
|
marker?: Partial<SceneMarkerDataFragment>;
|
||||||
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TagLink: React.FC<IProps> = (props: IProps) => {
|
export const TagLink: React.FC<IProps> = (props: IProps) => {
|
||||||
@@ -30,7 +31,7 @@ export const TagLink: React.FC<IProps> = (props: IProps) => {
|
|||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Badge className="tag-item" variant="secondary">
|
<Badge className={`tag-item ${props.className}`} variant="secondary">
|
||||||
<Link to={link}>{title}</Link>
|
<Link to={link}>{title}</Link>
|
||||||
</Badge>
|
</Badge>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ interface IProps {
|
|||||||
export const StudioCard: React.FC<IProps> = ({ studio }) => {
|
export const StudioCard: React.FC<IProps> = ({ studio }) => {
|
||||||
return (
|
return (
|
||||||
<Card className="studio-card">
|
<Card className="studio-card">
|
||||||
<Link to={`/studios/${studio.id}`} className="studio-image">
|
<Link to={`/studios/${studio.id}`} className="studio-card-header">
|
||||||
<img alt={studio.name} src={studio.image_path ?? ""} />
|
<img className="studio-card-image" alt={studio.name} src={studio.image_path ?? ""} />
|
||||||
</Link>
|
</Link>
|
||||||
<div className="card-section">
|
<div className="card-section">
|
||||||
<h5 className="text-truncate">{studio.name}</h5>
|
<h5 className="text-truncate">{studio.name}</h5>
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ export const Studio: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{isNew && <h2>Add Studio</h2>}
|
{isNew && <h2>Add Studio</h2>}
|
||||||
<img className="logo" alt={name} src={imagePreview} />
|
<img className="logo" alt={name} src={imagePreview} />
|
||||||
<Table id="performer-details" style={{ width: "100%" }}>
|
<Table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{TableUtils.renderInputGroup({
|
{TableUtils.renderInputGroup({
|
||||||
title: "Name",
|
title: "Name",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const StudioList: React.FC = () => {
|
|||||||
|
|
||||||
if (filter.displayMode === DisplayMode.Grid) {
|
if (filter.displayMode === DisplayMode.Grid) {
|
||||||
return (
|
return (
|
||||||
<div className="grid">
|
<div className="row px-xl-5 justify-content-center">
|
||||||
{result.data.findStudios.studios.map(studio => (
|
{result.data.findStudios.studios.map(studio => (
|
||||||
<StudioCard key={studio.id} studio={studio} />
|
<StudioCard key={studio.id} studio={studio} />
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -98,11 +98,11 @@ export const TagList: React.FC = () => {
|
|||||||
|
|
||||||
const tagElements = data.allTags.map(tag => {
|
const tagElements = data.allTags.map(tag => {
|
||||||
return (
|
return (
|
||||||
<div key={tag.id} className="tag-list-row">
|
<div key={tag.id} className="tag-list-row row">
|
||||||
<Button variant="link" onClick={() => setEditingTag(tag)}>
|
<Button variant="link" onClick={() => setEditingTag(tag)}>
|
||||||
{tag.name}
|
{tag.name}
|
||||||
</Button>
|
</Button>
|
||||||
<div style={{ float: "right" }}>
|
<div className="ml-auto">
|
||||||
<Button variant="secondary" onClick={() => onAutoTag(tag)}>
|
<Button variant="secondary" onClick={() => onAutoTag(tag)}>
|
||||||
Auto Tag
|
Auto Tag
|
||||||
</Button>
|
</Button>
|
||||||
@@ -131,7 +131,7 @@ export const TagList: React.FC = () => {
|
|||||||
<div id="tag-list-container">
|
<div id="tag-list-container">
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
style={{ marginTop: "20px" }}
|
className="mt-2"
|
||||||
onClick={() => setEditingTag({})}
|
onClick={() => setEditingTag({})}
|
||||||
>
|
>
|
||||||
New Tag
|
New Tag
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
color: #444;
|
color: #444;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
line-height: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ export const WallItem: React.FC<IWallItemProps> = (props: IWallItemProps) => {
|
|||||||
/>
|
/>
|
||||||
{showTextContainer ? (
|
{showTextContainer ? (
|
||||||
<div className="scene-wall-item-text-container">
|
<div className="scene-wall-item-text-container">
|
||||||
<div style={{ lineHeight: 1 }}>{title}</div>
|
<div>{title}</div>
|
||||||
{tags}
|
{tags}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -257,7 +257,6 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
defaultValue={props.filter.searchTerm}
|
defaultValue={props.filter.searchTerm}
|
||||||
onChange={onChangeQuery}
|
onChange={onChangeQuery}
|
||||||
className="filter-item col-5 col-sm-2"
|
className="filter-item col-5 col-sm-2"
|
||||||
style={{ width: "inherit" }}
|
|
||||||
/>
|
/>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
as="select"
|
as="select"
|
||||||
@@ -316,13 +315,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
{renderMore()}
|
{renderMore()}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div className="d-flex justify-content-center">
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
margin: "10px auto"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{renderFilterTags()}
|
{renderFilterTags()}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -10,35 +10,36 @@ interface IPerformerCardProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PerformerCard: React.FC<IPerformerCardProps> = (
|
export const PerformerCard: React.FC<IPerformerCardProps> = (
|
||||||
props: IPerformerCardProps
|
{ performer, ageFromDate }
|
||||||
) => {
|
) => {
|
||||||
const age = TextUtils.age(props.performer.birthdate, props.ageFromDate);
|
const age = TextUtils.age(performer.birthdate, ageFromDate);
|
||||||
const ageString = `${age} years old${
|
const ageString = `${age} years old${
|
||||||
props.ageFromDate ? " in this scene." : "."
|
ageFromDate ? " in this scene." : "."
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
function maybeRenderFavoriteBanner() {
|
function maybeRenderFavoriteBanner() {
|
||||||
if (props.performer.favorite === false) {
|
if (performer.favorite === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return <div className="rating-banner rating-5">FAVORITE</div>;
|
return <div className="rating-banner rating-5">FAVORITE</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="performer-card">
|
<Card>
|
||||||
<Link
|
<Link
|
||||||
to={`/performers/${props.performer.id}`}
|
to={`/performers/${performer.id}`}
|
||||||
className="performer previewable image"
|
|
||||||
style={{ backgroundImage: `url(${props.performer.image_path})` }}
|
|
||||||
>
|
>
|
||||||
|
<img
|
||||||
|
className="image-thumbnail card-image"
|
||||||
|
alt={performer.name ?? ''} src={performer.image_path ?? ''} />
|
||||||
{maybeRenderFavoriteBanner()}
|
{maybeRenderFavoriteBanner()}
|
||||||
</Link>
|
</Link>
|
||||||
<div className="card-section">
|
<div className="card-section">
|
||||||
<h5 className="text-truncate">{props.performer.name}</h5>
|
<h5 className="text-truncate">{performer.name}</h5>
|
||||||
{age !== 0 ? <div className="text-muted">{ageString}</div> : ""}
|
{age !== 0 ? <div className="text-muted">{ageString}</div> : ""}
|
||||||
<div className="text-muted">
|
<div className="text-muted">
|
||||||
Stars in {props.performer.scene_count}{" "}
|
Stars in {performer.scene_count}{" "}
|
||||||
<Link to={NavUtils.makePerformerScenesUrl(props.performer)}>
|
<Link to={NavUtils.makePerformerScenesUrl(performer)}>
|
||||||
scenes
|
scenes
|
||||||
</Link>
|
</Link>
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
{queryableScrapers
|
{queryableScrapers
|
||||||
? queryableScrapers.map(s => (
|
? queryableScrapers.map(s => (
|
||||||
<Button
|
<Button
|
||||||
|
key={s.name}
|
||||||
variant="link"
|
variant="link"
|
||||||
onClick={() => onDisplayFreeOnesDialog(s)}
|
onClick={() => onDisplayFreeOnesDialog(s)}
|
||||||
>
|
>
|
||||||
@@ -294,7 +295,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
value={url}
|
value={url ?? ''}
|
||||||
readOnly={!isEditing}
|
readOnly={!isEditing}
|
||||||
plaintext={!isEditing}
|
plaintext={!isEditing}
|
||||||
placeholder="URL"
|
placeholder="URL"
|
||||||
@@ -310,7 +311,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
function maybeRenderButtons() {
|
function maybeRenderButtons() {
|
||||||
if (isEditing) {
|
if (isEditing) {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="row">
|
||||||
<Button
|
<Button
|
||||||
className="edit-button"
|
className="edit-button"
|
||||||
variant="primary"
|
variant="primary"
|
||||||
@@ -330,7 +331,11 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
{renderScraperMenu()}
|
{renderScraperMenu()}
|
||||||
</>
|
<ImageInput
|
||||||
|
isEditing={!!isEditing}
|
||||||
|
onImageChange={onImageChangeHandler}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,7 +382,7 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
{renderDeleteAlert()}
|
{renderDeleteAlert()}
|
||||||
{renderScraperDialog()}
|
{renderScraperDialog()}
|
||||||
|
|
||||||
<Table id="performer-details" style={{ width: "100%" }}>
|
<Table id="performer-details" className="w-100">
|
||||||
<tbody>
|
<tbody>
|
||||||
{maybeRenderName()}
|
{maybeRenderName()}
|
||||||
{maybeRenderAliases()}
|
{maybeRenderAliases()}
|
||||||
@@ -449,10 +454,6 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
|
|||||||
isEditing: !!isEditing,
|
isEditing: !!isEditing,
|
||||||
onChange: setInstagram
|
onChange: setInstagram
|
||||||
})}
|
})}
|
||||||
<ImageInput
|
|
||||||
isEditing={!!isEditing}
|
|
||||||
onImageChange={onImageChangeHandler}
|
|
||||||
/>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
|
|||||||
@@ -14,48 +14,29 @@ interface IPerformerListTableProps {
|
|||||||
export const PerformerListTable: React.FC<IPerformerListTableProps> = (
|
export const PerformerListTable: React.FC<IPerformerListTableProps> = (
|
||||||
props: IPerformerListTableProps
|
props: IPerformerListTableProps
|
||||||
) => {
|
) => {
|
||||||
function maybeRenderFavoriteHeart(performer: GQL.PerformerDataFragment) {
|
const renderPerformerRow = (performer: GQL.PerformerDataFragment) => (
|
||||||
if (!performer.favorite) {
|
<tr key={performer.id}>
|
||||||
return;
|
<td>
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Button disabled className="favorite">
|
|
||||||
<Icon icon="heart" />
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderPerformerImage(performer: GQL.PerformerDataFragment) {
|
|
||||||
const style: React.CSSProperties = {
|
|
||||||
backgroundImage: `url('${performer.image_path}')`,
|
|
||||||
lineHeight: 5,
|
|
||||||
backgroundSize: "contain",
|
|
||||||
display: "inline-block",
|
|
||||||
backgroundPosition: "center",
|
|
||||||
backgroundRepeat: "no-repeat"
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link
|
<Link
|
||||||
className="performer-list-thumbnail"
|
|
||||||
to={`/performers/${performer.id}`}
|
to={`/performers/${performer.id}`}
|
||||||
style={style}
|
>
|
||||||
/>
|
<img className="image-thumbnail" alt={performer.name ?? ""} src={performer.image_path ?? ''} />
|
||||||
);
|
</Link>
|
||||||
}
|
</td>
|
||||||
|
<td className="text-left">
|
||||||
function renderPerformerRow(performer: GQL.PerformerDataFragment) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<tr>
|
|
||||||
<td>{renderPerformerImage(performer)}</td>
|
|
||||||
<td style={{ textAlign: "left" }}>
|
|
||||||
<Link to={`/performers/${performer.id}`}>
|
<Link to={`/performers/${performer.id}`}>
|
||||||
<h5 className="text-truncate">{performer.name}</h5>
|
<h5 className="text-truncate">{performer.name}</h5>
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
<td>{performer.aliases ? performer.aliases : ""}</td>
|
<td>{performer.aliases ? performer.aliases : ""}</td>
|
||||||
<td>{maybeRenderFavoriteHeart(performer)}</td>
|
<td>{
|
||||||
|
performer.favorite && (
|
||||||
|
<Button disabled className="favorite">
|
||||||
|
<Icon icon="heart" />
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Link to={NavUtils.makePerformerScenesUrl(performer)}>
|
<Link to={NavUtils.makePerformerScenesUrl(performer)}>
|
||||||
<h6>{performer.scene_count}</h6>
|
<h6>{performer.scene_count}</h6>
|
||||||
@@ -64,12 +45,9 @@ export const PerformerListTable: React.FC<IPerformerListTableProps> = (
|
|||||||
<td>{performer.birthdate}</td>
|
<td>{performer.birthdate}</td>
|
||||||
<td>{performer.height}</td>
|
<td>{performer.height}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<div className="grid">
|
<div className="grid">
|
||||||
<Table bordered striped>
|
<Table bordered striped>
|
||||||
<thead>
|
<thead>
|
||||||
@@ -86,6 +64,5 @@ export const PerformerListTable: React.FC<IPerformerListTableProps> = (
|
|||||||
<tbody>{props.performers.map(renderPerformerRow)}</tbody>
|
<tbody>{props.performers.map(renderPerformerRow)}</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,3 @@
|
|||||||
.performer.image {
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
height: 50vh;
|
|
||||||
min-height: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#performer-details {
|
#performer-details {
|
||||||
td {
|
td {
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
|
|||||||
@@ -63,20 +63,13 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
function maybeRenderSceneStudioOverlay() {
|
function maybeRenderSceneStudioOverlay() {
|
||||||
if (!props.scene.studio) return;
|
if (!props.scene.studio) return;
|
||||||
|
|
||||||
let style: React.CSSProperties = {
|
|
||||||
backgroundImage: `url('${props.scene.studio.image_path}')`
|
|
||||||
};
|
|
||||||
|
|
||||||
let text = "";
|
|
||||||
if (showStudioAsText) {
|
|
||||||
style = {};
|
|
||||||
text = props.scene.studio.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="scene-studio-overlay">
|
<div className="scene-studio-overlay">
|
||||||
<Link to={`/studios/${props.scene.studio.id}`} style={style}>
|
<Link to={`/studios/${props.scene.studio.id}`}>
|
||||||
{text}
|
{ showStudioAsText
|
||||||
|
? props.scene.studio.name
|
||||||
|
: <img className="image-thumbnail" alt={props.scene.studio.name} src={props.scene.studio.image_path ?? ''} />
|
||||||
|
}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -103,13 +96,14 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
if (props.scene.performers.length <= 0) return;
|
if (props.scene.performers.length <= 0) return;
|
||||||
|
|
||||||
const popoverContent = props.scene.performers.map(performer => (
|
const popoverContent = props.scene.performers.map(performer => (
|
||||||
<div className="performer-tag-container" key="performer">
|
<div className="performer-tag-container row" key="performer">
|
||||||
<Link
|
<Link
|
||||||
to={`/performers/${performer.id}`}
|
to={`/performers/${performer.id}`}
|
||||||
className="performer-tag previewable image"
|
className="performer-tag col m-auto zoom-2"
|
||||||
style={{ backgroundImage: `url(${performer.image_path})` }}
|
>
|
||||||
/>
|
<img className="image-thumbnail" alt={performer.name ?? ''} src={performer.image_path ?? ''} />
|
||||||
<TagLink key={performer.id} performer={performer} />
|
</Link>
|
||||||
|
<TagLink key={performer.id} performer={performer} className="d-block" />
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -182,7 +176,7 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
className={`zoom-${props.zoomIndex} scene-card`}
|
className={`scene-card zoom-${props.zoomIndex}`}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
>
|
>
|
||||||
@@ -200,20 +194,18 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
{maybeRenderSceneStudioOverlay()}
|
{maybeRenderSceneStudioOverlay()}
|
||||||
<Link
|
<Link
|
||||||
to={`/scenes/${props.scene.id}`}
|
to={`/scenes/${props.scene.id}`}
|
||||||
className={cx("image", "previewable", { portrait: isPortrait() })}
|
className="scene-card-link"
|
||||||
>
|
>
|
||||||
<div className="video-container">
|
|
||||||
{maybeRenderRatingBanner()}
|
{maybeRenderRatingBanner()}
|
||||||
{maybeRenderSceneSpecsOverlay()}
|
{maybeRenderSceneSpecsOverlay()}
|
||||||
<video
|
<video
|
||||||
loop
|
loop
|
||||||
className={cx("preview", { portrait: isPortrait() })}
|
className={cx('scene-card-video', { portrait: isPortrait() })}
|
||||||
poster={props.scene.paths.screenshot || ""}
|
poster={props.scene.paths.screenshot || ""}
|
||||||
ref={videoHoverHook.videoEl}
|
ref={videoHoverHook.videoEl}
|
||||||
>
|
>
|
||||||
{previewPath ? <source src={previewPath} /> : ""}
|
{previewPath ? <source src={previewPath} /> : ""}
|
||||||
</video>
|
</video>
|
||||||
</div>
|
|
||||||
</Link>
|
</Link>
|
||||||
<div className="card-section">
|
<div className="card-section">
|
||||||
<h5 className="text-truncate">
|
<h5 className="text-truncate">
|
||||||
@@ -222,13 +214,15 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
: TextUtils.fileNameFromPath(props.scene.path)}
|
: TextUtils.fileNameFromPath(props.scene.path)}
|
||||||
</h5>
|
</h5>
|
||||||
<span>{props.scene.date}</span>
|
<span>{props.scene.date}</span>
|
||||||
|
{ props.scene.details && (
|
||||||
<p>
|
<p>
|
||||||
{TextUtils.truncate(
|
{TextUtils.truncate(
|
||||||
props.scene.details ?? "",
|
props.scene.details,
|
||||||
100,
|
100,
|
||||||
"... (continued)"
|
"... (continued)"
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{maybeRenderPopoverButtonGroup()}
|
{maybeRenderPopoverButtonGroup()}
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ export const PrimaryTags: React.FC<IPrimaryTags> = ({
|
|||||||
return (
|
return (
|
||||||
<div key={marker.id}>
|
<div key={marker.id}>
|
||||||
<hr />
|
<hr />
|
||||||
<div>
|
<div className="row">
|
||||||
<Button variant="link" onClick={() => onClickMarker(marker)}>
|
<Button variant="link" onClick={() => onClickMarker(marker)}>
|
||||||
{marker.title}
|
{marker.title}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="link"
|
variant="link"
|
||||||
style={{ float: "right" }}
|
className="ml-auto"
|
||||||
onClick={() => onEdit(marker)}
|
onClick={() => onEdit(marker)}
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
|
|||||||
@@ -153,17 +153,17 @@ export const SceneMarkerForm: React.FC<ISceneMarkerForm> = ({
|
|||||||
</div>
|
</div>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
</div>
|
</div>
|
||||||
<div className="buttons-container">
|
<div className="buttons-container row">
|
||||||
<Button variant="primary" type="submit">
|
<Button variant="primary" type="submit">
|
||||||
Submit
|
Submit
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="button" onClick={onClose}>
|
<Button variant="secondary" type="button" onClick={onClose} className="ml-2">
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
{editingMarker && (
|
{editingMarker && (
|
||||||
<Button
|
<Button
|
||||||
variant="danger"
|
variant="danger"
|
||||||
style={{ float: "right", marginRight: "10px" }}
|
className="ml-auto"
|
||||||
onClick={() => onDelete()}
|
onClick={() => onDelete()}
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ export const SceneList: React.FC<ISceneList> = ({
|
|||||||
}
|
}
|
||||||
if (filter.displayMode === DisplayMode.Grid) {
|
if (filter.displayMode === DisplayMode.Grid) {
|
||||||
return (
|
return (
|
||||||
<div className="grid">
|
<div className="row justify-content-center">
|
||||||
{result.data.findScenes.scenes.map(scene =>
|
{result.data.findScenes.scenes.map(scene =>
|
||||||
renderSceneCard(scene, selectedIds, zoomIndex)
|
renderSceneCard(scene, selectedIds, zoomIndex)
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -11,63 +11,30 @@ interface ISceneListTableProps {
|
|||||||
export const SceneListTable: React.FC<ISceneListTableProps> = (
|
export const SceneListTable: React.FC<ISceneListTableProps> = (
|
||||||
props: ISceneListTableProps
|
props: ISceneListTableProps
|
||||||
) => {
|
) => {
|
||||||
function renderSceneImage(scene: GQL.SlimSceneDataFragment) {
|
const renderTags = (tags: GQL.Tag[]) => (
|
||||||
const style: React.CSSProperties = {
|
tags.map(tag => (
|
||||||
backgroundImage: `url('${scene.paths.screenshot}')`,
|
|
||||||
lineHeight: 5,
|
|
||||||
backgroundSize: "contain",
|
|
||||||
display: "inline-block",
|
|
||||||
backgroundPosition: "center",
|
|
||||||
backgroundRepeat: "no-repeat"
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
className="scene-list-thumbnail"
|
|
||||||
to={`/scenes/${scene.id}`}
|
|
||||||
style={style}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderDuration(scene: GQL.SlimSceneDataFragment) {
|
|
||||||
if (scene.file.duration === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return TextUtils.secondsToTimestamp(scene.file.duration ?? 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderTags(tags: GQL.Tag[]) {
|
|
||||||
return tags.map(tag => (
|
|
||||||
<Link key={tag.id} to={NavUtils.makeTagScenesUrl(tag)}>
|
<Link key={tag.id} to={NavUtils.makeTagScenesUrl(tag)}>
|
||||||
<h6>{tag.name}</h6>
|
<h6>{tag.name}</h6>
|
||||||
</Link>
|
</Link>
|
||||||
));
|
))
|
||||||
}
|
|
||||||
|
|
||||||
function renderPerformers(performers: Partial<GQL.Performer>[]) {
|
|
||||||
return performers.map(performer => (
|
|
||||||
<Link key={performer.id} to={NavUtils.makePerformerScenesUrl(performer)}>
|
|
||||||
<h6>{performer.name}</h6>
|
|
||||||
</Link>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderStudio(studio: Partial<GQL.Studio> | undefined) {
|
|
||||||
if (studio) {
|
|
||||||
return (
|
|
||||||
<Link to={NavUtils.makeStudioScenesUrl(studio)}>
|
|
||||||
<h6>{studio.name}</h6>
|
|
||||||
</Link>
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderSceneRow(scene: GQL.SlimSceneDataFragment) {
|
const renderPerformers = (performers: Partial<GQL.Performer>[]) => (
|
||||||
return (
|
performers.map(performer => (
|
||||||
|
<Link key={performer.id} to={NavUtils.makePerformerScenesUrl(performer)} />
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderSceneRow = (scene: GQL.SlimSceneDataFragment) => (
|
||||||
<tr key={scene.id}>
|
<tr key={scene.id}>
|
||||||
<td>{renderSceneImage(scene)}</td>
|
<td>
|
||||||
<td style={{ textAlign: "left" }}>
|
<Link
|
||||||
|
to={`/scenes/${scene.id}`}
|
||||||
|
>
|
||||||
|
<img className="image-thumbnail" alt={scene.title ?? ''} src={scene.paths.screenshot ?? ''} />
|
||||||
|
</Link>
|
||||||
|
</td>
|
||||||
|
<td className="text-left">
|
||||||
<Link to={`/scenes/${scene.id}`}>
|
<Link to={`/scenes/${scene.id}`}>
|
||||||
<h5 className="text-truncate">
|
<h5 className="text-truncate">
|
||||||
{scene.title ?? TextUtils.fileNameFromPath(scene.path)}
|
{scene.title ?? TextUtils.fileNameFromPath(scene.path)}
|
||||||
@@ -75,13 +42,17 @@ export const SceneListTable: React.FC<ISceneListTableProps> = (
|
|||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
<td>{scene.rating ? scene.rating : ""}</td>
|
<td>{scene.rating ? scene.rating : ""}</td>
|
||||||
<td>{renderDuration(scene)}</td>
|
<td>{scene.file.duration && TextUtils.secondsToTimestamp(scene.file.duration) }</td>
|
||||||
<td>{renderTags(scene.tags)}</td>
|
<td>{renderTags(scene.tags)}</td>
|
||||||
<td>{renderPerformers(scene.performers)}</td>
|
<td>{renderPerformers(scene.performers)}</td>
|
||||||
<td>{renderStudio(scene.studio ?? undefined)}</td>
|
<td>{ scene.studio && (
|
||||||
|
<Link to={NavUtils.makeStudioScenesUrl(scene.studio)}>
|
||||||
|
<h6>{scene.studio.name}</h6>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
)
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid">
|
<div className="grid">
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export class ScenePlayerImpl extends React.Component<
|
|||||||
return (
|
return (
|
||||||
<ReactJWPlayer
|
<ReactJWPlayer
|
||||||
playerId={JWUtils.playerID}
|
playerId={JWUtils.playerID}
|
||||||
playerScript="http://192.168.1.65:9999/jwplayer/jwplayer.js"
|
playerScript="http://localhost:9999/jwplayer/jwplayer.js"
|
||||||
customProps={config}
|
customProps={config}
|
||||||
onReady={this.onReady}
|
onReady={this.onReady}
|
||||||
onSeeked={this.onSeeked}
|
onSeeked={this.onSeeked}
|
||||||
|
|||||||
@@ -264,10 +264,11 @@ export const SceneSelectedOptions: React.FC<IListOperationProps> = (
|
|||||||
<Form.Label>Rating</Form.Label>
|
<Form.Label>Rating</Form.Label>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
as="select"
|
as="select"
|
||||||
|
value={rating}
|
||||||
onChange={(event: any) => setRating(event.target.value)}
|
onChange={(event: any) => setRating(event.target.value)}
|
||||||
>
|
>
|
||||||
{["", "1", "2", "3", "4", "5"].map(opt => (
|
{["", "1", "2", "3", "4", "5"].map(opt => (
|
||||||
<option selected={opt === rating} value={opt}>
|
<option key={opt} value={opt}>
|
||||||
{opt}
|
{opt}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -13,12 +13,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid {
|
.row {
|
||||||
.scene-card {
|
.scene-card {
|
||||||
padding-bottom: 0;
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scene-card-link {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-section {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding: .5rem 1rem 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-select {
|
||||||
|
left: .5rem;
|
||||||
|
margin-top: -12px;
|
||||||
|
opacity: .5;
|
||||||
|
padding-left: 15px;
|
||||||
|
position: absolute;
|
||||||
|
top: .7rem;
|
||||||
|
width: 1.2rem;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.performer-tag-container {
|
.performer-tag-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
@@ -105,3 +126,24 @@
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.studio-card {
|
||||||
|
padding: .5rem;
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
height: 150px;
|
||||||
|
line-height: 150px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-image {
|
||||||
|
max-height: 150px;
|
||||||
|
object-fit: contain;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 320px;
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
.studio-card {
|
|
||||||
padding: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.studio-image {
|
|
||||||
height: 150px;
|
|
||||||
line-height: 150px;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -25,126 +25,71 @@ code {
|
|||||||
margin: $pt-grid-size $pt-grid-size 0 0;
|
margin: $pt-grid-size $pt-grid-size 0 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.performer-card,
|
|
||||||
.studio-card {
|
|
||||||
min-width: 185px;
|
|
||||||
width: 320px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.wall {
|
&.wall {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
& .performer-list-thumbnail {
|
|
||||||
height: 100px;
|
|
||||||
min-width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .scene-list-thumbnail {
|
|
||||||
min-height: 50px;
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table td {
|
table td {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
margin: 0 0 10px 10px;
|
margin: 5px;
|
||||||
overflow: hidden;
|
}
|
||||||
|
|
||||||
@media (min-width: 576px) {
|
@media (min-width: 576px) {
|
||||||
&.zoom-0 {
|
.zoom-0 {
|
||||||
width: 15rem;
|
width: 15rem;
|
||||||
|
|
||||||
.previewable {
|
|
||||||
max-height: 11.25rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.previewable.portrait {
|
.zoom-1 {
|
||||||
max-height: 11.25rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.zoom-1 {
|
|
||||||
width: 20rem;
|
width: 20rem;
|
||||||
|
|
||||||
.previewable {
|
|
||||||
max-height: 15rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.previewable.portrait {
|
.zoom-2 {
|
||||||
|
width: 30rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-3 {
|
||||||
|
width: 40rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-card-video {
|
||||||
|
height: auto;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.zoom-0 {
|
||||||
|
height: 11.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-1 {
|
||||||
height: 15rem;
|
height: 15rem;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&.zoom-2 {
|
.zoom-2 {
|
||||||
width: 30rem;
|
|
||||||
|
|
||||||
.previewable {
|
|
||||||
max-height: 22.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.previewable.portrait {
|
|
||||||
height: 22.5rem;
|
height: 22.5rem;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&.zoom-3 {
|
.zoom-3 {
|
||||||
width: 40rem;
|
|
||||||
|
|
||||||
.previewable {
|
|
||||||
max-height: 30rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.previewable.portrait {
|
|
||||||
height: 30rem;
|
height: 30rem;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-select {
|
|
||||||
margin-top: -12px;
|
|
||||||
opacity: .5;
|
|
||||||
padding-left: 15px;
|
|
||||||
position: absolute;
|
|
||||||
width: 1.2rem;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.previewable {
|
.image-thumbnail {
|
||||||
display: block;
|
height: 100px;
|
||||||
line-height: 0;
|
min-width: 50px;
|
||||||
margin: -20px 0 0 -20px;
|
|
||||||
max-height: 240px;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
width: calc(100% + 40px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.previewable.portrait {
|
|
||||||
height: 240px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
video.preview {
|
|
||||||
display: block;
|
|
||||||
margin: 0 auto;
|
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
width: 100%;
|
object-position: center 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
video.preview.portrait {
|
.card-image {
|
||||||
height: 100%;
|
height: 30rem;
|
||||||
width: auto;
|
min-width: 11.25rem;
|
||||||
|
width: 20rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-item,
|
.filter-item,
|
||||||
@@ -204,16 +149,6 @@ video.preview.portrait {
|
|||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-section {
|
|
||||||
padding: 10px 0 0 0;
|
|
||||||
|
|
||||||
&.centered {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.rating-5 {
|
.rating-5 {
|
||||||
background: #ff2f39;
|
background: #ff2f39;
|
||||||
}
|
}
|
||||||
@@ -264,26 +199,27 @@ video.preview.portrait {
|
|||||||
.scene-studio-overlay {
|
.scene-studio-overlay {
|
||||||
display: block;
|
display: block;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
height: 20%;
|
height: 10%;
|
||||||
|
max-width: 40%;
|
||||||
opacity: .75;
|
opacity: .75;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: .7rem;
|
right: .7rem;
|
||||||
top: .7rem;
|
top: .7rem;
|
||||||
width: 40%;
|
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
|
|
||||||
|
.image-thumbnail {
|
||||||
|
height: auto;
|
||||||
|
max-height: 50px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
background-position: right top;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: contain;
|
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 100%;
|
|
||||||
letter-spacing: -.03rem;
|
letter-spacing: -.03rem;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-shadow: 0 0 3px #000;
|
text-shadow: 0 0 3px #000;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,6 +404,12 @@ video.preview.portrait {
|
|||||||
.form-control {
|
.form-control {
|
||||||
&-plaintext {
|
&-plaintext {
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
option {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: transparent;
|
color: transparent;
|
||||||
@@ -496,6 +438,7 @@ video.preview.portrait {
|
|||||||
|
|
||||||
.image-input {
|
.image-input {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
margin-left: .5rem;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@@ -504,7 +447,6 @@ video.preview.portrait {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[type=file] {
|
[type=file] {
|
||||||
cursor: inherit;
|
|
||||||
display: block;
|
display: block;
|
||||||
filter: alpha(opacity=0);
|
filter: alpha(opacity=0);
|
||||||
font-size: 999px;
|
font-size: 999px;
|
||||||
@@ -515,6 +457,11 @@ video.preview.portrait {
|
|||||||
right: 0;
|
right: 0;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,3 +512,7 @@ video.preview.portrait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
white-space: "pre-wrap";
|
||||||
|
}
|
||||||
|
|||||||
@@ -99,6 +99,16 @@ hr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
td {
|
||||||
|
padding: .25rem .75rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.popover {
|
.popover {
|
||||||
max-width: inherit;
|
max-width: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user