mirror of
https://github.com/Radarr/Radarr.git
synced 2024-08-18 08:19:38 +02:00
New: Show ExtraFiles in UI
This commit is contained in:
parent
3576f529ec
commit
f338941cfc
@ -25,6 +25,7 @@ import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||
import Popover from 'Components/Tooltip/Popover';
|
||||
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
||||
import MovieFileEditorTable from 'MovieFile/Editor/MovieFileEditorTable';
|
||||
import ExtraFileTable from 'MovieFile/Extras/ExtraFileTable';
|
||||
import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector';
|
||||
import QualityProfileNameConnector from 'Settings/Profiles/Quality/QualityProfileNameConnector';
|
||||
import MoviePoster from 'Movie/MoviePoster';
|
||||
@ -182,6 +183,7 @@ class MovieDetails extends Component {
|
||||
isSmallScreen,
|
||||
movieFilesError,
|
||||
movieCreditsError,
|
||||
extraFilesError,
|
||||
hasMovieFiles,
|
||||
previousMovie,
|
||||
nextMovie,
|
||||
@ -457,15 +459,25 @@ class MovieDetails extends Component {
|
||||
|
||||
<div className={styles.contentContainer}>
|
||||
{
|
||||
!isPopulated && !movieFilesError && !movieCreditsError &&
|
||||
!isPopulated && !movieFilesError && !movieCreditsError && !extraFilesError &&
|
||||
<LoadingIndicator />
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && movieFilesError && !movieCreditsError &&
|
||||
!isFetching && movieFilesError &&
|
||||
<div>Loading movie files failed</div>
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && movieCreditsError &&
|
||||
<div>Loading movie credits failed</div>
|
||||
}
|
||||
|
||||
{
|
||||
!isFetching && extraFilesError &&
|
||||
<div>Loading movie extra files failed</div>
|
||||
}
|
||||
|
||||
<Tabs selectedIndex={this.state.tabIndex} onSelect={(tabIndex) => this.setState({ selectedTabIndex: tabIndex })}>
|
||||
<TabList
|
||||
className={styles.tabList}
|
||||
@ -537,6 +549,9 @@ class MovieDetails extends Component {
|
||||
<MovieFileEditorTable
|
||||
movieId={id}
|
||||
/>
|
||||
<ExtraFileTable
|
||||
movieId={id}
|
||||
/>
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel>
|
||||
@ -623,6 +638,7 @@ MovieDetails.propTypes = {
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
movieFilesError: PropTypes.object,
|
||||
movieCreditsError: PropTypes.object,
|
||||
extraFilesError: PropTypes.object,
|
||||
hasMovieFiles: PropTypes.bool.isRequired,
|
||||
previousMovie: PropTypes.object.isRequired,
|
||||
nextMovie: PropTypes.object.isRequired,
|
||||
|
@ -9,6 +9,7 @@ import createAllMoviesSelector from 'Store/Selectors/createAllMoviesSelector';
|
||||
import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
|
||||
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
|
||||
import { fetchMovieFiles, clearMovieFiles } from 'Store/Actions/movieFileActions';
|
||||
import { fetchExtraFiles, clearExtraFiles } from 'Store/Actions/extraFileActions';
|
||||
import { fetchMovieCredits, clearMovieCredits } from 'Store/Actions/movieCreditsActions';
|
||||
import { toggleMovieMonitored } from 'Store/Actions/movieActions';
|
||||
import { fetchQueueDetails, clearQueueDetails } from 'Store/Actions/queueActions';
|
||||
@ -59,15 +60,33 @@ const selectMovieCredits = createSelector(
|
||||
}
|
||||
);
|
||||
|
||||
const selectExtraFiles = createSelector(
|
||||
(state) => state.extraFiles,
|
||||
(extraFiles) => {
|
||||
const {
|
||||
isFetching,
|
||||
isPopulated,
|
||||
error
|
||||
} = extraFiles;
|
||||
|
||||
return {
|
||||
isExtraFilesFetching: isFetching,
|
||||
isExtraFilesPopulated: isPopulated,
|
||||
extraFilesError: error
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state, { titleSlug }) => titleSlug,
|
||||
selectMovieFiles,
|
||||
selectMovieCredits,
|
||||
selectExtraFiles,
|
||||
createAllMoviesSelector(),
|
||||
createCommandsSelector(),
|
||||
createDimensionsSelector(),
|
||||
(titleSlug, movieFiles, movieCredits, allMovies, commands, dimensions) => {
|
||||
(titleSlug, movieFiles, movieCredits, extraFiles, allMovies, commands, dimensions) => {
|
||||
const sortedMovies = _.orderBy(allMovies, 'sortTitle');
|
||||
const movieIndex = _.findIndex(sortedMovies, { titleSlug });
|
||||
const movie = sortedMovies[movieIndex];
|
||||
@ -90,6 +109,12 @@ function createMapStateToProps() {
|
||||
movieCreditsError
|
||||
} = movieCredits;
|
||||
|
||||
const {
|
||||
isExtraFilesFetching,
|
||||
isExtraFilesPopulated,
|
||||
extraFilesError
|
||||
} = extraFiles;
|
||||
|
||||
const previousMovie = sortedMovies[movieIndex - 1] || _.last(sortedMovies);
|
||||
const nextMovie = sortedMovies[movieIndex + 1] || _.first(sortedMovies);
|
||||
const isMovieRefreshing = isCommandExecuting(findCommand(commands, { name: commandNames.REFRESH_MOVIE, movieId: movie.id }));
|
||||
@ -107,8 +132,8 @@ function createMapStateToProps() {
|
||||
isRenamingMovieCommand.body.movieIds.indexOf(movie.id) > -1
|
||||
);
|
||||
|
||||
const isFetching = isMovieFilesFetching && isMovieCreditsFetching;
|
||||
const isPopulated = isMovieFilesPopulated && isMovieCreditsPopulated;
|
||||
const isFetching = isMovieFilesFetching || isMovieCreditsFetching || isExtraFilesFetching;
|
||||
const isPopulated = isMovieFilesPopulated && isMovieCreditsPopulated && isExtraFilesPopulated;
|
||||
const alternateTitles = _.reduce(movie.alternateTitles, (acc, alternateTitle) => {
|
||||
acc.push(alternateTitle.title);
|
||||
return acc;
|
||||
@ -127,6 +152,7 @@ function createMapStateToProps() {
|
||||
isPopulated,
|
||||
movieFilesError,
|
||||
movieCreditsError,
|
||||
extraFilesError,
|
||||
hasMovieFiles,
|
||||
sizeOnDisk,
|
||||
previousMovie,
|
||||
@ -142,6 +168,8 @@ const mapDispatchToProps = {
|
||||
clearMovieFiles,
|
||||
fetchMovieCredits,
|
||||
clearMovieCredits,
|
||||
fetchExtraFiles,
|
||||
clearExtraFiles,
|
||||
clearReleases,
|
||||
cancelFetchReleases,
|
||||
fetchNetImportSchema,
|
||||
@ -200,6 +228,7 @@ class MovieDetailsConnector extends Component {
|
||||
const movieId = this.props.id;
|
||||
|
||||
this.props.fetchMovieFiles({ movieId });
|
||||
this.props.fetchExtraFiles({ movieId });
|
||||
this.props.fetchMovieCredits({ movieId });
|
||||
this.props.fetchQueueDetails({ movieId });
|
||||
this.props.fetchNetImportSchema();
|
||||
@ -208,6 +237,7 @@ class MovieDetailsConnector extends Component {
|
||||
unpopulate = () => {
|
||||
this.props.cancelFetchReleases();
|
||||
this.props.clearMovieFiles();
|
||||
this.props.clearExtraFiles();
|
||||
this.props.clearMovieCredits();
|
||||
this.props.clearQueueDetails();
|
||||
this.props.clearReleases();
|
||||
@ -263,6 +293,8 @@ MovieDetailsConnector.propTypes = {
|
||||
isSmallScreen: PropTypes.bool.isRequired,
|
||||
fetchMovieFiles: PropTypes.func.isRequired,
|
||||
clearMovieFiles: PropTypes.func.isRequired,
|
||||
fetchExtraFiles: PropTypes.func.isRequired,
|
||||
clearExtraFiles: PropTypes.func.isRequired,
|
||||
fetchMovieCredits: PropTypes.func.isRequired,
|
||||
clearMovieCredits: PropTypes.func.isRequired,
|
||||
clearReleases: PropTypes.func.isRequired,
|
||||
|
10
frontend/src/MovieFile/Editor/MovieFileEditorTable.css
Normal file
10
frontend/src/MovieFile/Editor/MovieFileEditorTable.css
Normal file
@ -0,0 +1,10 @@
|
||||
.container {
|
||||
margin-top: 20px;
|
||||
border: 1px solid $borderColor;
|
||||
border-radius: 4px;
|
||||
background-color: $white;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import MovieFileEditorTableContentConnector from './MovieFileEditorTableContentConnector';
|
||||
import styles from './MovieFileEditorTable.css';
|
||||
|
||||
function MovieFileEditorTable(props) {
|
||||
const {
|
||||
@ -8,9 +9,11 @@ function MovieFileEditorTable(props) {
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<MovieFileEditorTableContentConnector
|
||||
movieId={movieId}
|
||||
/>
|
||||
<div className={styles.container}>
|
||||
<MovieFileEditorTableContentConnector
|
||||
movieId={movieId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
10
frontend/src/MovieFile/Extras/ExtraFileRow.css
Normal file
10
frontend/src/MovieFile/Extras/ExtraFileRow.css
Normal file
@ -0,0 +1,10 @@
|
||||
.relativePath {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.extension,
|
||||
.type {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
}
|
63
frontend/src/MovieFile/Extras/ExtraFileRow.js
Normal file
63
frontend/src/MovieFile/Extras/ExtraFileRow.js
Normal file
@ -0,0 +1,63 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import titleCase from 'Utilities/String/titleCase';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import styles from './ExtraFileRow.css';
|
||||
|
||||
class ExtraFileRow extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
relativePath,
|
||||
extension,
|
||||
type
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<TableRow>
|
||||
<TableRowCell
|
||||
className={styles.relativePath}
|
||||
title={relativePath}
|
||||
>
|
||||
{relativePath}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell
|
||||
className={styles.extension}
|
||||
title={extension}
|
||||
>
|
||||
{extension}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell
|
||||
className={styles.type}
|
||||
title={type}
|
||||
>
|
||||
{titleCase(type)}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.actions}>
|
||||
<IconButton
|
||||
name={icons.INFO}
|
||||
/>
|
||||
</TableRowCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExtraFileRow.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
extension: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
relativePath: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
export default ExtraFileRow;
|
10
frontend/src/MovieFile/Extras/ExtraFileTable.css
Normal file
10
frontend/src/MovieFile/Extras/ExtraFileTable.css
Normal file
@ -0,0 +1,10 @@
|
||||
.container {
|
||||
margin-top: 20px;
|
||||
border: 1px solid $borderColor;
|
||||
border-radius: 4px;
|
||||
background-color: $white;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
25
frontend/src/MovieFile/Extras/ExtraFileTable.js
Normal file
25
frontend/src/MovieFile/Extras/ExtraFileTable.js
Normal file
@ -0,0 +1,25 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import ExtraFileTableContentConnector from './ExtraFileTableContentConnector';
|
||||
import styles from './ExtraFileTable.css';
|
||||
|
||||
function ExtraFileTable(props) {
|
||||
const {
|
||||
movieId
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<ExtraFileTableContentConnector
|
||||
movieId={movieId}
|
||||
/>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
ExtraFileTable.propTypes = {
|
||||
movieId: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
export default ExtraFileTable;
|
10
frontend/src/MovieFile/Extras/ExtraFileTableContent.css
Normal file
10
frontend/src/MovieFile/Extras/ExtraFileTableContent.css
Normal file
@ -0,0 +1,10 @@
|
||||
.actions {
|
||||
display: flex;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.blankpad {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 2em;
|
||||
}
|
80
frontend/src/MovieFile/Extras/ExtraFileTableContent.js
Normal file
80
frontend/src/MovieFile/Extras/ExtraFileTableContent.js
Normal file
@ -0,0 +1,80 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import ExtraFileRow from './ExtraFileRow';
|
||||
import styles from './ExtraFileTableContent.css';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'relativePath',
|
||||
label: 'Extra File',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'extension',
|
||||
label: 'Extension',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
label: 'Type',
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'action',
|
||||
label: React.createElement(IconButton, { name: icons.ADVANCED_SETTINGS }),
|
||||
isVisible: true
|
||||
}
|
||||
];
|
||||
|
||||
class ExtraFileTableContent extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
items
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
!items.length &&
|
||||
<div className={styles.blankpad}>
|
||||
No extra files to manage.
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!!items.length &&
|
||||
<Table columns={columns}>
|
||||
<TableBody>
|
||||
{
|
||||
items.map((item) => {
|
||||
return (
|
||||
<ExtraFileRow
|
||||
key={item.id}
|
||||
{...item}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</TableBody>
|
||||
</Table>
|
||||
}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ExtraFileTableContent.propTypes = {
|
||||
movieId: PropTypes.number,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default ExtraFileTableContent;
|
@ -0,0 +1,50 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import createMovieSelector from 'Store/Selectors/createMovieSelector';
|
||||
import ExtraFileTableContent from './ExtraFileTableContent';
|
||||
|
||||
function createMapStateToProps() {
|
||||
return createSelector(
|
||||
(state) => state.extraFiles,
|
||||
createMovieSelector(),
|
||||
(
|
||||
ExtraFiles
|
||||
) => {
|
||||
return {
|
||||
items: ExtraFiles.items,
|
||||
error: null
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
};
|
||||
}
|
||||
|
||||
class ExtraFileTableContentConnector extends Component {
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<ExtraFileTableContent
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ExtraFileTableContentConnector.propTypes = {
|
||||
movieId: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(ExtraFileTableContentConnector);
|
49
frontend/src/Store/Actions/extraFileActions.js
Normal file
49
frontend/src/Store/Actions/extraFileActions.js
Normal file
@ -0,0 +1,49 @@
|
||||
import { createAction } from 'redux-actions';
|
||||
import { createThunk, handleThunks } from 'Store/thunks';
|
||||
import createFetchHandler from './Creators/createFetchHandler';
|
||||
import createHandleActions from './Creators/createHandleActions';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
||||
export const section = 'extraFiles';
|
||||
|
||||
//
|
||||
// State
|
||||
|
||||
export const defaultState = {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: []
|
||||
};
|
||||
|
||||
//
|
||||
// Actions Types
|
||||
|
||||
export const FETCH_EXTRA_FILES = 'extraFiles/fetchExtraFiles';
|
||||
export const CLEAR_EXTRA_FILES = 'extraFiles/clearExtraFiles';
|
||||
|
||||
//
|
||||
// Action Creators
|
||||
|
||||
export const fetchExtraFiles = createThunk(FETCH_EXTRA_FILES);
|
||||
export const clearExtraFiles = createAction(CLEAR_EXTRA_FILES);
|
||||
|
||||
//
|
||||
// Action Handlers
|
||||
|
||||
export const actionHandlers = handleThunks({
|
||||
[FETCH_EXTRA_FILES]: createFetchHandler(section, '/extraFile')
|
||||
});
|
||||
|
||||
//
|
||||
// Reducers
|
||||
|
||||
export const reducers = createHandleActions({
|
||||
|
||||
[CLEAR_EXTRA_FILES]: (state) => {
|
||||
return Object.assign({}, state, defaultState);
|
||||
}
|
||||
|
||||
}, defaultState, section);
|
@ -6,6 +6,7 @@ import * as captcha from './captchaActions';
|
||||
import * as customFilters from './customFilterActions';
|
||||
import * as commands from './commandActions';
|
||||
import * as movieFiles from './movieFileActions';
|
||||
import * as extraFiles from './extraFileActions';
|
||||
import * as history from './historyActions';
|
||||
import * as importMovie from './importMovieActions';
|
||||
import * as interactiveImportActions from './interactiveImportActions';
|
||||
@ -33,6 +34,7 @@ export default [
|
||||
commands,
|
||||
customFilters,
|
||||
movieFiles,
|
||||
extraFiles,
|
||||
history,
|
||||
importMovie,
|
||||
interactiveImportActions,
|
||||
|
46
src/Radarr.Api.V3/ExtraFiles/ExtraFileModule.cs
Normal file
46
src/Radarr.Api.V3/ExtraFiles/ExtraFileModule.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Extras.Files;
|
||||
using NzbDrone.Core.Extras.Metadata.Files;
|
||||
using NzbDrone.Core.Extras.Others;
|
||||
using NzbDrone.Core.Extras.Subtitles;
|
||||
using Radarr.Http;
|
||||
using Radarr.Http.REST;
|
||||
|
||||
namespace Radarr.Api.V3.ExtraFiles
|
||||
{
|
||||
public class ExtraFileModule : RadarrRestModule<ExtraFileResource>
|
||||
{
|
||||
private readonly IExtraFileService<SubtitleFile> _subtitleFileService;
|
||||
private readonly IExtraFileService<MetadataFile> _metadataFileService;
|
||||
private readonly IExtraFileService<OtherExtraFile> _otherFileService;
|
||||
|
||||
public ExtraFileModule(IExtraFileService<SubtitleFile> subtitleFileService, IExtraFileService<MetadataFile> metadataFileService, IExtraFileService<OtherExtraFile> otherExtraFileService)
|
||||
: base("/extrafile")
|
||||
{
|
||||
_subtitleFileService = subtitleFileService;
|
||||
_metadataFileService = metadataFileService;
|
||||
_otherFileService = otherExtraFileService;
|
||||
GetResourceAll = GetFiles;
|
||||
}
|
||||
|
||||
private List<ExtraFileResource> GetFiles()
|
||||
{
|
||||
if (!Request.Query.MovieId.HasValue)
|
||||
{
|
||||
throw new BadRequestException("MovieId is missing");
|
||||
}
|
||||
|
||||
var extraFiles = new List<ExtraFileResource>();
|
||||
|
||||
List<SubtitleFile> subtitleFiles = _subtitleFileService.GetFilesByMovie(Request.Query.MovieId);
|
||||
List<MetadataFile> metadataFiles = _metadataFileService.GetFilesByMovie(Request.Query.MovieId);
|
||||
List<OtherExtraFile> otherExtraFiles = _otherFileService.GetFilesByMovie(Request.Query.MovieId);
|
||||
|
||||
extraFiles.AddRange(subtitleFiles.ToResource());
|
||||
extraFiles.AddRange(metadataFiles.ToResource());
|
||||
extraFiles.AddRange(otherExtraFiles.ToResource());
|
||||
|
||||
return extraFiles;
|
||||
}
|
||||
}
|
||||
}
|
91
src/Radarr.Api.V3/ExtraFiles/ExtraFileResource.cs
Normal file
91
src/Radarr.Api.V3/ExtraFiles/ExtraFileResource.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Extras.Files;
|
||||
using NzbDrone.Core.Extras.Metadata.Files;
|
||||
using NzbDrone.Core.Extras.Others;
|
||||
using NzbDrone.Core.Extras.Subtitles;
|
||||
using Radarr.Http.REST;
|
||||
|
||||
namespace Radarr.Api.V3.ExtraFiles
|
||||
{
|
||||
public class ExtraFileResource : RestResource
|
||||
{
|
||||
public int MovieId { get; set; }
|
||||
public int? MovieFileId { get; set; }
|
||||
public string RelativePath { get; set; }
|
||||
public string Extension { get; set; }
|
||||
public ExtraFileType Type { get; set; }
|
||||
}
|
||||
|
||||
public static class ExtraFileResourceMapper
|
||||
{
|
||||
public static ExtraFileResource ToResource(this MetadataFile model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ExtraFileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
MovieId = model.MovieId,
|
||||
MovieFileId = model.MovieFileId,
|
||||
RelativePath = model.RelativePath,
|
||||
Extension = model.Extension,
|
||||
Type = ExtraFileType.Metadata
|
||||
};
|
||||
}
|
||||
|
||||
public static ExtraFileResource ToResource(this SubtitleFile model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ExtraFileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
MovieId = model.MovieId,
|
||||
MovieFileId = model.MovieFileId,
|
||||
RelativePath = model.RelativePath,
|
||||
Extension = model.Extension,
|
||||
Type = ExtraFileType.Subtitle
|
||||
};
|
||||
}
|
||||
|
||||
public static ExtraFileResource ToResource(this OtherExtraFile model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ExtraFileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
MovieId = model.MovieId,
|
||||
MovieFileId = model.MovieFileId,
|
||||
RelativePath = model.RelativePath,
|
||||
Extension = model.Extension,
|
||||
Type = ExtraFileType.Other
|
||||
};
|
||||
}
|
||||
|
||||
public static List<ExtraFileResource> ToResource(this IEnumerable<SubtitleFile> movies)
|
||||
{
|
||||
return movies.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
public static List<ExtraFileResource> ToResource(this IEnumerable<MetadataFile> movies)
|
||||
{
|
||||
return movies.Select(ToResource).ToList();
|
||||
}
|
||||
|
||||
public static List<ExtraFileResource> ToResource(this IEnumerable<OtherExtraFile> movies)
|
||||
{
|
||||
return movies.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user