Compare commits

...

457 Commits

Author SHA1 Message Date
JonnyWong16
e908c45cf2 v2.0.4-beta 2017-12-29 16:35:24 -08:00
JonnyWong16
c37e934f42 Check concurrent streams from the server instead of database 2017-12-29 16:29:20 -08:00
JonnyWong16
41f91956b8 Make sure current activity is loaded before refreshing 2017-12-29 16:26:50 -08:00
JonnyWong16
8b2bd5ce79 Add collections info pages 2017-12-29 15:52:08 -08:00
JonnyWong16
28e4151157 Remember tab when going back on library and user pages 2017-12-29 11:34:41 -08:00
JonnyWong16
66d45293e6 Add test Plex Web URL button 2017-12-29 10:47:31 -08:00
JonnyWong16
243eeeff67 v2.0.3-beta 2017-12-25 09:58:24 -08:00
JonnyWong16
18520e24d1 Report correct release version on beta 2017-12-25 09:48:33 -08:00
JonnyWong16
87743171b7 Fix write session history optimized_version_title column name 2017-12-25 09:07:02 -08:00
JonnyWong16
452f0747c8 Add missing stream info modal css 2017-12-25 09:02:33 -08:00
JonnyWong16
a20747044c Fix sync ID 2017-12-25 09:00:42 -08:00
JonnyWong16
e60241ca73 v2.0.2-beta 2017-12-24 13:53:49 -08:00
JonnyWong16
c69e68a4a8 Alias media info title to sort title 2017-12-24 11:29:12 -08:00
JonnyWong16
561d994328 Fix config version updgrade 2017-12-24 07:52:11 -08:00
JonnyWong16
33acf9402d Improved synced and optimized version info 2017-12-23 11:52:28 -08:00
JonnyWong16
0a42cb4135 Update stream info modal 2017-12-22 22:04:40 -08:00
JonnyWong16
19695c220b Fix some missing subtitle database columns 2017-12-22 19:55:21 -08:00
JonnyWong16
1fbc0165e6 Fix source video/audio/subtitle parameters in notifications 2017-12-22 14:22:37 -08:00
JonnyWong16
4dd05e217a Add back HTTP Proxy setting 2017-12-22 13:01:25 -08:00
JonnyWong16
b77a409414 Add sort title to metadata, sort media info tables by sort title 2017-12-22 12:40:58 -08:00
JonnyWong16
b2157df026 Default blank session value when writing session history 2017-12-22 11:47:28 -08:00
JonnyWong16
0b8d5954f9 Fix librariaes page 2017-12-22 10:30:45 -08:00
JonnyWong16
0d60c7b728 Remove unused logos 2017-12-21 15:30:24 -08:00
JonnyWong16
de58136314 Do not send recently added notification if item updated more than 24 hours ago 2017-12-21 15:22:18 -08:00
JonnyWong16
4e718056b6 Remove bif thumbnail setting 2017-12-21 11:23:27 -08:00
JonnyWong16
480913362e Fix default setup wizard settings 2017-12-21 11:23:11 -08:00
JonnyWong16
ad2f61132a Change logos to svgs 2017-12-21 10:49:14 -08:00
JonnyWong16
0e2df4ba14 Add note to enable 3rd party APIs for link lookup 2017-12-21 10:47:32 -08:00
JonnyWong16
c342273742 Retrieve session by session key 2017-12-19 22:20:24 -08:00
JonnyWong16
0cb147cd8f Cleanup safari-pinned-tab svg 2017-12-19 21:49:09 -08:00
JonnyWong16
11b2a17fb3 Fix white in logo text 2017-12-19 21:36:11 -08:00
JonnyWong16
23486ff235 Update favicons 2017-12-19 21:29:07 -08:00
JonnyWong16
a9e24bc0c5 Remove update section ids 2017-12-19 20:36:24 -08:00
JonnyWong16
3c22496ea2 Fix some platform mappings 2017-12-19 20:28:40 -08:00
JonnyWong16
b8164ca556 Validate condition logic on save 2017-12-19 17:32:37 -08:00
JonnyWong16
19565b3d0a Add message to verify server for error communicating 2017-12-19 17:27:20 -08:00
JonnyWong16
50ce17ac72 Fix missing users table cache parameter 2017-12-19 16:40:45 -08:00
JonnyWong16
e51a425389 API enabled by default 2017-12-19 11:47:59 -08:00
JonnyWong16
3df7642193 Missing save button in settings 2017-12-19 11:21:07 -08:00
JonnyWong16
38ad9c9893 v2.0.1-beta 2017-12-19 10:56:25 -08:00
JonnyWong16
fb75b9566f Temporarily disable browser notifications 2017-12-19 10:33:42 -08:00
JonnyWong16
80a6118bf9 Fix music stats background fallback 2017-12-19 09:42:11 -08:00
JonnyWong16
6b2bc0108b Fix Join apikey 2017-12-18 23:09:50 -08:00
JonnyWong16
bd07cf5a04 Missing video_height database column 2017-12-18 13:51:14 -08:00
JonnyWong16
f07ad960dc Merge branch 'v2' into nightly 2017-12-17 23:21:31 -08:00
JonnyWong16
824e975598 v2.0.0-beta 2017-12-17 23:17:44 -08:00
JonnyWong16
4f44c64e4a Switch to master/beta/nightly branches 2017-12-17 23:13:15 -08:00
JonnyWong16
a449670667 Some more first run fixes 2017-12-17 23:12:56 -08:00
JonnyWong16
7cd38581a6 Fix duplicate database column video_width 2017-12-17 22:52:38 -08:00
JonnyWong16
507ecee2e3 Update links in readme 2017-12-16 13:32:02 -08:00
JonnyWong16
95a6c62dd9 Fix clipped shadow in logos 2017-12-16 12:52:33 -08:00
JonnyWong16
b8c1fef700 Add Tautulli text logo 2017-12-16 12:52:33 -08:00
JonnyWong16
7a8301a8dc Update git repo links 2017-12-16 12:52:33 -08:00
JonnyWong16
19f029cff0 Rename PlexPy to Tautulli 2017-12-16 12:52:33 -08:00
JonnyWong16
55bdde808b Update all Tautulli image assets 2017-12-16 12:47:05 -08:00
JonnyWong16
abab2f3f6b Update setup wizard 2017-12-16 12:43:14 -08:00
JonnyWong16
c586fe1d07 Update session database with all session data 2017-12-16 09:08:17 -08:00
JonnyWong16
1b0c32f4e7 Fix logging for subtitles enabled 2017-12-16 09:07:32 -08:00
JonnyWong16
e667f4487f Log new stream info to database 2017-12-14 20:00:33 -08:00
JonnyWong16
507be2e6e3 Remove monitoring interval setting 2017-12-14 19:59:53 -08:00
JonnyWong16
5ff3c433b2 Add missing concurrent streams icon 2017-12-14 06:44:39 -08:00
JonnyWong16
7c825f72aa Add background colour to poster blur 2017-12-13 22:34:12 -08:00
JonnyWong16
36e604dc91 Add blur poster behind cover art 2017-12-13 22:22:27 -08:00
JonnyWong16
b6c5068bc4 Rename svg, add ios, change padding 2017-12-13 21:26:39 -08:00
JonnyWong16
af78f98106 svg icon css background contain 2017-12-13 20:50:26 -08:00
JonnyWong16
b209c29749 Use svg for platform and library icons 2017-12-13 20:48:04 -08:00
JonnyWong16
e28965f8b3 Fix info in terminate stream modal 2017-12-12 22:22:38 -08:00
JonnyWong16
117c228672 Update Plex logs setting help text 2017-12-11 21:30:17 -08:00
JonnyWong16
359273e26e Group library statistic cards by library type 2017-12-11 21:28:26 -08:00
JonnyWong16
b22ae58f79 Updated library cards on the homepage 2017-12-10 20:33:14 -08:00
JonnyWong16
07d8fbb7f4 Reset recently added scoller before refresh 2017-12-10 16:39:10 -08:00
JonnyWong16
9edce2d387 Move 3rd Pary APIs settings 2017-12-10 15:26:32 -08:00
JonnyWong16
1787fff8c3 Update to use Plex hub search 2017-12-09 23:59:25 -08:00
JonnyWong16
1b5e5f37d0 Add option to override Plex Web URL 2017-12-09 23:08:52 -08:00
JonnyWong16
b76143116c Better restart/shutdown refresh page polling 2017-12-09 22:32:39 -08:00
JonnyWong16
20e3eebd6a Add setting for manual server connection 2017-12-09 22:14:43 -08:00
JonnyWong16
f42f1182f2 Reimplement recently added delay to group items 2017-12-09 21:34:41 -08:00
JonnyWong16
7e7609743a Add callback to force stop stale streams 2017-12-09 02:09:14 -08:00
JonnyWong16
a00f36f83b Do not send Plex server down on websocket excpetion 2017-12-09 01:54:43 -08:00
JonnyWong16
e353d0518c Reword QR instructions 2017-12-08 23:02:58 -08:00
JonnyWong16
5efe2be7b2 Fix app parameter in api 2017-12-08 22:29:40 -08:00
JonnyWong16
53d0bef260 Add app parameter to api 2017-12-08 22:26:06 -08:00
JonnyWong16
ecd0a199f1 Add mobile device last seen 2017-12-08 22:05:44 -08:00
JonnyWong16
019787b32d Add mobile device settings 2017-12-08 20:52:55 -08:00
JonnyWong16
1ca1f9975c Product instead of Platform on activity card 2017-12-08 17:46:19 -08:00
JonnyWong16
2d76991a86 Fix watch staistics posters hover title 2017-12-08 10:11:41 -08:00
JonnyWong16
2fee437010 Double check if notificaitons was already sent 2017-12-07 22:11:05 -08:00
JonnyWong16
4e7c91617b Forgot import for 595af9e 2017-12-07 20:59:11 -08:00
JonnyWong16
86e1e99b33 Fix watch statistics poster link 2017-12-07 19:54:59 -08:00
JonnyWong16
595af9e70b Retrieve poster directly from Plex for GroupMe 2017-12-07 19:45:22 -08:00
JonnyWong16
d23c4ef319 Upload from Imgur to Telegram directly 2017-12-07 19:45:03 -08:00
JonnyWong16
1d9d16b69b Rename Plex websocket log 2017-12-02 12:28:38 -08:00
JonnyWong16
a6ee70b7ec Fix typo in Prowl key config 2017-12-02 09:36:31 -08:00
JonnyWong16
7921681fad Try returning unicode request message 2017-12-02 09:01:45 -08:00
JonnyWong16
256ddde07d Add keys and ids to Android app notification payload data 2017-12-02 08:52:06 -08:00
JonnyWong16
e606bd512f Fix missing 'or' in condition for on_stop notifications 2017-12-02 08:51:23 -08:00
JonnyWong16
ffb38ef599 Update blacklist after changing notifier configs 2017-12-01 12:31:27 -08:00
JonnyWong16
f9e7c2bdb6 Fix typo in Pushover config in 9ba6b23 2017-12-01 12:31:09 -08:00
JonnyWong16
76cc61e0c2 Change MQTT client_id to clientid 2017-12-01 12:07:29 -08:00
JonnyWong16
9ba6b230e6 Change logger blacklist to set and unify notifier blacklist keys 2017-12-01 12:00:50 -08:00
JonnyWong16
31f03e0114 Fix unicode error in notification text when using conversion or splice 2017-11-30 21:51:25 -08:00
JonnyWong16
7e7693f206 Better apikey generation 2017-11-30 20:00:44 -08:00
JonnyWong16
6cae12d467 Revert Android App notification encryption to SHA1 2017-11-30 19:47:31 -08:00
JonnyWong16
1235f73332 Fix getting source media info parts 2017-11-11 20:26:17 -08:00
JonnyWong16
75dfb82a88 Rename history table column to "Date" 2017-11-11 19:56:24 -08:00
JonnyWong16
a2eeda64df Add ability to delete synced items 2017-11-11 19:41:51 -08:00
JonnyWong16
718049b9f3 Add custom modifiers to notification text 2017-11-11 18:07:42 -08:00
JonnyWong16
fdff9d7454 Default to 'Unknown' for any missing activity values 2017-11-10 21:13:03 -08:00
JonnyWong16
976418de0f Fallback for failed media info id matching 2017-11-10 20:10:46 -08:00
JonnyWong16
e51e9493b1 Remove stats count setting 2017-11-07 20:30:28 -08:00
JonnyWong16
8535fa4e0a Don't use new library icons 2017-11-07 20:30:03 -08:00
JonnyWong16
16b05a47c0 Manually merge v2-new-icons into v2 2017-11-06 21:28:51 -08:00
JonnyWong16
ff7fee6abf Make sure activity progress cannot exceed 100% 2017-11-06 20:31:46 -08:00
JonnyWong16
7f2e740bc0 Fallback stream duration 2017-11-06 20:22:49 -08:00
JonnyWong16
3df31bb01b Lock scrolling of activity card overflow 2017-11-06 18:09:35 -08:00
JonnyWong16
c6a36cb4cf Add user to recently watched card and date to most concurrent card 2017-11-05 14:51:04 -08:00
JonnyWong16
2873d8bba3 Lock scroller on statistics cards 2017-11-05 13:28:27 -08:00
JonnyWong16
d77696be59 Flexbox activity card metadata 2017-11-05 13:28:10 -08:00
JonnyWong16
1bd2f332d9 Plex for Vizio uses Opera platform 2017-11-05 12:59:20 -08:00
JonnyWong16
e4a2616ffa Prevent password autofill in settings 2017-11-05 12:08:36 -08:00
JonnyWong16
99f93a8d50 Combine activity header into one activity function 2017-11-05 11:06:51 -08:00
JonnyWong16
e80d88c9ff Make sure there are stats before creating the watched statistic cards 2017-11-05 07:35:08 -08:00
JonnyWong16
8d2c9a7764 New watch statistics cards 2017-11-05 00:30:44 -07:00
JonnyWong16
de589f59a1 A bit of CSS cleanup for activity cards 2017-11-04 23:12:05 -07:00
JonnyWong16
627f552976 Fix some channel metadata for activity 2017-11-03 20:31:11 -07:00
JonnyWong16
67bac92849 Add channels to activity 2017-11-03 19:46:41 -07:00
JonnyWong16
e1dc299cba Add identifying playback of synced items 2017-11-02 18:33:18 -07:00
JonnyWong16
3f668ae5c6 Add pseudo progress bar update 2017-11-01 20:11:40 -07:00
JonnyWong16
0d54e9f2d6 Cache css and js based on commit hash or version number 2017-11-01 19:23:14 -07:00
JonnyWong16
ef6ef868e0 Temporary fixes for masked info for guest access 2017-11-01 19:13:54 -07:00
JonnyWong16
5d8da23c3f Add pseudo view offset counter 2017-10-31 23:28:01 -07:00
JonnyWong16
43f285951d Add background to statistic cards 2017-10-30 23:47:24 -07:00
JonnyWong16
7714ecc7dd Fix some background overflow bleeding 2017-10-30 23:46:59 -07:00
JonnyWong16
6a39201961 Ease-in-out trasition for terminate button 2017-10-30 23:09:37 -07:00
JonnyWong16
f0ca7385b9 Move admin CSS to separate file 2017-10-30 23:00:45 -07:00
JonnyWong16
567bba0c44 Sorted raw stream info json 2017-10-29 11:43:49 -07:00
JonnyWong16
7559c0c6f8 Json values are integers not strings 2017-10-29 11:43:38 -07:00
JonnyWong16
58bcd068f2 Fix HW transcoding indicator 2017-10-29 11:23:53 -07:00
JonnyWong16
7047829943 Add hidden raw stream info 2017-10-29 11:13:50 -07:00
JonnyWong16
b6a634ea6f Add media type icon 2017-10-29 10:48:01 -07:00
JonnyWong16
15a871889f Add info icon for bandwidth tooltip 2017-10-29 10:35:37 -07:00
JonnyWong16
9d2cfaa3f5 Toggle terminte session button when hovering over entire card 2017-10-29 10:25:32 -07:00
JonnyWong16
8625d3f127 Fix some incorrect codec info displayed 2017-10-29 10:23:51 -07:00
JonnyWong16
f07a7fa2cf New current activity cards 2017-10-29 02:45:18 -07:00
JonnyWong16
c6a4c4d6b3 Remove websocket require restart message in settings 2017-10-29 00:25:33 -07:00
JonnyWong16
df55f70991 Fix bif thumb for music 2017-10-14 14:38:54 -07:00
JonnyWong16
37951cd69b Manually merge v1.4.25 into v2 2017-10-02 18:14:46 -07:00
JonnyWong16
cfd3099626 v1.4.25 2017-10-02 18:08:23 -07:00
JonnyWong16
3db6c98c27 Fix tab to space 2017-10-02 18:07:16 -07:00
JonnyWong16
3c04b04b98 Make TMDb and TVmaze lookup optional 2017-10-01 12:04:29 -07:00
JonnyWong16
d207d4a508 Add missing Trakt.tv provider name 2017-10-01 11:51:09 -07:00
JonnyWong16
df4e466fdf Manually merge v1.4.24 into v2 2017-10-01 11:19:42 -07:00
JonnyWong16
a6fd7b581f Rename column header to "Total Played Duration" 2017-09-30 23:42:12 -07:00
JonnyWong16
58712a2d05 Add api and websocket to preformatted log reader 2017-09-30 23:39:00 -07:00
JonnyWong16
39da58d3bc Log failed login attempts 2017-09-30 23:34:46 -07:00
JonnyWong16
daec864f50 Manually merge v1.4.23 into v2 2017-09-30 16:47:26 -07:00
JonnyWong16
54cd860c13 Separate API and websocket logging 2017-09-30 16:42:25 -07:00
JonnyWong16
fe210646c3 Use player product name if no title 2017-09-30 16:41:29 -07:00
JonnyWong16
3c1d0d3128 Reset button state after modal shown on info page 2017-09-30 11:00:24 -07:00
JonnyWong16
5d2f1d7014 Select notification agent for manual recently aded notifications
* And add to API
2017-09-30 10:46:08 -07:00
JonnyWong16
a17c3f8138 Return empty dict if tvmaze/themoviedb lookup fails 2017-09-28 19:59:54 -07:00
JonnyWong16
45f002a797 Add manual trigger for recently added notifications from the info page 2017-09-26 22:21:04 -07:00
JonnyWong16
4a16ee6865 Update web interface settings help text 2017-09-26 21:03:11 -07:00
JonnyWong16
76e9e24c41 Simpler http root check when starting webserver 2017-09-26 20:58:20 -07:00
JonnyWong16
92a3589588 Check for / in http root setting 2017-09-26 20:52:03 -07:00
JonnyWong16
1e10ddec99 Move modals to template includes on history page 2017-09-26 20:27:15 -07:00
JonnyWong16
ad827e62f6 Fix typo from cd007ee
* Also better https replace for Imgur urls
2017-09-18 19:42:28 -07:00
JonnyWong16
6dd7e8445a Add default values for session bandwidth and location 2017-09-13 18:54:03 -07:00
JonnyWong16
9364e5ab91 Add purge to user delete message 2017-09-13 18:52:46 -07:00
JonnyWong16
9a48383eb4 Use stopped time to calculate duration for current activity in history table 2017-08-25 23:00:40 -07:00
JonnyWong16
07524242c0 Replace IP with session location 2017-08-23 22:24:22 -07:00
JonnyWong16
3b0e4bf254 Only update bif if playing state 2017-08-23 22:23:33 -07:00
JonnyWong16
da3abf11a2 Fix use float when rounding bitrate/bandwidth 2017-08-23 22:10:24 -07:00
JonnyWong16
aee752e04e Add MQTT notification agent 2017-08-23 20:51:27 -07:00
JonnyWong16
b4fa6befdf Fix test script args 2017-08-23 20:46:46 -07:00
JonnyWong16
cd007ee0eb Catch exception so websocket doesn't crash when failed to process data 2017-08-23 20:33:14 -07:00
JonnyWong16
bbe309e7bd Set session state for buffer events 2017-08-23 20:29:48 -07:00
JonnyWong16
f414d7aa16 Check for localhost in QR address 2017-08-22 22:33:58 -07:00
JonnyWong16
be2989ead1 Allow manual entry of QR code server address 2017-08-22 22:03:55 -07:00
JonnyWong16
1c8e581cf1 Write stopped time to database for all events
* To prevent the "long duration" websocket issue for missing stop events
2017-08-22 20:29:21 -07:00
JonnyWong16
a81dfe83a9 Turn on logging of disabled user/library notifications 2017-08-19 23:49:32 -07:00
JonnyWong16
4b9b8d61f2 Add loader message to homepage toggles 2017-08-19 23:49:08 -07:00
JonnyWong16
4fa5fb909c Fixed height recently added row when empty 2017-08-19 23:35:42 -07:00
JonnyWong16
2d7fb82dd6 Fix API json encoding 2017-08-19 21:38:22 -07:00
JonnyWong16
48152c9ba3 Fix stream width and height info 2017-08-19 21:23:41 -07:00
JonnyWong16
a5771dccf5 Fix session start log format error 2017-08-19 21:23:16 -07:00
JonnyWong16
581b8375b9 Manually merge v1.4.22 into v2 2017-08-19 21:11:08 -07:00
JonnyWong16
9058c5accb Explicitly assign websocket state 2017-08-18 10:57:02 -07:00
JonnyWong16
a0799e8197 Initialize scheduler to reconnect websocket when failed on startup 2017-08-13 09:44:15 -07:00
JonnyWong16
21309ba280 Remove speed from activity when transcode throttled 2017-08-13 09:43:45 -07:00
JonnyWong16
b66018a5c3 Increase activity refresh to 2 seconds 2017-08-13 09:10:00 -07:00
JonnyWong16
f0e14b6de5 Round bitrate/bandwidth to Mbps 2017-08-13 09:09:39 -07:00
JonnyWong16
845c3d419a Add audio quality profiles 2017-08-08 21:38:46 -07:00
JonnyWong16
00e281dfb7 Fix crashing when streaming clips 2017-08-08 21:37:57 -07:00
JonnyWong16
862c9cea87 Add network and bandwidth to current activity
* Move quality profile to info bar
2017-08-07 11:25:26 -07:00
JonnyWong16
427f24dffe Add inner shadow for terminate session button 2017-08-04 08:55:08 -07:00
JonnyWong16
68072d8340 Manual merge of v1.4.21 into v2 2017-08-02 21:37:59 -07:00
JonnyWong16
1ac4d43db2 Add message for no recently added items 2017-08-02 21:22:37 -07:00
JonnyWong16
e0b78adfee Add recently added media type toggles to homepage 2017-08-02 21:12:59 -07:00
JonnyWong16
0c481fc005 Fix media info tables 2017-07-26 19:17:24 -07:00
JonnyWong16
9f6ee3e761 Return blank TVMaze/TMDB info on failed database queries 2017-07-26 15:45:09 -07:00
JonnyWong16
81dca01302 Create table indices after table upgrades 2017-07-26 15:42:27 -07:00
JonnyWong16
0c62a83145 Add terminate session button to current activity 2017-07-23 13:03:16 -07:00
JonnyWong16
c780b9fd65 Remove help text for provider notification parameters 2017-07-23 02:12:30 -07:00
JonnyWong16
0e180cb242 Add provider links for Discord, Hipchat, Pushover, and Slack 2017-07-23 01:56:44 -07:00
JonnyWong16
41101921ed Add rating key to The Movie Database and TVmaze lookups 2017-07-23 01:56:44 -07:00
JonnyWong16
80ee8f9617 Add The Movie Database lookup 2017-07-23 01:56:33 -07:00
JonnyWong16
1f55b5457e Add homepage stats toggles 2017-07-22 18:13:53 -07:00
William Comartin
527af7063d New icons for platforms and libraries 2017-07-18 20:46:00 -04:00
William Comartin
25455e8194 Add user_id param to get_users_table 2017-07-15 22:08:59 -04:00
JonnyWong16
c27c1379d0 Update Facebook for provider link only
* Custom poster/metadata removed in Graph API v2.9
2017-07-10 22:34:50 -07:00
JonnyWong16
42a7ae36c2 Add TVmaze lookup 2017-07-10 22:33:20 -07:00
JonnyWong16
ce846d65cb Imgur uploads to use requests library 2017-07-10 22:21:12 -07:00
JonnyWong16
dc25ef857f Refactor notifier requests and better logging 2017-07-08 15:07:01 -07:00
JonnyWong16
6f0c650a72 Separate movie/episode/track watched percent 2017-07-07 19:01:04 -07:00
JonnyWong16
8348424758 Merge branch 'v2-notifications-conditions' into v2 2017-07-07 18:09:34 -07:00
JonnyWong16
9701474662 Update all notifiers to use requests library 2017-07-06 22:42:34 -07:00
JonnyWong16
e284a17034 Fix logic parsing for nested and 2017-07-06 09:20:32 -07:00
JonnyWong16
abf55df26d Add GroupMe notification agent 2017-07-05 21:51:15 -07:00
JonnyWong16
6488a7436a Send single MQTT notification 2017-07-05 21:10:39 -07:00
JonnyWong16
cceff2e8dd Add note about order of operations 2017-07-05 19:27:45 -07:00
JonnyWong16
161e6f70d0 Remove the use of eval for evaluating custom notification logic 2017-07-05 19:13:02 -07:00
JonnyWong16
d4e5a750e0 Add condition parameter type passed from JS 2017-07-05 18:47:34 -07:00
William Comartin
b1264bedd8 Merge branch 'v2-notifications-conditions' of github.com:JonnyWong16/plexpy into v2-notifications-conditions 2017-07-05 16:37:53 -04:00
William Comartin
5323ae2943 Update filterer.jquery.js newest version adds type to conditions output from update method 2017-07-05 16:37:23 -04:00
Nicholas Alipaz
e17c551555 Fix reviewed items by JonnyWong16 2017-06-20 17:03:03 -07:00
Nicholas Alipaz
f7166f37f5 Remove MQTT settings form config 2017-06-20 16:54:01 -07:00
Nicholas Alipaz
6bc12e17fd Initial mqtt notification agent 2017-06-20 15:14:05 -07:00
JonnyWong16
ae5777e612 Another temporary fix for media_part_info 2017-05-16 22:26:20 -07:00
JonnyWong16
1b5a7d78d4 Temporary fix for metadata media_info 2017-05-16 22:05:34 -07:00
JonnyWong16
7ba2b7828c Check for blank parameter and operator 2017-05-08 09:21:49 -07:00
William Comartin
1eac1002b2 Update Filterer, Fixes null Values issue 2017-05-08 11:57:54 -04:00
William Comartin
f41280f5b9 Setup Selectize for Filterer Values 2017-05-08 00:30:55 -04:00
JonnyWong16
8653b5b928 Update log error message 2017-05-07 20:26:12 -07:00
JonnyWong16
5b5ebadfea Use list of values for conditions 2017-05-07 17:40:41 -07:00
JonnyWong16
12c94ee79e Add parsing and evaluating custom notification conditions 2017-05-07 13:07:24 -07:00
JonnyWong16
d536a10d20 Fix notification parameters category names 2017-05-06 23:26:42 -07:00
JonnyWong16
2db3b093b9 Remove blank parameter option 2017-05-06 23:26:26 -07:00
William Comartin
8aa94cc32d Update Filterer, add properties from server to fill in the Filterer 2017-05-07 01:47:00 -04:00
JonnyWong16
2e83b42ba9 Add blank defaults to conditions and parameters 2017-05-06 22:43:49 -07:00
JonnyWong16
42b1a0d3de Pass parameters to notifier config modal 2017-05-06 22:04:24 -07:00
JonnyWong16
9d49a2bd11 Missing bracket in help text 2017-05-05 23:26:09 -07:00
JonnyWong16
f3349c64a9 Add settings for notification conditions filterer 2017-05-05 23:14:11 -07:00
JonnyWong16
565dea5ecf Dynamically build notification parameters 2017-05-05 22:25:06 -07:00
JonnyWong16
2ebe849b8e Allow temporary device token through api 2017-04-30 19:51:53 -07:00
JonnyWong16
84bfe99017 Download config and database from the settings 2017-04-22 13:23:16 -07:00
JonnyWong16
7c0c7eea30 Remove global logging toggles 2017-04-22 12:44:46 -07:00
JonnyWong16
77b0f69b0c Catch notification thread exception 2017-04-22 11:14:53 -07:00
JonnyWong16
e71e588a91 Fix crash if session is missing stream_video_bitrate 2017-04-20 23:28:11 -07:00
JonnyWong16
beb8df9dda Add thumbnails to notification options 2017-04-19 22:09:39 -07:00
JonnyWong16
014cac7789 Add thumb to android notification 2017-04-19 22:04:02 -07:00
JonnyWong16
41caaa7730 Fixed width icon in notification logs table 2017-04-19 22:03:42 -07:00
JonnyWong16
997e2cdfd8 Encrypt notification with device token instead of api key 2017-04-19 20:21:10 -07:00
JonnyWong16
a939d1bfd8 Fix notify_log success column name 2017-04-19 19:59:59 -07:00
JonnyWong16
59f12c71a9 Manual merge v2 notifications encryption 2017-04-19 19:58:39 -07:00
JonnyWong16
0528ce983f Send notification ID to the android app 2017-04-19 19:52:01 -07:00
JonnyWong16
f2f28f48cb Log test notifications 2017-04-19 19:43:22 -07:00
JonnyWong16
006e7c214d Add notification success to database 2017-04-19 19:32:35 -07:00
JonnyWong16
fc37a8afa3 Switch to SHA1 and remove gcm_tag 2017-04-19 09:49:13 -07:00
JonnyWong16
c2243320ec Log API error message 2017-04-14 17:26:20 -07:00
JonnyWong16
f5969f271a Remove global notification toggles 2017-04-10 21:14:26 -07:00
JonnyWong16
c7063b5973 Improve Facebook auth polling 2017-04-02 12:20:14 -07:00
JonnyWong16
23e0379beb Fallback to parent poster for Imgur upload 2017-04-02 11:01:47 -07:00
JonnyWong16
08619244f0 Generate a unique token for each mobile device 2017-03-31 21:02:09 -07:00
JonnyWong16
5029b19d37 Add note about https for QR scan 2017-03-31 18:14:48 -07:00
JonnyWong16
4bdf520bce Check device is registered before sending notification 2017-03-31 18:14:32 -07:00
JonnyWong16
0a493b9349 Fix to make queries safe 2017-03-31 09:37:22 -07:00
JonnyWong16
a612de52f9 Forgot missing comma 2017-03-31 09:11:48 -07:00
JonnyWong16
a85d4a678d Check git remote branch before splitting 2017-03-30 19:36:38 -07:00
JonnyWong16
08fdcac240 Fix OSX notifier agent id key 2017-03-30 19:34:37 -07:00
JonnyWong16
40060255ee Add automatic Android app QR scan verification 2017-03-30 19:25:45 -07:00
JonnyWong16
d2da193978 Combine android app config notes 2017-03-30 18:14:28 -07:00
JonnyWong16
441c56854d Add android app notification priority option 2017-03-29 22:32:56 -07:00
JonnyWong16
e6023a4702 Add notification encryption warning message 2017-03-29 22:32:35 -07:00
JonnyWong16
d031d74bc6 Check for pycryptodome library on import 2017-03-29 21:24:40 -07:00
JonnyWong16
2952d1360a Update .gitignore for certs only in root directory 2017-03-29 20:03:03 -07:00
JonnyWong16
301ef85e89 Encrypt OneSignal notifications 2017-03-29 20:02:48 -07:00
JonnyWong16
ddf671abd1 Add ability to unregister mobile devices 2017-03-28 21:44:18 -07:00
JonnyWong16
f60c978d80 Fix bc5ce52 2017-03-28 10:09:55 -07:00
JonnyWong16
42a895b095 Change Pushy to OneSignal for push notifications 2017-03-28 09:38:03 -07:00
JonnyWong16
c405f04e9c Fix Pushy device token and add logging 2017-03-27 21:12:39 -07:00
JonnyWong16
bc5ce52236 Fix 50969c2 2017-03-27 21:05:46 -07:00
JonnyWong16
896922de4f Update Android app device registration 2017-03-27 20:50:00 -07:00
JonnyWong16
203a6d47b4 Fix track metadata 2017-03-27 11:34:54 -07:00
JonnyWong16
8e13e2deb2 Add device token to android app notifier config 2017-03-25 23:39:32 -07:00
JonnyWong16
d18c2ffddb Add register android app for push notifications 2017-03-25 23:13:35 -07:00
JonnyWong16
50969c24cc Temporary fix for show/season media info tables 2017-03-25 23:12:23 -07:00
JonnyWong16
f3070763fa Fix some stream info overrides 2017-03-25 13:25:45 -07:00
JonnyWong16
ca093875b4 Don't uppercase TrueHD 2017-03-25 12:28:32 -07:00
JonnyWong16
f77e061ff1 Catch notifier config error 2017-03-25 12:17:04 -07:00
JonnyWong16
0df1bd137d Fix splitting of script arguments 2017-03-25 11:58:37 -07:00
JonnyWong16
3513f7fe2c Add banner to metadata 2017-03-15 09:01:39 -07:00
JonnyWong16
d845b3f7b0 Add user rating to metadata 2017-03-15 08:36:45 -07:00
JonnyWong16
9318c4742d Manual merge of v1.4.17 into v2 2017-03-04 16:02:37 -08:00
JonnyWong16
8a2696adf7 Fix edit friendly name on user page 2017-03-04 10:05:29 -08:00
JonnyWong16
fd1bd7f215 Improve quality profile logic 2017-03-03 18:15:14 -08:00
JonnyWong16
74876ea3c9 Fix transcode decision 2017-03-03 17:44:20 -08:00
JonnyWong16
f6fc142c47 Add Rotten Tomatoes rating 2017-03-03 17:21:52 -08:00
JonnyWong16
78fd83746e Add subtitle direct stream to activity 2017-03-03 16:56:07 -08:00
JonnyWong16
2794a4b550 Add audio channel substitutions 2017-03-02 22:14:23 -08:00
JonnyWong16
7244b15821 Fix link to Plex Web 3.0 in notifications 2017-03-02 18:06:25 -08:00
JonnyWong16
45a1c119ac Rewrite imgur url to https 2017-03-02 18:02:10 -08:00
JonnyWong16
82b42f92a9 Add session throttled key for backwards compatibility
* And fix check for optimized version
2017-03-02 18:01:59 -08:00
JonnyWong16
c4fc831968 Fix refresh of burn subtitle info 2017-03-01 20:52:30 -08:00
JonnyWong16
83c1ca195f Testing more detailed activity pane 2017-02-28 22:27:07 -08:00
JonnyWong16
3166b91cb7 Always show notifier ID on notification agents table 2017-02-28 20:59:25 -08:00
JonnyWong16
914e3a3988 Check use bif setting 2017-02-28 20:58:59 -08:00
JonnyWong16
9fee0d711a Fix clip links in history table 2017-02-26 22:29:36 -08:00
JonnyWong16
989ebcd3b7 Media type clip fixes 2017-02-26 16:11:18 -08:00
JonnyWong16
a46b24213b Add more source media parameters 2017-02-26 16:00:32 -08:00
JonnyWong16
c01731ebe9 Fix Plex Web 3.0 link 2017-02-26 09:52:25 -08:00
JonnyWong16
89b837393d Unicode full title 2017-02-26 09:52:04 -08:00
JonnyWong16
cea851d38e Add terminate session to API 2017-02-25 22:53:32 -08:00
JonnyWong16
992f0baf93 Add detailed stream info to notification options 2017-02-25 22:30:47 -08:00
JonnyWong16
e272a0eecc Update session info 2017-02-25 20:32:54 -08:00
JonnyWong16
0c95297659 Reorganize settings 2017-02-25 11:27:59 -08:00
JonnyWong16
628cef11fa Make sure notification threads exit on shutdown 2017-02-25 10:59:51 -08:00
JonnyWong16
2c5d131019 Check if recently added notifications disabled for library 2017-02-25 10:36:28 -08:00
JonnyWong16
67e5c7de2c Change Pushbullet to use Access-Token header 2017-02-11 11:02:21 -08:00
JonnyWong16
00ff9c5736 Strip white characters from notification subject and body 2017-02-07 18:41:31 -08:00
JonnyWong16
ca472ff597 Improved IP address handling (includes IPv6) 2017-02-05 18:55:10 -08:00
JonnyWong16
d875f21647 Move all modals out of body-container 2017-02-03 17:23:20 -08:00
JonnyWong16
403ed7f63f Update media flags bundle 2017-02-03 16:28:05 -08:00
JonnyWong16
3e67177f73 Slack option to use thumbnail 2017-02-02 21:34:51 -08:00
JonnyWong16
e49517ef05 Add a space 2017-02-02 20:40:10 -08:00
JonnyWong16
f44121e2f9 Stacked user/library edit modals 2017-02-02 20:37:44 -08:00
JonnyWong16
de6215a933 Fix for stacked modals 2017-02-02 20:37:34 -08:00
JonnyWong16
876ff65694 Fix wide modal on small screens 2017-02-02 20:35:12 -08:00
JonnyWong16
1c142ef3f4 Add ability to duplicate a notifier 2017-02-02 20:34:27 -08:00
JonnyWong16
bfe5209c05 Fix wording and reordering of notifier configs 2017-02-02 20:23:38 -08:00
JonnyWong16
83ac03578d Trim notifiier text inputs before saving 2017-01-30 19:19:12 -08:00
JonnyWong16
e34472084c Add port to Slack connection when used with Mattermost 2017-01-30 19:18:29 -08:00
JonnyWong16
4dce0ec015 Verify color hex code for Discord and Slack 2017-01-30 19:16:05 -08:00
JonnyWong16
304c2429bb Don't use default subject/body with blank notification text
* Allow different notifications using the media type tags
2017-01-29 17:31:47 -08:00
JonnyWong16
957c7aeab9 Update Discord, Facebook, Hipchat, and Slack info cards
* Add option to hide plot summaries
2017-01-29 17:23:27 -08:00
JonnyWong16
07a1136839 Clean up PrettyMetadata 2017-01-27 23:24:19 -08:00
JonnyWong16
70f006d06d Update Discord, Slack, and Hipchat cards 2017-01-27 23:12:46 -08:00
JonnyWong16
651f4ebf5f Fix websocket on_created 2017-01-27 23:12:33 -08:00
JonnyWong16
fc7b396e45 Log recently added items to the database
* Temporarily disable recently added upgrade notifications
2017-01-27 20:50:46 -08:00
JonnyWong16
eac31d10f1 Fix some notifier text 2017-01-27 20:49:33 -08:00
JonnyWong16
270d4f510a Add https certificate chain 2017-01-15 11:49:48 -08:00
JonnyWong16
285599cf90 Fix typo 2017-01-15 11:49:27 -08:00
JonnyWong16
01ec812e1c Fix missing recently added notifications 2016-12-06 20:31:18 -08:00
JonnyWong16
9cf51d403a Add link to Discord card 2016-12-06 20:07:28 -08:00
JonnyWong16
dfac33723a Reword QR scanner help text 2016-12-06 18:08:18 -08:00
JonnyWong16
655f1c249e Add show and episode title to get_history API 2016-11-29 20:54:27 -08:00
JonnyWong16
e31e531f9c Fix websocket timeline json 2016-11-25 21:06:43 -08:00
JonnyWong16
d7cef5add7 Manual merge of v1.4.16 into v2 2016-11-25 19:16:43 -08:00
JonnyWong16
03eec610fa Add separate settings tab for PlexPy Remote App 2016-11-18 22:39:44 -08:00
JonnyWong16
66191d2ff9 Put QR code in pre block 2016-11-17 23:37:33 -08:00
JonnyWong16
9e64463e70 Add QR code to link PlexPy Remote android app 2016-11-17 23:14:23 -08:00
JonnyWong16
ebf014406d Use fallback text if invalid subject or body 2016-11-14 21:33:37 -08:00
JonnyWong16
21f6a076cb Don't capitalize video and audio decision 2016-11-11 21:43:00 -08:00
JonnyWong16
bb938d4482 Fix Script test action 2016-11-11 13:54:35 -08:00
JonnyWong16
411e798f8e Rename script configuration tabs 2016-11-11 13:37:39 -08:00
JonnyWong16
0c5fa37d8b Select test script over configured script 2016-11-11 13:37:39 -08:00
JonnyWong16
fd4a2bdb4d Make sure agent is in v1 before upgrading agents 2016-11-11 13:37:39 -08:00
JonnyWong16
38d2345cd2 Option to send recently added notification for new versions 2016-11-11 13:37:38 -08:00
JonnyWong16
cc45ad0b63 Simplify random Arnold quote choice 2016-11-11 13:37:38 -08:00
JonnyWong16
0ab9cdf97c Only preview notification text for valid media types 2016-11-11 13:37:37 -08:00
JonnyWong16
580595e5fa Fix set temporary session stopped time 2016-11-11 13:37:37 -08:00
JonnyWong16
ca573ce73a Make sure parameters have media type for PrettyMetadata 2016-11-11 13:37:37 -08:00
JonnyWong16
c75099decc Fix script timeout 2016-11-11 13:37:36 -08:00
JonnyWong16
d874697eef Add notifier text preview 2016-11-11 13:37:11 -08:00
JonnyWong16
cb5252b8d4 Update Plex Home Theater and XBMC notification agents 2016-11-11 13:37:11 -08:00
JonnyWong16
5f28ead6e9 Make sure to get metadata media info for notification 2016-11-11 13:36:26 -08:00
JonnyWong16
bf99c0e290 Note auto line breaks in email HTML 2016-11-11 13:36:26 -08:00
JonnyWong16
5aaa014207 Option to group recently added by parent or grandparent 2016-11-11 13:36:25 -08:00
JonnyWong16
a13f84fbf6 Only split once for git remote/branch 2016-11-11 13:36:25 -08:00
JonnyWong16
1618921a57 Add notifier configs to logger blacklist 2016-11-11 13:36:25 -08:00
JonnyWong16
864063676f Default http_proxy on and remove setting 2016-11-11 13:36:25 -08:00
JonnyWong16
17649bf36a Catch websocket expection 2016-11-11 13:36:24 -08:00
JonnyWong16
8f22b118be Use default subject and body if blank 2016-11-11 13:36:24 -08:00
JonnyWong16
6f97036446 Enable TTS for Discord 2016-11-11 13:36:24 -08:00
JonnyWong16
ffcde69352 Fix Facebook authorization 2016-11-11 13:36:24 -08:00
JonnyWong16
1520062878 Remove experimental tag for Discord 2016-11-11 13:36:24 -08:00
JonnyWong16
228777963f Script logger error message for unspecified folder 2016-11-11 13:36:23 -08:00
JonnyWong16
08a9b59ca4 Remove 'on_' prefix from notifier actions 2016-11-11 13:36:23 -08:00
JonnyWong16
7da1edfcc5 Change missing image to warning 2016-11-11 13:36:23 -08:00
JonnyWong16
f63b5514f3 Stop capitalizing the action name in notifications 2016-11-11 13:36:23 -08:00
JonnyWong16
486ddb55b2 Change wording 2016-11-11 13:36:23 -08:00
JonnyWong16
6720b44f43 Don't auto close modal when saving notifier config 2016-11-11 13:36:22 -08:00
JonnyWong16
0c7db9c1ee Add attachement colour option for Slack 2016-11-11 13:36:22 -08:00
JonnyWong16
7df455309e Fix poster upload logger message 2016-11-11 13:36:22 -08:00
JonnyWong16
0a4b3f02db Remove api v1 import 2016-11-11 13:36:22 -08:00
JonnyWong16
b8fc6e6b0f A bit of performance improvement 2016-11-11 13:36:22 -08:00
JonnyWong16
39b8f49894 Center restart message 2016-11-11 13:36:22 -08:00
JonnyWong16
c3b5621dda Fix fallback body text 2016-11-11 13:36:21 -08:00
JonnyWong16
5d58d9f5d4 Fix getting user stream count for notifications 2016-11-11 13:36:21 -08:00
JonnyWong16
52a6f639b0 Cleanup activity processor 2016-11-11 13:36:21 -08:00
JonnyWong16
cfcd32a10b Update read changelog for variable headers and list levels 2016-11-11 13:36:21 -08:00
JonnyWong16
9e8d55e0f3 Update notification logs table 2016-11-11 13:36:21 -08:00
JonnyWong16
ed6a42f747 Create a new database table for poster urls 2016-11-11 13:36:20 -08:00
JonnyWong16
ffdd9c9cbf Rework notification logic to only build parameters once per action
* Instead of rebuilding for each notification agent
* Change season/episode to use season poster
* Change album/track to use album art
2016-11-11 13:36:20 -08:00
JonnyWong16
f45bd49421 Comment out Discord TTS 2016-11-11 13:36:20 -08:00
JonnyWong16
e9cfc59400 Add pretty metadata for season and album 2016-11-11 13:36:19 -08:00
JonnyWong16
b98faa0671 Update Slack agent 2016-11-11 13:36:18 -08:00
JonnyWong16
bfb6aee908 Mark Discord as experimental 2016-11-11 13:36:18 -08:00
JonnyWong16
5b6f876ddc Add Discord notification agent 2016-11-11 13:36:16 -08:00
JonnyWong16
6737f45948 Some typos 2016-11-11 13:36:15 -08:00
JonnyWong16
1b42f95643 Alphabetize notification agents 2016-11-11 13:36:15 -08:00
JonnyWong16
b3f43f956e Add delay to check for valid DLNA session 2016-11-11 13:36:15 -08:00
JonnyWong16
abe75c9744 Change git remote/branch textbox width 2016-11-11 13:36:15 -08:00
JonnyWong16
1b1e4639fd Log DLNA platform 2016-11-11 13:36:15 -08:00
JonnyWong16
6d0327f662 Don't nest metadata dict
* Return metadata dict directly
2016-11-11 13:36:14 -08:00
JonnyWong16
19e379f084 Add Git section in settings 2016-11-11 13:35:25 -08:00
JonnyWong16
2f291b167e Add grouped metadata note 2016-11-11 13:35:25 -08:00
JonnyWong16
d47daba8c1 Auto redirect if available before countdown on state change 2016-11-11 13:35:25 -08:00
JonnyWong16
27183483a9 Fix check for media info before parsing xml 2016-11-11 13:32:37 -08:00
JonnyWong16
31b6ff003a Fix Pushover notifications 2016-11-11 13:32:37 -08:00
JonnyWong16
0e58369873 Add media info metadata params for notifications 2016-11-11 13:32:37 -08:00
JonnyWong16
94ddf041aa Fix notifier table column name 2016-11-11 13:32:37 -08:00
JonnyWong16
bca9da3964 Make entire notifier stacked config click to open modal 2016-11-11 13:32:37 -08:00
JonnyWong16
1ca1b5aefa Chnage wording for branch checkout warning message 2016-11-11 13:32:36 -08:00
JonnyWong16
9eec985fb9 Move git remote/branch to extra settings 2016-11-11 13:32:36 -08:00
JonnyWong16
d1551bd8c7 Add option to switch the git remote and branch 2016-11-11 13:32:36 -08:00
JonnyWong16
91716527a4 Option to update PlexPy automatically 2016-11-11 13:32:36 -08:00
JonnyWong16
83c304290b Add PlexPy update notifications 2016-11-11 13:32:35 -08:00
JonnyWong16
5ee986593c Disable check server response when websocket connected 2016-11-11 13:31:23 -08:00
JonnyWong16
7187aff1a6 Minor notifier fixes
* Email replace \n with <br>
* Slack and Hipchat help text wording
2016-11-11 13:31:23 -08:00
JonnyWong16
44f39e7fea Actually set notifier config when sending notifications 2016-11-11 13:31:22 -08:00
JonnyWong16
f42d7b0da0 Remove old templates 2016-11-11 13:31:22 -08:00
JonnyWong16
50941055fb Automatically show config modal when adding a new notifier 2016-11-11 13:31:22 -08:00
JonnyWong16
a361296930 Make changelog and notifier config modal wider 2016-11-11 13:31:22 -08:00
JonnyWong16
61507c03a0 Add get_pms_update to the API 2016-11-11 13:31:22 -08:00
JonnyWong16
8595fb97ce Fix bell tooltip on the notifiers table 2016-11-11 13:31:21 -08:00
JonnyWong16
7a37408459 Add advanced config for number of notification threads 2016-11-11 13:31:21 -08:00
JonnyWong16
303ccce8b4 Some more cleanup 2016-11-11 13:31:21 -08:00
JonnyWong16
d8cc76c7d7 Set temporary session stop times on websocket disconnect 2016-11-11 13:31:21 -08:00
JonnyWong16
fd35295093 Remove unused settings 2016-11-11 13:31:21 -08:00
JonnyWong16
72764c614e Add logger message 2016-11-11 13:31:20 -08:00
JonnyWong16
b8106186fb Add advanced setting for remote access ping threshold 2016-11-11 13:31:20 -08:00
JonnyWong16
eb3c189ab6 Rework task scheduler for websocket only 2016-11-11 13:31:20 -08:00
JonnyWong16
16c7d27508 Default to websocket connection
* No polling failover
2016-11-11 13:31:20 -08:00
JonnyWong16
be50ecd033 Default True for no data notifications 2016-11-11 13:31:20 -08:00
JonnyWong16
4170ed55a6 Cleanup recently_added_grandparent javascript in settings 2016-11-11 13:31:19 -08:00
JonnyWong16
31c9ecaf44 Clean up timeline state 2016-11-11 13:31:19 -08:00
JonnyWong16
e1bd5ed49e Add grouped notification params 2016-11-11 13:31:19 -08:00
JonnyWong16
d97cacff14 More intelligent grouping of recently added
* Websocket only
2016-11-11 13:31:19 -08:00
JonnyWong16
8ed2f0eafa Another attempt at using websockets for recently added 2016-11-11 13:31:19 -08:00
JonnyWong16
438e525319 Add user_id to session started log message 2016-11-11 13:31:18 -08:00
JonnyWong16
2a2237f542 Check concurrent streams by API instead of database 2016-11-11 13:31:18 -08:00
JonnyWong16
06db6826ed Check media_type in params when building notification text 2016-11-11 13:31:18 -08:00
JonnyWong16
08a8b5fee0 Multithreaded notification queue 2016-11-11 13:31:18 -08:00
JonnyWong16
82f4c99025 Check on_watched condition before adding to queue 2016-11-11 13:31:18 -08:00
JonnyWong16
7b2a7aff9f Update notification handler for all notification triggers 2016-11-11 13:31:18 -08:00
JonnyWong16
1206d13978 Add notifier id to config modal 2016-11-11 13:31:17 -08:00
JonnyWong16
8bdf1af021 Add previously configured notification agents to the new system 2016-11-11 13:30:52 -08:00
JonnyWong16
f0595b8b0a Add new notification system 2016-11-11 13:30:52 -08:00
JonnyWong16
258ec197d7 Uniform logger 2016-11-11 13:28:18 -08:00
JonnyWong16
7d3711bf5a Add last_insert_id module to database 2016-11-11 13:28:18 -08:00
JonnyWong16
8925a0dc78 Remove API v1 2016-11-11 13:28:18 -08:00
JonnyWong16
38ccd26b96 Allow data to be passed for confirmAjaxCall 2016-11-11 13:28:18 -08:00
JonnyWong16
7e8fddc50c Make sure confirm modal is above other modals 2016-11-11 13:28:17 -08:00
JonnyWong16
bc1452d1d0 Remove old current activity template 2016-11-11 13:28:17 -08:00
JonnyWong16
d285107cfb Remove shared Imgur client ID 2016-11-11 13:28:17 -08:00
JonnyWong16
354700fcbb Show changelog on update 2016-11-11 13:28:17 -08:00
286 changed files with 31316 additions and 12493 deletions

