Start styling changes. After updating to this force a refresh (shift+refresh) in your browser to reload styles.

Make more use of card-type layouts.
Make tables responsive.
This commit is contained in:
Tim 2015-06-28 16:59:36 +02:00
parent 4f1056cf87
commit 762199344c
14 changed files with 1367 additions and 303 deletions

View file

@ -30,10 +30,10 @@
</div> </div>
</div> </div>
<div class="container"> <div class="container-fluid">
<div class='row'> <div class='row-fluid'>
<div class='span12'> <div class='span12'>
<div class="wellbg"> <div class="card-back">
<form action="configUpdate" method="post" class="form" id="configUpdate"> <form action="configUpdate" method="post" class="form" id="configUpdate">
<div role="tabpanel"> <div role="tabpanel">
<!-- Nav tabs --> <!-- Nav tabs -->
@ -206,165 +206,7 @@
</div> </div>
</div> </div>
<input type="button" class="btn btn-medium btn-primary" value="Save" onclick="doAjaxCall('configUpdate',$(this),'tabs',true);return false;" data-success="Changes saved successfully"> <input type="button" class="btn btn-medium btn-primary" value="Save" onclick="doAjaxCall('configUpdate',$(this),'tabs',true);return false;" data-success="Changes saved successfully">
<div id="dateTimeOptionsModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="dateTimeOptionsModal" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<i class="fa fa-remove"></i>
</button>
<h3 id="myModalLabel">Date &amp; Time Format Options</h3>
</div>
<div class="modal-body">
<div class="span6">
<table>
<tbody>
<tr>
<td colspan="3"><h5>Day</h5></td>
</tr>
<tr>
<td align="center"><strong>DD</strong></td>
<td width="300">Numeric, with leading zeros</td>
<td>01 to 31</td>
</tr>
<tr>
<td align="center"><strong>D</strong></td>
<td>Numeric, without leading zeros</td>
<td>1 to 31</td>
</tr>
<tr>
<td align="center"><strong>Do</strong></td>
<td>The English suffix for the day of the month</td>
<td>st, nd or th in the 1st, 2nd or 15th.</td>
</tr>
<tr>
<td colspan="3"><h5>Month</h5></td>
</tr>
<tr>
<td align="center"><strong>MM</strong></td>
<td>Numeric, with leading zeros</td>
<td>01 to 31</td>
</tr>
<tr>
<td align="center"><strong>M</strong></td>
<td>Numeric, without leading zeros</td>
<td>1 to 31</td>
</tr>
<tr>
<td align="center"><strong>MMMM</strong></td>
<td>Textual full</td>
<td>January to December</td>
</tr>
<tr>
<td align="center"><strong>MMM</strong></td>
<td>Textual three letters</td>
<td>Jan to Dec</td>
</tr>
<tr>
<td colspan="3"><h5>Year</h5></td>
</tr>
<tr>
<td align="center"><strong>YYYY</strong></td>
<td>Numeric, 4 digits</td>
<td>Eg., 1999, 2003</td>
</tr>
<tr>
<td align="center"><strong>YY</strong></td>
<td>Numeric, 2 digits</td>
<td>Eg., 99, 03</td>
</tr>
<tr>
<td colspan="3"><h5>Time</h5></td>
</tr>
<tr>
<td align="center"><strong>a</strong></td>
<td width="300">am/pm Lowercase</td>
<td>am, pm</td>
</tr>
<tr>
<td align="center"><strong>A</strong></td>
<td>AM/PM Uppercase</td>
<td>AM, PM</td>
</tr>
<tr>
<td align="center"><strong>h</strong></td>
<td>Hour, 12-hour, without leading zeros</td>
<td>1-12</td>
</tr>
<tr>
<td align="center"><strong>hh</strong></td>
<td>Hour, 12-hour, with leading zeros</td>
<td>01-12</td>
</tr>
<tr>
<td align="center"><strong>H</strong></td>
<td>Hour, 24-hour, without leading zeros</td>
<td>0-23</td>
</tr>
<tr>
<td align="center"><strong>HH</strong></td>
<td>Hour, 24-hour, with leading zeros</td>
<td>00-23</td>
</tr>
<tr>
<td align="center"><strong>mm</strong></td>
<td>Minutes, with leading zeros</td>
<td>00-59</td>
</tr>
<tr>
<td align="center"><strong>ss</strong></td>
<td>Seconds, with leading zeros</td>
<td>00-59</td>
</tr>
<tr>
<td align="center"><strong>zz</strong></td>
<td>Timezone abbreviation</td>
<td>Eg., EST, MDT ...</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer"></div>
</div>
<div id="pms-auth-modal" class="modal hide fade" tabindex="-1" role="dialog"
aria-labelledby="ip-info-modal" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i
class="fa fa-remove"></i></button>
<h3 id="PMSAuthModal">Fetch Plex.tv Token</h3>
</div>
<div class="modal-body" id="modal-text">
<div>
<div class="span6">
<span>
This will attempt to fetch your token for you. This will not work on Internet Explorer 9 or lower.
PlexPy does not store your username and password.
</span>
<br/><br/>
<div class="form-group">
<label for="pms_username">PMS Username</label>
<input type="text" id="pms_username" name="pms_username" size="30">
<p class="help-block">Username for Plex.tv authentication.</p>
</div>
<div class="form-group">
<label for="pms_password">PMS Password</label>
<input type="password" id="pms_password" name="pms_password" size="30">
<p class="help-block">Password for Plex.tv authentication.</p>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="">
<input type="button" id="get-pms-auth-token" class="btn btn-primary" value="Fetch Token">
<span id="pms-token-status"></span>
</div>
</div>
</div>
</div>
<!-- <!--
<div role="tabpanel" class="tab-pane" id="tabs-5"> <div role="tabpanel" class="tab-pane" id="tabs-5">
<div class="wellbg"> <div class="wellbg">
@ -716,6 +558,164 @@
</form> </form>
</div> </div>
</div> </div>
<div id="dateTimeOptionsModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="dateTimeOptionsModal" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<i class="fa fa-remove"></i>
</button>
<h3 id="myModalLabel">Date &amp; Time Format Options</h3>
</div>
<div class="modal-body">
<div class="card-back">
<table>
<tbody>
<tr>
<td colspan="3"><h5>Day</h5></td>
</tr>
<tr>
<td align="center"><strong>DD</strong></td>
<td width="300">Numeric, with leading zeros</td>
<td>01 to 31</td>
</tr>
<tr>
<td align="center"><strong>D</strong></td>
<td>Numeric, without leading zeros</td>
<td>1 to 31</td>
</tr>
<tr>
<td align="center"><strong>Do</strong></td>
<td>The English suffix for the day of the month</td>
<td>st, nd or th in the 1st, 2nd or 15th.</td>
</tr>
<tr>
<td colspan="3"><h5>Month</h5></td>
</tr>
<tr>
<td align="center"><strong>MM</strong></td>
<td>Numeric, with leading zeros</td>
<td>01 to 31</td>
</tr>
<tr>
<td align="center"><strong>M</strong></td>
<td>Numeric, without leading zeros</td>
<td>1 to 31</td>
</tr>
<tr>
<td align="center"><strong>MMMM</strong></td>
<td>Textual full</td>
<td>January to December</td>
</tr>
<tr>
<td align="center"><strong>MMM</strong></td>
<td>Textual three letters</td>
<td>Jan to Dec</td>
</tr>
<tr>
<td colspan="3"><h5>Year</h5></td>
</tr>
<tr>
<td align="center"><strong>YYYY</strong></td>
<td>Numeric, 4 digits</td>
<td>Eg., 1999, 2003</td>
</tr>
<tr>
<td align="center"><strong>YY</strong></td>
<td>Numeric, 2 digits</td>
<td>Eg., 99, 03</td>
</tr>
<tr>
<td colspan="3"><h5>Time</h5></td>
</tr>
<tr>
<td align="center"><strong>a</strong></td>
<td width="300">am/pm Lowercase</td>
<td>am, pm</td>
</tr>
<tr>
<td align="center"><strong>A</strong></td>
<td>AM/PM Uppercase</td>
<td>AM, PM</td>
</tr>
<tr>
<td align="center"><strong>h</strong></td>
<td>Hour, 12-hour, without leading zeros</td>
<td>1-12</td>
</tr>
<tr>
<td align="center"><strong>hh</strong></td>
<td>Hour, 12-hour, with leading zeros</td>
<td>01-12</td>
</tr>
<tr>
<td align="center"><strong>H</strong></td>
<td>Hour, 24-hour, without leading zeros</td>
<td>0-23</td>
</tr>
<tr>
<td align="center"><strong>HH</strong></td>
<td>Hour, 24-hour, with leading zeros</td>
<td>00-23</td>
</tr>
<tr>
<td align="center"><strong>mm</strong></td>
<td>Minutes, with leading zeros</td>
<td>00-59</td>
</tr>
<tr>
<td align="center"><strong>ss</strong></td>
<td>Seconds, with leading zeros</td>
<td>00-59</td>
</tr>
<tr>
<td align="center"><strong>zz</strong></td>
<td>Timezone abbreviation</td>
<td>Eg., EST, MDT ...</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer"></div>
</div>
<div id="pms-auth-modal" class="modal hide fade" tabindex="-1" role="dialog"
aria-labelledby="ip-info-modal" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i
class="fa fa-remove"></i></button>
<h3 id="PMSAuthModal">Fetch Plex.tv Token</h3>
</div>
<div class="modal-body" id="modal-text">
<div>
<div class="card-back">
<span>
This will attempt to fetch your token for you. This will not work on Internet Explorer 9 or lower.
PlexPy does not store your username and password.
</span>
<br/><br/>
<div class="form-group">
<label for="pms_username">PMS Username</label>
<input type="text" id="pms_username" name="pms_username" size="30">
<p class="help-block">Username for Plex.tv authentication.</p>
</div>
<div class="form-group">
<label for="pms_password">PMS Password</label>
<input type="password" id="pms_password" name="pms_password" size="30">
<p class="help-block">Password for Plex.tv authentication.</p>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="">
<input type="button" id="get-pms-auth-token" class="btn btn-primary" value="Fetch Token">
<span id="pms-token-status"></span>
</div>
</div>
</div>
</div>
</div> </div>
</%def> </%def>

