1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

#680 - added auto organize page

This commit is contained in:
Luke Pulverenti 2014-01-21 01:10:58 -05:00
parent fda9b3d93d
commit 9ab4adcd33
10 changed files with 481 additions and 159 deletions

View file

@ -666,6 +666,37 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
});
};
self.getFileOrganizationResults = function (options) {
var url = self.getUrl("Library/FileOrganization", options || {});
return self.ajax({
type: "GET",
url: url,
dataType: "json"
});
};
self.deleteOriginalFileFromOrganizationResult = function (id) {
var url = self.getUrl("Library/FileOrganizations/" + id + "/File");
return self.ajax({
type: "DELETE",
url: url
});
};
self.performOrganization = function (id) {
var url = self.getUrl("Library/FileOrganizations/" + id + "/Organize");
return self.ajax({
type: "POST",
url: url
});
};
self.getLiveTvSeriesTimer = function (id) {
if (!id) {

View file

@ -76,3 +76,10 @@
background-color: #eeeeee; /* non-RGBA fallback */
background-color: rgba(0,0,0,.1);
}
.stripedTable tbody tr:nth-child(odd) td,
.stripedTable tbody tr:nth-child(odd) th {
background-color: #eeeeee; /* non-RGBA fallback */
background-color: rgba(0,0,0,.04);
}

View file

@ -171,7 +171,7 @@
}
.labelPageSize {
margin-left: 1em;
margin-left: 1em!important;
}

View file

@ -846,3 +846,12 @@ progress {
max-width: 1100px;
}
}
.organizerButtonCell {
white-space: nowrap;
}
.organizerButton {
margin-top: 0;
margin-bottom: 0;
}

View file

@ -1,30 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<title>Media Library</title>
<title>Auto-Organize</title>
</head>
<body>
<div id="libraryFileOrganizerPage" data-role="page" class="page type-interior mediaLibraryPage">
<div id="libraryFileOrganizerPage" data-role="page" class="page type-interior organizePage">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="library.html" data-role="button">Media Folders</a>
<a href="librarysettings.html" data-role="button">Settings</a>
<a href="#" data-role="button" class="ui-btn-active">File Organizer</a>
<a href="libraryfileorganizerlog.html" data-role="button">Activity Log</a>
<a href="#" data-role="button" class="ui-btn-active">TV Settings</a>
</div>
<form class="libraryFileOrganizerForm">
<p>File organizing allows the server to monitor your download folders for new files and move them to your media directories.</p>
<p>The file organizer monitors your download folders for new files and moves them to your media directories.</p>
<div data-role="controlgroup" data-type="horizontal" data-mini="true" class="sortingTabs" style="display: none;">
<input type="radio" name="radioSortingSettingsTab" class="radioSortingSettingsTab" id="radioTvSortingSettings" value="tv" checked="checked">
<label for="radioTvSortingSettings">TV Sorting</label>
<input type="radio" name="radioSortingSettingsTab" class="radioSortingSettingsTab" id="radioMovieSortingSettings" value="movies">
<label for="radioMovieSortingSettings">Movie Sorting</label>
</div>
<div class="tvTab tab">
<p>TV file organizing will only add episodes to existing series. It will not create new series folders.</p>
<ul data-role="listview" class="ulForm" style="margin-bottom: 0!important;">
<li>
@ -44,6 +36,7 @@
<li>
<label for="txtMinFileSize">Minimum file size (MB): </label>
<input type="number" id="txtMinFileSize" name="txtMinFileSize" pattern="[0-9]*" required="required" min="0" data-mini="true" />
<div class="fieldDescription">Files under this size will be ignored.</div>
</li>
<li>
<label for="txtSeasonFolderPattern">Season folder pattern: </label>
@ -77,52 +70,52 @@
</thead>
<tbody>
<tr>
<th>Series Name</th>
<td>Series Name</td>
<td>%sn</td>
<td>Series Name</td>
</tr>
<tr>
<th>Series Name</th>
<td>Series Name</td>
<td>%s.n</td>
<td>Series.Name</td>
</tr>
<tr>
<th>Series Name</th>
<td>Series Name</td>
<td>%s_n</td>
<td>Series_Name</td>
</tr>
<tr>
<th>Season Number</th>
<td>Season Number</td>
<td>%s</td>
<td>1</td>
</tr>
<tr>
<th>Season Number</th>
<td>Season Number</td>
<td>%0s</td>
<td>01</td>
</tr>
<tr>
<th>Episode Number</th>
<td>Episode Number</td>
<td>%e</td>
<td>4</td>
</tr>
<tr>
<th>Episode Number</th>
<td>Episode Number</td>
<td>%0e</td>
<td>04</td>
</tr>
<tr>
<th>Episode Name</th>
<td>Episode Name</td>
<td>%en</td>
<td>Episode Name</td>
</tr>
<tr>
<th>Episode Name</th>
<td>Episode Name</td>
<td>%e.n</td>
<td>Episode.Name</td>
</tr>
<tr>
<th>Episode Name</th>
<td>Episode Name</td>
<td>%e_n</td>
<td>Episode_Name</td>
</tr>
@ -147,7 +140,6 @@
<div class="fieldDescription">With trial mode enabled, file organizations will be logged but not executed.</div>
</li>
</ul>
</div>
<ul data-role="listview" class="ulForm">
<li>

