Compare commits

...

340 Commits

Author SHA1 Message Date
JonnyWong16
cff6b44109 Merge branch 'dev' 2016-01-29 21:32:37 -08:00
JonnyWong16
fb7ad9438e v1.3.4 2016-01-29 21:31:25 -08:00
JonnyWong16
afc265a188 Fix schedulers not starting with library update 2016-01-29 21:26:27 -08:00
JonnyWong16
01fe7bf612 Reorganize notification options 2016-01-29 19:06:08 -08:00
JonnyWong16
1cb75bd053 Remove unnecessary quoting of script arguments 2016-01-29 18:47:12 -08:00
JonnyWong16
0eaea4d011 Fix empty libraries not added 2016-01-29 18:38:19 -08:00
JonnyWong16
67377a2561 Fix server verification in settings 2016-01-27 23:32:21 -08:00
JonnyWong16
a8aae9f1f5 Fix libraries and users refresh 2016-01-27 23:32:01 -08:00
JonnyWong16
a9ce92decb Change Telegram wording 2016-01-27 21:30:35 -08:00
JonnyWong16
c19162295a Update Facebook instructions 2016-01-27 21:20:04 -08:00
JonnyWong16
58796c45ed Remove built in Twitter consumer key and secret 2016-01-27 21:19:18 -08:00
JonnyWong16
d94b348780 Fix buffer notifications even when disabled with websockets 2016-01-27 19:52:30 -08:00
JonnyWong16
95f92bd292 Add unique identifiers to notification options 2016-01-27 19:51:58 -08:00
JonnyWong16
bc52ac3559 Remove media type toggles from recently added notifications 2016-01-27 19:51:36 -08:00
JonnyWong16
8bbc6a6611 Fix libraries without section_id in database 2016-01-27 19:51:10 -08:00
JonnyWong16
8902b93a26 Merge branch 'dev' 2016-01-26 00:14:38 -08:00
JonnyWong16
ae36af807d v1.3.3 2016-01-26 00:13:58 -08:00
JonnyWong16
fd256625c6 Fix Plays by Month graph not loading 2016-01-25 18:43:51 -08:00
JonnyWong16
bee543a25a Disable datatables caching 2016-01-25 18:30:30 -08:00
JonnyWong16
55eb79cb52 Even faster library updating 2016-01-25 12:01:59 -08:00
JonnyWong16
35965a8320 Merge branch 'dev' 2016-01-24 22:52:47 -08:00
JonnyWong16
8a902ae3e6 v1.3.2 2016-01-24 22:51:36 -08:00
JonnyWong16
52bed5bf98 Attempt at improved library updating 2016-01-24 22:19:48 -08:00
JonnyWong16
9e83f6d779 Another fix for 'datestamp' and 'timestamp' 2016-01-24 09:52:20 -08:00
JonnyWong16
0ba5012464 Merge branch 'dev' 2016-01-23 22:59:46 -08:00
JonnyWong16
73ff28465d v1.3.1 2016-01-23 22:58:44 -08:00
JonnyWong16
7484d65dbb Fix datestamp and timestamp notification options 2016-01-23 22:53:13 -08:00
JonnyWong16
4a120e7a54 Fix unable to startup if library refresh fails 2016-01-23 21:06:41 -08:00
JonnyWong16
8d63d85821 Fix star rating overlapping text 2016-01-23 19:14:54 -08:00
JonnyWong16
5cec84a802 More descriptive libraries updating message 2016-01-23 19:13:16 -08:00
JonnyWong16
48da41690d Fix empty brackets on tables 2016-01-23 19:12:13 -08:00
JonnyWong16
1c82241f30 Fix notifier config ajax calls for reverse proxies 2016-01-23 16:23:20 -08:00
JonnyWong16
b1ea3bcd4e Rename last watched to last played 2016-01-23 14:06:25 -08:00
JonnyWong16
05e485b55e Merge branch 'dev' 2016-01-23 13:23:45 -08:00
JonnyWong16
c62e0e4e99 v1.3.0 2016-01-23 13:21:51 -08:00
JonnyWong16
3c6a1a02b8 Merge pull request #462 from jackwilsdon/fix-restart-dev
Use os.execv instead of subprocess.Popen to restart the process
2016-01-23 13:16:13 -08:00
JonnyWong16
cc287607cd Allow custom search query to update metadata 2016-01-23 12:40:41 -08:00
JonnyWong16
b24e9a2185 Allow custom redirect uri with Facebook notifier 2016-01-23 08:12:41 -08:00
JonnyWong16
01791eac52 Fix rating_key on sync table 2016-01-23 08:05:04 -08:00
JonnyWong16
651b57a93f Add datestamp and timestamp notification options 2016-01-22 19:16:15 -08:00
JonnyWong16
cc857364f4 Fix typos in Notifiers logger 2016-01-22 18:01:32 -08:00
JonnyWong16
f29d7c8cfb Fix stream info modal on Users and Libraries pages 2016-01-22 17:59:20 -08:00
JonnyWong16
af4d0248d9 Revert https cert and key to custom directory 2016-01-22 10:17:17 -08:00
JonnyWong16
2990664b2b Fix section_id for plexwatch import 2016-01-22 09:09:37 -08:00
Jack Wilsdon
ed52038bc4 Use os.execv instead of subprocess.Popen to restart the process
This fixes #460.
2016-01-22 13:19:27 +00:00
JonnyWong16
ee125dfadc Forgot 'not' in 2dcae5e219 2016-01-19 08:31:49 -08:00
JonnyWong16
196048cf38 Work around for iOS web app links opening in Safari 2016-01-19 00:06:14 -08:00
JonnyWong16
5faf357045 Disable logging while library update in progress 2016-01-18 23:48:31 -08:00
JonnyWong16
4e0f06f24d Remove unique constraint for section_id and username 2016-01-18 22:20:14 -08:00
JonnyWong16
717530fff7 Fix Users list not sorting alphabetically 2016-01-18 19:55:10 -08:00
JonnyWong16
4a5e38dc1e Fix error refreshing library counts when XML fails
* Also increase http request timeout to 20 seconds
2016-01-18 19:27:58 -08:00
JonnyWong16
419f8dadad Fix another typo 2016-01-18 19:03:55 -08:00
JonnyWong16
2dcae5e219 Fix folders not created in the data directory 2016-01-18 18:52:01 -08:00
JonnyWong16
36a99f70a3 Fix error when script directory doesn't exist 2016-01-18 18:30:22 -08:00
JonnyWong16
c98cf858c1 Fix typo on edit library and edit user modals 2016-01-18 18:24:07 -08:00
JonnyWong16
dd463f00a7 Fix Facebook authorization not working 2016-01-18 18:22:48 -08:00
JonnyWong16
2459340c6f Fix user duplicated in Library user stats 2016-01-18 12:59:26 -08:00
JonnyWong16
76db5ffa3a Use font awesome for star rating 2016-01-17 22:16:12 -08:00
JonnyWong16
2db0e9c280 Add all media flags 2016-01-17 22:14:16 -08:00
JonnyWong16
db6dbe6c19 Fix refresh media info table doubling rows 2016-01-17 22:14:12 -08:00
JonnyWong16
ecedd4d231 Merge pull request #263 from drzoidberg33/library-id-changes
Library id changes
2016-01-17 16:43:46 -08:00
JonnyWong16
1809b95e2d Add setting to enable calculating total file sizes
* Setting is disabled by default
2016-01-17 16:15:28 -08:00
JonnyWong16
0d7e261bd1 Improved caching and fixed tables 2016-01-17 12:34:23 -08:00
JonnyWong16
908941fb82 Prettier thumbnail popovers 2016-01-17 01:10:25 -08:00
JonnyWong16
fbacc4f789 Add media info icons to info page 2016-01-16 23:17:04 -08:00
Jonathan Wong
3c1290e8fd Some more minor changes 2016-01-16 19:27:40 -08:00
Jonathan Wong
35528ef602 Get file sizes for media info table 2016-01-16 18:23:08 -08:00
Jonathan Wong
c0f0cb0d9e Don't cache last watched or play count 2016-01-16 04:10:21 -08:00
Jonathan Wong
4a65dc1d6e Start database section id update on its own thread 2016-01-16 03:31:00 -08:00
Jonathan Wong
b4a25e33bb Fix websocket log spam
* Bug where websocket reports a session playing while /status/sessions
reports nothing.
2016-01-16 03:28:39 -08:00
Jonathan Wong
7f1a08dd04 Final clean up 2016-01-16 01:51:50 -08:00
Jonathan Wong
6152a1e913 Fix bugs with media info table 2016-01-15 22:15:45 -08:00
Jonathan Wong
002cb93187 Clean up for welcome page 2016-01-15 20:59:14 -08:00
Jonathan Wong
381c3da31c Add media info table to library page 2016-01-15 20:59:02 -08:00
Jonathan Wong
10e4d562ab Clean up graphs.py 2016-01-15 20:58:57 -08:00
Jonathan Wong
2a85e11ad9 Add library recently added 2016-01-15 20:58:55 -08:00
Jonathan Wong
95b55760ad Add sortable homepage cards 2016-01-15 20:58:53 -08:00
Jonathan Wong
636f898da8 Massive code cleanup
* Finish up library pages (toggles and notifications)
* Update user pages to match library pages
* Fix no current activity bif thumbnail at the start of a stream
* Improved logging throughout PlexPy
2016-01-15 20:58:44 -08:00
Jonathan Wong
5fedac691d Add individual library page 2016-01-15 20:50:18 -08:00
Jonathan Wong
979d68957e Clean up users page to match libraries page 2016-01-15 20:49:59 -08:00
Jonathan Wong
a5b0837cf5 Add libraries page 2016-01-15 20:49:41 -08:00
Jonathan Wong
8ba68dcfcf Change home cards config to list type 2016-01-15 20:49:22 -08:00
Jonathan Wong
8f367d140f Add item counts to database
* Add schedule task to refresh libraries list
* Update library stats to use library_sections table
2016-01-15 20:49:04 -08:00
Jonathan Wong
771885f27f Add update metadata feature
* Use rating_key instead of item_id for history info
2016-01-15 20:48:47 -08:00
Jonathan Wong
09aac22909 Initial library_id changes
* Give the library sections their own db table.
2016-01-15 20:48:29 -08:00
Jonathan Wong
1de3c0d559 Fixes for testing script notifications 2016-01-15 00:33:40 -08:00
JonnyWong16
0988b68c8c Merge pull request #391 from PHoSawyer/dev
CentOS 6.X startup script
2016-01-13 00:24:31 -08:00
Jonathan Wong
325ad4094e Clean up Web Apps 2016-01-13 00:16:50 -08:00
JonnyWong16
16a09407e4 Merge pull request #436 from zobe123/dev
Web Apps
2016-01-13 00:12:12 -08:00
JonnyWong16
84256f42c6 Merge pull request #419 from JonnyWong16/facebook-agent
Add Facebook notification agent
2016-01-12 23:28:03 -08:00
JonnyWong16
7befbef6ec Add Facebook notification agent 2016-01-12 23:22:54 -08:00
Jonathan Wong
754df5bea7 Fix to get new pms identifier on server change 2016-01-12 22:39:32 -08:00
Jonathan Wong
78ee646558 Fix for empty most concurrent stat 2016-01-12 22:06:21 -08:00
Jonathan Wong
3d6f89d309 Clean up scripts 2016-01-12 21:38:47 -08:00
JonnyWong16
e321479712 Merge pull request #373 from Hellowlol/scripts
Scripts
2016-01-12 21:05:26 -08:00
Hellowlol
9328b7e586 Add scripts 2016-01-12 22:12:48 +01:00
zobe123
50ace54cd0 improvements 2016-01-12 20:59:32 +01:00
Hellowlol
ad365c7dd0 fix conflicts 2016-01-11 22:24:13 +01:00
zobe123
11427dbecd added commits how JonnyWong16 wanted
* added iOS WebAPP Icons/Splashscreens
* added android WebAPP Icons/Splashscreens
* added IE10 Icons
* Updated plexpy.css - prevents the text is larger than the box on small
screens.
2016-01-11 21:31:46 +01:00
Jonathan Wong
b490831a50 More concurrent stream stats
* Also fix graph queries
2016-01-08 22:49:04 -08:00
JonnyWong16
af76017a79 Fix datatable paging visual bug in Firefox 2016-01-08 17:58:04 -08:00
JonnyWong16
43409b3089 Fix month name localization on play totals graph
#423
2016-01-07 20:37:00 -08:00
Jonathan Wong
bfad769f93 Return message for missing changelog file 2016-01-06 18:54:30 -08:00
Jonathan Wong
7e5dce1c14 Fix regression for grouped recently added metadata 2016-01-03 23:49:58 -08:00
JonnyWong16
8ba4bebe01 Merge pull request #401 from Hellowlol/patch-4
Enable webapp for mobile devices
2015-12-31 20:16:39 -08:00
JonnyWong16
78a87db017 Merge pull request #414 from JonnyWong16/miscellaneous-fixes
Allow SSL when verifying server in settings and test notifications
2015-12-31 20:14:12 -08:00
JonnyWong16
b73a259f68 Clean up Slack agent 2015-12-31 20:13:54 -08:00
JonnyWong16
65f27ee605 Add Email from name option 2015-12-31 20:06:31 -08:00
JonnyWong16
6d5b5e15d5 Remove PlexPy Pushover API token
* User's own API token is now required
2015-12-31 20:06:29 -08:00
JonnyWong16
f31c4dcccd Add test notification for all agents 2015-12-31 20:04:08 -08:00
JonnyWong16
1e616fa585 Allow SSL when verifying server in settings 2015-12-31 20:02:54 -08:00
JonnyWong16
0d2666f7d3 Merge pull request #418 from richipargo/slack-agent
Add slack as a notification agent
2015-12-31 19:58:57 -08:00
Ricardo Tapia
0dd8970668 added url icon validation 2015-12-31 21:13:20 -06:00
Ricardo Tapia
89cda3dcff typo for telegram agent 2015-12-31 21:08:24 -06:00
Ricardo Tapia
1d48688518 finished slack integration 2015-12-31 21:04:33 -06:00
richipargo
0b59f5e29c Slack notification config 2015-12-31 16:26:10 -06:00
Ricardo Tapia
5aebc8d191 slack config options 2015-12-31 15:34:53 -06:00
richipargo
6e00c5da04 Return Settings 2015-12-31 15:21:01 -06:00
Ricardo Tapia
50b06e041c initial agent settings 2015-12-31 13:22:27 -06:00
JonnyWong16
1c539f00dd Fix duration for grouped home stats 2015-12-27 19:46:29 -08:00
JonnyWong16
87ca432ec8 Fix get server friendly name after wizard 2015-12-26 19:55:36 -08:00
Hellowlol
ca33f4a2a5 webapp
https://github.com/drzoidberg33/plexpy/issues/398
2015-12-27 01:07:31 +01:00
Jonathan Wong
9409303f24 Merge branch 'dev' 2015-12-22 19:36:10 -08:00
Jonathan Wong
94a3d35c90 v1.2.16 2015-12-22 19:35:11 -08:00
Jonathan Wong
851de4934b Change logs to 50 line default 2015-12-22 19:31:59 -08:00
JonnyWong16
2942640eb9 Fix most concurrent stat for empty database 2015-12-22 10:21:55 -08:00
PHoSawyer
1cef037db5 CentOS 6.X startup script
Init file for CentOS 6.X systems, variables exist for different install directorys. Please note, current version of Python is 2.6 and PlexPy requires 2.7. A variable exists to point to this path.

