diff --git a/dashboard-ui/css/detailtable.css b/dashboard-ui/css/detailtable.css
index c7920d5fdd..5111c8dae7 100644
--- a/dashboard-ui/css/detailtable.css
+++ b/dashboard-ui/css/detailtable.css
@@ -11,6 +11,7 @@
text-align: left;
width: 100%;
margin: 0 auto;
+ text-shadow: none!important;
}
.stretchedDetailTable {
diff --git a/dashboard-ui/css/metadataeditor.css b/dashboard-ui/css/metadataeditor.css
index 6b726b412e..38b5b25594 100644
--- a/dashboard-ui/css/metadataeditor.css
+++ b/dashboard-ui/css/metadataeditor.css
@@ -53,7 +53,6 @@
background-repeat: no-repeat;
background-size: contain;
display: block;
-
/* For the box shadow so that the bottom border isnt underneath the text */
z-index: 100000;
position: relative;
@@ -145,6 +144,24 @@
}
}
+.libraryReportIndicator {
+ position: relative;
+ display: block;
+ text-align: center;
+ vertical-align: middle;
+ width: 24px;
+ height: 19px;
+ padding-top: 3px;
+ border-radius: 50%;
+ color: #fff;
+ background: rgb(204, 0, 0);
+ background: rgba(204, 0, 0, .8);
+}
+
+ .libraryReportIndicator div:after {
+ background-color: transparent !important;
+ }
+
.editorTile {
display: inline-block;
margin: 5px;
diff --git a/dashboard-ui/libraryreport.html b/dashboard-ui/libraryreport.html
new file mode 100644
index 0000000000..4c4761fe82
--- /dev/null
+++ b/dashboard-ui/libraryreport.html
@@ -0,0 +1,165 @@
+
+
+
+ Media Browser
+
+
+
+
+
+
+
+
Library List
+
+
+
+
+
+
+ |
+ Parent |
+ Name |
+ Type |
+ Date/Year |
+ Rating |
+ Runtime |
+ Features |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dashboard-ui/scripts/edititemimages.js b/dashboard-ui/scripts/edititemimages.js
index d5f782e6fd..4accdb59c2 100644
--- a/dashboard-ui/scripts/edititemimages.js
+++ b/dashboard-ui/scripts/edititemimages.js
@@ -538,6 +538,15 @@
$('.libraryTree', page).on('itemclicked', function (event, data) {
+ if (data.itemType == "libraryreport") {
+ Dashboard.navigate('libraryreport.html');
+ return;
+ }
+
+ if (data.itemType == "livetvservice") {
+ return;
+ }
+
if (data.id != currentItem.Id) {
MetadataEditor.currentItemId = data.id;
diff --git a/dashboard-ui/scripts/edititemmetadata.js b/dashboard-ui/scripts/edititemmetadata.js
index c8039e0e10..cbc0d7a065 100644
--- a/dashboard-ui/scripts/edititemmetadata.js
+++ b/dashboard-ui/scripts/edititemmetadata.js
@@ -1155,6 +1155,11 @@
$('.libraryTree', page).on('itemclicked', function (event, data) {
+ if (data.itemType == "libraryreport") {
+ Dashboard.navigate('libraryreport.html');
+ return;
+ }
+
if (data.itemType == "livetvservice") {
return;
}
diff --git a/dashboard-ui/scripts/edititempeople.js b/dashboard-ui/scripts/edititempeople.js
index b88a6622e4..897df48bc7 100644
--- a/dashboard-ui/scripts/edititempeople.js
+++ b/dashboard-ui/scripts/edititempeople.js
@@ -254,6 +254,15 @@
$('.libraryTree', page).on('itemclicked', function (event, data) {
+ if (data.itemType == "libraryreport") {
+ Dashboard.navigate('libraryreport.html');
+ return;
+ }
+
+ if (data.itemType == "livetvservice") {
+ return;
+ }
+
if (data.id != currentItem.Id) {
MetadataEditor.currentItemId = data.id;
MetadataEditor.currentItemName = data.itemName;
diff --git a/dashboard-ui/scripts/editorsidebar.js b/dashboard-ui/scripts/editorsidebar.js
index cf8f95c3b1..6ba515efde 100644
--- a/dashboard-ui/scripts/editorsidebar.js
+++ b/dashboard-ui/scripts/editorsidebar.js
@@ -106,6 +106,8 @@
nodes.push({ attr: { id: name, rel: 'folder', itemtype: 'livetvservice' }, data: htmlName, state: 'closed' });
}
+ nodes.push({ attr: { id: 'libraryreport', rel: 'default', itemtype: 'libraryreport' }, data: 'Library List' });
+
callback(nodes);
});
@@ -141,6 +143,11 @@
var itemtype = node.attr("itemtype");
+ if (itemtype == 'libraryreport') {
+
+ return;
+ }
+
if (itemtype == 'livetvservice') {
loadLiveTvChannels(id, openItems, callback);
diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js
index 6d18a23280..5f732786df 100644
--- a/dashboard-ui/scripts/librarybrowser.js
+++ b/dashboard-ui/scripts/librarybrowser.js
@@ -1760,7 +1760,8 @@
if (item.Status == "Continuing") {
miscInfo.push(item.ProductionYear + "-Present");
- } else if (item.ProductionYear) {
+ }
+ else if (item.ProductionYear) {
text = item.ProductionYear;
diff --git a/dashboard-ui/scripts/libraryreport.js b/dashboard-ui/scripts/libraryreport.js
new file mode 100644
index 0000000000..b960e604ab
--- /dev/null
+++ b/dashboard-ui/scripts/libraryreport.js
@@ -0,0 +1,391 @@
+(function ($, document, window) {
+
+ // The base query options
+ var query = {
+
+ SortBy: "SeriesSortName,SortName",
+ SortOrder: "Ascending",
+ Recursive: true,
+ Fields: "",
+ StartIndex: 0
+ };
+
+ function getFriendlyTypeName(type) {
+
+ if (type == "MusicArtist") {
+ return "Artist";
+ }
+ if (type == "MusicAlbum") {
+ return "Album";
+ }
+ if (type == "Audio") {
+ return "Song";
+ }
+ if (type == "BoxSet") {
+ return "Collection";
+ }
+ return type;
+ }
+
+ function getTableRowsHtml(items) {
+
+ var html = '';
+
+ for (var i = 0, length = items.length; i < length; i++) {
+
+ var item = items[i];
+
+ html += '';
+
+ html += '';
+
+ if (item.IsUnidentified) {
+ html += '';
+ }
+ html += ' | ';
+
+ html += '';
+ if (item.SeriesName) {
+ html += '' + item.SeriesName + '';
+ }
+ else if (item.Album) {
+ html += item.Album + ' ';
+ }
+ else if (item.AlbumArtist) {
+ html += item.AlbumArtist + ' ';
+ }
+ else {
+ html += ' ';
+ }
+ html += ' | ';
+
+ html += '';
+ html += '' + LibraryBrowser.getPosterViewDisplayName(item, false, true) + '';
+ html += ' | ';
+
+ html += '';
+ html += getFriendlyTypeName(item.Type);
+ html += ' | ';
+
+ html += '';
+ if (item.PremiereDate && item.Type != "Series") {
+ try {
+ var date = parseISO8601Date(item.PremiereDate, { toLocal: true });
+
+ html += date.toLocaleDateString();
+ }
+ catch (e) {
+ html += ' ';
+ }
+ }
+ else if (item.ProductionYear) {
+ html += item.ProductionYear;
+
+ if (item.Status == "Continuing") {
+ html += "-Present";
+ }
+ else if (item.EndDate) {
+
+ try {
+
+ var endYear = parseISO8601Date(item.EndDate, { toLocal: true }).getFullYear();
+
+ if (endYear != item.ProductionYear) {
+ html += "-" + parseISO8601Date(item.EndDate, { toLocal: true }).getFullYear();
+ }
+
+ }
+ catch (e) {
+ console.log("Error parsing date: " + item.EndDate);
+ }
+ }
+
+ } else {
+ html += ' ';
+ }
+ html += ' | ';
+
+ html += '';
+ html += item.OfficialRating || ' ';
+ html += ' | ';
+
+ html += '';
+
+ if (item.RunTimeTicks) {
+ html += Dashboard.getDisplayTime(item.RunTimeTicks);
+ } else {
+ html += ' ';
+ }
+ html += ' | ';
+
+ html += '';
+ if (item.SpecialFeatureCount == 1) {
+
+ html += '1 Special ';
+ }
+ else if (item.SpecialFeatureCount) {
+
+ html += item.SpecialFeatureCount + ' Specials ';
+ }
+ if (item.LocalTrailerCount == 1) {
+
+ html += '1 Trailer ';
+ }
+ else if (item.LocalTrailerCount) {
+
+ html += item.LocalTrailerCount + ' Trailers ';
+ }
+ html += ' | ';
+
+ html += '
';
+ }
+
+ return html;
+ }
+
+ function renderItems(page, result) {
+
+ // Scroll back up so they can see the results from the beginning
+ $(document).scrollTop(0);
+
+ $('.listTopPaging', page).html(LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, true)).trigger('create');
+
+ updateFilterControls(page);
+
+ $('.listBottomPaging', page).html(LibraryBrowser.getPagingHtml(query, result.TotalRecordCount)).trigger('create');
+
+ $('.resultBody', page).html(getTableRowsHtml(result.Items)).parents('.tblLibraryReport').table("refresh").trigger('create');
+
+ $('.btnNextPage', page).on('click', function () {
+ query.StartIndex += query.Limit;
+ reloadItems(page);
+ });
+
+ $('.btnPreviousPage', page).on('click', function () {
+ query.StartIndex -= query.Limit;
+ reloadItems(page);
+ });
+
+ $('.selectPageSize', page).on('change', function () {
+ query.Limit = parseInt(this.value);
+ query.StartIndex = 0;
+ reloadItems(page);
+ });
+ }
+
+ function reloadItems(page) {
+
+ var url = ApiClient.getUrl("Items", query);
+
+ $.getJSON(url).done(function (result) {
+
+ renderItems(page, result);
+
+ });
+ }
+
+ function updateFilterControls(page) {
+
+ $('.chkTypeFilter', page).each(function () {
+
+ var filters = "," + (query.IncludeItemTypes || "");
+ var filterName = this.getAttribute('data-filter');
+
+ this.checked = filters.indexOf(',' + filterName) != -1;
+
+ }).checkboxradio('refresh');
+
+ $('.chkVideoTypeFilter', page).each(function () {
+
+ var filters = "," + (query.VideoTypes || "");
+ var filterName = this.getAttribute('data-filter');
+
+ this.checked = filters.indexOf(',' + filterName) != -1;
+
+ }).checkboxradio('refresh');
+
+ $('#chk3D', page).checked(query.Is3D == true).checkboxradio('refresh');
+ $('#chkHD', page).checked(query.IsHD == true).checkboxradio('refresh');
+ $('#chkSD', page).checked(query.IsHD == false).checkboxradio('refresh');
+
+ $('#chkSubtitle', page).checked(query.HasSubtitles == true).checkboxradio('refresh');
+ $('#chkTrailer', page).checked(query.HasTrailer == true).checkboxradio('refresh');
+ $('#chkSpecialFeature', page).checked(query.HasSpecialFeature == true).checkboxradio('refresh');
+ $('#chkThemeSong', page).checked(query.HasThemeSong == true).checkboxradio('refresh');
+ $('#chkThemeVideo', page).checked(query.HasThemeVideo == true).checkboxradio('refresh');
+
+ $('#chkMissingOverview', page).checked(query.HasOverview == false).checkboxradio('refresh');
+ $('#chkYearMismatch', page).checked(query.IsYearMismatched == true).checkboxradio('refresh');
+ }
+
+ $(document).on('pageinit', "#libraryReportPage", function () {
+
+ var page = this;
+
+ $('.libraryTree', page).on('itemclicked', function (event, data) {
+
+ if (data.itemType == "libraryreport") {
+ return;
+ }
+
+ if (data.itemType == "livetvservice") {
+ return;
+ }
+
+ Dashboard.navigate('edititemmetadata.html?id=' + data.id);
+ });
+
+ $('#radioBasicFilters', page).on('change', function () {
+
+ if (this.checked) {
+ $('.basicFilters', page).show();
+ $('.advancedFilters', page).hide();
+ } else {
+ $('.basicFilters', page).hide();
+ }
+ });
+
+ $('#radioAdvancedFilters', page).on('change', function () {
+
+ if (this.checked) {
+ $('.advancedFilters', page).show();
+ $('.basicFilters', page).hide();
+ } else {
+ $('.advancedFilters', page).hide();
+ }
+ });
+
+ $('.chkTypeFilter', page).on('change', function () {
+
+ var filterName = this.getAttribute('data-filter');
+ var filters = query.IncludeItemTypes || "";
+
+ filters = (',' + filters).replace(',' + filterName, '').substring(1);
+
+ if (this.checked) {
+ filters = filters ? (filters + ',' + filterName) : filterName;
+ }
+
+ query.StartIndex = 0;
+ query.IncludeItemTypes = filters;
+
+ reloadItems(page);
+ });
+
+ $('.chkVideoTypeFilter', page).on('change', function () {
+
+ var filterName = this.getAttribute('data-filter');
+ var filters = query.VideoTypes || "";
+
+ filters = (',' + filters).replace(',' + filterName, '').substring(1);
+
+ if (this.checked) {
+ filters = filters ? (filters + ',' + filterName) : filterName;
+ }
+
+ query.StartIndex = 0;
+ query.VideoTypes = filters;
+
+ reloadItems(page);
+ });
+
+ $('#chk3D', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.Is3D = this.checked ? true : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkHD', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.IsHD = this.checked ? true : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkSD', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.IsHD = this.checked ? false : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkSubtitle', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.HasSubtitles = this.checked ? true : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkTrailer', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.HasTrailer = this.checked ? true : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkSpecialFeature', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.HasSpecialFeature = this.checked ? true : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkThemeSong', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.HasThemeSong = this.checked ? true : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkThemeVideo', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.HasThemeVideo = this.checked ? true : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkMissingOverview', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.HasOverview = this.checked ? false : null;
+
+ reloadItems(page);
+ });
+
+ $('#chkYearMismatch', page).on('change', function () {
+
+ query.StartIndex = 0;
+ query.IsYearMismatched = this.checked ? true : null;
+
+ reloadItems(page);
+ });
+
+ }).on('pagebeforeshow', "#libraryReportPage", function () {
+
+ var page = this;
+ var limit = LibraryBrowser.getDefaultPageSize();
+
+ // If the default page size has changed, the start index will have to be reset
+ if (limit != query.Limit) {
+ query.Limit = limit;
+ query.StartIndex = 0;
+ }
+
+ reloadItems(page);
+
+ }).on('pageshow', "#libraryReportPage", function () {
+
+ updateFilterControls(this);
+ });
+
+})(jQuery, document, window);
+
diff --git a/dashboard-ui/scripts/movies.js b/dashboard-ui/scripts/movies.js
index c964c2fb61..69ae53e56d 100644
--- a/dashboard-ui/scripts/movies.js
+++ b/dashboard-ui/scripts/movies.js
@@ -176,24 +176,6 @@
reloadItems(page);
});
-
- $('.chkVideoTypeFilter', this).on('change', function () {
-
- var filterName = this.getAttribute('data-filter');
- var filters = query.VideoTypes || "";
-
- filters = (',' + filters).replace(',' + filterName, '').substring(1);
-
- if (this.checked) {
- filters = filters ? (filters + ',' + filterName) : filterName;
- }
-
- query.StartIndex = 0;
- query.VideoTypes = filters;
-
- reloadItems(page);
- });
-
$('#selectView', this).on('change', function () {
view = this.value;
@@ -212,6 +194,23 @@
LibraryBrowser.saveViewSetting('movies', view);
});
+ $('.chkVideoTypeFilter', this).on('change', function () {
+
+ var filterName = this.getAttribute('data-filter');
+ var filters = query.VideoTypes || "";
+
+ filters = (',' + filters).replace(',' + filterName, '').substring(1);
+
+ if (this.checked) {
+ filters = filters ? (filters + ',' + filterName) : filterName;
+ }
+
+ query.StartIndex = 0;
+ query.VideoTypes = filters;
+
+ reloadItems(page);
+ });
+
$('#chk3D', this).on('change', function () {
query.StartIndex = 0;