View file

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Auto-Organize</title>
</head>
<body>
<div id="libraryFileOrganizerLogPage" data-role="page" class="page type-interior adminPage organizePage">
<div data-role="content">
<div class="content-primary">
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
<a href="#" data-role="button" class="ui-btn-active">Activity Log</a>
<a href="libraryfileorganizer.html" data-role="button">TV Settings</a>
</div>
<div style="margin: -15px 0 1em;text-align:left;">
<div class="listTopPaging">
</div>
</div>
<table id="movie-table" data-role="table" data-mode="reflow" class="tblOrganizationResults stripedTable ui-responsive table-stroke">
<thead>
<tr>
<th data-priority="2">Date</th>
<th data-priority="1">Source</th>
<th data-priority="3">Destination</th>
<th data-priority="1">Result</th>
<th data-priority="1"></th>
</tr>
</thead>
<tbody class="resultBody">
</tbody>
</table>
<br />
<div class="listBottomPaging">
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -1426,7 +1426,7 @@
return html;
},
getPagingHtml: function (query, totalRecordCount, updatePageSizeSetting, pageSizes) {
getPagingHtml: function (query, totalRecordCount, updatePageSizeSetting, pageSizes, showLimit) {
if (query.Limit && updatePageSizeSetting !== false) {
localStorage.setItem('pagesize', query.Limit);
@ -1451,7 +1451,7 @@
var recordsEnd = Math.min(query.StartIndex + query.Limit, totalRecordCount);
// 20 is the minimum page size
var showControls = totalRecordCount > 20;
var showControls = totalRecordCount > 20 || query.Limit < totalRecordCount;
html += '<div class="listPaging">';
@ -1461,16 +1461,20 @@
html += startAtDisplay + '-' + recordsEnd + ' of ' + totalRecordCount;
if (showControls) {
html += ', page ' + dropdownHtml + ' of ' + pageCount;
//html += ', page ' + dropdownHtml + ' of ' + pageCount;
}
html += '</span>';
if (showControls) {
html += '<div data-role="controlgroup" data-type="horizontal" style="display:inline-block;">';
html += '<button data-icon="arrow-l" data-iconpos="notext" data-inline="true" data-mini="true" class="btnPreviousPage" ' + (query.StartIndex ? '' : 'disabled') + '>Previous Page</button>';
html += '<button data-icon="arrow-r" data-iconpos="notext" data-inline="true" data-mini="true" class="btnNextPage" ' + (query.StartIndex + query.Limit > totalRecordCount ? 'disabled' : '') + '>Next Page</button>';
html += '</div>';
if (showLimit !== false) {
var id = "selectPageSize" + new Date().getTime();
var options = '';
@ -1495,6 +1499,7 @@
// Add styles to defeat jquery mobile
html += '<label style="display:inline;font-size:inherit;" class="labelPageSize" for="' + id + '">Limit: </label><select class="selectPageSize" id="' + id + '" data-enhance="false" data-role="none">' + options + '</select>';
}
}
html += '</div>';

View file

@ -52,13 +52,13 @@
var page = this;
$('#txtSeasonFolderPattern', page).on('change keypress', function() {
$('#txtSeasonFolderPattern', page).on('change keyup', function () {
updateSeasonPatternHelp(page, this.value);
});
$('#txtEpisodePattern', page).on('change keypress', function () {
$('#txtEpisodePattern', page).on('change keyup', function () {
updateEpisodePatternHelp(page, this.value);

View file

@ -0,0 +1,237 @@
(function ($, document, window) {
var query = {
StartIndex: 0,
Limit: 50
};
var currentResult;
function showStatusMessage(id) {
var item = currentResult.Items.filter(function (i) {
return i.Id == id;
})[0];
Dashboard.alert({
title: getStatusText(item, false),
message: item.StatusMessage
});
}
function deleteOriginalFile(page, id) {
var item = currentResult.Items.filter(function (i) {
return i.Id == id;
})[0];
var message = 'The following file will be deleted:<p>' + item.OriginalPath + '</p><p>Are you sure you wish to proceed?</p>';
Dashboard.confirm(message, "Delete File", function (confirmResult) {
if (confirmResult) {
Dashboard.showLoadingMsg();
ApiClient.deleteOriginalFileFromOrganizationResult(id).done(function () {
Dashboard.hideLoadingMsg();
reloadItems(page);
});
}
});
}
function organizeFile(page, id) {
var item = currentResult.Items.filter(function (i) {
return i.Id == id;
})[0];
var message = 'The following file will be moved from:<p>' + item.OriginalPath + '</p><p>to:</p><p>' + item.TargetPath + '</p><p>Are you sure you wish to proceed?</p>';
Dashboard.confirm(message, "Organize File", function (confirmResult) {
if (confirmResult) {
Dashboard.showLoadingMsg();
ApiClient.performOrganization(id).done(function () {
Dashboard.hideLoadingMsg();
reloadItems(page);
});
}
});
}
function reloadItems(page) {
Dashboard.showLoadingMsg();
ApiClient.getFileOrganizationResults(query).done(function (result) {
currentResult = result;
renderResults(page, result);
Dashboard.hideLoadingMsg();
});
}
function getStatusText(item, enhance) {
var status = item.Status;
var color = null;
if (status == 'SkippedTrial') {
status = 'Trial';
}
else if (status == 'SkippedExisting') {
status = 'Skipped';
}
else if (status == 'Failure') {
color = '#cc0000';
status = 'Failed';
}
if (status == 'Success') {
color = 'green';
status = 'Success';
}
if (enhance && enhance) {
if (item.StatusMessage) {
return '<a style="color:' + color + ';" data-resultid="' + item.Id + '" href="#" class="btnShowStatusMessage">' + status + '</a>';
} else {
return '<span data-resultid="' + item.Id + '" style="color:' + color + ';">' + status + '</span>';
}
}
return status;
}
function renderResults(page, result) {
var rows = result.Items.map(function (item) {
var html = '';
html += '<tr>';
html += '<td>';
var date = parseISO8601Date(item.Date, { toLocal: true });
html += date.toLocaleDateString();
html += '</td>';
html += '<td>';
html += item.OriginalFileName || '';
html += '</td>';
html += '<td>';
html += item.TargetPath || '';
html += '</td>';
html += '<td>';
html += getStatusText(item, true);
html += '</td>';
html += '<td class="organizerButtonCell">';
if (item.Status == 'SkippedTrial' || item.Status == 'SkippedExisting') {
html += '<button data-resultid="' + item.Id + '" type="button" data-inline="true" data-icon="action" data-mini="true" data-iconpos="notext" class="btnProcessResult organizerButton" title="Organize File">Process</button>';
} else {
html += '<button style="visibility:hidden;" type="button" data-inline="true" data-icon="info" data-mini="true" data-iconpos="notext" class="organizerButton"></button>';
}
if (item.Status != 'Success') {
html += '<button data-resultid="' + item.Id + '" type="button" data-inline="true" data-icon="delete" data-mini="true" data-iconpos="notext" class="btnDeleteResult organizerButton" title="Delete">Delete File</button>';
}
html += '</td>';
html += '</tr>';
return html;
}).join('');
var elem = $('.resultBody', page).html(rows).parents('.tblOrganizationResults').table("refresh").trigger('create');
$('.btnShowStatusMessage', elem).on('click', function () {
var id = this.getAttribute('data-resultid');
showStatusMessage(id);
});
$('.btnProcessResult', elem).on('click', function () {
var id = this.getAttribute('data-resultid');
organizeFile(page, id);
});
$('.btnDeleteResult', elem).on('click', function () {
var id = this.getAttribute('data-resultid');
deleteOriginalFile(page, id);
});
var pagingHtml = LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);
$('.listTopPaging', page).html(pagingHtml).trigger('create');
if (result.TotalRecordCount > query.Limit && result.TotalRecordCount > 50) {
$('.listBottomPaging', page).html(pagingHtml).trigger('create');
} else {
$('.listBottomPaging', page).empty();
}
$('.selectPage', page).on('change', function () {
query.StartIndex = (parseInt(this.value) - 1) * query.Limit;
reloadItems(page);
});
$('.btnNextPage', page).on('click', function () {
query.StartIndex += query.Limit;
reloadItems(page);
});
$('.btnPreviousPage', page).on('click', function () {
query.StartIndex -= query.Limit;
reloadItems(page);
});
}
$(document).on('pageshow', "#libraryFileOrganizerLogPage", function () {
var page = this;
reloadItems(page);
}).on('pagehide', "#libraryFileOrganizerLogPage", function () {
currentResult = null;
});
})(jQuery, document, window);

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.238" targetFramework="net45" />
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.240" targetFramework="net45" />
</packages>