8
.gitignore vendored
View File

@@ -19,10 +19,10 @@ cache/*
# HTTPS Cert/Key #
##################
*.crt
*.key
*.csr
*.pem
/*.crt
/*.key
/*.csr
/*.pem
# Mergetool
*.orgin

124
API.md
View File

@@ -783,55 +783,53 @@ Optional parameters:
Returns:
json:
{"metadata":
{"actors": [
"Kit Harington",
"Emilia Clarke",
"Isaac Hempstead-Wright",
"Maisie Williams",
"Liam Cunningham",
],
"added_at": "1461572396",
"art": "/library/metadata/1219/art/1462175063",
"content_rating": "TV-MA",
"directors": [
"Jeremy Podeswa"
],
"duration": "2998290",
"genres": [
"Adventure",
"Drama",
"Fantasy"
],
"grandparent_rating_key": "1219",
"grandparent_thumb": "/library/metadata/1219/thumb/1462175063",
"grandparent_title": "Game of Thrones",
"guid": "com.plexapp.agents.thetvdb://121361/6/1?lang=en",
"labels": [],
"last_viewed_at": "1462165717",
"library_name": "TV Shows",
"media_index": "1",
"media_type": "episode",
"originally_available_at": "2016-04-24",
"parent_media_index": "6",
"parent_rating_key": "153036",
"parent_thumb": "/library/metadata/153036/thumb/1462175062",
"parent_title": "",
"rating": "7.8",
"rating_key": "153037",
"section_id": "2",
"studio": "HBO",
"summary": "Jon Snow is dead. Daenerys meets a strong man. Cersei sees her daughter again.",
"tagline": "",
"thumb": "/library/metadata/153037/thumb/1462175060",
"title": "The Red Woman",
"updated_at": "1462175060",
"writers": [
"David Benioff",
"D. B. Weiss"
],
"year": "2016"
}
{"actors": [
"Kit Harington",
"Emilia Clarke",
"Isaac Hempstead-Wright",
"Maisie Williams",
"Liam Cunningham",
],
"added_at": "1461572396",
"art": "/library/metadata/1219/art/1462175063",
"content_rating": "TV-MA",
"directors": [
"Jeremy Podeswa"
],
"duration": "2998290",
"genres": [
"Adventure",
"Drama",
"Fantasy"
],
"grandparent_rating_key": "1219",
"grandparent_thumb": "/library/metadata/1219/thumb/1462175063",
"grandparent_title": "Game of Thrones",
"guid": "com.plexapp.agents.thetvdb://121361/6/1?lang=en",
"labels": [],
"last_viewed_at": "1462165717",
"library_name": "TV Shows",
"media_index": "1",
"media_type": "episode",
"originally_available_at": "2016-04-24",
"parent_media_index": "6",
"parent_rating_key": "153036",
"parent_thumb": "/library/metadata/153036/thumb/1462175062",
"parent_title": "",
"rating": "7.8",
"rating_key": "153037",
"section_id": "2",
"studio": "HBO",
"summary": "Jon Snow is dead. Daenerys meets a strong man. Cersei sees her daughter again.",
"tagline": "",
"thumb": "/library/metadata/153037/thumb/1462175060",
"title": "The Red Woman",
"updated_at": "1462175060",
"writers": [
"David Benioff",
"D. B. Weiss"
],
"year": "2016"
}
```
@@ -1176,6 +1174,34 @@ Returns:
```
### get_pms_update
Check for updates to the Plex Media Server.
```
Required parameters:
None
Optional parameters:
None
Returns:
json:
{"update_available": true,
"platform": "Windows",
"release_date": "1473721409",
"version": "1.1.4.2757-24ffd60",
"requirements": "...",
"extra_info": "...",
"changelog_added": "...",
"changelog_fixed": "...",
"label": "Download",
"distro": "english",
"distro_build": "windows-i386",
"download_url": "https://downloads.plex.tv/...",
}
```
### get_recently_added
Get all items that where recelty added to plex.

View File

@@ -1,5 +1,141 @@
# Changelog
## v2.0.4-beta (2017-12-29)
* Monitoring:
* Fix: Current activity cards duplicating on the homepage.
* Notifications:
* Fix: Concurrent stream notifications being sent when there is an incorrect number of streams.
* UI:
* New: Info pages for collections.
* New: Button to test Plex Web URL override.
* Fix: Library and User pages return to the correct tab when pressing back.
## v2.0.3-beta (2017-12-25)
* Monitoring:
* Fix: Missing sync ID error causing logging to crash.
* Fix: Incorrect optimized version title column name causing logging to crash.
* Notifications:
* Fix: Report correct beta version for Tautulli update notifications.
* UI:
* Fix: Missing CSS for stream info modal.
## v2.0.2-beta (2017-12-24)
* Monitoring:
* Fix: Websocket connection fails to start with existing streams when upgrading to v2.
* Fix: Long request URI for refreshing current activity on the homepage.
* Fix: Missing subtitle database columns.
* Fix: Details for synced and optimized versions reporting incorrectly.
* Notifications:
* Fix: Recently added notifications sending for previously added items. It is now limited to past 24 hours only.
* Fix: Source video/audio/subtitle parameters showing up as blank.
* Change: Validate condition logic when saving a notification agent.
* API:
* Change: API is enabled by default on new installs.
* UI:
* New: Add logo svg files. (Thanks @Fish2)
* New: Updated stream info modal.
* Change: Media info tables sort by sort title instead of title.
* Other:
* Fix: Updating library IDs message on libraries page.
* Fix: Wtched percentage settings not saving after restart.
* Remove: Video Preview Thumbnails setting no longer used.
* Change: Add back HTTP Proxy setting under the Web Interface settings tab.
* Change: "Group Table and Watch Statistics History" and "Current Activity in History Tables" enabled by default on new installs.
## v2.0.1-beta (2017-12-19)
* Monitoring:
* Fix: Missing video_height database column.
* Notifications:
* Fix: Join API key.
* Change: Temporarily disable broken browser notifications.
* UI:
* Fix: Incorrect fallback image for music watch statistics.
## v2.0.0-beta (2017-12-18)
* Monitoring:
* New: More detailed stream info including subtitles, bitrates, bandwidth, and quality profiles.
* New: Terminate sessions from the current activity (Plex Pass only).
* Change: Monitoring uses websockets only now.
* Notifications:
* New: Completely new notification system.
* Allow adding multiple of the same notification agent and/or duplicating existing notification agents.
* Each notification agent has it's own notification triggers and notification text.
* Notification agents are stored in the database instead of the config file. Some notification configurations may have been lost in the transfer. Sorry.
* New: Discord notification agent.
* New: GroupMe notification agent.
* New: MQTT notification agent.
* New: More customizable info cards for Discord, Facebook, Hipchat, and Slack.
* New: Script notifications are configured individually per script with separate arguments for each notification action.
* New: Icon and duration options for Plex Home Theater and XBMC notifications.
* New: Notification for Tautulli updates.
* New: Added &lt;show&gt;, &lt;season&gt;, &lt;artist&gt;, and &lt;album&gt; notification exclusion tags.
* &lt;tv&gt; is renamed to &lt;episode&gt;, and &lt;music&gt; is renamed to &lt;track&gt;
* New: Preview notification text in the notifier settings.
* New: Properly group recently added notifications when adding a batch of media.
* The {season_num}, {episode_num}, and {track_num} parameters will be substituted with the range (e.g. 06-10)
* New: Option to group recently added notifications by show/artist or season/album.
* New: More detailed media info (video, audio, subtitle, file, etc.) notification options available.
* New: Added notification text modifiers to change case and slice lists.
* New: Custom notification conditions using parameters to filter notifications.
* New: Button to trigger manual recently added notifications from the info pages.
* New: Lookup TVMaze and TheMovieDatabase links.
* Remove: The shared Imgur client ID has been removed. Please enter your own client ID in the settings to continue uploading posters.
* Change: Notifications with a blank subject or body will no longer be sent at all.
* Change: Line breaks inserted automatically in Email notification text.
* Change: Notifications for season/episodes now use the season poster and album/track now use the album art.
* Change: The {action} parameter is no longer capitalized.
* Change: Notification success or failure added to notification logs.
* API:
* New: Added check for Plex Media Server updates with the Tautulli API.
* New: Added show/artist and episode/track titles to the "get_history" API command.
* New: Added manual trigger for recently added notifications.
* Remove: Defunct API v1.
* Change: The "notify" API command now requires a notifier_id instead of an agent_id. The notifier ID can be found in the settings for each notification agent.
* Change: The returned json for the "get_metadata" API command is no longer nested under the "metadata" key.
* UI:
* New: Updated current activity, watch statistics, and library statistics cards on the home page.
* New: Toggle stats and recently added categories directly on the homepage.
* New: Ability to delete synced items from the Synced Items page.
* New: Updated platform icons to a uniform style.
* Remove: Setting for number of top items for watch statistic cards.
* Change: Separate API and websocket logs.
* Android Tautulli Remote App (beta):
* New: Download the Tautulli Remote app on Google Play!
* Link the app using a QR code in the Tautulli settings.
* New: Push notifications directly to the Tautulli Remote app.
* Other:
* New: Option to update Tautulli automatically when an update is available.
* New: Option to switch the tracking git remote and branch.
* New: Option to change the path to your git environment variable.
* New: Option to use a HTTPS certificate chain.
* New: Option to override the Plex Web URL for click-through links.
* New: Separate watched percentage for movies, episodes, and tracks.
* New: Show changelog after updating Tautulli.
* New: Support for IPv6 geolocation lookup.
* New: Download the Tautulli configuration file or database from the settings.
* New: Log failed Tautulli login attempts.
* Fix: Modal popups not working on mobile Safari.
* Fix: Prevent password managers from autofilling the password in the settings.
* Fix: Unable to search with special characters.
* Remove: Some unused options have been removed from the settings page.
* Change: The database schema has been changed, and reverting back to PlexPy v1 will not work.
* Change: The dev branch has been depreciated. A master/beta/nightly system is used instead.
## v1.4.25 (2017-10-02)
* Fix: Tab instead of spaces preventing startup.
## v1.4.24 (2017-10-01)
* Fix: New Plex Web urls. (Thanks @Joshua1337)

View File

@@ -6,20 +6,20 @@
# -*- coding: utf-8 -*-
# This file is part of PlexPy.
# This file is part of Tautulli.
#
# PlexPy is free software: you can redistribute it and/or modify
# Tautulli is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PlexPy is distributed in the hope that it will be useful,
# Tautulli is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
# along with Tautulli. If not, see <http://www.gnu.org/licenses/>.
import os
import sys
@@ -43,11 +43,11 @@ signal.signal(signal.SIGTERM, plexpy.sig_handler)
def main():
"""
PlexPy application entry point. Parses arguments, setups encoding and
Tautulli application entry point. Parses arguments, setups encoding and
initializes the application.
"""
# Fixed paths to PlexPy
# Fixed paths to Tautulli
if hasattr(sys, 'frozen'):
plexpy.FULL_PATH = os.path.abspath(sys.executable)
else:
@@ -81,9 +81,9 @@ def main():
parser.add_argument(
'-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')
'-p', '--port', type=int, help='Force Tautulli to run on a specified port')
parser.add_argument(
'--dev', action='store_true', help='Start PlexPy in the development environment')
'--dev', action='store_true', help='Start Tautulli in the development environment')
parser.add_argument(
'--datadir', help='Specify a directory where to store your data files')
parser.add_argument(
@@ -93,8 +93,8 @@ def main():
parser.add_argument(
'--pidfile', help='Create a pid file (only relevant when running as a daemon)')
parser.add_argument(
'--nofork', action='store_true', help='Start PlexPy as a service, do not fork when restarting')
'--nofork', action='store_true', help='Start Tautulli as a service, do not fork when restarting')
args = parser.parse_args()
if args.verbose:
@@ -108,7 +108,7 @@ def main():
if args.dev:
plexpy.DEV = True
logger.debug(u"PlexPy is running in the dev environment.")
logger.debug(u"Tautulli is running in the dev environment.")
if args.daemon:
if sys.platform == 'win32':
@@ -119,9 +119,9 @@ def main():
plexpy.QUIET = True
if args.nofork:
plexpy.NOFORK = True
logger.info("PlexPy is running as a service, it will not fork when restarted.")
plexpy.NOFORK = True
logger.info("Tautulli is running as a service, it will not fork when restarted.")
if args.pidfile:
plexpy.PIDFILE = str(args.pidfile)
@@ -195,14 +195,11 @@ def main():
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()
try:
web_socket.start_thread()
except:
logger.warn(u"Websocket :: Unable to open connection.")
plexpy.initialize_scheduler()
# Force the http port if neccessary
if args.port:
@@ -230,6 +227,7 @@ def main():
'http_proxy': plexpy.CONFIG.HTTP_PROXY,
'enable_https': plexpy.CONFIG.ENABLE_HTTPS,
'https_cert': plexpy.CONFIG.HTTPS_CERT,
'https_cert_chain': plexpy.CONFIG.HTTPS_CERT_CHAIN,
'https_key': plexpy.CONFIG.HTTPS_KEY,
'http_username': plexpy.CONFIG.HTTP_USERNAME,
'http_password': plexpy.CONFIG.HTTP_PASSWORD,
@@ -256,6 +254,8 @@ def main():
plexpy.shutdown()
elif plexpy.SIGNAL == 'restart':
plexpy.shutdown(restart=True)
elif plexpy.SIGNAL == 'checkout':
plexpy.shutdown(restart=True, checkout=True)
else:
plexpy.shutdown(restart=True, update=True)

View File

@@ -1,8 +1,8 @@
# PlexPy
# Tautulli
[![Discord](https://img.shields.io/badge/Discord-PlexPy-738bd7.svg?style=flat-square)](https://discord.gg/36ggawe)
[![Gitter](https://img.shields.io/badge/Gitter-PlexPy-ed1965.svg?style=flat-square)](https://gitter.im/plexpy/general)
[![Plex Forums](https://img.shields.io/badge/Plex%20Forums-PlexPy-E5A00D.svg?style=flat-square)](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program)
[![Discord](https://img.shields.io/badge/Discord-Tautulli-7289DA.svg?style=flat-square)](https://discord.gg/36ggawe)
[![Reddit](https://img.shields.io/badge/Reddit-Tautulli-FF5700.svg?style=flat-square)](https://www.reddit.com/r/Tautulli/)
[![Plex Forums](https://img.shields.io/badge/Plex%20Forums-Tautulli-E5A00D.svg?style=flat-square)](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program)
A python based web application for monitoring, analytics and notifications for [Plex Media Server](https://plex.tv).
@@ -27,13 +27,13 @@ This project is based on code from [Headphones](https://github.com/rembo10/headp
## Preview
* [Full preview gallery on Imgur](https://imgur.com/a/RwQPM)
* [Full preview gallery on our website](http://tautulli.com)
![PlexPy Homepage](https://i.imgur.com/0D0uFJg.jpg)
![Tautulli Homepage](http://tautulli.com/images/screenshots/activity.png?v=2)
## Installation and Support
* [Installation Guides](https://github.com/JonnyWong16/plexpy/wiki/Installation) shows you how to install PlexPy.
* [Installation Guides](https://github.com/JonnyWong16/plexpy/wiki/Installation) shows you how to install Tautulli.
* [FAQs](https://github.com/JonnyWong16/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.
@@ -49,7 +49,7 @@ This project is based on code from [Headphones](https://github.com/rembo10/headp
- Checking the [Wiki](https://github.com/JonnyWong16/plexpy/wiki) for
[ [Installation] ](https://github.com/JonnyWong16/plexpy/wiki/Installation) and
[ [FAQs] ](https://github.com/JonnyWong16/plexpy/wiki/Frequently-Asked-Questions-(FAQ)).
- For basic questions try asking on [Gitter](https://gitter.im/plexpy/general) or the [Plex Forums](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) first before opening an issue.
- For basic questions try asking on [Discord](https://discord.gg/36ggawe), [Reddit](https://www.reddit.com/r/Tautulli), or the [Plex Forums](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) first before opening an issue.
##### If nothing has worked:

View File

@@ -8,129 +8,38 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>PlexPy - ${title} | ${server_name}</title>
<title>Tautulli - ${title} | ${server_name}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<link href="${http_root}css/bootstrap3/bootstrap.css" rel="stylesheet">
<link href="${http_root}css/pnotify.custom.min.css" rel="stylesheet" />
<link href="${http_root}css/plexpy.css" rel="stylesheet">
<link href="${http_root}css/plexpy.css${cache_param}" rel="stylesheet">
<link href="${http_root}css/opensans.min.css" rel="stylesheet">
<link href="${http_root}css/font-awesome.min.css" rel="stylesheet">
${next.headIncludes()}
<link rel="icon" type="image/x-icon" href="${http_root}images/favicon.ico"/>
<link rel="shortcut icon" href="${http_root}images/favicon.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">
<!-- Favicons -->
<link rel="icon" type="image/png" sizes="32x32" href="${http_root}images/favicon/favicon-32x32.png?v=2.0.1">
<link rel="icon" type="image/png" sizes="16x16" href="${http_root}images/favicon/favicon-16x16.png?v=2.0.1">
<link rel="shortcut icon" href="${http_root}images/favicon/favicon.ico?v=2.0.1">
<!-- ICONS -->
<!-- IE10 icon -->
<meta name="application-name" content="PlexPy" />
<meta name="msapplication-config" content="${http_root}xml/IEconfig.xml"/>
<!-- Android >M39 icon -->
<link rel="manifest" href="${http_root}json/Android-manifest.json">
<!-- iPad retina icon -->
<link href="${http_root}images/res/ios/icon-76@2x.png" sizes="152x152" rel="apple-touch-icon-precomposed">
<!-- iPad retina icon (iOS < 7) -->
<link href="${http_root}images/res/ios/icon-72@2x.png" sizes="144x144" rel="apple-touch-icon-precomposed">
<!-- iPad non-retina icon -->
<link href="${http_root}images/res/ios/icon-76.png" sizes="76x76" rel="apple-touch-icon-precomposed">
<!-- iPad non-retina icon (iOS < 7) -->
<link href="${http_root}images/res/ios/icon-72.png" sizes="72x72" rel="apple-touch-icon-precomposed">
<!-- iPhone 6 Plus icon -->
<link href="${http_root}images/res/ios/icon-60@2x.png" sizes="120x120" rel="apple-touch-icon-precomposed">
<!-- iPhone retina icon (iOS < 7) -->
<link href="${http_root}images/res/ios/icon@2x.png" sizes="114x114" rel="apple-touch-icon-precomposed">
<!-- iPhone non-retina icon (iOS < 7) -->
<link href="${http_root}images/res/ios/icon.png" sizes="57x57" rel="apple-touch-icon-precomposed">
<!-- iPhone / iPod Touch -->
<link href="${http_root}images/res/ios/icon-60@3x.png" sizes="180x180" rel="apple-touch-icon-precomposed">
<link href="${http_root}images/res/ios/icon-60.png" sizes="60x60" rel="apple-touch-icon-precomposed">
<!-- Spotlight Icon -->
<link href="${http_root}images/res/ios/icon-40.png" sizes="40x40" rel="apple-touch-icon-precomposed">
<link href="${http_root}images/res/ios/icon-40@2x.png" sizes="80x80" rel="apple-touch-icon-precomposed">
<!-- iPhone Spotlight and Settings Icon -->
<link href="${http_root}images/res/ios/icon-small.png" sizes="29x29" rel="apple-touch-icon-precomposed">
<link href="${http_root}images/res/ios/icon-small@2x.png" sizes="58x58" rel="apple-touch-icon-precomposed">
<!-- iPad Spotlight and Settings Icon -->
<link href="${http_root}images/res/ios/icon-50.png" sizes="50x50" rel="apple-touch-icon-precomposed">
<link href="${http_root}images/res/ios/icon-50@2x.png" sizes="100x100" rel="apple-touch-icon-precomposed">
<!-- STARTUP IMAGES -->
<!-- iPad retina portrait startup image -->
<link href="${http_root}images/res/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="${http_root}images/res/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="${http_root}images/res/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="${http_root}images/res/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="${http_root}images/res/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="${http_root}images/res/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="${http_root}images/res/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="${http_root}images/res/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="${http_root}images/res/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="${http_root}images/res/ios/Default~iphone.png"
media="(device-width: 320px) and (device-height: 480px)
and (-webkit-device-pixel-ratio: 1)"
rel="apple-touch-startup-image">
<!-- Android -->
<link rel="icon" type="image/png" sizes="192x192" href="${http_root}images/favicon/android-chrome-192x192.png?v=2.0.0">
<link rel="manifest" href="${http_root}images/favicon/manifest.json?v=2.0.1">
<meta name="theme-color" content="#282a2d">
<!-- Apple -->
<link rel="apple-touch-icon" sizes="180x180" href="${http_root}images/favicon/apple-touch-icon.png?v=2.0.1">
<link rel="mask-icon" href="${http_root}images/favicon/safari-pinned-tab.svg?v=2.0.1" color="#282a2d">
<meta name="apple-mobile-web-app-title" content="Tautulli">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport" content="initial-scale=1">
<meta name="format-detection" content="telephone=no">
<!-- Microsoft -->
<meta name="application-name" content="Tautulli">
<meta name="msapplication-config" content="${http_root}images/favicon/browserconfig.xml?v=2.0.1">
</head>
<body class="content">
@@ -139,7 +48,7 @@
% if _session['user_group'] == 'admin':
% if plexpy.CONFIG.CHECK_GITHUB and not plexpy.CURRENT_VERSION:
<div id="updatebar" style="display: none;">
You're running an unknown version of PlexPy.<br />
You're running an unknown version of Tautulli.<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':
@@ -161,7 +70,7 @@
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="home">
<img alt="PlexPy" src="${http_root}images/logo-plexpy@2x.png" height="40">
<img alt="Tautulli" src="${http_root}images/logo-tautulli.svg" height="45">
</a>
</div>
<div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1">
@@ -245,25 +154,14 @@
</nav>
</div>
<div id="confirm-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="confirm-modal">
<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">Confirm</h4>
</div>
<div class="modal-body">
<div id="confirm-message" style="text-align: center; margin-top: 20px; margin-bottom: 20px;">
</div>
</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-button">Confirm</button>
</div>
</div>
</div>
${next.headerIncludes()}
<div class="body-container">
${next.body()}
</div>
${next.modalIncludes()}
% if _session['user_group'] != 'admin':
<div id="admin-login-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="admin-login-modal">
<div class="modal-dialog" role="document">
@@ -310,13 +208,13 @@
<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">PlexPy Donation</h4>
<h4 class="modal-title">Tautulli Donation</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12" style="text-align: center;">
<h4>
<strong>Thank you for supporting PlexPy!</strong>
<strong>Thank you for supporting Tautulli!</strong>
</h4>
<p>
Please select a donation method.
@@ -336,7 +234,7 @@
<p>
Click the button below to continue to PayPal.
</p>
<a href="${anon_url('https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=6XPPKTDSX9QFL&lc=US&item_name=PlexPy&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted')}" target="_blank">
<a href="${anon_url('https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=6XPPKTDSX9QFL&lc=US&item_name=Tautulli&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted')}" target="_blank">
<img src="images/gold-rect-paypal-34px.png" alt="PayPal">
</a>
</div>
@@ -344,7 +242,7 @@
<p>
Click the button below to continue to Flattr.
</p>
<a href="${anon_url('https://flattr.com/submit/auto?user_id=JonnyWong16&url=https://github.com/JonnyWong16/plexpy&title=PlexPy&language=en_GB&tags=github&category=software')}" target="_blank">
<a href="${anon_url('https://flattr.com/submit/auto?user_id=JonnyWong16&url=https://github.com/JonnyWong16/plexpy&title=Tautulli&language=en_GB&tags=github&category=software')}" target="_blank">
<img src="images/flattr-badge-large.png" alt="Flattr">
</a>
</div>
@@ -364,21 +262,31 @@
</div>
% endif
${next.headerIncludes()}
<div class="body-container">
${next.body()}
<div id="confirm-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="confirm-modal">
<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">Confirm</h4>
</div>
<div class="modal-body">
<div id="confirm-message" style="text-align: center; margin-top: 20px; margin-bottom: 20px;">
</div>
</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-button">Confirm</button>
</div>
</div>
</div>
</div>
<script src="${http_root}js/jquery-2.1.4.min.js"></script>
<script src="${http_root}js/bootstrap.min.js"></script>
<script src="${http_root}js/bootstrap-hover-dropdown.min.js"></script>
<script src="${http_root}js/pnotify.custom.min.js"></script>
<script src="${http_root}js/script.js"></script>
<script src="${http_root}js/script.js${cache_param}"></script>
<script src="${http_root}js/jquery.qrcode.min.js"></script>
% if _session['user_group'] == 'admin' and plexpy.CONFIG.BROWSER_ENABLED:
<script src="${http_root}js/ajaxNotifications.js"></script>
% else:
% endif
<script>
% if _session['user_group'] == 'admin':
$('#updateDismiss').click(function() {
@@ -392,7 +300,7 @@ ${next.headerIncludes()}
}
$("#nav-shutdown").click(function() {
$("#confirm-message").text("Are you sure you want to shutdown PlexPy?");
$("#confirm-message").text("Are you sure you want to shutdown Tautulli?");
$('#confirm-modal').modal();
$('#confirm-modal').one('click', '#confirm-button', function () {
window.location.href = "shutdown";
@@ -400,7 +308,7 @@ ${next.headerIncludes()}
});
$("#nav-restart").click(function() {
$("#confirm-message").text("Are you sure you want to restart PlexPy?");
$("#confirm-message").text("Are you sure you want to restart Tautulli?");
$('#confirm-modal').modal();
$('#confirm-modal').one('click', '#confirm-button', function () {
window.location.href = "restart";
@@ -465,6 +373,18 @@ ${next.headerIncludes()}
}
});
}
// Allow stacked bootstrap modals
$(document).on('show.bs.modal', '.modal', function (event) {
var zIndex = 1040 + (10 * $('.modal:visible').length);
$(this).css('z-index', zIndex);
setTimeout(function() {
$('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack');
}, 0);
});
$(document).on('hidden.bs.modal', '.modal', function () {
$('.modal:visible').length && $(document.body).addClass('modal-open');
});
});
% if _session['user_group'] != 'admin':
@@ -477,6 +397,7 @@ ${next.javascriptIncludes()}
</body>
</html>
<%def name="modalIncludes()"></%def>
<%def name="javascriptIncludes()"></%def>
<%def name="headIncludes()"></%def>
<%def name="headerIncludes()"></%def>

View File

@@ -31,15 +31,15 @@ DOCUMENTATION :: END
% endif
<tr>
<td>Configuration File:</td>
<td>${plexpy.CONFIG_FILE}</td>
<td><a class="no-highlight" href="download_config" data-toggle="tooltip" data-placement="right" title="Download Configuration">${plexpy.CONFIG_FILE}</a></td>
</tr>
<tr>
<td>Database File:</td>
<td>${plexpy.DB_FILE}</td>
<td><a class="no-highlight" href="download_database" data-toggle="tooltip" data-placement="right" title="Download Database">${plexpy.DB_FILE}</a></td>
</tr>
<tr>
<td>Log File:</td>
<td><a class="no-highlight" href="logFile" target="_blank">${os.path.join(plexpy.CONFIG.LOG_DIR, logger.FILENAME)}</a></td>
<td><a class="no-highlight" href="download_log" data-toggle="tooltip" data-placement="right" title="Download Log">${os.path.join(plexpy.CONFIG.LOG_DIR, logger.FILENAME)}</a></td>
</tr>
<tr>
<td>Backup Directory:</td>
@@ -77,78 +77,37 @@ DOCUMENTATION :: END
<a id="source-link" class="no-highlight" href="${anon_url('https://github.com/%s/plexpy' % plexpy.CONFIG.GIT_USER)}" target="_blank">GitHub Source</a> |
<a class="no-highlight guidelines-modal-link" href="${anon_url('https://github.com/%s/plexpy/issues' % plexpy.CONFIG.GIT_USER)}" data-id="issue">GitHub Issues</a> |
<a class="no-highlight guidelines-modal-link" href="${anon_url('http://feathub.com/%s/plexpy' % plexpy.CONFIG.GIT_USER)}" data-id="feature request">FeatHub Feature Requests</a> |
<a class="no-highlight" href="${anon_url('https://github.com/%s/plexpy/wiki' % plexpy.CONFIG.GIT_USER)}" target="_blank">PlexPy Wiki</a> |
<a id="faq-source-link" class="no-highlight" href="${anon_url('https://github.com/%s/plexpy/wiki/Frequently-Asked-Questions-(FAQ)' % plexpy.CONFIG.GIT_USER)}" target="_blank">PlexPy FAQ</a>
<a class="no-highlight" href="${anon_url('https://github.com/%s/plexpy/wiki' % plexpy.CONFIG.GIT_USER)}" target="_blank">Tautulli Wiki</a> |
<a id="faq-source-link" class="no-highlight" href="${anon_url('https://github.com/%s/plexpy/wiki/Frequently-Asked-Questions-(FAQ)' % plexpy.CONFIG.GIT_USER)}" target="_blank">Tautulli FAQ</a>
</td>
</tr>
<tr>
<td>Support:</td>
<td>
<a class="no-highlight support-modal-link" href="${anon_url('https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program')}" target="_blank">Plex Forums</a> |
<a class="no-highlight support-modal-link" href="${anon_url('https://gitter.im/plexpy/general')}" target="_blank">PlexPy Gitter Chat</a> |
<a id="best-support-link" class="no-highlight support-modal-link" href="${anon_url('https://discord.gg/011TFFWSuNFI02EKr')}" target="_blank">/r/Plex Discord Server</a> |
<a class="no-highlight support-modal-link" href="${anon_url('https://discord.gg/36ggawe')}" target="_blank">PlexPy Discord Server</a>
<a class="no-highlight support-modal-link" href="${anon_url('https://discord.gg/36ggawe')}" target="_blank">Tautulli Discord Server</a> |
<a class="no-highlight support-modal-link" href="${anon_url('https://www.reddit.com/r/Tautulli')}" target="_blank">Tautulli Subreddit</a> |
<a class="no-highlight support-modal-link" href="${anon_url('https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program')}" target="_blank">Plex Forums</a>
</td>
</tr>
</tbody>
</table>
<div id="guidelines-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="guidelines-modal">
<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">Guidelines</h4>
</div>
<div class="modal-body">
<div style="text-align: center; margin-top: 20px; margin-bottom: 20px;">
<strong>Please read the <a href="#" target="_blank" id="guidelines-link">guidelines</a> in the README document <br />before submitting a new <span id="guidelines-type"></span>!</strong>
<br /><br />
Your post may be removed for failure to follow the guidelines.
</div>
</div>
<div class="modal-footer">
<a href="#" target="_blank" id="guidelines-continue" class="btn btn-bright">Continue</a>
</div>
</div>
</div>
</div>
<div id="support-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="support-modal">
<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">Support</h4>
</div>
<div class="modal-body">
<div style="text-align: center; margin-top: 20px; margin-bottom: 20px;">
<strong>Please read the <a href="#" target="_blank" id="faq-link">FAQ</a> before asking for help!</strong>
</div>
</div>
<div class="modal-footer">
<a href="#" target="_blank" id="support-continue" class="btn btn-bright">Continue</a>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$("#install_geoip_db, #reinstall_geoip_db").click(function () {
var msg = 'Are you sure you want to install the GeoLite2 database?<br /><br />' +
'The database is used to lookup IP address geolocation info.<br />' +
'The database will be downloaded from <a href="${anon_url("https://dev.maxmind.com/geoip/geoip2/geolite2/")}" target="_blank">MaxMind</a>, <br />' +
'and requires <strong>100MB</strong> of free space to install in your PlexPy directory.<br />'
'and requires <strong>100MB</strong> of free space to install in your Tautulli directory.<br />'
var url = 'install_geoip_db';
confirmAjaxCall(url, msg, 'Installing GeoLite2 database.', getConfigurationTable);
confirmAjaxCall(url, msg, null, 'Installing GeoLite2 database.', getConfigurationTable);
});
$("#uninstall_geoip_db").click(function () {
var msg = 'Are you sure you want to uninstall the GeoLite2 database?<br /><br />' +
'You will not be able to lookup IP address geolocation info.';
var url = 'uninstall_geoip_db';
confirmAjaxCall(url, msg, 'Uninstalling GeoLite2 database.', getConfigurationTable);
confirmAjaxCall(url, msg, null, 'Uninstalling GeoLite2 database.', getConfigurationTable);
});
$('.guidelines-modal-link').on('click', function (e) {
@@ -168,5 +127,11 @@ DOCUMENTATION :: END
$('#support-modal').modal('hide');
});
});
$('body').tooltip({
selector: '[data-toggle="tooltip"]',
container: 'body'
});
});
</script>

View File

@@ -0,0 +1,904 @@
/*************** SCROLLBAR BASE CSS ***************/
.scroll-wrapper {
overflow: hidden !important;
padding: 0 !important;
position: relative;
}
.scroll-wrapper > .scroll-content {
border: none !important;
box-sizing: content-box !important;
height: auto;
left: 0;
margin: 0;
max-height: none;
max-width: none !important;
overflow: scroll !important;
padding: 0;
position: relative !important;
top: 0;
width: auto !important;
}
.scroll-wrapper > .scroll-content::-webkit-scrollbar {
height: 0;
width: 0;
}
.scroll-wrapper.scroll--rtl {
direction: rtl;
}
.scroll-element {
box-sizing: content-box;
display: none;
}
.scroll-element div {
box-sizing: content-box;
}
.scroll-element .scroll-bar,
.scroll-element .scroll-arrow {
cursor: default;
}
.scroll-element.scroll-x.scroll-scrollx_visible, .scroll-element.scroll-y.scroll-scrolly_visible {
display: block;
}
.scroll-textarea {
border: 1px solid #cccccc;
border-top-color: #999999;
}
.scroll-textarea > .scroll-content {
overflow: hidden !important;
}
.scroll-textarea > .scroll-content > textarea {
border: none !important;
box-sizing: border-box;
height: 100% !important;
margin: 0;
max-height: none !important;
max-width: none !important;
overflow: scroll !important;
outline: none;
padding: 2px;
position: relative !important;
top: 0;
width: 100% !important;
}
.scroll-textarea > .scroll-content > textarea::-webkit-scrollbar {
height: 0;
width: 0;
}
/*************** SIMPLE INNER SCROLLBAR ***************/
.scrollbar-inner > .scroll-element,
.scrollbar-inner > .scroll-element div {
border: none;
margin: 0;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-inner > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-inner > .scroll-element.scroll-x {
bottom: 2px;
height: 8px;
left: 0;
width: 100%;
}
.scrollbar-inner > .scroll-element.scroll-y {
height: 100%;
right: 2px;
top: 0;
width: 8px;
}
.scrollbar-inner > .scroll-element .scroll-element_outer {
overflow: hidden;
}
.scrollbar-inner > .scroll-element .scroll-element_outer,
.scrollbar-inner > .scroll-element .scroll-element_track,
.scrollbar-inner > .scroll-element .scroll-bar {
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.scrollbar-inner > .scroll-element .scroll-element_track,
.scrollbar-inner > .scroll-element .scroll-bar {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
filter: alpha(opacity=40);
opacity: 0.4;
}
.scrollbar-inner > .scroll-element .scroll-element_track {
background-color: #e0e0e0;
}
.scrollbar-inner > .scroll-element .scroll-bar {
background-color: #c2c2c2;
}
.scrollbar-inner > .scroll-element:hover .scroll-bar {
background-color: #919191;
}
.scrollbar-inner > .scroll-element.scroll-draggable .scroll-bar {
background-color: #919191;
}
/* update scrollbar offset if both scrolls are visible */
.scrollbar-inner > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track {
left: -12px;
}
.scrollbar-inner > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track {
top: -12px;
}
.scrollbar-inner > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size {
left: -12px;
}
.scrollbar-inner > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size {
top: -12px;
}
/*************** SIMPLE OUTER SCROLLBAR ***************/
.scrollbar-outer > .scroll-element,
.scrollbar-outer > .scroll-element div {
border: none;
margin: 0;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-outer > .scroll-element {
background-color: #ffffff;
}
.scrollbar-outer > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-outer > .scroll-element.scroll-x {
bottom: 0;
height: 12px;
left: 0;
width: 100%;
}
.scrollbar-outer > .scroll-element.scroll-y {
height: 100%;
right: 0;
top: 0;
width: 12px;
}
.scrollbar-outer > .scroll-element.scroll-x .scroll-element_outer {
height: 8px;
top: 2px;
}
.scrollbar-outer > .scroll-element.scroll-y .scroll-element_outer {
left: 2px;
width: 8px;
}
.scrollbar-outer > .scroll-element .scroll-element_outer {
overflow: hidden;
}
.scrollbar-outer > .scroll-element .scroll-element_track {
background-color: #eeeeee;
}
.scrollbar-outer > .scroll-element .scroll-element_outer,
.scrollbar-outer > .scroll-element .scroll-element_track,
.scrollbar-outer > .scroll-element .scroll-bar {
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
}
.scrollbar-outer > .scroll-element .scroll-bar {
background-color: #d9d9d9;
}
.scrollbar-outer > .scroll-element .scroll-bar:hover {
background-color: #c2c2c2;
}
.scrollbar-outer > .scroll-element.scroll-draggable .scroll-bar {
background-color: #919191;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-outer > .scroll-content.scroll-scrolly_visible {
left: -12px;
margin-left: 12px;
}
.scrollbar-outer > .scroll-content.scroll-scrollx_visible {
top: -12px;
margin-top: 12px;
}
.scrollbar-outer > .scroll-element.scroll-x .scroll-bar {
min-width: 10px;
}
.scrollbar-outer > .scroll-element.scroll-y .scroll-bar {
min-height: 10px;
}
/* update scrollbar offset if both scrolls are visible */
.scrollbar-outer > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track {
left: -14px;
}
.scrollbar-outer > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track {
top: -14px;
}
.scrollbar-outer > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size {
left: -14px;
}
.scrollbar-outer > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size {
top: -14px;
}
/*************** SCROLLBAR MAC OS X ***************/
.scrollbar-macosx > .scroll-element,
.scrollbar-macosx > .scroll-element div {
background: none;
border: none;
margin: 0;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-macosx > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-macosx > .scroll-element .scroll-element_track {
display: none;
}
.scrollbar-macosx > .scroll-element .scroll-bar {
background-color: #6C6E71;
display: block;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
opacity: 0;
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
-ms-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.scrollbar-macosx:hover > .scroll-element .scroll-bar,
.scrollbar-macosx > .scroll-element.scroll-draggable .scroll-bar {
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
filter: alpha(opacity=70);
opacity: 0.7;
}
.scrollbar-macosx > .scroll-element.scroll-x {
bottom: 0px;
height: 0px;
left: 0;
min-width: 100%;
overflow: visible;
width: 100%;
}
.scrollbar-macosx > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
right: 0px;
top: 0;
width: 0px;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-macosx > .scroll-element.scroll-x .scroll-bar {
height: 7px;
min-width: 10px;
top: -9px;
}
.scrollbar-macosx > .scroll-element.scroll-y .scroll-bar {
left: -9px;
min-height: 10px;
width: 7px;
}
.scrollbar-macosx > .scroll-element.scroll-x .scroll-element_outer {
left: 2px;
}
.scrollbar-macosx > .scroll-element.scroll-x .scroll-element_size {
left: -4px;
}
.scrollbar-macosx > .scroll-element.scroll-y .scroll-element_outer {
top: 2px;
}
.scrollbar-macosx > .scroll-element.scroll-y .scroll-element_size {
top: -4px;
}
/* update scrollbar offset if both scrolls are visible */
.scrollbar-macosx > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size {
left: -11px;
}
.scrollbar-macosx > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size {
top: -11px;
}
/*************** SCROLLBAR LIGHT ***************/
.scrollbar-light > .scroll-element,
.scrollbar-light > .scroll-element div {
border: none;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-light > .scroll-element {
background-color: #ffffff;
}
.scrollbar-light > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-light > .scroll-element .scroll-element_outer {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
.scrollbar-light > .scroll-element .scroll-element_size {
background: #dbdbdb;
background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2RiZGJkYiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlOGU4ZTgiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+");
background: -moz-linear-gradient(left, #dbdbdb 0%, #e8e8e8 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, #dbdbdb), color-stop(100%, #e8e8e8));
background: -webkit-linear-gradient(left, #dbdbdb 0%, #e8e8e8 100%);
background: -o-linear-gradient(left, #dbdbdb 0%, #e8e8e8 100%);
background: -ms-linear-gradient(left, #dbdbdb 0%, #e8e8e8 100%);
background: linear-gradient(to right, #dbdbdb 0%, #e8e8e8 100%);
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
.scrollbar-light > .scroll-element.scroll-x {
bottom: 0;
height: 17px;
left: 0;
min-width: 100%;
width: 100%;
}
.scrollbar-light > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
right: 0;
top: 0;
width: 17px;
}
.scrollbar-light > .scroll-element .scroll-bar {
background: #fefefe;
background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIxMDAlIiB5Mj0iMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZlZmVmZSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmNWY1ZjUiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+");
background: -moz-linear-gradient(left, #fefefe 0%, #f5f5f5 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%, #fefefe), color-stop(100%, #f5f5f5));
background: -webkit-linear-gradient(left, #fefefe 0%, #f5f5f5 100%);
background: -o-linear-gradient(left, #fefefe 0%, #f5f5f5 100%);
background: -ms-linear-gradient(left, #fefefe 0%, #f5f5f5 100%);
background: linear-gradient(to right, #fefefe 0%, #f5f5f5 100%);
border: 1px solid #dbdbdb;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-light > .scroll-content.scroll-scrolly_visible {
left: -17px;
margin-left: 17px;
}
.scrollbar-light > .scroll-content.scroll-scrollx_visible {
top: -17px;
margin-top: 17px;
}
.scrollbar-light > .scroll-element.scroll-x .scroll-bar {
height: 10px;
min-width: 10px;
top: 0px;
}
.scrollbar-light > .scroll-element.scroll-y .scroll-bar {
left: 0px;
min-height: 10px;
width: 10px;
}
.scrollbar-light > .scroll-element.scroll-x .scroll-element_outer {
height: 12px;
left: 2px;
top: 2px;
}
.scrollbar-light > .scroll-element.scroll-x .scroll-element_size {
left: -4px;
}
.scrollbar-light > .scroll-element.scroll-y .scroll-element_outer {
left: 2px;
top: 2px;
width: 12px;
}
.scrollbar-light > .scroll-element.scroll-y .scroll-element_size {
top: -4px;
}
/* update scrollbar offset if both scrolls are visible */
.scrollbar-light > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size {
left: -19px;
}
.scrollbar-light > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size {
top: -19px;
}
.scrollbar-light > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track {
left: -19px;
}
.scrollbar-light > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track {
top: -19px;
}
/*************** SCROLLBAR RAIL ***************/
.scrollbar-rail > .scroll-element,
.scrollbar-rail > .scroll-element div {
border: none;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-rail > .scroll-element {
background-color: #ffffff;
}
.scrollbar-rail > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-rail > .scroll-element .scroll-element_size {
background-color: #999;
background-color: rgba(0, 0, 0, 0.3);
}
.scrollbar-rail > .scroll-element .scroll-element_outer:hover .scroll-element_size {
background-color: #666;
background-color: rgba(0, 0, 0, 0.5);
}
.scrollbar-rail > .scroll-element.scroll-x {
bottom: 0;
height: 12px;
left: 0;
min-width: 100%;
padding: 3px 0 2px;
width: 100%;
}
.scrollbar-rail > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
padding: 0 2px 0 3px;
right: 0;
top: 0;
width: 12px;
}
.scrollbar-rail > .scroll-element .scroll-bar {
background-color: #d0b9a0;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5);
}
.scrollbar-rail > .scroll-element .scroll-element_outer:hover .scroll-bar {
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6);
}
/* scrollbar height/width & offset from container borders */
.scrollbar-rail > .scroll-content.scroll-scrolly_visible {
left: -17px;
margin-left: 17px;
}
.scrollbar-rail > .scroll-content.scroll-scrollx_visible {
margin-top: 17px;
top: -17px;
}
.scrollbar-rail > .scroll-element.scroll-x .scroll-bar {
height: 10px;
min-width: 10px;
top: 1px;
}
.scrollbar-rail > .scroll-element.scroll-y .scroll-bar {
left: 1px;
min-height: 10px;
width: 10px;
}
.scrollbar-rail > .scroll-element.scroll-x .scroll-element_outer {
height: 15px;
left: 5px;
}
.scrollbar-rail > .scroll-element.scroll-x .scroll-element_size {
height: 2px;
left: -10px;
top: 5px;
}
.scrollbar-rail > .scroll-element.scroll-y .scroll-element_outer {
top: 5px;
width: 15px;
}
.scrollbar-rail > .scroll-element.scroll-y .scroll-element_size {
left: 5px;
top: -10px;
width: 2px;
}
/* update scrollbar offset if both scrolls are visible */
.scrollbar-rail > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size {
left: -25px;
}
.scrollbar-rail > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size {
top: -25px;
}
.scrollbar-rail > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track {
left: -25px;
}
.scrollbar-rail > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track {
top: -25px;
}
/*************** SCROLLBAR DYNAMIC ***************/
.scrollbar-dynamic > .scroll-element,
.scrollbar-dynamic > .scroll-element div {
background: none;
border: none;
margin: 0;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-dynamic > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-dynamic > .scroll-element.scroll-x {
bottom: 2px;
height: 7px;
left: 0;
min-width: 100%;
width: 100%;
}
.scrollbar-dynamic > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
right: 2px;
top: 0;
width: 7px;
}
.scrollbar-dynamic > .scroll-element .scroll-element_outer {
opacity: 0.3;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
}
.scrollbar-dynamic > .scroll-element .scroll-element_size {
background-color: #cccccc;
opacity: 0;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
-webkit-transition: opacity 0.2s;
-moz-transition: opacity 0.2s;
-o-transition: opacity 0.2s;
-ms-transition: opacity 0.2s;
transition: opacity 0.2s;
}
.scrollbar-dynamic > .scroll-element .scroll-bar {
background-color: #6c6e71;
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-dynamic > .scroll-element.scroll-x .scroll-bar {
bottom: 0;
height: 7px;
min-width: 24px;
top: auto;
}
.scrollbar-dynamic > .scroll-element.scroll-y .scroll-bar {
left: auto;
min-height: 24px;
right: 0;
width: 7px;
}
.scrollbar-dynamic > .scroll-element.scroll-x .scroll-element_outer {
bottom: 0;
top: auto;
left: 2px;
-webkit-transition: height 0.2s;
-moz-transition: height 0.2s;
-o-transition: height 0.2s;
-ms-transition: height 0.2s;
transition: height 0.2s;
}
.scrollbar-dynamic > .scroll-element.scroll-y .scroll-element_outer {
left: auto;
right: 0;
top: 2px;
-webkit-transition: width 0.2s;
-moz-transition: width 0.2s;
-o-transition: width 0.2s;
-ms-transition: width 0.2s;
transition: width 0.2s;
}
.scrollbar-dynamic > .scroll-element.scroll-x .scroll-element_size {
left: -4px;
}
.scrollbar-dynamic > .scroll-element.scroll-y .scroll-element_size {
top: -4px;
}
/* update scrollbar offset if both scrolls are visible */
.scrollbar-dynamic > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size {
left: -11px;
}
.scrollbar-dynamic > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size {
top: -11px;
}
/* hover & drag */
.scrollbar-dynamic > .scroll-element:hover .scroll-element_outer,
.scrollbar-dynamic > .scroll-element.scroll-draggable .scroll-element_outer {
overflow: hidden;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
filter: alpha(opacity=70);
opacity: 0.7;
}
.scrollbar-dynamic > .scroll-element:hover .scroll-element_outer .scroll-element_size,
.scrollbar-dynamic > .scroll-element.scroll-draggable .scroll-element_outer .scroll-element_size {
opacity: 1;
}
.scrollbar-dynamic > .scroll-element:hover .scroll-element_outer .scroll-bar,
.scrollbar-dynamic > .scroll-element.scroll-draggable .scroll-element_outer .scroll-bar {
height: 100%;
width: 100%;
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
}
.scrollbar-dynamic > .scroll-element.scroll-x:hover .scroll-element_outer,
.scrollbar-dynamic > .scroll-element.scroll-x.scroll-draggable .scroll-element_outer {
height: 20px;
min-height: 7px;
}
.scrollbar-dynamic > .scroll-element.scroll-y:hover .scroll-element_outer,
.scrollbar-dynamic > .scroll-element.scroll-y.scroll-draggable .scroll-element_outer {
min-width: 7px;
width: 20px;
}
/*************** SCROLLBAR GOOGLE CHROME ***************/
.scrollbar-chrome > .scroll-element,
.scrollbar-chrome > .scroll-element div {
border: none;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
z-index: 10;
}
.scrollbar-chrome > .scroll-element {
background-color: #ffffff;
}
.scrollbar-chrome > .scroll-element div {
display: block;
height: 100%;
left: 0;
top: 0;
width: 100%;
}
.scrollbar-chrome > .scroll-element .scroll-element_track {
background: #f1f1f1;
border: 1px solid #dbdbdb;
}
.scrollbar-chrome > .scroll-element.scroll-x {
bottom: 0;
height: 16px;
left: 0;
min-width: 100%;
width: 100%;
}
.scrollbar-chrome > .scroll-element.scroll-y {
height: 100%;
min-height: 100%;
right: 0;
top: 0;
width: 16px;
}
.scrollbar-chrome > .scroll-element .scroll-bar {
background-color: #d9d9d9;
border: 1px solid #bdbdbd;
cursor: default;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
.scrollbar-chrome > .scroll-element .scroll-bar:hover {
background-color: #c2c2c2;
border-color: #a9a9a9;
}
.scrollbar-chrome > .scroll-element.scroll-draggable .scroll-bar {
background-color: #919191;
border-color: #7e7e7e;
}
/* scrollbar height/width & offset from container borders */
.scrollbar-chrome > .scroll-content.scroll-scrolly_visible {
left: -16px;
margin-left: 16px;
}
.scrollbar-chrome > .scroll-content.scroll-scrollx_visible {
top: -16px;
margin-top: 16px;
}
.scrollbar-chrome > .scroll-element.scroll-x .scroll-bar {
height: 8px;
min-width: 10px;
top: 3px;
}
.scrollbar-chrome > .scroll-element.scroll-y .scroll-bar {
left: 3px;
min-height: 10px;
width: 8px;
}
.scrollbar-chrome > .scroll-element.scroll-x .scroll-element_outer {
border-left: 1px solid #dbdbdb;
}
.scrollbar-chrome > .scroll-element.scroll-x .scroll-element_track {
height: 14px;
left: -3px;
}
.scrollbar-chrome > .scroll-element.scroll-x .scroll-element_size {
height: 14px;
left: -4px;
}
.scrollbar-chrome > .scroll-element.scroll-y .scroll-element_outer {
border-top: 1px solid #dbdbdb;
}
.scrollbar-chrome > .scroll-element.scroll-y .scroll-element_track {
top: -3px;
width: 14px;
}
.scrollbar-chrome > .scroll-element.scroll-y .scroll-element_size {
top: -4px;
width: 14px;
}
/* update scrollbar offset if both scrolls are visible */
.scrollbar-chrome > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_size {
left: -19px;
}
.scrollbar-chrome > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_size {
top: -19px;
}
.scrollbar-chrome > .scroll-element.scroll-x.scroll-scrolly_visible .scroll-element_track {
left: -19px;
}
.scrollbar-chrome > .scroll-element.scroll-y.scroll-scrollx_visible .scroll-element_track {
top: -19px;
}

View File

@@ -34,7 +34,7 @@ table.display {
margin: 0 auto;
clear: both;
width: 100%;
font-size: 14px;
font-size: 12px;
line-height: 25px;
/* Note Firefox 3.5 and before have a bug with border-collapse
* ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 )
@@ -332,4 +332,86 @@ div.box {
}
td.no-wrap, th.no-wrap {
white-space:nowrap;
}
}
/*
* Custom styles
*/
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);
}
table.display tr.shown + tr:hover a,
table.display tr.shown + tr td:hover a,
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^='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: #cc7b19;
}
table.display tr.shown + tr .pagination > .disabled > a,
table.display tr.shown + tr .pagination > .disabled > a:hover {
color: #444444;
}
table.display tr.shown + tr .pagination > li > a:hover {
color: #e9a049;
}
table.display tr.odd td,
table.display tr.even td {
padding: 5px 10px !important;
}
table[id^='history_child'] {
margin-top: 0;
opacity: .6;
}
table[id^='media_info_child'] {
margin-top: 0;
}
div[id^='history_child'] thead th,
div[id^='media_info_child'] thead th {
line-height: 0;
height: 0 !important;
overflow: hidden;
}
div[id^='history_child'] div.row,
div[id^='media_info_child'] div.row {
margin: 0;
}
div[id^='history_child'] div.col-sm-12,
div[id^='media_info_child'] div.col-sm-12 {
padding: 0;
}
div[id^='history_child'] div.dataTables_scrollBody,
div[id^='media_info_child'] div.dataTables_scrollBody {
overflow: hidden !important;
}
div[id^='media_info_child'] div[id^='media_info_child'] div.dataTables_scrollHead thead th {
line-height: 25px;
height: 35px !important;
overflow: hidden;
}
.current-activity-row {
background-color: rgba(255,255,255,.1) !important;
}
.current-activity-row:hover {
background-color: rgba(255,255,255,0.125) !important;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,328 +0,0 @@
<%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: current_activity.html
Version: 0.1
Variable names: data [list]
data :: Usable parameters
data['stream_count'] Returns the current number of active streams
data['sessions'] Returns an array containing session data
data[sessions] :: Usable parameters
== Global keys ==
session_key Returns a unique session id for the active stream
rating_key Returns the unique identifier for the media item.
media_index Returns the index of the media item.
parent_media_index Returns the index of the media item's parent.
media_type Returns the type of session. Either 'track', 'episode' or 'movie'.
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
bif_thumb Returns the location of the item's bif thumbnail. Use with pms_image_proxy.
art Returns the location of the item's artwork
progress_percent Returns the current progress of the item. 0 to 100.
user Returns the name of the user owning the session.
user_id Returns the Plex user id if available.
machine_id Returns the machine id of the players being used.
friendly_name Returns the friendlly name of the user owning the session.
user_thumb Returns the profile picture of the user owning the session.
state Returns the state of the current session. Either 'playing', 'paused' or 'buffering'.
title Returns the name of the episode, movie or music track.
year Returns the year of the episode, movie, or clip.
ip_address Returns the ip address of the stream.
player Returns the name of the platform used to play the stream.
platform Returns the type of platform used to play the stream.
throttled Returns true if the transcode session is throttled.
transcode_progress Returns the current transcode progress of the item. 0 to 100.
transcode_speed Returns the current transcode speed of the item.
audio_decision Returns the audio transcode decision. Either 'transcode', 'copy' or 'direct play'.
audio_codec Returns the name of the audio codec.
audio_channels Returns the number of audio channels.
grandparent_title Returns the title of the item's grandparent.
parent_title Returns the title of the item's parent.
video_decision Returns the video transcode decision. Either 'transcode', 'copy' or 'direct play'.
video_codec Returns the name of the video codec.
height Returns the value of the video height.
width Returns the value of the video width.
container Returns the value of the media container.
bitrate Returns the value of the media bitrate.
video_resolution Returns the value of the video resolution.
video_framerate Returns the value of the video framerate.
video_aspect_ratio Returns the value of the video aspect ratio.
transcode_audio_channels Returns the amount of audio channels if there is a transcode session.
transcode_audio_codec Returns the name of the audio codec if there is a transcode session.
transcode_video_codec Returns the name of the video codec if there is a transcode session.
transcode_width Returns the video width if there is a transcode session.
transcode_height Returns the video height if there is a transcode session.
transcode_container Returns the value of media container if there is a transcode session.
transcode_protocol Returns the value of media protocol if there is a transcode session.
indexes Returns true if the media has media indexes and are enabled
DOCUMENTATION :: END
</%doc>
% if data is not None:
% if data['stream_count'] != '0':
% 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') and a['rating_key']:
<a href="info?rating_key=${a['rating_key']}">
% else:
<a href="#">
% endif
<div class="dashboard-activity-poster">
% if not a['art'].startswith('interfaces') or not a['thumb'].startswith('interfaces'):
% 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&fallback=art);"></div>
% 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&fallback=art);"></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&fallback=art); display: none;"></div>
% else:
% if a['media_type'] == 'track':
<div class="dashboard-activity-cover-face-bg" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div>
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div>
% elif a['media_type'] == 'clip':
% if a['art'][:4] == 'http':
<div class="dashboard-activity-poster-face" style="background-image: url(${a['art']});"></div>
% elif a['thumb'][:4] == 'http':
<div class="dashboard-activity-poster-face" style="background-image: url(${a['thumb']});"></div>
% else:
% if a['art']:
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['art']}&width=500&height=280&fallback=art);"></div>
% else:
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=280&fallback=art);"></div>
% endif
% endif
% elif a['media_type'] == 'photo':
<div class="dashboard-activity-poster-face bif" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=500&height=500&fallback=cover);"></div>
% else:
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${a['thumb']}&width=300&height=300&fallback=cover);"></div>
% endif
% endif
% else:
<div class="dashboard-activity-poster-face" style="background-image: url(${a['art']});"></div>
% endif
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
<div class="dashboard-activity-button-info">
<button type="button" class="btn btn-activity-info btn-lg" data-target="#stream-${a['session_key']}">
<i class="fa fa-info-circle"></i>
</button>
</div>
<div id="stream-${a['session_key']}" class="dashboard-activity-info-details-overlay">
<div class="dashboard-activity-info-details-content">
<div id="platform-${a['session_key']}" title="${a['platform']}">
<script>
$("#platform-${a['session_key']}").html("<div class='dashboard-activity-info-platform-box' style='background-image: url(" + getPlatformImagePath('${a['platform']}') + ");'>");
</script>
</div>
<div class="dashboard-activity-info-platform">
<strong>${a['player']}</strong><br />
% if a['state'] == 'playing':
State &nbsp;<strong>Playing</strong>
% elif a['state'] == 'paused':
State &nbsp;<strong>Paused</strong>
% elif a['state'] == 'buffering':
State &nbsp;<strong>Buffering</strong>
% endif
</div>
% if a['media_type'] == 'track':
% if a['audio_decision'] == 'direct play':
Stream &nbsp;<strong>Direct Play</strong>
% elif a['audio_decision'] == 'copy':
Stream &nbsp;<strong>Direct Stream</strong>
% else:
Stream &nbsp;<strong>Transcoding
(Speed: ${a['transcode_speed']})
% if a['throttled'] == '1':
(Throttled)
% endif
</strong>
% endif
<br />
% if a['audio_decision'] == 'direct play':
Audio &nbsp;<strong>Direct Play (${a['audio_codec']}) (${a['audio_channels']}ch)</strong>
% elif a['audio_decision'] == 'copy':
Audio &nbsp;<strong>Direct Stream (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
% elif a['audio_decision'] == 'transcode':
Audio &nbsp;<strong>Transcode (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
% endif
% elif a['media_type'] == 'episode' or a['media_type'] == 'movie' or a['media_type'] == 'clip':
% if a['video_decision'] == 'direct play' and a['audio_decision'] == 'direct play':
Stream &nbsp;<strong>Direct Play</strong>
% elif a['video_decision'] == 'copy' and a['audio_decision'] == 'copy':
Stream &nbsp;<strong>Direct Stream</strong>
% else:
Stream &nbsp;<strong>Transcoding
(Speed: ${a['transcode_speed']})
% if a['throttled'] == '1':
(Throttled)
% endif
</strong>
% endif
<br />
% if a['video_decision'] == 'direct play':
Video &nbsp;<strong>Direct Play (${a['video_codec']}) (${a['width']}x${a['height']})</strong>
% elif a['video_decision'] == 'copy':
Video &nbsp;<strong>Direct Stream (${a['transcode_video_codec']}) (${a['width']}x${a['height']})</strong>
% elif a['video_decision'] == 'transcode':
Video &nbsp;<strong>Transcode (${a['transcode_video_codec']}) (${a['transcode_width']}x${a['transcode_height']})</strong>
% endif
<br />
% if a['audio_decision'] == 'direct play':
Audio &nbsp;<strong>Direct Play (${a['audio_codec']}) (${a['audio_channels']}ch)</strong>
% elif a['audio_decision'] == 'copy':
Audio &nbsp;<strong>Direct Stream (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
% elif a['audio_decision'] == 'transcode':
Audio &nbsp;<strong>Transcode (${a['transcode_audio_codec']}) (${a['transcode_audio_channels']}ch)</strong>
% endif
% elif a['media_type'] == 'photo':
% if a['video_decision'] == 'direct play':
Stream &nbsp;<strong>Direct Play</strong>
% elif a['video_decision'] == 'copy':
Stream &nbsp;<strong>Direct Stream</strong>
% else:
Stream &nbsp;<strong>
Transcoding
(Speed: ${a['transcode_speed']})
% if a['throttled'] == '1':
(Throttled)
% endif
</strong>
% endif
% endif
<br>
</div>
</div>
% if a['media_type'] != 'photo':
<div class="dashboard-activity-poster-info-bar">
<div class="dashboard-activity-poster-info-ip-address">
% if a['ip_address']:
<span>IP: ${a['ip_address']}</span>
% else:
<span>IP: N/A</span>
% endif
<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>
</div>
</div>
% endif
</div>
% if (a['media_type'] == 'movie' or a['media_type'] == 'episode' or a['media_type'] == 'track') and a['rating_key']:
</a>
% else:
</a>
% endif
<div class="dashboard-activity-progress">
<div class="dashboard-activity-progress-bar">
<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">
% if a['user_id']:
<a href="user?user_id=${a['user_id']}">
<div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${a['user_thumb']});"></div>
</a>
% else:
<div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${a['user_thumb']});"></div>
% endif
<div class="dashboard-activity-metadata-title">
% if a['state'] == 'playing':
<i class="fa fa-play"></i>&nbsp;
% elif a['state'] == 'paused':
<i class="fa fa-pause"></i>&nbsp;
% elif a['state'] == 'buffering':
<i class="fa fa-spinner"></i>&nbsp;
% endif
% if a['rating_key']:
% if a['media_type'] == 'episode':
<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?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?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:
<span title="${a['title']}">${a['title']}</span>
% endif
% else:
${a['title']}
% endif
</div>
<div class="dashboard-activity-metadata-subtitle">
% if a['rating_key']:
% if a['media_type'] == 'episode':
<span title="S${a['parent_media_index']} &middot; E${a['media_index']}">S${a['parent_media_index']} &middot; E${a['media_index']}</span>
% elif a['media_type'] == 'movie':
<span title="${a['year']}">${a['year']}</span>
% elif a['media_type'] == 'track':
<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:
<span title="${a['year']}">${a['year']}</span>
% endif
% 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['friendly_name']}
% endif
</div>
</div>
</div>
% endfor
<script>
// When using bif indexes make the image transition a little smoother.
$('.bif').each(function() {
$(this).hide().fadeIn(1000);
});
// Convert timestamps to readable times
$('.progress_time').each(function(index) {
$(this).html(millisecondsToMinutes($(this).text(), false));
});
// Show/Hide activity info
$('.btn-activity-info').on('click', function(e) {
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>
% endif
% else:
<div class="text-muted">There was an error communicating with your Plex Server. Please check your <a
href="settings">settings</a>.
</div><br>
% endif

View File

@@ -30,7 +30,7 @@ year Returns the year of the episode, movie, or clip.
ip_address Returns the ip address of the stream.
player Returns the name of the platform used to play the stream.
platform Returns the type of platform used to play the stream.
throttled Returns true if the transcode session is throttled.
transcode_throttled Returns true if the transcode session is throttled.
transcode_progress Returns the current transcode progress of the item. 0 to 100.
transcode_speed Returns the current transcode speed of the item.
audio_decision Returns the audio transcode decision. Either 'transcode', 'copy' or 'direct play'.
@@ -59,169 +59,304 @@ indexes Returns true if the media has media indexes and are
DOCUMENTATION :: END
</%doc>
% if data is not None:
% if session is not None:
<%
from collections import defaultdict
from urllib import quote
from plexpy import helpers
data['indexes'] = helpers.cast_to_int(data['indexes'])
import plexpy
%>
<div class="dashboard-instance" id="instance-${data['session_key']}" data-id="${data['session_key']}">
<div class="dashboard-hover-container">
% if (data['media_type'] == 'movie' or data['media_type'] == 'episode' or data['media_type'] == 'track') and data['rating_key']:
<a href="info?rating_key=${data['rating_key']}">
<% data = defaultdict(lambda: 'Unknown', **session) %>
<% sk = data['session_key'] %>
<div class="dashboard-activity-instance" id="activity-instance-${sk}" data-key="${sk}" data-id="${data['session_id']}"
data-rating_key="${data['rating_key']}" data-parent_rating_key="${data['parent_rating_key']}" data-grandparent_rating_key="${data['grandparent_rating_key']}">
<div class="dashboard-activity-container">
<div class="dashboard-activity-background-overlay">
% if data['channel_stream'] == 0:
<div id="background-${sk}" class="dashboard-activity-background" style="background-image: url(pms_image_proxy?img=${data['art']}&width=500&height=280&fallback=art&refresh=true);"></div>
% else:
<a href="#">
% if (data['art'] and data['art'].startswith('http')) or (data['thumb'] and data['thumb'].startswith('http')):
<div id="background-${sk}" class="dashboard-activity-background" style="background-image: url(${data['art']});"></div>
% else:
<!--Hacky solution to escape the image url until I come up with something better-->
<div id="background-${sk}" class="dashboard-activity-background" style="background-image: url(pms_image_proxy?img=${quote(data['art'] or data['thumb'])}&width=500&height=280&fallback=art&refresh=true&clip=true);"></div>
% endif
<div class="dashboard-activity-poster" id="poster-${data['session_key']}">
% if not data['art'].startswith('interfaces') or not data['thumb'].startswith('interfaces'):
% if (data['media_type'] == 'movie' and not data['indexes']) or (data['indexes'] and not data['view_offset']):
<div id="bif-${data['session_key']}" class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${data['art']}&width=500&height=280&fallback=art);"></div>
% elif (data['media_type'] == 'episode' and not data['indexes']) or (data['indexes'] and not data['view_offset']):
<div id="bif-${data['session_key']}" class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${data['art']}&width=500&height=280&fallback=art);"></div>
% elif data['indexes']:
<div id="bif-${data['session_key']}" class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${data['bif_thumb']}&width=500&height=280&fallback=art); display: none;"></div>
% endif
<div class="dashboard-activity-poster-container hidden-xs">
% if data['media_type'] == 'track':
<div id="poster-${sk}-bg" class="dashboard-activity-poster-blur" style="background-image: url(pms_image_proxy?img=${data['parent_thumb']}&width=300&height=300&fallback=cover&refresh=true);"></div>
% endif
% if data['channel_stream'] == 0:
% if data['media_type'] == 'movie':
<a id="poster-url-${sk}" href="info?rating_key=${data['rating_key']}" title="${data['title']}">
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=450&fallback=poster&refresh=true);"></div>
</a>
% elif data['media_type'] == 'episode':
<a id="poster-url-${sk}" href="info?rating_key=${data['grandparent_rating_key']}" title="${data['grandparent_title']}">
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(pms_image_proxy?img=${data['grandparent_thumb']}&width=300&height=450&fallback=poster&refresh=true);"></div>
</a>
% elif data['media_type'] == 'track':
<a id="poster-url-${sk}" href="info?rating_key=${data['parent_rating_key']}" title="${data['parent_title']}">
<div id="poster-${sk}" class="dashboard-activity-cover" style="background-image: url(pms_image_proxy?img=${data['parent_thumb']}&width=300&height=300&fallback=cover&refresh=true);"></div>
</a>
% elif data['media_type'] in ('photo', 'clip'):
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(pms_image_proxy?img=${data['parent_thumb']}&width=300&height=450&fallback=poster&refresh=true);"></div>
% else:
% if data['media_type'] == 'track':
<div class="dashboard-activity-cover-face-bg" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=300&fallback=cover);"></div>
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=300&fallback=cover);"></div>
% elif data['media_type'] == 'clip':
% if data['art'].startswith('http'):
<div class="dashboard-activity-poster-face" style="background-image: url(${data['art']});"></div>
% elif data['thumb'].startswith('http'):
<div class="dashboard-activity-poster-face" style="background-image: url(${data['thumb']});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(images/art.png);"></div>
% endif
% else:
% if data['channel_icon'].startswith('http'):
<div id="poster-${sk}" class="dashboard-activity-poster-blur" style="background-image: url(${data['channel_icon']});"></div>
<div id="poster-${sk}" class="dashboard-activity-cover" style="background-image: url(${data['channel_icon']});"></div>
% else:
% if data['art']:
<!--Hacky solution to escape the image url until I come up with something better-->
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${quote(data['art'])}&width=500&height=280&fallback=art);"></div>
% else:
<!--Hacky solution to escape the image url until I come up with something better-->
<div class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${quote(data['thumb'])}&width=500&height=280&fallback=art);"></div>
<div id="poster-${sk}" class="dashboard-activity-poster-blur" style="background-image: url(pms_image_proxy?img=${data['channel_icon']}&width=300&height=300&fallback=cover&refresh=true);"></div>
<div id="poster-${sk}" class="dashboard-activity-cover" style="background-image: url(pms_image_proxy?img=${data['channel_icon']}&width=300&height=300&fallback=cover&refresh=true);"></div>
% endif
% endif
% elif data['media_type'] == 'photo':
<div id="bif-${data['session_key']}" class="dashboard-activity-poster-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=500&fallback=cover);"></div>
% else:
<div class="dashboard-activity-cover-face" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=300&height=300&fallback=cover);"></div>
% endif
% endif
% else:
<div class="dashboard-activity-poster-face" style="background-image: url(${data['art']});"></div>
% endif
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image left" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
<div class="dashboard-activity-button-info">
<button type="button" class="btn btn-activity-info btn-lg" data-target="#stream-${data['session_key']}" data-id="${data['session_key']}">
<i class="fa fa-info-circle"></i>
</button>
</div>
<div id="stream-${data['session_key']}" class="dashboard-activity-info-details-overlay">
<div class="dashboard-activity-info-details-content">
<div id="platform-${data['session_key']}" title="${data['platform']}">
<script>
$("#platform-${data['session_key']}").html("<div class='dashboard-activity-info-platform-box' style='background-image: url(" + getPlatformImagePath('${data['platform']}') + ");'>");
</script>
</div>
<div class="dashboard-activity-info-platform">
<strong>${data['player']}</strong><br />
<span id="overlay-play-state-${data['session_key']}">
% if data['state'] == 'playing':
State &nbsp;<strong>Playing</strong>
% elif data['state'] == 'paused':
State &nbsp;<strong>Paused</strong>
% elif data['state'] == 'buffering':
State &nbsp;<strong>Buffering</strong>
% endif
</span>
</div>
<span id="transcode-state-${data['session_key']}">
% if data['video_decision'] == 'transcode' or data['audio_decision'] == 'transcode':
Stream &nbsp;<strong>Transcode (Speed: ${data['transcode_speed']})
% if data['throttled'] == '1':
(Throttled)
% endif
</strong>
% elif data['video_decision'] == 'copy' or data['audio_decision'] == 'copy':
Stream &nbsp;<strong>Direct Stream</strong>
% else:
Stream &nbsp;<strong>Direct Play</strong>
% endif
<br />
% if data['video_decision'] and data['media_type'] != 'photo':
% if data['video_decision'] == 'transcode':
Video &nbsp;<strong>Transcode (${data['transcode_video_codec']}) (${data['transcode_width']}x${data['transcode_height']})</strong>
% elif data['video_decision'] == 'copy':
Video &nbsp;<strong>Direct Stream (${data['transcode_video_codec']}) (${data['width']}x${data['height']})</strong>
% endif
</div>
<div class="dashboard-activity-info-icon">
<%
if not _session['user_group'] == 'admin' or not data['session_id']:
no_terminate = '-no-terminate'
else:
no_terminate = ''
%>
<div id="platform-${sk}" class="dashboard-activity-info-platform${no_terminate} svg-icon platform-${data['platform_name']}" title="${data['platform']}"></div>
% if _session['user_group'] == 'admin' and plexpy.CONFIG.PMS_PLEXPASS and data['session_id']:
<div class="dashboard-activity-terminate-session" id="terminate-button-${sk}" data-key="${sk}" data-id="${data['session_id']}" data-toggle="tooltip" title="Terminate Stream">
<i class="fa fa-times" style="padding-top: 8px;"></i>
</div>
% endif
</div>
<div class="dashboard-activity-info-container">
<div class="dashboard-activity-info-scroller scrollbar-macosx">
<div class="dashboard-activity-info scoller-content">
<ul class="list-unstyled dashboard-activity-info-list">
<li class="dashboard-activity-info-item">
<div class="sub-heading">Product</div>
<div class="sub-value">${data['product']}</div>
</li>
<li class="dashboard-activity-info-item">
<div class="sub-heading">Player</div>
<div class="sub-value">${data['player']}</div>
</li>
<li class="dashboard-activity-info-item">
<div class="sub-heading">Quality</div>
<div class="sub-value" id="stream_quality-${sk}">
% if data['media_type'] != 'photo' and data['quality_profile'] != 'Unknown':
<%
br = helpers.cast_to_int(data['stream_bitrate']) or ''
if br:
if br > 1000:
br = '(' + str(round(br / 1000.0, 1)) + ' Mbps)'
else:
br = '(' + str(br) + ' kbps)'
%>
${data['quality_profile']} ${br}
% else:
Video &nbsp;<strong>Direct Play (${data['video_codec']}) (${data['width']}x${data['height']})</strong>
${data['quality_profile']}
% endif
<br />
% endif
% if data['audio_decision']:
% if data['audio_decision'] == 'transcode':
Audio &nbsp;<strong>Transcode (${data['transcode_audio_codec']}) (${data['transcode_audio_channels']}ch)</strong>
% elif data['audio_decision'] == 'copy':
Audio &nbsp;<strong>Direct Stream (${data['transcode_audio_codec']}) (${data['transcode_audio_channels']}ch)</strong>
% else:
Audio &nbsp;<strong>Direct Play (${data['audio_codec']}) (${data['audio_channels']}ch)</strong>
% endif
% endif
</span>
</div>
</div>
% if data['media_type'] != 'photo':
<div class="dashboard-activity-poster-info-bar">
<div class="dashboard-activity-poster-info-ip-address">
% if data['ip_address']:
<span>IP: ${data['ip_address']}</span>
% else:
<span>IP: N/A</span>
</div>
</li>
% if data['optimized_version'] == 1:
<li class="dashboard-activity-info-item">
<div class="sub-heading">Optimized</div>
<div class="sub-value" id="optimized_version-${sk}">
${data['optimized_version_profile']} (${data['optimized_version_title']})
</div>
</li>
% endif
<br />
ETA:
<span id="stream-eta-${data['session_key']}">
<script>
$("#stream-eta-${data['session_key']}").html(moment().add(parseInt("${data['duration']}") - parseInt("${data['view_offset']}"), 'milliseconds').format(time_format));
</script>
</span>
</div>
<div class="dashboard-activity-poster-info-time">
<span class="progress_time" id="stream-view-offset-${data['session_key']}">
<script>
$("#stream-view-offset-${data['session_key']}").html(millisecondsToMinutes(parseInt("${data['view_offset']}"), false));
</script>
</span>/<span class="progress_time" id="stream-duration-${data['session_key']}">
<script>
$("#stream-duration-${data['session_key']}").html(millisecondsToMinutes(parseInt("${data['duration']}"), false));
</script>
</span>
</div>
% if data['synced_version'] == 1:
<li class="dashboard-activity-info-item">
<div class="sub-heading">Synced</div>
<div class="sub-value" id="synced_version-${sk}">
${data['synced_version_profile']}
</div>
</li>
% endif
</ul>
<ul class="list-unstyled dashboard-activity-info-list">
<li class="dashboard-activity-info-item">
% if _session['user_group'] == 'admin':
<div class="sub-heading"><span class="raw-stream-info-modal" data-toggle="modal" data-target="#raw-stream-info-modal" data-key="${sk}">Stream</span></div>\
% else:
<div class="sub-heading">Stream</div>
% endif
<div class="sub-value" id="transcode_decision-${sk}">
% if data['transcode_decision'] == 'transcode':
Transcode
% if data['transcode_throttled'] == 1:
(Throttled)
% else:
(Speed: ${data['transcode_speed']})
% endif
% elif data['transcode_decision'] == 'copy':
Direct Stream
% else:
Direct Play
% endif
</div>
</li>
<li class="dashboard-activity-info-item">
<div class="sub-heading">Container</div>
<div class="sub-value" id="transcode_container-${sk}">
% if data.get('stream_container_decision') == 'transcode':
Transcode (${data['container'].upper()} &rarr; ${data['stream_container'].upper()})
% else:
Direct Play (${data['container'].upper()})
% endif
</div>
</li>
% if data['media_type'] in ('movie', 'episode', 'clip', 'photo'):
<li class="dashboard-activity-info-item">
<div class="sub-heading">Video</div>
<div class="sub-value" id="video_decision-${sk}">
% if data['media_type'] in ('movie', 'episode', 'clip'):
% if data.get('stream_video_decision') == 'transcode':
<%
hw_d = hw_e = ''
if data['transcode_hw_requested'] == 1 and data['transcode_hw_full_pipeline'] == 0:
hw_d = ' (HW)'
elif data['transcode_hw_requested'] == 1 and data['transcode_hw_full_pipeline'] == 1:
hw_d = hw_e = ' (HW)'
%>
Transcode (${data['video_codec'].upper()}${hw_d} ${plexpy.common.VIDEO_RESOLUTION_OVERRIDES.get(data['video_resolution'], data['video_resolution'])} &rarr; ${data['stream_video_codec'].upper()}${hw_e} ${plexpy.common.VIDEO_RESOLUTION_OVERRIDES.get(data['stream_video_resolution'], data['stream_video_resolution'])})
% elif data.get('stream_video_decision') == 'copy':
Direct Stream (${data['stream_video_codec'].upper()} ${plexpy.common.VIDEO_RESOLUTION_OVERRIDES.get(data['stream_video_resolution'], data['stream_video_resolution'])})
% else:
Direct Play (${data['video_codec'].upper()} ${plexpy.common.VIDEO_RESOLUTION_OVERRIDES.get(data['video_resolution'], data['video_resolution'])})
% endif
% elif data['media_type'] == 'photo':
Direct Play (${data['width']}x${data['height']})
% endif
</div>
</li>
% endif
% if data['media_type'] in ('movie', 'episode', 'clip', 'track'):
<li class="dashboard-activity-info-item">
<div class="sub-heading">Audio</div>
<div class="sub-value" id="audio_decision-${sk}">
% if data.get('stream_audio_decision') == 'transcode':
Transcode (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} ${data['audio_channel_layout'].split('(')[0].capitalize()} &rarr; ${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
% elif data.get('stream_audio_decision') == 'copy':
Direct Stream (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
% else:
Direct Play (${plexpy.common.AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} ${data['audio_channel_layout'].split('(')[0].capitalize()})
% endif
</div>
</li>
% endif
% if data['media_type'] in ('movie', 'episode', 'clip'):
<li class="dashboard-activity-info-item">
<div class="sub-heading">Subtitle</div>
<div class="sub-value" id="subtitle_decision-${sk}">
% if data['subtitles'] == 1:
% if data['stream_subtitle_decision'] == 'transcode':
Transcode (${data['subtitle_codec'].upper()} &rarr; ${data['stream_subtitle_codec'].upper()})
% elif data['stream_subtitle_decision'] == 'copy':
Direct Stream (${data['subtitle_codec'].upper()})
% elif data['stream_subtitle_decision'] == 'burn':
Burn (${data['subtitle_codec'].upper()})
% else:
Direct Play (${data['stream_subtitle_codec'].upper() if data['synced_version'] else data['subtitle_codec'].upper()})
% endif
% else:
None
% endif
</div>
</li>
% endif
</ul>
<ul class="list-unstyled dashboard-activity-info-list">
<li class="dashboard-activity-info-item">
<div class="sub-heading">Location</div>
<div class="sub-value">
% if data['ip_address'] != 'N/A':
${'LAN' if data['local'] == 1 else 'WAN'}: ${data['ip_address']}
<a href="#" class="external_ip-modal" data-toggle="modal" data-target="#ip-info-modal" data-ip="${data['ip_address']}">
<span id="external_ip-${sk}" class="external-ip-tooltip" data-toggle="tooltip" title="Lookup IP" style="display: none;"><i class="fa fa-map-marker"></i></span>
</a>
<script>
isPrivateIP("${data['ip_address']}").then(function () {
$("#external_ip-${sk}").hide();
}, function () {
$("#external_ip-${sk}").show();
});
</script>
% else:
N/A
% endif
</div>
</li>
<li class="dashboard-activity-info-item">
<div class="sub-heading">Bandwidth</div>
<div class="sub-value">
% if data['media_type'] != 'photo' and helpers.cast_to_int(data['bandwidth']):
<%
bw = helpers.cast_to_int(data['bandwidth'])
if bw != "Unknown":
if bw > 1000:
bw = str(round(bw / 1000.0, 1)) + ' Mbps'
else:
bw = str(bw) + ' kbps'
%>
<span id="stream-bandwidth-${sk}">${bw}</span>
<span id="streaming-brain-${sk}" data-toggle="tooltip" title="Streaming Brain Estimate"><i class="fa fa-info-circle"></i></span>
% elif data['synced_version'] == 1 or data['channel_stream'] == 1:
<span id="stream-bandwidth-${sk}">None</span>
% else:
<span id="stream-bandwidth-${sk}">Unknown</span>
% endif
</div>
</li>
</ul>
</div>
</div>
% if data['media_type'] != 'photo':
<div class="dashboard-activity-info-time">
% if data['view_offset']:
ETA:
<span id="stream-eta-${sk}">
<script>
$("#stream-eta-${sk}").html(moment().add(parseInt("${data['stream_duration']}") - parseInt("${data['view_offset']}"), 'milliseconds').format(time_format));
</script>
</span><br /><span class="progress_time_offset" id="stream-view-offset-${sk}" data-last_view_offset="${data['view_offset']}" data-view_offset="${data['view_offset']}" data-stream_duration="${data['stream_duration']}" data-state="${data['state']}">
<script>
$("#stream-view-offset-${sk}").html(millisecondsToMinutes(parseInt("${data['view_offset']}"), false));
</script>
</span> / <span class="progress_time_total" id="stream-duration-${sk}">
<script>
$("#stream-duration-${sk}").html(millisecondsToMinutes(parseInt("${data['stream_duration']}"), false));
</script>
</span>
% else:
ETA: Unknown<br />0:00 / <span class="progress_time_total" id="stream-duration-${sk}">
<script>
$("#stream-duration-${sk}").html(millisecondsToMinutes(parseInt("${data['stream_duration']}"), false));
</script>
</span>
% endif
</div>
% if (data['media_type'] == 'movie' or data['media_type'] == 'episode' or data['media_type'] == 'track') and data['rating_key']:
</a>
% else:
</a>
% endif
% endif
</div>
</div>
<div class="dashboard-activity-progress">
<div class="dashboard-activity-progress-bar">
<div id="bufferbar-${data['session_key']}" class="bufferbar" style="width: ${data['transcode_progress']}%" data-toggle="tooltip" title="Transcoder Progress ${data['transcode_progress']}%">${data['transcode_progress']}%</div>
<div id="bar-${data['session_key']}" class="bar" style="width: ${data['progress_percent']}%" data-toggle="tooltip" title="Stream Progress ${data['progress_percent']}%">${data['progress_percent']}%</div>
<div id="buffer-bar-${sk}" class="buffer-bar" style="width: ${data['transcode_progress']}%" data-toggle="tooltip" title="Transcoder Progress ${data['transcode_progress']}%">${data['transcode_progress']}%</div>
<div id="progress-bar-${sk}" class="progress-bar" style="width: ${data['progress_percent']}%" data-last_view_offset="${data['view_offset']}" data-view_offset="${data['view_offset']}" data-stream_duration="${data['stream_duration']}" data-state="${data['state']}" data-toggle="tooltip" title="Stream Progress ${data['progress_percent']}%">${data['progress_percent']}%</div>
</div>
</div>
</div>
<div class="dashboard-activity-metadata-wrapper">
% if data['user_id']:
<a href="user?user_id=${data['user_id']}">
<a href="user?user_id=${data['user_id']}" title="${data['friendly_name']}">
<div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${data['user_thumb']});"></div>
</a>
% else:
<div class="dashboard-activity-metadata-user-thumb" style="background-image: url(${data['user_thumb']});"></div>
% endif
<div class="dashboard-activity-metadata-title">
<span id="play-state-${data['session_key']}">
<div class="dashboard-activity-metadata-title-container">
<div id="play-state-${sk}" class="dashboard-activity-metadata-play_state-icon" title="${data['state'].capitalize()}">
% if data['state'] == 'playing':
<i class="fa fa-fw fa-play"></i>&nbsp;
% elif data['state'] == 'paused':
@@ -229,49 +364,91 @@ DOCUMENTATION :: END
% elif data['state'] == 'buffering':
<i class="fa fa-fw fa-spinner"></i>&nbsp;
% endif
</span>
% if data['rating_key']:
% if data['media_type'] == 'episode':
<a href="info?rating_key=${data['grandparent_rating_key']}" title="${data['grandparent_title']}">${data['grandparent_title']}</a>
- <a href="info?rating_key=${data['rating_key']}" title="${data['title']}">${data['title']}</a>
% elif data['media_type'] == 'movie':
<a href="info?rating_key=${data['rating_key']}" title="${data['title']}">${data['title']}</a>
% elif data['media_type'] == 'clip':
<span title="${data['title']}">${data['title']}</span>
% elif data['media_type'] == 'track':
<a href="info?rating_key=${data['grandparent_rating_key']}" title="${data['grandparent_title']}">${data['grandparent_title']}</a>
- <a href="info?rating_key=${data['rating_key']}" title="${data['title']}">${data['title']}</a>
% elif data['media_type'] == 'photo':
<span title="${data['parent_title']}">${data['parent_title']}</span>
% else:
<span title="${data['title']}">${data['title']}</span>
% endif
% else:
${data['title']}
% endif
</div>
<div class="dashboard-activity-metadata-title">
% if data['channel_stream'] == 0:
% if data['media_type'] == 'movie':
<a href="info?rating_key=${data['rating_key']}" title="${data['title']}">${data['title']}</a>
% elif data['media_type'] == 'episode':
<a href="info?rating_key=${data['grandparent_rating_key']}" title="${data['grandparent_title']}">${data['grandparent_title']}</a>
- <a href="info?rating_key=${data['rating_key']}" title="${data['title']}">${data['title']}</a>
% elif data['media_type'] == 'track':
<a id="metadata-grandparent_title-${sk}" href="info?rating_key=${data['grandparent_rating_key']}" title="${data['grandparent_title']}">${data['grandparent_title']}</a>
- <a id="metadata-title-${sk}" href="info?rating_key=${data['rating_key']}" title="${data['title']}">${data['title']}</a>
% elif data['media_type'] == 'photo':
<span title="${data['parent_title']}">${data['parent_title']}</span>
% elif data['media_type'] == 'clip':
<span title="${data['title']}">${data['title']}</span>
% else:
<span title="${data['title']}">${data['title']}</span>
% endif
% elif data['media_type'] == 'episode' and data['grandparent_title']:
<span title="${data['grandparent_title']}">${data['grandparent_title']}</span>
- <span title="${data['title']}">${data['title']}</span>
% else:
<span title="${data['title']}">${data['title']}</span>
% endif
</div>
</div>
<div class="dashboard-activity-metadata-subtitle">
% if data['rating_key']:
% if data['media_type'] == 'episode':
<a href="info?rating_key=${data['parent_rating_key']}" title="Season ${data['parent_media_index']}" class="text-muted">S${data['parent_media_index']}</a>
&middot; <a href="info?rating_key=${data['rating_key']}" title="Episode ${data['media_index']}" class="text-muted">E${data['media_index']}</a>
% elif data['media_type'] == 'movie':
<span title="${data['year']}">${data['year']}</span>
% elif data['media_type'] == 'track':
<a href="info?rating_key=${data['parent_rating_key']}" title="${data['parent_title']}">${data['parent_title']}</a>
% elif data['media_type'] == 'photo':
<span title="${data['title']}">${data['title']}</span>
<div class="dashboard-activity-metadata-subtitle-container">
% if data['channel_stream'] == 0:
<div id="media-type-${sk}" class="dashboard-activity-metadata-media_type-icon" title="${data['media_type'].capitalize()}">
% if data['media_type'] == 'movie':
<i class="fa fa-fw fa-film"></i>&nbsp;
% elif data['media_type'] == 'episode':
<i class="fa fa-fw fa-television"></i>&nbsp;
% elif data['media_type'] == 'track':
<i class="fa fa-fw fa-music"></i>&nbsp;
% elif data['media_type'] == 'photo':
<i class="fa fa-fw fa-picture-o"></i>&nbsp;
% elif data['media_type'] == 'clip':
<i class="fa fa-fw fa-video-camera"></i>&nbsp;
% endif
</div>
% else:
<span title="${data['year']}">${data['year']}</span>
% endif
% endif
</div>
<div class="dashboard-activity-metadata-user">
% if data['user_id']:
<a href="user?user_id=${data['user_id']}" title="${data['friendly_name']}">${data['friendly_name']}</a>
% else:
${data['friendly_name']}
<div id="media-type-${sk}" title="Channel">
<i class="fa fa-fw fa-cloud"></i>&nbsp;
</div>
% endif
<div class="dashboard-activity-metadata-subtitle">
% if data['channel_stream'] == 0:
% if data['media_type'] == 'movie':
<span title="${data['year']}" class="sub-heading">${data['year']}</span>
% elif data['media_type'] == 'episode':
<a href="info?rating_key=${data['parent_rating_key']}" title="Season ${data['parent_media_index']}" class="sub-heading">S${data['parent_media_index']}</a>
&middot; <a href="info?rating_key=${data['rating_key']}" title="Episode ${data['media_index']}" class="sub-heading">E${data['media_index']}</a>
% elif data['media_type'] == 'track':
<a id="metadata-parent_title-${sk}" href="info?rating_key=${data['parent_rating_key']}" title="${data['parent_title']}" class="sub-heading">${data['parent_title']}</a>
% elif data['media_type'] == 'photo':
<span title="${data['title']}" class="sub-heading">${data['title']}</span>
% else:
<span title="${data['year']}" class="sub-heading">${data['year']}</span>
% endif
% elif data['channel_title']:
<span title="${data['channel_title']}" class="sub-heading">${data['channel_title']}</span>
% if data['media_type'] == 'episode' and data['parent_media_index'] and data['media_index']:
(<span title="Season ${data['parent_media_index']}" class="sub-heading">S${data['parent_media_index']}</span>
&middot; <span title="Episode ${data['media_index']}" class="sub-heading">E${data['media_index']}</span>)
% elif data['media_type'] == 'episode' and data['originally_available_at']:
(<span title="${data['originally_available_at']}" class="sub-heading">${data['originally_available_at']}</span>)
% endif
% else:
<span title="Channel" class="sub-heading">Channel</span>
% if data['media_type'] == 'episode' and data['parent_media_index'] and data['media_index']:
(<span title="Season ${data['parent_media_index']}" class="sub-heading">S${data['parent_media_index']}</span>
&middot; <span title="Episode ${data['media_index']}" class="sub-heading">E${data['media_index']}</span>)
% elif data['media_type'] == 'episode' and data['originally_available_at']:
(<span title="${data['originally_available_at']}" class="sub-heading">${data['originally_available_at']}</span>)
% endif
% endif
</div>
<div class="dashboard-activity-metadata-user">
% if data['user_id']:
<a href="user?user_id=${data['user_id']}" title="${data['friendly_name']}">${data['friendly_name']}</a>
% else:
${data['friendly_name']}
% endif
</div>
</div>
</div>
</div>

View File

@@ -45,7 +45,7 @@ DOCUMENTATION :: END
<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>
<p class="help-block">Change the library's picture in Tautulli. To reset to default, leave this field empty and save.</p>
</div>
<div class="checkbox">
<label>
@@ -81,24 +81,6 @@ DOCUMENTATION :: END
</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 () {
@@ -133,47 +115,19 @@ DOCUMENTATION :: END
});
});
$("#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();
}
});
});
$('#delete-all-history').click(function () {
var msg = 'Are you REALLY sure you want to purge all history for the <strong>${data["section_name"]}</strong> library?<br>' +
'This is permanent and cannot be undone!';
var url = 'delete_all_library_history';
confirmAjaxCall(url, msg, { section_id: '${data["section_id"]}' }, null, function () { location.reload(); });
});
$(document).ready(function() {
// Move #confirm-modal to parent container
if (!($('#edit-library-modal').next().is('#confirm-modal-purge'))) {
$('#confirm-modal-purge').appendTo($('#edit-library-modal').parent());
}
$('#edit-library-modal > #confirm-modal-purge').remove();
$('#edit-library-modal').css('z-index', '1050');
$('.modal-backdrop').not('.modal-backdrop-stack').css('z-index', '1049');
$('.modal-backdrop').not('.modal-backdrop-stack').addClass('modal-backdrop-stack');
$('#confirm-modal-purge').on('show.bs.modal', function () {
// Fix position to match parent modal
var currentPadding = parseInt($('body').css('padding-right'));
$(this).children('.modal-dialog').css('left', -currentPadding/2);
$('#edit-library-modal').css('overflow-y', 'hidden');
});
$('#confirm-modal-purge').on('shown.bs.modal', function () {
$(this).css('z-index', '1060');
$('.modal-backdrop').not('.modal-backdrop-stack').css('z-index', '1059');
$('.modal-backdrop').not('.modal-backdrop-stack').addClass('modal-backdrop-stack');
});
$('#confirm-modal-purge').on('hidden.bs.modal', function () {
$('body').addClass('modal-open');
$('#edit-library-modal').css('overflow-y', 'auto');
});
});
</script>
% endif

