mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
Merge pull request #142 from WithoutPants/performer_list_view
Add performer list view.
This commit is contained in:
@@ -57,7 +57,6 @@ export const Stats: FunctionComponent = () => {
|
|||||||
* Filters for performers and studios only supports one item, even though it's a multi select.
|
* Filters for performers and studios only supports one item, even though it's a multi select.
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
* List view for scenes / performers
|
|
||||||
* Websocket connection to display logs in the UI
|
* Websocket connection to display logs in the UI
|
||||||
`}
|
`}
|
||||||
</pre>
|
</pre>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { IBaseProps } from "../../models/base-props";
|
|||||||
import { ListFilterModel } from "../../models/list-filter/filter";
|
import { ListFilterModel } from "../../models/list-filter/filter";
|
||||||
import { DisplayMode, FilterMode } from "../../models/list-filter/types";
|
import { DisplayMode, FilterMode } from "../../models/list-filter/types";
|
||||||
import { PerformerCard } from "./PerformerCard";
|
import { PerformerCard } from "./PerformerCard";
|
||||||
|
import { PerformerListTable } from "./PerformerListTable";
|
||||||
|
|
||||||
interface IPerformerListProps extends IBaseProps {}
|
interface IPerformerListProps extends IBaseProps {}
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ export const PerformerList: FunctionComponent<IPerformerListProps> = (props: IPe
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (filter.displayMode === DisplayMode.List) {
|
} else if (filter.displayMode === DisplayMode.List) {
|
||||||
return <h1>TODO</h1>;
|
return <PerformerListTable performers={result.data.findPerformers.performers}/>;
|
||||||
} else if (filter.displayMode === DisplayMode.Wall) {
|
} else if (filter.displayMode === DisplayMode.Wall) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
107
ui/v2/src/components/performers/PerformerListTable.tsx
Normal file
107
ui/v2/src/components/performers/PerformerListTable.tsx
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import {
|
||||||
|
HTMLTable,
|
||||||
|
H5,
|
||||||
|
H6,
|
||||||
|
Button,
|
||||||
|
} from "@blueprintjs/core";
|
||||||
|
import React, { FunctionComponent } from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import * as GQL from "../../core/generated-graphql";
|
||||||
|
import { NavigationUtils } from "../../utils/navigation";
|
||||||
|
|
||||||
|
interface IPerformerListTableProps {
|
||||||
|
performers: GQL.PerformerDataFragment[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PerformerListTable: FunctionComponent<IPerformerListTableProps> = (props: IPerformerListTableProps) => {
|
||||||
|
|
||||||
|
function maybeRenderFavoriteHeart(performer : GQL.PerformerDataFragment) {
|
||||||
|
if (!performer.favorite) { return; }
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
icon="heart"
|
||||||
|
disabled={true}
|
||||||
|
className="favorite"
|
||||||
|
minimal={true}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
className="performer-list-thumbnail"
|
||||||
|
to={`/performers/${performer.id}`}
|
||||||
|
style={style}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPerformerRow(performer : GQL.PerformerDataFragment) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{renderPerformerImage(performer)}
|
||||||
|
</td>
|
||||||
|
<td style={{textAlign: "left"}}>
|
||||||
|
<Link to={`/performers/${performer.id}`}>
|
||||||
|
<H5 style={{textOverflow: "ellipsis", overflow: "hidden"}}>
|
||||||
|
{performer.name}
|
||||||
|
</H5>
|
||||||
|
</Link>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{performer.aliases ? performer.aliases : ''}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{maybeRenderFavoriteHeart(performer)}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Link to={NavigationUtils.makePerformerScenesUrl(performer)}>
|
||||||
|
<H6>{performer.scene_count}</H6>
|
||||||
|
</Link>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{performer.birthdate}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{performer.height}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="grid">
|
||||||
|
<HTMLTable>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Aliases</th>
|
||||||
|
<th>Favourite</th>
|
||||||
|
<th>Scene Count</th>
|
||||||
|
<th>Birthdate</th>
|
||||||
|
<th>Height</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{props.performers.map(renderPerformerRow)}
|
||||||
|
</tbody>
|
||||||
|
</HTMLTable>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
H4,
|
|
||||||
HTMLTable,
|
HTMLTable,
|
||||||
H5,
|
H5,
|
||||||
H6,
|
H6,
|
||||||
@@ -8,7 +7,6 @@ import {
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import * as GQL from "../../core/generated-graphql";
|
import * as GQL from "../../core/generated-graphql";
|
||||||
import { TextUtils } from "../../utils/text";
|
import { TextUtils } from "../../utils/text";
|
||||||
import { TagLink } from "../Shared/TagLink";
|
|
||||||
import { NavigationUtils } from "../../utils/navigation";
|
import { NavigationUtils } from "../../utils/navigation";
|
||||||
|
|
||||||
interface ISceneListTableProps {
|
interface ISceneListTableProps {
|
||||||
@@ -17,6 +15,24 @@ import { NavigationUtils } from "../../utils/navigation";
|
|||||||
|
|
||||||
export const SceneListTable: FunctionComponent<ISceneListTableProps> = (props: ISceneListTableProps) => {
|
export const SceneListTable: FunctionComponent<ISceneListTableProps> = (props: ISceneListTableProps) => {
|
||||||
|
|
||||||
|
function renderSceneImage(scene : GQL.SlimSceneDataFragment) {
|
||||||
|
const style: React.CSSProperties = {
|
||||||
|
backgroundImage: `url('${scene.paths.screenshot}')`,
|
||||||
|
lineHeight: 5,
|
||||||
|
backgroundSize: "contain",
|
||||||
|
display: "inline-block",
|
||||||
|
backgroundPosition: "center",
|
||||||
|
backgroundRepeat: "no-repeat",
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
className="scene-list-thumbnail"
|
||||||
|
to={`/performers/${scene.id}`}
|
||||||
|
style={style}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function renderDuration(scene : GQL.SlimSceneDataFragment) {
|
function renderDuration(scene : GQL.SlimSceneDataFragment) {
|
||||||
if (scene.file.duration === undefined) { return; }
|
if (scene.file.duration === undefined) { return; }
|
||||||
return TextUtils.secondsToTimestamp(scene.file.duration);
|
return TextUtils.secondsToTimestamp(scene.file.duration);
|
||||||
@@ -53,6 +69,9 @@ import { NavigationUtils } from "../../utils/navigation";
|
|||||||
<>
|
<>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
{renderSceneImage(scene)}
|
||||||
|
</td>
|
||||||
|
<td style={{textAlign: "left"}}>
|
||||||
<Link to={`/scenes/${scene.id}`}>
|
<Link to={`/scenes/${scene.id}`}>
|
||||||
<H5 style={{textOverflow: "ellipsis", overflow: "hidden"}}>
|
<H5 style={{textOverflow: "ellipsis", overflow: "hidden"}}>
|
||||||
{!!scene.title ? scene.title : TextUtils.fileNameFromPath(scene.path)}
|
{!!scene.title ? scene.title : TextUtils.fileNameFromPath(scene.path)}
|
||||||
@@ -85,6 +104,7 @@ import { NavigationUtils } from "../../utils/navigation";
|
|||||||
<HTMLTable>
|
<HTMLTable>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th></th>
|
||||||
<th>Title</th>
|
<th>Title</th>
|
||||||
<th>Rating</th>
|
<th>Rating</th>
|
||||||
<th>Duration</th>
|
<th>Duration</th>
|
||||||
|
|||||||
@@ -44,6 +44,25 @@ code {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& .bp3-button.favorite .bp3-icon {
|
||||||
|
color: #ff7373 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
& .performer-list-thumbnail {
|
||||||
|
min-width: 50px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .scene-list-thumbnail {
|
||||||
|
width: 150px;
|
||||||
|
min-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& table td {
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-item {
|
.grid-item {
|
||||||
|
|||||||
Reference in New Issue
Block a user