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

create sync job items pages

This commit is contained in:
Luke Pulverenti 2014-12-31 01:24:49 -05:00
parent 955e6cda51
commit 25a2d421dc
10 changed files with 442 additions and 23 deletions

View file

@ -18,7 +18,7 @@
<h2 class="pluginName"></h2> <h2 class="pluginName"></h2>
<p id="tagline" style="font-style: italic;"></p> <p id="tagline" style="font-style: italic;"></p>
<p id="pPreviewImage" style="text-align: center;"></p> <p id="pPreviewImage"></p>
<p id="overview"></p> <p id="overview"></p>

View file

@ -1260,7 +1260,7 @@ a.itemTag:hover {
.listItem a:first-child { .listItem a:first-child {
margin-right: 0 !important; margin-right: 0 !important;
background-color: transparent !important; background-color: transparent !important;
border-color: #282828 !important; border-color: #d8d8d8 !important;
} }
.listItem a + a { .listItem a + a {
@ -1269,9 +1269,17 @@ a.itemTag:hover {
} }
.listItem:hover a { .listItem:hover a {
background-color: #eee !important;
}
.page[data-theme='b'] .listItem:hover a {
background-color: #333 !important; background-color: #333 !important;
} }
.page[data-theme='b'] .listItem a:first-child {
border-color: #282828 !important;
}
@media all and (max-width: 600px) { @media all and (max-width: 600px) {
.itemsListview .ui-li-aside { .itemsListview .ui-li-aside {

24
dashboard-ui/mysync.html Normal file
View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>${TitleSync}</title>
</head>
<body>
<div id="mySyncActivityPage" data-role="page" data-theme="b" class="page libraryPage syncActivityPage mySyncPage" data-contextname="${TitleSync}">
<div class="libraryViewNav">
<a href="#" class="ui-btn-active">${TabSyncJobs}</a>
</div>
<div data-role="content">
<div class="ehsContent">
<br/>
<div class="syncActivity">
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<title>${TitleSync}</title>
</head>
<body>
<div id="mySyncJobPage" data-role="page" data-theme="b" class="page libraryPage syncJobPage mySyncPage" data-contextname="${TitleSync}">
<div class="libraryViewNav">
<a href="mysync.html" class="ui-btn-active">${TabSyncJobs}</a>
</div>
<div data-role="content">
<div class="readOnlyContent" style="margin: 0 auto;">
<h1>${HeaderSyncJobInfo}</h1>
<form class="syncJobForm"></form>
<br />
<br />
<div class="jobItems"></div>
</div>
</div>
<script type="text/javascript">
$('.syncJobForm').off('submit', SyncJobPage.onSubmit).on('submit', SyncJobPage.onSubmit);
</script>
</div>
</body>
</html>

View file

@ -76,12 +76,13 @@
html += '<div class="libraryMenuOptions">'; html += '<div class="libraryMenuOptions">';
html += '</div>'; html += '</div>';
html += '<div class="adminMenuOptions">';
html += '<div class="libraryMenuDivider"></div>'; html += '<div class="libraryMenuDivider"></div>';
html += '<div class="adminMenuOptions">';
html += '<a class="viewMenuLink viewMenuTextLink lnkMediaFolder editorViewMenu iconViewMenu" data-itemid="editor" href="edititemmetadata.html"><span class="fa fa-edit"></span>' + Globalize.translate('ButtonMetadataManager') + '</a>'; html += '<a class="viewMenuLink viewMenuTextLink lnkMediaFolder editorViewMenu iconViewMenu" data-itemid="editor" href="edititemmetadata.html"><span class="fa fa-edit"></span>' + Globalize.translate('ButtonMetadataManager') + '</a>';
html += '<a class="viewMenuLink viewMenuTextLink lnkMediaFolder reportsViewMenu iconViewMenu" data-itemid="reports" href="reports.html"><span class="fa fa-bar-chart"></span>' + Globalize.translate('ButtonReports') + '</a>'; html += '<a class="viewMenuLink viewMenuTextLink lnkMediaFolder iconViewMenu" data-itemid="reports" href="reports.html"><span class="fa fa-bar-chart"></span>' + Globalize.translate('ButtonReports') + '</a>';
html += '</div>'; html += '</div>';
html += '<a class="viewMenuLink viewMenuTextLink lnkMediaFolder iconViewMenu syncViewMenu" data-itemid="mysync" href="mysync.html"><span class="fa fa-cloud"></span>' + Globalize.translate('ButtonSync') + '</a>';
return html; return html;
} }
@ -120,6 +121,7 @@
if (!apiClient) { if (!apiClient) {
$('.adminMenuOptions').hide(); $('.adminMenuOptions').hide();
$('.syncViewMenu').hide();
return; return;
} }
@ -196,6 +198,11 @@
} else { } else {
$('.adminMenuOptions').hide(); $('.adminMenuOptions').hide();
} }
if (user.Policy.EnableSync) {
$('.syncViewMenu').show();
} else {
$('.syncViewMenu').hide();
}
}); });
} }
@ -305,8 +312,9 @@
var isChannelsPage = page.hasClass('channelsPage'); var isChannelsPage = page.hasClass('channelsPage');
var isEditorPage = page.hasClass('metadataEditorPage'); var isEditorPage = page.hasClass('metadataEditorPage');
var isReportsPage = page.hasClass('reportsPage'); var isReportsPage = page.hasClass('reportsPage');
var isMySyncPage = page.hasClass('mySyncPage');
var id = isLiveTvPage || isChannelsPage || isEditorPage || isReportsPage || page.hasClass('allLibraryPage') ? var id = isLiveTvPage || isChannelsPage || isEditorPage || isReportsPage || isMySyncPage || page.hasClass('allLibraryPage') ?
'' : '' :
getTopParentId() || ''; getTopParentId() || '';
@ -326,6 +334,9 @@
else if (isReportsPage && itemId == 'reports') { else if (isReportsPage && itemId == 'reports') {
$(this).addClass('selectedMediaFolder'); $(this).addClass('selectedMediaFolder');
} }
else if (isMySyncPage && itemId == 'mysync') {
$(this).addClass('selectedMediaFolder');
}
else if (id && itemId == id) { else if (id && itemId == id) {
$(this).addClass('selectedMediaFolder'); $(this).addClass('selectedMediaFolder');
} }