View file

@ -0,0 +1,106 @@
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child,
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child {
position: relative;
padding-left: 30px;
cursor: pointer;
}
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child:before {
top: 8px;
left: 4px;
height: 16px;
width: 16px;
display: block;
position: absolute;
color: white;
border: 2px solid white;
border-radius: 16px;
text-align: center;
line-height: 14px;
box-shadow: 0 0 3px #444;
box-sizing: content-box;
content: '+';
background-color: #31b131;
}
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child.dataTables_empty:before,
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child.dataTables_empty:before {
display: none;
}
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child:before,
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child:before {
content: '-';
background-color: #d33333;
}
table.dataTable.dtr-inline.collapsed > tbody > tr.child td:before {
display: none;
}
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child,
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child {
padding-left: 27px;
}
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child:before,
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child:before {
top: 5px;
left: 4px;
height: 14px;
width: 14px;
border-radius: 14px;
line-height: 12px;
}
table.dataTable.dtr-column > tbody > tr > td.control,
table.dataTable.dtr-column > tbody > tr > th.control {
position: relative;
cursor: pointer;
}
table.dataTable.dtr-column > tbody > tr > td.control:before,
table.dataTable.dtr-column > tbody > tr > th.control:before {
top: 50%;
left: 50%;
height: 16px;
width: 16px;
margin-top: -10px;
margin-left: -10px;
display: block;
position: absolute;
color: white;
border: 2px solid white;
border-radius: 16px;
text-align: center;
line-height: 14px;
box-shadow: 0 0 3px #444;
box-sizing: content-box;
content: '+';
background-color: #31b131;
}
table.dataTable.dtr-column > tbody > tr.parent td.control:before,
table.dataTable.dtr-column > tbody > tr.parent th.control:before {
content: '-';
background-color: #d33333;
}
table.dataTable > tbody > tr.child {
padding: 0.5em 1em;
}
table.dataTable > tbody > tr.child:hover {
background: transparent !important;
}
table.dataTable > tbody > tr.child ul {
display: inline-block;
list-style-type: none;
margin: 0;
padding: 0;
}
table.dataTable > tbody > tr.child ul li {
border-bottom: 1px solid #efefef;
padding: 0.5em 0;
}
table.dataTable > tbody > tr.child ul li:first-child {
padding-top: 0;
}
table.dataTable > tbody > tr.child ul li:last-child {
border-bottom: none;
}
table.dataTable > tbody > tr.child span.dtr-title {
display: inline-block;
min-width: 75px;
font-weight: bold;
}

View file

