Compare commits
420 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5cc6e0b172 | ||
![]() |
bff22900cb | ||
![]() |
5e79c9fd62 | ||
![]() |
92f55c254c | ||
![]() |
39034e38f6 | ||
![]() |
3c7b9558fe | ||
![]() |
c8f7f40b46 | ||
![]() |
2a764cf190 | ||
![]() |
ba6ef4d629 | ||
![]() |
67d3505733 | ||
![]() |
252145cf58 | ||
![]() |
dbc62542ef | ||
![]() |
005829ab72 | ||
![]() |
448c8b0e8a | ||
![]() |
ff0e724ee5 | ||
![]() |
568e4a5ee8 | ||
![]() |
fbf4a524c1 | ||
![]() |
29db2e958f | ||
![]() |
cc7bcbf9d5 | ||
![]() |
98d4484e6c | ||
![]() |
0b126278f9 | ||
![]() |
cc919415bb | ||
![]() |
a3f398390c | ||
![]() |
5ae89368f1 | ||
![]() |
c8f1cb0a0a | ||
![]() |
f783b08b78 | ||
![]() |
85e0c6d3cd | ||
![]() |
2259a96058 | ||
![]() |
afed5841e7 | ||
![]() |
52361cd505 | ||
![]() |
b743cca7bc | ||
![]() |
1d01d0bff1 | ||
![]() |
c45a488962 | ||
![]() |
6731c44541 | ||
![]() |
b04ed83963 | ||
![]() |
c35b79e642 | ||
![]() |
ed8c7c1052 | ||
![]() |
498a074222 | ||
![]() |
3fe6db4d42 | ||
![]() |
6e5cd82dfb | ||
![]() |
cbf3488de9 | ||
![]() |
c72314fb71 | ||
![]() |
c4af6feb92 | ||
![]() |
08537c1d69 | ||
![]() |
425da82f5f | ||
![]() |
2cfbf7c39a | ||
![]() |
d4eed9f8fd | ||
![]() |
fe10170826 | ||
![]() |
8dc3b0b250 | ||
![]() |
75da1220af | ||
![]() |
37a2c3c631 | ||
![]() |
5c5722714d | ||
![]() |
2ba529f9e3 | ||
![]() |
fd760ff015 | ||
![]() |
daab1d917b | ||
![]() |
4c3a63a7e1 | ||
![]() |
7cc58b84da | ||
![]() |
2bac4ac1a7 | ||
![]() |
c5b2b86786 | ||
![]() |
5652a2b6c2 | ||
![]() |
bd19f543a2 | ||
![]() |
cc1e888227 | ||
![]() |
d73e379dcf | ||
![]() |
0569abd00d | ||
![]() |
7f5d9bec87 | ||
![]() |
b39e7bbb6d | ||
![]() |
70270a8e3b | ||
![]() |
efdc050a28 | ||
![]() |
e8a65df7f0 | ||
![]() |
59628a72fb | ||
![]() |
a4d6c6c0d8 | ||
![]() |
bea82c6640 | ||
![]() |
1ba3bdfbda | ||
![]() |
98b4000bc0 | ||
![]() |
14f6824931 | ||
![]() |
795d7d0a93 | ||
![]() |
673fa2b556 | ||
![]() |
0e2504fc78 | ||
![]() |
2afca9f2b4 | ||
![]() |
464d2a541d | ||
![]() |
fa8c5e0982 | ||
![]() |
5e15884d8f | ||
![]() |
b5e9ff3b4e | ||
![]() |
fed7d4cc34 | ||
![]() |
d7ab066ff8 | ||
![]() |
4100917016 | ||
![]() |
5d2c1ffb88 | ||
![]() |
ddb0f198a9 | ||
![]() |
13438e3e25 | ||
![]() |
05a410b327 | ||
![]() |
23fa64d289 | ||
![]() |
1920c9b7e3 | ||
![]() |
eedd0d9c07 | ||
![]() |
9ef389d335 | ||
![]() |
6542997520 | ||
![]() |
a58b2e2038 | ||
![]() |
6860e348dc | ||
![]() |
5e094e7597 | ||
![]() |
2f2cb8386b | ||
![]() |
965fd170bd | ||
![]() |
2610d29b60 | ||
![]() |
064131c842 | ||
![]() |
00b6bf8394 | ||
![]() |
2a885d709d | ||
![]() |
5bed46c0aa | ||
![]() |
8b27c7e01a | ||
![]() |
177902a286 | ||
![]() |
48b0f7dc27 | ||
![]() |
d5f4a1a48a | ||
![]() |
de9f60aa7f | ||
![]() |
c93b65b299 | ||
![]() |
3c6a6cdc5b | ||
![]() |
b669f3d715 | ||
![]() |
f663fac220 | ||
![]() |
bc42e79bb5 | ||
![]() |
ca29333cd0 | ||
![]() |
f9f478e100 | ||
![]() |
97c414d1ad | ||
![]() |
7afbd98d17 | ||
![]() |
1f5c60588e | ||
![]() |
284ab45a17 | ||
![]() |
eab6365af9 | ||
![]() |
de86516a0a | ||
![]() |
3e50e11933 | ||
![]() |
e2ac8be451 | ||
![]() |
0e53252a27 | ||
![]() |
b1ecff3d10 | ||
![]() |
0fee4fee2a | ||
![]() |
66282d817c | ||
![]() |
932c93e573 | ||
![]() |
71d30af582 | ||
![]() |
1c8428c3ea | ||
![]() |
e38e98d9e7 | ||
![]() |
85b3f081bf | ||
![]() |
3926d97fc6 | ||
![]() |
13ac8f2ea4 | ||
![]() |
d94f991ab5 | ||
![]() |
d476d2e96a | ||
![]() |
635bf364ac | ||
![]() |
e1c7a37f62 | ||
![]() |
9d780701f5 | ||
![]() |
0bd40405b5 | ||
![]() |
25c2f95e48 | ||
![]() |
5d738e58eb | ||
![]() |
70325f9247 | ||
![]() |
38c9c5a6ea | ||
![]() |
c90dd147bb | ||
![]() |
322f106e75 | ||
![]() |
91a5529438 | ||
![]() |
8f7dd2df6a | ||
![]() |
2fcd55eb60 | ||
![]() |
9359567a8a | ||
![]() |
42bfacfb19 | ||
![]() |
71131c699e | ||
![]() |
6ebfc516a6 | ||
![]() |
5c952b1d86 | ||
![]() |
1d9a4e0b99 | ||
![]() |
ebae628d8d | ||
![]() |
9865460fe5 | ||
![]() |
39884b71fe | ||
![]() |
82b7128c04 | ||
![]() |
16756ddb8c | ||
![]() |
877002961f | ||
![]() |
7e9e68ecd8 | ||
![]() |
6419190272 | ||
![]() |
ac42563c5e | ||
![]() |
98c1063e07 | ||
![]() |
a4dfc57cbe | ||
![]() |
db543b8912 | ||
![]() |
49fb4540a2 | ||
![]() |
e2120393a2 | ||
![]() |
0b301fff3f | ||
![]() |
eeb351e991 | ||
![]() |
1095e29b4d | ||
![]() |
be058eaff7 | ||
![]() |
f409dda2ef | ||
![]() |
f409cdda8f | ||
![]() |
9cd6396c35 | ||
![]() |
ee754ea533 | ||
![]() |
36de20dd75 | ||
![]() |
a957e8eb4f | ||
![]() |
14a90d84ec | ||
![]() |
fae9bc618a | ||
![]() |
3248e6500e | ||
![]() |
c17bf79d79 | ||
![]() |
1ff1270bfa | ||
![]() |
b1a2cf33d8 | ||
![]() |
b2292e98c1 | ||
![]() |
4d156a8911 | ||
![]() |
7193b6518b | ||
![]() |
cff6b44109 | ||
![]() |
fb7ad9438e | ||
![]() |
afc265a188 | ||
![]() |
01fe7bf612 | ||
![]() |
1cb75bd053 | ||
![]() |
0eaea4d011 | ||
![]() |
67377a2561 | ||
![]() |
a8aae9f1f5 | ||
![]() |
a9ce92decb | ||
![]() |
c19162295a | ||
![]() |
58796c45ed | ||
![]() |
d94b348780 | ||
![]() |
95f92bd292 | ||
![]() |
bc52ac3559 | ||
![]() |
8bbc6a6611 | ||
![]() |
8902b93a26 | ||
![]() |
ae36af807d | ||
![]() |
fd256625c6 | ||
![]() |
bee543a25a | ||
![]() |
55eb79cb52 | ||
![]() |
35965a8320 | ||
![]() |
8a902ae3e6 | ||
![]() |
52bed5bf98 | ||
![]() |
9e83f6d779 | ||
![]() |
0873beaed2 | ||
![]() |
0ba5012464 | ||
![]() |
73ff28465d | ||
![]() |
7484d65dbb | ||
![]() |
4a120e7a54 | ||
![]() |
8d63d85821 | ||
![]() |
5cec84a802 | ||
![]() |
48da41690d | ||
![]() |
1c82241f30 | ||
![]() |
b1ea3bcd4e | ||
![]() |
05e485b55e | ||
![]() |
c62e0e4e99 | ||
![]() |
3c6a1a02b8 | ||
![]() |
cc287607cd | ||
![]() |
b24e9a2185 | ||
![]() |
01791eac52 | ||
![]() |
651b57a93f | ||
![]() |
cc857364f4 | ||
![]() |
f29d7c8cfb | ||
![]() |
af4d0248d9 | ||
![]() |
2990664b2b | ||
![]() |
ed52038bc4 | ||
![]() |
ee125dfadc | ||
![]() |
196048cf38 | ||
![]() |
5faf357045 | ||
![]() |
4e0f06f24d | ||
![]() |
717530fff7 | ||
![]() |
4a5e38dc1e | ||
![]() |
419f8dadad | ||
![]() |
2dcae5e219 | ||
![]() |
36a99f70a3 | ||
![]() |
c98cf858c1 | ||
![]() |
dd463f00a7 | ||
![]() |
2459340c6f | ||
![]() |
76db5ffa3a | ||
![]() |
2db0e9c280 | ||
![]() |
db6dbe6c19 | ||
![]() |
ecedd4d231 | ||
![]() |
1809b95e2d | ||
![]() |
0d7e261bd1 | ||
![]() |
908941fb82 | ||
![]() |
fbacc4f789 | ||
![]() |
3c1290e8fd | ||
![]() |
35528ef602 | ||
![]() |
c0f0cb0d9e | ||
![]() |
4a65dc1d6e | ||
![]() |
b4a25e33bb | ||
![]() |
7f1a08dd04 | ||
![]() |
6152a1e913 | ||
![]() |
002cb93187 | ||
![]() |
381c3da31c | ||
![]() |
10e4d562ab | ||
![]() |
2a85e11ad9 | ||
![]() |
95b55760ad | ||
![]() |
636f898da8 | ||
![]() |
5fedac691d | ||
![]() |
979d68957e | ||
![]() |
a5b0837cf5 | ||
![]() |
8ba68dcfcf | ||
![]() |
8f367d140f | ||
![]() |
771885f27f | ||
![]() |
09aac22909 | ||
![]() |
1de3c0d559 | ||
![]() |
0988b68c8c | ||
![]() |
325ad4094e | ||
![]() |
16a09407e4 | ||
![]() |
84256f42c6 | ||
![]() |
7befbef6ec | ||
![]() |
754df5bea7 | ||
![]() |
78ee646558 | ||
![]() |
3d6f89d309 | ||
![]() |
e321479712 | ||
![]() |
9328b7e586 | ||
![]() |
50ace54cd0 | ||
![]() |
ad365c7dd0 | ||
![]() |
11427dbecd | ||
![]() |
b490831a50 | ||
![]() |
af76017a79 | ||
![]() |
43409b3089 | ||
![]() |
bfad769f93 | ||
![]() |
7e5dce1c14 | ||
![]() |
8ba4bebe01 | ||
![]() |
78a87db017 | ||
![]() |
b73a259f68 | ||
![]() |
65f27ee605 | ||
![]() |
6d5b5e15d5 | ||
![]() |
f31c4dcccd | ||
![]() |
1e616fa585 | ||
![]() |
0d2666f7d3 | ||
![]() |
0dd8970668 | ||
![]() |
89cda3dcff | ||
![]() |
1d48688518 | ||
![]() |
0b59f5e29c | ||
![]() |
5aebc8d191 | ||
![]() |
6e00c5da04 | ||
![]() |
50b06e041c | ||
![]() |
1c539f00dd | ||
![]() |
87ca432ec8 | ||
![]() |
ca33f4a2a5 | ||
![]() |
9409303f24 | ||
![]() |
94a3d35c90 | ||
![]() |
851de4934b | ||
![]() |
2942640eb9 | ||
![]() |
1cef037db5 | ||
![]() |
a00d43092d | ||
![]() |
45c2f50018 | ||
![]() |
ef8c6e82e6 | ||
![]() |
3eebb58da5 | ||
![]() |
447c50fd03 | ||
![]() |
0620ebebcf | ||
![]() |
cf081ee291 | ||
![]() |
3c29b8e9c5 | ||
![]() |
6143da5a6a | ||
![]() |
664f71575c | ||
![]() |
9ae111b8a1 | ||
![]() |
18682c7a2e | ||
![]() |
b21c50dfcf | ||
![]() |
49b6965e8e | ||
![]() |
c6cc2b8831 | ||
![]() |
f9f65eae53 | ||
![]() |
b51d442673 | ||
![]() |
5863b62ccf | ||
![]() |
66bb922012 | ||
![]() |
53876e8f0d | ||
![]() |
cb7ba7fdde | ||
![]() |
9cf6793b24 | ||
![]() |
6e62ffdd22 | ||
![]() |
c042d9e39a | ||
![]() |
1262de2ae2 | ||
![]() |
307230cec8 | ||
![]() |
4fa2711e78 | ||
![]() |
5c9c2f9ab8 | ||
![]() |
604155b41b | ||
![]() |
6e4198e7be | ||
![]() |
14d4940d05 | ||
![]() |
a6b0cdef97 | ||
![]() |
6265943607 | ||
![]() |
de39f7691c | ||
![]() |
921a219beb | ||
![]() |
b9c95d49a6 | ||
![]() |
fc0be6bce2 | ||
![]() |
8db891cfe6 | ||
![]() |
f6e77cc578 | ||
![]() |
a3782f9150 | ||
![]() |
7546c7ef42 | ||
![]() |
53de8cda30 | ||
![]() |
1fb7473dc5 | ||
![]() |
cc9d09bd54 | ||
![]() |
42ff4a2f62 | ||
![]() |
3fa5f80fc4 | ||
![]() |
9b5b7ef8db | ||
![]() |
560acf62fe | ||
![]() |
27d12922da | ||
![]() |
37b92f3d88 | ||
![]() |
79d5c0c92e | ||
![]() |
0bdaedd486 | ||
![]() |
018a201688 | ||
![]() |
a5bd7e6563 | ||
![]() |
a055feccd5 | ||
![]() |
ba68a9b52b | ||
![]() |
49669dc7e0 | ||
![]() |
5bdf79606e | ||
![]() |
ff3a9e47df | ||
![]() |
a18ba24f4a | ||
![]() |
baeb744a7c | ||
![]() |
d07add383f | ||
![]() |
a1f18bc133 | ||
![]() |
e00c23bc49 | ||
![]() |
0228a356e4 | ||
![]() |
b0fa0d534e | ||
![]() |
1157fda96c | ||
![]() |
bbf774379d | ||
![]() |
24c8c4319d | ||
![]() |
3b8f9f5892 | ||
![]() |
b47ccd06f9 | ||
![]() |
8c4292f9ac | ||
![]() |
a8fbf8ab1d | ||
![]() |
38e9938666 | ||
![]() |
93c4a0652e | ||
![]() |
2fff6647fd | ||
![]() |
36f0f60c49 | ||
![]() |
d12b57e1de | ||
![]() |
deb16428ed | ||
![]() |
a75aba4aee | ||
![]() |
bb5aa2be3d | ||
![]() |
ef6ef98541 | ||
![]() |
89f581f63e | ||
![]() |
6081fa329b | ||
![]() |
112811f3e2 | ||
![]() |
ede07595c3 | ||
![]() |
08d65623dd | ||
![]() |
7540b5fb34 | ||
![]() |
10c54c2d10 | ||
![]() |
b8d9c8cc47 | ||
![]() |
bac5018b27 | ||
![]() |
c65d9898c8 | ||
![]() |
d7284c40bd | ||
![]() |
1c00f82097 | ||
![]() |
c501923f2b | ||
![]() |
81b22a8c36 | ||
![]() |
beb66396fe | ||
![]() |
aaf3de68cf | ||
![]() |
c827c9e825 | ||
![]() |
5100fdbc96 | ||
![]() |
fae3f38a88 | ||
![]() |
a8236222fb |
6
.gitignore
vendored
@@ -21,6 +21,10 @@ cache/*
|
||||
*.crt
|
||||
*.key
|
||||
*.csr
|
||||
*.pem
|
||||
|
||||
# Mergetool
|
||||
*.orgin
|
||||
|
||||
# OS generated files #
|
||||
######################
|
||||
@@ -31,7 +35,7 @@ Icon?
|
||||
Thumbs.db
|
||||
|
||||
#Ignore files generated by PyCharm
|
||||
.idea/*
|
||||
*.idea/*
|
||||
|
||||
#Ignore files generated by vi
|
||||
*.swp
|
||||
|
281
CHANGELOG.md
@@ -1,5 +1,286 @@
|
||||
# Changelog
|
||||
|
||||
## v1.3.13 (2016-03-27)
|
||||
|
||||
* Fix: Only mask strings longer than 5 characters in logs.
|
||||
|
||||
|
||||
## v1.3.12 (2016-03-27)
|
||||
|
||||
* Fix: "Check GitHub for updates" not rescheduling when toggling setting.
|
||||
* Fix: Bug where notifications would fail if metadata is not found.
|
||||
* Fix: Bug where notifications would fail if unable to upload poster to Imgur.
|
||||
* Fix: PlexPy will now start properly for different Python environment variables.
|
||||
* New: Feature requests moved to FeatHub.
|
||||
* New: Ability to specify a GitHub API token for updates (optional).
|
||||
* New: Mask out sensitive information from the logs.
|
||||
* New: New and updated Arnold quotes. (Thanks @Vilsol & @Chrisophogus)
|
||||
* New: "First" and "Last" page buttons to datatables.
|
||||
* New: Access log file from the "Help & Info" page.
|
||||
* New: CherryPy environment options (for development). (Thanks @codedecay)
|
||||
* New: PlexPy development environment (for development only).
|
||||
* Change: Facebook posts with a posters now include a summary.
|
||||
* Change: Facebook posts now use a default poster if the poster is not found or unable to upload to Imgur.
|
||||
* Change: IFTTT events can be fromatted with the {action} name.
|
||||
* Change: Logs now use ISO date format to avoid locale encoding errors. (Thanks @alshain)
|
||||
* Remove: Non-functioning Plex notification agent.
|
||||
|
||||
|
||||
## v1.3.11 (2016-03-15)
|
||||
|
||||
* Fix: Typo preventing history logging for websockets.
|
||||
|
||||
|
||||
## v1.3.10 (2016-03-12)
|
||||
|
||||
* Fix: Actually allow HTML tags for Pushover.
|
||||
* Fix: PlexPy not restarting on Windows if there is a space in the folder path.
|
||||
* Fix: Reconnect websocket when changing PMS SSL setting.
|
||||
* Fix: Datatables not loading when view_offset or duration is blank.
|
||||
* Fix: Bug when checking the PMS version in the settings.
|
||||
* Fix: Auto-refreshing of log tables.
|
||||
* Fix: Logging of IPv6 addresses. (PMS version >0.9.14 only.)
|
||||
* Fix: Hide days selection from the Play Totals graph page.
|
||||
* Fix: PlexPy overwriting user's own SSL certificate/key.
|
||||
* Fix: Multiple watched notifications when using websocket.
|
||||
* Fix: Some missing python library imports.
|
||||
* Fix: Some typos in settings and PlexWatch importer.
|
||||
* New: Ability to get notified of PMS updates.
|
||||
* New: Ability to disable the link to Plex Web with Facebook notifications and use IMDB, TVDB, TMDb, or Last.fm instead.
|
||||
* New: Ability to reset Imgur poster url from the info page if the poster is changed.
|
||||
* New: Tooltips on the current activity progress bars.
|
||||
* New: Side scrolling of Recently Added/Recently Played items.
|
||||
* New: Document all date/time format options.
|
||||
* New: Button to clear notification logs.
|
||||
* New: Customizable backup, cache, and log directories.
|
||||
* Change: Retry writing sessions to history if it fails, so sessions don't get lost. (Activity pinger only, not availble for websocket.)
|
||||
* Change: Save any unknown sessions to the "Local" user.
|
||||
* Change: History table modal is filtered depending on which graph series is clicked.
|
||||
* Change: Revert back to saving the state of datatables (search, sorting, entries per page, etc.).
|
||||
* Change: Newlines are not longer stripped from notification text which allows for finer control of how notifications look.
|
||||
* Change: Updated FreeNAS/FreeBSD init scripts. (Must have updated jails.) (Thanks @chiviak)
|
||||
|
||||
|
||||
## v1.3.9 (2016-02-21)
|
||||
|
||||
* Fix: Recently added notification not sent to all notification agents.
|
||||
* New: Pushover HTML support. (Thanks @elseym)
|
||||
|
||||
|
||||
## v1.3.8 (2016-02-21)
|
||||
|
||||
* Fix: Regression unable to clear HTTP password.
|
||||
* Fix: Remove media tags from script arguments for server notifications.
|
||||
* Fix: Encode poster titles to UTF-8 for Imgur upload.
|
||||
* Fix: Allow notifications to send without poster if Imgur upload fails.
|
||||
* New: Notification Logs table in the Logs tab.
|
||||
* New: Toggle in settings to enable posters in notifications. (Disabled by default.)
|
||||
* Change: Save Imgur poster URL to database so upload is not needed every time.
|
||||
* Change: Notify log in database to log each event as a separate entry.
|
||||
* Change: Monitor remote access is unchecked if remote access is disabled on server.
|
||||
|
||||
|
||||
## v1.3.7 (2016-02-20)
|
||||
|
||||
* Fix: Verifying server with SSL enabled.
|
||||
* Fix: Regression where {stream_duration} reported as 0.
|
||||
* Fix: Video metadata flags showing up for track info.
|
||||
* Fix: Custom library icons not applied to Library Statistics.
|
||||
* Fix: Typos in the Web UI.
|
||||
* New: ETA to Current Activity overlay.
|
||||
* New: Total duration to Libraries and Users tables.
|
||||
* New: {machine_id} to notification options.
|
||||
* New: IMDB, TVDB, TMDb, Last.fm, and Trackt IDs/URLs to notification options.
|
||||
* New: {poster_url} to notification options using Imgur.
|
||||
* New: Poster and link for Facebook notifications.
|
||||
* New: Log javascript errors from the Web UI.
|
||||
* New: Configuration and Scheduler info to the settings page.
|
||||
* New: Schedule background task to backup the PlexPy database.
|
||||
* New: URL anonymizer for external links.
|
||||
* New: Plex Media Scanner log file to Log viewer.
|
||||
* New: API v2 (sill very experimental). (Thanks @Hellowlol)
|
||||
* Change: Allow secure websocket connections.
|
||||
* Change: History grouping now accounts for the view offset.
|
||||
* Change: Subject line can be toggled off for Facebook, Slack, Telegram, and Twitter.
|
||||
* Change: Create self-signed SSL certificates when enabling HTTPS.
|
||||
* Change: Revert homepage "Last Played" to "Last Watched".
|
||||
* Change: Disable monitor remote access checkbox if remote access is not enabled on the PMS.
|
||||
* Change: Disable IP logging checkbox if PMS version is 0.9.14 or greater.
|
||||
|
||||
|
||||
## v1.3.6 (2016-02-03)
|
||||
|
||||
* Fix: Regression where {duration} not reported in minutes.
|
||||
* Fix: Proper daemonizing in FreeBSD and FreeNAS init scripts.
|
||||
* Change: Update readme documentation.
|
||||
|
||||
|
||||
## v1.3.5 (2016-02-02)
|
||||
|
||||
* Fix: Removing unique constraints from database.
|
||||
* Fix: Unable to expand media info table when missing "Added At" date.
|
||||
* Fix: Server verification for unpublished servers.
|
||||
* Fix: Updating PMS identifier for server change.
|
||||
* New: {stream_time}, {remaining_time}, and {progress_time} to notification options.
|
||||
* New: Powershell script support. (Thanks @Hellowlol)
|
||||
* New: Method to delete duplicate libraries.
|
||||
* Change: Daemonize before running start up tasks.
|
||||
|
||||
|
||||
## 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.
|
||||
* New: Unique identifiers to notification options.
|
||||
* Remove: Requirement of media type toggles for recently added notifications.
|
||||
* Remove: Built in Twitter key and secret.
|
||||
* Change: 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)
|
||||
|
||||
* New: Brand new Libraries section.
|
||||
* New: Lots of new library statistics.
|
||||
* New: Media info table for libraries.
|
||||
* New: Web app for Android and iOS. (Thanks @zobe123)
|
||||
* New: Slack notification agent. (Thanks @richipargo)
|
||||
* New: Facebook notification agent.
|
||||
* New: Custom script notification agent. (Thanks @Hellowlol)
|
||||
* New: Custom "From Name" to email notification agent.
|
||||
* New: Ability to test notifications / send custom one-off notifications.
|
||||
* New: 'datestamp' and 'timestamp' notification options.
|
||||
* New: More concurrent stream statistics.
|
||||
* New: Media info flags on the info pages.
|
||||
* New: Ability to fix broken metadata if the item has been moved in Plex.
|
||||
* New: Ability to rearrange the homepage statistics cards.
|
||||
* New: 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
|
||||
|
@@ -1,12 +1,45 @@
|
||||
# Contributing to PlexPy
|
||||
|
||||
## Issues
|
||||
In case you read this because you are posting an issue, please take a minute and conside the things below. The issue tracker is not a support forum. It is primarily intended to submit bugs, improvements or feature requests. However, we are glad to help you, and make sure the problem is not caused by PlexPy, but don't expect step-by-step answers.
|
||||
In case you read this because you are posting an issue, please take a minute and conside the things below. The issue tracker is not a support forum. It is primarily intended to submit bugs. However, we are glad to help you, and make sure the problem is not caused by PlexPy, but don't expect step-by-step answers.
|
||||
|
||||
* Use the search function. Chances are that your problem is already discussed. Do not append to (closed) issues if your problem does not fit the discussion.
|
||||
* Visit the [Troubleshooting](../../wiki/TroubleShooting) wiki first.
|
||||
* Use [proper formatting](https://help.github.com/articles/github-flavored-markdown/). Paste your logs in code blocks.
|
||||
* Close your issue if you resolved it.
|
||||
##### Many issues can simply be solved by:
|
||||
|
||||
- Making sure you update to the latest version.
|
||||
- Turning your device off and on again.
|
||||
- Analyzing your logs, you just might find the solution yourself!
|
||||
- Using the **search** function to see if this issue has already been reported/solved.
|
||||
- Checking the [Wiki](https://github.com/drzoidberg33/plexpy/wiki) for
|
||||
[ [Installation] ](https://github.com/drzoidberg33/plexpy/wiki/Installation) and
|
||||
[ [FAQs] ](https://github.com/drzoidberg33/plexpy/wiki/Frequently-Asked-Questions-(FAQ)).
|
||||
- For basic questions try asking on [Gitter](https://gitter.im/drzoidberg33/plexpy) or the [Plex Forums](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) first before opening an issue.
|
||||
|
||||
##### If nothing has worked:
|
||||
|
||||
1. Open a new issue on the GitHub [issue tracker](http://github.com/drzoidberg33/plexpy/issues).
|
||||
2. Provide a clear title to easily help identify your problem.
|
||||
3. Use proper [markdown syntax](https://help.github.com/articles/github-flavored-markdown) to structure your post (i.e. code/log in code blocks).
|
||||
4. Make sure you provide the following information:
|
||||
- [ ] Version
|
||||
- [ ] Branch
|
||||
- [ ] Commit hash
|
||||
- [ ] Operating system
|
||||
- [ ] Python version
|
||||
- [ ] What you did?
|
||||
- [ ] What happened?
|
||||
- [ ] What you expected?
|
||||
- [ ] How can we reproduce your issue?
|
||||
- [ ] What are your (relevant) settings?
|
||||
- [ ] Include a link to your **FULL** (not just a few lines!) log file that has the error. Please use [Gist](http://gist.github.com) or [Pastebin](http://pastebin.com/).
|
||||
5. Close your issue when it's solved! If you found the solution yourself please comment so that others benefit from it.
|
||||
|
||||
## Feature Requests
|
||||
|
||||
Feature requests are handled on [FeatHub](http://feathub.com/drzoidberg33/plexpy).
|
||||
|
||||
1. Search the existing requests to see if your suggestion has already been submitted.
|
||||
2. If a similar request exists, give it a thumbs up (+1), or add additional comments to the request.
|
||||
3. If no similar requests exist, you can create a new one. Make sure to provide a clear title to easily identify the feature request.
|
||||
|
||||
## Pull Requests
|
||||
If you think you can contribute code to the PlexPy repository, do not hesitate to submit a pull request.
|
||||
|
53
PlexPy.py
@@ -1,4 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
#!/bin/sh
|
||||
''''which python >/dev/null 2>&1 && exec python "$0" "$@" # '''
|
||||
''''which python2 >/dev/null 2>&1 && exec python2 "$0" "$@" # '''
|
||||
''''which python2.7 >/dev/null 2>&1 && exec python2.7 "$0" "$@" # '''
|
||||
''''exec echo "Error: Python not found!" # '''
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of PlexPy.
|
||||
@@ -76,11 +81,14 @@ def main():
|
||||
'-d', '--daemon', action='store_true', help='Run as a daemon')
|
||||
parser.add_argument(
|
||||
'-p', '--port', type=int, help='Force PlexPy to run on a specified port')
|
||||
parser.add_argument(
|
||||
'--dev', action='store_true', help='Start PlexPy in the development environment')
|
||||
parser.add_argument(
|
||||
'--datadir', help='Specify a directory where to store your data files')
|
||||
parser.add_argument('--config', help='Specify a config file to use')
|
||||
parser.add_argument('--nolaunch', action='store_true',
|
||||
help='Prevent browser from launching on startup')
|
||||
parser.add_argument(
|
||||
'--config', help='Specify a config file to use')
|
||||
parser.add_argument(
|
||||
'--nolaunch', action='store_true', help='Prevent browser from launching on startup')
|
||||
parser.add_argument(
|
||||
'--pidfile', help='Create a pid file (only relevant when running as a daemon)')
|
||||
|
||||
@@ -95,6 +103,10 @@ def main():
|
||||
logger.initLogger(console=not plexpy.QUIET, log_dir=False,
|
||||
verbose=plexpy.VERBOSE)
|
||||
|
||||
if args.dev:
|
||||
plexpy.DEV = True
|
||||
logger.debug(u"PlexPy is running in the dev environment.")
|
||||
|
||||
if args.daemon:
|
||||
if sys.platform == 'win32':
|
||||
sys.stderr.write(
|
||||
@@ -153,11 +165,24 @@ def main():
|
||||
# Put the database in the DATA_DIR
|
||||
plexpy.DB_FILE = os.path.join(plexpy.DATA_DIR, 'plexpy.db')
|
||||
|
||||
if plexpy.DAEMON:
|
||||
plexpy.daemonize()
|
||||
|
||||
# Read config and start logging
|
||||
plexpy.initialize(config_file)
|
||||
|
||||
if plexpy.DAEMON:
|
||||
plexpy.daemonize()
|
||||
# Start the background threads
|
||||
plexpy.start()
|
||||
|
||||
# Open connection for websocket
|
||||
if plexpy.CONFIG.MONITORING_USE_WEBSOCKET:
|
||||
try:
|
||||
web_socket.start_thread()
|
||||
except:
|
||||
logger.warn(u"Websocket :: Unable to open connection.")
|
||||
# Fallback to polling
|
||||
plexpy.POLLING_FAILOVER = True
|
||||
plexpy.initialize_scheduler()
|
||||
|
||||
# Force the http port if neccessary
|
||||
if args.port:
|
||||
@@ -181,6 +206,7 @@ def main():
|
||||
'http_port': http_port,
|
||||
'http_host': plexpy.CONFIG.HTTP_HOST,
|
||||
'http_root': plexpy.CONFIG.HTTP_ROOT,
|
||||
'http_environment': plexpy.CONFIG.HTTP_ENVIRONMENT,
|
||||
'http_proxy': plexpy.CONFIG.HTTP_PROXY,
|
||||
'enable_https': plexpy.CONFIG.ENABLE_HTTPS,
|
||||
'https_cert': plexpy.CONFIG.HTTPS_CERT,
|
||||
@@ -190,21 +216,8 @@ def main():
|
||||
}
|
||||
webstart.initialize(web_config)
|
||||
|
||||
# Start the background threads
|
||||
plexpy.start()
|
||||
|
||||
# Open connection for websocket
|
||||
if plexpy.CONFIG.MONITORING_USE_WEBSOCKET:
|
||||
try:
|
||||
web_socket.start_thread()
|
||||
except:
|
||||
logger.warn(u"Websocket :: Unable to open connection.")
|
||||
# Fallback to polling
|
||||
plexpy.POLLING_FAILOVER = True
|
||||
plexpy.initialize_scheduler()
|
||||
|
||||
# Open webbrowser
|
||||
if plexpy.CONFIG.LAUNCH_BROWSER and not args.nolaunch:
|
||||
if plexpy.CONFIG.LAUNCH_BROWSER and not args.nolaunch and not plexpy.DEV:
|
||||
plexpy.launch_browser(plexpy.CONFIG.HTTP_HOST, http_port,
|
||||
plexpy.CONFIG.HTTP_ROOT)
|
||||
|
||||
|
168
README.md
@@ -1,121 +1,79 @@
|
||||
#PlexPy
|
||||
# PlexPy
|
||||
|
||||
[](https://gitter.im/drzoidberg33/plexpy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
A python based web application for monitoring, analytics and notifications for Plex Media Server (www.plex.tv).
|
||||
|
||||
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)
|
||||
|
||||
## Features
|
||||
|
||||
###Support
|
||||
-----------
|
||||
* PlexPy Wiki: https://github.com/drzoidberg33/plexpy/wiki
|
||||
* Responsive web design viewable on desktop, tablet and mobile web browsers.
|
||||
* Themed to complement Plex/Web.
|
||||
* Easy configuration setup (no separate web server required).
|
||||
* Monitor current Plex Media Server activity.
|
||||
* Fully customizable notifications for stream activity and recently added media.
|
||||
* Top statistics on home page with configurable duration and measurement metric.
|
||||
* Global watching history with search/filtering & dynamic column sorting.
|
||||
* Full user list with general information and comparison stats.
|
||||
* Individual user information including devices IP addresses.
|
||||
* Complete library statistics and media file information.
|
||||
* Rich analytics presented using Highcharts graphing.
|
||||
* Beautiful content information pages.
|
||||
* Full sync list data on all users syncing items from your library.
|
||||
* And many more!!
|
||||
|
||||
## Installation and Support
|
||||
|
||||
###Features
|
||||
-----------
|
||||
* Responsive web design viewable on desktop, tablet and mobile web browsers
|
||||
|
||||
* Themed to complement Plex/Web
|
||||
|
||||
* Easy configuration setup via html form
|
||||
|
||||
* Current Plex Media Server viewing activity including:
|
||||
* number of current users
|
||||
* title
|
||||
* progress
|
||||
* platform
|
||||
* user
|
||||
* state (playing, paused, buffering, etc)
|
||||
* stream type (direct, transcoded)
|
||||
* video type & resolution
|
||||
* audio type & channel count.
|
||||
|
||||
* Top statistics on home page with configurable duration and measurement metric:
|
||||
* Most watched TV
|
||||
* Most popular TV
|
||||
* Most watched Movie
|
||||
* Most popular Movie
|
||||
* Most active user
|
||||
* Most active platform
|
||||
|
||||
* Recently added media and how long ago it was added
|
||||
|
||||
* Global watching history with search/filtering & dynamic column sorting
|
||||
* date
|
||||
* user
|
||||
* platform
|
||||
* ip address
|
||||
* title
|
||||
* stream information details
|
||||
* start time
|
||||
* paused duration length
|
||||
* stop time
|
||||
* duration length
|
||||
* watched progress
|
||||
* show/hide columns
|
||||
* delete mode - allows deletion of specific history items
|
||||
|
||||
* Full user list with general information and comparison stats
|
||||
|
||||
* Individual user information
|
||||
* username and gravatar (if available)
|
||||
* daily, weekly, monthly, all time stats for play count and duration length
|
||||
* individual platform stats for each user
|
||||
* public ip address history with last seen date and geo tag location
|
||||
* recently watched content
|
||||
* watching history
|
||||
* synced items
|
||||
* assign users custom friendly names within PlexPy
|
||||
* assign users custom avatar URL within PlexPy
|
||||
* disable history logging per user
|
||||
* disable notifications per user
|
||||
* option to purge all history per user.
|
||||
|
||||
* Rich analytics presented using Highcharts graphing
|
||||
* user-selectable time periods of 30, 90 or 365 days
|
||||
* daily watch count and duration
|
||||
* totals by day of week and hours of the day
|
||||
* totals by top 10 platform
|
||||
* totals by top 10 users
|
||||
* detailed breakdown by transcode decision
|
||||
* source and stream resolutions
|
||||
* transcode decision counts by user and platform
|
||||
* total monthly counts
|
||||
|
||||
* Content information pages
|
||||
* movies (includes watching history)
|
||||
* tv shows (includes watching history)
|
||||
* tv seasons
|
||||
* tv episodes (includes watching history)
|
||||
|
||||
* Full sync list data on all users syncing items from your library
|
||||
|
||||
## Installation and Notes
|
||||
|
||||
* [Installation page](../../wiki/Installation) shows you how to install PlexPy.
|
||||
* [Usage guide](../../wiki/Usage-guide) introduces you to PlexPy.
|
||||
* [Troubleshooting page](../../wiki/TroubleShooting) in the wiki can help you with common problems.
|
||||
|
||||
**Issues** can be reported on the GitHub issue tracker considering these rules:
|
||||
|
||||
1. Analyze your log, you just might find the solution yourself!
|
||||
2. You read the wiki and searched existing issues, but this is not solving your problem.
|
||||
3. Post the issue with a clear title, description and the HP log and use [proper markdown syntax](https://help.github.com/articles/github-flavored-markdown) to structure your text (code/log in code blocks).
|
||||
4. Close your issue when it's solved! If you found the solution yourself please comment so that others benefit from it.
|
||||
|
||||
**Feature requests** can be reported on the GitHub issue tracker too:
|
||||
|
||||
1. Search for similar existing 'issues', feature requests can be recognized by the label 'Request'.
|
||||
2. If a similar Request exists, post a comment (+1, or add a new idea to the existing request), otherwise you can create a new one.
|
||||
|
||||
If you **comply with these rules** you can [post your request/issue](http://github.com/drzoidberg33/plexpy/issues).
|
||||
* [Installation Guides](https://github.com/drzoidberg33/plexpy/wiki/Installation) shows you how to install PlexPy.
|
||||
* [FAQs](https://github.com/drzoidberg33/plexpy/wiki/Frequently-Asked-Questions-(FAQ)) in the wiki can help you with common problems.
|
||||
|
||||
**Support** the project by implementing new features, solving support tickets and provide bug fixes.
|
||||
|
||||
## Issues
|
||||
|
||||
##### Many issues can simply be solved by:
|
||||
|
||||
- Making sure you update to the latest version.
|
||||
- Turning your device off and on again.
|
||||
- Analyzing your logs, you just might find the solution yourself!
|
||||
- Using the **search** function to see if this issue has already been reported/solved.
|
||||
- Checking the [Wiki](https://github.com/drzoidberg33/plexpy/wiki) for
|
||||
[ [Installation] ](https://github.com/drzoidberg33/plexpy/wiki/Installation) and
|
||||
[ [FAQs] ](https://github.com/drzoidberg33/plexpy/wiki/Frequently-Asked-Questions-(FAQ)).
|
||||
- For basic questions try asking on [Gitter](https://gitter.im/drzoidberg33/plexpy) or the [Plex Forums](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) first before opening an issue.
|
||||
|
||||
##### If nothing has worked:
|
||||
|
||||
1. Open a new issue on the GitHub [issue tracker](http://github.com/drzoidberg33/plexpy/issues).
|
||||
2. Provide a clear title to easily help identify your problem.
|
||||
3. Use proper [markdown syntax](https://help.github.com/articles/github-flavored-markdown) to structure your post (i.e. code/log in code blocks).
|
||||
4. Make sure you provide the following information:
|
||||
- [ ] Version
|
||||
- [ ] Branch
|
||||
- [ ] Commit hash
|
||||
- [ ] Operating system
|
||||
- [ ] Python version
|
||||
- [ ] What you did?
|
||||
- [ ] What happened?
|
||||
- [ ] What you expected?
|
||||
- [ ] How can we reproduce your issue?
|
||||
- [ ] What are your (relevant) settings?
|
||||
- [ ] Include a link to your **FULL** (not just a few lines!) log file that has the error. Please use [Gist](http://gist.github.com) or [Pastebin](http://pastebin.com/).
|
||||
5. Close your issue when it's solved! If you found the solution yourself please comment so that others benefit from it.
|
||||
|
||||
## Feature Requests
|
||||
|
||||
Feature requests are handled on [FeatHub](http://feathub.com/drzoidberg33/plexpy).
|
||||
|
||||
1. Search the existing requests to see if your suggestion has already been submitted.
|
||||
2. If a similar request exists, give it a thumbs up (+1), or add additional comments to the request.
|
||||
3. If no similar requests exist, you can create a new one. Make sure to provide a clear title to easily identify the feature request.
|
||||
|
||||
## License
|
||||
|
||||
This is free software under the GPL v3 open source license. Feel free to do with it what you wish, but any modification must be open sourced. A copy of the license is included.
|
||||
|
||||
This software includes Highsoft software libraries which you may freely distribute for non-commercial use. Commerical users must licence this software, for more information visit https://shop.highsoft.com/faq/non-commercial#non-commercial-redistribution.
|
||||
This software includes Highsoft software libraries which you may freely distribute for non-commercial use. Commerical users must licence this software, for more information visit https://shop.highsoft.com/faq/non-commercial#non-commercial-redistribution.
|
@@ -1,6 +1,7 @@
|
||||
<%
|
||||
import plexpy
|
||||
from plexpy import version
|
||||
from plexpy.helpers import anon_url
|
||||
%>
|
||||
<!doctype html>
|
||||
|
||||
@@ -18,12 +19,117 @@ from plexpy import version
|
||||
${next.headIncludes()}
|
||||
|
||||
<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="apple-touch-icon" href="interfaces/default/images/icon_iphone.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="interfaces/default/images/icon_ipad.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="interfaces/default/images/icon_iphone@2x.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="interfaces/default/images/icon_ipad@2x.png">
|
||||
|
||||
<!-- Allow web app to be run in full-screen mode. -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<!-- 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>
|
||||
|
||||
<body class="content">
|
||||
@@ -31,15 +137,15 @@ from plexpy import version
|
||||
<div id="ajaxMsg" class="ajaxMsg"></div>
|
||||
% if plexpy.CONFIG.CHECK_GITHUB and not plexpy.CURRENT_VERSION:
|
||||
<div id="updatebar" style="display: none;">
|
||||
You're running an unknown version of PlexPy. <a href="update">Update</a> or
|
||||
<a href="#" id="updateDismiss">Close</a>
|
||||
You're running an unknown version of PlexPy.<br />
|
||||
<a href="update">Update</a> or <a href="#" id="updateDismiss">Close</a>
|
||||
</div>
|
||||
% elif plexpy.CONFIG.CHECK_GITHUB and plexpy.CURRENT_VERSION != plexpy.LATEST_VERSION and plexpy.COMMITS_BEHIND > 0 and plexpy.INSTALL_TYPE != 'win':
|
||||
<div id="updatebar" style="display: none;">
|
||||
A <a
|
||||
href="https://github.com/${plexpy.CONFIG.GIT_USER}/plexpy/compare/${plexpy.CURRENT_VERSION}...${plexpy.LATEST_VERSION}" target="_blank">
|
||||
newer version</a> is available. You're ${plexpy.COMMITS_BEHIND} commits behind. <a href="update">Update</a> or
|
||||
<a href="#" id="updateDismiss">Close</a>
|
||||
A <a href="${anon_url('https://github.com/%s/plexpy/compare/%s...%s' % (plexpy.CONFIG.GIT_USER, plexpy.CURRENT_VERSION, plexpy.LATEST_VERSION))}" target="_blank">
|
||||
newer version</a> is available.<br />
|
||||
You're ${plexpy.COMMITS_BEHIND} commits behind.<br />
|
||||
<a href="update">Update</a> or <a href="#" id="updateDismiss">Close</a>
|
||||
</div>
|
||||
% endif
|
||||
<nav class="navbar navbar-fixed-top">
|
||||
@@ -57,7 +163,7 @@ from plexpy import version
|
||||
</div>
|
||||
<div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li>
|
||||
<li class="hidden-sm hidden-xs">
|
||||
<form action="search" method="post" class="form" id="search_form">
|
||||
<div class="input-group">
|
||||
<span class="input-textbox">
|
||||
@@ -69,37 +175,42 @@ from plexpy import version
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
% if title=="Home":
|
||||
% if title == "Home":
|
||||
<li class="active"><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
|
||||
% else:
|
||||
<li><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
|
||||
% 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>
|
||||
% else:
|
||||
<li><a href="users">Users</a></li>
|
||||
% endif
|
||||
% if title=="History":
|
||||
% if title == "History":
|
||||
<li class="active"><a href="history">History</a></li>
|
||||
% else:
|
||||
<li><a href="history">History</a></li>
|
||||
% endif
|
||||
% if title=="Graphs":
|
||||
% if title == "Graphs":
|
||||
<li class="active"><a href="graphs">Graphs</a></li>
|
||||
% else:
|
||||
<li><a href="graphs">Graphs</a></li>
|
||||
% endif
|
||||
% if title=="Synced Items":
|
||||
% if title == "Synced Items":
|
||||
<li class="active"><a href="sync">Synced Items</a></li>
|
||||
% else:
|
||||
<li><a href="sync">Synced Items</a></li>
|
||||
% endif
|
||||
% if title=="Log":
|
||||
% if title == "Log":
|
||||
<li class="active"><a href="logs">Logs</a></li>
|
||||
% else:
|
||||
<li><a href="logs">Logs</a></li>
|
||||
% endif
|
||||
% if title=="Settings":
|
||||
% if title == "Settings":
|
||||
<li class="active"><a href="settings">Settings</a></li>
|
||||
% else:
|
||||
<li><a href="settings">Settings</a></li>
|
||||
@@ -135,22 +246,37 @@ ${next.headerIncludes()}
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
url: 'search',
|
||||
data: { 'query': $('#query').val() }
|
||||
data: { query: $('#query').val() }
|
||||
})
|
||||
} else {
|
||||
e.preventDefault();
|
||||
$('#search_button').removeClass('btn-inactive');
|
||||
$('#query').clearQueue().val('').animate({ right: '0', width: '250px' }).addClass('active').focus();
|
||||
$('#query').clearQueue().val('').animate({ right: '0', width: '200px' }).addClass('active').focus();
|
||||
}
|
||||
})
|
||||
$('#query').on('blur', function (e) {
|
||||
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');
|
||||
}).removeClass('active');
|
||||
}
|
||||
});
|
||||
</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()}
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -235,8 +235,8 @@ fieldset[disabled] .btn-bright:active,
|
||||
.btn-bright.disabled.active,
|
||||
.btn-bright[disabled].active,
|
||||
fieldset[disabled] .btn-bright.active {
|
||||
background-color: #5cb85c;
|
||||
border-color: #4cae4c;
|
||||
background-color: #c9302c;
|
||||
border-color: #ac2925;
|
||||
}
|
||||
.btn-bright .badge {
|
||||
color: #fff;
|
||||
@@ -487,7 +487,8 @@ textarea.form-control:focus {
|
||||
.users-poster-face {
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
background-size: contain;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
-webkit-border-radius: 50%;
|
||||
@@ -497,6 +498,17 @@ textarea.form-control:focus {
|
||||
-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);
|
||||
}
|
||||
.libraries-poster-face {
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
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 .cover-face:hover,
|
||||
a .users-poster-face:hover {
|
||||
@@ -737,14 +749,20 @@ a:hover .dashboard-activity-poster {
|
||||
transition: all 0s;
|
||||
}
|
||||
.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;
|
||||
position: absolute;
|
||||
height: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.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-image: -moz-linear-gradient(top, #fbb450, #f89406);
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
|
||||
@@ -757,6 +775,37 @@ a:hover .dashboard-activity-poster {
|
||||
height: 6px;
|
||||
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 {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@@ -833,10 +882,11 @@ a .dashboard-activity-metadata-user-thumb:hover {
|
||||
}
|
||||
.dashboard-recent-media-row {
|
||||
width: 100%;
|
||||
margin:0 auto;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.dashboard-recent-media {
|
||||
width: 100%;
|
||||
@@ -1157,6 +1207,7 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
|
||||
width: 250px;
|
||||
height: 1px;
|
||||
margin: 0 40px 20px 25px;
|
||||
position: relative;
|
||||
}
|
||||
.summary-content {
|
||||
position: relative;
|
||||
@@ -1180,6 +1231,20 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
|
||||
margin-left: 2px;
|
||||
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 {
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
@@ -1256,31 +1321,24 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
|
||||
line-height: 18px;
|
||||
color: #fff;
|
||||
}
|
||||
.rateit {
|
||||
display: -moz-inline-box;
|
||||
.star-rating {
|
||||
display: inline-block;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
font-size: 15px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
float: right;
|
||||
margin-top: 3px;
|
||||
height: 21px;
|
||||
float: right;
|
||||
}
|
||||
.rateit .rateit-range {
|
||||
background: url(../images/star-gray-32.png);
|
||||
background-size: contain;
|
||||
height: 16px;
|
||||
.star-rating .star-icon {
|
||||
width: auto;
|
||||
margin-left: 2px;
|
||||
color: #F9AA03;
|
||||
}
|
||||
.rateit .rateit-selected {
|
||||
background: url(../images/star-32.png);
|
||||
background-size: contain;
|
||||
height: 16px;
|
||||
.star-rating .star-icon-o {
|
||||
width: auto;
|
||||
margin-left: 2px;
|
||||
color: #999;
|
||||
}
|
||||
#children-list, #search-results-list {
|
||||
position: relative;
|
||||
@@ -1500,7 +1558,8 @@ a:hover .item-children-poster {
|
||||
float: left;
|
||||
margin-top: 15px;
|
||||
margin-right: 15px;
|
||||
background-size: contain;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
-webkit-border-radius: 50%;
|
||||
@@ -1615,7 +1674,6 @@ a:hover .item-children-poster {
|
||||
}
|
||||
.user-player-instance-box {
|
||||
float: left;
|
||||
width: 75px;
|
||||
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);
|
||||
@@ -1637,6 +1695,7 @@ a:hover .item-children-poster {
|
||||
font-weight: normal;
|
||||
width: 140px;
|
||||
margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.user-player-instance-playcount h3 {
|
||||
font-size: 30px;
|
||||
@@ -1656,6 +1715,36 @@ a:hover .item-children-poster {
|
||||
top: 15px;
|
||||
left: 0px;
|
||||
}
|
||||
.library-info-poster-face {
|
||||
float: left;
|
||||
margin-top: 15px;
|
||||
margin-right: 15px;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
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 ul {
|
||||
@@ -1686,6 +1775,7 @@ a:hover .item-children-poster {
|
||||
padding-left: 80px;
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.home-platforms-instance-name {
|
||||
color: #fff;
|
||||
@@ -2087,9 +2177,14 @@ a .home-platforms-instance-list-oval:hover,
|
||||
float: right;
|
||||
}
|
||||
.colvis-button-bar,
|
||||
.refresh-users-button {
|
||||
.refresh-users-button,
|
||||
.refresh-libraries-button {
|
||||
float: right;
|
||||
}
|
||||
.refresh-users-button,
|
||||
.refresh-libraries-button {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.nav-settings,
|
||||
.nav-settings ul {
|
||||
margin: 0px 0px 20px 0px;
|
||||
@@ -2286,6 +2381,9 @@ a .home-platforms-instance-list-oval:hover,
|
||||
width: 250px;
|
||||
z-index: 9999;
|
||||
}
|
||||
.dataTables_paginate li {
|
||||
margin: 0;
|
||||
}
|
||||
.tooltip.top .tooltip-arrow {
|
||||
border-top-color: #fff;
|
||||
}
|
||||
@@ -2303,42 +2401,55 @@ a .home-platforms-instance-list-oval:hover,
|
||||
background: #fff;
|
||||
border: 0;
|
||||
font-weight: bold;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.history-title .popover.right {
|
||||
margin-left: 12px;
|
||||
z-index: 5;
|
||||
.history-thumbnail-popover {
|
||||
z-index: 2;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
.history-title .popover.right .popover-content {
|
||||
padding: 5px 8px;
|
||||
.history-thumbnail-popover.popover.left {
|
||||
margin-left: -15px;
|
||||
}
|
||||
.history-thumbnail-popover.popover.right {
|
||||
margin-left: 15px;
|
||||
}
|
||||
.history-thumbnail-popover .popover-content {
|
||||
color: #000;
|
||||
padding: 0;
|
||||
}
|
||||
.history-thumbnail {
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
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;
|
||||
}
|
||||
.edit-user-toggles > input[type='checkbox'] {
|
||||
.edit-user-toggles > input[type='checkbox'],
|
||||
.edit-library-toggles > input[type='checkbox'] {
|
||||
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;
|
||||
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;
|
||||
cursor: pointer;
|
||||
}
|
||||
.edit-user-name > input[type='text'] {
|
||||
margin: 0;
|
||||
}
|
||||
.popover {
|
||||
z-index: 2;
|
||||
}
|
||||
.popover .popover-content {
|
||||
color: #000;
|
||||
}
|
||||
.noTransition
|
||||
{
|
||||
-moz-transition: none !important;
|
||||
@@ -2374,7 +2485,10 @@ a .home-platforms-instance-list-oval:hover,
|
||||
top: 5px;
|
||||
left: 12px;
|
||||
}
|
||||
#users-to-delete > li {
|
||||
#users-to-delete > li,
|
||||
#users-to-purge > li,
|
||||
#libraries-to-delete > li,
|
||||
#libraries-to-purge > li {
|
||||
color: #e9a049;
|
||||
}
|
||||
#updatebar {
|
||||
@@ -2424,9 +2538,8 @@ a .home-platforms-instance-list-oval:hover,
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 15px;
|
||||
@@ -2452,12 +2565,19 @@ a .home-platforms-instance-list-oval:hover,
|
||||
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 {
|
||||
display: none;
|
||||
}
|
||||
table.display tr.shown + tr > td {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
table.display tr.shown + tr:hover {
|
||||
background-color: rgba(255,255,255,0);
|
||||
@@ -2468,7 +2588,9 @@ table.display tr.shown + tr .pagination > .active > a,
|
||||
table.display tr.shown + tr .pagination > .active > a:hover {
|
||||
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;
|
||||
}
|
||||
table.display tr.shown + tr .pagination > .disabled > a {
|
||||
@@ -2479,21 +2601,29 @@ table.display tr.shown + tr .pagination > li > a:hover {
|
||||
}
|
||||
table[id^='history_child'] {
|
||||
margin-top: 0;
|
||||
margin-left: -4px;
|
||||
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;
|
||||
height: 0 !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
table[id^='media_info_child'] table[id^='media_info_child'] thead th {
|
||||
line-height: 25px;
|
||||
height: 35px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
#search_form {
|
||||
width: 350px;
|
||||
width: 300px;
|
||||
padding: 8px 15px;
|
||||
}
|
||||
#search_form span.input-textbox {
|
||||
overflow: hidden;
|
||||
width: 250px;
|
||||
width: 200px;
|
||||
height: 34px;
|
||||
display: inline-flex;
|
||||
float: right;
|
||||
@@ -2504,11 +2634,11 @@ table[id^='history_child'] thead th {
|
||||
margin-top: 0;
|
||||
float: right;
|
||||
position: relative;
|
||||
right: -250px;
|
||||
right: -200px;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
#search_form #query.active {
|
||||
width: 250px;
|
||||
width: 200px;
|
||||
right: 0px;
|
||||
}
|
||||
#search_form #search_button.btn-inactive {
|
||||
@@ -2519,4 +2649,144 @@ table[id^='history_child'] thead th {
|
||||
-ms-transition: background 0.3s;
|
||||
-o-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 {
|
||||
width: 100%;
|
||||
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.time-options td:first-child {
|
||||
padding-left: 10px;
|
||||
width: 125px;
|
||||
}
|
||||
.notification-params.time-options td:nth-child(2) {
|
||||
padding-left: 10px;
|
||||
width: 275px;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.small-muted {
|
||||
font-size: small;
|
||||
color: #777;
|
||||
}
|
||||
.config-info-table,
|
||||
.config-scheduler-table {
|
||||
width: 100%
|
||||
}
|
||||
.config-info-table td,
|
||||
.config-info-table th,
|
||||
.config-scheduler-table td,
|
||||
.config-scheduler-table th {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.config-info-table td:first-child {
|
||||
width: 150px;
|
||||
}
|
||||
.config-scheduler-table td:first-child {
|
||||
width: 225px;
|
||||
}
|
||||
.config-scheduler-table th {
|
||||
color: #fff;
|
||||
}
|
||||
a.no-highlight {
|
||||
color: #777;
|
||||
}
|
||||
a.no-highlight:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.top-line {
|
||||
border-top: 1px dotted #777;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.help-bold {
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
.save-button {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.nav-dashboard > li {
|
||||
float: left;
|
||||
}
|
||||
.btn-gray.disabled,
|
||||
.btn-gray.disabled:focus,
|
||||
.btn-gray.disabled:hover,
|
||||
.btn-gray.disabled:active {
|
||||
color: #323232;
|
||||
cursor: default;
|
||||
}
|
||||
.nav-header > li > a:focus,
|
||||
.nav-header > li > a:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
#recently-added-row-scroller,
|
||||
#recently-watched-row-scroller {
|
||||
position: relative;
|
||||
}
|
@@ -69,12 +69,12 @@ DOCUMENTATION :: END
|
||||
% for a in data['sessions']:
|
||||
<div class="dashboard-instance" id="instance-${a['session_key']}">
|
||||
% 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
|
||||
<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>
|
||||
% 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>
|
||||
% 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>
|
||||
@@ -198,6 +198,13 @@ DOCUMENTATION :: END
|
||||
% else:
|
||||
<span>IP: N/A</span>
|
||||
% endif
|
||||
<br />
|
||||
ETA:
|
||||
<span id="stream-eta-${a['session_key']}">
|
||||
<script>
|
||||
$("#stream-eta-${a['session_key']}").html(moment().add(parseInt(${a['duration']}) - parseInt(${a['view_offset']}), 'milliseconds').format(time_format));
|
||||
</script>
|
||||
</span>
|
||||
</div>
|
||||
<div class="dashboard-activity-poster-info-time">
|
||||
<span class="progress_time">${a['view_offset']}</span>/<span class="progress_time">${a['duration']}</span>
|
||||
@@ -210,8 +217,8 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
<div class="dashboard-activity-progress">
|
||||
<div class="dashboard-activity-progress-bar">
|
||||
<div class="bufferbar" style="width: ${a['transcode_progress']}%">${a['transcode_progress']}%</div>
|
||||
<div class="bar" style="width: ${a['progress_percent']}%">${a['progress_percent']}%</div>
|
||||
<div class="bufferbar" style="width: ${a['transcode_progress']}%" data-toggle="tooltip" title="Transcoder Progress">${a['transcode_progress']}%</div>
|
||||
<div class="bar" style="width: ${a['progress_percent']}%" data-toggle="tooltip" title="Stream Progress">${a['progress_percent']}%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dashboard-activity-metadata-wrapper">
|
||||
@@ -227,13 +234,13 @@ DOCUMENTATION :: END
|
||||
<i class="fa fa-spinner"></i>
|
||||
% endif
|
||||
% 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':
|
||||
<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':
|
||||
<span title="${a['title']}">${a['title']}</span>
|
||||
% 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':
|
||||
<span title="${a['parent_title']}">${a['parent_title']}</span>
|
||||
% else:
|
||||
@@ -246,7 +253,7 @@ DOCUMENTATION :: END
|
||||
% elif a['media_type'] == 'movie':
|
||||
<span title="${a['year']}">${a['year']}</span>
|
||||
% 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':
|
||||
<span title="${a['title']}">${a['title']}</span>
|
||||
% else:
|
||||
@@ -254,11 +261,7 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</div>
|
||||
<div class="dashboard-activity-metadata-user">
|
||||
% if a['user_id']:
|
||||
<a href="user?user_id=${a['user_id']}" title="${a['friendly_name']}">${a['friendly_name']}</a>
|
||||
% else:
|
||||
<a href="user?user=${a['user']}" title="${a['friendly_name']}">${a['friendly_name']}</a>
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -280,6 +283,15 @@ DOCUMENTATION :: END
|
||||
e.preventDefault();
|
||||
$($(this).attr('data-target')).toggle();
|
||||
});
|
||||
|
||||
// Add hover class to dashboard-instance
|
||||
$('.dashboard-activity-poster, .dashboard-activity-progress-bar').hover(function() {
|
||||
$(this).closest('.dashboard-instance').addClass('hover');
|
||||
}, function() {
|
||||
$(this).closest('.dashboard-instance').removeClass('hover');
|
||||
});
|
||||
|
||||
$('.bar, .bufferbar').tooltip({container: 'body', placement: 'right', delay: 50});
|
||||
</script>
|
||||
% else:
|
||||
<div class="text-muted">Nothing is currently being watched.</div><br>
|
||||
|
@@ -15,11 +15,13 @@ DOCUMENTATION :: END
|
||||
</%doc>
|
||||
|
||||
% if data != None:
|
||||
% if data == '0':
|
||||
<h3>Activity</h3>
|
||||
% if data == '0':
|
||||
<h3>Activity</h3>
|
||||
% elif data == '1':
|
||||
<h3>Activity <small>${data} stream</small></h3>
|
||||
% else:
|
||||
<h3>Activity <small>${data} streams</small></h3>
|
||||
% endif
|
||||
% else:
|
||||
<h3>Activity <small>${data} stream(s)</small></h3>
|
||||
<h3>Activity</h3>
|
||||
% endif
|
||||
% else:
|
||||
<h3>Activity</h3>
|
||||
% endif
|
179
data/interfaces/default/edit_library.html
Normal 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
|
@@ -10,21 +10,30 @@ Variable names: data [list]
|
||||
data :: Usable parameters
|
||||
|
||||
== Global keys ==
|
||||
user Return the real Plex username
|
||||
user_id Return the Plex user_id
|
||||
friendly_name Returns the friendly edited Plex username
|
||||
do_notify Returns bool value for whether the user should trigger notifications
|
||||
keep_history Returns bool value for whether the user's activity should be logged
|
||||
user_id Returns the user id of the user.
|
||||
username Returns the user's username.
|
||||
friendly_name Returns the friendly name of the user.
|
||||
email Returns the user's email address.
|
||||
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
|
||||
</%doc>
|
||||
|
||||
% if data is not None:
|
||||
<%!
|
||||
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 user <strong>${data['user']}</strong></h4>
|
||||
<h4 class="modal-title">Edit user <strong>${data['username']}</strong></h4>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-text">
|
||||
<fieldset>
|
||||
@@ -41,22 +50,22 @@ DOCUMENTATION :: END
|
||||
<label for="profile_url">Profile Picture URL</label>
|
||||
<div class="row">
|
||||
<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>
|
||||
<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 class="checkbox">
|
||||
<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>
|
||||
<p class="help-block">Uncheck this if you do not want to receive notifications for this user's activity.</p>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<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>
|
||||
<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>
|
||||
% if data['user_id']:
|
||||
<div class="form-group">
|
||||
@@ -69,7 +78,7 @@ DOCUMENTATION :: END
|
||||
<div class="modal-footer">
|
||||
<div>
|
||||
<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>
|
||||
@@ -93,10 +102,10 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// Set new friendly name
|
||||
$("#save_user_name").click(function() {
|
||||
// Set user options
|
||||
$("#save_user").on('click', function () {
|
||||
var friendly_name = $("#friendly_name").val();
|
||||
var thumb = $("#profile_url").val();
|
||||
var custom_thumb = $("#custom_avatar_url").val();
|
||||
var do_notify = 0;
|
||||
var keep_history = 0;
|
||||
if ($("#do_notify").is(":checked")) {
|
||||
@@ -106,35 +115,21 @@ DOCUMENTATION :: END
|
||||
keep_history = 1;
|
||||
}
|
||||
|
||||
% if data['user_id']:
|
||||
$.ajax({
|
||||
url: 'edit_user',
|
||||
data: {user_id: '${data['user_id']}', 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);
|
||||
}
|
||||
});
|
||||
% 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
|
||||
$.ajax({
|
||||
url: 'edit_user',
|
||||
data: {
|
||||
user_id: '${data["user_id"]}',
|
||||
friendly_name: friendly_name,
|
||||
custom_thumb: custom_thumb,
|
||||
do_notify: do_notify,
|
||||
keep_history: keep_history
|
||||
},
|
||||
cache: false,
|
||||
async: true,
|
||||
success: function(data) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#delete-all-history").on('click', function() {
|
||||
@@ -142,7 +137,7 @@ DOCUMENTATION :: END
|
||||
$('#confirm-modal').one('click', '#confirm-purge', function () {
|
||||
$.ajax({
|
||||
url: 'delete_all_user_history',
|
||||
data: {user_id: '${data['user_id']}'},
|
||||
data: { user_id: '${data["user_id"]}' },
|
||||
cache: false,
|
||||
async: true,
|
||||
success: function(data) {
|
||||
@@ -155,7 +150,8 @@ DOCUMENTATION :: END
|
||||
$(document).ready(function() {
|
||||
// Move #confirm-modal to parent container
|
||||
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').css('z-index', '1050');
|
||||
@@ -179,5 +175,4 @@ DOCUMENTATION :: END
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
% endif
|
@@ -13,110 +13,132 @@
|
||||
</div>
|
||||
<div class="button-bar hidden-xs">
|
||||
<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">
|
||||
<input type="radio" name="yaxis-options" id="yaxis-count" value="plays" autocomplete="off" checked> Play Count
|
||||
</label>
|
||||
<label class="btn btn-dark">
|
||||
<input type="radio" name="yaxis-options" id="yaxis-duration" value="duration" autocomplete="off"> Play Duration
|
||||
</label>
|
||||
% endif
|
||||
</div>
|
||||
<div class="btn-group" data-toggle="buttons" id="days-selection">
|
||||
<label class="btn btn-dark">
|
||||
<input type="radio" name="date-options" id="graph-7" value="7" autocomplete="off"> 7 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
|
||||
<div class="btn-group" id="days-selection">
|
||||
<label>
|
||||
<input type="number" name="graph-days" id="graph-days" value="${config['graph_days']}" min="1" /> days
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
<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"><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>
|
||||
% endif
|
||||
</ul>
|
||||
<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 class="row">
|
||||
<div class="col-md-12">
|
||||
<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>
|
||||
<p class="help-block">
|
||||
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.
|
||||
</p>
|
||||
<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>
|
||||
% else:
|
||||
<div role="tabpanel" class="tab-pane" id="tabs-1">
|
||||
% endif
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<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>
|
||||
<p class="help-block">
|
||||
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.
|
||||
</p>
|
||||
<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 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">
|
||||
% endif
|
||||
<div class="row">
|
||||
<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>
|
||||
@@ -189,7 +211,11 @@
|
||||
</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">
|
||||
% endif
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h4><i class="fa fa-calendar"></i> Plays by Month <small>Last 12 months</small></h4>
|
||||
@@ -223,7 +249,7 @@
|
||||
|
||||
<script>
|
||||
// Modal popup dialog
|
||||
function selectHandler(selectedDate) {
|
||||
function selectHandler(selectedDate, selectedSeries) {
|
||||
|
||||
try
|
||||
{
|
||||
@@ -233,10 +259,25 @@
|
||||
var y = dateValue.getFullYear();
|
||||
var dateString = '' + y + '-' + (m<=9 ? '0' + m : m) + '-' + (d <= 9 ? '0' + d : d);
|
||||
|
||||
var media_type = 'all';
|
||||
var transcode_decision = null;
|
||||
switch(selectedSeries) {
|
||||
case "TV": media_type = 'episode'; break;
|
||||
case "Movies": media_type = 'movie'; break;
|
||||
case "Music": media_type = 'track'; break;
|
||||
case "Direct Play": transcode_decision = 'direct play'; break;
|
||||
case "Direct Stream": transcode_decision = 'copy'; break;
|
||||
case "Transcode": transcode_decision = 'transcode'; break;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
"url": "history_table_modal",
|
||||
url: "history_table_modal",
|
||||
type: 'post',
|
||||
data: { 'start_date': dateString },
|
||||
data: {
|
||||
start_date: dateString,
|
||||
media_type: media_type,
|
||||
transcode_decision: transcode_decision
|
||||
},
|
||||
complete: function(xhr, status) {
|
||||
$('#history-modal').modal('show');
|
||||
$("#history-modal").html(xhr.responseText);
|
||||
@@ -245,7 +286,7 @@
|
||||
}
|
||||
catch(err)
|
||||
{
|
||||
console.log("Failed to retrieve data");
|
||||
console.log("Failed to retrieve history modal data.");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -263,40 +304,18 @@
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
|
||||
// Save graph state to cookies
|
||||
$('input[name=yaxis-options]').change(function() {
|
||||
setCookie('graphType', $(this).val(), 365, '/');
|
||||
});
|
||||
$('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 from config
|
||||
var yaxis = "${config['graph_type']}";
|
||||
var current_range = ${config['graph_days']};
|
||||
var current_tab = "${'#' + config['graph_tab']}";
|
||||
|
||||
// Initial values for graph if no saved state
|
||||
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');
|
||||
}
|
||||
$('.days').html(current_range);
|
||||
|
||||
var music_visible = (${config['music_logging_enable']} == 1 ? true : false);
|
||||
|
||||
function loadGraphsTab1(time_range, yaxis) {
|
||||
$('#days-selection').show();
|
||||
|
||||
setGraphFormat(yaxis);
|
||||
|
||||
$.ajax({
|
||||
@@ -380,6 +399,8 @@
|
||||
}
|
||||
|
||||
function loadGraphsTab2(time_range, yaxis) {
|
||||
$('#days-selection').show();
|
||||
|
||||
setGraphFormat(yaxis);
|
||||
|
||||
$.ajax({
|
||||
@@ -458,6 +479,8 @@
|
||||
}
|
||||
|
||||
function loadGraphsTab3(yaxis) {
|
||||
$('#days-selection').hide();
|
||||
|
||||
setGraphFormat(yaxis);
|
||||
|
||||
$.ajax({
|
||||
@@ -476,40 +499,61 @@
|
||||
}
|
||||
|
||||
// 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
|
||||
$('#graph-tabs a[href="#tabs-1"]').on('shown.bs.tab', function (e) {
|
||||
e.preventDefault();
|
||||
current_tab = $(this).attr('href');
|
||||
$('#days-selection').show();
|
||||
loadGraphsTab1(current_range, yaxis);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_tab: current_tab.replace('#','') },
|
||||
async: true
|
||||
});
|
||||
})
|
||||
|
||||
// Tab2 opened
|
||||
$('#graph-tabs a[href="#tabs-2"]').on('shown.bs.tab', function (e) {
|
||||
e.preventDefault();
|
||||
current_tab = $(this).attr('href');
|
||||
$('#days-selection').show();
|
||||
loadGraphsTab2(current_range, yaxis);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_tab: current_tab.replace('#','') },
|
||||
async: true
|
||||
});
|
||||
})
|
||||
|
||||
// Tab3 opened
|
||||
$('#graph-tabs a[href="#tabs-3"]').on('shown.bs.tab', function (e) {
|
||||
e.preventDefault();
|
||||
current_tab = $(this).attr('href');
|
||||
$('#days-selection').hide();
|
||||
console.log('loading....');
|
||||
loadGraphsTab3(yaxis);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_tab: current_tab.replace('#','') },
|
||||
async: true
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
// Date range changed
|
||||
$('#days-selection').on('change', function() {
|
||||
current_range = $('input[name=date-options]:checked', '#days-selection').val();
|
||||
$('#graph-days').on('change', function() {
|
||||
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-2') { loadGraphsTab2(current_range, yaxis); }
|
||||
$('.days').html(current_range);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_days: current_range},
|
||||
async: true
|
||||
});
|
||||
});
|
||||
|
||||
// Y-axis changed
|
||||
@@ -518,6 +562,11 @@
|
||||
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); }
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_type: yaxis},
|
||||
async: true
|
||||
});
|
||||
});
|
||||
|
||||
function setGraphFormat(type) {
|
||||
|
@@ -22,21 +22,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
<table class="display" id="history_table" width="100%">
|
||||
<table class="display history_table" id="history_table" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align='left' id="delete_row">Delete</th>
|
||||
<th align='left' id="time">Time</th>
|
||||
<th align='left' id="friendly_name">User</th>
|
||||
<th align='left' id="ip_address">IP Address</th>
|
||||
<th align='left' id="platform">Platform</th>
|
||||
<th align='left' id="device">Player</th>
|
||||
<th align='left' id="title">Title</th>
|
||||
<th align='left' id="started">Started</th>
|
||||
<th align='left' id="paused_counter">Paused</th>
|
||||
<th align='left' id="stopped">Stopped</th>
|
||||
<th align='left' id="duration">Duration</th>
|
||||
<th align='left' id="percent_complete"></th>
|
||||
<th align="left" id="delete_row">Delete</th>
|
||||
<th align="left" id="time">Time</th>
|
||||
<th align="left" id="friendly_name">User</th>
|
||||
<th align="left" id="ip_address">IP Address</th>
|
||||
<th align="left" id="platform">Platform</th>
|
||||
<th align="left" id="device">Player</th>
|
||||
<th align="left" id="title">Title</th>
|
||||
<th align="left" id="started">Started</th>
|
||||
<th align="left" id="paused_counter">Paused</th>
|
||||
<th align="left" id="stopped">Stopped</th>
|
||||
<th align="left" id="duration">Duration</th>
|
||||
<th align="left" id="percent_complete"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -83,8 +83,8 @@
|
||||
type: 'post',
|
||||
data: function (d) {
|
||||
return {
|
||||
'json_data': JSON.stringify(d),
|
||||
'media_type': media_type
|
||||
json_data: JSON.stringify(d),
|
||||
media_type: media_type
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -5,19 +5,19 @@
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
||||
<h4 class="modal-title" id="myModalLabel">
|
||||
<strong><span id="modal_header_ip_address">
|
||||
<i class="fa fa-history"></i> History for <span id="date-header">${data}</span>
|
||||
<i class="fa fa-history"></i> History for <span id="date-header">${data['start_date']}</span>
|
||||
</span></strong>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-text">
|
||||
<table class="display" id="history_table" width="100%">
|
||||
<table class="display history_table" id="history_table_modal" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align='left' id="started">Started</th>
|
||||
<th align='left' id="stopped">Stopped</th>
|
||||
<th align='left' id="friendly_name">User</th>
|
||||
<th align='left' id="player">Player</th>
|
||||
<th align='left' id="title">Title</th>
|
||||
<th align="left" id="started">Started</th>
|
||||
<th align="left" id="stopped">Stopped</th>
|
||||
<th align="left" id="friendly_name">User</th>
|
||||
<th align="left" id="player">Player</th>
|
||||
<th align="left" id="title">Title</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -32,21 +32,24 @@
|
||||
<script src="interfaces/default/js/tables/history_table_modal.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#date-header').html(moment('${data}','YYYY-MM-DD').format('ddd MMM Do YYYY'));
|
||||
$('#date-header').html(moment('${data["start_date"]}','YYYY-MM-DD').format('ddd MMM Do YYYY'));
|
||||
history_table_modal_options.ajax = {
|
||||
"url": "get_history",
|
||||
type: "post",
|
||||
url: 'get_history',
|
||||
type: 'post',
|
||||
data: function ( d ) {
|
||||
return { 'json_data': JSON.stringify( d ),
|
||||
'grouping': false,
|
||||
'start_date': '${data}'
|
||||
};
|
||||
return {
|
||||
json_data: JSON.stringify(d),
|
||||
grouping: false,
|
||||
start_date: "${data['start_date']}",
|
||||
media_type: "${data.get('media_type')}",
|
||||
transcode_decision: "${data.get('transcode_decision')}"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
history_table = $('#history_table').DataTable(history_table_modal_options);
|
||||
history_table = $('#history_table_modal').DataTable(history_table_modal_options);
|
||||
|
||||
clearSearchButton('history_table', history_table);
|
||||
clearSearchButton('history_table_modal', history_table);
|
||||
|
||||
// Move #info-modal to parent container
|
||||
if (!($('#history-modal').next().is('#info-modal'))) {
|
||||
|
@@ -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.
|
||||
|
||||
== 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' ==
|
||||
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
|
||||
</%doc>
|
||||
|
||||
@@ -65,8 +70,8 @@ DOCUMENTATION :: END
|
||||
%>
|
||||
|
||||
% if data:
|
||||
% if data[0]['stat_id']:
|
||||
<ul class="list-unstyled">
|
||||
% if any(top_stat['rows'] for top_stat in data):
|
||||
% for top_stat in data:
|
||||
% if top_stat['stat_id'] == 'top_tv' and top_stat['rows']:
|
||||
<div class="home-platforms-instance">
|
||||
@@ -77,7 +82,7 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
<div class="home-platforms-instance-playcount">
|
||||
<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']}
|
||||
</a>
|
||||
</h4>
|
||||
@@ -89,7 +94,7 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</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']:
|
||||
<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>
|
||||
@@ -100,18 +105,18 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<div class="home-platforms-instance-list-name">
|
||||
<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']}
|
||||
</a>
|
||||
</h5>
|
||||
@@ -125,7 +130,7 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</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']:
|
||||
<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>
|
||||
@@ -157,7 +162,7 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
<div class="home-platforms-instance-playcount">
|
||||
<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']}
|
||||
</a>
|
||||
</h4>
|
||||
@@ -165,7 +170,7 @@ DOCUMENTATION :: END
|
||||
<p> users</p>
|
||||
</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'] != '':
|
||||
<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>
|
||||
@@ -176,18 +181,18 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<div class="home-platforms-instance-list-name">
|
||||
<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']}
|
||||
</a>
|
||||
</h5>
|
||||
@@ -197,7 +202,7 @@ DOCUMENTATION :: END
|
||||
<p> users</p>
|
||||
</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']:
|
||||
<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>
|
||||
@@ -229,7 +234,7 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
<div class="home-platforms-instance-playcount">
|
||||
<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']}
|
||||
</a>
|
||||
</h4>
|
||||
@@ -241,7 +246,7 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</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']:
|
||||
<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>
|
||||
@@ -252,18 +257,18 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<div class="home-platforms-instance-list-name">
|
||||
<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']}
|
||||
</a>
|
||||
</h5>
|
||||
@@ -277,7 +282,7 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</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']:
|
||||
<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>
|
||||
@@ -309,7 +314,7 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
<div class="home-platforms-instance-playcount">
|
||||
<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']}
|
||||
</a>
|
||||
</h4>
|
||||
@@ -317,7 +322,7 @@ DOCUMENTATION :: END
|
||||
<p> users</p>
|
||||
</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']:
|
||||
<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>
|
||||
@@ -328,18 +333,18 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<div class="home-platforms-instance-list-name">
|
||||
<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']}
|
||||
</a>
|
||||
</h5>
|
||||
@@ -349,7 +354,7 @@ DOCUMENTATION :: END
|
||||
<p> users</p>
|
||||
</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']:
|
||||
<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>
|
||||
@@ -381,7 +386,7 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
<div class="home-platforms-instance-playcount">
|
||||
<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']}
|
||||
</a>
|
||||
</h4>
|
||||
@@ -393,7 +398,7 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</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']:
|
||||
<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>
|
||||
@@ -404,18 +409,18 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<div class="home-platforms-instance-list-name">
|
||||
<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']}
|
||||
</a>
|
||||
</h5>
|
||||
@@ -429,7 +434,7 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</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']:
|
||||
<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>
|
||||
@@ -461,7 +466,7 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
<div class="home-platforms-instance-playcount">
|
||||
<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']}
|
||||
</a>
|
||||
</h4>
|
||||
@@ -469,7 +474,7 @@ DOCUMENTATION :: END
|
||||
<p> users</p>
|
||||
</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'] != '':
|
||||
<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>
|
||||
@@ -480,18 +485,18 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<div class="home-platforms-instance-list-name">
|
||||
<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']}
|
||||
</a>
|
||||
</h5>
|
||||
@@ -501,7 +506,7 @@ DOCUMENTATION :: END
|
||||
<p> users</p>
|
||||
</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']:
|
||||
<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>
|
||||
@@ -564,13 +569,13 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<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']}') + ");'>");
|
||||
</script>
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<div class="home-platforms-instance-list-name">
|
||||
@@ -691,7 +696,7 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
<div class="home-platforms-instance-last-user">
|
||||
<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']}
|
||||
</a>
|
||||
</h4>
|
||||
@@ -709,11 +714,11 @@ DOCUMENTATION :: END
|
||||
<script>
|
||||
$('#last-watch-stat').text(moment(${top_stat['rows'][0]['last_watch']},"X").format(date_format));
|
||||
</script>
|
||||
</span> - ${top_stat['rows'][0]['platform_type']}
|
||||
</span> - ${top_stat['rows'][0]['player']}
|
||||
</p>
|
||||
</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']:
|
||||
<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>
|
||||
@@ -724,18 +729,18 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
</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>
|
||||
<ul class="list-unstyled">
|
||||
<div class="slider">
|
||||
<div class="home-platforms-instance-list">
|
||||
% for row in top_stat['rows']:
|
||||
%if loop.index > 0:
|
||||
% if loop.index > 0:
|
||||
<li>
|
||||
<div class="home-platforms-instance-list-info">
|
||||
<div class="home-platforms-instance-list-name">
|
||||
<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']}
|
||||
</a>
|
||||
</h5>
|
||||
@@ -755,17 +760,17 @@ DOCUMENTATION :: END
|
||||
<script>
|
||||
$('#home-platforms-instance-list-last-watch-${loop.index + 1}').text(moment(${top_stat['rows'][loop.index]['last_watch']},"X").format(date_format));
|
||||
</script>
|
||||
</span> - ${top_stat['rows'][loop.index]['platform_type']}
|
||||
</span> - ${top_stat['rows'][loop.index]['player']}
|
||||
</p>
|
||||
</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']:
|
||||
<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>
|
||||
% 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>
|
||||
% endif
|
||||
@@ -782,8 +787,74 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
</li>
|
||||
</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
|
||||
% endfor
|
||||
% else:
|
||||
<div class="text-muted">No stats to show for the selected period.</div><br>
|
||||
% endif
|
||||
</ul>
|
||||
<script>
|
||||
var topZIndex = 2;
|
||||
@@ -799,9 +870,5 @@ DOCUMENTATION :: END
|
||||
});
|
||||
</script>
|
||||
% else:
|
||||
<div class="text-muted">No stats for 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>
|
||||
<div class="text-muted">No stats to show for the selected period.</div><br>
|
||||
% endif
|
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 66 KiB |
BIN
data/interfaces/default/images/home-stat_most-concurrent.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
data/interfaces/default/images/media_flags/aspect_ratio/1.33.png
Normal file
After Width: | Height: | Size: 926 B |
BIN
data/interfaces/default/images/media_flags/aspect_ratio/1.66.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
data/interfaces/default/images/media_flags/aspect_ratio/1.78.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
data/interfaces/default/images/media_flags/aspect_ratio/1.85.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
data/interfaces/default/images/media_flags/aspect_ratio/2.20.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
data/interfaces/default/images/media_flags/aspect_ratio/2.25.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
data/interfaces/default/images/media_flags/aspect_ratio/2.35.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
data/interfaces/default/images/media_flags/audio_channels/1.png
Normal file
After Width: | Height: | Size: 662 B |
BIN
data/interfaces/default/images/media_flags/audio_channels/2.png
Normal file
After Width: | Height: | Size: 873 B |
BIN
data/interfaces/default/images/media_flags/audio_channels/5.png
Normal file
After Width: | Height: | Size: 671 B |
BIN
data/interfaces/default/images/media_flags/audio_channels/6.png
Normal file
After Width: | Height: | Size: 671 B |
BIN
data/interfaces/default/images/media_flags/audio_channels/7.png
Normal file
After Width: | Height: | Size: 757 B |
BIN
data/interfaces/default/images/media_flags/audio_channels/8.png
Normal file
After Width: | Height: | Size: 527 B |
BIN
data/interfaces/default/images/media_flags/audio_codec/aac.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/aif.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/aifc.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/aiff.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/alac.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/ape.png
Normal file
After Width: | Height: | Size: 523 B |
BIN
data/interfaces/default/images/media_flags/audio_codec/cdda.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.5 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/dts.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/eac3.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/flac.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/m4a.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/mlp.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/mp2.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/mp3.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/mpc.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/ogg.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/pcm.png
Normal file
After Width: | Height: | Size: 827 B |
BIN
data/interfaces/default/images/media_flags/audio_codec/ra.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/shn.png
Normal file
After Width: | Height: | Size: 270 B |
BIN
data/interfaces/default/images/media_flags/audio_codec/wav.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/wave.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/wma.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/wmahd.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 778 B |
BIN
data/interfaces/default/images/media_flags/audio_codec/wmav2.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
data/interfaces/default/images/media_flags/audio_codec/wv.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
data/interfaces/default/images/media_flags/content_rating/G.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 2.0 KiB |
BIN
data/interfaces/default/images/media_flags/content_rating/NR.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 2.2 KiB |
BIN
data/interfaces/default/images/media_flags/content_rating/PG.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
data/interfaces/default/images/media_flags/content_rating/R.png
Normal file
After Width: | Height: | Size: 928 B |
After Width: | Height: | Size: 931 B |
After Width: | Height: | Size: 1017 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 821 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
BIN
data/interfaces/default/images/media_flags/content_rating/X.png
Normal file
After Width: | Height: | Size: 990 B |
After Width: | Height: | Size: 539 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.4 KiB |