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

update file organizer form

This commit is contained in:
Luke Pulverenti 2016-02-12 23:34:47 -05:00
parent c0d966f1d8
commit 79cf0837a0
4 changed files with 134 additions and 587 deletions

View file

@ -1,490 +1,130 @@
define(['paperdialoghelper', 'paper-tabs', 'paper-item', 'paper-input', 'paper-fab', 'paper-item-body'], function (paperDialogHelper) {
define(['paperdialoghelper', 'paper-checkbox', 'paper-input', 'paper-button'], function (paperDialogHelper) {
var currentItemId;
var currentFile;
var currentDeferred;
var hasChanges = false;
var reloadItems;
function onApiFailure(e) {
function submitEpisodeForm(form) {
Dashboard.hideLoadingMsg();
Dashboard.alert({
title: Globalize.translate('AutoOrganizeError'),
message: Globalize.translate('ErrorOrganizingFileWithErrorCode', e.getResponseHeader("X-Application-Error-Code"))
});
}
function initEpisodeForm(context, item) {
$('.inputFile', context).html(item.OriginalFileName);
$('#txtSeason', context).val(item.ExtractedSeasonNumber);
$('#txtEpisode', context).val(item.ExtractedEpisodeNumber);
$('#txtEndingEpisode', context).val(item.ExtractedEndingEpisodeNumber);
$('#chkRememberCorrection', context).val(false);
$('#hfResultId', context).val(item.Id);
ApiClient.getItems(null, {
recursive: true,
includeItemTypes: 'Series',
sortBy: 'SortName'
}).then(function (result) {
var seriesHtml = result.Items.map(function (s) {
return '<option value="' + s.Id + '">' + s.Name + '</option>';
}).join('');
seriesHtml = '<option value=""></option>' + seriesHtml;
$('#selectSeries', context).html(seriesHtml);
}, onApiFailure);
}
function submitEpisodeForm(dlg) {
Dashboard.showLoadingMsg();
var resultId = $('#hfResultId', form).val();
var targetFolder = $('#spanTargetFolder', form).text();
var elemString = $('#hfNewSeriesProviderIds', form).val();
var newSeriesName = $('#hfNewSeriesName', form).val();
var newSeriesYear = $('#hfNewSeriesYear', form).val();
var resultId = $('#hfResultId', dlg).val();
var options = {
SeriesId: $('#selectSeries', form).val(),
SeasonNumber: $('#txtSeason', form).val(),
EpisodeNumber: $('#txtEpisode', form).val(),
EndingEpisodeNumber: $('#txtEndingEpisode', form).val(),
RememberCorrection: $('#chkRememberCorrection', form).checked(),
NewSeriesProviderIds: elemString,
NewSeriesName: newSeriesName,
NewSeriesYear: newSeriesYear,
TargetFolder: targetFolder
SeriesId: $('#selectSeries', dlg).val(),
SeasonNumber: $('#txtSeason', dlg).val(),
EpisodeNumber: $('#txtEpisode', dlg).val(),
EndingEpisodeNumber: $('#txtEndingEpisode', dlg).val(),
RememberCorrection: $('#chkRememberCorrection', dlg).checked()
};
ApiClient.performEpisodeOrganization(resultId, options).then(function () {
Dashboard.hideLoadingMsg();
document.querySelector('.organizerDialog').close();
reloadItems();
dlg.submitted = true;
paperDialogHelper.close(dlg);
}, onApiFailure);
}
function submitMovieForm(form) {
return {
show: function (item) {
return new Promise(function (resolve, reject) {
Dashboard.showLoadingMsg();
var xhr = new XMLHttpRequest();
xhr.open('GET', 'components/fileorganizer/fileorganizer.template.html', true);
var resultId = $('#hfResultIdMovie', form).val();
xhr.onload = function (e) {
var targetFolder = $('#selectMovieFolder', form).val();
var options = {
MovieName: $('#txtMovieName', form).val(),
MovieYear: $('#txtMovieYear', form).val(),
TargetFolder: targetFolder
};
ApiClient.performMovieOrganization(resultId, options).then(function () {
Dashboard.hideLoadingMsg();
document.querySelector('.organizerDialog').close();
reloadItems();
}, onApiFailure);
}
function searchForIdentificationResults(popup, itemtype) {
var lookupInfo = {
Name: $('#txtMovieName', popup).val(),
Year: $('#txtMovieYear', popup).val(),
};
var url = ApiClient.getUrl("Items/RemoteSearch/Movie");
if (itemtype == 'tvshows') {
lookupInfo.Name = $('#txtNewSeriesName', popup).val();
lookupInfo.Year = $('#txtNewSeriesYear', popup).val();
url = ApiClient.getUrl("Items/RemoteSearch/Series");
}
if (!lookupInfo.Name) {
Dashboard.alert(Globalize.translate('MessagePleaseEnterNameOrId'));
return;
}
lookupInfo = {
SearchInfo: lookupInfo,
IncludeDisabledProviders: true
};
Dashboard.showLoadingMsg();
ApiClient.ajax({
type: "POST",
url: url,
data: JSON.stringify(lookupInfo),
dataType: "json",
contentType: "application/json"
}).then(function (results) {
Dashboard.hideLoadingMsg();
showIdentificationSearchResults(popup, results, itemtype);
$('#btnBack', popup).off('click').on('click', function () {
$('.identificationResultForm', popup).hide();
$('.organizeMovieForm', popup).show();
$('.createSeriesForm', popup).show();
if (itemtype == 'tvshows') {
$('#btnBack', popup).off('click').on('click', function () {
$('.createSeriesForm', popup).hide();
$('.episodeCorrectionForm', popup).show();
$('#btnBack', popup).off('click').on('click', function () {
popup.close();
});
});
}
else {
$('#btnBack', popup).off('click').on('click', function () {
popup.close();
var template = this.response;
var dlg = paperDialogHelper.createDialog({
removeOnClose: true,
size: 'small'
});
dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a');
dlg.classList.add('formDialog');
var html = '';
html += Globalize.translateDocument(template);
dlg.innerHTML = html;
document.body.appendChild(dlg);
dlg.querySelector('.dialogHeaderTitle').innerHTML = Globalize.translate('FileOrganizeManually');
paperDialogHelper.open(dlg);
dlg.addEventListener('iron-overlay-closed', function () {
if (dlg.submitted) {
resolve();
} else {
reject();
}
});
dlg.querySelector('.btnCancel').addEventListener('click', function (e) {
paperDialogHelper.close(dlg);
});
dlg.querySelector('form').addEventListener('submit', function (e) {
submitEpisodeForm(dlg);
e.preventDefault();
return false;
});
initEpisodeForm(dlg, item);
}
xhr.send();
});
}, onApiFailure);
}
function showIdentificationSearchResults(popup, results, itemtype) {
$('.organizeMovieForm', popup).hide();
$('.createSeriesForm', popup).hide();
$('.identificationResultForm', popup).show();
var html = '';
for (var i = 0, length = results.length; i < length; i++) {
var result = results[i];
html += getIdentifyResultHtml(result, i);
}
var elem = $('.identificationSearchResultList', popup).html(html).trigger('create');
$('.searchImage', elem).on('click', function () {
var index = parseInt(this.getAttribute('data-index'));
var currentResult = results[index];
$('.identificationResultForm', popup).hide();
var targetName = currentResult.Name;
if (currentResult.ProductionYear) {
targetName = targetName + ' (' + currentResult.ProductionYear + ')';
}
if (itemtype == 'tvshows') {
$('#txtNewSeriesName', popup).val(currentResult.Name);
$('#txtNewSeriesYear', popup).val(currentResult.ProductionYear);
$('#txtSelectedNewSeries', popup).val(targetName);
$('#txtSelectedNewSeries2', popup).val(targetName);
$('#hfNewSeriesName', popup).val(currentResult.Name);
$('#hfNewSeriesYear', popup).val(currentResult.ProductionYear);
var elems = currentResult.ProviderIds;
$('#hfNewSeriesProviderIds', popup).val(JSON.stringify(elems));
$('.createSeriesForm', popup).show();
$('#btnBack', popup).off('click').on('click', function () {
$('.createSeriesForm', popup).hide();
$('.episodeCorrectionForm', popup).show();
$('#btnBack', popup).off('click').on('click', function () {
popup.close();
});
});
}
else {
$('#txtMovieName', popup).val(currentResult.Name);
$('#txtMovieYear', popup).val(currentResult.ProductionYear);
$('#txtSelectedMovie', popup).val(targetName);
$('.organizeMovieForm', popup).show();
$('#btnBack', popup).off('click').on('click', function () {
popup.close();
});
}
});
}
function getSearchImageDisplayUrl(url, provider) {
return ApiClient.getUrl("Items/RemoteSearch/Image", { imageUrl: url, ProviderName: provider });
}
function getIdentifyResultHtml(result, index) {
var html = '';
var cssClass = "searchImageContainer remoteImageContainer";
cssClass += " searchPosterImageContainer";
html += '<div class="' + cssClass + '">';
if (result.ImageUrl) {
var displayUrl = getSearchImageDisplayUrl(result.ImageUrl, result.SearchProviderName);
html += '<a href="#" class="searchImage" data-index="' + index + '" style="background-image:url(\'' + displayUrl + '\');">';
} else {
html += '<a href="#" class="searchImage iconCardImage" data-index="' + index + '"><iron-icon icon="search"></iron-icon>';
}
html += '</a>';
html += '<div class="remoteImageDetails" style="background-color: transparent">';
html += result.Name;
html += '</div>';
html += '<div class="remoteImageDetails" style="background-color: transparent">';
html += result.ProductionYear || '&nbsp;';
html += '</div>';
html += '</div>';
return html;
}
function onEpisodeCorrectionFormSubmit() {
submitEpisodeForm(this);
return false;
}
function onOrganizeMovieFormFormSubmit() {
submitMovieForm(this);
return false;
}
function showTab(popup, index) {
$('.organizeMovieForm', popup).show();
$('.episodeCorrectionForm', popup).show();
$('.identificationResultForm', popup).hide();
$('.createSeriesForm', popup).hide();
$('.popupTabPage', popup).addClass('hide')[index].classList.remove('hide');
$('#btnBack', popup).off('click').on('click', function () {
popup.close();
});
}
function initEditor(popup, item, allSeries, movieLocations, seriesLocations) {
$('#divNewSeries', popup).hide();
showTab(popup, 0);
$('.inputFile', popup).html(item.OriginalFileName);
$('#txtSeason', popup).val(item.ExtractedSeasonNumber);
$('#txtEpisode', popup).val(item.ExtractedEpisodeNumber);
$('#txtEndingEpisode', popup).val(item.ExtractedEndingEpisodeNumber);
$('#chkRememberCorrection', popup).val(false);
$('.extractedName', popup).html(item.ExtractedName);
if (!item.ExtractedName || item.ExtractedName.length < 4) {
$('#divRememberCorrection', popup).hide();
}
$('#txtNewSeriesName', popup).val(item.ExtractedName);
$('#txtNewSeriesYear', popup).val(item.ExtractedYear);
$('#hfResultId', popup).val(item.Id);
$('#hfResultIdMovie', popup).val(item.Id);
$('#hfNewSeriesProviderIds', popup).val(null);
$('#hfNewSeriesName', popup).val(null);
$('#hfNewSeriesYear', popup).val(null);
$('#txtSelectedNewSeries', popup).val(null);
$('#txtSelectedNewSeries2', popup).val(null);
$('#txtMovieName', popup).val(item.ExtractedMovieName);
$('#txtMovieYear', popup).val(item.ExtractedMovieYear);
$('#txtSelectedMovie', popup).val(null);
var seriesHtml = allSeries.map(function (s) {
return '<option value="' + s.Id + '">' + s.Name + '</option>';
}).join('');
seriesHtml = '<option value=""></option>' + seriesHtml;
$('#selectSeries', popup).html(seriesHtml);
var movieFolderHtml = movieLocations.map(function (s) {
return '<option value="' + s.value + '">' + s.display + '</option>';
}).join('');
if (movieLocations.length > 1) {
movieFolderHtml = '<option value=""></option>' + movieFolderHtml;
}
var seriesFolderHtml = seriesLocations.map(function (s) {
return '<option value="' + s.value + '">' + s.display + '</option>';
}).join('');
if (seriesLocations.length > 1) {
seriesFolderHtml = '<option value=""></option>' + seriesFolderHtml;
}
$('#selectMovieFolder', popup).html(movieFolderHtml);
$('#selectSeriesFolder', popup).html(seriesFolderHtml);
$('.episodeCorrectionForm').off('submit', onEpisodeCorrectionFormSubmit).on('submit', onEpisodeCorrectionFormSubmit);
$('.organizeMovieForm').off('submit', onOrganizeMovieFormFormSubmit).on('submit', onOrganizeMovieFormFormSubmit);
$('#btnIdentifyMovie', popup).on('click', function () {
searchForIdentificationResults(popup, 'movies');
});
$('#btnIdentifySeries', popup).on('click', function () {
searchForIdentificationResults(popup, 'tvshows');
});
$('.txt-readonly', popup).keydown(function (e) {
e.preventDefault();
});
$('#btnNewSeries', popup).on('click', function () {
$('.episodeCorrectionForm', popup).hide();
$('.createSeriesForm', popup).show();
$('#btnBack', popup).off('click').on('click', function () {
$('.createSeriesForm', popup).hide();
$('.episodeCorrectionForm', popup).show();
$('#btnBack', popup).off('click').on('click', function () {
popup.close();
});
});
});
$('.createSeriesForm').off('submit').on('submit', function () {
var folder = $('#selectSeriesFolder', popup).val();
$('#spanTargetFolder', popup).text(folder);
$('#divSelectSeries', popup).hide();
$('#divNewSeries', popup).show();
$('.episodeCorrectionForm', popup).show();
$('.createSeriesForm', popup).hide();
$('#btnBack', popup).off('click').on('click', function () {
popup.close();
});
return false;
});
}
function showEditor(page, item, allSeries, movieLocations, seriesLocations, reloadDelegate) {
reloadItems = reloadDelegate;
var xhr = new XMLHttpRequest();
xhr.open('GET', 'components/fileorganizer/fileorganizer.template.html', true);
xhr.onload = function (e) {
var template = this.response;
var dlg = createDialog();
dlg.setAttribute('id', 'with-backdrop');
var html = '';
//html += '<div class="ui-bar-a" style="text-align: left; padding: 10px 15px; margin: 0">';
html += '<h2 class="dialogHeader">';
html += '<paper-fab icon="arrow-back" mini class="btnCloseDialog" id="btnBack"></paper-fab>';
html += '<div style="display:inline-block;margin-left:.6em;vertical-align:middle;">' + Globalize.translate('FileOrganizeManually') + '</div>';
html += '</h2>';
//html += '</div>';
html += '<div style="padding:0; margin: 10px 0px 0px 0px"><paper-tabs hidescrollbuttons selected="0">';
html += '<paper-tab id="popupTab1" class="episodeTabButton">TV Episode</paper-tab>';
html += '<paper-tab id="popupTab2" class="movieTabButton">Movie</paper-tab>';
html += '</paper-tabs></div>';
html += '<div class="editorContent" style="margin:auto;">';
html += Globalize.translateDocument(template);
html += '</div>';
dlg.innerHTML = html;
document.body.appendChild(dlg);
initEditor(dlg, item, allSeries, movieLocations, seriesLocations);
// Has to be assigned a z-index after the call to .open()
$(dlg).on('iron-overlay-closed', onDialogClosed);
var tabs = dlg.querySelector('paper-tabs');
$(tabs).on('iron-select', function () {
var self = this;
var selected = this.selected;
showTab(dlg, selected);
//setTimeout(function () {
// Events.trigger(self, 'tabchange');
//}, 400);
});
//.on('tabchange', function () {
// var selected = this.selected;
// showTab(dlg, selected);
//});
dlg.classList.add('organizerDialog');
paperDialogHelper.open(dlg);
//PaperDialogHelper.openWithHash(dlg, 'fileorganizer');
//dlg.open();
$('#btnBack', dlg).on('click', function () {
paperDialogHelper.close(dlg);
});
};
xhr.send();
}
function createDialog() {
//var dlg = document.createElement('paper-dialog');
var dlg = paperDialogHelper.createDialog({
removeOnClose: true
});
dlg.classList.add('ui-body-a');
dlg.classList.add('background-theme-a');
return dlg;
}
function onApiFailure(e) {
Dashboard.hideLoadingMsg();
document.querySelector('.organizerDialog').close();
if (e.status == 0) {
Dashboard.alert({
title: 'Auto-Organize',
message: 'The operation is going to take a little longer. The view will be updated on completion.'
});
}
else {
Dashboard.alert({
title: Globalize.translate('AutoOrganizeError'),
message: Globalize.translate('ErrorOrganizingFileWithErrorCode', e.getResponseHeader("X-Application-Error-Code"))
});
}
}
function onDialogClosed() {
$(this).remove();
Dashboard.hideLoadingMsg();
currentDeferred.resolveWith(null, [hasChanges]);
}
window.FileOrganizer = {
show: function (page, item, allSeries, movieLocations, seriesLocations, reloadDelegate) {
var deferred = DeferredBuilder.Deferred();
currentDeferred = deferred;
hasChanges = false;
showEditor(page, item, allSeries, movieLocations, seriesLocations, reloadDelegate);
return deferred.promise();
}
};
});
});

View file

@ -1,127 +1,34 @@
<div class="dialogHeader">
<paper-icon-button icon="close" class="btnCancel" tabindex="-1"></paper-icon-button>
<div class="dialogHeaderTitle">
${HeaderInviteUser}
</div>
</div>
<div class="popupTabPage">
<form class="episodeCorrectionForm">
<p><span class="inputFile"></span></p>
<div class="layout horizontal center-center" style="margin: 1em 0 1em;" id="divSelectSeries">
<div>
<label for="selectSeries">${LabelSeries}</label>
<select id="selectSeries" data-mini="true"></select>
</div>
<button type="button" id="btnNewSeries" data-icon="add" data-mini="true" style="width: auto; margin-left: 15px !important; margin-top: 13px !important">
New
</button>
</div>
<div style="margin: 1em 0 1em; display: none" id="divNewSeries">
<label for="txtSelectedNewSeries2">New Series</label>
<input id="txtSelectedNewSeries2" class="txt-readonly" disabled />
<div class="fieldDescription"><span id="spanTargetFolder"></span></div>
</div>
<div style="margin: 1em 0;">
<label for="txtSeason">${LabelSeasonNumber}</label>
<input id="txtSeason" type="number" pattern="[0-9]*" required="required" min="0" />
</div>
<div style="margin: 1em 0;">
<label for="txtEpisode">${LabelEpisodeNumber}</label>
<input id="txtEpisode" type="number" pattern="[0-9]*" required="required" min="0" />
</div>
<div style="margin: 1em 0;">
<label for="txtEndingEpisode">${LabelEndingEpisodeNumber}</label>
<input id="txtEndingEpisode" type="number" pattern="[0-9]*" min="0" />
<div class="fieldDescription">${LabelEndingEpisodeNumberHelp}</div>
</div>
<div id="divRememberCorrection" style="margin: 1em 0;">
<label style="display:block">${TabSmartMatch}</label>
<input type="checkbox" id="chkRememberCorrection" name="chkRememberCorrection" data-mini="true" />
<label for="chkRememberCorrection">${LabelOrganizeSmartMatchOption}: <span class="extractedName" style="font-weight: bold; font-style: italic" /></label>
</div>
<p>
<button type="submit" data-theme="b" data-icon="check" data-mini="true">
${ButtonOk}
</button>
</p>
<input id="hfResultId" type="hidden" />
<input id="hfNewSeriesProviderIds" type="hidden" />
<input id="hfNewSeriesName" type="hidden" />
<input id="hfNewSeriesYear" type="hidden" />
</form>
<form class="episodeCorrectionForm" style="margin:auto;">
<form class="createSeriesForm">
<p><span class="inputFile"></span></p>
<div style="margin: 1em 0 1em;">
<label for="txtNewSeriesName">${LabelSeries}</label>
<input id="txtNewSeriesName" required="required" />
</div>
<div style="margin: 1em 0;">
<label for="txtNewSeriesYear">${LabelYear}</label>
<input id="txtNewSeriesYear" type="number" pattern="[0-9]*" min="0" />
</div>
<div style="margin: 1em 0;">
<button type="button" data-icon="info" id="btnIdentifySeries" data-mini="true">
${ButtonIdentify}
</button>
</div>
<div style="margin: 1em 0 1em;">
<label for="txtSelectedNewSeries">Selected Series</label>
<!-- When setting the disabled attribute, the required checking on submit does not work.
Therefore class text-readonly is used instead to prevent keyboard input -->
<input id="txtSelectedNewSeries" class="txt-readonly" required="required" />
</div>
<div style="margin: 1em 0 1em;">
<label for="selectSeriesFolder">Destination Folder</label>
<select id="selectSeriesFolder" data-mini="true" required="required"></select>
</div>
<p>
<button type="submit" id="btnCreateNewSeries" data-theme="b" data-icon="check" data-mini="true">
Create Series
</button>
</p>
</form>
<p><span class="inputFile"></span></p>
</div>
<div class="popupTabPage hide">
<form class="organizeMovieForm">
<p><span class="inputFile"></span></p>
<div style="margin: 1em 0 1em; min-width: 350px;">
<label for="txtMovieName">Movie</label>
<input id="txtMovieName" required="required" min="0" />
</div>
<div style="margin: 1em 0;">
<label for="txtMovieYear">Year</label>
<input id="txtMovieYear" type="number" pattern="[0-9]*" min="0" />
</div>
<div style="margin: 1em 0;">
<button type="button" data-icon="info" id="btnIdentifyMovie" data-mini="true">
${ButtonIdentify}
</button>
</div>
<div style="margin: 1em 0 1em;">
<label for="txtSelectedMovie">Selected Movie</label>
<input id="txtSelectedMovie" class="txt-readonly" required="required" />
</div>
<div style="margin: 1em 0 1em; min-width: 350px;">
<label for="selectMovieFolder">Destination Folder</label>
<select id="selectMovieFolder" data-mini="true" required="required"></select>
</div>
<p>
<button type="submit" data-theme="b" data-icon="check" data-mini="true">
${ButtonOk}
</button>
</p>
<input id="hfResultIdMovie" type="hidden" />
</form>
</div>
<div class="identificationResultForm">
<form>
<div class="identificationSearchResults" style="height:auto; min-width: 350px; min-height: 350px;">
<div class="identificationSearchResultList"></div>
</div>
</form>
</div>
<div style="margin: 1em 0 1em; min-width: 250px;">
<label for="selectSeries" class="selectLabel">${LabelSeries}</label>
<select id="selectSeries" data-mini="true" required="required"></select>
</div>
<div style="margin: 1em 0;">
<paper-input id="txtSeason" type="number" pattern="[0-9]*" required min="0" label="${LabelSeasonNumber}"></paper-input>
</div>
<div style="margin: 1em 0;">
<paper-input id="txtEpisode" type="number" pattern="[0-9]*" required min="0" label="${LabelEpisodeNumber}"></paper-input>
</div>
<div style="margin: 1em 0;">
<paper-input id="txtEndingEpisode" type="number" pattern="[0-9]*" min="0" label="${LabelEndingEpisodeNumber}"></paper-input>
<div class="fieldDescription">${LabelEndingEpisodeNumberHelp}</div>
</div>
<br />
<div>
<paper-checkbox type="checkbox" id="chkRememberCorrection">${OptionRememberOrganizeCorrection}</paper-checkbox>
</div>
<br />
<button type="submit" data-role="none" class="clearButton">
<paper-button raised class="submit block"><iron-icon icon="check"></iron-icon><span>${ButtonOk}</span></paper-button>
</button>
<input id="hfResultId" type="hidden" />
</form>

View file

@ -109,8 +109,8 @@
html += Globalize.translateDocument(template);
dlg.innerHTML = html;
// needed for the collapsible
document.body.appendChild(dlg);
// needed for the collapsible
$(dlg.querySelector('form')).trigger('create');
paperDialogHelper.open(dlg);

View file

@ -97,11 +97,11 @@
}, onApiFailure);
}
function showEpisodeCorrectionPopup(page, item, allSeries, movieLocations, seriesLocations) {
function showEpisodeCorrectionPopup(page, item) {
require(['components/fileorganizer/fileorganizer'], function () {
require(['components/fileorganizer/fileorganizer'], function (fileorganizer) {
FileOrganizer.show(page, item, allSeries, movieLocations, seriesLocations, function () {
fileorganizer.show(item).then(function () {
reloadItems(page);
});
});