View file

@ -218,7 +218,7 @@
$(document).on('headercreated', function (e) { $(document).on('headercreated', function (e) {
if (ConnectionManager.currentApiClient()) { if (ConnectionManager.currentApiClient()) {
$('<a class="headerButton headerButtonRight btnNotifications" href="#" title="Notifications"><div class="btnNotificationsInner">0</div></a>').insertBefore($('.headerUserButton')).on('click', Notifications.showNotificationsFlyout); $('<a class="headerButton headerButtonRight btnNotifications" href="#" title="Notifications"><div class="btnNotificationsInner">0</div></a>').insertAfter($('.headerSearchButton')).on('click', Notifications.showNotificationsFlyout);
Notifications.updateNotificationCount(); Notifications.updateNotificationCount();
} }

View file

@ -38,18 +38,20 @@
return target ? target.Name : 'Unknown Device'; return target ? target.Name : 'Unknown Device';
} }
function getSyncJobHtml(job) { function getSyncJobHtml(page, job, cardBoxCssClass, syncJobPage) {
var html = ''; var html = '';
html += "<div class='card squareCard' data-id='" + job.Id + "'>"; html += "<div class='card squareCard' data-id='" + job.Id + "'>";
html += '<div class="cardBox visualCardBox">'; html += '<div class="' + cardBoxCssClass + '">';
html += '<div class="cardScalable">'; html += '<div class="cardScalable">';
html += '<div class="cardPadder"></div>'; html += '<div class="cardPadder"></div>';
html += '<div class="cardContent">'; syncJobPage += '?id=' + job.Id;
html += '<a class="cardContent" href="' + syncJobPage + '">';
var imgUrl; var imgUrl;
var style = ''; var style = '';
@ -86,7 +88,7 @@
} }
// cardContent // cardContent
html += "</div>"; html += "</a>";
// cardScalable // cardScalable
html += "</div>"; html += "</div>";
@ -138,18 +140,39 @@
var html = ''; var html = '';
var lastTargetName = ''; var lastTargetName = '';
var cardBoxCssClass = 'cardBox visualCardBox';
var barCssClass = 'ui-bar-a';
if ($(page).hasClass('libraryPage')) {
cardBoxCssClass += ' visualCardBox-b';
barCssClass = 'detailSectionHeader';
}
var syncJobPage = 'syncjob.html';
if ($(page).hasClass('mySyncPage')) {
syncJobPage = 'mysyncjob.html';
}
for (var i = 0, length = jobs.length; i < length; i++) { for (var i = 0, length = jobs.length; i < length; i++) {
var job = jobs[i]; var job = jobs[i];
var targetName = getSyncTargetName(targets, job.TargetId); var targetName = getSyncTargetName(targets, job.TargetId);
if (targetName != lastTargetName) { if (targetName != lastTargetName) {
html += '<p style="font-size: 24px; border-bottom: 1px solid #ddd; margin: .5em 0; font-weight:300;">' + targetName + '</p>';
lastTargetName = targetName; if (lastTargetName) {
html += '<br/>';
html += '<br/>';
html += '<br/>';
} }
html += getSyncJobHtml(job); lastTargetName = targetName;
html += '<div class="' + barCssClass + '" style="padding: 0 1em;"><p>' + targetName + '</p></div>';
}
html += getSyncJobHtml(page, job, cardBoxCssClass, syncJobPage);
} }
var elem = $('.syncActivity', page).html(html).trigger('create'); var elem = $('.syncActivity', page).html(html).trigger('create');
@ -157,6 +180,11 @@
$('.btnJobMenu', elem).on('click', function () { $('.btnJobMenu', elem).on('click', function () {
showJobMenu(this); showJobMenu(this);
}); });
if (!jobs.length) {
elem.html('<div style="padding:1em .25em;">' + Globalize.translate('MessageNoSyncJobsFound') + '</div>');
}
} }
function showJobMenu(elem) { function showJobMenu(elem) {
@ -195,9 +223,17 @@
Dashboard.showLoadingMsg(); Dashboard.showLoadingMsg();
var promise1 = ApiClient.getJSON(ApiClient.getUrl('Sync/Jobs')); var options = {};
var promise2 = ApiClient.getJSON(ApiClient.getUrl('Sync/Targets')); Dashboard.getCurrentUser().done(function (user) {
if ($(page).hasClass('mySyncPage')) {
options.UserId = Dashboard.getCurrentUserId();
}
var promise1 = ApiClient.getJSON(ApiClient.getUrl('Sync/Jobs', options));
var promise2 = ApiClient.getJSON(ApiClient.getUrl('Sync/Targets', options));
$.when(promise1, promise2).done(function (response1, response2) { $.when(promise1, promise2).done(function (response1, response2) {
@ -206,18 +242,15 @@
Dashboard.hideLoadingMsg(); Dashboard.hideLoadingMsg();
}); });
});
} }
$(document).on('pageshow', "#syncActivityPage", function () { $(document).on('pageshow', ".syncActivityPage", function () {
var page = this; var page = this;
reloadData(page); reloadData(page);
}).on('pageinit', "#syncActivityPage", function () {
var page = this;
}); });
})(); })();

