mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 20:34:37 +03:00
Show counts on entity list tabs (#2169)
This commit is contained in:
committed by
GitHub
parent
849c590b2a
commit
90a4931bdc
@@ -1,3 +1,6 @@
|
|||||||
|
### 🎨 Improvements
|
||||||
|
Show counts on list tabs in Performer, Studio and Tag pages. ([#2169](https://github.com/stashapp/stash/pull/2169))
|
||||||
|
|
||||||
### 🐛 Bug fixes
|
### 🐛 Bug fixes
|
||||||
* Generate sprites for short video files. ([#2167](https://github.com/stashapp/stash/pull/2167))
|
* Generate sprites for short video files. ([#2167](https://github.com/stashapp/stash/pull/2167))
|
||||||
* Fix stash-box scraping including underscores in ethnicity. ([#2191](https://github.com/stashapp/stash/pull/2191))
|
* Fix stash-box scraping including underscores in ethnicity. ([#2191](https://github.com/stashapp/stash/pull/2191))
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useMemo, useState } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { Button, Tabs, Tab } from "react-bootstrap";
|
import { Button, Tabs, Tab, Badge } from "react-bootstrap";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
import { useParams, useHistory } from "react-router-dom";
|
import { useParams, useHistory } from "react-router-dom";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
@@ -147,16 +147,56 @@ const PerformerPage: React.FC<IProps> = ({ performer }) => {
|
|||||||
<Tab eventKey="details" title={intl.formatMessage({ id: "details" })}>
|
<Tab eventKey="details" title={intl.formatMessage({ id: "details" })}>
|
||||||
<PerformerDetailsPanel performer={performer} />
|
<PerformerDetailsPanel performer={performer} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="scenes" title={intl.formatMessage({ id: "scenes" })}>
|
<Tab
|
||||||
|
eventKey="scenes"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "scenes" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(performer.scene_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<PerformerScenesPanel performer={performer} />
|
<PerformerScenesPanel performer={performer} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="galleries" title={intl.formatMessage({ id: "galleries" })}>
|
<Tab
|
||||||
|
eventKey="galleries"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "galleries" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(performer.gallery_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<PerformerGalleriesPanel performer={performer} />
|
<PerformerGalleriesPanel performer={performer} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="images" title={intl.formatMessage({ id: "images" })}>
|
<Tab
|
||||||
|
eventKey="images"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "images" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(performer.image_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<PerformerImagesPanel performer={performer} />
|
<PerformerImagesPanel performer={performer} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="movies" title={intl.formatMessage({ id: "movies" })}>
|
<Tab
|
||||||
|
eventKey="movies"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "movies" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(performer.movie_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<PerformerMoviesPanel performer={performer} />
|
<PerformerMoviesPanel performer={performer} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="edit" title={intl.formatMessage({ id: "actions.edit" })}>
|
<Tab eventKey="edit" title={intl.formatMessage({ id: "actions.edit" })}>
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export const SettingsServicesPanel: React.FC = () => {
|
|||||||
function renderDeadline(until?: string) {
|
function renderDeadline(until?: string) {
|
||||||
if (until) {
|
if (until) {
|
||||||
const deadline = new Date(until);
|
const deadline = new Date(until);
|
||||||
return `until ${deadline.toLocaleString()}`;
|
return `until ${intl.formatDate(deadline)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Tabs, Tab } from "react-bootstrap";
|
import { Tabs, Tab, Badge } from "react-bootstrap";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useParams, useHistory } from "react-router-dom";
|
import { useParams, useHistory } from "react-router-dom";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
@@ -216,16 +216,43 @@ const StudioPage: React.FC<IProps> = ({ studio }) => {
|
|||||||
activeKey={activeTabKey}
|
activeKey={activeTabKey}
|
||||||
onSelect={setActiveTabKey}
|
onSelect={setActiveTabKey}
|
||||||
>
|
>
|
||||||
<Tab eventKey="scenes" title={intl.formatMessage({ id: "scenes" })}>
|
<Tab
|
||||||
|
eventKey="scenes"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "scenes" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(studio.scene_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<StudioScenesPanel studio={studio} />
|
<StudioScenesPanel studio={studio} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
eventKey="galleries"
|
eventKey="galleries"
|
||||||
title={intl.formatMessage({ id: "galleries" })}
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "galleries" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(studio.gallery_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<StudioGalleriesPanel studio={studio} />
|
<StudioGalleriesPanel studio={studio} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="images" title={intl.formatMessage({ id: "images" })}>
|
<Tab
|
||||||
|
eventKey="images"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "images" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(studio.image_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<StudioImagesPanel studio={studio} />
|
<StudioImagesPanel studio={studio} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
@@ -234,12 +261,29 @@ const StudioPage: React.FC<IProps> = ({ studio }) => {
|
|||||||
>
|
>
|
||||||
<StudioPerformersPanel studio={studio} />
|
<StudioPerformersPanel studio={studio} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="movies" title={intl.formatMessage({ id: "movies" })}>
|
<Tab
|
||||||
|
eventKey="movies"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "movies" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(studio.movie_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<StudioMoviesPanel studio={studio} />
|
<StudioMoviesPanel studio={studio} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
eventKey="childstudios"
|
eventKey="childstudios"
|
||||||
title={intl.formatMessage({ id: "subsidiary_studios" })}
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "subsidiary_studios" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(studio.child_studios?.length)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<StudioChildrenPanel studio={studio} />
|
<StudioChildrenPanel studio={studio} />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Tabs, Tab, Dropdown } from "react-bootstrap";
|
import { Tabs, Tab, Dropdown, Badge } from "react-bootstrap";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useParams, useHistory } from "react-router-dom";
|
import { useParams, useHistory } from "react-router-dom";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
@@ -297,27 +297,68 @@ const TagPage: React.FC<IProps> = ({ tag }) => {
|
|||||||
activeKey={activeTabKey}
|
activeKey={activeTabKey}
|
||||||
onSelect={setActiveTabKey}
|
onSelect={setActiveTabKey}
|
||||||
>
|
>
|
||||||
<Tab eventKey="scenes" title={intl.formatMessage({ id: "scenes" })}>
|
<Tab
|
||||||
|
eventKey="scenes"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "scenes" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(tag.scene_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<TagScenesPanel tag={tag} />
|
<TagScenesPanel tag={tag} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab eventKey="images" title={intl.formatMessage({ id: "images" })}>
|
<Tab
|
||||||
|
eventKey="images"
|
||||||
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "images" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(tag.image_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
>
|
||||||
<TagImagesPanel tag={tag} />
|
<TagImagesPanel tag={tag} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
eventKey="galleries"
|
eventKey="galleries"
|
||||||
title={intl.formatMessage({ id: "galleries" })}
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "galleries" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(tag.gallery_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<TagGalleriesPanel tag={tag} />
|
<TagGalleriesPanel tag={tag} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
eventKey="markers"
|
eventKey="markers"
|
||||||
title={intl.formatMessage({ id: "markers" })}
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "markers" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(tag.scene_marker_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<TagMarkersPanel tag={tag} />
|
<TagMarkersPanel tag={tag} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
eventKey="performers"
|
eventKey="performers"
|
||||||
title={intl.formatMessage({ id: "performers" })}
|
title={
|
||||||
|
<React.Fragment>
|
||||||
|
{intl.formatMessage({ id: "performers" })}
|
||||||
|
<Badge className="left-spacing" pill variant="secondary">
|
||||||
|
{intl.formatNumber(tag.performer_count ?? 0)}
|
||||||
|
</Badge>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<TagPerformersPanel tag={tag} />
|
<TagPerformersPanel tag={tag} />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|||||||
@@ -752,3 +752,7 @@ select {
|
|||||||
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4.95 10' fill='%23fff'><polygon points='1.41 4.67 2.48 3.18 3.54 4.67 1.41 4.67'/><polygon points='3.54 5.33 2.48 6.82 1.41 5.33 3.54 5.33'/></svg>")
|
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4.95 10' fill='%23fff'><polygon points='1.41 4.67 2.48 3.18 3.54 4.67 1.41 4.67'/><polygon points='3.54 5.33 2.48 6.82 1.41 5.33 3.54 5.33'/></svg>")
|
||||||
no-repeat right 2px center;
|
no-repeat right 2px center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.left-spacing {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user