mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
fix: better ordering of RequestButton options & properly handle failed requests (#2944)
* fix: better ordering of RequestButton options & properly handle failed requests * fix: appease prettier
This commit is contained in:
@@ -4430,7 +4430,16 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
nullable: true
|
||||
enum: [all, approved, available, pending, processing, unavailable]
|
||||
enum:
|
||||
[
|
||||
all,
|
||||
approved,
|
||||
available,
|
||||
pending,
|
||||
processing,
|
||||
unavailable,
|
||||
failed,
|
||||
]
|
||||
- in: query
|
||||
name: sort
|
||||
schema:
|
||||
|
@@ -2,6 +2,7 @@ export enum MediaRequestStatus {
|
||||
PENDING = 1,
|
||||
APPROVED,
|
||||
DECLINED,
|
||||
FAILED,
|
||||
}
|
||||
|
||||
export enum MediaType {
|
||||
|
@@ -451,10 +451,13 @@ export class MediaRequest {
|
||||
await mediaRepository.save(media);
|
||||
})
|
||||
.catch(async () => {
|
||||
media[this.is4k ? 'status4k' : 'status'] = MediaStatus.UNKNOWN;
|
||||
await mediaRepository.save(media);
|
||||
const requestRepository = getRepository(MediaRequest);
|
||||
|
||||
this.status = MediaRequestStatus.FAILED;
|
||||
requestRepository.save(this);
|
||||
|
||||
logger.warn(
|
||||
'Something went wrong sending movie request to Radarr, marking status as UNKNOWN',
|
||||
'Something went wrong sending movie request to Radarr, marking status as FAILED',
|
||||
{
|
||||
label: 'Media Request',
|
||||
requestId: this.id,
|
||||
@@ -684,10 +687,13 @@ export class MediaRequest {
|
||||
await mediaRepository.save(media);
|
||||
})
|
||||
.catch(async () => {
|
||||
media[this.is4k ? 'status4k' : 'status'] = MediaStatus.UNKNOWN;
|
||||
await mediaRepository.save(media);
|
||||
const requestRepository = getRepository(MediaRequest);
|
||||
|
||||
this.status = MediaRequestStatus.FAILED;
|
||||
requestRepository.save(this);
|
||||
|
||||
logger.warn(
|
||||
'Something went wrong sending series request to Sonarr, marking status as UNKNOWN',
|
||||
'Something went wrong sending series request to Sonarr, marking status as FAILED',
|
||||
{
|
||||
label: 'Media Request',
|
||||
requestId: this.id,
|
||||
|
@@ -40,11 +40,15 @@ requestRoutes.get<Record<string, unknown>, RequestResultsResponse>(
|
||||
MediaRequestStatus.APPROVED,
|
||||
];
|
||||
break;
|
||||
case 'failed':
|
||||
statusFilter = [MediaRequestStatus.FAILED];
|
||||
break;
|
||||
default:
|
||||
statusFilter = [
|
||||
MediaRequestStatus.PENDING,
|
||||
MediaRequestStatus.APPROVED,
|
||||
MediaRequestStatus.DECLINED,
|
||||
MediaRequestStatus.FAILED,
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -179,6 +179,11 @@ const RequestBlock = ({ request, onUpdate }: RequestBlockProps) => {
|
||||
{intl.formatMessage(globalMessages.pending)}
|
||||
</Badge>
|
||||
)}
|
||||
{request.status === MediaRequestStatus.FAILED && (
|
||||
<Badge badgeType="danger">
|
||||
{intl.formatMessage(globalMessages.failed)}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center text-sm leading-5 sm:mt-0">
|
||||
|
@@ -77,13 +77,13 @@ const RequestButton = ({
|
||||
(request) => request.status === MediaRequestStatus.PENDING && request.is4k
|
||||
);
|
||||
|
||||
// Current user's pending request, or the first pending request
|
||||
const activeRequest = useMemo(() => {
|
||||
return activeRequests && activeRequests.length > 0
|
||||
? activeRequests.find((request) => request.requestedBy.id === user?.id) ??
|
||||
activeRequests[0]
|
||||
: undefined;
|
||||
}, [activeRequests, user]);
|
||||
|
||||
const active4kRequest = useMemo(() => {
|
||||
return active4kRequests && active4kRequests.length > 0
|
||||
? active4kRequests.find(
|
||||
@@ -121,6 +121,151 @@ const RequestButton = ({
|
||||
};
|
||||
|
||||
const buttons: ButtonOption[] = [];
|
||||
|
||||
// If there are pending requests, show request management options first
|
||||
if (activeRequest || active4kRequest) {
|
||||
if (
|
||||
activeRequest &&
|
||||
(activeRequest.requestedBy.id === user?.id ||
|
||||
(activeRequests?.length === 1 &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS)))
|
||||
) {
|
||||
buttons.push({
|
||||
id: 'active-request',
|
||||
text: intl.formatMessage(messages.viewrequest),
|
||||
action: () => {
|
||||
setEditRequest(true);
|
||||
setShowRequestModal(true);
|
||||
},
|
||||
svg: <InformationCircleIcon />,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
activeRequest &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
mediaType === 'movie'
|
||||
) {
|
||||
buttons.push(
|
||||
{
|
||||
id: 'approve-request',
|
||||
text: intl.formatMessage(messages.approverequest),
|
||||
action: () => {
|
||||
modifyRequest(activeRequest, 'approve');
|
||||
},
|
||||
svg: <CheckIcon />,
|
||||
},
|
||||
{
|
||||
id: 'decline-request',
|
||||
text: intl.formatMessage(messages.declinerequest),
|
||||
action: () => {
|
||||
modifyRequest(activeRequest, 'decline');
|
||||
},
|
||||
svg: <XIcon />,
|
||||
}
|
||||
);
|
||||
} else if (
|
||||
activeRequests &&
|
||||
activeRequests.length > 0 &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
mediaType === 'tv'
|
||||
) {
|
||||
buttons.push(
|
||||
{
|
||||
id: 'approve-request-batch',
|
||||
text: intl.formatMessage(messages.approverequests, {
|
||||
requestCount: activeRequests.length,
|
||||
}),
|
||||
action: () => {
|
||||
modifyRequests(activeRequests, 'approve');
|
||||
},
|
||||
svg: <CheckIcon />,
|
||||
},
|
||||
{
|
||||
id: 'decline-request-batch',
|
||||
text: intl.formatMessage(messages.declinerequests, {
|
||||
requestCount: activeRequests.length,
|
||||
}),
|
||||
action: () => {
|
||||
modifyRequests(activeRequests, 'decline');
|
||||
},
|
||||
svg: <XIcon />,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
active4kRequest &&
|
||||
(active4kRequest.requestedBy.id === user?.id ||
|
||||
(active4kRequests?.length === 1 &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS)))
|
||||
) {
|
||||
buttons.push({
|
||||
id: 'active-4k-request',
|
||||
text: intl.formatMessage(messages.viewrequest4k),
|
||||
action: () => {
|
||||
setEditRequest(true);
|
||||
setShowRequest4kModal(true);
|
||||
},
|
||||
svg: <InformationCircleIcon />,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
active4kRequest &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
mediaType === 'movie'
|
||||
) {
|
||||
buttons.push(
|
||||
{
|
||||
id: 'approve-4k-request',
|
||||
text: intl.formatMessage(messages.approverequest4k),
|
||||
action: () => {
|
||||
modifyRequest(active4kRequest, 'approve');
|
||||
},
|
||||
svg: <CheckIcon />,
|
||||
},
|
||||
{
|
||||
id: 'decline-4k-request',
|
||||
text: intl.formatMessage(messages.declinerequest4k),
|
||||
action: () => {
|
||||
modifyRequest(active4kRequest, 'decline');
|
||||
},
|
||||
svg: <XIcon />,
|
||||
}
|
||||
);
|
||||
} else if (
|
||||
active4kRequests &&
|
||||
active4kRequests.length > 0 &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
mediaType === 'tv'
|
||||
) {
|
||||
buttons.push(
|
||||
{
|
||||
id: 'approve-4k-request-batch',
|
||||
text: intl.formatMessage(messages.approve4krequests, {
|
||||
requestCount: active4kRequests.length,
|
||||
}),
|
||||
action: () => {
|
||||
modifyRequests(active4kRequests, 'approve');
|
||||
},
|
||||
svg: <CheckIcon />,
|
||||
},
|
||||
{
|
||||
id: 'decline-4k-request-batch',
|
||||
text: intl.formatMessage(messages.decline4krequests, {
|
||||
requestCount: active4kRequests.length,
|
||||
}),
|
||||
action: () => {
|
||||
modifyRequests(active4kRequests, 'decline');
|
||||
},
|
||||
svg: <XIcon />,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Standard request button
|
||||
if (
|
||||
(!media || media.status === MediaStatus.UNKNOWN) &&
|
||||
hasPermission(
|
||||
@@ -142,8 +287,29 @@ const RequestButton = ({
|
||||
},
|
||||
svg: <DownloadIcon />,
|
||||
});
|
||||
} else if (
|
||||
mediaType === 'tv' &&
|
||||
(!activeRequest || activeRequest.requestedBy.id !== user?.id) &&
|
||||
hasPermission([Permission.REQUEST, Permission.REQUEST_TV], {
|
||||
type: 'or',
|
||||
}) &&
|
||||
media &&
|
||||
media.status !== MediaStatus.AVAILABLE &&
|
||||
media.status !== MediaStatus.UNKNOWN &&
|
||||
!isShowComplete
|
||||
) {
|
||||
buttons.push({
|
||||
id: 'request-more',
|
||||
text: intl.formatMessage(messages.requestmore),
|
||||
action: () => {
|
||||
setEditRequest(false);
|
||||
setShowRequestModal(true);
|
||||
},
|
||||
svg: <DownloadIcon />,
|
||||
});
|
||||
}
|
||||
|
||||
// 4K request button
|
||||
if (
|
||||
(!media || media.status4k === MediaStatus.UNKNOWN) &&
|
||||
hasPermission(
|
||||
@@ -167,175 +333,7 @@ const RequestButton = ({
|
||||
},
|
||||
svg: <DownloadIcon />,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
activeRequest &&
|
||||
(activeRequest.requestedBy.id === user?.id ||
|
||||
(activeRequests?.length === 1 &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS)))
|
||||
) {
|
||||
buttons.push({
|
||||
id: 'active-request',
|
||||
text: intl.formatMessage(messages.viewrequest),
|
||||
action: () => {
|
||||
setEditRequest(true);
|
||||
setShowRequestModal(true);
|
||||
},
|
||||
svg: <InformationCircleIcon />,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
active4kRequest &&
|
||||
(active4kRequest.requestedBy.id === user?.id ||
|
||||
(active4kRequests?.length === 1 &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS)))
|
||||
) {
|
||||
buttons.push({
|
||||
id: 'active-4k-request',
|
||||
text: intl.formatMessage(messages.viewrequest4k),
|
||||
action: () => {
|
||||
setEditRequest(true);
|
||||
setShowRequest4kModal(true);
|
||||
},
|
||||
svg: <InformationCircleIcon />,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
activeRequest &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
mediaType === 'movie'
|
||||
) {
|
||||
buttons.push(
|
||||
{
|
||||
id: 'approve-request',
|
||||
text: intl.formatMessage(messages.approverequest),
|
||||
action: () => {
|
||||
modifyRequest(activeRequest, 'approve');
|
||||
},
|
||||
svg: <CheckIcon />,
|
||||
},
|
||||
{
|
||||
id: 'decline-request',
|
||||
text: intl.formatMessage(messages.declinerequest),
|
||||
action: () => {
|
||||
modifyRequest(activeRequest, 'decline');
|
||||
},
|
||||
svg: <XIcon />,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
activeRequests &&
|
||||
activeRequests.length > 0 &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
mediaType === 'tv'
|
||||
) {
|
||||
buttons.push(
|
||||
{
|
||||
id: 'approve-request-batch',
|
||||
text: intl.formatMessage(messages.approverequests, {
|
||||
requestCount: activeRequests.length,
|
||||
}),
|
||||
action: () => {
|
||||
modifyRequests(activeRequests, 'approve');
|
||||
},
|
||||
svg: <CheckIcon />,
|
||||
},
|
||||
{
|
||||
id: 'decline-request-batch',
|
||||
text: intl.formatMessage(messages.declinerequests, {
|
||||
requestCount: activeRequests.length,
|
||||
}),
|
||||
action: () => {
|
||||
modifyRequests(activeRequests, 'decline');
|
||||
},
|
||||
svg: <XIcon />,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
active4kRequest &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
mediaType === 'movie'
|
||||
) {
|
||||
buttons.push(
|
||||
{
|
||||
id: 'approve-4k-request',
|
||||
text: intl.formatMessage(messages.approverequest4k),
|
||||
action: () => {
|
||||
modifyRequest(active4kRequest, 'approve');
|
||||
},
|
||||
svg: <CheckIcon />,
|
||||
},
|
||||
{
|
||||
id: 'decline-4k-request',
|
||||
text: intl.formatMessage(messages.declinerequest4k),
|
||||
action: () => {
|
||||
modifyRequest(active4kRequest, 'decline');
|
||||
},
|
||||
svg: <XIcon />,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
active4kRequests &&
|
||||
active4kRequests.length > 0 &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) &&
|
||||
mediaType === 'tv'
|
||||
) {
|
||||
buttons.push(
|
||||
{
|
||||
id: 'approve-4k-request-batch',
|
||||
text: intl.formatMessage(messages.approve4krequests, {
|
||||
requestCount: active4kRequests.length,
|
||||
}),
|
||||
action: () => {
|
||||
modifyRequests(active4kRequests, 'approve');
|
||||
},
|
||||
svg: <CheckIcon />,
|
||||
},
|
||||
{
|
||||
id: 'decline-4k-request-batch',
|
||||
text: intl.formatMessage(messages.decline4krequests, {
|
||||
requestCount: active4kRequests.length,
|
||||
}),
|
||||
action: () => {
|
||||
modifyRequests(active4kRequests, 'decline');
|
||||
},
|
||||
svg: <XIcon />,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
mediaType === 'tv' &&
|
||||
(!activeRequest || activeRequest.requestedBy.id !== user?.id) &&
|
||||
hasPermission([Permission.REQUEST, Permission.REQUEST_TV], {
|
||||
type: 'or',
|
||||
}) &&
|
||||
media &&
|
||||
media.status !== MediaStatus.AVAILABLE &&
|
||||
media.status !== MediaStatus.UNKNOWN &&
|
||||
!isShowComplete
|
||||
) {
|
||||
buttons.push({
|
||||
id: 'request-more',
|
||||
text: intl.formatMessage(messages.requestmore),
|
||||
action: () => {
|
||||
setEditRequest(false);
|
||||
setShowRequestModal(true);
|
||||
},
|
||||
svg: <DownloadIcon />,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
} else if (
|
||||
mediaType === 'tv' &&
|
||||
(!active4kRequest || active4kRequest.requestedBy.id !== user?.id) &&
|
||||
hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], {
|
||||
|
@@ -12,10 +12,7 @@ import { useInView } from 'react-intersection-observer';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import { useToasts } from 'react-toast-notifications';
|
||||
import useSWR, { mutate } from 'swr';
|
||||
import {
|
||||
MediaRequestStatus,
|
||||
MediaStatus,
|
||||
} from '../../../server/constants/media';
|
||||
import { MediaRequestStatus } from '../../../server/constants/media';
|
||||
import type { MediaRequest } from '../../../server/entity/MediaRequest';
|
||||
import type { MovieDetails } from '../../../server/models/Movie';
|
||||
import type { TvDetails } from '../../../server/models/Tv';
|
||||
@@ -275,8 +272,7 @@ const RequestCard = ({ request, onTitleData }: RequestCardProps) => {
|
||||
<Badge badgeType="danger">
|
||||
{intl.formatMessage(globalMessages.declined)}
|
||||
</Badge>
|
||||
) : requestData.media[requestData.is4k ? 'status4k' : 'status'] ===
|
||||
MediaStatus.UNKNOWN ? (
|
||||
) : requestData.status === MediaRequestStatus.FAILED ? (
|
||||
<Badge
|
||||
badgeType="danger"
|
||||
href={`/${requestData.type}/${requestData.media.tmdbId}?manage=1`}
|
||||
@@ -305,9 +301,7 @@ const RequestCard = ({ request, onTitleData }: RequestCardProps) => {
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-1 items-end space-x-2">
|
||||
{requestData.media[requestData.is4k ? 'status4k' : 'status'] ===
|
||||
MediaStatus.UNKNOWN &&
|
||||
requestData.status !== MediaRequestStatus.DECLINED &&
|
||||
{requestData.status === MediaRequestStatus.FAILED &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) && (
|
||||
<Button
|
||||
buttonType="primary"
|
||||
|
@@ -12,10 +12,7 @@ import { useInView } from 'react-intersection-observer';
|
||||
import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
|
||||
import { useToasts } from 'react-toast-notifications';
|
||||
import useSWR from 'swr';
|
||||
import {
|
||||
MediaRequestStatus,
|
||||
MediaStatus,
|
||||
} from '../../../../server/constants/media';
|
||||
import { MediaRequestStatus } from '../../../../server/constants/media';
|
||||
import type { MediaRequest } from '../../../../server/entity/MediaRequest';
|
||||
import type { MovieDetails } from '../../../../server/models/Movie';
|
||||
import type { TvDetails } from '../../../../server/models/Tv';
|
||||
@@ -273,9 +270,7 @@ const RequestItem = ({ request, revalidateList }: RequestItemProps) => {
|
||||
<Badge badgeType="danger">
|
||||
{intl.formatMessage(globalMessages.declined)}
|
||||
</Badge>
|
||||
) : requestData.media[
|
||||
requestData.is4k ? 'status4k' : 'status'
|
||||
] === MediaStatus.UNKNOWN ? (
|
||||
) : requestData.status === MediaRequestStatus.FAILED ? (
|
||||
<Badge
|
||||
badgeType="danger"
|
||||
href={`/${requestData.type}/${requestData.media.tmdbId}?manage=1`}
|
||||
@@ -402,9 +397,7 @@ const RequestItem = ({ request, revalidateList }: RequestItemProps) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="z-10 mt-4 flex w-full flex-col justify-center space-y-2 pl-4 pr-4 xl:mt-0 xl:w-96 xl:items-end xl:pl-0">
|
||||
{requestData.media[requestData.is4k ? 'status4k' : 'status'] ===
|
||||
MediaStatus.UNKNOWN &&
|
||||
requestData.status !== MediaRequestStatus.DECLINED &&
|
||||
{requestData.status === MediaRequestStatus.FAILED &&
|
||||
hasPermission(Permission.MANAGE_REQUESTS) && (
|
||||
<Button
|
||||
className="w-full"
|
||||
|
@@ -33,6 +33,7 @@ enum Filter {
|
||||
PROCESSING = 'processing',
|
||||
AVAILABLE = 'available',
|
||||
UNAVAILABLE = 'unavailable',
|
||||
FAILED = 'failed',
|
||||
}
|
||||
|
||||
type Sort = 'added' | 'modified';
|
||||
@@ -158,6 +159,9 @@ const RequestList = () => {
|
||||
<option value="processing">
|
||||
{intl.formatMessage(globalMessages.processing)}
|
||||
</option>
|
||||
<option value="failed">
|
||||
{intl.formatMessage(globalMessages.failed)}
|
||||
</option>
|
||||
<option value="available">
|
||||
{intl.formatMessage(globalMessages.available)}
|
||||
</option>
|
||||
|
Reference in New Issue
Block a user