View file

@ -0,0 +1,285 @@
(function () {
function renderJob(page, job, editOptions) {
var html = '';
html += '<p>';
html += '<label>' + Globalize.translate('LabelName') + '</label>';
html += '<input id="txtJobName" type="text" required="required" />';
html += '</p>';
html += '<p>';
html += '<label>' + Globalize.translate('LabelSyncTo') + '</label>';
html += '<input id="txtTargetName" type="text" readonly="readonly" />';
html += '</p>';
html += '<p>';
html += '<label for="selectQuality">' + Globalize.translate('LabelQuality') + '</label>';
html += '<select id="selectQuality" data-mini="true">';
html += '<option value="High">' + Globalize.translate('OptionHigh') + '</option>';
html += '<option value="Medium">' + Globalize.translate('OptionMedium') + '</option>';
html += '<option value="Low">' + Globalize.translate('OptionLow') + '</option>';
html += '</select>';
html += '</p>';
if (editOptions.Options.indexOf('UnwatchedOnly') != -1) {
html += '<br/>';
html += '<div>';
html += '<label for="chkUnwatchedOnly">' + Globalize.translate('OptionSyncUnwatchedVideosOnly') + '</label>';
html += '<input type="checkbox" id="chkUnwatchedOnly" data-mini="true" />';
html += '<div class="fieldDescription">' + Globalize.translate('OptionSyncUnwatchedVideosOnlyHelp') + '</div>';
html += '</div>';
}
if (editOptions.Options.indexOf('SyncNewContent') != -1) {
html += '<br/>';
html += '<div>';
html += '<label for="chkSyncNewContent">' + Globalize.translate('OptionAutomaticallySyncNewContent') + '</label>';
html += '<input type="checkbox" id="chkSyncNewContent" data-mini="true" />';
html += '<div class="fieldDescription">' + Globalize.translate('OptionAutomaticallySyncNewContentHelp') + '</div>';
html += '</div>';
}
if (editOptions.Options.indexOf('ItemLimit') != -1) {
html += '<br/>';
html += '<div>';
html += '<label for="txtItemLimit">' + Globalize.translate('LabelItemLimit') + '</label>';
html += '<input type="number" id="txtItemLimit" data-mini="true" step="1" min="1" />';
html += '<div class="fieldDescription">' + Globalize.translate('LabelItemLimitHelp') + '</div>';
html += '</div>';
}
html += '<br/>';
html += '<br/>';
html += '<button type="submit" data-icon="check">' + Globalize.translate('ButtonSave') + '</button>';
$('.syncJobForm', page).html(html).trigger('create');
fillJobValues(page, job, editOptions);
}
function getJobItemHtml(jobItem, index) {
var html = '';
var cssClass = 'ui-li-has-thumb listItem';
html += '<li class="' + cssClass + '"' + ' data-itemid="' + jobItem.Id + '" data-status="' + jobItem.Status + '">';
var hasActions = jobItem.Status != 'RemovedFromDevice';
hasActions = false;
html += '<a href="#">';
var imgUrl;
if (jobItem.PrimaryImageItemId) {
imgUrl = ApiClient.getImageUrl(jobItem.PrimaryImageItemId, {
type: "Primary",
width: 80,
tag: jobItem.PrimaryImageTag,
minScale: 1.5
});
}
if (imgUrl) {
if (index < 10) {
html += '<div class="listviewImage ui-li-thumb" style="background-image:url(\'' + imgUrl + '\');"></div>';
} else {
html += '<div class="listviewImage ui-li-thumb lazy" data-src="' + imgUrl + '"></div>';
}
}
html += '<h3>';
html += jobItem.ItemName;
html += '</h3>';
html += '<p>';
var stasusLabel = Globalize.translate('SyncJobItemStatus' + jobItem.Status);
html += stasusLabel;
html += '</p>';
html += '</a>';
if (hasActions) {
html += '<a href="#" data-icon="ellipsis-v" class="listviewMenuButton btnJobItemMenu">';
} else {
html += '<a href="#" data-icon="ellipsis-v" class="listviewMenuButton btnJobItemMenu" style="visibility:hidden;">';
}
html += '</a>';
html += '</li>';
return html;
}
function renderJobItems(page, items) {
var html = '';
html += '<ul data-role="listview" class="itemsListview">';
html += '<li data-role="list-divider">';
html += Globalize.translate('HeaderItems');
html += '</li>';
var index = 0;
html += items.map(function (i) {
return getJobItemHtml(i, index++);
}).join('');
html += '</ul>';
var elem = $('.jobItems', page).html(html).trigger('create');
$('.btnJobItemMenu', elem).on('click', function () {
showJobItemMenu(this);
});
}
function showJobItemMenu(elem) {
var page = $(elem).parents('.page');
var listItem = $(elem).parents('li');
var id = listItem.attr('data-itemid');
var status = listItem.attr('data-status');
$('.jobMenu', page).popup("close").remove();
var html = '<div data-role="popup" class="jobMenu tapHoldMenu" data-theme="a">';
html += '<ul data-role="listview" style="min-width: 180px;">';
html += '<li data-role="list-divider">' + Globalize.translate('HeaderMenu') + '</li>';
if (status != 'Cancelled' && status != 'RemovedFromDevice' && status != 'Failed') {
html += '<li data-icon="delete"><a href="#" class="btnCancelJob" data-id="' + id + '">' + Globalize.translate('ButtonCancel') + '</a></li>';
}
html += '</ul>';
html += '</div>';
page.append(html);
var flyout = $('.jobMenu', page).popup({ positionTo: elem || "window" }).trigger('create').popup("open").on("popupafterclose", function () {
$(this).off("popupafterclose").remove();
});
$('.btnCancelJob', flyout).on('click', function () {
//cancelJob(page, this.getAttribute('data-id'));
});
}
function fillJobValues(page, job, editOptions) {
$('#txtJobName', page).val(job.Name);
$('#selectQuality', page).val(job.Quality).selectmenu('refresh');
$('#chkUnwatchedOnly', page).checked(job.UnwatchedOnly).checkboxradio('refresh');
$('#chkSyncNewContent', page).checked(job.SyncNewContent).checkboxradio('refresh');
$('#txtItemLimit', page).val(job.ItemLimit);
var target = editOptions.Targets.filter(function (t) {
return t.Id == job.TargetId;
})[0];
var targetName = target ? target.Name : '';
$('#txtTargetName', page).val(targetName);
}
function loadJob(page) {
Dashboard.showLoadingMsg();
var id = getParameterByName('id');
ApiClient.getJSON(ApiClient.getUrl('Sync/Jobs/' + id)).done(function (job) {
ApiClient.getJSON(ApiClient.getUrl('Sync/Options', {
UserId: job.UserId,
ItemIds: (job.RequestedItemIds && job.RequestedItemIds.length ? job.RequestedItemIds.join('') : null),
ParentId: job.ParentId,
Category: job.Category
})).done(function (options) {
renderJob(page, job, options);
Dashboard.hideLoadingMsg();
});
});
ApiClient.getJSON(ApiClient.getUrl('Sync/JobItems', {
JobId: id,
AddMetadata: true
})).done(function (result) {
renderJobItems(page, result.Items);
Dashboard.hideLoadingMsg();
});
}
function saveJob(page) {
Dashboard.showLoadingMsg();
var id = getParameterByName('id');
ApiClient.getJSON(ApiClient.getUrl('Sync/Jobs/' + id)).done(function (job) {
job.Name = $('#txtJobName', page).val();
job.Quality = $('#selectQuality', page).val();
job.ItemLimit = $('#txtItemLimit', page).val();
job.SyncNewContent = $('#chkSyncNewContent', page).checked();
job.UnwatchedOnly = $('#chkUnwatchedOnly', page).checked();
ApiClient.ajax({
url: ApiClient.getUrl('Sync/Jobs/' + id),
type: 'POST',
data: JSON.stringify(job),
contentType: "application/json"
}).done(function () {
Dashboard.hideLoadingMsg();
Dashboard.alert(Globalize.translate('SettingsSaved'));
});
});
}
$(document).on('pageshow', ".syncJobPage", function () {
var page = this;
loadJob(page);
}).on('pageinit', ".syncJobPage", function () {
var page = this;
});
window.SyncJobPage = {
onSubmit: function () {
var form = this;
var page = $(form).parents('.page');
saveJob(page);
return false;
}
};
})();

View file

@ -4,7 +4,7 @@
<title>${TitleSync}</title> <title>${TitleSync}</title>
</head> </head>
<body> <body>
<div id="syncActivityPage" data-role="page" class="page type-interior syncConfigurationPage"> <div id="syncActivityPage" data-role="page" class="page type-interior syncConfigurationPage syncActivityPage">
<div data-role="content"> <div data-role="content">
<div class="content-primary"> <div class="content-primary">

30
dashboard-ui/syncjob.html Normal file
View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<title>${TitleSync}</title>
</head>
<body>
<div id="syncJobPage" data-role="page" class="page type-interior syncConfigurationPage syncJobPage">
<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">${TabActivity}</a>
<a href="syncsettings.html" data-role="button">${TabSettings}</a>
</div>
<div class="readOnlyContent">
<form class="syncJobForm"></form>
<br />
<br />
<div class="jobItems"></div>
</div>
</div>
</div>
<script type="text/javascript">
$('.syncJobForm').off('submit', SyncJobPage.onSubmit).on('submit', SyncJobPage.onSubmit);
</script>
</div>
</body>
</html>