Since PlexPy is based on Headphones, I just copied the init script for Headphones and changed the paths and added the Python2.7 path
2015-12-21 15:20:35 +00:00
Jonathan Wong
a00d43092d Merge branch 'dev' 2015-12-20 09:34:38 -08:00
Jonathan Wong
45c2f50018 v1.2.15 2015-12-20 09:33:04 -08:00
JonnyWong16
ef8c6e82e6 Merge pull request #381 from JonnyWong16/miscellaneous-fixes
Group watch statistics history
2015-12-20 03:22:39 -08:00
Jonathan Wong
3eebb58da5 Fix most concurrent count with duplicate time entires 2015-12-20 03:14:39 -08:00
Jonathan Wong
447c50fd03 Group watch statistics history 2015-12-19 20:40:30 -08:00
Jonathan Wong
0620ebebcf Touch up current activity status bar hover effect 2015-12-17 23:26:26 -08:00
JonnyWong16
cf081ee291 Merge pull request #380 from zobe123/patch-1
Added Statusbar hover effect with percentage
2015-12-17 23:18:22 -08:00
zobe123
3c29b8e9c5 Update plexpy.css
Added Statusbar hover effect with percentage
2015-12-17 23:33:53 +01:00
zobe123
6143da5a6a Update pmsconnect.py
some additions to Show readable transcode progress
2015-12-17 23:25:29 +01:00
JonnyWong16
664f71575c Merge pull request #370 from JonnyWong16/miscellaneous-fixes
Miscellaneous fixes
2015-12-16 19:52:07 -08:00
Jonathan Wong
9ae111b8a1 Fix Growl notifications 2015-12-16 19:42:51 -08:00
Jonathan Wong
18682c7a2e Add logger info for Boxcar2 notification sent 2015-12-15 19:56:14 -08:00
Jonathan Wong
b21c50dfcf Fix typo on settings page 2015-12-13 23:53:22 -08:00
Jonathan Wong
49b6965e8e Add CC and BCC and multiple email recipients 2015-12-13 15:08:43 -08:00
Jonathan Wong
c6cc2b8831 Save graph type/days/tab to config file
* Change input for graph days range
2015-12-13 11:35:33 -08:00
Jonathan Wong
f9f65eae53 Add duration to history table footer 2015-12-13 09:36:54 -08:00
Jonathan Wong
b51d442673 Add notification for remote access/server back up 2015-12-13 09:31:11 -08:00
Jonathan Wong
5863b62ccf Add notifier name to modal title 2015-12-12 17:32:32 -08:00
Jonathan Wong
66bb922012 Add stream details to notification options
* Also beautify modal
2015-12-12 17:31:52 -08:00
Jonathan Wong
53876e8f0d Add time range to most concurrent stat
* Reorder cards
2015-12-12 16:21:54 -08:00
Jonathan Wong
cb7ba7fdde Clean up if statement in current activity header 2015-12-12 14:36:57 -08:00
Jonathan Wong
9cf6793b24 Add most concurrent streams home statistic 2015-12-12 14:34:42 -08:00
Jonathan Wong
6e62ffdd22 Get Pushbullet devices automatically using API 2015-12-12 14:34:11 -08:00
Jonathan Wong
c042d9e39a Fix metadata for grouped recently added notifications 2015-12-12 14:31:04 -08:00
Jonathan Wong
1262de2ae2 Clean up notifiers 2015-12-12 14:30:42 -08:00
JonnyWong16
307230cec8 Merge pull request #365 from zobe123/patch-1
Update current_activity_header.html
2015-12-12 14:10:27 -08:00
drzoidberg33
4fa2711e78 Merge pull request #367 from drzoidberg33/frontend-tweaks
Fix greedy search bar.
2015-12-12 16:20:44 +02:00
Tim
5c9c2f9ab8 Fix greedy search bar. 2015-12-12 16:19:30 +02:00
zobe123
604155b41b Update current_activity_header.html
remove "no"
2015-12-11 22:23:14 +01:00
zobe123
6e4198e7be Update current_activity_header.html
dynamic "s" at the word stream/streams
added "no" before Activity when their is no activity
2015-12-10 23:56:02 +01:00
drzoidberg33
14d4940d05 Merge pull request #363 from InAnimaTe/dev
add .pem cert to ignore list
2015-12-09 18:47:22 +02:00
Mario Loria
a6b0cdef97 add .pem cert to ignore list 2015-12-09 11:00:53 -05:00
Tim
6265943607 Merge branch 'dev' 2015-12-07 22:32:00 +02:00
Tim
de39f7691c v1.2.14 2015-12-07 22:31:00 +02:00
drzoidberg33
921a219beb Merge pull request #352 from drzoidberg33/security-fixes
Fix regression on select_single queries Resolves #350
2015-12-07 22:26:33 +02:00
Tim
b9c95d49a6 Fix regression on select_single queries. 2015-12-07 22:22:47 +02:00
Jonathan Wong
fc0be6bce2 Merge branch 'dev' 2015-12-06 11:41:08 -08:00
Jonathan Wong
8db891cfe6 v1.2.13 2015-12-06 11:40:17 -08:00
JonnyWong16
f6e77cc578 Merge pull request #346 from JonnyWong16/miscellaneous-fixes
Fix current activity
2015-12-06 11:36:05 -08:00
Jonathan Wong
a3782f9150 Fix dict key for IP address in current activity 2015-12-06 11:30:33 -08:00
drzoidberg33
7546c7ef42 Merge pull request #345 from drzoidberg33/security-fixes
Security fixes
2015-12-06 21:23:43 +02:00
Jonathan Wong
53de8cda30 Match newline between tags for notification text 2015-12-06 11:13:46 -08:00
Tim
1fb7473dc5 Sanitize sync row items. 2015-12-06 21:04:33 +02:00
Tim
cc9d09bd54 Allow HTML encoded content to be displayed in notification setting descriptions. 2015-12-06 20:49:00 +02:00
Tim
42ff4a2f62 Merge branch 'dev' 2015-12-06 20:02:18 +02:00
Tim
3fa5f80fc4 v1.2.12 2015-12-06 20:01:38 +02:00
drzoidberg33
9b5b7ef8db Merge pull request #343 from drzoidberg33/security-fixes
No need to sanitize same items more than once.
2015-12-06 19:59:34 +02:00
Tim
560acf62fe No need to sanitize same items more than once. 2015-12-06 18:45:02 +02:00
drzoidberg33
27d12922da Merge pull request #339 from drzoidberg33/security-fixes
Move dict_factory out of database class.
2015-12-06 18:10:26 +02:00
Tim
37b92f3d88 Move dict_factory out of database class. 2015-12-06 18:09:18 +02:00
Tim
79d5c0c92e Merge branch 'dev' 2015-12-06 17:33:12 +02:00
Tim
0bdaedd486 Fix more regresssions. 2015-12-06 17:32:25 +02:00
drzoidberg33
018a201688 Merge pull request #338 from drzoidberg33/security-fixes
More dict key fixes.
2015-12-06 17:21:54 +02:00
Tim
a5bd7e6563 More dict key fixes. 2015-12-06 17:19:09 +02:00
drzoidberg33
a055feccd5 Merge pull request #337 from drzoidberg33/security-fixes
Fix changelog modal output.
2015-12-06 16:38:54 +02:00
Tim
ba68a9b52b Fix changelog modal output. 2015-12-06 16:32:07 +02:00
Tim
49669dc7e0 Merge branch 'dev' 2015-12-06 16:16:39 +02:00
Tim
5bdf79606e v1.2.10 2015-12-06 16:16:03 +02:00
drzoidberg33
ff3a9e47df Merge pull request #335 from drzoidberg33/security-fixes
Fix count type graphs.
2015-12-06 16:12:28 +02:00
Tim
a18ba24f4a Fix count type graphs. 2015-12-06 16:07:57 +02:00
Tim
baeb744a7c Merge branch 'dev' 2015-12-06 14:53:04 +02:00
Tim
d07add383f v1.2.9 2015-12-06 14:52:19 +02:00
drzoidberg33
a1f18bc133 Merge pull request #334 from drzoidberg33/security-fixes
Escape input on friendy_name change.
2015-12-06 14:41:31 +02:00
Tim
e00c23bc49 Escape input on friendy_name change. 2015-12-06 14:39:50 +02:00
drzoidberg33
0228a356e4 Merge pull request #333 from drzoidberg33/security-fixes
Better sanitization on templates and datatables output.
2015-12-06 14:18:22 +02:00
Tim
b0fa0d534e Better sanitization on templates and datatables output. 2015-12-06 14:09:38 +02:00
Jonathan Wong
1157fda96c Hide Pushalot notifier message logging 2015-12-06 00:52:43 -08:00
Jonathan Wong
bbf774379d Merge branch 'dev' 2015-12-05 23:45:35 -08:00
Jonathan Wong
24c8c4319d v1.2.8 2015-12-05 23:44:02 -08:00
JonnyWong16
3b8f9f5892 Merge pull request #328 from JonnyWong16/miscellaneous-fixes
Fix recently added
2015-12-05 23:28:49 -08:00
Jonathan Wong
b47ccd06f9 Sanitize player name 2015-12-05 23:26:54 -08:00
Jonathan Wong
8c4292f9ac Fix recently added using added at time 2015-12-05 14:23:10 -08:00
JonnyWong16
a8fbf8ab1d Merge pull request #327 from zobe123/dev
add Microsoft Edge platform
2015-12-05 11:05:30 -08:00
zobe123
38e9938666 Add Microsoft Edge platform image. 2015-12-05 13:31:56 +01:00
zobe123
93c4a0652e Revert "Add Image for Microsoft Edge"
This reverts commit d12b57e1de.
2015-12-05 13:29:10 +01:00
zobe123
2fff6647fd Revert "Update msedge.png"
This reverts commit 36f0f60c49.
2015-12-05 13:29:01 +01:00
zobe123
36f0f60c49 Update msedge.png 2015-12-05 13:02:53 +01:00
zobe123
d12b57e1de Add Image for Microsoft Edge 2015-12-05 13:02:19 +01:00
zobe123
deb16428ed Update script.js 2015-12-05 12:57:26 +01:00
drzoidberg33
a75aba4aee Merge pull request #324 from JonnyWong16/miscellaneous-fixes
Only schedule job for recently added or monitor remote access if sett…
2015-12-04 20:12:44 +02:00
Jonathan Wong
bb5aa2be3d Remember previous recently added items
* Only pull metadata if there are new recently added items since the
last check
2015-12-03 19:50:46 -08:00
Jonathan Wong
ef6ef98541 Clean up settings help text and wording 2015-12-03 19:07:24 -08:00
Jonathan Wong
89f581f63e Only schedule job for recently added or monitor remote access if setting enabled 2015-12-03 18:40:18 -08:00
JonnyWong16
6081fa329b Merge pull request #321 from JonnyWong16/miscellaneous-fixes
Miscellaneous fixes
2015-12-03 10:39:12 -08:00
Jonathan Wong
112811f3e2 Fix subject UTF-8 encode for Prowl notifier 2015-12-02 19:18:04 -08:00
Jonathan Wong
ede07595c3 Match newline characters in notification text 2015-12-02 19:15:46 -08:00
JonnyWong16
08d65623dd Merge pull request #306 from JonnyWong16/miscellaneous-fixes
Delete users
2015-12-02 17:05:39 -08:00
Jonathan Wong
7540b5fb34 Fix recently added notification delay 2015-12-01 22:54:58 -08:00
Jonathan Wong
10c54c2d10 Only show IPv4 addresses 2015-12-01 21:57:02 -08:00
Jonathan Wong
b8d9c8cc47 Set blank metadata so recently added check continues when and item isn't found 2015-12-01 21:50:47 -08:00
Jonathan Wong
bac5018b27 Add channel support to Telegram notifier 2015-12-01 21:31:48 -08:00
Jonathan Wong
c65d9898c8 Add icon for Apple tvOS 2015-12-01 20:05:37 -08:00
Jonathan Wong
d7284c40bd Allow unicode in notification subject and body 2015-12-01 20:03:25 -08:00
Jonathan Wong
1c00f82097 Add ability to delete users 2015-11-27 21:13:17 -08:00
Jonathan Wong
c501923f2b Hide Pushalot notifier response logging 2015-11-27 18:13:20 -08:00
Jonathan Wong
81b22a8c36 Merge branch 'dev' 2015-11-27 06:38:31 -08:00
Jonathan Wong
beb66396fe v1.2.7 2015-11-27 06:33:03 -08:00
Jonathan Wong
aaf3de68cf Fix IP address in notifications 2015-11-27 06:29:41 -08:00
Jonathan Wong
c827c9e825 Fix IP logging again
* Really this time...
2015-11-27 12:33:34 +02:00
Tim van der Westhuizen
5100fdbc96 Merge branch 'dev' 2015-11-27 10:53:28 +02:00
Tim van der Westhuizen
fae3f38a88 v1.2.6 2015-11-27 10:52:29 +02:00
Tim van der Westhuizen
a8236222fb Catch null ratingKeys in plexWatch db importer.
Make sure we have a string when parsing the latinToAscii function.
2015-11-27 10:45:25 +02:00
Jonathan Wong
2be4d9b6c9 Merge branch 'dev' 2015-11-26 19:08:46 -08:00
Jonathan Wong
00934b04d2 Fix IP logging again
* Really this time...
2015-11-26 19:06:51 -08:00
Jonathan Wong
1e28b22c70 Merge branch 'dev' 2015-11-25 20:23:44 -08:00
Jonathan Wong
776061605f Fix IP logging again 2015-11-25 20:20:06 -08:00
Jonathan Wong
683e5663e1 Merge branch 'dev' 2015-11-25 19:16:50 -08:00
Jonathan Wong
090011c9a5 v1.2.5 2015-11-25 19:15:40 -08:00
Jonathan Wong
30b11bce98 Actually add video and audio decision to notifications 2015-11-25 19:13:08 -08:00
Jonathan Wong
2a91ec1560 Fix season and episode number notification option return at least one digit 2015-11-25 19:07:23 -08:00
Jonathan Wong
908ce1ff8d Fix IP address logging 2015-11-25 19:02:59 -08:00
Jonathan Wong
fac47ee68b Fix log spam if notifications turned off 2015-11-25 18:14:08 -08:00
Jonathan Wong
0f8c122ee3 Add video and audio decision to notification options 2015-11-25 18:12:20 -08:00
Jonathan Wong
893c91a15d Merge branch 'dev' 2015-11-24 18:51:35 -08:00
Jonathan Wong
6d152cf308 v1.2.4 2015-11-24 18:49:35 -08:00
Jonathan Wong
af2d0446da Hide fix metadata button for now 2015-11-24 18:21:59 -08:00
Jonathan Wong
244b03ba3e No restart required for monitoring remote access 2015-11-23 23:10:49 -08:00
Jonathan Wong
50e0629890 Fix unicode server name 2015-11-23 23:10:31 -08:00
Jonathan Wong
c296b38b78 Fix text glitch on welcome wizard 2015-11-23 23:10:16 -08:00
Jonathan Wong
f7cdfd3f30 Upgrade config file from previous versions 2015-11-23 23:10:01 -08:00
drzoidberg33
44cb2400d0 Remove donate link 2015-11-23 10:56:44 +02:00
Jonathan Wong
d297597fa6 Separate out movie and tv logging 2015-11-22 22:19:37 -08:00
Jonathan Wong
168e74aa23 Add logger for recently added 2015-11-22 22:15:28 -08:00
Jonathan Wong
35fa8a749b Fix PMS IP error message 2015-11-22 12:28:24 -08:00
Jonathan Wong
21a1870884 Fix callback in wrong spot 2015-11-22 12:24:57 -08:00
Jonathan Wong
1d86187f79 Fix "Please verify your server" setting bug 2015-11-22 12:11:22 -08:00
JonnyWong16
558f7873f5 Merge pull request #289 from JonnyWong16/miscellaneous-fixes
Use Plex API to check remote access down
2015-11-22 10:33:30 -08:00
Jonathan Wong
a20a52f5f1 Refresh port mapping before checking remote access 2015-11-22 10:22:15 -08:00
Jonathan Wong
17bb57d5f5 Apply media type toggles to recently added 2015-11-21 10:28:26 -08:00
Jonathan Wong
e6aef01508 Separate out TV notification toggle in settings 2015-11-21 10:27:51 -08:00
Jonathan Wong
013d957e47 Use Plex API to check remote access down 2015-11-21 10:13:26 -08:00
Jonathan Wong
99e064e040 Add wording for Pushover group key 2015-11-20 19:04:54 -08:00
JonnyWong16
9e5334ac81 Merge pull request #282 from JonnyWong16/miscellaneous-fixes
IPv6 support, fix recently added, get server name, notify server down
2015-11-20 06:28:02 -08:00
Jonathan Wong
fd43cf5dd4 Add setting to enable remote access monitoring 2015-11-19 19:40:50 -08:00
Jonathan Wong
9aea663754 Logger info for email notification sent 2015-11-17 23:39:02 -08:00
Jonathan Wong
223e2b2b32 Add notification for Plex external port down 2015-11-17 23:38:46 -08:00
Jonathan Wong
ca91adbd53 Add check for Plex external port down 2015-11-17 23:35:41 -08:00
Jonathan Wong
4fffbf8a0c Add server uptime 2015-11-17 19:31:13 -08:00
Jonathan Wong
c3ea35806e Move check for server down to check_active_sessions 2015-11-17 06:57:02 -08:00
Jonathan Wong
1c4df69e61 Toggle bell icon for on_down 2015-11-16 23:52:03 -08:00
Jonathan Wong
707c30b0af Fix missing pmsconnect 2015-11-16 23:28:43 -08:00
Jonathan Wong
4d87666a42 Schedule job to check if server down 2015-11-16 23:19:59 -08:00
Jonathan Wong
b28ac1543a Add notification for server down 2015-11-16 23:19:37 -08:00
Jonathan Wong
1983597cf1 Fix get_server_friendly_name 2015-11-16 22:51:21 -08:00
Jonathan Wong
69a3b5134f Switch recently added to only use activity pinger
* Fixed activity pinger logic for grouping notifications
2015-11-16 21:19:04 -08:00
Jonathan Wong
53044c75dd Add setting for recently added notification delay 2015-11-16 21:17:47 -08:00
Jonathan Wong
12056ac2ba Get server name as a scheduled task 2015-11-16 18:31:22 -08:00
Jonathan Wong
7c8fb58600 Change input to textarea for notification body 2015-11-15 23:51:31 -08:00
Jonathan Wong
da2e7635bd Fix notification tags removal for show and artist 2015-11-15 23:50:58 -08:00
Jonathan Wong
f8b75eadc6 Improved get server friendly name
* Add server friendly name to page title
2015-11-15 21:35:53 -08:00
Jonathan Wong
e9bc767c3b Fix username for database queries
* Get the updated username from the users table instead of the one
stored in the session_history table.
2015-11-15 20:59:04 -08:00
Jonathan Wong
1644bbd4b7 Check for IPv4 mapped IPv6 address in PMS logs 2015-11-15 10:26:03 -08:00
Jonathan Wong
18b328a387 Fix private IP address for IPv6 2015-11-15 10:17:28 -08:00
Tim van der Westhuizen
98411f0715 Move IP geolocation service. Temporary until a suitable replacement can be found. 2015-11-13 17:51:25 +02:00
JonnyWong16
fcb3474312 Merge pull request #278 from JonnyWong16/miscellaneous-fixes
Add IP address to current activity
2015-11-12 06:13:08 -08:00
Jonathan Wong
6362b51902 Add ip_address to notification options
* Also track_name
2015-11-11 14:48:59 -08:00
Jonathan Wong
d79d5d5b39 Better IP address handling for current activity 2015-11-11 09:16:28 -08:00
Jonathan Wong
80df8f6191 Add IP address to sessions for PMS 0.9.14 2015-11-11 08:59:55 -08:00
Jonathan Wong
fd9cf7017b Add IP address to current activity 2015-11-10 19:28:14 -08:00
JonnyWong16
2eed2d54ca Merge pull request #274 from JonnyWong16/miscellaneous-fixes
Add more metadata options to notifications
2015-11-09 19:16:08 -08:00
Jonathan Wong
0c33e7492a Open notifier description links in new window 2015-11-09 17:55:37 -08:00
Jonathan Wong
dd137e5c36 Minor notifier text changes 2015-11-08 15:44:59 -08:00
Jonathan Wong
dea9663adf Add more metadata options to notifications 2015-11-08 15:38:30 -08:00
Tim van der Westhuizen
767dd20bdc Make sure we set the PMS client identifier when auto verifying servers at first run. 2015-11-06 17:18:22 +02:00
Tim
c350943041 Add some debug logging for websocket timeline events. 2015-11-05 22:49:05 +02:00
drzoidberg33
c60340d88b Merge pull request #269 from JonnyWong16/miscellaneous-fixes
Miscellaneous fixes
2015-11-02 23:17:41 +02:00
drzoidberg33
276c0e5c7d Merge pull request #267 from onedr0p/feature/telegram_notifications
Feature/telegram notifications
2015-11-02 23:11:55 +02:00
Jonathan Wong
054f116017 Fix title encode for Pushover notifications 2015-11-01 20:38:22 -08:00
Jonathan Wong
e9017a8342 Escape double quotes in search query 2015-11-01 20:37:28 -08:00
Devin Buhl
9cff20ca16 set text format on encode 2015-11-01 11:03:36 -05:00
Devin Buhl
6cbfacaeae added event / suject to notifcation text 2015-10-31 01:59:13 -04:00
devin
8ebfa20db0 Fixed notifications, and added strings to describe bot token and chat id 2015-10-28 20:36:09 -04:00
devin
5beb4876fb removed telegram lib, updated wording, and used a simple request for sending the notif 2015-10-28 20:28:41 -04:00
devin
c723d33d38 telegram updates to notifiers.py 2015-10-28 07:31:07 -04:00
devin
f75fca12c8 telegram updates to config.py 2015-10-28 07:30:41 -04:00
devin
8671707e4d added telegram lib from repo leandrotoledo/python-telegram-bot 2015-10-28 07:29:57 -04:00
drzoidberg33
a9316ebea1 Merge pull request #265 from drzoidberg33/ip-lookup-provider
Change IP lookup provider
2015-10-28 13:06:35 +02:00
Tim van der Westhuizen
ef86740466 Change order of location details in IP lookup. 2015-10-27 15:25:40 +02:00
Tim van der Westhuizen
57cb755668 Change IP lookup provider to Telize.com which supply an SSL endpoint. 2015-10-27 13:53:47 +02:00
JonnyWong16
aa75cf2b73 Merge pull request #259 from JonnyWong16/recently-added
Recently added
2015-10-26 18:04:11 -07:00
Jonathan Wong
3f8224fec5 List notifications agents alphabetically 2015-10-26 18:00:51 -07:00
Jonathan Wong
0b67abb2a2 Fix typos 2015-10-26 17:52:51 -07:00
Jonathan Wong
872ef2771e Fix double recently added episode notifications 2015-10-25 22:00:51 -07:00
Jonathan Wong
3b457304e9 Fix build_notify_text again
* Separate session and timeline
2015-10-25 21:12:19 -07:00
Jonathan Wong
974c672a87 Format code 2015-10-25 17:38:41 -07:00
Jonathan Wong
b9f47df930 Update activity_pinger for recently added 2015-10-25 17:21:49 -07:00
Jonathan Wong
4c388f60d6 Add config to group recently added by grandparent 2015-10-25 13:30:25 -07:00
Jonathan Wong
d6b31dc542 Set on_created notification in database 2015-10-25 12:20:00 -07:00
Jonathan Wong
539cd60e92 Fix notification_handler 2015-10-24 21:23:19 -07:00
Jonathan Wong
056bcd1488 Update notification handler for timeline events 2015-10-24 21:23:03 -07:00
Jonathan Wong
1c58a47073 Update websocket and handler for timeline events 2015-10-24 21:22:46 -07:00
Jonathan Wong
32cf1ada8b Add config settings for on_created
* Note: on_created is recently added
2015-10-24 21:22:29 -07:00
Jonathan Wong
968132099e Change metadata 'type' to 'media_type' 2015-10-24 21:18:09 -07:00
Tim van der Westhuizen
7b3874dcaa Add Plex Media Player icon. 2015-10-23 11:37:13 +02:00
Tim van der Westhuizen
0302b2412a Fix platform overrides for graphs. 2015-10-22 18:12:50 +02:00
Tim van der Westhuizen
4ac5329019 Add Konvergo to platform name overrides. 2015-10-22 17:45:23 +02:00
Tim van der Westhuizen
37bc68573c Implement IFTTT notification option. PR #241. 2015-10-22 16:04:31 +02:00
Tim
dc8996c4d2 Escape single quotes for usernames on user stats page. 2015-10-21 22:06:02 +02:00
drzoidberg33
1ef9d72534 Merge pull request #256 from JonnyWong16/miscellaneous-fixes
Miscellaneous fixes
2015-10-20 13:15:49 +02:00
Jonathan Wong
db7225fbad Clean up code 2015-10-20 00:48:26 -07:00
Jonathan Wong
2c354ad783 Fix bug in search query 2015-10-18 17:47:21 -07:00
Jonathan Wong
b96abc8853 Add detailed logger messages for database queries 2015-10-18 13:53:23 -07:00
Jonathan Wong
c4dc81e8fb Change order args are created for datatable query
* Make sure search filter args are created after custom_where
2015-10-18 13:29:29 -07:00
Jonathan Wong
be753983fe Fix breadcrumbs for update metadata page 2015-10-18 13:14:22 -07:00
Jonathan Wong
1bcb34d7eb Add button to fix metadata on info pages 2015-10-18 13:02:16 -07:00
Jonathan Wong
2243cd1de9 Add filtering of media_type from history table 2015-10-18 11:50:01 -07:00
Jonathan Wong
1ff58a85dc Fix bug in "Last Watched" statistics
*Fix if two users watched the same item, it would only show the most
recent user.
2015-10-18 10:27:18 -07:00
Tim
428706d9a7 Merge branch 'dev' 2015-10-18 00:27:41 +02:00
Tim
5967636ef9 v1.2.3 2015-10-18 00:26:44 +02:00
drzoidberg33
ddc9563de9 Merge pull request #252 from JonnyWong16/miscellaneous-fixes
Miscellaneous fixes
2015-10-16 16:40:23 +02:00
Jonathan Wong
3d1a1b5e45 Fix watch stats not showing on homepage 2015-10-15 18:02:28 -07:00
Jonathan Wong
60b330573e Increase width of user watch time stats 2015-10-13 20:59:24 -07:00
Jonathan Wong
76c1558473 Add {remaining_duration} to notifications
* Also clean up/reorder notification parameters
2015-10-13 20:42:26 -07:00
840 changed files with 20388 additions and 5027 deletions

