mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
fix(frontend): more issues-related fixes (#2234)
* fix(frontend): more issues-related fixes * fix: permission VIEW_ISSUES is also sufficient for viewing issues in slideover * fix(frontend): only display issue notif types user is eligible to receive * fix: don't display issues block in slideover if no open issues * fix: move year out of link in issue details header * fix: use 'view' global string for issue block button * fix: issue/request/user list sort options
This commit is contained in:
@@ -13,7 +13,7 @@ const Badge: React.FC<BadgeProps> = ({
|
||||
children,
|
||||
}) => {
|
||||
const badgeStyle = [
|
||||
'px-2 inline-flex text-xs leading-5 font-semibold rounded-full',
|
||||
'px-2 inline-flex text-xs leading-5 font-semibold rounded-full whitespace-nowrap',
|
||||
];
|
||||
|
||||
if (url) {
|
||||
|
@@ -8,6 +8,7 @@ import Link from 'next/link';
|
||||
import React from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import type Issue from '../../../server/entity/Issue';
|
||||
import globalMessages from '../../i18n/globalMessages';
|
||||
import Button from '../Common/Button';
|
||||
import { issueOptions } from '../IssueModal/constants';
|
||||
|
||||
@@ -56,7 +57,7 @@ const IssueBlock: React.FC<IssueBlockProps> = ({ issue }) => {
|
||||
<Link href={`/issues/${issue.id}`} passHref>
|
||||
<Button buttonType="primary" buttonSize="sm" as="a">
|
||||
<EyeIcon />
|
||||
<span>View</span>
|
||||
<span>{intl.formatMessage(globalMessages.view)}</span>
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
@@ -44,7 +44,7 @@ const messages = defineMessages({
|
||||
reopenissueandcomment: 'Reopen with Comment',
|
||||
issuepagetitle: 'Issue',
|
||||
playonplex: 'Play on Plex',
|
||||
play4konplex: 'Play 4K on Plex',
|
||||
play4konplex: 'Play in 4K on Plex',
|
||||
openinarr: 'Open in {arr}',
|
||||
openin4karr: 'Open in 4K {arr}',
|
||||
toasteditdescriptionsuccess: 'Issue description edited successfully!',
|
||||
@@ -228,7 +228,7 @@ const IssueDetails: React.FC = () => {
|
||||
<div className="media-title">
|
||||
<div className="media-status">
|
||||
{issueData.status === IssueStatus.OPEN && (
|
||||
<Badge badgeType="primary">
|
||||
<Badge badgeType="warning">
|
||||
{intl.formatMessage(globalMessages.open)}
|
||||
</Badge>
|
||||
)}
|
||||
@@ -244,15 +244,11 @@ const IssueDetails: React.FC = () => {
|
||||
issueData.media.mediaType === MediaType.MOVIE ? 'movie' : 'tv'
|
||||
}/${data.id}`}
|
||||
>
|
||||
<a className="hover:underline">
|
||||
{title}{' '}
|
||||
<a className="hover:underline">{title}</a>
|
||||
</Link>{' '}
|
||||
{releaseYear && (
|
||||
<span className="media-year">
|
||||
({releaseYear.slice(0, 4)})
|
||||
</span>
|
||||
<span className="media-year">({releaseYear.slice(0, 4)})</span>
|
||||
)}
|
||||
</a>
|
||||
</Link>
|
||||
</h1>
|
||||
<span className="media-attributes">
|
||||
{intl.formatMessage(messages.openedby, {
|
||||
|
@@ -183,7 +183,7 @@ const IssueItem: React.FC<IssueItemProps> = ({ issue }) => {
|
||||
{intl.formatMessage(messages.issuestatus)}
|
||||
</span>
|
||||
{issue.status === IssueStatus.OPEN ? (
|
||||
<Badge badgeType="primary">
|
||||
<Badge badgeType="warning">
|
||||
{intl.formatMessage(globalMessages.open)}
|
||||
</Badge>
|
||||
) : (
|
||||
|
@@ -19,7 +19,7 @@ import IssueItem from './IssueItem';
|
||||
|
||||
const messages = defineMessages({
|
||||
issues: 'Issues',
|
||||
sortAdded: 'Request Date',
|
||||
sortAdded: 'Most Recent',
|
||||
sortModified: 'Last Modified',
|
||||
showallissues: 'Show All Issues',
|
||||
});
|
||||
|
@@ -9,9 +9,12 @@ import { defineMessages, useIntl } from 'react-intl';
|
||||
import { useToasts } from 'react-toast-notifications';
|
||||
import useSWR from 'swr';
|
||||
import * as Yup from 'yup';
|
||||
import { MediaStatus } from '../../../../server/constants/media';
|
||||
import type Issue from '../../../../server/entity/Issue';
|
||||
import { MovieDetails } from '../../../../server/models/Movie';
|
||||
import { TvDetails } from '../../../../server/models/Tv';
|
||||
import useSettings from '../../../hooks/useSettings';
|
||||
import { Permission, useUser } from '../../../hooks/useUser';
|
||||
import globalMessages from '../../../i18n/globalMessages';
|
||||
import Button from '../../Common/Button';
|
||||
import Modal from '../../Common/Modal';
|
||||
@@ -21,7 +24,9 @@ const messages = defineMessages({
|
||||
validationMessageRequired: 'You must provide a description',
|
||||
issomethingwrong: 'Is there a problem with {title}?',
|
||||
whatswrong: "What's wrong?",
|
||||
providedetail: 'Provide a detailed explanation of the issue.',
|
||||
providedetail:
|
||||
'Please provide a detailed explanation of the issue you encountered.',
|
||||
extras: 'Extras',
|
||||
season: 'Season {seasonNumber}',
|
||||
episode: 'Episode {episodeNumber}',
|
||||
allseasons: 'All Seasons',
|
||||
@@ -56,6 +61,8 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
|
||||
tmdbId,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const settings = useSettings();
|
||||
const { hasPermission } = useUser();
|
||||
const { addToast } = useToasts();
|
||||
const { data, error } = useSWR<MovieDetails | TvDetails>(
|
||||
tmdbId ? `/api/v1/${mediaType}/${tmdbId}` : null
|
||||
@@ -65,6 +72,20 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
const availableSeasons = (data?.mediaInfo?.seasons ?? [])
|
||||
.filter(
|
||||
(season) =>
|
||||
season.status === MediaStatus.AVAILABLE ||
|
||||
season.status === MediaStatus.PARTIALLY_AVAILABLE ||
|
||||
(settings.currentSettings.series4kEnabled &&
|
||||
hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], {
|
||||
type: 'or',
|
||||
}) &&
|
||||
(season.status4k === MediaStatus.AVAILABLE ||
|
||||
season.status4k === MediaStatus.PARTIALLY_AVAILABLE))
|
||||
)
|
||||
.map((season) => season.seasonNumber);
|
||||
|
||||
const CreateIssueModalSchema = Yup.object().shape({
|
||||
message: Yup.string().required(
|
||||
intl.formatMessage(messages.validationMessageRequired)
|
||||
@@ -76,7 +97,7 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
|
||||
initialValues={{
|
||||
selectedIssue: issueOptions[0],
|
||||
message: '',
|
||||
problemSeason: 0,
|
||||
problemSeason: availableSeasons.length === 1 ? availableSeasons[0] : 0,
|
||||
problemEpisode: 0,
|
||||
}}
|
||||
validationSchema={CreateIssueModalSchema}
|
||||
@@ -162,17 +183,22 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
|
||||
as="select"
|
||||
id="problemSeason"
|
||||
name="problemSeason"
|
||||
disabled={availableSeasons.length === 1}
|
||||
>
|
||||
{availableSeasons.length > 1 && (
|
||||
<option value={0}>
|
||||
{intl.formatMessage(messages.allseasons)}
|
||||
</option>
|
||||
{data.seasons.map((season) => (
|
||||
)}
|
||||
{availableSeasons.map((season) => (
|
||||
<option
|
||||
value={season.seasonNumber}
|
||||
key={`problem-season-${season.seasonNumber}`}
|
||||
value={season}
|
||||
key={`problem-season-${season}`}
|
||||
>
|
||||
{intl.formatMessage(messages.season, {
|
||||
seasonNumber: season.seasonNumber,
|
||||
{season === 0
|
||||
? intl.formatMessage(messages.extras)
|
||||
: intl.formatMessage(messages.season, {
|
||||
seasonNumber: season,
|
||||
})}
|
||||
</option>
|
||||
))}
|
||||
|
@@ -19,6 +19,7 @@ import RequestBlock from '../RequestBlock';
|
||||
|
||||
const messages = defineMessages({
|
||||
manageModalTitle: 'Manage {mediaType}',
|
||||
manageModalIssues: 'Open Issues',
|
||||
manageModalRequests: 'Requests',
|
||||
manageModalNoRequests: 'No requests.',
|
||||
manageModalClearMedia: 'Clear Media Data',
|
||||
@@ -77,6 +78,11 @@ const ManageSlideOver: React.FC<
|
||||
revalidate();
|
||||
};
|
||||
|
||||
const openIssues =
|
||||
data.mediaInfo?.issues?.filter(
|
||||
(issue) => issue.status === IssueStatus.OPEN
|
||||
) ?? [];
|
||||
|
||||
return (
|
||||
<SlideOver
|
||||
show={show}
|
||||
@@ -155,14 +161,17 @@ const ManageSlideOver: React.FC<
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{(data.mediaInfo?.issues ?? []).length > 0 && (
|
||||
{hasPermission([Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES], {
|
||||
type: 'or',
|
||||
}) &&
|
||||
openIssues.length > 0 && (
|
||||
<>
|
||||
<h3 className="mb-2 text-xl">Open Issues</h3>
|
||||
<h3 className="mb-2 text-xl">
|
||||
{intl.formatMessage(messages.manageModalIssues)}
|
||||
</h3>
|
||||
<div className="mb-4 overflow-hidden bg-gray-600 rounded-md shadow">
|
||||
<ul>
|
||||
{data.mediaInfo?.issues
|
||||
?.filter((issue) => issue.status === IssueStatus.OPEN)
|
||||
.map((issue) => (
|
||||
{openIssues.map((issue) => (
|
||||
<li
|
||||
key={`manage-issue-${issue.id}`}
|
||||
className="border-b border-gray-700 last:border-b-0"
|
||||
|
@@ -330,7 +330,14 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
|
||||
onUpdate={() => revalidate()}
|
||||
/>
|
||||
{(data.mediaInfo?.status === MediaStatus.AVAILABLE ||
|
||||
data.mediaInfo?.status4k === MediaStatus.AVAILABLE) &&
|
||||
(settings.currentSettings.movie4kEnabled &&
|
||||
hasPermission(
|
||||
[Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE],
|
||||
{
|
||||
type: 'or',
|
||||
}
|
||||
) &&
|
||||
data.mediaInfo?.status4k === MediaStatus.AVAILABLE)) &&
|
||||
hasPermission(
|
||||
[Permission.CREATE_ISSUES, Permission.MANAGE_ISSUES],
|
||||
{
|
||||
@@ -338,7 +345,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
|
||||
}
|
||||
) && (
|
||||
<Button
|
||||
buttonType="danger"
|
||||
buttonType="warning"
|
||||
className="ml-2 first:ml-0"
|
||||
onClick={() => setShowIssueModal(true)}
|
||||
>
|
||||
@@ -348,11 +355,17 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
|
||||
{hasPermission(Permission.MANAGE_REQUESTS) && (
|
||||
<Button
|
||||
buttonType="default"
|
||||
className="ml-2 first:ml-0"
|
||||
className="relative ml-2 first:ml-0"
|
||||
onClick={() => setShowManager(true)}
|
||||
>
|
||||
<CogIcon className="!mr-0" />
|
||||
{(
|
||||
{hasPermission(
|
||||
[Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
|
||||
{
|
||||
type: 'or',
|
||||
}
|
||||
) &&
|
||||
(
|
||||
data.mediaInfo?.issues.filter(
|
||||
(issue) => issue.status === IssueStatus.OPEN
|
||||
) ?? []
|
||||
|
@@ -274,6 +274,11 @@ const NotificationTypeSelector: React.FC<NotificationTypeSelectorProps> = ({
|
||||
: messages.issuecommentDescription
|
||||
),
|
||||
value: Notification.ISSUE_COMMENT,
|
||||
hidden:
|
||||
user &&
|
||||
!hasPermission([Permission.MANAGE_ISSUES, Permission.CREATE_ISSUES], {
|
||||
type: 'or',
|
||||
}),
|
||||
hasNotifyUser:
|
||||
!user || hasPermission(Permission.MANAGE_ISSUES) ? false : true,
|
||||
},
|
||||
@@ -286,6 +291,11 @@ const NotificationTypeSelector: React.FC<NotificationTypeSelectorProps> = ({
|
||||
: messages.issueresolvedDescription
|
||||
),
|
||||
value: Notification.ISSUE_RESOLVED,
|
||||
hidden:
|
||||
user &&
|
||||
!hasPermission([Permission.MANAGE_ISSUES, Permission.CREATE_ISSUES], {
|
||||
type: 'or',
|
||||
}),
|
||||
hasNotifyUser: true,
|
||||
},
|
||||
];
|
||||
|
@@ -22,7 +22,7 @@ import RequestItem from './RequestItem';
|
||||
const messages = defineMessages({
|
||||
requests: 'Requests',
|
||||
showallrequests: 'Show All Requests',
|
||||
sortAdded: 'Request Date',
|
||||
sortAdded: 'Most Recent',
|
||||
sortModified: 'Last Modified',
|
||||
});
|
||||
|
||||
|
@@ -331,9 +331,14 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
|
||||
is4kShowComplete={is4kComplete}
|
||||
/>
|
||||
{(data.mediaInfo?.status === MediaStatus.AVAILABLE ||
|
||||
data.mediaInfo?.status4k === MediaStatus.AVAILABLE ||
|
||||
data.mediaInfo?.status === MediaStatus.PARTIALLY_AVAILABLE ||
|
||||
data?.mediaInfo?.status4k === MediaStatus.PARTIALLY_AVAILABLE) &&
|
||||
(settings.currentSettings.series4kEnabled &&
|
||||
hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], {
|
||||
type: 'or',
|
||||
}) &&
|
||||
(data.mediaInfo?.status4k === MediaStatus.AVAILABLE ||
|
||||
data?.mediaInfo?.status4k ===
|
||||
MediaStatus.PARTIALLY_AVAILABLE))) &&
|
||||
hasPermission(
|
||||
[Permission.CREATE_ISSUES, Permission.MANAGE_ISSUES],
|
||||
{
|
||||
@@ -341,7 +346,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
|
||||
}
|
||||
) && (
|
||||
<Button
|
||||
buttonType="danger"
|
||||
buttonType="warning"
|
||||
className="ml-2 first:ml-0"
|
||||
onClick={() => setShowIssueModal(true)}
|
||||
>
|
||||
@@ -351,11 +356,17 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
|
||||
{hasPermission(Permission.MANAGE_REQUESTS) && (
|
||||
<Button
|
||||
buttonType="default"
|
||||
className="ml-2 first:ml-0"
|
||||
className="relative ml-2 first:ml-0"
|
||||
onClick={() => setShowManager(true)}
|
||||
>
|
||||
<CogIcon className="!mr-0" />
|
||||
{(
|
||||
{hasPermission(
|
||||
[Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
|
||||
{
|
||||
type: 'or',
|
||||
}
|
||||
) &&
|
||||
(
|
||||
data.mediaInfo?.issues.filter(
|
||||
(issue) => issue.status === IssueStatus.OPEN
|
||||
) ?? []
|
||||
|
@@ -46,8 +46,7 @@ const messages = defineMessages({
|
||||
totalrequests: 'Requests',
|
||||
accounttype: 'Type',
|
||||
role: 'Role',
|
||||
created: 'Created',
|
||||
lastupdated: 'Updated',
|
||||
created: 'Joined',
|
||||
bulkedit: 'Bulk Edit',
|
||||
owner: 'Owner',
|
||||
admin: 'Admin',
|
||||
@@ -75,8 +74,7 @@ const messages = defineMessages({
|
||||
autogeneratepassword: 'Automatically Generate Password',
|
||||
autogeneratepasswordTip: 'Email a server-generated password to the user',
|
||||
validationEmail: 'You must provide a valid email address',
|
||||
sortCreated: 'Creation Date',
|
||||
sortUpdated: 'Last Updated',
|
||||
sortCreated: 'Join Date',
|
||||
sortDisplayName: 'Display Name',
|
||||
sortRequests: 'Request Count',
|
||||
localLoginDisabled:
|
||||
@@ -91,7 +89,7 @@ const UserList: React.FC = () => {
|
||||
const settings = useSettings();
|
||||
const { addToast } = useToasts();
|
||||
const { user: currentUser, hasPermission: currentHasPermission } = useUser();
|
||||
const [currentSort, setCurrentSort] = useState<Sort>('created');
|
||||
const [currentSort, setCurrentSort] = useState<Sort>('displayname');
|
||||
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
|
||||
|
||||
const page = router.query.page ? Number(router.query.page) : 1;
|
||||
@@ -522,9 +520,6 @@ const UserList: React.FC = () => {
|
||||
<option value="created">
|
||||
{intl.formatMessage(messages.sortCreated)}
|
||||
</option>
|
||||
<option value="updated">
|
||||
{intl.formatMessage(messages.sortUpdated)}
|
||||
</option>
|
||||
<option value="requests">
|
||||
{intl.formatMessage(messages.sortRequests)}
|
||||
</option>
|
||||
@@ -556,7 +551,6 @@ const UserList: React.FC = () => {
|
||||
<Table.TH>{intl.formatMessage(messages.accounttype)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.role)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.created)}</Table.TH>
|
||||
<Table.TH>{intl.formatMessage(messages.lastupdated)}</Table.TH>
|
||||
<Table.TH className="text-right">
|
||||
{(data.results ?? []).length > 1 && (
|
||||
<Button
|
||||
@@ -652,13 +646,6 @@ const UserList: React.FC = () => {
|
||||
day: 'numeric',
|
||||
})}
|
||||
</Table.TD>
|
||||
<Table.TD>
|
||||
{intl.formatDate(user.updatedAt, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
})}
|
||||
</Table.TD>
|
||||
<Table.TD alignText="right">
|
||||
<Button
|
||||
buttonType="warning"
|
||||
|
@@ -57,7 +57,7 @@
|
||||
"components.IssueDetails.openedby": "#{issueId} opened {relativeTime} by {username}",
|
||||
"components.IssueDetails.openin4karr": "Open in 4K {arr}",
|
||||
"components.IssueDetails.openinarr": "Open in {arr}",
|
||||
"components.IssueDetails.play4konplex": "Play 4K on Plex",
|
||||
"components.IssueDetails.play4konplex": "Play in 4K on Plex",
|
||||
"components.IssueDetails.playonplex": "Play on Plex",
|
||||
"components.IssueDetails.problemepisode": "Affected Episode",
|
||||
"components.IssueDetails.problemseason": "Affected Season",
|
||||
@@ -82,15 +82,16 @@
|
||||
"components.IssueList.IssueItem.viewissue": "View Issue",
|
||||
"components.IssueList.issues": "Issues",
|
||||
"components.IssueList.showallissues": "Show All Issues",
|
||||
"components.IssueList.sortAdded": "Request Date",
|
||||
"components.IssueList.sortAdded": "Most Recent",
|
||||
"components.IssueList.sortModified": "Last Modified",
|
||||
"components.IssueModal.CreateIssueModal.allepisodes": "All Episodes",
|
||||
"components.IssueModal.CreateIssueModal.allseasons": "All Seasons",
|
||||
"components.IssueModal.CreateIssueModal.episode": "Episode {episodeNumber}",
|
||||
"components.IssueModal.CreateIssueModal.extras": "Extras",
|
||||
"components.IssueModal.CreateIssueModal.issomethingwrong": "Is there a problem with {title}?",
|
||||
"components.IssueModal.CreateIssueModal.problemepisode": "Affected Episode",
|
||||
"components.IssueModal.CreateIssueModal.problemseason": "Affected Season",
|
||||
"components.IssueModal.CreateIssueModal.providedetail": "Provide a detailed explanation of the issue.",
|
||||
"components.IssueModal.CreateIssueModal.providedetail": "Please provide a detailed explanation of the issue you encountered.",
|
||||
"components.IssueModal.CreateIssueModal.reportissue": "Report an Issue",
|
||||
"components.IssueModal.CreateIssueModal.season": "Season {seasonNumber}",
|
||||
"components.IssueModal.CreateIssueModal.submitissue": "Submit Issue",
|
||||
@@ -134,6 +135,7 @@
|
||||
"components.ManageSlideOver.downloadstatus": "Download Status",
|
||||
"components.ManageSlideOver.manageModalClearMedia": "Clear Media Data",
|
||||
"components.ManageSlideOver.manageModalClearMediaWarning": "* This will irreversibly remove all data for this {mediaType}, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.",
|
||||
"components.ManageSlideOver.manageModalIssues": "Open Issues",
|
||||
"components.ManageSlideOver.manageModalNoRequests": "No requests.",
|
||||
"components.ManageSlideOver.manageModalRequests": "Requests",
|
||||
"components.ManageSlideOver.manageModalTitle": "Manage {mediaType}",
|
||||
@@ -287,7 +289,7 @@
|
||||
"components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Season} other {Seasons}}",
|
||||
"components.RequestList.requests": "Requests",
|
||||
"components.RequestList.showallrequests": "Show All Requests",
|
||||
"components.RequestList.sortAdded": "Request Date",
|
||||
"components.RequestList.sortAdded": "Most Recent",
|
||||
"components.RequestList.sortModified": "Last Modified",
|
||||
"components.RequestModal.AdvancedRequester.advancedoptions": "Advanced",
|
||||
"components.RequestModal.AdvancedRequester.animenote": "* This series is an anime.",
|
||||
@@ -799,7 +801,7 @@
|
||||
"components.UserList.autogeneratepasswordTip": "Email a server-generated password to the user",
|
||||
"components.UserList.bulkedit": "Bulk Edit",
|
||||
"components.UserList.create": "Create",
|
||||
"components.UserList.created": "Created",
|
||||
"components.UserList.created": "Joined",
|
||||
"components.UserList.createlocaluser": "Create Local User",
|
||||
"components.UserList.creating": "Creating…",
|
||||
"components.UserList.deleteconfirm": "Are you sure you want to delete this user? All of their request data will be permanently removed.",
|
||||
@@ -810,7 +812,6 @@
|
||||
"components.UserList.importedfromplex": "{userCount, plural, one {# new user} other {# new users}} imported from Plex successfully!",
|
||||
"components.UserList.importfromplex": "Import Users from Plex",
|
||||
"components.UserList.importfromplexerror": "Something went wrong while importing users from Plex.",
|
||||
"components.UserList.lastupdated": "Updated",
|
||||
"components.UserList.localLoginDisabled": "The <strong>Enable Local Sign-In</strong> setting is currently disabled.",
|
||||
"components.UserList.localuser": "Local User",
|
||||
"components.UserList.nouserstoimport": "No new users to import from Plex.",
|
||||
@@ -819,10 +820,9 @@
|
||||
"components.UserList.passwordinfodescription": "Configure an application URL and enable email notifications to allow automatic password generation.",
|
||||
"components.UserList.plexuser": "Plex User",
|
||||
"components.UserList.role": "Role",
|
||||
"components.UserList.sortCreated": "Creation Date",
|
||||
"components.UserList.sortCreated": "Join Date",
|
||||
"components.UserList.sortDisplayName": "Display Name",
|
||||
"components.UserList.sortRequests": "Request Count",
|
||||
"components.UserList.sortUpdated": "Last Updated",
|
||||
"components.UserList.totalrequests": "Requests",
|
||||
"components.UserList.user": "User",
|
||||
"components.UserList.usercreatedfailed": "Something went wrong while creating the user.",
|
||||
|
Reference in New Issue
Block a user