View File

@@ -54,7 +54,7 @@ DOCUMENTATION :: END
<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.</p>
<p class="help-block">Change the users profile picture in Tautulli. To reset to default, leave this field empty and save.</p>
</div>
<div class="checkbox">
<label>
@@ -72,7 +72,7 @@ DOCUMENTATION :: END
<label>
<input type="checkbox" id="allow_guest" name="allow_guest" value="1" ${helpers.checked(data['allow_guest'])}> Allow Guest Access
</label>
<p class="help-block">Uncheck this if you do not want to allow this user to login to PlexPy.</p>
<p class="help-block">Uncheck this if you do not want to allow this user to login to Tautulli.</p>
</div>
% if data['user_id']:
<div class="form-group">
@@ -90,28 +90,10 @@ DOCUMENTATION :: END
</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 user?</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>
// Set user options
$("#save_user").on('click', function () {
var friendly_name = $("#friendly_name").val();
var friendly_name = $("input#friendly_name").val();
var custom_thumb = $("#custom_avatar_url").val();
var do_notify = 0;
var keep_history = 0;
@@ -144,47 +126,19 @@ DOCUMENTATION :: END
});
});
$("#delete-all-history").on('click', function() {
$('#confirm-modal-purge').modal();
$('#confirm-modal-purge').one('click', '#confirm-purge', function () {
$.ajax({
url: 'delete_all_user_history',
data: { user_id: '${data["user_id"]}' },
cache: false,
async: true,
success: function(data) {
location.reload();
}
});
});
$('#delete-all-history').click(function () {
var msg = 'Are you REALLY sure you want to purge all history for the <strong>${data["username"]}</strong> user?<br>' +
'This is permanent and cannot be undone!';
var url = 'delete_all_user_history';
confirmAjaxCall(url, msg, { user_id: '${data["user_id"]}' }, null, function () { location.reload(); });
});
$(document).ready(function() {
// Move #confirm-modal-purge to parent container
if (!($('#edit-user-modal').next().is('#confirm-modal-purge'))) {
$('#confirm-modal-purge').appendTo($('#edit-user-modal').parent());
}
$('#edit-user-modal > #confirm-modal-purge').remove();
$('#edit-user-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-user-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-user-modal').css('overflow-y', 'auto');
});
});
</script>
% endif