1
.gitignore vendored
View File

@@ -21,6 +21,7 @@ cache/*
*.crt *.crt
*.key *.key
*.csr *.csr
*.pem
# OS generated files # # OS generated files #
###################### ######################

View File

@@ -1,5 +1,198 @@
# Changelog # Changelog
## v1.3.4 (2016-01-29)
* Fix: Activity checker not starting with library update (history not logging).
* Fix: Libraries duplicated in database.
* Fix: Buffer notifications even when disabled when using websockets.
* Fix: Libraries and Users lists not refreshing.
* Fix: Server verification in settings.
* Fix: Empty libraries not added to database.
* Add: Unique identifier to notification options.
* Remove: Media type toggles for recently added notifications.
* Remove: Built in Twitter key and secret.
* Remove: Unnecessary quoting of script arguments.
* Change: Facebook notification instructions.
## v1.3.3 (2016-01-26)
* Fix: Plays by Month graph not loading.
* Change: Disable caching for datatables.
* Change: Improved updating library data in the database again.
## v1.3.2 (2016-01-24)
* Fix: 'datestamp' and 'timestamp' for server notifications.
* Change: New method for updating library data in database.
## v1.3.1 (2016-01-23)
* Fix: Notifiers authorization popups for reverse proxies.
* Fix: Empty brackets in titles on tables.
* Fix: Star rating overlapping text.
* Fix: Unable to startup when library refresh fails.
* Fix: Unable to parse 'datestamp' and 'timestamp' format.
* Change: Rename "Last Watched" to "Last Played".
* Change: More descriptive libraries updating message.
## v1.3.0 (2016-01-23)
* Add: Brand new Libraries section.
* Add: Lots of new library statistics.
* Add: Media info table for libraries.
* Add: Web app for Android and iOS. (Thanks @zobe123)
* Add: Slack notification agent. (Thanks @richipargo)
* Add: Facebook notification agent.
* Add: Custom script notification agent. (Thanks @Hellowlol)
* Add: Custom "From Name" to email notification agent.
* Add: Ability to test notifications / send custom one-off notifications.
* Add: 'datestamp' and 'timestamp' notification options.
* Add: More concurrent stream statistics.
* Add: Media info flags on the info pages.
* Add: Ability to fix broken metadata if the item has been moved in Plex.
* Add: Ability to rearrange the homepage statistics cards.
* Add: CentOS startup script (Thanks @PHoSawyer)
* Fix: Server name blank after first run wizard.
* Fix: Incorrect duration for grouped home stats.
* Fix: Allow SSL when verifying server in settings.
* Fix: Metadata for grouped recently added notifications.
* Fix: Unable to access settings with missing changelog file.
* Fix: Month name localization on play totals graphs.
* Fix: Get new PMS identifier when changing servers.
* Fix: Websocket log spam when there is no active session.
* Fix: Logs and cache folder not created in the data directory.
* Fix: Title links on sync table.
* Fix: Other various minor bugs and graphical glitches.
* Change: Prettier thumbnail popovers on tables.
* Change: Star ratings to use css/font-awesome.
* Change: More detailed logging info to warnings and errors.
* Change: Better PlexPy process restart handling (Thanks @jackwilsdon)
* Change: Massive behind the scenes code cleanup.
* Remove: Built in Pushover API token (User's own API token is now required).
## v1.2.16 (2015-12-22)
* Fix Most Concurrent stream stat for emtpy databases
* Change logs to 50 lines by default
## v1.2.15 (2015-12-20)
* Fix navbar covering current activity on smaller screens.
* Fix metadata for grouped recently added notifications.
* Fix Growl notification agent not working.
* Change graph days selection.
* Change watch statistics to match table history grouping.
* Add automatic discovery of Pushbullet devices.
* Add Most Concurrent Streams watch statistic.
* Add precentage to current activity progress bars.
* Add a bunch of stream details to notification options.
* Add notification for Plex Remote Access/Plex Media Server back up.
* Add CC/BCC and multiple recipients to email notification agent.
* Add total watch time to history table footer.
## v1.2.14 (2015-12-07)
* Fix regression with PlexWatch db importer and buffer warnings.
## v1.2.13 (2015-12-06)
* Fix match newlines between tags in notification text.
* Fix current activity not showing on PMS 0.9.12.
## v1.2.12 (2015-12-06)
* Fix for "too many open files" error.
## v1.2.11 (2015-12-06)
* Fix more regressions (sorry).
## v1.2.10 (2015-12-06)
* Fix broken count graphs regression.
## v1.2.9 (2015-12-06)
* Fix and improve text sanitization.
## v1.2.8 (2015-12-06)
* Fix sanitize player names
* Fix recently added notification delay
* Fix recently added metadata queries
* Fix multiple lines in notification body text
* Fix UTF-8 encoding in Prowl notifications subject line
* Change to only log IPv4 addresses
* Add global toggle for recently added notifcations
* Add feature to delete users
* Add channel support for Telegram notification agent
* Add icon for Apple tvOS
* Add icon for Microsoft Edge
## v1.2.7 (2015-11-27)
* Fix IP address option in notifications
## v1.2.6 (2015-11-27)
* Fixes for IP logging in PMS < 0.9.14.x.
* Fix issue in plexWatch importer when trying to import item with no ratingKey.
## v1.2.5 (2015-11-25)
* Add video_decision and audio_decision to notification options
* Fix IP address logging
* Fix log spam if notifications disabled
## v1.2.4 (2015-11-24)
* Add filtering by media type in the history table
* Add IFTTT notification agent
* Add Telegram notification agent
* Add notifications for recently added media
* Add notifications for server down and remote access down
* Add more metadata to notifications options
* Add IP address to notification options (for PMS 0.9.14 and above)
* Add server uptime to notification options
* Add IP address to current activity
* Add IPv6 address logging
* Add PMS server name to the page title
* Fix bug in "Last Watched" statistic
* Fix bug in search query
* Fix bug on user pages for usernames with single quotes
* Fix name for new Plex Media Center
* Fix Pushover notifications with unicode characters
* Fix bug with showing old usernames in datatables
* Fix bug with "Please verify your server" in settings
* Change IP lookup provider
* Change notifications custom body text to larger text box
* Change movie/tv logging and notifications into individual options
## v1.2.3 (2015-10-18)
* Added "remaining time" as notification substitution.
* Fix bug on home stats cards.
* Fix visual bug on user page.
## v1.2.2 (2015-10-12) ## v1.2.2 (2015-10-12)
* Add server discovery on first run. * Add server discovery on first run.

View File

@@ -6,11 +6,7 @@ A python based web application for monitoring, analytics and notifications for P
This project is based on code from Headphones (https://github.com/rembo10/headphones) and PlexWatchWeb (https://github.com/ecleese/plexWatchWeb). This project is based on code from Headphones (https://github.com/rembo10/headphones) and PlexWatchWeb (https://github.com/ecleese/plexWatchWeb).
* plexPy forum thread: https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program * PlexPy forum thread: https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program
If you'd like to buy me a beer, hit the donate button below. All donations go to the project maintainer (primarily for the procurement of liquid refreshment).
[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G9HZK9BDJLKT6)
###Support ###Support

View File

@@ -7,7 +7,7 @@ from plexpy import version
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>PlexPy - ${title}</title> <title>PlexPy - ${title} | ${server_name}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
@@ -18,12 +18,117 @@ from plexpy import version
${next.headIncludes()} ${next.headIncludes()}
<link rel="icon" type="image/x-icon" href="interfaces/default/images/favicon.ico"/> <link rel="icon" type="image/x-icon" href="interfaces/default/images/favicon.ico"/>
<!-- touch icons -->
<link rel="shortcut icon" href="interfaces/default/images/favicon.png"> <link rel="shortcut icon" href="interfaces/default/images/favicon.png">
<link rel="apple-touch-icon" href="interfaces/default/images/icon_iphone.png">
<link rel="apple-touch-icon" sizes="72x72" href="interfaces/default/images/icon_ipad.png"> <!-- Allow web app to be run in full-screen mode. -->
<link rel="apple-touch-icon" sizes="114x114" href="interfaces/default/images/icon_iphone@2x.png"> <meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" sizes="144x144" href="interfaces/default/images/icon_ipad@2x.png"> <!-- Configure the status bar. -->
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- Set the viewport. -->
<meta name="viewport" content="initial-scale=1">
<!-- Disable automatic phone number detection. -->
<meta name="format-detection" content="telephone=no">
<!-- ICONS -->
<!-- IE10 icon -->
<meta name="application-name" content="PlexPy" />
<meta name="msapplication-config" content="interfaces/default/xml/IEconfig.xml"/>
<!-- Android >M39 icon -->
<link rel="manifest" href="interfaces/default/json/Android-manifest.json">
<!-- iPad retina icon -->
<link href="interfaces/default/images/res/ios/icon-76@2x.png" sizes="152x152" rel="apple-touch-icon-precomposed">
<!-- iPad retina icon (iOS < 7) -->
<link href="interfaces/default/images/res/ios/icon-72@2x.png" sizes="144x144" rel="apple-touch-icon-precomposed">
<!-- iPad non-retina icon -->
<link href="interfaces/default/images/res/ios/icon-76.png" sizes="76x76" rel="apple-touch-icon-precomposed">
<!-- iPad non-retina icon (iOS < 7) -->
<link href="interfaces/default/images/res/ios/icon-72.png" sizes="72x72" rel="apple-touch-icon-precomposed">
<!-- iPhone 6 Plus icon -->
<link href="interfaces/default/images/res/ios/icon-60@2x.png" sizes="120x120" rel="apple-touch-icon-precomposed">
<!-- iPhone retina icon (iOS < 7) -->
<link href="interfaces/default/images/res/ios/icon@2x.png" sizes="114x114" rel="apple-touch-icon-precomposed">
<!-- iPhone non-retina icon (iOS < 7) -->
<link href="interfaces/default/images/res/ios/icon.png" sizes="57x57" rel="apple-touch-icon-precomposed">
<!-- iPhone / iPod Touch -->
<link href="interfaces/default/images/res/ios/icon-60@3x.png" sizes="180x180" rel="apple-touch-icon-precomposed">
<link href="interfaces/default/images/res/ios/icon-60.png" sizes="60x60" rel="apple-touch-icon-precomposed">
<!-- Spotlight Icon -->
<link href="interfaces/default/images/res/ios/icon-40.png" sizes="40x40" rel="apple-touch-icon-precomposed">
<link href="interfaces/default/images/res/ios/icon-40@2x.png" sizes="80x80" rel="apple-touch-icon-precomposed">
<!-- iPhone Spotlight and Settings Icon -->
<link href="interfaces/default/images/res/ios/icon-small.png" sizes="29x29" rel="apple-touch-icon-precomposed">
<link href="interfaces/default/images/res/ios/icon-small@2x.png" sizes="58x58" rel="apple-touch-icon-precomposed">
<!-- iPad Spotlight and Settings Icon -->
<link href="interfaces/default/images/res/ios/icon-50.png" sizes="50x50" rel="apple-touch-icon-precomposed">
<link href="interfaces/default/images/res/ios/icon-50@2x.png" sizes="100x100" rel="apple-touch-icon-precomposed">
<!-- STARTUP IMAGES -->
<!-- iPad retina portrait startup image -->
<link href="interfaces/default/images/res/screen/ios/Default-Portrait@2x~ipad.png"
media="(device-width: 768px) and (device-height: 1024px)
and (-webkit-device-pixel-ratio: 2)
and (orientation: portrait)"
rel="apple-touch-startup-image">
<!-- iPad retina landscape startup image -->
<link href="interfaces/default/images/res/screen/ios/Default-Landscape@2x~ipad.png"
media="(device-width: 768px) and (device-height: 1024px)
and (-webkit-device-pixel-ratio: 2)
and (orientation: landscape)"
rel="apple-touch-startup-image">
<!-- iPad non-retina portrait startup image -->
<link href="interfaces/default/images/res/screen/ios/Default-Portrait~ipad.png"
media="(device-width: 768px) and (device-height: 1024px)
and (-webkit-device-pixel-ratio: 1)
and (orientation: portrait)"
rel="apple-touch-startup-image">
<!-- iPad non-retina landscape startup image -->
<link href="interfaces/default/images/res/screen/ios/Default-Landscape~ipad.png"
media="(device-width: 768px) and (device-height: 1024px)
and (-webkit-device-pixel-ratio: 1)
and (orientation: landscape)"
rel="apple-touch-startup-image">
<!-- iPhone 6 Plus portrait startup image -->
<link href="interfaces/default/images/res/screen/ios/Default-736h.png"
media="(device-width: 414px) and (device-height: 736px)
and (-webkit-device-pixel-ratio: 3)
and (orientation: portrait)"
rel="apple-touch-startup-image">
<!-- iPhone 6 Plus landscape startup image -->
<link href="interfaces/default/images/res/screen/ios/Default-Landscape-736h.png"
media="(device-width: 414px) and (device-height: 736px)
and (-webkit-device-pixel-ratio: 3)
and (orientation: landscape)"
rel="apple-touch-startup-image">
<!-- iPhone 6 startup image -->
<link href="interfaces/default/images/res/screen/ios/Default-667h.png"
media="(device-width: 375px) and (device-height: 667px)
and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image">
<!-- iPhone 5 startup image -->
<link href="interfaces/default/images/res/screen/ios/Default-568h@2x~iphone5.jpg"
media="(device-width: 320px) and (device-height: 568px)
and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image">
<!-- iPhone < 5 retina startup image -->
<link href="interfaces/default/images/res/screen/ios/Default@2x~iphone.png"
media="(device-width: 320px) and (device-height: 480px)
and (-webkit-device-pixel-ratio: 2)"
rel="apple-touch-startup-image">
<!-- iPhone < 5 non-retina startup image -->
<link href="interfaces/default/images/res/screen/ios/Default~iphone.png"
media="(device-width: 320px) and (device-height: 480px)
and (-webkit-device-pixel-ratio: 1)"
rel="apple-touch-startup-image">
</head> </head>
<body class="content"> <body class="content">
@@ -57,11 +162,11 @@ from plexpy import version
</div> </div>
<div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1"> <div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li> <li class="hidden-sm hidden-xs">
<form action="search" method="post" class="form" id="search_form"> <form action="search" method="post" class="form" id="search_form">
<div class="input-group"> <div class="input-group">
<span class="input-textbox"> <span class="input-textbox">
<input type="text" class="form-control" name="search_query" id="search_query" aria-label="Search" placeholder="Search..."/> <input type="text" class="form-control" name="query" id="query" aria-label="Search" placeholder="Search..."/>
</span> </span>
<span class="input-group-btn"> <span class="input-group-btn">
<button class="btn btn-dark btn-inactive" type="submit" id="search_button"><i class="fa fa-search"></i></button> <button class="btn btn-dark btn-inactive" type="submit" id="search_button"><i class="fa fa-search"></i></button>
@@ -69,37 +174,42 @@ from plexpy import version
</div> </div>
</form> </form>
</li> </li>
% if title=="Home": % if title == "Home":
<li class="active"><a href="home"><i class="fa fa-lg fa-home"></i></a></li> <li class="active"><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
% else: % else:
<li><a href="home"><i class="fa fa-lg fa-home"></i></a></li> <li><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
% endif % endif
% if title=="Users" or title=="User": % if title == "Libraries" or title == "Library" or title == "Info":
<li class="active"><a href="libraries">Libraries</a></li>
% else:
<li><a href="libraries">Libraries</a></li>
% endif
% if title == "Users" or title == "User":
<li class="active"><a href="users">Users</a></li> <li class="active"><a href="users">Users</a></li>
% else: % else:
<li><a href="users">Users</a></li> <li><a href="users">Users</a></li>
% endif % endif
% if title=="History": % if title == "History":
<li class="active"><a href="history">History</a></li> <li class="active"><a href="history">History</a></li>
% else: % else:
<li><a href="history">History</a></li> <li><a href="history">History</a></li>
% endif % endif
% if title=="Graphs": % if title == "Graphs":
<li class="active"><a href="graphs">Graphs</a></li> <li class="active"><a href="graphs">Graphs</a></li>
% else: % else:
<li><a href="graphs">Graphs</a></li> <li><a href="graphs">Graphs</a></li>
% endif % endif
% if title=="Synced Items": % if title == "Synced Items":
<li class="active"><a href="sync">Synced Items</a></li> <li class="active"><a href="sync">Synced Items</a></li>
% else: % else:
<li><a href="sync">Synced Items</a></li> <li><a href="sync">Synced Items</a></li>
% endif % endif
% if title=="Log": % if title == "Log":
<li class="active"><a href="logs">Logs</a></li> <li class="active"><a href="logs">Logs</a></li>
% else: % else:
<li><a href="logs">Logs</a></li> <li><a href="logs">Logs</a></li>
% endif % endif
% if title=="Settings": % if title == "Settings":
<li class="active"><a href="settings">Settings</a></li> <li class="active"><a href="settings">Settings</a></li>
% else: % else:
<li><a href="settings">Settings</a></li> <li><a href="settings">Settings</a></li>
@@ -131,26 +241,41 @@ ${next.headerIncludes()}
</script> </script>
<script> <script>
$('#search_form').submit(function (e) { $('#search_form').submit(function (e) {
if ($('#search_query').hasClass('active') && $('#search_query').val().trim() != '') { if ($('#query').hasClass('active') && $('#query').val().trim() != '') {
$.ajax({ $.ajax({
type: 'post', type: 'post',
url: 'search', url: 'search',
data: { 'query': $('#search_query').val() } data: { query: $('#query').val() }
}) })
} else { } else {
e.preventDefault(); e.preventDefault();
$('#search_button').removeClass('btn-inactive'); $('#search_button').removeClass('btn-inactive');
$('#search_query').clearQueue().val('').animate({ right: '0', width: '250px' }).addClass('active').focus(); $('#query').clearQueue().val('').animate({ right: '0', width: '200px' }).addClass('active').focus();
} }
}) })
$('#search_query').on('blur', function (e) { $('#query').on('blur', function (e) {
if ($(this).val().trim() == '') { if ($(this).val().trim() == '') {
$(this).delay(200).animate({ right: '-250px', width: '0' }, function () { $(this).delay(200).animate({ right: '-200px', width: '0' }, function () {
$('#search_button').addClass('btn-inactive'); $('#search_button').addClass('btn-inactive');
}).removeClass('active'); }).removeClass('active');
} }
}); });
</script> </script>
<script>
// Work around for iOS web app links opening in Safari
$(document).ready(function () {
if (("standalone" in window.navigator) && window.navigator.standalone) {
// For iOS Apps
$('a').on('click', function (e) {
e.preventDefault();
var new_location = $(this).attr('href');
if (new_location != undefined && new_location.substr(0, 1) != '#' && $(this).attr('data-method') == undefined) {
window.location = new_location;
}
});
}
});
</script>
${next.javascriptIncludes()} ${next.javascriptIncludes()}
</body> </body>
</html> </html>

View File

@@ -235,8 +235,8 @@ fieldset[disabled] .btn-bright:active,
.btn-bright.disabled.active, .btn-bright.disabled.active,
.btn-bright[disabled].active, .btn-bright[disabled].active,
fieldset[disabled] .btn-bright.active { fieldset[disabled] .btn-bright.active {
background-color: #5cb85c; background-color: #c9302c;
border-color: #4cae4c; border-color: #ac2925;
} }
.btn-bright .badge { .btn-bright .badge {
color: #fff; color: #fff;
@@ -341,6 +341,24 @@ input[type="color"],
border-radius: 3px; border-radius: 3px;
transition: background-color .3s; transition: background-color .3s;
} }
textarea.form-control {
height: initial;
margin: 5px 0 5px 0;
color: #fff;
border: 0px solid #444;
background: #555;
padding: 6px 12px;
background-color: #555;
border-radius: 3px;
transition: background-color .3s;
resize: none;
}
textarea.form-control:focus {
outline: 0;
color: #555;
background-color: #fff;
transition: background-color .3s;
}
.pagination > li > a, .pagination > li > a,
.pagination > li > span { .pagination > li > span {
position: relative; position: relative;
@@ -469,7 +487,8 @@ input[type="color"],
.users-poster-face { .users-poster-face {
overflow: hidden; overflow: hidden;
float: left; float: left;
background-size: contain; background-size: cover;
background-position: center;
height: 40px; height: 40px;
width: 40px; width: 40px;
-webkit-border-radius: 50%; -webkit-border-radius: 50%;
@@ -479,6 +498,16 @@ input[type="color"],
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1); -moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1); box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
} }
.libraries-poster-face {
overflow: hidden;
float: left;
background-size: contain;
height: 40px;
width: 40px;
/*-webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);*/
}
a .poster-face:hover, a .poster-face:hover,
a .cover-face:hover, a .cover-face:hover,
a .users-poster-face:hover { a .users-poster-face:hover {
@@ -688,6 +717,14 @@ a:hover .dashboard-activity-poster {
white-space: nowrap; white-space: nowrap;
width: 150px; width: 150px;
} }
.dashboard-activity-poster-info-ip-address {
position: absolute;
bottom: 5px;
left: 10px;
text-align: left;
font-size: 12px;
color: #eee;
}
.dashboard-activity-poster-info-time { .dashboard-activity-poster-info-time {
position: absolute; position: absolute;
bottom: 5px; bottom: 5px;
@@ -711,14 +748,20 @@ a:hover .dashboard-activity-poster {
transition: all 0s; transition: all 0s;
} }
.dashboard-activity-progress .bufferbar { .dashboard-activity-progress .bufferbar {
padding-top: 6px; padding-right: 3px;
font-size: x-small;
text-align: right;
color: rgba(255, 255, 255, 0);
background-color: #444; background-color: #444;
position: absolute; position: absolute;
height: 6px; height: 6px;
overflow: hidden; overflow: hidden;
} }
.dashboard-activity-progress .bar { .dashboard-activity-progress .bar {
padding-top: 6px; padding-right: 3px;
font-size: x-small;
text-align: right;
color: rgba(255, 255, 255, 0);
background-color: #faa732; background-color: #faa732;
background-image: -moz-linear-gradient(top, #fbb450, #f89406); background-image: -moz-linear-gradient(top, #fbb450, #f89406);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406)); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
@@ -731,6 +774,37 @@ a:hover .dashboard-activity-poster {
height: 6px; height: 6px;
overflow: hidden; overflow: hidden;
} }
.dashboard-instance.hover .dashboard-activity-progress-bar {
height: 14px;
transform-origin: top;
transition: all .2s ease;
border-radius: 0px 0px 3px 3px;
}
.dashboard-instance.hover .bar {
height: 14px;
transform-origin: top;
transition: all .2s ease;
border-radius: 0px 0px 3px 3px;
color: rgba(255, 255, 255, 1);
background-image: -webkit-linear-gradient(left,rgba(0,0,0,0.25),0%,rgba(0,0,0,0),50px);
background-image: -moz-linear-gradient(left,rgba(0,0,0,0.25) 0%,rgba(0,0,0,0) 50px);
background-image: linear-gradient(to left,rgba(0,0,0,0.25) 0%,rgba(0,0,0,0) 50px);
}
.dashboard-instance.hover .bufferbar {
height: 14px;
transform-origin: top;
transition: all .2s ease;
border-radius: 0px 0px 3px 3px;
color: rgba(255, 255, 255, 1);
background-image: -webkit-linear-gradient(left,rgba(0,0,0,0.25),0%,rgba(0,0,0,0),50px);
background-image: -moz-linear-gradient(left,rgba(0,0,0,0.25) 0%,rgba(0,0,0,0) 50px);
background-image: linear-gradient(to left,rgba(0,0,0,0.25) 0%,rgba(0,0,0,0) 50px);
}
.dashboard-instance.hover .dashboard-activity-metadata-wrapper {
margin-top: 11px;
transform-origin: top;
transition: all .2s ease;
}
.dashboard-activity-metadata-wrapper { .dashboard-activity-metadata-wrapper {
position: relative; position: relative;
width: 100%; width: 100%;
@@ -1131,6 +1205,7 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
width: 250px; width: 250px;
height: 1px; height: 1px;
margin: 0 40px 20px 25px; margin: 0 40px 20px 25px;
position: relative;
} }
.summary-content { .summary-content {
position: relative; position: relative;
@@ -1154,6 +1229,20 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
margin-left: 2px; margin-left: 2px;
margin-right: 10px; margin-right: 10px;
} }
.summary-content-media-info-wrapper {
width: 100%;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
}
.summary-content-media-flag {
width: auto;
height: auto;
max-width: 75pt;
max-height: 15px;
margin: 0 5px;
}
.summary-content-summary { .summary-content-summary {
overflow: hidden; overflow: hidden;
color: #fff; color: #fff;
@@ -1230,31 +1319,24 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
line-height: 18px; line-height: 18px;
color: #fff; color: #fff;
} }
.rateit { .star-rating {
display: -moz-inline-box;
display: inline-block; display: inline-block;
-webkit-user-select: none; font-size: 15px;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-touch-callout: none;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
float: right;
margin-top: 3px; margin-top: 3px;
height: 21px; height: 21px;
float: right;
} }
.rateit .rateit-range { .star-rating .star-icon {
background: url(../images/star-gray-32.png); width: auto;
background-size: contain; margin-left: 2px;
height: 16px; color: #F9AA03;
} }
.rateit .rateit-selected { .star-rating .star-icon-o {
background: url(../images/star-32.png); width: auto;
background-size: contain; margin-left: 2px;
height: 16px; color: #999;
} }
#children-list, #search-results-list { #children-list, #search-results-list {
position: relative; position: relative;
@@ -1474,7 +1556,8 @@ a:hover .item-children-poster {
float: left; float: left;
margin-top: 15px; margin-top: 15px;
margin-right: 15px; margin-right: 15px;
background-size: contain; background-size: cover;
background-position: center;
height: 80px; height: 80px;
width: 80px; width: 80px;
-webkit-border-radius: 50%; -webkit-border-radius: 50%;
@@ -1518,7 +1601,7 @@ a:hover .item-children-poster {
} }
.user-overview-stats-instance { .user-overview-stats-instance {
float: left; float: left;
width: 350px; width: 400px;
height: 80px; height: 80px;
margin-bottom: 25px; margin-bottom: 25px;
} }
@@ -1531,7 +1614,7 @@ a:hover .item-children-poster {
.user-overview-stats-instance li { .user-overview-stats-instance li {
float: left; float: left;
list-style: none; list-style: none;
width: 340px; width: 100%;
height: 90px; height: 90px;
} }
.user-overview-stats-instance-text { .user-overview-stats-instance-text {
@@ -1589,7 +1672,6 @@ a:hover .item-children-poster {
} }
.user-player-instance-box { .user-player-instance-box {
float: left; float: left;
width: 75px;
border-radius: 3px; border-radius: 3px;
-webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1); -webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1); -moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
@@ -1611,6 +1693,7 @@ a:hover .item-children-poster {
font-weight: normal; font-weight: normal;
width: 140px; width: 140px;
margin-left: 10px; margin-left: 10px;
margin-bottom: 10px;
} }
.user-player-instance-playcount h3 { .user-player-instance-playcount h3 {
font-size: 30px; font-size: 30px;
@@ -1630,6 +1713,35 @@ a:hover .item-children-poster {
top: 15px; top: 15px;
left: 0px; left: 0px;
} }
.library-info-poster-face {
float: left;
margin-top: 15px;
margin-right: 15px;
background-size: contain;
height: 80px;
width: 80px;
/*-webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);*/
}
.library-user-instance-box {
float: left;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
-webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
background-size: contain;
position: relative;
height: 80px;
width: 80px;
}
.library-user-instance-box:hover {
-webkit-box-shadow: inset 0 0 0 2px #e9a049;
-moz-box-shadow: inset 0 0 0 2px #e9a049;
box-shadow: inset 0 0 0 2px #e9a049;
}
.home-platforms { .home-platforms {
} }
.home-platforms ul { .home-platforms ul {
@@ -1660,6 +1772,7 @@ a:hover .item-children-poster {
padding-left: 80px; padding-left: 80px;
width: 100%; width: 100%;
height: 120px; height: 120px;
overflow: hidden;
} }
.home-platforms-instance-name { .home-platforms-instance-name {
color: #fff; color: #fff;
@@ -2061,7 +2174,8 @@ a .home-platforms-instance-list-oval:hover,
float: right; float: right;
} }
.colvis-button-bar, .colvis-button-bar,
.refresh-users-button { .refresh-users-button,
.refresh-libraries-button {
float: right; float: right;
} }
.nav-settings, .nav-settings,
@@ -2260,6 +2374,9 @@ a .home-platforms-instance-list-oval:hover,
width: 250px; width: 250px;
z-index: 9999; z-index: 9999;
} }
.dataTables_paginate li {
margin: 0;
}
.tooltip.top .tooltip-arrow { .tooltip.top .tooltip-arrow {
border-top-color: #fff; border-top-color: #fff;
} }
@@ -2277,42 +2394,52 @@ a .home-platforms-instance-list-oval:hover,
background: #fff; background: #fff;
border: 0; border: 0;
font-weight: bold; font-weight: bold;
border-radius: 2px;
} }
.history-title .popover.right { .history-thumbnail-popover {
margin-left: 12px; z-index: 2;
z-index: 5; padding: 0;
border: 0;
} }
.history-title .popover.right .popover-content { .history-thumbnail-popover.popover.right {
padding: 5px 8px; margin-left: 15px;
}
.history-thumbnail-popover .popover-content {
color: #000;
padding: 0;
} }
.history-thumbnail { .history-thumbnail {
background-position: center; background-position: center;
background-size: cover; background-size: cover;
width: 80px; width: 80px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
} }
.edit-user-toggles { .edit-user-toggles,
.edit-library-toggles {
padding-right: 10px; padding-right: 10px;
} }
.edit-user-toggles > input[type='checkbox'] { .edit-user-toggles > input[type='checkbox'],
.edit-library-toggles > input[type='checkbox'] {
display: none; display: none;
} }
.edit-user-toggles > input[type='checkbox'] + label { .edit-user-toggles > input[type='checkbox'] + label,
.edit-library-toggles > input[type='checkbox'] + label {
color: #444; color: #444;
cursor: pointer; cursor: pointer;
} }
.edit-user-toggles > input[type='checkbox']:checked + label { .edit-user-toggles > input[type='checkbox']:checked + label,
.edit-library-toggles > input[type='checkbox']:checked + label {
color: #fff; color: #fff;
cursor: pointer; cursor: pointer;
} }
.edit-user-name > input[type='text'] { .edit-user-name > input[type='text'] {
margin: 0; margin: 0;
} }
.popover {
z-index: 2;
}
.popover .popover-content {
color: #000;
}
.noTransition .noTransition
{ {
-moz-transition: none !important; -moz-transition: none !important;
@@ -2348,7 +2475,10 @@ a .home-platforms-instance-list-oval:hover,
top: 5px; top: 5px;
left: 12px; left: 12px;
} }
#users-to-delete > li { #users-to-delete > li,
#users-to-purge > li,
#libraries-to-delete > li,
#libraries-to-purge > li {
color: #e9a049; color: #e9a049;
} }
#updatebar { #updatebar {
@@ -2398,9 +2528,8 @@ a .home-platforms-instance-list-oval:hover,
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
overflow-x: hidden; overflow: auto;
overflow-y: auto; -webkit-overflow-scrolling: touch;
} }
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 15px; width: 15px;
@@ -2426,12 +2555,19 @@ a .home-platforms-instance-list-oval:hover,
width: 100%; width: 100%;
} }
} }
table.display,
table.display tr.shown + tr table[id^='history_child'],
table.display tr.shown + tr table[id^='media_info_child'],
table.display tr.shown + tr table[id^='media_info_child'] tr.shown + tr table[id^='media_info_child'] {
table-layout: auto;
}
table.display tr.shown + tr div.slider { table.display tr.shown + tr div.slider {
display: none; display: none;
} }
table.display tr.shown + tr > td { table.display tr.shown + tr > td {
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
padding-left: 0;
} }
table.display tr.shown + tr:hover { table.display tr.shown + tr:hover {
background-color: rgba(255,255,255,0); background-color: rgba(255,255,255,0);
@@ -2442,7 +2578,9 @@ table.display tr.shown + tr .pagination > .active > a,
table.display tr.shown + tr .pagination > .active > a:hover { table.display tr.shown + tr .pagination > .active > a:hover {
color: #fff; color: #fff;
} }
table.display tr.shown + tr table[id^='history_child'] td:hover a { table.display tr.shown + tr table[id^='history_child'] td:hover a,
table.display tr.shown + tr table[id^='media_info_child'] > tr > td:hover a,
table.display tr.shown + tr table[id^='media_info_child'] tr.shown + tr table[id^='media_info_child'] td:hover a {
color: #F9AA03; color: #F9AA03;
} }
table.display tr.shown + tr .pagination > .disabled > a { table.display tr.shown + tr .pagination > .disabled > a {
@@ -2453,36 +2591,44 @@ table.display tr.shown + tr .pagination > li > a:hover {
} }
table[id^='history_child'] { table[id^='history_child'] {
margin-top: 0; margin-top: 0;
margin-left: -4px;
opacity: .6; opacity: .6;
} }
table[id^='history_child'] thead th { table[id^='media_info_child'] {
margin-top: 0;
}
table[id^='history_child'] thead th,
table[id^='media_info_child'] thead th {
line-height: 0; line-height: 0;
height: 0 !important; height: 0 !important;
overflow: hidden; overflow: hidden;
} }
table[id^='media_info_child'] table[id^='media_info_child'] thead th {
line-height: 25px;
height: 35px !important;
overflow: hidden;
}
#search_form { #search_form {
width: 350px; width: 300px;
padding: 8px 15px; padding: 8px 15px;
} }
#search_form span.input-textbox { #search_form span.input-textbox {
overflow: hidden; overflow: hidden;
width: 250px; width: 200px;
height: 34px; height: 34px;
display: inline-flex; display: inline-flex;
float: right; float: right;
} }
#search_form #search_query { #search_form #query {
width: 0; width: 0;
height: 34px; height: 34px;
margin-top: 0; margin-top: 0;
float: right; float: right;
position: relative; position: relative;
right: -250px; right: -200px;
border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px;
} }
#search_form #search_query.active { #search_form #query.active {
width: 250px; width: 200px;
right: 0px; right: 0px;
} }
#search_form #search_button.btn-inactive { #search_form #search_button.btn-inactive {
@@ -2493,4 +2639,77 @@ table[id^='history_child'] thead th {
-ms-transition: background 0.3s; -ms-transition: background 0.3s;
-o-transition: background 0.3s; -o-transition: background 0.3s;
transition: background 0.3s; transition: background 0.3s;
}
#update_search_form div.input-group {
display: inline-table;
vertical-align: middle;
max-width: 250px;
}
#update_search_form #update_query {
margin: 5px 0 0 0.5em;
}
.notification-params {
margin-top: 10px;
background-color: #282828;
}
.notification-params th {
padding-left: 10px;
height: 30px;
}
.notification-params td {
height: 25px;
}
.notification-params td:first-child {
padding-left: 10px;
width: 200px;
}
.notification-params td:not(:first-child) {
padding-right: 10px;
}
.notification-params tr:nth-child(odd) td {
background-color: rgba(255,255,255,0.035);
}
.notification-params tr:nth-child(even) td {
background-color: rgba(255,255,255,0.010);
}
#days-selection label {
margin-bottom: 0;
}
#graph-days {
margin: 0;
width: 75px;
height: 34px;
}
.card-sortable {
height: 36px;
padding: 0 20px 0 0;
line-height: 34px;
cursor: move;
cursor: -webkit-grab;
cursor: grab;
border-bottom: 1px solid #232323;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
.card {
position: relative;
background-color: #282828;
border-top: 1px solid #2d2d2d;
}
.card label {
font-weight: normal;
}
.card-handle {
display: inline-block;
width: 30px;
margin-right: 10px;
color: #444;
text-align: center;
background-color: #2f2f2f;
}
.selectize-input input[type='text'] {
height: 20px;
} }

