mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Responsive styles for portrait orientation phones
This commit is contained in:
@@ -49,7 +49,7 @@
|
|||||||
"function-whitespace-after": "always",
|
"function-whitespace-after": "always",
|
||||||
"length-zero-no-unit": true,
|
"length-zero-no-unit": true,
|
||||||
"max-empty-lines": 1,
|
"max-empty-lines": 1,
|
||||||
"max-nesting-depth": 3,
|
"max-nesting-depth": 4,
|
||||||
"max-line-length": 100,
|
"max-line-length": 100,
|
||||||
"media-feature-colon-space-after": "always",
|
"media-feature-colon-space-after": "always",
|
||||||
"media-feature-colon-space-before": "never",
|
"media-feature-colon-space-before": "never",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const App: React.FC = () => (
|
|||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<ToastProvider>
|
<ToastProvider>
|
||||||
<MainNavbar />
|
<MainNavbar />
|
||||||
<div className="main">
|
<div className="main container-fluid">
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" component={Stats} />
|
<Route exact path="/" component={Stats} />
|
||||||
<Route path="/scenes" component={Scenes} />
|
<Route path="/scenes" component={Scenes} />
|
||||||
|
|||||||
@@ -64,13 +64,18 @@ export const MainNavbar: React.FC = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Navbar fixed="top" variant="dark" bg="dark">
|
<Navbar fixed="top" variant="dark" bg="dark" className="top-nav">
|
||||||
<Navbar.Brand as="div">
|
<Navbar.Brand as="div">
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<Button className="minimal">Stash</Button>
|
<Button className="minimal brand-link d-none d-sm-inline-block">
|
||||||
|
Stash
|
||||||
|
</Button>
|
||||||
|
<Button className="minimal brand-icon d-inline d-sm-none">
|
||||||
|
<img src="http://192.168.1.65:9999/favicon.ico" alt="" />
|
||||||
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</Navbar.Brand>
|
</Navbar.Brand>
|
||||||
<Nav className="mr-auto">
|
<Nav className="mr-md-auto">
|
||||||
{menuItems.map(i => (
|
{menuItems.map(i => (
|
||||||
<LinkContainer
|
<LinkContainer
|
||||||
activeClassName="active"
|
activeClassName="active"
|
||||||
@@ -80,13 +85,15 @@ export const MainNavbar: React.FC = () => {
|
|||||||
>
|
>
|
||||||
<Button className="minimal">
|
<Button className="minimal">
|
||||||
<Icon icon={i.icon} />
|
<Icon icon={i.icon} />
|
||||||
<span>{i.text}</span>
|
<span className="d-none d-sm-inline">{i.text}</span>
|
||||||
</Button>
|
</Button>
|
||||||
</LinkContainer>
|
</LinkContainer>
|
||||||
))}
|
))}
|
||||||
</Nav>
|
</Nav>
|
||||||
<Nav>
|
<Nav>
|
||||||
|
<div className="d-none d-sm-block">
|
||||||
{newButton}
|
{newButton}
|
||||||
|
</div>
|
||||||
<LinkContainer exact to="/settings">
|
<LinkContainer exact to="/settings">
|
||||||
<Button className="minimal">
|
<Button className="minimal">
|
||||||
<Icon icon="cog" />
|
<Icon icon="cog" />
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export const ParserInput: React.FC<IParserInputProps> = (props: IParserInputProp
|
|||||||
<InputGroup.Append>
|
<InputGroup.Append>
|
||||||
<DropdownButton id="parser-field-select" title="Add Field">
|
<DropdownButton id="parser-field-select" title="Add Field">
|
||||||
{validFields.map(item => (
|
{validFields.map(item => (
|
||||||
<Dropdown.Item onSelect={() => addParserField(item)}>
|
<Dropdown.Item key={item.field} onSelect={() => addParserField(item)}>
|
||||||
<span>{item.field}</span>
|
<span>{item.field}</span>
|
||||||
<span className="ml-auto">{item.helperText}</span>
|
<span className="ml-auto">{item.helperText}</span>
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
@@ -184,7 +184,7 @@ export const ParserInput: React.FC<IParserInputProps> = (props: IParserInputProp
|
|||||||
<Form.Group>
|
<Form.Group>
|
||||||
<DropdownButton variant="secondary" id="recipe-select" title="Select Parser Recipe">
|
<DropdownButton variant="secondary" id="recipe-select" title="Select Parser Recipe">
|
||||||
{builtInRecipes.map(item => (
|
{builtInRecipes.map(item => (
|
||||||
<Dropdown.Item onSelect={() => setParserRecipe(item)}>
|
<Dropdown.Item key={item.pattern} onSelect={() => setParserRecipe(item)}>
|
||||||
<span>{item.pattern}</span>
|
<span>{item.pattern}</span>
|
||||||
<span className="mr-auto">{item.description}</span>
|
<span className="mr-auto">{item.description}</span>
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ export const ShowFields = (props: IShowFieldsProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fieldRows = [...props.fields.entries()].map(([label, enabled]) => (
|
const fieldRows = [...props.fields.entries()].map(([label, enabled]) => (
|
||||||
<div
|
<Button
|
||||||
|
className="minimal d-block"
|
||||||
key={label}
|
key={label}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleClick(label);
|
handleClick(label);
|
||||||
@@ -28,7 +29,7 @@ export const ShowFields = (props: IShowFieldsProps) => {
|
|||||||
>
|
>
|
||||||
<Icon icon={enabled ? "check" : "times"} />
|
<Icon icon={enabled ? "check" : "times"} />
|
||||||
<span>{label}</span>
|
<span>{label}</span>
|
||||||
</div>
|
</Button>
|
||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
<Form.Group id="database-path">
|
<Form.Group id="database-path">
|
||||||
<h6>Database Path</h6>
|
<h6>Database Path</h6>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
defaultValue={databasePath}
|
defaultValue={databasePath}
|
||||||
onChange={(e: any) => setDatabasePath(e.target.value)}
|
onChange={(e: any) => setDatabasePath(e.target.value)}
|
||||||
/>
|
/>
|
||||||
@@ -186,7 +186,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
<Form.Group id="generated-path">
|
<Form.Group id="generated-path">
|
||||||
<h6>Generated Path</h6>
|
<h6>Generated Path</h6>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
defaultValue={generatedPath}
|
defaultValue={generatedPath}
|
||||||
onChange={(e: any) => setGeneratedPath(e.target.value)}
|
onChange={(e: any) => setGeneratedPath(e.target.value)}
|
||||||
/>
|
/>
|
||||||
@@ -203,7 +203,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
&& excludes.map((regexp, i) => (
|
&& excludes.map((regexp, i) => (
|
||||||
<InputGroup>
|
<InputGroup>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
value={regexp}
|
value={regexp}
|
||||||
onChange={(e: any) =>
|
onChange={(e: any) =>
|
||||||
excludeRegexChanged(i, e.target.value)
|
excludeRegexChanged(i, e.target.value)
|
||||||
@@ -246,7 +246,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
<Form.Group id="transcode-size">
|
<Form.Group id="transcode-size">
|
||||||
<h6>Maximum transcode size</h6>
|
<h6>Maximum transcode size</h6>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
as="select"
|
as="select"
|
||||||
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
|
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
|
||||||
setMaxTranscodeSize(translateQuality(event.currentTarget.value))
|
setMaxTranscodeSize(translateQuality(event.currentTarget.value))
|
||||||
@@ -266,7 +266,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
<Form.Group id="streaming-transcode-size">
|
<Form.Group id="streaming-transcode-size">
|
||||||
<h6>Maximum streaming transcode size</h6>
|
<h6>Maximum streaming transcode size</h6>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
as="select"
|
as="select"
|
||||||
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
|
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
|
||||||
setMaxStreamingTranscodeSize(
|
setMaxStreamingTranscodeSize(
|
||||||
@@ -294,7 +294,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
<Form.Group id="username">
|
<Form.Group id="username">
|
||||||
<h6>Username</h6>
|
<h6>Username</h6>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
defaultValue={username}
|
defaultValue={username}
|
||||||
onChange={(e: React.FormEvent<HTMLInputElement>) =>
|
onChange={(e: React.FormEvent<HTMLInputElement>) =>
|
||||||
setUsername(e.currentTarget.value)
|
setUsername(e.currentTarget.value)
|
||||||
@@ -307,7 +307,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
<Form.Group id="password">
|
<Form.Group id="password">
|
||||||
<h6>Password</h6>
|
<h6>Password</h6>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
type="password"
|
type="password"
|
||||||
defaultValue={password}
|
defaultValue={password}
|
||||||
onChange={(e: React.FormEvent<HTMLInputElement>) =>
|
onChange={(e: React.FormEvent<HTMLInputElement>) =>
|
||||||
@@ -326,7 +326,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
<Form.Group id="log-file">
|
<Form.Group id="log-file">
|
||||||
<h6>Log file</h6>
|
<h6>Log file</h6>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
defaultValue={logFile}
|
defaultValue={logFile}
|
||||||
onChange={(e: React.FormEvent<HTMLInputElement>) =>
|
onChange={(e: React.FormEvent<HTMLInputElement>) =>
|
||||||
setLogFile(e.currentTarget.value)
|
setLogFile(e.currentTarget.value)
|
||||||
@@ -354,7 +354,7 @@ export const SettingsConfigurationPanel: React.FC = () => {
|
|||||||
<Form.Group id="log-level">
|
<Form.Group id="log-level">
|
||||||
<h6>Log Level</h6>
|
<h6>Log Level</h6>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
as="select"
|
as="select"
|
||||||
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
|
onChange={(event: React.FormEvent<HTMLSelectElement>) =>
|
||||||
setLogLevel(event.currentTarget.value)
|
setLogLevel(event.currentTarget.value)
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export const SettingsInterfacePanel: React.FC = () => {
|
|||||||
<Form.Group id="max-loop-duration">
|
<Form.Group id="max-loop-duration">
|
||||||
<Form.Label>Maximum loop duration</Form.Label>
|
<Form.Label>Maximum loop duration</Form.Label>
|
||||||
<DurationInput
|
<DurationInput
|
||||||
className="col-4"
|
className="col col-sm-4"
|
||||||
numericValue={maximumLoopDuration}
|
numericValue={maximumLoopDuration}
|
||||||
onValueChange={duration => setMaximumLoopDuration(duration)}
|
onValueChange={duration => setMaximumLoopDuration(duration)}
|
||||||
/>
|
/>
|
||||||
@@ -129,7 +129,7 @@ export const SettingsInterfacePanel: React.FC = () => {
|
|||||||
value={css}
|
value={css}
|
||||||
onChange={(e: any) => setCSS(e.target.value)}
|
onChange={(e: any) => setCSS(e.target.value)}
|
||||||
rows={16}
|
rows={16}
|
||||||
className="col-6"
|
className="col col-sm-6"
|
||||||
></Form.Control>
|
></Form.Control>
|
||||||
<Form.Text className="text-muted">
|
<Form.Text className="text-muted">
|
||||||
Page must be reloaded for changes to take effect.
|
Page must be reloaded for changes to take effect.
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ const LogElement: React.FC<ILogElementProps> = ({ logEntry }) => {
|
|||||||
<div className="row">
|
<div className="row">
|
||||||
<span className="log-time">{logEntry.time}</span>
|
<span className="log-time">{logEntry.time}</span>
|
||||||
<span className={`${levelClass(logEntry.level)}`}>{level}</span>
|
<span className={`${levelClass(logEntry.level)}`}>{level}</span>
|
||||||
<span className="col-9">{logEntry.message}</span>
|
<span className="col col-sm-9">{logEntry.message}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -99,9 +99,9 @@ export const SettingsLogsPanel: React.FC = () => {
|
|||||||
<>
|
<>
|
||||||
<h4>Logs</h4>
|
<h4>Logs</h4>
|
||||||
<Form.Row id="log-level">
|
<Form.Row id="log-level">
|
||||||
<Form.Label className="col-2">Log Level</Form.Label>
|
<Form.Label className="col-6 col-sm-2">Log Level</Form.Label>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="col-2"
|
className="col-6 col-sm-2"
|
||||||
as="select"
|
as="select"
|
||||||
defaultValue={logLevel}
|
defaultValue={logLevel}
|
||||||
onChange={event => setLogLevel(event.currentTarget.value)}
|
onChange={event => setLogLevel(event.currentTarget.value)}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export const DetailsEditNavbar: React.FC<IProps> = (props: IProps) => {
|
|||||||
function renderDeleteButton() {
|
function renderDeleteButton() {
|
||||||
if (props.isNew || props.isEditing) return;
|
if (props.isNew || props.isEditing) return;
|
||||||
return (
|
return (
|
||||||
<Button variant="danger" className="delete" onClick={() => setIsDeleteAlertOpen(true)}>
|
<Button variant="danger" className="delete d-none d-sm-block" onClick={() => setIsDeleteAlertOpen(true)}>
|
||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export const FolderSelect: React.FC<IProps> = (props: IProps) => {
|
|||||||
<ul className="folder-list">
|
<ul className="folder-list">
|
||||||
{selectableDirectories.map(path => {
|
{selectableDirectories.map(path => {
|
||||||
return (
|
return (
|
||||||
<li className="folder-item">
|
<li key={path} className="folder-item">
|
||||||
<Button
|
<Button
|
||||||
variant="link"
|
variant="link"
|
||||||
key={path}
|
key={path}
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ export const Stats: React.FC = () => {
|
|||||||
if (error) return <span>error.message</span>;
|
if (error) return <span>error.message</span>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-75 m-auto">
|
<div className="mt-5">
|
||||||
<nav className="w-75 m-auto d-flex flex-row">
|
<div className="col col-sm-8 m-sm-auto">
|
||||||
|
<nav className="col col-sm-8 m-sm-auto row">
|
||||||
<div className="flex-grow-1">
|
<div className="flex-grow-1">
|
||||||
<div>
|
<div>
|
||||||
<p className="heading">Scenes</p>
|
<p className="heading">Scenes</p>
|
||||||
@@ -45,11 +46,8 @@ export const Stats: React.FC = () => {
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<h5>Notes</h5>
|
<h5>Notes</h5>
|
||||||
<pre>
|
<em>This is still an early version, some things are still a work in progress.</em>
|
||||||
{`
|
</div>
|
||||||
This is still an early version, some things are still a work in progress.
|
|
||||||
`}
|
|
||||||
</pre>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ export const Studio: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className={cx('studio-details', { 'col-4': !isNew, 'col-8': isNew})}>
|
<div className={cx('studio-details', { 'col ml-sm-5': !isNew, 'col-8': isNew})}>
|
||||||
{ 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 id="performer-details" style={{ width: "100%" }}>
|
||||||
@@ -180,7 +180,7 @@ export const Studio: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{ !isNew && (
|
{ !isNew && (
|
||||||
<div className="col-8">
|
<div className="col-12 col-sm-8">
|
||||||
<StudioScenesPanel studio={studio} />
|
<StudioScenesPanel studio={studio} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
.studio-details {
|
.studio-details {
|
||||||
padding-left: 4rem;
|
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
margin: 4rem 0;
|
margin: 4rem 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -93,6 +93,10 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 20%;
|
width: 20%;
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
video,
|
video,
|
||||||
img {
|
img {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export const WallPanel: React.FC<IWallPanelProps> = (
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`wall-overlay ${overlayClassName}`} />
|
<div className={`wall-overlay ${overlayClassName}`} />
|
||||||
<div className="wall grid">
|
<div className="wall grid row">
|
||||||
{maybeRenderScenes()}
|
{maybeRenderScenes()}
|
||||||
{maybeRenderSceneMarkers()}
|
{maybeRenderSceneMarkers()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
if (props.onChangeZoom) {
|
if (props.onChangeZoom) {
|
||||||
return (
|
return (
|
||||||
<Form.Control
|
<Form.Control
|
||||||
className="zoom-slider col-1"
|
className="zoom-slider col-1 d-none d-sm-block"
|
||||||
type="range"
|
type="range"
|
||||||
min={0}
|
min={0}
|
||||||
max={3}
|
max={3}
|
||||||
@@ -249,14 +249,14 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
defaultValue={props.filter.searchTerm}
|
defaultValue={props.filter.searchTerm}
|
||||||
onChange={onChangeQuery}
|
onChange={onChangeQuery}
|
||||||
className="filter-item"
|
className="filter-item col-5 col-sm-2"
|
||||||
style={{ width: "inherit" }}
|
style={{ width: "inherit" }}
|
||||||
/>
|
/>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
as="select"
|
as="select"
|
||||||
onChange={onChangePageSize}
|
onChange={onChangePageSize}
|
||||||
value={props.filter.itemsPerPage.toString()}
|
value={props.filter.itemsPerPage.toString()}
|
||||||
className="filter-item col-1"
|
className="filter-item col-1 d-none d-sm-inline"
|
||||||
>
|
>
|
||||||
{PAGE_SIZE_OPTIONS.map(s => (
|
{PAGE_SIZE_OPTIONS.map(s => (
|
||||||
<option value={s} key={s}>{s}</option>
|
<option value={s} key={s}>{s}</option>
|
||||||
@@ -298,13 +298,13 @@ export const ListFilter: React.FC<IListFilterProps> = (
|
|||||||
editingCriterion={editingCriterion}
|
editingCriterion={editingCriterion}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ButtonGroup className="filter-item">
|
<ButtonGroup className="filter-item d-none d-sm-inline-flex">
|
||||||
{renderDisplayModeOptions()}
|
{renderDisplayModeOptions()}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
||||||
{maybeRenderZoom()}
|
{maybeRenderZoom()}
|
||||||
|
|
||||||
<ButtonGroup className="filter-item">{renderMore()}</ButtonGroup>
|
<ButtonGroup className="filter-item d-none d-sm-inline-flex">{renderMore()}</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -37,9 +37,20 @@ export const Pagination: React.FC<IPaginationProps> = ({
|
|||||||
i => startPage + i
|
i => startPage + i
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const calculatePageClass = (buttonPage:number) => {
|
||||||
|
if(pages.length <= 4) return '';
|
||||||
|
|
||||||
|
if(currentPage === 1 && buttonPage <= 4) return '';
|
||||||
|
const maxPage = pages[pages.length - 1];
|
||||||
|
if(currentPage === maxPage && buttonPage > (maxPage - 3)) return '';
|
||||||
|
if(Math.abs(buttonPage - currentPage) <= 1) return '';
|
||||||
|
return 'd-none d-sm-block'
|
||||||
|
}
|
||||||
|
|
||||||
const pageButtons = pages.map((page: number) => (
|
const pageButtons = pages.map((page: number) => (
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
className={calculatePageClass(page)}
|
||||||
key={page}
|
key={page}
|
||||||
active={currentPage === page}
|
active={currentPage === page}
|
||||||
onClick={() => onChangePage(page)}
|
onClick={() => onChangePage(page)}
|
||||||
@@ -54,9 +65,11 @@ export const Pagination: React.FC<IPaginationProps> = ({
|
|||||||
return (
|
return (
|
||||||
<ButtonGroup className="filter-container pagination">
|
<ButtonGroup className="filter-container pagination">
|
||||||
<Button variant="secondary" disabled={currentPage === 1} onClick={() => onChangePage(1)}>
|
<Button variant="secondary" disabled={currentPage === 1} onClick={() => onChangePage(1)}>
|
||||||
First
|
<span className="d-none d-sm-inline">First</span>
|
||||||
|
<span className="d-inline d-sm-none">《</span>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
className="d-none d-sm-block"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
disabled={currentPage === 1}
|
disabled={currentPage === 1}
|
||||||
onClick={() => onChangePage(currentPage - 1)}
|
onClick={() => onChangePage(currentPage - 1)}
|
||||||
@@ -65,6 +78,7 @@ export const Pagination: React.FC<IPaginationProps> = ({
|
|||||||
</Button>
|
</Button>
|
||||||
{pageButtons}
|
{pageButtons}
|
||||||
<Button
|
<Button
|
||||||
|
className="d-none d-sm-block"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
disabled={currentPage === totalPages}
|
disabled={currentPage === totalPages}
|
||||||
onClick={() => onChangePage(currentPage + 1)}
|
onClick={() => onChangePage(currentPage + 1)}
|
||||||
@@ -76,7 +90,8 @@ export const Pagination: React.FC<IPaginationProps> = ({
|
|||||||
disabled={currentPage === totalPages}
|
disabled={currentPage === totalPages}
|
||||||
onClick={() => onChangePage(totalPages)}
|
onClick={() => onChangePage(totalPages)}
|
||||||
>
|
>
|
||||||
Last
|
<span className="d-none d-sm-inline">Last</span>
|
||||||
|
<span className="d-inline d-sm-none">》</span>
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ export const Performer: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderIcons = () => (
|
const renderIcons = () => (
|
||||||
<span className="name-icons">
|
<span className="name-icons d-block d-sm-inline">
|
||||||
<Button
|
<Button
|
||||||
className={cx('minimal', performer.favorite ? "favorite" : "not-favorite")}
|
className={cx('minimal', performer.favorite ? "favorite" : "not-favorite")}
|
||||||
onClick={() => setFavorite(!performer.favorite)}
|
onClick={() => setFavorite(!performer.favorite)}
|
||||||
@@ -217,13 +217,19 @@ export const Performer: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="performer-page" className="row">
|
<div id="performer-page" className="row">
|
||||||
<div className="image-container col-4 offset-1">
|
<div className="image-container col-sm-4 offset-sm-1 d-none d-sm-block">
|
||||||
<Button variant="link" onClick={() => setLightboxIsOpen(true)}>
|
<Button variant="link" onClick={() => setLightboxIsOpen(true)}>
|
||||||
<img className="performer" src={imagePreview} alt="Performer" />
|
<img className="performer" src={imagePreview} alt="Performer" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-6">
|
<div className="col col-sm-6">
|
||||||
<div className="performer-head">
|
<div className="row">
|
||||||
|
<div className="image-container col-6 d-block d-sm-none">
|
||||||
|
<Button variant="link" onClick={() => setLightboxIsOpen(true)}>
|
||||||
|
<img className="performer" src={imagePreview} alt="Performer" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="performer-head col-6 col-sm-12">
|
||||||
<h2>
|
<h2>
|
||||||
{performer.name}
|
{performer.name}
|
||||||
{renderIcons()}
|
{renderIcons()}
|
||||||
@@ -231,6 +237,7 @@ export const Performer: React.FC = () => {
|
|||||||
{maybeRenderAliases()}
|
{maybeRenderAliases()}
|
||||||
{maybeRenderAge()}
|
{maybeRenderAge()}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="performer-body">
|
<div className="performer-body">
|
||||||
<div className="performer-tabs">{renderTabs()}</div>
|
<div className="performer-tabs">{renderTabs()}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const PerformerList: React.FC = () => {
|
|||||||
}
|
}
|
||||||
if (filter.displayMode === DisplayMode.Grid) {
|
if (filter.displayMode === DisplayMode.Grid) {
|
||||||
return (
|
return (
|
||||||
<div className="grid">
|
<div className="grid row">
|
||||||
{result.data.findPerformers.performers.map(p => (
|
{result.data.findPerformers.performers.map(p => (
|
||||||
<PerformerCard key={p.id} performer={p} />
|
<PerformerCard key={p.id} performer={p} />
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
>
|
>
|
||||||
<Form.Control
|
<Form.Control
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
className="card-select"
|
className="card-select d-none d-sm-block"
|
||||||
checked={props.selected}
|
checked={props.selected}
|
||||||
onChange={() => props.onSelectedChanged(!props.selected, shiftKey)}
|
onChange={() => props.onSelectedChanged(!props.selected, shiftKey)}
|
||||||
onClick={(event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
|
onClick={(event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const PrimaryTags: React.FC<IPrimaryTags> = ({ sceneMarkers, onClickMarke
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="primary-card col-3" key={id}>
|
<Card className="primary-card col-12 col-sm-3" key={id}>
|
||||||
<h3>{primaries[id].name}</h3>
|
<h3>{primaries[id].name}</h3>
|
||||||
<Card.Body className="primary-card-body">
|
<Card.Body className="primary-card-body">
|
||||||
{ markers }
|
{ markers }
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const Scene: React.FC = () => {
|
|||||||
timestamp={timestamp}
|
timestamp={timestamp}
|
||||||
autoplay={autoplay}
|
autoplay={autoplay}
|
||||||
/>
|
/>
|
||||||
<div id="details-container">
|
<div id="details-container" className="col col-sm-9 m-sm-auto">
|
||||||
<Tabs id="scene-tabs" mountOnEnter>
|
<Tabs id="scene-tabs" mountOnEnter>
|
||||||
<Tab eventKey="scene-details-panel" title="Details">
|
<Tab eventKey="scene-details-panel" title="Details">
|
||||||
<SceneDetailPanel scene={scene} />
|
<SceneDetailPanel scene={scene} />
|
||||||
@@ -83,7 +83,7 @@ export const Scene: React.FC = () => {
|
|||||||
<Tab className="file-info-panel" eventKey="scene-file-info-panel" title="File Info">
|
<Tab className="file-info-panel" eventKey="scene-file-info-panel" title="File Info">
|
||||||
<SceneFileInfoPanel scene={scene} />
|
<SceneFileInfoPanel scene={scene} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="scene-edit-panel" title="Edit">
|
<Tab eventKey="scene-edit-panel" title="Edit" tabClassName="d-none d-sm-block">
|
||||||
<SceneEditPanel
|
<SceneEditPanel
|
||||||
scene={scene}
|
scene={scene}
|
||||||
onUpdate={newScene => setScene(newScene)}
|
onUpdate={newScene => setScene(newScene)}
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ export const SceneDetailPanel: React.FC<ISceneDetailProps> = props => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<h1 className="col scene-header">
|
<h3 className="col scene-header text-truncate">
|
||||||
{props.scene.title ?? TextUtils.fileNameFromPath(props.scene.path)}
|
{props.scene.title ?? TextUtils.fileNameFromPath(props.scene.path)}
|
||||||
</h1>
|
</h3>
|
||||||
<div className="col-6 scene-details">
|
<div className="col-6 scene-details">
|
||||||
<h4>{props.scene.date ?? ''}</h4>
|
<h4>{props.scene.date ?? ''}</h4>
|
||||||
{props.scene.rating ? <h6>Rating: {props.scene.rating}</h6> : ""}
|
{props.scene.rating ? <h6>Rating: {props.scene.rating}</h6> : ""}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Table } from "react-bootstrap";
|
|
||||||
import * as GQL from "src/core/generated-graphql";
|
import * as GQL from "src/core/generated-graphql";
|
||||||
import { TextUtils } from "src/utils";
|
import { TextUtils } from "src/utils";
|
||||||
|
|
||||||
@@ -12,10 +11,10 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
) => {
|
) => {
|
||||||
function renderChecksum() {
|
function renderChecksum() {
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Checksum</td>
|
<span className="col-4">Checksum</span>
|
||||||
<td>{props.scene.checksum}</td>
|
<span className="col-8 text-truncate">{props.scene.checksum}</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,25 +23,25 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
scene: { path }
|
scene: { path }
|
||||||
} = props;
|
} = props;
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Path</td>
|
<span className="col-4">Path</span>
|
||||||
<td>
|
<span className="col-8 text-truncate">
|
||||||
<a href={`file://${path}`}>{`file://${props.scene.path}`}</a>{" "}
|
<a href={`file://${path}`}>{`file://${props.scene.path}`}</a>{" "}
|
||||||
</td>
|
</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderStream() {
|
function renderStream() {
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Stream</td>
|
<span className="col-4">Stream</span>
|
||||||
<td>
|
<span className="col-8 text-truncate">
|
||||||
<a href={props.scene.paths.stream ?? ""}>
|
<a href={props.scene.paths.stream ?? ""}>
|
||||||
{props.scene.paths.stream}
|
{props.scene.paths.stream}
|
||||||
</a>{" "}
|
</a>{" "}
|
||||||
</td>
|
</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,12 +50,12 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>File Size</td>
|
<span className="col-4">File Size</span>
|
||||||
<td>
|
<span className="col-8 text-truncate">
|
||||||
{TextUtils.fileSize(parseInt(props.scene.file.size ?? "0", 10))}
|
{TextUtils.fileSize(parseInt(props.scene.file.size ?? "0", 10))}
|
||||||
</td>
|
</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,10 +64,12 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Duration</td>
|
<span className="col-4">Duration</span>
|
||||||
<td>{TextUtils.secondsToTimestamp(props.scene.file.duration ?? 0)}</td>
|
<span className="col-8 text-truncate">
|
||||||
</tr>
|
{TextUtils.secondsToTimestamp(props.scene.file.duration ?? 0)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,12 +78,12 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Dimensions</td>
|
<span className="col-4">Dimensions</span>
|
||||||
<td>
|
<span className="col-8 text-truncate">
|
||||||
{props.scene.file.width} x {props.scene.file.height}
|
{props.scene.file.width} x {props.scene.file.height}
|
||||||
</td>
|
</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,22 +92,22 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Frame Rate</td>
|
<span className="col-4">Frame Rate</span>
|
||||||
<td>{props.scene.file.framerate} frames per second</td>
|
<span className="col-8 text-truncate">{props.scene.file.framerate} frames per second</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderBitRate() {
|
function renderbitrate() {
|
||||||
if (props.scene.file.bitrate === undefined) {
|
if (props.scene.file.bitrate === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Bit Rate</td>
|
<span className="col-4">Bit Rate</span>
|
||||||
<td>{TextUtils.bitRate(props.scene.file.bitrate ?? 0)}</td>
|
<span className="col-8 text-truncate">{TextUtils.bitRate(props.scene.file.bitrate ?? 0)}</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,10 +116,10 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Video Codec</td>
|
<span className="col-4">Video Codec</span>
|
||||||
<td>{props.scene.file.video_codec}</td>
|
<span className="col-8 text-truncate">{props.scene.file.video_codec}</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,10 +128,10 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Audio Codec</td>
|
<span className="col-4">Audio Codec</span>
|
||||||
<td>{props.scene.file.audio_codec}</td>
|
<span className="col-8 text-truncate">{props.scene.file.audio_codec}</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,17 +140,15 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<div className="row">
|
||||||
<td>Downloaded From</td>
|
<span className="col-4">Downloaded From</span>
|
||||||
<td>{props.scene.url}</td>
|
<span className="col-8 text-truncate">{props.scene.url}</span>
|
||||||
</tr>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="container scene-file-info">
|
||||||
<Table>
|
|
||||||
<tbody>
|
|
||||||
{renderChecksum()}
|
{renderChecksum()}
|
||||||
{renderPath()}
|
{renderPath()}
|
||||||
{renderStream()}
|
{renderStream()}
|
||||||
@@ -157,12 +156,10 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
|
|||||||
{renderDuration()}
|
{renderDuration()}
|
||||||
{renderDimensions()}
|
{renderDimensions()}
|
||||||
{renderFrameRate()}
|
{renderFrameRate()}
|
||||||
{renderBitRate()}
|
{renderbitrate()}
|
||||||
{renderVideoCodec()}
|
{renderVideoCodec()}
|
||||||
{renderAudioCodec()}
|
{renderAudioCodec()}
|
||||||
{renderUrl()}
|
{renderUrl()}
|
||||||
</tbody>
|
</div>
|
||||||
</Table>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,11 +51,13 @@ export const SceneMarkersPanel: React.FC<ISceneMarkersPanelProps> = (
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={() => onOpenEditor()}>Create Marker</Button>
|
<Button onClick={() => onOpenEditor()}>Create Marker</Button>
|
||||||
|
<div className="container">
|
||||||
<PrimaryTags
|
<PrimaryTags
|
||||||
sceneMarkers={props.scene.scene_markers ?? []}
|
sceneMarkers={props.scene.scene_markers ?? []}
|
||||||
onClickMarker={onClickMarker}
|
onClickMarker={onClickMarker}
|
||||||
onEdit={onOpenEditor}
|
onEdit={onOpenEditor}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<WallPanel
|
<WallPanel
|
||||||
sceneMarkers={props.scene.scene_markers}
|
sceneMarkers={props.scene.scene_markers}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export class ScenePlayerImpl extends React.Component<
|
|||||||
return (
|
return (
|
||||||
<ReactJWPlayer
|
<ReactJWPlayer
|
||||||
playerId={JWUtils.playerID}
|
playerId={JWUtils.playerID}
|
||||||
playerScript="http://localhost:9999/jwplayer/jwplayer.js"
|
playerScript="http://192.168.1.65:9999/jwplayer/jwplayer.js"
|
||||||
customProps={config}
|
customProps={config}
|
||||||
onReady={this.onReady}
|
onReady={this.onReady}
|
||||||
onSeeked={this.onSeeked}
|
onSeeked={this.onSeeked}
|
||||||
@@ -205,8 +205,8 @@ export class ScenePlayerImpl extends React.Component<
|
|||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<HotKeys keyMap={KeyMap} handlers={this.KeyHandlers}>
|
<HotKeys keyMap={KeyMap} handlers={this.KeyHandlers} className="row">
|
||||||
<div id="jwplayer-container">
|
<div id="jwplayer-container" className="w-100 col-sm-9 m-sm-auto no-gutter" >
|
||||||
{this.renderPlayer()}
|
{this.renderPlayer()}
|
||||||
<ScenePlayerScrubber
|
<ScenePlayerScrubber
|
||||||
scene={this.props.scene}
|
scene={this.props.scene}
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ export const ScenePlayerScrubber: React.FC<IScenePlayerScrubberProps> = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="scrubber-wrapper">
|
<div className="scrubber-wrapper d-none d-sm-block">
|
||||||
<Button
|
<Button
|
||||||
variant="link"
|
variant="link"
|
||||||
className="scrubber-button"
|
className="scrubber-button"
|
||||||
|
|||||||
@@ -78,8 +78,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file-info-panel {
|
.file-info-panel {
|
||||||
td {
|
div {
|
||||||
padding: .4rem;
|
margin-bottom: .5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ body {
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: $pt-navbar-height 0 0 0;
|
padding: $pt-navbar-height 0 0 0;
|
||||||
|
|
||||||
|
@media (min-width: 600px) {
|
||||||
|
min-width: 845px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
@@ -21,6 +25,12 @@ 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;
|
||||||
@@ -44,8 +54,8 @@ code {
|
|||||||
.card {
|
.card {
|
||||||
margin: 0 0 10px 10px;
|
margin: 0 0 10px 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 20rem;
|
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
&.zoom-0 {
|
&.zoom-0 {
|
||||||
width: 15rem;
|
width: 15rem;
|
||||||
|
|
||||||
@@ -93,6 +103,7 @@ code {
|
|||||||
height: 30rem;
|
height: 30rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.card-select {
|
.card-select {
|
||||||
margin-top: -12px;
|
margin-top: -12px;
|
||||||
@@ -314,11 +325,6 @@ video.preview.portrait {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#details-container {
|
|
||||||
margin: 10px auto;
|
|
||||||
width: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pre {
|
.pre {
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
@@ -527,3 +533,35 @@ video.preview.portrait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* stylelint-enable */
|
/* stylelint-enable */
|
||||||
|
|
||||||
|
.brand-icon {
|
||||||
|
padding: 3px 6px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav {
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
a {
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.nav-tabs {
|
||||||
|
border: none;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
border: none;
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-bottom: 2px solid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user