mirror of
https://github.com/Radarr/Radarr.git
synced 2024-10-26 14:42:34 +02:00
Files tab is now present. (#245)
* Adding file info tab. Not finished yet. * Adding more media info options. * Deleting files now works. Fixes #127 * Fix button for modifying episode files. * Get Media Info when running DiskScanService.
This commit is contained in:
parent
5daece0ed4
commit
29586667cb
89
src/NzbDrone.Api/Movies/MovieFileModule.cs
Normal file
89
src/NzbDrone.Api/Movies/MovieFileModule.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.EpisodeFiles
|
||||
{
|
||||
public class MovieFileModule : NzbDroneRestModuleWithSignalR<MovieFileResource, MovieFile>
|
||||
//IHandle<EpisodeFileAddedEvent>
|
||||
{
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly IRecycleBinProvider _recycleBinProvider;
|
||||
private readonly IMovieService _seriesService;
|
||||
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MovieFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMediaFileService mediaFileService,
|
||||
IRecycleBinProvider recycleBinProvider,
|
||||
IMovieService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
Logger logger)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_mediaFileService = mediaFileService;
|
||||
_recycleBinProvider = recycleBinProvider;
|
||||
_seriesService = seriesService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
_logger = logger;
|
||||
/*GetResourceById = GetEpisodeFile;
|
||||
GetResourceAll = GetEpisodeFiles;
|
||||
UpdateResource = SetQuality;*/
|
||||
DeleteResource = DeleteEpisodeFile;
|
||||
}
|
||||
|
||||
/*private EpisodeFileResource GetEpisodeFile(int id)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(id);
|
||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||
|
||||
return episodeFile.ToResource(series, _qualityUpgradableSpecification);
|
||||
}
|
||||
|
||||
private List<EpisodeFileResource> GetEpisodeFiles()
|
||||
{
|
||||
if (!Request.Query.SeriesId.HasValue)
|
||||
{
|
||||
throw new BadRequestException("seriesId is missing");
|
||||
}
|
||||
|
||||
var seriesId = (int)Request.Query.SeriesId;
|
||||
|
||||
var series = _seriesService.GetSeries(seriesId);
|
||||
|
||||
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _qualityUpgradableSpecification));
|
||||
}
|
||||
|
||||
private void SetQuality(EpisodeFileResource episodeFileResource)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
|
||||
episodeFile.Quality = episodeFileResource.Quality;
|
||||
_mediaFileService.Update(episodeFile);
|
||||
}*/
|
||||
|
||||
private void DeleteEpisodeFile(int id)
|
||||
{
|
||||
var episodeFile = _mediaFileService.GetMovie(id);
|
||||
var series = _seriesService.GetMovie(episodeFile.MovieId);
|
||||
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
|
||||
|
||||
_logger.Info("Deleting episode file: {0}", fullPath);
|
||||
_recycleBinProvider.DeleteFile(fullPath);
|
||||
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
|
||||
}
|
||||
|
||||
public void Handle(EpisodeFileAddedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.EpisodeFile.Id);
|
||||
}
|
||||
}
|
||||
}
|
@ -116,6 +116,7 @@
|
||||
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
|
||||
<Compile Include="Indexers\ReleaseModuleBase.cs" />
|
||||
<Compile Include="Indexers\ReleasePushModule.cs" />
|
||||
<Compile Include="Movies\MovieFileModule.cs" />
|
||||
<Compile Include="Movies\MovieModule.cs" />
|
||||
<Compile Include="Movies\RenameMovieModule.cs" />
|
||||
<Compile Include="Movies\RenameMovieResource.cs" />
|
||||
|
@ -30,8 +30,8 @@ public MovieFileResource()
|
||||
public string ReleaseGroup { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public MovieResource Movie { get; set; }
|
||||
|
||||
|
||||
public string Edition { get; set; }
|
||||
public Core.MediaFiles.MediaInfo.MediaInfoModel MediaInfo { get; set; }
|
||||
|
||||
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
||||
}
|
||||
@ -63,7 +63,8 @@ public static MovieFileResource ToResource(this MovieFile model)
|
||||
ReleaseGroup = model.ReleaseGroup,
|
||||
Quality = model.Quality,
|
||||
Movie = movie,
|
||||
|
||||
MediaInfo = model.MediaInfo,
|
||||
Edition = model.Edition
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
using System.Data;
|
||||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(117)]
|
||||
public class update_movie_file : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Create.Column("Edition").OnTable("MovieFiles").AsString().Nullable();
|
||||
Execute.WithConnection(SetSortTitles);
|
||||
}
|
||||
|
||||
private void SetSortTitles(IDbConnection conn, IDbTransaction tran)
|
||||
{
|
||||
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||
{
|
||||
getSeriesCmd.Transaction = tran;
|
||||
getSeriesCmd.CommandText = @"SELECT Id, RelativePath FROM MovieFiles";
|
||||
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||
{
|
||||
while (seriesReader.Read())
|
||||
{
|
||||
var id = seriesReader.GetInt32(0);
|
||||
var relativePath = seriesReader.GetString(1);
|
||||
|
||||
var edition = Parser.Parser.ParseMovieTitle(relativePath).Edition;
|
||||
|
||||
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||
{
|
||||
updateCmd.Transaction = tran;
|
||||
updateCmd.CommandText = "UPDATE MovieFiles SET Edition = ? WHERE Id = ?";
|
||||
updateCmd.AddParameter(edition);
|
||||
updateCmd.AddParameter(id);
|
||||
|
||||
updateCmd.ExecuteNonQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -83,6 +83,7 @@ public List<ImportResult> Import(List<ImportDecision> decisions, bool newDownloa
|
||||
episodeFile.MediaInfo = localMovie.MediaInfo;
|
||||
episodeFile.Movie = localMovie.Movie;
|
||||
episodeFile.ReleaseGroup = localMovie.ParsedMovieInfo.ReleaseGroup;
|
||||
episodeFile.Edition = localMovie.ParsedMovieInfo.Edition;
|
||||
|
||||
bool copyOnly;
|
||||
switch (importMode)
|
||||
|
@ -57,7 +57,7 @@ public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series s
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Movie movie)
|
||||
{
|
||||
return GetImportDecisions(videoFiles, movie, null, false);
|
||||
return GetImportDecisions(videoFiles, movie, null, true);
|
||||
}
|
||||
|
||||
public List<ImportDecision> GetImportDecisions(List<string> videoFiles, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource)
|
||||
|
@ -26,6 +26,7 @@ public interface IMediaFileService
|
||||
List<string> FilterExistingFiles(List<string> files, Series series);
|
||||
List<string> FilterExistingFiles(List<string> files, Movie movie);
|
||||
EpisodeFile Get(int id);
|
||||
MovieFile GetMovie(int id);
|
||||
List<EpisodeFile> Get(IEnumerable<int> ids);
|
||||
List<MovieFile> GetMovies(IEnumerable<int> ids);
|
||||
|
||||
@ -150,5 +151,9 @@ public void Update(MovieFile episodeFile)
|
||||
_movieFileRepository.Update(episodeFile);
|
||||
}
|
||||
|
||||
public MovieFile GetMovie(int id)
|
||||
{
|
||||
return _movieFileRepository.Get(id);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ public class MovieFile : ModelBase
|
||||
public string ReleaseGroup { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public MediaInfoModel MediaInfo { get; set; }
|
||||
public string Edition { get; set; }
|
||||
public LazyLoaded<Movie> Movie { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
|
@ -183,6 +183,7 @@
|
||||
<Compile Include="Datastore\Migration\002_remove_tvrage_imdb_unique_constraint.cs" />
|
||||
<Compile Include="Datastore\Migration\003_remove_clean_title_from_scene_mapping.cs" />
|
||||
<Compile Include="Datastore\Migration\004_updated_history.cs" />
|
||||
<Compile Include="Datastore\Migration\117_update_movie_file.cs" />
|
||||
<Compile Include="Datastore\Migration\116_update_movie_sorttitle_again.cs" />
|
||||
<Compile Include="Datastore\Migration\115_update_movie_sorttitle.cs" />
|
||||
<Compile Include="Datastore\Migration\111_remove_bitmetv.cs" />
|
||||
|
15
src/UI/Cells/FileTitleCell.js
Normal file
15
src/UI/Cells/FileTitleCell.js
Normal file
@ -0,0 +1,15 @@
|
||||
var NzbDroneCell = require('./NzbDroneCell');
|
||||
|
||||
module.exports = NzbDroneCell.extend({
|
||||
className : 'file-title-cell',
|
||||
|
||||
render : function() {
|
||||
this.$el.empty();
|
||||
|
||||
var title = this.model.get('relativePath');
|
||||
this.$el.html(title);
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
23
src/UI/Cells/MediaInfoCell.js
Normal file
23
src/UI/Cells/MediaInfoCell.js
Normal file
@ -0,0 +1,23 @@
|
||||
var NzbDroneCell = require('./NzbDroneCell');
|
||||
|
||||
module.exports = NzbDroneCell.extend({
|
||||
className : 'release-title-cell',
|
||||
|
||||
render : function() {
|
||||
this.$el.empty();
|
||||
|
||||
var info = this.model.get('mediaInfo');
|
||||
if (info) {
|
||||
var runtime = info.runTime;
|
||||
if (runtime) {
|
||||
runtime = runtime.split(".")[0];
|
||||
}
|
||||
var video = "{0} ({1}x{2}) ({3})".format(info.videoCodec, info.width, info.height, runtime);
|
||||
var audio = "{0} ({1})".format(info.audioFormat, info.audioLanguages);
|
||||
this.$el.html(video + " " + audio);
|
||||
}
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
{{#if_gt proper compare="1"}}
|
||||
<span class="badge badge-info" title="PROPER">{{quality.name}}</span>
|
||||
{{else}}
|
||||
<span class="badge">{{quality.name}}</span>
|
||||
{{/if_gt}}
|
||||
<span class="badge" title="{{#if hardcodedSubs}}Warning: {{hardcodedSubs}}{{/if}}">{{quality.name}}</span>
|
||||
{{/if_gt}}
|
||||
|
@ -17,4 +17,4 @@ module.exports = NzbDroneCell.extend({
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -11,6 +11,7 @@ var LoadingView = require('../../Shared/LoadingView');
|
||||
var EpisodeFileEditorLayout = require('../../EpisodeFile/Editor/EpisodeFileEditorLayout');
|
||||
var HistoryLayout = require('../History/MovieHistoryLayout');
|
||||
var SearchLayout = require('../Search/MovieSearchLayout');
|
||||
var FilesLayout = require("../Files/FilesLayout");
|
||||
require('backstrech');
|
||||
require('../../Mixins/backbone.signalr.mixin');
|
||||
|
||||
@ -22,7 +23,8 @@ module.exports = Marionette.Layout.extend({
|
||||
seasons : '#seasons',
|
||||
info : '#info',
|
||||
search : '#movie-search',
|
||||
history : '#movie-history'
|
||||
history : '#movie-history',
|
||||
files : "#movie-files"
|
||||
},
|
||||
|
||||
|
||||
@ -36,11 +38,12 @@ module.exports = Marionette.Layout.extend({
|
||||
poster : '.x-movie-poster',
|
||||
manualSearch : '.x-manual-search',
|
||||
history : '.x-movie-history',
|
||||
search : '.x-movie-search'
|
||||
search : '.x-movie-search',
|
||||
files : ".x-movie-files"
|
||||
},
|
||||
|
||||
events : {
|
||||
'click .x-episode-file-editor' : '_openEpisodeFileEditor',
|
||||
'click .x-episode-file-editor' : '_showFiles',
|
||||
'click .x-monitored' : '_toggleMonitored',
|
||||
'click .x-edit' : '_editMovie',
|
||||
'click .x-refresh' : '_refreshMovies',
|
||||
@ -48,7 +51,8 @@ module.exports = Marionette.Layout.extend({
|
||||
'click .x-search' : '_moviesSearch',
|
||||
'click .x-manual-search' : '_showSearch',
|
||||
'click .x-movie-history' : '_showHistory',
|
||||
'click .x-movie-search' : '_showSearch'
|
||||
'click .x-movie-search' : '_showSearch',
|
||||
"click .x-movie-files" : "_showFiles",
|
||||
},
|
||||
|
||||
initialize : function() {
|
||||
@ -72,11 +76,18 @@ module.exports = Marionette.Layout.extend({
|
||||
this.searchLayout = new SearchLayout({ model : this.model });
|
||||
this.searchLayout.startManualSearch = true;
|
||||
|
||||
this.filesLayout = new FilesLayout({ model : this.model });
|
||||
|
||||
this._showBackdrop();
|
||||
this._showSeasons();
|
||||
this._setMonitoredState();
|
||||
this._showInfo();
|
||||
this._showHistory();
|
||||
if (this.model.get("movieFile")) {
|
||||
this._showFiles()
|
||||
} else {
|
||||
this._showHistory();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
onRender : function() {
|
||||
@ -144,6 +155,15 @@ module.exports = Marionette.Layout.extend({
|
||||
this.search.show(this.searchLayout);
|
||||
},
|
||||
|
||||
_showFiles : function(e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
this.ui.files.tab('show');
|
||||
this.files.show(this.filesLayout);
|
||||
},
|
||||
|
||||
_toggleMonitored : function() {
|
||||
var savePromise = this.model.save('monitored', !this.model.get('monitored'), { wait : true });
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
{{title}}
|
||||
<div class="movie-actions pull-right">
|
||||
<div class="x-episode-file-editor">
|
||||
<i class="icon-sonarr-episode-file" title="Modify episode files for movie"/>
|
||||
<i class="icon-sonarr-episode-file" title="Modify movie files"/>
|
||||
</div>
|
||||
<div class="x-refresh">
|
||||
<i class="icon-sonarr-refresh icon-can-spin" title="Update movie info and scan disk"/>
|
||||
@ -42,10 +42,12 @@
|
||||
<ul class="nav nav-tabs" id="myTab">
|
||||
<li><a href="#movie-history" class="x-movie-history">History</a></li>
|
||||
<li><a href="#movie-search" class="x-movie-search">Search</a></li>
|
||||
<li><a href="#movie-files" class="x-movie-files">Files</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane" id="movie-history"/>
|
||||
<div class="tab-pane" id="movie-search"/>
|
||||
<div class="tab-pane" id="movie-files"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
26
src/UI/Movies/Files/DeleteFileCell.js
Normal file
26
src/UI/Movies/Files/DeleteFileCell.js
Normal file
@ -0,0 +1,26 @@
|
||||
var vent = require('vent');
|
||||
var Backgrid = require('backgrid');
|
||||
|
||||
module.exports = Backgrid.Cell.extend({
|
||||
className : 'delete-episode-file-cell',
|
||||
|
||||
events : {
|
||||
'click' : '_onClick'
|
||||
},
|
||||
|
||||
render : function() {
|
||||
this.$el.empty();
|
||||
this.$el.html('<i class="icon-sonarr-delete" title="Delete movie file from disk"></i>');
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_onClick : function() {
|
||||
var self = this;
|
||||
if (window.confirm('Are you sure you want to delete \'{0}\' from disk?'.format(this.model.get('relativePath')))) {
|
||||
this.model.destroy().done(function() {
|
||||
vent.trigger(vent.Events.MovieFileDeleted, { movieFile : self.model });
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
3
src/UI/Movies/Files/FileModel.js
Normal file
3
src/UI/Movies/Files/FileModel.js
Normal file
@ -0,0 +1,3 @@
|
||||
var Backbone = require('backbone');
|
||||
|
||||
module.exports = Backbone.Model.extend({});
|
30
src/UI/Movies/Files/FilesCollection.js
Normal file
30
src/UI/Movies/Files/FilesCollection.js
Normal file
@ -0,0 +1,30 @@
|
||||
var PagableCollection = require('backbone.pageable');
|
||||
var FileModel = require('./FileModel');
|
||||
var AsSortedCollection = require('../../Mixins/AsSortedCollection');
|
||||
|
||||
var Collection = PagableCollection.extend({
|
||||
url : window.NzbDrone.ApiRoot + "/moviefile",
|
||||
model : FileModel,
|
||||
|
||||
state : {
|
||||
pageSize : 2000,
|
||||
sortKey : 'title',
|
||||
order : -1
|
||||
},
|
||||
|
||||
mode : 'client',
|
||||
|
||||
sortMappings : {
|
||||
'quality' : {
|
||||
sortKey : "qualityWeight"
|
||||
},
|
||||
"edition" : {
|
||||
sortKey : "edition"
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
Collection = AsSortedCollection.call(Collection);
|
||||
|
||||
module.exports = Collection;
|
107
src/UI/Movies/Files/FilesLayout.js
Normal file
107
src/UI/Movies/Files/FilesLayout.js
Normal file
@ -0,0 +1,107 @@
|
||||
var vent = require('vent');
|
||||
var Marionette = require('marionette');
|
||||
var Backgrid = require('backgrid');
|
||||
//var ButtonsView = require('./ButtonsView');
|
||||
//var ManualSearchLayout = require('./ManualLayout');
|
||||
var FilesCollection = require('./FilesCollection');
|
||||
var CommandController = require('../../Commands/CommandController');
|
||||
var LoadingView = require('../../Shared/LoadingView');
|
||||
var NoResultsView = require('./NoFilesView');
|
||||
var FileModel = require("./FileModel");
|
||||
var FileTitleCell = require('../../Cells/FileTitleCell');
|
||||
var FileSizeCell = require('../../Cells/FileSizeCell');
|
||||
var QualityCell = require('../../Cells/QualityCell');
|
||||
var MediaInfoCell = require('../../Cells/MediaInfoCell');
|
||||
var ApprovalStatusCell = require('../../Cells/ApprovalStatusCell');
|
||||
var DownloadReportCell = require('../../Release/DownloadReportCell');
|
||||
var AgeCell = require('../../Release/AgeCell');
|
||||
var ProtocolCell = require('../../Release/ProtocolCell');
|
||||
var PeersCell = require('../../Release/PeersCell');
|
||||
var EditionCell = require('../../Cells/EditionCell');
|
||||
var DeleteFileCell = require("./DeleteFileCell");
|
||||
|
||||
module.exports = Marionette.Layout.extend({
|
||||
template : 'Movies/Files/FilesLayoutTemplate',
|
||||
|
||||
regions : {
|
||||
main : '#movie-files-region',
|
||||
grid : "#movie-files-grid"
|
||||
},
|
||||
|
||||
events : {
|
||||
'click .x-search-auto' : '_searchAuto',
|
||||
'click .x-search-manual' : '_searchManual',
|
||||
'click .x-search-back' : '_showButtons'
|
||||
},
|
||||
|
||||
columns : [
|
||||
{
|
||||
name : 'title',
|
||||
label : 'Title',
|
||||
cell : FileTitleCell
|
||||
},
|
||||
{
|
||||
name : "mediaInfo",
|
||||
label : "Media Info",
|
||||
cell : MediaInfoCell
|
||||
},
|
||||
{
|
||||
name : 'edition',
|
||||
label : 'Edition',
|
||||
cell : EditionCell,
|
||||
title : "Edition",
|
||||
},
|
||||
{
|
||||
name : 'size',
|
||||
label : 'Size',
|
||||
cell : FileSizeCell
|
||||
},
|
||||
{
|
||||
name : 'quality',
|
||||
label : 'Quality',
|
||||
cell : QualityCell,
|
||||
},
|
||||
{
|
||||
name : "delete",
|
||||
label : "",
|
||||
cell : DeleteFileCell,
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
initialize : function(movie) {
|
||||
this.filesCollection = new FilesCollection();
|
||||
var file = movie.model.get("movieFile");
|
||||
this.filesCollection.add(file);
|
||||
//this.listenTo(this.releaseCollection, 'sync', this._showSearchResults);
|
||||
},
|
||||
|
||||
onShow : function() {
|
||||
this.grid.show(new Backgrid.Grid({
|
||||
row : Backgrid.Row,
|
||||
columns : this.columns,
|
||||
collection : this.filesCollection,
|
||||
className : 'table table-hover'
|
||||
}));
|
||||
},
|
||||
|
||||
_showMainView : function() {
|
||||
this.main.show(this.mainView);
|
||||
},
|
||||
|
||||
_showButtons : function() {
|
||||
this._showMainView();
|
||||
},
|
||||
|
||||
_showSearchResults : function() {
|
||||
if (this.releaseCollection.length === 0) {
|
||||
this.mainView = new NoResultsView();
|
||||
}
|
||||
|
||||
else {
|
||||
//this.mainView = new ManualSearchLayout({ collection : this.releaseCollection });
|
||||
}
|
||||
|
||||
this._showMainView();
|
||||
}
|
||||
});
|
1
src/UI/Movies/Files/FilesLayoutTemplate.hbs
Normal file
1
src/UI/Movies/Files/FilesLayoutTemplate.hbs
Normal file
@ -0,0 +1 @@
|
||||
<div id="movie-files-region"><div id="movie-files-grid" class="table-responsive"></div></div>
|
5
src/UI/Movies/Files/NoFilesView.js
Normal file
5
src/UI/Movies/Files/NoFilesView.js
Normal file
@ -0,0 +1,5 @@
|
||||
var Marionette = require('marionette');
|
||||
|
||||
module.exports = Marionette.ItemView.extend({
|
||||
template : 'Movies/Files/NoFilesViewTemplate'
|
||||
});
|
3
src/UI/Movies/Files/NoFilesViewTemplate.hbs
Normal file
3
src/UI/Movies/Files/NoFilesViewTemplate.hbs
Normal file
@ -0,0 +1,3 @@
|
||||
<p class="text-warning">
|
||||
No files for this movie.
|
||||
</p>
|
Loading…
Reference in New Issue
Block a user