View File

@@ -32,6 +32,7 @@ user_thumb Returns the profile picture of the user owning the s
state Returns the state of the current session. Either 'playing', 'paused' or 'buffering'. state Returns the state of the current session. Either 'playing', 'paused' or 'buffering'.
title Returns the name of the episode, movie or music track. title Returns the name of the episode, movie or music track.
year Returns the year of the episode, movie, or clip. year Returns the year of the episode, movie, or clip.
ip_address Returns the ip address of the stream.
player Returns the name of the platform used to play the stream. player Returns the name of the platform used to play the stream.
platform Returns the type of platform used to play the stream. platform Returns the type of platform used to play the stream.
throttled Returns true if the transcode session is throttled. throttled Returns true if the transcode session is throttled.
@@ -68,12 +69,12 @@ DOCUMENTATION :: END
% for a in data['sessions']: % for a in data['sessions']:
<div class="dashboard-instance" id="instance-${a['session_key']}"> <div class="dashboard-instance" id="instance-${a['session_key']}">
% if a['media_type'] == 'movie' or a['media_type'] == 'episode' or a['media_type'] == 'track': % if a['media_type'] == 'movie' or a['media_type'] == 'episode' or a['media_type'] == 'track':
<a href="info?item_id=${a['rating_key']}"> <a href="info?rating_key=${a['rating_key']}">
% endif % endif
<div class="dashboard-activity-poster"> <div class="dashboard-activity-poster">
% if a['media_type'] == 'movie' and not a['indexes']: % if (a['media_type'] == 'movie' and not a['indexes']) or (a['indexes'] and not a['view_offset']):
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div> <div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
% elif a['media_type'] == 'episode' and not a['indexes']: % elif (a['media_type'] == 'episode' and not a['indexes']) or (a['indexes'] and not a['view_offset']):
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div> <div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280);"></div>
% elif a['indexes']: % elif a['indexes']:
<div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['bif_thumb']}&width=500&height=280); display: none;"></div> <div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['bif_thumb']}&width=500&height=280); display: none;"></div>
@@ -191,6 +192,13 @@ DOCUMENTATION :: END
</div> </div>
% if a['media_type'] != 'photo': % if a['media_type'] != 'photo':
<div class="dashboard-activity-poster-info-bar"> <div class="dashboard-activity-poster-info-bar">
<div class="dashboard-activity-poster-info-ip-address">
% if a['ip_address']:
<span>IP: ${a['ip_address']}</span>
% else:
<span>IP: N/A</span>
% endif
</div>
<div class="dashboard-activity-poster-info-time"> <div class="dashboard-activity-poster-info-time">
<span class="progress_time">${a['view_offset']}</span>/<span class="progress_time">${a['duration']}</span> <span class="progress_time">${a['view_offset']}</span>/<span class="progress_time">${a['duration']}</span>
</div> </div>
@@ -219,13 +227,13 @@ DOCUMENTATION :: END
<i class="fa fa-spinner"></i>&nbsp; <i class="fa fa-spinner"></i>&nbsp;
% endif % endif
% if a['media_type'] == 'episode': % if a['media_type'] == 'episode':
<a href="info?item_id=${a['rating_key']}" title="${a['grandparent_title']} - ${a['title']}">${a['grandparent_title']} - ${a['title']}</a> <a href="info?rating_key=${a['rating_key']}" title="${a['grandparent_title']} - ${a['title']}">${a['grandparent_title']} - ${a['title']}</a>
% elif a['media_type'] == 'movie': % elif a['media_type'] == 'movie':
<a href="info?item_id=${a['rating_key']}" title="${a['title']}">${a['title']}</a> <a href="info?rating_key=${a['rating_key']}" title="${a['title']}">${a['title']}</a>
% elif a['media_type'] == 'clip': % elif a['media_type'] == 'clip':
<span title="${a['title']}">${a['title']}</span> <span title="${a['title']}">${a['title']}</span>
% elif a['media_type'] == 'track': % elif a['media_type'] == 'track':
<a href="info?item_id=${a['rating_key']}" title="${a['grandparent_title']} - ${a['title']}">${a['grandparent_title']} - ${a['title']}</a> <a href="info?rating_key=${a['rating_key']}" title="${a['grandparent_title']} - ${a['title']}">${a['grandparent_title']} - ${a['title']}</a>
% elif a['media_type'] == 'photo': % elif a['media_type'] == 'photo':
<span title="${a['parent_title']}">${a['parent_title']}</span> <span title="${a['parent_title']}">${a['parent_title']}</span>
% else: % else:
@@ -238,7 +246,7 @@ DOCUMENTATION :: END
% elif a['media_type'] == 'movie': % elif a['media_type'] == 'movie':
<span title="${a['year']}">${a['year']}</span> <span title="${a['year']}">${a['year']}</span>
% elif a['media_type'] == 'track': % elif a['media_type'] == 'track':
<a href="info?item_id=${a['parent_rating_key']}" title="${a['parent_title']}">${a['parent_title']}</a> <a href="info?rating_key=${a['parent_rating_key']}" title="${a['parent_title']}">${a['parent_title']}</a>
% elif a['media_type'] == 'photo': % elif a['media_type'] == 'photo':
<span title="${a['title']}">${a['title']}</span> <span title="${a['title']}">${a['title']}</span>
% else: % else:
@@ -272,6 +280,13 @@ DOCUMENTATION :: END
e.preventDefault(); e.preventDefault();
$($(this).attr('data-target')).toggle(); $($(this).attr('data-target')).toggle();
}); });
// Add hover class to dashboard-instance
$('.dashboard-activity-poster').hover(function() {
$(this).closest('.dashboard-instance').addClass('hover');
}, function() {
$(this).closest('.dashboard-instance').removeClass('hover');
});
</script> </script>
% else: % else:
<div class="text-muted">Nothing is currently being watched.</div><br> <div class="text-muted">Nothing is currently being watched.</div><br>