View File

@@ -20,7 +20,7 @@
</select>
</label>
</div>
<div class="btn-group" data-toggle="buttons" id="yaxis-selection">
<div class="btn-group" style="margin-right: 2px;" 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
@@ -37,15 +37,15 @@
</label>
% endif
</div>
<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 class="input-group pull-right" style="width: 1px;" id="days-selection">
<span class="input-group-addon btn-dark inactive">Last</span>
<input type="number" class="form-control" name="graph-days" id="graph-days" value="${config['graph_days']}" min="1" data-default="7" data-toggle="tooltip" title="Min: 1 day" />
<span class="input-group-addon btn-dark inactive">days</span>
</div>
<div class="btn-group" id="months-selection">
<label>
<input type="number" name="graph-months" id="graph-months" value="${config['graph_months']}" min="1" /> months
</label>
<div class="input-group pull-right" style="width: 1px;" id="months-selection">
<span class="input-group-addon btn-dark inactive">Last</span>
<input type="number" class="form-control" name="graph-months" id="graph-months" value="${config['graph_months']}" min="1" data-default="12" data-toggle="tooltip" title="Min: 1 month" />
<span class="input-group-addon btn-dark inactive">months</span>
</div>
</div>
</div>
@@ -245,13 +245,18 @@
</div>
</div>
</div>
<div class="modal fade" id="history-modal" tabindex="-1" role="dialog" aria-labelledby="history-modal">
</div>
</div>
</div>
</div>
</%def>
<%def name="modalIncludes()">
<div class="modal fade" id="history-modal" tabindex="-1" role="dialog" aria-labelledby="history-modal">
</div>
<div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal">
</div>
</%def>
<%def name="javascriptIncludes()">
<script src="${http_root}js/moment-with-locale.js"></script>
<script src="${http_root}js/moment-duration-format.js"></script>
@@ -287,16 +292,17 @@
$.ajax({
url: "history_table_modal",
type: 'post',
data: {
cache: false,
async: true,
data: {
user_id: selected_user_id,
start_date: dateString,
media_type: media_type,
transcode_decision: transcode_decision
},
complete: function(xhr, status) {
$('#history-modal').modal('show');
$("#history-modal").html(xhr.responseText);
$('#history-modal').modal();
}
});
}
@@ -566,11 +572,7 @@
e.preventDefault();
current_tab = $(this).attr('href');
loadGraphsTab1(current_day_range, yaxis);
$.ajax({
url: 'set_graph_config',
data: { graph_tab: current_tab.replace('#','') },
async: true
});
$.post('set_graph_config', { graph_tab: current_tab.replace('#','') });
})
// Tab2 opened
@@ -578,11 +580,7 @@
e.preventDefault();
current_tab = $(this).attr('href');
loadGraphsTab2(current_day_range, yaxis);
$.ajax({
url: 'set_graph_config',
data: { graph_tab: current_tab.replace('#','') },
async: true
});
$.post('set_graph_config', { graph_tab: current_tab.replace('#','') });
})
// Tab3 opened
@@ -590,46 +588,28 @@
e.preventDefault();
current_tab = $(this).attr('href');
loadGraphsTab3(current_month_range, yaxis);
$.ajax({
url: 'set_graph_config',
data: { graph_tab: current_tab.replace('#','') },
async: true
});
$.post('set_graph_config', { graph_tab: current_tab.replace('#','') });
})
// Date range changed
$('#graph-days').tooltip({ container: 'body', placement: 'top', html: true });
$('#graph-days').on('change', function() {
current_day_range = Math.round($(this).val());
$(this).val(current_day_range);
if (current_day_range < 1) {
$(this).val(7);
current_day_range = 7;
}
forceMinMax($(this));
current_day_range = $(this).val();
if (current_tab == '#tabs-1') { loadGraphsTab1(current_day_range, yaxis); }
if (current_tab == '#tabs-2') { loadGraphsTab2(current_day_range, yaxis); }
$('.days').html(current_day_range);
$.ajax({
url: 'set_graph_config',
data: { graph_days: current_day_range},
async: true
});
$.post('set_graph_config', { graph_days: current_day_range });
});
// Month range changed
$('#graph-months').tooltip({ container: 'body', placement: 'top', html: true });
$('#graph-months').on('change', function() {
current_month_range = Math.round($(this).val());
$(this).val(current_month_range);
if (current_month_range < 1) {
$(this).val(12);
current_month_range = 12;
}
forceMinMax($(this));
current_month_range = $(this).val();
if (current_tab == '#tabs-3') { loadGraphsTab3(current_month_range, yaxis); }
$('.months').html(current_month_range);
$.ajax({
url: 'set_graph_config',
data: { graph_months: current_month_range},
async: true
});
$.post('set_graph_config', { graph_months: current_month_range });
});
// User changed
@@ -646,11 +626,7 @@
if (current_tab == '#tabs-1') { loadGraphsTab1(current_day_range, yaxis); }
if (current_tab == '#tabs-2') { loadGraphsTab2(current_day_range, yaxis); }
if (current_tab == '#tabs-3') { loadGraphsTab3(current_month_range, yaxis); }
$.ajax({
url: 'set_graph_config',
data: { graph_type: yaxis},
async: true
});
$.post('set_graph_config', { graph_type: yaxis });
});
function setGraphFormat(type) {

View File

@@ -45,6 +45,9 @@
<input type="radio" name="media_type-filter" id="history-music" value="track" autocomplete="off"> Music
</label>
</div>
<div class="btn-group">
<button class="btn btn-dark refresh-history-button" id="refresh-history-list"><i class="fa fa-refresh"></i> Refresh history</button>
</div>
<div class="btn-group colvis-button-bar"></div>
</div>
</div>
@@ -53,7 +56,7 @@
<thead>
<tr>
<th align="left" id="delete_row">Delete</th>
<th align="left" id="time">Time</th>
<th align="left" id="date">Date</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>
@@ -69,26 +72,29 @@
<tbody>
</tbody>
</table>
<div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal">
</div>
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
</div>
<div class="modal fade" id="confirm-modal-delete" tabindex="-1" role="dialog" aria-labelledby="confirm-modal-delete">
<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 Delete</h4>
</div>
<div class="modal-body" style="text-align: center;">
<p>Are you REALLY sure you want to delete <strong><span id="deleteCount"></span></strong> history item(s)?</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-delete">Delete</button>
</div>
</div>
</div>
</div>
</%def>
<%def name="modalIncludes()">
<div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal">
</div>
<div class="modal fade" id="ip-info-modal" tabindex="-1" role="dialog" aria-labelledby="ip-info-modal">
</div>
<div class="modal fade" id="confirm-modal-delete" tabindex="-1" role="dialog" aria-labelledby="confirm-modal-delete">
<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 Delete</h4>
</div>
<div class="modal-body" style="text-align: center;">
<p>Are you REALLY sure you want to delete <strong><span id="deleteCount"></span></strong> history item(s)?</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-delete">Delete</button>
</div>
</div>
</div>
@@ -101,7 +107,7 @@
<script src="${http_root}js/dataTables.bootstrap.min.js"></script>
<script src="${http_root}js/dataTables.bootstrap.pagination.js"></script>
<script src="${http_root}js/moment-with-locale.js"></script>
<script src="${http_root}js/tables/history_table.js"></script>
<script src="${http_root}js/tables/history_table.js${cache_param}"></script>
<script>
$(document).ready(function () {
// Load user ids and names (for the selector)
@@ -166,17 +172,18 @@
$('#deleteCount').text(history_to_delete.length);
$('#confirm-modal-delete').modal();
$('#confirm-modal-delete').one('click', '#confirm-delete', function () {
for (var i = 0; i < history_to_delete.length; i++) {
history_to_delete.forEach(function(row, idx) {
$.ajax({
url: 'delete_history_rows',
data: { row_id: history_to_delete[i] },
type: 'POST',
data: { row_id: row },
async: true,
success: function (data) {
var msg = "History deleted";
showMsg(msg, false, true, 2000);
}
});
}
});
history_table.draw();
});
}
@@ -196,5 +203,9 @@
});
% endif
});
$("#refresh-history-list").click(function() {
history_table.draw();
});
</script>
</%def>