@ -79,7 +79,6 @@
.dataTables_paginate { .dataTables_paginate {
float: right; float: right;
text-align: right; text-align: right;
margin-top: 7px;
margin-right: 15px; margin-right: 15px;
} }
@ -145,7 +144,7 @@ table.display {
clear: both; clear: both;
width: 100%; width: 100%;
font-size: 14px; font-size: 14px;
line-height: 30px; line-height: 25px;
/* Note Firefox 3.5 and before have a bug with border-collapse /* Note Firefox 3.5 and before have a bug with border-collapse
* ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 ) * ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 )
* border-spacing: 0; is one possible option. Conditional-css.com is * border-spacing: 0; is one possible option. Conditional-css.com is
@ -176,6 +175,36 @@ table.display thead th i {
margin-top: -1px; margin-top: -1px;
} }
table.display thead .sorting,
table.display thead .sorting_asc,
table.display thead .sorting_desc {
cursor: pointer;
*cursor: hand;
}
table.display thead .sorting,
table.display thead .sorting_asc,
table.display thead .sorting_desc,
table.display thead .sorting_asc_disabled,
table.display thead .sorting_desc_disabled {
background-repeat: no-repeat;
background-position: left;
}
table.display thead .sorting {
background-image: url("../images/sort_both.png");
}
table.display thead .sorting_asc {
background-image: url("../images/sort_asc.png");
}
table.display thead .sorting_desc {
background-image: url("../images/sort_desc.png");
}
table.display thead .sorting_asc_disabled {
background-image: url("../images/sort_asc_disabled.png");
}
table.display thead .sorting_desc_disabled {
background-image: url("../images/sort_desc_disabled.png");
}
table.display tfoot th { table.display tfoot th {
padding: 3px 18px 3px 10px; padding: 3px 18px 3px 10px;
border-top: 1px solid black; border-top: 1px solid black;
@ -188,7 +217,6 @@ table.display tr.heading2 td {
table.display td { table.display td {
padding: 5px 0 5px 20px; padding: 5px 0 5px 20px;
white-space:nowrap;
} }
table.display td.title { table.display td.title {
@ -620,3 +648,7 @@ div.box {
border: 1px solid #8080FF; border: 1px solid #8080FF;
background-color: #E5E5FF; background-color: #E5E5FF;
} }
td.no-wrap, th.no-wrap {
white-space:nowrap;
}

View file

@ -863,7 +863,6 @@ pre code {
.label, .label,
.badge { .badge {
display: inline-block; display: inline-block;
font-size: 14px;
padding: 4px 8px; padding: 4px 8px;
border-radius: 10px; border-radius: 10px;
vertical-align: baseline; vertical-align: baseline;
@ -879,7 +878,6 @@ pre code {
display: inline-block; display: inline-block;
font-weight: normal; font-weight: normal;
padding: 4px 8px; padding: 4px 8px;
font-size: 14px;
border-radius: 10px; border-radius: 10px;
vertical-align: baseline; vertical-align: baseline;
white-space: nowrap; white-space: nowrap;
@ -1217,7 +1215,7 @@ button,
select, select,
textarea { textarea {
color: #fff; color: #fff;
font-size: 16px; font-size: 14x;
font-weight: normal; font-weight: normal;
line-height: normal; line-height: normal;
} }
@ -2224,6 +2222,7 @@ input[type="button"].btn-block {
/* Darken IE7 buttons by default so they stand out more given they won't have borders */ /* Darken IE7 buttons by default so they stand out more given they won't have borders */
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
padding: 6px 25px; padding: 6px 25px;
} }
.btn-primary:hover, .btn-primary:hover,
.btn-primary:focus, .btn-primary:focus,
@ -4070,6 +4069,7 @@ text-shadow: 0 0 10px rgba(255,255,255,0.85);
} }
.pagination { .pagination {
margin: 0px 0; margin: 0px 0;
padding-top: 12px;
} }
.pagination ul { .pagination ul {
display: inline-block; display: inline-block;
@ -4094,7 +4094,7 @@ text-shadow: 0 0 10px rgba(255,255,255,0.85);
line-height: 20px; line-height: 20px;
text-decoration: none; text-decoration: none;
background-color: #262626; background-color: #262626;
border: 1px solid #1f1f1f; border: 1px solid #444444;
border-left-width: 0; border-left-width: 0;
} }
.pagination ul > li > a:hover, .pagination ul > li > a:hover,
@ -4114,7 +4114,7 @@ text-shadow: 0 0 10px rgba(255,255,255,0.85);
.pagination ul > .disabled > a, .pagination ul > .disabled > a,
.pagination ul > .disabled > a:hover, .pagination ul > .disabled > a:hover,
.pagination ul > .disabled > a:focus { .pagination ul > .disabled > a:focus {
color: #222; color: #444444;
background-color: transparent; background-color: transparent;
cursor: default; cursor: default;
text-shadow: none; text-shadow: none;
@ -8169,3 +8169,29 @@ ol.test >li {
text-align: center; text-align: center;
line-height: 300px; line-height: 300px;
} }
.card-back {
padding: 20px;
background-color: #282828;
margin-left: auto;
margin-right: auto;
margin-top: 20px;
margin-bottom: 20px;
width: 80%;
overflow: hidden;
}
.table-card-back {
padding: 20px 20px 20px 40px;
background-color: #282828;
margin-left: auto;
margin-right: auto;
margin-top: 20px;
margin-bottom: 20px;
width: 90%;
overflow: hidden;
}
.table-card-back td {
font-size: 12px;
}

View file

@ -5,6 +5,7 @@ from plexpy import helpers
<%def name="headIncludes()"> <%def name="headIncludes()">
<link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css"> <link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css">
<link rel="stylesheet" href="interfaces/default/css/dataTables.responsive.css">
</%def> </%def>
<%def name="body()"> <%def name="body()">
@ -23,23 +24,23 @@ from plexpy import helpers
<div class='container-fluid'> <div class='container-fluid'>
<div class='row-fluid'> <div class='row-fluid'>
<div class='span12'> <div class='span12'>
<div class='wellbg'> <div class='table-card-back'>
<table class="display" id="history_table" width="100%"> <table class="display" id="history_table" width="100%">
<thead> <thead>
<tr> <tr>
<th align='left' id="id"><i class='fa fa-sort'></i> ID</th> <th class="never" align='left' id="id">ID</th>
<th align='left' id="time"><i class='fa fa-sort'></i> Time</th> <th class="all" align='left' id="time">Time</th>
<th align='left' id="user"><i class='fa fa-sort'></i> User</th> <th class="all" align='left' id="user">User</th>
<th align='left' id="platform"><i class='fa fa-sort'></i> Platform</th> <th class="min-tablet" align='left' id="platform">Platform</th>
<th align='left' id="ip_address"><i class='fa fa-sort'></i> IP Address</th> <th class="desktop" align='left' id="ip_address">IP Address</th>
<th align='left' id="title"><i class='fa fa-sort'></i> Title</th> <th class="min-tablet" align='left' id="title">Title</th>
<th align='left' id="started"><i class='fa fa-sort'></i> Started</th> <th class="desktop" align='left' id="started">Started</th>
<th align='left' id="paused_counter"><i class='fa fa-sort'></i> Paused</th> <th class="desktop" align='left' id="paused_counter">Paused</th>
<th align='left' id="stopped"><i class='fa fa-sort'></i> Stopped</th> <th class="desktop" align='left' id="stopped">Stopped</th>
<th align='left' id="duration"><i class='fa fa-sort'></i> Duration</th> <th class="desktop" align='left' id="duration">Duration</th>
<th align='left' id="percent_complete"> Completed</th> <th class="desktop" align='left' id="percent_complete">Completed</th>
<th align='left' id="rating_key"> RatingKey</th> <th class="never" align='left' id="rating_key">RatingKey</th>
<th align='left' id="xml"></th> <th class="never" align='left' id="xml"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -59,6 +60,7 @@ from plexpy import helpers
<%def name="javascriptIncludes()"> <%def name="javascriptIncludes()">
<script src="interfaces/default/js/jquery.dataTables.min.js"></script> <script src="interfaces/default/js/jquery.dataTables.min.js"></script>
<script src="interfaces/default/js/dataTables.responsive.js"></script>
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script> <script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
<script src="interfaces/default/js/moment-with-locale.js"></script> <script src="interfaces/default/js/moment-with-locale.js"></script>
<script src="interfaces/default/js/tables/history_table.js"></script> <script src="interfaces/default/js/tables/history_table.js"></script>

View file

@ -55,6 +55,7 @@ from plexpy import helpers
<%def name="headIncludes()"> <%def name="headIncludes()">
<link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css"> <link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css">
<link rel="stylesheet" href="interfaces/default/css/dataTables.responsive.css">
</%def> </%def>
<%def name="body()"> <%def name="body()">
@ -178,34 +179,33 @@ from plexpy import helpers
<div class='container-fluid'> <div class='container-fluid'>
<div class='row-fluid'> <div class='row-fluid'>
<div class='span12'> <div class='span12'>
<div class='wellbg'> <div class='table-card-back'>
% if data['type'] == 'movie' or data['type'] == 'episode' or data['type'] == 'show': % if data['type'] == 'movie' or data['type'] == 'episode' or data['type'] == 'show':
<div class="wellheader">
<div class="dashboard-wellheader">
<h3>Watch history for <strong>${data['title']}</strong></h3> <h3>Watch history for <strong>${data['title']}</strong></h3>
</div> </div>
</div> <div class="table-card-back">
<table class="display" id="history_table" width="100%"> <table class="display" id="history_table" width="100%">
<thead> <thead>
<tr> <tr>
<th align='left' id="id"><i class='fa fa-sort'></i> ID</th> <th class="never" align='left' id="id">ID</th>
<th align='left' id="date"><i class='fa fa-sort'></i> Time</th> <th class="all" align='left' id="time">Time</th>
<th align='left' id="user"><i class='fa fa-sort'></i> User</th> <th class="all" align='left' id="user">User</th>
<th align='left' id="platform"><i class='fa fa-sort'></i> Platform</th> <th class="min-tablet" align='left' id="platform">Platform</th>
<th align='left' id="ip_address"><i class='fa fa-sort'></i> IP Address</th> <th class="desktop" align='left' id="ip_address">IP Address</th>
<th align='left' id="title"><i class='fa fa-sort'></i> Title</th> <th class="min-tablet" align='left' id="title">Title</th>
<th align='left' id="started"><i class='fa fa-sort'></i> Started</th> <th class="desktop" align='left' id="started">Started</th>
<th align='left' id="paused_counter"><i class='fa fa-sort'></i> Paused</th> <th class="desktop" align='left' id="paused_counter">Paused</th>
<th align='left' id="stopped"><i class='fa fa-sort'></i> Stopped</th> <th class="desktop" align='left' id="stopped">Stopped</th>
<th align='left' id="duration"><i class='fa fa-sort'></i> Duration</th> <th class="desktop" align='left' id="duration">Duration</th>
<th align='left' id="percent_complete"> Completed</th> <th class="desktop" align='left' id="percent_complete">Completed</th>
<th align='left' id="rating_key"> RatingKey</th> <th class="never" align='left' id="rating_key">RatingKey</th>
<th align='left' id="xml"></th> <th class="never" align='left' id="xml"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
</tbody> </tbody>
</table> </table>
</div>
<div id="info-modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="info-modal" <div id="info-modal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="info-modal"
aria-hidden="true"> aria-hidden="true">
</div> </div>
@ -220,7 +220,6 @@ from plexpy import helpers
% endif % endif
</div> </div>
</div> </div>
</div>
</div> </div>
% else: % else:
<div class="clear"></div> <div class="clear"></div>
@ -238,6 +237,7 @@ from plexpy import helpers
<%def name="javascriptIncludes()"> <%def name="javascriptIncludes()">
<script src="interfaces/default/js/jquery.rateit.min.js"></script> <script src="interfaces/default/js/jquery.rateit.min.js"></script>
<script src="interfaces/default/js/jquery.dataTables.min.js"></script> <script src="interfaces/default/js/jquery.dataTables.min.js"></script>
<script src="interfaces/default/js/dataTables.responsive.js"></script>
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script> <script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
<script src="interfaces/default/js/moment-with-locale.js"></script> <script src="interfaces/default/js/moment-with-locale.js"></script>

View file

@ -0,0 +1,873 @@
/*! Responsive 1.0.6
* 2014-2015 SpryMedia Ltd - datatables.net/license
*/
/**
* @summary Responsive
* @description Responsive tables plug-in for DataTables
* @version 1.0.6
* @file dataTables.responsive.js
* @author SpryMedia Ltd (www.sprymedia.co.uk)
* @contact www.sprymedia.co.uk/contact
* @copyright Copyright 2014-2015 SpryMedia Ltd.
*
* This source file is free software, available under the following license:
* MIT license - http://datatables.net/license/mit
*
* This source file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
*
* For details please refer to: http://www.datatables.net
*/
(function(window, document, undefined) {
var factory = function( $, DataTable ) {
"use strict";
/**
* Responsive is a plug-in for the DataTables library that makes use of
* DataTables' ability to change the visibility of columns, changing the
* visibility of columns so the displayed columns fit into the table container.
* The end result is that complex tables will be dynamically adjusted to fit
* into the viewport, be it on a desktop, tablet or mobile browser.
*
* Responsive for DataTables has two modes of operation, which can used
* individually or combined:
*
* * Class name based control - columns assigned class names that match the
* breakpoint logic can be shown / hidden as required for each breakpoint.
* * Automatic control - columns are automatically hidden when there is no
* room left to display them. Columns removed from the right.
*
* In additional to column visibility control, Responsive also has built into
* options to use DataTables' child row display to show / hide the information
* from the table that has been hidden. There are also two modes of operation
* for this child row display:
*
* * Inline - when the control element that the user can use to show / hide
* child rows is displayed inside the first column of the table.
* * Column - where a whole column is dedicated to be the show / hide control.
*
* Initialisation of Responsive is performed by:
*
* * Adding the class `responsive` or `dt-responsive` to the table. In this case
* Responsive will automatically be initialised with the default configuration
* options when the DataTable is created.
* * Using the `responsive` option in the DataTables configuration options. This
* can also be used to specify the configuration options, or simply set to
* `true` to use the defaults.
*
* @class
* @param {object} settings DataTables settings object for the host table
* @param {object} [opts] Configuration options
* @requires jQuery 1.7+
* @requires DataTables 1.10.1+
*
* @example
* $('#example').DataTable( {
* responsive: true
* } );
* } );
*/
var Responsive = function ( settings, opts ) {
// Sanity check that we are using DataTables 1.10 or newer
if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.1' ) ) {
throw 'DataTables Responsive requires DataTables 1.10.1 or newer';
}
this.s = {
dt: new DataTable.Api( settings ),
columns: []
};
// Check if responsive has already been initialised on this table
if ( this.s.dt.settings()[0].responsive ) {
return;
}
// details is an object, but for simplicity the user can give it as a string
if ( opts && typeof opts.details === 'string' ) {
opts.details = { type: opts.details };
}
this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
settings.responsive = this;
this._constructor();
};
Responsive.prototype = {
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constructor
*/
/**
* Initialise the Responsive instance
*
* @private
*/
_constructor: function ()
{
var that = this;
var dt = this.s.dt;
dt.settings()[0]._responsive = this;
// Use DataTables' private throttle function to avoid processor thrashing
$(window).on( 'resize.dtr orientationchange.dtr', dt.settings()[0].oApi._fnThrottle( function () {
that._resize();
} ) );
// Destroy event handler
dt.on( 'destroy.dtr', function () {
$(window).off( 'resize.dtr orientationchange.dtr draw.dtr' );
} );
// Reorder the breakpoints array here in case they have been added out
// of order
this.c.breakpoints.sort( function (a, b) {
return a.width < b.width ? 1 :
a.width > b.width ? -1 : 0;
} );
// Determine which columns are already hidden, and should therefore
// remain hidden. todo - should this be done? See thread 22677
//
// this.s.alwaysHidden = dt.columns(':hidden').indexes();
this._classLogic();
this._resizeAuto();
// Details handler
var details = this.c.details;
if ( details.type ) {
that._detailsInit();
this._detailsVis();
dt.on( 'column-visibility.dtr', function () {
that._detailsVis();
} );
// Redraw the details box on each draw. This is used until
// DataTables implements a native `updated` event for rows
dt.on( 'draw.dtr', function () {
dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
var row = dt.row( idx );
if ( row.child.isShown() ) {
var info = that.c.details.renderer( dt, idx );
row.child( info, 'child' ).show();
}
} );
} );
$(dt.table().node()).addClass( 'dtr-'+details.type );
}
// First pass - draw the table for the current viewport size
this._resize();
},
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Private methods
*/
/**
* Calculate the visibility for the columns in a table for a given
* breakpoint. The result is pre-determined based on the class logic if
* class names are used to control all columns, but the width of the table
* is also used if there are columns which are to be automatically shown
* and hidden.
*
* @param {string} breakpoint Breakpoint name to use for the calculation
* @return {array} Array of boolean values initiating the visibility of each
* column.
* @private
*/
_columnsVisiblity: function ( breakpoint )
{
var dt = this.s.dt;
var columns = this.s.columns;
var i, ien;
// Class logic - determine which columns are in this breakpoint based
// on the classes. If no class control (i.e. `auto`) then `-` is used
// to indicate this to the rest of the function
var display = $.map( columns, function ( col ) {
return col.auto && col.minWidth === null ?
false :
col.auto === true ?
'-' :
$.inArray( breakpoint, col.includeIn ) !== -1;
} );
// Auto column control - first pass: how much width is taken by the
// ones that must be included from the non-auto columns
var requiredWidth = 0;
for ( i=0, ien=display.length ; i<ien ; i++ ) {
if ( display[i] === true ) {
requiredWidth += columns[i].minWidth;
}
}
// Second pass, use up any remaining width for other columns. For
// scrolling tables we need to subtract the width of the scrollbar. It
// may not be requires which makes this sub-optimal, but it would
// require another full redraw to make complete use of those extra few
// pixels
var scrolling = dt.settings()[0].oScroll;
var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
var widthAvailable = dt.table().container().offsetWidth - bar;
var usedWidth = widthAvailable - requiredWidth;
// Control column needs to always be included. This makes it sub-
// optimal in terms of using the available with, but to stop layout
// thrashing or overflow. Also we need to account for the control column
// width first so we know how much width is available for the other
// columns, since the control column might not be the first one shown
for ( i=0, ien=display.length ; i<ien ; i++ ) {
if ( columns[i].control ) {
usedWidth -= columns[i].minWidth;
}
}
// Allow columns to be shown (counting from the left) until we run out
// of room
var empty = false;
for ( i=0, ien=display.length ; i<ien ; i++ ) {
if ( display[i] === '-' && ! columns[i].control ) {
// Once we've found a column that won't fit we don't let any
// others display either, or columns might disappear in the
// middle of the table
if ( empty || usedWidth - columns[i].minWidth < 0 ) {
empty = true;
display[i] = false;
}
else {
display[i] = true;
}
usedWidth -= columns[i].minWidth;
}
}
// Determine if the 'control' column should be shown (if there is one).
// This is the case when there is a hidden column (that is not the
// control column). The two loops look inefficient here, but they are
// trivial and will fly through. We need to know the outcome from the
// first , before the action in the second can be taken
var showControl = false;
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
if ( ! columns[i].control && ! columns[i].never && ! display[i] ) {
showControl = true;
break;
}
}
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
if ( columns[i].control ) {
display[i] = showControl;
}
}
// Finally we need to make sure that there is at least one column that
// is visible
if ( $.inArray( true, display ) === -1 ) {
display[0] = true;
}
return display;
},
/**
* Create the internal `columns` array with information about the columns
* for the table. This includes determining which breakpoints the column
* will appear in, based upon class names in the column, which makes up the
* vast majority of this method.
*
* @private
*/
_classLogic: function ()
{
var that = this;
var calc = {};
var breakpoints = this.c.breakpoints;
var columns = this.s.dt.columns().eq(0).map( function (i) {
var className = this.column(i).header().className;
return {
className: className,
includeIn: [],
auto: false,
control: false,
never: className.match(/\bnever\b/) ? true : false
};
} );
// Simply add a breakpoint to `includeIn` array, ensuring that there are
// no duplicates
var add = function ( colIdx, name ) {
var includeIn = columns[ colIdx ].includeIn;
if ( $.inArray( name, includeIn ) === -1 ) {
includeIn.push( name );
}
};
var column = function ( colIdx, name, operator, matched ) {
var size, i, ien;
if ( ! operator ) {
columns[ colIdx ].includeIn.push( name );
}
else if ( operator === 'max-' ) {
// Add this breakpoint and all smaller
size = that._find( name ).width;
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
if ( breakpoints[i].width <= size ) {
add( colIdx, breakpoints[i].name );
}
}
}
else if ( operator === 'min-' ) {
// Add this breakpoint and all larger
size = that._find( name ).width;
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
if ( breakpoints[i].width >= size ) {
add( colIdx, breakpoints[i].name );
}
}
}
else if ( operator === 'not-' ) {
// Add all but this breakpoint (xxx need extra information)
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
add( colIdx, breakpoints[i].name );
}
}
}
};
// Loop over each column and determine if it has a responsive control
// class
columns.each( function ( col, i ) {
var classNames = col.className.split(' ');
var hasClass = false;
// Split the class name up so multiple rules can be applied if needed
for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
var className = $.trim( classNames[k] );
if ( className === 'all' ) {
// Include in all
hasClass = true;
col.includeIn = $.map( breakpoints, function (a) {
return a.name;
} );
return;
}
else if ( className === 'none' || className === 'never' ) {
// Include in none (default) and no auto
hasClass = true;
return;
}
else if ( className === 'control' ) {
// Special column that is only visible, when one of the other
// columns is hidden. This is used for the details control
hasClass = true;
col.control = true;
return;
}
$.each( breakpoints, function ( j, breakpoint ) {
// Does this column have a class that matches this breakpoint?
var brokenPoint = breakpoint.name.split('-');
var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
var match = className.match( re );
if ( match ) {
hasClass = true;
if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
// Class name matches breakpoint name fully
column( i, breakpoint.name, match[1], match[2]+match[3] );
}
else if ( match[2] === brokenPoint[0] && ! match[3] ) {
// Class name matched primary breakpoint name with no qualifier
column( i, breakpoint.name, match[1], match[2] );
}
}
} );
}
// If there was no control class, then automatic sizing is used
if ( ! hasClass ) {
col.auto = true;
}
} );
this.s.columns = columns;
},
/**
* Initialisation for the details handler
*
* @private
*/
_detailsInit: function ()
{
var that = this;
var dt = this.s.dt;
var details = this.c.details;
// The inline type always uses the first child as the target
if ( details.type === 'inline' ) {
details.target = 'td:first-child';
}
// type.target can be a string jQuery selector or a column index
var target = details.target;
var selector = typeof target === 'string' ? target : 'td';
// Click handler to show / hide the details rows when they are available
$( dt.table().body() ).on( 'click', selector, function (e) {
// If the table is not collapsed (i.e. there is no hidden columns)
// then take no action
if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
return;
}
// Check that the row is actually a DataTable's controlled node
if ( ! dt.row( $(this).closest('tr') ).length ) {
return;
}
// For column index, we determine if we should act or not in the
// handler - otherwise it is already okay
if ( typeof target === 'number' ) {
var targetIdx = target < 0 ?
dt.columns().eq(0).length + target :
target;
if ( dt.cell( this ).index().column !== targetIdx ) {
return;
}
}
// $().closest() includes itself in its check
var row = dt.row( $(this).closest('tr') );
if ( row.child.isShown() ) {
row.child( false );
$( row.node() ).removeClass( 'parent' );
}
else {
var info = that.c.details.renderer( dt, row[0] );
row.child( info, 'child' ).show();
$( row.node() ).addClass( 'parent' );
}
} );
},
/**
* Update the child rows in the table whenever the column visibility changes
*
* @private
*/
_detailsVis: function ()
{
var that = this;
var dt = this.s.dt;
// Find how many columns are hidden
var hiddenColumns = dt.columns().indexes().filter( function ( idx ) {
var col = dt.column( idx );
if ( col.visible() ) {
return null;
}
// Only counts as hidden if it doesn't have the `never` class
return $( col.header() ).hasClass( 'never' ) ? null : idx;
} );
var haveHidden = true;
if ( hiddenColumns.length === 0 || ( hiddenColumns.length === 1 && this.s.columns[ hiddenColumns[0] ].control ) ) {
haveHidden = false;
}
if ( haveHidden ) {
// Show all existing child rows
dt.rows( { page: 'current' } ).eq(0).each( function (idx) {
var row = dt.row( idx );
if ( row.child() ) {
var info = that.c.details.renderer( dt, row[0] );
// The renderer can return false to have no child row
if ( info === false ) {
row.child.hide();
}
else {
row.child( info, 'child' ).show();
}
}
} );
}
else {
// Hide all existing child rows
dt.rows( { page: 'current' } ).eq(0).each( function (idx) {
dt.row( idx ).child.hide();
} );
}
},
/**
* Find a breakpoint object from a name
* @param {string} name Breakpoint name to find
* @return {object} Breakpoint description object
*/
_find: function ( name )
{
var breakpoints = this.c.breakpoints;
for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
if ( breakpoints[i].name === name ) {
return breakpoints[i];
}
}
},
/**
* Alter the table display for a resized viewport. This involves first
* determining what breakpoint the window currently is in, getting the
* column visibilities to apply and then setting them.
*
* @private
*/
_resize: function ()
{
var dt = this.s.dt;
var width = $(window).width();
var breakpoints = this.c.breakpoints;
var breakpoint = breakpoints[0].name;
var columns = this.s.columns;
var i, ien;
// Determine what breakpoint we are currently at
for ( i=breakpoints.length-1 ; i>=0 ; i-- ) {
if ( width <= breakpoints[i].width ) {
breakpoint = breakpoints[i].name;
break;
}
}
// Show the columns for that break point
var columnsVis = this._columnsVisiblity( breakpoint );
// Set the class before the column visibility is changed so event
// listeners know what the state is. Need to determine if there are
// any columns that are not visible but can be shown
var collapsedClass = false;
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
if ( columnsVis[i] === false && ! columns[i].never ) {
collapsedClass = true;
break;
}
}
$( dt.table().node() ).toggleClass('collapsed', collapsedClass );
dt.columns().eq(0).each( function ( colIdx, i ) {
dt.column( colIdx ).visible( columnsVis[i] );
} );
},
/**
* Determine the width of each column in the table so the auto column hiding
* has that information to work with. This method is never going to be 100%
* perfect since column widths can change slightly per page, but without
* seriously compromising performance this is quite effective.
*
* @private
*/
_resizeAuto: function ()
{
var dt = this.s.dt;
var columns = this.s.columns;
// Are we allowed to do auto sizing?
if ( ! this.c.auto ) {
return;
}
// Are there any columns that actually need auto-sizing, or do they all
// have classes defined
if ( $.inArray( true, $.map( columns, function (c) { return c.auto; } ) ) === -1 ) {
return;
}
// Clone the table with the current data in it
var tableWidth = dt.table().node().offsetWidth;
var columnWidths = dt.columns;
var clonedTable = dt.table().node().cloneNode( false );
var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
var clonedBody = $( dt.table().body().cloneNode( false ) ).appendTo( clonedTable );
$( dt.table().footer() ).clone( false ).appendTo( clonedTable );
// This is a bit slow, but we need to get a clone of each row that
// includes all columns. As such, try to do this as little as possible.
dt.rows( { page: 'current' } ).indexes().flatten().each( function ( idx ) {
var clone = dt.row( idx ).node().cloneNode( true );
if ( dt.columns( ':hidden' ).flatten().length ) {
$(clone).append( dt.cells( idx, ':hidden' ).nodes().to$().clone() );
}
$(clone).appendTo( clonedBody );
} );
var cells = dt.columns().header().to$().clone( false );
$('<tr/>')
.append( cells )
.appendTo( clonedHeader );
// In the inline case extra padding is applied to the first column to
// give space for the show / hide icon. We need to use this in the
// calculation
if ( this.c.details.type === 'inline' ) {
$(clonedTable).addClass( 'dtr-inline collapsed' );
}
var inserted = $('<div/>')
.css( {
width: 1,
height: 1,
overflow: 'hidden'
} )
.append( clonedTable );
// Remove columns which are not to be included
inserted.find('th.never, td.never').remove();
inserted.insertBefore( dt.table().node() );
// The cloned header now contains the smallest that each column can be
dt.columns().eq(0).each( function ( idx ) {
columns[idx].minWidth = cells[ idx ].offsetWidth || 0;
} );
inserted.remove();
}
};
/**
* List of default breakpoints. Each item in the array is an object with two
* properties:
*
* * `name` - the breakpoint name.
* * `width` - the breakpoint width
*
* @name Responsive.breakpoints
* @static
*/
Responsive.breakpoints = [
{ name: 'desktop', width: Infinity },
{ name: 'tablet-l', width: 1024 },
{ name: 'tablet-p', width: 768 },
{ name: 'mobile-l', width: 480 },
{ name: 'mobile-p', width: 320 }
];
/**
* Responsive default settings for initialisation
*
* @namespace
* @name Responsive.defaults
* @static
*/
Responsive.defaults = {
/**
* List of breakpoints for the instance. Note that this means that each
* instance can have its own breakpoints. Additionally, the breakpoints
* cannot be changed once an instance has been creased.
*
* @type {Array}
* @default Takes the value of `Responsive.breakpoints`
*/
breakpoints: Responsive.breakpoints,
/**
* Enable / disable auto hiding calculations. It can help to increase
* performance slightly if you disable this option, but all columns would
* need to have breakpoint classes assigned to them
*
* @type {Boolean}
* @default `true`
*/
auto: true,
/**
* Details control. If given as a string value, the `type` property of the
* default object is set to that value, and the defaults used for the rest
* of the object - this is for ease of implementation.
*
* The object consists of the following properties:
*
* * `renderer` - function that is called for display of the child row data.
* The default function will show the data from the hidden columns
* * `target` - Used as the selector for what objects to attach the child
* open / close to
* * `type` - `false` to disable the details display, `inline` or `column`
* for the two control types
*
* @type {Object|string}
*/
details: {
renderer: function ( api, rowIdx ) {
var data = api.cells( rowIdx, ':hidden' ).eq(0).map( function ( cell ) {
var header = $( api.column( cell.column ).header() );
var idx = api.cell( cell ).index();
if ( header.hasClass( 'control' ) || header.hasClass( 'never' ) ) {
return '';
}
// Use a non-public DT API method to render the data for display
// This needs to be updated when DT adds a suitable method for
// this type of data retrieval
var dtPrivate = api.settings()[0];
var cellData = dtPrivate.oApi._fnGetCellData(
dtPrivate, idx.row, idx.column, 'display'
);
var title = header.text();
if ( title ) {
title = title + ':';
}
return '<li data-dtr-index="'+idx.column+'">'+
'<span class="dtr-title">'+
title+
'</span> '+
'<span class="dtr-data">'+
cellData+
'</span>'+
'</li>';
} ).toArray().join('');
return data ?
$('<ul data-dtr-index="'+rowIdx+'"/>').append( data ) :
false;
},
target: 0,
type: 'inline'
}
};
/*
* API
*/
var Api = $.fn.dataTable.Api;
// Doesn't do anything - work around for a bug in DT... Not documented
Api.register( 'responsive()', function () {
return this;
} );
Api.register( 'responsive.index()', function ( li ) {
li = $(li);
return {
column: li.data('dtr-index'),
row: li.parent().data('dtr-index')
};
} );
Api.register( 'responsive.rebuild()', function () {
return this.iterator( 'table', function ( ctx ) {
if ( ctx._responsive ) {
ctx._responsive._classLogic();
}
} );
} );
Api.register( 'responsive.recalc()', function () {
return this.iterator( 'table', function ( ctx ) {
if ( ctx._responsive ) {
ctx._responsive._resizeAuto();
ctx._responsive._resize();
}
} );
} );
/**
* Version information
*
* @name Responsive.version
* @static
*/
Responsive.version = '1.0.6';
$.fn.dataTable.Responsive = Responsive;
$.fn.DataTable.Responsive = Responsive;
// Attach a listener to the document which listens for DataTables initialisation
// events so we can automatically initialise
$(document).on( 'init.dt.dtr', function (e, settings, json) {
if ( e.namespace !== 'dt' ) {
return;
}
if ( $(settings.nTable).hasClass( 'responsive' ) ||
$(settings.nTable).hasClass( 'dt-responsive' ) ||
settings.oInit.responsive ||
DataTable.defaults.responsive
) {
var init = settings.oInit.responsive;
if ( init !== false ) {
new Responsive( settings, $.isPlainObject( init ) ? init : {} );
}
}
} );
return Responsive;
}; // /factory
// Define as an AMD module if possible
if ( typeof define === 'function' && define.amd ) {
define( ['jquery', 'datatables'], factory );
}
else if ( typeof exports === 'object' ) {
// Node/CommonJS
factory( require('jquery'), require('datatables') );
}
else if ( jQuery && !jQuery.fn.dataTable.Responsive ) {
// Otherwise simply initialise as normal, stopping multiple evaluation
factory( jQuery, jQuery.fn.dataTable );
}
})(window, document);