View File

@@ -15,11 +15,13 @@ DOCUMENTATION :: END
</%doc> </%doc>
% if data != None: % if data != None:
% if data == '0': % if data == '0':
<h3>Activity</h3> <h3>Activity</h3>
% elif data == '1':
<h3>Activity <small>${data} stream</small></h3>
% else:
<h3>Activity <small>${data} streams</small></h3>
% endif
% else: % else:
<h3>Activity <small>${data} stream(s)</small></h3> <h3>Activity</h3>
% endif % endif
% else:
<h3>Activity</h3>
% endif

View File

@@ -0,0 +1,179 @@
<%doc>
USAGE DOCUMENTATION :: PLEASE LEAVE THIS AT THE TOP OF THIS FILE
For Mako templating syntax documentation please visit: http://docs.makotemplates.org/en/latest/
Filename: edit_library.html
Version: 0.1
Variable names: data [list]
data :: Usable parameters
== Global keys ==
section_id Returns the library id of the library.
section_name Returns the name of the library.
section_type Returns the type of the library.
library_thumb Returns the thumbnail for the library.
custom_thumb Returns the custom thumbnail for the library.
library_art Returns the artwork for the library.
count Returns the item count for the library.
parent_count Returns the parent item count for the library.
child_count Returns the child item count for the library.
do_notify Returns bool value for whether to send notifications for the library.
keep_history Returns bool value for whether to keep history for the library.
DOCUMENTATION :: END
</%doc>
<%!
from plexpy import helpers
%>
% if data != None:
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title">Edit library <strong>${data['section_name']}</strong></h4>
</div>
<div class="modal-body" id="modal-text">
<fieldset>
<div class="form-group">
<label for="profile_url">Library Picture URL</label>
<div class="row">
<div class="col-md-8">
<input type="text" class="form-control" id="custom_thumb_url" name="custom_thumb_url" value="${data['library_thumb']}">
</div>
</div>
<p class="help-block">Change the library's picture in PlexPy. To reset to default, leave this field empty and save.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="do_notify" name="do_notify" value="1" ${helpers.checked(data['do_notify'])}> Enable notifications
</label>
<p class="help-block">Uncheck this if you do not want to receive notifications for this library's activity.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="keep_history" name="keep_history" value="1" ${helpers.checked(data['keep_history'])}> Keep history
</label>
<p class="help-block">Uncheck this if you do not want to keep any history on this library's activity.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="do_notify_created" name="do_notify_created" value="1" ${helpers.checked(data['do_notify_created'])}> Enable recently added notifications
</label>
<p class="help-block">Uncheck this if you do not want to receive recently added notifications for this library.</p>
</div>
% if data['section_id']:
<div class="form-group">
<button class="btn btn-danger" id="delete-all-history">Purge</button>
<p class="help-block">DANGER ZONE! Click the purge button to remove all history logged for this library. This is permanent!</p>
</div>
% endif
</fieldset>
</div>
<div class="modal-footer">
<div>
<span id="edit-library-status-message"></span>
<input type="button" id="save_library" class="btn btn-bright" value="Save">
</div>
</div>
</div>
</div>
<div id="confirm-modal-purge" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="confirm-modal-purge">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title" id="myModalLabel">Confirm Purge</h4>
</div>
<div class="modal-body" style="text-align: center;">
<p>Are you REALLY sure you want to purge all history for this library?</p>
<p>This is permanent and cannot be undone!</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-dark" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger btn-ok" data-dismiss="modal" id="confirm-purge">Purge</button>
</div>
</div>
</div>
</div>
<script>
// Save library options
$("#save_library").on('click', function () {
var custom_thumb = $("#custom_thumb_url").val();
var do_notify = 0;
var do_notify_created = 0;
var keep_history = 0;
if ($("#do_notify").is(":checked")) {
do_notify = 1;
}
if ($("#do_notify_created").is(":checked")) {
do_notify_created = 1;
}
if ($("#keep_history").is(":checked")) {
keep_history = 1;
}
$.ajax({
url: 'edit_library',
data: {
section_id: '${data["section_id"]}',
custom_thumb: custom_thumb,
do_notify: do_notify,
do_notify_created: do_notify_created,
keep_history: keep_history
},
cache: false,
async: true,
success: function (data) {
location.reload();
}
});
});
$("#delete-all-history").on('click', function() {
$('#confirm-modal-purge').modal();
$('#confirm-modal-purge').one('click', '#confirm-purge', function () {
$.ajax({
url: 'delete_all_library_history',
data: { section_id: '${data["section_id"]}' },
cache: false,
async: true,
success: function(data) {
location.reload();
}
});
});
});
$(document).ready(function() {
// Move #confirm-modal to parent container
if (!($('#edit-library-modal').next().is('#confirm-modal-purge'))) {
$('#confirm-modal-purge').appendTo($('#edit-library-modal').parent());
}
$('#edit-library-modal > #confirm-modal-purge').remove();
$('#edit-library-modal').css('z-index', '1050');
$('.modal-backdrop').not('.modal-backdrop-stack').css('z-index', '1049');
$('.modal-backdrop').not('.modal-backdrop-stack').addClass('modal-backdrop-stack');
$('#confirm-modal-purge').on('show.bs.modal', function () {
// Fix position to match parent modal
var currentPadding = parseInt($('body').css('padding-right'));
$(this).children('.modal-dialog').css('left', -currentPadding/2);
$('#edit-library-modal').css('overflow-y', 'hidden');
});
$('#confirm-modal-purge').on('shown.bs.modal', function () {
$(this).css('z-index', '1060');
$('.modal-backdrop').not('.modal-backdrop-stack').css('z-index', '1059');
$('.modal-backdrop').not('.modal-backdrop-stack').addClass('modal-backdrop-stack');
});
$('#confirm-modal-purge').on('hidden.bs.modal', function () {
$('body').addClass('modal-open');
$('#edit-library-modal').css('overflow-y', 'auto');
});
});
</script>
% endif

