From ba670d06aa9b09e5d4a95a97e21c40f921e33baa Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 5 Nov 2019 01:08:38 +0100 Subject: [PATCH 01/24] Added charjs and fetch user activity to graph from new user/activity endpoint. This fetches tautulli stats based on the plex user_id linked with the seasoned account. --- package.json | 1 + src/components/ActivityPage.vue | 123 ++++++++++++++++++++++++++++++++ src/routes.js | 5 ++ yarn.lock | 30 +++++++- 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 src/components/ActivityPage.vue diff --git a/package.json b/package.json index fde1d5a..27505fd 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "dependencies": { "axios": "^0.18.1", "babel-plugin-transform-object-rest-spread": "^6.26.0", + "chart.js": "^2.9.2", "connect-history-api-fallback": "^1.3.0", "express": "^4.16.1", "vue": "^2.5.2", diff --git a/src/components/ActivityPage.vue b/src/components/ActivityPage.vue new file mode 100644 index 0000000..454bcf2 --- /dev/null +++ b/src/components/ActivityPage.vue @@ -0,0 +1,123 @@ + + + + + \ No newline at end of file diff --git a/src/routes.js b/src/routes.js index eecb58c..4dbd90d 100644 --- a/src/routes.js +++ b/src/routes.js @@ -11,6 +11,11 @@ let routes = [ path: '/', component: (resolve) => require(['./components/Home.vue'], resolve) }, + { + name: 'activity', + path: '/activity', + component: (resolve) => require(['./components/ActivityPage.vue'], resolve) + }, { name: 'profile', path: '/profile', diff --git a/yarn.lock b/yarn.lock index be7a22d..9a60d7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1729,6 +1729,29 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz#1647f4f726638d3ea4a750cf5d1975c1c7919a85" integrity sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg== +chart.js@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.2.tgz#5f7397f2fc33ca406836dbaed3cc39943bbb9f80" + integrity sha512-AagP9h27gU7hhx8F64BOFpNZGV0R1Pz1nhsi0M1+KLhtniX6ElqLl0z0obKSiuGMl9tcRe6ZhruCGCJWmH6snQ== + dependencies: + chartjs-color "^2.1.0" + moment "^2.10.2" + +chartjs-color-string@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71" + integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A== + dependencies: + color-name "^1.0.0" + +chartjs-color@^2.1.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0" + integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w== + dependencies: + chartjs-color-string "^0.6.0" + color-convert "^1.9.3" + chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.2: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -1873,7 +1896,7 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" -color-convert@^1.3.0, color-convert@^1.9.0: +color-convert@^1.3.0, color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -4660,6 +4683,11 @@ module-deps-sortable@5.0.0: through2 "^2.0.0" xtend "^4.0.0" +moment@^2.10.2: + version "2.24.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" + integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" From 8d09ba4d076360f337d313ed5f4642ac714f6c6a Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 25 Nov 2019 22:55:34 +0100 Subject: [PATCH 02/24] get movie now has optional url parameters to also include existance and release dates in response --- src/api.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api.js b/src/api.js index 1d0533b..1023e4d 100644 --- a/src/api.js +++ b/src/api.js @@ -18,12 +18,18 @@ const ELASTIC_INDEX = config.ELASTIC_INDEX * @param {boolean} [credits=false] Include credits * @returns {object} Tmdb response */ -const getMovie = (id, credits=false) => { +const getMovie = (id, checkExistance=false, credits=false, release_dates=false) => { const url = new URL('v2/movie', SEASONED_URL) url.pathname = path.join(url.pathname, id.toString()) + if (checkExistance) { + url.searchParams.append('check_existance', true) + } if (credits) { url.searchParams.append('credits', true) } + if(release_dates) { + url.searchParams.append('release_dates', true) + } return fetch(url.href) .then(resp => resp.json()) From e3502a76903e537ffbafb492050972d7c99aee2d Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 25 Nov 2019 22:56:01 +0100 Subject: [PATCH 03/24] Searching tmdb should also include authorization token for search history. --- src/api.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/api.js b/src/api.js index 1023e4d..cf84985 100644 --- a/src/api.js +++ b/src/api.js @@ -107,7 +107,9 @@ const searchTmdb = (query, page=1) => { url.searchParams.append('query', query) url.searchParams.append('page', page) - return fetch(url.href) + const headers = { authorization: localStorage.getItem('token') } + + return fetch(url.href, { headers }) .then(resp => resp.json()) .catch(error => { console.error(`api error searching: ${query}, page: ${page}`); throw error }) } From 33e3ee34897141a81b94c7aa28fe76a71999863f Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 25 Nov 2019 22:57:05 +0100 Subject: [PATCH 04/24] Authenticating with plex now happens to seasonedShows backend and not through plex.tv. --- src/api.js | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/api.js b/src/api.js index cf84985..dd2f38c 100644 --- a/src/api.js +++ b/src/api.js @@ -214,29 +214,20 @@ const getRequestStatus = (id, type, authorization_token=undefined) => { // - - - Authenticate with plex - - - const plexAuthenticate = (username, password) => { - const url = new URL('https://plex.tv/api/v2/users/signin') - + const url = new URL('v1/user/authenticate', SEASONED_URL) + const body = { username, password } const headers = { 'Content-Type': 'application/json', - 'X-Plex-Platform': 'Linux', - 'X-Plex-Version': 'v2.0.24', - 'X-Plex-Platform-Version': '4.13.0-36-generic', - 'X-Plex-Device-Name': 'Tautulli', - 'X-Plex-Client-Identifier': '123' + authorization: storage.token } - let formData = new FormData() - formData.set('login', username) - formData.set('password', password) - formData.set('rememberMe', false) - - return axios({ - method: 'POST', - url: url.href, - headers: headers, - data: formData - }) - .catch(error => { console.error(`api error authentication plex: ${username}`); throw error }) + return fetch(url.href, { + method: 'POST', + headers, + body: JSON.stringify(body) + }) + .then(resp => resp.json()) + .catch(error => { console.error(`api error authentication plex: ${username}`); throw error }) } From bcfce66ec0286d29380cb4040b501916d37e7e36 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 25 Nov 2019 23:03:22 +0100 Subject: [PATCH 05/24] Matched is set to false if exists_in_plex is undefined (not a part of the response body). nesteDataToString is simplified in the way it parses its input data. getMovie uses optional second parameter check_existance to check if the file exists in plex. --- src/components/Movie.vue | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/Movie.vue b/src/components/Movie.vue index 213f937..a6df088 100644 --- a/src/components/Movie.vue +++ b/src/components/Movie.vue @@ -151,7 +151,7 @@ export default { this.title = movie.title this.poster = movie.poster this.backdrop = movie.backdrop - this.matched = movie.existsInPlex + this.matched = movie.exists_in_plex || false this.checkIfRequested(movie) .then(status => this.requested = status) @@ -161,9 +161,7 @@ export default { return await getRequestStatus(movie.id, movie.type) }, nestedDataToString(data) { - let nestedArray = [] - data.forEach(item => nestedArray.push(item)); - return nestedArray.join(', '); + return data.join(', ') }, sendRequest(){ request(this.id, this.type, storage.token) @@ -200,7 +198,7 @@ export default { this.prevDocumentTitle = store.getters['documentTitle/title'] if (this.type === 'movie') { - getMovie(this.id) + getMovie(this.id, true) .then(this.parseResponse) .catch(error => { this.$router.push({ name: '404' }); From 3ff963f0076627e319b1390671dba6bd1bf4226f Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 25 Nov 2019 23:11:59 +0100 Subject: [PATCH 06/24] Implemented download activity overlay on movielistitems if progress movie object key exists. --- src/components/MoviesListItem.vue | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/components/MoviesListItem.vue b/src/components/MoviesListItem.vue index aa8364d..a78b01d 100644 --- a/src/components/MoviesListItem.vue +++ b/src/components/MoviesListItem.vue @@ -6,6 +6,11 @@
+ +
+ + {{ movie.download.state }}: {{ movie.download.progress }}% +

{{ movie.title }}

@@ -115,3 +120,46 @@ export default { } } + + \ No newline at end of file From 9bc7f29162290d53c3841703fd56e1f9874a0c7d Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 25 Nov 2019 23:12:36 +0100 Subject: [PATCH 07/24] Decreased the padding around movie list items on large screens to let the grow a bit larger. --- src/components/MoviesListItem.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoviesListItem.vue b/src/components/MoviesListItem.vue index a78b01d..989617b 100644 --- a/src/components/MoviesListItem.vue +++ b/src/components/MoviesListItem.vue @@ -72,7 +72,7 @@ export default { } @include desktop-lg-min{ - padding: 20px; + padding: 15px; width: 12.5%; } From d0a251f69a7e2e2685a80c73670496fe9abca4af Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 25 Nov 2019 23:25:08 +0100 Subject: [PATCH 08/24] Moved register and login requests to api.js. --- src/api.js | 39 ++++++++++++++++++++++++++++++++ src/components/Register.vue | 29 +++++++++++------------- src/components/Signin.vue | 44 +++++++++++++++++-------------------- 3 files changed, 72 insertions(+), 40 deletions(-) diff --git a/src/api.js b/src/api.js index dd2f38c..8668aac 100644 --- a/src/api.js +++ b/src/api.js @@ -211,6 +211,43 @@ const getRequestStatus = (id, type, authorization_token=undefined) => { .catch(err => Promise.reject(err)) } +// - - - Seasoned user endpoints - - - + +const register = (username, password) => { + const url = new URL('v1/user', SEASONED_URL) + const options = { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username, password }) + } + + return fetch(url.href, options) + .then(resp => resp.json()) + .catch(error => { + console.error('Unexpected error occured before receiving response. Error:', error) + // TODO log to sentry the issue here + throw error + }) +} + +const login = (username, password) => { + const url = new URL('v1/user/login', SEASONED_URL) + const options = { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username, password }) + } + + return fetch(url.href, options) + .then(resp => checkStatus) + .then(resp => resp.json()) + .catch(error => { + console.error('Unexpected error occured before receiving response. Error:', error) + // TODO log to sentry the issue here + throw error + }) +} + // - - - Authenticate with plex - - - const plexAuthenticate = (username, password) => { @@ -303,6 +340,8 @@ export { request, getRequestStatus, plexAuthenticate, + register, + login, getEmoji, elasticSearchMoviesAndShows } diff --git a/src/components/Register.vue b/src/components/Register.vue index 5d94ff1..38d5c43 100644 --- a/src/components/Register.vue +++ b/src/components/Register.vue @@ -18,7 +18,7 @@ \ No newline at end of file From 6bba3197351f42b5f7aa22d881feafade770d9a9 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 24 Dec 2019 13:14:10 +0100 Subject: [PATCH 12/24] Formatting --- src/components/Signin.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/Signin.vue b/src/components/Signin.vue index 5b3042a..e25dc40 100644 --- a/src/components/Signin.vue +++ b/src/components/Signin.vue @@ -2,7 +2,10 @@

Sign in

- + sign in From 32257dc64ea72c887e20c60a960fc18f330ce2fb Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Tue, 24 Dec 2019 13:15:33 +0100 Subject: [PATCH 13/24] Info can now also be Array and will display the list elements in a column. Also made hader sticky and decreased some margin and increased the font. --- src/components/ListHeader.vue | 29 +++++++++++++++++------------ src/components/Profile.vue | 25 ++++--------------------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/components/ListHeader.vue b/src/components/ListHeader.vue index d36d163..1453ded 100644 --- a/src/components/ListHeader.vue +++ b/src/components/ListHeader.vue @@ -2,8 +2,11 @@

{{ title }}

- {{ info }} - +
+ {{ item }} +
+ {{ info }} + View All
@@ -19,10 +22,10 @@ export default { sticky: { type: Boolean, required: false, - default: false + default: true }, info: { - type: String, + type: [String, Array], required: false }, link: { @@ -37,12 +40,16 @@ export default {