View file

@ -12,6 +12,9 @@ $.ajax({
history_table_options = { history_table_options = {
"destroy": true, "destroy": true,
"responsive": {
details: false
},
"language": { "language": {
"search": "Search: ", "search": "Search: ",
"lengthMenu":"Show _MENU_ entries per page", "lengthMenu":"Show _MENU_ entries per page",
@ -24,14 +27,15 @@ history_table_options = {
"sPaginationType": "bootstrap", "sPaginationType": "bootstrap",
"processing": false, "processing": false,
"serverSide": true, "serverSide": true,
"pageLength": 10, "pageLength": 25,
"order": [ 1, 'desc'], "order": [ 1, 'desc'],
"columnDefs": [ "columnDefs": [
{ {
"targets": [0], "targets": [0],
"data":"id", "data":"id",
"visible": false, "visible": false,
"searchable": false "searchable": false,
"className": "no-wrap"
}, },
{ {
"targets": [1], "targets": [1],
@ -44,7 +48,8 @@ history_table_options = {
$(td).html(moment(cellData,"X").format(date_format)); $(td).html(moment(cellData,"X").format(date_format));
} }
}, },
"searchable": false "searchable": false,
"className": "no-wrap"
}, },
{ {
"targets": [2], "targets": [2],
@ -56,6 +61,7 @@ history_table_options = {
$(td).html(cellData); $(td).html(cellData);
} }
}, },
"className": "no-wrap"
}, },
{ {
"targets": [3], "targets": [3],
@ -65,7 +71,7 @@ history_table_options = {
$(td).html('<a href="#info-modal" data-toggle="modal"><span data-toggle="tooltip" data-placement="left" title="Stream Info" id="stream-info" class="badge badge-inverse"><i class="fa fa-info"></i></span></a>&nbsp'+cellData); $(td).html('<a href="#info-modal" data-toggle="modal"><span data-toggle="tooltip" data-placement="left" title="Stream Info" id="stream-info" class="badge badge-inverse"><i class="fa fa-info"></i></span></a>&nbsp'+cellData);
} }
}, },
"className": "modal-control" "className": "modal-control no-wrap"
}, },
{ {
"targets": [4], "targets": [4],
@ -74,7 +80,8 @@ history_table_options = {
if ((cellData == '') || (cellData == '0')) { if ((cellData == '') || (cellData == '0')) {
$(td).html('n/a'); $(td).html('n/a');
} }
} },
"className": "no-wrap"
}, },
{ {
"targets": [5], "targets": [5],
@ -82,7 +89,7 @@ history_table_options = {
"name":"title", "name":"title",
"createdCell": function (td, cellData, rowData, row, col) { "createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== '') { if (cellData !== '') {
$(td).html('<div class="history-table-title"><a href="info?rating_key=' + rowData['rating_key'] + '">' + cellData + '</a></div>'); $(td).html('<a href="info?rating_key=' + rowData['rating_key'] + '">' + cellData + '</a>');
} }
} }
}, },
@ -92,7 +99,8 @@ history_table_options = {
"render": function ( data, type, full ) { "render": function ( data, type, full ) {
return moment(data, "X").format(time_format); return moment(data, "X").format(time_format);
}, },
"searchable": false "searchable": false,
"className": "no-wrap"
}, },
{ {
"targets": [7], "targets": [7],
@ -100,7 +108,8 @@ history_table_options = {
"render": function ( data, type, full ) { "render": function ( data, type, full ) {
return Math.round(moment.duration(data, 'seconds').as('minutes')) + ' mins'; return Math.round(moment.duration(data, 'seconds').as('minutes')) + ' mins';
}, },
"searchable": false "searchable": false,
"className": "no-wrap"
}, },
{ {
"targets": [8], "targets": [8],
@ -112,7 +121,8 @@ history_table_options = {
return data; return data;
} }
}, },
"searchable": false "searchable": false,
"className": "no-wrap"
}, },
{ {
"targets": [9], "targets": [9],
@ -124,7 +134,8 @@ history_table_options = {
return data; return data;
} }
}, },
"searchable": false "searchable": false,
"className": "no-wrap"
}, },
{ {
"targets": [10], "targets": [10],
@ -137,7 +148,8 @@ history_table_options = {
return '<span class="badge">100%</span>'; return '<span class="badge">100%</span>';
} }
}, },
"searchable": false "searchable": false,
"className": "no-wrap"
}, },
{ {
"targets": [11], "targets": [11],

View file

@ -1,4 +1,7 @@
$('#log_table').dataTable( { $('#log_table').dataTable( {
"responsive": {
details: false
},
"processing": false, "processing": false,
"serverSide": true, "serverSide": true,
"ajax": { "ajax": {

View file

@ -1,4 +1,7 @@
user_ip_table_options = { user_ip_table_options = {
"responsive": {
details: false
},
"destroy": true, "destroy": true,
"language": { "language": {
"search": "Search: ", "search": "Search: ",
@ -23,7 +26,8 @@ user_ip_table_options = {
return moment(data, "X").fromNow(); return moment(data, "X").fromNow();
}, },
"searchable": false, "searchable": false,
"width": "15%" "width": "15%",
"className": "no-wrap"
}, },
{ {
"targets": [1], "targets": [1],
@ -41,7 +45,8 @@ user_ip_table_options = {
$(td).html('<a href="#ip-info-modal" data-toggle="modal"><span data-toggle="ip-tooltip" data-placement="left" title="IP Address Info" id="ip-info"><i class="icon-map-marker icon-white"></i></span>&nbsp' + cellData +'</a>'); $(td).html('<a href="#ip-info-modal" data-toggle="modal"><span data-toggle="ip-tooltip" data-placement="left" title="IP Address Info" id="ip-info"><i class="icon-map-marker icon-white"></i></span>&nbsp' + cellData +'</a>');
} }
}, },
"width": "15%" "width": "15%",
"className": "no-wrap"
}, },
{ {
"targets": [2], "targets": [2],

View file

@ -1,4 +1,7 @@
users_list_table_options = { users_list_table_options = {
"responsive": {
details: false
},
"language": { "language": {
"search": "Search: ", "search": "Search: ",
"lengthMenu":"Show _MENU_ entries per page", "lengthMenu":"Show _MENU_ entries per page",

View file

@ -5,6 +5,7 @@ from plexpy import helpers
<%def name="headIncludes()"> <%def name="headIncludes()">
<link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css"> <link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css">
<link rel="stylesheet" href="interfaces/default/css/dataTables.responsive.css">
<style> <style>
td {word-wrap: break-word} td {word-wrap: break-word}
</style> </style>
@ -33,13 +34,13 @@ from plexpy import helpers
<div class='container-fluid'> <div class='container-fluid'>
<div class='row-fluid'> <div class='row-fluid'>
<div class='span12'> <div class='span12'>
<div class='wellbg'> <div class='table-card-back'>
<table class="display" id="log_table" width="100%"> <table class="display" id="log_table" width="100%">
<thead> <thead>
<tr> <tr>
<th align='left' id="timestamp"><i class='fa fa-sort'></i> Timestamp</th> <th align='left' id="timestamp">Timestamp</th>
<th align='left' id="level"><i class='fa fa-sort'></i> Level</th> <th align='left' id="level">Level</th>
<th align='left' id="message"><i class='fa fa-sort'></i> Message</th> <th align='left' id="message">Message</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -67,6 +68,7 @@ from plexpy import helpers
<%def name="javascriptIncludes()"> <%def name="javascriptIncludes()">
<script src="interfaces/default/js/jquery.dataTables.min.js"></script> <script src="interfaces/default/js/jquery.dataTables.min.js"></script>
<script src="interfaces/default/js/dataTables.responsive.js"></script>
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script> <script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
<script src="interfaces/default/js/tables/logs.js"></script> <script src="interfaces/default/js/tables/logs.js"></script>
<script> <script>

View file

@ -22,6 +22,7 @@ from plexpy import helpers
<%def name="headIncludes()"> <%def name="headIncludes()">
<link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css"> <link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css">
<link rel="stylesheet" href="interfaces/default/css/dataTables.responsive.css">
</%def> </%def>
% if user != None: % if user != None:
@ -105,31 +106,30 @@ from plexpy import helpers
<div class="container-fluid"> <div class="container-fluid">
<div class="row-fluid"> <div class="row-fluid">
<div class="span12"> <div class="span12">
<div class="wellbg"> <div class="table-card-back">
<div class="wellheader">
<div class="dashboard-wellheader">
<h3>IP Addresses for <strong> <h3>IP Addresses for <strong>
${user} ${user}
</strong></h3> </strong></h3>
</div> </div>
</div> <div class="table-card-back">
<table id="user_ip_table" class="display" width="100%"> <table id="user_ip_table" class="display" width="100%">
<thead> <thead>
<tr> <tr>
<th align="left"><i class="fa fa-sort"></i> Last seen</th> <th class="all" align="left">Last seen</th>
<th align="left"><i class="fa fa-sort"></i> IP Address</th> <th class="all" align="left">IP Address</th>
<th align="left"><i class="fa fa-sort"></i> Play Count</th> <th class="min-tablet" align="left">Play Count</th>
<th align="left"><i class="fa fa-sort"></i> Platform (Last Seen)</th> <th class="min-tablet" align="left">Platform (Last Seen)</th>
<th align="left"> Last Watched</th> <th class="desktop" align="left">Last Watched</th>
</tr> </tr>
</thead> </thead>
</table> </table>
</div>
<div id="ip-info-modal" class="modal hide fade" tabindex="-1" role="dialog" <div id="ip-info-modal" class="modal hide fade" tabindex="-1" role="dialog"
aria-labelledby="ip-info-modal" aria-hidden="true"> aria-labelledby="ip-info-modal" aria-hidden="true">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i <button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i
class="fa fa-remove"></i></button> class="fa fa-remove"></i></button>
<h3 id="myModalLabel">IP Address: <strong><span id="ip_address"></span></strong></h3> <h3 id="myModalLabel">IP Address: <strong><span id="modal_header_ip_address"></span></strong></h3>
</div> </div>
<div class="modal-body" id="modal-text"> <div class="modal-body" id="modal-text">
<div class="span6"> <div class="span6">
@ -158,40 +158,38 @@ from plexpy import helpers
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="tab-pane" id="userHistory"> <div class="tab-pane" id="userHistory">
<div class="container-fluid"> <div class="container-fluid">
<div class="row-fluid"> <div class="row-fluid">
<div class="span12"> <div class="span12">
<div class="wellbg"> <div class="table-card-back">
<div class="wellheader">
<div class="dashboard-wellheader">
<h3>Watch History for <strong> <h3>Watch History for <strong>
${user} ${user}
</strong></h3> </strong></h3>
</div> </div>
</div> <div class="table-card-back">
<table class="display" id="history_table" width="100%"> <table class="display" id="history_table" width="100%">
<thead> <thead>
<tr> <tr>
<th align='left' id="id"><i class='fa fa-sort'></i> ID</th> <th class="never" align='left' id="id">ID</th>
<th align='left' id="date"><i class='fa fa-sort'></i> Time</th> <th class="all" align='left' id="time">Time</th>
<th align='left' id="user"><i class='fa fa-sort'></i> User</th> <th class="never" align='left' id="user">User</th>
<th align='left' id="platform"><i class='fa fa-sort'></i> Platform</th> <th class="min-tablet" align='left' id="platform">Platform</th>
<th align='left' id="ip_address"><i class='fa fa-sort'></i> IP Address</th> <th class="desktop" align='left' id="ip_address">IP Address</th>
<th align='left' id="title"><i class='fa fa-sort'></i> Title</th> <th class="min-tablet" align='left' id="title">Title</th>
<th align='left' id="started"><i class='fa fa-sort'></i> Started</th> <th class="desktop" align='left' id="started">Started</th>
<th align='left' id="paused_counter"><i class='fa fa-sort'></i> Paused</th> <th class="desktop" align='left' id="paused_counter">Paused</th>
<th align='left' id="stopped"><i class='fa fa-sort'></i> Stopped</th> <th class="desktop" align='left' id="stopped">Stopped</th>
<th align='left' id="duration"><i class='fa fa-sort'></i> Duration</th> <th class="desktop" align='left' id="duration">Duration</th>
<th align='left' id="percent_complete"> Completed</th> <th class="desktop" align='left' id="percent_complete">Completed</th>
<th align='left' id="rating_key"> RatingKey</th> <th class="never" align='left' id="rating_key">RatingKey</th>
<th align='left' id="xml"></th> <th class="never" align='left' id="xml"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
</tbody> </tbody>
</table> </table>
</div>
<div id="info-modal" class="modal hide fade" tabindex="-1" role="dialog" <div id="info-modal" class="modal hide fade" tabindex="-1" role="dialog"
aria-labelledby="info-modal" aria-hidden="true"> aria-labelledby="info-modal" aria-hidden="true">
</div> </div>
@ -199,13 +197,13 @@ from plexpy import helpers
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>
<footer></footer> <footer></footer>
</%def> </%def>
<%def name="javascriptIncludes()"> <%def name="javascriptIncludes()">
<script src="interfaces/default/js/jquery.dataTables.min.js"></script> <script src="interfaces/default/js/jquery.dataTables.min.js"></script>
<script src="interfaces/default/js/dataTables.responsive.js"></script>
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script> <script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
<script src="interfaces/default/js/moment-with-locale.js"></script> <script src="interfaces/default/js/moment-with-locale.js"></script>
<script src="interfaces/default/js/tables/history_table.js"></script> <script src="interfaces/default/js/tables/history_table.js"></script>

View file

@ -5,6 +5,7 @@ from plexpy import helpers
<%def name="headIncludes()"> <%def name="headIncludes()">
<link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css"> <link rel="stylesheet" href="interfaces/default/css/plexwatch-tables.css">
<link rel="stylesheet" href="interfaces/default/css/dataTables.responsive.css">
</%def> </%def>
<%def name="body()"> <%def name="body()">
@ -22,15 +23,15 @@ from plexpy import helpers
<div class='container-fluid'> <div class='container-fluid'>
<div class='row-fluid'> <div class='row-fluid'>
<div class='span12'> <div class='span12'>
<div class='wellbg'> <div class='table-card-back'>
<table id="users_list_table" class="display" width="100%"> <table id="users_list_table" class="display" width="100%">
<thead> <thead>
<tr> <tr>
<th align="right" id="avatar"></th> <th class="all" align="right" id="avatar"></th>
<th align="left" id="username"><i class='fa fa-sort'></i> User</th> <th class="all" align="left" id="username">User</th>
<th align="left" id="last_seen"><i class='fa fa-sort'></i> Last Seen</th> <th class="min-tablet" align="left" id="last_seen">Last Seen</th>
<th align="left" id="last_known_ip"><i class='fa fa-sort'></i> Last Known IP</th> <th class="min-tablet" align="left" id="last_known_ip">Last Known IP</th>
<th align="left" id="total_plays"><i class='fa fa-sort'></i> Total Plays</th> <th class="min-tablet" align="left" id="total_plays">Total Plays</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -46,6 +47,7 @@ from plexpy import helpers
<%def name="javascriptIncludes()"> <%def name="javascriptIncludes()">
<script src="interfaces/default/js/jquery.dataTables.min.js"></script> <script src="interfaces/default/js/jquery.dataTables.min.js"></script>
<script src="interfaces/default/js/dataTables.responsive.js"></script>
<script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script> <script src="interfaces/default/js/jquery.dataTables.bootstrap.pagination.integration.js"></script>
<script src="interfaces/default/js/moment-with-locale.js"></script> <script src="interfaces/default/js/moment-with-locale.js"></script>
<script src="interfaces/default/js/tables/users.js"></script> <script src="interfaces/default/js/tables/users.js"></script>