View File

@@ -10,21 +10,30 @@ Variable names: data [list]
data :: Usable parameters data :: Usable parameters
== Global keys == == Global keys ==
user Return the real Plex username user_id Returns the user id of the user.
user_id Return the Plex user_id username Returns the user's username.
friendly_name Returns the friendly edited Plex username friendly_name Returns the friendly name of the user.
do_notify Returns bool value for whether the user should trigger notifications email Returns the user's email address.
keep_history Returns bool value for whether the user's activity should be logged user_thumb Returns the thumbnail for the user.
is_home_user Returns bool value for whether the user is part of a Plex Home.
is_allow_sync Returns bool value for whether the user has sync rights.
is_restricted Returns bool value for whether the user account is restricted.
do_notify Returns bool value for whether to send notifications for the user.
keep_history Returns bool value for whether to keep history for the user.
DOCUMENTATION :: END DOCUMENTATION :: END
</%doc> </%doc>
% if data is not None: <%!
from plexpy import helpers
%>
% if data != None:
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title">Edit user <strong>${data['user']}</strong></h4> <h4 class="modal-title">Edit user <strong>${data['username']}</strong></h4>
</div> </div>
<div class="modal-body" id="modal-text"> <div class="modal-body" id="modal-text">
<fieldset> <fieldset>
@@ -41,22 +50,22 @@ DOCUMENTATION :: END
<label for="profile_url">Profile Picture URL</label> <label for="profile_url">Profile Picture URL</label>
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-8">
<input type="text" class="form-control" id="profile_url" name="profile_url" value="${data['thumb']}"> <input type="text" class="form-control" id="custom_avatar_url" name="custom_avatar_url" value="${data['user_thumb']}">
</div> </div>
</div> </div>
<p class="help-block">Change the users profile picture in PlexPy. To reset to default, leave this field empty and save then perform a user refresh.</p> <p class="help-block">Change the users profile picture in PlexPy. To reset to default, leave this field empty and save.</p>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" id="do_notify" name="do_notify" value="1" ${data['do_notify']}> Enable notifications <input type="checkbox" id="do_notify" name="do_notify" value="1" ${helpers.checked(data['do_notify'])}> Enable notifications
</label> </label>
<p class="help-block">Uncheck this if you do not want to receive notifications for this user's activity.</p> <p class="help-block">Uncheck this if you do not want to receive notifications for this user's activity.</p>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label> <label>
<input type="checkbox" id="keep_history" name="keep_history" value="1" ${data['keep_history']}> Keep history <input type="checkbox" id="keep_history" name="keep_history" value="1" ${helpers.checked(data['keep_history'])}> Keep history
</label> </label>
<p class="help-block">Uncheck this if you do not want this keep any history on this user's activity.</p> <p class="help-block">Uncheck this if you do not want to keep any history on this user's activity.</p>
</div> </div>
% if data['user_id']: % if data['user_id']:
<div class="form-group"> <div class="form-group">
@@ -69,7 +78,7 @@ DOCUMENTATION :: END
<div class="modal-footer"> <div class="modal-footer">
<div> <div>
<span id="edit-user-status-message"></span> <span id="edit-user-status-message"></span>
<input type="button" id="save_user_name" class="btn btn-bright" value="Save"> <input type="button" id="save_user" class="btn btn-bright" value="Save">
</div> </div>
</div> </div>
</div> </div>
@@ -93,10 +102,10 @@ DOCUMENTATION :: END
</div> </div>
</div> </div>
<script> <script>
// Set new friendly name // Set user options
$("#save_user_name").click(function() { $("#save_user").on('click', function () {
var friendly_name = $("#friendly_name").val(); var friendly_name = $("#friendly_name").val();
var thumb = $("#profile_url").val(); var custom_thumb = $("#custom_avatar_url").val();
var do_notify = 0; var do_notify = 0;
var keep_history = 0; var keep_history = 0;
if ($("#do_notify").is(":checked")) { if ($("#do_notify").is(":checked")) {
@@ -106,35 +115,21 @@ DOCUMENTATION :: END
keep_history = 1; keep_history = 1;
} }
% if data['user_id']: $.ajax({
$.ajax({ url: 'edit_user',
url: 'edit_user', data: {
data: {user_id: '${data['user_id']}', friendly_name: friendly_name, do_notify: do_notify, keep_history: keep_history, thumb: thumb}, user_id: '${data["user_id"]}',
cache: false, friendly_name: friendly_name,
async: true, custom_thumb: custom_thumb,
success: function(data) { do_notify: do_notify,
$("#edit-user-status-message").html(data); keep_history: keep_history
if ($.trim(friendly_name) !== '') { },
$(".set-username").html(friendly_name); cache: false,
} async: true,
$("#user-profile-thumb").attr('src', thumb); success: function(data) {
} location.reload();
}); }
% else: });
$.ajax({
url: 'edit_user',
data: {user: '${data['user']}', friendly_name: friendly_name, do_notify: do_notify, keep_history: keep_history, thumb: thumb},
cache: false,
async: true,
success: function(data) {
$("#edit-user-status-message").html(data);
if ($.trim(friendly_name) !== '') {
$(".set-username").html(friendly_name);
}
$("#user-profile-thumb").attr('src', thumb);
}
});
% endif
}); });
$("#delete-all-history").on('click', function() { $("#delete-all-history").on('click', function() {
@@ -142,7 +137,7 @@ DOCUMENTATION :: END
$('#confirm-modal').one('click', '#confirm-purge', function () { $('#confirm-modal').one('click', '#confirm-purge', function () {
$.ajax({ $.ajax({
url: 'delete_all_user_history', url: 'delete_all_user_history',
data: {user_id: '${data['user_id']}'}, data: { user_id: '${data["user_id"]}' },
cache: false, cache: false,
async: true, async: true,
success: function(data) { success: function(data) {
@@ -155,7 +150,8 @@ DOCUMENTATION :: END
$(document).ready(function() { $(document).ready(function() {
// Move #confirm-modal to parent container // Move #confirm-modal to parent container
if(!($('#edit-user-modal').next().is('#confirm-modal'))) { if(!($('#edit-user-modal').next().is('#confirm-modal'))) {
$('#confirm-modal').appendTo($('#edit-user-modal').parent()); } $('#confirm-modal').appendTo($('#edit-user-modal').parent());
}
$('#edit-user-modal > #confirm-modal').remove(); $('#edit-user-modal > #confirm-modal').remove();
$('#edit-user-modal').css('z-index', '1050'); $('#edit-user-modal').css('z-index', '1050');
@@ -179,5 +175,4 @@ DOCUMENTATION :: END
}); });
}); });
</script> </script>
% endif % endif

View File

@@ -13,110 +13,132 @@
</div> </div>
<div class="button-bar hidden-xs"> <div class="button-bar hidden-xs">
<div class="btn-group" data-toggle="buttons" id="yaxis-selection"> <div class="btn-group" data-toggle="buttons" id="yaxis-selection">
% if config['graph_type'] == 'duration':
<label class="btn btn-dark">
<input type="radio" name="yaxis-options" id="yaxis-count" value="plays" autocomplete="off"> Play Count
</label>
<label class="btn btn-dark active">
<input type="radio" name="yaxis-options" id="yaxis-duration" value="duration" autocomplete="off" checked> Play Duration
</label>
% else:
<label class="btn btn-dark active"> <label class="btn btn-dark active">
<input type="radio" name="yaxis-options" id="yaxis-count" value="plays" autocomplete="off" checked> Play Count <input type="radio" name="yaxis-options" id="yaxis-count" value="plays" autocomplete="off" checked> Play Count
</label> </label>
<label class="btn btn-dark"> <label class="btn btn-dark">
<input type="radio" name="yaxis-options" id="yaxis-duration" value="duration" autocomplete="off"> Play Duration <input type="radio" name="yaxis-options" id="yaxis-duration" value="duration" autocomplete="off"> Play Duration
</label> </label>
% endif
</div> </div>
<div class="btn-group" data-toggle="buttons" id="days-selection"> <div class="btn-group" id="days-selection">
<label class="btn btn-dark"> <label>
<input type="radio" name="date-options" id="graph-7" value="7" autocomplete="off"> 7 days <input type="number" name="graph-days" id="graph-days" value="${config['graph_days']}" min="1" /> days
</label>
<label class="btn btn-dark active">
<input type="radio" name="date-options" id="graph-30" value="30" autocomplete="off" checked> 30 days
</label>
<label class="btn btn-dark">
<input type="radio" name="date-options" id="graph-90" value="90" autocomplete="off"> 90 days
</label>
<label class="btn btn-dark">
<input type="radio" name="date-options" id="graph-365" value="365" autocomplete="off"> 1 year
</label> </label>
</div> </div>
</div> </div>
</div> </div>
<div class='table-card-back'> <div class='table-card-back'>
<ul class="nav nav-pills" role="tablist" id="graph-tabs"> <ul class="nav nav-pills" role="tablist" id="graph-tabs">
% if config['graph_tab'] == 'tabs-3':
<li role="presentation"><a href="#tabs-1" aria-controls="tabs-1" data-toggle="tab" role="tab">Plays by period</a></li>
<li role="presentation"><a href="#tabs-2" aria-controls="tabs-2" data-toggle="tab" role="tab">Stream Info</a></li>
<li role="presentation" class="active"><a href="#tabs-3" aria-controls="tabs-3" data-toggle="tab" role="tab">Play Totals</a></li>
% elif config['graph_tab'] == 'tabs-2':
<li role="presentation"><a href="#tabs-1" aria-controls="tabs-1" data-toggle="tab" role="tab">Plays by period</a></li>
<li role="presentation" class="active"><a href="#tabs-2" aria-controls="tabs-2" data-toggle="tab" role="tab">Stream Info</a></li>
<li role="presentation"><a href="#tabs-3" aria-controls="tabs-3" data-toggle="tab" role="tab">Play Totals</a></li>
% else:
<li role="presentation" class="active"><a href="#tabs-1" aria-controls="tabs-1" data-toggle="tab" role="tab">Plays by period</a></li> <li role="presentation" class="active"><a href="#tabs-1" aria-controls="tabs-1" data-toggle="tab" role="tab">Plays by period</a></li>
<li role="presentation"><a href="#tabs-2" aria-controls="tabs-2" data-toggle="tab" role="tab">Stream Info</a></li> <li role="presentation"><a href="#tabs-2" aria-controls="tabs-2" data-toggle="tab" role="tab">Stream Info</a></li>
<li role="presentation"><a href="#tabs-3" aria-controls="tabs-3" data-toggle="tab" role="tab">Play Totals</a></li> <li role="presentation"><a href="#tabs-3" aria-controls="tabs-3" data-toggle="tab" role="tab">Play Totals</a></li>
% endif
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
% if config['graph_tab'] != 'tabs-2' and config['graph_tab'] != 'tabs-3':
<div role="tabpanel" class="tab-pane active" id="tabs-1"> <div role="tabpanel" class="tab-pane active" id="tabs-1">
<div class="row"> % else:
<div class="col-md-12"> <div role="tabpanel" class="tab-pane" id="tabs-1">
<h4><i class="fa fa-history"></i> Daily <span class="yaxis-text">Play count</span> <small>Last <span class="days">30</span> days</small></h4> % endif
<p class="help-block"> <div class="row">
The total play count or duration of tv, movies, and music played per day. Click a graph point to open up a list of items played for that specific date. <div class="col-md-12">
</p> <h4><i class="fa fa-history"></i> Daily <span class="yaxis-text">Play count</span> <small>Last <span class="days">30</span> days</small></h4>
<div class="graphs-instance"> <p class="help-block">
<div class="watch-chart" id="chart_div_plays_by_day"> The total play count or duration of tv, movies, and music played per day. Click a graph point to open up a list of items played for that specific date.
<div class="graphs-load"><i class="fa fa-refresh fa-spin"></i> Loading chart...</div> </p>
<br> <div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_day">
<div class="graphs-load"><i class="fa fa-refresh fa-spin"></i> Loading chart...</div>
<br>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h4><i class="fa fa-calendar"></i> <span class="yaxis-text">Play count</span> by day of week <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of tv, movies, and music played per day of the week.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_dayofweek" style="float: left;">
<div class="graphs-load">
<i class="fa fa-refresh fa-spin"></i> Loading chart...
</div>
<br>
</div>
</div>
</div>
<div class="col-md-6">
<h4><i class="fa fa-clock-o"></i> <span class="yaxis-text">Play count</span> by hour of day <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of tv, movies, and music played per hour of the day.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_hourofday">
<div class="graphs-load">
<i class="fa fa-refresh fa-spin"></i> Loading chart...
</div>
<br>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h4><i class="fa fa-television"></i> <span class="yaxis-text">Play count</span> by top 10 platforms <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of tv, movies, and music played by top 10 most active platforms.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_platform" style="float: left;">
<div class="graphs-load">
<i class="fa fa-refresh fa-spin"></i> Loading chart...
</div>
<br>
</div>
</div>
</div>
<div class="col-md-6">
<h4><i class="fa fa-user"></i> <span class="yaxis-text">Play count</span> by top 10 users <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of tv, movies, and music played by top 10 most active users.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_user">
<div class="graphs-load">
<i class="fa fa-refresh fa-spin"></i> Loading chart...
</div>
<br>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col-md-6">
<h4><i class="fa fa-calendar"></i> <span class="yaxis-text">Play count</span> by day of week <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of tv, movies, and music played per day of the week.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_dayofweek" style="float: left;">
<div class="graphs-load"><i class="fa fa-refresh fa-spin"></i> Loading chart...
</div>
<br>
</div>
</div>
</div>
<div class="col-md-6">
<h4><i class="fa fa-clock-o"></i> <span class="yaxis-text">Play count</span> by hour of day <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of tv, movies, and music played per hour of the day.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_hourofday">
<div class="graphs-load"><i class="fa fa-refresh fa-spin"></i> Loading chart...
</div>
<br>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h4><i class="fa fa-television"></i> <span class="yaxis-text">Play count</span> by top 10 platforms <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of tv, movies, and music played by top 10 most active platforms.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_platform" style="float: left;">
<div class="graphs-load"><i class="fa fa-refresh fa-spin"></i> Loading chart...
</div>
<br>
</div>
</div>
</div>
<div class="col-md-6">
<h4><i class="fa fa-user"></i> <span class="yaxis-text">Play count</span> by top 10 users <small>Last <span class="days">30</span> days</small></h4>
<p class="help-block">
The combined total of tv, movies, and music played by top 10 most active users.
</p>
<div class="graphs-instance">
<div class="watch-chart" id="chart_div_plays_by_user">
<div class="graphs-load"><i class="fa fa-refresh fa-spin"></i> Loading chart...
</div>
<br>
</div>
</div>
</div>
</div>
</div>
% if config['graph_tab'] == 'tabs-2':
<div role="tabpanel" class="tab-pane active" id="tabs-2">
% else:
<div role="tabpanel" class="tab-pane" id="tabs-2"> <div role="tabpanel" class="tab-pane" id="tabs-2">
% endif
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<h4><i class="fa fa-video-camera"></i> Daily Stream type breakdown <small>Last <span class="days">30</span> days</small></h4> <h4><i class="fa fa-video-camera"></i> Daily Stream type breakdown <small>Last <span class="days">30</span> days</small></h4>
@@ -189,7 +211,11 @@
</div> </div>
</div> </div>
% if config['graph_tab'] == 'tabs-3':
<div role="tabpanel" class="tab-pane active" id="tabs-3">
% else:
<div role="tabpanel" class="tab-pane" id="tabs-3"> <div role="tabpanel" class="tab-pane" id="tabs-3">
% endif
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<h4><i class="fa fa-calendar"></i> Plays by Month <small>Last 12 months</small></h4> <h4><i class="fa fa-calendar"></i> Plays by Month <small>Last 12 months</small></h4>
@@ -263,36 +289,12 @@
<script> <script>
$(document).ready(function () { $(document).ready(function () {
// Save graph state to cookies // Initial values for graph from config
$('input[name=yaxis-options]').change(function() { var yaxis = "${config['graph_type']}";
setCookie('graphType', $(this).val(), 365, '/'); var current_range = ${config['graph_days']};
}); var current_tab = "${'#' + config['graph_tab']}";
$('input[name=date-options]').change(function() {
setCookie('graphDate', $(this).val(), 365, '/');
});
$('a[data-toggle=tab]').click(function() {
setCookie('graphTab', $(this).attr('href'), 365, '/');
});
// Initial values for graph if no saved state $('.days').html(current_range);
var yaxis = 'plays';
var current_range = 30;
var current_tab = '#tabs-1';
// Read saved graph state from cookies and set initial values
if(getCookie('graphType')) {
var yaxis = getCookie('graphType');
$('input[name=yaxis-options][value=' + yaxis + ']').prop('checked', true).trigger('click');
}
if(getCookie('graphDate')) {
var current_range = getCookie('graphDate');
$('input[name=date-options][value=' + current_range + ']').prop('checked', true).trigger('click');
$('.days').html(current_range);
}
if(getCookie('graphTab')) {
var current_tab = getCookie('graphTab');
$('a[data-toggle=tab][href=' + current_tab + ']').trigger('click');
}
var music_visible = (${config['music_logging_enable']} == 1 ? true : false); var music_visible = (${config['music_logging_enable']} == 1 ? true : false);
@@ -476,40 +478,61 @@
} }
// Set initial state // Set initial state
loadGraphsTab1(current_range, yaxis); if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); }
if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); }
if (current_tab == '#tabs-3') { loadGraphsTab3(yaxis); }
// Tab1 opened // Tab1 opened
$('#graph-tabs a[href="#tabs-1"]').on('shown.bs.tab', function (e) { $('#graph-tabs a[href="#tabs-1"]').on('shown.bs.tab', function (e) {
e.preventDefault(); e.preventDefault();
current_tab = $(this).attr('href'); current_tab = $(this).attr('href');
$('#days-selection').show();
loadGraphsTab1(current_range, yaxis); loadGraphsTab1(current_range, yaxis);
$.ajax({
url: 'set_graph_config',
data: { graph_tab: current_tab.replace('#','') },
async: true
});
}) })
// Tab2 opened // Tab2 opened
$('#graph-tabs a[href="#tabs-2"]').on('shown.bs.tab', function (e) { $('#graph-tabs a[href="#tabs-2"]').on('shown.bs.tab', function (e) {
e.preventDefault(); e.preventDefault();
current_tab = $(this).attr('href'); current_tab = $(this).attr('href');
$('#days-selection').show();
loadGraphsTab2(current_range, yaxis); loadGraphsTab2(current_range, yaxis);
$.ajax({
url: 'set_graph_config',
data: { graph_tab: current_tab.replace('#','') },
async: true
});
}) })
// Tab3 opened // Tab3 opened
$('#graph-tabs a[href="#tabs-3"]').on('shown.bs.tab', function (e) { $('#graph-tabs a[href="#tabs-3"]').on('shown.bs.tab', function (e) {
e.preventDefault(); e.preventDefault();
current_tab = $(this).attr('href'); current_tab = $(this).attr('href');
$('#days-selection').hide();
console.log('loading....');
loadGraphsTab3(yaxis); loadGraphsTab3(yaxis);
$.ajax({
url: 'set_graph_config',
data: { graph_tab: current_tab.replace('#','') },
async: true
});
}) })
// Date range changed // Date range changed
$('#days-selection').on('change', function() { $('#graph-days').on('change', function() {
current_range = $('input[name=date-options]:checked', '#days-selection').val(); current_range = $(this).val();
if (current_range < 1) {
$(this).val(7);
current_range = 7;
}
if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); } if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); }
if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); } if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); }
$('.days').html(current_range); $('.days').html(current_range);
$.ajax({
url: 'set_graph_config',
data: { graph_days: current_range},
async: true
});
}); });
// Y-axis changed // Y-axis changed
@@ -518,6 +541,11 @@
if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); } if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); }
if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); } if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); }
if (current_tab == '#tabs-3') { loadGraphsTab3(yaxis); } if (current_tab == '#tabs-3') { loadGraphsTab3(yaxis); }
$.ajax({
url: 'set_graph_config',
data: { graph_type: yaxis},
async: true
});
}); });
function setGraphFormat(type) { function setGraphFormat(type) {

View File

@@ -25,18 +25,18 @@
<table class="display" id="history_table" width="100%"> <table class="display" id="history_table" width="100%">
<thead> <thead>
<tr> <tr>
<th align='left' id="delete_row">Delete</th> <th align="left" id="delete_row">Delete</th>
<th align='left' id="time">Time</th> <th align="left" id="time">Time</th>
<th align='left' id="friendly_name">User</th> <th align="left" id="friendly_name">User</th>
<th align='left' id="ip_address">IP Address</th> <th align="left" id="ip_address">IP Address</th>
<th align='left' id="platform">Platform</th> <th align="left" id="platform">Platform</th>
<th align='left' id="device">Player</th> <th align="left" id="device">Player</th>
<th align='left' id="title">Title</th> <th align="left" id="title">Title</th>
<th align='left' id="started">Started</th> <th align="left" id="started">Started</th>
<th align='left' id="paused_counter">Paused</th> <th align="left" id="paused_counter">Paused</th>
<th align='left' id="stopped">Stopped</th> <th align="left" id="stopped">Stopped</th>
<th align='left' id="duration">Duration</th> <th align="left" id="duration">Duration</th>
<th align='left' id="percent_complete"></th> <th align="left" id="percent_complete"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -76,19 +76,50 @@
<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>
<script> <script>
$(document).ready(function() { $(document).ready(function () {
history_table_options.ajax = { function loadHistoryTable(media_type) {
"url": "get_history", history_table_options.ajax = {
type: "post", url: 'get_history',
data: function ( d ) { type: 'post',
return { 'json_data': JSON.stringify( d ) }; data: function (d) {
return {
json_data: JSON.stringify(d),
media_type: media_type
};
}
} }
} history_table = $('#history_table').DataTable(history_table_options);
history_table = $('#history_table').DataTable(history_table_options); var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 11] });
var colvis = new $.fn.dataTable.ColVis(history_table, { buttonText: '<i class="fa fa-columns"></i> Select columns', buttonClass: 'btn btn-dark', exclude: [0, 11] }); $(colvis.button()).appendTo('div.colvis-button-bar');
$(colvis.button()).appendTo('div.colvis-button-bar');
clearSearchButton('history_table', history_table); clearSearchButton('history_table', history_table);
$('#history_table_filter').prepend('<div class="btn-group" data-toggle="buttons" id="media_type-selection" style="padding-right: 15px;"> \
<label class="btn btn-dark active"> \
<input type="radio" name="media_type-filter" id="history-all" value="all" autocomplete="off"> All \
</label> \
<label class="btn btn-dark"> \
<input type="radio" name="media_type-filter" id="history-movies" value="movie" autocomplete="off"> Movies \
</label> \
<label class="btn btn-dark"> \
<input type="radio" name="media_type-filter" id="history-tv_shows" value="episode" autocomplete="off"> TV Shows \
</label> \
<label class="btn btn-dark"> \
<input type="radio" name="media_type-filter" id="history-music" value="track" autocomplete="off"> Music \
</label> \
</div>');
$('#media_type-selection').on('change', function () {
$('#media_type-selection > label').removeClass('active');
selected_filter = $('input[name=media_type-filter]:checked', '#media_type-selection');
$(selected_filter).closest('label').addClass('active');
media_type = $(selected_filter).val();
history_table.draw();
});
}
var media_type = 'all';
loadHistoryTable(media_type);
$('#row-edit-mode').on('click', function() { $('#row-edit-mode').on('click', function() {
$('#row-edit-mode-alert').fadeIn(200); $('#row-edit-mode-alert').fadeIn(200);

View File

@@ -13,11 +13,11 @@
<table class="display" id="history_table" width="100%"> <table class="display" id="history_table" width="100%">
<thead> <thead>
<tr> <tr>
<th align='left' id="started">Started</th> <th align="left" id="started">Started</th>
<th align='left' id="stopped">Stopped</th> <th align="left" id="stopped">Stopped</th>
<th align='left' id="friendly_name">User</th> <th align="left" id="friendly_name">User</th>
<th align='left' id="player">Player</th> <th align="left" id="player">Player</th>
<th align='left' id="title">Title</th> <th align="left" id="title">Title</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -34,13 +34,14 @@
$(document).ready(function() { $(document).ready(function() {
$('#date-header').html(moment('${data}','YYYY-MM-DD').format('ddd MMM Do YYYY')); $('#date-header').html(moment('${data}','YYYY-MM-DD').format('ddd MMM Do YYYY'));
history_table_modal_options.ajax = { history_table_modal_options.ajax = {
"url": "get_history", url: 'get_history',
type: "post", type: 'post',
data: function ( d ) { data: function ( d ) {
return { 'json_data': JSON.stringify( d ), return {
'grouping': false, json_data: JSON.stringify(d),
'start_date': '${data}' grouping: false,
}; start_date: '${data}'
};
} }
} }

View File

@@ -39,11 +39,16 @@ user_id Returns the user id for the associated stat.
friendly_name Returns the friendly name of the user for the associated stat. friendly_name Returns the friendly name of the user for the associated stat.
== Only if 'stat_id' is 'top_platform' or 'last_watched' == == Only if 'stat_id' is 'top_platform' or 'last_watched' ==
platform_type Returns the platform name for the associated stat. player Returns the player name for the associated stat.
== Only if 'stat_id' is 'last_watched' == == Only if 'stat_id' is 'last_watched' ==
last_watch Returns the time the media item was last watched. last_watch Returns the time the media item was last watched.
== Only if 'stat_id' is 'most_concurrent' ==
count Returns the count of the most concurrent streams.
started Returns the start time of the most concurrent streams.
stopped Returns the stop time of the most concurrent streams.
DOCUMENTATION :: END DOCUMENTATION :: END
</%doc> </%doc>
@@ -65,8 +70,8 @@ DOCUMENTATION :: END
%> %>
% if data: % if data:
% if data[0]['rows']:
<ul class="list-unstyled"> <ul class="list-unstyled">
% if any(top_stat['rows'] for top_stat in data):
% for top_stat in data: % for top_stat in data:
% if top_stat['stat_id'] == 'top_tv' and top_stat['rows']: % if top_stat['stat_id'] == 'top_tv' and top_stat['rows']:
<div class="home-platforms-instance"> <div class="home-platforms-instance">
@@ -77,7 +82,7 @@ DOCUMENTATION :: END
</div> </div>
<div class="home-platforms-instance-playcount"> <div class="home-platforms-instance-playcount">
<h4> <h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h4> </h4>
@@ -89,7 +94,7 @@ DOCUMENTATION :: END
% endif % endif
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['grandparent_thumb']: % if top_stat['rows'][0]['grandparent_thumb']:
<div class="home-platforms-instance-poster"> <div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -100,18 +105,18 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</a> </a>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
<h5> <h5>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
${top_stat['rows'][loop.index]['title']} ${top_stat['rows'][loop.index]['title']}
</a> </a>
</h5> </h5>
@@ -125,7 +130,7 @@ DOCUMENTATION :: END
% endif % endif
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['grandparent_thumb']: % if top_stat['rows'][loop.index]['grandparent_thumb']:
<div class="home-platforms-instance-list-poster"> <div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -157,7 +162,7 @@ DOCUMENTATION :: END
</div> </div>
<div class="home-platforms-instance-playcount"> <div class="home-platforms-instance-playcount">
<h4> <h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h4> </h4>
@@ -165,7 +170,7 @@ DOCUMENTATION :: END
<p> users</p> <p> users</p>
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['grandparent_thumb'] != '': % if top_stat['rows'][0]['grandparent_thumb'] != '':
<div class="home-platforms-instance-poster"> <div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -176,18 +181,18 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</a> </a>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
<h5> <h5>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
${top_stat['rows'][loop.index]['title']} ${top_stat['rows'][loop.index]['title']}
</a> </a>
</h5> </h5>
@@ -197,7 +202,7 @@ DOCUMENTATION :: END
<p> users</p> <p> users</p>
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['grandparent_thumb']: % if top_stat['rows'][loop.index]['grandparent_thumb']:
<div class="home-platforms-instance-list-poster"> <div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -229,7 +234,7 @@ DOCUMENTATION :: END
</div> </div>
<div class="home-platforms-instance-playcount"> <div class="home-platforms-instance-playcount">
<h4> <h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h4> </h4>
@@ -241,7 +246,7 @@ DOCUMENTATION :: END
% endif % endif
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['thumb']: % if top_stat['rows'][0]['thumb']:
<div class="home-platforms-instance-poster"> <div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -252,18 +257,18 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</a> </a>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
<h5> <h5>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
${top_stat['rows'][loop.index]['title']} ${top_stat['rows'][loop.index]['title']}
</a> </a>
</h5> </h5>
@@ -277,7 +282,7 @@ DOCUMENTATION :: END
% endif % endif
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['thumb']: % if top_stat['rows'][loop.index]['thumb']:
<div class="home-platforms-instance-list-poster"> <div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -309,7 +314,7 @@ DOCUMENTATION :: END
</div> </div>
<div class="home-platforms-instance-playcount"> <div class="home-platforms-instance-playcount">
<h4> <h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h4> </h4>
@@ -317,7 +322,7 @@ DOCUMENTATION :: END
<p> users</p> <p> users</p>
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['thumb']: % if top_stat['rows'][0]['thumb']:
<div class="home-platforms-instance-poster"> <div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -328,18 +333,18 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</a> </a>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
<h5> <h5>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
${top_stat['rows'][loop.index]['title']} ${top_stat['rows'][loop.index]['title']}
</a> </a>
</h5> </h5>
@@ -349,7 +354,7 @@ DOCUMENTATION :: END
<p> users</p> <p> users</p>
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['thumb']: % if top_stat['rows'][loop.index]['thumb']:
<div class="home-platforms-instance-list-poster"> <div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -381,7 +386,7 @@ DOCUMENTATION :: END
</div> </div>
<div class="home-platforms-instance-playcount"> <div class="home-platforms-instance-playcount">
<h4> <h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h4> </h4>
@@ -393,7 +398,7 @@ DOCUMENTATION :: END
% endif % endif
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['grandparent_thumb']: % if top_stat['rows'][0]['grandparent_thumb']:
<div class="home-platforms-instance-poster"> <div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div> <div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div>
@@ -404,18 +409,18 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</a> </a>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
<h5> <h5>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
${top_stat['rows'][loop.index]['title']} ${top_stat['rows'][loop.index]['title']}
</a> </a>
</h5> </h5>
@@ -429,7 +434,7 @@ DOCUMENTATION :: END
% endif % endif
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['grandparent_thumb']: % if top_stat['rows'][loop.index]['grandparent_thumb']:
<div class="home-platforms-instance-list-poster"> <div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div> <div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div>
@@ -461,7 +466,7 @@ DOCUMENTATION :: END
</div> </div>
<div class="home-platforms-instance-playcount"> <div class="home-platforms-instance-playcount">
<h4> <h4>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h4> </h4>
@@ -469,7 +474,7 @@ DOCUMENTATION :: END
<p> users</p> <p> users</p>
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}"> <a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['grandparent_thumb'] != '': % if top_stat['rows'][0]['grandparent_thumb'] != '':
<div class="home-platforms-instance-poster"> <div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div> <div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div>
@@ -480,18 +485,18 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</a> </a>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
<h5> <h5>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
${top_stat['rows'][loop.index]['title']} ${top_stat['rows'][loop.index]['title']}
</a> </a>
</h5> </h5>
@@ -501,7 +506,7 @@ DOCUMENTATION :: END
<p> users</p> <p> users</p>
</div> </div>
</div> </div>
<a href="info?item_id=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['grandparent_thumb']: % if top_stat['rows'][loop.index]['grandparent_thumb']:
<div class="home-platforms-instance-list-poster"> <div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div> <div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div>
@@ -564,13 +569,13 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</a> </a>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
@@ -642,13 +647,13 @@ DOCUMENTATION :: END
$("#platform-stat").html("<div class='home-platforms-instance-box' style='background-image: url(" + getPlatformImagePath('${top_stat['rows'][0]['platform_type']}') + ");'>"); $("#platform-stat").html("<div class='home-platforms-instance-box' style='background-image: url(" + getPlatformImagePath('${top_stat['rows'][0]['platform_type']}') + ");'>");
</script> </script>
</div> </div>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
@@ -687,11 +692,11 @@ DOCUMENTATION :: END
<li> <li>
<div class="home-platforms-instance-info"> <div class="home-platforms-instance-info">
<div class="home-platforms-instance-name"> <div class="home-platforms-instance-name">
<h4>Last Watched</h4> <h4>Last Played</h4>
</div> </div>
<div class="home-platforms-instance-last-user"> <div class="home-platforms-instance-last-user">
<h4> <h4>
<a href="info?source=history&item_id=${top_stat['rows'][0]['row_id']}" title="${top_stat['rows'][0]['title']}"> <a href="info?source=history&rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
${top_stat['rows'][0]['title']} ${top_stat['rows'][0]['title']}
</a> </a>
</h4> </h4>
@@ -709,11 +714,11 @@ DOCUMENTATION :: END
<script> <script>
$('#last-watch-stat').text(moment(${top_stat['rows'][0]['last_watch']},"X").format(date_format)); $('#last-watch-stat').text(moment(${top_stat['rows'][0]['last_watch']},"X").format(date_format));
</script> </script>
</span> - ${top_stat['rows'][0]['platform_type']} </span> - ${top_stat['rows'][0]['player']}
</p> </p>
</div> </div>
</div> </div>
<a href="info?source=history&item_id=${top_stat['rows'][0]['row_id']}" title="${top_stat['rows'][0]['title']}"> <a href="info?source=history&rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['thumb']: % if top_stat['rows'][0]['thumb']:
<div class="home-platforms-instance-poster"> <div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['thumb']}&width=300&height=450&fallback=poster);"></div>
@@ -724,18 +729,18 @@ DOCUMENTATION :: END
</div> </div>
% endif % endif
</a> </a>
%if len(top_stat['rows']) > 1: % if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div> <div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled"> <ul class="list-unstyled">
<div class="slider"> <div class="slider">
<div class="home-platforms-instance-list"> <div class="home-platforms-instance-list">
% for row in top_stat['rows']: % for row in top_stat['rows']:
%if loop.index > 0: % if loop.index > 0:
<li> <li>
<div class="home-platforms-instance-list-info"> <div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name"> <div class="home-platforms-instance-list-name">
<h5> <h5>
<a href="info?source=history&item_id=${top_stat['rows'][loop.index]['row_id']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?source=history&rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
${top_stat['rows'][loop.index]['title']} ${top_stat['rows'][loop.index]['title']}
</a> </a>
</h5> </h5>
@@ -755,17 +760,17 @@ DOCUMENTATION :: END
<script> <script>
$('#home-platforms-instance-list-last-watch-${loop.index + 1}').text(moment(${top_stat['rows'][loop.index]['last_watch']},"X").format(date_format)); $('#home-platforms-instance-list-last-watch-${loop.index + 1}').text(moment(${top_stat['rows'][loop.index]['last_watch']},"X").format(date_format));
</script> </script>
</span> - ${top_stat['rows'][loop.index]['platform_type']} </span> - ${top_stat['rows'][loop.index]['player']}
</p> </p>
</div> </div>
</div> </div>
<a href="info?source=history&item_id=${top_stat['rows'][loop.index]['row_id']}" title="${top_stat['rows'][loop.index]['title']}"> <a href="info?source=history&rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['thumb']: % if top_stat['rows'][loop.index]['thumb']:
<div class="home-platforms-instance-list-poster"> <div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div> <div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['thumb']}&width=300&height=450&fallback=poster);"></div>
</div> </div>
% else: % else:
<div class="home-platforms-instance-poster2"> <div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div> <div class="home-platforms-list-poster-face" style="background-image: url(interfaces/default/images/poster.png);"></div>
</div> </div>
% endif % endif
@@ -782,8 +787,74 @@ DOCUMENTATION :: END
% endif % endif
</li> </li>
</div> </div>
% elif top_stat['stat_id'] == 'most_concurrent' and top_stat['rows']:
<div class="home-platforms-instance">
<li>
<div class="home-platforms-instance-info">
<div class="home-platforms-instance-name">
<h4>Most Concurrent Streams</h4>
</div>
<div class="home-platforms-instance-playcount">
<h4>
<span id="most-concurrent-start">
<script>
$('#most-concurrent-start').text(moment(${top_stat['rows'][0]['started']},"X").format(date_format + ' ' + time_format));
</script>
</span>
</h4>
<h3>${top_stat['rows'][0]['count']}</h3>
<p> streams</p>
</div>
</div>
<div class="home-platforms-instance-poster">
<div class="home-platforms-instance-box" style="background-image: url(interfaces/default/images/home-stat_most-concurrent.png);"></div>
</div>
% if len(top_stat['rows']) > 1:
<div class="home-platforms-instance-list-chevron"><i class="fa fa-chevron-down"></i></div>
<ul class="list-unstyled">
<div class="slider">
<div class="home-platforms-instance-list">
% for row in top_stat['rows']:
% if loop.index > 0:
<li>
<div class="home-platforms-instance-list-info">
<div class="home-platforms-instance-list-name">
<h5>
${top_stat['rows'][loop.index]['title']}
</h5>
</div>
<div class="home-platforms-instance-list-playcount">
<h3>${top_stat['rows'][loop.index]['count']}</h3>
<p> streams
% if top_stat['rows'][loop.index]['started']:
- <span id="most-concurrent-start-${loop.index + 1}">
<script>
$('#most-concurrent-start-${loop.index + 1}').text(moment(${top_stat['rows'][loop.index]['started']},"X").format(date_format + ' ' + time_format));
</script>
</span>
% else:
- N/A
% endif
</p>
</div>
</div>
<div class="home-platforms-instance-poster">
<div class="home-platforms-instance-list-box" style="background-image: url(interfaces/default/images/home-stat_most-concurrent.png);"></div>
</div>
</li>
% endif
% endfor
</div>
</div>
</ul>
% endif
</li>
</div>
% endif % endif
% endfor % endfor
% else:
<div class="text-muted">No stats to show for the selected period.</div><br>
% endif
</ul> </ul>
<script> <script>
var topZIndex = 2; var topZIndex = 2;
@@ -799,9 +870,5 @@ DOCUMENTATION :: END
}); });
</script> </script>
% else: % else:
<div class="text-muted">No stats for selected period.</div><br> <div class="text-muted">No stats to show for the selected period.</div><br>
% endif
% else:
<div class="text-muted">Unable to retrieve data from database. Please check your <a href="settings">settings</a>.
</div><br>
% endif % endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Some files were not shown because too many files have changed in this diff Show More