View File

@@ -27,9 +27,8 @@
<div class="modal-footer"></div>
</div>
</div>
<div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal">
</div>
<script src="${http_root}js/tables/history_table_modal.js"></script>
<script src="${http_root}js/tables/history_table_modal.js${cache_param}"></script>
<script>
$(document).ready(function() {
$('#date-header').html(moment('${data["start_date"]}','YYYY-MM-DD').format('ddd MMM Do YYYY'));
@@ -44,39 +43,13 @@
start_date: "${data['start_date']}",
media_type: "${data.get('media_type')}",
transcode_decision: "${data.get('transcode_decision')}"
};
};
}
}
history_table = $('#history_table_modal').DataTable(history_table_modal_options);
clearSearchButton('history_table_modal', history_table);
// Move #info-modal to parent container
if (!($('#history-modal').next().is('#info-modal'))) {
$('#info-modal').appendTo($('#history-modal').parent());
}
$('#history-modal > #info-modal').remove();
$('#history-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');
$('#info-modal').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);
$('#history-modal').css('overflow-y', 'hidden');
setTimeout(function () {
$('#info-modal').css('z-index', '1060');
$('.modal-backdrop').not('.modal-backdrop-stack').css('z-index', '1059');
$('.modal-backdrop').not('.modal-backdrop-stack').addClass('modal-backdrop-stack');
}, 0);
});
$('#info-modal').on('hidden.bs.modal', function () {
$('body').addClass('modal-open');
$('#history-modal').css('overflow-y', 'auto');
});
});
</script>
% else:

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="${http_root}images/favicon/mstile-70x70.png?v=2.0.1"/>
<square150x150logo src="${http_root}images/favicon/mstile-150x150.png?v=2.0.1"/>
<square310x310logo src="${http_root}images/favicon/mstile-310x310.png?v=2.0.1"/>
<TileColor>#282a2d</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,18 @@
{
"name": "Tautulli",
"icons": [
{
"src": "${http_root}images/favicon/android-chrome-192x192.png?v=2.0.1",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "${http_root}images/favicon/android-chrome-256x256.png?v=2.0.1",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#282a2d",
"background_color": "#282a2d",
"display": "standalone"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1 @@
<svg version="1" xmlns="http://www.w3.org/2000/svg" width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000" preserveAspectRatio="xMidYMid meet"><g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none"><path d="M5695 6555 c-135 -34 -244 -94 -342 -189 -40 -39 -73 -76 -73 -83 0 -7 -4 -13 -10 -13 -14 0 -87 -156 -106 -225 -22 -83 -26 -234 -8 -320 17 -79 86 -230 133 -288 l30 -39 -48 -71 c-39 -57 -159 -228 -251 -357 -69 -97 -398 -564 -416 -590 -13 -19 -60 -87 -105 -150 -45 -63 -107 -151 -138 -195 -30 -44 -59 -84 -63 -90 -7 -9 -251 -354 -346 -490 -92 -131 -173 -245 -175 -245 -1 0 -34 9 -72 21 -130 38 -325 31 -454 -18 -168 -63 -313 -196 -385 -354 -39 -87 -65 -183 -68 -256 0 -24 -3 -43 -4 -43 -2 0 -43 46 -91 102 -49 57 -100 117 -115 133 -14 17 -128 149 -253 295 -125 146 -251 292 -279 324 -56 65 -77 89 -108 126 -58 68 -152 178 -172 200 -12 14 -50 57 -83 96 l-61 71 27 44 c58 93 91 217 92 342 2 161 -38 294 -125 412 -133 181 -316 279 -542 292 -470 27 -833 -434 -699 -887 74 -251 275 -437 530 -490 132 -28 334 -6 421 45 l42 24 173 -197 c96 -108 186 -210 200 -227 15 -16 163 -187 330 -380 458 -529 491 -567 526 -605 18 -19 31 -35 30 -36 -6 -5 -265 -161 -277 -167 -8 -4 -34 -20 -58 -35 -194 -124 -634 -382 -651 -382 -12 0 -46 20 -75 44 -60 49 -180 112 -242 127 -21 5 -48 12 -59 15 -11 4 -65 9 -121 11 -81 4 -117 1 -182 -15 -261 -66 -462 -270 -528 -537 -10 -40 -11 -217 -2 -258 5 -23 11 -51 14 -61 29 -145 147 -312 284 -403 123 -82 224 -114 370 -118 83 -3 124 2 240 29 36 9 133 57 187 94 60 41 111 91 153 152 14 19 28 37 32 40 19 15 71 140 89 217 17 73 20 107 16 198 -4 61 -7 121 -9 134 -3 28 -46 0 482 321 179 108 379 228 444 265 104 59 120 65 133 52 13 -13 12 -22 -10 -78 -49 -123 -58 -165 -62 -262 -7 -149 25 -286 89 -383 47 -72 91 -128 125 -158 19 -17 39 -36 45 -42 27 -25 136 -94 150 -94 8 0 17 -4 20 -9 3 -5 16 -11 28 -14 13 -3 50 -12 83 -21 74 -19 278 -15 345 7 198 65 358 196 435 358 16 34 20 36 49 28 17 -4 49 -10 71 -14 22 -3 99 -16 170 -30 72 -13 144 -26 160 -29 28 -5 101 -18 170 -31 17 -3 80 -14 140 -25 61 -11 124 -22 140 -25 17 -4 49 -9 72 -12 40 -5 42 -7 48 -47 14 -98 29 -147 73 -235 36 -75 61 -110 121 -171 154 -154 280 -210 480 -213 134 -2 180 5 273 40 212 83 371 262 427 481 24 93 25 255 2 342 -64 241 -245 428 -481 501 -62 18 -97 23 -200 22 -107 0 -136 -4 -205 -26 -44 -15 -109 -43 -145 -64 -83 -48 -208 -171 -250 -245 -17 -32 -35 -60 -38 -61 -4 -2 -46 4 -93 13 -48 10 -104 20 -125 23 -22 3 -46 8 -54 11 -8 3 -33 7 -55 10 -38 5 -58 9 -122 21 -16 3 -53 10 -83 15 -30 6 -66 12 -79 15 -13 2 -103 19 -200 36 -169 30 -207 42 -196 60 10 16 -28 155 -62 224 -19 39 -54 96 -78 127 l-45 58 40 52 c96 125 143 266 143 433 1 164 -27 263 -108 391 -19 30 -35 57 -35 61 0 3 31 49 69 102 57 81 450 638 625 889 28 40 62 88 76 107 14 18 194 274 400 568 291 414 379 534 393 531 10 -2 27 -6 37 -9 78 -25 240 -29 338 -9 433 87 677 573 489 974 -93 200 -255 332 -478 389 -87 22 -227 25 -304 6z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="483.904px" height="409.539px" viewBox="66.712 194.513 483.904 409.539"
enable-background="new 66.712 194.513 483.904 409.539" xml:space="preserve">
<g>
<g>
<path fill="none" d="M41.209,627.586c0-151.979,0-303.963,0-456.118c177.822,0,355.688,0,533.881,0c0,151.922,0,304.021,0,456.118
C397.214,627.586,219.233,627.586,41.209,627.586z M461.314,421.571c-110.652,0-220.389,0-329.873,0c0,18.87,0,36.226,0,54.729
c110.29,0,219.734,0,329.824,0c0,6.858-0.271,12.563,0.058,18.231c0.659,11.344,8.853,15.958,18.112,9.46
c22.087-15.499,43.824-31.503,65.474-47.611c7.678-5.715,7.621-10.63-0.234-16.467c-21.352-15.862-42.87-31.508-64.563-46.902
c-9.542-6.773-17.488-2.864-18.691,8.976C460.813,407.959,461.314,414.046,461.314,421.571z M130.996,574.741
c74.536,0,148.057,0,222.423,0c0,6.464-0.617,11.836,0.192,16.98c0.662,4.21,2.17,10.746,4.826,11.622
c4.329,1.427,10.994,0.66,14.77-1.943c21.297-14.688,42.098-30.1,62.911-45.474c8.887-6.564,8.992-11.503,0.233-18.001
c-20.777-15.419-41.647-30.727-62.83-45.579c-3.569-2.503-10.381-4.832-13.03-3.118c-3.676,2.376-5.784,8.447-6.81,13.308
c-1.126,5.336-0.257,11.091-0.257,17.757c-75.009,0-148.525,0-222.43,0C130.996,538.558,130.996,555.663,130.996,574.741z
M130.83,281.392c49.453,0,97.705,0,146.88,0c0,6.838-0.232,12.506,0.049,18.148c0.585,11.758,9.078,16.246,18.887,9.342
c21.767-15.316,43.232-31.064,64.624-46.902c8.01-5.932,7.995-11.301-0.134-17.342c-21.053-15.65-42.257-31.103-63.625-46.318
c-10.735-7.647-18.836-3.478-19.734,9.846c-0.378,5.611-0.063,11.27-0.063,18.431c-49.546,0-98.1,0-146.885,0
C130.83,245.229,130.83,262.325,130.83,281.392z M188.205,379.701c0,6.939-0.606,12.297,0.19,17.438
c0.649,4.198,2.088,10.688,4.753,11.61c4.316,1.496,11.054,0.904,14.8-1.673c21.612-14.857,42.736-30.435,63.834-46.026
c8.481-6.265,8.471-11.812-0.159-18.227c-21.054-15.647-42.241-31.123-63.625-46.315c-10.656-7.571-18.899-3.211-19.724,10.07
c-0.365,5.875-0.062,11.793-0.062,18.885c-20.45,0-38.938,0-57.202,0c0,18.619,0,35.973,0,54.238
C149.953,379.701,168.131,379.701,188.205,379.701z M66.712,280.18c17.568,0,33.699,0,49.59,0c0-18.261,0-35.579,0-53.046
c-16.925,0-33.07,0-49.59,0C66.712,245.159,66.712,262.481,66.712,280.18z M66.869,325.488c0,18.556,0,35.876,0,53.543
c16.862,0,33,0,49.278,0c0-18.274,0-35.852,0-53.543C99.359,325.488,83.5,325.488,66.869,325.488z M116.673,422.747
c-17.484,0-33.644,0-49.668,0c0,17.835,0,34.781,0,51.779c17.017,0,33.178,0,49.668,0
C116.673,456.924,116.673,440.208,116.673,422.747z M116.497,520.842c-17.01,0-33.43,0-49.552,0c0,18.244,0,35.566,0,53.021
c16.944,0,33.084,0,49.552,0C116.497,555.793,116.497,538.471,116.497,520.842z"/>
<path fill="#FFFFFF" d="M461.314,421.571c0-7.525-0.503-13.612,0.105-19.586c1.203-11.839,9.149-15.749,18.691-8.976
c21.691,15.396,43.211,31.04,64.563,46.902c7.855,5.837,7.912,10.752,0.234,16.467c-21.648,16.108-43.387,32.112-65.474,47.611
c-9.261,6.498-17.453,1.884-18.112-9.46c-0.329-5.67-0.058-11.373-0.058-18.231c-110.09,0-219.534,0-329.824,0
c0-18.503,0-35.857,0-54.729C240.927,421.571,350.662,421.571,461.314,421.571z"/>
<path fill="#FFFFFF" d="M130.996,574.741c0-19.078,0-36.185,0-54.448c73.904,0,147.42,0,222.43,0
c0-6.666-0.869-12.421,0.257-17.757c1.024-4.859,3.134-10.932,6.81-13.308c2.649-1.714,9.461,0.615,13.029,3.118
c21.184,14.854,42.054,30.16,62.831,45.579c8.759,6.498,8.652,11.437-0.233,18.001c-20.813,15.374-41.614,30.786-62.911,45.474
c-3.774,2.604-10.439,3.369-14.77,1.943c-2.656-0.876-4.165-7.412-4.826-11.622c-0.811-5.146-0.192-10.518-0.192-16.98
C279.053,574.741,205.532,574.741,130.996,574.741z"/>
<path fill="#FFFFFF" d="M130.83,281.392c0-19.067,0-36.163,0-54.795c48.785,0,97.339,0,146.885,0
c0-7.161-0.315-12.82,0.063-18.431c0.898-13.323,8.999-17.493,19.734-9.846c21.368,15.215,42.572,30.668,63.625,46.318
c8.129,6.041,8.144,11.411,0.133,17.342c-21.391,15.838-42.855,31.586-64.623,46.902c-9.81,6.904-18.302,2.417-18.887-9.342
c-0.281-5.643-0.049-11.31-0.049-18.148C228.535,281.392,180.283,281.392,130.83,281.392z"/>
<path fill="#FFFFFF" d="M188.205,379.701c-20.074,0-38.252,0-57.192,0c0-18.265,0-35.619,0-54.238c18.264,0,36.752,0,57.202,0
c0-7.092-0.303-13.01,0.062-18.885c0.825-13.281,9.067-17.641,19.724-10.07c21.383,15.193,42.57,30.668,63.625,46.315
c8.63,6.416,8.64,11.962,0.159,18.227c-21.099,15.591-42.222,31.169-63.834,46.026c-3.746,2.577-10.484,3.169-14.8,1.673
c-2.666-0.923-4.104-7.412-4.753-11.61C187.599,391.999,188.205,386.64,188.205,379.701z"/>
<path fill="#FFFFFF" d="M66.712,280.18c0-17.699,0-35.021,0-53.046c16.52,0,32.665,0,49.59,0c0,17.468,0,34.786,0,53.046
C100.411,280.18,84.281,280.18,66.712,280.18z"/>
<path fill="#FFFFFF" d="M66.869,325.488c16.63,0,32.49,0,49.278,0c0,17.692,0,35.27,0,53.543c-16.278,0-32.416,0-49.278,0
C66.869,361.364,66.869,344.044,66.869,325.488z"/>
<path fill="#E5A00D" d="M116.673,422.747c0,17.461,0,34.177,0,51.779c-16.49,0-32.652,0-49.668,0c0-16.998,0-33.944,0-51.779
C83.029,422.747,99.188,422.747,116.673,422.747z"/>
<path fill="#FFFFFF" d="M116.497,520.842c0,17.629,0,34.951,0,53.021c-16.468,0-32.608,0-49.552,0c0-17.455,0-34.777,0-53.021
C83.067,520.842,99.487,520.842,116.497,520.842z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>artist</title>
<path fill="#fff" d="M9.201 24.681c0-6.699 0-13.358 0-20.035 7.594-1.505 15.157-3.004 22.768-4.513 0 0.172 0 0.319 0 0.465 0 7.067-0.026 14.135 0.021 21.202 0.010 1.498-0.59 2.57-1.716 3.423-1.999 1.512-4.26 2.145-6.751 1.88-0.504-0.054-1.020-0.205-1.481-0.418-1.502-0.695-1.856-2.122-0.908-3.48 0.826-1.184 1.99-1.924 3.302-2.433 1.362-0.528 2.774-0.843 4.252-0.719 0.324 0.027 0.646 0.084 0.994 0.13 0-4.345 0-8.679 0-13.050-6.062 1.204-12.099 2.404-18.16 3.608 0 0.196 0 0.345 0 0.495 0 5.174-0.006 10.349 0.004 15.523 0.003 1.409-0.802 2.302-1.854 3.056-0.889 0.637-1.859 1.114-2.906 1.426-1.524 0.453-3.067 0.627-4.619 0.169-0.952-0.281-1.789-0.736-2.010-1.83-0.136-0.673 0.098-1.269 0.459-1.822 0.772-1.183 1.947-1.853 3.193-2.388 1.662-0.714 3.394-1.043 5.207-0.698 0.048 0.009 0.099 0.005 0.206 0.010z"></path>
</svg>

After

Width:  |  Height:  |  Size: 979 B

View File

@@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>movie</title>
<path fill="#fff" d="M0 1.416c10.695 0 21.315 0 32 0 0 9.719 0 19.417 0 29.168-10.635 0-21.293 0-32 0 0-9.699 0-19.399 0-29.168zM9.202 15.129c4.535 0 9.065 0 13.609 0 0-3.798 0-7.579 0-11.355-4.563 0-9.075 0-13.609 0 0 3.801 0 7.551 0 11.355zM9.215 28.909c4.581 0 9.093 0 13.61 0 0-3.818 0-7.585 0-11.382-4.549 0-9.062 0-13.61 0 0 3.803 0 7.57 0 11.382zM6.813 5.983c0-0.753 0-1.467 0-2.209-1.138 0-2.235 0-3.33 0 0 0.766 0 1.48 0 2.209 1.131 0 2.21 0 3.33 0zM25.231 3.754c0 0.783 0 1.494 0 2.219 1.141 0 2.235 0 3.33 0 0-0.763 0-1.476 0-2.219-1.12 0-2.198 0-3.33 0zM25.233 12.938c0 0.777 0 1.492 0 2.19 1.149 0 2.248 0 3.335 0 0-0.754 0-1.452 0-2.19-1.116 0-2.197 0-3.335 0zM25.227 22.074c0 0.783 0 1.496 0 2.218 1.139 0 2.235 0 3.335 0 0-0.758 0-1.471 0-2.218-1.119 0-2.196 0-3.335 0zM3.472 26.689c0 0.768 0 1.481 0 2.221 1.133 0 2.226 0 3.34 0 0-0.763 0-1.475 0-2.221-1.119 0-2.197 0-3.34 0zM28.579 26.711c-1.112 0-2.225 0-3.353 0 0 0.749 0 1.462 0 2.202 1.137 0 2.233 0 3.353 0 0-0.748 0-1.447 0-2.202zM6.817 15.155c0-0.774 0-1.468 0-2.21-1.133 0-2.229 0-3.338 0 0 0.761 0 1.473 0 2.21 1.127 0 2.207 0 3.338 0zM3.463 19.73c1.165 0 2.242 0 3.346 0 0-0.759 0-1.469 0-2.189-1.143 0-2.239 0-3.346 0 0 0.748 0 1.446 0 2.189zM28.559 19.733c0-0.764 0-1.479 0-2.188-1.144 0-2.241 0-3.34 0 0 0.752 0 1.448 0 2.188 1.114 0 2.195 0 3.34 0zM6.791 24.304c0-0.798 0-1.511 0-2.215-1.145 0-2.225 0-3.312 0 0 0.766 0 1.481 0 2.215 1.129 0 2.211 0 3.312 0zM3.489 8.378c0 0.771 0 1.464 0 2.145 1.138 0 2.219 0 3.319 0 0-0.74 0-1.431 0-2.145-1.129 0-2.211 0-3.319 0zM28.554 10.538c0-0.775 0-1.464 0-2.137-1.146 0-2.242 0-3.319 0 0 0.747 0 1.438 0 2.137 1.131 0 2.21 0 3.319 0z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,6 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>photo</title>
<path fill="#fff" d="M25.208 2.266c0 1.514 0 2.976 0 4.513 2.281 0 4.505 0 6.792 0 0 7.681 0 15.287 0 22.955-10.643 0-21.3 0-32 0 0-7.626 0-15.236 0-22.913 2.258 0 4.486 0 6.792 0 0-1.546 0-3.029 0-4.555 6.152 0 12.226 0 18.415 0zM16.008 9.209c-5.026-0.004-9.12 4.079-9.123 9.099-0.004 4.961 4.099 9.069 9.074 9.085 5.022 0.016 9.124-4.047 9.159-9.070 0.035-4.985-4.087-9.109-9.109-9.114z"></path>
<path fill="#fff" d="M20.601 18.292c0.003 2.551-2.070 4.626-4.61 4.613-2.558-0.013-4.595-2.069-4.591-4.634 0.003-2.524 2.038-4.557 4.577-4.572 2.562-0.015 4.621 2.030 4.624 4.593z"></path>
</svg>

After

Width:  |  Height:  |  Size: 746 B

View File

@@ -0,0 +1,12 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>playlist</title>
<path fill="#fff" d="M9.167 10.268c7.653 0 15.208 0 22.82 0 0 1.147 0 2.268 0 3.451-7.583 0-15.172 0-22.82 0 0-1.134 0-2.274 0-3.451z"></path>
<path fill="#fff" d="M9.14 21.73c0-1.152 0-2.257 0-3.424 7.609 0 15.212 0 22.86 0 0 1.132 0 2.252 0 3.424-7.607 0-15.191 0-22.86 0z"></path>
<path fill="#fff" d="M9.217 5.679c0-1.145 0-2.23 0-3.363 7.562 0 15.101 0 22.683 0 0 1.113 0 2.213 0 3.363-7.539 0-15.080 0-22.683 0z"></path>
<path fill="#fff" d="M9.225 29.708c0-1.132 0-2.214 0-3.336 7.558 0 15.086 0 22.668 0 0 1.086 0 2.186 0 3.336-7.526 0-15.071 0-22.668 0z"></path>
<path fill="#fff" d="M0.007 10.279c1.58 0 3.043 0 4.551 0 0 1.153 0 2.272 0 3.444-1.511 0-3.011 0-4.551 0 0-1.157 0-2.292 0-3.444z"></path>
<path fill="#fff" d="M4.527 2.292c0 1.183 0 2.284 0 3.424-1.496 0-2.957 0-4.479 0 0-1.142 0-2.276 0-3.424 1.51 0 2.971 0 4.479 0z"></path>
<path fill="#fff" d="M4.571 18.3c0 1.151 0 2.254 0 3.416-1.515 0-3.019 0-4.571 0 0-1.127 0-2.247 0-3.416 1.513 0 3.001 0 4.571 0z"></path>
<path fill="#fff" d="M4.54 26.352c0 1.137 0 2.218 0 3.354-1.494 0-2.975 0-4.506 0 0-1.094 0-2.192 0-3.354 1.489 0 2.965 0 4.506 0z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,6 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>show</title>
<path fill="#fff" d="M0 26.565c0-8.38 0-16.706 0-25.089 10.661 0 21.307 0 32 0 0 8.343 0 16.686 0 25.089-10.637 0-21.283 0-32 0zM3.514 4.937c0 5.355 0 10.634 0 15.901 8.375 0 16.691 0 24.994 0 0-5.331 0-10.612 0-15.901-8.356 0-16.656 0-24.994 0z"></path>
<path fill="#fff" d="M6.874 30.524c0-0.553 0-1.056 0-1.602 6.084 0 12.136 0 18.25 0 0 0.509 0 1.029 0 1.602-6.050 0-12.12 0-18.25 0z"></path>
</svg>

After

Width:  |  Height:  |  Size: 555 B

View File

@@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>video</title>
<path fill="#fff" d="M20.662 27.439c-6.971 0-13.797 0-20.662 0 0-7.639 0-15.235 0-22.878 6.846 0 13.672 0 20.588 0 0 2.962 0 5.932 0 9.091 3.87-2.316 7.591-4.542 11.412-6.828 0 6.153 0 12.176 0 18.33-3.769-2.257-7.494-4.488-11.338-6.789 0 3.070 0 6.035 0 9.075z"></path>
</svg>

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="900px"
height="300px" viewBox="-41.335 -35.197 900 300" enable-background="new -41.335 -35.197 900 300" xml:space="preserve">
<g id="Layer_1">
<g id="Logo">
<image overflow="visible" opacity="0.15" enable-background="new " width="259" height="193" xlink:href="13AD46AC.png" transform="matrix(0.9547 0 0 0.9547 -17.8804 54.1814)">
</image>
<image overflow="visible" opacity="0.15" enable-background="new " width="259" height="258" xlink:href="13AD46AD.png" transform="matrix(0.9547 0 0 0.9584 -17.8804 -8.8303)">
</image>
</g>
</g>
<g id="Layer_2">
<g>
<path fill="none" d="M349.343,165.396c7.493,0,14.836,0,22.407,0c-3.766-12.354-7.495-24.585-11.333-37.175
C356.665,140.819,353.017,153.064,349.343,165.396z"/>
<path fill="#FFFFFF" d="M103.83,174.477c-7.6,0-14.441-3.232-19.236-8.394l-4.595,2.845l1.406,1.593
c-2.429,3.979-3.83,8.656-3.83,13.66c0,14.5,11.755,26.255,26.255,26.255c10.38,0,19.351-6.024,23.612-14.767l37.675,5.471
c0.22,14.31,11.881,25.845,26.244,25.845c14.5,0,26.254-11.755,26.254-26.254c0-14.5-11.754-26.254-26.254-26.254
c-10.438,0-19.453,6.092-23.685,14.915l-37.598-5.46c-0.064-6.86-2.759-13.089-7.125-17.73
C118.165,171.293,111.371,174.477,103.83,174.477z"/>
<path fill="#FFFFFF" d="M77.574,148.22c0-0.054,0.004-0.107,0.004-0.161l-41.163-46.637c3.078-4.301,4.895-9.564,4.895-15.257
c0-14.5-11.754-26.254-26.254-26.254c-14.5,0-26.254,11.754-26.254,26.254S0.556,112.42,15.056,112.42
c4.464,0,8.666-1.117,12.347-3.083l44.545,50.47l6.701-4.148C77.953,153.299,77.574,150.804,77.574,148.22z"/>
<path fill="#E5A00D" d="M191.361,49.885c14.5,0,26.254-11.754,26.254-26.254c0-14.499-11.754-26.254-26.254-26.254
s-26.254,11.755-26.254,26.254c0,7.145,2.858,13.619,7.488,18.353l-58.186,82.207c-3.237-1.427-6.814-2.226-10.58-2.226
c-14.446,0-26.165,11.669-26.252,26.095c0,0.054-0.004,0.107-0.004,0.161c0,2.584,0.379,5.078,1.075,7.438l-6.701,4.148
l-37.506,23.223c-4.801-5.255-11.708-8.552-19.386-8.552c-14.5,0-26.254,11.754-26.254,26.254
c0,14.499,11.754,26.254,26.254,26.254c14.5,0,26.254-11.755,26.254-26.254c0-2.506-0.358-4.926-1.014-7.221l39.703-24.582
l4.595-2.845c4.794,5.161,11.636,8.394,19.236,8.394c7.542,0,14.335-3.185,19.124-8.275c4.419-4.699,7.132-11.021,7.132-17.981
c0-6.396-2.29-12.257-6.092-16.812l58.736-82.983C185.434,49.367,188.336,49.885,191.361,49.885z"/>
<path fill="#FFFFFF" d="M384.772,151.627c-4.399-12.521-8.814-25.034-13.223-37.553c-7.552,0-15.106,0-22.657,0.002
c-0.14,0.612-0.221,1.246-0.428,1.836c-8.502,24.335-17.017,48.666-25.526,72.996c-1.451,4.146-2.887,8.298-4.363,12.536
c6.686,0,13.198,0,19.792,0c2.095-6.874,4.172-13.694,6.248-20.514c10.593,0,21.056,0,31.594,0
c2.102,6.893,4.177,13.707,6.245,20.489c6.66,0,13.147,0,19.773,0c-0.229-0.676-0.409-1.213-0.597-1.747
C396.014,183.656,390.4,167.638,384.772,151.627z M349.343,165.396c3.674-12.332,7.322-24.577,11.074-37.175
c3.837,12.59,7.567,24.82,11.333,37.175C364.179,165.396,356.836,165.396,349.343,165.396z"/>
<path fill="#FFFFFF" d="M319.072,114.459c-21.916,0-43.668,0-65.421,0c0,5.112,0,10.227,0,15.341c7.836,0,15.672,0,23.691,0
c0,24.046,0,47.786,0,71.621c6.164,0,12.144,0,18.361,0c0-23.902,0-47.698,0-71.682c7.948,0,15.66,0,23.369,0
C319.072,124.549,319.072,119.549,319.072,114.459z"/>
<path fill="#FFFFFF" d="M480.615,114.554c-6.176,0-12.154,0-18.348,0c0,0.843,0,1.593,0,2.341c0,16.42,0.021,32.838-0.021,49.258
c-0.006,2.674-0.119,5.373-0.494,8.017c-0.997,7.07-4.634,11.153-11.06,12.587c-3.731,0.83-7.491,0.754-11.238,0
c-5.745-1.157-9.344-4.668-10.58-10.297c-0.678-3.088-0.958-6.318-0.976-9.488c-0.093-16.737-0.044-33.477-0.044-50.216
c0-0.733,0-1.467,0-2.149c-6.296,0-12.276,0-18.33,0c0,0.591,0,1.036,0,1.481c0,18.209-0.012,36.416,0.018,54.625
c0.003,1.908,0.127,3.835,0.396,5.726c1.632,11.409,7.683,19.563,18.562,23.516c11.146,4.052,22.489,3.83,33.593-0.392
c7.936-3.017,13.483-8.627,16.483-16.618c1.474-3.93,2.044-8.024,2.042-12.21c-0.006-18.146-0.002-36.29-0.002-54.436
C480.615,115.744,480.615,115.187,480.615,114.554z"/>
<path fill="#FFFFFF" d="M636.532,114.554c-6.16,0-12.139,0-18.348,0c0,0.925,0,1.621,0,2.319c0,16.482,0.021,32.967-0.021,49.449
c-0.006,2.609-0.125,5.244-0.49,7.825c-1.003,7.126-4.74,11.291-11.226,12.654c-3.674,0.771-7.373,0.702-11.055-0.038
c-5.741-1.155-9.354-4.651-10.596-10.281c-0.682-3.086-0.964-6.317-0.979-9.487c-0.093-16.738-0.043-33.477-0.043-50.216
c0-0.739,0-1.477,0-2.18c-6.279,0-12.26,0-18.332,0c0,0.582,0,1.025,0,1.467c0.002,18.272-0.011,36.544,0.02,54.816
c0.002,1.846,0.132,3.707,0.391,5.533c1.626,11.411,7.669,19.567,18.546,23.533c11.212,4.09,22.621,3.836,33.771-0.445
c7.851-3.018,13.345-8.613,16.315-16.541c1.521-4.052,2.06-8.275,2.056-12.592c-0.018-17.953-0.008-35.905-0.008-53.858
C636.532,115.892,636.532,115.269,636.532,114.554z"/>
<path fill="#FFFFFF" d="M490.405,129.793c7.813,0,15.523,0,23.479,0c0,23.979,0,47.771,0,71.649c6.172,0,12.101,0,18.425,0
c0-23.949,0-47.739,0-71.729c7.947,0,15.655,0,23.378,0c0-5.158,0-10.115,0-15.116c-21.82,0-43.531,0-65.282,0
C490.405,119.691,490.405,124.648,490.405,129.793z"/>
<path fill="#FFFFFF" d="M673.407,114.58c-6.199,0-12.176,0-18.193,0c0,29.021,0,57.92,0,86.857c17.832,0,35.528,0,53.335,0
c0-5.191,0-10.146,0-15.306c-11.72,0-23.322,0-35.142,0C673.407,162.143,673.407,138.362,673.407,114.58z"/>
<path fill="#FFFFFF" d="M738.668,114.593c-6.197,0-12.172,0-18.216,0c0,28.985,0,57.833,0,86.831c17.905,0,35.6,0,53.371,0
c0-5.106,0-10.107,0-15.316c-11.729,0-23.335,0-35.155,0C738.668,162.119,738.668,138.339,738.668,114.593z"/>
<path fill="#FFFFFF" d="M786.183,201.464c6.083,0,12.02,0,18.095,0c0-29.09,0-57.987,0-86.879c-6.12,0-12.097,0-18.095,0
C786.183,143.612,786.183,172.513,786.183,201.464z"/>
<ellipse fill="#E5A00D" cx="795.229" cy="91.416" rx="12.458" ry="12.44"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="298.961px" height="300px" viewBox="0 0 298.961 300" enable-background="new 0 0 298.961 300" xml:space="preserve">
<image overflow="visible" opacity="0.15" enable-background="new " width="259" height="193" xlink:href="93124B54.png" transform="matrix(1 0 0 1 22.6465 89.25)">
</image>
<path fill="#FFFFFF" d="M241.811,215.25c-10.935,0-20.376,6.382-24.809,15.623l-39.383-5.715
c-0.139-15.068-12.392-27.242-27.493-27.242c-5.385,0-10.405,1.554-14.646,4.229l-55.963-63.414
c3.224-4.505,5.127-10.02,5.127-15.981c0-15.188-12.312-27.5-27.5-27.5s-27.5,12.312-27.5,27.5s12.312,27.5,27.5,27.5
c4.677,0,9.079-1.171,12.934-3.23l56.56,64.089c-2.544,4.168-4.012,9.065-4.012,14.307c0,15.188,12.312,27.5,27.5,27.5
c10.872,0,20.269-6.311,24.731-15.467l39.464,5.727c0.229,14.99,12.443,27.074,27.489,27.074c15.188,0,27.5-12.313,27.5-27.5
S256.998,215.25,241.811,215.25z"/>
<image overflow="visible" opacity="0.15" enable-background="new " width="259" height="259" xlink:href="93124B55.png" transform="matrix(1 0 0 1 22.6465 23.25)">
</image>
<path fill="#E5A00D" d="M241.811,29.75c-15.188,0-27.5,12.312-27.5,27.5c0,7.48,2.99,14.258,7.835,19.216l-60.943,86.113
c-3.389-1.493-7.134-2.329-11.076-2.329c-15.188,0-27.5,12.313-27.5,27.5c0,2.704,0.397,5.314,1.125,7.783l-46.306,28.668
c-5.028-5.5-12.261-8.951-20.3-8.951c-15.188,0-27.5,12.313-27.5,27.5s12.312,27.5,27.5,27.5s27.5-12.313,27.5-27.5
c0-2.627-0.376-5.165-1.064-7.571l46.396-28.723c5.022,5.407,12.189,8.794,20.15,8.794c15.188,0,27.5-12.313,27.5-27.5
c0-6.701-2.399-12.84-6.382-17.611l61.515-86.92c2.836,0.988,5.88,1.532,9.052,1.532c15.188,0,27.5-12.312,27.5-27.5
S256.998,29.75,241.811,29.75z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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